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