## diffname carrera/devether.c 1993/0903 ## diff -e /dev/null /n/fornaxdump/1993/0903/sys/src/brazil/carrera/devether.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "../port/error.h" #include "../port/netif.h" /* * ethernet address stored in prom */ typedef struct { ulong pad0; ulong byte; uvlong pad1; } Etheraddr; #define EPCENETPROM EPCSWIN(Etheraddr, 0x2000) /* * SEEQ/EDLC device registers */ typedef struct { struct { ulong pad; ulong byte; } addr[6]; /* address */ ulong pad; ulong tcmd; /* transmit command */ ulong pad0; ulong rcmd; /* receive command */ ulong pad1[5]; ulong tbaselo; /* low bits of xmit buff base */ ulong pad2; ulong tbasehi; /* high bits of xmit buff base */ ulong pad3; ulong tlimit; /* xmit buffer limit */ ulong pad4; ulong tindex; /* xmit buffer limit */ ulong pad5; ulong ttop; /* xmit buffer top */ ulong pad6; ulong tbptr; /* xmit buffer byte pointer */ ulong pad7; ulong tstat; /* transmit status */ ulong pad8; ulong titimer; /* transmit interrupt timer */ ulong pad9[5]; ulong rbaselo; /* rcv buffer base addr */ ulong pad10; ulong rbasehi; /* high bits of rcv buffer base addr */ ulong pad11; ulong rlimit; /* rcv buffer limit */ ulong pad12; ulong rindex; /* rcv buffer index */ ulong pad13; ulong rtop; /* rcv buffer top */ ulong pad14; ulong rbptr; /* rcv buffer byte pointer */ ulong pad15; ulong rstat; /* rcv status */ ulong pad16; ulong ritimer; /* rcv interrupt timer */ } EDLCdev; #define EPCEDLC EPCSWIN(EDLCdev, 0xa200) /* * LXT901 device registers */ typedef struct { ulong pad0; ulong stat; /* some LXT901 pins + SQE ctrl (r/w) */ ulong pad1; ulong collisions; /* total collisions -- 16 bits (r) */ uchar pad2[7]; uchar loopback; /* loopback enable -- 1 bit (w) */ ulong pad3; ulong edlcself; /* EDLC self rcv enable -- 1 bit (w) */ } LXTdev; #define EPCLXT EPCSWIN(LXTdev, 0x8000) enum { /* transmit command bits */ Tigood= 1<<3, /* interrupt on good xmit */ Ti16tries= 1<<2, /* interrupt on 16 retries */ Ticoll= 1<<1, /* interrupt on collision */ Tiunder= 1<<0, /* interrupt on underflow */ /* receive command bits */ Rmulti= 3<<6, /* recv station/broadcast/multicast */ Rnormal= 2<<6, /* recv station/broadcast */ Rall= 1<<6, /* receive all frames */ Rigood= 1<<5, /* interrupt on good frames */ Riend= 1<<4, /* interrupt on end of frame */ Rishort= 1<<3, /* interrupt on short frame */ Ridrbl= 1<<2, /* interrupt on dribble error */ Ricrc= 1<<1, /* interrupt on CRC error */ Riover= 1<<0, /* interrupt on overflow error */ Renab= (Rigood|Riend|Rishort|Ridrbl|Ricrc), /* receive status bits */ Rgood= 1<<5, /* good frame */ Rend= 1<<4, /* end of frame */ Rshort= 1<<3, /* short frame */ Rdrbl= 1<<2, /* dribble error */ Rcrc= 1<<1, /* CRC error */ Rover= 1<<0, /* overflow error */ /* interrupt level for ether */ ILenet= 0x60, /* manifest constants */ logNxmt= 8, Nxmt= 1<loopback = 1; x = lxt->loopback; USED(x); /* step 2: shut off transmitter */ while(edlc->ttop != edlc->tindex) edlc->ttop = edlc->tindex; ether.tindex = ether.ttop = edlc->ttop; /* step 3: reset edlc */ misc->set = 0x200; x = misc->reset; USED(x); delay(1); /* 1ms but 10micros is enough */ misc->clr = 0x200; x = misc->reset; USED(x); /* step 4: enable transmitter interrupts */ edlc->tcmd = Tigood | Ti16tries | Ticoll | Tiunder; /* step 5: set address from prom, start receiver, * and reset receive pointer */ for(i = 0; i < Netheraddr; i++) edlc->addr[i].byte = EPCENETPROM[5-i].byte & 0xff; if(ether.prom) edlc->rcmd = Renab | Rall; else edlc->rcmd = Renab | Rnormal; ether.rindex = edlc->rindex; ether.rtop = edlc->rtop = RPREV(ether.rindex); /* step 6: attach to ether */ lxt->loopback = 0; } void etherintr(void) { EDLCdev *edlc = EPCEDLC; EPCmisc *misc = EPCMISC; Netfile *f, **fp; Pbuf *p; int x; ushort t; while(edlc->rindex != ether.rindex){ p = ðer.rbuf[ether.rindex]; /* statistics */ if(p->stat & (Rshort|Rdrbl|Rcrc|Rover)){ if(p->stat & (Rdrbl|Rcrc)) ether.crcs++; if(p->stat & Rover) ether.overflows++; if(p->stat & Rshort) ether.frames++; } if(p->stat & Rgood){ x = (p->rlen[0]<<8) | p->rlen[1]; t = (p->type[0]<<8) | p->type[1]; for(fp = ether.f; fp < ðer.f[Ntypes]; fp++){ f = *fp; if(f == 0) continue; if(f->type == t || f->type < 0) qproduce(f->in, p->d, x); } } /* * because of a chip bug, we have to reset if rtop * and rindex get too close. */ x = edlc->rtop - edlc->rindex; if(x < 0) x += Nrcv; if(x <= 64){ etherhardreset(); } else { edlc->rtop = ether.rindex; ether.rindex = RSUCC(ether.rindex); } } /* reenable holdoff and EPC interrupts */ misc->clr = 0x10; misc->set = 0x10; epcenable(EIenet); } /* * turn promiscuous mode on/off */ static void promiscuous(void *arg, int on) { EDLCdev *edlc = EPCEDLC; USED(arg); if(on) edlc->rcmd = Renab | Rall; else edlc->rcmd = Renab | Rnormal; } void etherreset(void) { EDLCdev *edlc = EPCEDLC; EPCmisc *misc = EPCMISC; ulong x, i; /* setup xmit buffers (pointers on chip assume KSEG0) */ edlc->tlimit = logNxmt - 1; ether.tbuf = xspanalloc(Nxmt*sizeof(Pbuf), 512*1024, 0); x = ((ulong)ether.tbuf) & ~KSEGM; edlc->tbasehi = 0; edlc->tbaselo = x; /* setup rcv buffers (pointers on chip assume KSEG0) */ edlc->rlimit = logNrcv - 1; ether.rbuf = xspanalloc(Nrcv*sizeof(Pbuf), 512*1024, 0); x = ((ulong)ether.rbuf) & ~KSEGM; edlc->rbasehi = 0; edlc->rbaselo = x; /* install interrupt handler */ sethandler(ILenet, etherintr); setleveldest(ILenet, 0, &EPCINTR->enetdest); epcenable(EIenet); /* turn off receive */ edlc->rcmd = 0; /* stop transmitter, we can't change tindex so we change ttop */ while(edlc->ttop != edlc->tindex) edlc->ttop = edlc->tindex; ether.tindex = ether.ttop = edlc->ttop; /* enable transmitter interrupts */ edlc->tcmd = Tigood | Ti16tries | Ticoll | Tiunder; /* set address from prom, start receiver, and reset receive pointer */ for(i = 0; i < Netheraddr; i++){ ether.ea[i] = EPCENETPROM[5-i].byte & 0xff; edlc->addr[i].byte = ether.ea[i]; } ether.rindex = edlc->rindex; ether.rtop = edlc->rtop = RPREV(ether.rindex); edlc->rcmd = Renab | Rnormal; /* set hold off timer value, and enable its interrupts (pulse) */ misc->set = ho800us; misc->clr = (~ho800us)&0x180; misc->clr = 0x10; misc->set = 0x10; /* general network interface structure */ netifinit(ðer, "ether", Ntypes, 32*1024); ether.alen = 6; memmove(ether.addr, ether.ea, 6); memmove(ether.bcast, etherbcast, 6); ether.promiscuous = promiscuous; ether.arg = ðer; } void etherinit(void) { } Chan* etherattach(char *spec) { return devattach('l', spec); } Chan* etherclone(Chan *c, Chan *nc) { return devclone(c, nc); } int etherwalk(Chan *c, char *name) { return netifwalk(ðer, c, name); } Chan* etheropen(Chan *c, int omode) { return netifopen(ðer, c, omode); } void ethercreate(Chan *c, char *name, int omode, ulong perm) { USED(c, name, omode, perm); } void etherclose(Chan *c) { netifclose(ðer, c); } long etherread(Chan *c, void *buf, long n, ulong offset) { return netifread(ðer, c, buf, n, offset); } static int isoutbuf(void *arg) { EDLCdev *edlc = arg; USED(arg); ether.tindex = edlc->tindex; return TSUCC(ether.ttop) != ether.tindex; } long etherwrite(Chan *c, void *buf, long n, ulong offset) { Pbuf *p; EDLCdev *edlc = EPCEDLC; USED(offset); if(n > ETHERMAXTU) error(Ebadarg); /* etherif.c handles structure */ if(NETTYPE(c->qid.path) != Ndataqid) return netifwrite(ðer, c, buf, n); /* we handle data */ qlock(ðer.tlock); tsleep(ðer.tr, isoutbuf, edlc, 10000); if(!isoutbuf(edlc)){ print("ether transmitter jammed\n"); } else { p = ðer.tbuf[ether.ttop]; memmove(p->d, buf, n); if(n < 60) { memset(p->d+n, 0, 60-n); n = 60; } memmove(p->s, ether.ea, sizeof(ether.ea)); p->tlen[0] = n; p->tlen[1] = n>>8; ether.ttop = TSUCC(ether.ttop); edlc->ttop = ether.ttop; } qunlock(ðer.tlock); return n; } void etherremove(Chan *c) { USED(c); } void etherstat(Chan *c, char *dp) { netifstat(ðer, c, dp); } void etherwstat(Chan *c, char *dp) { netifwstat(ðer, c, dp); } . ## diffname carrera/devether.c 1993/0904 ## diff -e /n/fornaxdump/1993/0903/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/0904/sys/src/brazil/carrera/devether.c 461c netifwstat(ether[0], c, dp); . 455c netifstat(ether[0], c, dp); . 442c qunlock(&ctlr->tlock); . 436,440c memmove(p->s, ctlr->ea, sizeof(ctlr->ea)); txpkt = &ctlr->tda[ctlr->th]; txpkt->size = n; txpkt->fsize = n; txpkt->link |= Eol; txpkt->status = Interface; ctlr->tda[PREV(ctlr->th, Ntb)].link &= ~Eol; ctlr->th = NEXT(ctlr->th, Ntb); WR(cr, Txp); . 429,430c } else { p =(Etherpkt*)ctlr->tb[ctlr->th]; . 425,427c qlock(&ctlr->tlock); tsleep(&ctlr->tr, isoutbuf, ctlr, 10000); if(!isoutbuf(ctlr)){ . 422c return netifwrite(ether[0], c, buf, n); . 412,413c Etherpkt *p; TXpkt *txpkt; Ether *ctlr = ether[0]; . 404,406c return ctlr->tda[ctlr->th].status == Host; . 402c Ether *ctlr = arg; . 396c return netifread(ether[0], c, buf, n, offset); . 390c netifclose(ether[0], c); . 378c return netifopen(ether[0], c, omode); . 372c return netifwalk(ether[0], c, name); . 344,349c netifinit(ether[0], "ether", Ntypes, 32*1024); ether[0]->alen = 6; memmove(ether[0]->addr, ether[0]->ea, 6); memmove(ether[0]->bcast, ctlr->ba, 6); ether[0]->promiscuous = promiscuous; ether[0]->arg = ether[0]; . 337,341c memset(ctlr->ba, 0xFF, sizeof(ctlr->ba)); . 335c reset(ctlr); . 332,333c ctlr = ether[0]; . 297,330c /* * Map the device registers and allocate * memory for the receive/transmit rings. * Set the physical ethernet address and * prime the interrupt handler. */ if(ether[0] == 0) { ether[0] = xspanalloc(sizeof(Ether), BY2PG, 64*1024); /* memmove(ether[0]->ea, eeprom.ea, sizeof(ether[0]->ea)); */ . 293,295c Ether *ctlr; . 287c WR(rcr, reg&~Pro); . 285c WR(rcr, reg|Pro); . 283a reg = RD(rcr); . 281c ushort reg; . 269,272d 267a if(status & Br){ print("sonic: bus retry occurred\n"); status &= ~Br; } if(status & AllIntr) print("sonic %ux\n", status); . 259,266c if(status & Lcd) status &= ~Lcd; /* * Warnings that something is afoot. */ if(status & Hbl){ print("sonic: cd heartbeat lost\n"); status &= ~Hbl; . 256,257c * We get a 'load CAM done' interrupt * after initialisation. Ignore it. . 254a noinput: . 253a status &= ~(Pktrx|Rde); . 252a else if(rxpkt->status & Fae) ctlr->frames++; else if(rxpkt->status & Crc) ctlr->crcs++; else ctlr->buffs++; /* * Finished with this packet, it becomes the * last free packet in the ring, so give it Eol, * and take the Eol bit off the previous packet. * Move the ring index on. */ rxpkt->link |= Eol; rxpkt->owner = Interface; ctlr->rda[PREV(ctlr->rh, Nrb)].link &= ~Eol; ctlr->rh = NEXT(ctlr->rh, Nrb); rxpkt = &ctlr->rda[ctlr->rh]; . 243,251c if((status & (Pktrx|Rde)) == 0) goto noinput; /* * A packet arrived or we ran out of descriptors. */ status &= ~(Pktrx|Rde); rxpkt = &ctlr->rda[ctlr->rh]; while(rxpkt->owner == Host){ ctlr->inpackets++; /* * If the packet was received OK, pass it up, * otherwise log the error. * SONIC gives us the CRC in the packet, so * remember to subtract it from the length. */ if(rxpkt->status & Prx) { x = (rxpkt->count & 0xFFFF)-4; p = (Etherpkt*)ctlr->rb[ctlr->rh]; t = (p->type[0]<<8) | p->type[1]; for(fp = ctlr->f; fp < &ctlr->f[Ntypes]; fp++){ f = *fp; if(f == 0) continue; if(f->type == t || f->type < 0) qproduce(f->in, p->d, x); } . 234,241c for(;;) { status = RD(isr) & AllIntr; if(status == 0) break; WR(isr, status); /* * Transmission complete, for good or bad. */ if(status & (Txdn|Txer)){ txpkt = &ctlr->tda[ctlr->ti]; while(txpkt->status != Host){ if(txpkt->status == Interface){ WR(ctda, LS16(txpkt)); WR(cr, Txp); break; } if((txpkt->status & Ptx) == 0) ctlr->oerrs++; txpkt->status = Host; ctlr->ti = NEXT(ctlr->ti, Ntb); txpkt = &ctlr->tda[ctlr->ti]; } status &= ~(Txdn|Txer); . 231,232c ctlr = ether[0]; . 229a Ether *ctlr; ulong status; TXpkt *txpkt; RXpkt *rxpkt; Etherpkt *p; Netfile *f, **fp; . 224,227d 217,218c iprint("wait rra\n"); WR(cr, Rrra); while(RD(cr) & Rrra) ; iprint("rra done\n"); /* * Initialise the transmit descriptor area (TDA). * Each descriptor describes one packet, we make no use * of having the packet in multiple fragments. * The descriptors are linked in a ring; overlapping transmission * with buffer queueing will cause some packets to * go out back-to-back. * * Load the SONIC registers to describe the TDA. */ for(i = 0; i < Ntb; i++){ ctlr->tda[i].status = Host; ctlr->tda[i].config = 0; ctlr->tda[i].count = 1; ctlr->tda[i].ptr0 = LS16(ctlr->tb[i]); ctlr->tda[i].ptr1 = MS16(ctlr->tb[i]); ctlr->tda[i].link = LS16(&ctlr->tda[NEXT(i, Ntb)]); } WR(ctda, LS16(&ctlr->tda[0])); WR(utda, MS16(&ctlr->tda[0])); /* * Initialise the software receive and transmit * ring indexes. */ ctlr->rh = 0; ctlr->ri = 0; ctlr->th = 0; ctlr->ti = 0; /* * Initialise the CAM descriptor area (CDA). * We only have one ethernet address to load, * broadcast is defined by the SONIC as all 1s. * * Load the SONIC registers to describe the CDA. * Tell the SONIC to load the CDA and wait for it * to complete. */ ctlr->cda.cep = 0; ctlr->cda.cap0 = (ctlr->ea[1]<<8)|ctlr->ea[0]; ctlr->cda.cap1 = (ctlr->ea[3]<<8)|ctlr->ea[2]; ctlr->cda.cap2 = (ctlr->ea[5]<<8)|ctlr->ea[4]; ctlr->cda.ce = 1; WR(cdp, LS16(&ctlr->cda)); WR(cdc, 1); WR(cr, Lcam); while(RD(cr) & Lcam) ; /* * Configure the receive control, transmit control * and interrupt-mask registers. * The SONIC is now initialised, but not enabled. */ WR(rcr, Err|Rnt|Brd); WR(tcr, 0); WR(imr, AllIntr); iprint("reset done\n"); . 214,215c /* * Load the SONIC registers to describe the RRA. * We set the rwp to beyond the area delimited by rsa and * rea. This means that since we've already allocated all * the buffers, we'll never get a 'receive buffer area * exhausted' interrupt and the rrp will just wrap round. * Tell the SONIC to load the RRA and wait for * it to complete. */ WR(urra, MS16(&ctlr->rra[0])); WR(rsa, LS16(&ctlr->rra[0])); WR(rrp, LS16(&ctlr->rra[0])); WR(rea, LS16(&ctlr->rra[Nrb])); WR(rwp, LS16(&ctlr->rra[Nrb+1])); . 209,212c WR(crda, LS16(ctlr->rda)); WR(urda, MS16(ctlr->rda)); WR(eobc, sizeof(ctlr->rb[0])/2 - 2); . 206,207c ctlr->rda[Nrb-1].link |= Eol; . 203,204c /* * Terminate the receive descriptor ring * and load the SONIC registers to describe the RDA. . 200,201c ctlr->rra[i].ptr0 = ctlr->rda[i].ptr0 = LS16(ctlr->rb[i]); ctlr->rra[i].ptr1 = ctlr->rda[i].ptr1 = MS16(ctlr->rb[i]); } . 193,198c ctlr->rda[i].link = LS16(&ctlr->rda[NEXT(i, Nrb)]); ctlr->rda[i].owner = Interface; . 188,191c /* * Initialise the receive resource area (RRA) and * the receive descriptor area (RDA). * * We use a simple scheme of one packet per descriptor. * We achieve this by setting the EOBC register to be * 2 (16-bit words) less than the buffer size; * thus the size of the receive buffers must be sizeof(Etherpkt)+4. * Set up the receive descriptors as a ring. */ for(i = 0; i < Nrb; i++){ ctlr->rra[i].wc0 = (sizeof(ctlr->rb[0])/2) & 0xFFFF; ctlr->rra[i].wc1 = ((sizeof(ctlr->rb[0])/2)>>16) & 0xFFFF; . 184,186c iprint("reset sonic dcr=#%lux mydcr=#%lux\n", RD(dcr), Sterm|Dw32|Lbr|Efm|W14tf); /* * Reset the SONIC, toggle the Rst bit. * Set the data config register for synchronous termination * and 32-bit data-path width. * Clear the descriptor and buffer area. */ WR(cr, Rst); WR(dcr, Sterm|Dw32|Lbr|Efm|W14tf); WR(cr, 0); . 179,182c int i; . 177c reset(Ether *ctlr) . 172,175c #define NEXT(x, l) (((x)+1)%(l)) #define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1) #define LS16(addr) (PADDR(addr) & 0xFFFF) #define MS16(addr) ((PADDR(addr)>>16) & 0xFFFF) . 170a Ether *ether[Nether]; . 169c }; . 167a int rh; /* first receive buffer owned by host */ int ri; /* first receive buffer owned by interface */ RXrsc rra[Nrb]; /* receive resource area */ RXpkt rda[Nrb]; /* receive descriptor area */ uchar rb[Nrb][sizeof(Etherpkt)+4]; /* receive buffer area */ TXpkt tda[Ntb]; /* transmit descriptor area */ uchar tb[Ntb][sizeof(Etherpkt)]; /* transmit buffer area */ Cam cda; /* CAM descriptor area */ . 166a int th; /* first transmit buffer owned by host */ int ti; /* first transmit buffer owned by interface */ . 162,164d 157,160c Sonic *sonic; /* SONIC registers */ . 155a uchar ba[6]; . 152a /* * Transmit Packet Descriptor. */ typedef struct { uchar pad0[2]; ushort status; /* transmit status */ uchar pad1[2]; ushort config; /* */ uchar pad2[2]; ushort size; /* byte count of entire packet */ uchar pad3[2]; ushort count; /* fragment count */ uchar pad4[2]; ushort ptr0; /* packet pointer */ uchar pad5[2]; ushort ptr1; uchar pad6[2]; ushort fsize; /* fragment size */ uchar pad7[2]; ushort link; /* descriptor link */ } TXpkt; enum{ Eol = 1, /* end of list bit in descriptor link */ Host = 0, /* descriptor belongs to host */ Interface = -1, /* descriptor belongs to interface */ Nether = 1, Ntypes= 8, }; /* * CAM Descriptor */ typedef struct { uchar pad0[2]; ushort cep; /* CAM entry pointer */ uchar pad1[2]; ushort cap0; /* CAM address port 0 */ uchar pad2[2]; ushort cap1; /* CAM address port 1 */ uchar pad3[2]; ushort cap2; /* CAM address port 2 */ uchar pad4[2]; ushort ce; /* CAM enable */ } Cam; typedef struct Ether Ether; . 143,151c uchar pad0[2]; ushort status; /* receive status */ uchar pad1[2]; ushort count; /* packet byte count */ uchar pad2[2]; ushort ptr0; /* buffer pointer */ uchar pad3[2]; ushort ptr1; uchar pad4[2]; ushort seqno; /* */ uchar pad5[2]; ushort link; /* descriptor link and EOL */ uchar pad6[2]; ushort owner; /* in use */ } RXpkt; . 139c * Receive Packet Descriptor. . 133,136c /* * Receive Resource Descriptor. */ typedef struct { uchar pad0[2]; ushort ptr0; /* buffer pointer in the RRA */ uchar pad1[2]; ushort ptr1; uchar pad2[2]; ushort wc0; /* buffer word count in the RRA */ uchar pad3[2]; ushort wc1; } RXrsc; . 118,130c Rfo = 0x0001, /* receive fifo overrun */ MpTally = 0x0002, /* missed packet tally counter rollover */ FaeTally= 0x0004, /* frame alignment error tally counter rollover */ CrcTally= 0x0008, /* Crc tally counter rollover */ Rbae = 0x0010, /* receive buffer area exceeded */ Rbe = 0x0020, /* receive buffer exhausted */ Rde = 0x0040, /* receive descriptors exhausted */ Txer = 0x0100, /* transmit error */ Txdn = 0x0200, /* transmission done */ Pktrx = 0x0400, /* packet received */ Pint = 0x0800, /* programmed interrupt */ Lcd = 0x1000, /* load CAM done */ Hbl = 0x2000, /* CD heartbeat lost */ Br = 0x4000, /* bus retry occurred */ AllIntr = 0x7771, /* all of the above */ . 115,116c Ptx = 0x0001, /* packet transmitted ok */ Pintr = 0x8000, /* programmable interrupt */ . 107,113c Prx = 0x0001, /* packet received ok */ Fae = 0x0004, /* frame alignment error */ Crc = 0x0008, /* CRC error */ Lpkt = 0x0040, /* last packet in rba */ Bc = 0x0080, /* broadcast packet received */ Pro = 0x1000, /* physical promiscuous mode */ Brd = 0x2000, /* accept broadcast packets */ Rnt = 0x4000, /* accept runt packets */ Err = 0x8000, /* accept packets with errors */ . 105c Dw32 = 0x0020, /* data width select */ Sterm = 0x0400, /* synchronous termination */ Lbr = 0x4000, /* latched bus retry */ Efm = 0x0010, /* Empty fill mode */ W14tf = 0x0003, /* 14 Word transmit fifo */ . 94,103c enum { Htx = 0x0001, /* halt transmission */ Txp = 0x0002, /* transmit packet(s) */ Rxdis = 0x0004, /* receiver disable */ Rxen = 0x0008, /* receiver enable */ Stp = 0x0010, /* stop timer */ St = 0x0020, /* start timer */ Rst = 0x0080, /* software reset */ Rrra = 0x0100, /* read RRA */ Lcam = 0x0200, /* load CAM */ . 88,92c Nrb = 16, /* receive buffers */ Ntb = 8, /* transmit buffers */ }; . 71,84c typedef struct { ulong cr; /* command */ ulong dcr; /* data configuration */ ulong rcr; /* receive control */ ulong tcr; /* transmit control */ ulong imr; /* interrupt mask */ ulong isr; /* interrupt status */ ulong utda; /* upper transmit descriptor address */ ulong ctda; /* current transmit descriptor address */ ulong pad0x08[5]; /* */ ulong urda; /* upper receive descriptor address */ ulong crda; /* current receive descriptor address */ ulong pad0x0F[4]; /* */ ulong eobc; /* end of buffer word count */ ulong urra; /* upper receive resource address */ ulong rsa; /* resource start address */ ulong rea; /* resource end address */ ulong rrp; /* resource read pointer */ ulong rwp; /* resource write pointer */ ulong pad0x19[8]; /* */ ulong cep; /* CAM entry pointer */ ulong cap2; /* CAM address port 2 */ ulong cap1; /* CAM address port 1 */ ulong cap0; /* CAM address port 0 */ ulong ce; /* CAM enable */ ulong cdp; /* CAM descriptor pointer */ ulong cdc; /* CAM descriptor count */ ulong sr; /* silicon revision */ ulong wt0; /* watchdog timer 0 */ ulong wt1; /* watchdog timer 1 */ ulong rsc; /* receive sequence counter */ ulong crct; /* CRC error tally */ ulong faet; /* FAE tally */ ulong mpt; /* missed packet tally */ ulong mdt; /* maximum deferral timer */ ulong pad0x30[15]; /* */ ulong dcr2; /* data configuration 2 */ } Sonic; . 32,69c #define RD(rn) (delay(1), *(ulong*)((ulong)&SONICADDR->rn^4)) #define WR(rn, v) (delay(1), *(ulong*)((ulong)&SONICADDR->rn^4) = v) . 21,30c #define SONICADDR ((Sonic*)Sonicbase) . 13,19d 11c * National Semiconductor DP83932 * Systems-Oriented Network Interface Controller * (SONIC) . ## diffname carrera/devether.c 1993/0905 ## diff -e /n/fornaxdump/1993/0904/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/0905/sys/src/brazil/carrera/devether.c 629a iprint("tx done %d\n", n); . 609d 607c if(!isoutbuf(ctlr)) . 596a iprint("ether tx\n"); . 540a static int enable; if(enable == 0) { enable = 1; WR(cr, Rxen); } . 533a enab(void) { WR(cr, Rxen); } void . 516c if(PADDR(ether[0])+sizeof(Ether) > Ntranslation*BY2PG) panic("sonic: 16M io map"); enetaddr(ether[0]->ea); . 482c iprint("sonic #%lux\n", status); . 477c iprint("sonic: bus retry occurred\n"); . 473c iprint("sonic: cd heartbeat lost\n"); . 414a pxp(rxpkt); . 413d 381a print("s %lux\n", status); . 364a pxp(RXpkt *rxpkt) { print("%lux %lux\n", rxpkt->pad0[0], rxpkt->pad0[1]); print("status %lux\n", rxpkt->status); /* receive status */ print("%lux %lux\n", rxpkt->pad1[0], rxpkt->pad1[1]); print("count %lux\n", rxpkt->count); /* packet byte count */ print("%lux %lux\n", rxpkt->pad2[0], rxpkt->pad2[1]); print("ptr0 %lux\n", rxpkt->ptr0); /* buffer pointer */ print("%lux %lux\n", rxpkt->pad3[0], rxpkt->pad3[1]); print("ptr1 %lux\n", rxpkt->ptr1); print("%lux %lux\n", rxpkt->pad4[0], rxpkt->pad4[1]); print("seqno %lux\n", rxpkt->seqno); /* */ print("%lux %lux\n", rxpkt->pad5[0], rxpkt->pad5[1]); print("link %lux\n", rxpkt->link); /* descriptor link and EOL */ print("%lux %lux\n", rxpkt->pad6[0], rxpkt->pad6[1]); print("owner %lux\n", rxpkt->owner); /* in use */ } void . 361d 298d 294d 277a iprint("eobc #%lux\n", RD(eobc)); . 268a ISquad(ctlr->rra); ISquad(ctlr->rda); ISquad(ctlr->rb); . 258c for(i = 0; i < Nrb; i++) { . 245c WR(dcr, 0x2423); /* 5-19 Carrera manual */ iprint("eobc #%lux\n", RD(eobc)); . 237d 186c typedef struct { . 180c Ntypes = 8, . 19a #define ISquad(s) if((ulong)s & 0x7) panic("sonoc: Quad alignment"); . ## diffname carrera/devether.c 1993/0906 ## diff -e /n/fornaxdump/1993/0905/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/0906/sys/src/brazil/carrera/devether.c 694a } #define swiz(s) (s<<24)|((s>>8)&0xff00)|((s<<8)&0xff0000)|(s>>24) void sonicswap(void *a, int n) { ulong *p, t0, t1; n = ((n+8)/8)*8; p = a; while(n) { t0 = p[0]; t1 = p[1]; p[0] = swiz(t1); p[1] = swiz(t0); p += 2; n -= 8; } . 674,675d 660a sonicswap(p, n); . 654c p =(Pbuf*)ctlr->tb[ctlr->th]; . 638,639d 632c Pbuf *p; . 581d 562,567d 541,543c if(ether[0] == 0) { ctlr = malloc(sizeof(Ether)); ether[0] = ctlr; initbufs(ctlr); . 538,539d 526a static void initbufs(Ether *c) { int i; uchar *mem; mem = xspanalloc(64*1024, BY2PG, 0); mem = CACHELINE(uchar, mem); /* * Descriptors must be built in uncached space */ c->rra = UNCACHED(RXrsc, mem); mem = QUAD(uchar, mem+Nrb*sizeof(RXrsc)); c->rda = UNCACHED(RXpkt, mem); mem = QUAD(uchar, mem+Nrb*sizeof(RXpkt)); c->tda = UNCACHED(TXpkt, mem); mem = QUAD(uchar, mem+Ntb*sizeof(TXpkt)); c->cda = UNCACHED(Cam, mem); /* * DMA buffers are cache coherent - but we must not straddle * a cache line */ mem = CACHELINE(uchar, mem+sizeof(Cam)); for(i = 0; i < Nrb; i++) { c->rb[i] = UNCACHED(uchar, mem); mem += sizeof(Pbuf)+4; mem = QUAD(uchar, mem); } for(i = 0; i < Ntb; i++) { c->tb[i] = UNCACHED(uchar, mem); mem += sizeof(Pbuf); mem = QUAD(uchar, mem); } } . 506c print("sonic #%lux\n", status); . 501c print("sonic: bus retry occurred\n"); . 497c print("sonic: cd heartbeat lost\n"); . 481c rxpkt = &c->rda[c->rh]; . 478,479c c->rda[PREV(c->rh, Nrb)].link &= ~Eol; c->rh = NEXT(c->rh, Nrb); . 468c c->buffs++; . 466c c->crcs++; . 463c c->frames++; . 448,460c if(rxpkt->status & Prx) sonicpkt(c, rxpkt, (Pbuf*)c->rb[c->rh]); . 445,446d 440c c->inpackets++; . 437,438c rxpkt = &c->rda[c->rh]; . 425,426c c->ti = NEXT(c->ti, Ntb); txpkt = &c->tda[c->ti]; . 422c c->oerrs++; . 413c txpkt = &c->tda[c->ti]; . 405d 399c c = ether[0]; . 396,397d 390,392c Ether *c; . 371,384c int len; ushort type; Netfile *f, **fp, **ep; /* * Sonic delivers CRC as part of the packet count */ len = (r->count & 0xFFFF)-4; sonicswap(p, len); type = (p->type[0]<<8) | p->type[1]; ep = &ctlr->f[Ntypes]; for(fp = ctlr->f; fp < ep; fp++) { f = *fp; if(f && (f->type == type || f->type < 0)) qproduce(f->in, p->d, len); } . 369c sonicpkt(Ether *ctlr, RXpkt *r, Pbuf *p) . 353a /* * End the reset * Load the Resource Descriptors and Cam contents */ WR(cr, 0); WR(cr, Rrra); while(RD(cr) & Rrra) ; . 351c WR(cdp, LS16(ctlr->cda)); . 345,349c ctlr->cda->cep = 0; ctlr->cda->cap0 = (ctlr->ea[1]<<8)|ctlr->ea[0]; ctlr->cda->cap1 = (ctlr->ea[3]<<8)|ctlr->ea[2]; ctlr->cda->cap2 = (ctlr->ea[5]<<8)|ctlr->ea[4]; ctlr->cda->ce = 1; . 342,343d 301,304d 292,293d 283,284c WR(eobc, Rxbuf/2 - 2); . 273d 270a /* * Check the important resources are QUAD aligned */ . 267,268c loadr = LS16(ctlr->rb[i]); wus(&ctlr->rra[i].ptr0, loadr); wus(&ctlr->rda[i].ptr0, loadr); hiadr = MS16(ctlr->rb[i]); wus(&ctlr->rra[i].ptr1, hiadr); wus(&ctlr->rda[i].ptr1, hiadr); . 264c ctlr->rda[i].link = LS16(&ctlr->rda[NEXT(i, Nrb)]); . 261,262c wus(&ctlr->rra[i].wc0, lolen); wus(&ctlr->rra[i].wc1, hilen); . 259a lolen = (Rxbuf/2) & 0xFFFF; hilen = ((Rxbuf/2)>>16) & 0xFFFF; . 257c * thus the size of the receive buffers must be sizeof(Pbuf)+4. . 247,248d 243c * Setup the descriptor and buffer area. . 237a ushort lolen, hilen, loadr, hiadr; . 234a wus(ushort *a, ushort v) { a[0] = v; a[-1] = v; } static void . 233a void sonicswap(void*, int); . 223a uchar *rb[Nrb]; /* receive buffer area */ uchar *tb[Ntb]; /* transmit buffer area */ . 217,222c RXrsc *rra; /* receive resource area */ RXpkt *rda; /* receive descriptor area */ TXpkt *tda; /* transmit descriptor area */ Cam *cda; /* CAM descriptor area */ . 207,208d 189,198c ushort pad0; ushort cap0; /* CAM address port 0 */ ushort pad1; ushort cep; /* CAM entry pointer */ ushort pad2; ushort cap2; /* CAM address port 2 */ ushort pad3; ushort cap1; /* CAM address port 1 */ ulong pad4; ushort pad5; ushort ce; /* CAM enable */ . 157,172c ushort pad1; ushort config; /* */ ushort pad0; ushort status; /* transmit status */ ushort pad3; ushort count; /* fragment count */ ushort pad2; ushort size; /* byte count of entire packet */ ushort pad5; ushort ptr1; ushort pad4; ushort ptr0; /* packet pointer */ ushort pad7; ushort link; /* descriptor link */ ushort pad6; ushort fsize; /* fragment size */ . 136,149c ushort pad0; ushort count; /* packet byte count */ ushort pad1; ushort status; /* receive status */ ushort pad2; ushort ptr1; /* buffer pointer */ ushort pad3; ushort ptr0; ushort pad4; ushort link; /* descriptor link and EOL */ ushort pad5; ushort seqno; /* */ ulong pad6; ushort pad7; ushort owner; /* in use */ . 121,128c ushort pad1; ushort ptr1; /* buffer pointer in the RRA */ ushort pad2; ushort ptr0; ushort pad3; ushort wc1; /* buffer word count in the RRA */ ushort pad4; ushort wc0; . 113a Rxbuf = sizeof(Pbuf)+4, Txbuf = sizeof(Pbuf), . 35c ulong crba0; /* DO NOT WRITE THESE */ ulong crba1; ulong rbwc0; ulong rbwc1; . 21a typedef struct Pbuf Pbuf; struct Pbuf { uchar d[6]; uchar s[6]; uchar type[2]; uchar data[1500]; uchar crc[4]; }; . 19,20c #define WR(rn, v) (delay(1), *(ulong*)((ulong)&SONICADDR->rn^4) = (v)) #define ISquad(s) if((ulong)s & 0x7) panic("sonic: Quad alignment"); . ## diffname carrera/devether.c 1993/0918 ## diff -e /n/fornaxdump/1993/0906/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/0918/sys/src/brazil/carrera/devether.c 725a poperror(); . 701a if(waserror()) { qunlock(&ctlr->tlock); nexterror(); } . 464a wakeup(&c->tr); . ## diffname carrera/devether.c 1993/1202 ## diff -e /n/fornaxdump/1993/0918/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/1202/sys/src/brazil/carrera/devether.c 701a if(etherloop(buf, n)) return n; . 684a static int etherloop(Etherpkt *p, long n) { int s, different; ushort t; Netfile *f, **fp; different = memcmp(p->d, p->s, sizeof(p->s)); if(different && memcmp(p->d, ether.bcast, sizeof(p->d))) return 0; s = splhi(); t = (p->type[0]<<8) | p->type[1]; for(fp = ether.f; fp < ðer.f[Ntypes]; fp++) { f = *fp; if(f == 0) continue; if(f->type == t || f->type < 0) switch(qproduce(f->in, p->d, n)){ case -1: print("etherloop overflow\n"); break; case -2: print("etherloop memory\n"); break; } } splx(s); return !different; } . ## diffname carrera/devether.c 1993/1208 ## diff -e /n/fornaxdump/1993/1202/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/1208/sys/src/brazil/carrera/devether.c 698c for(fp = ether[0]->f; fp < ðer[0]->f[Ntypes]; fp++) { . 693c if(different && memcmp(p->d, ether[0]->bcast, sizeof(p->d))) . ## diffname carrera/devether.c 1993/1211 ## diff -e /n/fornaxdump/1993/1208/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/1211/sys/src/brazil/carrera/devether.c 745a reset(ctlr); WR(cr, Rxen); } . 744c if(!isoutbuf(ctlr)) { . 742c tsleep(&ctlr->tr, isoutbuf, ctlr, 1000); . ## diffname carrera/devether.c 1993/1212 ## diff -e /n/fornaxdump/1993/1211/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/1212/sys/src/brazil/carrera/devether.c 750c p = (Pbuf*)ctlr->tb[ctlr->th]; . 744,748c if(!isoutbuf(ctlr)) print("ether transmitter jammed cr #%lux\n", RD(cr)); . 742c tsleep(&ctlr->tr, isoutbuf, ctlr, 10000); . 731a if(n > ETHERMAXTU) error(Ebadarg); . 725,727d 678,685d 517c * Warnings that something is atoe. . 465c if(isoutbuf(c)) wakeup(&c->tr); . 427a static int isoutbuf(void *arg) { Ether *ctlr = arg; return ctlr->tda[ctlr->th].status == Host; } . 78c Ntb = 16, /* transmit buffers */ . ## diffname carrera/devether.c 1993/1217 ## diff -e /n/fornaxdump/1993/1212/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/1217/sys/src/brazil/carrera/devether.c 597a if(mem >= base+64*1024) panic("sonic init"); . 565a base = mem; . 563c uchar *mem, *base; . 534a for(;;); . 533c WR(cr, 0); iprint("sonic: bus retry occurred\n"); . 77,78c Nrb = 8, /* receive buffers */ Ntb = 8, /* transmit buffers */ . 18,19c #define RD(rn) (delay(0), *(ulong*)((ulong)&SONICADDR->rn^4)) #define WR(rn, v) (delay(0), *(ulong*)((ulong)&SONICADDR->rn^4) = (v)) . ## diffname carrera/devether.c 1993/1218 ## diff -e /n/fornaxdump/1993/1217/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/1218/sys/src/brazil/carrera/devether.c 536d 533,534c print("sonic: bus retry occurred\n"); . 253a sncdly(void) { int i, j, *pj; pj = &j; for(i = 0; i < 200; i++) *pj++; } static void . 77c Nrb = 16, /* receive buffers */ . 18,19c #define RD(rn) (sncdly(), *(ulong*)((ulong)&SONICADDR->rn^4)) #define WR(rn, v) (sncdly(), *(ulong*)((ulong)&SONICADDR->rn^4) = (v)) . ## diffname carrera/devether.c 1993/1219 ## diff -e /n/fornaxdump/1993/1218/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/1219/sys/src/brazil/carrera/devether.c 624d 466c if(status & (Txdn|Txer)) { . 460a /* Clear the interrupt cause */ . 254,263d 18,19c #define RD(rn) (delay(0), *(ulong*)((ulong)&SONICADDR->rn^4)) #define WR(rn, v) (delay(0), *(ulong*)((ulong)&SONICADDR->rn^4) = (v)) . ## diffname carrera/devether.c 1993/1231 ## diff -e /n/fornaxdump/1993/1219/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/1231/sys/src/brazil/carrera/devether.c 589d 584,587d 566c mem = xspanalloc(64*1024, 8, 64*1024); . ## diffname carrera/devether.c 1994/0107 ## diff -e /n/fornaxdump/1993/1231/sys/src/brazil/carrera/devether.c /n/fornaxdump/1994/0107/sys/src/brazil/carrera/devether.c 760c s = &ctlr->tda[PREV(ctlr->th, Ntb)].link; wus(s, *s & ~Eol); . 758c wus(&txpkt->link, txpkt->link|Eol); . 735a ctlr->outpackets++; . 718a ushort *s; . 539a } . 538c if(status & AllIntr) { WR(isr, status); . 533,536d 525,531d 523c if(status & Lcd) { WR(isr, Lcd); . 515a WR(isr, status & (Pktrx|Rde)); . 511c s = &c->rda[PREV(c->rh, Nrb)].link; wus(s, *s & ~Eol); . 509c wus(&rxpkt->link, rxpkt->link|Eol); . 502a rxpkt->status = 0; . 472a WR(isr, status & (Txdn|Txer)); . 451,452c /* * Warnings that something is atoe. */ if(status & Hbl){ WR(isr, Hbl); status &= ~Hbl; print("sonic: cd heartbeat lost\n"); } if(status & Br){ WR(cr, Rst); print("sonic: bus retry occurred\n"); (*(void(*)(void))0xA001C020)(); status &= ~Br; } . 439a ushort *s; . 400c WR(rcr, Brd); . 385,386d 382d 273a WR(cr, 0); . ## diffname carrera/devether.c 1994/0524 ## diff -e /n/fornaxdump/1994/0107/sys/src/brazil/carrera/devether.c /n/fornaxdump/1994/0524/sys/src/brazil/carrera/devether.c 573c /* Put the ethernet buffers in the same place * as the bootrom */ mem = (void*)(KZERO|0x2000); . ## diffname carrera/devether.c 1995/0108 ## diff -e /n/fornaxdump/1994/0524/sys/src/brazil/carrera/devether.c /n/fornaxdump/1995/0108/sys/src/brazil/carrera/devether.c 781a } long etherbwrite(Chan *c, Block *bp, ulong offset) { return devbwrite(c, bp, offset); . 693a Block* etherbread(Chan *c, long n, ulong offset) { return devbread(c, n, offset); } . ## diffname carrera/devether.c 1995/0114 ## diff -e /n/fornaxdump/1995/0108/sys/src/brazil/carrera/devether.c /n/fornaxdump/1995/0114/sys/src/brazil/carrera/devether.c 770d 747a p = buf; memmove(p->s, ctlr->ea, sizeof(ctlr->ea)); . 713c for(fp = ctlr->f; fp < &ctlr->f[Ntypes]; fp++) { . 707,708c different = memcmp(p->d, ctlr->ea, sizeof(ctlr->ea)); if(different && memcmp(p->d, ctlr->bcast, sizeof(p->d))) . 705a Ether *ctlr = ether[0]; . ## diffname carrera/devether.c 1995/0520 ## diff -e /n/fornaxdump/1995/0114/sys/src/brazil/carrera/devether.c /n/fornaxdump/1995/0520/sys/src/brazil/carrera/devether.c 654a if(*spec && strcmp(spec, "0") != 0) error(Eio); . ## diffname carrera/devether.c 1997/0327 ## diff -e /n/fornaxdump/1995/0520/sys/src/brazil/carrera/devether.c /n/emeliedump/1997/0327/sys/src/brazil/carrera/devether.c 836a int parseether(uchar *to, char *from) { char nip[4]; char *p; int i; p = from; for(i = 0; i < 6; i++){ if(*p == 0) return -1; nip[0] = *p++; if(*p == 0) return -1; nip[1] = *p++; nip[2] = 0; to[i] = strtoul(nip, 0, 16); if(*p == ':') p++; } return 0; } Dev etherdevtab = { etherreset, devinit, etherattach, devclone, etherwalk, etherstat, etheropen, ethercreate, etherclose, etherread, devbread, etherwrite, devbwrite, etherremove, etherwstat, }; . 821c static void . 813c static void . 807c static void . 795,801c static void . 734c static long . 696,701d 684c static void . 678c static void . 672c static Chan* . 660,666c static int . 641,646c static Chan* . 633c netifinit(ether[0], "ether0", Ntypes, 32*1024); . 609c static void . 403c static void . 251c static void sonicswap(void*, int); . 244c static Ether *ether[Nether]; . ## diffname carrera/devether.c 1997/0408 ## diff -e /n/emeliedump/1997/0327/sys/src/brazil/carrera/devether.c /n/emeliedump/1997/0408/sys/src/brazil/carrera/devether.c 838a 'l', "ether", . ## diffname carrera/devether.c 1997/1210 ## diff -e /n/emeliedump/1997/0408/sys/src/brazil/carrera/devether.c /n/emeliedump/1997/1210/sys/src/brazil/carrera/devether.c 854c etherbwrite, . 852c etherbread, . 837a #define POLY 0xedb88320 /* really slow 32 bit crc for ethers */ ulong ethercrc(uchar* p, int len) { int i, j; ulong crc, b; crc = 0xffffffff; for(i = 0; i < len; i++){ b = *p++; for(j = 0; j < 8; j++){ crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0); b >>= 1; } } return crc; } . 816c parseether(uchar* to, char* from) . 812a if(ether) free(ether); . 803,811c ether->alen = Eaddrlen; memset(ether->bcast, 0xFF, Eaddrlen); ether->arg = ether; ether->promiscuous = ether->dev->promiscuous; ether->multicast = ether->dev->multicast; etherxx[ctlrno] = ether; ether = 0; break; } . 798,801c snprint(name, sizeof(name), "ether%d", ctlrno); if(ether->mbps == 100){ netifinit(ether, name, Ntypes, 256*1024); if(ether->oq == 0) ether->oq = qopen(256*1024, 1, 0, 0); } else{ netifinit(ether, name, Ntypes, 32*1024); if(ether->oq == 0) ether->oq = qopen(64*1024, 1, 0, 0); } if(ether->oq == 0) panic("etherreset %s", name); . 796c i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX", ctlrno, ether->type, ether->mbps, ether->port); if(ether->irq) i += sprint(buf+i, " irq %d", ether->irq); if(ether->mem) i += sprint(buf+i, " addr 0x%luX", PADDR(ether->mem)); if(ether->size) i += sprint(buf+i, " size 0x%luX", ether->size); i += sprint(buf+i, ": %2.2uX%2.2uX%2.2uX%2.2uX%2.2uX%2.2uX", ether->addr[0], ether->addr[1], ether->addr[2], ether->addr[3], ether->addr[4], ether->addr[5]); sprint(buf+i, "\n"); print(buf); . 790,794c /* * IRQ2 doesn't really exist, it's used to gang the interrupt * controllers together. A device set to IRQ2 will appear on * the second interrupt controller as IRQ9. */ if(ether->irq == 2) ether->irq = 9; intrenable(VectorPIC+ether->irq, ether->interrupt, ether, ether->tbdf); . 784,788c for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){ if(ether == 0) ether = malloc(sizeof(Ether)); memset(ether, 0, sizeof(Ether)); ether->ctlrno = ctlrno; ether->tbdf = BUSUNKNOWN; ether->mbps = 10; if(isaconfig("ether", ctlrno, ether) == 0) continue; for(n = 0; endev[n]; n++){ if(cistrcmp(endev[n]->name, ether->type)) continue; ether->dev = endev[n]; for(i = 0; i < ether->nopt; i++){ if(strncmp(ether->opt[i], "ea=", 3)) continue; if(parseether(ether->addr, ðer->opt[i][3]) == -1) memset(ether->addr, 0, Eaddrlen); } if(endev[n]->reset(ether)) break; . 781,782c Ether *ether; int i, n, ctlrno; char name[NAMELEN], buf[128]; . 778,779c void etherreset(void) . 775c return etheroq(ether, bp); . 772,773c if(n < ETHERMINTU){ freeb(bp); error(Etoosmall); } . 748,770c if(n > ETHERMAXTU){ freeb(bp); error(Ebadarg); . 740,745d 725,738c n = BLEN(bp); ether = etherxx[chan->dev]; if(NETTYPE(chan->qid.path) != Ndataqid){ n = netifwrite(ether, chan, bp->rp, n); freeb(bp); . 720,723c Ether *ether; long n; . 718c etherbwrite(Chan* chan, Block* bp, ulong) . 673,716d 667,670c return etheroq(ether, bp); . 661,665c bp = allocb(n); if(waserror()){ freeb(bp); nexterror(); } memmove(bp->rp, buf, n); memmove(bp->rp+Eaddrlen, ether->addr, Eaddrlen); poperror(); bp->wp += n; . 655,659c if(n > ETHERMAXTU) error(Etoobig); if(n < ETHERMINTU) error(Etoosmall); . 646,653c ether = etherxx[chan->dev]; if(NETTYPE(chan->qid.path) != Ndataqid) return netifwrite(ether, chan, buf, n); . 644c Ether *ether; Block *bp; . 641,642c static long etherwrite(Chan* chan, void* buf, long n, ulong) . 628,638c return len; . 626d 609,624c if(!loopback){ if(ether->dev && ether->dev->transmit){ qbwrite(ether->oq, bp); ether->dev->transmit(ether); } else{ freeb(bp); return 0; } . 600,607d 583,598c pkt = (Etherpkt*)bp->rp; len = BLEN(bp); loopback = (memcmp(pkt->d, ether->addr, sizeof(pkt->d)) == 0); if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){ s = splhi(); etheriq(ether, bp, loopback); splx(s); . 581c * Check if the packet has to be placed back onto the input queue, * i.e. if it's a loopback or broadcast packet or the interface is * in promiscuous mode. * If it's a loopback packet indicate to etheriq that the data isn't * needed and return, etheriq will pass-on or free the block. . 573,578c ether->outpackets++; . 570,571c int len, loopback, s; Etherpkt *pkt; . 567,568c static int etheroq(Ether* ether, Block* bp) . 550,564c return bp; . 548c if(freebp){ freeb(bp); return 0; } . 533,546c if(fx){ qpass(fx->in, bp); return 0; . 530,531c } . 507,528c etherrtrace(f, pkt, len); . 490,505c /* * Multiplex the packet to all the connections which want it. * If the packet is not to be used subsequently (freebp != 0), * attempt to simply pass it into one of the connections, thereby * saving a copy of the data (usual case hopefully). */ for(fp = ether->f; fp < ep; fp++){ if((f = *fp) && (f->type == type || f->type < 0)){ if(f->type > -2){ if(freebp && fx == 0) fx = f; else if(xbp = iallocb(len)){ memmove(xbp->wp, pkt, len); xbp->wp += len; qpass(f->in, xbp); } else ether->soverflows++; } . 488a } . 484,487c return bp; . 450,482c /* check for valid multcast addresses */ if((pkt->d[0] & 1) && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) && ether->prom == 0){ if(!activemulti(ether, pkt->d, sizeof(pkt->d))){ if(freebp){ freeb(bp); bp = 0; . 445,448c pkt = (Etherpkt*)bp->rp; len = BLEN(bp); type = (pkt->type[0]<<8)|pkt->type[1]; fx = 0; ep = ðer->f[Ntypes]; . 443c ether->inpackets++; . 437,441c Etherpkt *pkt; ushort type; int len; Netfile **ep, *f, **fp, *fx; Block *xbp; . 434,435c Block* etheriq(Ether* ether, Block* bp, int freebp) . 431c if(qwindow(f->in) <= 0) return; if(len > 64) n = 64; else n = len; bp = iallocb(n); if(bp == 0) return; memmove(bp->wp, pkt->d, n); i = TK2MS(MACHP(0)->ticks); bp->wp[58] = len>>8; bp->wp[59] = len; bp->wp[60] = i>>24; bp->wp[61] = i>>16; bp->wp[62] = i>>8; bp->wp[63] = i; bp->wp += 64; qpass(f->in, bp); . 429c int i, n; Block *bp; . 426,427c static void etherrtrace(Netfile* f, Etherpkt* pkt, int len) . 406,423c netifwstat(etherxx[chan->dev], chan, dp); . 404c etherwstat(Chan* chan, char* dp) . 263,400d 261c etherremove(Chan*) . 256,257c return netifbread(etherxx[chan->dev], chan, n, offset); . 233,254c static Block* etherbread(Chan* chan, long n, ulong offset) . 230,231c return netifread(ether, chan, buf, n, offset); } . 225,228c ether = etherxx[chan->dev]; if((chan->qid.path & CHDIR) == 0 && ether->dev && ether->dev->ifstat){ /* * With some controllers it is necessary to reach * into the chip to extract statistics. */ if(NETTYPE(chan->qid.path) == Nifstatqid) return ether->dev->ifstat(ether, buf, n, offset); else if(NETTYPE(chan->qid.path) == Nstatqid) ether->dev->ifstat(ether, buf, 0, offset); } . 222,223c Ether *ether; . 219,220c static long etherread(Chan* chan, void* buf, long n, ulong offset) . 206,217c netifclose(etherxx[chan->dev], chan); } . 192,204c static void etherclose(Chan* chan) . 174,190c } . 169,172c static void ethercreate(Chan*, char*, int, ulong) . 152,167c return netifopen(etherxx[chan->dev], chan, omode); } . 147,150c static Chan* etheropen(Chan* chan, int omode) . 137,145c netifstat(etherxx[chan->dev], chan, dp); } . 93,135c static void etherstat(Chan* chan, char* dp) . 83,91c return netifwalk(etherxx[chan->dev], chan, name); } . 81c static int etherwalk(Chan* chan, char* name) . 75,79c chan = devattach('l', spec); chan->dev = ctlrno; if(etherxx[ctlrno]->dev && etherxx[ctlrno]->dev->attach) etherxx[ctlrno]->dev->attach(etherxx[ctlrno]); return chan; } . 32,73c ctlrno = 0; if(spec && *spec){ ctlrno = strtoul(spec, &p, 0); if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther)) error(Ebadarg); } if(etherxx[ctlrno] == 0) error(Enodev); . 25,30c ulong ctlrno; char *p; Chan *chan; . 18,23c Chan* etherattach(char* spec) . 16c static Ether *etherxx[MaxEther]; . 10,14c #include "etherif.h" . 1,8c #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "ureg.h" #include "../port/error.h" #include "../port/netif.h" . ## diffname carrera/devether.c 1998/0319 ## diff -e /n/emeliedump/1997/1210/sys/src/brazil/carrera/devether.c /n/emeliedump/1998/0319/sys/src/brazil/carrera/devether.c 234c etherwrite(Chan* chan, void* buf, long n, vlong) . 70a ulong offset = off; . 68c etherread(Chan* chan, void* buf, long n, vlong off) . ## diffname carrera/devether.c 1999/0629 ## diff -e /n/emeliedump/1998/0319/sys/src/brazil/carrera/devether.c /n/emeliedump/1999/0629/sys/src/brazil/carrera/devether.c 329c i += sprint(buf+i, " irq %ld", ether->irq); . ## diffname carrera/devether.c 2000/0713 ## diff -e /n/emeliedump/1999/0629/sys/src/brazil/carrera/devether.c /n/emeliedump/2000/0713/sys/src/9/carrera/devether.c 117,118c bp = iallocb(64); if(bp == nil) . 113,114c if(len > 58) n = 58; . ## diffname carrera/devether.c 2001/0527 # deleted ## diff -e /n/emeliedump/2000/0713/sys/src/9/carrera/devether.c /n/emeliedump/2001/0527/sys/src/9/carrera/devether.c 1,431d