From 21f299faa09da03b4e9a1620e705048941df1a22 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 24 Apr 1992 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1992-04-24 --- pc/devether.c | 825 ++++++++++++++++++++++++++++---------------------- pc/devhard.c | 15 +- pc/vga.c | 27 -- 3 files changed, 467 insertions(+), 400 deletions(-) diff --git a/pc/devether.c b/pc/devether.c index c92a34ac3bfaa702fe06a30139760f82cd1b353f..eec09709377d1f4ebdfb7583b1e29e9c51a0207c 100644 --- a/pc/devether.c +++ b/pc/devether.c @@ -1,14 +1,3 @@ -/* - * Western Digital ethernet adapter - * BUGS: - * no more than one controller - * TODO: - * fix for different controller types - * output - * deal with stalling and restarting output on input overflow - * fix magic ring constants - * rewrite per SMC doc - */ #include "u.h" #include "../port/lib.h" #include "mem.h" @@ -18,78 +7,48 @@ #include "io.h" #include "devtab.h" -static int debug; - -typedef struct Ctlr Ctlr; +typedef struct Hw Hw; +typedef struct Buffer Buffer; typedef struct Type Type; -typedef struct Ring Ring; - -enum { - IObase = 0x360, - RAMbase = 0xC8000, - RAMsize = 8*1024, - BUFsize = 256, +typedef struct Ctlr Ctlr; - RINGbase = 6, /* gak */ - RINGsize = 32, /* gak */ +struct Hw { + int addr; /* interface address */ + void *ram; /* interface shared memory address */ + int ramsz; /* interface shared memory size */ + void (*reset)(Ctlr*); + void (*init)(Ctlr*); + void (*mode)(Ctlr*, int); + void (*online)(Ctlr*, int); + void (*receive)(Ctlr*); + void (*transmit)(Ctlr*); + void (*intr)(Ureg*); +}; +static Hw wd8013; - Nctlr = 1, +enum { + Nctlr = 1, /* even one of these is too many */ NType = 9, /* types/interface */ + + Nrb = 16, /* software receive buffers */ + Ntb = 4, /* software transmit buffers */ }; -#define NEXT(x, l) ((((x)+1)%(l)) == 0 ? RINGbase: (((x)+1)%(l))) -#define PREV(x, l) (((x)-1) < RINGbase ? (l-1): ((x)-1)) +#define NEXT(x, l) (((x)+1)%(l)) +#define OFFSETOF(t, m) ((unsigned)&(((t*)0)->m)) +#define HOWMANY(x, y) (((x)+((y)-1))/(y)) +#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y)) -/* - * 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] */ - - Pstart = NIC+0x01, /* write */ - Pstop = NIC+0x02, /* write */ - Bnry = NIC+0x03, - Tsr = NIC+0x04, /* read */ - Tpsr = Tsr, /* write */ - Tbcr0 = NIC+0x05, /* write */ - Tbcr1 = NIC+0x06, /* write */ - Isr = NIC+0x07, - Rbcr0 = NIC+0x0A, - Rbcr1 = NIC+0x0B, - Rsr = NIC+0x0C, /* read */ - Rcr = Rsr, /* write */ - Cntr0 = NIC+0x0D, /* read */ - Tcr = Cntr0, /* write */ - Cntr1 = NIC+0x0E, /* read */ - Dcr = Cntr1, /* write */ - Cntr2 = NIC+0x0F, /* read */ - Imr = Cntr2, /* write */ - - Par0 = NIC+0x01, /* Page 1 */ - Curr = NIC+0x07, +struct Buffer { + uchar owner; + uchar busy; + ushort len; + Etherpkt pkt; }; -/* - * 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 */ -}; - -struct Ring { - uchar status; - uchar next; - uchar len0; - uchar len1; - uchar data[BUFsize-4]; + Host = 0, /* buffer owned by host */ + Interface = 1, /* buffer owned by interface */ }; /* @@ -105,74 +64,122 @@ struct Type { }; /* - * per ethernet + * per ethernet */ struct Ctlr { QLock; - Ring *ring; - Rendez rr; /* rendezvous for an input buffer */ - Queue rq; - uchar bnry; - uchar curr; + Hw *hw; - Etherpkt *xpkt; - QLock xl; - Rendez xr; - uchar xbusy; + ushort nrb; /* number of software receive buffers */ + ushort ntb; /* number of software transmit buffers */ + Buffer *rb; /* software receive buffers */ + Buffer *tb; /* software transmit buffers */ - int iobase; /* I/O base address */ + uchar ea[6]; /* ethernet address */ + uchar ba[6]; /* broadcast address */ - Type type[NType]; - uchar ea[6]; - uchar ba[6]; + Rendez rr; /* rendezvous for a receive buffer */ + QLock rlock; /* semaphore on rc */ + ushort rh; /* first receive buffer belonging to host */ + ushort ri; /* first receive buffer belonging to interface */ + + Rendez tr; /* rendezvous for a transmit buffer */ + QLock tlock; /* semaphore on tc */ + ushort th; /* first transmit buffer belonging to host */ + ushort ti; /* first transmit buffer belonging to interface */ - uchar prom; /* true if promiscuous mode */ - uchar kproc; /* true if kproc started */ - char name[NAMELEN]; /* name of kproc */ + Type type[NType]; + uchar prom; /* true if promiscuous mode */ + uchar kproc; /* true if kproc started */ + char name[NAMELEN]; /* name of kproc */ Network net; Netprot prot[NType]; + Queue lbq; /* software loopback packet queue */ + int inpackets; int outpackets; - int crcs; /* input crc errors */ - int oerrs; /* output errors */ - int frames; /* framing errors */ - int overflows; /* packet overflows */ - int buffs; /* buffering errors */ + int crcs; /* input crc errors */ + int oerrs; /* output errors */ + int frames; /* framing errors */ + int overflows; /* packet overflows */ + int buffs; /* buffering errors */ }; static Ctlr ctlr[Nctlr]; -static Etherpkt txpkt; +void +etherinit(void) +{ +} -static void -xmemmove(void *to, void *from, long len) +Chan* +etherclone(Chan *c, Chan *nc) { - ushort *t, *f; - int s; - Ctlr *cp = &ctlr[0]; - uchar reg; + return devclone(c, nc); +} - t = to; - f = from; - len = (len+1)/2; - s = splhi(); - reg = inb(cp->iobase+0x05); - outb(cp->iobase+Imr, 0); - outb(cp->iobase+0x05, 0x80|reg); - while(len--) - *t++ = *f++; - outb(cp->iobase+0x05, reg); - outb(cp->iobase+Imr, 0x1F); - splx(s); +int +etherwalk(Chan *c, char *name) +{ + return netwalk(c, name, &ctlr[0].net); +} + +void +etherstat(Chan *c, char *dp) +{ + netstat(c, dp, &ctlr[0].net); +} + +Chan* +etheropen(Chan *c, int omode) +{ + return netopen(c, omode, &ctlr[0].net); +} + +void +ethercreate(Chan *c, char *name, int omode, ulong perm) +{ + error(Eperm); +} + +void +etherclose(Chan *c) +{ + if(c->stream) + streamclose(c); +} + +long +etherread(Chan *c, void *a, long n, ulong offset) +{ + return netread(c, a, n, offset, &ctlr[0].net); +} + +long +etherwrite(Chan *c, char *a, long n, ulong offset) +{ + return streamwrite(c, a, n, 0); +} + +void +etherremove(Chan *c) +{ + error(Eperm); +} + +void +etherwstat(Chan *c, char *dp) +{ + netwstat(c, dp, &ctlr[0].net); } static int -isxfree(void *arg) +isobuf(void *arg) { Ctlr *cp = arg; - return cp->xbusy == 0; + cp->tb[cp->th].owner == Host; } static void @@ -182,25 +189,23 @@ etheroput(Queue *q, Block *bp) int len, n; Type *tp; Etherpkt *p; + Buffer *tb; Block *nbp; - cp = ((Type *)q->ptr)->ctlr; if(bp->type == M_CTL){ tp = q->ptr; if(streamparse("connect", bp)) tp->type = strtol((char *)bp->rptr, 0, 0); else if(streamparse("promiscuous", bp)) { tp->prom = 1; - qlock(cp); - cp->prom++; - if(cp->prom == 1) - outb(cp->iobase+Rcr, 0x14); /* PRO|AB */ - qunlock(cp); + (*tp->ctlr->hw->mode)(tp->ctlr, 1); } freeb(bp); return; } + cp = ((Type *)q->ptr)->ctlr; + /* * give packet a local address, return upstream if destined for * this machine. @@ -212,7 +217,7 @@ etheroput(Queue *q, Block *bp) if(memcmp(cp->ea, p->d, sizeof(cp->ea)) == 0){ len = blen(bp); if (bp = expandb(bp, len >= ETHERMINTU ? len: ETHERMINTU)){ - putq(&cp->rq, bp); + putq(&cp->lbq, bp); wakeup(&cp->rr); } return; @@ -222,7 +227,7 @@ etheroput(Queue *q, Block *bp) nbp = copyb(bp, len); if(nbp = expandb(nbp, len >= ETHERMINTU ? len: ETHERMINTU)){ nbp->wptr = nbp->rptr+len; - putq(&cp->rq, nbp); + putq(&cp->lbq, nbp); wakeup(&cp->rr); } } @@ -230,20 +235,22 @@ etheroput(Queue *q, Block *bp) /* * only one transmitter at a time */ - qlock(&cp->xl); + qlock(&cp->tlock); if(waserror()){ freeb(bp); - qunlock(&cp->xl); + qunlock(&cp->tlock); nexterror(); } /* - * Wait till we get an output buffer + * wait till we get an output buffer. + * should try to restart. */ - tsleep(&cp->xr, isxfree, cp, 1000); - if(isxfree(cp) == 0) - print("Tx wedged\n"); - p = &txpkt; +print("oput sleep\n"); + sleep(&cp->tr, isobuf, cp); + + tb = &cp->tb[cp->th]; + p = &tb->pkt; /* * copy message into buffer @@ -271,18 +278,20 @@ etheroput(Queue *q, Block *bp) * give packet a local address */ memmove(p->s, cp->ea, sizeof(cp->ea)); - xmemmove(cp->xpkt, p, len); /* + * set up the transmit buffer and * start the transmission */ - outb(cp->iobase+Tbcr0, len & 0xFF); - outb(cp->iobase+Tbcr1, (len>>8) & 0xFF); - outb(cp->iobase+Cr, 0x26); /* Page0|TXP|STA */ - cp->xbusy = 1; + cp->outpackets++; + tb->len = len; + tb->owner = Interface; + cp->th = NEXT(cp->th, cp->ntb); + (*cp->hw->transmit)(cp); freeb(bp); - qunlock(&cp->xl); + qunlock(&cp->tlock); +print("oput done\n"); poperror(); } @@ -320,13 +329,8 @@ etherstclose(Queue *q) Type *tp; tp = (Type *)(q->ptr); - if(tp->prom){ - qlock(tp->ctlr); - tp->ctlr->prom--; - if(tp->ctlr->prom == 0) - outb(tp->ctlr->iobase+Rcr, 0x04);/* AB */ - qunlock(tp->ctlr); - } + if(tp->prom) + (*tp->ctlr->hw->mode)(tp->ctlr, 0); qlock(tp); tp->type = 0; tp->q = 0; @@ -389,129 +393,12 @@ typefill(Chan *c, char *p, int n) } static void -intr(Ureg *ur) -{ - Ctlr *cp = &ctlr[0]; - uchar isr, bnry, curr; - - 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->overflows += inb(cp->iobase+Cntr2); - } - if(isr & Ptx) - cp->outpackets++; - if(isr & (Txe|Ptx)){ - cp->xbusy = 0; - wakeup(&cp->xr); - } - if(isr & Ovw){ - bnry = inb(cp->iobase+Bnry); - outb(cp->iobase+bnry, bnry); - cp->buffs++; - } - /* - * we have received packets. - * this is the only place, other than the init code, - * where we set the controller to Page1. - * we must be sure to reset it back to Page0 in case - * we interrupted some other part of this driver. - */ - if(isr & (Rxe|Prx)){ - outb(cp->iobase+Cr, 0x62); /* Page1, RD2|STA */ - cp->curr = inb(cp->iobase+Curr); - outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */ -if(debug) - print("I%d/%d/%d|", isr, cp->curr, cp->bnry); - wakeup(&cp->rr); - } - } -} - -/* - * the following initialisation procedure - * is mandatory. - * we leave the chip idling on internal loopback - * and pointing to Page0. - */ -static void -init(Ctlr *cp) -{ - int i; - - 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 */ - cp->bnry = RINGbase; - outb(cp->iobase+Bnry, cp->bnry); - cp->ring = (Ring*)(KZERO|RAMbase); - outb(cp->iobase+Pstart, RINGbase); - outb(cp->iobase+Pstop, RINGsize); - 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]); - cp->curr = cp->bnry+1; - outb(cp->iobase+Curr, cp->curr); - - outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */ - outb(cp->iobase+Tpsr, 0); - cp->xpkt = (Etherpkt*)(KZERO|RAMbase); -} - -void -etherreset(void) +etherup(Ctlr *cp, Etherpkt *p, int len) { - Ctlr *cp = &ctlr[0]; - int i; - uchar reg; - - cp->iobase = IObase; - reg = 0x40|inb(cp->iobase); - outb(cp->iobase, reg); - reg = 0x40|inb(cp->iobase+0x05); - outb(cp->iobase+0x05, reg); -for(i = 0; i < 0x10; i++) - print("#%2.2ux ", inb(cp->iobase+i)); -print("\n"); - for(i = 0; i < sizeof(cp->ea); i++) - cp->ea[i] = inb(cp->iobase+EA+i); - init(cp); - setvec(Ethervec, intr); - memset(cp->ba, 0xFF, sizeof(cp->ba)); - - cp->net.name = "ether"; - cp->net.nconv = NType; - 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, uchar *d0, int len0, uchar *d1, int len1) -{ - Etherpkt *p; Block *bp; Type *tp; int t; - p = (Etherpkt*)d0; t = (p->type[0]<<8)|p->type[1]; for(tp = &cp->type[0]; tp < &cp->type[NType]; tp++){ /* @@ -537,11 +424,9 @@ etherup(Ctlr *cp, uchar *d0, int len0, uchar *d1, int len1) continue; } if(waserror() == 0){ - bp = allocb(len0+len1); - xmemmove(bp->rptr, d0, len0); - if(len1) - xmemmove(bp->rptr+len0, d1, len1); - bp->wptr += len0+len1; + bp = allocb(len); + memmove(bp->rptr, p, len); + bp->wptr += len; bp->flags |= S_DELIM; PUTNEXT(tp->q, bp); } @@ -550,181 +435,389 @@ etherup(Ctlr *cp, uchar *d0, int len0, uchar *d1, int len1) } } -static void -printpkt(uchar bnry, ushort len, Etherpkt *p) -{ - int i; - - print("%.2ux: %.4d d(%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux)s(%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux)t(%.2ux %.2ux)\n", - bnry, len, - p->d[0], p->d[1], p->d[2], p->d[3], p->d[4], p->d[5], - p->s[0], p->s[1], p->s[2], p->s[3], p->s[4], p->s[5], - p->type[0], p->type[1]); -} - static int isinput(void *arg) { Ctlr *cp = arg; - return NEXT(cp->bnry, RINGsize) != cp->curr; + return cp->lbq.first || cp->rb[cp->ri].owner == Host; } static void etherkproc(void *arg) { Ctlr *cp = arg; + Buffer *rb; Block *bp; - uchar bnry, curr; - Ring *rp; - int len0, len1; if(waserror()){ print("%s noted\n", cp->name); - init(cp); + (*cp->hw->init)(cp); cp->kproc = 0; nexterror(); } cp->kproc = 1; for(;;){ - sleep(&cp->rr, isinput, cp); + qlock(&cp->rlock); + /* * process any internal loopback packets */ - while(bp = getq(&cp->rq)){ + while(bp = getq(&cp->lbq)){ cp->inpackets++; - etherup(cp, bp->rptr, BLEN(bp), 0, 0); + etherup(cp, (Etherpkt*)bp->rptr, BLEN(bp)); freeb(bp); } /* * process any received packets */ - bnry = NEXT(cp->bnry, RINGsize); - while(bnry != cp->curr){ - rp = &cp->ring[bnry]; + while(cp->rb[cp->rh].owner == Host){ cp->inpackets++; - len0 = ((rp->len1<<8)+rp->len0)-4; - len1 = 0; + rb = &cp->rb[cp->rh]; + etherup(cp, &rb->pkt, rb->len); + rb->owner = Interface; + cp->rh = NEXT(cp->rh, Nrb); + } - if(rp->data+len0 >= (uchar*)&cp->ring[RINGsize]){ - len1 = rp->data+len0 - (uchar*)&cp->ring[RINGsize]; - len0 = (uchar*)&cp->ring[RINGsize] - rp->data; - } + qunlock(&cp->rlock); + sleep(&cp->rr, isinput, cp); + } +} - etherup(cp, rp->data, len0, (uchar*)&cp->ring[RINGbase], len1); +void +etherreset(void) +{ + Ctlr *cp = &ctlr[0]; + cp->hw = &wd8013; + (*cp->hw->reset)(cp); + memset(cp->ba, 0xFF, sizeof(cp->ba)); -if(debug) - print("K%d/%d/%d|", bnry, rp->next, PREV(rp->next, RINGsize)); - bnry = rp->next; - cp->bnry = PREV(bnry, RINGsize); - outb(cp->iobase+Bnry, cp->bnry); - } - } + cp->net.name = "ether"; + cp->net.nconv = NType; + 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; } -void -etherinit(void) +Chan* +etherattach(char *spec) { int ctlrno = 0; + Ctlr *cp = &ctlr[ctlrno]; + int i; + + cp->rh = 0; + cp->ri = 0; + for(i = 0; i < cp->nrb; i++) + cp->rb[i].owner = Interface; + + cp->th = 0; + cp->ti = 0; + for(i = 0; i < cp->ntb; i++) + cp->tb[i].owner = Host; /* * put the receiver online * and start the kproc */ - 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]); + + (*cp->hw->online)(cp, 1); + if(cp->kproc == 0){ + sprint(cp->name, "ether%dkproc", ctlrno); + kproc(cp->name, etherkproc, cp); } -} - -Chan * -etherattach(char *spec) -{ return devattach('l', spec); } -Chan * -etherclone(Chan *c, Chan *nc) -{ - return devclone(c, nc); -} +typedef struct { + uchar msr; /* 83C584 bus interface */ + uchar icr; + uchar iar; + uchar bio; + uchar irr; + uchar laar; + uchar ijr; + uchar gp2; + uchar lan[6]; + uchar id; + uchar cksum; + + union { /* DP8390/83C690 LAN controller */ + struct { /* Page0, read */ + uchar cr; + uchar clda0; + uchar clda1; + uchar bnry; + uchar tsr; + uchar ncr; + uchar fifo; + uchar isr; + uchar crda0; + uchar crda1; + uchar pad0x0A; + uchar pad0x0B; + uchar rsr; + uchar cntr0; + uchar cntr1; + uchar cntr2; + } r; + struct { /* Page0, write */ + uchar cr; + uchar pstart; + uchar pstop; + uchar bnry; + uchar tpsr; + uchar tbcr0; + uchar tbcr1; + uchar isr; + uchar rsar0; + uchar rsar1; + uchar rbcr0; + uchar rbcr1; + uchar rcr; + uchar tcr; + uchar dcr; + uchar imr; + } w; + struct { /* Page1, read/write */ + uchar cr; + uchar par[6]; + uchar curr; + uchar mar[8]; + }; + }; +} Wd8013; + +#define IN(hw, m) inb((hw)->addr+OFFSETOF(Wd8013, m)) +#define OUT(hw, m, x) outb((hw)->addr+OFFSETOF(Wd8013, m), (x)) -int -etherwalk(Chan *c, char *name) +/* + */ +static void +wd8013reset(Ctlr *cp) { - return netwalk(c, name, &ctlr[0].net); -} + Hw *hw = cp->hw; + int i; + uchar msr; -void -etherstat(Chan *c, char *dp) -{ - netstat(c, dp, &ctlr[0].net); -} +print("reset\n"); + cp->rb = ialloc(sizeof(Buffer)*Nrb, 0); + cp->nrb = Nrb; + cp->tb = ialloc(sizeof(Buffer)*Ntb, 0); + cp->ntb = Ntb; -Chan * -etheropen(Chan *c, int omode) + msr = IN(hw, msr); + OUT(hw, msr, 0x40|msr); { - return netopen(c, omode, &ctlr[0].net); +int addr = hw->addr; + +for(i = 0; i < 16; i++){ + print("#%2.2ux ", inb(addr)); + addr++; +} +print("\n"); +} + for(i = 0; i < sizeof(cp->ea); i++) + cp->ea[i] = IN(hw, lan[i]); + (*hw->init)(cp); + setvec(Ethervec, hw->intr); } -void -ethercreate(Chan *c, char *name, int omode, ulong perm) +/* + * we leave the chip idling on internal loopback + * and pointing to Page0. + */ +static void +wd8013init(Ctlr *cp) { - error(Eperm); + Hw *hw = cp->hw; + int i; + uchar bnry; + +print("init %d %d\n", HOWMANY(sizeof(Etherpkt), 256), HOWMANY(hw->ramsz, 256)); + OUT(hw, w.cr, 0x21); /* Page0|RD2|STP */ + OUT(hw, w.dcr, 0x48); /* FT1|LS */ + OUT(hw, w.rbcr0, 0); + OUT(hw, w.rbcr1, 0); + OUT(hw, w.rcr, 0x04); /* AB */ + OUT(hw, w.tcr, 0x20); /* LB0 */ + + bnry = HOWMANY(sizeof(Etherpkt), 256); + OUT(hw, w.bnry, bnry); + OUT(hw, w.pstart, bnry); + OUT(hw, w.pstop, HOWMANY(hw->ramsz, 256)); + OUT(hw, w.isr, 0xFF); + OUT(hw, w.imr, 0x1F); /* OVWE|TXEE|RXEE|PTXE|PRXE */ + + OUT(hw, w.cr, 0x61); /* Page1|RD2|STP */ + for(i = 0; i < sizeof(cp->ea); i++) + OUT(hw, par[i], cp->ea[i]); + OUT(hw, curr, bnry+1); + + OUT(hw, w.cr, 0x22); /* Page0|RD2|STA */ + OUT(hw, w.tpsr, 0); } void -etherremove(Chan *c) +wd8013mode(Ctlr *cp, int on) { - error(Eperm); + qlock(cp); + if(on){ + cp->prom++; + if(cp->prom == 1) + OUT(cp->hw, w.rcr, 0x14);/* PRO|AB */ + } + else { + cp->prom--; + if(cp->prom == 0) + OUT(cp->hw, w.rcr, 0x04);/* AB */ + } + qunlock(cp); } -void -etherwstat(Chan *c, char *dp) +static void +wd8013online(Ctlr *cp, int on) { - netwstat(c, dp, &ctlr[0].net); + OUT(cp->hw, w.tcr, 0); } -void -etherclose(Chan *c) +static void +wd8013receive(Ctlr *cp) { - if(c->stream) - streamclose(c); + Hw *hw = cp->hw; + Buffer *rb; + uchar bnry, curr, next; + typedef struct Ring { + uchar status; + uchar next; + uchar len0; + uchar len1; + uchar data[256-4]; + } Ring; + Ring *p; + int len; + + bnry = IN(hw, r.bnry); + next = NEXT(bnry, HOWMANY(hw->ramsz, 256)); + if(next == 0) + next = HOWMANY(sizeof(Etherpkt), 256); + for(;;){ + OUT(hw, w.cr, 0x62); /* Page1|RD2|STA */ + curr = IN(hw, curr); + OUT(hw, w.cr, 0x22); /* Page0|RD2|STA */ + if(next == curr) + break; + cp->inpackets++; + p = &((Ring*)hw->ram)[next]; + len = (p->len1<<8)|p->len0; + + rb = &cp->rb[cp->ri]; + if(rb->owner == Interface){ + rb->len = len; + /*copy in packet*/ + rb->owner = Host; + cp->ri = NEXT(cp->ri, Nrb); + } + + next = p->next; + bnry = next-1; + if(bnry < HOWMANY(sizeof(Etherpkt), 256)) + bnry = HOWMANY(hw->ramsz, 256)-1; + OUT(hw, w.bnry, bnry); + } } -long -etherread(Chan *c, void *a, long n, ulong offset) +static void +wd8013transmit(Ctlr *cp) { - return netread(c, a, n, offset, &ctlr[0].net); + Hw *hw; + Buffer *tb; + int s; + +print("transmit\n"); + s = splhi(); + tb = &cp->tb[cp->ti]; + if(tb->busy == 0 && tb->owner == Interface){ + hw = cp->hw; +print("transmit memove %lux %lux, %d\n", hw->ram, &tb->pkt, tb->len); + memmove(hw->ram, &tb->pkt, tb->len); + OUT(hw, w.tbcr0, tb->len & 0xFF); + OUT(hw, w.tbcr1, (tb->len>>8) & 0xFF); + OUT(hw, w.cr, 0x26); /* Page0|RD2|TXP|STA */ + tb->busy = 1; + } + splx(s); +print("transmit done\n"); } -long -etherwrite(Chan *c, char *a, long n, ulong offset) +static void +wd8013intr(Ureg *ur) { - return streamwrite(c, a, n, 0); + Ctlr *cp = &ctlr[0]; + Hw *hw = cp->hw; + Buffer *tb; + uchar isr; + + while(isr = IN(hw, r.isr)){ + OUT(hw, w.isr, isr); + if(isr & 0x08) /* Txe - transmit error */ + cp->oerrs++; + if(isr & 0x04){ /* Rxe - receive error */ + cp->frames += IN(hw, r.cntr0); + cp->crcs += IN(hw, r.cntr1); + cp->buffs += IN(hw, r.cntr2); + } + if(isr & 0x02) /* Ptx - packet transmitted */ + cp->outpackets++; + /* + * a packet completed transmission, successfully or + * not. start transmission on the next buffered packet, + * and wake the output routine. + */ + if(isr & (0x08|0x02)){ + tb = &cp->tb[cp->ti]; + tb->owner = Host; + tb->busy = 0; + cp->ti = NEXT(cp->ti, Ntb); + (*cp->hw->transmit)(cp); + wakeup(&cp->tr); + } + if(isr & 0x10) /* Ovw - overwrite warning */ + cp->overflows++; + /* + * we have received packets. + */ + if(isr & (0x04|0x01)){ /* Rxe|Prx - packet received */ + (*cp->hw->receive)(cp); + wakeup(&cp->rr); + } + } } +static Hw wd8013 = { + 0x360, /* I/O base address */ + KZERO|0xC8000, /* shared memory address */ + 8*1024, /* shared memory size */ + wd8013reset, + wd8013init, + wd8013mode, + wd8013online, + wd8013receive, + wd8013transmit, + wd8013intr, +}; + void consdebug(void) { - Ctlr *cp = &ctlr[0]; - uchar bnry, curr, isr; - int s; - - s = splhi(); -debug++; - bnry = inb(cp->iobase+Bnry); - outb(cp->iobase+Cr, 0x62); /* Page1, RD2|STA */ - curr = inb(cp->iobase+Curr); - outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */ - isr = inb(cp->iobase+Isr); - print("b%d c%d x%d B%d C%d I%ux", - cp->bnry, cp->curr, cp->xbusy, bnry, curr, isr); - print("\t%d %d %d %d %d %d %d\n", cp->inpackets, cp->outpackets, - cp->crcs, cp->oerrs, cp->frames, cp->overflows, cp->buffs); - splx(s); } diff --git a/pc/devhard.c b/pc/devhard.c index 250d26cd2d1f53fda9d6051ea59f277677825129..941c97ccc182af8980332110ae2df1754f4880de 100644 --- a/pc/devhard.c +++ b/pc/devhard.c @@ -242,13 +242,10 @@ hardattach(char *spec) break; default: /* others: we hope this works */ if (drivecomment) { - print("unknown hard disk type, magic=%04x\n", + print("unknown hard disk type, magic=%04x", dp->id.magic); - print(" lcyls=%d lheads=%d sectors=%d\n", + print(" cyl=%d h=%d sec=%d\n", dp->id.lcyls, dp->id.lheads, dp->id.ls2t); - print(" ncyls=%d nheads=%d dlcyls=%d dlheads=%d\n", - dp->id.ncyls, dp->id.nheads, dp->id.dlcyls, - dp->id.dlheads); } dp->cyl = dp->id.lcyls; dp->heads = dp->id.lheads; @@ -724,9 +721,13 @@ hardintr(Ureg *ur) cp->cmd = 0; wakeup(&cp->r); break; + case 0: /* + * These don't seem to mean anything. Should we wakeup? + */ + break; default: - print("weird disk interrupt, cmd=%02x\n", - cp->cmd); + print("weird disk interrupt, cmd=%02x, status=%02x\n", + cp->cmd, cp->status); break; } } diff --git a/pc/vga.c b/pc/vga.c index 17bde46b97dcf93c907751d91419a1b794606a21..a52e5a0a2662885293a9f0953c88780ddc44d669 100644 --- a/pc/vga.c +++ b/pc/vga.c @@ -66,30 +66,6 @@ struct VGAmode uchar attribute[0x15]; }; -#ifdef ORIGINALSAFARI -/* - * 640x480 display, 16 bit color - */ -VGAmode mode12 = -{ - /* general */ - 0xe3, 0x00, /* 0x70, 0x04, these are read-only */ - /* sequence */ - 0x03, 0x01, 0x0f, 0x00, 0x06, - /* crt */ - 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, - 0xea, 0x0c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3, - 0xff, - /* graphics */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, - 0xff, - /* attribute */ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x01, 0x00, 0x0f, 0x00, 0x00, -}; -#else /* * 640x480 display, 16 bit color - attempt at SVGA version...ches */ @@ -112,9 +88,6 @@ VGAmode mode12 = 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x3f, 0x01, 0x10, 0x0f, 0x00, 0x00, }; -#endif - -#define TESTDELAY 1 void genout(int reg, int val)