Annotation of sys/dev/cardbus/if_rtw_cardbus.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_rtw_cardbus.c,v 1.11 2006/10/12 16:35:52 grange Exp $ */
2: /* $NetBSD: if_rtw_cardbus.c,v 1.4 2004/12/20 21:05:34 dyoung Exp $ */
3:
4: /*-
5: * Copyright (c) 2004, 2005 David Young. All rights reserved.
6: *
7: * Adapted for the RTL8180 by David Young.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. The name of David Young may not be used to endorse or promote
18: * products derived from this software without specific prior
19: * written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY
22: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David
25: * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32: * OF SUCH DAMAGE.
33: */
34: /*-
35: * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
36: * All rights reserved.
37: *
38: * This code is derived from software contributed to The NetBSD Foundation
39: * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
40: * NASA Ames Research Center.
41: *
42: * Redistribution and use in source and binary forms, with or without
43: * modification, are permitted provided that the following conditions
44: * are met:
45: * 1. Redistributions of source code must retain the above copyright
46: * notice, this list of conditions and the following disclaimer.
47: * 2. Redistributions in binary form must reproduce the above copyright
48: * notice, this list of conditions and the following disclaimer in the
49: * documentation and/or other materials provided with the distribution.
50: * 3. All advertising materials mentioning features or use of this software
51: * must display the following acknowledgement:
52: * This product includes software developed by the NetBSD
53: * Foundation, Inc. and its contributors.
54: * 4. Neither the name of The NetBSD Foundation nor the names of its
55: * contributors may be used to endorse or promote products derived
56: * from this software without specific prior written permission.
57: *
58: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
59: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
60: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
61: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
62: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
63: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
64: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
65: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
66: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
67: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
68: * POSSIBILITY OF SUCH DAMAGE.
69: */
70:
71: /*
72: * Cardbus front-end for the Realtek RTL8180 802.11 MAC/BBP driver.
73: *
74: * TBD factor with atw, tlp Cardbus front-ends?
75: */
76:
77: #include <sys/cdefs.h>
78:
79: #include "bpfilter.h"
80:
81: #include <sys/param.h>
82: #include <sys/systm.h>
83: #include <sys/mbuf.h>
84: #include <sys/malloc.h>
85: #include <sys/kernel.h>
86: #include <sys/socket.h>
87: #include <sys/ioctl.h>
88: #include <sys/errno.h>
89: #include <sys/device.h>
90:
91: #include <machine/endian.h>
92:
93: #include <net/if.h>
94: #include <net/if_dl.h>
95: #include <net/if_media.h>
96: #ifdef INET
97: #include <netinet/in.h>
98: #include <netinet/if_ether.h>
99: #endif
100:
101: #include <net80211/ieee80211_radiotap.h>
102: #include <net80211/ieee80211_var.h>
103:
104: #if NBPFILTER > 0
105: #include <net/bpf.h>
106: #endif
107:
108: #include <machine/bus.h>
109: #include <machine/intr.h>
110:
111: #include <dev/ic/rtwreg.h>
112: #include <dev/ic/rtwvar.h>
113:
114: #include <dev/pci/pcivar.h>
115: #include <dev/pci/pcireg.h>
116: #include <dev/pci/pcidevs.h>
117:
118: #include <dev/cardbus/cardbusvar.h>
119: #include <dev/pci/pcidevs.h>
120:
121: /*
122: * PCI configuration space registers used by the RTL8180.
123: */
124: #define RTW_PCI_IOBA 0x10 /* i/o mapped base */
125: #define RTW_PCI_MMBA 0x14 /* memory mapped base */
126:
127: struct rtw_cardbus_softc {
128: struct rtw_softc sc_rtw; /* real RTL8180 softc */
129:
130: /* CardBus-specific goo. */
131: void *sc_ih; /* interrupt handle */
132: cardbus_devfunc_t sc_ct; /* our CardBus devfuncs */
133: cardbustag_t sc_tag; /* our CardBus tag */
134: int sc_csr; /* CSR bits */
135: bus_size_t sc_mapsize; /* size of the mapped bus space
136: * region
137: */
138:
139: int sc_cben; /* CardBus enables */
140: int sc_bar_reg; /* which BAR to use */
141: pcireg_t sc_bar_val; /* value of the BAR */
142:
143: int sc_intrline; /* interrupt line */
144: };
145:
146: int rtw_cardbus_match(struct device *, void *, void *);
147: void rtw_cardbus_attach(struct device *, struct device *, void *);
148: int rtw_cardbus_detach(struct device *, int);
149: void rtw_cardbus_intr_ack(struct rtw_regs *);
150: void rtw_cardbus_funcregen(struct rtw_regs *, int);
151:
152: struct cfattach rtw_cardbus_ca = {
153: sizeof(struct rtw_cardbus_softc), rtw_cardbus_match, rtw_cardbus_attach,
154: rtw_cardbus_detach
155: };
156:
157: void rtw_cardbus_setup(struct rtw_cardbus_softc *);
158:
159: int rtw_cardbus_enable(struct rtw_softc *);
160: void rtw_cardbus_disable(struct rtw_softc *);
161: void rtw_cardbus_power(struct rtw_softc *, int);
162:
163: const struct cardbus_matchid rtw_cardbus_devices[] = {
164: { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8185 },
165: { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8180 },
166: { PCI_VENDOR_BELKIN2, PCI_PRODUCT_BELKIN2_F5D6020V3 },
167: { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DWL610 },
168: };
169:
170: int
171: rtw_cardbus_match(struct device *parent, void *match, void *aux)
172: {
173: return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
174: rtw_cardbus_devices,
175: sizeof(rtw_cardbus_devices)/sizeof(rtw_cardbus_devices[0])));
176: }
177:
178: void
179: rtw_cardbus_intr_ack(struct rtw_regs *regs)
180: {
181: RTW_WRITE(regs, RTW_FER, RTW_FER_INTR);
182: }
183:
184: void
185: rtw_cardbus_funcregen(struct rtw_regs *regs, int enable)
186: {
187: u_int32_t reg;
188: rtw_config0123_enable(regs, 1);
189: reg = RTW_READ(regs, RTW_CONFIG3);
190: if (enable) {
191: RTW_WRITE(regs, RTW_CONFIG3, reg | RTW_CONFIG3_FUNCREGEN);
192: } else {
193: RTW_WRITE(regs, RTW_CONFIG3, reg & ~RTW_CONFIG3_FUNCREGEN);
194: }
195: rtw_config0123_enable(regs, 0);
196: }
197:
198: void
199: rtw_cardbus_attach(struct device *parent, struct device *self, void *aux)
200: {
201: struct rtw_cardbus_softc *csc = (void *)self;
202: struct rtw_softc *sc = &csc->sc_rtw;
203: struct rtw_regs *regs = &sc->sc_regs;
204: struct cardbus_attach_args *ca = aux;
205: cardbus_devfunc_t ct = ca->ca_ct;
206: bus_addr_t adr;
207: int rev;
208:
209: sc->sc_dmat = ca->ca_dmat;
210: csc->sc_ct = ct;
211: csc->sc_tag = ca->ca_tag;
212:
213: /*
214: * Power management hooks.
215: */
216: sc->sc_enable = rtw_cardbus_enable;
217: sc->sc_disable = rtw_cardbus_disable;
218: sc->sc_power = rtw_cardbus_power;
219:
220: sc->sc_intr_ack = rtw_cardbus_intr_ack;
221:
222: /* Get revision info. */
223: rev = PCI_REVISION(ca->ca_class);
224:
225: RTW_DPRINTF(RTW_DEBUG_ATTACH,
226: ("%s: pass %d.%d signature %08x\n", sc->sc_dev.dv_xname,
227: (rev >> 4) & 0xf, rev & 0xf,
228: cardbus_conf_read(ct->ct_cc, ct->ct_cf, csc->sc_tag, 0x80)));
229:
230: /*
231: * Map the device.
232: */
233: csc->sc_csr = CARDBUS_COMMAND_MASTER_ENABLE;
234: if (Cardbus_mapreg_map(ct, RTW_PCI_MMBA,
235: CARDBUS_MAPREG_TYPE_MEM, 0, ®s->r_bt, ®s->r_bh, &adr,
236: &csc->sc_mapsize) == 0) {
237: RTW_DPRINTF(RTW_DEBUG_ATTACH,
238: ("%s: %s mapped %lu bytes mem space\n",
239: sc->sc_dev.dv_xname, __func__, (long)csc->sc_mapsize));
240: csc->sc_cben = CARDBUS_MEM_ENABLE;
241: csc->sc_csr |= CARDBUS_COMMAND_MEM_ENABLE;
242: csc->sc_bar_reg = RTW_PCI_MMBA;
243: csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_MEM;
244: } else if (Cardbus_mapreg_map(ct, RTW_PCI_IOBA,
245: CARDBUS_MAPREG_TYPE_IO, 0, ®s->r_bt, ®s->r_bh, &adr,
246: &csc->sc_mapsize) == 0) {
247: RTW_DPRINTF(RTW_DEBUG_ATTACH,
248: ("%s: %s mapped %lu bytes I/O space\n",
249: sc->sc_dev.dv_xname, __func__, (long)csc->sc_mapsize));
250: csc->sc_cben = CARDBUS_IO_ENABLE;
251: csc->sc_csr |= CARDBUS_COMMAND_IO_ENABLE;
252: csc->sc_bar_reg = RTW_PCI_IOBA;
253: csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_IO;
254: } else {
255: printf("%s: unable to map device registers\n",
256: sc->sc_dev.dv_xname);
257: return;
258: }
259:
260: /*
261: * Bring the chip out of powersave mode and initialize the
262: * configuration registers.
263: */
264: rtw_cardbus_setup(csc);
265:
266: /* Remember which interrupt line. */
267: csc->sc_intrline = ca->ca_intrline;
268:
269: printf(" irq %d\n", csc->sc_intrline);
270:
271: /*
272: * Finish off the attach.
273: */
274: rtw_attach(sc);
275:
276: rtw_cardbus_funcregen(regs, 1);
277:
278: RTW_WRITE(regs, RTW_FEMR, RTW_FEMR_INTR);
279: RTW_WRITE(regs, RTW_FER, RTW_FER_INTR);
280:
281: /*
282: * Power down the socket.
283: */
284: Cardbus_function_disable(csc->sc_ct);
285: }
286:
287: int
288: rtw_cardbus_detach(struct device *self, int flags)
289: {
290: struct rtw_cardbus_softc *csc = (void *)self;
291: struct rtw_softc *sc = &csc->sc_rtw;
292: struct rtw_regs *regs = &sc->sc_regs;
293: struct cardbus_devfunc *ct = csc->sc_ct;
294: int rv;
295:
296: #if defined(DIAGNOSTIC)
297: if (ct == NULL)
298: panic("%s: data structure lacks", sc->sc_dev.dv_xname);
299: #endif
300:
301: rv = rtw_detach(sc);
302: if (rv)
303: return (rv);
304:
305: rtw_cardbus_funcregen(regs, 0);
306:
307: /*
308: * Unhook the interrupt handler.
309: */
310: if (csc->sc_ih != NULL)
311: cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
312:
313: /*
314: * Release bus space and close window.
315: */
316: if (csc->sc_bar_reg != 0)
317: Cardbus_mapreg_unmap(ct, csc->sc_bar_reg,
318: regs->r_bt, regs->r_bh, csc->sc_mapsize);
319:
320: return (0);
321: }
322:
323: int
324: rtw_cardbus_enable(struct rtw_softc *sc)
325: {
326: struct rtw_cardbus_softc *csc = (void *) sc;
327: cardbus_devfunc_t ct = csc->sc_ct;
328: cardbus_chipset_tag_t cc = ct->ct_cc;
329: cardbus_function_tag_t cf = ct->ct_cf;
330:
331: /*
332: * Power on the socket.
333: */
334: Cardbus_function_enable(ct);
335:
336: /*
337: * Set up the PCI configuration registers.
338: */
339: rtw_cardbus_setup(csc);
340:
341: /*
342: * Map and establish the interrupt.
343: */
344: csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
345: rtw_intr, sc, sc->sc_dev.dv_xname);
346: if (csc->sc_ih == NULL) {
347: printf("%s: unable to establish interrupt at %d\n",
348: sc->sc_dev.dv_xname, csc->sc_intrline);
349: Cardbus_function_disable(csc->sc_ct);
350: return (1);
351: }
352:
353: rtw_cardbus_funcregen(&sc->sc_regs, 1);
354:
355: RTW_WRITE(&sc->sc_regs, RTW_FEMR, RTW_FEMR_INTR);
356: RTW_WRITE(&sc->sc_regs, RTW_FER, RTW_FER_INTR);
357:
358: return (0);
359: }
360:
361: void
362: rtw_cardbus_disable(struct rtw_softc *sc)
363: {
364: struct rtw_cardbus_softc *csc = (void *) sc;
365: cardbus_devfunc_t ct = csc->sc_ct;
366: cardbus_chipset_tag_t cc = ct->ct_cc;
367: cardbus_function_tag_t cf = ct->ct_cf;
368:
369: RTW_WRITE(&sc->sc_regs, RTW_FEMR,
370: RTW_READ(&sc->sc_regs, RTW_FEMR) & ~RTW_FEMR_INTR);
371:
372: rtw_cardbus_funcregen(&sc->sc_regs, 0);
373:
374: /* Unhook the interrupt handler. */
375: cardbus_intr_disestablish(cc, cf, csc->sc_ih);
376: csc->sc_ih = NULL;
377:
378: /* Power down the socket. */
379: Cardbus_function_disable(ct);
380: }
381:
382: void
383: rtw_cardbus_power(struct rtw_softc *sc, int why)
384: {
385: RTW_DPRINTF(RTW_DEBUG_ATTACH,
386: ("%s: rtw_cardbus_power\n", sc->sc_dev.dv_xname));
387:
388: if (why == PWR_RESUME)
389: rtw_enable(sc);
390: }
391:
392: void
393: rtw_cardbus_setup(struct rtw_cardbus_softc *csc)
394: {
395: struct rtw_softc *sc = &csc->sc_rtw;
396: cardbus_devfunc_t ct = csc->sc_ct;
397: cardbus_chipset_tag_t cc = ct->ct_cc;
398: cardbus_function_tag_t cf = ct->ct_cf;
399: pcireg_t reg;
400: int pmreg;
401:
402: if (cardbus_get_capability(cc, cf, csc->sc_tag,
403: PCI_CAP_PWRMGMT, &pmreg, 0)) {
404: reg = cardbus_conf_read(cc, cf, csc->sc_tag, pmreg + 4) & 0x03;
405: #if 1 /* XXX Probably not right for CardBus. */
406: if (reg == 3) {
407: /*
408: * The card has lost all configuration data in
409: * this state, so punt.
410: */
411: printf("%s: unable to wake up from power state D3\n",
412: sc->sc_dev.dv_xname);
413: return;
414: }
415: #endif
416: if (reg != 0) {
417: printf("%s: waking up from power state D%d\n",
418: sc->sc_dev.dv_xname, reg);
419: cardbus_conf_write(cc, cf, csc->sc_tag,
420: pmreg + 4, 0);
421: }
422: }
423:
424: /* Program the BAR. */
425: cardbus_conf_write(cc, cf, csc->sc_tag, csc->sc_bar_reg,
426: csc->sc_bar_val);
427:
428: /* Make sure the right access type is on the CardBus bridge. */
429: (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
430: (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
431:
432: /* Enable the appropriate bits in the PCI CSR. */
433: reg = cardbus_conf_read(cc, cf, csc->sc_tag,
434: CARDBUS_COMMAND_STATUS_REG);
435: reg &= ~(CARDBUS_COMMAND_IO_ENABLE|CARDBUS_COMMAND_MEM_ENABLE);
436: reg |= csc->sc_csr;
437: cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_COMMAND_STATUS_REG,
438: reg);
439:
440: /*
441: * Make sure the latency timer is set to some reasonable
442: * value.
443: */
444: reg = cardbus_conf_read(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG);
445: if (CARDBUS_LATTIMER(reg) < 0x20) {
446: reg &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
447: reg |= (0x20 << CARDBUS_LATTIMER_SHIFT);
448: cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG, reg);
449: }
450: }
CVSweb