]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/etherdp83820.c
pc/ether*: use 64-bit physical addresses and check pci membar types and sizes
[plan9front.git] / sys / src / 9 / pc / etherdp83820.c
1 /*
2  * National Semiconductor DP83820
3  * 10/100/1000 Mb/s Ethernet Network Interface Controller
4  * (Gig-NIC).
5  * Driver assumes little-endian and 32-bit host throughout.
6  */
7 #include "u.h"
8 #include "../port/lib.h"
9 #include "mem.h"
10 #include "dat.h"
11 #include "fns.h"
12 #include "io.h"
13 #include "../port/error.h"
14 #include "../port/netif.h"
15 #include "../port/etherif.h"
16 #include "../port/ethermii.h"
17
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 */
60 };
61
62 enum {                                  /* Cr */
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,
75 };
76
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 */
105 };
106
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 */
115 };
116
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 */
149 };
150
151 enum {                                  /* Interrupt Enable */
152         Ien             = 0x00000001,   /* Interrupt Enable */
153 };
154
155 enum {                                  /* Interrupt Holdoff */
156         IhSHFT          = 0,            /* Interrupt Holdoff */
157         IhMASK          = 0x000000FF,
158         Ihctl           = 0x00000100,   /* Interrupt Holdoff Control */
159 };
160
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 */
174 };
175
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 */
185 };
186
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,
192 };
193
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 */
211 };
212
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 */
227 };
228
229 enum {                                  /* Receive Filter/Match Data */
230         RfdataSHFT      = 0,            /* Receive Filter Data */
231         RfdataMASK      = 0x0000FFFF,
232         BmaskSHFT       = 16,           /* Byte Mask */
233         BmaskMASK       = 0x00030000,
234 };
235
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 */
241 };
242
243 enum {                                  /* MIB Data */
244         Nmibd           = 11,           /* Number of MIB Data Registers */
245 };
246
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 */
256 };
257
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 */
263 };
264
265 enum {                                  /* VLAN Data */
266         VtypeSHFT       = 0,            /* VLAN Type Field */
267         VtypeMASK       = 0x0000FFFF,
268         VtciSHFT        = 16,           /* VLAN Tag Control Information */
269         VtciMASK        = 0xFFFF0000,
270 };
271
272 enum {                                  /* Clockrun Control/Status */
273         Clkrunen        = 0x00000001,   /* CLKRUN Enable */
274         Pmeen           = 0x00000100,   /* PME Enable */
275         Pmests          = 0x00008000,   /* PME Status */
276 };
277
278 typedef struct {
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 */
283
284         Block*  bp;                     /* Block containing bufptr */
285         u32int  unused;                 /* pad to 64-bit */
286 } Desc;
287
288 enum {                                  /* Common cmdsts bits */
289         SizeMASK        = 0x0000FFFF,   /* Descriptor Byte Count */
290         SizeSHFT        = 0,
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 */
296 };
297
298 enum {                                  /* Transmit cmdsts bits */
299         CcntMASK        = 0x000F0000,   /* Collision Count */
300         CcntSHFT        = 16,
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 */
308 };
309
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 */
319         DestSHFT        = 23,
320         Rxo             = 0x02000000,   /* Receive Overrun */
321         Rxa             = 0x04000000,   /* Receive Aborted */
322 };
323
324 enum {                                  /* extsts bits */
325         EvtciMASK       = 0x0000FFFF,   /* VLAN Tag Control Information */
326         EvtciSHFT       = 0,
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 */
334 };
335
336 enum {
337         Nrd             = 256,
338         Nrb             = 4*Nrd,
339         Rbsz            = ROUNDUP(sizeof(Etherpkt)+8, 8),
340         Ntd             = 128,
341 };
342
343 typedef struct Ctlr Ctlr;
344 typedef struct Ctlr {
345         uvlong  port;
346         Pcidev* pcidev;
347         Ctlr*   next;
348         int     active;
349         int     id;
350
351         int     eepromsz;               /* address size in bits */
352         ushort* eeprom;
353
354         int*    nic;
355         int     cfg;
356         int     imr;
357
358         QLock   alock;                  /* attach */
359         Lock    ilock;                  /* init */
360         void*   alloc;                  /* base of per-Ctlr allocated data */
361
362         Mii*    mii;
363
364         Lock    rdlock;                 /* receive */
365         Desc*   rd;
366         int     nrd;
367         int     nrb;
368         int     rdx;
369         int     rxcfg;
370
371         Lock    tlock;                  /* transmit */
372         Desc*   td;
373         int     ntd;
374         int     tdh;
375         int     tdt;
376         int     ntq;
377         int     txcfg;
378
379         int     rxidle;
380
381         uint    mibd[Nmibd];
382
383         int     ec;
384         int     owc;
385         int     ed;
386         int     crs;
387         int     tfu;
388         int     txa;
389 } Ctlr;
390
391 #define csr32r(c, r)    (*((c)->nic+((r)/4)))
392 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
393
394 static Ctlr* dp83820ctlrhead;
395 static Ctlr* dp83820ctlrtail;
396
397 static Lock dp83820rblock;              /* free receive Blocks */
398 static Block* dp83820rbpool;
399
400 static char* dp83820mibs[Nmibd] = {
401         "RXErroredPkts",
402         "RXFCSErrors",
403         "RXMsdPktErrors",
404         "RXFAErrors",
405         "RXSymbolErrors",
406         "RXFrameToLong",
407         "RXIRLErrors",
408         "RXBadOpcodes",
409         "RXPauseFrames",
410         "TXPauseFrames",
411         "TXSQEErrors",
412 };
413
414 static int
415 mdior(Ctlr* ctlr, int n)
416 {
417         int data, i, mear, r;
418
419         mear = csr32r(ctlr, Mear);
420         r = ~(Mdc|Mddir) & mear;
421         data = 0;
422         for(i = n-1; i >= 0; i--){
423                 if(csr32r(ctlr, Mear) & Mdio)
424                         data |= (1<<i);
425                 csr32w(ctlr, Mear, Mdc|r);
426                 csr32w(ctlr, Mear, r);
427         }
428         csr32w(ctlr, Mear, mear);
429
430         return data;
431 }
432
433 static void
434 mdiow(Ctlr* ctlr, int bits, int n)
435 {
436         int i, mear, r;
437
438         mear = csr32r(ctlr, Mear);
439         r = Mddir|(~Mdc & mear);
440         for(i = n-1; i >= 0; i--){
441                 if(bits & (1<<i))
442                         r |= Mdio;
443                 else
444                         r &= ~Mdio;
445                 csr32w(ctlr, Mear, r);
446                 csr32w(ctlr, Mear, Mdc|r);
447         }
448         csr32w(ctlr, Mear, mear);
449 }
450
451 static int
452 dp83820miimir(Mii* mii, int pa, int ra)
453 {
454         int data;
455         Ctlr *ctlr;
456
457         ctlr = mii->ctlr;
458
459         /*
460          * MII Management Interface Read.
461          *
462          * Preamble;
463          * ST+OP+PA+RA;
464          * LT + 16 data bits.
465          */
466         mdiow(ctlr, 0xFFFFFFFF, 32);
467         mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
468         data = mdior(ctlr, 18);
469
470         if(data & 0x10000)
471                 return -1;
472
473         return data & 0xFFFF;
474 }
475
476 static int
477 dp83820miimiw(Mii* mii, int pa, int ra, int data)
478 {
479         Ctlr *ctlr;
480
481         ctlr = mii->ctlr;
482
483         /*
484          * MII Management Interface Write.
485          *
486          * Preamble;
487          * ST+OP+PA+RA+LT + 16 data bits;
488          * Z.
489          */
490         mdiow(ctlr, 0xFFFFFFFF, 32);
491         data &= 0xFFFF;
492         data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
493         mdiow(ctlr, data, 32);
494
495         return 0;
496 }
497
498 static Block *
499 dp83820rballoc(Desc* desc)
500 {
501         Block *bp;
502
503         if(desc->bp == nil){
504                 ilock(&dp83820rblock);
505                 if((bp = dp83820rbpool) == nil){
506                         iunlock(&dp83820rblock);
507                         desc->bp = nil;
508                         desc->cmdsts = Own;
509                         return nil;
510                 }
511                 dp83820rbpool = bp->next;
512                 bp->next = nil;
513                 iunlock(&dp83820rblock);
514         
515                 desc->bufptr = PCIWADDR(bp->rp);
516                 desc->bp = bp;
517         }
518         else{
519                 bp = desc->bp;
520                 bp->rp = bp->lim - Rbsz;
521                 bp->wp = bp->rp;
522         }
523
524         coherence();
525         desc->cmdsts = Intr|Rbsz;
526
527         return bp;
528 }
529
530 static void
531 dp83820rbfree(Block *bp)
532 {
533         bp->rp = bp->lim - Rbsz;
534         bp->wp = bp->rp;
535
536         ilock(&dp83820rblock);
537         bp->next = dp83820rbpool;
538         dp83820rbpool = bp;
539         iunlock(&dp83820rblock);
540 }
541
542 static void
543 dp83820halt(Ctlr* ctlr)
544 {
545         int i, timeo;
546
547         ilock(&ctlr->ilock);
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)))
553                         break;
554                 microdelay(1);
555         }
556         csr32w(ctlr, Mibc, Frz);
557         iunlock(&ctlr->ilock);
558
559         if(ctlr->rd != nil){
560                 for(i = 0; i < ctlr->nrd; i++){
561                         if(ctlr->rd[i].bp == nil)
562                                 continue;
563                         freeb(ctlr->rd[i].bp);
564                         ctlr->rd[i].bp = nil;
565                 }
566         }
567         if(ctlr->td != nil){
568                 for(i = 0; i < ctlr->ntd; i++){
569                         if(ctlr->td[i].bp == nil)
570                                 continue;
571                         freeb(ctlr->td[i].bp);
572                         ctlr->td[i].bp = nil;
573                 }
574         }
575 }
576
577 static void
578 dp83820cfg(Ctlr* ctlr)
579 {
580         int cfg;
581
582         /*
583          * Don't know how to deal with a TBI yet.
584          */
585         if(ctlr->mii == nil)
586                 return;
587
588         /*
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.
593          */
594         cfg = csr32r(ctlr, Cfg);
595         if(!(cfg & Dupsts)){
596                 ctlr->rxcfg |= Rxfd;
597                 ctlr->txcfg |= Csi|Hbi;
598                 iprint("83820: full duplex, ");
599         }
600         else{
601                 ctlr->rxcfg &= ~Rxfd;
602                 ctlr->txcfg &= ~(Csi|Hbi);
603                 iprint("83820: half duplex, ");
604         }
605         csr32w(ctlr, Rxcfg, ctlr->rxcfg);
606         csr32w(ctlr, Txcfg, ctlr->txcfg);
607
608         switch(cfg & (Spdsts1000|Spdsts100)){
609         case Spdsts1000:                /* 100Mbps */
610         default:                        /* 10Mbps */
611                 ctlr->cfg &= ~Mode1000;
612                 if((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000)
613                         iprint("100Mb/s\n");
614                 else
615                         iprint("10Mb/s\n");
616                 break;
617         case Spdsts100:                 /* 1Gbps */
618                 ctlr->cfg |= Mode1000;
619                 iprint("1Gb/s\n");
620                 break;
621         }
622         csr32w(ctlr, Cfg, ctlr->cfg);
623 }
624
625 static void
626 dp83820init(Ether* edev)
627 {
628         int i;
629         Ctlr *ctlr;
630         Desc *desc;
631         uchar *alloc;
632
633         ctlr = edev->ctlr;
634
635         dp83820halt(ctlr);
636
637         /*
638          * Receiver
639          */
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));
644         ctlr->rdx = 0;
645         for(i = 0; i < ctlr->nrd; i++){
646                 desc = &ctlr->rd[i];
647                 desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]);
648                 if(dp83820rballoc(desc) == nil)
649                         continue;
650         }
651         csr32w(ctlr, Rxdphi, 0);
652         csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd));
653
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]);
657         }
658         csr32w(ctlr, Rfcr, Rfen|Aab|Aam|Apm);
659
660         ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT);
661         ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok;
662
663         /*
664          * Transmitter.
665          */
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++){
670                 desc = &ctlr->td[i];
671                 desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]);
672         }
673         csr32w(ctlr, Txdphi, 0);
674         csr32w(ctlr, Txdp, PCIWADDR(ctlr->td));
675
676         ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT);
677         ctlr->imr |= Txurn|Txidle|Txdesc|Txok;
678
679         ilock(&ctlr->ilock);
680
681         dp83820cfg(ctlr);
682
683         csr32w(ctlr, Mibc, Aclr);
684         ctlr->imr |= Mib;
685
686         csr32w(ctlr, Imr, ctlr->imr);
687
688         /* try coalescing adjacent interrupts; use hold-off interval of 100µs */
689         csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT));
690
691         csr32w(ctlr, Ier, Ien);
692         csr32w(ctlr, Cr, Rxe|Txe);
693
694         iunlock(&ctlr->ilock);
695 }
696
697 static void
698 dp83820attach(Ether* edev)
699 {
700         Block *bp;
701         Ctlr *ctlr;
702
703         ctlr = edev->ctlr;
704         qlock(&ctlr->alock);
705         if(ctlr->alloc != nil){
706                 qunlock(&ctlr->alock);
707                 return;
708         }
709
710         if(waserror()){
711                 if(ctlr->mii != nil){
712                         free(ctlr->mii);
713                         ctlr->mii = nil;
714                 }
715                 if(ctlr->alloc != nil){
716                         free(ctlr->alloc);
717                         ctlr->alloc = nil;
718                 }
719                 qunlock(&ctlr->alock);
720                 nexterror();
721         }
722
723         if(!(ctlr->cfg & Tbien)){
724                 if((ctlr->mii = malloc(sizeof(Mii))) == nil)
725                         error(Enomem);
726                 ctlr->mii->ctlr = ctlr;
727                 ctlr->mii->mir = dp83820miimir;
728                 ctlr->mii->miw = dp83820miimiw;
729                 if(mii(ctlr->mii, ~0) == 0)
730                         error("no PHY");
731                 ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien;
732                 ctlr->imr |= Phy;
733         }
734
735         ctlr->nrd = Nrd;
736         ctlr->nrb = Nrb;
737         ctlr->ntd = Ntd;
738         ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0);
739         if(ctlr->alloc == nil)
740                 error(Enomem);
741
742         for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){
743                 if((bp = allocb(Rbsz)) == nil)
744                         break;
745                 bp->free = dp83820rbfree;
746                 dp83820rbfree(bp);
747         }
748
749         dp83820init(edev);
750
751         qunlock(&ctlr->alock);
752         poperror();
753 }
754
755 static void
756 dp83820transmit(Ether* edev)
757 {
758         Block *bp;
759         Ctlr *ctlr;
760         Desc *desc;
761         int cmdsts, r, x;
762
763         ctlr = edev->ctlr;
764
765         ilock(&ctlr->tlock);
766
767         bp = nil;
768         for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){
769                 desc = &ctlr->td[x];
770                 if((cmdsts = desc->cmdsts) & Own)
771                         break;
772                 if(!(cmdsts & Ok)){
773                         if(cmdsts & Ec)
774                                 ctlr->ec++;
775                         if(cmdsts & Owc)
776                                 ctlr->owc++;
777                         if(cmdsts & Ed)
778                                 ctlr->ed++;
779                         if(cmdsts & Crs)
780                                 ctlr->crs++;
781                         if(cmdsts & Tfu)
782                                 ctlr->tfu++;
783                         if(cmdsts & Txa)
784                                 ctlr->txa++;
785                         edev->oerrs++;
786                 }
787                 desc->bp->next = bp;
788                 bp = desc->bp;
789                 desc->bp = nil;
790
791                 ctlr->ntq--;
792         }
793         ctlr->tdh = x;
794         if(bp != nil)
795                 freeblist(bp);
796
797         x = ctlr->tdt;
798         while(ctlr->ntq < (ctlr->ntd-1)){
799                 if((bp = qget(edev->oq)) == nil)
800                         break;
801
802                 desc = &ctlr->td[x];
803                 desc->bufptr = PCIWADDR(bp->rp);
804                 desc->bp = bp;
805                 ctlr->ntq++;
806                 coherence();
807                 desc->cmdsts = Own|Intr|BLEN(bp);
808
809                 x = NEXT(x, ctlr->ntd);
810         }
811         if(x != ctlr->tdt){
812                 ctlr->tdt = x;
813                 r = csr32r(ctlr, Cr);
814                 csr32w(ctlr, Cr, Txe|r);
815         }
816
817         iunlock(&ctlr->tlock);
818 }
819
820 static void
821 dp83820interrupt(Ureg*, void* arg)
822 {
823         Block *bp;
824         Ctlr *ctlr;
825         Desc *desc;
826         Ether *edev;
827         int cmdsts, i, isr, r, x;
828
829         edev = arg;
830         ctlr = edev->ctlr;
831
832         for(isr = csr32r(ctlr, Isr); isr & ctlr->imr; isr = csr32r(ctlr, Isr)){
833                 if(isr & (Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok)){
834                         x = ctlr->rdx;
835                         desc = &ctlr->rd[x];
836                         while((cmdsts = desc->cmdsts) & Own){
837                                 if((cmdsts & Ok) && desc->bp != nil){
838                                         bp = desc->bp;
839                                         desc->bp = nil;
840                                         bp->wp += cmdsts & SizeMASK;
841                                         etheriq(edev, bp);
842                                 }
843                                 else if(0 && !(cmdsts & Ok)){
844                                         iprint("dp83820: rx %8.8uX:", cmdsts);
845                                         bp = desc->bp;
846                                         for(i = 0; i < 20; i++)
847                                                 iprint(" %2.2uX", bp->rp[i]);
848                                         iprint("\n");
849                                 }
850                                 dp83820rballoc(desc);
851
852                                 x = NEXT(x, ctlr->nrd);
853                                 desc = &ctlr->rd[x];
854                         }
855                         ctlr->rdx = x;
856
857                         if(isr & Rxidle){
858                                 r = csr32r(ctlr, Cr);
859                                 csr32w(ctlr, Cr, Rxe|r);
860                                 ctlr->rxidle++;
861                         }
862
863                         isr &= ~(Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok);
864                 }
865
866                 if(isr & Txurn){
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;
872                                 x++;
873                                 ctlr->txcfg |= x<<TxdrthSHFT;
874                                 csr32w(ctlr, Txcfg, ctlr->txcfg);
875                         }
876                 }
877
878                 if(isr & (Txurn|Txidle|Txdesc|Txok)){
879                         dp83820transmit(edev);
880                         isr &= ~(Txurn|Txidle|Txdesc|Txok);
881                 }
882
883                 if(isr & Mib){
884                         for(i = 0; i < Nmibd; i++){
885                                 r = csr32r(ctlr, Mibd+(i*sizeof(int)));
886                                 ctlr->mibd[i] += r & 0xFFFF;
887                         }
888                         isr &= ~Mib;
889                 }
890
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",
894                                 csr32r(ctlr, Cfg),
895                                 ctlr->mii->mir(ctlr->mii, 1, Bmsr));
896                         dp83820cfg(ctlr);
897                         isr &= ~Phy;
898                 }
899                 if(isr)
900                         iprint("dp83820: isr %8.8uX\n", isr);
901         }
902 }
903
904 static long
905 dp83820ifstat(Ether* edev, void* a, long n, ulong offset)
906 {
907         char *p;
908         Ctlr *ctlr;
909         int i, l, r;
910
911         ctlr = edev->ctlr;
912
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))];
917
918         if(n == 0)
919                 return 0;
920
921         p = smalloc(READSTR);
922         l = 0;
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);
929         }
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);
937
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]);
943         }
944         l += snprint(p+l, READSTR-l, "\n");
945
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);
953                 }
954                 snprint(p+l, READSTR-l, "\n");
955         }
956
957         n = readstr(offset, a, n, p);
958         free(p);
959
960         return n;
961 }
962
963 static void
964 dp83820promiscuous(void* arg, int on)
965 {
966         USED(arg, on);
967 }
968
969 /* multicast already on, don't need to do anything */
970 static void
971 dp83820multicast(void*, uchar*, int)
972 {
973 }
974
975 static int
976 dp83820detach(Ctlr* ctlr)
977 {
978         /*
979          * Soft reset the controller.
980          */
981         csr32w(ctlr, Cr, Rst);
982         delay(1);
983         while(csr32r(ctlr, Cr) & Rst)
984                 delay(1);
985         return 0;
986 }
987
988 static void
989 dp83820shutdown(Ether* ether)
990 {
991 print("dp83820shutdown\n");
992         dp83820detach(ether->ctlr);
993 }
994
995 static int
996 atc93c46r(Ctlr* ctlr, int address)
997 {
998         int data, i, mear, r, size;
999
1000         /*
1001          * Analog Technology, Inc. ATC93C46
1002          * or equivalent serial EEPROM.
1003          */
1004         mear = csr32r(ctlr, Mear);
1005         mear &= ~(Eesel|Eeclk|Eedo|Eedi);
1006         r = Eesel|mear;
1007
1008 reread:
1009         csr32w(ctlr, Mear, r);
1010         data = 0x06;
1011         for(i = 3-1; i >= 0; i--){
1012                 if(data & (1<<i))
1013                         r |= Eedi;
1014                 else
1015                         r &= ~Eedi;
1016                 csr32w(ctlr, Mear, r);
1017                 csr32w(ctlr, Mear, Eeclk|r);
1018                 microdelay(1);
1019                 csr32w(ctlr, Mear, r);
1020                 microdelay(1);
1021         }
1022
1023         /*
1024          * First time through must work out the EEPROM size.
1025          */
1026         if((size = ctlr->eepromsz) == 0)
1027                 size = 8;
1028
1029         for(size = size-1; size >= 0; size--){
1030                 if(address & (1<<size))
1031                         r |= Eedi;
1032                 else
1033                         r &= ~Eedi;
1034                 csr32w(ctlr, Mear, r);
1035                 microdelay(1);
1036                 csr32w(ctlr, Mear, Eeclk|r);
1037                 microdelay(1);
1038                 csr32w(ctlr, Mear, r);
1039                 microdelay(1);
1040                 if(!(csr32r(ctlr, Mear) & Eedo))
1041                         break;
1042         }
1043         r &= ~Eedi;
1044
1045         data = 0;
1046         for(i = 16-1; i >= 0; i--){
1047                 csr32w(ctlr, Mear, Eeclk|r);
1048                 microdelay(1);
1049                 if(csr32r(ctlr, Mear) & Eedo)
1050                         data |= (1<<i);
1051                 csr32w(ctlr, Mear, r);
1052                 microdelay(1);
1053         }
1054
1055         csr32w(ctlr, Mear, mear);
1056
1057         if(ctlr->eepromsz == 0){
1058                 ctlr->eepromsz = 8-size;
1059                 ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
1060                 goto reread;
1061         }
1062
1063         return data;
1064 }
1065
1066 static int
1067 dp83820reset(Ctlr* ctlr)
1068 {
1069         int i, r;
1070         unsigned char sum;
1071
1072         /*
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
1076          * the reset.
1077          */
1078         dp83820detach(ctlr);
1079
1080         atc93c46r(ctlr, 0);
1081         if(ctlr->eeprom == nil) {
1082                 print("dp83820reset: no eeprom\n");
1083                 return -1;
1084         }
1085         sum = 0;
1086         for(i = 0; i < 0x0E; i++){
1087                 r = atc93c46r(ctlr, i);
1088                 ctlr->eeprom[i] = r;
1089                 sum += r;
1090                 sum += r>>8;
1091         }
1092
1093         if(sum != 0){
1094                 print("dp83820reset: bad EEPROM checksum\n");
1095                 return -1;
1096         }
1097
1098 #ifdef notdef
1099         csr32w(ctlr, Gpior, ctlr->eeprom[4]);
1100
1101         cfg = Extstsen|Exd;
1102         r = csr32r(ctlr, Cfg);
1103         if(ctlr->eeprom[5] & 0x0001)
1104                 cfg |= Ext125;
1105         if(ctlr->eeprom[5] & 0x0002)
1106                 cfg |= M64addren;
1107         if((ctlr->eeprom[5] & 0x0004) && (r & Pci64det))
1108                 cfg |= Data64en;
1109         if(ctlr->eeprom[5] & 0x0008)
1110                 cfg |= T64addren;
1111         if(!(pcicfgr16(ctlr->pcidev, PciPCR) & 0x10))
1112                 cfg |= Mwidis;
1113         if(ctlr->eeprom[5] & 0x0020)
1114                 cfg |= Mrmdis;
1115         if(ctlr->eeprom[5] & 0x0080)
1116                 cfg |= Mode1000;
1117         if(ctlr->eeprom[5] & 0x0200)
1118                 cfg |= Tbien|Mode1000;
1119         /*
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
1123          * it hasn't?
1124          */
1125 #else
1126         // r = csr32r(ctlr, Cfg);
1127         // r &= ~(Mode1000|T64addren|Data64en|M64addren);
1128         // csr32w(ctlr, Cfg, r);
1129         // csr32w(ctlr, Cfg, 0x2000);
1130 #endif                                          /* notdef */
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);
1136
1137         return 0;
1138 }
1139
1140 static void
1141 dp83820pci(void)
1142 {
1143         void *mem;
1144         Pcidev *p;
1145         Ctlr *ctlr;
1146
1147         p = nil;
1148         while(p = pcimatch(p, 0, 0)){
1149                 if(p->ccrb != Pcibcnet || p->ccru != Pciscether)
1150                         continue;
1151                 if(p->mem[1].bar & 1)
1152                         continue;
1153
1154                 switch((p->did<<16)|p->vid){
1155                 default:
1156                         continue;
1157                 case (0x0022<<16)|0x100B:       /* DP83820 (Gig-NIC) */
1158                         break;
1159                 }
1160
1161                 mem = vmap(p->mem[1].bar & ~0xF, p->mem[1].size);
1162                 if(mem == nil){
1163                         print("DP83820: can't map %llux\n", p->mem[1].bar & ~0xF);
1164                         continue;
1165                 }
1166
1167                 ctlr = malloc(sizeof(Ctlr));
1168                 if(ctlr == nil){
1169                         print("DP83820: can't allocate memory\n");
1170                         continue;
1171                 }
1172                 ctlr->port = p->mem[1].bar & ~0xF;
1173                 ctlr->pcidev = p;
1174                 pcienable(p);
1175                 ctlr->id = (p->did<<16)|p->vid;
1176
1177                 ctlr->nic = mem;
1178                 if(dp83820reset(ctlr)){
1179                         free(ctlr);
1180                         continue;
1181                 }
1182                 pcisetbme(p);
1183
1184                 if(dp83820ctlrhead != nil)
1185                         dp83820ctlrtail->next = ctlr;
1186                 else
1187                         dp83820ctlrhead = ctlr;
1188                 dp83820ctlrtail = ctlr;
1189         }
1190 }
1191
1192 static int
1193 dp83820pnp(Ether* edev)
1194 {
1195         int i;
1196         Ctlr *ctlr;
1197         uchar ea[Eaddrlen];
1198
1199         if(dp83820ctlrhead == nil)
1200                 dp83820pci();
1201
1202         /*
1203          * Any adapter matches if no edev->port is supplied,
1204          * otherwise the ports must match.
1205          */
1206         for(ctlr = dp83820ctlrhead; ctlr != nil; ctlr = ctlr->next){
1207                 if(ctlr->active)
1208                         continue;
1209                 if(edev->port == 0 || edev->port == ctlr->port){
1210                         ctlr->active = 1;
1211                         break;
1212                 }
1213         }
1214         if(ctlr == nil)
1215                 return -1;
1216
1217         edev->ctlr = ctlr;
1218         edev->port = ctlr->port;
1219         edev->irq = ctlr->pcidev->intl;
1220         edev->tbdf = ctlr->pcidev->tbdf;
1221         edev->mbps = 1000;
1222
1223         /*
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.
1227          */
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;
1233                 }
1234
1235         edev->attach = dp83820attach;
1236         edev->transmit = dp83820transmit;
1237         edev->ifstat = dp83820ifstat;
1238
1239         edev->arg = edev;
1240         edev->promiscuous = dp83820promiscuous;
1241         edev->multicast = dp83820multicast;
1242         edev->shutdown = dp83820shutdown;
1243
1244         intrenable(edev->irq, dp83820interrupt, edev, edev->tbdf, edev->name);
1245
1246         return 0;
1247 }
1248
1249 void
1250 etherdp83820link(void)
1251 {
1252         addethercard("DP83820", dp83820pnp);
1253 }