Line data Source code
1 : /* $OpenBSD: if_ath_cardbus.c,v 1.19 2015/11/24 17:11:39 mpi Exp $ */
2 : /* $NetBSD: if_ath_cardbus.c,v 1.4 2004/08/02 19:14:28 mycroft Exp $ */
3 :
4 : /*
5 : * Copyright (c) 2003
6 : * Ichiro FUKUHARA <ichiro@ichiro.org>.
7 : * All rights reserved.
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. All advertising materials mentioning features or use of this software
18 : * must display the following acknowledgement:
19 : * This product includes software developed by Ichiro FUKUHARA.
20 : * 4. The name of the company nor the name of the author may be used to
21 : * endorse or promote products derived from this software without specific
22 : * prior written permission.
23 : *
24 : * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
25 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 : * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
28 : * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 : * SUCH DAMAGE.
35 : */
36 :
37 : /*
38 : * CardBus bus front-end for the AR5001 Wireless LAN 802.11a/b/g CardBus.
39 : */
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/gpio.h>
51 : #include <sys/endian.h>
52 :
53 : #include <net/if.h>
54 : #include <net/if_media.h>
55 :
56 : #include <netinet/in.h>
57 : #include <netinet/if_ether.h>
58 :
59 : #include <net80211/ieee80211_var.h>
60 : #include <net80211/ieee80211_rssadapt.h>
61 :
62 : #include <machine/bus.h>
63 : #include <machine/intr.h>
64 :
65 : #include <dev/gpio/gpiovar.h>
66 :
67 : #include <dev/pci/pcivar.h>
68 : #include <dev/pci/pcireg.h>
69 : #include <dev/pci/pcidevs.h>
70 :
71 : #include <dev/cardbus/cardbusvar.h>
72 :
73 : #include <dev/ic/athvar.h>
74 :
75 : /*
76 : * PCI configuration space registers
77 : */
78 : #define ATH_PCI_MMBA 0x10 /* memory mapped base */
79 :
80 : struct ath_cardbus_softc {
81 : struct ath_softc sc_ath;
82 :
83 : /* CardBus-specific goo. */
84 : void *sc_ih; /* interrupt handle */
85 : cardbus_devfunc_t sc_ct; /* our CardBus devfuncs */
86 : pcitag_t sc_tag; /* our CardBus tag */
87 :
88 : pcireg_t sc_bar_val; /* value of the BAR */
89 :
90 : int sc_intrline; /* interrupt line */
91 : pci_chipset_tag_t sc_pc;
92 : };
93 :
94 : int ath_cardbus_match(struct device *, void *, void *);
95 : void ath_cardbus_attach(struct device *, struct device *, void *);
96 : int ath_cardbus_detach(struct device *, int);
97 :
98 : struct cfattach ath_cardbus_ca = {
99 : sizeof(struct ath_cardbus_softc),
100 : ath_cardbus_match,
101 : ath_cardbus_attach,
102 : ath_cardbus_detach
103 : };
104 :
105 :
106 : void ath_cardbus_setup(struct ath_cardbus_softc *);
107 :
108 : int ath_cardbus_enable(struct ath_softc *);
109 : void ath_cardbus_disable(struct ath_softc *);
110 : void ath_cardbus_power(struct ath_softc *, int);
111 :
112 : int
113 0 : ath_cardbus_match(struct device *parent, void *match, void *aux)
114 : {
115 0 : struct cardbus_attach_args *ca = aux;
116 : const char* devname;
117 :
118 0 : devname = ath_hal_probe(PCI_VENDOR(ca->ca_id),
119 0 : PCI_PRODUCT(ca->ca_id));
120 :
121 0 : if (devname)
122 0 : return (1);
123 :
124 0 : return (0);
125 0 : }
126 :
127 : void
128 0 : ath_cardbus_attach(struct device *parent, struct device *self, void *aux)
129 : {
130 0 : struct ath_cardbus_softc *csc = (void *)self;
131 0 : struct ath_softc *sc = &csc->sc_ath;
132 0 : struct cardbus_attach_args *ca = aux;
133 0 : cardbus_devfunc_t ct = ca->ca_ct;
134 0 : bus_addr_t adr;
135 :
136 0 : sc->sc_dmat = ca->ca_dmat;
137 0 : csc->sc_ct = ct;
138 0 : csc->sc_tag = ca->ca_tag;
139 0 : csc->sc_pc = ca->ca_pc;
140 :
141 : /*
142 : * Power management hooks.
143 : */
144 0 : sc->sc_enable = ath_cardbus_enable;
145 0 : sc->sc_disable = ath_cardbus_disable;
146 0 : sc->sc_power = ath_cardbus_power;
147 :
148 : /*
149 : * Map the device.
150 : */
151 0 : if (Cardbus_mapreg_map(ct, ATH_PCI_MMBA, PCI_MAPREG_TYPE_MEM, 0,
152 0 : &sc->sc_st, &sc->sc_sh, &adr, &sc->sc_ss) == 0) {
153 0 : csc->sc_bar_val = adr | PCI_MAPREG_TYPE_MEM;
154 : }
155 :
156 : else {
157 0 : printf(": unable to map device registers\n");
158 0 : return;
159 : }
160 :
161 : /*
162 : * Set up the PCI configuration registers.
163 : */
164 0 : ath_cardbus_setup(csc);
165 :
166 : /* Remember which interrupt line. */
167 0 : csc->sc_intrline = ca->ca_intrline;
168 :
169 0 : printf(": irq %d\n", csc->sc_intrline);
170 :
171 : /*
172 : * Finish off the attach.
173 : */
174 0 : ath_attach(PCI_PRODUCT(ca->ca_id), sc);
175 :
176 : /*
177 : * Power down the socket.
178 : */
179 0 : Cardbus_function_disable(csc->sc_ct);
180 0 : }
181 :
182 : int
183 0 : ath_cardbus_detach(struct device *self, int flags)
184 : {
185 0 : struct ath_cardbus_softc *csc = (void *)self;
186 0 : struct ath_softc *sc = &csc->sc_ath;
187 0 : struct cardbus_devfunc *ct = csc->sc_ct;
188 : int rv;
189 :
190 : #if defined(DIAGNOSTIC)
191 0 : if (ct == NULL)
192 0 : panic("%s: data structure lacks", sc->sc_dev.dv_xname);
193 : #endif
194 :
195 0 : rv = ath_detach(sc, flags);
196 0 : if (rv)
197 0 : return (rv);
198 :
199 : /*
200 : * Unhook the interrupt handler.
201 : */
202 0 : if (csc->sc_ih != NULL) {
203 0 : cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
204 0 : csc->sc_ih = NULL;
205 0 : }
206 :
207 : /*
208 : * Release bus space and close window.
209 : */
210 0 : Cardbus_mapreg_unmap(ct, ATH_PCI_MMBA,
211 : sc->sc_st, sc->sc_sh, sc->sc_ss);
212 :
213 0 : return (0);
214 0 : }
215 :
216 : int
217 0 : ath_cardbus_enable(struct ath_softc *sc)
218 : {
219 0 : struct ath_cardbus_softc *csc = (void *) sc;
220 0 : cardbus_devfunc_t ct = csc->sc_ct;
221 0 : cardbus_chipset_tag_t cc = ct->ct_cc;
222 0 : cardbus_function_tag_t cf = ct->ct_cf;
223 :
224 : /*
225 : * Power on the socket.
226 : */
227 0 : Cardbus_function_enable(ct);
228 :
229 : /*
230 : * Set up the PCI configuration registers.
231 : */
232 0 : ath_cardbus_setup(csc);
233 :
234 : /*
235 : * Map and establish the interrupt.
236 : */
237 0 : csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
238 0 : ath_intr, sc, sc->sc_dev.dv_xname);
239 0 : if (csc->sc_ih == NULL) {
240 0 : printf(": unable to establish irq %d\n",
241 0 : csc->sc_intrline);
242 0 : Cardbus_function_disable(csc->sc_ct);
243 0 : return (1);
244 : }
245 0 : return (0);
246 0 : }
247 :
248 : void
249 0 : ath_cardbus_disable(struct ath_softc *sc)
250 : {
251 0 : struct ath_cardbus_softc *csc = (void *) sc;
252 0 : cardbus_devfunc_t ct = csc->sc_ct;
253 0 : cardbus_chipset_tag_t cc = ct->ct_cc;
254 0 : cardbus_function_tag_t cf = ct->ct_cf;
255 :
256 : /* Unhook the interrupt handler. */
257 0 : cardbus_intr_disestablish(cc, cf, csc->sc_ih);
258 0 : csc->sc_ih = NULL;
259 :
260 : /* Power down the socket. */
261 0 : Cardbus_function_disable(ct);
262 0 : }
263 :
264 : void
265 0 : ath_cardbus_power(struct ath_softc *sc, int why)
266 : {
267 0 : if (why == DVACT_RESUME)
268 0 : ath_enable(sc);
269 0 : }
270 :
271 : void
272 0 : ath_cardbus_setup(struct ath_cardbus_softc *csc)
273 : {
274 0 : cardbus_devfunc_t ct = csc->sc_ct;
275 0 : cardbus_chipset_tag_t cc = ct->ct_cc;
276 0 : pci_chipset_tag_t pc = csc->sc_pc;
277 : pcireg_t reg;
278 :
279 : #ifdef notyet
280 : (void)cardbus_setpowerstate(sc->sc_dev.dv_xname, ct, csc->sc_tag,
281 : PCI_PWR_D0);
282 : #endif
283 :
284 : /* Program the BAR. */
285 0 : pci_conf_write(pc, csc->sc_tag, ATH_PCI_MMBA,
286 0 : csc->sc_bar_val);
287 :
288 : /* Make sure the right access type is on the CardBus bridge. */
289 0 : (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
290 0 : (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
291 :
292 : /* Enable the appropriate bits in the PCI CSR. */
293 0 : reg = pci_conf_read(pc, csc->sc_tag,
294 : PCI_COMMAND_STATUS_REG);
295 0 : reg |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE;
296 0 : pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG,
297 : reg);
298 :
299 : /*
300 : * Make sure the latency timer is set to some reasonable
301 : * value.
302 : */
303 0 : reg = pci_conf_read(pc, csc->sc_tag, PCI_BHLC_REG);
304 0 : if (PCI_LATTIMER(reg) < 0x20) {
305 0 : reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
306 0 : reg |= (0x20 << PCI_LATTIMER_SHIFT);
307 0 : pci_conf_write(pc, csc->sc_tag, PCI_BHLC_REG, reg);
308 0 : }
309 0 : }
|