1 /*- 2 * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13 * redistribution must be conditioned upon including a substantially 14 * similar Disclaimer requirement for further binary redistribution. 15 * 16 * NO WARRANTY 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 /* 34 * PCI/Cardbus front-end for the Atheros Wireless LAN controller driver. 35 */ 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/module.h> 40 #include <sys/kernel.h> 41 #include <sys/lock.h> 42 #include <sys/mutex.h> 43 #include <sys/errno.h> 44 45 #include <machine/bus.h> 46 #include <machine/resource.h> 47 #include <sys/bus.h> 48 #include <sys/rman.h> 49 50 #include <sys/socket.h> 51 52 #include <net/if.h> 53 #include <net/if_media.h> 54 #include <net/if_arp.h> 55 56 #include <net80211/ieee80211_var.h> 57 58 #include <dev/ath/if_athvar.h> 59 #include <contrib/dev/ath/ah.h> 60 61 #include <dev/pci/pcivar.h> 62 #include <dev/pci/pcireg.h> 63 64 /* 65 * PCI glue. 66 */ 67 68 struct ath_pci_softc { 69 struct ath_softc sc_sc; 70 struct resource *sc_sr; /* memory resource */ 71 struct resource *sc_irq; /* irq resource */ 72 void *sc_ih; /* interrupt handler */ 73 }; 74 75 #define BS_BAR 0x10 76 #define PCIR_RETRY_TIMEOUT 0x41 77 78 static int 79 ath_pci_probe(device_t dev) 80 { 81 const char* devname; 82 83 devname = ath_hal_probe(pci_get_vendor(dev), pci_get_device(dev)); 84 if (devname != NULL) { 85 device_set_desc(dev, devname); 86 return BUS_PROBE_DEFAULT; 87 } 88 return ENXIO; 89 } 90 91 static u_int32_t 92 ath_pci_setup(device_t dev) 93 { 94 u_int32_t cmd; 95 96 /* 97 * Enable memory mapping and bus mastering. 98 */ 99 cmd = pci_read_config(dev, PCIR_COMMAND, 4); 100 cmd |= PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN; 101 pci_write_config(dev, PCIR_COMMAND, cmd, 4); 102 cmd = pci_read_config(dev, PCIR_COMMAND, 4); 103 if ((cmd & PCIM_CMD_MEMEN) == 0) { 104 device_printf(dev, "failed to enable memory mapping\n"); 105 return 0; 106 } 107 if ((cmd & PCIM_CMD_BUSMASTEREN) == 0) { 108 device_printf(dev, "failed to enable bus mastering\n"); 109 return 0; 110 } 111 112 /* 113 * Disable retry timeout to keep PCI Tx retries from 114 * interfering with C3 CPU state. 115 */ 116 pci_write_config(dev, PCIR_RETRY_TIMEOUT, 0, 1); 117 118 return 1; 119 } 120 121 static int 122 ath_pci_attach(device_t dev) 123 { 124 struct ath_pci_softc *psc = device_get_softc(dev); 125 struct ath_softc *sc = &psc->sc_sc; 126 int error = ENXIO; 127 int rid; 128 129 sc->sc_dev = dev; 130 131 if (!ath_pci_setup(dev)) 132 goto bad; 133 134 /* 135 * Setup memory-mapping of PCI registers. 136 */ 137 rid = BS_BAR; 138 psc->sc_sr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 139 RF_ACTIVE); 140 if (psc->sc_sr == NULL) { 141 device_printf(dev, "cannot map register space\n"); 142 goto bad; 143 } 144 /* XXX uintptr_t is a bandaid for ia64; to be fixed */ 145 sc->sc_st = (HAL_BUS_TAG)(uintptr_t) rman_get_bustag(psc->sc_sr); 146 sc->sc_sh = (HAL_BUS_HANDLE) rman_get_bushandle(psc->sc_sr); 147 /* 148 * Mark device invalid so any interrupts (shared or otherwise) 149 * that arrive before the HAL is setup are discarded. 150 */ 151 sc->sc_invalid = 1; 152 153 /* 154 * Arrange interrupt line. 155 */ 156 rid = 0; 157 psc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 158 RF_SHAREABLE|RF_ACTIVE); 159 if (psc->sc_irq == NULL) { 160 device_printf(dev, "could not map interrupt\n"); 161 goto bad1; 162 } 163 if (bus_setup_intr(dev, psc->sc_irq, 164 INTR_TYPE_NET | INTR_MPSAFE, 165 NULL, ath_intr, sc, &psc->sc_ih)) { 166 device_printf(dev, "could not establish interrupt\n"); 167 goto bad2; 168 } 169 170 /* 171 * Setup DMA descriptor area. 172 */ 173 if (bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 174 1, 0, /* alignment, bounds */ 175 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 176 BUS_SPACE_MAXADDR, /* highaddr */ 177 NULL, NULL, /* filter, filterarg */ 178 0x3ffff, /* maxsize XXX */ 179 ATH_MAX_SCATTER, /* nsegments */ 180 0x3ffff, /* maxsegsize XXX */ 181 BUS_DMA_ALLOCNOW, /* flags */ 182 NULL, /* lockfunc */ 183 NULL, /* lockarg */ 184 &sc->sc_dmat)) { 185 device_printf(dev, "cannot allocate DMA tag\n"); 186 goto bad3; 187 } 188 189 ATH_LOCK_INIT(sc); 190 191 error = ath_attach(pci_get_device(dev), sc); 192 if (error == 0) /* success */ 193 return 0; 194 195 ATH_LOCK_DESTROY(sc); 196 bus_dma_tag_destroy(sc->sc_dmat); 197 bad3: 198 bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih); 199 bad2: 200 bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq); 201 bad1: 202 bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, psc->sc_sr); 203 bad: 204 return (error); 205 } 206 207 static int 208 ath_pci_detach(device_t dev) 209 { 210 struct ath_pci_softc *psc = device_get_softc(dev); 211 struct ath_softc *sc = &psc->sc_sc; 212 213 /* check if device was removed */ 214 sc->sc_invalid = !bus_child_present(dev); 215 216 ath_detach(sc); 217 218 bus_generic_detach(dev); 219 bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih); 220 bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq); 221 222 bus_dma_tag_destroy(sc->sc_dmat); 223 bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, psc->sc_sr); 224 225 ATH_LOCK_DESTROY(sc); 226 227 return (0); 228 } 229 230 static int 231 ath_pci_shutdown(device_t dev) 232 { 233 struct ath_pci_softc *psc = device_get_softc(dev); 234 235 ath_shutdown(&psc->sc_sc); 236 return (0); 237 } 238 239 static int 240 ath_pci_suspend(device_t dev) 241 { 242 struct ath_pci_softc *psc = device_get_softc(dev); 243 244 ath_suspend(&psc->sc_sc); 245 246 return (0); 247 } 248 249 static int 250 ath_pci_resume(device_t dev) 251 { 252 struct ath_pci_softc *psc = device_get_softc(dev); 253 254 if (!ath_pci_setup(dev)) 255 return ENXIO; 256 257 ath_resume(&psc->sc_sc); 258 259 return (0); 260 } 261 262 static device_method_t ath_pci_methods[] = { 263 /* Device interface */ 264 DEVMETHOD(device_probe, ath_pci_probe), 265 DEVMETHOD(device_attach, ath_pci_attach), 266 DEVMETHOD(device_detach, ath_pci_detach), 267 DEVMETHOD(device_shutdown, ath_pci_shutdown), 268 DEVMETHOD(device_suspend, ath_pci_suspend), 269 DEVMETHOD(device_resume, ath_pci_resume), 270 271 { 0,0 } 272 }; 273 static driver_t ath_pci_driver = { 274 "ath", 275 ath_pci_methods, 276 sizeof (struct ath_pci_softc) 277 }; 278 static devclass_t ath_devclass; 279 DRIVER_MODULE(if_ath, pci, ath_pci_driver, ath_devclass, 0, 0); 280 DRIVER_MODULE(if_ath, cardbus, ath_pci_driver, ath_devclass, 0, 0); 281 MODULE_VERSION(if_ath, 1); 282 MODULE_DEPEND(if_ath, ath_hal, 1, 1, 1); /* Atheros HAL */ 283 MODULE_DEPEND(if_ath, wlan, 1, 1, 1); /* 802.11 media layer */ 284 MODULE_DEPEND(if_ath, ath_rate, 1, 1, 1); /* rate control algorithm */ 285