2 * Netgear GA620 Gigabit Ethernet Card.
3 * Specific for the Alteon Tigon 2 and Intel Pentium or later.
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?
14 #include "../port/lib.h"
19 #include "../port/error.h"
20 #include "../port/netif.h"
21 #include "../port/etherif.h"
23 #define malign(n) xspanalloc((n), 32, 0)
24 #include "etherga620fw.h"
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 */
34 DMAas = 0x011C, /* DMA Assist State */
36 CPUAstate = 0x0140, /* CPU A State */
37 CPUApc = 0x0144, /* CPU A Programme Counter */
39 CPUBstate = 0x0240, /* CPU B State */
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 */
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 */
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 */
71 Cr = 0x0700, /* Command Ring */
73 Lmw = 0x0800, /* Local Memory Window */
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 */
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 */
95 SyncSRAM = 0x00100000, /* Set Synchronous SRAM Timing */
99 PCIwm32 = 0x000000C0, /* Write Max DMA 32 */
100 PCImrm = 0x00020000, /* Use Memory Read Multiple Command */
103 PCIrcmd = 0x06000000, /* PCI Read Command */
104 PCIwcmd = 0x70000000, /* PCI Write Command */
107 enum { /* CPUAstate */
108 CPUrf = 0x00000010, /* ROM Fail */
109 CPUhalt = 0x00010000, /* Halt the internal CPU */
110 CPUhie = 0x00040000, /* HALT instruction executed */
114 BswapBD = 0x00000002, /* Byte Swap Buffer Descriptors */
115 WswapBD = 0x00000004, /* Word Swap Buffer Descriptors */
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 */
124 Lmwsz = 2*1024, /* Local Memory Window Size */
127 * legal values are 0x3800 iff Nsr is 128, 0x3000 iff Nsr is 256,
128 * or 0x2000 iff Nsr is 512.
130 Sr = 0x2000, /* Send Ring (accessed via Lmw) */
134 Lpref = 0x00008000, /* Preferred Link */
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 */
146 typedef struct Host64 {
151 typedef struct Ere { /* Event Ring Element */
152 int event; /* event<<24 | code<<12 | index */
156 typedef int Cmd; /* cmd<<24 | flags<<12 | index */
158 typedef struct Rbd { /* Receive Buffer Descriptor */
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 */
165 void* opaque; /* passed to receive return ring */
168 typedef struct Sbd { /* Send Buffer Descriptor */
170 int lenflags; /* len<<16 | flags */
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 */
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 */
196 typedef struct Rcb { /* Ring Control Block */
197 Host64 addr; /* points to the Rbd ring */
198 int control; /* max_len<<16 | flags */
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 */
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 */
230 * these sizes are all fixed in the card,
231 * except for Nsr, which has only 3 valid sizes.
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 */
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 */
252 typedef struct Ctlr Ctlr;
270 int nsr; /* currently in send ring */
273 int nrsr; /* currently in Receive Standard Ring */
275 int nrjr; /* currently in Receive Jumbo Ring */
277 int nrmr; /* currently in Receive Mini Ring */
279 int rrrci; /* Receive Return Ring Consumer Index */
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) */
285 int interrupts; /* statistics */
289 int coalupdateonly; /* tuning */
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 */
298 static Ctlr* ctlrhead;
299 static Ctlr* ctlrtail;
301 #define csr32r(c, r) (*((c)->nic+((r)/4)))
302 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
305 sethost64(Host64* host64, void* addr)
309 uvl = PCIWADDR(addr);
310 host64->hi = uvl>>32;
311 host64->lo = uvl & 0xFFFFFFFFL;
315 ga620command(Ctlr* ctlr, int cmd, int flags, int index)
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);
326 ga620attach(Ether* edev)
335 ga620ifstat(Ether* edev, void* a, long n, ulong offset)
345 p = smalloc(READSTR);
347 for(i = 0; i < 256; i++){
348 if((r = ctlr->gib->statistics[i]) == 0)
350 l += snprint(p+l, READSTR-l, "%d: %ud\n", i, r);
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);
363 n = readstr(offset, a, n, p);
370 ga620ctl(Ether* edev, void* buf, long n)
381 cb = parsecmd(buf, n);
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;
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;
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;
406 control = ctlr->gib->rsrcb.control;
407 control &= ~(TcpUdpCksum|NoPseudoHdrCksum);
408 ctlr->gib->rsrcb.control = control;
410 ctlr->hardwarecksum = 0;
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;
417 control = ctlr->gib->rsrcb.control;
418 control |= (TcpUdpCksum|NoPseudoHdrCksum);
419 ctlr->gib->rsrcb.control = control;
421 ctlr->hardwarecksum = 1;
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])
432 csr32w(ctlr, Rct, ctlr->rct);
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])
441 csr32w(ctlr, Sct, ctlr->sct);
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])
450 csr32w(ctlr, St, ctlr->st);
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])
459 csr32w(ctlr, SmcBD, ctlr->smcbd);
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])
468 csr32w(ctlr, RmcBD, ctlr->rmcbd);
481 _ga620transmit(Ether* edev)
489 * For now there are no smarts here, just empty the
490 * ring and try to fill it back up. Tuning comes later.
493 ilock(&ctlr->srlock);
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.
502 for(sci = ctlr->sci[2]; sci != ctlr->sci[0]; sci = NEXT(sci, Nsr)){
503 if(ctlr->srb[sci] == nil)
505 freeb(ctlr->srb[sci]);
506 ctlr->srb[sci] = nil;
511 sci = PREV(sci, Nsr);
512 for(spi = csr32r(ctlr, Spi); spi != sci; spi = NEXT(spi, Nsr)){
513 if((bp = qget(edev->oq)) == nil)
516 sbd = &ctlr->sr[spi];
517 sethost64(&sbd->addr, bp->rp);
518 sbd->lenflags = BLEN(bp)<<16 | Fend;
523 csr32w(ctlr, Spi, spi);
525 iunlock(&ctlr->srlock);
531 ga620transmit(Ether* edev)
533 _ga620transmit(edev);
537 ga620replenish(Ctlr* ctlr)
543 rspi = csr32r(ctlr, Rspi);
544 while(ctlr->nrsr < NrsrHI){
545 if((bp = iallocb(ETHERMAXTU+4)) == nil)
547 rbd = &ctlr->rsr[rspi];
548 sethost64(&rbd->addr, bp->rp);
549 rbd->indexlen = rspi<<16 | (ETHERMAXTU+4);
553 rspi = NEXT(rspi, Nrsr);
556 csr32w(ctlr, Rspi, rspi);
560 ga620event(Ether *edev, int eci, int epi)
562 unsigned event, code;
567 event = ctlr->er[eci].event;
568 code = (event >> 12) & ((1<<12)-1);
570 case 0x01: /* firmware operational */
571 /* host stack (us) is up. 3rd arg of 2 means down. */
572 ga620command(ctlr, 0x01, 0x01, 0x00);
574 * link negotiation: any speed is okay.
575 * 3rd arg of 1 selects gigabit only; 2 10/100 only.
577 ga620command(ctlr, 0x0B, 0x00, 0x00);
578 print("#l%d: ga620: port %8.8lluX: firmware is up\n",
579 edev->ctlrno, ctlr->port);
581 case 0x04: /* statistics updated */
583 case 0x06: /* link state changed */
589 print("#l%d: link down\n", edev->ctlrno);
592 edev->mbps = 100; /* it's 10 or 100 */
596 print("#l%d: %dMbps link up\n",
597 edev->ctlrno, edev->mbps);
599 case 0x07: /* event error */
601 print("#l%d: ga620: er[%d] = %8.8uX\n", edev->ctlrno,
605 eci = NEXT(eci, Ner);
607 csr32w(ctlr, Eci, eci);
611 ga620receive(Ether* edev)
619 while(ctlr->rrrci != ctlr->rrrpi[0]){
620 rbd = &ctlr->rrr[ctlr->rrrci];
622 * Errors are collected in the statistics block so
623 * no need to tally them here, let ifstat do the work.
625 len = rbd->indexlen & 0xFFFF;
626 if(!(rbd->flags & Ferror) && len != 0){
635 if(rbd->flags & Frjr)
637 else if(rbd->flags & Frmr)
642 ctlr->rrrci = NEXT(ctlr->rrrci, Nrrr);
647 ga620interrupt(Ureg*, void* arg)
657 if(!(csr32r(ctlr, Mhc) & Is))
667 if(ctlr->rrrci != ctlr->rrrpi[0]){
672 if(_ga620transmit(edev) != 0)
675 csr = csr32r(ctlr, Eci);
676 if(csr != ctlr->epi[0]){
677 ga620event(edev, csr, ctlr->epi[0]);
681 if(ctlr->nrsr <= NrsrLO)
682 ga620replenish(ctlr);
692 ctlr->ticks += tsc1-tsc0;
696 ga620lmw(Ctlr* ctlr, int addr, int* data, int len)
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.
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.
716 csr32w(ctlr, Wba, addr);
718 l = ROUNDUP(addr+1, Lmwsz) - addr;
722 lmw = Lmw + (addr & (Lmwsz-1));
723 for(i = 0; i < l; i += 4){
726 csr32w(ctlr, lmw+i, v);
735 ga620init(Ether* edev)
739 int csr, ea, i, flags;
744 * Load the MAC address.
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);
752 * General Information Block.
754 ctlr->gib = malloc(sizeof(Gib));
755 sethost64(&host64, ctlr->gib);
756 csr32w(ctlr, Gip, host64.hi);
757 csr32w(ctlr, Gip+4, host64.lo);
761 * This is located in host memory. Allocate the ring,
762 * tell the NIC where it is and initialise the indices.
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);
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.
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);
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
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.
796 ctlr->sr = malign(sizeof(Sbd)*Nsr);
797 sethost64(&ctlr->gib->srcb.addr, ctlr->sr);
798 if(ctlr->hardwarecksum)
799 flags = TcpUdpCksum|NoPseudoHdrCksum|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);
810 * Receive Standard Ring.
812 ctlr->rsr = malign(sizeof(Rbd)*Nrsr);
813 sethost64(&ctlr->gib->rsrcb.addr, ctlr->rsr);
814 if(ctlr->hardwarecksum)
815 flags = TcpUdpCksum|NoPseudoHdrCksum;
818 ctlr->gib->rsrcb.control = (ETHERMAXTU+4)<<16 | flags;
819 csr32w(ctlr, Rspi, 0);
822 * Jumbo and Mini Rings. Unused for now.
824 ctlr->gib->rjrcb.control = RingDisabled;
825 ctlr->gib->rmrcb.control = RingDisabled;
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.
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);
839 * Refresh Stats Pointer.
840 * For now just point it at the existing statistics block.
842 sethost64(&ctlr->gib->rsp, ctlr->gib->statistics);
846 * Use the recommended values.
848 csr32w(ctlr, DMArc, 0x80);
849 csr32w(ctlr, DMAwc, 0x80);
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).
856 if(NrjrHI > 0 || Nsr > 128)
857 csr32w(ctlr, Tbr, 64/3);
859 csr32w(ctlr, Tbr, 4);
862 * Tuneable parameters.
863 * These defaults are based on the tuning hints in the Alteon
864 * Host/NIC Software Interface Definition and example software.
866 ctlr->rct = 1/*100*/;
867 csr32w(ctlr, Rct, ctlr->rct);
869 csr32w(ctlr, Sct, ctlr->sct);
871 csr32w(ctlr, St, ctlr->st);
873 csr32w(ctlr, SmcBD, ctlr->smcbd);
874 ctlr->rmcbd = 4/*6*/;
875 csr32w(ctlr, RmcBD, ctlr->rmcbd);
878 * Enable DMA Assist Logic.
880 csr = csr32r(ctlr, DMAas) & ~0x03;
881 csr32w(ctlr, DMAas, csr|0x01);
885 * The bits are set here but the NIC must be given a command
886 * once it is running to set negotiation in motion.
888 csr32w(ctlr, Gln, Le|Lean|Lofc|Lfd|L1000MB|Lpref);
889 csr32w(ctlr, Fln, Le|Lean|Lhd|Lfd|L100MB|L10MB);
892 * A unique index for this controller and the maximum packet
894 * For now only standard packets are expected.
896 csr32w(ctlr, Ifx, 1);
897 csr32w(ctlr, IfMTU, ETHERMAXTU+4);
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
910 * Start the firmware.
912 csr32w(ctlr, CPUApc, tigon2FwStartAddr);
913 csr = csr32r(ctlr, CPUAstate) & ~CPUhalt;
914 csr32w(ctlr, CPUAstate, csr);
920 at24c32io(Ctlr* ctlr, char* op, int data)
925 mlc = csr32r(ctlr, Mlc);
930 for(p = op; *p != '\0'; p++){
936 case ':': /* start of 8-bit loop */
942 case ';': /* end of 8-bit loop */
951 case 'C': /* assert clock */
954 case 'c': /* deassert clock */
957 case 'D': /* next bit in 'data' byte */
965 case 'E': /* enable data output */
968 case 'e': /* disable data output */
971 case 'I': /* input bit */
972 i = (csr32r(ctlr, Mlc) & EEdi) != 0;
978 case 'O': /* assert data output */
981 case 'o': /* deassert data output */
985 csr32w(ctlr, Mlc, mlc);
994 at24c32r(Ctlr* ctlr, int addr)
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
1005 * Start condition - a high to low transition of data
1006 * with the clock high must precede any other command.
1008 at24c32io(ctlr, "OECoc", 0);
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).
1016 if(at24c32io(ctlr, "oE :DCc; oeCIc", 0xA0) != 0)
1018 if(at24c32io(ctlr, "oE :DCc; oeCIc", addr>>8) != 0)
1020 if(at24c32io(ctlr, "oE :DCc; oeCIc", addr) != 0)
1024 * Now send another start condition followed by a
1025 * request to read the device. The EEPROM responds
1026 * by clocking out the data.
1028 at24c32io(ctlr, "OECoc", 0);
1029 if(at24c32io(ctlr, "oE :DCc; oeCIc", 0xA1) != 0)
1031 data = at24c32io(ctlr, ":CIc;", 0xA1);
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.
1040 at24c32io(ctlr, "oECOc", 0);
1046 ga620detach(Ctlr* ctlr)
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.
1056 csr32w(ctlr, Mhc, Hr<<24 | Hr);
1057 csr32w(ctlr, Mhc, (Eews|Ci)<<24 | Eews|Ci);
1060 for(timeo = 0; timeo < 500000; timeo++){
1061 if((csr32r(ctlr, CPUAstate) & (CPUhie|CPUrf)) == CPUhie)
1065 if((csr32r(ctlr, CPUAstate) & (CPUhie|CPUrf)) != CPUhie)
1067 csr32w(ctlr, CPUAstate, CPUhalt);
1070 * After reset, CPU B seems to be stuck in 'CPUrf'.
1071 * Worry about it later.
1073 csr32w(ctlr, CPUBstate, CPUhalt);
1079 ga620shutdown(Ether* ether)
1081 print("ga620shutdown\n");
1082 ga620detach(ether->ctlr);
1086 ga620reset(Ctlr* ctlr)
1090 if(ga620detach(ctlr) < 0)
1094 * Tigon 2 PCI NICs have 512KB SRAM per bank.
1095 * Clear out any lingering serial EEPROM state
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);
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).
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;
1113 pcicfgw8(ctlr->pcidev, PciCLS, 32/4);
1116 csr32w(ctlr, Ps, csr);
1121 csr32w(ctlr, Om, Fatal|NoJFrag|BswapDMA|WswapBD);
1124 * Snarf the MAC address from the serial EEPROM.
1126 for(i = 0; i < Eaddrlen; i++){
1127 if((r = at24c32r(ctlr, 0x8E+i)) == -1)
1133 * Load the firmware.
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);
1152 while(p = pcimatch(p, 0, 0)){
1153 if(p->ccrb != 0x02 || p->ccru != 0)
1155 if(p->mem[0].bar & 1)
1158 switch(p->did<<16 | p->vid){
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 */
1170 mem = vmap(p->mem[0].bar & ~0xF, p->mem[0].size);
1172 print("ga620: can't map %llux\n", p->mem[0].bar & ~0xF);
1176 ctlr = malloc(sizeof(Ctlr));
1178 print("ga620: can't allocate memory\n");
1181 ctlr->port = p->mem[0].bar & ~0xF;
1185 ctlr->id = p->did<<16 | p->vid;
1188 if(ga620reset(ctlr)){
1195 ctlrtail->next = ctlr;
1203 ga620promiscuous(void *arg, int on)
1207 /* 3rd arg: 1 enables, 2 disables */
1208 ga620command(ether->ctlr, 0xa, (on? 1: 2), 0);
1212 ga620multicast(void *arg, uchar *addr, int add)
1218 ga620command(ether->ctlr, 0xe, 1, 0); /* 1 == enable */
1222 ga620pnp(Ether* edev)
1231 * Any adapter matches if no edev->port is supplied,
1232 * otherwise the ports must match.
1234 for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
1237 if(edev->port == 0 || edev->port == ctlr->port){
1246 edev->port = ctlr->port;
1247 edev->irq = ctlr->pcidev->intl;
1248 edev->tbdf = ctlr->pcidev->tbdf;
1249 edev->mbps = 1000; /* placeholder */
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.
1256 memset(ea, 0, Eaddrlen);
1257 if(memcmp(ea, edev->ea, Eaddrlen) == 0)
1258 memmove(edev->ea, ctlr->ea, Eaddrlen);
1263 * Linkage to the generic ethernet driver.
1265 edev->attach = ga620attach;
1266 edev->transmit = ga620transmit;
1267 edev->ifstat = ga620ifstat;
1268 edev->ctl = ga620ctl;
1271 edev->promiscuous = ga620promiscuous;
1272 edev->multicast = ga620multicast;
1273 edev->shutdown = ga620shutdown;
1275 intrenable(edev->irq, ga620interrupt, edev, edev->tbdf, edev->name);
1281 etherga620link(void)
1283 addethercard("GA620", ga620pnp);