From 1656551c58c9b264f5f5d416abab6af3c3c06280 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 13 May 1999 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1999-05-13 --- pc/devlml.c | 102 ++++++++++++++++++++++++++-------------------- pc/devlml.h | 8 ++-- pc/ns16552.h | 30 +++++++++++--- port/devns16552.c | 69 +++++++++++++++++++++++-------- 4 files changed, 139 insertions(+), 70 deletions(-) diff --git a/pc/devlml.c b/pc/devlml.c index 96fa69ea4d25436a5f9c2ce5122531bd2943e6e7..a2a7a6a8ab18ff203807bc76b2644876b906607c 100644 --- a/pc/devlml.c +++ b/pc/devlml.c @@ -11,33 +11,34 @@ // Lml 22 driver enum{ + Qdir, Q819, Q856, Qreg, - Qvideo, + Qjvideo, Qjframe, }; -static Dirtab viddir[]={ -// name, qid, size, mode - "vid819", {Q819}, 0, 0644, - "vid856", {Q856}, 0, 0644, - "vidreg", {Qreg}, 0, 0644, - "video", {Qvideo}, 0, 0666, +static Dirtab lmldir[]={ +// name, qid, size, mode + "lml819", {Q819}, 0, 0644, + "lml856", {Q856}, 0, 0644, + "lmlreg", {Qreg}, 0, 0644, + "jvideo", {Qjvideo}, 0, 0666, "jframe", {Qjframe}, 0, 0666, }; CodeData * codeData; -int currentBuffer; -int currentBufferLength; +int currentBuffer; +int currentBufferLength; void * currentBufferPtr; -int frameNo; +int frameNo; Rendez sleeper; -int singleFrame; -int bufferPrepared; -int hdrPos; -int nopens; +int singleFrame; +int bufferPrepared; +int hdrPos; +int nopens; uchar q856[3]; static FrameHeader frameHeader = { @@ -455,14 +456,13 @@ vwrite(Chan *, void *va, long count, vlong pos) { static void lmlintr(Ureg *, void *); static void -vidreset(void) +lmlreset(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); @@ -472,7 +472,7 @@ vidreset(void) } print("Installing Motion JPEG driver %s\n", MJPG_VERSION); - print("Buffer size %ux\n", sizeof(CodeData)); + print("Buffer at 0x%.8lux, size 0x%.8ux\n", codeData, sizeof(CodeData)); // Get access to DMA memory buffer memset(codeData, 0xAA, sizeof(CodeData)); @@ -491,7 +491,7 @@ vidreset(void) pciPhysBaseAddr = (void *)(pcidev->mem[0].bar & ~0x0F); - print("zr36067 found at %lux\n", pciPhysBaseAddr); + print("zr36067 found at 0x%.8lux", pciPhysBaseAddr); regpa = upamalloc(pcidev->mem[0].bar & ~0x0F, pcidev->mem[0].size, 0); if (regpa == 0) { @@ -499,6 +499,7 @@ vidreset(void) return; } pciBaseAddr = (ulong)KADDR(regpa); + print(", mapped at 0x%.8lux\n", pciBaseAddr); // make sure the device will respond to mem accesses // (pcicmd_master | pcicmd_memory) -- probably superfluous @@ -510,30 +511,29 @@ vidreset(void) // Interrupt handler intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf); - print("LML33 Installed\n"); return; } static Chan* -vidattach(char *spec) +lmlattach(char *spec) { return devattach('V', spec); } static int -vidwalk(Chan *c, char *name) +lmlwalk(Chan *c, char *name) { - return devwalk(c, name, viddir, nelem(viddir), devgen); + return devwalk(c, name, lmldir, nelem(lmldir), devgen); } static void -vidstat(Chan *c, char *dp) +lmlstat(Chan *c, char *dp) { - devstat(c, dp, viddir, nelem(viddir), devgen); + devstat(c, dp, lmldir, nelem(lmldir), devgen); } static Chan* -vidopen(Chan *c, int omode) +lmlopen(Chan *c, int omode) { c->aux = 0; switch(c->qid.path){ @@ -541,7 +541,7 @@ vidopen(Chan *c, int omode) case Q856: case Qreg: break; - case Qvideo: + case Qjvideo: case Qjframe: if (nopens) error(Einuse); @@ -556,28 +556,34 @@ vidopen(Chan *c, int omode) // allow one open total for these two break; } - return devopen(c, omode, viddir, nelem(viddir), devgen); + return devopen(c, omode, lmldir, nelem(lmldir), devgen); } static void -vidclose(Chan *c) +lmlclose(Chan *c) { switch(c->qid.path){ case Q819: case Q856: case Qreg: - case Qvideo: + case Qjvideo: case Qjframe: authclose(c); } } static long -vidread(Chan *c, void *va, long n, vlong off) { +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){ + + case Qdir: + return devdirread(c, (char *)buf, n, lmldir, nelem(lmldir), devgen); - switch(c->qid.path){ case Q819: if (off < 0 || off + n > 0x20) return 0; @@ -621,24 +627,30 @@ vidread(Chan *c, void *va, long n, vlong off) { break; case 4: if (off & (n-1)) return 0; - *(long *)buf = readl(pciBaseAddr + off); + v = readl(pciBaseAddr + off); + *(long *)buf = v; +print("reading %lux at %lux (%lux)\n", v, pciBaseAddr + off, off); break; default: return 0; } return n; - case Qvideo: + case Qjvideo: case Qjframe: return vread(c, buf, n, off); } } static long -vidwrite(Chan *c, void *va, long n, vlong off) { +lmlwrite(Chan *c, void *va, long n, vlong off) { int i; uchar *buf = va; - switch(c->qid.path){ + switch(c->qid.path & ~CHDIR){ + + case Qdir: + error(Eperm); + case Q819: if (off < 0 || off + n > 0x20) return 0; @@ -680,28 +692,28 @@ vidwrite(Chan *c, void *va, long n, vlong off) { return 0; } return n; - case Qvideo: + case Qjvideo: case Qjframe: return vwrite(c, buf, n, off); } } -Dev viddevtab = { +Dev lmldevtab = { 'V', "video", - vidreset, + lmlreset, devinit, - vidattach, + lmlattach, devclone, - vidwalk, - vidstat, - vidopen, + lmlwalk, + lmlstat, + lmlopen, devcreate, - vidclose, - vidread, + lmlclose, + lmlread, devbread, - vidwrite, + lmlwrite, devbwrite, devremove, devwstat, diff --git a/pc/devlml.h b/pc/devlml.h index d22414d902e9c6be74cce242d8394e3c50bd633b..2fe25fc25c8e118df71bacf7d880852defaf9b86 100644 --- a/pc/devlml.h +++ b/pc/devlml.h @@ -12,7 +12,7 @@ // driver. // The number of uS delay in I2C state transitions (probably >= 10) -#define I2C_DELAY 15 +#define I2C_DELAY 50 // The amount of spinning to do before the I2C bus is timed out #define I2C_TIMEOUT 10000000 @@ -89,9 +89,9 @@ 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 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)) diff --git a/pc/ns16552.h b/pc/ns16552.h index 5299f23a35ac44d69b49110ff6fe1a8e399e8b8b..678bde28de5421fc395e89a66177ee7f93557710 100644 --- a/pc/ns16552.h +++ b/pc/ns16552.h @@ -14,7 +14,7 @@ enum #define uartwrreg(u,r,v) outb((u)->port + r, (u)->sticky[r] | (v)) #define uartrdreg(u,r) inb((u)->port + r) -void ns16552setup(ulong, ulong, char*); +void ns16552setup(ulong, ulong, char*, int); void ns16552special(int, int, Queue**, Queue**, int (*)(Queue*, int)); void uartclock(void); /* @@ -93,9 +93,9 @@ ns16552install(void) already = 1; /* first two ports are always there and always the normal frequency */ - ns16552setup(0x3F8, UartFREQ, "eia0"); + ns16552setup(0x3F8, UartFREQ, "eia0", Ns550); intrenable(IrqUART0, ns16552intrx, (void*)0, BUSUNKNOWN); - ns16552setup(0x2F8, UartFREQ, "eia1"); + ns16552setup(0x2F8, UartFREQ, "eia1", Ns550); intrenable(IrqUART1, ns16552intrx, (void*)1, BUSUNKNOWN); addclock0link(uartclock); @@ -133,9 +133,29 @@ ns16552install(void) port = sc->port; for(j=0; j < sc->size; j++){ sprint(name, "eia%d%2.2d", nscard, j); - ns16552setup(port, sc->freq, name); + ns16552setup(port, sc->freq, name, Ns550); port += 8; } + } else if(cistrcmp(sc->type, "turbo650") == 0){ + /* + * port gives base port address for the uart + * irq is interrupt + * freq is the baud rate generator frequency + */ + if(sc->freq == 0) + sc->freq = UartFREQ*4; + sprint(name, "eia%d00", nscard); + ns16552setup(sc->port, sc->freq, name, Ns650); + + /* + * multiply clock speed by 4 + */ + if(sc->mem == 0) + outb(0x2c8, 0); + else + outb(sc->mem, 0); + + intrenable(sc->irq, ns16552intrx, (void*)(nuart-1), BUSUNKNOWN); } else if(cistrcmp(sc->type, "com") == 0 && sc->port != 0x3F8 && sc->port != 0x2F8){ /* * port gives base port address for the uart @@ -145,7 +165,7 @@ ns16552install(void) if(sc->freq == 0) sc->freq = UartFREQ; sprint(name, "eia%d00", nscard); - ns16552setup(sc->port, sc->freq, name); + ns16552setup(sc->port, sc->freq, name, Ns550); intrenable(sc->irq, ns16552intrx, (void*)(nuart-1), BUSUNKNOWN); } nscard++; diff --git a/port/devns16552.c b/port/devns16552.c index fb419d8b407d8a83220046ed56cd69a5414e4a27..bb8527df979b190722e469da90596387ee8c910f 100644 --- a/port/devns16552.c +++ b/port/devns16552.c @@ -22,11 +22,17 @@ enum Ixmt= (1<<1), /* for xmit buffer empty */ Irstat=(1<<2), /* for change in rcv'er status */ Imstat=(1<<3), /* for change in modem status */ + Isleep=(1<<4), /* put in sleep mode; 16C650 */ + Ixoff= (1<<5), /* for xoff received; 16C650 */ + Irts= (1<<6), /* for !rts asserted in auto mode; 16C650 */ + Icts= (1<<7), /* for !cts asserted in auto mode; 16C650 */ Istat= 2, /* interrupt flag (read) */ Fenabd=(3<<6), /* on if fifo's enabled */ + Irctsd=(1<<4), /* auto rts or cts changed state */ Fifoctl=2, /* fifo control (write) */ Fena= (1<<0), /* enable xmit/rcv fifos */ - Ftrig= (1<<6), /* trigger after 4 input characters */ + Ftrig4= (1<<6), /* trigger after 4 input characters */ + Ftrig24= (2<<6), /* trigger after 24 input characters */ Fclear=(3<<1), /* clear xmit & rcv fifos */ Format= 3, /* byte format */ Bits8= (3<<0), /* 8 bits/byte */ @@ -36,12 +42,16 @@ enum Pforce=(1<<5), /* force parity */ Break= (1<<6), /* generate a break */ Dra= (1<<7), /* address the divisor */ + Ers= 0xbf, /* enable enhaced register set on 16C650 */ Mctl= 4, /* modem control */ Dtr= (1<<0), /* data terminal ready */ Rts= (1<<1), /* request to send */ Ri= (1<<2), /* ring */ Inton= (1<<3), /* turn on interrupts */ Loop= (1<<4), /* loop back */ + Intsel=(1<<5), /* NO! open source interrupts; 16C650 */ + Irda= (1<<6), /* infrared interface; 16C650 */ + Cdiv= (1<<7), /* divide clock by four; 16C650 */ Lstat= 5, /* line status */ Inready=(1<<0), /* receive buffer full */ Oerror=(1<<1), /* receiver overrun */ @@ -60,12 +70,20 @@ enum Scratch=7, /* scratchpad */ Dlsb= 0, /* divisor lsb */ Dmsb= 1, /* divisor msb */ + Efr= 2, /* enhanced features for 16C650 */ + Eena= (1<<4), /* enable enhanced bits in normal registers */ + Arts= (1<<6), /* auto rts */ + Acts= (1<<7), /* auto cts */ CTLS= 023, CTLQ= 021, Stagesize= 1024, Nuart= 32, /* max per machine */ + + Ns450= 0, + Ns550, + Ns650, }; typedef struct Uart Uart; @@ -79,7 +97,7 @@ struct Uart char name[NAMELEN]; uchar sticky[8]; /* sticky write register values */ - ulong port; + ulong port; /* io ports */ ulong freq; /* clock frequency */ uchar mask; /* bits/char */ int dev; @@ -96,7 +114,7 @@ struct Uart Lock flock; /* fifo */ uchar fifoon; /* fifo's enabled */ - uchar nofifo; /* earlier chip version with nofifo */ + uchar type; /* chip version */ Lock rlock; /* receive */ uchar istage[Stagesize]; @@ -207,7 +225,6 @@ ns16552bits(Uart *p, int bits) uartwrreg(p, Format, 0); } - /* * toggle DTR */ @@ -255,7 +272,7 @@ ns16552fifoon(Uart *p) { ulong i, x; - if(p->nofifo) + if(p->type < Ns550) return; x = splhi(); @@ -273,11 +290,14 @@ ns16552fifoon(Uart *p) /* turn on fifo */ p->fifoon = 1; - uartwrreg(p, Fifoctl, Fena|Ftrig); + if(p->type == Ns650) + uartwrreg(p, Fifoctl, Fena|Ftrig24); + else + uartwrreg(p, Fifoctl, Fena|Ftrig4); if((p->istat & Fenabd) == 0){ /* didn't work, must be an earlier chip type */ - p->nofifo = 1; + p->type = Ns450; } splx(x); @@ -289,16 +309,32 @@ ns16552fifoon(Uart *p) static void ns16552mflow(Uart *p, int n) { + + ilock(&p->tlock); if(n){ - p->sticky[Iena] |= Imstat; - uartwrreg(p, Iena, 0); - p->modem = 1; - p->cts = uartrdreg(p, Mstat) & Cts; +print("mflow type %d\n", p->type); + if(p->type == Ns650){ + outb(p->port + Format, 0xbf); + outb(p->port + Efr, Eena|Arts|Acts); + uartwrreg(p, Format, 0); + p->cts = 1; + } else { + p->sticky[Iena] |= Imstat; + uartwrreg(p, Iena, 0); + p->modem = 1; + p->cts = uartrdreg(p, Mstat) & Cts; + } } else { - p->sticky[Iena] &= ~Imstat; - uartwrreg(p, Iena, 0); - p->modem = 0; + if(p->type == Ns650){ + outb(p->port + Format, 0xbf); + outb(p->port + Efr, Eena|Arts|Acts); + uartwrreg(p, Format, 0); + } else { + p->sticky[Iena] &= ~Imstat; + uartwrreg(p, Iena, 0); + p->modem = 0; + } p->cts = 1; } iunlock(&p->tlock); @@ -521,7 +557,7 @@ ns16552setup0(Uart *p) * called by main() to create a new duart */ void -ns16552setup(ulong port, ulong freq, char *name) +ns16552setup(ulong port, ulong freq, char *name, int type) { Uart *p; @@ -535,6 +571,7 @@ ns16552setup(ulong port, ulong freq, char *name) nuart++; p->port = port; p->freq = freq; + p->type = type; ns16552setup0(p); } @@ -990,7 +1027,7 @@ ns16552write(Chan *c, void *buf, long n, vlong) * It must be something I don't understand. -- presotto */ lock(&p->flock); - if((p->istat & Fenabd) == 0 && p->fifoon && p->nofifo == 0) + if((p->istat & Fenabd) == 0 && p->fifoon && p->type < Ns550) ns16552fifoon(p); unlock(&p->flock);