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