1145247Sdamien/*- 2156321Sdamien * Copyright (c) 2005, 2006 3145247Sdamien * Damien Bergamini <damien.bergamini@free.fr> 4145247Sdamien * 5145247Sdamien * Permission to use, copy, modify, and distribute this software for any 6145247Sdamien * purpose with or without fee is hereby granted, provided that the above 7145247Sdamien * copyright notice and this permission notice appear in all copies. 8145247Sdamien * 9145247Sdamien * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10145247Sdamien * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11145247Sdamien * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12145247Sdamien * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13145247Sdamien * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14145247Sdamien * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15145247Sdamien * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16145247Sdamien */ 17145247Sdamien 18145247Sdamien#include <sys/cdefs.h> 19145247Sdamien__FBSDID("$FreeBSD: stable/11/sys/dev/ral/if_ral_pci.c 352563 2019-09-20 19:56:55Z mizhka $"); 20145247Sdamien 21145247Sdamien/* 22156321Sdamien * PCI/Cardbus front-end for the Ralink RT2560/RT2561/RT2561S/RT2661 driver. 23145247Sdamien */ 24145247Sdamien 25145247Sdamien#include <sys/param.h> 26260061Smarius#include <sys/systm.h> 27260061Smarius#include <sys/bus.h> 28145247Sdamien#include <sys/kernel.h> 29260061Smarius#include <sys/lock.h> 30145247Sdamien#include <sys/malloc.h> 31287197Sglebius#include <sys/mbuf.h> 32145247Sdamien#include <sys/module.h> 33260061Smarius#include <sys/mutex.h> 34260061Smarius#include <sys/rman.h> 35260061Smarius#include <sys/socket.h> 36145247Sdamien 37145247Sdamien#include <machine/bus.h> 38145247Sdamien#include <machine/resource.h> 39145247Sdamien 40260061Smarius#include <net/ethernet.h> 41145247Sdamien#include <net/if.h> 42145247Sdamien#include <net/if_media.h> 43260061Smarius#include <net/route.h> 44145247Sdamien 45145247Sdamien#include <net80211/ieee80211_var.h> 46145247Sdamien#include <net80211/ieee80211_radiotap.h> 47145247Sdamien 48145247Sdamien#include <dev/pci/pcireg.h> 49145247Sdamien#include <dev/pci/pcivar.h> 50145247Sdamien 51156327Ssilby#include <dev/ral/rt2560var.h> 52156327Ssilby#include <dev/ral/rt2661var.h> 53235233Sbschmidt#include <dev/ral/rt2860var.h> 54145247Sdamien 55145247SdamienMODULE_DEPEND(ral, pci, 1, 1, 1); 56178354SsamMODULE_DEPEND(ral, firmware, 1, 1, 1); 57145247SdamienMODULE_DEPEND(ral, wlan, 1, 1, 1); 58178354SsamMODULE_DEPEND(ral, wlan_amrr, 1, 1, 1); 59145247Sdamien 60260061Smariusstatic int ral_msi_disable; 61260061SmariusTUNABLE_INT("hw.ral.msi_disable", &ral_msi_disable); 62260061Smarius 63145247Sdamienstruct ral_pci_ident { 64145247Sdamien uint16_t vendor; 65145247Sdamien uint16_t device; 66145247Sdamien const char *name; 67145247Sdamien}; 68145247Sdamien 69145247Sdamienstatic const struct ral_pci_ident ral_pci_ids[] = { 70235233Sbschmidt { 0x1432, 0x7708, "Edimax RT2860" }, 71235233Sbschmidt { 0x1432, 0x7711, "Edimax RT3591" }, 72235233Sbschmidt { 0x1432, 0x7722, "Edimax RT3591" }, 73235233Sbschmidt { 0x1432, 0x7727, "Edimax RT2860" }, 74235233Sbschmidt { 0x1432, 0x7728, "Edimax RT2860" }, 75235233Sbschmidt { 0x1432, 0x7738, "Edimax RT2860" }, 76235233Sbschmidt { 0x1432, 0x7748, "Edimax RT2860" }, 77235233Sbschmidt { 0x1432, 0x7758, "Edimax RT2860" }, 78235233Sbschmidt { 0x1432, 0x7768, "Edimax RT2860" }, 79235233Sbschmidt { 0x1462, 0x891a, "MSI RT3090" }, 80156321Sdamien { 0x1814, 0x0201, "Ralink Technology RT2560" }, 81156321Sdamien { 0x1814, 0x0301, "Ralink Technology RT2561S" }, 82156321Sdamien { 0x1814, 0x0302, "Ralink Technology RT2561" }, 83156321Sdamien { 0x1814, 0x0401, "Ralink Technology RT2661" }, 84235233Sbschmidt { 0x1814, 0x0601, "Ralink Technology RT2860" }, 85235233Sbschmidt { 0x1814, 0x0681, "Ralink Technology RT2890" }, 86235233Sbschmidt { 0x1814, 0x0701, "Ralink Technology RT2760" }, 87235233Sbschmidt { 0x1814, 0x0781, "Ralink Technology RT2790" }, 88235233Sbschmidt { 0x1814, 0x3060, "Ralink Technology RT3060" }, 89235233Sbschmidt { 0x1814, 0x3062, "Ralink Technology RT3062" }, 90235233Sbschmidt { 0x1814, 0x3090, "Ralink Technology RT3090" }, 91235233Sbschmidt { 0x1814, 0x3091, "Ralink Technology RT3091" }, 92235233Sbschmidt { 0x1814, 0x3092, "Ralink Technology RT3092" }, 93235233Sbschmidt { 0x1814, 0x3390, "Ralink Technology RT3390" }, 94235233Sbschmidt { 0x1814, 0x3562, "Ralink Technology RT3562" }, 95235233Sbschmidt { 0x1814, 0x3592, "Ralink Technology RT3592" }, 96235233Sbschmidt { 0x1814, 0x3593, "Ralink Technology RT3593" }, 97278551Skevlo { 0x1814, 0x5360, "Ralink Technology RT5390" }, 98278551Skevlo { 0x1814, 0x5362, "Ralink Technology RT5392" }, 99235233Sbschmidt { 0x1814, 0x5390, "Ralink Technology RT5390" }, 100278551Skevlo { 0x1814, 0x5392, "Ralink Technology RT5392" }, 101235233Sbschmidt { 0x1814, 0x539a, "Ralink Technology RT5390" }, 102352563Smizhka { 0x1814, 0x539b, "Ralink Technology RT5390" }, 103235233Sbschmidt { 0x1814, 0x539f, "Ralink Technology RT5390" }, 104235233Sbschmidt { 0x1a3b, 0x1059, "AWT RT2890" }, 105145247Sdamien { 0, 0, NULL } 106145247Sdamien}; 107145247Sdamien 108260061Smariusstatic const struct ral_opns { 109156321Sdamien int (*attach)(device_t, int); 110156321Sdamien int (*detach)(void *); 111156321Sdamien void (*shutdown)(void *); 112156321Sdamien void (*suspend)(void *); 113156321Sdamien void (*resume)(void *); 114156321Sdamien void (*intr)(void *); 115156321Sdamien 116156321Sdamien} ral_rt2560_opns = { 117156321Sdamien rt2560_attach, 118156321Sdamien rt2560_detach, 119170530Ssam rt2560_stop, 120170530Ssam rt2560_stop, 121156321Sdamien rt2560_resume, 122156321Sdamien rt2560_intr 123156321Sdamien 124156321Sdamien}, ral_rt2661_opns = { 125156321Sdamien rt2661_attach, 126156321Sdamien rt2661_detach, 127156321Sdamien rt2661_shutdown, 128156321Sdamien rt2661_suspend, 129156321Sdamien rt2661_resume, 130156321Sdamien rt2661_intr 131235233Sbschmidt}, ral_rt2860_opns = { 132235233Sbschmidt rt2860_attach, 133235233Sbschmidt rt2860_detach, 134235233Sbschmidt rt2860_shutdown, 135235233Sbschmidt rt2860_suspend, 136235233Sbschmidt rt2860_resume, 137235233Sbschmidt rt2860_intr 138156321Sdamien}; 139156321Sdamien 140156321Sdamienstruct ral_pci_softc { 141156321Sdamien union { 142156321Sdamien struct rt2560_softc sc_rt2560; 143156321Sdamien struct rt2661_softc sc_rt2661; 144235233Sbschmidt struct rt2860_softc sc_rt2860; 145156321Sdamien } u; 146156321Sdamien 147260061Smarius const struct ral_opns *sc_opns; 148156321Sdamien struct resource *irq; 149156321Sdamien struct resource *mem; 150156321Sdamien void *sc_ih; 151156321Sdamien}; 152156321Sdamien 153145247Sdamienstatic int ral_pci_probe(device_t); 154145247Sdamienstatic int ral_pci_attach(device_t); 155156321Sdamienstatic int ral_pci_detach(device_t); 156156321Sdamienstatic int ral_pci_shutdown(device_t); 157145247Sdamienstatic int ral_pci_suspend(device_t); 158145247Sdamienstatic int ral_pci_resume(device_t); 159145247Sdamien 160145247Sdamienstatic device_method_t ral_pci_methods[] = { 161145247Sdamien /* Device interface */ 162145247Sdamien DEVMETHOD(device_probe, ral_pci_probe), 163145247Sdamien DEVMETHOD(device_attach, ral_pci_attach), 164156321Sdamien DEVMETHOD(device_detach, ral_pci_detach), 165156321Sdamien DEVMETHOD(device_shutdown, ral_pci_shutdown), 166145247Sdamien DEVMETHOD(device_suspend, ral_pci_suspend), 167145247Sdamien DEVMETHOD(device_resume, ral_pci_resume), 168145247Sdamien 169260061Smarius DEVMETHOD_END 170145247Sdamien}; 171145247Sdamien 172145247Sdamienstatic driver_t ral_pci_driver = { 173145247Sdamien "ral", 174145247Sdamien ral_pci_methods, 175156321Sdamien sizeof (struct ral_pci_softc) 176145247Sdamien}; 177145247Sdamien 178156321Sdamienstatic devclass_t ral_devclass; 179156321Sdamien 180260061SmariusDRIVER_MODULE(ral, pci, ral_pci_driver, ral_devclass, NULL, NULL); 181145247Sdamien 182145247Sdamienstatic int 183145247Sdamienral_pci_probe(device_t dev) 184145247Sdamien{ 185145247Sdamien const struct ral_pci_ident *ident; 186145247Sdamien 187145247Sdamien for (ident = ral_pci_ids; ident->name != NULL; ident++) { 188145247Sdamien if (pci_get_vendor(dev) == ident->vendor && 189145247Sdamien pci_get_device(dev) == ident->device) { 190145247Sdamien device_set_desc(dev, ident->name); 191260061Smarius return (BUS_PROBE_DEFAULT); 192145247Sdamien } 193145247Sdamien } 194145247Sdamien return ENXIO; 195145247Sdamien} 196145247Sdamien 197145247Sdamienstatic int 198145247Sdamienral_pci_attach(device_t dev) 199145247Sdamien{ 200156321Sdamien struct ral_pci_softc *psc = device_get_softc(dev); 201156321Sdamien struct rt2560_softc *sc = &psc->u.sc_rt2560; 202260061Smarius int count, error, rid; 203145247Sdamien 204145247Sdamien pci_enable_busmaster(dev); 205145247Sdamien 206235233Sbschmidt switch (pci_get_device(dev)) { 207235233Sbschmidt case 0x0201: 208235233Sbschmidt psc->sc_opns = &ral_rt2560_opns; 209235233Sbschmidt break; 210235233Sbschmidt case 0x0301: 211235233Sbschmidt case 0x0302: 212235233Sbschmidt case 0x0401: 213235233Sbschmidt psc->sc_opns = &ral_rt2661_opns; 214235233Sbschmidt break; 215235233Sbschmidt default: 216235233Sbschmidt psc->sc_opns = &ral_rt2860_opns; 217235233Sbschmidt break; 218235233Sbschmidt } 219156321Sdamien 220260061Smarius rid = PCIR_BAR(0); 221260061Smarius psc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 222156321Sdamien RF_ACTIVE); 223156321Sdamien if (psc->mem == NULL) { 224156321Sdamien device_printf(dev, "could not allocate memory resource\n"); 225156321Sdamien return ENXIO; 226156321Sdamien } 227156321Sdamien 228156321Sdamien sc->sc_st = rman_get_bustag(psc->mem); 229156321Sdamien sc->sc_sh = rman_get_bushandle(psc->mem); 230170530Ssam sc->sc_invalid = 1; 231170530Ssam 232260061Smarius rid = 0; 233260061Smarius if (ral_msi_disable == 0) { 234260061Smarius count = 1; 235260061Smarius if (pci_alloc_msi(dev, &count) == 0) 236260061Smarius rid = 1; 237260061Smarius } 238260061Smarius psc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE | 239260061Smarius (rid != 0 ? 0 : RF_SHAREABLE)); 240156321Sdamien if (psc->irq == NULL) { 241156321Sdamien device_printf(dev, "could not allocate interrupt resource\n"); 242260061Smarius pci_release_msi(dev); 243260061Smarius bus_release_resource(dev, SYS_RES_MEMORY, 244260061Smarius rman_get_rid(psc->mem), psc->mem); 245156321Sdamien return ENXIO; 246156321Sdamien } 247156321Sdamien 248156321Sdamien error = (*psc->sc_opns->attach)(dev, pci_get_device(dev)); 249260061Smarius if (error != 0) { 250260061Smarius (void)ral_pci_detach(dev); 251145247Sdamien return error; 252260061Smarius } 253145247Sdamien 254156321Sdamien /* 255156321Sdamien * Hook our interrupt after all initialization is complete. 256156321Sdamien */ 257156321Sdamien error = bus_setup_intr(dev, psc->irq, INTR_TYPE_NET | INTR_MPSAFE, 258166901Spiso NULL, psc->sc_opns->intr, psc, &psc->sc_ih); 259156321Sdamien if (error != 0) { 260156321Sdamien device_printf(dev, "could not set up interrupt\n"); 261260061Smarius (void)ral_pci_detach(dev); 262156321Sdamien return error; 263156321Sdamien } 264170530Ssam sc->sc_invalid = 0; 265170530Ssam 266156321Sdamien return 0; 267145247Sdamien} 268145247Sdamien 269145247Sdamienstatic int 270156321Sdamienral_pci_detach(device_t dev) 271156321Sdamien{ 272156321Sdamien struct ral_pci_softc *psc = device_get_softc(dev); 273170530Ssam struct rt2560_softc *sc = &psc->u.sc_rt2560; 274170530Ssam 275170530Ssam /* check if device was removed */ 276170530Ssam sc->sc_invalid = !bus_child_present(dev); 277260061Smarius 278260061Smarius if (psc->sc_ih != NULL) 279260061Smarius bus_teardown_intr(dev, psc->irq, psc->sc_ih); 280156321Sdamien (*psc->sc_opns->detach)(psc); 281156321Sdamien 282156321Sdamien bus_generic_detach(dev); 283260061Smarius bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(psc->irq), 284260061Smarius psc->irq); 285260061Smarius pci_release_msi(dev); 286156321Sdamien 287260061Smarius bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(psc->mem), 288260061Smarius psc->mem); 289156321Sdamien 290156321Sdamien return 0; 291156321Sdamien} 292156321Sdamien 293156321Sdamienstatic int 294156321Sdamienral_pci_shutdown(device_t dev) 295156321Sdamien{ 296156321Sdamien struct ral_pci_softc *psc = device_get_softc(dev); 297156321Sdamien 298156321Sdamien (*psc->sc_opns->shutdown)(psc); 299156321Sdamien 300156321Sdamien return 0; 301156321Sdamien} 302156321Sdamien 303156321Sdamienstatic int 304145247Sdamienral_pci_suspend(device_t dev) 305145247Sdamien{ 306156321Sdamien struct ral_pci_softc *psc = device_get_softc(dev); 307145247Sdamien 308156321Sdamien (*psc->sc_opns->suspend)(psc); 309145247Sdamien 310145247Sdamien return 0; 311145247Sdamien} 312145247Sdamien 313145247Sdamienstatic int 314145247Sdamienral_pci_resume(device_t dev) 315145247Sdamien{ 316156321Sdamien struct ral_pci_softc *psc = device_get_softc(dev); 317145247Sdamien 318156321Sdamien (*psc->sc_opns->resume)(psc); 319145247Sdamien 320145247Sdamien return 0; 321145247Sdamien} 322