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