1 /*	$OpenBSD: if_lmc_common.c,v 1.9 2004/05/12 06:35:11 tedu Exp $ */
2 /*	$NetBSD: if_lmc_common.c,v 1.1 1999/03/25 03:32:43 explorer Exp $	*/
3 
4 /*-
5  * Copyright (c) 1997-1999 LAN Media Corporation (LMC)
6  * All rights reserved.  www.lanmedia.com
7  *
8  * This code is written by Michael Graff <graff@vix.com> for LMC.
9  * The code is derived from permitted modifications to software created
10  * by Matt Thomas (matt@3am-software.com).
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above
18  *    copyright notice, this list of conditions and the following disclaimer
19  *    in the documentation and/or other materials provided with the
20  *    distribution.
21  * 3. All marketing or advertising materials mentioning features or
22  *    use of this software must display the following acknowledgement:
23  *      This product includes software developed by LAN Media Corporation
24  *      and its contributors.
25  * 4. Neither the name of LAN Media Corporation nor the names of its
26  *    contributors may be used to endorse or promote products derived
27  *    from this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY LAN MEDIA CORPORATION AND CONTRIBUTORS
30  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
31  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
33  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
39  * THE POSSIBILITY OF SUCH DAMAGE.
40  */
41 
42 /*-
43  * Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com)
44  * All rights reserved.
45  *
46  * Redistribution and use in source and binary forms, with or without
47  * modification, are permitted provided that the following conditions
48  * are met:
49  * 1. Redistributions of source code must retain the above copyright
50  *    notice, this list of conditions and the following disclaimer.
51  * 2. The name of the author may not be used to endorse or promote products
52  *    derived from this software without specific prior written permission
53  *
54  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
55  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
56  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
57  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
58  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
59  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
60  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
61  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
62  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
63  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64  */
65 
66 #include <sys/param.h>
67 #include <sys/systm.h>
68 #include <sys/mbuf.h>
69 #include <sys/socket.h>
70 #include <sys/ioctl.h>
71 #include <sys/errno.h>
72 #include <sys/malloc.h>
73 #include <sys/kernel.h>
74 #include <sys/proc.h>	/* only for declaration of wakeup() used by vm.h */
75 #if defined(__FreeBSD__)
76 #include <machine/clock.h>
77 #elif defined(__bsdi__) || defined(__NetBSD__) || defined(__OpenBSD__)
78 #include <sys/device.h>
79 #endif
80 
81 #if defined(__NetBSD__)
82 #include <dev/pci/pcidevs.h>
83 #include "rnd.h"
84 #if NRND > 0
85 #include <sys/rnd.h>
86 #endif
87 #endif
88 
89 #if defined(__OpenBSD__)
90 #include <dev/pci/pcidevs.h>
91 #endif
92 
93 #include <net/if.h>
94 #include <net/if_types.h>
95 #include <net/if_dl.h>
96 #include <net/netisr.h>
97 
98 #include "bpfilter.h"
99 #if NBPFILTER > 0
100 #include <net/bpf.h>
101 #endif
102 
103 #include <uvm/uvm_extern.h>
104 
105 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
106 #include <net/if_sppp.h>
107 #endif
108 
109 #if defined(__bsdi__)
110 #if INET
111 #include <netinet/in.h>
112 #include <netinet/in_systm.h>
113 #include <netinet/ip.h>
114 #endif
115 
116 #include <net/netisr.h>
117 #include <net/if.h>
118 #include <net/netisr.h>
119 #include <net/if_types.h>
120 #include <net/if_p2p.h>
121 #include <net/if_c_hdlc.h>
122 #endif
123 
124 #if defined(__FreeBSD__)
125 #include <vm/pmap.h>
126 #include <pci.h>
127 #if NPCI > 0
128 #include <pci/pcivar.h>
129 #include <pci/dc21040reg.h>
130 #define INCLUDE_PATH_PREFIX "pci/"
131 #endif
132 #endif /* __FreeBSD__ */
133 
134 #if defined(__bsdi__)
135 #include <i386/pci/ic/dc21040.h>
136 #include <i386/isa/isa.h>
137 #include <i386/isa/icu.h>
138 #include <i386/isa/dma.h>
139 #include <i386/isa/isavar.h>
140 #include <i386/pci/pci.h>
141 
142 #define	INCLUDE_PATH_PREFIX	"i386/pci/"
143 #endif /* __bsdi__ */
144 
145 #if defined(__NetBSD__) || defined(__OpenBSD__)
146 #include <machine/bus.h>
147 #if defined(__alpha__) && defined(__NetBSD__)
148 #include <machine/intr.h>
149 #endif
150 #include <dev/pci/pcireg.h>
151 #include <dev/pci/pcivar.h>
152 #include <dev/ic/dc21040reg.h>
153 #define	INCLUDE_PATH_PREFIX	"dev/pci/"
154 #endif /* __NetBSD__ */
155 
156 #if defined(__OpenBSD__)
157 #define d_length1 u.bd_length1
158 #define d_length2 u.bd_length2
159 #define d_flag u.bd_flag
160 #endif
161 
162 /*
163  * Sigh.  Every OS puts these in different places.  NetBSD and FreeBSD use
164  * a C preprocessor that allows this hack, but BSDI does not.
165  */
166 #if defined(__NetBSD__) || defined(__FreeBSD__)
167 #include INCLUDE_PATH_PREFIX "if_lmc_types.h"
168 #include INCLUDE_PATH_PREFIX "if_lmcioctl.h"
169 #include INCLUDE_PATH_PREFIX "if_lmcvar.h"
170 #elif defined(__OpenBSD__)
171 #include <dev/pci/if_lmc_types.h>
172 #include <dev/pci/if_lmcioctl.h>
173 #include <dev/pci/if_lmcvar.h>
174 #else /* BSDI */
175 #include "i386/pci/if_lmc_types.h"
176 #include "i386/pci/if_lmcioctl.h"
177 #include "i386/pci/if_lmcvar.h"
178 #endif
179 
180 void
lmc_gpio_mkinput(lmc_softc_t * const sc,u_int32_t bits)181 lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits)
182 {
183 	sc->lmc_gpio_io &= ~bits;
184 	LMC_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET | (sc->lmc_gpio_io));
185 }
186 
187 void
lmc_gpio_mkoutput(lmc_softc_t * const sc,u_int32_t bits)188 lmc_gpio_mkoutput(lmc_softc_t * const sc, u_int32_t bits)
189 {
190 	sc->lmc_gpio_io |= bits;
191 	LMC_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET | (sc->lmc_gpio_io));
192 }
193 
194 void
lmc_led_on(lmc_softc_t * const sc,u_int32_t led)195 lmc_led_on(lmc_softc_t * const sc, u_int32_t led)
196 {
197 	sc->lmc_miireg16 &= ~led;
198 	lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
199 }
200 
201 void
lmc_led_off(lmc_softc_t * const sc,u_int32_t led)202 lmc_led_off(lmc_softc_t * const sc, u_int32_t led)
203 {
204 	sc->lmc_miireg16 |= led;
205 	lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
206 }
207 
208 void
lmc_reset(lmc_softc_t * const sc)209 lmc_reset(lmc_softc_t * const sc)
210 {
211 	sc->lmc_miireg16 |= LMC_MII16_FIFO_RESET;
212 	lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
213 
214 	sc->lmc_miireg16 &= ~LMC_MII16_FIFO_RESET;
215 	lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
216 
217 	/*
218 	 * make some of the GPIO pins be outputs
219 	 */
220 	lmc_gpio_mkoutput(sc, LMC_GEP_DP | LMC_GEP_RESET);
221 
222 	/*
223 	 * drive DP and RESET low to force configuration.  This also forces
224 	 * the transmitter clock to be internal, but we expect to reset
225 	 * that later anyway.
226 	 */
227 	sc->lmc_gpio &= ~(LMC_GEP_DP | LMC_GEP_RESET);
228 	LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
229 
230 	/*
231 	 * hold for more than 10 microseconds
232 	 */
233 	DELAY(50);
234 
235 	/*
236 	 * stop driving Xilinx-related signals
237 	 */
238 	lmc_gpio_mkinput(sc, LMC_GEP_DP | LMC_GEP_RESET);
239 
240 	/*
241 	 * busy wait for the chip to reset
242 	 */
243 	while ((LMC_CSR_READ(sc, csr_gp) & LMC_GEP_DP) == 0);
244 
245 	/*
246 	 * Call media specific init routine
247 	 */
248 	sc->lmc_media->init(sc);
249 }
250 
251 void
lmc_dec_reset(lmc_softc_t * const sc)252 lmc_dec_reset(lmc_softc_t * const sc)
253 {
254 #ifndef __linux__
255 	lmc_ringinfo_t *ri;
256 	tulip_desc_t *di;
257 #endif
258 	u_int32_t val;
259 
260 	/*
261 	 * disable all interrupts
262 	 */
263 	sc->lmc_intrmask = 0;
264 	LMC_CSR_WRITE(sc, csr_intr, sc->lmc_intrmask);
265 
266 	/*
267 	 * we are, obviously, down.
268 	 */
269 #ifndef __linux__
270 	sc->lmc_flags &= ~(LMC_IFUP | LMC_MODEMOK);
271 
272 	DP(("lmc_dec_reset\n"));
273 #endif
274 
275 	/*
276 	 * Reset the chip with a software reset command.
277 	 * Wait 10 microseconds (actually 50 PCI cycles but at
278 	 * 33MHz that comes to two microseconds but wait a
279 	 * bit longer anyways)
280 	 */
281 	LMC_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
282 	DELAY(10);
283 	sc->lmc_cmdmode = LMC_CSR_READ(sc, csr_command);
284 
285 	/*
286 	 * We want:
287 	 *   no ethernet address in frames we write
288 	 *   disable padding (txdesc, padding disable)
289 	 *   ignore runt frames (rdes0 bit 15)
290 	 *   no receiver watchdog or transmitter jabber timer
291 	 *       (csr15 bit 0,14 == 1)
292 	 *   if using 16-bit CRC, turn off CRC (trans desc, crc disable)
293 	 */
294 
295 #ifndef TULIP_CMD_RECEIVEALL
296 #define TULIP_CMD_RECEIVEALL 0x40000000L
297 #endif
298 
299 	sc->lmc_cmdmode |= ( TULIP_CMD_PROMISCUOUS
300 			       | TULIP_CMD_FULLDUPLEX
301 			       | TULIP_CMD_PASSBADPKT
302 			       | TULIP_CMD_NOHEARTBEAT
303 			       | TULIP_CMD_PORTSELECT
304 			       | TULIP_CMD_RECEIVEALL
305 			       | TULIP_CMD_MUSTBEONE
306 			       );
307 	sc->lmc_cmdmode &= ~( TULIP_CMD_OPERMODE
308 				| TULIP_CMD_THRESHOLDCTL
309 				| TULIP_CMD_STOREFWD
310 				| TULIP_CMD_TXTHRSHLDCTL
311 				);
312 
313 	LMC_CSR_WRITE(sc, csr_command, sc->lmc_cmdmode);
314 
315 	/*
316 	 * disable receiver watchdog and transmit jabber
317 	 */
318 	val = LMC_CSR_READ(sc, csr_sia_general);
319 	val |= (TULIP_WATCHDOG_TXDISABLE | TULIP_WATCHDOG_RXDISABLE);
320 	LMC_CSR_WRITE(sc, csr_sia_general, val);
321 
322 	/*
323 	 * turn off those LEDs...
324 	 */
325 	sc->lmc_miireg16 |= LMC_MII16_LED_ALL;
326 	lmc_led_on(sc, LMC_MII16_LED0);
327 
328 #ifndef __linux__
329 	/*
330 	 * reprogram the tx desc, rx desc, and PCI bus options
331 	 */
332 	LMC_CSR_WRITE(sc, csr_txlist,
333 			LMC_KVATOPHYS(sc, &sc->lmc_txinfo.ri_first[0]));
334 	LMC_CSR_WRITE(sc, csr_rxlist,
335 			LMC_KVATOPHYS(sc, &sc->lmc_rxinfo.ri_first[0]));
336 	LMC_CSR_WRITE(sc, csr_busmode,
337 			(1 << (LMC_BURSTSIZE(sc->lmc_unit) + 8))
338 			|TULIP_BUSMODE_CACHE_ALIGN8
339 			|TULIP_BUSMODE_READMULTIPLE
340 			|(BYTE_ORDER != LITTLE_ENDIAN ? TULIP_BUSMODE_BIGENDIAN : 0));
341 
342 	sc->lmc_txq.ifq_maxlen = LMC_TXDESCS;
343 
344 	/*
345 	 * Free all the mbufs that were on the transmit ring.
346 	 */
347 	for (;;) {
348 		struct mbuf *m;
349 
350 		IF_DEQUEUE(&sc->lmc_txq, m);
351 		if (m == NULL)
352 			break;
353 		m_freem(m);
354 	}
355 
356 	/*
357 	 * reset descriptor state and reclaim all descriptors.
358 	 */
359 	ri = &sc->lmc_txinfo;
360 	ri->ri_nextin = ri->ri_nextout = ri->ri_first;
361 	ri->ri_free = ri->ri_max;
362 	for (di = ri->ri_first; di < ri->ri_last; di++)
363 		di->d_status = 0;
364 
365 	/*
366 	 * We need to collect all the mbufs were on the
367 	 * receive ring before we reinit it either to put
368 	 * them back on or to know if we have to allocate
369 	 * more.
370 	 */
371 	ri = &sc->lmc_rxinfo;
372 	ri->ri_nextin = ri->ri_nextout = ri->ri_first;
373 	ri->ri_free = ri->ri_max;
374 	for (di = ri->ri_first; di < ri->ri_last; di++) {
375 		di->d_status = 0;
376 		di->d_length1 = 0; di->d_addr1 = 0;
377 		di->d_length2 = 0; di->d_addr2 = 0;
378 	}
379 	for (;;) {
380 		struct mbuf *m;
381 		IF_DEQUEUE(&sc->lmc_rxq, m);
382 		if (m == NULL)
383 			break;
384 		m_freem(m);
385 	}
386 #endif
387 }
388 
389 void
lmc_initcsrs(lmc_softc_t * const sc,lmc_csrptr_t csr_base,size_t csr_size)390 lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base,
391 	     size_t csr_size)
392 {
393 	sc->lmc_csrs.csr_busmode	= csr_base +  0 * csr_size;
394 	sc->lmc_csrs.csr_txpoll		= csr_base +  1 * csr_size;
395 	sc->lmc_csrs.csr_rxpoll		= csr_base +  2 * csr_size;
396 	sc->lmc_csrs.csr_rxlist		= csr_base +  3 * csr_size;
397 	sc->lmc_csrs.csr_txlist		= csr_base +  4 * csr_size;
398 	sc->lmc_csrs.csr_status		= csr_base +  5 * csr_size;
399 	sc->lmc_csrs.csr_command	= csr_base +  6 * csr_size;
400 	sc->lmc_csrs.csr_intr		= csr_base +  7 * csr_size;
401 	sc->lmc_csrs.csr_missed_frames	= csr_base +  8 * csr_size;
402 	sc->lmc_csrs.csr_9		= csr_base +  9 * csr_size;
403 	sc->lmc_csrs.csr_10		= csr_base + 10 * csr_size;
404 	sc->lmc_csrs.csr_11		= csr_base + 11 * csr_size;
405 	sc->lmc_csrs.csr_12		= csr_base + 12 * csr_size;
406 	sc->lmc_csrs.csr_13		= csr_base + 13 * csr_size;
407 	sc->lmc_csrs.csr_14		= csr_base + 14 * csr_size;
408 	sc->lmc_csrs.csr_15		= csr_base + 15 * csr_size;
409 }
410