if_ral_pci.c revision 156321
1145247Sdamien/* $FreeBSD: head/sys/dev/ral/if_ral_pci.c 156321 2006-03-05 20:36:56Z damien $ */ 2145247Sdamien 3145247Sdamien/*- 4156321Sdamien * Copyright (c) 2005, 2006 5145247Sdamien * Damien Bergamini <damien.bergamini@free.fr> 6145247Sdamien * 7145247Sdamien * Permission to use, copy, modify, and distribute this software for any 8145247Sdamien * purpose with or without fee is hereby granted, provided that the above 9145247Sdamien * copyright notice and this permission notice appear in all copies. 10145247Sdamien * 11145247Sdamien * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12145247Sdamien * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13145247Sdamien * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14145247Sdamien * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15145247Sdamien * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16145247Sdamien * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17145247Sdamien * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18145247Sdamien */ 19145247Sdamien 20145247Sdamien#include <sys/cdefs.h> 21145247Sdamien__FBSDID("$FreeBSD: head/sys/dev/ral/if_ral_pci.c 156321 2006-03-05 20:36:56Z damien $"); 22145247Sdamien 23145247Sdamien/* 24156321Sdamien * PCI/Cardbus front-end for the Ralink RT2560/RT2561/RT2561S/RT2661 driver. 25145247Sdamien */ 26145247Sdamien 27145247Sdamien#include <sys/param.h> 28145247Sdamien#include <sys/sysctl.h> 29145247Sdamien#include <sys/sockio.h> 30145247Sdamien#include <sys/mbuf.h> 31145247Sdamien#include <sys/kernel.h> 32145247Sdamien#include <sys/socket.h> 33145247Sdamien#include <sys/systm.h> 34145247Sdamien#include <sys/malloc.h> 35145247Sdamien#include <sys/module.h> 36145247Sdamien#include <sys/bus.h> 37145247Sdamien#include <sys/endian.h> 38145247Sdamien 39145247Sdamien#include <machine/bus.h> 40145247Sdamien#include <machine/resource.h> 41145247Sdamien#include <machine/clock.h> 42145247Sdamien#include <sys/rman.h> 43145247Sdamien 44145247Sdamien#include <net/bpf.h> 45145247Sdamien#include <net/if.h> 46145247Sdamien#include <net/if_arp.h> 47145247Sdamien#include <net/ethernet.h> 48145247Sdamien#include <net/if_dl.h> 49145247Sdamien#include <net/if_media.h> 50145247Sdamien#include <net/if_types.h> 51145247Sdamien 52145247Sdamien#include <net80211/ieee80211_var.h> 53145247Sdamien#include <net80211/ieee80211_radiotap.h> 54145247Sdamien 55145247Sdamien#include <dev/pci/pcireg.h> 56145247Sdamien#include <dev/pci/pcivar.h> 57145247Sdamien 58156321Sdamien#include <dev/rt61/if_ralrate.h> 59156321Sdamien#include <dev/rt61/rt2560var.h> 60156321Sdamien#include <dev/rt61/rt2661var.h> 61145247Sdamien 62145247SdamienMODULE_DEPEND(ral, pci, 1, 1, 1); 63145247SdamienMODULE_DEPEND(ral, wlan, 1, 1, 1); 64145247Sdamien 65145247Sdamienstruct ral_pci_ident { 66145247Sdamien uint16_t vendor; 67145247Sdamien uint16_t device; 68145247Sdamien const char *name; 69145247Sdamien}; 70145247Sdamien 71145247Sdamienstatic const struct ral_pci_ident ral_pci_ids[] = { 72156321Sdamien { 0x1814, 0x0201, "Ralink Technology RT2560" }, 73156321Sdamien { 0x1814, 0x0301, "Ralink Technology RT2561S" }, 74156321Sdamien { 0x1814, 0x0302, "Ralink Technology RT2561" }, 75156321Sdamien { 0x1814, 0x0401, "Ralink Technology RT2661" }, 76145247Sdamien 77145247Sdamien { 0, 0, NULL } 78145247Sdamien}; 79145247Sdamien 80156321Sdamienstatic struct ral_opns { 81156321Sdamien int (*attach)(device_t, int); 82156321Sdamien int (*detach)(void *); 83156321Sdamien void (*shutdown)(void *); 84156321Sdamien void (*suspend)(void *); 85156321Sdamien void (*resume)(void *); 86156321Sdamien void (*intr)(void *); 87156321Sdamien 88156321Sdamien} ral_rt2560_opns = { 89156321Sdamien rt2560_attach, 90156321Sdamien rt2560_detach, 91156321Sdamien rt2560_shutdown, 92156321Sdamien rt2560_suspend, 93156321Sdamien rt2560_resume, 94156321Sdamien rt2560_intr 95156321Sdamien 96156321Sdamien}, ral_rt2661_opns = { 97156321Sdamien rt2661_attach, 98156321Sdamien rt2661_detach, 99156321Sdamien rt2661_shutdown, 100156321Sdamien rt2661_suspend, 101156321Sdamien rt2661_resume, 102156321Sdamien rt2661_intr 103156321Sdamien}; 104156321Sdamien 105156321Sdamienstruct ral_pci_softc { 106156321Sdamien union { 107156321Sdamien struct rt2560_softc sc_rt2560; 108156321Sdamien struct rt2661_softc sc_rt2661; 109156321Sdamien } u; 110156321Sdamien 111156321Sdamien struct ral_opns *sc_opns; 112156321Sdamien int irq_rid; 113156321Sdamien int mem_rid; 114156321Sdamien struct resource *irq; 115156321Sdamien struct resource *mem; 116156321Sdamien void *sc_ih; 117156321Sdamien}; 118156321Sdamien 119145247Sdamienstatic int ral_pci_probe(device_t); 120145247Sdamienstatic int ral_pci_attach(device_t); 121156321Sdamienstatic int ral_pci_detach(device_t); 122156321Sdamienstatic int ral_pci_shutdown(device_t); 123145247Sdamienstatic int ral_pci_suspend(device_t); 124145247Sdamienstatic int ral_pci_resume(device_t); 125145247Sdamien 126145247Sdamienstatic device_method_t ral_pci_methods[] = { 127145247Sdamien /* Device interface */ 128145247Sdamien DEVMETHOD(device_probe, ral_pci_probe), 129145247Sdamien DEVMETHOD(device_attach, ral_pci_attach), 130156321Sdamien DEVMETHOD(device_detach, ral_pci_detach), 131156321Sdamien DEVMETHOD(device_shutdown, ral_pci_shutdown), 132145247Sdamien DEVMETHOD(device_suspend, ral_pci_suspend), 133145247Sdamien DEVMETHOD(device_resume, ral_pci_resume), 134145247Sdamien 135145247Sdamien { 0, 0 } 136145247Sdamien}; 137145247Sdamien 138145247Sdamienstatic driver_t ral_pci_driver = { 139145247Sdamien "ral", 140145247Sdamien ral_pci_methods, 141156321Sdamien sizeof (struct ral_pci_softc) 142145247Sdamien}; 143145247Sdamien 144156321Sdamienstatic devclass_t ral_devclass; 145156321Sdamien 146145247SdamienDRIVER_MODULE(ral, pci, ral_pci_driver, ral_devclass, 0, 0); 147145247SdamienDRIVER_MODULE(ral, cardbus, ral_pci_driver, ral_devclass, 0, 0); 148145247Sdamien 149145247Sdamienstatic int 150145247Sdamienral_pci_probe(device_t dev) 151145247Sdamien{ 152145247Sdamien const struct ral_pci_ident *ident; 153145247Sdamien 154145247Sdamien for (ident = ral_pci_ids; ident->name != NULL; ident++) { 155145247Sdamien if (pci_get_vendor(dev) == ident->vendor && 156145247Sdamien pci_get_device(dev) == ident->device) { 157145247Sdamien device_set_desc(dev, ident->name); 158145247Sdamien return 0; 159145247Sdamien } 160145247Sdamien } 161145247Sdamien return ENXIO; 162145247Sdamien} 163145247Sdamien 164145247Sdamien/* Base Address Register */ 165145247Sdamien#define RAL_PCI_BAR0 0x10 166145247Sdamien 167145247Sdamienstatic int 168145247Sdamienral_pci_attach(device_t dev) 169145247Sdamien{ 170156321Sdamien struct ral_pci_softc *psc = device_get_softc(dev); 171156321Sdamien struct rt2560_softc *sc = &psc->u.sc_rt2560; 172145247Sdamien int error; 173145247Sdamien 174145247Sdamien if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { 175145247Sdamien device_printf(dev, "chip is in D%d power mode " 176145247Sdamien "-- setting to D0\n", pci_get_powerstate(dev)); 177145247Sdamien pci_set_powerstate(dev, PCI_POWERSTATE_D0); 178145247Sdamien } 179145247Sdamien 180145247Sdamien /* enable bus-mastering */ 181145247Sdamien pci_enable_busmaster(dev); 182145247Sdamien 183156321Sdamien psc->sc_opns = (pci_get_device(dev) == 0x0201) ? &ral_rt2560_opns : 184156321Sdamien &ral_rt2661_opns; 185156321Sdamien 186156321Sdamien psc->mem_rid = RAL_PCI_BAR0; 187156321Sdamien psc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &psc->mem_rid, 188156321Sdamien RF_ACTIVE); 189156321Sdamien if (psc->mem == NULL) { 190156321Sdamien device_printf(dev, "could not allocate memory resource\n"); 191156321Sdamien return ENXIO; 192156321Sdamien } 193156321Sdamien 194156321Sdamien sc->sc_st = rman_get_bustag(psc->mem); 195156321Sdamien sc->sc_sh = rman_get_bushandle(psc->mem); 196156321Sdamien 197156321Sdamien psc->irq_rid = 0; 198156321Sdamien psc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &psc->irq_rid, 199156321Sdamien RF_ACTIVE | RF_SHAREABLE); 200156321Sdamien if (psc->irq == NULL) { 201156321Sdamien device_printf(dev, "could not allocate interrupt resource\n"); 202156321Sdamien return ENXIO; 203156321Sdamien } 204156321Sdamien 205156321Sdamien error = (*psc->sc_opns->attach)(dev, pci_get_device(dev)); 206145247Sdamien if (error != 0) 207145247Sdamien return error; 208145247Sdamien 209156321Sdamien /* 210156321Sdamien * Hook our interrupt after all initialization is complete. 211156321Sdamien */ 212156321Sdamien error = bus_setup_intr(dev, psc->irq, INTR_TYPE_NET | INTR_MPSAFE, 213156321Sdamien psc->sc_opns->intr, psc, &psc->sc_ih); 214156321Sdamien if (error != 0) { 215156321Sdamien device_printf(dev, "could not set up interrupt\n"); 216156321Sdamien return error; 217156321Sdamien } 218145247Sdamien 219156321Sdamien return 0; 220145247Sdamien} 221145247Sdamien 222145247Sdamienstatic int 223156321Sdamienral_pci_detach(device_t dev) 224156321Sdamien{ 225156321Sdamien struct ral_pci_softc *psc = device_get_softc(dev); 226156321Sdamien 227156321Sdamien (*psc->sc_opns->detach)(psc); 228156321Sdamien 229156321Sdamien bus_generic_detach(dev); 230156321Sdamien bus_teardown_intr(dev, psc->irq, psc->sc_ih); 231156321Sdamien bus_release_resource(dev, SYS_RES_IRQ, psc->irq_rid, psc->irq); 232156321Sdamien 233156321Sdamien bus_release_resource(dev, SYS_RES_MEMORY, psc->mem_rid, psc->mem); 234156321Sdamien 235156321Sdamien return 0; 236156321Sdamien} 237156321Sdamien 238156321Sdamienstatic int 239156321Sdamienral_pci_shutdown(device_t dev) 240156321Sdamien{ 241156321Sdamien struct ral_pci_softc *psc = device_get_softc(dev); 242156321Sdamien 243156321Sdamien (*psc->sc_opns->shutdown)(psc); 244156321Sdamien 245156321Sdamien return 0; 246156321Sdamien} 247156321Sdamien 248156321Sdamienstatic int 249145247Sdamienral_pci_suspend(device_t dev) 250145247Sdamien{ 251156321Sdamien struct ral_pci_softc *psc = device_get_softc(dev); 252145247Sdamien 253156321Sdamien (*psc->sc_opns->suspend)(psc); 254145247Sdamien 255145247Sdamien return 0; 256145247Sdamien} 257145247Sdamien 258145247Sdamienstatic int 259145247Sdamienral_pci_resume(device_t dev) 260145247Sdamien{ 261156321Sdamien struct ral_pci_softc *psc = device_get_softc(dev); 262145247Sdamien 263156321Sdamien (*psc->sc_opns->resume)(psc); 264145247Sdamien 265145247Sdamien return 0; 266145247Sdamien} 267