1 /* $FreeBSD$ */ 2 3 /*- 4 * Copyright (c) 2005 5 * Damien Bergamini <damien.bergamini@free.fr> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/cdefs.h> 21 __FBSDID("$FreeBSD$"); 22 23 /* 24 * PCI front-end for the Ralink RT2500 driver. 25 */ 26 27 #include <sys/param.h> 28 #include <sys/sysctl.h> 29 #include <sys/sockio.h> 30 #include <sys/mbuf.h> 31 #include <sys/kernel.h> 32 #include <sys/socket.h> 33 #include <sys/systm.h> 34 #include <sys/malloc.h> 35 #include <sys/module.h> 36 #include <sys/bus.h> 37 #include <sys/endian.h> 38 39 #include <machine/bus.h> 40 #include <machine/resource.h> 41 #include <machine/clock.h> 42 #include <sys/rman.h> 43 44 #include <net/bpf.h> 45 #include <net/if.h> 46 #include <net/if_arp.h> 47 #include <net/ethernet.h> 48 #include <net/if_dl.h> 49 #include <net/if_media.h> 50 #include <net/if_types.h> 51 52 #include <net80211/ieee80211_var.h> 53 #include <net80211/ieee80211_radiotap.h> 54 55 #include <dev/pci/pcireg.h> 56 #include <dev/pci/pcivar.h> 57 58 #include <dev/ral/if_ralrate.h> 59 #include <dev/ral/if_ralreg.h> 60 #include <dev/ral/if_ralvar.h> 61 62 MODULE_DEPEND(ral, pci, 1, 1, 1); 63 MODULE_DEPEND(ral, wlan, 1, 1, 1); 64 65 struct ral_pci_ident { 66 uint16_t vendor; 67 uint16_t device; 68 const char *name; 69 }; 70 71 static const struct ral_pci_ident ral_pci_ids[] = { 72 { 0x1814, 0x0201, "Ralink Technology RT2500" }, 73 74 { 0, 0, NULL } 75 }; 76 77 static int ral_pci_probe(device_t); 78 static int ral_pci_attach(device_t); 79 static int ral_pci_suspend(device_t); 80 static int ral_pci_resume(device_t); 81 82 static device_method_t ral_pci_methods[] = { 83 /* Device interface */ 84 DEVMETHOD(device_probe, ral_pci_probe), 85 DEVMETHOD(device_attach, ral_pci_attach), 86 DEVMETHOD(device_detach, ral_detach), 87 DEVMETHOD(device_suspend, ral_pci_suspend), 88 DEVMETHOD(device_resume, ral_pci_resume), 89 90 { 0, 0 } 91 }; 92 93 static driver_t ral_pci_driver = { 94 "ral", 95 ral_pci_methods, 96 sizeof (struct ral_softc) 97 }; 98 99 DRIVER_MODULE(ral, pci, ral_pci_driver, ral_devclass, 0, 0); 100 DRIVER_MODULE(ral, cardbus, ral_pci_driver, ral_devclass, 0, 0); 101 102 static int 103 ral_pci_probe(device_t dev) 104 { 105 const struct ral_pci_ident *ident; 106 107 for (ident = ral_pci_ids; ident->name != NULL; ident++) { 108 if (pci_get_vendor(dev) == ident->vendor && 109 pci_get_device(dev) == ident->device) { 110 device_set_desc(dev, ident->name); 111 return 0; 112 } 113 } 114 return ENXIO; 115 } 116 117 /* Base Address Register */ 118 #define RAL_PCI_BAR0 0x10 119 120 static int 121 ral_pci_attach(device_t dev) 122 { 123 int error; 124 125 if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { 126 device_printf(dev, "chip is in D%d power mode " 127 "-- setting to D0\n", pci_get_powerstate(dev)); 128 pci_set_powerstate(dev, PCI_POWERSTATE_D0); 129 } 130 131 /* enable bus-mastering */ 132 pci_enable_busmaster(dev); 133 134 error = ral_alloc(dev, RAL_PCI_BAR0); 135 if (error != 0) 136 return error; 137 138 error = ral_attach(dev); 139 if (error != 0) 140 ral_free(dev); 141 142 return error; 143 } 144 145 static int 146 ral_pci_suspend(device_t dev) 147 { 148 struct ral_softc *sc = device_get_softc(dev); 149 150 ral_stop(sc); 151 152 return 0; 153 } 154 155 static int 156 ral_pci_resume(device_t dev) 157 { 158 struct ral_softc *sc = device_get_softc(dev); 159 struct ifnet *ifp = sc->sc_ic.ic_ifp; 160 161 if (ifp->if_flags & IFF_UP) { 162 ifp->if_init(ifp->if_softc); 163 if (ifp->if_drv_flags & IFF_DRV_RUNNING) 164 ifp->if_start(ifp); 165 } 166 167 return 0; 168 } 169