Annotation of sys/dev/pci/if_lmc_common.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_lmc_common.c,v 1.11 2005/11/07 00:29:21 brad 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 "bpfilter.h"
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: #include <sys/device.h>
78:
79: #include <dev/pci/pcidevs.h>
80:
81: #include <net/if.h>
82: #include <net/if_types.h>
83: #include <net/if_dl.h>
84: #include <net/netisr.h>
85:
86: #if NBPFILTER > 0
87: #include <net/bpf.h>
88: #endif
89:
90: #include <net/if_sppp.h>
91:
92: #include <machine/bus.h>
93:
94: #include <dev/pci/pcireg.h>
95: #include <dev/pci/pcivar.h>
96: #include <dev/ic/dc21040reg.h>
97:
98: #define d_length1 u.bd_length1
99: #define d_length2 u.bd_length2
100: #define d_flag u.bd_flag
101:
102: #include <dev/pci/if_lmc_types.h>
103: #include <dev/pci/if_lmcioctl.h>
104: #include <dev/pci/if_lmcvar.h>
105:
106: void
107: lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits)
108: {
109: sc->lmc_gpio_io &= ~bits;
110: LMC_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET | (sc->lmc_gpio_io));
111: }
112:
113: void
114: lmc_gpio_mkoutput(lmc_softc_t * const sc, u_int32_t bits)
115: {
116: sc->lmc_gpio_io |= bits;
117: LMC_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET | (sc->lmc_gpio_io));
118: }
119:
120: void
121: lmc_led_on(lmc_softc_t * const sc, u_int32_t led)
122: {
123: sc->lmc_miireg16 &= ~led;
124: lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
125: }
126:
127: void
128: lmc_led_off(lmc_softc_t * const sc, u_int32_t led)
129: {
130: sc->lmc_miireg16 |= led;
131: lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
132: }
133:
134: void
135: lmc_reset(lmc_softc_t * const sc)
136: {
137: sc->lmc_miireg16 |= LMC_MII16_FIFO_RESET;
138: lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
139:
140: sc->lmc_miireg16 &= ~LMC_MII16_FIFO_RESET;
141: lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
142:
143: /*
144: * make some of the GPIO pins be outputs
145: */
146: lmc_gpio_mkoutput(sc, LMC_GEP_DP | LMC_GEP_RESET);
147:
148: /*
149: * drive DP and RESET low to force configuration. This also forces
150: * the transmitter clock to be internal, but we expect to reset
151: * that later anyway.
152: */
153: sc->lmc_gpio &= ~(LMC_GEP_DP | LMC_GEP_RESET);
154: LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
155:
156: /*
157: * hold for more than 10 microseconds
158: */
159: DELAY(50);
160:
161: /*
162: * stop driving Xilinx-related signals
163: */
164: lmc_gpio_mkinput(sc, LMC_GEP_DP | LMC_GEP_RESET);
165:
166: /*
167: * busy wait for the chip to reset
168: */
169: while ((LMC_CSR_READ(sc, csr_gp) & LMC_GEP_DP) == 0);
170:
171: /*
172: * Call media specific init routine
173: */
174: sc->lmc_media->init(sc);
175: }
176:
177: void
178: lmc_dec_reset(lmc_softc_t * const sc)
179: {
180: #ifndef __linux__
181: lmc_ringinfo_t *ri;
182: lmc_desc_t *di;
183: #endif
184: u_int32_t val;
185:
186: /*
187: * disable all interrupts
188: */
189: sc->lmc_intrmask = 0;
190: LMC_CSR_WRITE(sc, csr_intr, sc->lmc_intrmask);
191:
192: /*
193: * we are, obviously, down.
194: */
195: #ifndef __linux__
196: sc->lmc_flags &= ~(LMC_IFUP | LMC_MODEMOK);
197:
198: DP(("lmc_dec_reset\n"));
199: #endif
200:
201: /*
202: * Reset the chip with a software reset command.
203: * Wait 10 microseconds (actually 50 PCI cycles but at
204: * 33MHz that comes to two microseconds but wait a
205: * bit longer anyways)
206: */
207: LMC_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
208: DELAY(10);
209: sc->lmc_cmdmode = LMC_CSR_READ(sc, csr_command);
210:
211: /*
212: * We want:
213: * no ethernet address in frames we write
214: * disable padding (txdesc, padding disable)
215: * ignore runt frames (rdes0 bit 15)
216: * no receiver watchdog or transmitter jabber timer
217: * (csr15 bit 0,14 == 1)
218: * if using 16-bit CRC, turn off CRC (trans desc, crc disable)
219: */
220:
221: #ifndef TULIP_CMD_RECEIVEALL
222: #define TULIP_CMD_RECEIVEALL 0x40000000L
223: #endif
224:
225: sc->lmc_cmdmode |= ( TULIP_CMD_PROMISCUOUS
226: | TULIP_CMD_FULLDUPLEX
227: | TULIP_CMD_PASSBADPKT
228: | TULIP_CMD_NOHEARTBEAT
229: | TULIP_CMD_PORTSELECT
230: | TULIP_CMD_RECEIVEALL
231: | TULIP_CMD_MUSTBEONE
232: );
233: sc->lmc_cmdmode &= ~( TULIP_CMD_OPERMODE
234: | TULIP_CMD_THRESHOLDCTL
235: | TULIP_CMD_STOREFWD
236: | TULIP_CMD_TXTHRSHLDCTL
237: );
238:
239: LMC_CSR_WRITE(sc, csr_command, sc->lmc_cmdmode);
240:
241: /*
242: * disable receiver watchdog and transmit jabber
243: */
244: val = LMC_CSR_READ(sc, csr_sia_general);
245: val |= (TULIP_WATCHDOG_TXDISABLE | TULIP_WATCHDOG_RXDISABLE);
246: LMC_CSR_WRITE(sc, csr_sia_general, val);
247:
248: /*
249: * turn off those LEDs...
250: */
251: sc->lmc_miireg16 |= LMC_MII16_LED_ALL;
252: lmc_led_on(sc, LMC_MII16_LED0);
253:
254: #ifndef __linux__
255: /*
256: * reprogram the tx desc, rx desc, and PCI bus options
257: */
258: LMC_CSR_WRITE(sc, csr_txlist, sc->lmc_txdescmap->dm_segs[0].ds_addr);
259: LMC_CSR_WRITE(sc, csr_rxlist, sc->lmc_rxdescmap->dm_segs[0].ds_addr);
260: LMC_CSR_WRITE(sc, csr_busmode,
261: (1 << (LMC_BURSTSIZE(sc->lmc_unit) + 8))
262: |TULIP_BUSMODE_CACHE_ALIGN8
263: |TULIP_BUSMODE_READMULTIPLE);
264:
265: sc->lmc_txq.ifq_maxlen = LMC_TXDESCS;
266:
267: /*
268: * Free all the mbufs that were on the transmit ring.
269: */
270: for (;;) {
271: bus_dmamap_t map;
272: struct mbuf *m;
273:
274: IF_DEQUEUE(&sc->lmc_txq, m);
275: if (m == NULL)
276: break;
277: map = LMC_GETCTX(m, bus_dmamap_t);
278: bus_dmamap_unload(sc->lmc_dmatag, map);
279: sc->lmc_txmaps[sc->lmc_txmaps_free++] = map;
280: m_freem(m);
281: }
282:
283: /*
284: * reset descriptor state and reclaim all descriptors.
285: */
286: ri = &sc->lmc_txinfo;
287: ri->ri_nextin = ri->ri_nextout = ri->ri_first;
288: ri->ri_free = ri->ri_max;
289: for (di = ri->ri_first; di < ri->ri_last; di++)
290: di->d_status = 0;
291: bus_dmamap_sync(sc->lmc_dmatag, sc->lmc_txdescmap,
292: 0, sc->lmc_txdescmap->dm_mapsize,
293: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
294:
295: /*
296: * We need to collect all the mbufs were on the
297: * receive ring before we reinit it either to put
298: * them back on or to know if we have to allocate
299: * more.
300: */
301: ri = &sc->lmc_rxinfo;
302: ri->ri_nextin = ri->ri_nextout = ri->ri_first;
303: ri->ri_free = ri->ri_max;
304: for (di = ri->ri_first; di < ri->ri_last; di++) {
305: u_int32_t ctl = di->d_ctl;
306: di->d_status = 0;
307: di->d_ctl = LMC_CTL(LMC_CTL_FLGS(ctl),0,0);
308: di->d_addr1 = 0;
309: di->d_addr2 = 0;
310: }
311: bus_dmamap_sync(sc->lmc_dmatag, sc->lmc_rxdescmap,
312: 0, sc->lmc_rxdescmap->dm_mapsize,
313: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
314: for (;;) {
315: bus_dmamap_t map;
316: struct mbuf *m;
317: IF_DEQUEUE(&sc->lmc_rxq, m);
318: if (m == NULL)
319: break;
320: map = LMC_GETCTX(m, bus_dmamap_t);
321: bus_dmamap_unload(sc->lmc_dmatag, map);
322: sc->lmc_rxmaps[sc->lmc_rxmaps_free++] = map;
323: m_freem(m);
324: }
325: #endif
326: }
327:
328: void
329: lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base,
330: size_t csr_size)
331: {
332: sc->lmc_csrs.csr_busmode = csr_base + 0 * csr_size;
333: sc->lmc_csrs.csr_txpoll = csr_base + 1 * csr_size;
334: sc->lmc_csrs.csr_rxpoll = csr_base + 2 * csr_size;
335: sc->lmc_csrs.csr_rxlist = csr_base + 3 * csr_size;
336: sc->lmc_csrs.csr_txlist = csr_base + 4 * csr_size;
337: sc->lmc_csrs.csr_status = csr_base + 5 * csr_size;
338: sc->lmc_csrs.csr_command = csr_base + 6 * csr_size;
339: sc->lmc_csrs.csr_intr = csr_base + 7 * csr_size;
340: sc->lmc_csrs.csr_missed_frames = csr_base + 8 * csr_size;
341: sc->lmc_csrs.csr_9 = csr_base + 9 * csr_size;
342: sc->lmc_csrs.csr_10 = csr_base + 10 * csr_size;
343: sc->lmc_csrs.csr_11 = csr_base + 11 * csr_size;
344: sc->lmc_csrs.csr_12 = csr_base + 12 * csr_size;
345: sc->lmc_csrs.csr_13 = csr_base + 13 * csr_size;
346: sc->lmc_csrs.csr_14 = csr_base + 14 * csr_size;
347: sc->lmc_csrs.csr_15 = csr_base + 15 * csr_size;
348: }
CVSweb