xref: /netbsd/sys/arch/i386/stand/lib/netif/i82557.c (revision 6550d01e)
1 /* $NetBSD: i82557.c,v 1.11 2008/12/14 18:46:33 christos Exp $ */
2 
3 /*
4  * Copyright (c) 1998, 1999
5  * 	Matthias Drochner.  All rights reserved.
6  * Copyright (c) 1995, David Greenman
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice unmodified, this list of conditions, and the following
14  *    disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/types.h>
33 #include <machine/pio.h>
34 
35 #include <dev/ic/i82557reg.h>
36 
37 #include <lib/libsa/stand.h>
38 
39 #include <libi386.h>
40 #include <pcivar.h>
41 
42 #if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
43 #include <lib/libkern/libkern.h>
44 #include <bootinfo.h>
45 #endif
46 
47 #include "etherdrv.h"
48 
49 #define RECVBUF_SIZE 1600 /* struct fxp_rfa + packet */
50 
51 #ifdef _STANDALONE
52 static pcihdl_t mytag;
53 static char recvbuf[RECVBUF_SIZE];
54 #define RECVBUF_PHYS vtophys(recvbuf)
55 #define RECVBUF_VIRT ((void *)recvbuf)
56 static union _sndbuf {
57 	struct fxp_cb_config cbp;
58 	struct fxp_cb_ias cb_ias;
59 	struct fxp_cb_tx txp;
60 } sndbuf;
61 #define SNDBUF_PHYS vtophys(&sndbuf)
62 #define SNDBUF_VIRT ((void *)&sndbuf)
63 #else /* !standalone, userspace testing environment */
64 #define	PCI_MODE1_ENABLE	0x80000000UL
65 static pcihdl_t mytag = PCI_MODE1_ENABLE | (PCIDEVNO << 11);
66 
67 extern void *mapmem(int, int);
68 void *dmamem; /* virtual */
69 #define RECVBUF_PHYS DMABASE
70 #define RECVBUF_VIRT dmamem
71 #define SNDBUF_PHYS (DMABASE + RECVBUF_SIZE)
72 #define SNDBUF_VIRT ((void *)(((char *)dmamem) + RECVBUF_SIZE))
73 #endif /* _STANDALONE */
74 
75 static void fxp_read_eeprom(uint16_t *, int, int);
76 static inline void fxp_scb_wait(void);
77 #ifdef DEBUG
78 static void fxp_checkintr(char *);
79 #else
80 #define fxp_checkintr(x)
81 #endif
82 static void fxp_startreceiver(void);
83 
84 /*
85  * Template for default configuration parameters.
86  * See struct fxp_cb_config for the bit definitions.
87  */
88 static uint8_t fxp_cb_config_template[] = {
89 	0x0, 0x0,		/* cb_status */
90 	0x80, 0x2,		/* cb_command */
91 	0xff, 0xff, 0xff, 0xff,	/* link_addr */
92 	0x16,	/*  0 */
93 	0x8,	/*  1 */
94 	0x0,	/*  2 */
95 	0x0,	/*  3 */
96 	0x0,	/*  4 */
97 	0x80,	/*  5 */
98 	0xb2,	/*  6 */
99 	0x3,	/*  7 */
100 	0x1,	/*  8 */
101 	0x0,	/*  9 */
102 	0x26,	/* 10 */
103 	0x0,	/* 11 */
104 	0x60,	/* 12 */
105 	0x0,	/* 13 */
106 	0xf2,	/* 14 */
107 	0x48,	/* 15 */
108 	0x0,	/* 16 */
109 	0x40,	/* 17 */
110 	0xf3,	/* 18 */
111 	0x0,	/* 19 */
112 	0x3f,	/* 20 */
113 	0x5	/* 21 */
114 };
115 
116 static int tx_threshold = 64; /* x8, max 192 */
117 
118 #define CSR_READ_1(reg) inb(iobase + (reg))
119 #define CSR_READ_2(reg) inw(iobase + (reg))
120 #define CSR_WRITE_1(reg, val) outb(iobase + (reg), val)
121 #define CSR_WRITE_2(reg, val) outw(iobase + (reg), val)
122 #define CSR_WRITE_4(reg, val) outl(iobase + (reg), val)
123 #define DELAY(n) delay(n)
124 
125 static int iobase;
126 
127 #if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
128 static struct btinfo_netif bi_netif;
129 #endif
130 
131 /*
132  * Wait for the previous command to be accepted (but not necessarily
133  * completed).
134  */
135 static inline void
136 fxp_scb_wait(void)
137 {
138 	int i = 10000;
139 
140 	while (CSR_READ_1(FXP_CSR_SCB_COMMAND) && --i)
141 		DELAY(1);
142 	if (i == 0)
143 		printf("fxp: WARNING: SCB timed out!\n");
144 }
145 
146 #ifdef DEBUG
147 static void
148 fxp_checkintr(char *msg)
149 {
150 	uint8_t statack;
151 	int i = 10000;
152 
153 	do {
154 		statack = CSR_READ_1(FXP_CSR_SCB_STATACK);
155 	} while ((statack == 0) && (--i > 0));
156 
157 	if (statack != 0) {
158 		CSR_WRITE_1(FXP_CSR_SCB_STATACK, statack);
159 		printf("%s: ack'd irq %x, i=%d\n", msg, statack, i);
160 	}
161 }
162 #endif
163 
164 int
165 EtherInit(unsigned char *myadr)
166 {
167 #ifndef _STANDALONE
168 	uint32_t id;
169 #endif
170 	volatile struct fxp_cb_config *cbp;
171 	volatile struct fxp_cb_ias *cb_ias;
172 	int i;
173 
174 	if (pcicheck()) {
175 		printf("pcicheck failed\n");
176 		return 0;
177 	}
178 #ifdef _STANDALONE
179 	if (pcifinddev(0x8086, 0x1229, &mytag)) {
180 		printf("no fxp\n");
181 		return 0;
182 	}
183 #else
184 	pcicfgread(&mytag, 0, &id);
185 	if (id != 0x12298086) {
186 		printf("no fxp\n");
187 		return 0;
188 	}
189 #endif
190 
191 	pcicfgread(&mytag, FXP_PCI_IOBA, &iobase);
192 	iobase &= ~3;
193 
194 #ifndef _STANDALONE
195 	dmamem = mapmem(DMABASE, DMASIZE);
196 	if (!dmamem)
197 		return 0;
198 #endif
199 
200 	fxp_read_eeprom((void *)myadr, 0, 3);
201 
202 	/*
203 	 * Initialize base of CBL and RFA memory. Loading with zero
204 	 * sets it up for regular linear addressing.
205 	 */
206 	CSR_WRITE_4(FXP_CSR_SCB_GENERAL, 0);
207 	CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_BASE);
208 
209 	fxp_scb_wait();
210 	CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_BASE);
211 
212 	cbp = SNDBUF_VIRT;
213 	/*
214 	 * This memcpy is kind of disgusting, but there are a bunch of must be
215 	 * zero and must be one bits in this structure and this is the easiest
216 	 * way to initialize them all to proper values.
217 	 */
218 	memcpy((void *)cbp, fxp_cb_config_template,
219 	      sizeof(fxp_cb_config_template));
220 
221 #define prm 0
222 #define phy_10Mbps_only 0
223 #define all_mcasts 0
224 	cbp->cb_status =	0;
225 	cbp->cb_command =	FXP_CB_COMMAND_CONFIG | FXP_CB_COMMAND_EL;
226 	cbp->link_addr =	-1;	/* (no) next command */
227 	cbp->byte_count =	22;	/* (22) bytes to config */
228 	cbp->rx_fifo_limit =	8;	/* rx fifo threshold (32 bytes) */
229 	cbp->tx_fifo_limit =	0;	/* tx fifo threshold (0 bytes) */
230 	cbp->adaptive_ifs =	0;	/* (no) adaptive interframe spacing */
231 	cbp->rx_dma_bytecount =	0;	/* (no) rx DMA max */
232 	cbp->tx_dma_bytecount =	0;	/* (no) tx DMA max */
233 	cbp->dma_mbce =		0;	/* (disable) dma max counters */
234 	cbp->late_scb =		0;	/* (don't) defer SCB update */
235 	cbp->tno_int_or_tco_en = 0;	/* (disable) tx not okay interrupt */
236 	cbp->ci_int =		0;	/* interrupt on CU not active */
237 	cbp->save_bf =		prm;	/* save bad frames */
238 	cbp->disc_short_rx =	!prm;	/* discard short packets */
239 	cbp->underrun_retry =	1;	/* retry mode (1) on DMA underrun */
240 	cbp->mediatype =	!phy_10Mbps_only; /* interface mode */
241 	cbp->nsai =		1;     /* (don't) disable source addr insert */
242 	cbp->preamble_length =	2;	/* (7 byte) preamble */
243 	cbp->loopback =		0;	/* (don't) loopback */
244 	cbp->linear_priority =	0;	/* (normal CSMA/CD operation) */
245 	cbp->linear_pri_mode =	0;	/* (wait after xmit only) */
246 	cbp->interfrm_spacing =	6;	/* (96 bits of) interframe spacing */
247 	cbp->promiscuous =	prm;	/* promiscuous mode */
248 	cbp->bcast_disable =	0;	/* (don't) disable broadcasts */
249 	cbp->crscdt =		0;	/* (CRS only) */
250 	cbp->stripping =	!prm;	/* truncate rx packet to byte count */
251 	cbp->padding =		1;	/* (do) pad short tx packets */
252 	cbp->rcv_crc_xfer =	0;	/* (don't) xfer CRC to host */
253 	cbp->force_fdx =	0;	/* (don't) force full duplex */
254 	cbp->fdx_pin_en =	1;	/* (enable) FDX# pin */
255 	cbp->multi_ia =		0;	/* (don't) accept multiple IAs */
256 	cbp->mc_all =		all_mcasts;/* accept all multicasts */
257 #undef prm
258 #undef phy_10Mbps_only
259 #undef all_mcasts
260 
261 	/*
262 	 * Start the config command/DMA.
263 	 */
264 	fxp_scb_wait();
265 	CSR_WRITE_4(FXP_CSR_SCB_GENERAL, SNDBUF_PHYS);
266 	CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
267 	/* ...and wait for it to complete. */
268 	i = 10000;
269 	while (!(cbp->cb_status & FXP_CB_STATUS_C) && (--i > 0))
270 		DELAY(1);
271 	if (i == 0)
272 		printf("config timeout");
273 
274 	fxp_checkintr("config");
275 
276 	cb_ias = SNDBUF_VIRT;
277 	/*
278 	 * Now initialize the station address. Temporarily use the TxCB
279 	 * memory area like we did above for the config CB.
280 	 */
281 	cb_ias->cb_status = 0;
282 	cb_ias->cb_command = FXP_CB_COMMAND_IAS | FXP_CB_COMMAND_EL;
283 	cb_ias->link_addr = -1;
284 	memcpy((void *)cb_ias->macaddr, myadr, 6);
285 
286 	/*
287 	 * Start the IAS (Individual Address Setup) command/DMA.
288 	 */
289 	fxp_scb_wait();
290 	/* address is still there */
291 	CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
292 	/* ...and wait for it to complete. */
293 	i = 10000;
294 	while (!(cb_ias->cb_status & FXP_CB_STATUS_C) && (--i > 0))
295 		DELAY(1);
296 	if (i == 0)
297 		printf("ias timeout");
298 
299 	fxp_checkintr("ias");
300 
301 	fxp_startreceiver();
302 
303 #if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
304 	strncpy(bi_netif.ifname, "fxp", sizeof(bi_netif.ifname));
305 	bi_netif.bus = BI_BUS_PCI;
306 	bi_netif.addr.tag = mytag;
307 
308 	BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif));
309 #endif
310 
311 	return 1;
312 }
313 
314 void
315 EtherStop(void)
316 {
317 
318 	/*
319 	 * Issue software reset
320 	 */
321 	CSR_WRITE_4(FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET);
322 	DELAY(10);
323 }
324 
325 int
326 EtherSend(char *pkt, int len)
327 {
328 	volatile struct fxp_cb_tx *txp;
329 #ifdef _STANDALONE
330 	static volatile struct fxp_tbd tbd;
331 #endif
332 	volatile struct fxp_tbd *tbdp;
333 	int i;
334 
335 	txp = SNDBUF_VIRT;
336 #ifdef _STANDALONE
337 	tbdp = &tbd;
338 	txp->tbd_array_addr = vtophys((void *)&tbd);
339 	tbdp->tb_addr = vtophys(pkt);
340 #else
341 	/* XXX assuming we send at max 400 bytes */
342 	tbdp = (struct fxp_tbd *)(SNDBUF_VIRT + 440);
343 	txp->tbd_array_addr = SNDBUF_PHYS + 440;
344 	memcpy(SNDBUF_VIRT + 400, pkt, len);
345 	tbdp->tb_addr = SNDBUF_PHYS + 400;
346 #endif
347 	tbdp->tb_size = len;
348 	txp->tbd_number = 1;
349 	txp->cb_status = 0;
350 	txp->cb_command =
351 	    FXP_CB_COMMAND_XMIT | FXP_CB_COMMAND_SF | FXP_CB_COMMAND_EL;
352 	txp->tx_threshold = tx_threshold;
353 
354 	txp->link_addr = -1;
355 	txp->byte_count = 0;
356 
357 	fxp_scb_wait();
358 	CSR_WRITE_4(FXP_CSR_SCB_GENERAL, SNDBUF_PHYS);
359 	CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
360 	/* ...and wait for it to complete. */
361 	i = 10000;
362 	while (!(txp->cb_status & FXP_CB_STATUS_C) && (--i > 0))
363 		DELAY(1);
364 	if (i == 0)
365 		printf("send timeout");
366 
367 	fxp_checkintr("send");
368 
369 	return len;
370 }
371 
372 static void
373 fxp_startreceiver(void)
374 {
375 	volatile struct fxp_rfa *rfa;
376 	uint32_t v;
377 
378 	rfa = RECVBUF_VIRT;
379 	rfa->size = RECVBUF_SIZE - sizeof(struct fxp_rfa);
380 	rfa->rfa_status = 0;
381 	rfa->rfa_control = FXP_RFA_CONTROL_S;
382 	rfa->actual_size = 0;
383 	v = RECVBUF_PHYS; /* close the "ring" */
384 	memcpy((void *)&rfa->link_addr, &v, sizeof(v));
385 	v = -1;
386 	memcpy((void *)&rfa->rbd_addr, &v, sizeof(v));
387 
388 	fxp_scb_wait();
389 	CSR_WRITE_4(FXP_CSR_SCB_GENERAL, RECVBUF_PHYS);
390 	CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_START);
391 }
392 
393 int
394 EtherReceive(char *pkt, int maxlen)
395 {
396 	uint8_t ruscus;
397 	volatile struct fxp_rfa *rfa;
398 	int len = 0;
399 
400 	ruscus = CSR_READ_1(FXP_CSR_SCB_RUSCUS);
401 	if (((ruscus >> 2) & 0x0f) == FXP_SCB_RUS_READY)
402 		return 0;
403 	if (((ruscus >> 2) & 0x0f) != FXP_SCB_RUS_SUSPENDED) {
404 		printf("rcv: ruscus=%x\n", ruscus);
405 		return 0;
406 	}
407 
408 	rfa = RECVBUF_VIRT;
409 	if (rfa->rfa_status & FXP_RFA_STATUS_C) {
410 		len = rfa->actual_size & 0x7ff;
411 		if (len <= maxlen) {
412 			memcpy(pkt, (char *) rfa + RFA_SIZE, maxlen);
413 #if 0
414 			printf("rfa status=%x, len=%x\n",
415 			       rfa->rfa_status, len);
416 #endif
417 		} else
418 			len = 0;
419 	}
420 
421 	fxp_scb_wait();
422 	CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_RESUME);
423 
424 	return len;
425 }
426 
427 /*
428  * Read from the serial EEPROM. Basically, you manually shift in
429  * the read opcode (one bit at a time) and then shift in the address,
430  * and then you shift out the data (all of this one bit at a time).
431  * The word size is 16 bits, so you have to provide the address for
432  * every 16 bits of data.
433  */
434 static void
435 fxp_read_eeprom(uint16_t *data, int offset, int words)
436 {
437 	uint16_t reg;
438 	int i, x;
439 
440 	for (i = 0; i < words; i++) {
441 		CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
442 		/*
443 		 * Shift in read opcode.
444 		 */
445 		for (x = 3; x > 0; x--) {
446 			if (FXP_EEPROM_OPC_READ & (1 << (x - 1))) {
447 				reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
448 			} else {
449 				reg = FXP_EEPROM_EECS;
450 			}
451 			CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
452 			CSR_WRITE_2(FXP_CSR_EEPROMCONTROL,
453 			    reg | FXP_EEPROM_EESK);
454 			DELAY(1);
455 			CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
456 			DELAY(1);
457 		}
458 		/*
459 		 * Shift in address.
460 		 */
461 		for (x = 6; x > 0; x--) {
462 			if ((i + offset) & (1 << (x - 1))) {
463 				reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
464 			} else {
465 				reg = FXP_EEPROM_EECS;
466 			}
467 			CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
468 			CSR_WRITE_2(FXP_CSR_EEPROMCONTROL,
469 			    reg | FXP_EEPROM_EESK);
470 			DELAY(1);
471 			CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
472 			DELAY(1);
473 		}
474 		reg = FXP_EEPROM_EECS;
475 		data[i] = 0;
476 		/*
477 		 * Shift out data.
478 		 */
479 		for (x = 16; x > 0; x--) {
480 			CSR_WRITE_2(FXP_CSR_EEPROMCONTROL,
481 			    reg | FXP_EEPROM_EESK);
482 			DELAY(1);
483 			if (CSR_READ_2(FXP_CSR_EEPROMCONTROL) &
484 			    FXP_EEPROM_EEDO)
485 				data[i] |= (1 << (x - 1));
486 			CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
487 			DELAY(1);
488 		}
489 		CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, 0);
490 		DELAY(1);
491 	}
492 }
493