1 /* $OpenBSD: if_acx_cardbus.c,v 1.22 2015/11/24 17:11:39 mpi Exp $ */ 2 3 /* 4 * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org> 5 * Copyright (c) 2005, 2006 6 * Damien Bergamini <damien.bergamini@free.fr> 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 /* 22 * CardBus front-end for the Texas Instruments ACX driver 23 */ 24 25 #include "bpfilter.h" 26 27 #include <sys/param.h> 28 #include <sys/sockio.h> 29 #include <sys/mbuf.h> 30 #include <sys/kernel.h> 31 #include <sys/socket.h> 32 #include <sys/systm.h> 33 #include <sys/malloc.h> 34 #include <sys/timeout.h> 35 #include <sys/device.h> 36 37 #include <machine/bus.h> 38 #include <machine/intr.h> 39 40 #include <net/if.h> 41 #include <net/if_media.h> 42 43 #include <netinet/in.h> 44 #include <netinet/if_ether.h> 45 46 #include <net80211/ieee80211_var.h> 47 #include <net80211/ieee80211_amrr.h> 48 #include <net80211/ieee80211_radiotap.h> 49 50 #include <dev/ic/acxvar.h> 51 52 #include <dev/pci/pcireg.h> 53 #include <dev/pci/pcivar.h> 54 #include <dev/pci/pcidevs.h> 55 56 #include <dev/cardbus/cardbusvar.h> 57 58 struct acx_cardbus_softc { 59 struct acx_softc sc_acx; 60 61 /* cardbus specific goo */ 62 cardbus_devfunc_t sc_ct; 63 pcitag_t sc_tag; 64 void *sc_ih; 65 bus_size_t sc_mapsize1; 66 bus_size_t sc_mapsize2; 67 pcireg_t sc_iobar_val; /* acx100 only */ 68 pcireg_t sc_bar1_val; 69 pcireg_t sc_bar2_val; 70 int sc_intrline; 71 72 /* hack for ACX100A */ 73 bus_space_tag_t sc_io_bt; 74 bus_space_handle_t sc_io_bh; 75 bus_size_t sc_iomapsize; 76 77 int sc_acx_attached; 78 pci_chipset_tag_t sc_pc; 79 }; 80 81 int acx_cardbus_match(struct device *, void *, void *); 82 void acx_cardbus_attach(struct device *, struct device *, void *); 83 int acx_cardbus_detach(struct device *, int); 84 85 struct cfattach acx_cardbus_ca = { 86 sizeof (struct acx_cardbus_softc), acx_cardbus_match, 87 acx_cardbus_attach, acx_cardbus_detach 88 }; 89 90 static const struct pci_matchid acx_cardbus_devices[] = { 91 { PCI_VENDOR_TI, PCI_PRODUCT_TI_ACX100A }, 92 { PCI_VENDOR_TI, PCI_PRODUCT_TI_ACX100B }, 93 { PCI_VENDOR_TI, PCI_PRODUCT_TI_ACX111 }, 94 }; 95 96 int acx_cardbus_enable(struct acx_softc *); 97 void acx_cardbus_disable(struct acx_softc *); 98 void acx_cardbus_power(struct acx_softc *, int); 99 void acx_cardbus_setup(struct acx_cardbus_softc *); 100 101 int 102 acx_cardbus_match(struct device *parent, void *match, void *aux) 103 { 104 return (cardbus_matchbyid((struct cardbus_attach_args *)aux, 105 acx_cardbus_devices, 106 sizeof (acx_cardbus_devices) / sizeof (acx_cardbus_devices[0]))); 107 } 108 109 void 110 acx_cardbus_attach(struct device *parent, struct device *self, void *aux) 111 { 112 struct acx_cardbus_softc *csc = (struct acx_cardbus_softc *)self; 113 struct acx_softc *sc = &csc->sc_acx; 114 struct cardbus_attach_args *ca = aux; 115 cardbus_devfunc_t ct = ca->ca_ct; 116 bus_addr_t base; 117 int error, b1 = CARDBUS_BASE0_REG, b2 = CARDBUS_BASE1_REG; 118 119 sc->sc_dmat = ca->ca_dmat; 120 csc->sc_ct = ct; 121 csc->sc_tag = ca->ca_tag; 122 csc->sc_intrline = ca->ca_intrline; 123 csc->sc_pc = ca->ca_pc; 124 125 /* power management hooks */ 126 sc->sc_enable = acx_cardbus_enable; 127 sc->sc_disable = acx_cardbus_disable; 128 sc->sc_power = acx_cardbus_power; 129 130 if (PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_TI_ACX100A) { 131 /* first map I/O space as seen in the dragonfly code */ 132 error = Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG, 133 PCI_MAPREG_TYPE_IO, 0, &csc->sc_io_bt, &csc->sc_io_bh, 134 &base, &csc->sc_iomapsize); 135 if (error != 0) { 136 printf(": can't map i/o space\n"); 137 return; 138 } 139 csc->sc_iobar_val = base | PCI_MAPREG_TYPE_IO; 140 b1 = CARDBUS_BASE1_REG; 141 b2 = CARDBUS_BASE2_REG; 142 } 143 144 /* map control/status registers */ 145 error = Cardbus_mapreg_map(ct, b1, PCI_MAPREG_TYPE_MEM, 0, 146 &sc->sc_mem1_bt, &sc->sc_mem1_bh, &base, &csc->sc_mapsize1); 147 if (error != 0) { 148 printf(": can't map mem1 space\n"); 149 return; 150 } 151 152 csc->sc_bar1_val = base | PCI_MAPREG_TYPE_MEM; 153 154 /* map the other memory region */ 155 error = Cardbus_mapreg_map(ct, b2, PCI_MAPREG_TYPE_MEM, 0, 156 &sc->sc_mem2_bt, &sc->sc_mem2_bh, &base, &csc->sc_mapsize2); 157 if (error != 0) { 158 printf(": can't map mem2 space\n"); 159 return; 160 } 161 162 csc->sc_bar2_val = base | PCI_MAPREG_TYPE_MEM; 163 164 /* set up the PCI configuration registers */ 165 acx_cardbus_setup(csc); 166 167 printf(": irq %d\n", csc->sc_intrline); 168 169 if (PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_TI_ACX111) 170 acx111_set_param(sc); 171 else 172 acx100_set_param(sc); 173 174 error = acx_attach(sc); 175 csc->sc_acx_attached = error == 0; 176 177 Cardbus_function_disable(ct); 178 } 179 180 int 181 acx_cardbus_detach(struct device *self, int flags) 182 { 183 struct acx_cardbus_softc *csc = (struct acx_cardbus_softc *)self; 184 struct acx_softc *sc = &csc->sc_acx; 185 cardbus_devfunc_t ct = csc->sc_ct; 186 cardbus_chipset_tag_t cc = ct->ct_cc; 187 cardbus_function_tag_t cf = ct->ct_cf; 188 int error, b1 = CARDBUS_BASE0_REG, b2 = CARDBUS_BASE1_REG; 189 190 if (csc->sc_acx_attached) { 191 error = acx_detach(sc); 192 if (error != 0) 193 return (error); 194 } 195 196 /* unhook the interrupt handler */ 197 if (csc->sc_ih != NULL) { 198 cardbus_intr_disestablish(cc, cf, csc->sc_ih); 199 csc->sc_ih = NULL; 200 } 201 202 /* release bus space and close window */ 203 if (csc->sc_iomapsize) { 204 b1 = CARDBUS_BASE1_REG; 205 b2 = CARDBUS_BASE2_REG; 206 } 207 Cardbus_mapreg_unmap(ct, b1, sc->sc_mem1_bt, 208 sc->sc_mem1_bh, csc->sc_mapsize1); 209 Cardbus_mapreg_unmap(ct, b2, sc->sc_mem2_bt, 210 sc->sc_mem2_bh, csc->sc_mapsize2); 211 if (csc->sc_iomapsize) 212 Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, csc->sc_io_bt, 213 csc->sc_io_bh, csc->sc_iomapsize); 214 215 return (0); 216 } 217 218 int 219 acx_cardbus_enable(struct acx_softc *sc) 220 { 221 struct acx_cardbus_softc *csc; 222 int error; 223 224 csc = (struct acx_cardbus_softc *)sc; 225 cardbus_devfunc_t ct = csc->sc_ct; 226 cardbus_chipset_tag_t cc = ct->ct_cc; 227 cardbus_function_tag_t cf = ct->ct_cf; 228 229 /* power on the socket */ 230 error = Cardbus_function_enable(ct); 231 if (error) 232 return error; 233 234 /* setup the PCI configuration registers */ 235 acx_cardbus_setup(csc); 236 237 /* map and establish the interrupt handler */ 238 csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET, 239 acx_intr, sc, sc->sc_dev.dv_xname); 240 if (csc->sc_ih == NULL) { 241 printf("%s: could not establish interrupt at %d\n", 242 sc->sc_dev.dv_xname, csc->sc_intrline); 243 Cardbus_function_disable(ct); 244 return (1); 245 } 246 247 return (0); 248 } 249 250 void 251 acx_cardbus_disable(struct acx_softc *sc) 252 { 253 struct acx_cardbus_softc *csc = (struct acx_cardbus_softc *)sc; 254 cardbus_devfunc_t ct = csc->sc_ct; 255 cardbus_chipset_tag_t cc = ct->ct_cc; 256 cardbus_function_tag_t cf = ct->ct_cf; 257 258 /* unhook the interrupt handler */ 259 cardbus_intr_disestablish(cc, cf, csc->sc_ih); 260 csc->sc_ih = NULL; 261 262 /* power down the socket */ 263 Cardbus_function_disable(ct); 264 } 265 266 void 267 acx_cardbus_power(struct acx_softc *sc, int why) 268 { 269 struct acx_cardbus_softc *csc = (struct acx_cardbus_softc *)sc; 270 271 if (why == DVACT_RESUME) { 272 /* kick the PCI configuration registers */ 273 acx_cardbus_setup(csc); 274 } 275 } 276 277 void 278 acx_cardbus_setup(struct acx_cardbus_softc *csc) 279 { 280 cardbus_devfunc_t ct = csc->sc_ct; 281 cardbus_chipset_tag_t cc = ct->ct_cc; 282 pci_chipset_tag_t pc = csc->sc_pc; 283 cardbus_function_tag_t cf = ct->ct_cf; 284 pcireg_t reg; 285 int b1 = CARDBUS_BASE0_REG, b2 = CARDBUS_BASE1_REG; 286 287 if (csc->sc_iobar_val) { 288 pci_conf_write(pc, csc->sc_tag, CARDBUS_BASE0_REG, 289 csc->sc_iobar_val); 290 b1 = CARDBUS_BASE1_REG; 291 b2 = CARDBUS_BASE2_REG; 292 /* (*cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE); */ 293 } 294 295 /* program the BAR */ 296 pci_conf_write(pc, csc->sc_tag, b1, csc->sc_bar1_val); 297 pci_conf_write(pc, csc->sc_tag, b2, csc->sc_bar2_val); 298 299 /* make sure the right access type is on the cardbus bridge */ 300 (*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE); 301 (*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE); 302 303 /* enable the appropriate bits in the PCI CSR */ 304 reg = pci_conf_read(pc, csc->sc_tag, 305 PCI_COMMAND_STATUS_REG); 306 reg |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE; 307 #if 0 308 if (csc->sc_iobar_val) 309 reg |= PCI_COMMAND_IO_ENABLE; 310 #endif 311 pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG, 312 reg); 313 } 314