From 1cac83d73c4b20e3f73bb85f3051baf7b8d0704e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 23 Apr 1999 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1999-04-23 --- alphapc/arch164.c | 11 +- alphapc/devfloppy.c | 39 +---- alphapc/dma.c | 72 ++++---- alphapc/ether2114x.c | 13 +- alphapc/fns.h | 2 +- alphapc/io.h | 3 + alphapc/main.c | 2 +- pc/devlml.c | 397 ++++++++++++++++++++++++++++++++++++++----- pc/devlml.h | 265 +++++------------------------ 9 files changed, 463 insertions(+), 341 deletions(-) diff --git a/alphapc/arch164.c b/alphapc/arch164.c index f1053d3f5c790ea438d7ccebcd59e05940a3bfe9..467aece130ead151dfcd747c2c17c3950ec8cd99 100644 --- a/alphapc/arch164.c +++ b/alphapc/arch164.c @@ -54,15 +54,17 @@ coreinit(void) } coresave[0] = core[0x140/4]; - /* direct map bottom 2G PCI target space to KZERO in window 1 */ - wind[0x500/4] = KZERO|1; - wind[0x540/4] = 0x7ff00000; +#ifdef notdef + /* direct map bottom 1G PCI target space to KZERO in window 1 */ + wind[0x500/4] = PCIWINDOW|1; + wind[0x540/4] = 0x3ff00000; wind[0x580/4] = 0; /* disable other windows */ wind[0x400/4] = 0; wind[0x600/4] = 0; wind[0x700/4] = 0; +#endif /* notdef */ /* clear error state */ core[0x8200/4] = 0x7ff; @@ -263,6 +265,7 @@ outb2117x(int port, int val) { mb(); *(uchar*)(iobase(port)) = val; + mb(); } void @@ -270,6 +273,7 @@ outs2117x(int port, ushort val) { mb(); *(ushort*)(iobase(port)) = val; + mb(); } void @@ -277,6 +281,7 @@ outl2117x(int port, ulong val) { mb(); *(ulong*)(iobase(port)) = val; + mb(); } void diff --git a/alphapc/devfloppy.c b/alphapc/devfloppy.c index 4e43269bef13add4a342969302389253762b6e71..0fc8b78a22af0ee1112ef844ca2c09ff8236215c 100644 --- a/alphapc/devfloppy.c +++ b/alphapc/devfloppy.c @@ -118,10 +118,8 @@ Dirtab floppydir[]={ static void fldump(void) { -mb(); DPRINT("sra %ux srb %ux dor %ux msr %ux dir %ux\n", inb(Psra), inb(Psrb), inb(Pdor), inb(Pmsr), inb(Pdir)); -mb(); } /* @@ -146,8 +144,6 @@ floppyreset(void) FDrive *dp; FType *t; ulong maxtsize; - - dmainit(DMAchan); floppysetup0(&fl); @@ -163,6 +159,8 @@ floppyreset(void) maxtsize = t->tsize; } + dmainit(DMAchan, maxtsize); + /* * allocate the drive storage */ @@ -174,9 +172,7 @@ floppyreset(void) */ fl.motor = 0; delay(10); -mb(); outb(Pdor, fl.motor | Fintena | Fena); -mb(); delay(10); /* @@ -267,23 +263,15 @@ changed(Chan *c, FDrive *dp) /* * if floppy has changed or first time through */ -mb(); if((inb(Pdir)&Fchange) || dp->vers == 0){ -mb(); DPRINT("changed\n"); fldump(); dp->vers++; floppysetdef(dp); start = dp->t; dp->confused = 1; /* make floppyon recal */ -DPRINT("b4 floppyon:\n"); -fldump(); floppyon(dp); -DPRINT("after floppyon:\n"); -fldump(); floppyseek(dp, dp->t->heads*dp->t->tsize); -DPRINT("after floppyseek:\n"); -fldump(); while(waserror()){ while(++dp->t){ if(dp->t == &floppytype[nelem(floppytype)]) @@ -486,9 +474,7 @@ floppyon(FDrive *dp) /* start motor and select drive */ alreadyon = fl.motor & MOTORBIT(dp->dev); fl.motor |= MOTORBIT(dp->dev); -mb(); outb(Pdor, fl.motor | Fintena | Fena | dp->dev); -mb(); if(!alreadyon){ /* wait for drive to spin up */ tsleep(&dp->r, return0, 0, 750); @@ -500,9 +486,7 @@ mb(); /* set transfer rate */ if(fl.rate != dp->t->rate){ fl.rate = dp->t->rate; -mb(); outb(Pdsr, fl.rate); -mb(); } /* get drive to a known cylinder */ @@ -521,9 +505,7 @@ static void floppyoff(FDrive *dp) { fl.motor &= ~MOTORBIT(dp->dev); -mb(); outb(Pdor, fl.motor | Fintena | Fena | dp->dev); -mb(); } /* @@ -538,10 +520,8 @@ floppycmd(void) fl.nstat = 0; for(i = 0; i < fl.ncmd; i++){ for(tries = 0; ; tries++){ -mb(); if((inb(Pmsr)&(Ffrom|Fready)) == Fready) break; -mb(); if(tries > 1000){ DPRINT("cmd %ux can't be sent (%d)\n", fl.cmd[0], i); fldump(); @@ -552,9 +532,7 @@ mb(); } microdelay(8); /* for machine independence */ } -mb(); outb(Pfdata, fl.cmd[i]); -mb(); } return 0; } @@ -576,9 +554,7 @@ floppyresult(void) for(i = 0; i < sizeof(fl.stat); i++){ /* wait for status byte */ for(tries = 0; ; tries++){ -mb(); s = inb(Pmsr)&(Ffrom|Fready); -mb(); if(s == Fready){ fl.nstat = i; return fl.nstat; @@ -593,10 +569,7 @@ mb(); } microdelay(8); /* for machine independence */ } -mb(); fl.stat[i] = inb(Pfdata); -mb(); -// print("stat[%d]: %.2ux\n", i, fl.stat[i]); } fl.nstat = sizeof(fl.stat); return fl.nstat; @@ -686,9 +659,7 @@ floppyrecal(FDrive *dp) return -1; floppywait(); if(fl.nstat < 2){ -mb(); DPRINT("recalibrate: confused %ux\n", inb(Pmsr)); -mb(); fl.confused = 1; return -1; } @@ -729,13 +700,9 @@ floppyrevive(void) splhi(); fl.ncmd = 1; fl.cmd[0] = 0; -mb(); outb(Pdor, 0); -mb(); delay(10); -mb(); outb(Pdor, Fintena|Fena); -mb(); delay(10); spllo(); fl.motor = 0; @@ -747,9 +714,7 @@ mb(); dp->confused = 1; /* set rate to a known value */ -mb(); outb(Pdsr, 0); -mb(); fl.rate = 0; DPRINT("floppyrevive out\n"); diff --git a/alphapc/dma.c b/alphapc/dma.c index ceea0333c02966191843a70a5c2cf7d035bee654..da9d2107dfdb12c32c79b156f41c2e1c375ffb72 100644 --- a/alphapc/dma.c +++ b/alphapc/dma.c @@ -9,23 +9,6 @@ typedef struct DMAport DMAport; typedef struct DMA DMA; typedef struct DMAxfer DMAxfer; -enum -{ - /* - * the byte registers for DMA0 are all one byte apart - */ - Dma0= 0x00, - Dma0status= Dma0+0x8, /* status port */ - Dma0reset= Dma0+0xD, /* reset port */ - - /* - * the byte registers for DMA1 are all two bytes apart (why?) - */ - Dma1= 0xC0, - Dma1status= Dma1+2*0x8, /* status port */ - Dma1reset= Dma1+2*0xD, /* reset port */ -}; - /* * state of a dma transfer */ @@ -33,6 +16,7 @@ struct DMAxfer { ulong bpa; /* bounce buffer physical address */ void* bva; /* bounce buffer virtual address */ + int blen; /* bounce buffer length */ void* va; /* virtual address destination/src */ long len; /* bytes to be transferred */ int isread; @@ -84,29 +68,42 @@ DMA dma[2] = { * initialisation routines of any devices which require DMA to ensure * the allocated bounce buffers are below the 16MB limit. */ -void -dmainit(int chan) +int +dmainit(int chan, int maxtransfer) { DMA *dp; DMAxfer *xp; - ulong v; + + if(maxtransfer > 64*1024) + maxtransfer = 64*1024; dp = &dma[(chan>>2)&1]; chan = chan & 3; xp = &dp->x[chan]; - if(xp->bva != nil) - return; - - v = (ulong)xalloc(BY2PG+BY2PG); - if(v == 0 || PADDR(v) >= 16*MB){ - print("dmainit: chan %d: 0x%luX out of range\n", chan, v); - xfree((void*)v); - v = 0; + if(xp->bva != nil){ + if(xp->blen < maxtransfer) + return 1; + return 0; } - xp->bva = (void*)ROUND(v, BY2PG); + + xp->bva = xspanalloc(maxtransfer, BY2PG, 64*1024); + if(xp->bva == nil) + return 1; xp->bpa = PADDR(xp->bva); + if(xp->bpa >= 16*MB){ + /* + * This will panic with the current + * implementation of xspanalloc(). + xfree(xp->bva); + */ + xp->bva = nil; + return 1; + } + xp->blen = maxtransfer; xp->len = 0; xp->isread = 0; + + return 0; } /* @@ -133,16 +130,17 @@ dmasetup(int chan, void *va, long len, int isread) /* * if this isn't kernel memory or crossing 64k boundary or above 16 meg - * use the allocated low memory page. + * use the bounce buffer. */ +#ifdef notdef pa = PADDR(va); if((((ulong)va)&0xF0000000) != KZERO || (pa&0xFFFF0000) != ((pa+len)&0xFFFF0000) || pa >= 16*MB) { if(xp->bva == nil) return -1; - if(len > BY2PG) - len = BY2PG; + if(len > xp->blen) + len = xp->blen; if(!isread) memmove(xp->bva, va, len); xp->va = va; @@ -152,17 +150,21 @@ dmasetup(int chan, void *va, long len, int isread) } else xp->len = 0; +#else + pa = PCIWADDR(va); +#endif /* notdef */ /* * this setup must be atomic */ - ilock(dp); mode = (isread ? 0x44 : 0x48) | chan; - outb(dp->mode, mode); /* single mode dma (give CPU a chance at mem) */ - outb(dp->page[chan], pa>>16); + ilock(dp); outb(dp->cbp, 0); /* set count & address to their first byte */ + outb(dp->mode, mode); /* single mode dma (give CPU a chance at mem) */ outb(dp->addr[chan], pa>>dp->shift); /* set address */ outb(dp->addr[chan], pa>>(8+dp->shift)); + outb(dp->page[chan], pa>>16); +outb(0x400|dp->page[chan], pa>>24); outb(dp->count[chan], (len>>dp->shift)-1); /* set count */ outb(dp->count[chan], ((len>>dp->shift)-1)>>8); outb(dp->sbm, chan); /* enable the channel */ diff --git a/alphapc/ether2114x.c b/alphapc/ether2114x.c index 0b025c23d3e1d3b31be4d983ad46de03877ef6dc..e6f41e879e7d10b5e47fac7d6beebbbb54987a7d 100644 --- a/alphapc/ether2114x.c +++ b/alphapc/ether2114x.c @@ -21,9 +21,6 @@ /* nasty PCI DMA hack... */ -#undef PADDR -#define PADDR(a) ((ulong)(a)) - #define DEBUG 0 #define debug if(DEBUG)print @@ -380,7 +377,7 @@ txstart(Ether* ether) ctlr->tdr[PREV(ctlr->tdrh, ctlr->ntdr)].control &= ~Ic; des = &ctlr->tdr[ctlr->tdrh]; des->bp = bp; - des->addr = PADDR(bp->rp); + des->addr = PCIWADDR(bp->rp); des->control |= control; ctlr->ntq++; coherence(); @@ -465,7 +462,7 @@ interrupt(Ureg*, void* arg) des->bp->wp = des->bp->rp+len; etheriq(ether, des->bp, 1); des->bp = bp; - des->addr = PADDR(bp->rp); + des->addr = PCIWADDR(bp->rp); } des->control &= Er; @@ -574,17 +571,17 @@ ctlrinit(Ether* ether) des->bp = allocb(ROUNDUP(sizeof(Etherpkt)+4, 4)); des->status = Own; des->control = ROUNDUP(sizeof(Etherpkt)+4, 4); - des->addr = PADDR(des->bp->rp); + des->addr = PCIWADDR(des->bp->rp); } ctlr->rdr[ctlr->nrdr-1].control |= Er; ctlr->rdrx = 0; - csr32w(ctlr, 3, PADDR(ctlr->rdr)); + csr32w(ctlr, 3, PCIWADDR(ctlr->rdr)); ctlr->tdr = xspanalloc(ctlr->ntdr*sizeof(Des), 8*sizeof(ulong), 0); ctlr->tdr[ctlr->ntdr-1].control |= Er; ctlr->tdrh = 0; ctlr->tdri = 0; - csr32w(ctlr, 4, PADDR(ctlr->tdr)); + csr32w(ctlr, 4, PCIWADDR(ctlr->tdr)); ctlr->mask = Nis|Ais|Fbe|Rwt|Rps|Ru|Ri|Unf|Tjt|Tps|Ti; csr32w(ctlr, 7, ctlr->mask); diff --git a/alphapc/fns.h b/alphapc/fns.h index 7d335cb95274e8b1ed842898e9ba8264bd858fc9..53c899ab7a33e49ac9df248979ae6429864b85ef 100644 --- a/alphapc/fns.h +++ b/alphapc/fns.h @@ -15,7 +15,7 @@ void cserve(ulong, ulong); int dmacount(int); int dmadone(int); void dmaend(int); -void dmainit(int); +int dmainit(int, int); long dmasetup(int, void*, long, int); void evenaddr(ulong); void fataltrap(Ureg *, char *); diff --git a/alphapc/io.h b/alphapc/io.h index 1473d266a32096a8d0e0ed87834faab8830b0c1c..e6e2a484d2254de7eca81c6ba9a3086e3167d979 100644 --- a/alphapc/io.h +++ b/alphapc/io.h @@ -202,3 +202,6 @@ typedef struct SCSIdev { char* type; Scsiio (*reset)(int, ISAConf*); } SCSIdev; + +#define PCIWINDOW 0x40000000 +#define PCIWADDR(va) (PADDR(va)+PCIWINDOW) diff --git a/alphapc/main.c b/alphapc/main.c index 6569202afb1395fb18d010193e4e5d261bc9bb83..4b3d5347e1e6854c4250dd9184e99f29ccb7b34c 100644 --- a/alphapc/main.c +++ b/alphapc/main.c @@ -54,11 +54,11 @@ main(void) percpu[32] |= (0<<16); /* default action */ #endif - pageinit(); procinit0(); initseg(); links(); chandevreset(); + pageinit(); swapinit(); userinit(); schedinit(); diff --git a/pc/devlml.c b/pc/devlml.c index 346bff7f81eb03ec96fb2784bd8fcadd12eaac08..c9efa05bb5f106ec6f150586f3c91c6792625013 100644 --- a/pc/devlml.c +++ b/pc/devlml.c @@ -13,10 +13,8 @@ enum{ Q819, Q856, - Qi22, Q060, Q067, - Qstat, Qvideo, Qjframe, }; @@ -25,10 +23,8 @@ static Dirtab viddir[]={ // name, qid, size, mode "vid819", {Q819}, 0, 0644, "vid856", {Q856}, 0, 0644, - "vidi22", {Qi22}, 0, 0644, "vid060", {Q060}, 0, 0644, "vid067", {Q067}, 0, 0644, - "vidstat", {Qstat}, 0, 0444, "video", {Qvideo}, 0, 0666, "jframe", {Qjframe}, 0, 0666, }; @@ -36,7 +32,318 @@ static Dirtab viddir[]={ CodeData * codeData; MjpgDrv * mjpgDrv; -static void lmlintr(Ureg *ur, void *arg); +static void +lml33_i2c_pause(void) { + + microdelay(I2C_DELAY); +} + +static void +lml33_i2c_waitscl(void) { + int i; + ulong a; + + for(i=0;;i++) { + a = readl(pciBaseAddr + ZR36057_I2C_BUS); + if (a & ZR36057_I2C_SCL) break; + if (i>I2C_TIMEOUT) error(Eio); + } +} + +static void +lml33_i2c_start(void) { + + writel(ZR36057_I2C_SCL|ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); + lml33_i2c_waitscl(); + lml33_i2c_pause(); + + writel(ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); + lml33_i2c_pause(); + + writel(0, pciBaseAddr + ZR36057_I2C_BUS); + lml33_i2c_pause(); +} + +static void +lml33_i2c_stop(void) { + // the clock should already be low, make sure data is + writel(0, pciBaseAddr + ZR36057_I2C_BUS); + lml33_i2c_pause(); + + // set clock high and wait for device to catch up + writel(ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); + lml33_i2c_waitscl(); + lml33_i2c_pause(); + + // set the data high to indicate the stop bit + writel(ZR36057_I2C_SCL|ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); + lml33_i2c_pause(); +} + +static void lml33_i2c_wrbit(int bit) { + if (bit){ + writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); // set data + lml33_i2c_pause(); + writel(ZR36057_I2C_SDA|ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); + lml33_i2c_waitscl(); + lml33_i2c_pause(); + writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); + lml33_i2c_pause(); + } else { + writel(0, pciBaseAddr + ZR36057_I2C_BUS); // clr data + lml33_i2c_pause(); + writel(ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); + lml33_i2c_waitscl(); + lml33_i2c_pause(); + writel(0, pciBaseAddr + ZR36057_I2C_BUS); + lml33_i2c_pause(); + } +} + +static int +lml33_i2c_rdbit(void) { + int bit; + // the clk line should be low + + // ensure we are not asserting the data line + writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); + lml33_i2c_pause(); + + // set the clock high and wait for device to catch up + writel(ZR36057_I2C_SDA|ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); + lml33_i2c_waitscl(); + lml33_i2c_pause(); + + // the data line should be a valid bit + bit = readl(pciBaseAddr+ZR36057_I2C_BUS); + if (bit & ZR36057_I2C_SDA){ + bit = 1; + } else { + bit = 0; + } + + // set the clock low to indicate end of cycle + writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); + lml33_i2c_pause(); + + return bit; +} + +static int +lml33_i2c_rdbyte(uchar *v) { + int i, ack; + uchar res; + + res = 0; + for (i=0;i<8;i++){ + res = res << 1; + res += lml33_i2c_rdbit(); + } + + ack = lml33_i2c_rdbit(); + + *v = res; + + return ack; +} + +static int +lml33_i2c_wrbyte(uchar v) { + int i, ack; + + for (i=0;i<8;i++){ + lml33_i2c_wrbit(v & 0x80); + v = v << 1; + } + + ack = lml33_i2c_rdbit(); + + return ack; +} + +static void +lml33_i2c_write_bytes(uchar addr, uchar sub, uchar *bytes, long num) { + int ack; + long i; + + lml33_i2c_start(); + + ack = lml33_i2c_wrbyte(addr); + if (ack == 1) error(Eio); + + ack = lml33_i2c_wrbyte(sub); + if (ack == 1) error(Eio); + + for(i=0;i>8 & 0x03); + lml33_post_write(guest_id, 2, reg & 0xff); + lml33_post_write(guest_id, 3, v); +} + +static uchar +lml33_zr060_read(int reg) { + int guest_id; + + guest_id = GID060; + + lml33_post_write(guest_id, 1, reg>>8 & 0x03); + lml33_post_write(guest_id, 2, reg & 0xff); + + return lml33_post_read(guest_id, 3); +} + +long +chipread(long addr, char *buf, long n, long off) { + long i; + + for (i = 0; i < n; i++) { + *buf++ = lml33_i2c_rd8(addr, off++); + } + return i; +} + +long +post060read(char *buf, long n, long off) { + long i; + + for (i = 0; i < n; i++) { + *buf++ = lml33_zr060_read(off++); + } + return i; +} + +static void lmlintr(Ureg *, void *); static void vidreset(void) @@ -44,6 +351,11 @@ vidreset(void) ulong regpa; int i; + pcidev = pcimatch(nil, PCI_VENDOR_ZORAN, PCI_DEVICE_ZORAN_36067); + if (pcidev == nil) { + print("No zr36067 found.\n"); + return; + } codeData = (CodeData*)xspanalloc(sizeof(CodeData), BY2PG, 0); if (codeData == nil) { print("devlml: xspanalloc(%ux, %ux, 0)\n", sizeof(CodeData), BY2PG); @@ -61,7 +373,7 @@ vidreset(void) codeData->statCom[i] = PADDR(&(codeData->fragmDescr[i])); codeData->statComInitial[i] = codeData->statCom[i]; codeData->fragmDescr[i].fragmAddress = - (H33_Fragment *)PADDR(&(codeData->frag[i])); + (Fragment *)PADDR(&(codeData->frag[i])); // Length is in double words, in position 1..20 codeData->fragmDescr[i].fragmLength = (FRAGSIZE >> 1) | FRAGM_FINAL_B; } @@ -71,39 +383,29 @@ vidreset(void) print("LML33: can't allocate dynamic memory for MjpgDrv\n"); return; } - if((lml33Board = xallocz(sizeof(LML33Board), 0)) == nil) { - print("LML33: can't allocate dynamic memory for lml33Board\n"); - return; - } print("initializing LML33 board..."); - lml33Board->pcidev = pcimatch(nil, PCI_VENDOR_ZORAN, PCI_DEVICE_ZORAN_36067); - if (lml33Board->pcidev == nil) { - print("zr36067 not found. Install aborted.\n"); - return; - } - lml33Board->pciPhysBaseAddr = - (void *)(lml33Board->pcidev->mem[0].bar & ~0x0F); + pciPhysBaseAddr = (void *)(pcidev->mem[0].bar & ~0x0F); - print("zr36067 found at %lux\n", lml33Board->pciPhysBaseAddr); + print("zr36067 found at %lux\n", pciPhysBaseAddr); - regpa = upamalloc(lml33Board->pcidev->mem[0].bar & ~0x0F, lml33Board->pcidev->mem[0].size, 0); + regpa = upamalloc(pcidev->mem[0].bar & ~0x0F, pcidev->mem[0].size, 0); if (regpa == 0) { print("lml: failed to map registers\n"); return; } - lml33Board->pciBaseAddr = KADDR(regpa); + pciBaseAddr = (ulong)KADDR(regpa); // make sure the device will respond to mem accesses // (pcicmd_master | pcicmd_memory) -- probably superfluous -// pcicfgw32(lml33Board->pcidev, PciPCR, 0x04 | 0x02); +// pcicfgw32(pcidev, PciPCR, 0x04 | 0x02); // set bus latency -- probably superfluous -// pcicfgw8(lml33Board->pcidev, PciLTR, 64); +// pcicfgw8(pcidev, PciLTR, 64); // Interrupt handler - intrenable(lml33Board->pcidev->intl, lmlintr, lml33Board, lml33Board->pcidev->tbdf); + intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf); print("LML33 Installed\n"); return; @@ -134,14 +436,10 @@ vidopen(Chan *c, int omode) switch(c->qid.path){ case Q819: case Q856: - case Qi22: case Q060: case Q067: // allow one open per file break; - case Qstat: - // allow many opens - break; case Qvideo: case Qjframe: // allow one open total for these two @@ -156,10 +454,8 @@ vidclose(Chan *c) switch(c->qid.path){ case Q819: case Q856: - case Qi22: case Q060: case Q067: - case Qstat: case Qvideo: case Qjframe: authclose(c); @@ -167,17 +463,23 @@ vidclose(Chan *c) } static long -vidread(Chan *c, void *buf, long n, vlong off) -{ +vidread(Chan *c, void *buf, long n, vlong off) { + switch(c->qid.path){ case Q819: + if (off < 0 || off + n > 20) + return 0; + return chipread(BT819Addr, buf, n, off); case Q856: - case Qi22: + if (off < 0xda || off + n > 0xe0) + return 0; + return chipread(BT856Addr, buf, n, off); case Q060: + return post060read(buf, n, off); case Q067: - return chipread(c, buf, n, off); - case Qstat: - return statread(c, buf, n, off); + if (off < 0 || off + n > 20 || (off & 0x3) || n != 4) return 0; + *(long *)buf = readl(pciBaseAddr + off); + return 4; case Qvideo: case Qjframe: return videoread(c, buf, n, off); @@ -187,6 +489,26 @@ vidread(Chan *c, void *buf, long n, vlong off) static long vidwrite(Chan *c, void *va, long n, vlong off) { + + switch(c->qid.path){ + case Q819: + if (off < 0 || off + n > 20) + return 0; + return chipwrite(BT819Addr, buf, n, off); + case Q856: + if (off < 0xda || off + n > 0xe0) + return 0; + return chipwrite(BT856Addr, buf, n, off); + case Q060: + return post060write(buf, n, off); + case Q067: + if (off < 0 || off + n > 20 || (off & 0x3) || n != 4) return 0; + writel(*(long *)buf, pciBaseAddr + off); + return 4; + case Qvideo: + case Qjframe: + return videowrite(c, buf, n, off); + } } Dev viddevtab = { @@ -211,9 +533,8 @@ Dev viddevtab = { }; static void -lmlintr(Ureg *ur, void *arg) +lmlintr(Ureg *ur, void *) { - LML33Board *lml33Board = (Lml33Board *)arg; - + } diff --git a/pc/devlml.h b/pc/devlml.h index 268fb6ba78d943abe8a5fbe254e657f6549b49b0..4e93d87feb38e5a2c9e328f31048f9489bbfbddd 100644 --- a/pc/devlml.h +++ b/pc/devlml.h @@ -11,52 +11,56 @@ // The following values can be modified to tune/set default behaviour of the // driver. -// The number of uS delay in I2C state transitions -#define H33_I2C_DELAY 10 +// The number of uS delay in I2C state transitions (probably >= 10) +#define I2C_DELAY 15 // The amount of spinning to do before the I2C bus is timed out -#define H33_I2C_TIMEOUT 10000000 +#define I2C_TIMEOUT 10000000 // The amount of spinning to do before the guest bus is timed out -#define H33_GUEST_TIMEOUT 10000000 +#define GUEST_TIMEOUT 10000000 // The amount of spinning to do before the polling of the still // transfer port is aborted. -#define H33_STILL_TIMEOUT 1000000 +#define STILL_TIMEOUT 1000000 // The following number is the maximum number of cards permited. Each // card found is mapped to a device minor number starting from 0. -#define H33_MAX_CARDS 1 +#define MAX_CARDS 1 // The following is the number of device types supported. -#define H33_DEVICE_COUNT 2 +#define DEVICE_COUNT 2 // The number of 8K pages per buffer, we will allocate four buffers, // locked into memory whenever the device is open so modify with care. -#define H33_PAGES 32 +#define PAGES 32 // The following are the datastructures needed by the device. +#define ZR36057_I2C_BUS 0x044 +// which bit of ZR36057_I2C_BUS is which +#define ZR36057_I2C_SCL 1 +#define ZR36057_I2C_SDA 2 -// A H33_Device records the properties of the various card types supported. +// A Device records the properties of the various card types supported. typedef struct { int number; // The H33_CARDTYPE_ assigned char *card_name; // A string name int zr060addr; // Which guest bus address for the ZR36060 -} H33_Device; +} Device; // An entry in the fragment table typedef struct { ulong address; // bus address of page int length; // length of page -} H33_RingPage; +} RingPage; // The structure that we will use to tell the '57 about the buffers -// The sizeof(H33_RingData) should not exceed page size +// The sizeof(RingData) should not exceed page size typedef struct { void *buffer[4]; ulong i_stat_com[4]; - H33_RingPage ring_pages[4][H33_PAGES]; -} H33_RingData; + RingPage ring_pages[4][PAGES]; +} RingData; typedef struct { int expect; // the buffer the int routine expects next @@ -64,7 +68,7 @@ typedef struct { int filled; // the current number of filled buffers int pages; // the number of complete pages int remainder; // the number of bytes in incomplete page -} H33_RingPtr; +} RingPtr; // The remainder of the #defs are constants which should not need changing. @@ -72,142 +76,17 @@ typedef struct { // these really belong in pci.h #define PCI_VENDOR_ZORAN 0x11de #define PCI_DEVICE_ZORAN_36057 0x6057 +#define PCI_DEVICE_ZORAN_36067 PCI_DEVICE_ZORAN_36057 -// The ZR36057 is mapped into a 4Kbyte block of the address space -// starting at PCI_BASE_ADDRESS_0. Its application specific registers -// are layed out within that space as follows. -#define ZR36057_VFEND_HORCON 0x000 -#define ZR36057_VFEND_VERCON 0x004 -#define ZR36057_VFEND_SCLPIX 0x008 -#define ZR36057_VDISP_TOP 0x00c -#define ZR36057_VDISP_BOT 0x010 -#define ZR36057_VSTRD_GRB 0x014 -#define ZR36057_VDISP_CONF 0x018 -#define ZR36057_MASK_TOP 0x01c -#define ZR36057_MASK_BOT 0x020 -#define ZR36057_OVRLY_CTL 0x024 -#define ZR36057_SYS_PCI 0x028 -#define ZR36057_GPIO_CTL 0x02c -#define ZR36057_MPEG_SRCW 0x030 -#define ZR36057_MPEG_CTFR_CTL 0x034 -#define ZR36057_MPEG_MEM_PTR 0x038 -#define ZR36057_INTR_STAT 0x03c -#define ZR36057_INTR_CTL 0x040 -#define ZR36057_I2C_BUS 0x044 -#define ZR36057_JPEG_MODE_CTL 0x100 -#define ZR36057_JPEG_PROC_CTL 0x104 -#define ZR36057_VSYNC_PARM 0x108 -#define ZR36057_HSYNC_PARM 0x10c -#define ZR36057_HOR_ACTIVE 0x110 -#define ZR36057_VER_ACTIVE 0x114 -#define ZR36057_FIELD_PROC 0x118 -#define ZR36057_JPEG_CODE_BASE 0x11C -#define ZR36057_JPEG_FIFO_THRHLD 0x120 -#define ZR36057_JPEG_GUESTID 0x124 -#define ZR36057_GUEST_CTL 0x12c -#define ZR36057_POST_OFFICE 0x200 -#define ZR36057_STILL_TRANS 0x300 -// The datasheet says that STILL_TRANS is 0x140, but the errata says it's 0x300 - -// which bits of the ZR36057_INTR... mean something special -#define ZR36057_INTR_GIRQ1 0x40000000 -#define ZR36057_INTR_GIRQ0 0x20000000 -#define ZR36057_INTR_CODREP 0x10000000 -#define ZR36057_INTR_JPEGREP 0x08000000 -#define ZR36057_INTR_ENABLE 0x01000000 +#define BT819Addr 0x8a +#define BT856Addr 0x88 +#define GID060 0 -// which bits of ZR36057_I2C_BUS mean something special -#define ZR36057_POST_PEND 0x02000000 -#define ZR36057_POST_TIME 0x01000000 -#define ZR36057_POST_DIR 0x00800000 - -// function of the Guest CS outputs -#define ZR36060_GUEST_DATA 0 -#define ZR36060_GUEST_START 1 -#define ZR36060_GUEST_RESET 3 - -// the still busy bit in ZR36057_STILL_TRANS -// this assumes we are working in little endian mode -#define ZR36057_STILL_BUSY 0x80000000 - -// which bit of ZR36057_I2C_BUS is which -#define ZR36057_I2C_SCL 1 -#define ZR36057_I2C_SDA 2 - -// The ZR36060 registers -#define ZR36060_LOAD 0x000 -#define ZR36060_FIFO_STAT 0x001 -#define ZR36060_INTERFACE 0x002 -#define ZR36060_MODE 0x003 -#define ZR36060_ZERO 0x004 -#define ZR36060_MBCV 0x005 -#define ZR36060_MARKERS_EN 0x006 -#define ZR36060_INT_MASK 0x007 -#define ZR36060_INT_STAT 0x008 -#define ZR36060_TCV_NEThi 0x009 -#define ZR36060_TCV_NETmh 0x00a -#define ZR36060_TCV_NETml 0x00b -#define ZR36060_TCV_NETlo 0x00c -#define ZR36060_TCV_DATAhi 0x00d -#define ZR36060_TCV_DATAmh 0x00e -#define ZR36060_TCV_DATAml 0x00f -#define ZR36060_TCV_DATAlo 0x010 -#define ZR36060_SFhi 0x011 -#define ZR36060_SFlo 0x012 -#define ZR36060_AFhi 0x013 -#define ZR36060_AFme 0x014 -#define ZR36060_AFlo 0x015 -#define ZR36060_ACVhi 0x016 -#define ZR36060_ACVmh 0x017 -#define ZR36060_ACVml 0x018 -#define ZR36060_ACVlo 0x019 -#define ZR36060_ATAhi 0x01a -#define ZR36060_ATAmh 0x01b -#define ZR36060_ATAml 0x01c -#define ZR36060_ATAlo 0x01d -#define ZR36060_ACV_TRUNhi 0x01e -#define ZR36060_ACV_TRUNmh 0x01f -#define ZR36060_ACV_TRUNml 0x020 -#define ZR36060_ACV_TRUNlo 0x021 -#define ZR36060_DEV_ID 0x022 -#define ZR36060_DEV_REV 0x023 -#define ZR36060_TEST_1 0x024 -#define ZR36060_TEST_2 0x025 -#define ZR36060_VCR 0x030 -#define ZR36060_VPR 0x031 -#define ZR36060_SCALE 0x032 -#define ZR36060_BKG_CLR_Y 0x033 -#define ZR36060_BKG_CLR_U 0x034 -#define ZR36060_BKG_CLR_V 0x035 -#define ZR36060_SYNC_VTOTALhi 0x036 -#define ZR36060_SYNC_VTOTALlo 0x037 -#define ZR36060_SYNC_HTOTALhi 0x038 -#define ZR36060_SYNC_HTOTALlo 0x039 -#define ZR36060_SYNC_VSIZE 0x03a -#define ZR36060_SYNC_HSIZE 0x03b -#define ZR36060_SYNC_BVSTART 0x03c -#define ZR36060_SYNC_BHSTART 0x03d -#define ZR36060_SYNC_BVENDhi 0x03e -#define ZR36060_SYNC_BVENDlo 0x03f -#define ZR36060_SYNC_BHENDhi 0x040 -#define ZR36060_SYNC_BHENDlo 0x041 -#define ZR36060_AA_VSTARThi 0x042 -#define ZR36060_AA_VSTARTlo 0x043 -#define ZR36060_AA_VENDhi 0x044 -#define ZR36060_AA_VENDlo 0x045 -#define ZR36060_AA_HSTARThi 0x046 -#define ZR36060_AA_HSTARTlo 0x047 -#define ZR36060_AA_HENDhi 0x048 -#define ZR36060_AA_HENDlo 0x049 -#define ZR36060_SW_VSTARThi 0x04a -#define ZR36060_SW_VSTARTlo 0x04b -#define ZR36060_SW_VENDhi 0x04c -#define ZR36060_SW_VENDlo 0x04d -#define ZR36060_SW_HSTARThi 0x04e -#define ZR36060_SW_HSTARTlo 0x04f -#define ZR36060_SW_HENDhi 0x050 -#define ZR36060_SW_HENDlo 0x051 +#define ZR36057_POST_OFFICE 0x200 +#define ZR36057_POST_PEND 0x02000000 +#define ZR36057_POST_TIME 0x01000000 +#define ZR36057_POST_DIR 0x00800000 #define MB 0x100000 #define NBUF 4 @@ -215,29 +94,36 @@ 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 MjpgDrv MjpgDrv; -typedef struct H33_Fragment H33_Fragment; -typedef struct H33_FragmentTable H33_FragmentTable; +typedef struct Fragment Fragment; +typedef struct FragmentTable FragmentTable; typedef struct CodeData CodeData; typedef struct ML33Board LML33Board; #define FRAGSIZE (MB/NBUF) -struct H33_Fragment { +struct Fragment { uchar fragbytes[FRAGSIZE]; }; -struct H33_FragmentTable { - H33_Fragment * fragmAddress; // Physical address +struct FragmentTable { + Fragment * fragmAddress; // Physical address ulong fragmLength; }; struct CodeData { - char idString[16]; - ulong statCom[4]; // Physical address - ulong statComInitial[4]; // Physical address - H33_FragmentTable fragmDescr[4]; - H33_Fragment frag[4]; + char idString[16]; + ulong statCom[4]; // Physical address + ulong statComInitial[4]; // Physical address + FragmentTable fragmDescr[4]; + Fragment frag[4]; }; extern char static_MjpgDrv_GPL_Notice[]; @@ -249,71 +135,14 @@ struct MjpgDrv { struct wait_queue * intrWaitQ; }; -#define PCI_DEVICE_ZORAN_36067 PCI_DEVICE_ZORAN_36057 - -struct ML33Board -{ - void * pciPhysBaseAddr; - void * pciBaseAddr; - Pcidev * pcidev; -}; - -extern void * H33Addr; -extern LML33Board * lml33Board; +static void * pciPhysBaseAddr; +static ulong pciBaseAddr; +static Pcidev * pcidev; -void LML33Board_ctor(LML33Board*); -void LML33Board_dtor(LML33Board*); -int LML33Board_installInterruptHandler(LML33Board*); -void LML33Board_initHardware(LML33Board*); void LML33Board_mjpegGo(LML33Board*); - -// ZR36067 (PCI controller) register memory access -ulong LML33Board_readL(LML33Board*,int addr); -void LML33Board_writeL(LML33Board*,int addr,ulong); -ushort LML33Board_readW(LML33Board*,int addr); -void LML33Board_writeW(LML33Board*,int addr,ushort); -uchar LML33Board_readB(LML33Board*,int addr); -void LML33Board_writeB(LML33Board*,int addr,uchar); -int LML33Board_getBit(LML33Board*,int addr,int); -void LML33Board_setBit(LML33Board*,int addr,int,int); - -// I2C (video encoder/decoder) manipulation functions -void h33_i2c_pause(LML33Board*); -int h33_i2c_waitscl(LML33Board*); -void h33_i2c_start(LML33Board*); -void h33_i2c_stop(LML33Board*); -void h33_i2c_wrbit(LML33Board*,int bit); -int h33_i2c_rdbit(LML33Board*); -int h33_i2c_wrbyte(LML33Board*,int value); -int h33_i2c_rdbyte(LML33Board*,int* value); -int h33_i2c_probe(LML33Board*,int addr); -int h33_i2c_wr8(LML33Board*,int addr, int sub, int value); -int h33_i2c_rd8(LML33Board*,int addr, int sub, int *value); -int h33_i2c_bt856rd8 (LML33Board*,int addr, int *msb); - -// GPIO access -void gpioSetDirection(int gpIO,int dir); -void gpioSet(int gpIO,int value); -int gpioGet(int gpIO); - -// PostOffice access functions -int h33_post_idle(void); -int h33_post_write(int guest, int reg, int value); -int h33_post_read(int guest, int reg); - -// ZR36060 -void h33_zr060_write(int reg, int value); -int h33_zr060_read(int reg); - void MjpgDrv_ctor(MjpgDrv*); void MjpgDrv_dtor(MjpgDrv*); int MjpgDrv_open(struct inode *iNode, struct file *filePtr); void MjpgDrv_release(struct inode *iNode, struct file *filePtr); void MjpgDrv_intrHandler(int irqNo, void *devId, struct pt_regs *ptRegs); - -void * static_CodeData_map(ulong h33PHighMemory,ulong h33BufferSize); -int CodeData_getReadyBuffer(CodeData*); -int CodeData_getProcessedBuffer(CodeData*this); -int CodeData_getBuffer(CodeData *,int bufferNo,void** bufferPtr,ushort* frameNo); -int CodeData_prepareBuffer(CodeData *, int bufferNo);