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"
15 #include "../port/etherif.h"
19 Nrdre = (1<<Lognrdre),/* receive descriptor ring entries */
21 Ntdre = (1<<Logntdre),/* transmit descriptor ring entries */
23 Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */
26 enum { /* DWIO I/O resource map */
27 Aprom = 0x0000, /* physical address */
28 Rdp = 0x0010, /* register data port */
29 Rap = 0x0014, /* register address port */
30 Sreset = 0x0018, /* software reset */
31 Bdp = 0x001C, /* bus configuration register data port */
35 Init = 0x0001, /* begin initialisation */
36 Strt = 0x0002, /* enable chip */
37 Stop = 0x0004, /* disable chip */
38 Tdmd = 0x0008, /* transmit demand */
39 Txon = 0x0010, /* transmitter on */
40 Rxon = 0x0020, /* receiver on */
41 Iena = 0x0040, /* interrupt enable */
42 Intr = 0x0080, /* interrupt flag */
43 Idon = 0x0100, /* initialisation done */
44 Tint = 0x0200, /* transmit interrupt */
45 Rint = 0x0400, /* receive interrupt */
46 Merr = 0x0800, /* memory error */
47 Miss = 0x1000, /* missed frame */
48 Cerr = 0x2000, /* collision */
49 Babl = 0x4000, /* transmitter timeout */
50 Err = 0x8000, /* Babl|Cerr|Miss|Merr */
54 Bswp = 0x0004, /* byte swap */
55 Emba = 0x0008, /* enable modified back-off algorithm */
56 Dxmt2pd = 0x0010, /* disable transmit two part deferral */
57 Lappen = 0x0020, /* look-ahead packet processing enable */
61 ApadXmt = 0x0800, /* auto pad transmit */
65 Prom = 0x8000, /* promiscuous mode */
68 typedef struct Iblock Iblock;
69 struct Iblock { /* Initialisation Block */
71 uchar rlen; /* upper 4 bits */
72 uchar tlen; /* upper 4 bits */
80 typedef struct Dre Dre;
81 struct Dre { /* descriptor ring entry */
83 ulong md1; /* status|bcnt */
84 ulong md2; /* rcc|rpc|mcnt */
90 Enp = 0x01000000, /* end of packet */
91 Stp = 0x02000000, /* start of packet */
92 RxBuff = 0x04000000, /* buffer error */
93 Def = 0x04000000, /* deferred */
94 Crc = 0x08000000, /* CRC error */
95 One = 0x08000000, /* one retry needed */
96 Oflo = 0x10000000, /* overflow error */
97 More = 0x10000000, /* more than one retry needed */
98 Fram = 0x20000000, /* framing error */
99 RxErr = 0x40000000, /* Fram|Oflo|Crc|RxBuff */
100 TxErr = 0x40000000, /* Uflo|Lcol|Lcar|Rtry */
105 Rtry = 0x04000000, /* failed after repeated retries */
106 Lcar = 0x08000000, /* loss of carrier */
107 Lcol = 0x10000000, /* late collision */
108 Uflo = 0x40000000, /* underflow error */
109 TxBuff = 0x80000000, /* buffer error */
112 typedef struct Ctlr Ctlr;
120 int init; /* initialisation in progress */
124 Dre* rdr; /* receive descriptor ring */
128 Dre* tdr; /* transmit descriptor ring */
129 int tdrh; /* host index into tdr */
130 int tdri; /* interface index into tdr */
131 int ntq; /* descriptors active */
133 ulong rxbuff; /* receive statistics */
138 ulong rtry; /* transmit statistics */
144 ulong merr; /* bobf is such a whiner */
148 int (*ior)(Ctlr*, int);
149 void (*iow)(Ctlr*, int, int);
152 static Ctlr* ctlrhead;
153 static Ctlr* ctlrtail;
156 * The Rdp, Rap, Sreset, Bdp ports are 32-bit port offset in the enumeration above.
157 * To get to 16-bit offsets, scale down with 0x10 staying the same.
160 io16r(Ctlr *c, int r)
164 return ins(c->port+r);
168 io16w(Ctlr *c, int r, int v)
176 io32r(Ctlr *c, int r)
178 return inl(c->port+r);
182 io32w(Ctlr *c, int r, int v)
193 ifstat(Ether* ether, void* a, long n, ulong offset)
201 ether->crcs = ctlr->crc;
202 ether->frames = ctlr->fram;
203 ether->buffs = ctlr->rxbuff+ctlr->txbuff;
204 ether->overflows = ctlr->oflo;
209 p = smalloc(READSTR);
210 len = snprint(p, READSTR, "Rxbuff: %ld\n", ctlr->rxbuff);
211 len += snprint(p+len, READSTR-len, "Crc: %ld\n", ctlr->crc);
212 len += snprint(p+len, READSTR-len, "Oflo: %ld\n", ctlr->oflo);
213 len += snprint(p+len, READSTR-len, "Fram: %ld\n", ctlr->fram);
214 len += snprint(p+len, READSTR-len, "Rtry: %ld\n", ctlr->rtry);
215 len += snprint(p+len, READSTR-len, "Lcar: %ld\n", ctlr->lcar);
216 len += snprint(p+len, READSTR-len, "Lcol: %ld\n", ctlr->lcol);
217 len += snprint(p+len, READSTR-len, "Uflo: %ld\n", ctlr->uflo);
218 len += snprint(p+len, READSTR-len, "Txbuff: %ld\n", ctlr->txbuff);
219 len += snprint(p+len, READSTR-len, "Merr: %ld\n", ctlr->merr);
220 len += snprint(p+len, READSTR-len, "Miss: %ld\n", ctlr->miss);
221 snprint(p+len, READSTR-len, "Babl: %ld\n", ctlr->babl);
223 n = readstr(offset, a, n, p);
237 * Initialise the receive and transmit buffer rings.
238 * The ring entries must be aligned on 16-byte boundaries.
240 * This routine is protected by ctlr->init.
243 ctlr->rb = malloc(Nrdre*sizeof(Block*));
245 ctlr->rdr = xspanalloc(Nrdre*sizeof(Dre), 0x10, 0);
246 for(i=0; i<Nrdre; i++){
247 bp = iallocb(Rbsize);
249 panic("can't allocate ethernet receive ring");
252 dre->addr = PADDR(bp->rp);
254 dre->md1 = Own|(-Rbsize & 0xFFFF);
261 ctlr->tb = malloc(Ntdre*sizeof(Block*));
263 ctlr->tdr = xspanalloc(Ntdre*sizeof(Dre), 0x10, 0);
264 memset(ctlr->tdr, 0, Ntdre*sizeof(Dre));
265 ctlr->tdrh = ctlr->tdri = 0;
269 promiscuous(void* arg, int on)
279 * Put the chip into promiscuous mode. First must wait until
280 * anyone transmitting is done, then stop the chip and put
281 * it in promiscuous mode. Restarting is made harder by the chip
282 * reloading the transmit and receive descriptor pointers with their
283 * base addresses when Strt is set (unlike the older Lance chip),
284 * so the rings must be re-initialised.
297 ctlr->iow(ctlr, Rdp, Stop);
299 ctlr->iow(ctlr, Rap, 15);
300 x = ctlr->ior(ctlr, Rdp) & ~Prom;
301 if(on || ether->nmaddr > 0)
303 ctlr->iow(ctlr, Rdp, x);
304 ctlr->iow(ctlr, Rap, 0);
310 ctlr->iow(ctlr, Rdp, Iena|Strt);
315 multicast(void* arg, uchar*, int)
318 promiscuous(arg, ether->prom);
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.
410 while(!(dre->md1 & Own)){
411 if(dre->md1 & RxErr){
412 if(dre->md1 & RxBuff)
421 else if(bp = iallocb(Rbsize)){
425 len = (dre->md2 & 0x0FFF)-4;
429 dre->addr = PADDR(bp->rp);
433 * Finished with this descriptor, reinitialise it,
434 * give it back to the chip, then on to the next...
437 dre->md1 = Own|(-Rbsize & 0xFFFF);
439 i = ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre);
446 * Transmitter interrupt: wakeup anyone waiting for a free descriptor.
456 if(dre->md1 & TxErr){
465 if(dre->md2 & TxBuff)
476 ctlr->tdri = NEXT(ctlr->tdri, Ntdre);
492 while(p = pcimatch(p, 0x1022, 0x2000)){
493 port = p->mem[0].bar & ~0x01;
494 if(ioalloc(port, p->mem[0].size, 0, "amd79c970") < 0){
495 print("amd79c970: port 0x%uX in use\n", port);
498 ctlr = malloc(sizeof(Ctlr));
500 print("amd79c970: can't allocate memory\n");
504 ctlr->port = p->mem[0].bar & ~0x01;
508 ctlrtail->next = ctlr;
526 * Any adapter matches if no port is supplied,
527 * otherwise the ports must match.
529 for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
532 if(ether->port == 0 || ether->port == ctlr->port){
541 * Allocate a controller structure and start to initialise it.
544 ether->port = ctlr->port;
545 ether->irq = ctlr->pcidev->intl;
546 ether->tbdf = ctlr->pcidev->tbdf;
549 pcienable(ctlr->pcidev);
550 pcisetbme(ctlr->pcidev);
555 if(io16w(ctlr, Rap, 0), io16r(ctlr, Rdp) == 4){
558 }else if(io32w(ctlr, Rap, 0), io32r(ctlr, Rdp) == 4){
562 print("#l%d: card doesn't talk right\n", ether->ctlrno);
567 ctlr->iow(ctlr, Rap, 88);
568 x = ctlr->ior(ctlr, Rdp);
569 ctlr->iow(ctlr, Rap, 89);
570 x |= ctlr->ior(ctlr, Rdp)<<16;
573 case 0x2420003: /* PCnet/PCI 79C970 */
574 case 0x2621003: /* PCnet/PCI II 79C970A */
577 case 0x2625003: /* PCnet-FAST III 79C973 */
581 print("#l%d: unknown PCnet card version 0x%.7ux\n",
582 ether->ctlrno, x&0xFFFFFFF);
588 * Set the software style in BCR20 to be PCnet-PCI to ensure 32-bit access.
589 * Set the auto pad transmit in CSR4.
591 ctlr->iow(ctlr, Rap, 20);
592 ctlr->iow(ctlr, Bdp, 0x0002);
594 ctlr->iow(ctlr, Rap, 4);
595 x = ctlr->ior(ctlr, Rdp) & 0xFFFF;
596 ctlr->iow(ctlr, Rdp, ApadXmt|x);
598 ctlr->iow(ctlr, Rap, 0);
601 * Check if the adapter's station address is to be overridden.
602 * If not, read it from the I/O-space and set in ether->ea prior to
603 * loading the station address in the initialisation block.
605 memset(ea, 0, Eaddrlen);
606 if(!memcmp(ea, ether->ea, Eaddrlen)){
607 x = ctlr->ior(ctlr, Aprom);
610 if(ctlr->ior == io16r)
611 x = ctlr->ior(ctlr, Aprom+2);
616 x = ctlr->ior(ctlr, Aprom+4);
622 x = ether->ea[0]<<16 | ether->ea[1]<<8 | ether->ea[2];
631 * Start to fill in the initialisation block
632 * (must be DWORD aligned).
634 ctlr->iblock.rlen = Lognrdre<<4;
635 ctlr->iblock.tlen = Logntdre<<4;
636 memmove(ctlr->iblock.padr, ether->ea, sizeof(ctlr->iblock.padr));
639 ctlr->iblock.rdra = PADDR(ctlr->rdr);
640 ctlr->iblock.tdra = PADDR(ctlr->tdr);
643 * Point the chip at the initialisation block and tell it to go.
644 * Mask the Idon interrupt and poll for completion. Strt and interrupt
645 * enables will be set later when attaching to the network.
647 x = PADDR(&ctlr->iblock);
648 ctlr->iow(ctlr, Rap, 1);
649 ctlr->iow(ctlr, Rdp, x & 0xFFFF);
650 ctlr->iow(ctlr, Rap, 2);
651 ctlr->iow(ctlr, Rdp, (x>>16) & 0xFFFF);
652 ctlr->iow(ctlr, Rap, 3);
653 ctlr->iow(ctlr, Rdp, Idon);
654 ctlr->iow(ctlr, Rap, 0);
655 ctlr->iow(ctlr, Rdp, Init);
657 while(!(ctlr->ior(ctlr, Rdp) & Idon))
661 * We used to set CSR0 to Idon|Stop here, and then
662 * in attach change it to Iena|Strt. Apparently the simulated
663 * 79C970 in VMware never enables after a write of Idon|Stop,
664 * so we enable the device here now.
666 ctlr->iow(ctlr, Rdp, Iena|Strt);
671 * Linkage to the generic ethernet driver.
673 ether->attach = attach;
674 ether->transmit = transmit;
675 ether->ifstat = ifstat;
678 ether->promiscuous = promiscuous;
679 ether->multicast = multicast;
680 // ether->shutdown = shutdown;
682 intrenable(ether->irq, interrupt, ether, ether->tbdf, ether->name);
688 ether79c970link(void)
690 addethercard("AMD79C970", reset);