1 /* $OpenBSD: if_malo_cardbus.c,v 1.12 2013/12/06 21:03:02 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "bpfilter.h" 20 21 #include <sys/param.h> 22 #include <sys/mbuf.h> 23 #include <sys/socket.h> 24 #include <sys/systm.h> 25 #include <sys/timeout.h> 26 27 #include <net/if.h> 28 #include <net/if_media.h> 29 30 #include <netinet/in.h> 31 #include <netinet/if_ether.h> 32 33 #include <net80211/ieee80211_var.h> 34 #include <net80211/ieee80211_radiotap.h> 35 36 #include <dev/pci/pcireg.h> 37 #include <dev/pci/pcivar.h> 38 #include <dev/pci/pcidevs.h> 39 40 #include <dev/cardbus/cardbusvar.h> 41 42 #include <dev/ic/malo.h> 43 44 struct malo_cardbus_softc { 45 struct malo_softc sc_malo; 46 47 /* cardbus specific goo */ 48 cardbus_devfunc_t sc_ct; 49 pcitag_t sc_tag; 50 void *sc_ih; 51 52 bus_size_t sc_mapsize1; 53 bus_size_t sc_mapsize2; 54 pcireg_t sc_bar1_val; 55 pcireg_t sc_bar2_val; 56 int sc_intrline; 57 pci_chipset_tag_t sc_pc; 58 }; 59 60 int malo_cardbus_match(struct device *parent, void *match, void *aux); 61 void malo_cardbus_attach(struct device *parent, struct device *self, 62 void *aux); 63 int malo_cardbus_detach(struct device *self, int flags); 64 void malo_cardbus_setup(struct malo_cardbus_softc *csc); 65 int malo_cardbus_enable(struct malo_softc *sc); 66 void malo_cardbus_disable(struct malo_softc *sc); 67 68 struct cfattach malo_cardbus_ca = { 69 sizeof (struct malo_cardbus_softc), malo_cardbus_match, 70 malo_cardbus_attach, malo_cardbus_detach 71 }; 72 73 static const struct pci_matchid malo_cardbus_devices[] = { 74 { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_88W8310 }, 75 { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_88W8335_1 }, 76 { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_88W8335_2 } 77 }; 78 79 int 80 malo_cardbus_match(struct device *parent, void *match, void *aux) 81 { 82 return (cardbus_matchbyid(aux, malo_cardbus_devices, 83 sizeof (malo_cardbus_devices) / sizeof (malo_cardbus_devices[0]))); 84 } 85 86 void 87 malo_cardbus_attach(struct device *parent, struct device *self, void *aux) 88 { 89 struct malo_cardbus_softc *csc = (struct malo_cardbus_softc *)self; 90 struct cardbus_attach_args *ca = aux; 91 struct malo_softc *sc = &csc->sc_malo; 92 cardbus_devfunc_t ct = ca->ca_ct; 93 bus_addr_t base; 94 int error; 95 96 sc->sc_dmat = ca->ca_dmat; 97 csc->sc_ct = ct; 98 csc->sc_tag = ca->ca_tag; 99 csc->sc_intrline = ca->ca_intrline; 100 csc->sc_pc = ca->ca_pc; 101 102 /* power management hooks */ 103 sc->sc_enable = malo_cardbus_enable; 104 sc->sc_disable = malo_cardbus_disable; 105 #if 0 106 sc->sc_power = malo_cardbus_power; 107 #endif 108 109 /* map control/status registers */ 110 error = Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG, 111 PCI_MAPREG_TYPE_MEM, 0, &sc->sc_mem1_bt, 112 &sc->sc_mem1_bh, &base, &csc->sc_mapsize1); 113 if (error != 0) { 114 printf(": can't map mem1 space\n"); 115 return; 116 } 117 csc->sc_bar1_val = base | PCI_MAPREG_TYPE_MEM; 118 119 /* map control/status registers */ 120 error = Cardbus_mapreg_map(ct, CARDBUS_BASE1_REG, 121 PCI_MAPREG_TYPE_MEM, 0, &sc->sc_mem2_bt, 122 &sc->sc_mem2_bh, &base, &csc->sc_mapsize2); 123 if (error != 0) { 124 printf(": can't map mem2 space\n"); 125 Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->sc_mem1_bt, 126 sc->sc_mem1_bh, csc->sc_mapsize1); 127 return; 128 } 129 csc->sc_bar2_val = base | PCI_MAPREG_TYPE_MEM; 130 131 /* set up the PCI configuration registers */ 132 malo_cardbus_setup(csc); 133 134 printf(": irq %d", csc->sc_intrline); 135 136 error = malo_attach(sc); 137 if (error != 0) 138 malo_cardbus_detach(&sc->sc_dev, 0); 139 140 Cardbus_function_disable(ct); 141 } 142 143 int 144 malo_cardbus_detach(struct device *self, int flags) 145 { 146 struct malo_cardbus_softc *csc = (struct malo_cardbus_softc *)self; 147 struct malo_softc *sc = &csc->sc_malo; 148 cardbus_devfunc_t ct = csc->sc_ct; 149 cardbus_chipset_tag_t cc = ct->ct_cc; 150 cardbus_function_tag_t cf = ct->ct_cf; 151 int error; 152 153 error = malo_detach(sc); 154 if (error != 0) 155 return (error); 156 157 /* unhook the interrupt handler */ 158 if (csc->sc_ih != NULL) { 159 cardbus_intr_disestablish(cc, cf, csc->sc_ih); 160 csc->sc_ih = NULL; 161 } 162 163 /* release bus space and close window */ 164 Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->sc_mem1_bt, 165 sc->sc_mem1_bh, csc->sc_mapsize1); 166 Cardbus_mapreg_unmap(ct, CARDBUS_BASE1_REG, sc->sc_mem2_bt, 167 sc->sc_mem2_bh, csc->sc_mapsize2); 168 169 return (0); 170 } 171 172 void 173 malo_cardbus_setup(struct malo_cardbus_softc *csc) 174 { 175 cardbus_devfunc_t ct = csc->sc_ct; 176 cardbus_chipset_tag_t cc = ct->ct_cc; 177 pci_chipset_tag_t pc = csc->sc_pc; 178 cardbus_function_tag_t cf = ct->ct_cf; 179 pcireg_t reg; 180 181 /* program the BAR */ 182 pci_conf_write(pc, csc->sc_tag, CARDBUS_BASE0_REG, 183 csc->sc_bar1_val); 184 pci_conf_write(pc, csc->sc_tag, CARDBUS_BASE1_REG, 185 csc->sc_bar2_val); 186 187 /* make sure the right access type is on the cardbus bridge */ 188 (*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE); 189 (*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE); 190 191 /* enable the appropriate bits in the PCI CSR */ 192 reg = pci_conf_read(pc, csc->sc_tag, 193 PCI_COMMAND_STATUS_REG); 194 reg |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE; 195 pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG, 196 reg); 197 } 198 199 int 200 malo_cardbus_enable(struct malo_softc *sc) 201 { 202 struct malo_cardbus_softc *csc = (struct malo_cardbus_softc *)sc; 203 cardbus_devfunc_t ct = csc->sc_ct; 204 cardbus_chipset_tag_t cc = ct->ct_cc; 205 cardbus_function_tag_t cf = ct->ct_cf; 206 207 /* power on the socket */ 208 Cardbus_function_enable(ct); 209 210 /* setup the PCI configuration registers */ 211 malo_cardbus_setup(csc); 212 213 /* map and establish the interrupt handler */ 214 csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET, 215 malo_intr, sc, sc->sc_dev.dv_xname); 216 if (csc->sc_ih == NULL) { 217 printf("%s: could not establish interrupt at %d\n", 218 sc->sc_dev.dv_xname, csc->sc_intrline); 219 Cardbus_function_disable(ct); 220 return (1); 221 } 222 223 return (0); 224 } 225 226 void 227 malo_cardbus_disable(struct malo_softc *sc) 228 { 229 struct malo_cardbus_softc *csc = (struct malo_cardbus_softc *)sc; 230 cardbus_devfunc_t ct = csc->sc_ct; 231 cardbus_chipset_tag_t cc = ct->ct_cc; 232 cardbus_function_tag_t cf = ct->ct_cf; 233 234 /* unhook the interrupt handler */ 235 cardbus_intr_disestablish(cc, cf, csc->sc_ih); 236 csc->sc_ih = NULL; 237 238 /* power down the socket */ 239 Cardbus_function_disable(ct); 240 } 241