1 /*
2 * VIA VT6105M Fast Ethernet Controller (Rhine III).
3 * To do:
4 * reorganise initialisation/shutdown/reset
5 * adjust Tx FIFO threshold on underflow - untested
6 * why does the link status never cause an interrupt?
7 * use the lproc as a periodic timer for stalls, etc.
8 * take non-HW stuff out of descriptor for 64-bit
9 * cleanliness
10 * why does the receive buffer alloc have a +3?
11 */
12 #include "u.h"
13 #include "../port/lib.h"
14 #include "mem.h"
15 #include "dat.h"
16 #include "fns.h"
17 #include "io.h"
18 #include "../port/error.h"
19 #include "../port/netif.h"
20
21 #include "etherif.h"
22 #include "ethermii.h"
23
24 enum {
25 Par0 = 0x00, /* Ethernet Address */
26 Rcr = 0x06, /* Receive Configuration */
27 Tcr = 0x07, /* Transmit Configuration */
28 Cr = 0x08, /* Control */
29 Tqw = 0x0A, /* Transmit Queue Wake */
30 Isr = 0x0C, /* Interrupt Status */
31 Imr = 0x0E, /* Interrupt Mask */
32 Mcfilt0 = 0x10, /* Multicast Filter 0 */
33 Mcfilt1 = 0x14, /* Multicast Filter 1 */
34 Rxdaddr = 0x18, /* Current Rd Address */
35 Txdaddr = 0x1C, /* Current Td Address */
36 Phyadr = 0x6C, /* Phy Address */
37 Miisr = 0x6D, /* MII Status */
38 Bcr0 = 0x6E, /* Bus Control */
39 Bcr1 = 0x6F,
40 Miicr = 0x70, /* MII Control */
41 Miiadr = 0x71, /* MII Address */
42 Miidata = 0x72, /* MII Data */
43 Eecsr = 0x74, /* EEPROM Control and Status */
44 CfgA = 0x78, /* Chip Configuration A */
45 CfgB = 0x79,
46 CfgC = 0x7A,
47 CfgD = 0x7B,
48 Cr0 = 0x80, /* Miscellaneous Control */
49 Cr1 = 0x81,
50 Pmcc = 0x82, /* Power Mgmt Capability Control */
51 Stickhw = 0x83, /* Sticky Hardware Control */
52 Misr = 0x84, /* MII Interrupt Control */
53 Mimr = 0x85, /* MII Interrupt Mask */
54 Wolcrclr = 0xA4,
55 Wolcgclr = 0xA7,
56 Pwrcsrclr = 0xAC,
57 };
58
59 enum { /* Rcr */
60 Sep = 0x01, /* Accept Error Packets */
61 Ar = 0x02, /* Accept Small Packets */
62 Am = 0x04, /* Accept Multicast */
63 Ab = 0x08, /* Accept Broadcast */
64 Prom = 0x10, /* Accept Physical Address Packets */
65 RrftMASK = 0xE0, /* Receive FIFO Threshold */
66 RrftSHIFT = 5,
67 Rrft64 = 0<<RrftSHIFT,
68 Rrft32 = 1<<RrftSHIFT,
69 Rrft128 = 2<<RrftSHIFT,
70 Rrft256 = 3<<RrftSHIFT,
71 Rrft512 = 4<<RrftSHIFT,
72 Rrft768 = 5<<RrftSHIFT,
73 Rrft1024 = 6<<RrftSHIFT,
74 RrftSAF = 7<<RrftSHIFT,
75 };
76
77 enum { /* Tcr */
78 Lb0 = 0x02, /* Loopback Mode */
79 Lb1 = 0x04,
80 Ofset = 0x08, /* Select Back-off Priority */
81 RtsfMASK = 0xE0, /* Transmit FIFO Threshold */
82 RtsfSHIFT = 5,
83 Rtsf128 = 0<<RtsfSHIFT,
84 Rtsf256 = 1<<RtsfSHIFT,
85 Rtsf512 = 2<<RtsfSHIFT,
86 Rtsf1024 = 3<<RtsfSHIFT,
87 RtsfSAF = 7<<RtsfSHIFT,
88 };
89
90 enum { /* Cr */
91 Init = 0x0001, /* INIT Process Begin */
92 Strt = 0x0002, /* Start NIC */
93 Stop = 0x0004, /* Stop NIC */
94 Rxon = 0x0008, /* Turn on Receive Process */
95 Txon = 0x0010, /* Turn on Transmit Process */
96 Tdmd = 0x0020, /* Transmit Poll Demand */
97 Rdmd = 0x0040, /* Receive Poll Demand */
98 Eren = 0x0100, /* Early Receive Enable */
99 Fdx = 0x0400, /* Set MAC to Full Duplex */
100 Dpoll = 0x0800, /* Disable Td/Rd Auto Polling */
101 Tdmd1 = 0x2000, /* Transmit Poll Demand 1 */
102 Rdmd1 = 0x4000, /* Receive Poll Demand 1 */
103 Sfrst = 0x8000, /* Software Reset */
104 };
105
106 enum { /* Isr/Imr */
107 Prx = 0x0001, /* Packet Received OK */
108 Ptx = 0x0002, /* Packet Transmitted OK */
109 Rxe = 0x0004, /* Receive Error */
110 Txe = 0x0008, /* Transmit Error */
111 Tu = 0x0010, /* Transmit Buffer Underflow */
112 Ru = 0x0020, /* Receive Buffer Link Error */
113 Be = 0x0040, /* PCI Bus Error */
114 Cnt = 0x0080, /* Counter Overflow */
115 Eri = 0x0100, /* Early Receive Interrupt */
116 Udfi = 0x0200, /* Tx FIFO Underflow */
117 Ovfi = 0x0400, /* Receive FIFO Overflow */
118 Pktrace = 0x0800, /* Hmmm... */
119 Norbf = 0x1000, /* No Receive Buffers */
120 Abti = 0x2000, /* Transmission Abort */
121 Srci = 0x4000, /* Port State Change */
122 Geni = 0x8000, /* General Purpose Interrupt */
123 };
124
125 enum { /* Phyadr */
126 PhyadMASK = 0x1F, /* PHY Address */
127 PhyadSHIFT = 0,
128 Mfdc = 0x20, /* Accelerate MDC Speed */
129 Mpo0 = 0x40, /* MII Polling Timer Interval */
130 Mpo1 = 0x80,
131 };
132
133 enum { /* Bcr0 */
134 DmaMASK = 0x07, /* DMA Length */
135 DmaSHIFT = 0,
136 Dma32 = 0<<DmaSHIFT,
137 Dma64 = 1<<DmaSHIFT,
138 Dma128 = 2<<DmaSHIFT,
139 Dma256 = 3<<DmaSHIFT,
140 Dma512 = 4<<DmaSHIFT,
141 Dma1024 = 5<<DmaSHIFT,
142 DmaSAF = 7<<DmaSHIFT,
143 CrftMASK = 0x38, /* Rx FIFO Threshold */
144 CrftSHIFT = 3,
145 Crft64 = 1<<CrftSHIFT,
146 Crft128 = 2<<CrftSHIFT,
147 Crft256 = 3<<CrftSHIFT,
148 Crft512 = 4<<CrftSHIFT,
149 Crft1024 = 5<<CrftSHIFT,
150 CrftSAF = 7<<CrftSHIFT,
151 Extled = 0x40, /* Extra LED Support Control */
152 Med2 = 0x80, /* Medium Select Control */
153 };
154
155 enum { /* Bcr1 */
156 PotMASK = 0x07, /* Polling Timer Interval */
157 PotSHIFT = 0,
158 CtftMASK = 0x38, /* Tx FIFO Threshold */
159 CtftSHIFT = 3,
160 Ctft64 = 1<<CtftSHIFT,
161 Ctft128 = 2<<CtftSHIFT,
162 Ctft256 = 3<<CtftSHIFT,
163 Ctft512 = 4<<CtftSHIFT,
164 Ctft1024 = 5<<CtftSHIFT,
165 CtftSAF = 7<<CtftSHIFT,
166 };
167
168 enum { /* Miicr */
169 Mdc = 0x01, /* Clock */
170 Mdi = 0x02, /* Data In */
171 Mdo = 0x04, /* Data Out */
172 Mout = 0x08, /* Output Enable */
173 Mdpm = 0x10, /* Direct Program Mode Enable */
174 Wcmd = 0x20, /* Write Enable */
175 Rcmd = 0x40, /* Read Enable */
176 Mauto = 0x80, /* Auto Polling Enable */
177 };
178
179 enum { /* Miiadr */
180 MadMASK = 0x1F, /* MII Port Address */
181 MadSHIFT = 0,
182 Mdone = 0x20, /* Accelerate MDC Speed */
183 Msrcen = 0x40, /* MII Polling Timer Interval */
184 Midle = 0x80,
185 };
186
187 enum { /* Eecsr */
188 Edo = 0x01, /* Data Out */
189 Edi = 0x02, /* Data In */
190 Eck = 0x04, /* Clock */
191 Ecs = 0x08, /* Chip Select */
192 Dpm = 0x10, /* Direct Program Mode Enable */
193 Autold = 0x20, /* Dynamic Reload */
194 Embp = 0x40, /* Embedded Program Enable */
195 Eepr = 0x80, /* Programmed */
196 };
197
198 /*
199 * Ring descriptor. The space allocated for each
200 * of these will be rounded up to a cache-line boundary.
201 * The first 4 elements are known to the hardware.
202 */
203 typedef struct Ds Ds;
204 typedef struct Ds {
205 u32int status;
206 u32int control;
207 u32int addr;
208 u32int branch;
209
210 Block* bp;
211 Ds* next;
212 Ds* prev;
213 } Ds;
214
215 enum { /* Rx Ds status */
216 Rerr = 0x00000001, /* Buff|Rxserr|Fov|Fae|Crc */
217 Crc = 0x00000002, /* CRC Error */
218 Fae = 0x00000004, /* Frame Alignment Error */
219 Fov = 0x00000008, /* FIFO Overflow */
220 Long = 0x00000010, /* A Long Packet */
221 Runt = 0x00000020, /* A Runt Packet */
222 Rxserr = 0x00000040, /* System Error */
223 Buff = 0x00000080, /* Buffer Underflow Error */
224 Rxedp = 0x00000100, /* End of Packet Buffer */
225 Rxstp = 0x00000200, /* Packet Start */
226 Chn = 0x00000400, /* Chain Buffer */
227 Phy = 0x00000800, /* Physical Address Packet */
228 Bar = 0x00001000, /* Broadcast Packet */
229 Mar = 0x00002000, /* Multicast Packet */
230 Rxok = 0x00008000, /* Packet Received OK */
231 LengthMASK = 0x07FF0000, /* Received Packet Length */
232 LengthSHIFT = 16,
233
234 Own = 0x80000000, /* Descriptor Owned by NIC */
235 };
236
237 enum { /* Rx Ds control */
238 RbsizeMASK = 0x000007FF, /* Receive Buffer Size */
239 RbsizeSHIFT = 0,
240 Tag = 0x00010000, /* Receive a Tagged Packet */
241 Udpkt = 0x00020000, /* Receive a UDP Packet */
242 Tcpkt = 0x00040000, /* Receive a TCP Packet */
243 Ipkt = 0x00080000, /* Receive an IP Packet */
244 Tuok = 0x00100000, /* TCP/UDP Checksum OK */
245 Ipok = 0x00200000, /* IP Checksum OK */
246 Snaptag = 0x00400000, /* Snap Packet + 802.1q Tag */
247 Rxlerr = 0x00800000, /* Receive Length Check Error */
248 IpktMASK = 0xff000000, /* Interesting Packet */
249 IpktSHIFT = 24,
250 };
251
252 enum { /* Tx Ds status */
253 NcrMASK = 0x0000000F, /* Collision Retry Count */
254 NcrSHIFT = 0,
255 Cols = 0x00000010, /* Experienced Collisions */
256 Cdh = 0x00000080, /* CD Heartbeat */
257 Abt = 0x00000100, /* Aborted after Excessive Collisions */
258 Owc = 0x00000200, /* Out of Window Collision */
259 Crs = 0x00000400, /* Carrier Sense Lost */
260 Udf = 0x00000800, /* FIFO Underflow */
261 Tbuff = 0x00001000, /* Invalid Td */
262 Txserr = 0x00002000, /* System Error */
263 Terr = 0x00008000, /* Excessive Collisions */
264 };
265
266 enum { /* Tx Ds control */
267 TbsMASK = 0x000007FF, /* Tx Buffer Size */
268 TbsSHIFT = 0,
269 Chain = 0x00008000, /* Chain Buffer */
270 Crcdisable = 0x00010000, /* Disable CRC generation */
271 Stp = 0x00200000, /* Start of Packet */
272 Edp = 0x00400000, /* End of Packet */
273 Ic = 0x00800000, /* Interrupt Control */
274 };
275
276 enum { /* Tx Ds branch */
277 Tdctl = 0x00000001, /* No Interrupt Generated */
278 };
279
280 enum {
281 Nrd = 196,
282 Ntd = 64,
283 Crcsz = 4,
284 Bslop = 48,
285 Rdbsz = ETHERMAXTU+Crcsz+Bslop,
286 Maxus = 1000000, /* Soekris 5501s take a while to reset */
287
288 Nrxstats = 8,
289 Ntxstats = 9,
290 };
291
292 typedef struct Ctlr Ctlr;
293 typedef struct Ctlr {
294 int port;
295 Pcidev* pcidev;
296 Ctlr* next;
297 int active;
298 int id;
299 uchar par[Eaddrlen];
300
301 QLock alock; /* attach */
302 void* alloc; /* descriptors, etc. */
303 int cls; /* alignment */
304 int nrd;
305 int ntd;
306
307 Ds* rd;
308 Ds* rdh;
309
310 Lock tlock;
311 Ds* td;
312 Ds* tdh;
313 Ds* tdt;
314 int tdused;
315
316 Lock clock; /* */
317 int cr;
318 int imr;
319 int tft; /* Tx threshold */
320
321 Mii* mii;
322 Rendez lrendez;
323 int lwakeup;
324
325 uint rxstats[Nrxstats]; /* statistics */
326 uint txstats[Ntxstats];
327 ulong totalt;
328 uint intr;
329 uint lintr;
330 uint lsleep;
331 uint rintr;
332 uint tintr;
333 uint txdw;
334 int tdumax;
335
336 uint abt;
337 uint tbuff;
338 uint udf;
339
340 uint abti;
341 uint udfi;
342 uint tu;
343
344 uint tuok;
345 uint ipok;
346 } Ctlr;
347
348 static Ctlr* vt6105Mctlrhead;
349 static Ctlr* vt6105Mctlrtail;
350
351 #define csr8r(c, r) (inb((c)->port+(r)))
352 #define csr16r(c, r) (ins((c)->port+(r)))
353 #define csr32r(c, r) (inl((c)->port+(r)))
354 #define csr8w(c, r, b) (outb((c)->port+(r), (int)(b)))
355 #define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w)))
356 #define csr32w(c, r, w) (outl((c)->port+(r), (ulong)(w)))
357
358 static Lock vt6105Mrblock; /* receive Block freelist */
359 static Block* vt6105Mrbpool;
360 static uint vt6105Mrbpoolsz;
361
362 typedef struct Regs Regs;
363 typedef struct Regs {
364 char* name;
365 int offset;
366 int size;
367 } Regs;
368
369 static Regs regs[] = {
370 // "Par0", Par0, 1,
371 // "Par1", Par0+1, 1,
372 // "Par2", Par0+2, 1,
373 // "Par3", Par0+3, 1,
374 // "Par4", Par0+4, 1,
375 // "Par5", Par0+5, 1,
376 "Rcr", Rcr, 1,
377 "Tcr", Tcr, 1,
378 "Cr0", Cr, 1,
379 "Cr1", Cr+1, 1,
380 "Isr0", Isr, 1,
381 "Isr1", Isr+1, 1,
382 "Imr0", Imr, 1,
383 "Imr1", Imr+1, 1,
384 // "Mcfilt0", Mcfilt0,4,
385 // "Mcfilt1", Mcfilt1,4,
386 // "Rxdaddr", Rxdaddr,4,
387 // "Txdaddr", Txdaddr,4,
388 "Phyadr", Phyadr, 1,
389 "Miisr", Miisr, 1,
390 "Bcr0", Bcr0, 1,
391 "Bcr1", Bcr1, 1,
392 "Miicr", Miicr, 1,
393 "Miiadr", Miiadr, 1,
394 // "Miidata", Miidata,2,
395 "Eecsr", Eecsr, 1,
396 "CfgA", CfgA, 1,
397 "CfgB", CfgB, 1,
398 "CfgC", CfgC, 1,
399 "CfgD", CfgD, 1,
400 "Cr0", Cr0, 1,
401 "Cr1", Cr1, 1,
402 "Pmcc", Pmcc, 1,
403 "Stickhw", Stickhw,1,
404 "Misr", Misr, 1,
405 "Mimr", Mimr, 1,
406 nil,
407 };
408
409 static char* rxstats[Nrxstats] = {
410 "Receiver Error",
411 "CRC Error",
412 "Frame Alignment Error",
413 "FIFO Overflow",
414 "Long Packet",
415 "Runt Packet",
416 "System Error",
417 "Buffer Underflow Error",
418 };
419 static char* txstats[Ntxstats] = {
420 "Aborted after Excessive Collisions",
421 "Out of Window Collision Seen",
422 "Carrier Sense Lost",
423 "FIFO Underflow",
424 "Invalid Td",
425 "System Error",
426 nil,
427 "Excessive Collisions",
428 };
429
430 static long
vt6105Mifstat(Ether * edev,void * a,long n,ulong offset)431 vt6105Mifstat(Ether* edev, void* a, long n, ulong offset)
432 {
433 int i, r;
434 Ctlr *ctlr;
435 char *alloc, *e, *p;
436
437 ctlr = edev->ctlr;
438
439 alloc = malloc(READSTR);
440 p = alloc;
441 if(p == nil)
442 error(Enomem);
443 e = p + READSTR;
444 for(i = 0; i < Nrxstats; i++){
445 p = seprint(p, e, "%s: %ud\n", rxstats[i], ctlr->rxstats[i]);
446 }
447 for(i = 0; i < Ntxstats; i++){
448 if(txstats[i] == nil)
449 continue;
450 p = seprint(p, e, "%s: %ud\n", txstats[i], ctlr->txstats[i]);
451 }
452 p = seprint(p, e, "cls: %ud\n", ctlr->cls);
453 p = seprint(p, e, "intr: %ud\n", ctlr->intr);
454 p = seprint(p, e, "lintr: %ud\n", ctlr->lintr);
455 p = seprint(p, e, "lsleep: %ud\n", ctlr->lsleep);
456 p = seprint(p, e, "rintr: %ud\n", ctlr->rintr);
457 p = seprint(p, e, "tintr: %ud\n", ctlr->tintr);
458 p = seprint(p, e, "txdw: %ud\n", ctlr->txdw);
459 p = seprint(p, e, "tdumax: %ud\n", ctlr->tdumax);
460 p = seprint(p, e, "tft: %ud\n", ctlr->tft);
461
462 p = seprint(p, e, "abt: %ud\n", ctlr->abt);
463 p = seprint(p, e, "tbuff: %ud\n", ctlr->tbuff);
464 p = seprint(p, e, "udf: %ud\n", ctlr->udf);
465 p = seprint(p, e, "abti: %ud\n", ctlr->abti);
466 p = seprint(p, e, "udfi: %ud\n", ctlr->udfi);
467 p = seprint(p, e, "tu: %ud\n", ctlr->tu);
468
469 p = seprint(p, e, "tuok: %ud\n", ctlr->tuok);
470 p = seprint(p, e, "ipok: %ud\n", ctlr->ipok);
471
472 p = seprint(p, e, "rbpoolsz: %ud\n", vt6105Mrbpoolsz);
473 p = seprint(p, e, "totalt: %uld\n", ctlr->totalt);
474
475 for(i = 0; regs[i].name != nil; i++){
476 p = seprint(p, e, "%s: %2.2x\n",
477 regs[i].name, csr8r(ctlr, regs[i].offset));
478 }
479
480 if(ctlr->mii != nil && ctlr->mii->curphy != nil){
481 p = seprint(p, e, "phy: ");
482 for(i = 0; i < NMiiPhyr; i++){
483 if(i && ((i & 0x07) == 0))
484 p = seprint(p, e, "\n ");
485 r = miimir(ctlr->mii, i);
486 p = seprint(p, e, " %4.4uX", r);
487 }
488 seprint(p, e, "\n");
489 }
490
491 n = readstr(offset, a, n, alloc);
492 free(alloc);
493
494 return n;
495 }
496
497 static void
vt6105Mpromiscuous(void * arg,int on)498 vt6105Mpromiscuous(void* arg, int on)
499 {
500 int rcr;
501 Ctlr *ctlr;
502 Ether *edev;
503
504 edev = arg;
505 ctlr = edev->ctlr;
506 rcr = csr8r(ctlr, Rcr);
507 if(on)
508 rcr |= Prom;
509 else
510 rcr &= ~Prom;
511 csr8w(ctlr, Rcr, rcr);
512 }
513
514 static void
vt6105Mmulticast(void * arg,uchar * addr,int on)515 vt6105Mmulticast(void* arg, uchar* addr, int on)
516 {
517 /*
518 * For now Am is set in Rcr.
519 * Will need to interlock with promiscuous
520 * when this gets filled in.
521 */
522 USED(arg, addr, on);
523 }
524
525 static int
vt6105Mwakeup(void * v)526 vt6105Mwakeup(void* v)
527 {
528 return *((int*)v) != 0;
529 }
530
531 static void
vt6105Mimr(Ctlr * ctlr,int imr)532 vt6105Mimr(Ctlr* ctlr, int imr)
533 {
534 ilock(&ctlr->clock);
535 ctlr->imr |= imr;
536 csr16w(ctlr, Imr, ctlr->imr);
537 iunlock(&ctlr->clock);
538 }
539
540 static void
vt6105Mlproc(void * arg)541 vt6105Mlproc(void* arg)
542 {
543 Ctlr *ctlr;
544 Ether *edev;
545 MiiPhy *phy;
546
547 edev = arg;
548 ctlr = edev->ctlr;
549 for(;;){
550 if(ctlr->mii == nil || ctlr->mii->curphy == nil)
551 break;
552 if(miistatus(ctlr->mii) < 0)
553 goto enable;
554
555 phy = ctlr->mii->curphy;
556 ilock(&ctlr->clock);
557 csr16w(ctlr, Cr, ctlr->cr & ~(Txon|Rxon));
558 if(phy->fd)
559 ctlr->cr |= Fdx;
560 else
561 ctlr->cr &= ~Fdx;
562 csr16w(ctlr, Cr, ctlr->cr);
563 iunlock(&ctlr->clock);
564 enable:
565 ctlr->lwakeup = 0;
566 vt6105Mimr(ctlr, Srci);
567
568 ctlr->lsleep++;
569 sleep(&ctlr->lrendez, vt6105Mwakeup, &ctlr->lwakeup);
570
571 }
572 pexit("vt6105Mlproc: done", 1);
573 }
574
575 static void
vt6105Mrbfree(Block * bp)576 vt6105Mrbfree(Block* bp)
577 {
578 bp->rp = bp->lim - (Rdbsz+3);
579 bp->wp = bp->rp;
580 bp->flag &= ~(Bipck | Budpck | Btcpck | Bpktck);
581
582 ilock(&vt6105Mrblock);
583 bp->next = vt6105Mrbpool;
584 vt6105Mrbpool = bp;
585 iunlock(&vt6105Mrblock);
586 }
587
588 static Block*
vt6105Mrballoc(void)589 vt6105Mrballoc(void)
590 {
591 Block *bp;
592
593 ilock(&vt6105Mrblock);
594 if((bp = vt6105Mrbpool) != nil){
595 vt6105Mrbpool = bp->next;
596 bp->next = nil;
597 _xinc(&bp->ref); /* prevent bp from being freed */
598 }
599 iunlock(&vt6105Mrblock);
600
601 if(bp == nil && (bp = iallocb(Rdbsz+3)) != nil){
602 bp->free = vt6105Mrbfree;
603 vt6105Mrbpoolsz++;
604 }
605 return bp;
606 }
607
608 static void
vt6105Mattach(Ether * edev)609 vt6105Mattach(Ether* edev)
610 {
611 Ctlr *ctlr;
612 // MiiPhy *phy;
613 uchar *alloc;
614 Ds *ds, *prev;
615 int dsz, i, timeo;
616 char name[KNAMELEN];
617
618 ctlr = edev->ctlr;
619 qlock(&ctlr->alock);
620 if(ctlr->alloc != nil){
621 qunlock(&ctlr->alock);
622 return;
623 }
624
625 /*
626 * Descriptor space.
627 * Receive descriptors should all be aligned on a 4-byte boundary,
628 * but try to do cache-line alignment.
629 */
630 ctlr->nrd = Nrd;
631 ctlr->ntd = Ntd;
632 dsz = ROUNDUP(sizeof(Ds), ctlr->cls);
633 alloc = mallocalign((ctlr->nrd+ctlr->ntd)*dsz, dsz, 0, 0);
634 if(alloc == nil){
635 qunlock(&ctlr->alock);
636 error(Enomem);
637 }
638 ctlr->alloc = alloc;
639
640 ctlr->rd = (Ds*)alloc;
641
642 if(waserror()){
643 ds = ctlr->rd;
644 for(i = 0; i < ctlr->nrd; i++){
645 if(ds->bp != nil){
646 freeb(ds->bp);
647 ds->bp = nil;
648 }
649 if((ds = ds->next) == nil)
650 break;
651 }
652 free(ctlr->alloc);
653 ctlr->alloc = nil;
654 qunlock(&ctlr->alock);
655 nexterror();
656 }
657
658 prev = (Ds*)(alloc + (ctlr->nrd-1)*dsz);
659 for(i = 0; i < ctlr->nrd; i++){
660 ds = (Ds*)alloc;
661 alloc += dsz;
662
663 ds->control = Ipkt|Tcpkt|Udpkt|Rdbsz;
664 ds->branch = PCIWADDR(alloc);
665
666 ds->bp = vt6105Mrballoc();
667 if(ds->bp == nil)
668 error("vt6105M: can't allocate receive ring\n");
669 ds->bp->rp = (uchar*)ROUNDUP((ulong)ds->bp->rp, 4);
670 ds->addr = PCIWADDR(ds->bp->rp);
671
672 ds->next = (Ds*)alloc;
673 ds->prev = prev;
674 prev = ds;
675
676 ds->status = Own;
677 }
678 prev->branch = 0;
679 prev->next = ctlr->rd;
680 prev->status = 0;
681 ctlr->rdh = ctlr->rd;
682
683 ctlr->td = (Ds*)alloc;
684 prev = (Ds*)(alloc + (ctlr->ntd-1)*dsz);
685 for(i = 0; i < ctlr->ntd; i++){
686 ds = (Ds*)alloc;
687 alloc += dsz;
688
689 ds->next = (Ds*)alloc;
690 ds->prev = prev;
691 prev = ds;
692 }
693 prev->next = ctlr->td;
694 ctlr->tdh = ctlr->tdt = ctlr->td;
695 ctlr->tdused = 0;
696
697 ctlr->cr = Dpoll|Rdmd/*|Txon|Rxon*/|Strt;
698 /*Srci|Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx*/
699 ctlr->imr = Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx;
700
701 ilock(&ctlr->clock);
702 csr32w(ctlr, Rxdaddr, PCIWADDR(ctlr->rd));
703 csr32w(ctlr, Txdaddr, PCIWADDR(ctlr->td));
704 csr16w(ctlr, Isr, ~0);
705 csr16w(ctlr, Imr, ctlr->imr);
706 csr16w(ctlr, Cr, ctlr->cr);
707 iunlock(&ctlr->clock);
708
709 /*
710 * Wait for link to be ready.
711 */
712 for(timeo = 0; timeo < 350; timeo++){
713 if(miistatus(ctlr->mii) == 0)
714 break;
715 tsleep(&up->sleep, return0, 0, 10);
716 }
717 // phy = ctlr->mii->curphy;
718 // print("%s: speed %d fd %d link %d rfc %d tfc %d\n",
719 // edev->name, phy->speed, phy->fd, phy->link, phy->rfc, phy->tfc);
720
721 ilock(&ctlr->clock);
722 ctlr->cr |= Txon|Rxon;
723 csr16w(ctlr, Cr, ctlr->cr);
724 iunlock(&ctlr->clock);
725
726 snprint(name, KNAMELEN, "#l%dlproc", edev->ctlrno);
727 kproc(name, vt6105Mlproc, edev);
728
729 qunlock(&ctlr->alock);
730 poperror();
731 }
732
733 static void
vt6105Mtransmit(Ether * edev)734 vt6105Mtransmit(Ether* edev)
735 {
736 Block *bp;
737 Ctlr *ctlr;
738 Ds *ds, *next;
739 int control, i, size, tdused, timeo;
740 long t;
741
742 ctlr = edev->ctlr;
743
744 ilock(&ctlr->tlock);
745 t = lcycles();
746
747 /*
748 * Free any completed packets
749 */
750 ds = ctlr->tdh;
751 for(tdused = ctlr->tdused; tdused > 0; tdused--){
752 /*
753 * For some errors the chip will turn the Tx engine
754 * off. Wait for that to happen.
755 * Could reset and re-init the chip here if it doesn't
756 * play fair.
757 * To do: adjust Tx FIFO threshold on underflow.
758 */
759 if(ds->status & (Abt|Tbuff|Udf)){
760 if(ds->status & Abt)
761 ctlr->abt++;
762 if(ds->status & Tbuff)
763 ctlr->tbuff++;
764 if(ds->status & Udf)
765 ctlr->udf++;
766 for(timeo = 0; timeo < 1000; timeo++){
767 if(!(csr16r(ctlr, Cr) & Txon))
768 break;
769 microdelay(1);
770 }
771 ds->status = Own;
772 csr32w(ctlr, Txdaddr, PCIWADDR(ds));
773 }
774
775 if(ds->status & Own)
776 break;
777 ds->addr = 0;
778 ds->branch = 0;
779
780 if(ds->bp != nil){
781 freeb(ds->bp);
782 ds->bp = nil;
783 }
784 for(i = 0; i < Ntxstats-1; i++){
785 if(ds->status & (1<<i))
786 ctlr->txstats[i]++;
787 }
788 ctlr->txstats[i] += (ds->status & NcrMASK)>>NcrSHIFT;
789
790 ds = ds->next;
791 }
792 ctlr->tdh = ds;
793
794 /*
795 * Try to fill the ring back up.
796 */
797 ds = ctlr->tdt;
798 while(tdused < ctlr->ntd-2){
799 if((bp = qget(edev->oq)) == nil)
800 break;
801 tdused++;
802
803 size = BLEN(bp);
804
805 next = ds->next;
806 ds->branch = PCIWADDR(ds->next)|Tdctl;
807
808 ds->bp = bp;
809 ds->addr = PCIWADDR(bp->rp);
810 control = Edp|Stp|((size<<TbsSHIFT) & TbsMASK);
811
812 ds->control = control;
813 if(tdused >= ctlr->ntd-2){
814 ctlr->txdw++;
815 ds->branch &= ~Tdctl;
816 }
817 coherence();
818 ds->status = Own;
819
820 ds = next;
821 }
822 ctlr->tdt = ds;
823 ctlr->tdused = tdused;
824 if(ctlr->tdused){
825 csr16w(ctlr, Cr, Tdmd|ctlr->cr);
826 if(tdused > ctlr->tdumax)
827 ctlr->tdumax = tdused;
828 }
829
830 ctlr->totalt += lcycles() - t;
831 iunlock(&ctlr->tlock);
832 }
833
834 static void
vt6105Mreceive(Ether * edev)835 vt6105Mreceive(Ether* edev)
836 {
837 Ds *ds;
838 Block *bp;
839 Ctlr *ctlr;
840 int i, len;
841
842 ctlr = edev->ctlr;
843
844 ds = ctlr->rdh;
845 while(!(ds->status & Own) && ds->status != 0){
846 /*
847 * Can Long packets be received OK?
848 * What happens to the Rxok bit?
849 */
850 if(ds->status & Rerr){
851 for(i = 0; i < Nrxstats; i++){
852 if(ds->status & (1<<i))
853 ctlr->rxstats[i]++;
854 }
855 }
856 else if(bp = vt6105Mrballoc()){
857 if(ds->control & Tuok){
858 ds->bp->flag |= Btcpck|Budpck;
859 ctlr->tuok++;
860 }
861 if(ds->control & Ipok){
862 ds->bp->flag |= Bipck;
863 ctlr->ipok++;
864 }
865 len = ((ds->status & LengthMASK)>>LengthSHIFT)-4;
866 ds->bp->wp = ds->bp->rp+len;
867 etheriq(edev, ds->bp, 1);
868 bp->rp = (uchar*)ROUNDUP((ulong)bp->rp, 4);
869 ds->addr = PCIWADDR(bp->rp);
870 ds->bp = bp;
871 }
872 ds->control = Ipkt|Tcpkt|Udpkt|Rdbsz;
873 ds->branch = 0;
874 ds->status = 0;
875
876 ds->prev->branch = PCIWADDR(ds);
877 coherence();
878 ds->prev->status = Own;
879
880 ds = ds->next;
881 }
882 ctlr->rdh = ds;
883
884 csr16w(ctlr, Cr, ctlr->cr);
885 }
886
887 static void
vt6105Minterrupt(Ureg *,void * arg)888 vt6105Minterrupt(Ureg*, void* arg)
889 {
890 Ctlr *ctlr;
891 Ether *edev;
892 int imr, isr, r, timeo;
893 long t;
894
895 edev = arg;
896 ctlr = edev->ctlr;
897
898 ilock(&ctlr->clock);
899 t = lcycles();
900
901 csr16w(ctlr, Imr, 0);
902 imr = ctlr->imr;
903 ctlr->intr++;
904 for(;;){
905 if((isr = csr16r(ctlr, Isr)) != 0)
906 csr16w(ctlr, Isr, isr);
907 if((isr & ctlr->imr) == 0)
908 break;
909
910 if(isr & Srci){
911 imr &= ~Srci;
912 ctlr->lwakeup = isr & Srci;
913 wakeup(&ctlr->lrendez);
914 isr &= ~Srci;
915 ctlr->lintr++;
916 }
917 if(isr & (Norbf|Pktrace|Ovfi|Ru|Rxe|Prx)){
918 vt6105Mreceive(edev);
919 isr &= ~(Norbf|Pktrace|Ovfi|Ru|Rxe|Prx);
920 ctlr->rintr++;
921 }
922 if(isr & (Abti|Udfi|Tu|Txe|Ptx)){
923 if(isr & (Abti|Udfi|Tu)){
924 if(isr & Abti)
925 ctlr->abti++;
926 if(isr & Udfi)
927 ctlr->udfi++;
928 if(isr & Tu)
929 ctlr->tu++;
930 for(timeo = 0; timeo < 1000; timeo++){
931 if(!(csr16r(ctlr, Cr) & Txon))
932 break;
933 microdelay(1);
934 }
935
936 if((isr & Udfi) && ctlr->tft < CtftSAF){
937 ctlr->tft += 1<<CtftSHIFT;
938 r = csr8r(ctlr, Bcr1) & ~CtftMASK;
939 csr8w(ctlr, Bcr1, r|ctlr->tft);
940 }
941 }
942
943
944 ctlr->totalt += lcycles() - t;
945 vt6105Mtransmit(edev);
946 t = lcycles();
947 isr &= ~(Abti|Udfi|Tu|Txe|Ptx);
948 ctlr->tintr++;
949 }
950 if(isr)
951 panic("vt6105M: isr %4.4uX\n", isr);
952 }
953 ctlr->imr = imr;
954 csr16w(ctlr, Imr, ctlr->imr);
955
956 ctlr->totalt += lcycles() - t;
957 iunlock(&ctlr->clock);
958 }
959
960 static int
vt6105Mmiimicmd(Mii * mii,int pa,int ra,int cmd,int data)961 vt6105Mmiimicmd(Mii* mii, int pa, int ra, int cmd, int data)
962 {
963 Ctlr *ctlr;
964 int r, timeo;
965
966 ctlr = mii->ctlr;
967
968 csr8w(ctlr, Miicr, 0);
969 r = csr8r(ctlr, Phyadr);
970 csr8w(ctlr, Phyadr, (r & ~PhyadMASK)|pa);
971 csr8w(ctlr, Phyadr, pa);
972 csr8w(ctlr, Miiadr, ra);
973 if(cmd == Wcmd)
974 csr16w(ctlr, Miidata, data);
975 csr8w(ctlr, Miicr, cmd);
976
977 for(timeo = 0; timeo < Maxus; timeo++){
978 if(!(csr8r(ctlr, Miicr) & cmd))
979 break;
980 microdelay(1);
981 }
982 if(timeo >= Maxus)
983 return -1;
984
985 if(cmd == Wcmd)
986 return 0;
987 return csr16r(ctlr, Miidata);
988 }
989
990 static int
vt6105Mmiimir(Mii * mii,int pa,int ra)991 vt6105Mmiimir(Mii* mii, int pa, int ra)
992 {
993 return vt6105Mmiimicmd(mii, pa, ra, Rcmd, 0);
994 }
995
996 static int
vt6105Mmiimiw(Mii * mii,int pa,int ra,int data)997 vt6105Mmiimiw(Mii* mii, int pa, int ra, int data)
998 {
999 return vt6105Mmiimicmd(mii, pa, ra, Wcmd, data);
1000 }
1001
1002 static int
vt6105Mdetach(Ctlr * ctlr)1003 vt6105Mdetach(Ctlr* ctlr)
1004 {
1005 int revid, timeo;
1006
1007 /*
1008 * Reset power management registers.
1009 */
1010 revid = pcicfgr8(ctlr->pcidev, PciRID);
1011 if(revid >= 0x40){
1012 /* Set power state D0. */
1013 csr8w(ctlr, Stickhw, csr8r(ctlr, Stickhw) & 0xFC);
1014
1015 /* Disable force PME-enable. */
1016 csr8w(ctlr, Wolcgclr, 0x80);
1017
1018 /* Clear WOL config and status bits. */
1019 csr8w(ctlr, Wolcrclr, 0xFF);
1020 csr8w(ctlr, Pwrcsrclr, 0xFF);
1021 }
1022
1023 /*
1024 * Soft reset the controller.
1025 */
1026 csr16w(ctlr, Cr, Stop);
1027 csr16w(ctlr, Cr, Stop|Sfrst);
1028 for(timeo = 0; timeo < Maxus; timeo++){
1029 if(!(csr16r(ctlr, Cr) & Sfrst))
1030 break;
1031 microdelay(1);
1032 }
1033 if(timeo >= Maxus)
1034 return -1;
1035
1036 return 0;
1037 }
1038
1039 static void
vt6105Mshutdown(Ether * ether)1040 vt6105Mshutdown(Ether *ether)
1041 {
1042 Ctlr *ctlr = ether->ctlr;
1043
1044 vt6105Mdetach(ctlr);
1045 }
1046
1047 static int
vt6105Mreset(Ctlr * ctlr)1048 vt6105Mreset(Ctlr* ctlr)
1049 {
1050 MiiPhy *phy;
1051 int i, r, timeo;
1052
1053 if(vt6105Mdetach(ctlr) < 0)
1054 return -1;
1055
1056 /*
1057 * Load the MAC address into the PAR[01]
1058 * registers.
1059 */
1060 r = csr8r(ctlr, Eecsr);
1061 csr8w(ctlr, Eecsr, Autold|r);
1062 for(timeo = 0; timeo < Maxus; timeo++){
1063 if(!(csr8r(ctlr, Cr) & Autold))
1064 break;
1065 microdelay(1);
1066 }
1067 if(timeo >= Maxus)
1068 return -1;
1069
1070 for(i = 0; i < Eaddrlen; i++)
1071 ctlr->par[i] = csr8r(ctlr, Par0+i);
1072
1073 /*
1074 * Configure DMA and Rx/Tx thresholds.
1075 * If the Rx/Tx threshold bits in Bcr[01] are 0 then
1076 * the thresholds are determined by Rcr/Tcr.
1077 */
1078 r = csr8r(ctlr, Bcr0) & ~(CrftMASK|DmaMASK);
1079 csr8w(ctlr, Bcr0, r|Crft128|DmaSAF);
1080 r = csr8r(ctlr, Bcr1) & ~CtftMASK;
1081 csr8w(ctlr, Bcr1, r|ctlr->tft);
1082
1083 r = csr8r(ctlr, Rcr) & ~(RrftMASK|Prom|Ar|Sep);
1084 csr8w(ctlr, Rcr, r|Ab|Am);
1085 csr32w(ctlr, Mcfilt0, ~0UL); /* accept all multicast */
1086 csr32w(ctlr, Mcfilt1, ~0UL);
1087
1088 r = csr8r(ctlr, Tcr) & ~(RtsfMASK|Ofset|Lb1|Lb0);
1089 csr8w(ctlr, Tcr, r);
1090
1091 /*
1092 * Link management.
1093 */
1094 if((ctlr->mii = malloc(sizeof(Mii))) == nil)
1095 return -1;
1096 ctlr->mii->mir = vt6105Mmiimir;
1097 ctlr->mii->miw = vt6105Mmiimiw;
1098 ctlr->mii->ctlr = ctlr;
1099
1100 if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
1101 free(ctlr->mii);
1102 ctlr->mii = nil;
1103 return -1;
1104 }
1105 // print("oui %X phyno %d\n", phy->oui, phy->phyno);
1106 USED(phy);
1107
1108 if(miistatus(ctlr->mii) < 0){
1109 // miireset(ctlr->mii);
1110 miiane(ctlr->mii, ~0, ~0, ~0);
1111 }
1112
1113 return 0;
1114 }
1115
1116 static void
vt6105Mpci(void)1117 vt6105Mpci(void)
1118 {
1119 Pcidev *p;
1120 Ctlr *ctlr;
1121 int cls, port;
1122
1123 p = nil;
1124 while(p = pcimatch(p, 0, 0)){
1125 if(p->ccrb != Pcibcnet || p->ccru != Pciscether)
1126 continue;
1127
1128 switch((p->did<<16)|p->vid){
1129 default:
1130 continue;
1131 case (0x3053<<16)|0x1106: /* Rhine III-M vt6105M */
1132 break;
1133 }
1134
1135 port = p->mem[0].bar & ~0x01;
1136 if(ioalloc(port, p->mem[0].size, 0, "vt6105M") < 0){
1137 print("vt6105M: port 0x%uX in use\n", port);
1138 continue;
1139 }
1140 ctlr = malloc(sizeof(Ctlr));
1141 if(ctlr == nil) {
1142 iofree(port);
1143 error(Enomem);
1144 }
1145 ctlr->port = port;
1146 ctlr->pcidev = p;
1147 ctlr->id = (p->did<<16)|p->vid;
1148 if((cls = pcicfgr8(p, PciCLS)) == 0 || cls == 0xFF)
1149 cls = 0x10;
1150 ctlr->cls = cls*4;
1151 if(ctlr->cls < sizeof(Ds)){
1152 print("vt6105M: cls %d < sizeof(Ds)\n", ctlr->cls);
1153 iofree(port);
1154 free(ctlr);
1155 continue;
1156 }
1157 ctlr->tft = CtftSAF;
1158
1159 if(vt6105Mreset(ctlr)){
1160 iofree(port);
1161 free(ctlr);
1162 continue;
1163 }
1164 pcisetbme(p);
1165
1166 if(vt6105Mctlrhead != nil)
1167 vt6105Mctlrtail->next = ctlr;
1168 else
1169 vt6105Mctlrhead = ctlr;
1170 vt6105Mctlrtail = ctlr;
1171 }
1172 }
1173
1174 static int
vt6105Mpnp(Ether * edev)1175 vt6105Mpnp(Ether* edev)
1176 {
1177 Ctlr *ctlr;
1178
1179 if(vt6105Mctlrhead == nil)
1180 vt6105Mpci();
1181
1182 /*
1183 * Any adapter matches if no edev->port is supplied,
1184 * otherwise the ports must match.
1185 */
1186 for(ctlr = vt6105Mctlrhead; ctlr != nil; ctlr = ctlr->next){
1187 if(ctlr->active)
1188 continue;
1189 if(edev->port == 0 || edev->port == ctlr->port){
1190 ctlr->active = 1;
1191 break;
1192 }
1193 }
1194 if(ctlr == nil)
1195 return -1;
1196
1197 edev->ctlr = ctlr;
1198 edev->port = ctlr->port;
1199 edev->irq = ctlr->pcidev->intl;
1200 edev->tbdf = ctlr->pcidev->tbdf;
1201 /*
1202 * Set to 1000Mb/s to fool the bsz calculation. We need
1203 * something better, though.
1204 */
1205 edev->mbps = 1000;
1206 memmove(edev->ea, ctlr->par, Eaddrlen);
1207
1208 /*
1209 * Linkage to the generic ethernet driver.
1210 */
1211 edev->attach = vt6105Mattach;
1212 edev->transmit = vt6105Mtransmit;
1213 edev->interrupt = vt6105Minterrupt;
1214 edev->ifstat = vt6105Mifstat;
1215 edev->shutdown = vt6105Mshutdown;
1216 edev->ctl = nil;
1217
1218 edev->arg = edev;
1219 edev->promiscuous = vt6105Mpromiscuous;
1220 edev->multicast = vt6105Mmulticast;
1221
1222 edev->maxmtu = ETHERMAXTU+Bslop;
1223
1224 return 0;
1225 }
1226
1227 void
ethervt6105mlink(void)1228 ethervt6105mlink(void)
1229 {
1230 addethercard("vt6105M", vt6105Mpnp);
1231 }
1232