Annotation of sys/dev/cardbus/if_rl_cardbus.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_rl_cardbus.c,v 1.16 2007/05/08 18:49:32 deraadt Exp $ */
2: /* $NetBSD: if_rl_cardbus.c,v 1.3.8.3 2001/11/14 19:14:02 nathanw Exp $ */
3:
4: /*
5: * Copyright (c) 2000 Masanori Kanaoka
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. The name of the author may not be used to endorse or promote products
17: * derived from this software without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29: */
30:
31: /*
32: * if_rl_cardbus.c:
33: * Cardbus specific routines for RealTek 8139 ethernet adapter.
34: * Tested for
35: * - elecom-Laneed LD-10/100CBA (Accton MPX5030)
36: * - MELCO LPC3-TX-CB (RealTek 8139)
37: */
38:
39: #include "bpfilter.h"
40:
41: #include <sys/param.h>
42: #include <sys/systm.h>
43: #include <sys/mbuf.h>
44: #include <sys/socket.h>
45: #include <sys/ioctl.h>
46: #include <sys/errno.h>
47: #include <sys/malloc.h>
48: #include <sys/kernel.h>
49: #include <sys/timeout.h>
50: #include <sys/device.h>
51:
52: #include <net/if.h>
53: #include <net/if_dl.h>
54: #include <net/if_types.h>
55: #include <net/if_media.h>
56:
57: #include <machine/endian.h>
58:
59: #if NBPFILTER > 0
60: #include <net/bpf.h>
61: #endif
62:
63: #ifdef INET
64: #include <netinet/in.h>
65: #include <netinet/in_systm.h>
66: #include <netinet/in_var.h>
67: #include <netinet/ip.h>
68: #include <netinet/if_ether.h>
69: #endif
70:
71: #include <machine/bus.h>
72: #include <machine/intr.h>
73:
74: #include <dev/mii/miivar.h>
75:
76: #include <dev/pci/pcivar.h>
77: #include <dev/pci/pcireg.h>
78: #include <dev/pci/pcidevs.h>
79:
80: #include <dev/cardbus/cardbusvar.h>
81:
82: /*
83: * Default to using PIO access for this driver. On SMP systems,
84: * there appear to be problems with memory mapped mode: it looks like
85: * doing too many memory mapped access back to back in rapid succession
86: * can hang the bus. I'm inclined to blame this on crummy design/construction
87: * on the part of RealTek. Memory mapped mode does appear to work on
88: * uniprocessor systems though.
89: */
90: #define RL_USEIOSPACE
91:
92: #include <dev/ic/rtl81x9reg.h>
93:
94: /*
95: * Various supported device vendors/types and their names.
96: */
97: const struct cardbus_matchid rl_cardbus_devices[] = {
98: { PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_5030 },
99: { PCI_VENDOR_ABOCOM, PCI_PRODUCT_ABOCOM_FE2000VX },
100: { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8138 },
101: { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8139 },
102: { PCI_VENDOR_COREGA, PCI_PRODUCT_COREGA_CB_TXD },
103: { PCI_VENDOR_COREGA, PCI_PRODUCT_COREGA_2CB_TXD },
104: { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DFE690TXD },
105: { PCI_VENDOR_PLANEX, PCI_PRODUCT_PLANEX_FNW_3603_TX },
106: { PCI_VENDOR_PLANEX, PCI_PRODUCT_PLANEX_FNW_3800_TX },
107: };
108:
109: struct rl_cardbus_softc {
110: struct rl_softc sc_rl; /* real rtk softc */
111:
112: /* CardBus-specific goo. */
113: void *sc_ih;
114: cardbus_devfunc_t sc_ct;
115: cardbustag_t sc_tag;
116: int sc_csr;
117: int sc_cben;
118: int sc_bar_reg;
119: pcireg_t sc_bar_val;
120: bus_size_t sc_mapsize;
121: int sc_intrline;
122: };
123:
124: static int rl_cardbus_match(struct device *, void *, void *);
125: static void rl_cardbus_attach(struct device *, struct device *, void *);
126: static int rl_cardbus_detach(struct device *, int);
127: void rl_cardbus_setup(struct rl_cardbus_softc *);
128:
129: struct cfattach rl_cardbus_ca = {
130: sizeof(struct rl_cardbus_softc), rl_cardbus_match, rl_cardbus_attach,
131: rl_cardbus_detach
132: };
133:
134: int
135: rl_cardbus_match(parent, match, aux)
136: struct device *parent;
137: void *match;
138: void *aux;
139: {
140: return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
141: rl_cardbus_devices,
142: sizeof(rl_cardbus_devices)/sizeof(rl_cardbus_devices[0])));
143: }
144:
145:
146: void
147: rl_cardbus_attach(parent, self, aux)
148: struct device *parent, *self;
149: void *aux;
150: {
151: struct rl_cardbus_softc *csc = (struct rl_cardbus_softc *)self;
152: struct rl_softc *sc = &csc->sc_rl;
153: struct cardbus_attach_args *ca = aux;
154: struct cardbus_softc *psc =
155: (struct cardbus_softc *)sc->sc_dev.dv_parent;
156: cardbus_chipset_tag_t cc = psc->sc_cc;
157: cardbus_function_tag_t cf = psc->sc_cf;
158: cardbus_devfunc_t ct = ca->ca_ct;
159: bus_addr_t adr;
160:
161: sc->sc_dmat = ca->ca_dmat;
162: csc->sc_ct = ct;
163: csc->sc_tag = ca->ca_tag;
164: csc->sc_intrline = ca->ca_intrline;
165:
166: /*
167: * Map control/status registers.
168: */
169: csc->sc_csr = CARDBUS_COMMAND_MASTER_ENABLE;
170: #ifdef RL_USEIOSPACE
171: if (Cardbus_mapreg_map(ct, RL_PCI_LOIO, CARDBUS_MAPREG_TYPE_IO, 0,
172: &sc->rl_btag, &sc->rl_bhandle, &adr, &csc->sc_mapsize) == 0) {
173: csc->sc_cben = CARDBUS_IO_ENABLE;
174: csc->sc_csr |= CARDBUS_COMMAND_IO_ENABLE;
175: csc->sc_bar_reg = RL_PCI_LOIO;
176: csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_IO;
177: }
178: #else
179: if (Cardbus_mapreg_map(ct, RL_PCI_LOMEM, CARDBUS_MAPREG_TYPE_MEM, 0,
180: &sc->rl_btag, &sc->rl_bhandle, &adr, &csc->sc_mapsize) == 0) {
181: csc->sc_cben = CARDBUS_MEM_ENABLE;
182: csc->sc_csr |= CARDBUS_COMMAND_MEM_ENABLE;
183: csc->sc_bar_reg = RL_PCI_LOMEM;
184: csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_MEM;
185: }
186: #endif
187: else {
188: printf("%s: unable to map deviceregisters\n",
189: sc->sc_dev.dv_xname);
190: return;
191: }
192:
193: Cardbus_function_enable(ct);
194:
195: rl_cardbus_setup(csc);
196:
197: /*
198: * Map and establish the interrupt.
199: */
200: csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
201: rl_intr, sc, sc->sc_dev.dv_xname);
202: if (csc->sc_ih == NULL) {
203: printf(": couldn't establish interrupt\n");
204: Cardbus_function_disable(csc->sc_ct);
205: return;
206: }
207: printf(": irq %d", csc->sc_intrline);
208:
209: /* XXX - hardcode this, for now */
210: sc->rl_type = RL_8139;
211:
212: rl_attach(sc);
213: }
214:
215: extern int rl_detach(struct rl_softc *);
216:
217: int
218: rl_detach(sc)
219: struct rl_softc *sc;
220: {
221: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
222:
223: /* Unhook our tick handler. */
224: timeout_del(&sc->sc_tick_tmo);
225:
226: /* Detach any PHYs we might have. */
227: if (LIST_FIRST(&sc->sc_mii.mii_phys) != NULL)
228: mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
229:
230: /* Delete any remaining media. */
231: ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
232:
233: ether_ifdetach(ifp);
234: if_detach(ifp);
235:
236: if (sc->sc_sdhook != NULL)
237: shutdownhook_disestablish(sc->sc_sdhook);
238: if (sc->sc_pwrhook != NULL)
239: powerhook_disestablish(sc->sc_pwrhook);
240:
241: return (0);
242: }
243:
244: int
245: rl_cardbus_detach(self, flags)
246: struct device *self;
247: int flags;
248: {
249: struct rl_cardbus_softc *csc = (void *) self;
250: struct rl_softc *sc = &csc->sc_rl;
251: struct cardbus_devfunc *ct = csc->sc_ct;
252: int rv;
253:
254: #ifdef DIAGNOSTIC
255: if (ct == NULL)
256: panic("%s: data structure lacks", sc->sc_dev.dv_xname);
257: #endif
258: rv = rl_detach(sc);
259: if (rv)
260: return (rv);
261: /*
262: * Unhook the interrupt handler.
263: */
264: if (csc->sc_ih != NULL)
265: cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
266:
267: /*
268: * Release bus space and close window.
269: */
270: if (csc->sc_bar_reg != 0)
271: Cardbus_mapreg_unmap(ct, csc->sc_bar_reg,
272: sc->rl_btag, sc->rl_bhandle, csc->sc_mapsize);
273:
274: return (0);
275: }
276:
277: void
278: rl_cardbus_setup(csc)
279: struct rl_cardbus_softc *csc;
280: {
281: struct rl_softc *sc = &csc->sc_rl;
282: cardbus_devfunc_t ct = csc->sc_ct;
283: cardbus_chipset_tag_t cc = ct->ct_cc;
284: cardbus_function_tag_t cf = ct->ct_cf;
285: pcireg_t reg, command;
286: int pmreg;
287:
288: /*
289: * Handle power management nonsense.
290: */
291: if (cardbus_get_capability(cc, cf, csc->sc_tag,
292: PCI_CAP_PWRMGMT, &pmreg, 0)) {
293: command = cardbus_conf_read(cc, cf, csc->sc_tag, pmreg + 4);
294: if (command & RL_PSTATE_MASK) {
295: pcireg_t iobase, membase, irq;
296:
297: /* Save important PCI config data. */
298: iobase = cardbus_conf_read(cc, cf, csc->sc_tag,
299: RL_PCI_LOIO);
300: membase = cardbus_conf_read(cc, cf,csc->sc_tag,
301: RL_PCI_LOMEM);
302: irq = cardbus_conf_read(cc, cf,csc->sc_tag,
303: PCI_PRODUCT_DELTA_8139);
304:
305: /* Reset the power state. */
306: printf("%s: chip is in D%d power mode "
307: "-- setting to D0\n", sc->sc_dev.dv_xname,
308: command & RL_PSTATE_MASK);
309: command &= 0xFFFFFFFC;
310: cardbus_conf_write(cc, cf, csc->sc_tag,
311: pmreg + 4, command);
312:
313: /* Restore PCI config data. */
314: cardbus_conf_write(cc, cf, csc->sc_tag,
315: RL_PCI_LOIO, iobase);
316: cardbus_conf_write(cc, cf, csc->sc_tag,
317: RL_PCI_LOMEM, membase);
318: cardbus_conf_write(cc, cf, csc->sc_tag,
319: PCI_PRODUCT_DELTA_8139, irq);
320: }
321: }
322:
323: /* Make sure the right access type is on the CardBus bridge. */
324: (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
325: (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
326:
327: /* Program the BAR */
328: cardbus_conf_write(cc, cf, csc->sc_tag,
329: csc->sc_bar_reg, csc->sc_bar_val);
330:
331: /* Enable the appropriate bits in the CARDBUS CSR. */
332: reg = cardbus_conf_read(cc, cf, csc->sc_tag,
333: CARDBUS_COMMAND_STATUS_REG);
334: reg &= ~(CARDBUS_COMMAND_IO_ENABLE|CARDBUS_COMMAND_MEM_ENABLE);
335: reg |= csc->sc_csr;
336: cardbus_conf_write(cc, cf, csc->sc_tag,
337: CARDBUS_COMMAND_STATUS_REG, reg);
338:
339: /*
340: * Make sure the latency timer is set to some reasonable
341: * value.
342: */
343: reg = cardbus_conf_read(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG);
344: if (CARDBUS_LATTIMER(reg) < 0x20) {
345: reg &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
346: reg |= (0x20 << CARDBUS_LATTIMER_SHIFT);
347: cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG, reg);
348: }
349: }
350:
CVSweb