]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/etherga620.c
pc/ether*: use 64-bit physical addresses and check pci membar types and sizes
[plan9front.git] / sys / src / 9 / pc / etherga620.c
1 /*
2  * Netgear GA620 Gigabit Ethernet Card.
3  * Specific for the Alteon Tigon 2 and Intel Pentium or later.
4  * To Do:
5  *      cache alignment for PCI Write-and-Invalidate
6  *      mini ring (what size)?
7  *      tune coalescing values
8  *      statistics formatting
9  *      don't update Spi if nothing to send
10  *      receive ring alignment
11  *      watchdog for link management?
12  */
13 #include "u.h"
14 #include "../port/lib.h"
15 #include "mem.h"
16 #include "dat.h"
17 #include "fns.h"
18 #include "io.h"
19 #include "../port/error.h"
20 #include "../port/netif.h"
21 #include "../port/etherif.h"
22
23 #define malign(n)       xspanalloc((n), 32, 0)
24 #include "etherga620fw.h"
25
26 enum {
27         Mhc             = 0x0040,       /* Miscellaneous Host Control */
28         Mlc             = 0x0044,       /* Miscellaneous Local Control */
29         Mc              = 0x0050,       /* Miscellaneous Configuration */
30         Ps              = 0x005C,       /* PCI State */
31         Wba             = 0x0068,       /* Window Base Address */
32         Wd              = 0x006C,       /* Window Data */
33
34         DMAas           = 0x011C,       /* DMA Assist State */
35
36         CPUAstate       = 0x0140,       /* CPU A State */
37         CPUApc          = 0x0144,       /* CPU A Programme Counter */
38
39         CPUBstate       = 0x0240,       /* CPU B State */
40
41         Hi              = 0x0504,       /* Host In Interrupt Handler */
42         Cpi             = 0x050C,       /* Command Producer Index */
43         Spi             = 0x0514,       /* Send Producer Index */
44         Rspi            = 0x051C,       /* Receive Standard Producer Index */
45         Rjpi            = 0x0524,       /* Receive Jumbo Producer Index */
46         Rmpi            = 0x052C,       /* Receive Mini Producer Index */
47
48         Mac             = 0x0600,       /* MAC Address */
49         Gip             = 0x0608,       /* General Information Pointer */
50         Om              = 0x0618,       /* Operating Mode */
51         DMArc           = 0x061C,       /* DMA Read Configuration */
52         DMAwc           = 0x0620,       /* DMA Write Configuration */
53         Tbr             = 0x0624,       /* Transmit Buffer Ratio */
54         Eci             = 0x0628,       /* Event Consumer Index */
55         Cci             = 0x062C,       /* Command Consumer Index */
56
57         Rct             = 0x0630,       /* Receive Coalesced Ticks */
58         Sct             = 0x0634,       /* Send Coalesced Ticks */
59         St              = 0x0638,       /* Stat Ticks */
60         SmcBD           = 0x063C,       /* Send Max. Coalesced BDs */
61         RmcBD           = 0x0640,       /* Receive Max. Coalesced BDs */
62         Nt              = 0x0644,       /* NIC Tracing */
63         Gln             = 0x0648,       /* Gigabit Link Negotiation */
64         Fln             = 0x064C,       /* 10/100 Link Negotiation */
65         Ifx             = 0x065C,       /* Interface Index */
66         IfMTU           = 0x0660,       /* Interface MTU */
67         Mi              = 0x0664,       /* Mask Interrupts */
68         Gls             = 0x0668,       /* Gigabit Link State */
69         Fls             = 0x066C,       /* 10/100 Link State */
70
71         Cr              = 0x0700,       /* Command Ring */
72
73         Lmw             = 0x0800,       /* Local Memory Window */
74 };
75
76 enum {                                  /* Mhc */
77         Is              = 0x00000001,   /* Interrupt State */
78         Ci              = 0x00000002,   /* Clear Interrupt */
79         Hr              = 0x00000008,   /* Hard Reset */
80         Eebs            = 0x00000010,   /* Enable Endian Byte Swap */
81         Eews            = 0x00000020,   /* Enable Endian Word (64-bit) swap */
82         Mpio            = 0x00000040,   /* Mask PCI Interrupt Output */
83 };
84
85 enum {                                  /* Mlc */
86         SRAM512         = 0x00000200,   /* SRAM Bank Size of 512KB */
87         SRAMmask        = 0x00000300,
88         EEclk           = 0x00100000,   /* Serial EEPROM Clock Output */
89         EEdoe           = 0x00200000,   /* Serial EEPROM Data Out Enable */
90         EEdo            = 0x00400000,   /* Serial EEPROM Data Out Value */
91         EEdi            = 0x00800000,   /* Serial EEPROM Data Input */
92 };
93
94 enum {                                  /* Mc */
95         SyncSRAM        = 0x00100000,   /* Set Synchronous SRAM Timing */
96 };
97
98 enum {                                  /* Ps */
99         PCIwm32         = 0x000000C0,   /* Write Max DMA 32 */
100         PCImrm          = 0x00020000,   /* Use Memory Read Multiple Command */
101         PCI66           = 0x00080000,
102         PCI32           = 0x00100000,
103         PCIrcmd         = 0x06000000,   /* PCI Read Command */
104         PCIwcmd         = 0x70000000,   /* PCI Write Command */
105 };
106
107 enum {                                  /* CPUAstate */
108         CPUrf           = 0x00000010,   /* ROM Fail */
109         CPUhalt         = 0x00010000,   /* Halt the internal CPU */
110         CPUhie          = 0x00040000,   /* HALT instruction executed */
111 };
112
113 enum {                                  /* Om */
114         BswapBD         = 0x00000002,   /* Byte Swap Buffer Descriptors */
115         WswapBD         = 0x00000004,   /* Word Swap Buffer Descriptors */
116         Warn            = 0x00000008,
117         BswapDMA        = 0x00000010,   /* Byte Swap DMA Data */
118         Only1DMA        = 0x00000040,   /* Only One DMA Active at a time */
119         NoJFrag         = 0x00000200,   /* Don't Fragment Jumbo Frames */
120         Fatal           = 0x40000000,
121 };
122
123 enum {                                  /* Lmw */
124         Lmwsz           = 2*1024,       /* Local Memory Window Size */
125
126         /*
127          * legal values are 0x3800 iff Nsr is 128, 0x3000 iff Nsr is 256,
128          * or 0x2000 iff Nsr is 512.
129          */
130         Sr              = 0x2000,       /* Send Ring (accessed via Lmw) */
131 };
132
133 enum {                                  /* Link */
134         Lpref           = 0x00008000,   /* Preferred Link */
135         L10MB           = 0x00010000,
136         L100MB          = 0x00020000,
137         L1000MB         = 0x00040000,
138         Lfd             = 0x00080000,   /* Full Duplex */
139         Lhd             = 0x00100000,   /* Half Duplex */
140         Lefc            = 0x00200000,   /* Emit Flow Control Packets */
141         Lofc            = 0x00800000,   /* Obey Flow Control Packets */
142         Lean            = 0x20000000,   /* Enable Autonegotiation/Sensing */
143         Le              = 0x40000000,   /* Link Enable */
144 };
145
146 typedef struct Host64 {
147         uint    hi;
148         uint    lo;
149 } Host64;
150
151 typedef struct Ere {                    /* Event Ring Element */
152         int     event;                  /* event<<24 | code<<12 | index */
153         int     unused;
154 } Ere;
155
156 typedef int Cmd;                        /* cmd<<24 | flags<<12 | index */
157
158 typedef struct Rbd {                    /* Receive Buffer Descriptor */
159         Host64  addr;
160         int     indexlen;               /* ring-index<<16 | buffer-length */
161         int     flags;                  /* only lower 16-bits */
162         int     checksum;               /* ip<<16 | tcp/udp */
163         int     error;                  /* only upper 16-bits */
164         int     reserved;
165         void*   opaque;                 /* passed to receive return ring */
166 } Rbd;
167
168 typedef struct Sbd {                    /* Send Buffer Descriptor */
169         Host64  addr;
170         int     lenflags;               /* len<<16 | flags */
171         int     reserved;
172 } Sbd;
173
174 enum {                                  /* Buffer Descriptor Flags */
175         Fend            = 0x00000004,   /* Frame Ends in this Buffer */
176         Frjr            = 0x00000010,   /* Receive Jumbo Ring Buffer */
177         Funicast        = 0x00000020,   /* Unicast packet (2-bit field) */
178         Fmulticast      = 0x00000040,   /* Multicast packet */
179         Fbroadcast      = 0x00000060,   /* Broadcast packet */
180         Ferror          = 0x00000400,   /* Frame Has Error */
181         Frmr            = 0x00001000,   /* Receive Mini Ring Buffer */
182 };
183
184 enum {                                  /* Buffer Error Flags */
185         Ecrc            = 0x00010000,   /* bad CRC */
186         Ecollision      = 0x00020000,   /* collision */
187         Elink           = 0x00040000,   /* link lost */
188         Ephy            = 0x00080000,   /* unspecified PHY frame decode error */
189         Eodd            = 0x00100000,   /* odd number of nibbles */
190         Emac            = 0x00200000,   /* unspecified MAC abort */
191         Elen64          = 0x00400000,   /* short packet */
192         Eresources      = 0x00800000,   /* MAC out of internal resources */
193         Egiant          = 0x01000000,   /* packet too big */
194 };
195
196 typedef struct Rcb {                    /* Ring Control Block */
197         Host64  addr;                   /* points to the Rbd ring */
198         int     control;                /* max_len<<16 | flags */
199         int     unused;
200 } Rcb;
201
202 enum {
203         TcpUdpCksum     = 0x0001,       /* Perform TCP or UDP checksum */
204         IpCksum         = 0x0002,       /* Perform IP checksum */
205         NoPseudoHdrCksum= 0x0008,       /* Don't include the pseudo header */
206         VlanAssist      = 0x0010,       /* Enable VLAN tagging */
207         CoalUpdateOnly  = 0x0020,       /* Coalesce transmit interrupts */
208         HostRing        = 0x0040,       /* Sr in host memory */
209         SnapCksum       = 0x0080,       /* Parse + offload 802.3 SNAP frames */
210         UseExtRxBd      = 0x0100,       /* Extended Rbd for Jumbo frames */
211         RingDisabled    = 0x0200,       /* Jumbo or Mini RCB only */
212 };
213
214 typedef struct Gib {                    /* General Information Block */
215         int     statistics[256];        /* Statistics */
216         Rcb     ercb;                   /* Event Ring */
217         Rcb     crcb;                   /* Command Ring */
218         Rcb     srcb;                   /* Send Ring */
219         Rcb     rsrcb;                  /* Receive Standard Ring */
220         Rcb     rjrcb;                  /* Receive Jumbo Ring */
221         Rcb     rmrcb;                  /* Receive Mini Ring */
222         Rcb     rrrcb;                  /* Receive Return Ring */
223         Host64  epp;                    /* Event Producer */
224         Host64  rrrpp;                  /* Receive Return Ring Producer */
225         Host64  scp;                    /* Send Consumer */
226         Host64  rsp;                    /* Refresh Stats */
227 } Gib;
228
229 /*
230  * these sizes are all fixed in the card,
231  * except for Nsr, which has only 3 valid sizes.
232  */
233 enum {                                  /* Host/NIC Interface ring sizes */
234         Ner             = 256,          /* event ring */
235         Ncr             = 64,           /* command ring */
236         Nsr             = 512,          /* send ring: 128, 256 or 512 */
237         Nrsr            = 512,          /* receive standard ring */
238         Nrjr            = 256,          /* receive jumbo ring */
239         Nrmr            = 1024,         /* receive mini ring, optional */
240         Nrrr            = 2048,         /* receive return ring */
241 };
242
243 enum {
244         NrsrHI          = 72,           /* Fill-level of Rsr (m.b. < Nrsr) */
245         NrsrLO          = 54,           /* Level at which to top-up ring */
246         NrjrHI          = 0,            /* Fill-level of Rjr (m.b. < Nrjr) */
247         NrjrLO          = 0,            /* Level at which to top-up ring */
248         NrmrHI          = 0,            /* Fill-level of Rmr (m.b. < Nrmr) */
249         NrmrLO          = 0,            /* Level at which to top-up ring */
250 };
251
252 typedef struct Ctlr Ctlr;
253 struct Ctlr {
254         uvlong  port;
255         Pcidev* pcidev;
256         Ctlr*   next;
257         int     active;
258         int     id;
259
260         uchar   ea[Eaddrlen];
261
262         int*    nic;
263         Gib*    gib;
264
265         Ere*    er;
266
267         Lock    srlock;
268         Sbd*    sr;
269         Block** srb;
270         int     nsr;                    /* currently in send ring */
271
272         Rbd*    rsr;
273         int     nrsr;                   /* currently in Receive Standard Ring */
274         Rbd*    rjr;
275         int     nrjr;                   /* currently in Receive Jumbo Ring */
276         Rbd*    rmr;
277         int     nrmr;                   /* currently in Receive Mini Ring */
278         Rbd*    rrr;
279         int     rrrci;                  /* Receive Return Ring Consumer Index */
280
281         int     epi[2];                 /* Event Producer Index */
282         int     rrrpi[2];               /* Receive Return Ring Producer Index */
283         int     sci[3];                 /* Send Consumer Index ([2] is host) */
284
285         int     interrupts;             /* statistics */
286         int     mi;
287         uvlong  ticks;
288
289         int     coalupdateonly;         /* tuning */
290         int     hardwarecksum;
291         int     rct;                    /* Receive Coalesce Ticks */
292         int     sct;                    /* Send Coalesce Ticks */
293         int     st;                     /* Stat Ticks */
294         int     smcbd;                  /* Send Max. Coalesced BDs */
295         int     rmcbd;                  /* Receive Max. Coalesced BDs */
296 };
297
298 static Ctlr* ctlrhead;
299 static Ctlr* ctlrtail;
300
301 #define csr32r(c, r)    (*((c)->nic+((r)/4)))
302 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
303
304 static void
305 sethost64(Host64* host64, void* addr)
306 {
307         uvlong uvl;
308
309         uvl = PCIWADDR(addr);
310         host64->hi = uvl>>32;
311         host64->lo = uvl & 0xFFFFFFFFL;
312 }
313
314 static void
315 ga620command(Ctlr* ctlr, int cmd, int flags, int index)
316 {
317         int cpi;
318
319         cpi = csr32r(ctlr, Cpi);
320         csr32w(ctlr, Cr+(cpi*4), cmd<<24 | flags<<12 | index);
321         cpi = NEXT(cpi, Ncr);
322         csr32w(ctlr, Cpi, cpi);
323 }
324
325 static void
326 ga620attach(Ether* edev)
327 {
328         Ctlr *ctlr;
329
330         ctlr = edev->ctlr;
331         USED(ctlr);
332 }
333
334 static long
335 ga620ifstat(Ether* edev, void* a, long n, ulong offset)
336 {
337         char *p;
338         Ctlr *ctlr;
339         int i, l, r;
340
341         ctlr = edev->ctlr;
342
343         if(n == 0)
344                 return 0;
345         p = smalloc(READSTR);
346         l = 0;
347         for(i = 0; i < 256; i++){
348                 if((r = ctlr->gib->statistics[i]) == 0)
349                         continue;
350                 l += snprint(p+l, READSTR-l, "%d: %ud\n", i, r);
351         }
352
353         l += snprint(p+l, READSTR-l, "interrupts: %ud\n", ctlr->interrupts);
354         l += snprint(p+l, READSTR-l, "mi: %ud\n", ctlr->mi);
355         l += snprint(p+l, READSTR-l, "ticks: %llud\n", ctlr->ticks);
356         l += snprint(p+l, READSTR-l, "coalupdateonly: %d\n", ctlr->coalupdateonly);
357         l += snprint(p+l, READSTR-l, "hardwarecksum: %d\n", ctlr->hardwarecksum);
358         l += snprint(p+l, READSTR-l, "rct: %d\n", ctlr->rct);
359         l += snprint(p+l, READSTR-l, "sct: %d\n", ctlr->sct);
360         l += snprint(p+l, READSTR-l, "smcbd: %d\n", ctlr->smcbd);
361         snprint(p+l, READSTR-l, "rmcbd: %d\n", ctlr->rmcbd);
362
363         n = readstr(offset, a, n, p);
364         free(p);
365
366         return n;
367 }
368
369 static long
370 ga620ctl(Ether* edev, void* buf, long n)
371 {
372         char *p;
373         Cmdbuf *cb;
374         Ctlr *ctlr;
375         int control, i, r;
376
377         ctlr = edev->ctlr;
378         if(ctlr == nil)
379                 error(Enonexist);
380         r = 0;
381         cb = parsecmd(buf, n);
382         if(cb->nf < 2)
383                 r = -1;
384         else if(cistrcmp(cb->f[0], "coalupdateonly") == 0){
385                 if(cistrcmp(cb->f[1], "off") == 0){
386                         control = ctlr->gib->srcb.control;
387                         control &= ~CoalUpdateOnly;
388                         ctlr->gib->srcb.control = control;
389                         ctlr->coalupdateonly = 0;
390                 }
391                 else if(cistrcmp(cb->f[1], "on") == 0){
392                         control = ctlr->gib->srcb.control;
393                         control |= CoalUpdateOnly;
394                         ctlr->gib->srcb.control = control;
395                         ctlr->coalupdateonly = 1;
396                 }
397                 else
398                         r = -1;
399         }
400         else if(cistrcmp(cb->f[0], "hardwarecksum") == 0){
401                 if(cistrcmp(cb->f[1], "off") == 0){
402                         control = ctlr->gib->srcb.control;
403                         control &= ~(TcpUdpCksum|NoPseudoHdrCksum);
404                         ctlr->gib->srcb.control = control;
405
406                         control = ctlr->gib->rsrcb.control;
407                         control &= ~(TcpUdpCksum|NoPseudoHdrCksum);
408                         ctlr->gib->rsrcb.control = control;
409
410                         ctlr->hardwarecksum = 0;
411                 }
412                 else if(cistrcmp(cb->f[1], "on") == 0){
413                         control = ctlr->gib->srcb.control;
414                         control |= (TcpUdpCksum|NoPseudoHdrCksum);
415                         ctlr->gib->srcb.control = control;
416
417                         control = ctlr->gib->rsrcb.control;
418                         control |= (TcpUdpCksum|NoPseudoHdrCksum);
419                         ctlr->gib->rsrcb.control = control;
420
421                         ctlr->hardwarecksum = 1;
422                 }
423                 else
424                         r = -1;
425         }
426         else if(cistrcmp(cb->f[0], "rct") == 0){
427                 i = strtol(cb->f[1], &p, 0);
428                 if(i < 0 || p == cb->f[1])
429                         r = -1;
430                 else{
431                         ctlr->rct = i;
432                         csr32w(ctlr, Rct, ctlr->rct);
433                 }
434         }
435         else if(cistrcmp(cb->f[0], "sct") == 0){
436                 i = strtol(cb->f[1], &p, 0);
437                 if(i < 0 || p == cb->f[1])
438                         r = -1;
439                 else{
440                         ctlr->sct = i;
441                         csr32w(ctlr, Sct, ctlr->sct);
442                 }
443         }
444         else if(cistrcmp(cb->f[0], "st") == 0){
445                 i = strtol(cb->f[1], &p, 0);
446                 if(i < 0 || p == cb->f[1])
447                         r = -1;
448                 else{
449                         ctlr->st = i;
450                         csr32w(ctlr, St, ctlr->st);
451                 }
452         }
453         else if(cistrcmp(cb->f[0], "smcbd") == 0){
454                 i = strtol(cb->f[1], &p, 0);
455                 if(i < 0 || p == cb->f[1])
456                         r = -1;
457                 else{
458                         ctlr->smcbd = i;
459                         csr32w(ctlr, SmcBD, ctlr->smcbd);
460                 }
461         }
462         else if(cistrcmp(cb->f[0], "rmcbd") == 0){
463                 i = strtol(cb->f[1], &p, 0);
464                 if(i < 0 || p == cb->f[1])
465                         r = -1;
466                 else{
467                         ctlr->rmcbd = i;
468                         csr32w(ctlr, RmcBD, ctlr->rmcbd);
469                 }
470         }
471         else
472                 r = -1;
473
474         free(cb);
475         if(r == 0)
476                 return n;
477         return r;
478 }
479
480 static int
481 _ga620transmit(Ether* edev)
482 {
483         Sbd *sbd;
484         Block *bp;
485         Ctlr *ctlr;
486         int sci, spi, work;
487
488         /*
489          * For now there are no smarts here, just empty the
490          * ring and try to fill it back up. Tuning comes later.
491          */
492         ctlr = edev->ctlr;
493         ilock(&ctlr->srlock);
494
495         /*
496          * Free any completed packets.
497          * Ctlr->sci[0] is where the NIC has got to consuming the ring.
498          * Ctlr->sci[2] is where the host has got to tidying up after the
499          * NIC has done with the packets.
500          */
501         work = 0;
502         for(sci = ctlr->sci[2]; sci != ctlr->sci[0]; sci = NEXT(sci, Nsr)){
503                 if(ctlr->srb[sci] == nil)
504                         continue;
505                 freeb(ctlr->srb[sci]);
506                 ctlr->srb[sci] = nil;
507                 work++;
508         }
509         ctlr->sci[2] = sci;
510
511         sci = PREV(sci, Nsr);
512         for(spi = csr32r(ctlr, Spi); spi != sci; spi = NEXT(spi, Nsr)){
513                 if((bp = qget(edev->oq)) == nil)
514                         break;
515
516                 sbd = &ctlr->sr[spi];
517                 sethost64(&sbd->addr, bp->rp);
518                 sbd->lenflags = BLEN(bp)<<16 | Fend;
519
520                 ctlr->srb[spi] = bp;
521                 work++;
522         }
523         csr32w(ctlr, Spi, spi);
524
525         iunlock(&ctlr->srlock);
526
527         return work;
528 }
529
530 static void
531 ga620transmit(Ether* edev)
532 {
533         _ga620transmit(edev);
534 }
535
536 static void
537 ga620replenish(Ctlr* ctlr)
538 {
539         Rbd *rbd;
540         int rspi;
541         Block *bp;
542
543         rspi = csr32r(ctlr, Rspi);
544         while(ctlr->nrsr < NrsrHI){
545                 if((bp = iallocb(ETHERMAXTU+4)) == nil)
546                         break;
547                 rbd = &ctlr->rsr[rspi];
548                 sethost64(&rbd->addr, bp->rp);
549                 rbd->indexlen = rspi<<16 | (ETHERMAXTU+4);
550                 rbd->flags = 0;
551                 rbd->opaque = bp;
552
553                 rspi = NEXT(rspi, Nrsr);
554                 ctlr->nrsr++;
555         }
556         csr32w(ctlr, Rspi, rspi);
557 }
558
559 static void
560 ga620event(Ether *edev, int eci, int epi)
561 {
562         unsigned event, code;
563         Ctlr *ctlr;
564
565         ctlr = edev->ctlr;
566         while(eci != epi){
567                 event = ctlr->er[eci].event;
568                 code = (event >> 12) & ((1<<12)-1);
569                 switch(event>>24){
570                 case 0x01:              /* firmware operational */
571                         /* host stack (us) is up.  3rd arg of 2 means down. */
572                         ga620command(ctlr, 0x01, 0x01, 0x00);
573                         /*
574                          * link negotiation: any speed is okay.
575                          * 3rd arg of 1 selects gigabit only; 2 10/100 only.
576                          */
577                         ga620command(ctlr, 0x0B, 0x00, 0x00);
578                         print("#l%d: ga620: port %8.8lluX: firmware is up\n",
579                                 edev->ctlrno, ctlr->port);
580                         break;
581                 case 0x04:              /* statistics updated */
582                         break;
583                 case 0x06:              /* link state changed */
584                         switch (code) {
585                         case 1:
586                                 edev->mbps = 1000;
587                                 break;
588                         case 2:
589                                 print("#l%d: link down\n", edev->ctlrno);
590                                 break;
591                         case 3:
592                                 edev->mbps = 100;       /* it's 10 or 100 */
593                                 break;
594                         }
595                         if (code != 2)
596                                 print("#l%d: %dMbps link up\n",
597                                         edev->ctlrno, edev->mbps);
598                         break;
599                 case 0x07:              /* event error */
600                 default:
601                         print("#l%d: ga620: er[%d] = %8.8uX\n", edev->ctlrno,
602                                 eci, event);
603                         break;
604                 }
605                 eci = NEXT(eci, Ner);
606         }
607         csr32w(ctlr, Eci, eci);
608 }
609
610 static void
611 ga620receive(Ether* edev)
612 {
613         int len;
614         Rbd *rbd;
615         Block *bp;
616         Ctlr* ctlr;
617
618         ctlr = edev->ctlr;
619         while(ctlr->rrrci != ctlr->rrrpi[0]){
620                 rbd = &ctlr->rrr[ctlr->rrrci];
621                 /*
622                  * Errors are collected in the statistics block so
623                  * no need to tally them here, let ifstat do the work.
624                  */
625                 len = rbd->indexlen & 0xFFFF;
626                 if(!(rbd->flags & Ferror) && len != 0){
627                         bp = rbd->opaque;
628                         bp->wp = bp->rp+len;
629                         etheriq(edev, bp);
630                 }
631                 else
632                         freeb(rbd->opaque);
633                 rbd->opaque = nil;
634
635                 if(rbd->flags & Frjr)
636                         ctlr->nrjr--;
637                 else if(rbd->flags & Frmr)
638                         ctlr->nrmr--;
639                 else
640                         ctlr->nrsr--;
641
642                 ctlr->rrrci = NEXT(ctlr->rrrci, Nrrr);
643         }
644 }
645
646 static void
647 ga620interrupt(Ureg*, void* arg)
648 {
649         int csr, ie, work;
650         Ctlr *ctlr;
651         Ether *edev;
652         uvlong tsc0, tsc1;
653
654         edev = arg;
655         ctlr = edev->ctlr;
656
657         if(!(csr32r(ctlr, Mhc) & Is))
658                 return;
659         cycles(&tsc0);
660
661         ctlr->interrupts++;
662         csr32w(ctlr, Hi, 1);
663
664         ie = 0;
665         work = 0;
666         while(ie < 2){
667                 if(ctlr->rrrci != ctlr->rrrpi[0]){
668                         ga620receive(edev);
669                         work = 1;
670                 }
671
672                 if(_ga620transmit(edev) != 0)
673                         work = 1;
674
675                 csr = csr32r(ctlr, Eci);
676                 if(csr != ctlr->epi[0]){
677                         ga620event(edev, csr, ctlr->epi[0]);
678                         work = 1;
679                 }
680
681                 if(ctlr->nrsr <= NrsrLO)
682                         ga620replenish(ctlr);
683                 if(work == 0){
684                         if(ie == 0)
685                                 csr32w(ctlr, Hi, 0);
686                         ie++;
687                 }
688                 work = 0;
689         }
690
691         cycles(&tsc1);
692         ctlr->ticks += tsc1-tsc0;
693 }
694
695 static void
696 ga620lmw(Ctlr* ctlr, int addr, int* data, int len)
697 {
698         int i, l, lmw, v;
699
700         /*
701          * Write to or clear ('data' == nil) 'len' bytes of the NIC
702          * local memory at address 'addr'.
703          * The destination address and count should be 32-bit aligned.
704          */
705         v = 0;
706         while(len > 0){
707                 /*
708                  * 1) Set the window. The (Lmwsz-1) bits are ignored
709                  *    in Wba when accessing through the local memory window;
710                  * 2) Find the minimum of how many bytes still to
711                  *    transfer and how many left in this window;
712                  * 3) Create the offset into the local memory window in the
713                  *    shared memory space then copy (or zero) the data;
714                  * 4) Bump the counts.
715                  */
716                 csr32w(ctlr, Wba, addr);
717
718                 l = ROUNDUP(addr+1, Lmwsz) - addr;
719                 if(l > len)
720                         l = len;
721
722                 lmw = Lmw + (addr & (Lmwsz-1));
723                 for(i = 0; i < l; i += 4){
724                         if(data != nil)
725                                 v = *data++;
726                         csr32w(ctlr, lmw+i, v);
727                 }
728
729                 len -= l;
730                 addr += l;
731         }
732 }
733
734 static int
735 ga620init(Ether* edev)
736 {
737         Ctlr *ctlr;
738         Host64 host64;
739         int csr, ea, i, flags;
740
741         ctlr = edev->ctlr;
742
743         /*
744          * Load the MAC address.
745          */
746         ea = edev->ea[0]<<8 | edev->ea[1];
747         csr32w(ctlr, Mac, ea);
748         ea = edev->ea[2]<<24 | edev->ea[3]<<16 | edev->ea[4]<<8 | edev->ea[5];
749         csr32w(ctlr, Mac+4, ea);
750
751         /*
752          * General Information Block.
753          */
754         ctlr->gib = malloc(sizeof(Gib));
755         sethost64(&host64, ctlr->gib);
756         csr32w(ctlr, Gip, host64.hi);
757         csr32w(ctlr, Gip+4, host64.lo);
758
759         /*
760          * Event Ring.
761          * This is located in host memory. Allocate the ring,
762          * tell the NIC where it is and initialise the indices.
763          */
764         ctlr->er = malign(sizeof(Ere)*Ner);
765         sethost64(&ctlr->gib->ercb.addr, ctlr->er);
766         sethost64(&ctlr->gib->epp, ctlr->epi);
767         csr32w(ctlr, Eci, 0);
768
769         /*
770          * Command Ring.
771          * This is located in the General Communications Region
772          * and so the value placed in the Rcb is unused, the NIC
773          * knows where it is. Stick in the value according to
774          * the datasheet anyway.
775          * Initialise the ring and indices.
776          */
777         ctlr->gib->crcb.addr.lo = Cr-0x400;
778         for(i = 0; i < Ncr*4; i += 4)
779                 csr32w(ctlr, Cr+i, 0);
780         csr32w(ctlr, Cpi, 0);
781         csr32w(ctlr, Cci, 0);
782
783         /*
784          * Send Ring.
785          * This ring is either in NIC memory at a fixed location depending
786          * on how big the ring is or it is in host memory. If in NIC
787          * memory it is accessed via the Local Memory Window; with a send
788          * ring size of 128 the window covers the whole ring and then need
789          * only be set once:
790          *      ctlr->sr = (uchar*)ctlr->nic+Lmw;
791          *      ga620lmw(ctlr, Sr, nil, sizeof(Sbd)*Nsr);
792          *      ctlr->gib->srcb.addr.lo = Sr;
793          * There is nowhere in the Sbd to hold the Block* associated
794          * with this entry so an external array must be kept.
795          */
796         ctlr->sr = malign(sizeof(Sbd)*Nsr);
797         sethost64(&ctlr->gib->srcb.addr, ctlr->sr);
798         if(ctlr->hardwarecksum)
799                 flags = TcpUdpCksum|NoPseudoHdrCksum|HostRing;
800         else 
801                 flags = HostRing;
802         if(ctlr->coalupdateonly) 
803                 flags |= CoalUpdateOnly;
804         ctlr->gib->srcb.control = Nsr<<16 | flags;
805         sethost64(&ctlr->gib->scp, ctlr->sci);
806         csr32w(ctlr, Spi, 0);
807         ctlr->srb = malloc(sizeof(Block*)*Nsr);
808
809         /*
810          * Receive Standard Ring.
811          */
812         ctlr->rsr = malign(sizeof(Rbd)*Nrsr);
813         sethost64(&ctlr->gib->rsrcb.addr, ctlr->rsr);
814         if(ctlr->hardwarecksum)
815                 flags = TcpUdpCksum|NoPseudoHdrCksum;
816         else
817                 flags = 0;
818         ctlr->gib->rsrcb.control = (ETHERMAXTU+4)<<16 | flags;
819         csr32w(ctlr, Rspi, 0);
820
821         /*
822          * Jumbo and Mini Rings. Unused for now.
823          */
824         ctlr->gib->rjrcb.control = RingDisabled;
825         ctlr->gib->rmrcb.control = RingDisabled;
826
827         /*
828          * Receive Return Ring.
829          * This is located in host memory. Allocate the ring,
830          * tell the NIC where it is and initialise the indices.
831          */
832         ctlr->rrr = malign(sizeof(Rbd)*Nrrr);
833         sethost64(&ctlr->gib->rrrcb.addr, ctlr->rrr);
834         ctlr->gib->rrrcb.control = Nrrr<<16 | 0;
835         sethost64(&ctlr->gib->rrrpp, ctlr->rrrpi);
836         ctlr->rrrci = 0;
837
838         /*
839          * Refresh Stats Pointer.
840          * For now just point it at the existing statistics block.
841          */
842         sethost64(&ctlr->gib->rsp, ctlr->gib->statistics);
843
844         /*
845          * DMA configuration.
846          * Use the recommended values.
847          */
848         csr32w(ctlr, DMArc, 0x80);
849         csr32w(ctlr, DMAwc, 0x80);
850
851         /*
852          * Transmit Buffer Ratio.
853          * Set to 1/3 of available buffer space (units are 1/64ths)
854          * if using Jumbo packets, ~64KB otherwise (assume 1MB on NIC).
855          */
856         if(NrjrHI > 0 || Nsr > 128)
857                 csr32w(ctlr, Tbr, 64/3);
858         else
859                 csr32w(ctlr, Tbr, 4);
860
861         /*
862          * Tuneable parameters.
863          * These defaults are based on the tuning hints in the Alteon
864          * Host/NIC Software Interface Definition and example software.
865          */
866         ctlr->rct = 1/*100*/;
867         csr32w(ctlr, Rct, ctlr->rct);
868         ctlr->sct = 0;
869         csr32w(ctlr, Sct, ctlr->sct);
870         ctlr->st = 1000000;
871         csr32w(ctlr, St, ctlr->st);
872         ctlr->smcbd = Nsr/4;
873         csr32w(ctlr, SmcBD, ctlr->smcbd);
874         ctlr->rmcbd = 4/*6*/;
875         csr32w(ctlr, RmcBD, ctlr->rmcbd);
876
877         /*
878          * Enable DMA Assist Logic.
879          */
880         csr = csr32r(ctlr, DMAas) & ~0x03;
881         csr32w(ctlr, DMAas, csr|0x01);
882
883         /*
884          * Link negotiation.
885          * The bits are set here but the NIC must be given a command
886          * once it is running to set negotiation in motion.
887          */
888         csr32w(ctlr, Gln, Le|Lean|Lofc|Lfd|L1000MB|Lpref);
889         csr32w(ctlr, Fln, Le|Lean|Lhd|Lfd|L100MB|L10MB);
890
891         /*
892          * A unique index for this controller and the maximum packet
893          * length expected.
894          * For now only standard packets are expected.
895          */
896         csr32w(ctlr, Ifx, 1);
897         csr32w(ctlr, IfMTU, ETHERMAXTU+4);
898
899         /*
900          * Enable Interrupts.
901          * There are 3 ways to mask interrupts - a bit in the Mhc (which
902          * is already cleared), the Mi register and the Hi mailbox.
903          * Writing to the Hi mailbox has the side-effect of clearing the
904          * PCI interrupt.
905          */
906         csr32w(ctlr, Mi, 0);
907         csr32w(ctlr, Hi, 0);
908
909         /*
910          * Start the firmware.
911          */
912         csr32w(ctlr, CPUApc, tigon2FwStartAddr);
913         csr = csr32r(ctlr, CPUAstate) & ~CPUhalt;
914         csr32w(ctlr, CPUAstate, csr);
915
916         return 0;
917 }
918
919 static int
920 at24c32io(Ctlr* ctlr, char* op, int data)
921 {
922         char *lp, *p;
923         int i, loop, mlc, r;
924
925         mlc = csr32r(ctlr, Mlc);
926
927         r = 0;
928         loop = -1;
929         lp = nil;
930         for(p = op; *p != '\0'; p++){
931                 switch(*p){
932                 default:
933                         return -1;
934                 case ' ':
935                         continue;
936                 case ':':                       /* start of 8-bit loop */
937                         if(lp != nil)
938                                 return -1;
939                         lp = p;
940                         loop = 7;
941                         continue;
942                 case ';':                       /* end of 8-bit loop */
943                         if(lp == nil)
944                                 return -1;
945                         loop--;
946                         if(loop >= 0)
947                                 p = lp;
948                         else
949                                 lp = nil;
950                         continue;
951                 case 'C':                       /* assert clock */
952                         mlc |= EEclk;
953                         break;
954                 case 'c':                       /* deassert clock */
955                         mlc &= ~EEclk;
956                         break;
957                 case 'D':                       /* next bit in 'data' byte */
958                         if(loop < 0)
959                                 return -1;
960                         if(data & (1<<loop))
961                                 mlc |= EEdo;
962                         else
963                                 mlc &= ~EEdo;
964                         break;
965                 case 'E':                       /* enable data output */
966                         mlc |= EEdoe;
967                         break;
968                 case 'e':                       /* disable data output */
969                         mlc &= ~EEdoe;
970                         break;
971                 case 'I':                       /* input bit */
972                         i = (csr32r(ctlr, Mlc) & EEdi) != 0;
973                         if(loop >= 0)
974                                 r |= (i<<loop);
975                         else
976                                 r = i;
977                         continue;
978                 case 'O':                       /* assert data output */
979                         mlc |= EEdo;
980                         break;
981                 case 'o':                       /* deassert data output */
982                         mlc &= ~EEdo;
983                         break;
984                 }
985                 csr32w(ctlr, Mlc, mlc);
986                 microdelay(1);
987         }
988         if(loop >= 0)
989                 return -1;
990         return r;
991 }
992
993 static int
994 at24c32r(Ctlr* ctlr, int addr)
995 {
996         int data;
997
998         /*
999          * Read a byte at address 'addr' from the Atmel AT24C32
1000          * Serial EEPROM. The 2-wire EEPROM access is controlled
1001          * by 4 bits in Mlc. See the AT24C32 datasheet for
1002          * protocol details.
1003          */
1004         /*
1005          * Start condition - a high to low transition of data
1006          * with the clock high must precede any other command.
1007          */
1008         at24c32io(ctlr, "OECoc", 0);
1009
1010         /*
1011          * Perform a random read at 'addr'. A dummy byte
1012          * write sequence is performed to clock in the device
1013          * and data word addresses (0 and 'addr' respectively).
1014          */
1015         data = -1;
1016         if(at24c32io(ctlr, "oE :DCc; oeCIc", 0xA0) != 0)
1017                 goto stop;
1018         if(at24c32io(ctlr, "oE :DCc; oeCIc", addr>>8) != 0)
1019                 goto stop;
1020         if(at24c32io(ctlr, "oE :DCc; oeCIc", addr) != 0)
1021                 goto stop;
1022
1023         /*
1024          * Now send another start condition followed by a
1025          * request to read the device. The EEPROM responds
1026          * by clocking out the data.
1027          */
1028         at24c32io(ctlr, "OECoc", 0);
1029         if(at24c32io(ctlr, "oE :DCc; oeCIc", 0xA1) != 0)
1030                 goto stop;
1031         data = at24c32io(ctlr, ":CIc;", 0xA1);
1032
1033 stop:
1034         /*
1035          * Stop condition - a low to high transition of data
1036          * with the clock high is a stop condition. After a read
1037          * sequence, the stop command will place the EEPROM in
1038          * a standby power mode.
1039          */
1040         at24c32io(ctlr, "oECOc", 0);
1041
1042         return data;
1043 }
1044
1045 static int
1046 ga620detach(Ctlr* ctlr)
1047 {
1048         int timeo;
1049
1050         /*
1051          * Hard reset (don't know which endian so catch both);
1052          * enable for little-endian mode;
1053          * wait for code to be loaded from serial EEPROM or flash;
1054          * make sure CPU A is halted.
1055          */
1056         csr32w(ctlr, Mhc, Hr<<24 | Hr);
1057         csr32w(ctlr, Mhc, (Eews|Ci)<<24 | Eews|Ci);
1058
1059         microdelay(1);
1060         for(timeo = 0; timeo < 500000; timeo++){
1061                 if((csr32r(ctlr, CPUAstate) & (CPUhie|CPUrf)) == CPUhie)
1062                         break;
1063                 microdelay(1);
1064         }
1065         if((csr32r(ctlr, CPUAstate) & (CPUhie|CPUrf)) != CPUhie)
1066                 return -1;
1067         csr32w(ctlr, CPUAstate, CPUhalt);
1068
1069         /*
1070          * After reset, CPU B seems to be stuck in 'CPUrf'.
1071          * Worry about it later.
1072          */
1073         csr32w(ctlr, CPUBstate, CPUhalt);
1074
1075         return 0;
1076 }
1077
1078 static void
1079 ga620shutdown(Ether* ether)
1080 {
1081 print("ga620shutdown\n");
1082         ga620detach(ether->ctlr);
1083 }
1084
1085 static int
1086 ga620reset(Ctlr* ctlr)
1087 {
1088         int cls, csr, i, r;
1089
1090         if(ga620detach(ctlr) < 0)
1091                 return -1;
1092
1093         /*
1094          * Tigon 2 PCI NICs have 512KB SRAM per bank.
1095          * Clear out any lingering serial EEPROM state
1096          * bits.
1097          */
1098         csr = csr32r(ctlr, Mlc) & ~(EEdi|EEdo|EEdoe|EEclk|SRAMmask);
1099         csr32w(ctlr, Mlc, SRAM512|csr);
1100         csr = csr32r(ctlr, Mc);
1101         csr32w(ctlr, Mc, SyncSRAM|csr);
1102
1103         /*
1104          * Initialise PCI State register.
1105          * If PCI Write-and-Invalidate is enabled set the max write DMA
1106          * value to the host cache-line size (32 on Pentium or later).
1107          */
1108         csr = csr32r(ctlr, Ps) & (PCI32|PCI66);
1109         csr |= PCIwcmd|PCIrcmd|PCImrm;
1110         if(ctlr->pcidev->pcr & 0x0010){
1111                 cls = pcicfgr8(ctlr->pcidev, PciCLS) * 4;
1112                 if(cls != 32)
1113                         pcicfgw8(ctlr->pcidev, PciCLS, 32/4);
1114                 csr |= PCIwm32;
1115         }
1116         csr32w(ctlr, Ps, csr);
1117
1118         /*
1119          * Operating Mode.
1120          */
1121         csr32w(ctlr, Om, Fatal|NoJFrag|BswapDMA|WswapBD);
1122
1123         /*
1124          * Snarf the MAC address from the serial EEPROM.
1125          */
1126         for(i = 0; i < Eaddrlen; i++){
1127                 if((r = at24c32r(ctlr, 0x8E+i)) == -1)
1128                         return -1;
1129                 ctlr->ea[i] = r;
1130         }
1131
1132         /*
1133          * Load the firmware.
1134          */
1135         ga620lmw(ctlr, tigon2FwTextAddr, tigon2FwText, tigon2FwTextLen);
1136         ga620lmw(ctlr, tigon2FwRodataAddr, tigon2FwRodata, tigon2FwRodataLen);
1137         ga620lmw(ctlr, tigon2FwDataAddr, tigon2FwData, tigon2FwDataLen);
1138         ga620lmw(ctlr, tigon2FwSbssAddr, nil, tigon2FwSbssLen);
1139         ga620lmw(ctlr, tigon2FwBssAddr, nil, tigon2FwBssLen);
1140
1141         return 0;
1142 }
1143
1144 static void
1145 ga620pci(void)
1146 {
1147         void *mem;
1148         Pcidev *p;
1149         Ctlr *ctlr;
1150
1151         p = nil;
1152         while(p = pcimatch(p, 0, 0)){
1153                 if(p->ccrb != 0x02 || p->ccru != 0)
1154                         continue;
1155                 if(p->mem[0].bar & 1)
1156                         continue;
1157
1158                 switch(p->did<<16 | p->vid){
1159                 default:
1160                         continue;
1161                 case 0x620A<<16 | 0x1385:       /* Netgear GA620 fiber */
1162                 case 0x630A<<16 | 0x1385:       /* Netgear GA620T copper */
1163                 case 0x0001<<16 | 0x12AE:       /* Alteon Acenic fiber
1164                                                  * and DEC DEGPA-SA */
1165                 case 0x0002<<16 | 0x12AE:       /* Alteon Acenic copper */
1166                 case 0x0009<<16 | 0x10A9:       /* SGI Acenic */
1167                         break;
1168                 }
1169
1170                 mem = vmap(p->mem[0].bar & ~0xF, p->mem[0].size);
1171                 if(mem == nil){
1172                         print("ga620: can't map %llux\n", p->mem[0].bar & ~0xF);
1173                         continue;
1174                 }
1175
1176                 ctlr = malloc(sizeof(Ctlr));
1177                 if(ctlr == nil){
1178                         print("ga620: can't allocate memory\n");
1179                         continue;
1180                 }
1181                 ctlr->port = p->mem[0].bar & ~0xF;
1182                 ctlr->pcidev = p;
1183                 pcienable(p);
1184
1185                 ctlr->id = p->did<<16 | p->vid;
1186
1187                 ctlr->nic = mem;
1188                 if(ga620reset(ctlr)){
1189                         free(ctlr);
1190                         continue;
1191                 }
1192                 pcisetbme(p);
1193
1194                 if(ctlrhead != nil)
1195                         ctlrtail->next = ctlr;
1196                 else
1197                         ctlrhead = ctlr;
1198                 ctlrtail = ctlr;
1199         }
1200 }
1201
1202 static void
1203 ga620promiscuous(void *arg, int on)
1204 {
1205         Ether *ether = arg;
1206
1207         /* 3rd arg: 1 enables, 2 disables */
1208         ga620command(ether->ctlr, 0xa, (on? 1: 2), 0);
1209 }
1210
1211 static void
1212 ga620multicast(void *arg, uchar *addr, int add)
1213 {
1214         Ether *ether = arg;
1215
1216         USED(addr);
1217         if (add)
1218                 ga620command(ether->ctlr, 0xe, 1, 0);   /* 1 == enable */
1219 }
1220
1221 static int
1222 ga620pnp(Ether* edev)
1223 {
1224         Ctlr *ctlr;
1225         uchar ea[Eaddrlen];
1226
1227         if(ctlrhead == nil)
1228                 ga620pci();
1229
1230         /*
1231          * Any adapter matches if no edev->port is supplied,
1232          * otherwise the ports must match.
1233          */
1234         for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
1235                 if(ctlr->active)
1236                         continue;
1237                 if(edev->port == 0 || edev->port == ctlr->port){
1238                         ctlr->active = 1;
1239                         break;
1240                 }
1241         }
1242         if(ctlr == nil)
1243                 return -1;
1244
1245         edev->ctlr = ctlr;
1246         edev->port = ctlr->port;
1247         edev->irq = ctlr->pcidev->intl;
1248         edev->tbdf = ctlr->pcidev->tbdf;
1249         edev->mbps = 1000;              /* placeholder */
1250
1251         /*
1252          * Check if the adapter's station address is to be overridden.
1253          * If not, read it from the EEPROM and set in ether->ea prior to
1254          * loading the station address in the hardware.
1255          */
1256         memset(ea, 0, Eaddrlen);
1257         if(memcmp(ea, edev->ea, Eaddrlen) == 0)
1258                 memmove(edev->ea, ctlr->ea, Eaddrlen);
1259
1260         ga620init(edev);
1261
1262         /*
1263          * Linkage to the generic ethernet driver.
1264          */
1265         edev->attach = ga620attach;
1266         edev->transmit = ga620transmit;
1267         edev->ifstat = ga620ifstat;
1268         edev->ctl = ga620ctl;
1269
1270         edev->arg = edev;
1271         edev->promiscuous = ga620promiscuous;
1272         edev->multicast = ga620multicast;
1273         edev->shutdown = ga620shutdown;
1274
1275         intrenable(edev->irq, ga620interrupt, edev, edev->tbdf, edev->name);
1276
1277         return 0;
1278 }
1279
1280 void
1281 etherga620link(void)
1282 {
1283         addethercard("GA620", ga620pnp);
1284 }