1 /*
2 * AMD79C970
3 * PCnet-PCI Single-Chip Ethernet Controller for PCI Local Bus
4 * To do:
5 * finish this rewrite
6 */
7 #include "u.h"
8 #include "../port/lib.h"
9 #include "mem.h"
10 #include "dat.h"
11 #include "fns.h"
12 #include "io.h"
13 #include "../port/error.h"
14 #include "../port/netif.h"
15
16 #include "etherif.h"
17
18 enum {
19 Lognrdre = 6,
20 Nrdre = (1<<Lognrdre),/* receive descriptor ring entries */
21 Logntdre = 4,
22 Ntdre = (1<<Logntdre),/* transmit descriptor ring entries */
23
24 Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */
25 };
26
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 */
33 };
34
35 enum { /* CSR0 */
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 */
52 };
53
54 enum { /* CSR3 */
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 */
59 };
60
61 enum { /* CSR4 */
62 ApadXmt = 0x0800, /* auto pad transmit */
63 };
64
65 enum { /* CSR15 */
66 Prom = 0x8000, /* promiscuous mode */
67 };
68
69 typedef struct Iblock Iblock;
70 struct Iblock { /* Initialisation Block */
71 ushort mode;
72 uchar rlen; /* upper 4 bits */
73 uchar tlen; /* upper 4 bits */
74 uchar padr[6];
75 uchar res[2];
76 uchar ladr[8];
77 ulong rdra;
78 ulong tdra;
79 };
80
81 typedef struct Dre Dre;
82 struct Dre { /* descriptor ring entry */
83 ulong addr;
84 ulong md1; /* status|bcnt */
85 ulong md2; /* rcc|rpc|mcnt */
86 Block* bp;
87 };
88
89 enum { /* md1 */
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 */
101 Own = 0x80000000,
102 };
103
104 enum { /* md2 */
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 */
110 };
111
112 typedef struct Ctlr Ctlr;
113 struct Ctlr {
114 Lock;
115 int port;
116 Pcidev* pcidev;
117 Ctlr* next;
118 int active;
119
120 int init; /* initialisation in progress */
121 Iblock iblock;
122
123 Dre* rdr; /* receive descriptor ring */
124 int rdrx;
125
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 */
130
131 ulong rxbuff; /* receive statistics */
132 ulong crc;
133 ulong oflo;
134 ulong fram;
135
136 ulong rtry; /* transmit statistics */
137 ulong lcar;
138 ulong lcol;
139 ulong uflo;
140 ulong txbuff;
141
142 ulong merr; /* bobf is such a whiner */
143 ulong miss;
144 ulong babl;
145
146 int (*ior)(Ctlr*, int);
147 void (*iow)(Ctlr*, int, int);
148 };
149
150 static Ctlr* ctlrhead;
151 static Ctlr* ctlrtail;
152
153 /*
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.
156 */
157 static int
io16r(Ctlr * c,int r)158 io16r(Ctlr *c, int r)
159 {
160 if(r >= Rdp)
161 r = (r-Rdp)/2+Rdp;
162 return ins(c->port+r);
163 }
164
165 static void
io16w(Ctlr * c,int r,int v)166 io16w(Ctlr *c, int r, int v)
167 {
168 if(r >= Rdp)
169 r = (r-Rdp)/2+Rdp;
170 outs(c->port+r, v);
171 }
172
173 static int
io32r(Ctlr * c,int r)174 io32r(Ctlr *c, int r)
175 {
176 return inl(c->port+r);
177 }
178
179 static void
io32w(Ctlr * c,int r,int v)180 io32w(Ctlr *c, int r, int v)
181 {
182 outl(c->port+r, v);
183 }
184
185 static void
attach(Ether *)186 attach(Ether*)
187 {
188 }
189
190 static long
ifstat(Ether * ether,void * a,long n,ulong offset)191 ifstat(Ether* ether, void* a, long n, ulong offset)
192 {
193 char *p;
194 int len;
195 Ctlr *ctlr;
196
197 ctlr = ether->ctlr;
198
199 ether->crcs = ctlr->crc;
200 ether->frames = ctlr->fram;
201 ether->buffs = ctlr->rxbuff+ctlr->txbuff;
202 ether->overflows = ctlr->oflo;
203
204 if(n == 0)
205 return 0;
206
207 p = malloc(READSTR);
208 if(p == nil)
209 error(Enomem);
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);
222
223 n = readstr(offset, a, n, p);
224 free(p);
225
226 return n;
227 }
228
229 static void
ringinit(Ctlr * ctlr)230 ringinit(Ctlr* ctlr)
231 {
232 Dre *dre;
233
234 /*
235 * Initialise the receive and transmit buffer rings.
236 * The ring entries must be aligned on 16-byte boundaries.
237 *
238 * This routine is protected by ctlr->init.
239 */
240 if(ctlr->rdr == 0){
241 ctlr->rdr = xspanalloc(Nrdre*sizeof(Dre), 0x10, 0);
242 for(dre = ctlr->rdr; dre < &ctlr->rdr[Nrdre]; dre++){
243 dre->bp = iallocb(Rbsize);
244 if(dre->bp == nil)
245 panic("can't allocate ethernet receive ring\n");
246 dre->addr = PADDR(dre->bp->rp);
247 dre->md2 = 0;
248 dre->md1 = Own|(-Rbsize & 0xFFFF);
249 }
250 }
251 ctlr->rdrx = 0;
252
253 if(ctlr->tdr == 0)
254 ctlr->tdr = xspanalloc(Ntdre*sizeof(Dre), 0x10, 0);
255 memset(ctlr->tdr, 0, Ntdre*sizeof(Dre));
256 ctlr->tdrh = ctlr->tdri = 0;
257 }
258
259 static void
promiscuous(void * arg,int on)260 promiscuous(void* arg, int on)
261 {
262 Ether *ether;
263 int x;
264 Ctlr *ctlr;
265
266 ether = arg;
267 ctlr = ether->ctlr;
268
269 /*
270 * Put the chip into promiscuous mode. First must wait until
271 * anyone transmitting is done, then stop the chip and put
272 * it in promiscuous mode. Restarting is made harder by the chip
273 * reloading the transmit and receive descriptor pointers with their
274 * base addresses when Strt is set (unlike the older Lance chip),
275 * so the rings must be re-initialised.
276 */
277 ilock(ctlr);
278 if(ctlr->init){
279 iunlock(ctlr);
280 return;
281 }
282 ctlr->init = 1;
283 iunlock(ctlr);
284
285 while(ctlr->ntq)
286 ;
287
288 ctlr->iow(ctlr, Rdp, Stop);
289
290 ctlr->iow(ctlr, Rap, 15);
291 x = ctlr->ior(ctlr, Rdp) & ~Prom;
292 if(on)
293 x |= Prom;
294 ctlr->iow(ctlr, Rdp, x);
295 ctlr->iow(ctlr, Rap, 0);
296
297 ringinit(ctlr);
298
299 ilock(ctlr);
300 ctlr->init = 0;
301 ctlr->iow(ctlr, Rdp, Iena|Strt);
302 iunlock(ctlr);
303 }
304
305 static void
multicast(void * arg,uchar *,int)306 multicast(void* arg, uchar*, int)
307 {
308 promiscuous(arg, 1);
309 }
310
311 static void
shutdown(Ether * ether)312 shutdown(Ether *ether)
313 {
314 Ctlr *ctlr;
315
316 ctlr = ether->ctlr;
317 ilock(ctlr);
318 io32r(ctlr, Sreset);
319 io16r(ctlr, Sreset);
320 iunlock(ctlr);
321 }
322
323 static void
txstart(Ether * ether)324 txstart(Ether* ether)
325 {
326 Ctlr *ctlr;
327 Block *bp;
328 Dre *dre;
329
330 ctlr = ether->ctlr;
331
332 if(ctlr->init)
333 return;
334
335 while(ctlr->ntq < (Ntdre-1)){
336 bp = qget(ether->oq);
337 if(bp == nil)
338 break;
339
340 /*
341 * Give ownership of the descriptor to the chip,
342 * increment the software ring descriptor pointer
343 * and tell the chip to poll.
344 * There's no need to pad to ETHERMINTU
345 * here as ApadXmt is set in CSR4.
346 */
347 dre = &ctlr->tdr[ctlr->tdrh];
348 dre->bp = bp;
349 dre->addr = PADDR(bp->rp);
350 dre->md2 = 0;
351 dre->md1 = Own|Stp|Enp|(-BLEN(bp) & 0xFFFF);
352 ctlr->ntq++;
353 ctlr->iow(ctlr, Rdp, Iena|Tdmd);
354 ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre);
355 }
356 }
357
358 static void
transmit(Ether * ether)359 transmit(Ether* ether)
360 {
361 Ctlr *ctlr;
362
363 ctlr = ether->ctlr;
364 ilock(ctlr);
365 txstart(ether);
366 iunlock(ctlr);
367 }
368
369 static void
interrupt(Ureg *,void * arg)370 interrupt(Ureg*, void* arg)
371 {
372 Ctlr *ctlr;
373 Ether *ether;
374 int csr0, len;
375 Dre *dre;
376 Block *bp;
377
378 ether = arg;
379 ctlr = ether->ctlr;
380
381 /*
382 * Acknowledge all interrupts and whine about those that shouldn't
383 * happen.
384 */
385 intrloop:
386 csr0 = ctlr->ior(ctlr, Rdp) & 0xFFFF;
387 ctlr->iow(ctlr, Rdp, Babl|Cerr|Miss|Merr|Rint|Tint|Iena);
388 if(csr0 & Merr)
389 ctlr->merr++;
390 if(csr0 & Miss)
391 ctlr->miss++;
392 if(csr0 & Babl)
393 ctlr->babl++;
394 //if(csr0 & (Babl|Miss|Merr))
395 // print("#l%d: csr0 = 0x%uX\n", ether->ctlrno, csr0);
396 if(!(csr0 & (Rint|Tint)))
397 return;
398
399 /*
400 * Receiver interrupt: run round the descriptor ring logging
401 * errors and passing valid receive data up to the higher levels
402 * until a descriptor is encountered still owned by the chip.
403 */
404 if(csr0 & Rint){
405 dre = &ctlr->rdr[ctlr->rdrx];
406 while(!(dre->md1 & Own)){
407 if(dre->md1 & RxErr){
408 if(dre->md1 & RxBuff)
409 ctlr->rxbuff++;
410 if(dre->md1 & Crc)
411 ctlr->crc++;
412 if(dre->md1 & Oflo)
413 ctlr->oflo++;
414 if(dre->md1 & Fram)
415 ctlr->fram++;
416 }
417 else if(bp = iallocb(Rbsize)){
418 len = (dre->md2 & 0x0FFF)-4;
419 dre->bp->wp = dre->bp->rp+len;
420 etheriq(ether, dre->bp, 1);
421 dre->bp = bp;
422 dre->addr = PADDR(bp->rp);
423 }
424
425 /*
426 * Finished with this descriptor, reinitialise it,
427 * give it back to the chip, then on to the next...
428 */
429 dre->md2 = 0;
430 dre->md1 = Own|(-Rbsize & 0xFFFF);
431
432 ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre);
433 dre = &ctlr->rdr[ctlr->rdrx];
434 }
435 }
436
437 /*
438 * Transmitter interrupt: wakeup anyone waiting for a free descriptor.
439 */
440 if(csr0 & Tint){
441 lock(ctlr);
442 while(ctlr->ntq){
443 dre = &ctlr->tdr[ctlr->tdri];
444 if(dre->md1 & Own)
445 break;
446
447 if(dre->md1 & TxErr){
448 if(dre->md2 & Rtry)
449 ctlr->rtry++;
450 if(dre->md2 & Lcar)
451 ctlr->lcar++;
452 if(dre->md2 & Lcol)
453 ctlr->lcol++;
454 if(dre->md2 & Uflo)
455 ctlr->uflo++;
456 if(dre->md2 & TxBuff)
457 ctlr->txbuff++;
458 ether->oerrs++;
459 }
460
461 freeb(dre->bp);
462
463 ctlr->ntq--;
464 ctlr->tdri = NEXT(ctlr->tdri, Ntdre);
465 }
466 txstart(ether);
467 unlock(ctlr);
468 }
469 goto intrloop;
470 }
471
472 static void
amd79c970pci(void)473 amd79c970pci(void)
474 {
475 int port;
476 Ctlr *ctlr;
477 Pcidev *p;
478
479 p = nil;
480 while(p = pcimatch(p, 0x1022, 0x2000)){
481 port = p->mem[0].bar & ~0x01;
482 if(ioalloc(port, p->mem[0].size, 0, "amd79c970") < 0){
483 print("amd79c970: port 0x%uX in use\n", port);
484 continue;
485 }
486 ctlr = malloc(sizeof(Ctlr));
487 if(ctlr == nil)
488 error(Enomem);
489 ctlr->port = p->mem[0].bar & ~0x01;
490 ctlr->pcidev = p;
491
492 if(ctlrhead != nil)
493 ctlrtail->next = ctlr;
494 else
495 ctlrhead = ctlr;
496 ctlrtail = ctlr;
497 }
498 }
499
500 static int
reset(Ether * ether)501 reset(Ether* ether)
502 {
503 int x;
504 uchar ea[Eaddrlen];
505 Ctlr *ctlr;
506
507 if(ctlrhead == nil)
508 amd79c970pci();
509
510 /*
511 * Any adapter matches if no port is supplied,
512 * otherwise the ports must match.
513 */
514 for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
515 if(ctlr->active)
516 continue;
517 if(ether->port == 0 || ether->port == ctlr->port){
518 ctlr->active = 1;
519 break;
520 }
521 }
522 if(ctlr == nil)
523 return -1;
524
525 /*
526 * Allocate a controller structure and start to initialise it.
527 */
528 ether->ctlr = ctlr;
529 ether->port = ctlr->port;
530 ether->irq = ctlr->pcidev->intl;
531 ether->tbdf = ctlr->pcidev->tbdf;
532 pcisetbme(ctlr->pcidev);
533 shutdown(ether);
534 ilock(ctlr);
535 ctlr->init = 1;
536
537 if(io16w(ctlr, Rap, 0), io16r(ctlr, Rdp) == 4){
538 ctlr->ior = io16r;
539 ctlr->iow = io16w;
540 }else if(io32w(ctlr, Rap, 0), io32r(ctlr, Rdp) == 4){
541 ctlr->ior = io32r;
542 ctlr->iow = io32w;
543 }else{
544 print("#l%d: card doesn't talk right\n", ether->ctlrno);
545 iunlock(ctlr);
546 return -1;
547 }
548
549 ctlr->iow(ctlr, Rap, 88);
550 x = ctlr->ior(ctlr, Rdp);
551 ctlr->iow(ctlr, Rap, 89);
552 x |= ctlr->ior(ctlr, Rdp)<<16;
553
554 switch(x&0xFFFFFFF){
555 case 0x2420003: /* PCnet/PCI 79C970 */
556 case 0x2621003: /* PCnet/PCI II 79C970A */
557 case 0x2625003: /* PCnet-FAST III 79C973 */
558 break;
559 default:
560 print("#l%d: unknown PCnet card version 0x%.7ux\n",
561 ether->ctlrno, x&0xFFFFFFF);
562 iunlock(ctlr);
563 return -1;
564 }
565
566 /*
567 * Set the software style in BCR20 to be PCnet-PCI to ensure 32-bit access.
568 * Set the auto pad transmit in CSR4.
569 */
570 ctlr->iow(ctlr, Rap, 20);
571 ctlr->iow(ctlr, Bdp, 0x0002);
572
573 ctlr->iow(ctlr, Rap, 4);
574 x = ctlr->ior(ctlr, Rdp) & 0xFFFF;
575 ctlr->iow(ctlr, Rdp, ApadXmt|x);
576
577 ctlr->iow(ctlr, Rap, 0);
578
579 /*
580 * Check if the adapter's station address is to be overridden.
581 * If not, read it from the I/O-space and set in ether->ea prior to
582 * loading the station address in the initialisation block.
583 */
584 memset(ea, 0, Eaddrlen);
585 if(!memcmp(ea, ether->ea, Eaddrlen)){
586 x = ctlr->ior(ctlr, Aprom);
587 ether->ea[0] = x;
588 ether->ea[1] = x>>8;
589 if(ctlr->ior == io16r)
590 x = ctlr->ior(ctlr, Aprom+2);
591 else
592 x >>= 16;
593 ether->ea[2] = x;
594 ether->ea[3] = x>>8;
595 x = ctlr->ior(ctlr, Aprom+4);
596 ether->ea[4] = x;
597 ether->ea[5] = x>>8;
598 }
599
600 /*
601 * Start to fill in the initialisation block
602 * (must be DWORD aligned).
603 */
604 ctlr->iblock.rlen = Lognrdre<<4;
605 ctlr->iblock.tlen = Logntdre<<4;
606 memmove(ctlr->iblock.padr, ether->ea, sizeof(ctlr->iblock.padr));
607
608 ringinit(ctlr);
609 ctlr->iblock.rdra = PADDR(ctlr->rdr);
610 ctlr->iblock.tdra = PADDR(ctlr->tdr);
611
612 /*
613 * Point the chip at the initialisation block and tell it to go.
614 * Mask the Idon interrupt and poll for completion. Strt and interrupt
615 * enables will be set later when attaching to the network.
616 */
617 x = PADDR(&ctlr->iblock);
618 ctlr->iow(ctlr, Rap, 1);
619 ctlr->iow(ctlr, Rdp, x & 0xFFFF);
620 ctlr->iow(ctlr, Rap, 2);
621 ctlr->iow(ctlr, Rdp, (x>>16) & 0xFFFF);
622 ctlr->iow(ctlr, Rap, 3);
623 ctlr->iow(ctlr, Rdp, Idon);
624 ctlr->iow(ctlr, Rap, 0);
625 ctlr->iow(ctlr, Rdp, Init);
626
627 while(!(ctlr->ior(ctlr, Rdp) & Idon))
628 ;
629
630 /*
631 * We used to set CSR0 to Idon|Stop here, and then
632 * in attach change it to Iena|Strt. Apparently the simulated
633 * 79C970 in VMware never enables after a write of Idon|Stop,
634 * so we enable the device here now.
635 */
636 ctlr->iow(ctlr, Rdp, Iena|Strt);
637 ctlr->init = 0;
638 iunlock(ctlr);
639
640 /*
641 * Linkage to the generic ethernet driver.
642 */
643 ether->attach = attach;
644 ether->transmit = transmit;
645 ether->interrupt = interrupt;
646 ether->ifstat = ifstat;
647
648 ether->arg = ether;
649 ether->promiscuous = promiscuous;
650 ether->multicast = multicast;
651 ether->shutdown = shutdown;
652
653 return 0;
654 }
655
656 void
ether79c970link(void)657 ether79c970link(void)
658 {
659 addethercard("AMD79C970", reset);
660 }
661