From d4546706feed0f9dcb007cec2888edfb0ba54819 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 15 May 1999 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1999-05-15 --- alphapc/devether.c | 2 +- alphapc/fns.h | 4 +- alphapc/l.s | 71 +++++++++++++------------ alphapc/main.c | 51 +++++++++++++++--- alphapc/trap.c | 66 +++++++++-------------- pc/devlml.c | 129 ++++++++++++++++++++++++++++++++++++++++----- pc/devlml.h | 7 --- 7 files changed, 226 insertions(+), 104 deletions(-) diff --git a/alphapc/devether.c b/alphapc/devether.c index 18c7a33109c2890f52c14c970e96e3340347fc28..37710031e72607d3db4b80c9d133b0821ae9cf27 100644 --- a/alphapc/devether.c +++ b/alphapc/devether.c @@ -356,7 +356,7 @@ etherreset(void) ether->irq = 9; intrenable(VectorPCI+ether->irq, ether->interrupt, ether, ether->tbdf); - i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d", + i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %ld", ctlrno, ether->type, ether->mbps, ether->port, ether->irq); if(ether->mem) i += sprint(buf+i, " addr 0x%luX", PADDR(ether->mem)); diff --git a/alphapc/fns.h b/alphapc/fns.h index f7a7b3cf9b507723142225a4b7888dcc828fc584..701712d2f78bbf32a709c6dc33dc21452c08064a 100644 --- a/alphapc/fns.h +++ b/alphapc/fns.h @@ -71,8 +71,8 @@ void pcisetbme(Pcidev*); void prflush(void); void printinit(void); #define procrestore(p) -#define procsave(p) -#define procsetup(p) ((p)->fpstate = FPinit) +void procsave(Proc*); +void procsetup(Proc*); void restfpregs(FPsave*); uvlong rpcc(uvlong*); void screeninit(void); diff --git a/alphapc/l.s b/alphapc/l.s index 7ffeb090e893cd5ed254c2562b84f77aa7a0520a..b50ebf97135c0482fb722761e3f513ef830cef50 100644 --- a/alphapc/l.s +++ b/alphapc/l.s @@ -1,6 +1,6 @@ #include "mem.h" -#define SP R30 +#define SP R30 #define HI_IPL 6 /* use 7 to disable mchecks */ @@ -23,48 +23,45 @@ clrbss: MOVL R0, bootconf(SB) /* passed in from boot loader */ _fpinit: - MOVQ R0, R16 + MOVQ $1, R16 CALL_PAL $PALwrfen - MOVQ $1, R1 - SLLQ $59, R1 /* normal rounding mode */ + + MOVQ initfpcr(SB), R1 /* MOVQ $0x2800800000000000, R1 */ MOVQ R1, (R30) MOVT (R30), F1 - EXCB MOVT F1, FPCR - EXCB MOVT $0.5, F28 ADDT F28, F28, F29 ADDT F29, F29, F30 - SUBT F28, F28, F0 - MOVT F0, F1 - MOVT F0, F2 - MOVT F0, F3 - MOVT F0, F4 - MOVT F0, F5 - MOVT F0, F6 - MOVT F0, F7 - MOVT F0, F8 - MOVT F0, F9 - MOVT F0, F10 - MOVT F0, F11 - MOVT F0, F12 - MOVT F0, F13 - MOVT F0, F14 - MOVT F0, F15 - MOVT F0, F16 - MOVT F0, F17 - MOVT F0, F18 - MOVT F0, F19 - MOVT F0, F20 - MOVT F0, F21 - MOVT F0, F22 - MOVT F0, F23 - MOVT F0, F24 - MOVT F0, F25 - MOVT F0, F26 - MOVT F0, F27 + MOVT F31, F1 + MOVT F31, F2 + MOVT F31, F3 + MOVT F31, F4 + MOVT F31, F5 + MOVT F31, F6 + MOVT F31, F7 + MOVT F31, F8 + MOVT F31, F9 + MOVT F31, F10 + MOVT F31, F11 + MOVT F31, F12 + MOVT F31, F13 + MOVT F31, F14 + MOVT F31, F15 + MOVT F31, F16 + MOVT F31, F17 + MOVT F31, F18 + MOVT F31, F19 + MOVT F31, F20 + MOVT F31, F21 + MOVT F31, F22 + MOVT F31, F23 + MOVT F31, F24 + MOVT F31, F25 + MOVT F31, F26 + MOVT F31, F27 JSR main(SB) MOVQ $_divq(SB), R31 /* touch _divq etc.; doesn't need to execute */ @@ -380,9 +377,15 @@ TEXT savefpregs(SB), $-8 MOVT F31, 0xF8(R0) MOVT FPCR, F0 MOVT F0, 0x100(R0) + + MOVQ $0, R16 + CALL_PAL $PALwrfen /* disable */ RET TEXT restfpregs(SB), $-8 + MOVQ $1, R16 + CALL_PAL $PALwrfen /* enable */ + MOVT 0x100(R0), F0 MOVT F0, FPCR MOVT 0x00(R0), F0 diff --git a/alphapc/main.c b/alphapc/main.c index e18b73f4e2de93e69beae82d0cb195da4e3f5dcb..e79942b90aca79f59f788423690d3871df10afbe 100644 --- a/alphapc/main.c +++ b/alphapc/main.c @@ -15,6 +15,7 @@ Hwrpb *hwrpb; Bootconf *bootconf; Conf conf; FPsave initfp; +uvlong initfpcr = 0x2800800000000000LL; void main(void) @@ -26,8 +27,6 @@ main(void) clockinit(); confinit(); archinit(); - savefpregs(&initfp); - fpenab(0); mmuinit(); xinit(); printinit(); @@ -47,8 +46,8 @@ main(void) #ifdef NEVER percpu = hwrpb + (hwrpb[40]>>2); -// percpu[32] |= 2; /* restart capable */ - percpu[32] &= ~1; /* boot in progress - not */ +// percpu[32] |= 2; /* restart capable */ + percpu[32] &= ~1; /* boot in progress - not */ // percpu[32] |= (3<<16); /* warm boot requested */ // percpu[32] |= (2<<16); /* cold boot requested */ // percpu[32] |= (4<<16); /* stay halted */ @@ -61,6 +60,8 @@ main(void) chandevreset(); pageinit(); swapinit(); + savefpregs(&initfp); +initfp.fpstatus = 0x68028000; userinit(); schedinit(); } @@ -131,9 +132,7 @@ userinit(void) strcpy(p->text, "*init*"); strcpy(p->user, eve); - p->fpstate = FPinit; - p->fpsave.fpstatus = initfp.fpstatus; - fpenab(0); + procsetup(p); /* * Kernel Stack @@ -170,6 +169,44 @@ userinit(void) ready(p); } +void +procsetup(Proc *p) +{ + p->fpstate = FPinit; + fpenab(0); +} + +void +procsave(Proc *p) +{ + if(p->fpstate == FPactive){ + if(p->state == Moribund) + fpenab(0); + else{ + /* + * Fpsave() stores without handling pending + * unmasked exeptions. Postnote() can't be called + * here as sleep() already has up->rlock, so + * the handling of pending exceptions is delayed + * until the process runs again and generates an + * emulation fault to activate the FPU. + */ + savefpregs(&up->fpsave); +//print("PS=%lux+", up->fpsave.fpstatus); + } + p->fpstate = FPinactive; + } + + /* + * Switch to the prototype page tables for this processor. + * While this processor is in the scheduler, the process could run + * on another processor and exit, returning the page tables to + * the free list where they could be reallocated and overwritten. + * When this processor eventually has to get an entry from the + * trashed page tables it will crash. + */ +} + void exit(int) { diff --git a/alphapc/trap.c b/alphapc/trap.c index 028d159a6fd0f863379dd4264997bdc564f4473d..60029acb520d2de46b379a0a85cf4a5952f33f46 100644 --- a/alphapc/trap.c +++ b/alphapc/trap.c @@ -46,11 +46,6 @@ trap(Ureg *ur) if(user){ up = m->proc; up->dbgreg = ur; - if(up && up->fpstate == FPactive) { - up->fpstate = FPinactive; - savefpregs(&up->fpsave); - fpenab(0); - } } switch ((int)ur->type) { case 1: /* arith */ @@ -82,15 +77,9 @@ trap(Ureg *ur) break; } - splhi(); - if(!user) - return; - - notify(ur); - if(up->fpstate == FPinactive) { - fpenab(1); - restfpregs(&up->fpsave); - up->fpstate = FPactive; + if(user && (up->procctl || up->nnote)){ + splhi(); + notify(ur); } } @@ -500,32 +489,32 @@ syscall(Ureg *aur) up->dbgreg = aur; ur->type = 5; /* for debugging */ - if(up->fpstate == FPactive) { - up->fpsave.fpstatus = getfcr(); - up->fpstate = FPinit; - fpenab(0); + up->scallnr = ur->r0; + + if(up->scallnr == RFORK && up->fpstate == FPactive){ + savefpregs(&up->fpsave); + up->fpstate = FPinactive; +//print("SR=%lux+", up->fpsave.fpstatus); } spllo(); - if(up->procctl) - procctl(up); - - up->scallnr = ur->r0; - up->nerrlab = 0; sp = ur->sp; + up->nerrlab = 0; ret = -1; if(waserror()) goto error; if(up->scallnr >= nsyscall){ - pprint("bad sys call %d pc %lux\n", up->scallnr, (ulong)ur->pc); + pprint("bad sys call %d pc %lux\n", + up->scallnr, (ulong)ur->pc); print("bad sys call %d pc %lux\n", up->scallnr, (ulong)ur->pc); postnote(up, 1, "sys: bad sys call", NDebug); error(Ebadarg); } if(sp & (BY2WD-1)){ /* XXX too weak? */ - pprint("odd sp in sys call pc %lux sp %lux\n", (ulong)ur->pc, (ulong)ur->sp); + pprint("odd sp in sys call pc %lux sp %lux\n", + (ulong)ur->pc, (ulong)ur->sp); postnote(up, 1, "sys: odd stack", NDebug); error(Ebadarg); } @@ -543,19 +532,15 @@ error: up->nerrlab = 0; up->psstate = 0; up->insyscall = 0; - if(up->scallnr == NOTED) /* ugly hack */ + if(up->scallnr == NOTED) /* ugly hack */ noted(ur, &aur, *(ulong*)(sp+2*BY2WD)); /* doesn't return */ - splhi(); if(up->scallnr!=RFORK && (up->procctl || up->nnote)){ ur->r0 = ret; /* load up for noted() */ if(notify(ur)) return ur->r0; } - if(up->fpstate == FPinactive) /* due to race with intr */ - up->fpstate = FPinit; - return ret; } @@ -605,7 +590,6 @@ execregs(ulong entry, ulong ssize, ulong nargs) ur = (Ureg*)up->dbgreg; ur->usp = (ulong)sp; ur->pc = entry; - up->fpsave.fpstatus = initfp.fpstatus; return USTKTOP-BY2WD; /* address of user-level clock */ } @@ -683,18 +667,20 @@ illegal(Ureg *ur) void fen(Ureg *ur) { - ulong fpcr; - - if ((ur->status&UMODE) && up) { - if(up->fpstate == FPinit) { + if(up){ + switch(up->fpstate){ + case FPinit: + restfpregs(&initfp); up->fpstate = FPactive; - fpcr = up->fpsave.fpstatus; - up->fpsave = initfp; - up->fpsave.fpstatus = fpcr; - fpenab(1); +//print("EI=%lux+", initfp.fpstatus); + return; + + case FPinactive: restfpregs(&up->fpsave); + up->fpstate = FPactive; +//print("EIA=%lux+", up->fpsave.fpstatus); return; } } - fataltrap(ur, "trap: floating enable"); /* should never happen */ + fataltrap(ur, "trap: floating enable"); /* should never happen */ } diff --git a/pc/devlml.c b/pc/devlml.c index 56b0e9a029afc8e85eefcf51b0900ad330350bc6..4eef957263df17957f1939f9ddef15f94bf9e938 100644 --- a/pc/devlml.c +++ b/pc/devlml.c @@ -8,6 +8,11 @@ #include "devlml.h" +#define DBGREGS 0x1 +#define DBGREAD 0x2 +#define DBGWRIT 0x4 +int debug = DBGREAD|DBGWRIT; + // Lml 22 driver enum{ @@ -15,6 +20,7 @@ enum{ Q819, Q856, Qreg, + Qmap, Qjvideo, Qjframe, }; @@ -24,6 +30,7 @@ static Dirtab lmldir[]={ "lml819", {Q819}, 0, 0644, "lml856", {Q856}, 0, 0644, "lmlreg", {Qreg}, 0, 0644, + "lmlmap", {Qmap}, 0, 0444, "jvideo", {Qjvideo}, 0, 0666, "jframe", {Qjframe}, 0, 0666, }; @@ -41,12 +48,75 @@ int hdrPos; int nopens; uchar q856[3]; +struct { + ulong pci; + ulong dma; + ulong codedata; +} lmlmap; + static FrameHeader frameHeader = { MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8, { 'L', 'M', 'L', '\0'}, -1, 0, 0, 0, 0 }; +ulong +writel(ulong v, ulong a) { + if (debug&DBGREGS) + pprint("writing %.8lux to %.8lux (%.4lux)\n", + v, a, (ulong)a-pciBaseAddr); + return *(ulong *)a = v; +} + +ushort +writew(ushort v, ulong a) { + if (debug&DBGREGS) + pprint("writing %.4ux to %.8lux (%.4lux)\n", + v, a, (ulong)a-pciBaseAddr); + return *(ushort *)a = v; +} + +uchar +writeb(uchar v, ulong a) { + if (debug&DBGREGS) + pprint("writing %.2ux to %.8lux (%.4lux)\n", + v, a, (ulong)a-pciBaseAddr); + return *(uchar *)a = v; +} + +ulong +readl(ulong a) { + ulong v; + + v = *(ulong*)a; + if (debug&DBGREGS) + pprint("reading %.8lux from %.8lux (%.4lux)\n", + v, a, (ulong)a-pciBaseAddr); + return v; +} + +ushort +readw(ulong a) { + ushort v; + + v = *(ushort*)a; + if (debug&DBGREGS) + pprint("reading %.4ux from %.8lux (%.4lux)\n", + v, a, (ulong)a-pciBaseAddr); + return v; +} + +uchar +readb(ulong a) { + uchar v; + + v = *(uchar*)a; + if (debug&DBGREGS) + pprint("reading %.2ux from %.8lux (%.4lux)\n", + v, a, (ulong)a-pciBaseAddr); + return v; +} + static void i2c_pause(void) { @@ -222,6 +292,7 @@ i2c_rd8(int addr, int sub) if (i2c_wrbyte(addr) == 1 || i2c_wrbyte(sub) == 1) { + if (debug&DBGREGS) pprint("i2c_rd8, failure 1\n"); i2c_stop(); return -1; } @@ -230,6 +301,7 @@ i2c_rd8(int addr, int sub) if (i2c_wrbyte(addr+1) == 1 || i2c_rdbyte(&msb) == 0){ + if (debug&DBGREGS) pprint("i2c_rd8, failure 2\n"); i2c_stop(); return -1; } @@ -303,10 +375,13 @@ vread(Chan *, void *va, long count, vlong pos) { vlong thetime; uchar *buf = va; - //print("devlml::vread() count=%ld pos=%lld\n", count, pos); + if(debug&DBGREAD) + pprint("devlml::vread() count=%ld pos=%lld\n", count, pos); // If we just begin reading a file, pos would never be 0 otherwise if (pos == 0 && hdrPos == -1) { + if(debug&DBGREAD) + pprint("devlml::first read\n"); currentBuffer = -1; currentBufferLength = 0; frameNo = -1; @@ -316,12 +391,18 @@ vread(Chan *, void *va, long count, vlong pos) { // We get to the end of the current buffer, also covers just // open file, since 0 >= -1 if(hdrPos == -1 && pos >= currentBufferLength) { + if(debug&DBGREAD) + pprint("devlml::prepareBuffer\n"); prepareBuffer(codeData, currentBuffer); // if not the first buffer read and single frame mode - return EOF if (currentBuffer != -1 && singleFrame) return 0; + if(debug&DBGREAD) + pprint("devlml::sleep\n"); while((currentBuffer = getProcessedBuffer(codeData)) == -1) sleep(&sleeper, return0, 0); + if(debug&DBGREAD) + pprint("devlml::wokeup\n"); currentBufferLength = getBuffer(codeData, currentBuffer, ¤tBufferPtr, &frameNo); @@ -362,7 +443,7 @@ vread(Chan *, void *va, long count, vlong pos) { memmove(buf + retcount, (char *)currentBufferPtr + pos, cpcount); retcount += cpcount; - //pr_debug("return %d %d\n",cpcount,retcount); + //pr_debug&DBGREGS("return %d %d\n",cpcount,retcount); return retcount; } @@ -511,6 +592,10 @@ lmlreset(void) // Interrupt handler intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf); + lmlmap.pci = pciBaseAddr; + lmlmap.dma = PADDR(codeData); + lmlmap.codedata = (ulong)codeData; + return; } @@ -540,6 +625,7 @@ lmlopen(Chan *c, int omode) case Q819: case Q856: case Qreg: + case Qmap: break; case Qjvideo: case Qjframe: @@ -566,8 +652,12 @@ lmlclose(Chan *c) case Q819: case Q856: case Qreg: + case Qmap: + authclose(c); + break; case Qjvideo: case Qjframe: + nopens = 0; authclose(c); } } @@ -577,7 +667,6 @@ lmlread(Chan *c, void *va, long n, vlong voff) { int i, d; uchar *buf = va; long off = voff; - long v; switch(c->qid.path & ~CHDIR){ @@ -591,7 +680,7 @@ lmlread(Chan *c, void *va, long n, vlong voff) { if ((d = i2c_rd8(BT819Addr, off++)) < 0) break; *buf++ = d; } - return n - i; + return i; case Q856: if (n != 1) return 0; @@ -614,6 +703,15 @@ lmlread(Chan *c, void *va, long n, vlong voff) { return 0; } return 1; + case Qmap: + if (off < 0) + return 0; + for (i = 0; i < n; i++) { + if (off + i > sizeof lmlmap) + break; + buf[i] = ((uchar *)&lmlmap)[off + i]; + } + return i; case Qreg: if (off < 0 || off + n > 0x400) return 0; @@ -627,9 +725,7 @@ lmlread(Chan *c, void *va, long n, vlong voff) { break; case 4: if (off & (n-1)) return 0; - v = readl(pciBaseAddr + off); - *(long *)buf = v; -print("reading %lux at %lux (%lux)\n", v, pciBaseAddr + off, off); + *(long *)buf = readl(pciBaseAddr + off); break; default: return 0; @@ -658,7 +754,7 @@ lmlwrite(Chan *c, void *va, long n, vlong voff) { for (i = n; i > 0; i--) if (i2c_wr8(BT819Addr, off++, *buf++) == 0) break; - return n - i; + return i; case Q856: if (n != 1 || off < 0xda || off + n > 0xe0) return 0; @@ -677,17 +773,20 @@ lmlwrite(Chan *c, void *va, long n, vlong voff) { } return 1; case Qreg: - if (off < 0 || off + n > 0x200 || (off & 0x3)) + if (off < 0 || off + n > 0x400) return 0; switch (n) { case 1: writeb(*buf, pciBaseAddr + off); break; case 2: + if (off & 0x1) + return 0; writew(*(short *)buf, pciBaseAddr + off); break; case 4: -print("writing %lux to %lux (%lux)\n", *(long *)buf, pciBaseAddr + off, off); + if (off & 0x3) + return 0; writel(*(long *)buf, pciBaseAddr + off); break; default: @@ -725,12 +824,16 @@ static void lmlintr(Ureg *, void *) { ulong flags = readl(pciBaseAddr+ZR36057_INTR_STAT); -// print("MjpgDrv_intrHandler stat=0x%08x\n", flags); + if(debug&(DBGREAD|DBGWRIT)) + print("MjpgDrv_intrHandler stat=0x%.8lux\n", flags); // Reset all interrupts from 067 writel(0xff000000, pciBaseAddr + ZR36057_INTR_STAT); - if(flags & ZR36057_INTR_JPEGREP) - wakeup(&sleeper); + if(flags & ZR36057_INTR_JPEGREP) { + if(debug&(DBGREAD|DBGWRIT)) + print("MjpgDrv_intrHandler wakeup\n"); + wakeup(&sleeper); + } return; } diff --git a/pc/devlml.h b/pc/devlml.h index fef9df0542ffb9757296f0c5b9229f215a10292b..5cd88e1c7f2e0a11c010ea7143b2d93ecfa76cba 100644 --- a/pc/devlml.h +++ b/pc/devlml.h @@ -89,13 +89,6 @@ typedef struct { #define FRAGM_FINAL_B 1 #define STAT_BIT 1 -#define writel(v, a) (*(ulong *)(a) = (v)) -#define writew(v, a) (*(ushort *)(a) = (v)) -#define writeb(v, a) (*(uchar *)(a) = (v)) -#define readl(a) (*(ulong *)(a)) -#define readw(a) (*(ushort *)(a)) -#define readb(a) (*(uchar *)(a)) - typedef struct FrameHeader FrameHeader; typedef struct MjpgDrv MjpgDrv; typedef struct Fragment Fragment;