2 * National Semiconductor DP83820
3 * 10/100/1000 Mb/s Ethernet Network Interface Controller
5 * Driver assumes little-endian and 32-bit host throughout.
8 #include "../port/lib.h"
13 #include "../port/error.h"
14 #include "../port/netif.h"
15 #include "../port/etherif.h"
16 #include "../port/ethermii.h"
18 enum { /* Registers */
19 Cr = 0x00, /* Command */
20 Cfg = 0x04, /* Configuration and Media Status */
21 Mear = 0x08, /* MII/EEPROM Access */
22 Ptscr = 0x0C, /* PCI Test Control */
23 Isr = 0x10, /* Interrupt Status */
24 Imr = 0x14, /* Interrupt Mask */
25 Ier = 0x18, /* Interrupt Enable */
26 Ihr = 0x1C, /* Interrupt Holdoff */
27 Txdp = 0x20, /* Transmit Descriptor Pointer */
28 Txdphi = 0x24, /* Transmit Descriptor Pointer Hi */
29 Txcfg = 0x28, /* Transmit Configuration */
30 Gpior = 0x2C, /* General Purpose I/O Control */
31 Rxdp = 0x30, /* Receive Descriptor Pointer */
32 Rxdphi = 0x34, /* Receive Descriptor Pointer Hi */
33 Rxcfg = 0x38, /* Receive Configuration */
34 Pqcr = 0x3C, /* Priority Queueing Control */
35 Wcsr = 0x40, /* Wake on LAN Control/Status */
36 Pcr = 0x44, /* Pause Control/Status */
37 Rfcr = 0x48, /* Receive Filter/Match Control */
38 Rfdr = 0x4C, /* Receive Filter/Match Data */
39 Brar = 0x50, /* Boot ROM Address */
40 Brdr = 0x54, /* Boot ROM Data */
41 Srr = 0x58, /* Silicon Revision */
42 Mibc = 0x5C, /* MIB Control */
43 Mibd = 0x60, /* MIB Data */
44 Txdp1 = 0xA0, /* Txdp Priority 1 */
45 Txdp2 = 0xA4, /* Txdp Priority 2 */
46 Txdp3 = 0xA8, /* Txdp Priority 3 */
47 Rxdp1 = 0xB0, /* Rxdp Priority 1 */
48 Rxdp2 = 0xB4, /* Rxdp Priority 2 */
49 Rxdp3 = 0xB8, /* Rxdp Priority 3 */
50 Vrcr = 0xBC, /* VLAN/IP Receive Control */
51 Vtcr = 0xC0, /* VLAN/IP Transmit Control */
52 Vdr = 0xC4, /* VLAN Data */
53 Ccsr = 0xCC, /* Clockrun Control/Status */
54 Tbicr = 0xE0, /* TBI Control */
55 Tbisr = 0xE4, /* TBI Status */
56 Tanar = 0xE8, /* TBI ANAR */
57 Tanlpar = 0xEC, /* TBI ANLPAR */
58 Taner = 0xF0, /* TBI ANER */
59 Tesr = 0xF4, /* TBI ESR */
63 Txe = 0x00000001, /* Transmit Enable */
64 Txd = 0x00000002, /* Transmit Disable */
65 Rxe = 0x00000004, /* Receiver Enable */
66 Rxd = 0x00000008, /* Receiver Disable */
67 Txr = 0x00000010, /* Transmitter Reset */
68 Rxr = 0x00000020, /* Receiver Reset */
69 Swien = 0x00000080, /* Software Interrupt Enable */
70 Rst = 0x00000100, /* Reset */
71 TxpriSHFT = 9, /* Tx Priority Queue Select */
72 TxpriMASK = 0x00001E00,
73 RxpriSHFT = 13, /* Rx Priority Queue Select */
74 RxpriMASK = 0x0001E000,
77 enum { /* Configuration and Media Status */
78 Bem = 0x00000001, /* Big Endian Mode */
79 Ext125 = 0x00000002, /* External 125MHz reference Select */
80 Bromdis = 0x00000004, /* Disable Boot ROM interface */
81 Pesel = 0x00000008, /* Parity Error Detection Action */
82 Exd = 0x00000010, /* Excessive Deferral Abort */
83 Pow = 0x00000020, /* Program Out of Window Timer */
84 Sb = 0x00000040, /* Single Back-off */
85 Reqalg = 0x00000080, /* PCI Bus Request Algorithm */
86 Extstsen = 0x00000100, /* Extended Status Enable */
87 Phydis = 0x00000200, /* Disable PHY */
88 Phyrst = 0x00000400, /* Reset PHY */
89 M64addren = 0x00000800, /* Master 64-bit Addressing Enable */
90 Data64en = 0x00001000, /* 64-bit Data Enable */
91 Pci64det = 0x00002000, /* PCI 64-bit Bus Detected */
92 T64addren = 0x00004000, /* Target 64-bit Addressing Enable */
93 Mwidis = 0x00008000, /* MWI Disable */
94 Mrmdis = 0x00010000, /* MRM Disable */
95 Tmrtest = 0x00020000, /* Timer Test Mode */
96 Spdstsien = 0x00040000, /* PHY Spdsts Interrupt Enable */
97 Lnkstsien = 0x00080000, /* PHY Lnksts Interrupt Enable */
98 Dupstsien = 0x00100000, /* PHY Dupsts Interrupt Enable */
99 Mode1000 = 0x00400000, /* 1000Mb/s Mode Control */
100 Tbien = 0x01000000, /* Ten-Bit Interface Enable */
101 Dupsts = 0x10000000, /* Full Duplex Status */
102 Spdsts100 = 0x20000000, /* SPEED100 Input Pin Status */
103 Spdsts1000 = 0x40000000, /* SPEED1000 Input Pin Status */
104 Lnksts = 0x80000000, /* Link Status */
107 enum { /* MII/EEPROM Access */
108 Eedi = 0x00000001, /* EEPROM Data In */
109 Eedo = 0x00000002, /* EEPROM Data Out */
110 Eeclk = 0x00000004, /* EEPROM Serial Clock */
111 Eesel = 0x00000008, /* EEPROM Chip Select */
112 Mdio = 0x00000010, /* MII Management Data */
113 Mddir = 0x00000020, /* MII Management Direction */
114 Mdc = 0x00000040, /* MII Management Clock */
117 enum { /* Interrupts */
118 Rxok = 0x00000001, /* Rx OK */
119 Rxdesc = 0x00000002, /* Rx Descriptor */
120 Rxerr = 0x00000004, /* Rx Packet Error */
121 Rxearly = 0x00000008, /* Rx Early Threshold */
122 Rxidle = 0x00000010, /* Rx Idle */
123 Rxorn = 0x00000020, /* Rx Overrun */
124 Txok = 0x00000040, /* Tx Packet OK */
125 Txdesc = 0x00000080, /* Tx Descriptor */
126 Txerr = 0x00000100, /* Tx Packet Error */
127 Txidle = 0x00000200, /* Tx Idle */
128 Txurn = 0x00000400, /* Tx Underrun */
129 Mib = 0x00000800, /* MIB Service */
130 Swi = 0x00001000, /* Software Interrupt */
131 Pme = 0x00002000, /* Power Management Event */
132 Phy = 0x00004000, /* PHY Interrupt */
133 Hibint = 0x00008000, /* High Bits Interrupt Set */
134 Rxsovr = 0x00010000, /* Rx Status FIFO Overrun */
135 Rtabt = 0x00020000, /* Received Target Abort */
136 Rmabt = 0x00040000, /* Received Master Abort */
137 Sserr = 0x00080000, /* Signalled System Error */
138 Dperr = 0x00100000, /* Detected Parity Error */
139 Rxrcmp = 0x00200000, /* Receive Reset Complete */
140 Txrcmp = 0x00400000, /* Transmit Reset Complete */
141 Rxdesc0 = 0x00800000, /* Rx Descriptor for Priority Queue 0 */
142 Rxdesc1 = 0x01000000, /* Rx Descriptor for Priority Queue 1 */
143 Rxdesc2 = 0x02000000, /* Rx Descriptor for Priority Queue 2 */
144 Rxdesc3 = 0x04000000, /* Rx Descriptor for Priority Queue 3 */
145 Txdesc0 = 0x08000000, /* Tx Descriptor for Priority Queue 0 */
146 Txdesc1 = 0x10000000, /* Tx Descriptor for Priority Queue 1 */
147 Txdesc2 = 0x20000000, /* Tx Descriptor for Priority Queue 2 */
148 Txdesc3 = 0x40000000, /* Tx Descriptor for Priority Queue 3 */
151 enum { /* Interrupt Enable */
152 Ien = 0x00000001, /* Interrupt Enable */
155 enum { /* Interrupt Holdoff */
156 IhSHFT = 0, /* Interrupt Holdoff */
158 Ihctl = 0x00000100, /* Interrupt Holdoff Control */
161 enum { /* Transmit Configuration */
162 TxdrthSHFT = 0, /* Tx Drain Threshold */
163 TxdrthMASK = 0x000000FF,
164 FlthSHFT = 16, /* Tx Fill Threshold */
165 FlthMASK = 0x0000FF00,
166 Brstdis = 0x00080000, /* 1000Mb/s Burst Disable */
167 MxdmaSHFT = 20, /* Max Size per Tx DMA Burst */
168 MxdmaMASK = 0x00700000,
169 Ecretryen = 0x00800000, /* Excessive Collision Retry Enable */
170 Atp = 0x10000000, /* Automatic Transmit Padding */
171 Mlb = 0x20000000, /* MAC Loopback */
172 Hbi = 0x40000000, /* Heartbeat Ignore */
173 Csi = 0x80000000, /* Carrier Sense Ignore */
176 enum { /* Receive Configuration */
177 RxdrthSHFT = 1, /* Rx Drain Threshold */
178 RxdrthMASK = 0x0000003E,
179 Airl = 0x04000000, /* Accept In-Range Length Errored */
180 Alp = 0x08000000, /* Accept Long Packets */
181 Rxfd = 0x10000000, /* Receive Full Duplex */
182 Stripcrc = 0x20000000, /* Strip CRC */
183 Arp = 0x40000000, /* Accept Runt Packets */
184 Aep = 0x80000000, /* Accept Errored Packets */
187 enum { /* Priority Queueing Control */
188 Txpqen = 0x00000001, /* Transmit Priority Queuing Enable */
189 Txfairen = 0x00000002, /* Transmit Fairness Enable */
190 RxpqenSHFT = 2, /* Receive Priority Queue Enable */
191 RxpqenMASK = 0x0000000C,
194 enum { /* Pause Control/Status */
195 PscntSHFT = 0, /* Pause Counter Value */
196 PscntMASK = 0x0000FFFF,
197 Pstx = 0x00020000, /* Transmit Pause Frame */
198 PsffloSHFT = 18, /* Rx Data FIFO Lo Threshold */
199 PsffloMASK = 0x000C0000,
200 PsffhiSHFT = 20, /* Rx Data FIFO Hi Threshold */
201 PsffhiMASK = 0x00300000,
202 PsstloSHFT = 22, /* Rx Stat FIFO Hi Threshold */
203 PsstloMASK = 0x00C00000,
204 PssthiSHFT = 24, /* Rx Stat FIFO Hi Threshold */
205 PssthiMASK = 0x03000000,
206 Psrcvd = 0x08000000, /* Pause Frame Received */
207 Psact = 0x10000000, /* Pause Active */
208 Psda = 0x20000000, /* Pause on Destination Address */
209 Psmcast = 0x40000000, /* Pause on Multicast */
210 Psen = 0x80000000, /* Pause Enable */
213 enum { /* Receive Filter/Match Control */
214 RfaddrSHFT = 0, /* Extended Register Address */
215 RfaddrMASK = 0x000003FF,
216 Ulm = 0x00080000, /* U/L bit mask */
217 Uhen = 0x00100000, /* Unicast Hash Enable */
218 Mhen = 0x00200000, /* Multicast Hash Enable */
219 Aarp = 0x00400000, /* Accept ARP Packets */
220 ApatSHFT = 23, /* Accept on Pattern Match */
221 ApatMASK = 0x07800000,
222 Apm = 0x08000000, /* Accept on Perfect Match */
223 Aau = 0x10000000, /* Accept All Unicast */
224 Aam = 0x20000000, /* Accept All Multicast */
225 Aab = 0x40000000, /* Accept All Broadcast */
226 Rfen = 0x80000000, /* Rx Filter Enable */
229 enum { /* Receive Filter/Match Data */
230 RfdataSHFT = 0, /* Receive Filter Data */
231 RfdataMASK = 0x0000FFFF,
232 BmaskSHFT = 16, /* Byte Mask */
233 BmaskMASK = 0x00030000,
236 enum { /* MIB Control */
237 Wrn = 0x00000001, /* Warning Test Indicator */
238 Frz = 0x00000002, /* Freeze All Counters */
239 Aclr = 0x00000004, /* Clear All Counters */
240 Mibs = 0x00000008, /* MIB Counter Strobe */
243 enum { /* MIB Data */
244 Nmibd = 11, /* Number of MIB Data Registers */
247 enum { /* VLAN/IP Receive Control */
248 Vtden = 0x00000001, /* VLAN Tag Detection Enable */
249 Vtren = 0x00000002, /* VLAN Tag Removal Enable */
250 Dvtf = 0x00000004, /* Discard VLAN Tagged Frames */
251 Dutf = 0x00000008, /* Discard Untagged Frames */
252 Ipen = 0x00000010, /* IP Checksum Enable */
253 Ripe = 0x00000020, /* Reject IP Checksum Errors */
254 Rtcpe = 0x00000040, /* Reject TCP Checksum Errors */
255 Rudpe = 0x00000080, /* Reject UDP Checksum Errors */
258 enum { /* VLAN/IP Transmit Control */
259 Vgti = 0x00000001, /* VLAN Global Tag Insertion */
260 Vppti = 0x00000002, /* VLAN Per-Packet Tag Insertion */
261 Gchk = 0x00000004, /* Global Checksum Generation */
262 Ppchk = 0x00000008, /* Per-Packet Checksum Generation */
265 enum { /* VLAN Data */
266 VtypeSHFT = 0, /* VLAN Type Field */
267 VtypeMASK = 0x0000FFFF,
268 VtciSHFT = 16, /* VLAN Tag Control Information */
269 VtciMASK = 0xFFFF0000,
272 enum { /* Clockrun Control/Status */
273 Clkrunen = 0x00000001, /* CLKRUN Enable */
274 Pmeen = 0x00000100, /* PME Enable */
275 Pmests = 0x00008000, /* PME Status */
279 u32int link; /* Link to the next descriptor */
280 u32int bufptr; /* pointer to data Buffer */
281 int cmdsts; /* Command/Status */
282 int extsts; /* optional Extended Status */
284 Block* bp; /* Block containing bufptr */
285 u32int unused; /* pad to 64-bit */
288 enum { /* Common cmdsts bits */
289 SizeMASK = 0x0000FFFF, /* Descriptor Byte Count */
291 Ok = 0x08000000, /* Packet OK */
292 Crc = 0x10000000, /* Suppress/Include CRC */
293 Intr = 0x20000000, /* Interrupt on ownership transfer */
294 More = 0x40000000, /* not last descriptor in a packet */
295 Own = 0x80000000, /* Descriptor Ownership */
298 enum { /* Transmit cmdsts bits */
299 CcntMASK = 0x000F0000, /* Collision Count */
301 Ec = 0x00100000, /* Excessive Collisions */
302 Owc = 0x00200000, /* Out of Window Collision */
303 Ed = 0x00400000, /* Excessive Deferral */
304 Td = 0x00800000, /* Transmit Deferred */
305 Crs = 0x01000000, /* Carrier Sense Lost */
306 Tfu = 0x02000000, /* Transmit FIFO Underrun */
307 Txa = 0x04000000, /* Transmit Abort */
310 enum { /* Receive cmdsts bits */
311 Irl = 0x00010000, /* In-Range Length Error */
312 Lbp = 0x00020000, /* Loopback Packet */
313 Fae = 0x00040000, /* Frame Alignment Error */
314 Crce = 0x00080000, /* CRC Error */
315 Ise = 0x00100000, /* Invalid Symbol Error */
316 Runt = 0x00200000, /* Runt Packet Received */
317 Long = 0x00400000, /* Too Long Packet Received */
318 DestMASK = 0x01800000, /* Destination Class */
320 Rxo = 0x02000000, /* Receive Overrun */
321 Rxa = 0x04000000, /* Receive Aborted */
324 enum { /* extsts bits */
325 EvtciMASK = 0x0000FFFF, /* VLAN Tag Control Information */
327 Vpkt = 0x00010000, /* VLAN Packet */
328 Ippkt = 0x00020000, /* IP Packet */
329 Iperr = 0x00040000, /* IP Checksum Error */
330 Tcppkt = 0x00080000, /* TCP Packet */
331 Tcperr = 0x00100000, /* TCP Checksum Error */
332 Udppkt = 0x00200000, /* UDP Packet */
333 Udperr = 0x00400000, /* UDP Checksum Error */
339 Rbsz = ROUNDUP(sizeof(Etherpkt)+8, 8),
343 typedef struct Ctlr Ctlr;
344 typedef struct Ctlr {
351 int eepromsz; /* address size in bits */
358 QLock alock; /* attach */
359 Lock ilock; /* init */
360 void* alloc; /* base of per-Ctlr allocated data */
364 Lock rdlock; /* receive */
371 Lock tlock; /* transmit */
391 #define csr32r(c, r) (*((c)->nic+((r)/4)))
392 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
394 static Ctlr* dp83820ctlrhead;
395 static Ctlr* dp83820ctlrtail;
397 static Lock dp83820rblock; /* free receive Blocks */
398 static Block* dp83820rbpool;
400 static char* dp83820mibs[Nmibd] = {
415 mdior(Ctlr* ctlr, int n)
417 int data, i, mear, r;
419 mear = csr32r(ctlr, Mear);
420 r = ~(Mdc|Mddir) & mear;
422 for(i = n-1; i >= 0; i--){
423 if(csr32r(ctlr, Mear) & Mdio)
425 csr32w(ctlr, Mear, Mdc|r);
426 csr32w(ctlr, Mear, r);
428 csr32w(ctlr, Mear, mear);
434 mdiow(Ctlr* ctlr, int bits, int n)
438 mear = csr32r(ctlr, Mear);
439 r = Mddir|(~Mdc & mear);
440 for(i = n-1; i >= 0; i--){
445 csr32w(ctlr, Mear, r);
446 csr32w(ctlr, Mear, Mdc|r);
448 csr32w(ctlr, Mear, mear);
452 dp83820miimir(Mii* mii, int pa, int ra)
460 * MII Management Interface Read.
466 mdiow(ctlr, 0xFFFFFFFF, 32);
467 mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
468 data = mdior(ctlr, 18);
473 return data & 0xFFFF;
477 dp83820miimiw(Mii* mii, int pa, int ra, int data)
484 * MII Management Interface Write.
487 * ST+OP+PA+RA+LT + 16 data bits;
490 mdiow(ctlr, 0xFFFFFFFF, 32);
492 data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
493 mdiow(ctlr, data, 32);
499 dp83820rballoc(Desc* desc)
504 ilock(&dp83820rblock);
505 if((bp = dp83820rbpool) == nil){
506 iunlock(&dp83820rblock);
511 dp83820rbpool = bp->next;
513 iunlock(&dp83820rblock);
515 desc->bufptr = PCIWADDR(bp->rp);
520 bp->rp = bp->lim - Rbsz;
525 desc->cmdsts = Intr|Rbsz;
531 dp83820rbfree(Block *bp)
533 bp->rp = bp->lim - Rbsz;
536 ilock(&dp83820rblock);
537 bp->next = dp83820rbpool;
539 iunlock(&dp83820rblock);
543 dp83820halt(Ctlr* ctlr)
548 csr32w(ctlr, Imr, 0);
549 csr32w(ctlr, Ier, 0);
550 csr32w(ctlr, Cr, Rxd|Txd);
551 for(timeo = 0; timeo < 1000; timeo++){
552 if(!(csr32r(ctlr, Cr) & (Rxe|Txe)))
556 csr32w(ctlr, Mibc, Frz);
557 iunlock(&ctlr->ilock);
560 for(i = 0; i < ctlr->nrd; i++){
561 if(ctlr->rd[i].bp == nil)
563 freeb(ctlr->rd[i].bp);
564 ctlr->rd[i].bp = nil;
568 for(i = 0; i < ctlr->ntd; i++){
569 if(ctlr->td[i].bp == nil)
571 freeb(ctlr->td[i].bp);
572 ctlr->td[i].bp = nil;
578 dp83820cfg(Ctlr* ctlr)
583 * Don't know how to deal with a TBI yet.
589 * The polarity of these bits is at the mercy
590 * of the board designer.
591 * The correct answer for all speed and duplex questions
592 * should be to query the phy.
594 cfg = csr32r(ctlr, Cfg);
597 ctlr->txcfg |= Csi|Hbi;
598 iprint("83820: full duplex, ");
601 ctlr->rxcfg &= ~Rxfd;
602 ctlr->txcfg &= ~(Csi|Hbi);
603 iprint("83820: half duplex, ");
605 csr32w(ctlr, Rxcfg, ctlr->rxcfg);
606 csr32w(ctlr, Txcfg, ctlr->txcfg);
608 switch(cfg & (Spdsts1000|Spdsts100)){
609 case Spdsts1000: /* 100Mbps */
610 default: /* 10Mbps */
611 ctlr->cfg &= ~Mode1000;
612 if((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000)
617 case Spdsts100: /* 1Gbps */
618 ctlr->cfg |= Mode1000;
622 csr32w(ctlr, Cfg, ctlr->cfg);
626 dp83820init(Ether* edev)
640 alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 8);
641 ctlr->rd = (Desc*)alloc;
642 alloc += ctlr->nrd*sizeof(Desc);
643 memset(ctlr->rd, 0, ctlr->nrd*sizeof(Desc));
645 for(i = 0; i < ctlr->nrd; i++){
647 desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]);
648 if(dp83820rballoc(desc) == nil)
651 csr32w(ctlr, Rxdphi, 0);
652 csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd));
654 for(i = 0; i < Eaddrlen; i += 2){
655 csr32w(ctlr, Rfcr, i);
656 csr32w(ctlr, Rfdr, (edev->ea[i+1]<<8)|edev->ea[i]);
658 csr32w(ctlr, Rfcr, Rfen|Aab|Aam|Apm);
660 ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT);
661 ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok;
666 ctlr->td = (Desc*)alloc;
667 memset(ctlr->td, 0, ctlr->ntd*sizeof(Desc));
668 ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;
669 for(i = 0; i < ctlr->ntd; i++){
671 desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]);
673 csr32w(ctlr, Txdphi, 0);
674 csr32w(ctlr, Txdp, PCIWADDR(ctlr->td));
676 ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT);
677 ctlr->imr |= Txurn|Txidle|Txdesc|Txok;
683 csr32w(ctlr, Mibc, Aclr);
686 csr32w(ctlr, Imr, ctlr->imr);
688 /* try coalescing adjacent interrupts; use hold-off interval of 100µs */
689 csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT));
691 csr32w(ctlr, Ier, Ien);
692 csr32w(ctlr, Cr, Rxe|Txe);
694 iunlock(&ctlr->ilock);
698 dp83820attach(Ether* edev)
705 if(ctlr->alloc != nil){
706 qunlock(&ctlr->alock);
711 if(ctlr->mii != nil){
715 if(ctlr->alloc != nil){
719 qunlock(&ctlr->alock);
723 if(!(ctlr->cfg & Tbien)){
724 if((ctlr->mii = malloc(sizeof(Mii))) == nil)
726 ctlr->mii->ctlr = ctlr;
727 ctlr->mii->mir = dp83820miimir;
728 ctlr->mii->miw = dp83820miimiw;
729 if(mii(ctlr->mii, ~0) == 0)
731 ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien;
738 ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0);
739 if(ctlr->alloc == nil)
742 for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){
743 if((bp = allocb(Rbsz)) == nil)
745 bp->free = dp83820rbfree;
751 qunlock(&ctlr->alock);
756 dp83820transmit(Ether* edev)
768 for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){
770 if((cmdsts = desc->cmdsts) & Own)
798 while(ctlr->ntq < (ctlr->ntd-1)){
799 if((bp = qget(edev->oq)) == nil)
803 desc->bufptr = PCIWADDR(bp->rp);
807 desc->cmdsts = Own|Intr|BLEN(bp);
809 x = NEXT(x, ctlr->ntd);
813 r = csr32r(ctlr, Cr);
814 csr32w(ctlr, Cr, Txe|r);
817 iunlock(&ctlr->tlock);
821 dp83820interrupt(Ureg*, void* arg)
827 int cmdsts, i, isr, r, x;
832 for(isr = csr32r(ctlr, Isr); isr & ctlr->imr; isr = csr32r(ctlr, Isr)){
833 if(isr & (Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok)){
836 while((cmdsts = desc->cmdsts) & Own){
837 if((cmdsts & Ok) && desc->bp != nil){
840 bp->wp += cmdsts & SizeMASK;
843 else if(0 && !(cmdsts & Ok)){
844 iprint("dp83820: rx %8.8uX:", cmdsts);
846 for(i = 0; i < 20; i++)
847 iprint(" %2.2uX", bp->rp[i]);
850 dp83820rballoc(desc);
852 x = NEXT(x, ctlr->nrd);
858 r = csr32r(ctlr, Cr);
859 csr32w(ctlr, Cr, Rxe|r);
863 isr &= ~(Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok);
867 x = (ctlr->txcfg & TxdrthMASK)>>TxdrthSHFT;
868 r = (ctlr->txcfg & FlthMASK)>>FlthSHFT;
869 if(x < ((TxdrthMASK)>>TxdrthSHFT)
870 && x < (2048/32 - r)){
871 ctlr->txcfg &= ~TxdrthMASK;
873 ctlr->txcfg |= x<<TxdrthSHFT;
874 csr32w(ctlr, Txcfg, ctlr->txcfg);
878 if(isr & (Txurn|Txidle|Txdesc|Txok)){
879 dp83820transmit(edev);
880 isr &= ~(Txurn|Txidle|Txdesc|Txok);
884 for(i = 0; i < Nmibd; i++){
885 r = csr32r(ctlr, Mibd+(i*sizeof(int)));
886 ctlr->mibd[i] += r & 0xFFFF;
891 if((isr & Phy) && ctlr->mii != nil){
892 ctlr->mii->mir(ctlr->mii, 1, Bmsr);
893 print("phy: cfg %8.8uX bmsr %4.4uX\n",
895 ctlr->mii->mir(ctlr->mii, 1, Bmsr));
900 iprint("dp83820: isr %8.8uX\n", isr);
905 dp83820ifstat(Ether* edev, void* a, long n, ulong offset)
913 edev->crcs = ctlr->mibd[Mibd+(1*sizeof(int))];
914 edev->frames = ctlr->mibd[Mibd+(3*sizeof(int))];
915 edev->buffs = ctlr->mibd[Mibd+(5*sizeof(int))];
916 edev->overflows = ctlr->mibd[Mibd+(2*sizeof(int))];
921 p = smalloc(READSTR);
923 for(i = 0; i < Nmibd; i++){
924 r = csr32r(ctlr, Mibd+(i*sizeof(int)));
925 ctlr->mibd[i] += r & 0xFFFF;
926 if(ctlr->mibd[i] != 0 && dp83820mibs[i] != nil)
927 l += snprint(p+l, READSTR-l, "%s: %ud %ud\n",
928 dp83820mibs[i], ctlr->mibd[i], r);
930 l += snprint(p+l, READSTR-l, "rxidle %d\n", ctlr->rxidle);
931 l += snprint(p+l, READSTR-l, "ec %d\n", ctlr->ec);
932 l += snprint(p+l, READSTR-l, "owc %d\n", ctlr->owc);
933 l += snprint(p+l, READSTR-l, "ed %d\n", ctlr->ed);
934 l += snprint(p+l, READSTR-l, "crs %d\n", ctlr->crs);
935 l += snprint(p+l, READSTR-l, "tfu %d\n", ctlr->tfu);
936 l += snprint(p+l, READSTR-l, "txa %d\n", ctlr->txa);
938 l += snprint(p+l, READSTR-l, "rom:");
939 for(i = 0; i < 0x10; i++){
940 if(i && ((i & 0x07) == 0))
941 l += snprint(p+l, READSTR-l, "\n ");
942 l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]);
944 l += snprint(p+l, READSTR-l, "\n");
946 if(ctlr->mii != nil && ctlr->mii->curphy != nil){
947 l += snprint(p+l, READSTR-l, "phy:");
948 for(i = 0; i < NMiiPhyr; i++){
949 if(i && ((i & 0x07) == 0))
950 l += snprint(p+l, READSTR-l, "\n ");
951 r = miimir(ctlr->mii, i);
952 l += snprint(p+l, READSTR-l, " %4.4uX", r);
954 snprint(p+l, READSTR-l, "\n");
957 n = readstr(offset, a, n, p);
964 dp83820promiscuous(void* arg, int on)
969 /* multicast already on, don't need to do anything */
971 dp83820multicast(void*, uchar*, int)
976 dp83820detach(Ctlr* ctlr)
979 * Soft reset the controller.
981 csr32w(ctlr, Cr, Rst);
983 while(csr32r(ctlr, Cr) & Rst)
989 dp83820shutdown(Ether* ether)
991 print("dp83820shutdown\n");
992 dp83820detach(ether->ctlr);
996 atc93c46r(Ctlr* ctlr, int address)
998 int data, i, mear, r, size;
1001 * Analog Technology, Inc. ATC93C46
1002 * or equivalent serial EEPROM.
1004 mear = csr32r(ctlr, Mear);
1005 mear &= ~(Eesel|Eeclk|Eedo|Eedi);
1009 csr32w(ctlr, Mear, r);
1011 for(i = 3-1; i >= 0; i--){
1016 csr32w(ctlr, Mear, r);
1017 csr32w(ctlr, Mear, Eeclk|r);
1019 csr32w(ctlr, Mear, r);
1024 * First time through must work out the EEPROM size.
1026 if((size = ctlr->eepromsz) == 0)
1029 for(size = size-1; size >= 0; size--){
1030 if(address & (1<<size))
1034 csr32w(ctlr, Mear, r);
1036 csr32w(ctlr, Mear, Eeclk|r);
1038 csr32w(ctlr, Mear, r);
1040 if(!(csr32r(ctlr, Mear) & Eedo))
1046 for(i = 16-1; i >= 0; i--){
1047 csr32w(ctlr, Mear, Eeclk|r);
1049 if(csr32r(ctlr, Mear) & Eedo)
1051 csr32w(ctlr, Mear, r);
1055 csr32w(ctlr, Mear, mear);
1057 if(ctlr->eepromsz == 0){
1058 ctlr->eepromsz = 8-size;
1059 ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
1067 dp83820reset(Ctlr* ctlr)
1073 * Soft reset the controller;
1074 * read the EEPROM to get the initial settings
1075 * of the Cfg and Gpior bits which should be cleared by
1078 dp83820detach(ctlr);
1081 if(ctlr->eeprom == nil) {
1082 print("dp83820reset: no eeprom\n");
1086 for(i = 0; i < 0x0E; i++){
1087 r = atc93c46r(ctlr, i);
1088 ctlr->eeprom[i] = r;
1094 print("dp83820reset: bad EEPROM checksum\n");
1099 csr32w(ctlr, Gpior, ctlr->eeprom[4]);
1102 r = csr32r(ctlr, Cfg);
1103 if(ctlr->eeprom[5] & 0x0001)
1105 if(ctlr->eeprom[5] & 0x0002)
1107 if((ctlr->eeprom[5] & 0x0004) && (r & Pci64det))
1109 if(ctlr->eeprom[5] & 0x0008)
1111 if(!(pcicfgr16(ctlr->pcidev, PciPCR) & 0x10))
1113 if(ctlr->eeprom[5] & 0x0020)
1115 if(ctlr->eeprom[5] & 0x0080)
1117 if(ctlr->eeprom[5] & 0x0200)
1118 cfg |= Tbien|Mode1000;
1120 * What about RO bits we might have destroyed with Rst?
1121 * What about Exd, Tmrtest, Extstsen, Pintctl?
1122 * Why does it think it has detected a 64-bit bus when
1126 // r = csr32r(ctlr, Cfg);
1127 // r &= ~(Mode1000|T64addren|Data64en|M64addren);
1128 // csr32w(ctlr, Cfg, r);
1129 // csr32w(ctlr, Cfg, 0x2000);
1131 ctlr->cfg = csr32r(ctlr, Cfg);
1132 print("cfg %8.8uX pcicfg %8.8uX\n", ctlr->cfg, pcicfgr32(ctlr->pcidev, PciPCR));
1133 ctlr->cfg &= ~(T64addren|Data64en|M64addren);
1134 csr32w(ctlr, Cfg, ctlr->cfg);
1135 csr32w(ctlr, Mibc, Aclr|Frz);
1148 while(p = pcimatch(p, 0, 0)){
1149 if(p->ccrb != Pcibcnet || p->ccru != Pciscether)
1151 if(p->mem[1].bar & 1)
1154 switch((p->did<<16)|p->vid){
1157 case (0x0022<<16)|0x100B: /* DP83820 (Gig-NIC) */
1161 mem = vmap(p->mem[1].bar & ~0xF, p->mem[1].size);
1163 print("DP83820: can't map %llux\n", p->mem[1].bar & ~0xF);
1167 ctlr = malloc(sizeof(Ctlr));
1169 print("DP83820: can't allocate memory\n");
1172 ctlr->port = p->mem[1].bar & ~0xF;
1175 ctlr->id = (p->did<<16)|p->vid;
1178 if(dp83820reset(ctlr)){
1184 if(dp83820ctlrhead != nil)
1185 dp83820ctlrtail->next = ctlr;
1187 dp83820ctlrhead = ctlr;
1188 dp83820ctlrtail = ctlr;
1193 dp83820pnp(Ether* edev)
1199 if(dp83820ctlrhead == nil)
1203 * Any adapter matches if no edev->port is supplied,
1204 * otherwise the ports must match.
1206 for(ctlr = dp83820ctlrhead; ctlr != nil; ctlr = ctlr->next){
1209 if(edev->port == 0 || edev->port == ctlr->port){
1218 edev->port = ctlr->port;
1219 edev->irq = ctlr->pcidev->intl;
1220 edev->tbdf = ctlr->pcidev->tbdf;
1224 * Check if the adapter's station address is to be overridden.
1225 * If not, read it from the EEPROM and set in ether->ea prior to
1226 * loading the station address in the hardware.
1228 memset(ea, 0, Eaddrlen);
1229 if(memcmp(ea, edev->ea, Eaddrlen) == 0)
1230 for(i = 0; i < Eaddrlen/2; i++){
1231 edev->ea[2*i] = ctlr->eeprom[0x0C-i];
1232 edev->ea[2*i+1] = ctlr->eeprom[0x0C-i]>>8;
1235 edev->attach = dp83820attach;
1236 edev->transmit = dp83820transmit;
1237 edev->ifstat = dp83820ifstat;
1240 edev->promiscuous = dp83820promiscuous;
1241 edev->multicast = dp83820multicast;
1242 edev->shutdown = dp83820shutdown;
1244 intrenable(edev->irq, dp83820interrupt, edev, edev->tbdf, edev->name);
1250 etherdp83820link(void)
1252 addethercard("DP83820", dp83820pnp);