| plan 9 kernel history: overview | file list | diff list |
1992/0424/pc/devether.c (diff list | history)
| 1992/0411/sys/src/9/pc/devether.c:1,14 – 1992/0424/sys/src/9/pc/devether.c:1,3 (short | long | prev | next) | ||
| 1992/0403 |
| |
| 1992/0404 |
| |
| 1992/0406 |
| |
| 1992/0403 |
| |
| 1992/0406 |
| |
| 1992/0407 |
| |
| 1992/0403 |
| |
| 1992/0411/sys/src/9/pc/devether.c:18,97 – 1992/0424/sys/src/9/pc/devether.c:7,56 | ||
| 1992/0403 | #include "io.h" #include "devtab.h" | |
| 1992/0410 |
| |
| 1992/0403 |
| |
| 1992/0424 | typedef struct Hw Hw; typedef struct Buffer Buffer; | |
| 1992/0410 | typedef struct Type Type; | |
| 1992/0404 |
| |
| 1992/0424 | typedef struct Ctlr Ctlr; | |
| 1992/0403 |
| |
| 1992/0411 |
| |
| 1992/0404 |
| |
| 1992/0403 | ||
| 1992/0410 |
| |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0424 | 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*); | |
| 1992/0404 | }; | |
| 1992/0424 | static Hw wd8013; | |
| 1992/0404 | ||
| 1992/0410 |
| |
| 1992/0408 | ||
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0424 | Nctlr = 1, /* even one of these is too many */ NType = 9, /* types/interface */ | |
| 1992/0403 |
| |
| 1992/0424 | Nrb = 16, /* software receive buffers */ Ntb = 4, /* software transmit buffers */ }; | |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0424 | #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)) | |
| 1992/0403 |
| |
| 1992/0424 | struct Buffer { uchar owner; uchar busy; ushort len; Etherpkt pkt; | |
| 1992/0404 | }; | |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0424 | Host = 0, /* buffer owned by host */ Interface = 1, /* buffer owned by interface */ | |
| 1992/0404 | }; | |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0407 |
| |
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0411/sys/src/9/pc/devether.c:105,178 – 1992/0424/sys/src/9/pc/devether.c:64,185 | ||
| 1992/0403 | }; /* | |
| 1992/0424 | * per ethernet | |
| 1992/0403 | */ struct Ctlr { QLock; | |
| 1992/0407 |
| |
| 1992/0403 |
| |
| 1992/0407 |
| |
| 1992/0404 |
| |
| 1992/0424 | Hw *hw; | |
| 1992/0403 | ||
| 1992/0407 |
| |
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0407 |
| |
| 1992/0424 | ushort nrb; /* number of software receive buffers */ ushort ntb; /* number of software transmit buffers */ Buffer *rb; /* software receive buffers */ Buffer *tb; /* software transmit buffers */ | |
| 1992/0403 |
| |
| 1992/0424 | uchar ea[6]; /* ethernet address */ uchar ba[6]; /* broadcast address */ | |
| 1992/0403 | ||
| 1992/0410 |
| |
| 1992/0403 |
| |
| 1992/0424 | 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 */ | |
| 1992/0403 |
| |
| 1992/0424 | 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 */ Type type[NType]; uchar prom; /* true if promiscuous mode */ uchar kproc; /* true if kproc started */ char name[NAMELEN]; /* name of kproc */ | |
| 1992/0403 | Network net; | |
| 1992/0410 | Netprot prot[NType]; | |
| 1992/0403 | ||
| 1992/0424 | Queue lbq; /* software loopback packet queue */ | |
| 1992/0403 | int inpackets; int outpackets; | |
| 1992/0424 | int crcs; /* input crc errors */ int oerrs; /* output errors */ int frames; /* framing errors */ int overflows; /* packet overflows */ int buffs; /* buffering errors */ | |
| 1992/0403 | }; static Ctlr ctlr[Nctlr]; | |
| 1992/0411 |
| |
| 1992/0424 | void etherinit(void) { } | |
| 1992/0411 |
| |
| 1992/0424 | Chan* etherclone(Chan *c, Chan *nc) | |
| 1992/0411 | { | |
| 1992/0424 | return devclone(c, nc); } | |
| 1992/0411 |
| |
| 1992/0424 | 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); | |
| 1992/0411 | } | |
| 1992/0424 | 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); } | |
| 1992/0407 | static int | |
| 1992/0424 | isobuf(void *arg) | |
| 1992/0407 | { Ctlr *cp = arg; | |
| 1992/0409 |
| |
| 1992/0424 | cp->tb[cp->th].owner == Host; | |
| 1992/0407 | } | |
| 1992/0403 | static void | |
| 1992/0411/sys/src/9/pc/devether.c:182,190 – 1992/0424/sys/src/9/pc/devether.c:189,197 | ||
| 1992/0403 | int len, n; | |
| 1992/0410 | Type *tp; | |
| 1992/0403 | Etherpkt *p; | |
| 1992/0424 | Buffer *tb; | |
| 1992/0403 | Block *nbp; | |
| 1992/0410 |
| |
| 1992/0403 | if(bp->type == M_CTL){ | |
| 1992/0410 | tp = q->ptr; | |
| 1992/0403 | if(streamparse("connect", bp)) | |
| 1992/0411/sys/src/9/pc/devether.c:191,206 – 1992/0424/sys/src/9/pc/devether.c:198,211 | ||
| 1992/0410 | tp->type = strtol((char *)bp->rptr, 0, 0); | |
| 1992/0403 | else if(streamparse("promiscuous", bp)) { | |
| 1992/0410 | tp->prom = 1; | |
| 1992/0406 |
| |
| 1992/0424 | (*tp->ctlr->hw->mode)(tp->ctlr, 1); | |
| 1992/0403 | } freeb(bp); return; } | |
| 1992/0424 | cp = ((Type *)q->ptr)->ctlr; | |
| 1992/0403 | /* * give packet a local address, return upstream if destined for * this machine. | |
| 1992/0411/sys/src/9/pc/devether.c:212,218 – 1992/0424/sys/src/9/pc/devether.c:217,223 | ||
| 1992/0406 | if(memcmp(cp->ea, p->d, sizeof(cp->ea)) == 0){ | |
| 1992/0403 | len = blen(bp); | |
| 1992/0406 | if (bp = expandb(bp, len >= ETHERMINTU ? len: ETHERMINTU)){ | |
| 1992/0424 | putq(&cp->lbq, bp); | |
| 1992/0406 | wakeup(&cp->rr); | |
| 1992/0403 | } return; | |
| 1992/0411/sys/src/9/pc/devether.c:222,228 – 1992/0424/sys/src/9/pc/devether.c:227,233 | ||
| 1992/0403 | nbp = copyb(bp, len); | |
| 1992/0406 | if(nbp = expandb(nbp, len >= ETHERMINTU ? len: ETHERMINTU)){ | |
| 1992/0403 | nbp->wptr = nbp->rptr+len; | |
| 1992/0406 |
| |
| 1992/0424 | putq(&cp->lbq, nbp); | |
| 1992/0406 | wakeup(&cp->rr); | |
| 1992/0403 | } } | |
| 1992/0411/sys/src/9/pc/devether.c:230,250 – 1992/0424/sys/src/9/pc/devether.c:235,257 | ||
| 1992/0403 | /* * only one transmitter at a time */ | |
| 1992/0407 |
| |
| 1992/0424 | qlock(&cp->tlock); | |
| 1992/0403 | if(waserror()){ | |
| 1992/0411 | freeb(bp); | |
| 1992/0407 |
| |
| 1992/0424 | qunlock(&cp->tlock); | |
| 1992/0403 | nexterror(); } /* | |
| 1992/0407 |
| |
| 1992/0424 | * wait till we get an output buffer. * should try to restart. | |
| 1992/0403 | */ | |
| 1992/0411 |
| |
| 1992/0424 | print("oput sleep\n"); sleep(&cp->tr, isobuf, cp); | |
| 1992/0403 | ||
| 1992/0424 | tb = &cp->tb[cp->th]; p = &tb->pkt; | |
| 1992/0403 | /* * copy message into buffer */ | |
| 1992/0411/sys/src/9/pc/devether.c:271,288 – 1992/0424/sys/src/9/pc/devether.c:278,297 | ||
| 1992/0407 | * give packet a local address | |
| 1992/0403 | */ | |
| 1992/0407 | memmove(p->s, cp->ea, sizeof(cp->ea)); | |
| 1992/0411 |
| |
| 1992/0403 | /* | |
| 1992/0424 | * set up the transmit buffer and | |
| 1992/0407 | * start the transmission | |
| 1992/0403 | */ | |
| 1992/0407 |
| |
| 1992/0424 | cp->outpackets++; tb->len = len; tb->owner = Interface; cp->th = NEXT(cp->th, cp->ntb); (*cp->hw->transmit)(cp); | |
| 1992/0403 | freeb(bp); | |
| 1992/0407 |
| |
| 1992/0424 | qunlock(&cp->tlock); print("oput done\n"); | |
| 1992/0403 | poperror(); } | |
| 1992/0411/sys/src/9/pc/devether.c:320,332 – 1992/0424/sys/src/9/pc/devether.c:329,336 | ||
| 1992/0410 | Type *tp; | |
| 1992/0403 | ||
| 1992/0410 | tp = (Type *)(q->ptr); | |
| 1992/0403 |
| |
| 1992/0424 | if(tp->prom) (*tp->ctlr->hw->mode)(tp->ctlr, 0); | |
| 1992/0410 | qlock(tp); tp->type = 0; tp->q = 0; | |
| 1992/0411/sys/src/9/pc/devether.c:389,517 – 1992/0424/sys/src/9/pc/devether.c:393,404 | ||
| 1992/0403 | } static void | |
| 1992/0424 | etherup(Ctlr *cp, Etherpkt *p, int len) | |
| 1992/0403 | { | |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0404 |
| |
| 1992/0407 |
| |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0404 |
| |
| 1992/0405 |
| |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0405 |
| |
| 1992/0404 |
| |
| 1992/0405 |
| |
| 1992/0403 |
| |
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0408 |
| |
| 1992/0407 |
| |
| 1992/0410 |
| |
| 1992/0404 |
| |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0408 |
| |
| 1992/0404 |
| |
| 1992/0407 |
| |
| 1992/0403 |
| |
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0411 |
| |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0411 |
| |
| 1992/0409 |
| |
| 1992/0404 |
| |
| 1992/0408 |
| |
| 1992/0404 |
| |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0404 | Block *bp; | |
| 1992/0410 | Type *tp; | |
| 1992/0404 | int t; | |
| 1992/0410 |
| |
| 1992/0404 | /* | |
| 1992/0411/sys/src/9/pc/devether.c:537,547 – 1992/0424/sys/src/9/pc/devether.c:424,432 | ||
| 1992/0404 | continue; } if(waserror() == 0){ | |
| 1992/0410 |
| |
| 1992/0411 |
| |
| 1992/0410 |
| |
| 1992/0411 |
| |
| 1992/0410 |
| |
| 1992/0424 | bp = allocb(len); memmove(bp->rptr, p, len); bp->wptr += len; | |
| 1992/0404 | bp->flags |= S_DELIM; | |
| 1992/0410 | PUTNEXT(tp->q, bp); | |
| 1992/0404 | } | |
| 1992/0411/sys/src/9/pc/devether.c:550,573 – 1992/0424/sys/src/9/pc/devether.c:435,446 | ||
| 1992/0404 | } } | |
| 1992/0406 |
| |
| 1992/0403 | static int isinput(void *arg) { | |
| 1992/0404 | Ctlr *cp = arg; | |
| 1992/0403 | ||
| 1992/0410 |
| |
| 1992/0424 | return cp->lbq.first || cp->rb[cp->ri].owner == Host; | |
| 1992/0403 | } static void | |
| 1992/0411/sys/src/9/pc/devether.c:574,599 – 1992/0424/sys/src/9/pc/devether.c:447,471 | ||
| 1992/0403 | etherkproc(void *arg) { | |
| 1992/0404 | Ctlr *cp = arg; | |
| 1992/0424 | Buffer *rb; | |
| 1992/0404 | Block *bp; | |
| 1992/0410 |
| |
| 1992/0403 | if(waserror()){ | |
| 1992/0404 | print("%s noted\n", cp->name); | |
| 1992/0424 | (*cp->hw->init)(cp); | |
| 1992/0404 | cp->kproc = 0; | |
| 1992/0403 | nexterror(); } | |
| 1992/0404 | cp->kproc = 1; | |
| 1992/0403 | for(;;){ | |
| 1992/0404 |
| |
| 1992/0424 | qlock(&cp->rlock); | |
| 1992/0406 | /* * process any internal loopback packets */ | |
| 1992/0404 |
| |
| 1992/0424 | while(bp = getq(&cp->lbq)){ | |
| 1992/0404 | cp->inpackets++; | |
| 1992/0410 |
| |
| 1992/0424 | etherup(cp, (Etherpkt*)bp->rptr, BLEN(bp)); | |
| 1992/0404 | freeb(bp); } | |
| 1992/0408 | ||
| 1992/0411/sys/src/9/pc/devether.c:600,730 – 1992/0424/sys/src/9/pc/devether.c:472,823 | ||
| 1992/0406 | /* * process any received packets */ | |
| 1992/0410 |
| |
| 1992/0408 |
| |
| 1992/0424 | while(cp->rb[cp->rh].owner == Host){ | |
| 1992/0406 | cp->inpackets++; | |
| 1992/0410 |
| |
| 1992/0424 | rb = &cp->rb[cp->rh]; etherup(cp, &rb->pkt, rb->len); rb->owner = Interface; cp->rh = NEXT(cp->rh, Nrb); } | |
| 1992/0410 |
| |
| 1992/0424 | qunlock(&cp->rlock); sleep(&cp->rr, isinput, cp); } } | |
| 1992/0410 |
| |
| 1992/0424 | void etherreset(void) { Ctlr *cp = &ctlr[0]; | |
| 1992/0410 | ||
| 1992/0424 | cp->hw = &wd8013; (*cp->hw->reset)(cp); | |
| 1992/0410 | ||
| 1992/0424 | memset(cp->ba, 0xFF, sizeof(cp->ba)); | |
| 1992/0410 |
| |
| 1992/0408 |
| |
| 1992/0410 |
| |
| 1992/0407 |
| |
| 1992/0406 |
| |
| 1992/0403 |
| |
| 1992/0424 | 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; | |
| 1992/0403 | } | |
| 1992/0424 | Chan* etherattach(char *spec) | |
| 1992/0403 | { int ctlrno = 0; | |
| 1992/0424 | Ctlr *cp = &ctlr[ctlrno]; int i; | |
| 1992/0403 | ||
| 1992/0424 | 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; | |
| 1992/0403 | /* * put the receiver online * and start the kproc */ | |
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0424 | (*cp->hw->online)(cp, 1); if(cp->kproc == 0){ sprint(cp->name, "ether%dkproc", ctlrno); kproc(cp->name, etherkproc, cp); | |
| 1992/0403 | } | |
| 1992/0424 | 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; | |
| 1992/0403 |
| |
| 1992/0424 | 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; | |
| 1992/0403 |
| |
| 1992/0424 | #define IN(hw, m) inb((hw)->addr+OFFSETOF(Wd8013, m)) #define OUT(hw, m, x) outb((hw)->addr+OFFSETOF(Wd8013, m), (x)) /* */ static void wd8013reset(Ctlr *cp) | |
| 1992/0403 | { | |
| 1992/0424 | Hw *hw = cp->hw; int i; uchar msr; | |
| 1992/0403 |
| |
| 1992/0424 | print("reset\n"); cp->rb = ialloc(sizeof(Buffer)*Nrb, 0); cp->nrb = Nrb; cp->tb = ialloc(sizeof(Buffer)*Ntb, 0); cp->ntb = Ntb; msr = IN(hw, msr); OUT(hw, msr, 0x40|msr); | |
| 1992/0403 | { | |
| 1992/0424 | int addr = hw->addr; for(i = 0; i < 16; i++){ print("#%2.2ux ", inb(addr)); addr++; | |
| 1992/0403 | } | |
| 1992/0424 | print("\n"); } for(i = 0; i < sizeof(cp->ea); i++) cp->ea[i] = IN(hw, lan[i]); (*hw->init)(cp); setvec(Ethervec, hw->intr); } | |
| 1992/0403 |
| |
| 1992/0424 | /* * we leave the chip idling on internal loopback * and pointing to Page0. */ static void wd8013init(Ctlr *cp) | |
| 1992/0403 | { | |
| 1992/0424 | 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); | |
| 1992/0403 | } void | |
| 1992/0424 | wd8013mode(Ctlr *cp, int on) | |
| 1992/0403 | { | |
| 1992/0424 | 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); | |
| 1992/0403 | } | |
| 1992/0424 | static void wd8013online(Ctlr *cp, int on) | |
| 1992/0403 | { | |
| 1992/0424 | OUT(cp->hw, w.tcr, 0); | |
| 1992/0403 | } | |
| 1992/0424 | static void wd8013receive(Ctlr *cp) | |
| 1992/0403 | { | |
| 1992/0424 | 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); } | |
| 1992/0403 | } | |
| 1992/0424 | static void wd8013transmit(Ctlr *cp) | |
| 1992/0403 | { | |
| 1992/0424 | 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"); | |
| 1992/0403 | } | |
| 1992/0424 | static void wd8013intr(Ureg *ur) | |
| 1992/0403 | { | |
| 1992/0424 | 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); } } | |
| 1992/0409 | } | |
| 1992/0424 | 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, }; | |
| 1992/0409 | void | |
| 1992/0411 | consdebug(void) | |
| 1992/0409 | { | |
| 1992/0410 |
| |
| 1992/0409 |
| |
| 1992/0410 |
| |
| 1992/0409 |
| |
| 1992/0403 | } | |