xref: /netbsd/sys/arch/i386/stand/lib/netif/i82557.c (revision bf9ec67e)
1 /* $NetBSD: i82557.c,v 1.7 2002/01/24 02:52:15 gson 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 caddr_t mapmem __P((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	__P((u_int16_t *, int, int));
76 static inline void fxp_scb_wait	__P((void));
77 #ifdef DEBUG
78 static void fxp_checkintr __P((char *));
79 #else
80 #define fxp_checkintr(x)
81 #endif
82 static void fxp_startreceiver __P((void));
83 
84 /*
85  * Template for default configuration parameters.
86  * See struct fxp_cb_config for the bit definitions.
87  */
88 static u_int8_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()
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(msg)
149 	char *msg;
150 {
151 	u_int8_t statack;
152 	int i = 10000;
153 
154 	do {
155 		statack = CSR_READ_1(FXP_CSR_SCB_STATACK);
156 	} while ((statack == 0) && (--i > 0));
157 
158 	if (statack != 0) {
159 		CSR_WRITE_1(FXP_CSR_SCB_STATACK, statack);
160 		printf("%s: ack'd irq %x, i=%d\n", msg, statack, i);
161 	}
162 }
163 #endif
164 
165 int
166 EtherInit(myadr)
167 	unsigned char *myadr;
168 {
169 #ifndef _STANDALONE
170 	u_int32_t id;
171 #endif
172 	volatile struct fxp_cb_config *cbp;
173 	volatile struct fxp_cb_ias *cb_ias;
174 	int i;
175 
176 	if (pcicheck()) {
177 		printf("pcicheck failed\n");
178 		return (0);
179 	}
180 #ifdef _STANDALONE
181 	if (pcifinddev(0x8086, 0x1229, &mytag)) {
182 		printf("no fxp\n");
183 		return (0);
184 	}
185 #else
186 	pcicfgread(&mytag, 0, &id);
187 	if (id != 0x12298086) {
188 		printf("no fxp\n");
189 		return (0);
190 	}
191 #endif
192 
193 	pcicfgread(&mytag, FXP_PCI_IOBA, &iobase);
194 	iobase &= ~3;
195 
196 #ifndef _STANDALONE
197 	dmamem = mapmem(DMABASE, DMASIZE);
198 	if (!dmamem)
199 		return (0);
200 #endif
201 
202 	fxp_read_eeprom((void *)myadr, 0, 3);
203 
204 	/*
205 	 * Initialize base of CBL and RFA memory. Loading with zero
206 	 * sets it up for regular linear addressing.
207 	 */
208 	CSR_WRITE_4(FXP_CSR_SCB_GENERAL, 0);
209 	CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_BASE);
210 
211 	fxp_scb_wait();
212 	CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_BASE);
213 
214 	cbp = SNDBUF_VIRT;
215 	/*
216 	 * This memcpy is kind of disgusting, but there are a bunch of must be
217 	 * zero and must be one bits in this structure and this is the easiest
218 	 * way to initialize them all to proper values.
219 	 */
220 	memcpy((void *)cbp, fxp_cb_config_template,
221 	      sizeof(fxp_cb_config_template));
222 
223 #define prm 0
224 #define phy_10Mbps_only 0
225 #define all_mcasts 0
226 	cbp->cb_status =	0;
227 	cbp->cb_command =	FXP_CB_COMMAND_CONFIG | FXP_CB_COMMAND_EL;
228 	cbp->link_addr =	-1;	/* (no) next command */
229 	cbp->byte_count =	22;	/* (22) bytes to config */
230 	cbp->rx_fifo_limit =	8;	/* rx fifo threshold (32 bytes) */
231 	cbp->tx_fifo_limit =	0;	/* tx fifo threshold (0 bytes) */
232 	cbp->adaptive_ifs =	0;	/* (no) adaptive interframe spacing */
233 	cbp->rx_dma_bytecount =	0;	/* (no) rx DMA max */
234 	cbp->tx_dma_bytecount =	0;	/* (no) tx DMA max */
235 	cbp->dma_mbce =		0;	/* (disable) dma max counters */
236 	cbp->late_scb =		0;	/* (don't) defer SCB update */
237 	cbp->tno_int_or_tco_en = 0;	/* (disable) tx not okay interrupt */
238 	cbp->ci_int =		0;	/* interrupt on CU not active */
239 	cbp->save_bf =		prm;	/* save bad frames */
240 	cbp->disc_short_rx =	!prm;	/* discard short packets */
241 	cbp->underrun_retry =	1;	/* retry mode (1) on DMA underrun */
242 	cbp->mediatype =	!phy_10Mbps_only; /* interface mode */
243 	cbp->nsai =		1;     /* (don't) disable source addr insert */
244 	cbp->preamble_length =	2;	/* (7 byte) preamble */
245 	cbp->loopback =		0;	/* (don't) loopback */
246 	cbp->linear_priority =	0;	/* (normal CSMA/CD operation) */
247 	cbp->linear_pri_mode =	0;	/* (wait after xmit only) */
248 	cbp->interfrm_spacing =	6;	/* (96 bits of) interframe spacing */
249 	cbp->promiscuous =	prm;	/* promiscuous mode */
250 	cbp->bcast_disable =	0;	/* (don't) disable broadcasts */
251 	cbp->crscdt =		0;	/* (CRS only) */
252 	cbp->stripping =	!prm;	/* truncate rx packet to byte count */
253 	cbp->padding =		1;	/* (do) pad short tx packets */
254 	cbp->rcv_crc_xfer =	0;	/* (don't) xfer CRC to host */
255 	cbp->force_fdx =	0;	/* (don't) force full duplex */
256 	cbp->fdx_pin_en =	1;	/* (enable) FDX# pin */
257 	cbp->multi_ia =		0;	/* (don't) accept multiple IAs */
258 	cbp->mc_all =		all_mcasts;/* accept all multicasts */
259 #undef prm
260 #undef phy_10Mbps_only
261 #undef all_mcasts
262 
263 	/*
264 	 * Start the config command/DMA.
265 	 */
266 	fxp_scb_wait();
267 	CSR_WRITE_4(FXP_CSR_SCB_GENERAL, SNDBUF_PHYS);
268 	CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
269 	/* ...and wait for it to complete. */
270 	i = 10000;
271 	while (!(cbp->cb_status & FXP_CB_STATUS_C) && (--i > 0))
272 		DELAY(1);
273 	if (i == 0)
274 		printf("config timeout");
275 
276 	fxp_checkintr("config");
277 
278 	cb_ias = SNDBUF_VIRT;
279 	/*
280 	 * Now initialize the station address. Temporarily use the TxCB
281 	 * memory area like we did above for the config CB.
282 	 */
283 	cb_ias->cb_status = 0;
284 	cb_ias->cb_command = FXP_CB_COMMAND_IAS | FXP_CB_COMMAND_EL;
285 	cb_ias->link_addr = -1;
286 	memcpy((void *)cb_ias->macaddr, myadr, 6);
287 
288 	/*
289 	 * Start the IAS (Individual Address Setup) command/DMA.
290 	 */
291 	fxp_scb_wait();
292 	/* address is still there */
293 	CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
294 	/* ...and wait for it to complete. */
295 	i = 10000;
296 	while (!(cb_ias->cb_status & FXP_CB_STATUS_C) && (--i > 0))
297 		DELAY(1);
298 	if (i == 0)
299 		printf("ias timeout");
300 
301 	fxp_checkintr("ias");
302 
303 	fxp_startreceiver();
304 
305 #if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
306 	strncpy(bi_netif.ifname, "fxp", sizeof(bi_netif.ifname));
307 	bi_netif.bus = BI_BUS_PCI;
308 	bi_netif.addr.tag = mytag;
309 
310 	BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif));
311 #endif
312 
313 	return (1);
314 }
315 
316 void
317 EtherStop()
318 {
319 	/*
320 	 * Issue software reset
321 	 */
322 	CSR_WRITE_4(FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET);
323 	DELAY(10);
324 }
325 
326 int EtherSend(pkt, len)
327 	char *pkt;
328 	int len;
329 {
330 	volatile struct fxp_cb_tx *txp;
331 #ifdef _STANDALONE
332 	static volatile struct fxp_tbd tbd;
333 #endif
334 	volatile struct fxp_tbd *tbdp;
335 	int i;
336 
337 	txp = SNDBUF_VIRT;
338 #ifdef _STANDALONE
339 	tbdp = &tbd;
340 	txp->tbd_array_addr = vtophys((void *)&tbd);
341 	tbdp->tb_addr = vtophys(pkt);
342 #else
343 	/* XXX assuming we send at max 400 bytes */
344 	tbdp = (struct fxp_tbd *)(SNDBUF_VIRT + 440);
345 	txp->tbd_array_addr = SNDBUF_PHYS + 440;
346 	memcpy(SNDBUF_VIRT + 400, pkt, len);
347 	tbdp->tb_addr = SNDBUF_PHYS + 400;
348 #endif
349 	tbdp->tb_size = len;
350 	txp->tbd_number = 1;
351 	txp->cb_status = 0;
352 	txp->cb_command =
353 	    FXP_CB_COMMAND_XMIT | FXP_CB_COMMAND_SF | FXP_CB_COMMAND_EL;
354 	txp->tx_threshold = tx_threshold;
355 
356 	txp->link_addr = -1;
357 	txp->byte_count = 0;
358 
359 	fxp_scb_wait();
360 	CSR_WRITE_4(FXP_CSR_SCB_GENERAL, SNDBUF_PHYS);
361 	CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
362 	/* ...and wait for it to complete. */
363 	i = 10000;
364 	while (!(txp->cb_status & FXP_CB_STATUS_C) && (--i > 0))
365 		DELAY(1);
366 	if (i == 0)
367 		printf("send timeout");
368 
369 	fxp_checkintr("send");
370 
371 	return (len);
372 }
373 
374 static void
375 fxp_startreceiver()
376 {
377 	volatile struct fxp_rfa *rfa;
378 	u_int32_t v;
379 
380 	rfa = RECVBUF_VIRT;
381 	rfa->size = RECVBUF_SIZE - sizeof(struct fxp_rfa);
382 	rfa->rfa_status = 0;
383 	rfa->rfa_control = FXP_RFA_CONTROL_S;
384 	rfa->actual_size = 0;
385 	v = RECVBUF_PHYS; /* close the "ring" */
386 	memcpy((void *)&rfa->link_addr, &v, sizeof(v));
387 	v = -1;
388 	memcpy((void *)&rfa->rbd_addr, &v, sizeof(v));
389 
390 	fxp_scb_wait();
391 	CSR_WRITE_4(FXP_CSR_SCB_GENERAL, RECVBUF_PHYS);
392 	CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_START);
393 }
394 
395 int
396 EtherReceive(pkt, maxlen)
397 	char *pkt;
398 	int maxlen;
399 {
400 	u_int8_t ruscus;
401 	volatile struct fxp_rfa *rfa;
402 	int len = 0;
403 
404 	ruscus = CSR_READ_1(FXP_CSR_SCB_RUSCUS);
405 	if (((ruscus >> 2) & 0x0f) == FXP_SCB_RUS_READY)
406 		return (0);
407 	if (((ruscus >> 2) & 0x0f) != FXP_SCB_RUS_SUSPENDED) {
408 		printf("rcv: ruscus=%x\n", ruscus);
409 		return (0);
410 	}
411 
412 	rfa = RECVBUF_VIRT;
413 	if (rfa->rfa_status & FXP_RFA_STATUS_C) {
414 		len = rfa->actual_size & 0x7ff;
415 		if (len <= maxlen) {
416 			memcpy(pkt, (caddr_t) rfa + RFA_SIZE, maxlen);
417 #if 0
418 			printf("rfa status=%x, len=%x\n",
419 			       rfa->rfa_status, len);
420 #endif
421 		} else
422 			len = 0;
423 	}
424 
425 	fxp_scb_wait();
426 	CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_RESUME);
427 
428 	return (len);
429 }
430 
431 /*
432  * Read from the serial EEPROM. Basically, you manually shift in
433  * the read opcode (one bit at a time) and then shift in the address,
434  * and then you shift out the data (all of this one bit at a time).
435  * The word size is 16 bits, so you have to provide the address for
436  * every 16 bits of data.
437  */
438 static void
439 fxp_read_eeprom(data, offset, words)
440 	u_int16_t *data;
441 	int offset;
442 	int words;
443 {
444 	u_int16_t reg;
445 	int i, x;
446 
447 	for (i = 0; i < words; i++) {
448 		CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
449 		/*
450 		 * Shift in read opcode.
451 		 */
452 		for (x = 3; x > 0; x--) {
453 			if (FXP_EEPROM_OPC_READ & (1 << (x - 1))) {
454 				reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
455 			} else {
456 				reg = FXP_EEPROM_EECS;
457 			}
458 			CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
459 			CSR_WRITE_2(FXP_CSR_EEPROMCONTROL,
460 			    reg | FXP_EEPROM_EESK);
461 			DELAY(1);
462 			CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
463 			DELAY(1);
464 		}
465 		/*
466 		 * Shift in address.
467 		 */
468 		for (x = 6; x > 0; x--) {
469 			if ((i + offset) & (1 << (x - 1))) {
470 				reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
471 			} else {
472 				reg = FXP_EEPROM_EECS;
473 			}
474 			CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
475 			CSR_WRITE_2(FXP_CSR_EEPROMCONTROL,
476 			    reg | FXP_EEPROM_EESK);
477 			DELAY(1);
478 			CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
479 			DELAY(1);
480 		}
481 		reg = FXP_EEPROM_EECS;
482 		data[i] = 0;
483 		/*
484 		 * Shift out data.
485 		 */
486 		for (x = 16; x > 0; x--) {
487 			CSR_WRITE_2(FXP_CSR_EEPROMCONTROL,
488 			    reg | FXP_EEPROM_EESK);
489 			DELAY(1);
490 			if (CSR_READ_2(FXP_CSR_EEPROMCONTROL) &
491 			    FXP_EEPROM_EEDO)
492 				data[i] |= (1 << (x - 1));
493 			CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
494 			DELAY(1);
495 		}
496 		CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, 0);
497 		DELAY(1);
498 	}
499 }
500 
501