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 */
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 */
123 Dre* rdr; /* receive descriptor ring */
126 Dre* tdr; /* transmit descriptor ring */
127 int tdrh; /* host index into tdr */
128 int tdri; /* interface index into tdr */
129 int ntq; /* descriptors active */
131 ulong rxbuff; /* receive statistics */
136 ulong rtry; /* transmit statistics */
142 ulong merr; /* bobf is such a whiner */
146 int (*ior)(Ctlr*, int);
147 void (*iow)(Ctlr*, int, int);
150 static Ctlr* ctlrhead;
151 static Ctlr* ctlrtail;
154 * The Rdp, Rap, Sreset, Bdp ports are 32-bit port offset in the enumeration above.
155 * To get to 16-bit offsets, scale down with 0x10 staying the same.
158 io16r(Ctlr *c, int r)
162 return ins(c->port+r);
166 io16w(Ctlr *c, int r, int v)
174 io32r(Ctlr *c, int r)
176 return inl(c->port+r);
180 io32w(Ctlr *c, int r, int v)
191 ifstat(Ether* ether, void* a, long n, ulong offset)
199 ether->crcs = ctlr->crc;
200 ether->frames = ctlr->fram;
201 ether->buffs = ctlr->rxbuff+ctlr->txbuff;
202 ether->overflows = ctlr->oflo;
208 len = snprint(p, READSTR, "Rxbuff: %ld\n", ctlr->rxbuff);
209 len += snprint(p+len, READSTR-len, "Crc: %ld\n", ctlr->crc);
210 len += snprint(p+len, READSTR-len, "Oflo: %ld\n", ctlr->oflo);
211 len += snprint(p+len, READSTR-len, "Fram: %ld\n", ctlr->fram);
212 len += snprint(p+len, READSTR-len, "Rtry: %ld\n", ctlr->rtry);
213 len += snprint(p+len, READSTR-len, "Lcar: %ld\n", ctlr->lcar);
214 len += snprint(p+len, READSTR-len, "Lcol: %ld\n", ctlr->lcol);
215 len += snprint(p+len, READSTR-len, "Uflo: %ld\n", ctlr->uflo);
216 len += snprint(p+len, READSTR-len, "Txbuff: %ld\n", ctlr->txbuff);
217 len += snprint(p+len, READSTR-len, "Merr: %ld\n", ctlr->merr);
218 len += snprint(p+len, READSTR-len, "Miss: %ld\n", ctlr->miss);
219 snprint(p+len, READSTR-len, "Babl: %ld\n", ctlr->babl);
221 n = readstr(offset, a, n, p);
233 * Initialise the receive and transmit buffer rings.
234 * The ring entries must be aligned on 16-byte boundaries.
236 * This routine is protected by ctlr->init.
239 ctlr->rdr = xspanalloc(Nrdre*sizeof(Dre), 0x10, 0);
240 for(dre = ctlr->rdr; dre < &ctlr->rdr[Nrdre]; dre++){
241 dre->bp = iallocb(Rbsize);
243 panic("can't allocate ethernet receive ring\n");
244 dre->addr = PADDR(dre->bp->rp);
246 dre->md1 = Own|(-Rbsize & 0xFFFF);
252 ctlr->tdr = xspanalloc(Ntdre*sizeof(Dre), 0x10, 0);
253 memset(ctlr->tdr, 0, Ntdre*sizeof(Dre));
254 ctlr->tdrh = ctlr->tdri = 0;
258 promiscuous(void* arg, int on)
268 * Put the chip into promiscuous mode. First must wait until
269 * anyone transmitting is done, then stop the chip and put
270 * it in promiscuous mode. Restarting is made harder by the chip
271 * reloading the transmit and receive descriptor pointers with their
272 * base addresses when Strt is set (unlike the older Lance chip),
273 * so the rings must be re-initialised.
286 ctlr->iow(ctlr, Rdp, Stop);
288 ctlr->iow(ctlr, Rap, 15);
289 x = ctlr->ior(ctlr, Rdp) & ~Prom;
292 ctlr->iow(ctlr, Rdp, x);
293 ctlr->iow(ctlr, Rap, 0);
299 ctlr->iow(ctlr, Rdp, Iena|Strt);
304 multicast(void* arg, uchar*, int)
310 txstart(Ether* ether)
321 while(ctlr->ntq < (Ntdre-1)){
322 bp = qget(ether->oq);
327 * Give ownership of the descriptor to the chip,
328 * increment the software ring descriptor pointer
329 * and tell the chip to poll.
330 * There's no need to pad to ETHERMINTU
331 * here as ApadXmt is set in CSR4.
333 dre = &ctlr->tdr[ctlr->tdrh];
335 dre->addr = PADDR(bp->rp);
337 dre->md1 = Own|Stp|Enp|(-BLEN(bp) & 0xFFFF);
339 ctlr->iow(ctlr, Rdp, Iena|Tdmd);
340 ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre);
345 transmit(Ether* ether)
356 interrupt(Ureg*, void* arg)
368 * Acknowledge all interrupts and whine about those that shouldn't
372 csr0 = ctlr->ior(ctlr, Rdp) & 0xFFFF;
373 ctlr->iow(ctlr, Rdp, Babl|Cerr|Miss|Merr|Rint|Tint|Iena);
380 //if(csr0 & (Babl|Miss|Merr))
381 // print("#l%d: csr0 = 0x%uX\n", ether->ctlrno, csr0);
382 if(!(csr0 & (Rint|Tint)))
386 * Receiver interrupt: run round the descriptor ring logging
387 * errors and passing valid receive data up to the higher levels
388 * until a descriptor is encountered still owned by the chip.
391 dre = &ctlr->rdr[ctlr->rdrx];
392 while(!(dre->md1 & Own)){
393 if(dre->md1 & RxErr){
394 if(dre->md1 & RxBuff)
403 else if(bp = iallocb(Rbsize)){
404 len = (dre->md2 & 0x0FFF)-4;
405 dre->bp->wp = dre->bp->rp+len;
406 etheriq(ether, dre->bp, 1);
408 dre->addr = PADDR(bp->rp);
412 * Finished with this descriptor, reinitialise it,
413 * give it back to the chip, then on to the next...
416 dre->md1 = Own|(-Rbsize & 0xFFFF);
418 ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre);
419 dre = &ctlr->rdr[ctlr->rdrx];
424 * Transmitter interrupt: wakeup anyone waiting for a free descriptor.
429 dre = &ctlr->tdr[ctlr->tdri];
433 if(dre->md1 & TxErr){
442 if(dre->md2 & TxBuff)
450 ctlr->tdri = NEXT(ctlr->tdri, Ntdre);
466 while(p = pcimatch(p, 0x1022, 0x2000)){
467 port = p->mem[0].bar & ~0x01;
468 if(ioalloc(port, p->mem[0].size, 0, "amd79c970") < 0){
469 print("amd79c970: port 0x%uX in use\n", port);
472 ctlr = malloc(sizeof(Ctlr));
473 ctlr->port = p->mem[0].bar & ~0x01;
477 ctlrtail->next = ctlr;
495 * Any adapter matches if no port is supplied,
496 * otherwise the ports must match.
498 for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
501 if(ether->port == 0 || ether->port == ctlr->port){
510 * Allocate a controller structure and start to initialise it.
513 ether->port = ctlr->port;
514 ether->irq = ctlr->pcidev->intl;
515 ether->tbdf = ctlr->pcidev->tbdf;
516 pcisetbme(ctlr->pcidev);
523 if(io16w(ctlr, Rap, 0), io16r(ctlr, Rdp) == 4){
526 }else if(io32w(ctlr, Rap, 0), io32r(ctlr, Rdp) == 4){
530 print("#l%d: card doesn't talk right\n", ether->ctlrno);
535 ctlr->iow(ctlr, Rap, 88);
536 x = ctlr->ior(ctlr, Rdp);
537 ctlr->iow(ctlr, Rap, 89);
538 x |= ctlr->ior(ctlr, Rdp)<<16;
541 case 0x2420003: /* PCnet/PCI 79C970 */
542 case 0x2621003: /* PCnet/PCI II 79C970A */
543 case 0x2625003: /* PCnet-FAST III 79C973 */
546 print("#l%d: unknown PCnet card version 0x%.7ux\n",
547 ether->ctlrno, x&0xFFFFFFF);
553 * Set the software style in BCR20 to be PCnet-PCI to ensure 32-bit access.
554 * Set the auto pad transmit in CSR4.
556 ctlr->iow(ctlr, Rap, 20);
557 ctlr->iow(ctlr, Bdp, 0x0002);
559 ctlr->iow(ctlr, Rap, 4);
560 x = ctlr->ior(ctlr, Rdp) & 0xFFFF;
561 ctlr->iow(ctlr, Rdp, ApadXmt|x);
563 ctlr->iow(ctlr, Rap, 0);
566 * Check if the adapter's station address is to be overridden.
567 * If not, read it from the I/O-space and set in ether->ea prior to
568 * loading the station address in the initialisation block.
570 memset(ea, 0, Eaddrlen);
571 if(!memcmp(ea, ether->ea, Eaddrlen)){
572 x = ctlr->ior(ctlr, Aprom);
575 if(ctlr->ior == io16r)
576 x = ctlr->ior(ctlr, Aprom+2);
581 x = ctlr->ior(ctlr, Aprom+4);
587 * Start to fill in the initialisation block
588 * (must be DWORD aligned).
590 ctlr->iblock.rlen = Lognrdre<<4;
591 ctlr->iblock.tlen = Logntdre<<4;
592 memmove(ctlr->iblock.padr, ether->ea, sizeof(ctlr->iblock.padr));
595 ctlr->iblock.rdra = PADDR(ctlr->rdr);
596 ctlr->iblock.tdra = PADDR(ctlr->tdr);
599 * Point the chip at the initialisation block and tell it to go.
600 * Mask the Idon interrupt and poll for completion. Strt and interrupt
601 * enables will be set later when attaching to the network.
603 x = PADDR(&ctlr->iblock);
604 ctlr->iow(ctlr, Rap, 1);
605 ctlr->iow(ctlr, Rdp, x & 0xFFFF);
606 ctlr->iow(ctlr, Rap, 2);
607 ctlr->iow(ctlr, Rdp, (x>>16) & 0xFFFF);
608 ctlr->iow(ctlr, Rap, 3);
609 ctlr->iow(ctlr, Rdp, Idon);
610 ctlr->iow(ctlr, Rap, 0);
611 ctlr->iow(ctlr, Rdp, Init);
613 while(!(ctlr->ior(ctlr, Rdp) & Idon))
617 * We used to set CSR0 to Idon|Stop here, and then
618 * in attach change it to Iena|Strt. Apparently the simulated
619 * 79C970 in VMware never enables after a write of Idon|Stop,
620 * so we enable the device here now.
622 ctlr->iow(ctlr, Rdp, Iena|Strt);
627 * Linkage to the generic ethernet driver.
629 ether->attach = attach;
630 ether->transmit = transmit;
631 ether->interrupt = interrupt;
632 ether->ifstat = ifstat;
635 ether->promiscuous = promiscuous;
636 ether->multicast = multicast;
637 // ether->shutdown = shutdown;
643 ether79c970link(void)
645 addethercard("AMD79C970", reset);