From 59b326371a85d41285987e6efd8a0bc7928480b9 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 4 Apr 1992 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1992-04-04 --- pc/devether.c | 361 +++++++++++++++++++++++++++++++++---------------- pc/kbd.c | 13 -- pc/main.c | 4 +- port/segment.c | 20 ++- 4 files changed, 259 insertions(+), 139 deletions(-) diff --git a/pc/devether.c b/pc/devether.c index ced4dbb0c511227279bb582908cd2f79faa247c6..8dbd982d0b4cd38d248fb4aa7da4ef4e1034e4d3 100644 --- a/pc/devether.c +++ b/pc/devether.c @@ -1,7 +1,7 @@ /* * Western Digital ethernet adapter * BUGS: - * more than one controller + * no more than one controller * fix for different controller types */ #include "u.h" @@ -15,24 +15,35 @@ typedef struct Ctlr Ctlr; typedef struct Pktype Pktype; +typedef struct Ring Ring; enum { IObase = 0x360, + RAMbase = 0xC8000, + RAMsize = 8*1024, + BUFsize = 256, + + Nctlr = 1, + NPktype = 9, /* types/interface */ +}; +/* + * register offsets from IObase + */ +enum { EA = 0x08, /* Ethernet Address in ROM */ ID = 0x0E, /* interface type */ NIC = 0x10, /* National DP8390 Chip */ Cr = NIC+0x00, /* Page [01] */ - Clda0 = NIC+0x01, /* read */ - Pstart = Clda0, /* write */ - Clda1 = NIC+0x02, /* read */ - Pstop = Clda1, /* write */ - Bnry = NIC+0x03, /* Page 0 */ + Pstart = NIC+0x01, /* write */ + Pstop = NIC+0x02, /* write */ + Bnry = NIC+0x03, Tsr = NIC+0x04, /* read */ Tpsr = Tsr, /* write */ - Ncr = NIC+0x05, + Tbcr0 = NIC+0x05, /* write */ + Tbcr1 = NIC+0x06, /* write */ Isr = NIC+0x07, Rbcr0 = NIC+0x0A, Rbcr1 = NIC+0x0B, @@ -47,19 +58,25 @@ enum { Par0 = NIC+0x01, /* Page 1 */ Curr = NIC+0x07, - Mar0 = NIC+0x08, - Mar1 = NIC+0x09, - Mar2 = NIC+0x0A, - Mar3 = NIC+0x0B, - Mar4 = NIC+0x0C, - Mar5 = NIC+0x0D, - Mar6 = NIC+0x0E, - Mar7 = NIC+0x0F, +}; - RAMbase = 0xC8000, +/* + * some register bits + */ +enum { + Prx = 0x01, /* Isr: packet received */ + Ptx = 0x02, /* packet transmitted */ + Rxe = 0x04, /* receive error */ + Txe = 0x08, /* transmit error */ + Ovw = 0x10, /* overwrite warning */ + Rst = 0x80, /* reset status */ +}; - Nctlr = 1, - NPktype = 9, /* types/interface */ +struct Ring { + uchar status; + uchar next; + ushort len; + uchar data[BUFsize-4]; }; /* @@ -81,9 +98,12 @@ struct Ctlr { QLock; Rendez rr; /* rendezvous for an input buffer */ + uchar bnry; + uchar curr; + uchar ovw; Queue rq; - Qlock xl; + QLock xl; Rendez xr; int iobase; /* I/O base address */ @@ -117,6 +137,8 @@ etheroput(Queue *q, Block *bp) Etherpkt *p; Block *nbp; +panic("etheroput\n"); +#ifdef notdef c = ((Pktype *)q->ptr)->ctlr; if(bp->type == M_CTL){ t = q->ptr; @@ -126,8 +148,10 @@ etheroput(Queue *q, Block *bp) t->prom = 1; qlock(c); c->prom++; - if(c->prom == 1) + if(c->prom == 1){ + outb(t->ctlr->iobase+Cr, 0x22); /* Page0, RD2|STA */ outb(c->iobase+Rcr, 0x14); /* PRO|AB */ + } qunlock(c); } freeb(bp); @@ -226,6 +250,7 @@ etheroput(Queue *q, Block *bp) poperror(); enet.outpackets++; +#endif } /* @@ -237,17 +262,17 @@ etheroput(Queue *q, Block *bp) static void etherstopen(Queue *q, Stream *s) { - Ctlr *c = &ctlr[0]; - Pktype *t; - - t = &c->pktype[s->id]; - qlock(t); - RD(q)->ptr = WR(q)->ptr = t; - t->type = 0; - t->q = RD(q); - t->inuse = 1; - t->ctlr = c; - qunlock(t); + Ctlr *cp = &ctlr[0]; + Pktype *pp; + + pp = &cp->pktype[s->id]; + qlock(pp); + RD(q)->ptr = WR(q)->ptr = pp; + pp->type = 0; + pp->q = RD(q); + pp->inuse = 1; + pp->ctlr = cp; + qunlock(pp); } /* @@ -259,23 +284,25 @@ etherstopen(Queue *q, Stream *s) static void etherstclose(Queue *q) { - Pktype *t; - - t = (Pktype *)(q->ptr); - if(t->prom){ - qlock(t->ctlr); - t->ctlr->prom--; - if(t->ctlr->prom == 0) - /* turn off promiscuous mode here */; - qunlock(t->ctlr); + Pktype *pp; + + pp = (Pktype *)(q->ptr); + if(pp->prom){ + qlock(pp->ctlr); + pp->ctlr->prom--; + if(pp->ctlr->prom == 0){ + outb(pp->ctlr->iobase+Cr, 0x22);/* Page0, RD2|STA */ + outb(pp->ctlr->iobase+Rcr, 0x04);/* AB */ + } + qunlock(pp->ctlr); } - qlock(t); - t->type = 0; - t->q = 0; - t->prom = 0; - t->inuse = 0; - netdisown(&t->ctlr->net, t - t->ctlr->pktype); - qunlock(t); + qlock(pp); + pp->type = 0; + pp->q = 0; + pp->prom = 0; + pp->inuse = 0; + netdisown(&pp->ctlr->net, pp - pp->ctlr->pktype); + qunlock(pp); } static Qinfo info = { @@ -287,35 +314,35 @@ static Qinfo info = { }; static int -clonecon(Chan *chan) +clonecon(Chan *c) { - Ctlr *c = &ctlr[0]; - Pktype *t; + Ctlr *cp = &ctlr[0]; + Pktype *pp; - for(t = c->pktype; t < &c->pktype[NPktype]; t++){ - qlock(t); - if(t->inuse || t->q){ - qunlock(t); + for(pp = cp->pktype; pp < &cp->pktype[NPktype]; pp++){ + qlock(pp); + if(pp->inuse || pp->q){ + qunlock(pp); continue; } - t->inuse = 1; - netown(&c->net, t - c->pktype, u->p->user, 0); - qunlock(t); - return t - c->pktype; + pp->inuse = 1; + netown(&cp->net, pp - cp->pktype, u->p->user, 0); + qunlock(pp); + return pp - cp->pktype; } exhausted("ether channels"); } static void -statsfill(Chan *chan, char *p, int n) +statsfill(Chan *c, char *p, int n) { - Ctlr *c = &ctlr[0]; + Ctlr *cp = &ctlr[0]; char buf[256]; sprint(buf, "in: %d\nout: %d\ncrc errs %d\noverflows: %d\nframe errs %d\nbuff errs: %d\noerrs %d\naddr: %.02x:%.02x:%.02x:%.02x:%.02x:%.02x\n", - c->inpackets, c->outpackets, c->crcs, - c->overflows, c->frames, c->buffs, c->oerrs, - c->ea[0], c->ea[1], c->ea[2], c->ea[3], c->ea[4], c->ea[5]); + cp->inpackets, cp->outpackets, cp->crcs, + cp->overflows, cp->frames, cp->buffs, cp->oerrs, + cp->ea[0], cp->ea[1], cp->ea[2], cp->ea[3], cp->ea[4], cp->ea[5]); strncpy(p, buf, n); } @@ -323,96 +350,205 @@ static void typefill(Chan *c, char *p, int n) { char buf[16]; - Pktype *t; + Pktype *pp; - t = &ctlr[0].pktype[STREAMID(c->qid.path)]; - sprint(buf, "%d", t->type); + pp = &ctlr[0].pktype[STREAMID(c->qid.path)]; + sprint(buf, "%d", pp->type); strncpy(p, buf, n); } static void intr(Ureg *ur) { - panic("ether intr\n"); + Ctlr *cp = &ctlr[0]; + uchar isr, curr; + + outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */ + while(isr = inb(cp->iobase+Isr)){ + outb(cp->iobase+Isr, isr); + if(isr & Txe) + cp->oerrs++; + if(isr & Rxe){ + cp->frames += inb(cp->iobase+Cntr0); + cp->crcs += inb(cp->iobase+Cntr1); + cp->buffs += inb(cp->iobase+Cntr2); + } + if(isr & Ptx) + cp->outpackets++; + if(isr & (Txe|Ptx)){ + panic("tx intr\n"); + } + /* + * the receive ring is full. + * put the NIC into loopback mode to give + * kproc a chance to process some packets. + */ + if(isr & Ovw){ + outb(cp->iobase+Cr, 0x21); /* Page0, RD2|STP */ + outb(cp->iobase+Rbcr0, 0); + outb(cp->iobase+Rbcr1, 0); + while((inb(cp->iobase+Isr) & Rst) == 0) + delay(1); + outb(cp->iobase+Tcr, 0x20); /* LB0 */ + outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */ + cp->ovw = 1; + } + /* + * we have received packets. + * this is the only place, other than the init code, + * where we set the controller to Page1. + * we must be careful to reset it back to Page0 in case + * we interrupted some other part of this driver. + */ + if(isr & (Ovw|Prx)){ + outb(cp->iobase+Cr, 0x62); /* Page1, RD2|STA */ + cp->curr = inb(cp->iobase+Curr); + outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */ + wakeup(&cp->rr); + } + } } /* * the following initialisation procedure * is mandatory - * after this, the chip is still offline + * we leave the chip idling on internal loopback */ static void -init(Ctlr *c) +init(Ctlr *cp) { int i; - outb(c->iobase+Cr, 0x21); /* Page0, RD2|STP */ - outb(c->iobase+Dcr, 0x48); /* FT1|LS */ - outb(c->iobase+Rbcr0, 0); - outb(c->iobase+Rbcr1, 0); - outb(c->iobase+Rcr, 0x04); /* AB */ - outb(c->iobase+Tcr, 0); - outb(c->iobase+Bnry, 6); - outb(c->iobase+Pstart, 6); /* 6*256 */ - outb(c->iobase+Pstop, 32); /* 8*1024/256 */ - outb(c->iobase+Isr, 0xFF); - outb(c->iobase+Imr, 0x0F); /* TXEE|RXEE|PTXE|PRXE */ - - outb(c->iobase+Cr, 0x61); /* Page1, RD2|STP */ - for(i = 0; i < sizeof(c->ea); i++) - outb(c->iobase+Par0+i, c->ea[i]); - outb(c->iobase+Curr, 6); /* 6*256 */ + outb(cp->iobase+Cr, 0x21); /* Page0, RD2|STP */ + outb(cp->iobase+Dcr, 0x48); /* FT1|LS */ + outb(cp->iobase+Rbcr0, 0); + outb(cp->iobase+Rbcr1, 0); + outb(cp->iobase+Rcr, 0x04); /* AB */ + outb(cp->iobase+Tcr, 0x20); /* LB0 */ + outb(cp->iobase+Bnry, 6); + cp->bnry = 6; + outb(cp->iobase+Pstart, 6); /* 6*256 */ + outb(cp->iobase+Pstop, 32); /* 8*1024/256 */ + outb(cp->iobase+Isr, 0xFF); + outb(cp->iobase+Imr, 0x1F); /* OVWE|TXEE|RXEE|PTXE|PRXE */ + + outb(cp->iobase+Cr, 0x61); /* Page1, RD2|STP */ + for(i = 0; i < sizeof(cp->ea); i++) + outb(cp->iobase+Par0+i, cp->ea[i]); + outb(cp->iobase+Curr, 6); /* 6*256 */ + cp->curr = 6; + + outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */ + outb(cp->iobase+Tpsr, 0); } void etherreset(void) { - Ctlr *c = &ctlr[0]; + Ctlr *cp = &ctlr[0]; int i; - c->iobase = IObase; - init(c); + cp->iobase = IObase; + init(cp); setvec(Ethervec, intr); - for(i = 0; i < sizeof(c->ea); i++) - c->ea[i] = inb(c->iobase+EA+i); - memset(c->ba, 0xFF, sizeof(c->ba)); - - c->net.name = "ether"; - c->net.nconv = NPktype; - c->net.devp = &info; - c->net.protop = 0; - c->net.listen = 0; - c->net.clone = clonecon; - c->net.ninfo = 2; - c->net.prot = c->prot; - c->net.info[0].name = "stats"; - c->net.info[0].fill = statsfill; - c->net.info[1].name = "type"; - c->net.info[1].fill = typefill; + for(i = 0; i < sizeof(cp->ea); i++) + cp->ea[i] = inb(cp->iobase+EA+i); + memset(cp->ba, 0xFF, sizeof(cp->ba)); + + cp->net.name = "ether"; + cp->net.nconv = NPktype; + cp->net.devp = &info; + cp->net.protop = 0; + cp->net.listen = 0; + cp->net.clone = clonecon; + cp->net.ninfo = 2; + cp->net.prot = cp->prot; + cp->net.info[0].name = "stats"; + cp->net.info[0].fill = statsfill; + cp->net.info[1].name = "type"; + cp->net.info[1].fill = typefill; +} + +static void +etherup(Ctlr *cp, Etherpkt *p, int len) +{ + Block *bp; + Pktype *pp; + int t; + + t = (p->type[0]<<8) | p->type[1]; + for(pp = &cp->pktype[0]; pp < &cp->pktype[NPktype]; pp++){ + /* + * check before locking just to save a lock + */ + if(pp->q == 0 || (t != pp->type && pp->type != -1)) + continue; + + /* + * only a trace channel gets packets destined for other machines + */ + if(pp->type != -1 && p->d[0] != 0xFF && memcmp(p->d, cp->ea, sizeof(p->d))) + continue; + + /* + * check after locking to make sure things didn't + * change under foot + */ + if(canqlock(pp) == 0) + continue; + if(pp->q == 0 || pp->q->next->len > Streamhi || (t != pp->type && pp->type != -1)){ + qunlock(pp); + continue; + } + if(waserror() == 0){ + bp = allocb(len); + memmove(bp->rptr, (uchar *)p, len); + bp->wptr += len; + bp->flags |= S_DELIM; + PUTNEXT(pp->q, bp); + } + poperror(); + qunlock(pp); + } } static int isinput(void *arg) { - Ctlr *c = arg; + Ctlr *cp = arg; - return 0; + return cp->bnry != cp->curr; } static void etherkproc(void *arg) { - Ctlr *c = arg; + Ctlr *cp = arg; + Block *bp; + uchar bnry, curr; + Ring *rp; if(waserror()){ - print("someone noted %s\n", c->name); - c->kproc = 0; + print("%s noted\n", cp->name); + init(cp); + cp->kproc = 0; nexterror(); } - c->kproc = 1; + cp->kproc = 1; for(;;){ - sleep(&c->rr, isinput, c); + sleep(&cp->rr, isinput, cp); + while(bp = getq(&cp->rq)){ + cp->inpackets++; + etherup(cp, (Etherpkt*)bp->rptr, BLEN(bp)); + freeb(bp); + } +#ifdef foo + bnry = inb(cp->iobase+Bnry); + while(bnry != cp->curr){ + rp = &((Ring *)RAMbase)[bnry]; + } +#endif } } @@ -425,8 +561,7 @@ etherinit(void) * put the receiver online * and start the kproc */ - outb(c->iobase+Cr, 0x22); /* Page0, RD2|STA */ - outb(c->iobase+Tpsr, 0); + outb(ctlr[ctlrno].iobase+Tcr, 0); if(ctlr[ctlrno].kproc == 0){ sprint(ctlr[ctlrno].name, "ether%dkproc", ctlrno); kproc(ctlr[ctlrno].name, etherkproc, &ctlr[ctlrno]); diff --git a/pc/kbd.c b/pc/kbd.c index cd5af26ed5b0e63218d2ef876a59c39d6f68fd76..370d1cbd5542e221a4f44e7ff52d9376c141e0dc 100644 --- a/pc/kbd.c +++ b/pc/kbd.c @@ -182,19 +182,6 @@ i8042a20(void) outready(); } -/* - * ask 8042 to reset the 386 - */ -void -i8042reset(void) -{ - outready(); - outb(Cmd, 0xD1); - outready(); - outb(Data, 0x0); - outready(); -} - void kbdinit(void) { diff --git a/pc/main.c b/pc/main.c index bf76dd64aa8152d89dd2b40ef970797c9e58bd03..62842ea3438f0f16799a4795fd8a435bccfba78e 100644 --- a/pc/main.c +++ b/pc/main.c @@ -430,8 +430,8 @@ exit(void) headreset(); /* via headland chip */ break; case At: - i8042reset(); /* via keyboard controller */ - break; + putcr3(0); /* crash and burn */ + for(;;); } } diff --git a/port/segment.c b/port/segment.c index aec30e9bd87ff3a5b80ee1bce198a496081763a1..91639cde6646b25a0e7e28bda04a0afcb687f135 100644 --- a/port/segment.c +++ b/port/segment.c @@ -275,20 +275,18 @@ imagereclaim(void) if(!canqlock(&ireclaim)) /* Somebody is already cleaning the page cache */ return; - for(;;) { - lock(&palloc); - for(p = palloc.head; p; p = p->next) { - if(p->image) + lock(&palloc); + for(p = palloc.head; p; p = p->next) { + if(p->image) + if(p->ref == 0) + if(p->image != &swapimage) { + lockpage(p); if(p->ref == 0) - if(p->image != &swapimage) { - lockpage(p); - if(p->ref == 0) - uncachepage(p); - unlockpage(p); - } + uncachepage(p); + unlockpage(p); } - unlock(&palloc); } + unlock(&palloc); qunlock(&ireclaim); }