xref: /plan9/sys/src/9/pc/etherdp83820.c (revision cebd3b46303b6884206200c08c0d8b3fb8dc989e)
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 	Rbsz		= ROUNDUP(sizeof(Etherpkt)+8, 8),
339 	/* were 256, 4*Nrd & 64, but 52, 253 and 9 are ample. */
340 	Nrd		= 128,
341 	Nrb		= 512,
342 	Ntd		= 32,
343 };
344 
345 typedef struct Ctlr Ctlr;
346 typedef struct Ctlr {
347 	int	port;
348 	Pcidev*	pcidev;
349 	Ctlr*	next;
350 	int	active;
351 	int	id;
352 
353 	int	eepromsz;		/* address size in bits */
354 	ushort*	eeprom;
355 
356 	int*	nic;
357 	int	cfg;
358 	int	imr;
359 
360 	QLock	alock;			/* attach */
361 	Lock	ilock;			/* init */
362 	void*	alloc;			/* base of per-Ctlr allocated data */
363 
364 	Mii*	mii;
365 
366 	Lock	rdlock;			/* receive */
367 	Desc*	rd;
368 	int	nrd;
369 	int	nrb;
370 	int	rdx;
371 	int	rxcfg;
372 
373 	Lock	tlock;			/* transmit */
374 	Desc*	td;
375 	int	ntd;
376 	int	tdh;
377 	int	tdt;
378 	int	ntq;
379 	int	txcfg;
380 
381 	int	rxidle;
382 
383 	uint	mibd[Nmibd];
384 
385 	int	ec;
386 	int	owc;
387 	int	ed;
388 	int	crs;
389 	int	tfu;
390 	int	txa;
391 } Ctlr;
392 
393 #define csr32r(c, r)	(*((c)->nic+((r)/4)))
394 #define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))
395 
396 static Ctlr* dp83820ctlrhead;
397 static Ctlr* dp83820ctlrtail;
398 
399 static Lock dp83820rblock;		/* free receive Blocks */
400 static Block* dp83820rbpool;
401 
402 static char* dp83820mibs[Nmibd] = {
403 	"RXErroredPkts",
404 	"RXFCSErrors",
405 	"RXMsdPktErrors",
406 	"RXFAErrors",
407 	"RXSymbolErrors",
408 	"RXFrameToLong",
409 	"RXIRLErrors",
410 	"RXBadOpcodes",
411 	"RXPauseFrames",
412 	"TXPauseFrames",
413 	"TXSQEErrors",
414 };
415 
416 static int
mdior(Ctlr * ctlr,int n)417 mdior(Ctlr* ctlr, int n)
418 {
419 	int data, i, mear, r;
420 
421 	mear = csr32r(ctlr, Mear);
422 	r = ~(Mdc|Mddir) & mear;
423 	data = 0;
424 	for(i = n-1; i >= 0; i--){
425 		if(csr32r(ctlr, Mear) & Mdio)
426 			data |= (1<<i);
427 		csr32w(ctlr, Mear, Mdc|r);
428 		csr32w(ctlr, Mear, r);
429 	}
430 	csr32w(ctlr, Mear, mear);
431 
432 	return data;
433 }
434 
435 static void
mdiow(Ctlr * ctlr,int bits,int n)436 mdiow(Ctlr* ctlr, int bits, int n)
437 {
438 	int i, mear, r;
439 
440 	mear = csr32r(ctlr, Mear);
441 	r = Mddir|(~Mdc & mear);
442 	for(i = n-1; i >= 0; i--){
443 		if(bits & (1<<i))
444 			r |= Mdio;
445 		else
446 			r &= ~Mdio;
447 		csr32w(ctlr, Mear, r);
448 		csr32w(ctlr, Mear, Mdc|r);
449 	}
450 	csr32w(ctlr, Mear, mear);
451 }
452 
453 static int
dp83820miimir(Mii * mii,int pa,int ra)454 dp83820miimir(Mii* mii, int pa, int ra)
455 {
456 	int data;
457 	Ctlr *ctlr;
458 
459 	ctlr = mii->ctlr;
460 
461 	/*
462 	 * MII Management Interface Read.
463 	 *
464 	 * Preamble;
465 	 * ST+OP+PA+RA;
466 	 * LT + 16 data bits.
467 	 */
468 	mdiow(ctlr, 0xFFFFFFFF, 32);
469 	mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
470 	data = mdior(ctlr, 18);
471 
472 	if(data & 0x10000)
473 		return -1;
474 
475 	return data & 0xFFFF;
476 }
477 
478 static int
dp83820miimiw(Mii * mii,int pa,int ra,int data)479 dp83820miimiw(Mii* mii, int pa, int ra, int data)
480 {
481 	Ctlr *ctlr;
482 
483 	ctlr = mii->ctlr;
484 
485 	/*
486 	 * MII Management Interface Write.
487 	 *
488 	 * Preamble;
489 	 * ST+OP+PA+RA+LT + 16 data bits;
490 	 * Z.
491 	 */
492 	mdiow(ctlr, 0xFFFFFFFF, 32);
493 	data &= 0xFFFF;
494 	data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
495 	mdiow(ctlr, data, 32);
496 
497 	return 0;
498 }
499 
500 static Block *
dp83820rballoc(Desc * desc)501 dp83820rballoc(Desc* desc)
502 {
503 	Block *bp;
504 
505 	if(desc->bp == nil){
506 		ilock(&dp83820rblock);
507 		if((bp = dp83820rbpool) == nil){
508 			iunlock(&dp83820rblock);
509 			desc->bp = nil;
510 			desc->cmdsts = Own;
511 			return nil;
512 		}
513 		dp83820rbpool = bp->next;
514 		bp->next = nil;
515 		_xinc(&bp->ref);	/* prevent bp from being freed */
516 		iunlock(&dp83820rblock);
517 
518 		desc->bufptr = PCIWADDR(bp->rp);
519 		desc->bp = bp;
520 	}
521 	else{
522 		bp = desc->bp;
523 		bp->rp = bp->lim - Rbsz;
524 		bp->wp = bp->rp;
525 	}
526 
527 	coherence();
528 	desc->cmdsts = Intr|Rbsz;
529 
530 	return bp;
531 }
532 
533 static void
dp83820rbfree(Block * bp)534 dp83820rbfree(Block *bp)
535 {
536 	bp->rp = bp->lim - Rbsz;
537 	bp->wp = bp->rp;
538 
539 	ilock(&dp83820rblock);
540 	bp->next = dp83820rbpool;
541 	dp83820rbpool = bp;
542 	iunlock(&dp83820rblock);
543 }
544 
545 static void
dp83820halt(Ctlr * ctlr)546 dp83820halt(Ctlr* ctlr)
547 {
548 	int i, timeo;
549 
550 	ilock(&ctlr->ilock);
551 	csr32w(ctlr, Imr, 0);
552 	csr32w(ctlr, Ier, 0);
553 	csr32w(ctlr, Cr, Rxd|Txd);
554 	for(timeo = 0; timeo < 1000; timeo++){
555 		if(!(csr32r(ctlr, Cr) & (Rxe|Txe)))
556 			break;
557 		microdelay(1);
558 	}
559 	csr32w(ctlr, Mibc, Frz);
560 	iunlock(&ctlr->ilock);
561 
562 	if(ctlr->rd != nil){
563 		for(i = 0; i < ctlr->nrd; i++){
564 			if(ctlr->rd[i].bp == nil)
565 				continue;
566 			freeb(ctlr->rd[i].bp);
567 			ctlr->rd[i].bp = nil;
568 		}
569 	}
570 	if(ctlr->td != nil){
571 		for(i = 0; i < ctlr->ntd; i++){
572 			if(ctlr->td[i].bp == nil)
573 				continue;
574 			freeb(ctlr->td[i].bp);
575 			ctlr->td[i].bp = nil;
576 		}
577 	}
578 }
579 
580 static void
dp83820cfg(Ctlr * ctlr)581 dp83820cfg(Ctlr* ctlr)
582 {
583 	int cfg;
584 
585 	/*
586 	 * Don't know how to deal with a TBI yet.
587 	 */
588 	if(ctlr->mii == nil)
589 		return;
590 
591 	/*
592 	 * The polarity of these bits is at the mercy
593 	 * of the board designer.
594 	 * The correct answer for all speed and duplex questions
595 	 * should be to query the phy.
596 	 */
597 	cfg = csr32r(ctlr, Cfg);
598 	if(!(cfg & Dupsts)){
599 		ctlr->rxcfg |= Rxfd;
600 		ctlr->txcfg |= Csi|Hbi;
601 		iprint("83820: full duplex, ");
602 	}
603 	else{
604 		ctlr->rxcfg &= ~Rxfd;
605 		ctlr->txcfg &= ~(Csi|Hbi);
606 		iprint("83820: half duplex, ");
607 	}
608 	csr32w(ctlr, Rxcfg, ctlr->rxcfg);
609 	csr32w(ctlr, Txcfg, ctlr->txcfg);
610 
611 	switch(cfg & (Spdsts1000|Spdsts100)){
612 	case Spdsts1000:		/* 100Mbps */
613 	default:			/* 10Mbps */
614 		ctlr->cfg &= ~Mode1000;
615 		if((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000)
616 			iprint("100Mb/s\n");
617 		else
618 			iprint("10Mb/s\n");
619 		break;
620 	case Spdsts100:			/* 1Gbps */
621 		ctlr->cfg |= Mode1000;
622 		iprint("1Gb/s\n");
623 		break;
624 	}
625 	csr32w(ctlr, Cfg, ctlr->cfg);
626 }
627 
628 static void
dp83820init(Ether * edev)629 dp83820init(Ether* edev)
630 {
631 	int i;
632 	Ctlr *ctlr;
633 	Desc *desc;
634 	uchar *alloc;
635 
636 	ctlr = edev->ctlr;
637 
638 	dp83820halt(ctlr);
639 
640 	/*
641 	 * Receiver
642 	 */
643 	alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 8);
644 	ctlr->rd = (Desc*)alloc;
645 	alloc += ctlr->nrd*sizeof(Desc);
646 	memset(ctlr->rd, 0, ctlr->nrd*sizeof(Desc));
647 	ctlr->rdx = 0;
648 	for(i = 0; i < ctlr->nrd; i++){
649 		desc = &ctlr->rd[i];
650 		desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]);
651 		if(dp83820rballoc(desc) == nil)
652 			continue;
653 	}
654 	csr32w(ctlr, Rxdphi, 0);
655 	csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd));
656 
657 	for(i = 0; i < Eaddrlen; i += 2){
658 		csr32w(ctlr, Rfcr, i);
659 		csr32w(ctlr, Rfdr, (edev->ea[i+1]<<8)|edev->ea[i]);
660 	}
661 	csr32w(ctlr, Rfcr, Rfen|Aab|Aam|Apm);
662 
663 	ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT);
664 	ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok;
665 
666 	/*
667 	 * Transmitter.
668 	 */
669 	ctlr->td = (Desc*)alloc;
670 	memset(ctlr->td, 0, ctlr->ntd*sizeof(Desc));
671 	ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;
672 	for(i = 0; i < ctlr->ntd; i++){
673 		desc = &ctlr->td[i];
674 		desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]);
675 	}
676 	csr32w(ctlr, Txdphi, 0);
677 	csr32w(ctlr, Txdp, PCIWADDR(ctlr->td));
678 
679 	ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT);
680 	ctlr->imr |= Txurn|Txidle|Txdesc|Txok;
681 
682 	ilock(&ctlr->ilock);
683 
684 	dp83820cfg(ctlr);
685 
686 	csr32w(ctlr, Mibc, Aclr);
687 	ctlr->imr |= Mib;
688 
689 	csr32w(ctlr, Imr, ctlr->imr);
690 
691 	/* try coalescing adjacent interrupts; use hold-off interval of 100µs */
692 	csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT));
693 
694 	csr32w(ctlr, Ier, Ien);
695 	csr32w(ctlr, Cr, Rxe|Txe);
696 
697 	iunlock(&ctlr->ilock);
698 }
699 
700 static void
dp83820attach(Ether * edev)701 dp83820attach(Ether* edev)
702 {
703 	Block *bp;
704 	Ctlr *ctlr;
705 
706 	ctlr = edev->ctlr;
707 	qlock(&ctlr->alock);
708 	if(ctlr->alloc != nil){
709 		qunlock(&ctlr->alock);
710 		return;
711 	}
712 
713 	if(waserror()){
714 		if(ctlr->mii != nil){
715 			free(ctlr->mii);
716 			ctlr->mii = nil;
717 		}
718 		if(ctlr->alloc != nil){
719 			free(ctlr->alloc);
720 			ctlr->alloc = nil;
721 		}
722 		qunlock(&ctlr->alock);
723 		nexterror();
724 	}
725 
726 	if(!(ctlr->cfg & Tbien)){
727 		if((ctlr->mii = malloc(sizeof(Mii))) == nil)
728 			error(Enomem);
729 		ctlr->mii->ctlr = ctlr;
730 		ctlr->mii->mir = dp83820miimir;
731 		ctlr->mii->miw = dp83820miimiw;
732 		if(mii(ctlr->mii, ~0) == 0)
733 			error("no PHY");
734 		ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien;
735 		ctlr->imr |= Phy;
736 	}
737 
738 	ctlr->nrd = Nrd;
739 	ctlr->nrb = Nrb;
740 	ctlr->ntd = Ntd;
741 	ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0);
742 	if(ctlr->alloc == nil)
743 		error(Enomem);
744 
745 	for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){
746 		if((bp = allocb(Rbsz)) == nil)
747 			break;
748 		bp->free = dp83820rbfree;
749 		dp83820rbfree(bp);
750 	}
751 
752 	dp83820init(edev);
753 
754 	qunlock(&ctlr->alock);
755 	poperror();
756 }
757 
758 static void
dp83820transmit(Ether * edev)759 dp83820transmit(Ether* edev)
760 {
761 	Block *bp;
762 	Ctlr *ctlr;
763 	Desc *desc;
764 	int cmdsts, r, x;
765 
766 	ctlr = edev->ctlr;
767 
768 	ilock(&ctlr->tlock);
769 
770 	bp = nil;
771 	for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){
772 		desc = &ctlr->td[x];
773 		if((cmdsts = desc->cmdsts) & Own)
774 			break;
775 		if(!(cmdsts & Ok)){
776 			if(cmdsts & Ec)
777 				ctlr->ec++;
778 			if(cmdsts & Owc)
779 				ctlr->owc++;
780 			if(cmdsts & Ed)
781 				ctlr->ed++;
782 			if(cmdsts & Crs)
783 				ctlr->crs++;
784 			if(cmdsts & Tfu)
785 				ctlr->tfu++;
786 			if(cmdsts & Txa)
787 				ctlr->txa++;
788 			edev->oerrs++;
789 		}
790 		desc->bp->next = bp;
791 		bp = desc->bp;
792 		desc->bp = nil;
793 
794 		ctlr->ntq--;
795 	}
796 	ctlr->tdh = x;
797 	if(bp != nil)
798 		freeblist(bp);
799 
800 	x = ctlr->tdt;
801 	while(ctlr->ntq < (ctlr->ntd-1)){
802 		if((bp = qget(edev->oq)) == nil)
803 			break;
804 
805 		desc = &ctlr->td[x];
806 		desc->bufptr = PCIWADDR(bp->rp);
807 		desc->bp = bp;
808 		ctlr->ntq++;
809 		coherence();
810 		desc->cmdsts = Own|Intr|BLEN(bp);
811 
812 		x = NEXT(x, ctlr->ntd);
813 	}
814 	if(x != ctlr->tdt){
815 		ctlr->tdt = x;
816 		r = csr32r(ctlr, Cr);
817 		csr32w(ctlr, Cr, Txe|r);
818 	}
819 
820 	iunlock(&ctlr->tlock);
821 }
822 
823 static void
dp83820interrupt(Ureg *,void * arg)824 dp83820interrupt(Ureg*, void* arg)
825 {
826 	Block *bp;
827 	Ctlr *ctlr;
828 	Desc *desc;
829 	Ether *edev;
830 	int cmdsts, i, isr, r, x;
831 
832 	edev = arg;
833 	ctlr = edev->ctlr;
834 
835 	for(isr = csr32r(ctlr, Isr); isr & ctlr->imr; isr = csr32r(ctlr, Isr)){
836 		if(isr & (Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok)){
837 			x = ctlr->rdx;
838 			desc = &ctlr->rd[x];
839 			while((cmdsts = desc->cmdsts) & Own){
840 				if((cmdsts & Ok) && desc->bp != nil){
841 					bp = desc->bp;
842 					desc->bp = nil;
843 					bp->wp += cmdsts & SizeMASK;
844 					etheriq(edev, bp, 1);
845 				}
846 				else if(0 && !(cmdsts & Ok)){
847 					iprint("dp83820: rx %8.8uX:", cmdsts);
848 					bp = desc->bp;
849 					for(i = 0; i < 20; i++)
850 						iprint(" %2.2uX", bp->rp[i]);
851 					iprint("\n");
852 				}
853 				dp83820rballoc(desc);
854 
855 				x = NEXT(x, ctlr->nrd);
856 				desc = &ctlr->rd[x];
857 			}
858 			ctlr->rdx = x;
859 
860 			if(isr & Rxidle){
861 				r = csr32r(ctlr, Cr);
862 				csr32w(ctlr, Cr, Rxe|r);
863 				ctlr->rxidle++;
864 			}
865 
866 			isr &= ~(Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok);
867 		}
868 
869 		if(isr & Txurn){
870 			x = (ctlr->txcfg & TxdrthMASK)>>TxdrthSHFT;
871 			r = (ctlr->txcfg & FlthMASK)>>FlthSHFT;
872 			if(x < ((TxdrthMASK)>>TxdrthSHFT)
873 			&& x < (2048/32 - r)){
874 				ctlr->txcfg &= ~TxdrthMASK;
875 				x++;
876 				ctlr->txcfg |= x<<TxdrthSHFT;
877 				csr32w(ctlr, Txcfg, ctlr->txcfg);
878 			}
879 		}
880 
881 		if(isr & (Txurn|Txidle|Txdesc|Txok)){
882 			dp83820transmit(edev);
883 			isr &= ~(Txurn|Txidle|Txdesc|Txok);
884 		}
885 
886 		if(isr & Mib){
887 			for(i = 0; i < Nmibd; i++){
888 				r = csr32r(ctlr, Mibd+(i*sizeof(int)));
889 				ctlr->mibd[i] += r & 0xFFFF;
890 			}
891 			isr &= ~Mib;
892 		}
893 
894 		if((isr & Phy) && ctlr->mii != nil){
895 			ctlr->mii->mir(ctlr->mii, 1, Bmsr);
896 			print("phy: cfg %8.8uX bmsr %4.4uX\n",
897 				csr32r(ctlr, Cfg),
898 				ctlr->mii->mir(ctlr->mii, 1, Bmsr));
899 			dp83820cfg(ctlr);
900 			isr &= ~Phy;
901 		}
902 		if(isr)
903 			iprint("dp83820: isr %8.8uX\n", isr);
904 	}
905 }
906 
907 static long
dp83820ifstat(Ether * edev,void * a,long n,ulong offset)908 dp83820ifstat(Ether* edev, void* a, long n, ulong offset)
909 {
910 	char *p;
911 	Ctlr *ctlr;
912 	int i, l, r;
913 
914 	ctlr = edev->ctlr;
915 
916 	edev->crcs = ctlr->mibd[Mibd+(1*sizeof(int))];
917 	edev->frames = ctlr->mibd[Mibd+(3*sizeof(int))];
918 	edev->buffs = ctlr->mibd[Mibd+(5*sizeof(int))];
919 	edev->overflows = ctlr->mibd[Mibd+(2*sizeof(int))];
920 
921 	if(n == 0)
922 		return 0;
923 
924 	p = malloc(READSTR);
925 	if(p == nil)
926 		error(Enomem);
927 	l = 0;
928 	for(i = 0; i < Nmibd; i++){
929 		r = csr32r(ctlr, Mibd+(i*sizeof(int)));
930 		ctlr->mibd[i] += r & 0xFFFF;
931 		if(ctlr->mibd[i] != 0 && dp83820mibs[i] != nil)
932 			l += snprint(p+l, READSTR-l, "%s: %ud %ud\n",
933 				dp83820mibs[i], ctlr->mibd[i], r);
934 	}
935 	l += snprint(p+l, READSTR-l, "rxidle %d\n", ctlr->rxidle);
936 	l += snprint(p+l, READSTR-l, "ec %d\n", ctlr->ec);
937 	l += snprint(p+l, READSTR-l, "owc %d\n", ctlr->owc);
938 	l += snprint(p+l, READSTR-l, "ed %d\n", ctlr->ed);
939 	l += snprint(p+l, READSTR-l, "crs %d\n", ctlr->crs);
940 	l += snprint(p+l, READSTR-l, "tfu %d\n", ctlr->tfu);
941 	l += snprint(p+l, READSTR-l, "txa %d\n", ctlr->txa);
942 
943 	l += snprint(p+l, READSTR, "rom:");
944 	for(i = 0; i < 0x10; i++){
945 		if(i && ((i & 0x07) == 0))
946 			l += snprint(p+l, READSTR-l, "\n    ");
947 		l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]);
948 	}
949 	l += snprint(p+l, READSTR-l, "\n");
950 
951 	if(ctlr->mii != nil && ctlr->mii->curphy != nil){
952 		l += snprint(p+l, READSTR, "phy:");
953 		for(i = 0; i < NMiiPhyr; i++){
954 			if(i && ((i & 0x07) == 0))
955 				l += snprint(p+l, READSTR-l, "\n    ");
956 			r = miimir(ctlr->mii, i);
957 			l += snprint(p+l, READSTR-l, " %4.4uX", r);
958 		}
959 		snprint(p+l, READSTR-l, "\n");
960 	}
961 
962 	n = readstr(offset, a, n, p);
963 	free(p);
964 
965 	return n;
966 }
967 
968 static void
dp83820promiscuous(void * arg,int on)969 dp83820promiscuous(void* arg, int on)
970 {
971 	USED(arg, on);
972 }
973 
974 /* multicast already on, don't need to do anything */
975 static void
dp83820multicast(void *,uchar *,int)976 dp83820multicast(void*, uchar*, int)
977 {
978 }
979 
980 static int
dp83820detach(Ctlr * ctlr)981 dp83820detach(Ctlr* ctlr)
982 {
983 	/*
984 	 * Soft reset the controller.
985 	 */
986 	csr32w(ctlr, Cr, Rst);
987 	delay(1);
988 	while(csr32r(ctlr, Cr) & Rst)
989 		delay(1);
990 	return 0;
991 }
992 
993 static void
dp83820shutdown(Ether * ether)994 dp83820shutdown(Ether* ether)
995 {
996 print("dp83820shutdown\n");
997 	dp83820detach(ether->ctlr);
998 }
999 
1000 static int
atc93c46r(Ctlr * ctlr,int address)1001 atc93c46r(Ctlr* ctlr, int address)
1002 {
1003 	int data, i, mear, r, size;
1004 
1005 	/*
1006 	 * Analog Technology, Inc. ATC93C46
1007 	 * or equivalent serial EEPROM.
1008 	 */
1009 	mear = csr32r(ctlr, Mear);
1010 	mear &= ~(Eesel|Eeclk|Eedo|Eedi);
1011 	r = Eesel|mear;
1012 
1013 reread:
1014 	csr32w(ctlr, Mear, r);
1015 	data = 0x06;
1016 	for(i = 3-1; i >= 0; i--){
1017 		if(data & (1<<i))
1018 			r |= Eedi;
1019 		else
1020 			r &= ~Eedi;
1021 		csr32w(ctlr, Mear, r);
1022 		csr32w(ctlr, Mear, Eeclk|r);
1023 		microdelay(1);
1024 		csr32w(ctlr, Mear, r);
1025 		microdelay(1);
1026 	}
1027 
1028 	/*
1029 	 * First time through must work out the EEPROM size.
1030 	 */
1031 	if((size = ctlr->eepromsz) == 0)
1032 		size = 8;
1033 
1034 	for(size = size-1; size >= 0; size--){
1035 		if(address & (1<<size))
1036 			r |= Eedi;
1037 		else
1038 			r &= ~Eedi;
1039 		csr32w(ctlr, Mear, r);
1040 		microdelay(1);
1041 		csr32w(ctlr, Mear, Eeclk|r);
1042 		microdelay(1);
1043 		csr32w(ctlr, Mear, r);
1044 		microdelay(1);
1045 		if(!(csr32r(ctlr, Mear) & Eedo))
1046 			break;
1047 	}
1048 	r &= ~Eedi;
1049 
1050 	data = 0;
1051 	for(i = 16-1; i >= 0; i--){
1052 		csr32w(ctlr, Mear, Eeclk|r);
1053 		microdelay(1);
1054 		if(csr32r(ctlr, Mear) & Eedo)
1055 			data |= (1<<i);
1056 		csr32w(ctlr, Mear, r);
1057 		microdelay(1);
1058 	}
1059 
1060 	csr32w(ctlr, Mear, mear);
1061 
1062 	if(ctlr->eepromsz == 0){
1063 		ctlr->eepromsz = 8-size;
1064 		ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
1065 		if(ctlr->eeprom == nil)
1066 			error(Enomem);
1067 		goto reread;
1068 	}
1069 
1070 	return data;
1071 }
1072 
1073 static int
dp83820reset(Ctlr * ctlr)1074 dp83820reset(Ctlr* ctlr)
1075 {
1076 	int i, r;
1077 	unsigned char sum;
1078 
1079 	/*
1080 	 * Soft reset the controller;
1081 	 * read the EEPROM to get the initial settings
1082 	 * of the Cfg and Gpior bits which should be cleared by
1083 	 * the reset.
1084 	 */
1085 	dp83820detach(ctlr);
1086 
1087 	atc93c46r(ctlr, 0);
1088 	if(ctlr->eeprom == nil) {
1089 		print("dp83820reset: no eeprom\n");
1090 		return -1;
1091 	}
1092 	sum = 0;
1093 	for(i = 0; i < 0x0E; i++){
1094 		r = atc93c46r(ctlr, i);
1095 		ctlr->eeprom[i] = r;
1096 		sum += r;
1097 		sum += r>>8;
1098 	}
1099 
1100 	if(sum != 0){
1101 		print("dp83820reset: bad EEPROM checksum\n");
1102 		return -1;
1103 	}
1104 
1105 #ifdef notdef
1106 	csr32w(ctlr, Gpior, ctlr->eeprom[4]);
1107 
1108 	cfg = Extstsen|Exd;
1109 	r = csr32r(ctlr, Cfg);
1110 	if(ctlr->eeprom[5] & 0x0001)
1111 		cfg |= Ext125;
1112 	if(ctlr->eeprom[5] & 0x0002)
1113 		cfg |= M64addren;
1114 	if((ctlr->eeprom[5] & 0x0004) && (r & Pci64det))
1115 		cfg |= Data64en;
1116 	if(ctlr->eeprom[5] & 0x0008)
1117 		cfg |= T64addren;
1118 	if(!(pcicfgr16(ctlr->pcidev, PciPCR) & 0x10))
1119 		cfg |= Mwidis;
1120 	if(ctlr->eeprom[5] & 0x0020)
1121 		cfg |= Mrmdis;
1122 	if(ctlr->eeprom[5] & 0x0080)
1123 		cfg |= Mode1000;
1124 	if(ctlr->eeprom[5] & 0x0200)
1125 		cfg |= Tbien|Mode1000;
1126 	/*
1127 	 * What about RO bits we might have destroyed with Rst?
1128 	 * What about Exd, Tmrtest, Extstsen, Pintctl?
1129 	 * Why does it think it has detected a 64-bit bus when
1130 	 * it hasn't?
1131 	 */
1132 #else
1133 	// r = csr32r(ctlr, Cfg);
1134 	// r &= ~(Mode1000|T64addren|Data64en|M64addren);
1135 	// csr32w(ctlr, Cfg, r);
1136 	// csr32w(ctlr, Cfg, 0x2000);
1137 #endif						/* notdef */
1138 	ctlr->cfg = csr32r(ctlr, Cfg);
1139 print("cfg %8.8uX pcicfg %8.8uX\n", ctlr->cfg, pcicfgr32(ctlr->pcidev, PciPCR));
1140 	ctlr->cfg &= ~(T64addren|Data64en|M64addren);
1141 	csr32w(ctlr, Cfg, ctlr->cfg);
1142 	csr32w(ctlr, Mibc, Aclr|Frz);
1143 
1144 	return 0;
1145 }
1146 
1147 static void
dp83820pci(void)1148 dp83820pci(void)
1149 {
1150 	void *mem;
1151 	Pcidev *p;
1152 	Ctlr *ctlr;
1153 
1154 	p = nil;
1155 	while(p = pcimatch(p, 0, 0)){
1156 		if(p->ccrb != Pcibcnet || p->ccru != Pciscether)
1157 			continue;
1158 
1159 		switch((p->did<<16)|p->vid){
1160 		default:
1161 			continue;
1162 		case (0x0022<<16)|0x100B:	/* DP83820 (Gig-NIC) */
1163 			break;
1164 		}
1165 
1166 		mem = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);
1167 		if(mem == 0){
1168 			print("DP83820: can't map %8.8luX\n", p->mem[1].bar);
1169 			continue;
1170 		}
1171 
1172 		ctlr = malloc(sizeof(Ctlr));
1173 		if(ctlr == nil) {
1174 			vunmap(mem, p->mem[1].size);
1175 			error(Enomem);
1176 		}
1177 		ctlr->port = p->mem[1].bar & ~0x0F;
1178 		ctlr->pcidev = p;
1179 		ctlr->id = (p->did<<16)|p->vid;
1180 
1181 		ctlr->nic = mem;
1182 		if(dp83820reset(ctlr)){
1183 			free(ctlr);
1184 			vunmap(mem, p->mem[1].size);
1185 			continue;
1186 		}
1187 		pcisetbme(p);
1188 
1189 		if(dp83820ctlrhead != nil)
1190 			dp83820ctlrtail->next = ctlr;
1191 		else
1192 			dp83820ctlrhead = ctlr;
1193 		dp83820ctlrtail = ctlr;
1194 	}
1195 }
1196 
1197 static int
dp83820pnp(Ether * edev)1198 dp83820pnp(Ether* edev)
1199 {
1200 	int i;
1201 	Ctlr *ctlr;
1202 	uchar ea[Eaddrlen];
1203 
1204 	if(dp83820ctlrhead == nil)
1205 		dp83820pci();
1206 
1207 	/*
1208 	 * Any adapter matches if no edev->port is supplied,
1209 	 * otherwise the ports must match.
1210 	 */
1211 	for(ctlr = dp83820ctlrhead; ctlr != nil; ctlr = ctlr->next){
1212 		if(ctlr->active)
1213 			continue;
1214 		if(edev->port == 0 || edev->port == ctlr->port){
1215 			ctlr->active = 1;
1216 			break;
1217 		}
1218 	}
1219 	if(ctlr == nil)
1220 		return -1;
1221 
1222 	edev->ctlr = ctlr;
1223 	edev->port = ctlr->port;
1224 	edev->irq = ctlr->pcidev->intl;
1225 	edev->tbdf = ctlr->pcidev->tbdf;
1226 	edev->mbps = 1000;
1227 
1228 	/*
1229 	 * Check if the adapter's station address is to be overridden.
1230 	 * If not, read it from the EEPROM and set in ether->ea prior to
1231 	 * loading the station address in the hardware.
1232 	 */
1233 	memset(ea, 0, Eaddrlen);
1234 	if(memcmp(ea, edev->ea, Eaddrlen) == 0)
1235 		for(i = 0; i < Eaddrlen/2; i++){
1236 			edev->ea[2*i] = ctlr->eeprom[0x0C-i];
1237 			edev->ea[2*i+1] = ctlr->eeprom[0x0C-i]>>8;
1238 		}
1239 
1240 	edev->attach = dp83820attach;
1241 	edev->transmit = dp83820transmit;
1242 	edev->interrupt = dp83820interrupt;
1243 	edev->ifstat = dp83820ifstat;
1244 
1245 	edev->arg = edev;
1246 	edev->promiscuous = dp83820promiscuous;
1247 	edev->multicast = dp83820multicast;
1248 	edev->shutdown = dp83820shutdown;
1249 
1250 	return 0;
1251 }
1252 
1253 void
etherdp83820link(void)1254 etherdp83820link(void)
1255 {
1256 	addethercard("DP83820", dp83820pnp);
1257 }
1258