]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ath/if_ath_ahb.c
[ath] [ath_rate] Fix ANI calibration during non-ACTIVE states; start poking at rate...
[FreeBSD/FreeBSD.git] / sys / dev / ath / if_ath_ahb.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
5  * Copyright (c) 2010-2011 Adrian Chadd, Xenion Pty Ltd
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  *    without modification.
14  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
15  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
16  *    redistribution must be conditioned upon including a substantially
17  *    similar Disclaimer requirement for further binary redistribution.
18  *
19  * NO WARRANTY
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
23  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
24  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
25  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
28  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30  * THE POSSIBILITY OF SUCH DAMAGES.
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 /*
37  * AHB bus front-end for the Atheros Wireless LAN controller driver.
38  */
39
40 #include "opt_ath.h"
41
42 #include <sys/param.h>
43 #include <sys/systm.h> 
44 #include <sys/malloc.h>
45 #include <sys/module.h>
46 #include <sys/kernel.h>
47 #include <sys/lock.h>
48 #include <sys/mutex.h>
49 #include <sys/errno.h>
50
51 #include <machine/bus.h>
52 #include <machine/resource.h>
53 #include <sys/bus.h>
54 #include <sys/rman.h>
55
56 #include <sys/socket.h>
57  
58 #include <net/if.h>
59 #include <net/if_media.h>
60 #include <net/if_arp.h>
61 #include <net/ethernet.h>
62
63 #include <net80211/ieee80211_var.h>
64
65 #include <dev/ath/if_athvar.h>
66
67 #include <mips/atheros/ar71xxreg.h>
68 #include <mips/atheros/ar91xxreg.h>
69 #include <mips/atheros/ar71xx_cpudef.h>
70
71 /* For EEPROM firmware */
72 #ifdef  ATH_EEPROM_FIRMWARE
73 #include <sys/linker.h>
74 #include <sys/firmware.h>
75 #endif  /* ATH_EEPROM_FIRMWARE */
76
77 /*
78  * bus glue.
79  */
80
81 /* number of 16 bit words */
82 #define ATH_EEPROM_DATA_SIZE    2048
83
84 struct ath_ahb_softc {
85         struct ath_softc        sc_sc;
86         struct resource         *sc_sr;         /* memory resource */
87         struct resource         *sc_irq;        /* irq resource */
88         void                    *sc_ih;         /* interrupt handler */
89 };
90
91 #define VENDOR_ATHEROS  0x168c
92 #define AR9130_DEVID    0x000b
93
94 static int
95 ath_ahb_probe(device_t dev)
96 {
97         int vendor_id, device_id;
98         const char* devname;
99
100         /*
101          * Check if a device/vendor ID is provided in hints.
102          */
103         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
104             "vendor_id", &vendor_id) != 0) {
105                 vendor_id = VENDOR_ATHEROS;
106         }
107
108         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
109             "device_id", &device_id) != 0) {
110                 device_id = AR9130_DEVID;
111         }
112
113         device_printf(dev, "Vendor=0x%04x, Device=0x%04x\n",
114             vendor_id & 0xffff,
115             device_id & 0xffff);
116
117         /* Attempt to probe */
118         devname = ath_hal_probe(vendor_id, device_id);
119
120         if (devname != NULL) {
121                 device_set_desc(dev, devname);
122                 return BUS_PROBE_DEFAULT;
123         }
124         return ENXIO;
125 }
126
127 static void
128 ath_ahb_intr(void *arg)
129 {
130         /* XXX TODO: check if its ours! */
131         ar71xx_device_flush_ddr(AR71XX_CPU_DDR_FLUSH_WMAC);
132         ath_intr(arg);
133 }
134
135 static int
136 ath_ahb_attach(device_t dev)
137 {
138         struct ath_ahb_softc *psc = device_get_softc(dev);
139         struct ath_softc *sc = &psc->sc_sc;
140         int error = ENXIO;
141         int rid;
142         int device_id, vendor_id;
143 #ifdef  ATH_EEPROM_FIRMWARE
144         const struct firmware *fw = NULL;
145         const char *buf;
146 #endif
147
148         sc->sc_dev = dev;
149
150         rid = 0;
151         psc->sc_sr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
152         if (psc->sc_sr == NULL) {
153                 device_printf(dev, "cannot map register space\n");
154                 goto bad;
155         }
156
157         sc->sc_st = (HAL_BUS_TAG) rman_get_bustag(psc->sc_sr);
158         sc->sc_sh = (HAL_BUS_HANDLE) rman_get_bushandle(psc->sc_sr);
159         /*
160          * Mark device invalid so any interrupts (shared or otherwise)
161          * that arrive before the HAL is setup are discarded.
162          */
163         sc->sc_invalid = 1;
164
165 #ifdef  ATH_EEPROM_FIRMWARE
166         /*
167          * If there's an EEPROM firmware image, load that in.
168          */
169         if (resource_string_value(device_get_name(dev), device_get_unit(dev),
170             "eeprom_firmware", &buf) == 0) {
171                 device_printf(dev, "%s: looking up firmware @ '%s'\n",
172                     __func__, buf);
173
174                 fw = firmware_get(buf);
175                 if (fw == NULL) {
176                         device_printf(dev, "%s: couldn't find firmware\n",
177                             __func__);
178                         goto bad1;
179                 }
180
181                 device_printf(dev, "%s: EEPROM firmware @ %p\n",
182                     __func__, fw->data);
183                 sc->sc_eepromdata =
184                     malloc(fw->datasize, M_TEMP, M_WAITOK | M_ZERO);
185                 if (! sc->sc_eepromdata) {
186                         device_printf(dev, "%s: can't malloc eepromdata\n",
187                             __func__);
188                         goto bad1;
189                 }
190                 memcpy(sc->sc_eepromdata, fw->data, fw->datasize);
191                 firmware_put(fw, 0);
192         }
193 #endif  /* ATH_EEPROM_FIRMWARE */
194
195         /*
196          * Arrange interrupt line.
197          */
198         rid = 0;
199         psc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE|RF_ACTIVE);
200         if (psc->sc_irq == NULL) {
201                 device_printf(dev, "could not map interrupt\n");
202                 goto bad1;
203         }
204         if (bus_setup_intr(dev, psc->sc_irq,
205                            INTR_TYPE_NET | INTR_MPSAFE,
206                            NULL, ath_ahb_intr, sc, &psc->sc_ih)) {
207                 device_printf(dev, "could not establish interrupt\n");
208                 goto bad2;
209         }
210
211         /*
212          * Setup DMA descriptor area.
213          */
214         if (bus_dma_tag_create(bus_get_dma_tag(dev),    /* parent */
215                                1, 0,                    /* alignment, bounds */
216                                BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
217                                BUS_SPACE_MAXADDR,       /* highaddr */
218                                NULL, NULL,              /* filter, filterarg */
219                                0x3ffff,                 /* maxsize XXX */
220                                ATH_MAX_SCATTER,         /* nsegments */
221                                0x3ffff,                 /* maxsegsize XXX */
222                                BUS_DMA_ALLOCNOW,        /* flags */
223                                NULL,                    /* lockfunc */
224                                NULL,                    /* lockarg */
225                                &sc->sc_dmat)) {
226                 device_printf(dev, "cannot allocate DMA tag\n");
227                 goto bad3;
228         }
229
230         /*
231          * Check if a device/vendor ID is provided in hints.
232          */
233         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
234             "vendor_id", &vendor_id) != 0) {
235                 vendor_id = VENDOR_ATHEROS;
236         }
237
238         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
239             "device_id", &device_id) != 0) {
240                 device_id = AR9130_DEVID;
241         }
242
243         ATH_LOCK_INIT(sc);
244         ATH_PCU_LOCK_INIT(sc);
245         ATH_RX_LOCK_INIT(sc);
246         ATH_TX_LOCK_INIT(sc);
247         ATH_TXSTATUS_LOCK_INIT(sc);
248
249         error = ath_attach(device_id, sc);
250         if (error == 0)                                 /* success */
251                 return 0;
252
253         ATH_TXSTATUS_LOCK_DESTROY(sc);
254         ATH_RX_LOCK_DESTROY(sc);
255         ATH_TX_LOCK_DESTROY(sc);
256         ATH_PCU_LOCK_DESTROY(sc);
257         ATH_LOCK_DESTROY(sc);
258         bus_dma_tag_destroy(sc->sc_dmat);
259 bad3:
260         bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih);
261 bad2:
262         bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq);
263 bad1:
264         bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_sr);
265 bad:
266         /* XXX?! */
267         if (sc->sc_eepromdata)
268                 free(sc->sc_eepromdata, M_TEMP);
269         return (error);
270 }
271
272 static int
273 ath_ahb_detach(device_t dev)
274 {
275         struct ath_ahb_softc *psc = device_get_softc(dev);
276         struct ath_softc *sc = &psc->sc_sc;
277
278         /* check if device was removed */
279         sc->sc_invalid = !bus_child_present(dev);
280
281         ath_detach(sc);
282
283         bus_generic_detach(dev);
284         bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih);
285         bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq);
286
287         bus_dma_tag_destroy(sc->sc_dmat);
288         bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_sr);
289         /* XXX?! */
290         if (sc->sc_eepromdata)
291                 free(sc->sc_eepromdata, M_TEMP);
292
293         ATH_TXSTATUS_LOCK_DESTROY(sc);
294         ATH_RX_LOCK_DESTROY(sc);
295         ATH_TX_LOCK_DESTROY(sc);
296         ATH_PCU_LOCK_DESTROY(sc);
297         ATH_LOCK_DESTROY(sc);
298
299         return (0);
300 }
301
302 static int
303 ath_ahb_shutdown(device_t dev)
304 {
305         struct ath_ahb_softc *psc = device_get_softc(dev);
306
307         ath_shutdown(&psc->sc_sc);
308         return (0);
309 }
310
311 static int
312 ath_ahb_suspend(device_t dev)
313 {
314         struct ath_ahb_softc *psc = device_get_softc(dev);
315
316         ath_suspend(&psc->sc_sc);
317
318         return (0);
319 }
320
321 static int
322 ath_ahb_resume(device_t dev)
323 {
324         struct ath_ahb_softc *psc = device_get_softc(dev);
325
326         ath_resume(&psc->sc_sc);
327
328         return (0);
329 }
330
331 static device_method_t ath_ahb_methods[] = {
332         /* Device interface */
333         DEVMETHOD(device_probe,         ath_ahb_probe),
334         DEVMETHOD(device_attach,        ath_ahb_attach),
335         DEVMETHOD(device_detach,        ath_ahb_detach),
336         DEVMETHOD(device_shutdown,      ath_ahb_shutdown),
337         DEVMETHOD(device_suspend,       ath_ahb_suspend),
338         DEVMETHOD(device_resume,        ath_ahb_resume),
339
340         { 0,0 }
341 };
342 static driver_t ath_ahb_driver = {
343         "ath",
344         ath_ahb_methods,
345         sizeof (struct ath_ahb_softc)
346 };
347 static  devclass_t ath_devclass;
348 DRIVER_MODULE(if_ath_ahb, nexus, ath_ahb_driver, ath_devclass, 0, 0);
349 DRIVER_MODULE(if_ath_ahb, apb, ath_ahb_driver, ath_devclass, 0, 0);
350 MODULE_VERSION(if_ath_ahb, 1);
351 MODULE_DEPEND(if_ath_ahb, wlan, 1, 1, 1);               /* 802.11 media layer */
352 MODULE_DEPEND(if_ath_ahb, ath_main, 1, 1, 1);           /* if_ath driver */
353 MODULE_DEPEND(if_ath_ahb, ath_hal, 1, 1, 1);            /* ath HAL */