Line data Source code
1 : /* $OpenBSD: if_atw_cardbus.c,v 1.24 2015/11/24 17:11:39 mpi Exp $ */
2 : /* $NetBSD: if_atw_cardbus.c,v 1.9 2004/07/23 07:07:55 dyoung Exp $ */
3 :
4 : /*-
5 : * Copyright (c) 1999, 2000, 2003 The NetBSD Foundation, Inc.
6 : * All rights reserved.
7 : *
8 : * This code is derived from software contributed to The NetBSD Foundation
9 : * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10 : * NASA Ames Research Center. This code was adapted for the ADMtek ADM8211
11 : * by David Young.
12 : *
13 : * Redistribution and use in source and binary forms, with or without
14 : * modification, are permitted provided that the following conditions
15 : * are met:
16 : * 1. Redistributions of source code must retain the above copyright
17 : * notice, this list of conditions and the following disclaimer.
18 : * 2. Redistributions in binary form must reproduce the above copyright
19 : * notice, this list of conditions and the following disclaimer in the
20 : * documentation and/or other materials provided with the distribution.
21 : *
22 : * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23 : * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 : * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26 : * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 : * POSSIBILITY OF SUCH DAMAGE.
33 : */
34 :
35 : /*
36 : * CardBus bus front-end for the ADMtek ADM8211 802.11 MAC/BBP driver.
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/malloc.h>
45 : #include <sys/kernel.h>
46 : #include <sys/socket.h>
47 : #include <sys/ioctl.h>
48 : #include <sys/errno.h>
49 : #include <sys/device.h>
50 : #include <sys/endian.h>
51 :
52 : #include <net/if.h>
53 : #include <net/if_media.h>
54 :
55 : #include <netinet/in.h>
56 : #include <netinet/if_ether.h>
57 :
58 : #include <net80211/ieee80211_radiotap.h>
59 : #include <net80211/ieee80211_var.h>
60 :
61 : #if NBPFILTER > 0
62 : #include <net/bpf.h>
63 : #endif
64 :
65 : #include <machine/bus.h>
66 : #include <machine/intr.h>
67 :
68 : #include <dev/ic/atwreg.h>
69 : #include <dev/ic/si4136reg.h>
70 : #include <dev/ic/atwvar.h>
71 :
72 : #include <dev/pci/pcivar.h>
73 : #include <dev/pci/pcireg.h>
74 : #include <dev/pci/pcidevs.h>
75 :
76 : #include <dev/cardbus/cardbusvar.h>
77 :
78 : /*
79 : * PCI configuration space registers used by the ADM8211.
80 : */
81 : #define ATW_PCI_IOBA 0x10 /* i/o mapped base */
82 : #define ATW_PCI_MMBA 0x14 /* memory mapped base */
83 :
84 : struct atw_cardbus_softc {
85 : struct atw_softc sc_atw; /* real ADM8211 softc */
86 :
87 : /* CardBus-specific goo. */
88 : void *sc_ih; /* interrupt handle */
89 : cardbus_devfunc_t sc_ct; /* our CardBus devfuncs */
90 : pcitag_t sc_tag; /* our CardBus tag */
91 : int sc_csr; /* CSR bits */
92 : bus_size_t sc_mapsize; /* the size of mapped bus space
93 : region */
94 :
95 : int sc_cben; /* CardBus enables */
96 : int sc_bar_reg; /* which BAR to use */
97 : pcireg_t sc_bar_val; /* value of the BAR */
98 :
99 : int sc_intrline; /* interrupt line */
100 : pci_chipset_tag_t sc_pc;
101 : };
102 :
103 : int atw_cardbus_match(struct device *, void *, void *);
104 : void atw_cardbus_attach(struct device *, struct device *, void *);
105 : int atw_cardbus_detach(struct device *, int);
106 :
107 : struct cfattach atw_cardbus_ca = {
108 : sizeof(struct atw_cardbus_softc), atw_cardbus_match, atw_cardbus_attach,
109 : atw_cardbus_detach
110 : };
111 :
112 : void atw_cardbus_setup(struct atw_cardbus_softc *);
113 :
114 : int atw_cardbus_enable(struct atw_softc *);
115 : void atw_cardbus_disable(struct atw_softc *);
116 : void atw_cardbus_power(struct atw_softc *, int);
117 :
118 : const struct pci_matchid atw_cardbus_devices[] = {
119 : { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_ADM8211 },
120 : { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CRSHPW796 },
121 : };
122 :
123 : int
124 0 : atw_cardbus_match(struct device *parent, void *match, void *aux)
125 : {
126 0 : return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
127 : atw_cardbus_devices, nitems(atw_cardbus_devices)));
128 : }
129 :
130 : void
131 0 : atw_cardbus_attach(struct device *parent, struct device *self, void *aux)
132 : {
133 0 : struct atw_cardbus_softc *csc = (void *)self;
134 0 : struct atw_softc *sc = &csc->sc_atw;
135 0 : struct cardbus_attach_args *ca = aux;
136 0 : cardbus_devfunc_t ct = ca->ca_ct;
137 0 : bus_addr_t adr;
138 :
139 0 : sc->sc_dmat = ca->ca_dmat;
140 0 : csc->sc_ct = ct;
141 0 : csc->sc_tag = ca->ca_tag;
142 0 : csc->sc_pc = ca->ca_pc;
143 :
144 : /*
145 : * Power management hooks.
146 : */
147 0 : sc->sc_enable = atw_cardbus_enable;
148 0 : sc->sc_disable = atw_cardbus_disable;
149 0 : sc->sc_power = atw_cardbus_power;
150 :
151 : /* Get revision info. */
152 0 : sc->sc_rev = PCI_REVISION(ca->ca_class);
153 :
154 : #if 0
155 : printf(": signature %08x\n%s",
156 : pci_conf_read(ca->ca_pc, csc->sc_tag, 0x80),
157 : sc->sc_dev.dv_xname);
158 : #endif
159 :
160 : /*
161 : * Map the device.
162 : */
163 0 : csc->sc_csr = PCI_COMMAND_MASTER_ENABLE;
164 0 : if (Cardbus_mapreg_map(ct, ATW_PCI_MMBA,
165 : PCI_MAPREG_TYPE_MEM, 0, &sc->sc_st, &sc->sc_sh, &adr,
166 0 : &csc->sc_mapsize) == 0) {
167 : #if 0
168 : printf(": atw_cardbus_attach mapped %d bytes mem space\n%s",
169 : csc->sc_mapsize, sc->sc_dev.dv_xname);
170 : #endif
171 0 : csc->sc_cben = CARDBUS_MEM_ENABLE;
172 0 : csc->sc_csr |= PCI_COMMAND_MEM_ENABLE;
173 0 : csc->sc_bar_reg = ATW_PCI_MMBA;
174 0 : csc->sc_bar_val = adr | PCI_MAPREG_TYPE_MEM;
175 0 : } else if (Cardbus_mapreg_map(ct, ATW_PCI_IOBA,
176 : PCI_MAPREG_TYPE_IO, 0, &sc->sc_st, &sc->sc_sh, &adr,
177 0 : &csc->sc_mapsize) == 0) {
178 : #if 0
179 : printf(": atw_cardbus_attach mapped %d bytes I/O space\n%s",
180 : csc->sc_mapsize, sc->sc_dev.dv_xname);
181 : #endif
182 0 : csc->sc_cben = CARDBUS_IO_ENABLE;
183 0 : csc->sc_csr |= PCI_COMMAND_IO_ENABLE;
184 0 : csc->sc_bar_reg = ATW_PCI_IOBA;
185 0 : csc->sc_bar_val = adr | PCI_MAPREG_TYPE_IO;
186 : } else {
187 0 : printf(": unable to map device registers\n");
188 0 : return;
189 : }
190 :
191 : /*
192 : * Bring the chip out of powersave mode and initialize the
193 : * configuration registers.
194 : */
195 0 : atw_cardbus_setup(csc);
196 :
197 : /* Remember which interrupt line. */
198 0 : csc->sc_intrline = ca->ca_intrline;
199 :
200 0 : printf(": revision %d.%d: irq %d\n",
201 0 : (sc->sc_rev >> 4) & 0xf, sc->sc_rev & 0xf, csc->sc_intrline);
202 : #if 0
203 : /*
204 : * The CardBus cards will make it to store-and-forward mode as
205 : * soon as you put them under any kind of load, so just start
206 : * out there.
207 : */
208 : sc->sc_txthresh = 3; /* TBD name constant */
209 : #endif
210 :
211 : /*
212 : * Finish off the attach.
213 : */
214 0 : atw_attach(sc);
215 :
216 0 : ATW_WRITE(sc, ATW_FER, ATW_FER_INTR);
217 :
218 : /*
219 : * Power down the socket.
220 : */
221 0 : Cardbus_function_disable(csc->sc_ct);
222 0 : }
223 :
224 : int
225 0 : atw_cardbus_detach(struct device *self, int flags)
226 : {
227 0 : struct atw_cardbus_softc *csc = (void *)self;
228 0 : struct atw_softc *sc = &csc->sc_atw;
229 0 : struct cardbus_devfunc *ct = csc->sc_ct;
230 : int rv;
231 :
232 : #if defined(DIAGNOSTIC)
233 0 : if (ct == NULL)
234 0 : panic("%s: data structure lacks", sc->sc_dev.dv_xname);
235 : #endif
236 :
237 0 : rv = atw_detach(sc);
238 0 : if (rv)
239 0 : return (rv);
240 :
241 : /*
242 : * Unhook the interrupt handler.
243 : */
244 0 : if (csc->sc_ih != NULL)
245 0 : cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
246 :
247 : /*
248 : * Release bus space and close window.
249 : */
250 0 : if (csc->sc_bar_reg != 0)
251 0 : Cardbus_mapreg_unmap(ct, csc->sc_bar_reg,
252 : sc->sc_st, sc->sc_sh, csc->sc_mapsize);
253 :
254 0 : return (0);
255 0 : }
256 :
257 : int
258 0 : atw_cardbus_enable(struct atw_softc *sc)
259 : {
260 0 : struct atw_cardbus_softc *csc = (void *) sc;
261 0 : cardbus_devfunc_t ct = csc->sc_ct;
262 0 : cardbus_chipset_tag_t cc = ct->ct_cc;
263 0 : cardbus_function_tag_t cf = ct->ct_cf;
264 :
265 : /*
266 : * Power on the socket.
267 : */
268 0 : Cardbus_function_enable(ct);
269 :
270 : /*
271 : * Set up the PCI configuration registers.
272 : */
273 0 : atw_cardbus_setup(csc);
274 :
275 : /*
276 : * Map and establish the interrupt.
277 : */
278 0 : csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
279 0 : atw_intr, sc, sc->sc_dev.dv_xname);
280 0 : if (csc->sc_ih == NULL) {
281 0 : printf("%s: unable to establish interrupt at %d\n",
282 0 : sc->sc_dev.dv_xname, csc->sc_intrline);
283 0 : Cardbus_function_disable(csc->sc_ct);
284 0 : return (1);
285 : }
286 :
287 0 : return (0);
288 0 : }
289 :
290 : void
291 0 : atw_cardbus_disable(struct atw_softc *sc)
292 : {
293 0 : struct atw_cardbus_softc *csc = (void *) sc;
294 0 : cardbus_devfunc_t ct = csc->sc_ct;
295 0 : cardbus_chipset_tag_t cc = ct->ct_cc;
296 0 : cardbus_function_tag_t cf = ct->ct_cf;
297 :
298 : /* Unhook the interrupt handler. */
299 0 : cardbus_intr_disestablish(cc, cf, csc->sc_ih);
300 0 : csc->sc_ih = NULL;
301 :
302 : /* Power down the socket. */
303 0 : Cardbus_function_disable(ct);
304 0 : }
305 :
306 : void
307 0 : atw_cardbus_power(struct atw_softc *sc, int why)
308 : {
309 0 : if (why == DVACT_RESUME)
310 0 : atw_enable(sc);
311 0 : }
312 :
313 : void
314 0 : atw_cardbus_setup(struct atw_cardbus_softc *csc)
315 : {
316 : #ifdef notyet
317 : struct atw_softc *sc = &csc->sc_atw;
318 : #endif
319 0 : cardbus_devfunc_t ct = csc->sc_ct;
320 0 : cardbus_chipset_tag_t cc = ct->ct_cc;
321 0 : pci_chipset_tag_t pc = csc->sc_pc;
322 : pcireg_t reg;
323 :
324 : #ifdef notyet
325 : (void)cardbus_setpowerstate(sc->sc_dev.dv_xname, ct, csc->sc_tag,
326 : PCI_PWR_D0);
327 : #endif
328 :
329 : /* Program the BAR. */
330 0 : pci_conf_write(pc, csc->sc_tag, csc->sc_bar_reg,
331 0 : csc->sc_bar_val);
332 :
333 : /* Make sure the right access type is on the CardBus bridge. */
334 0 : (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
335 0 : (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
336 :
337 : /* Enable the appropriate bits in the PCI CSR. */
338 0 : reg = pci_conf_read(pc, csc->sc_tag,
339 : PCI_COMMAND_STATUS_REG);
340 0 : reg &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
341 0 : reg |= csc->sc_csr;
342 0 : pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG,
343 : reg);
344 :
345 : /*
346 : * Make sure the latency timer is set to some reasonable
347 : * value.
348 : */
349 0 : reg = pci_conf_read(pc, csc->sc_tag, PCI_BHLC_REG);
350 0 : if (PCI_LATTIMER(reg) < 0x20) {
351 0 : reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
352 0 : reg |= (0x20 << PCI_LATTIMER_SHIFT);
353 0 : pci_conf_write(pc, csc->sc_tag, PCI_BHLC_REG, reg);
354 0 : }
355 0 : }
|