From 827f3ac8e5183a72d9b71f81b7b24da459501772 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 22 Sep 2001 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2001-09-22 --- ip/devip.c | 8 +++ ip/il.c | 2 +- ip/ip.h | 2 + ip/tcp.c | 4 +- pc/devusb.c | 21 +++++--- pc/fns.h | 1 + pc/uarti8250.c | 19 +++++++ pc/uartpci.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++++ port/chan.c | 1 + 9 files changed, 179 insertions(+), 10 deletions(-) create mode 100644 pc/uartpci.c diff --git a/ip/devip.c b/ip/devip.c index 8c57776b4669eb9d21865132cdcff5abab8897cc..879ec1906a792022fb6ac100335bd6c61c914f4a 100644 --- a/ip/devip.c +++ b/ip/devip.c @@ -1344,3 +1344,11 @@ ndbwrite(Fs *f, char *a, ulong off, int n) f->ndb[off+n] = 0; return n; } + +ulong +scalednconv(void) +{ + if(cpuserver && conf.npage*BY2PG >= 128*MB) + return Nchans*4; + return Nchans; +} diff --git a/ip/il.c b/ip/il.c index 192976fde4a30632f42e01400f29e1a7269242c8..1ccef41ba19beb848bf485603933f5e31587cd74 100644 --- a/ip/il.c +++ b/ip/il.c @@ -1386,7 +1386,7 @@ ilinit(Fs *f) il->inuse = ilinuse; il->gc = nil; il->ipproto = IP_ILPROTO; - il->nc = Nchans; + il->nc = scalednconv(); il->ptclsize = sizeof(Ilcb); Fsproto(f, il); } diff --git a/ip/ip.h b/ip/ip.h index b89706b942c5a4566f65d04bb3fd5741073900fb..d4197c55f5784e00e86f3377dda21c4f70527bce 100644 --- a/ip/ip.h +++ b/ip/ip.h @@ -305,7 +305,9 @@ Proto* Fsrcvpcolx(Fs*, uchar); char* Fsstdconnect(Conv*, char**, int); char* Fsstdannounce(Conv*, char**, int); char* Fsstdbind(Conv*, char**, int); +ulong scalednconv(void); void closeconv(Conv*); + /* * logging */ diff --git a/ip/tcp.c b/ip/tcp.c index 670eb29b29e462696d9930cf8d71b665535d37ff..fcbf58ade2eaaae74d6128fac9c80e837e6650c4 100644 --- a/ip/tcp.c +++ b/ip/tcp.c @@ -2321,9 +2321,9 @@ tcpinit(Fs *fs) tcp->inuse = tcpinuse; tcp->gc = tcpgc; tcp->ipproto = IP_TCPPROTO; - tcp->nc = Nchans; + tcp->nc = scalednconv(); tcp->ptclsize = sizeof(Tcpctl); - tpriv->stats[MaxConn] = Nchans; + tpriv->stats[MaxConn] = tcp->nc; Fsproto(fs, tcp); } diff --git a/pc/devusb.c b/pc/devusb.c index 5e2060f344695b251d726d948f10f94ce95ee759..a8a7739bcfa305bd10446c554f8846e783275de9 100644 --- a/pc/devusb.c +++ b/pc/devusb.c @@ -204,7 +204,7 @@ struct Endpt { int data01; /* 0=DATA0, 1=DATA1 */ byte eof; ulong csp; - byte isopen; /* ep operations forbidde on open endpoints */ + byte isopen; /* ep operations forbidden on open endpoints */ byte mode; /* OREAD, OWRITE, ORDWR */ byte nbuf; /* number of buffers allowed */ byte iso; @@ -877,8 +877,8 @@ schedendpt(Endpt *e) if (e->isopen){ return -1; } - - e->curblock = allocb(e->maxpkt); + if (e->curblock == nil) + e->curblock = allocb(e->maxpkt); if (e->curblock == nil) panic("schedept: allocb"); e->curbytes = 0; @@ -975,10 +975,8 @@ devendpt(Udev *d, int id, int add) e->ref = 1; e->x = id&0xF; e->id = id; - e->iso = 0; e->sched = -1; e->maxpkt = 8; - e->pollms = 0; e->nbuf = 1; e->dev = d; e->active = 0; @@ -1005,7 +1003,6 @@ freept(Endpt *e) { if(e != nil && decref(e) == 0){ XPRINT("freept(%d,%d)\n", e->dev->x, e->x); - e->isopen = 0; unschedendpt(e); e->dev->ep[e->x] = nil; eptdeactivate(e); @@ -1561,8 +1558,8 @@ usbopen(Chan *c, int omode) } if(schedendpt(e) < 0) error("can't schedule USB endpoint"); + e->isopen++; eptactivate(e); - e->isopen = 1; } incref(d); break; @@ -1599,6 +1596,7 @@ void usbclose(Chan *c) { Udev *d; + int s; if(c->qid.type == QTDIR || c->qid.path < Q3rd) return; @@ -1608,6 +1606,15 @@ usbclose(Chan *c) nexterror(); } d = usbdevice(c); + s = QID(c->qid) - Qep0; + if(s >= 0 && s < nelem(d->ep)){ + Endpt *e; + if((e = d->ep[s]) == nil) { + XPRINT("usbopen failed (endpoint)\n"); + error(Enodev); + } + e->isopen--; + } if(QID(c->qid) == Qctl) d->busy = 0; if(c->flag & COPEN) diff --git a/pc/fns.h b/pc/fns.h index e9030a9410f56a5c81b1c6a16b810f5fbf3e6620..406f150975e01983cf46f376913543286bb7fa4d 100644 --- a/pc/fns.h +++ b/pc/fns.h @@ -43,6 +43,7 @@ int i8042auxcmd(int); void i8042auxenable(void (*)(int, int)); void i8042reset(void); void i8250console(void); +void* i8250alloc(int, int, int); void i8253init(int, int); void i8253enable(void); uvlong i8253read(uvlong*); diff --git a/pc/uarti8250.c b/pc/uarti8250.c index 301f51d5861b973592abf1b5de4989891b1934bd..49463efbebb3df2a770285c1ab48b9f6f8b85534 100644 --- a/pc/uarti8250.c +++ b/pc/uarti8250.c @@ -521,6 +521,11 @@ i8250disable(Uart* uart) ctlr = uart->regs; ctlr->sticky[Ier] = 0; csr8w(ctlr, Ier, 0); + + if(ctlr->iena != 0){ + intrdisable(ctlr->irq, i8250interrupt, uart, ctlr->tbdf, uart->name); + ctlr->iena = 0; + } } static void @@ -554,6 +559,20 @@ i8250enable(Uart* uart, int ie) (*uart->phys->rts)(uart, 1); } +void* +i8250alloc(int io, int irq, int tbdf) +{ + Ctlr *ctlr; + + if((ctlr = malloc(sizeof(Ctlr))) != nil){ + ctlr->io = io; + ctlr->irq = irq; + ctlr->tbdf = tbdf; + } + + return ctlr; +} + static Uart* i8250pnp(void) { diff --git a/pc/uartpci.c b/pc/uartpci.c new file mode 100644 index 0000000000000000000000000000000000000000..5e116abc689b648007df0a6187ad73dca1262d49 --- /dev/null +++ b/pc/uartpci.c @@ -0,0 +1,131 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" + +extern PhysUart i8250physuart; +extern PhysUart pciphysuart; +extern void* i8250alloc(int, int, int); + +static Uart* +uartpci(int ctlrno, Pcidev* p, int barno, int n, int freq, char* name) +{ + int i, io; + void *ctlr; + char buf[64]; + Uart *head, *uart; + + io = p->mem[barno].bar & ~0x01; + snprint(buf, sizeof(buf), "%s%d", pciphysuart.name, ctlrno); + if(ioalloc(io, p->mem[barno].size, 0, buf) < 0){ + print("uartpci: I/O 0x%uX in use\n", io); + return nil; + } + + head = uart = malloc(sizeof(Uart)*n); + + for(i = 0; i < n; i++){ + ctlr = i8250alloc(io, p->intl, p->tbdf); + io += 8; + if(ctlr == nil) + continue; + + uart->regs = ctlr; + snprint(buf, sizeof(buf), "%s.%8.8uX", name, p->tbdf); + kstrdup(&uart->name, buf); + uart->freq = freq; + uart->phys = &i8250physuart; + if(uart != head) + (uart-1)->next = uart; + uart++; + } + + return head; +} + +static Uart* +uartpcipnp(void) +{ + Pcidev *p; + char *name; + int ctlrno, n, subid; + Uart *head, *tail, *uart; + + /* + * Loop through all PCI devices looking for simple serial + * controllers (ccrb == 0x07) and configure the ones which + * are familiar. All suitable devices are configured to + * simply point to the generic i8250 driver. + */ + head = tail = nil; + ctlrno = 0; + for(p = pcimatch(nil, 0, 0); p != nil; p = pcimatch(p, 0, 0)){ + if(p->ccrb != 0x07 || p->ccru != 0) + continue; + + switch((p->did<<16)|p->vid){ + default: + continue; + case (0x9050<<16)|0x10B5: /* Perle PCI-Fast4 */ + /* + * These devices consists of a PLX bridge (the above + * PCI VID+DID) behind which are some 16C654 UARTs. + * Must check the subsystem VID and DID for correct + * match. + */ + subid = pcicfgr16(p, PciSVID); + subid |= pcicfgr16(p, PciSID)<<16; + switch(subid){ + default: + continue; + case (0x0011<<16)|0x12E0: /* Perle PCI-Fast16 */ + n = 16; + name = "PCI-Fast16"; + break; + case (0x0021<<16)|0x12E0: /* Perle PCI-Fast8 */ + n = 8; + name = "PCI-Fast8"; + break; + case (0x0031<<16)|0x12E0: /* Perle PCI-Fast4 */ + n = 4; + name = "PCI-Fast4"; + break; + } + uart = uartpci(ctlrno, p, 2, n, 7372800, name); + if(uart == nil) + continue; + break; + } + + if(head != nil) + tail->next = uart; + else + head = uart; + for(tail = uart; tail->next != nil; tail = tail->next) + ; + ctlrno++; + } + + return head; +} + +PhysUart pciphysuart = { + .name = "UartPCI", + .pnp = uartpcipnp, + .enable = nil, + .disable = nil, + .kick = nil, + .dobreak = nil, + .baud = nil, + .bits = nil, + .stop = nil, + .parity = nil, + .modemctl = nil, + .rts = nil, + .dtr = nil, + .status = nil, + .fifo = nil, +}; diff --git a/port/chan.c b/port/chan.c index 8cc86b022aaa8744c1f76fe6d05d245953ee79f9..40c699ae51ad6166943adbdf64ecffe51bf24de7 100644 --- a/port/chan.c +++ b/port/chan.c @@ -1237,6 +1237,7 @@ if(c->umh != nil){ putmhead(m); cclose(c); c = cnew; + c->name = addelem(c->name, e.elems[e.nelems-1]); break; }else{ /* create failed */ cclose(cnew);