3 * PCnet-PCI Single-Chip Ethernet Controller for PCI Local Bus
8 #include "../port/lib.h"
13 #include "../port/error.h"
14 #include "../port/netif.h"
20 Nrdre = (1<<Lognrdre),/* receive descriptor ring entries */
22 Ntdre = (1<<Logntdre),/* transmit descriptor ring entries */
24 Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */
27 enum { /* DWIO I/O resource map */
28 Aprom = 0x0000, /* physical address */
29 Rdp = 0x0010, /* register data port */
30 Rap = 0x0014, /* register address port */
31 Sreset = 0x0018, /* software reset */
32 Bdp = 0x001C, /* bus configuration register data port */
36 Init = 0x0001, /* begin initialisation */
37 Strt = 0x0002, /* enable chip */
38 Stop = 0x0004, /* disable chip */
39 Tdmd = 0x0008, /* transmit demand */
40 Txon = 0x0010, /* transmitter on */
41 Rxon = 0x0020, /* receiver on */
42 Iena = 0x0040, /* interrupt enable */
43 Intr = 0x0080, /* interrupt flag */
44 Idon = 0x0100, /* initialisation done */
45 Tint = 0x0200, /* transmit interrupt */
46 Rint = 0x0400, /* receive interrupt */
47 Merr = 0x0800, /* memory error */
48 Miss = 0x1000, /* missed frame */
49 Cerr = 0x2000, /* collision */
50 Babl = 0x4000, /* transmitter timeout */
51 Err = 0x8000, /* Babl|Cerr|Miss|Merr */
55 Bswp = 0x0004, /* byte swap */
56 Emba = 0x0008, /* enable modified back-off algorithm */
57 Dxmt2pd = 0x0010, /* disable transmit two part deferral */
58 Lappen = 0x0020, /* look-ahead packet processing enable */
62 ApadXmt = 0x0800, /* auto pad transmit */
66 Prom = 0x8000, /* promiscuous mode */
69 typedef struct Iblock Iblock;
70 struct Iblock { /* Initialisation Block */
72 uchar rlen; /* upper 4 bits */
73 uchar tlen; /* upper 4 bits */
81 typedef struct Dre Dre;
82 struct Dre { /* descriptor ring entry */
84 ulong md1; /* status|bcnt */
85 ulong md2; /* rcc|rpc|mcnt */
91 Enp = 0x01000000, /* end of packet */
92 Stp = 0x02000000, /* start of packet */
93 RxBuff = 0x04000000, /* buffer error */
94 Def = 0x04000000, /* deferred */
95 Crc = 0x08000000, /* CRC error */
96 One = 0x08000000, /* one retry needed */
97 Oflo = 0x10000000, /* overflow error */
98 More = 0x10000000, /* more than one retry needed */
99 Fram = 0x20000000, /* framing error */
100 RxErr = 0x40000000, /* Fram|Oflo|Crc|RxBuff */
101 TxErr = 0x40000000, /* Uflo|Lcol|Lcar|Rtry */
106 Rtry = 0x04000000, /* failed after repeated retries */
107 Lcar = 0x08000000, /* loss of carrier */
108 Lcol = 0x10000000, /* late collision */
109 Uflo = 0x40000000, /* underflow error */
110 TxBuff = 0x80000000, /* buffer error */
113 typedef struct Ctlr Ctlr;
121 int init; /* initialisation in progress */
125 Dre* rdr; /* receive descriptor ring */
129 Dre* tdr; /* transmit descriptor ring */
130 int tdrh; /* host index into tdr */
131 int tdri; /* interface index into tdr */
132 int ntq; /* descriptors active */
134 ulong rxbuff; /* receive statistics */
139 ulong rtry; /* transmit statistics */
145 ulong merr; /* bobf is such a whiner */
149 int (*ior)(Ctlr*, int);
150 void (*iow)(Ctlr*, int, int);
153 static Ctlr* ctlrhead;
154 static Ctlr* ctlrtail;
157 * The Rdp, Rap, Sreset, Bdp ports are 32-bit port offset in the enumeration above.
158 * To get to 16-bit offsets, scale down with 0x10 staying the same.
161 io16r(Ctlr *c, int r)
165 return ins(c->port+r);
169 io16w(Ctlr *c, int r, int v)
177 io32r(Ctlr *c, int r)
179 return inl(c->port+r);
183 io32w(Ctlr *c, int r, int v)
194 ifstat(Ether* ether, void* a, long n, ulong offset)
202 ether->crcs = ctlr->crc;
203 ether->frames = ctlr->fram;
204 ether->buffs = ctlr->rxbuff+ctlr->txbuff;
205 ether->overflows = ctlr->oflo;
210 p = smalloc(READSTR);
211 len = snprint(p, READSTR, "Rxbuff: %ld\n", ctlr->rxbuff);
212 len += snprint(p+len, READSTR-len, "Crc: %ld\n", ctlr->crc);
213 len += snprint(p+len, READSTR-len, "Oflo: %ld\n", ctlr->oflo);
214 len += snprint(p+len, READSTR-len, "Fram: %ld\n", ctlr->fram);
215 len += snprint(p+len, READSTR-len, "Rtry: %ld\n", ctlr->rtry);
216 len += snprint(p+len, READSTR-len, "Lcar: %ld\n", ctlr->lcar);
217 len += snprint(p+len, READSTR-len, "Lcol: %ld\n", ctlr->lcol);
218 len += snprint(p+len, READSTR-len, "Uflo: %ld\n", ctlr->uflo);
219 len += snprint(p+len, READSTR-len, "Txbuff: %ld\n", ctlr->txbuff);
220 len += snprint(p+len, READSTR-len, "Merr: %ld\n", ctlr->merr);
221 len += snprint(p+len, READSTR-len, "Miss: %ld\n", ctlr->miss);
222 snprint(p+len, READSTR-len, "Babl: %ld\n", ctlr->babl);
224 n = readstr(offset, a, n, p);
238 * Initialise the receive and transmit buffer rings.
239 * The ring entries must be aligned on 16-byte boundaries.
241 * This routine is protected by ctlr->init.
244 ctlr->rb = malloc(Nrdre*sizeof(Block*));
246 ctlr->rdr = xspanalloc(Nrdre*sizeof(Dre), 0x10, 0);
247 for(i=0; i<Nrdre; i++){
248 bp = iallocb(Rbsize);
250 panic("can't allocate ethernet receive ring");
253 dre->addr = PADDR(bp->rp);
255 dre->md1 = Own|(-Rbsize & 0xFFFF);
262 ctlr->tb = malloc(Ntdre*sizeof(Block*));
264 ctlr->tdr = xspanalloc(Ntdre*sizeof(Dre), 0x10, 0);
265 memset(ctlr->tdr, 0, Ntdre*sizeof(Dre));
266 ctlr->tdrh = ctlr->tdri = 0;
270 promiscuous(void* arg, int on)
280 * Put the chip into promiscuous mode. First must wait until
281 * anyone transmitting is done, then stop the chip and put
282 * it in promiscuous mode. Restarting is made harder by the chip
283 * reloading the transmit and receive descriptor pointers with their
284 * base addresses when Strt is set (unlike the older Lance chip),
285 * so the rings must be re-initialised.
298 ctlr->iow(ctlr, Rdp, Stop);
300 ctlr->iow(ctlr, Rap, 15);
301 x = ctlr->ior(ctlr, Rdp) & ~Prom;
304 ctlr->iow(ctlr, Rdp, x);
305 ctlr->iow(ctlr, Rap, 0);
311 ctlr->iow(ctlr, Rdp, Iena|Strt);
316 multicast(void* arg, uchar*, int)
322 txstart(Ether* ether)
334 while(ctlr->ntq < (Ntdre-1)){
335 bp = qget(ether->oq);
340 * Give ownership of the descriptor to the chip,
341 * increment the software ring descriptor pointer
342 * and tell the chip to poll.
343 * There's no need to pad to ETHERMINTU
344 * here as ApadXmt is set in CSR4.
347 if(ctlr->tb[i] != nil)
351 dre->addr = PADDR(bp->rp);
353 dre->md1 = Own|Stp|Enp|(-BLEN(bp) & 0xFFFF);
355 ctlr->iow(ctlr, Rdp, Iena|Tdmd);
356 ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre);
361 transmit(Ether* ether)
372 interrupt(Ureg*, void* arg)
384 * Acknowledge all interrupts and whine about those that shouldn't
388 csr0 = ctlr->ior(ctlr, Rdp) & 0xFFFF;
389 ctlr->iow(ctlr, Rdp, Babl|Cerr|Miss|Merr|Rint|Tint|Iena);
396 //if(csr0 & (Babl|Miss|Merr))
397 // print("#l%d: csr0 = 0x%uX\n", ether->ctlrno, csr0);
398 if(!(csr0 & (Rint|Tint)))
402 * Receiver interrupt: run round the descriptor ring logging
403 * errors and passing valid receive data up to the higher levels
404 * until a descriptor is encountered still owned by the chip.
409 while(!(dre->md1 & Own)){
410 if(dre->md1 & RxErr){
411 if(dre->md1 & RxBuff)
420 else if(bp = iallocb(Rbsize)){
424 len = (dre->md2 & 0x0FFF)-4;
426 etheriq(ether, bb, 1);
428 dre->addr = PADDR(bp->rp);
432 * Finished with this descriptor, reinitialise it,
433 * give it back to the chip, then on to the next...
436 dre->md1 = Own|(-Rbsize & 0xFFFF);
438 ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre);
439 dre = &ctlr->rdr[ctlr->rdrx];
444 * Transmitter interrupt: wakeup anyone waiting for a free descriptor.
454 if(dre->md1 & TxErr){
463 if(dre->md2 & TxBuff)
474 ctlr->tdri = NEXT(ctlr->tdri, Ntdre);
490 while(p = pcimatch(p, 0x1022, 0x2000)){
491 port = p->mem[0].bar & ~0x01;
492 if(ioalloc(port, p->mem[0].size, 0, "amd79c970") < 0){
493 print("amd79c970: port 0x%uX in use\n", port);
496 ctlr = malloc(sizeof(Ctlr));
498 print("amd79c970: can't allocate memory\n");
502 ctlr->port = p->mem[0].bar & ~0x01;
506 ctlrtail->next = ctlr;
524 * Any adapter matches if no port is supplied,
525 * otherwise the ports must match.
527 for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
530 if(ether->port == 0 || ether->port == ctlr->port){
539 * Allocate a controller structure and start to initialise it.
542 ether->port = ctlr->port;
543 ether->irq = ctlr->pcidev->intl;
544 ether->tbdf = ctlr->pcidev->tbdf;
545 pcisetbme(ctlr->pcidev);
552 if(io16w(ctlr, Rap, 0), io16r(ctlr, Rdp) == 4){
555 }else if(io32w(ctlr, Rap, 0), io32r(ctlr, Rdp) == 4){
559 print("#l%d: card doesn't talk right\n", ether->ctlrno);
564 ctlr->iow(ctlr, Rap, 88);
565 x = ctlr->ior(ctlr, Rdp);
566 ctlr->iow(ctlr, Rap, 89);
567 x |= ctlr->ior(ctlr, Rdp)<<16;
570 case 0x2420003: /* PCnet/PCI 79C970 */
571 case 0x2621003: /* PCnet/PCI II 79C970A */
572 case 0x2625003: /* PCnet-FAST III 79C973 */
575 print("#l%d: unknown PCnet card version 0x%.7ux\n",
576 ether->ctlrno, x&0xFFFFFFF);
582 * Set the software style in BCR20 to be PCnet-PCI to ensure 32-bit access.
583 * Set the auto pad transmit in CSR4.
585 ctlr->iow(ctlr, Rap, 20);
586 ctlr->iow(ctlr, Bdp, 0x0002);
588 ctlr->iow(ctlr, Rap, 4);
589 x = ctlr->ior(ctlr, Rdp) & 0xFFFF;
590 ctlr->iow(ctlr, Rdp, ApadXmt|x);
592 ctlr->iow(ctlr, Rap, 0);
595 * Check if the adapter's station address is to be overridden.
596 * If not, read it from the I/O-space and set in ether->ea prior to
597 * loading the station address in the initialisation block.
599 memset(ea, 0, Eaddrlen);
600 if(!memcmp(ea, ether->ea, Eaddrlen)){
601 x = ctlr->ior(ctlr, Aprom);
604 if(ctlr->ior == io16r)
605 x = ctlr->ior(ctlr, Aprom+2);
610 x = ctlr->ior(ctlr, Aprom+4);
616 * Start to fill in the initialisation block
617 * (must be DWORD aligned).
619 ctlr->iblock.rlen = Lognrdre<<4;
620 ctlr->iblock.tlen = Logntdre<<4;
621 memmove(ctlr->iblock.padr, ether->ea, sizeof(ctlr->iblock.padr));
624 ctlr->iblock.rdra = PADDR(ctlr->rdr);
625 ctlr->iblock.tdra = PADDR(ctlr->tdr);
628 * Point the chip at the initialisation block and tell it to go.
629 * Mask the Idon interrupt and poll for completion. Strt and interrupt
630 * enables will be set later when attaching to the network.
632 x = PADDR(&ctlr->iblock);
633 ctlr->iow(ctlr, Rap, 1);
634 ctlr->iow(ctlr, Rdp, x & 0xFFFF);
635 ctlr->iow(ctlr, Rap, 2);
636 ctlr->iow(ctlr, Rdp, (x>>16) & 0xFFFF);
637 ctlr->iow(ctlr, Rap, 3);
638 ctlr->iow(ctlr, Rdp, Idon);
639 ctlr->iow(ctlr, Rap, 0);
640 ctlr->iow(ctlr, Rdp, Init);
642 while(!(ctlr->ior(ctlr, Rdp) & Idon))
646 * We used to set CSR0 to Idon|Stop here, and then
647 * in attach change it to Iena|Strt. Apparently the simulated
648 * 79C970 in VMware never enables after a write of Idon|Stop,
649 * so we enable the device here now.
651 ctlr->iow(ctlr, Rdp, Iena|Strt);
656 * Linkage to the generic ethernet driver.
658 ether->attach = attach;
659 ether->transmit = transmit;
660 ether->interrupt = interrupt;
661 ether->ifstat = ifstat;
664 ether->promiscuous = promiscuous;
665 ether->multicast = multicast;
666 // ether->shutdown = shutdown;
672 ether79c970link(void)
674 addethercard("AMD79C970", reset);