]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/etherdp83820.c
ether8169, etherdp83820, ethervt6102: fix snprint READSTR bugs (thanks pap)
[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
16 #include "etherif.h"
17 #include "ethermii.h"
18
19 enum {                                  /* Registers */
20         Cr              = 0x00,         /* Command */
21         Cfg             = 0x04,         /* Configuration and Media Status */
22         Mear            = 0x08,         /* MII/EEPROM Access */
23         Ptscr           = 0x0C,         /* PCI Test Control */
24         Isr             = 0x10,         /* Interrupt Status */
25         Imr             = 0x14,         /* Interrupt Mask */
26         Ier             = 0x18,         /* Interrupt Enable */
27         Ihr             = 0x1C,         /* Interrupt Holdoff */
28         Txdp            = 0x20,         /* Transmit Descriptor Pointer */
29         Txdphi          = 0x24,         /* Transmit Descriptor Pointer Hi */
30         Txcfg           = 0x28,         /* Transmit Configuration */
31         Gpior           = 0x2C,         /* General Purpose I/O Control */
32         Rxdp            = 0x30,         /* Receive Descriptor Pointer */
33         Rxdphi          = 0x34,         /* Receive Descriptor Pointer Hi */
34         Rxcfg           = 0x38,         /* Receive Configuration */
35         Pqcr            = 0x3C,         /* Priority Queueing Control */
36         Wcsr            = 0x40,         /* Wake on LAN Control/Status */
37         Pcr             = 0x44,         /* Pause Control/Status */
38         Rfcr            = 0x48,         /* Receive Filter/Match Control */
39         Rfdr            = 0x4C,         /* Receive Filter/Match Data */
40         Brar            = 0x50,         /* Boot ROM Address */
41         Brdr            = 0x54,         /* Boot ROM Data */
42         Srr             = 0x58,         /* Silicon Revision */
43         Mibc            = 0x5C,         /* MIB Control */
44         Mibd            = 0x60,         /* MIB Data */
45         Txdp1           = 0xA0,         /* Txdp Priority 1 */
46         Txdp2           = 0xA4,         /* Txdp Priority 2 */
47         Txdp3           = 0xA8,         /* Txdp Priority 3 */
48         Rxdp1           = 0xB0,         /* Rxdp Priority 1 */
49         Rxdp2           = 0xB4,         /* Rxdp Priority 2 */
50         Rxdp3           = 0xB8,         /* Rxdp Priority 3 */
51         Vrcr            = 0xBC,         /* VLAN/IP Receive Control */
52         Vtcr            = 0xC0,         /* VLAN/IP Transmit Control */
53         Vdr             = 0xC4,         /* VLAN Data */
54         Ccsr            = 0xCC,         /* Clockrun Control/Status */
55         Tbicr           = 0xE0,         /* TBI Control */
56         Tbisr           = 0xE4,         /* TBI Status */
57         Tanar           = 0xE8,         /* TBI ANAR */
58         Tanlpar         = 0xEC,         /* TBI ANLPAR */
59         Taner           = 0xF0,         /* TBI ANER */
60         Tesr            = 0xF4,         /* TBI ESR */
61 };
62
63 enum {                                  /* Cr */
64         Txe             = 0x00000001,   /* Transmit Enable */
65         Txd             = 0x00000002,   /* Transmit Disable */
66         Rxe             = 0x00000004,   /* Receiver Enable */
67         Rxd             = 0x00000008,   /* Receiver Disable */
68         Txr             = 0x00000010,   /* Transmitter Reset */
69         Rxr             = 0x00000020,   /* Receiver Reset */
70         Swien           = 0x00000080,   /* Software Interrupt Enable */
71         Rst             = 0x00000100,   /* Reset */
72         TxpriSHFT       = 9,            /* Tx Priority Queue Select */
73         TxpriMASK       = 0x00001E00,
74         RxpriSHFT       = 13,           /* Rx Priority Queue Select */
75         RxpriMASK       = 0x0001E000,
76 };
77
78 enum {                                  /* Configuration and Media Status */
79         Bem             = 0x00000001,   /* Big Endian Mode */
80         Ext125          = 0x00000002,   /* External 125MHz reference Select */
81         Bromdis         = 0x00000004,   /* Disable Boot ROM interface */
82         Pesel           = 0x00000008,   /* Parity Error Detection Action */
83         Exd             = 0x00000010,   /* Excessive Deferral Abort */
84         Pow             = 0x00000020,   /* Program Out of Window Timer */
85         Sb              = 0x00000040,   /* Single Back-off */
86         Reqalg          = 0x00000080,   /* PCI Bus Request Algorithm */
87         Extstsen        = 0x00000100,   /* Extended Status Enable */
88         Phydis          = 0x00000200,   /* Disable PHY */
89         Phyrst          = 0x00000400,   /* Reset PHY */
90         M64addren       = 0x00000800,   /* Master 64-bit Addressing Enable */
91         Data64en        = 0x00001000,   /* 64-bit Data Enable */
92         Pci64det        = 0x00002000,   /* PCI 64-bit Bus Detected */
93         T64addren       = 0x00004000,   /* Target 64-bit Addressing Enable */
94         Mwidis          = 0x00008000,   /* MWI Disable */
95         Mrmdis          = 0x00010000,   /* MRM Disable */
96         Tmrtest         = 0x00020000,   /* Timer Test Mode */
97         Spdstsien       = 0x00040000,   /* PHY Spdsts Interrupt Enable */
98         Lnkstsien       = 0x00080000,   /* PHY Lnksts Interrupt Enable */
99         Dupstsien       = 0x00100000,   /* PHY Dupsts Interrupt Enable */
100         Mode1000        = 0x00400000,   /* 1000Mb/s Mode Control */
101         Tbien           = 0x01000000,   /* Ten-Bit Interface Enable */
102         Dupsts          = 0x10000000,   /* Full Duplex Status */
103         Spdsts100       = 0x20000000,   /* SPEED100 Input Pin Status */
104         Spdsts1000      = 0x40000000,   /* SPEED1000 Input Pin Status */
105         Lnksts          = 0x80000000,   /* Link Status */
106 };
107
108 enum {                                  /* MII/EEPROM Access */
109         Eedi            = 0x00000001,   /* EEPROM Data In */
110         Eedo            = 0x00000002,   /* EEPROM Data Out */
111         Eeclk           = 0x00000004,   /* EEPROM Serial Clock */
112         Eesel           = 0x00000008,   /* EEPROM Chip Select */
113         Mdio            = 0x00000010,   /* MII Management Data */
114         Mddir           = 0x00000020,   /* MII Management Direction */
115         Mdc             = 0x00000040,   /* MII Management Clock */
116 };
117
118 enum {                                  /* Interrupts */
119         Rxok            = 0x00000001,   /* Rx OK */
120         Rxdesc          = 0x00000002,   /* Rx Descriptor */
121         Rxerr           = 0x00000004,   /* Rx Packet Error */
122         Rxearly         = 0x00000008,   /* Rx Early Threshold */
123         Rxidle          = 0x00000010,   /* Rx Idle */
124         Rxorn           = 0x00000020,   /* Rx Overrun */
125         Txok            = 0x00000040,   /* Tx Packet OK */
126         Txdesc          = 0x00000080,   /* Tx Descriptor */
127         Txerr           = 0x00000100,   /* Tx Packet Error */
128         Txidle          = 0x00000200,   /* Tx Idle */
129         Txurn           = 0x00000400,   /* Tx Underrun */
130         Mib             = 0x00000800,   /* MIB Service */
131         Swi             = 0x00001000,   /* Software Interrupt */
132         Pme             = 0x00002000,   /* Power Management Event */
133         Phy             = 0x00004000,   /* PHY Interrupt */
134         Hibint          = 0x00008000,   /* High Bits Interrupt Set */
135         Rxsovr          = 0x00010000,   /* Rx Status FIFO Overrun */
136         Rtabt           = 0x00020000,   /* Received Target Abort */
137         Rmabt           = 0x00040000,   /* Received Master Abort */
138         Sserr           = 0x00080000,   /* Signalled System Error */
139         Dperr           = 0x00100000,   /* Detected Parity Error */
140         Rxrcmp          = 0x00200000,   /* Receive Reset Complete */
141         Txrcmp          = 0x00400000,   /* Transmit Reset Complete */
142         Rxdesc0         = 0x00800000,   /* Rx Descriptor for Priority Queue 0 */
143         Rxdesc1         = 0x01000000,   /* Rx Descriptor for Priority Queue 1 */
144         Rxdesc2         = 0x02000000,   /* Rx Descriptor for Priority Queue 2 */
145         Rxdesc3         = 0x04000000,   /* Rx Descriptor for Priority Queue 3 */
146         Txdesc0         = 0x08000000,   /* Tx Descriptor for Priority Queue 0 */
147         Txdesc1         = 0x10000000,   /* Tx Descriptor for Priority Queue 1 */
148         Txdesc2         = 0x20000000,   /* Tx Descriptor for Priority Queue 2 */
149         Txdesc3         = 0x40000000,   /* Tx Descriptor for Priority Queue 3 */
150 };
151
152 enum {                                  /* Interrupt Enable */
153         Ien             = 0x00000001,   /* Interrupt Enable */
154 };
155
156 enum {                                  /* Interrupt Holdoff */
157         IhSHFT          = 0,            /* Interrupt Holdoff */
158         IhMASK          = 0x000000FF,
159         Ihctl           = 0x00000100,   /* Interrupt Holdoff Control */
160 };
161
162 enum {                                  /* Transmit Configuration */
163         TxdrthSHFT      = 0,            /* Tx Drain Threshold */
164         TxdrthMASK      = 0x000000FF,
165         FlthSHFT        = 16,           /* Tx Fill Threshold */
166         FlthMASK        = 0x0000FF00,
167         Brstdis         = 0x00080000,   /* 1000Mb/s Burst Disable */
168         MxdmaSHFT       = 20,           /* Max Size per Tx DMA Burst */
169         MxdmaMASK       = 0x00700000,
170         Ecretryen       = 0x00800000,   /* Excessive Collision Retry Enable */
171         Atp             = 0x10000000,   /* Automatic Transmit Padding */
172         Mlb             = 0x20000000,   /* MAC Loopback */
173         Hbi             = 0x40000000,   /* Heartbeat Ignore */
174         Csi             = 0x80000000,   /* Carrier Sense Ignore */
175 };
176
177 enum {                                  /* Receive Configuration */
178         RxdrthSHFT      = 1,            /* Rx Drain Threshold */
179         RxdrthMASK      = 0x0000003E,
180         Airl            = 0x04000000,   /* Accept In-Range Length Errored */
181         Alp             = 0x08000000,   /* Accept Long Packets */
182         Rxfd            = 0x10000000,   /* Receive Full Duplex */
183         Stripcrc        = 0x20000000,   /* Strip CRC */
184         Arp             = 0x40000000,   /* Accept Runt Packets */
185         Aep             = 0x80000000,   /* Accept Errored Packets */
186 };
187
188 enum {                                  /* Priority Queueing Control */
189         Txpqen          = 0x00000001,   /* Transmit Priority Queuing Enable */
190         Txfairen        = 0x00000002,   /* Transmit Fairness Enable */
191         RxpqenSHFT      = 2,            /* Receive Priority Queue Enable */
192         RxpqenMASK      = 0x0000000C,
193 };
194
195 enum {                                  /* Pause Control/Status */
196         PscntSHFT       = 0,            /* Pause Counter Value */
197         PscntMASK       = 0x0000FFFF,
198         Pstx            = 0x00020000,   /* Transmit Pause Frame */
199         PsffloSHFT      = 18,           /* Rx Data FIFO Lo Threshold */
200         PsffloMASK      = 0x000C0000,
201         PsffhiSHFT      = 20,           /* Rx Data FIFO Hi Threshold */
202         PsffhiMASK      = 0x00300000,
203         PsstloSHFT      = 22,           /* Rx Stat FIFO Hi Threshold */
204         PsstloMASK      = 0x00C00000,
205         PssthiSHFT      = 24,           /* Rx Stat FIFO Hi Threshold */
206         PssthiMASK      = 0x03000000,
207         Psrcvd          = 0x08000000,   /* Pause Frame Received */
208         Psact           = 0x10000000,   /* Pause Active */
209         Psda            = 0x20000000,   /* Pause on Destination Address */
210         Psmcast         = 0x40000000,   /* Pause on Multicast */
211         Psen            = 0x80000000,   /* Pause Enable */
212 };
213
214 enum {                                  /* Receive Filter/Match Control */
215         RfaddrSHFT      = 0,            /* Extended Register Address */
216         RfaddrMASK      = 0x000003FF,
217         Ulm             = 0x00080000,   /* U/L bit mask */
218         Uhen            = 0x00100000,   /* Unicast Hash Enable */
219         Mhen            = 0x00200000,   /* Multicast Hash Enable */
220         Aarp            = 0x00400000,   /* Accept ARP Packets */
221         ApatSHFT        = 23,           /* Accept on Pattern Match */
222         ApatMASK        = 0x07800000,
223         Apm             = 0x08000000,   /* Accept on Perfect Match */
224         Aau             = 0x10000000,   /* Accept All Unicast */
225         Aam             = 0x20000000,   /* Accept All Multicast */
226         Aab             = 0x40000000,   /* Accept All Broadcast */
227         Rfen            = 0x80000000,   /* Rx Filter Enable */
228 };
229
230 enum {                                  /* Receive Filter/Match Data */
231         RfdataSHFT      = 0,            /* Receive Filter Data */
232         RfdataMASK      = 0x0000FFFF,
233         BmaskSHFT       = 16,           /* Byte Mask */
234         BmaskMASK       = 0x00030000,
235 };
236
237 enum {                                  /* MIB Control */
238         Wrn             = 0x00000001,   /* Warning Test Indicator */
239         Frz             = 0x00000002,   /* Freeze All Counters */
240         Aclr            = 0x00000004,   /* Clear All Counters */
241         Mibs            = 0x00000008,   /* MIB Counter Strobe */
242 };
243
244 enum {                                  /* MIB Data */
245         Nmibd           = 11,           /* Number of MIB Data Registers */
246 };
247
248 enum {                                  /* VLAN/IP Receive Control */
249         Vtden           = 0x00000001,   /* VLAN Tag Detection Enable */
250         Vtren           = 0x00000002,   /* VLAN Tag Removal Enable */
251         Dvtf            = 0x00000004,   /* Discard VLAN Tagged Frames */
252         Dutf            = 0x00000008,   /* Discard Untagged Frames */
253         Ipen            = 0x00000010,   /* IP Checksum Enable */
254         Ripe            = 0x00000020,   /* Reject IP Checksum Errors */
255         Rtcpe           = 0x00000040,   /* Reject TCP Checksum Errors */
256         Rudpe           = 0x00000080,   /* Reject UDP Checksum Errors */
257 };
258
259 enum {                                  /* VLAN/IP Transmit Control */
260         Vgti            = 0x00000001,   /* VLAN Global Tag Insertion */
261         Vppti           = 0x00000002,   /* VLAN Per-Packet Tag Insertion */
262         Gchk            = 0x00000004,   /* Global Checksum Generation */
263         Ppchk           = 0x00000008,   /* Per-Packet Checksum Generation */
264 };
265
266 enum {                                  /* VLAN Data */
267         VtypeSHFT       = 0,            /* VLAN Type Field */
268         VtypeMASK       = 0x0000FFFF,
269         VtciSHFT        = 16,           /* VLAN Tag Control Information */
270         VtciMASK        = 0xFFFF0000,
271 };
272
273 enum {                                  /* Clockrun Control/Status */
274         Clkrunen        = 0x00000001,   /* CLKRUN Enable */
275         Pmeen           = 0x00000100,   /* PME Enable */
276         Pmests          = 0x00008000,   /* PME Status */
277 };
278
279 typedef struct {
280         u32int  link;                   /* Link to the next descriptor */
281         u32int  bufptr;                 /* pointer to data Buffer */
282         int     cmdsts;                 /* Command/Status */
283         int     extsts;                 /* optional Extended Status */
284
285         Block*  bp;                     /* Block containing bufptr */
286         u32int  unused;                 /* pad to 64-bit */
287 } Desc;
288
289 enum {                                  /* Common cmdsts bits */
290         SizeMASK        = 0x0000FFFF,   /* Descriptor Byte Count */
291         SizeSHFT        = 0,
292         Ok              = 0x08000000,   /* Packet OK */
293         Crc             = 0x10000000,   /* Suppress/Include CRC */
294         Intr            = 0x20000000,   /* Interrupt on ownership transfer */
295         More            = 0x40000000,   /* not last descriptor in a packet */
296         Own             = 0x80000000,   /* Descriptor Ownership */
297 };
298
299 enum {                                  /* Transmit cmdsts bits */
300         CcntMASK        = 0x000F0000,   /* Collision Count */
301         CcntSHFT        = 16,
302         Ec              = 0x00100000,   /* Excessive Collisions */
303         Owc             = 0x00200000,   /* Out of Window Collision */
304         Ed              = 0x00400000,   /* Excessive Deferral */
305         Td              = 0x00800000,   /* Transmit Deferred */
306         Crs             = 0x01000000,   /* Carrier Sense Lost */
307         Tfu             = 0x02000000,   /* Transmit FIFO Underrun */
308         Txa             = 0x04000000,   /* Transmit Abort */
309 };
310
311 enum {                                  /* Receive cmdsts bits */
312         Irl             = 0x00010000,   /* In-Range Length Error */
313         Lbp             = 0x00020000,   /* Loopback Packet */
314         Fae             = 0x00040000,   /* Frame Alignment Error */
315         Crce            = 0x00080000,   /* CRC Error */
316         Ise             = 0x00100000,   /* Invalid Symbol Error */
317         Runt            = 0x00200000,   /* Runt Packet Received */
318         Long            = 0x00400000,   /* Too Long Packet Received */
319         DestMASK        = 0x01800000,   /* Destination Class */
320         DestSHFT        = 23,
321         Rxo             = 0x02000000,   /* Receive Overrun */
322         Rxa             = 0x04000000,   /* Receive Aborted */
323 };
324
325 enum {                                  /* extsts bits */
326         EvtciMASK       = 0x0000FFFF,   /* VLAN Tag Control Information */
327         EvtciSHFT       = 0,
328         Vpkt            = 0x00010000,   /* VLAN Packet */
329         Ippkt           = 0x00020000,   /* IP Packet */
330         Iperr           = 0x00040000,   /* IP Checksum Error */
331         Tcppkt          = 0x00080000,   /* TCP Packet */
332         Tcperr          = 0x00100000,   /* TCP Checksum Error */
333         Udppkt          = 0x00200000,   /* UDP Packet */
334         Udperr          = 0x00400000,   /* UDP Checksum Error */
335 };
336
337 enum {
338         Nrd             = 256,
339         Nrb             = 4*Nrd,
340         Rbsz            = ROUNDUP(sizeof(Etherpkt)+8, 8),
341         Ntd             = 128,
342 };
343
344 typedef struct Ctlr Ctlr;
345 typedef struct Ctlr {
346         int     port;
347         Pcidev* pcidev;
348         Ctlr*   next;
349         int     active;
350         int     id;
351
352         int     eepromsz;               /* address size in bits */
353         ushort* eeprom;
354
355         int*    nic;
356         int     cfg;
357         int     imr;
358
359         QLock   alock;                  /* attach */
360         Lock    ilock;                  /* init */
361         void*   alloc;                  /* base of per-Ctlr allocated data */
362
363         Mii*    mii;
364
365         Lock    rdlock;                 /* receive */
366         Desc*   rd;
367         int     nrd;
368         int     nrb;
369         int     rdx;
370         int     rxcfg;
371
372         Lock    tlock;                  /* transmit */
373         Desc*   td;
374         int     ntd;
375         int     tdh;
376         int     tdt;
377         int     ntq;
378         int     txcfg;
379
380         int     rxidle;
381
382         uint    mibd[Nmibd];
383
384         int     ec;
385         int     owc;
386         int     ed;
387         int     crs;
388         int     tfu;
389         int     txa;
390 } Ctlr;
391
392 #define csr32r(c, r)    (*((c)->nic+((r)/4)))
393 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
394
395 static Ctlr* dp83820ctlrhead;
396 static Ctlr* dp83820ctlrtail;
397
398 static Lock dp83820rblock;              /* free receive Blocks */
399 static Block* dp83820rbpool;
400
401 static char* dp83820mibs[Nmibd] = {
402         "RXErroredPkts",
403         "RXFCSErrors",
404         "RXMsdPktErrors",
405         "RXFAErrors",
406         "RXSymbolErrors",
407         "RXFrameToLong",
408         "RXIRLErrors",
409         "RXBadOpcodes",
410         "RXPauseFrames",
411         "TXPauseFrames",
412         "TXSQEErrors",
413 };
414
415 static int
416 mdior(Ctlr* ctlr, int n)
417 {
418         int data, i, mear, r;
419
420         mear = csr32r(ctlr, Mear);
421         r = ~(Mdc|Mddir) & mear;
422         data = 0;
423         for(i = n-1; i >= 0; i--){
424                 if(csr32r(ctlr, Mear) & Mdio)
425                         data |= (1<<i);
426                 csr32w(ctlr, Mear, Mdc|r);
427                 csr32w(ctlr, Mear, r);
428         }
429         csr32w(ctlr, Mear, mear);
430
431         return data;
432 }
433
434 static void
435 mdiow(Ctlr* ctlr, int bits, int n)
436 {
437         int i, mear, r;
438
439         mear = csr32r(ctlr, Mear);
440         r = Mddir|(~Mdc & mear);
441         for(i = n-1; i >= 0; i--){
442                 if(bits & (1<<i))
443                         r |= Mdio;
444                 else
445                         r &= ~Mdio;
446                 csr32w(ctlr, Mear, r);
447                 csr32w(ctlr, Mear, Mdc|r);
448         }
449         csr32w(ctlr, Mear, mear);
450 }
451
452 static int
453 dp83820miimir(Mii* mii, int pa, int ra)
454 {
455         int data;
456         Ctlr *ctlr;
457
458         ctlr = mii->ctlr;
459
460         /*
461          * MII Management Interface Read.
462          *
463          * Preamble;
464          * ST+OP+PA+RA;
465          * LT + 16 data bits.
466          */
467         mdiow(ctlr, 0xFFFFFFFF, 32);
468         mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
469         data = mdior(ctlr, 18);
470
471         if(data & 0x10000)
472                 return -1;
473
474         return data & 0xFFFF;
475 }
476
477 static int
478 dp83820miimiw(Mii* mii, int pa, int ra, int data)
479 {
480         Ctlr *ctlr;
481
482         ctlr = mii->ctlr;
483
484         /*
485          * MII Management Interface Write.
486          *
487          * Preamble;
488          * ST+OP+PA+RA+LT + 16 data bits;
489          * Z.
490          */
491         mdiow(ctlr, 0xFFFFFFFF, 32);
492         data &= 0xFFFF;
493         data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
494         mdiow(ctlr, data, 32);
495
496         return 0;
497 }
498
499 static Block *
500 dp83820rballoc(Desc* desc)
501 {
502         Block *bp;
503
504         if(desc->bp == nil){
505                 ilock(&dp83820rblock);
506                 if((bp = dp83820rbpool) == nil){
507                         iunlock(&dp83820rblock);
508                         desc->bp = nil;
509                         desc->cmdsts = Own;
510                         return nil;
511                 }
512                 dp83820rbpool = bp->next;
513                 bp->next = nil;
514                 _xinc(&bp->ref);        /* prevent bp from being freed */
515                 iunlock(&dp83820rblock);
516         
517                 desc->bufptr = PCIWADDR(bp->rp);
518                 desc->bp = bp;
519         }
520         else{
521                 bp = desc->bp;
522                 bp->rp = bp->lim - Rbsz;
523                 bp->wp = bp->rp;
524         }
525
526         coherence();
527         desc->cmdsts = Intr|Rbsz;
528
529         return bp;
530 }
531
532 static void
533 dp83820rbfree(Block *bp)
534 {
535         bp->rp = bp->lim - Rbsz;
536         bp->wp = bp->rp;
537
538         ilock(&dp83820rblock);
539         bp->next = dp83820rbpool;
540         dp83820rbpool = bp;
541         iunlock(&dp83820rblock);
542 }
543
544 static void
545 dp83820halt(Ctlr* ctlr)
546 {
547         int i, timeo;
548
549         ilock(&ctlr->ilock);
550         csr32w(ctlr, Imr, 0);
551         csr32w(ctlr, Ier, 0);
552         csr32w(ctlr, Cr, Rxd|Txd);
553         for(timeo = 0; timeo < 1000; timeo++){
554                 if(!(csr32r(ctlr, Cr) & (Rxe|Txe)))
555                         break;
556                 microdelay(1);
557         }
558         csr32w(ctlr, Mibc, Frz);
559         iunlock(&ctlr->ilock);
560
561         if(ctlr->rd != nil){
562                 for(i = 0; i < ctlr->nrd; i++){
563                         if(ctlr->rd[i].bp == nil)
564                                 continue;
565                         freeb(ctlr->rd[i].bp);
566                         ctlr->rd[i].bp = nil;
567                 }
568         }
569         if(ctlr->td != nil){
570                 for(i = 0; i < ctlr->ntd; i++){
571                         if(ctlr->td[i].bp == nil)
572                                 continue;
573                         freeb(ctlr->td[i].bp);
574                         ctlr->td[i].bp = nil;
575                 }
576         }
577 }
578
579 static void
580 dp83820cfg(Ctlr* ctlr)
581 {
582         int cfg;
583
584         /*
585          * Don't know how to deal with a TBI yet.
586          */
587         if(ctlr->mii == nil)
588                 return;
589
590         /*
591          * The polarity of these bits is at the mercy
592          * of the board designer.
593          * The correct answer for all speed and duplex questions
594          * should be to query the phy.
595          */
596         cfg = csr32r(ctlr, Cfg);
597         if(!(cfg & Dupsts)){
598                 ctlr->rxcfg |= Rxfd;
599                 ctlr->txcfg |= Csi|Hbi;
600                 iprint("83820: full duplex, ");
601         }
602         else{
603                 ctlr->rxcfg &= ~Rxfd;
604                 ctlr->txcfg &= ~(Csi|Hbi);
605                 iprint("83820: half duplex, ");
606         }
607         csr32w(ctlr, Rxcfg, ctlr->rxcfg);
608         csr32w(ctlr, Txcfg, ctlr->txcfg);
609
610         switch(cfg & (Spdsts1000|Spdsts100)){
611         case Spdsts1000:                /* 100Mbps */
612         default:                        /* 10Mbps */
613                 ctlr->cfg &= ~Mode1000;
614                 if((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000)
615                         iprint("100Mb/s\n");
616                 else
617                         iprint("10Mb/s\n");
618                 break;
619         case Spdsts100:                 /* 1Gbps */
620                 ctlr->cfg |= Mode1000;
621                 iprint("1Gb/s\n");
622                 break;
623         }
624         csr32w(ctlr, Cfg, ctlr->cfg);
625 }
626
627 static void
628 dp83820init(Ether* edev)
629 {
630         int i;
631         Ctlr *ctlr;
632         Desc *desc;
633         uchar *alloc;
634
635         ctlr = edev->ctlr;
636
637         dp83820halt(ctlr);
638
639         /*
640          * Receiver
641          */
642         alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 8);
643         ctlr->rd = (Desc*)alloc;
644         alloc += ctlr->nrd*sizeof(Desc);
645         memset(ctlr->rd, 0, ctlr->nrd*sizeof(Desc));
646         ctlr->rdx = 0;
647         for(i = 0; i < ctlr->nrd; i++){
648                 desc = &ctlr->rd[i];
649                 desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]);
650                 if(dp83820rballoc(desc) == nil)
651                         continue;
652         }
653         csr32w(ctlr, Rxdphi, 0);
654         csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd));
655
656         for(i = 0; i < Eaddrlen; i += 2){
657                 csr32w(ctlr, Rfcr, i);
658                 csr32w(ctlr, Rfdr, (edev->ea[i+1]<<8)|edev->ea[i]);
659         }
660         csr32w(ctlr, Rfcr, Rfen|Aab|Aam|Apm);
661
662         ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT);
663         ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok;
664
665         /*
666          * Transmitter.
667          */
668         ctlr->td = (Desc*)alloc;
669         memset(ctlr->td, 0, ctlr->ntd*sizeof(Desc));
670         ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;
671         for(i = 0; i < ctlr->ntd; i++){
672                 desc = &ctlr->td[i];
673                 desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]);
674         }
675         csr32w(ctlr, Txdphi, 0);
676         csr32w(ctlr, Txdp, PCIWADDR(ctlr->td));
677
678         ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT);
679         ctlr->imr |= Txurn|Txidle|Txdesc|Txok;
680
681         ilock(&ctlr->ilock);
682
683         dp83820cfg(ctlr);
684
685         csr32w(ctlr, Mibc, Aclr);
686         ctlr->imr |= Mib;
687
688         csr32w(ctlr, Imr, ctlr->imr);
689
690         /* try coalescing adjacent interrupts; use hold-off interval of 100µs */
691         csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT));
692
693         csr32w(ctlr, Ier, Ien);
694         csr32w(ctlr, Cr, Rxe|Txe);
695
696         iunlock(&ctlr->ilock);
697 }
698
699 static void
700 dp83820attach(Ether* edev)
701 {
702         Block *bp;
703         Ctlr *ctlr;
704
705         ctlr = edev->ctlr;
706         qlock(&ctlr->alock);
707         if(ctlr->alloc != nil){
708                 qunlock(&ctlr->alock);
709                 return;
710         }
711
712         if(waserror()){
713                 if(ctlr->mii != nil){
714                         free(ctlr->mii);
715                         ctlr->mii = nil;
716                 }
717                 if(ctlr->alloc != nil){
718                         free(ctlr->alloc);
719                         ctlr->alloc = nil;
720                 }
721                 qunlock(&ctlr->alock);
722                 nexterror();
723         }
724
725         if(!(ctlr->cfg & Tbien)){
726                 if((ctlr->mii = malloc(sizeof(Mii))) == nil)
727                         error(Enomem);
728                 ctlr->mii->ctlr = ctlr;
729                 ctlr->mii->mir = dp83820miimir;
730                 ctlr->mii->miw = dp83820miimiw;
731                 if(mii(ctlr->mii, ~0) == 0)
732                         error("no PHY");
733                 ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien;
734                 ctlr->imr |= Phy;
735         }
736
737         ctlr->nrd = Nrd;
738         ctlr->nrb = Nrb;
739         ctlr->ntd = Ntd;
740         ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0);
741         if(ctlr->alloc == nil)
742                 error(Enomem);
743
744         for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){
745                 if((bp = allocb(Rbsz)) == nil)
746                         break;
747                 bp->free = dp83820rbfree;
748                 dp83820rbfree(bp);
749         }
750
751         dp83820init(edev);
752
753         qunlock(&ctlr->alock);
754         poperror();
755 }
756
757 static void
758 dp83820transmit(Ether* edev)
759 {
760         Block *bp;
761         Ctlr *ctlr;
762         Desc *desc;
763         int cmdsts, r, x;
764
765         ctlr = edev->ctlr;
766
767         ilock(&ctlr->tlock);
768
769         bp = nil;
770         for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){
771                 desc = &ctlr->td[x];
772                 if((cmdsts = desc->cmdsts) & Own)
773                         break;
774                 if(!(cmdsts & Ok)){
775                         if(cmdsts & Ec)
776                                 ctlr->ec++;
777                         if(cmdsts & Owc)
778                                 ctlr->owc++;
779                         if(cmdsts & Ed)
780                                 ctlr->ed++;
781                         if(cmdsts & Crs)
782                                 ctlr->crs++;
783                         if(cmdsts & Tfu)
784                                 ctlr->tfu++;
785                         if(cmdsts & Txa)
786                                 ctlr->txa++;
787                         edev->oerrs++;
788                 }
789                 desc->bp->next = bp;
790                 bp = desc->bp;
791                 desc->bp = nil;
792
793                 ctlr->ntq--;
794         }
795         ctlr->tdh = x;
796         if(bp != nil)
797                 freeblist(bp);
798
799         x = ctlr->tdt;
800         while(ctlr->ntq < (ctlr->ntd-1)){
801                 if((bp = qget(edev->oq)) == nil)
802                         break;
803
804                 desc = &ctlr->td[x];
805                 desc->bufptr = PCIWADDR(bp->rp);
806                 desc->bp = bp;
807                 ctlr->ntq++;
808                 coherence();
809                 desc->cmdsts = Own|Intr|BLEN(bp);
810
811                 x = NEXT(x, ctlr->ntd);
812         }
813         if(x != ctlr->tdt){
814                 ctlr->tdt = x;
815                 r = csr32r(ctlr, Cr);
816                 csr32w(ctlr, Cr, Txe|r);
817         }
818
819         iunlock(&ctlr->tlock);
820 }
821
822 static void
823 dp83820interrupt(Ureg*, void* arg)
824 {
825         Block *bp;
826         Ctlr *ctlr;
827         Desc *desc;
828         Ether *edev;
829         int cmdsts, i, isr, r, x;
830
831         edev = arg;
832         ctlr = edev->ctlr;
833
834         for(isr = csr32r(ctlr, Isr); isr & ctlr->imr; isr = csr32r(ctlr, Isr)){
835                 if(isr & (Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok)){
836                         x = ctlr->rdx;
837                         desc = &ctlr->rd[x];
838                         while((cmdsts = desc->cmdsts) & Own){
839                                 if((cmdsts & Ok) && desc->bp != nil){
840                                         bp = desc->bp;
841                                         desc->bp = nil;
842                                         bp->wp += cmdsts & SizeMASK;
843                                         etheriq(edev, bp, 1);
844                                 }
845                                 else if(0 && !(cmdsts & Ok)){
846                                         iprint("dp83820: rx %8.8uX:", cmdsts);
847                                         bp = desc->bp;
848                                         for(i = 0; i < 20; i++)
849                                                 iprint(" %2.2uX", bp->rp[i]);
850                                         iprint("\n");
851                                 }
852                                 dp83820rballoc(desc);
853
854                                 x = NEXT(x, ctlr->nrd);
855                                 desc = &ctlr->rd[x];
856                         }
857                         ctlr->rdx = x;
858
859                         if(isr & Rxidle){
860                                 r = csr32r(ctlr, Cr);
861                                 csr32w(ctlr, Cr, Rxe|r);
862                                 ctlr->rxidle++;
863                         }
864
865                         isr &= ~(Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok);
866                 }
867
868                 if(isr & Txurn){
869                         x = (ctlr->txcfg & TxdrthMASK)>>TxdrthSHFT;
870                         r = (ctlr->txcfg & FlthMASK)>>FlthSHFT;
871                         if(x < ((TxdrthMASK)>>TxdrthSHFT)
872                         && x < (2048/32 - r)){
873                                 ctlr->txcfg &= ~TxdrthMASK;
874                                 x++;
875                                 ctlr->txcfg |= x<<TxdrthSHFT;
876                                 csr32w(ctlr, Txcfg, ctlr->txcfg);
877                         }
878                 }
879
880                 if(isr & (Txurn|Txidle|Txdesc|Txok)){
881                         dp83820transmit(edev);
882                         isr &= ~(Txurn|Txidle|Txdesc|Txok);
883                 }
884
885                 if(isr & Mib){
886                         for(i = 0; i < Nmibd; i++){
887                                 r = csr32r(ctlr, Mibd+(i*sizeof(int)));
888                                 ctlr->mibd[i] += r & 0xFFFF;
889                         }
890                         isr &= ~Mib;
891                 }
892
893                 if((isr & Phy) && ctlr->mii != nil){
894                         ctlr->mii->mir(ctlr->mii, 1, Bmsr);
895                         print("phy: cfg %8.8uX bmsr %4.4uX\n",
896                                 csr32r(ctlr, Cfg),
897                                 ctlr->mii->mir(ctlr->mii, 1, Bmsr));
898                         dp83820cfg(ctlr);
899                         isr &= ~Phy;
900                 }
901                 if(isr)
902                         iprint("dp83820: isr %8.8uX\n", isr);
903         }
904 }
905
906 static long
907 dp83820ifstat(Ether* edev, void* a, long n, ulong offset)
908 {
909         char *p;
910         Ctlr *ctlr;
911         int i, l, r;
912
913         ctlr = edev->ctlr;
914
915         edev->crcs = ctlr->mibd[Mibd+(1*sizeof(int))];
916         edev->frames = ctlr->mibd[Mibd+(3*sizeof(int))];
917         edev->buffs = ctlr->mibd[Mibd+(5*sizeof(int))];
918         edev->overflows = ctlr->mibd[Mibd+(2*sizeof(int))];
919
920         if(n == 0)
921                 return 0;
922
923         p = smalloc(READSTR);
924         l = 0;
925         for(i = 0; i < Nmibd; i++){
926                 r = csr32r(ctlr, Mibd+(i*sizeof(int)));
927                 ctlr->mibd[i] += r & 0xFFFF;
928                 if(ctlr->mibd[i] != 0 && dp83820mibs[i] != nil)
929                         l += snprint(p+l, READSTR-l, "%s: %ud %ud\n",
930                                 dp83820mibs[i], ctlr->mibd[i], r);
931         }
932         l += snprint(p+l, READSTR-l, "rxidle %d\n", ctlr->rxidle);
933         l += snprint(p+l, READSTR-l, "ec %d\n", ctlr->ec);
934         l += snprint(p+l, READSTR-l, "owc %d\n", ctlr->owc);
935         l += snprint(p+l, READSTR-l, "ed %d\n", ctlr->ed);
936         l += snprint(p+l, READSTR-l, "crs %d\n", ctlr->crs);
937         l += snprint(p+l, READSTR-l, "tfu %d\n", ctlr->tfu);
938         l += snprint(p+l, READSTR-l, "txa %d\n", ctlr->txa);
939
940         l += snprint(p+l, READSTR-l, "rom:");
941         for(i = 0; i < 0x10; i++){
942                 if(i && ((i & 0x07) == 0))
943                         l += snprint(p+l, READSTR-l, "\n    ");
944                 l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]);
945         }
946         l += snprint(p+l, READSTR-l, "\n");
947
948         if(ctlr->mii != nil && ctlr->mii->curphy != nil){
949                 l += snprint(p+l, READSTR-l, "phy:");
950                 for(i = 0; i < NMiiPhyr; i++){
951                         if(i && ((i & 0x07) == 0))
952                                 l += snprint(p+l, READSTR-l, "\n    ");
953                         r = miimir(ctlr->mii, i);
954                         l += snprint(p+l, READSTR-l, " %4.4uX", r);
955                 }
956                 snprint(p+l, READSTR-l, "\n");
957         }
958
959         n = readstr(offset, a, n, p);
960         free(p);
961
962         return n;
963 }
964
965 static void
966 dp83820promiscuous(void* arg, int on)
967 {
968         USED(arg, on);
969 }
970
971 /* multicast already on, don't need to do anything */
972 static void
973 dp83820multicast(void*, uchar*, int)
974 {
975 }
976
977 static int
978 dp83820detach(Ctlr* ctlr)
979 {
980         /*
981          * Soft reset the controller.
982          */
983         csr32w(ctlr, Cr, Rst);
984         delay(1);
985         while(csr32r(ctlr, Cr) & Rst)
986                 delay(1);
987         return 0;
988 }
989
990 static void
991 dp83820shutdown(Ether* ether)
992 {
993 print("dp83820shutdown\n");
994         dp83820detach(ether->ctlr);
995 }
996
997 static int
998 atc93c46r(Ctlr* ctlr, int address)
999 {
1000         int data, i, mear, r, size;
1001
1002         /*
1003          * Analog Technology, Inc. ATC93C46
1004          * or equivalent serial EEPROM.
1005          */
1006         mear = csr32r(ctlr, Mear);
1007         mear &= ~(Eesel|Eeclk|Eedo|Eedi);
1008         r = Eesel|mear;
1009
1010 reread:
1011         csr32w(ctlr, Mear, r);
1012         data = 0x06;
1013         for(i = 3-1; i >= 0; i--){
1014                 if(data & (1<<i))
1015                         r |= Eedi;
1016                 else
1017                         r &= ~Eedi;
1018                 csr32w(ctlr, Mear, r);
1019                 csr32w(ctlr, Mear, Eeclk|r);
1020                 microdelay(1);
1021                 csr32w(ctlr, Mear, r);
1022                 microdelay(1);
1023         }
1024
1025         /*
1026          * First time through must work out the EEPROM size.
1027          */
1028         if((size = ctlr->eepromsz) == 0)
1029                 size = 8;
1030
1031         for(size = size-1; size >= 0; size--){
1032                 if(address & (1<<size))
1033                         r |= Eedi;
1034                 else
1035                         r &= ~Eedi;
1036                 csr32w(ctlr, Mear, r);
1037                 microdelay(1);
1038                 csr32w(ctlr, Mear, Eeclk|r);
1039                 microdelay(1);
1040                 csr32w(ctlr, Mear, r);
1041                 microdelay(1);
1042                 if(!(csr32r(ctlr, Mear) & Eedo))
1043                         break;
1044         }
1045         r &= ~Eedi;
1046
1047         data = 0;
1048         for(i = 16-1; i >= 0; i--){
1049                 csr32w(ctlr, Mear, Eeclk|r);
1050                 microdelay(1);
1051                 if(csr32r(ctlr, Mear) & Eedo)
1052                         data |= (1<<i);
1053                 csr32w(ctlr, Mear, r);
1054                 microdelay(1);
1055         }
1056
1057         csr32w(ctlr, Mear, mear);
1058
1059         if(ctlr->eepromsz == 0){
1060                 ctlr->eepromsz = 8-size;
1061                 ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
1062                 goto reread;
1063         }
1064
1065         return data;
1066 }
1067
1068 static int
1069 dp83820reset(Ctlr* ctlr)
1070 {
1071         int i, r;
1072         unsigned char sum;
1073
1074         /*
1075          * Soft reset the controller;
1076          * read the EEPROM to get the initial settings
1077          * of the Cfg and Gpior bits which should be cleared by
1078          * the reset.
1079          */
1080         dp83820detach(ctlr);
1081
1082         atc93c46r(ctlr, 0);
1083         if(ctlr->eeprom == nil) {
1084                 print("dp83820reset: no eeprom\n");
1085                 return -1;
1086         }
1087         sum = 0;
1088         for(i = 0; i < 0x0E; i++){
1089                 r = atc93c46r(ctlr, i);
1090                 ctlr->eeprom[i] = r;
1091                 sum += r;
1092                 sum += r>>8;
1093         }
1094
1095         if(sum != 0){
1096                 print("dp83820reset: bad EEPROM checksum\n");
1097                 return -1;
1098         }
1099
1100 #ifdef notdef
1101         csr32w(ctlr, Gpior, ctlr->eeprom[4]);
1102
1103         cfg = Extstsen|Exd;
1104         r = csr32r(ctlr, Cfg);
1105         if(ctlr->eeprom[5] & 0x0001)
1106                 cfg |= Ext125;
1107         if(ctlr->eeprom[5] & 0x0002)
1108                 cfg |= M64addren;
1109         if((ctlr->eeprom[5] & 0x0004) && (r & Pci64det))
1110                 cfg |= Data64en;
1111         if(ctlr->eeprom[5] & 0x0008)
1112                 cfg |= T64addren;
1113         if(!(pcicfgr16(ctlr->pcidev, PciPCR) & 0x10))
1114                 cfg |= Mwidis;
1115         if(ctlr->eeprom[5] & 0x0020)
1116                 cfg |= Mrmdis;
1117         if(ctlr->eeprom[5] & 0x0080)
1118                 cfg |= Mode1000;
1119         if(ctlr->eeprom[5] & 0x0200)
1120                 cfg |= Tbien|Mode1000;
1121         /*
1122          * What about RO bits we might have destroyed with Rst?
1123          * What about Exd, Tmrtest, Extstsen, Pintctl?
1124          * Why does it think it has detected a 64-bit bus when
1125          * it hasn't?
1126          */
1127 #else
1128         // r = csr32r(ctlr, Cfg);
1129         // r &= ~(Mode1000|T64addren|Data64en|M64addren);
1130         // csr32w(ctlr, Cfg, r);
1131         // csr32w(ctlr, Cfg, 0x2000);
1132 #endif                                          /* notdef */
1133         ctlr->cfg = csr32r(ctlr, Cfg);
1134 print("cfg %8.8uX pcicfg %8.8uX\n", ctlr->cfg, pcicfgr32(ctlr->pcidev, PciPCR));
1135         ctlr->cfg &= ~(T64addren|Data64en|M64addren);
1136         csr32w(ctlr, Cfg, ctlr->cfg);
1137         csr32w(ctlr, Mibc, Aclr|Frz);
1138
1139         return 0;
1140 }
1141
1142 static void
1143 dp83820pci(void)
1144 {
1145         void *mem;
1146         Pcidev *p;
1147         Ctlr *ctlr;
1148
1149         p = nil;
1150         while(p = pcimatch(p, 0, 0)){
1151                 if(p->ccrb != Pcibcnet || p->ccru != Pciscether)
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 & ~0x0F, p->mem[1].size);
1162                 if(mem == 0){
1163                         print("DP83820: can't map %8.8luX\n", p->mem[1].bar);
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 & ~0x0F;
1173                 ctlr->pcidev = p;
1174                 ctlr->id = (p->did<<16)|p->vid;
1175
1176                 ctlr->nic = mem;
1177                 if(dp83820reset(ctlr)){
1178                         free(ctlr);
1179                         continue;
1180                 }
1181                 pcisetbme(p);
1182
1183                 if(dp83820ctlrhead != nil)
1184                         dp83820ctlrtail->next = ctlr;
1185                 else
1186                         dp83820ctlrhead = ctlr;
1187                 dp83820ctlrtail = ctlr;
1188         }
1189 }
1190
1191 static int
1192 dp83820pnp(Ether* edev)
1193 {
1194         int i;
1195         Ctlr *ctlr;
1196         uchar ea[Eaddrlen];
1197
1198         if(dp83820ctlrhead == nil)
1199                 dp83820pci();
1200
1201         /*
1202          * Any adapter matches if no edev->port is supplied,
1203          * otherwise the ports must match.
1204          */
1205         for(ctlr = dp83820ctlrhead; ctlr != nil; ctlr = ctlr->next){
1206                 if(ctlr->active)
1207                         continue;
1208                 if(edev->port == 0 || edev->port == ctlr->port){
1209                         ctlr->active = 1;
1210                         break;
1211                 }
1212         }
1213         if(ctlr == nil)
1214                 return -1;
1215
1216         edev->ctlr = ctlr;
1217         edev->port = ctlr->port;
1218         edev->irq = ctlr->pcidev->intl;
1219         edev->tbdf = ctlr->pcidev->tbdf;
1220         edev->mbps = 1000;
1221
1222         /*
1223          * Check if the adapter's station address is to be overridden.
1224          * If not, read it from the EEPROM and set in ether->ea prior to
1225          * loading the station address in the hardware.
1226          */
1227         memset(ea, 0, Eaddrlen);
1228         if(memcmp(ea, edev->ea, Eaddrlen) == 0)
1229                 for(i = 0; i < Eaddrlen/2; i++){
1230                         edev->ea[2*i] = ctlr->eeprom[0x0C-i];
1231                         edev->ea[2*i+1] = ctlr->eeprom[0x0C-i]>>8;
1232                 }
1233
1234         edev->attach = dp83820attach;
1235         edev->transmit = dp83820transmit;
1236         edev->interrupt = dp83820interrupt;
1237         edev->ifstat = dp83820ifstat;
1238
1239         edev->arg = edev;
1240         edev->promiscuous = dp83820promiscuous;
1241         edev->multicast = dp83820multicast;
1242         edev->shutdown = dp83820shutdown;
1243
1244         return 0;
1245 }
1246
1247 void
1248 etherdp83820link(void)
1249 {
1250         addethercard("DP83820", dp83820pnp);
1251 }