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