Plan 9 from Bell Labs 1999-05-17
6 files changed, 77 insertions(+), 83 deletions(-) M pc/devlml.c M pc/devlml.h M pc/trap.c M port/portdat.h M port/print.c M port/tod.c
M pc/devlml.c => pc/devlml.c +37 -29
@@ 11,10 11,16 @@ #define DBGREGS 0x1 #define DBGREAD 0x2 #define DBGWRIT 0x4 int debug = DBGREAD|DBGWRIT; int debug = DBGREAD|DBGWRIT|DBGREGS; // Lml 22 driver struct { ulong pci; ulong dma; ulong codedata; } lmlmap; enum{ Qdir, Q819, @@ 29,8 35,8 @@ static Dirtab lmldir[]={ // name, qid, size, mode "lml819", {Q819}, 0, 0644, "lml856", {Q856}, 0, 0644, "lmlreg", {Qreg}, 0, 0644, "lmlmap", {Qmap}, 0, 0444, "lmlreg", {Qreg}, 0x400, 0644, "lmlmap", {Qmap}, sizeof lmlmap, 0444, "jvideo", {Qjvideo}, 0, 0666, "jframe", {Qjframe}, 0, 0666, }; @@ 48,12 54,6 @@ 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'}, @@ 63,24 63,24 @@ static FrameHeader frameHeader = { ulong writel(ulong v, ulong a) { if (debug&DBGREGS) pprint("writing %.8lux to %.8lux (%.4lux)\n", v, a, (ulong)a-pciBaseAddr); pprint("%.8lux (%.8lux) <-- %.8lux\n", a, (ulong)a-pciBaseAddr, v); 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); pprint("%.8lux (%.8lux) <-- %.4ux\n", a, (ulong)a-pciBaseAddr, v); 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); pprint("%.8lux (%.8lux) <-- %.2ux\n", a, (ulong)a-pciBaseAddr, v); return *(uchar *)a = v; } @@ 90,8 90,8 @@ readl(ulong a) { v = *(ulong*)a; if (debug&DBGREGS) pprint("reading %.8lux from %.8lux (%.4lux)\n", v, a, (ulong)a-pciBaseAddr); pprint("%.8lux (%.8lux) --> %.8lux\n", a, (ulong)a-pciBaseAddr, v); return v; } @@ 101,8 101,8 @@ readw(ulong a) { v = *(ushort*)a; if (debug&DBGREGS) pprint("reading %.4ux from %.8lux (%.4lux)\n", v, a, (ulong)a-pciBaseAddr); pprint("%.8lux (%.8lux) --> %.4ux\n", a, (ulong)a-pciBaseAddr, v); return v; } @@ 112,8 112,8 @@ readb(ulong a) { v = *(uchar*)a; if (debug&DBGREGS) pprint("reading %.2ux from %.8lux (%.4lux)\n", v, a, (ulong)a-pciBaseAddr); pprint("%.8lux (%.8lux) --> %.2ux\n", a, (ulong)a-pciBaseAddr, v); return v; } @@ 330,7 330,7 @@ static int prepareBuffer(CodeData * this, int bufferNo) { if(bufferNo >= 0 && bufferNo < NBUF && (this->statCom[bufferNo] & STAT_BIT)) { this->statCom[bufferNo] = this->statComInitial[bufferNo]; return this->fragmDescr[bufferNo].fragmLength; return this->fragdesc[bufferNo].leng; } else return -1; } @@ 354,7 354,7 @@ static int getBuffer(CodeData *this, int bufferNo, void** bufferPtr, int* frameNo) { int codeLength; if(this->statCom[bufferNo] & STAT_BIT) { *bufferPtr = (void*)this->fragmDescr[bufferNo].fragmAddress; *bufferPtr = (void*)this->fragdesc[bufferNo].addr; *frameNo = this->statCom[bufferNo] >> 24; codeLength=((this->statCom[bufferNo] & 0x00FFFFFF) >> 1); return codeLength; @@ 560,12 560,11 @@ lmlreset(void) strncpy(codeData->idString, MJPG_VERSION, strlen(MJPG_VERSION)); for(i = 0; i < NBUF; i++) { codeData->statCom[i] = PADDR(&(codeData->fragmDescr[i])); codeData->statCom[i] = PADDR(&(codeData->fragdesc[i])); codeData->statComInitial[i] = codeData->statCom[i]; codeData->fragmDescr[i].fragmAddress = (Fragment *)PADDR(&(codeData->frag[i])); codeData->fragdesc[i].addr = PADDR(&(codeData->frag[i])); // Length is in double words, in position 1..20 codeData->fragmDescr[i].fragmLength = (FRAGSIZE >> 1) | FRAGM_FINAL_B; codeData->fragdesc[i].leng = (FRAGSIZE >> 1) | FRAGM_FINAL_B; } print("initializing LML33 board..."); @@ 620,6 619,8 @@ lmlstat(Chan *c, char *dp) static Chan* lmlopen(Chan *c, int omode) { int i; c->aux = 0; switch(c->qid.path){ case Q819: @@ 639,7 640,14 @@ lmlopen(Chan *c, int omode) frameNo = 0; bufferPrepared = 0; hdrPos = -1; for (i = 0; i < 4; i++) { codeData->statCom[i] = codeData->statComInitial[i]; // Also memset the buffer with some fill value memset(&(codeData->frag[i]),0x55,sizeof codeData->frag[i]); } // allow one open total for these two intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf); break; } return devopen(c, omode, lmldir, nelem(lmldir), devgen); @@ 707,7 715,7 @@ lmlread(Chan *c, void *va, long n, vlong voff) { if (off < 0) return 0; for (i = 0; i < n; i++) { if (off + i > sizeof lmlmap) if (off + i >= sizeof lmlmap) break; buf[i] = ((uchar *)&lmlmap)[off + i]; } @@ 749,7 757,7 @@ lmlwrite(Chan *c, void *va, long n, vlong voff) { error(Eperm); case Q819: if (off < 0 || off + n > 0x20) if (off < 0 || off + n >= 0x20) return 0; for (i = n; i > 0; i--) if (i2c_wr8(BT819Addr, off++, *buf++) == 0)
M pc/devlml.h => pc/devlml.h +7 -29
@@ 50,28 50,6 @@ typedef struct { int zr060addr; // Which guest bus address for the ZR36060 } Device; // An entry in the fragment table typedef struct { ulong address; // bus address of page int length; // length of page } RingPage; // The structure that we will use to tell the '57 about the buffers // The sizeof(RingData) should not exceed page size typedef struct { void *buffer[4]; ulong i_stat_com[4]; RingPage ring_pages[4][PAGES]; } RingData; typedef struct { int expect; // the buffer the int routine expects next int which; // which ring buffer the read or write uses int filled; // the current number of filled buffers int pages; // the number of complete pages int remainder; // the number of bytes in incomplete page } RingPtr; // The remainder of the #defs are constants which should not need changing. // The PCI vendor and device ids of the zoran chipset on the dc30 @@ 103,16 81,16 @@ struct Fragment { }; struct FragmentTable { // Don't modify this struct, used by h/w Fragment * fragmAddress; // Physical address ulong fragmLength; ulong addr; // Physical address ulong leng; }; struct CodeData { // Don't modify this struct, used by h/w char idString[16]; ulong statCom[4]; // Physical address ulong statComInitial[4]; // Physical address FragmentTable fragmDescr[4]; Fragment frag[4]; char idString[16]; ulong statCom[4]; // Physical address ulong statComInitial[4]; // Physical address FragmentTable fragdesc[4]; Fragment frag[4]; }; static void * pciPhysBaseAddr;
M pc/trap.c => pc/trap.c +6 -1
@@ 681,8 681,13 @@ linkproc(void) void kprocchild(Proc* p, void (*func)(void*), void* arg) { /* * gotolabel() needs a word on the stack in * which to place the return PC used to jump * to linkproc(). */ p->sched.pc = (ulong)linkproc; p->sched.sp = (ulong)p->kstack+KSTACK; p->sched.sp = (ulong)p->kstack+KSTACK-BY2WD; p->kpfun = func; p->kparg = arg;
M port/portdat.h => port/portdat.h +1 -0
@@ 784,3 784,4 @@ extern int nsyscall; #pragma varargck type "V" uchar* #pragma varargck type "E" uchar* #pragma varargck type "M" uchar* #pragma varargck type "p" void*
M port/print.c => port/print.c +10 -0
@@ 18,6 18,7 @@ enum FSHORT = 1<<4, FUNSIGN = 1<<5, FVLONG = 1<<6, FPOINTER = 1<<7, }; int printcol; @@ 64,6 65,7 @@ initfmt(void) fmtindex['o'] = cc; fmtindex['x'] = cc; fmtindex['X'] = cc; fmtindex['p'] = cc; cc++; fmtconv[cc] = cconv; @@ 242,6 244,10 @@ numbconv(va_list *arg, Fconv *fp) case 'x': b = 16; break; case 'p': fp->f3 |= FPOINTER|FUNSIGN; b = 16; break; } f = 0; @@ 272,6 278,10 @@ numbconv(va_list *arg, Fconv *fp) v = (ushort)h; break; case FUNSIGN|FPOINTER: v = (ulong)va_arg(*arg, void*); break; default: v = va_arg(*arg, int); break;
M port/tod.c => port/tod.c +16 -24
@@ 29,9 29,7 @@ struct { Lock; int s1; // time = ((ticks>>s2)*multiplier)>>(s1-s2) vlong multiplier; // ... int s2; // ... vlong multiplier; // t = off + (multiplier*ticks)>>31 vlong hz; // frequency of fast clock vlong last; // last reading of fast clock vlong off; // offset from epoch to last @@ 55,19 53,6 @@ todinit(void) void todsetfreq(vlong f) { // the shift is an attempt to maintain precision // during the caculations. the number of bits in // the multiplier should be log(TODFREQ) + 31 - log(f). // // Freq bits // 167 MHZ 34 // 267 MHZ 33 // 500 MHZ 32 // // in all cases, we need to call todget() at least once // a second to keep the subsequent calculations from // overflowing. ilock(&tod); tod.hz = f; tod.multiplier = (TODFREQ<<31)/f; @@ 81,11 66,12 @@ void todset(vlong t, vlong delta, int n) { ilock(&tod); tod.sstart = tod.send = 0; if(t >= 0){ tod.off = t; tod.last = fastticks(nil); tod.lasttime = 0; tod.delta = 0; tod.sstart = tod.send; } else { if(n <= 0) n = 1; @@ 121,7 107,7 @@ todget(void) diff = ticks - tod.last; // add in correction if(tod.sstart < tod.send){ if(tod.sstart != tod.send){ t = MACHP(0)->ticks; if(t >= tod.send) t = tod.send; @@ 129,13 115,15 @@ todget(void) tod.sstart = t; } // convert to epoch, make sure calculation is unsigned x = (((uvlong)diff) * ((uvlong)tod.multiplier)) >> 31; // convert to epoch x = (diff * tod.multiplier) >> 31; x += tod.off; // protect against overflows (gettod is called at least once a second) tod.last = ticks; tod.off = x; // protect against overflows if(diff > tod.hz){ tod.last = ticks; tod.off = x; } // time can't go backwards if(x < tod.lasttime) @@ 152,9 140,13 @@ todget(void) void todfix(void) { static ulong last; // once a second, make sure we don't overflow if((MACHP(0)->ticks % HZ) == 0) if(MACHP(0)->ticks - last >= HZ){ last = MACHP(0)->ticks; todget(); } } long