xref: /inferno-os/os/boot/pc/ether82563.c (revision 8a8c2d742b51525f66c2210e3c8a251de10022ff)
1 /*
2  * bootstrap driver for
3  * Intel 82563, 82571, 82573 Gigabit Ethernet PCI-Express Controllers
4  */
5 #include "u.h"
6 #include "lib.h"
7 #include "mem.h"
8 #include "dat.h"
9 #include "fns.h"
10 #include "io.h"
11 
12 #include "etherif.h"
13 
14 /* compatibility with cpu kernels */
15 #define iallocb allocb
16 #ifndef CACHELINESZ
17 #define CACHELINESZ	32		/* pentium & later */
18 #endif
19 
20 /* from pci.c */
21 enum
22 {					/* command register pcidev->pcr */
23 	IOen		= 1<<0,
24 	MEMen		= 1<<1,
25 	MASen		= 1<<2,
26 	MemWrInv	= 1<<4,
27 	PErrEn		= 1<<6,
28 	SErrEn		= 1<<8,
29 };
30 
31 /*
32  * these are in the order they appear in the manual, not numeric order.
33  * It was too hard to find them in the book. Ref 21489, rev 2.6
34  */
35 
36 enum {
37 	/* General */
38 
39 	Ctrl		= 0x00000000,	/* Device Control */
40 	Status		= 0x00000008,	/* Device Status */
41 	Eec		= 0x00000010,	/* EEPROM/Flash Control/Data */
42 	Eerd		= 0x00000014,	/* EEPROM Read */
43 	Ctrlext		= 0x00000018,	/* Extended Device Control */
44 	Fla		= 0x0000001c,	/* Flash Access */
45 	Mdic		= 0x00000020,	/* MDI Control */
46 	Seresctl	= 0x00000024,	/* Serdes ana */
47 	Fcal		= 0x00000028,	/* Flow Control Address Low */
48 	Fcah		= 0x0000002C,	/* Flow Control Address High */
49 	Fct		= 0x00000030,	/* Flow Control Type */
50 	Kumctrlsta	= 0x00000034,	/* Kumeran Controll and Status Register */
51 	Vet		= 0x00000038,	/* VLAN EtherType */
52 	Fcttv		= 0x00000170,	/* Flow Control Transmit Timer Value */
53 	Txcw		= 0x00000178,	/* Transmit Configuration Word */
54 	Rxcw		= 0x00000180,	/* Receive Configuration Word */
55 	Ledctl		= 0x00000E00,	/* LED control */
56 	Pba		= 0x00001000,	/* Packet Buffer Allocation */
57 
58 	/* Interrupt */
59 
60 	Icr		= 0x000000C0,	/* Interrupt Cause Read */
61 	Ics		= 0x000000C8,	/* Interrupt Cause Set */
62 	Ims		= 0x000000D0,	/* Interrupt Mask Set/Read */
63 	Imc		= 0x000000D8,	/* Interrupt mask Clear */
64 	Iam		= 0x000000E0,	/* Interrupt acknowledge Auto Mask */
65 
66 	/* Receive */
67 
68 	Rctl		= 0x00000100,	/* Receive Control */
69 	Ert		= 0x00002008,	/* Early Receive Threshold (573[EVL] only) */
70 	Fcrtl		= 0x00002160,	/* Flow Control RX Threshold Low */
71 	Fcrth		= 0x00002168,	/* Flow Control Rx Threshold High */
72 	Psrctl		= 0x00002170,	/* Packet Split Receive Control */
73 	Rdbal		= 0x00002800,	/* Rdesc Base Address Low Queue 0 */
74 	Rdbah		= 0x00002804,	/* Rdesc Base Address High Queue 0 */
75 	Rdlen		= 0x00002808,	/* Receive Descriptor Length Queue 0 */
76 	Rdh		= 0x00002810,	/* Receive Descriptor Head Queue 0 */
77 	Rdt		= 0x00002818,	/* Receive Descriptor Tail Queue 0 */
78 	Rdtr		= 0x00002820,	/* Receive Descriptor Timer Ring */
79 	Rxdctl		= 0x00002828,	/* Receive Descriptor Control */
80 	Radv		= 0x0000282C,	/* Receive Interrupt Absolute Delay Timer */
81 	Rdbal1		= 0x00002900,	/* Rdesc Base Address Low Queue 1 */
82 	Rdbah1		= 0x00002804,	/* Rdesc Base Address High Queue 1 */
83 	Rdlen1		= 0x00002908,	/* Receive Descriptor Length Queue 1 */
84 	Rdh1		= 0x00002910,	/* Receive Descriptor Head Queue 1 */
85 	Rdt1		= 0x00002918,	/* Receive Descriptor Tail Queue 1 */
86 	Rxdctl1		= 0x00002928,	/* Receive Descriptor Control Queue 1 */
87 	Rsrpd		= 0x00002c00,	/* Receive Small Packet Detect */
88 	Raid		= 0x00002c08,	/* Receive ACK interrupt delay */
89 	Cpuvec		= 0x00002c10,	/* CPU Vector */
90 	Rxcsum		= 0x00005000,	/* Receive Checksum Control */
91 	Rfctl		= 0x00005008,	/* Receive Filter Control */
92 	Mta		= 0x00005200,	/* Multicast Table Array */
93 	Ral		= 0x00005400,	/* Receive Address Low */
94 	Rah		= 0x00005404,	/* Receive Address High */
95 	Vfta		= 0x00005600,	/* VLAN Filter Table Array */
96 	Mrqc		= 0x00005818,	/* Multiple Receive Queues Command */
97 	Rssim		= 0x00005864,	/* RSS Interrupt Mask */
98 	Rssir		= 0x00005868,	/* RSS Interrupt Request */
99 	Reta		= 0x00005c00,	/* Redirection Table */
100 	Rssrk		= 0x00005c80,	/* RSS Random Key */
101 
102 	/* Transmit */
103 
104 	Tctl		= 0x00000400,	/* Transmit Control */
105 	Tipg		= 0x00000410,	/* Transmit IPG */
106 	Tdbal		= 0x00003800,	/* Tdesc Base Address Low */
107 	Tdbah		= 0x00003804,	/* Tdesc Base Address High */
108 	Tdlen		= 0x00003808,	/* Transmit Descriptor Length */
109 	Tdh		= 0x00003810,	/* Transmit Descriptor Head */
110 	Tdt		= 0x00003818,	/* Transmit Descriptor Tail */
111 	Tidv		= 0x00003820,	/* Transmit Interrupt Delay Value */
112 	Txdctl		= 0x00003828,	/* Transmit Descriptor Control */
113 	Tadv		= 0x0000382C,	/* Transmit Interrupt Absolute Delay Timer */
114 	Tarc0		= 0x00003840,	/* Transmit Arbitration Counter Queue 0 */
115 	Tdbal1		= 0x00003900,	/* Transmit Descriptor Base Low Queue 1 */
116 	Tdbah1		= 0x00003904,	/* Transmit Descriptor Base High Queue 1 */
117 	Tdlen1		= 0x00003908,	/* Transmit Descriptor Length Queue 1 */
118 	Tdh1		= 0x00003910,	/* Transmit Descriptor Head Queue 1 */
119 	Tdt1		= 0x00003918,	/* Transmit Descriptor Tail Queue 1 */
120 	Txdctl1		= 0x00003928,	/* Transmit Descriptor Control 1 */
121 	Tarc1		= 0x00003940,	/* Transmit Arbitration Counter Queue 1 */
122 
123 	/* Statistics */
124 
125 	Statistics	= 0x00004000,	/* Start of Statistics Area */
126 	Gorcl		= 0x88/4,	/* Good Octets Received Count */
127 	Gotcl		= 0x90/4,	/* Good Octets Transmitted Count */
128 	Torl		= 0xC0/4,	/* Total Octets Received */
129 	Totl		= 0xC8/4,	/* Total Octets Transmitted */
130 	Nstatistics	= 64,
131 
132 };
133 
134 enum {					/* Ctrl */
135 	GIOmd		= 1<<2,		/* BIO master disable */
136 	Lrst		= 1<<3,		/* link reset */
137 	Slu		= 1<<6,		/* Set Link Up */
138 	SspeedMASK	= 3<<8,		/* Speed Selection */
139 	SspeedSHIFT	= 8,
140 	Sspeed10	= 0x00000000,	/* 10Mb/s */
141 	Sspeed100	= 0x00000100,	/* 100Mb/s */
142 	Sspeed1000	= 0x00000200,	/* 1000Mb/s */
143 	Frcspd		= 1<<11,	/* Force Speed */
144 	Frcdplx		= 1<<12,	/* Force Duplex */
145 	SwdpinsloMASK	= 0x003C0000,	/* Software Defined Pins - lo nibble */
146 	SwdpinsloSHIFT	= 18,
147 	SwdpioloMASK	= 0x03C00000,	/* Software Defined Pins - I or O */
148 	SwdpioloSHIFT	= 22,
149 	Devrst		= 1<<26,	/* Device Reset */
150 	Rfce		= 1<<27,	/* Receive Flow Control Enable */
151 	Tfce		= 1<<28,	/* Transmit Flow Control Enable */
152 	Vme		= 1<<30,	/* VLAN Mode Enable */
153 	Phy_rst		= 1<<31,	/* Phy Reset */
154 };
155 
156 enum {					/* Status */
157 	Lu		= 1<<1,		/* Link Up */
158 	Lanid		= 3<<2,		/* mask for Lan ID. */
159 	Txoff		= 1<<4,		/* Transmission Paused */
160 	Tbimode		= 1<<5,		/* TBI Mode Indication */
161 	SpeedMASK	= 0x000000C0,
162 	Speed10		= 0x00000000,	/* 10Mb/s */
163 	Speed100	= 0x00000040,	/* 100Mb/s */
164 	Speed1000	= 0x00000080,	/* 1000Mb/s */
165 	Phyra		= 1<<10,	/* PHY Reset Asserted */
166 	GIOme		= 1<<19,	/* GIO Master Enable Status */
167 };
168 
169 enum {					/* Ctrl and Status */
170 	Fd		= 0x00000001,	/* Full-Duplex */
171 	AsdvMASK	= 0x00000300,
172 	Asdv10		= 0x00000000,	/* 10Mb/s */
173 	Asdv100		= 0x00000100,	/* 100Mb/s */
174 	Asdv1000	= 0x00000200,	/* 1000Mb/s */
175 };
176 
177 enum {					/* Eec */
178 	Sk		= 1<<0,		/* Clock input to the EEPROM */
179 	Cs		= 1<<1,		/* Chip Select */
180 	Di		= 1<<2,		/* Data Input to the EEPROM */
181 	Do		= 1<<3,		/* Data Output from the EEPROM */
182 	Areq		= 1<<6,		/* EEPROM Access Request */
183 	Agnt		= 1<<7,		/* EEPROM Access Grant */
184 };
185 
186 enum {					/* Eerd */
187 	ee_start	= 1<<0,		/* Start Read */
188 	ee_done		= 1<<1,		/* Read done */
189 	ee_addr		= 0xfff8<<2,	/* Read address [15:2] */
190 	ee_data		= 0xffff<<16,	/* Read Data; Data returned from eeprom/nvm */
191 };
192 
193 enum {					/* Ctrlext */
194 	Asdchk		= 1<<12,	/* ASD Check */
195 	Eerst		= 1<<13,	/* EEPROM Reset */
196 	Spdbyps		= 1<<15,	/* Speed Select Bypass */
197 };
198 
199 enum {					/* EEPROM content offsets */
200 	Ea		= 0x00,		/* Ethernet Address */
201 	Cf		= 0x03,		/* Compatibility Field */
202 	Icw1		= 0x0A,		/* Initialization Control Word 1 */
203 	Sid		= 0x0B,		/* Subsystem ID */
204 	Svid		= 0x0C,		/* Subsystem Vendor ID */
205 	Did		= 0x0D,		/* Device ID */
206 	Vid		= 0x0E,		/* Vendor ID */
207 	Icw2		= 0x0F,		/* Initialization Control Word 2 */
208 };
209 
210 enum {					/* Mdic */
211 	MDIdMASK	= 0x0000FFFF,	/* Data */
212 	MDIdSHIFT	= 0,
213 	MDIrMASK	= 0x001F0000,	/* PHY Register Address */
214 	MDIrSHIFT	= 16,
215 	MDIpMASK	= 0x03E00000,	/* PHY Address */
216 	MDIpSHIFT	= 21,
217 	MDIwop		= 0x04000000,	/* Write Operation */
218 	MDIrop		= 0x08000000,	/* Read Operation */
219 	MDIready	= 0x10000000,	/* End of Transaction */
220 	MDIie		= 0x20000000,	/* Interrupt Enable */
221 	MDIe		= 0x40000000,	/* Error */
222 };
223 
224 enum {					/* Icr, Ics, Ims, Imc */
225 	Txdw		= 0x00000001,	/* Transmit Descriptor Written Back */
226 	Txqe		= 0x00000002,	/* Transmit Queue Empty */
227 	Lsc		= 0x00000004,	/* Link Status Change */
228 	Rxseq		= 0x00000008,	/* Receive Sequence Error */
229 	Rxdmt0		= 0x00000010,	/* Rdesc Minimum Threshold Reached */
230 	Rxo		= 0x00000040,	/* Receiver Overrun */
231 	Rxt0		= 0x00000080,	/* Receiver Timer Interrupt */
232 	Mdac		= 0x00000200,	/* MDIO Access Completed */
233 	Rxcfg		= 0x00000400,	/* Receiving /C/ ordered sets */
234 	Gpi0		= 0x00000800,	/* General Purpose Interrupts */
235 	Gpi1		= 0x00001000,
236 	Gpi2		= 0x00002000,
237 	Gpi3		= 0x00004000,
238 	Ack		= 0x00020000,	/* receive ACK frame */
239 };
240 
241 enum {					/* Txcw */
242 	TxcwFd		= 0x00000020,	/* Full Duplex */
243 	TxcwHd		= 0x00000040,	/* Half Duplex */
244 	TxcwPauseMASK	= 0x00000180,	/* Pause */
245 	TxcwPauseSHIFT	= 7,
246 	TxcwPs		= 1<<TxcwPauseSHIFT,	/* Pause Supported */
247 	TxcwAs		= 2<<TxcwPauseSHIFT,	/* Asymmetric FC desired */
248 	TxcwRfiMASK	= 0x00003000,	/* Remote Fault Indication */
249 	TxcwRfiSHIFT	= 12,
250 	TxcwNpr		= 0x00008000,	/* Next Page Request */
251 	TxcwConfig	= 0x40000000,	/* Transmit COnfig Control */
252 	TxcwAne		= 0x80000000,	/* Auto-Negotiation Enable */
253 };
254 
255 enum {					/* Rctl */
256 	Rrst		= 0x00000001,	/* Receiver Software Reset */
257 	Ren		= 0x00000002,	/* Receiver Enable */
258 	Sbp		= 0x00000004,	/* Store Bad Packets */
259 	Upe		= 0x00000008,	/* Unicast Promiscuous Enable */
260 	Mpe		= 0x00000010,	/* Multicast Promiscuous Enable */
261 	Lpe		= 0x00000020,	/* Long Packet Reception Enable */
262 	LbmMASK		= 0x000000C0,	/* Loopback Mode */
263 	LbmOFF		= 0x00000000,	/* No Loopback */
264 	LbmTBI		= 0x00000040,	/* TBI Loopback */
265 	LbmMII		= 0x00000080,	/* GMII/MII Loopback */
266 	LbmXCVR		= 0x000000C0,	/* Transceiver Loopback */
267 	RdtmsMASK	= 0x00000300,	/* Rdesc Minimum Threshold Size */
268 	RdtmsHALF	= 0x00000000,	/* Threshold is 1/2 Rdlen */
269 	RdtmsQUARTER	= 0x00000100,	/* Threshold is 1/4 Rdlen */
270 	RdtmsEIGHTH	= 0x00000200,	/* Threshold is 1/8 Rdlen */
271 	MoMASK		= 0x00003000,	/* Multicast Offset */
272 	Bam		= 0x00008000,	/* Broadcast Accept Mode */
273 	BsizeMASK	= 0x00030000,	/* Receive Buffer Size */
274 	Bsize2048	= 0x00000000,
275 	Bsize1024	= 0x00010000,
276 	Bsize512	= 0x00020000,
277 	Bsize256	= 0x00030000,
278 	Vfe		= 0x00040000,	/* VLAN Filter Enable */
279 	Cfien		= 0x00080000,	/* Canonical Form Indicator Enable */
280 	Cfi		= 0x00100000,	/* Canonical Form Indicator value */
281 	Dpf		= 0x00400000,	/* Discard Pause Frames */
282 	Pmcf		= 0x00800000,	/* Pass MAC Control Frames */
283 	Bsex		= 0x02000000,	/* Buffer Size Extension */
284 	Secrc		= 0x04000000,	/* Strip CRC from incoming packet */
285 };
286 
287 enum {					/* Tctl */
288 	Trst		= 0x00000001,	/* Transmitter Software Reset */
289 	Ten		= 0x00000002,	/* Transmit Enable */
290 	Psp		= 0x00000008,	/* Pad Short Packets */
291 	Mulr		= 0x10000000,	/* Allow multiple concurrent requests */
292 	CtMASK		= 0x00000FF0,	/* Collision Threshold */
293 	CtSHIFT		= 4,
294 	ColdMASK	= 0x003FF000,	/* Collision Distance */
295 	ColdSHIFT	= 12,
296 	Swxoff		= 0x00400000,	/* Sofware XOFF Transmission */
297 	Pbe		= 0x00800000,	/* Packet Burst Enable */
298 	Rtlc		= 0x01000000,	/* Re-transmit on Late Collision */
299 	Nrtu		= 0x02000000,	/* No Re-transmit on Underrrun */
300 };
301 
302 enum {					/* [RT]xdctl */
303 	PthreshMASK	= 0x0000003F,	/* Prefetch Threshold */
304 	PthreshSHIFT	= 0,
305 	HthreshMASK	= 0x00003F00,	/* Host Threshold */
306 	HthreshSHIFT	= 8,
307 	WthreshMASK	= 0x003F0000,	/* Writebacj Threshold */
308 	WthreshSHIFT	= 16,
309 	Gran		= 0x01000000,	/* Granularity */
310 };
311 
312 enum {					/* Rxcsum */
313 	PcssMASK	= 0x000000FF,	/* Packet Checksum Start */
314 	PcssSHIFT	= 0,
315 	Ipofl		= 0x00000100,	/* IP Checksum Off-load Enable */
316 	Tuofl		= 0x00000200,	/* TCP/UDP Checksum Off-load Enable */
317 };
318 
319 typedef struct Rdesc {			/* Receive Descriptor */
320 	uint	addr[2];
321 	ushort	length;
322 	ushort	checksum;
323 	uchar	status;
324 	uchar	errors;
325 	ushort	special;
326 } Rdesc;
327 
328 enum {					/* Rdesc status */
329 	Rdd		= 0x01,		/* Descriptor Done */
330 	Reop		= 0x02,		/* End of Packet */
331 	Ixsm		= 0x04,		/* Ignore Checksum Indication */
332 	Vp		= 0x08,		/* Packet is 802.1Q (matched VET) */
333 	Tcpcs		= 0x20,		/* TCP Checksum Calculated on Packet */
334 	Ipcs		= 0x40,		/* IP Checksum Calculated on Packet */
335 	Pif		= 0x80,		/* Passed in-exact filter */
336 };
337 
338 enum {					/* Rdesc errors */
339 	Ce		= 0x01,		/* CRC Error or Alignment Error */
340 	Se		= 0x02,		/* Symbol Error */
341 	Seq		= 0x04,		/* Sequence Error */
342 	Cxe		= 0x10,		/* Carrier Extension Error */
343 	Tcpe		= 0x20,		/* TCP/UDP Checksum Error */
344 	Ipe		= 0x40,		/* IP Checksum Error */
345 	Rxe		= 0x80,		/* RX Data Error */
346 };
347 
348 typedef struct Tdesc {			/* Legacy+Normal Transmit Descriptor */
349 	uint	addr[2];
350 	uint	control;		/* varies with descriptor type */
351 	uint	status;			/* varies with descriptor type */
352 } Tdesc;
353 
354 enum {					/* Tdesc control */
355 	LenMASK		= 0x000FFFFF,	/* Data/Packet Length Field */
356 	LenSHIFT	= 0,
357 	DtypeCD		= 0x00000000,	/* Data Type 'Context Descriptor' */
358 	DtypeDD		= 0x00100000,	/* Data Type 'Data Descriptor' */
359 	PtypeTCP	= 0x01000000,	/* TCP/UDP Packet Type (CD) */
360 	Teop		= 0x01000000,	/* End of Packet (DD) */
361 	PtypeIP		= 0x02000000,	/* IP Packet Type (CD) */
362 	Ifcs		= 0x02000000,	/* Insert FCS (DD) */
363 	Tse		= 0x04000000,	/* TCP Segmentation Enable */
364 	Rs		= 0x08000000,	/* Report Status */
365 	Rps		= 0x10000000,	/* Report Status Sent */
366 	Dext		= 0x20000000,	/* Descriptor Extension */
367 	Vle		= 0x40000000,	/* VLAN Packet Enable */
368 	Ide		= 0x80000000,	/* Interrupt Delay Enable */
369 };
370 
371 enum {					/* Tdesc status */
372 	Tdd		= 0x00000001,	/* Descriptor Done */
373 	Ec		= 0x00000002,	/* Excess Collisions */
374 	Lc		= 0x00000004,	/* Late Collision */
375 	Tu		= 0x00000008,	/* Transmit Underrun */
376 	CssMASK		= 0x0000FF00,	/* Checksum Start Field */
377 	CssSHIFT	= 8,
378 };
379 
380 enum {
381 	Nrdesc		= 128,		/* multiple of 8 */
382 	Ntdesc		= 128,		/* multiple of 8 */
383 };
384 
385 enum {
386 	i82563,
387 	i82571,
388 	i82573,
389 };
390 
391 static char *tname[] = {
392 	"i82563",
393 	"i82571",
394 	"i82573",
395 };
396 
397 #define Type	tname[ctlr->type]
398 
399 typedef struct Ctlr Ctlr;
400 struct Ctlr {
401 	int	port;
402 	Pcidev	*pcidev;
403 	Ctlr	*next;
404 	int	active;
405 	int	cls;
406 	ushort	eeprom[0x40];
407 	uchar	ra[Eaddrlen];		/* receive address */
408 	int	type;
409 
410 	int*	nic;
411 	Lock	imlock;
412 	int	im;			/* interrupt mask */
413 
414 	Lock	slock;
415 	uint	statistics[Nstatistics];
416 
417 	Rdesc	*rdba;			/* receive descriptor base address */
418 	Block	**rb;			/* receive buffers */
419 	int	rdh;			/* receive descriptor head */
420 	int	rdt;			/* receive descriptor tail */
421 
422 	Tdesc	*tdba;			/* transmit descriptor base address */
423 	Lock	tdlock;
424 	Block	**tb;			/* transmit buffers */
425 	int	tdh;			/* transmit descriptor head */
426 	int	tdt;			/* transmit descriptor tail */
427 
428 	int	txcw;
429 	int	fcrtl;
430 	int	fcrth;
431 
432 	/* bootstrap goo */
433 	Block	*bqhead;		/* transmission queue */
434 	Block	*bqtail;
435 };
436 
437 static Ctlr	*ctlrhead;
438 static Ctlr	*ctlrtail;
439 
440 #define csr32r(c, r)	(*((c)->nic+((r)/4)))
441 #define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))
442 
443 static void
i82563im(Ctlr * ctlr,int im)444 i82563im(Ctlr* ctlr, int im)
445 {
446 	ilock(&ctlr->imlock);
447 	ctlr->im |= im;
448 	csr32w(ctlr, Ims, ctlr->im);
449 	iunlock(&ctlr->imlock);
450 }
451 
452 static void
i82563attach(Ether * edev)453 i82563attach(Ether* edev)
454 {
455 	int ctl;
456 	Ctlr *ctlr;
457 
458 	ctlr = edev->ctlr;
459 	i82563im(ctlr, 0);
460 	ctl = csr32r(ctlr, Rctl)|Ren;
461 	csr32w(ctlr, Rctl, ctl);
462 	ctl = csr32r(ctlr, Tctl)|Ten;
463 	csr32w(ctlr, Tctl, ctl);
464 }
465 
466 
467 static void
txstart(Ether * edev)468 txstart(Ether *edev)
469 {
470 	int tdh, tdt;
471 	Ctlr *ctlr = edev->ctlr;
472 	Block *bp;
473 	Tdesc *tdesc;
474 
475 	/*
476 	 * Try to fill the ring back up, moving buffers from the transmit q.
477 	 */
478 	tdh = PREV(ctlr->tdh, Ntdesc);
479 	for(tdt = ctlr->tdt; tdt != tdh; tdt = NEXT(tdt, Ntdesc)){
480 		/* pull off the head of the transmission queue */
481 		if((bp = ctlr->bqhead) == nil)	/* was qget(edev->oq) */
482 			break;
483 		ctlr->bqhead = bp->next;
484 		if (ctlr->bqtail == bp)
485 			ctlr->bqtail = nil;
486 
487 		/* set up a descriptor for it */
488 		tdesc = &ctlr->tdba[tdt];
489 		tdesc->addr[0] = PCIWADDR(bp->rp);
490 		tdesc->addr[1] = 0;
491 		tdesc->control = /* Ide | */ Rs | Ifcs | Teop | BLEN(bp);
492 
493 		ctlr->tb[tdt] = bp;
494 	}
495 	ctlr->tdt = tdt;
496 	csr32w(ctlr, Tdt, tdt);
497 	i82563im(ctlr, Txdw);
498 }
499 
500 static Block *
fromringbuf(Ether * ether)501 fromringbuf(Ether *ether)
502 {
503 	RingBuf *tb = &ether->tb[ether->ti];
504 	Block *bp = allocb(tb->len);
505 
506 	memmove(bp->wp, tb->pkt, tb->len);
507 	memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
508 	bp->wp += tb->len;
509 	return bp;
510 }
511 
512 static void
i82563transmit(Ether * edev)513 i82563transmit(Ether* edev)
514 {
515 	Block *bp;
516 	Ctlr *ctlr;
517 	Tdesc *tdesc;
518 	RingBuf *tb;
519 	int tdh;
520 
521 	ctlr = edev->ctlr;
522 	ilock(&ctlr->tdlock);
523 
524 	/*
525 	 * Free any completed packets
526 	 * - try to get the soft tdh to catch the tdt;
527 	 * - if the packet had an underrun bump the threshold
528 	 *   - the Tu bit doesn't seem to ever be set, perhaps
529 	 *     because Rs mode is used?
530 	 */
531 	tdh = ctlr->tdh;
532 	for(;;){
533 		tdesc = &ctlr->tdba[tdh];
534 		if(!(tdesc->status & Tdd))
535 			break;
536 		if(ctlr->tb[tdh] != nil){
537 			freeb(ctlr->tb[tdh]);
538 			ctlr->tb[tdh] = nil;
539 		}
540 		tdesc->status = 0;
541 		tdh = NEXT(tdh, Ntdesc);
542 	}
543 	ctlr->tdh = tdh;
544 
545 	/* copy packets from the software RingBuf to the transmission q */
546 	while((tb = &edev->tb[edev->ti])->owner == Interface){
547 		bp = fromringbuf(edev);
548 //		print("#l%d: tx %d %E %E\n", edev->ctlrno, edev->ti, bp->rp,
549 //			bp->rp+6);
550 
551 		if(ctlr->bqhead)
552 			ctlr->bqtail->next = bp;
553 		else
554 			ctlr->bqhead = bp;
555 		ctlr->bqtail = bp;
556 
557 		txstart(edev);		/* kick transmitter */
558 		tb->owner = Host;	/* give descriptor back */
559 		edev->ti = NEXT(edev->ti, edev->ntb);
560 	}
561 	iunlock(&ctlr->tdlock);
562 }
563 
564 static void
i82563replenish(Ctlr * ctlr)565 i82563replenish(Ctlr* ctlr)
566 {
567 	int rdt;
568 	Block *bp;
569 	Rdesc *rdesc;
570 
571 	rdt = ctlr->rdt;
572 	while(NEXT(rdt, Nrdesc) != ctlr->rdh){
573 		rdesc = &ctlr->rdba[rdt];
574 		if(ctlr->rb[rdt] != nil){
575 			/* nothing to do */
576 		}
577 		else if((bp = iallocb(2048)) != nil){
578 			ctlr->rb[rdt] = bp;
579 			rdesc->addr[0] = PCIWADDR(bp->rp);
580 			rdesc->addr[1] = 0;
581 		}
582 		else
583 			break;
584 		rdesc->status = 0;
585 
586 		rdt = NEXT(rdt, Nrdesc);
587 	}
588 	ctlr->rdt = rdt;
589 	csr32w(ctlr, Rdt, rdt);
590 }
591 
592 static void
toringbuf(Ether * ether,Block * bp)593 toringbuf(Ether *ether, Block *bp)
594 {
595 	RingBuf *rb = &ether->rb[ether->ri];
596 
597 	if (rb->owner == Interface) {
598 		rb->len = BLEN(bp);
599 		memmove(rb->pkt, bp->rp, rb->len);
600 		rb->owner = Host;
601 		ether->ri = NEXT(ether->ri, ether->nrb);
602 	} else if (debug)
603 		print("#l%d: toringbuf: dropping packets @ ri %d\n",
604 			ether->ctlrno, ether->ri);
605 }
606 
607 static void
i82563interrupt(Ureg *,void * arg)608 i82563interrupt(Ureg*, void* arg)
609 {
610 	int icr, im, rdh, txdw = 0;
611 	Block *bp;
612 	Ctlr *ctlr;
613 	Ether *edev;
614 	Rdesc *rdesc;
615 
616 	edev = arg;
617 	ctlr = edev->ctlr;
618 
619 	ilock(&ctlr->imlock);
620 	csr32w(ctlr, Imc, ~0);
621 	im = ctlr->im;
622 
623 	for(icr = csr32r(ctlr, Icr); icr & ctlr->im; icr = csr32r(ctlr, Icr)){
624 		if(icr & (Rxseq|Lsc)){
625 			/* should be more here */
626 		}
627 
628 		rdh = ctlr->rdh;
629 		for (;;) {
630 			rdesc = &ctlr->rdba[rdh];
631 			if(!(rdesc->status & Rdd))
632 				break;
633 			if ((rdesc->status & Reop) && rdesc->errors == 0) {
634 				bp = ctlr->rb[rdh];
635 				if(0 && memcmp(bp->rp, broadcast, 6) != 0)
636 					print("#l%d: rx %d %E %E %d\n",
637 						edev->ctlrno, rdh, bp->rp,
638 						bp->rp+6, rdesc->length);
639 				ctlr->rb[rdh] = nil;
640 				bp->wp += rdesc->length;
641 				toringbuf(edev, bp);
642 				freeb(bp);
643 			} else if (rdesc->status & Reop && rdesc->errors)
644 				print("%s: input packet error 0x%ux\n",
645 					Type, rdesc->errors);
646 			rdesc->status = 0;
647 			rdh = NEXT(rdh, Nrdesc);
648 		}
649 		ctlr->rdh = rdh;
650 		if(icr & Rxdmt0)
651 			i82563replenish(ctlr);
652 		if(icr & Txdw){
653 			im &= ~Txdw;
654 			txdw++;
655 		}
656 	}
657 	ctlr->im = im;
658 	csr32w(ctlr, Ims, im);
659 	iunlock(&ctlr->imlock);
660 	if(txdw)
661 		i82563transmit(edev);
662 }
663 
664 static void
i82563init(Ether * edev)665 i82563init(Ether* edev)
666 {
667 	int csr, i, r;
668 	Ctlr *ctlr;
669 
670 	ctlr = edev->ctlr;
671 	csr = edev->ea[3]<<24 | edev->ea[2]<<16 | edev->ea[1]<<8 | edev->ea[0];
672 	csr32w(ctlr, Ral, csr);
673 	csr = 0x80000000 | edev->ea[5]<<8 | edev->ea[4];
674 	csr32w(ctlr, Rah, csr);
675 	for (i = 1; i < 16; i++) {
676 		csr32w(ctlr, Ral+i*8, 0);
677 		csr32w(ctlr, Rah+i*8, 0);
678 	}
679 	for(i = 0; i < 128; i++)
680 		csr32w(ctlr, Mta+i*4, 0);
681 	csr32w(ctlr, Rctl, 0);
682 	ctlr->rdba = xspanalloc(Nrdesc*sizeof(Rdesc), 256, 0);
683 	csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));
684 	csr32w(ctlr, Rdbah, 0);
685 	csr32w(ctlr, Rdlen, Nrdesc*sizeof(Rdesc));
686 	ctlr->rdh = 0;
687 	csr32w(ctlr, Rdh, ctlr->rdh);
688 	ctlr->rdt = 0;
689 	csr32w(ctlr, Rdt, ctlr->rdt);
690 	ctlr->rb = malloc(sizeof(Block*)*Nrdesc);
691 	i82563replenish(ctlr);
692 	csr32w(ctlr, Rdtr, 0);
693 	csr32w(ctlr, Rctl, Dpf | Bsize2048 | Bam | RdtmsHALF);
694 	i82563im(ctlr, Rxt0 | Rxo | Rxdmt0 | Rxseq | Ack);
695 
696 	csr32w(ctlr, Tctl, 0x0F<<CtSHIFT | Psp | 0x3f<<ColdSHIFT | Mulr);
697 	csr32w(ctlr, Tipg, 6<<20 | 8<<10 | 8);
698 	csr32w(ctlr, Tidv, 1);
699 
700 	ctlr->tdba = xspanalloc(Ntdesc*sizeof(Tdesc), 256, 0);
701 	memset(ctlr->tdba, 0, Ntdesc*sizeof(Tdesc));
702 	csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba));
703 
704 	csr32w(ctlr, Tdbah, 0);
705 	csr32w(ctlr, Tdlen, Ntdesc*sizeof(Tdesc));
706 	ctlr->tdh = 0;
707 	csr32w(ctlr, Tdh, ctlr->tdh);
708 	ctlr->tdt = 0;
709 	csr32w(ctlr, Tdt, ctlr->tdt);
710 	ctlr->tb = malloc(sizeof(Block*)*Ntdesc);
711 
712 //	r = 4<<WthreshSHIFT | 4<<HthreshSHIFT | 8<<PthreshSHIFT;
713 //	csr32w(ctlr, Txdctl, r);
714 	csr32w(ctlr, Rxcsum, Tuofl | Ipofl | ETHERHDRSIZE<<PcssSHIFT);
715 	r = csr32r(ctlr, Tctl);
716 	r |= Ten;
717 	csr32w(ctlr, Tctl, r);
718 }
719 
720 
721 static ushort
eeread(Ctlr * ctlr,int adr)722 eeread(Ctlr* ctlr, int adr)
723 {
724 	csr32w(ctlr, Eerd, ee_start | adr << 2);
725 	while ((csr32r(ctlr, Eerd) & ee_done) == 0)
726 		;
727 	return csr32r(ctlr, Eerd) >> 16;
728 }
729 
730 static int
eeload(Ctlr * ctlr)731 eeload(Ctlr* ctlr)
732 {
733 	ushort sum;
734 	int data, adr;
735 
736 	sum = 0;
737 	for (adr = 0; adr < 0x40; adr++) {
738 		data = eeread(ctlr, adr);
739 		ctlr->eeprom[adr] = data;
740 		sum += data;
741 	}
742 	return sum;
743 }
744 
745 
746 static void
detach(Ctlr * ctlr)747 detach(Ctlr *ctlr)
748 {
749 	int r;
750 
751 	csr32w(ctlr, Imc, ~0);
752 	csr32w(ctlr, Rctl, 0);
753 	csr32w(ctlr, Tctl, 0);
754 
755 	delay(10);
756 
757 	r = csr32r(ctlr, Ctrl);
758 	csr32w(ctlr, Ctrl, Devrst | r);
759 	/* apparently needed on multi-GHz processors to avoid infinite loops */
760 	delay(1);
761 	while(csr32r(ctlr, Ctrl) & Devrst)
762 		;
763 
764 	if(1 || ctlr->type != i82563){
765 		r = csr32r(ctlr, Ctrl);
766 		csr32w(ctlr, Ctrl, Slu | r);
767 	}
768 
769 	csr32w(ctlr, Ctrlext, Eerst | csr32r(ctlr, Ctrlext));
770 	delay(1);
771 	while(csr32r(ctlr, Ctrlext) & Eerst)
772 		;
773 
774 	csr32w(ctlr, Imc, ~0);
775 	delay(1);
776 	while(csr32r(ctlr, Icr))
777 		;
778 }
779 
780 static void
i82563detach(Ether * edev)781 i82563detach(Ether *edev)
782 {
783 	detach(edev->ctlr);
784 }
785 
786 static void
i82563shutdown(Ether * ether)787 i82563shutdown(Ether* ether)
788 {
789 	i82563detach(ether);
790 }
791 
792 static int
i82563reset(Ctlr * ctlr)793 i82563reset(Ctlr* ctlr)
794 {
795 	int i, r;
796 
797 	detach(ctlr);
798 
799 	r = eeload(ctlr);
800 	if (r != 0 && r != 0xBABA){
801 		print("%s: bad EEPROM checksum - 0x%4.4ux\n", Type, r);
802 		return -1;
803 	}
804 
805 	for(i = Ea; i < Eaddrlen/2; i++){
806 		ctlr->ra[2*i]   = ctlr->eeprom[i];
807 		ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
808 	}
809 	r = (csr32r(ctlr, Status) & Lanid) >> 2;
810 	ctlr->ra[5] += r;		/* ea ctlr[1] = ea ctlr[0]+1 */
811 
812 	r = ctlr->ra[3]<<24 | ctlr->ra[2]<<16 | ctlr->ra[1]<<8 | ctlr->ra[0];
813 	csr32w(ctlr, Ral, r);
814 	r = 0x80000000 | ctlr->ra[5]<<8 | ctlr->ra[4];
815 	csr32w(ctlr, Rah, r);
816 	for(i = 1; i < 16; i++){
817 		csr32w(ctlr, Ral+i*8, 0);
818 		csr32w(ctlr, Rah+i*8, 0);
819 	}
820 
821 	for(i = 0; i < 128; i++)
822 		csr32w(ctlr, Mta+i*4, 0);
823 
824 	csr32w(ctlr, Fcal, 0x00C28001);
825 	csr32w(ctlr, Fcah, 0x00000100);
826 	csr32w(ctlr, Fct,  0x00008808);
827 	csr32w(ctlr, Fcttv, 0x00000100);
828 
829 	csr32w(ctlr, Fcrtl, ctlr->fcrtl);
830 	csr32w(ctlr, Fcrth, ctlr->fcrth);
831 
832 	ilock(&ctlr->imlock);
833 	csr32w(ctlr, Imc, ~0);
834 	ctlr->im = 0;		/* was = Lsc, which hangs some controllers */
835 	csr32w(ctlr, Ims, ctlr->im);
836 	iunlock(&ctlr->imlock);
837 
838 	return 0;
839 }
840 
841 static void
i82563pci(void)842 i82563pci(void)
843 {
844 	int port, type, cls;
845 	Pcidev *p;
846 	Ctlr *ctlr;
847 	static int first = 1;
848 
849 	if (first)
850 		first = 0;
851 	else
852 		return;
853 
854 	p = nil;
855 	while(p = pcimatch(p, 0x8086, 0)){
856 		switch(p->did){
857 		case 0x1096:
858 		case 0x10ba:
859 			type = i82563;
860 			break;
861 		case 0x108b:		/*  e */
862 		case 0x108c:		/*  e (iamt) */
863 		case 0x109a:		/*  l */
864 			type = i82573;
865 			break;
866 		default:
867 			continue;
868 		}
869 
870 		port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
871 		if(port == 0){
872 			print("%s: can't map %d @ 0x%8.8lux\n", tname[type],
873 				p->mem[0].size, p->mem[0].bar);
874 			continue;
875 		}
876 
877 		if(p->pcr & MemWrInv){
878 			cls = pcicfgr8(p, PciCLS) * 4;
879 			if(cls != CACHELINESZ)
880 				pcicfgw8(p, PciCLS, CACHELINESZ/4);
881 		}
882 
883 		cls = pcicfgr8(p, PciCLS);
884 		switch(cls){
885 		default:
886 			print("%s: unexpected CLS - %d bytes\n",
887 				tname[type], cls*sizeof(long));
888 			break;
889 		case 0x00:
890 		case 0xFF:
891 			/* alphapc 164lx returns 0 */
892 			print("%s: unusable PciCLS: %d, using %d longs\n",
893 				tname[type], cls, CACHELINESZ/sizeof(long));
894 			cls = CACHELINESZ/sizeof(long);
895 			pcicfgw8(p, PciCLS, cls);
896 			break;
897 		case 0x08:
898 		case 0x10:
899 			break;
900 		}
901 
902 		ctlr = malloc(sizeof(Ctlr));
903 		ctlr->port = port;
904 		ctlr->pcidev = p;
905 		ctlr->cls = cls*4;
906 		ctlr->type = type;
907 		ctlr->nic = KADDR(ctlr->port);
908 		if(i82563reset(ctlr)){
909 			free(ctlr);
910 			continue;
911 		}
912 		pcisetbme(p);
913 
914 		if(ctlrhead != nil)
915 			ctlrtail->next = ctlr;
916 		else
917 			ctlrhead = ctlr;
918 		ctlrtail = ctlr;
919 	}
920 }
921 
922 static uchar nilea[Eaddrlen];
923 
924 int
i82563pnp(Ether * edev)925 i82563pnp(Ether* edev)
926 {
927 	Ctlr *ctlr;
928 
929 	if(ctlrhead == nil)
930 		i82563pci();
931 
932 	/*
933 	 * Any adapter matches if no edev->port is supplied,
934 	 * otherwise the ports must match.
935 	 */
936 	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
937 		if(ctlr->active)
938 			continue;
939 		if(edev->port == 0 || edev->port == ctlr->port){
940 			ctlr->active = 1;
941 			break;
942 		}
943 	}
944 	if(ctlr == nil)
945 		return -1;
946 
947 	edev->ctlr = ctlr;
948 	edev->port = ctlr->port;
949 	edev->irq = ctlr->pcidev->intl;
950 	edev->tbdf = ctlr->pcidev->tbdf;
951 //	edev->mbps = 1000;
952 
953 	if(memcmp(edev->ea, nilea, Eaddrlen) == 0)
954 		memmove(edev->ea, ctlr->ra, Eaddrlen);
955 	i82563init(edev);
956 
957 	/*
958 	 * Linkage to the generic ethernet driver.
959 	 */
960 	edev->attach = i82563attach;
961 	edev->transmit = i82563transmit;
962 	edev->interrupt = i82563interrupt;
963 	edev->detach = i82563detach;
964 
965 	/*
966 	 * with the current structure, there is no right place for this.
967 	 * ideally, we recognize the interface, note it's down and move on.
968 	 * currently either we can skip the interface or note it is down,
969 	 * but not both.
970 	 */
971 	if((csr32r(ctlr, Status)&Lu) == 0){
972 		print("ether#%d: 82563 (%s): link down\n", edev->ctlrno, Type);
973 		return -1;
974 	}
975 
976 	return 0;
977 }
978