1 /* $OpenBSD: if_acx_cardbus.c,v 1.24 2024/05/24 06:26:47 jsg 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/systm.h> 29 #include <sys/timeout.h> 30 #include <sys/device.h> 31 32 #include <machine/bus.h> 33 34 #include <net/if.h> 35 #include <net/if_media.h> 36 37 #include <netinet/in.h> 38 #include <netinet/if_ether.h> 39 40 #include <net80211/ieee80211_var.h> 41 #include <net80211/ieee80211_amrr.h> 42 #include <net80211/ieee80211_radiotap.h> 43 44 #include <dev/ic/acxvar.h> 45 46 #include <dev/pci/pcireg.h> 47 #include <dev/pci/pcivar.h> 48 #include <dev/pci/pcidevs.h> 49 50 #include <dev/cardbus/cardbusvar.h> 51 52 struct acx_cardbus_softc { 53 struct acx_softc sc_acx; 54 55 /* cardbus specific goo */ 56 cardbus_devfunc_t sc_ct; 57 pcitag_t sc_tag; 58 void *sc_ih; 59 bus_size_t sc_mapsize1; 60 bus_size_t sc_mapsize2; 61 pcireg_t sc_iobar_val; /* acx100 only */ 62 pcireg_t sc_bar1_val; 63 pcireg_t sc_bar2_val; 64 int sc_intrline; 65 66 /* hack for ACX100A */ 67 bus_space_tag_t sc_io_bt; 68 bus_space_handle_t sc_io_bh; 69 bus_size_t sc_iomapsize; 70 71 int sc_acx_attached; 72 pci_chipset_tag_t sc_pc; 73 }; 74 75 int acx_cardbus_match(struct device *, void *, void *); 76 void acx_cardbus_attach(struct device *, struct device *, void *); 77 int acx_cardbus_detach(struct device *, int); 78 79 const struct cfattach acx_cardbus_ca = { 80 sizeof (struct acx_cardbus_softc), acx_cardbus_match, 81 acx_cardbus_attach, acx_cardbus_detach 82 }; 83 84 static const struct pci_matchid acx_cardbus_devices[] = { 85 { PCI_VENDOR_TI, PCI_PRODUCT_TI_ACX100A }, 86 { PCI_VENDOR_TI, PCI_PRODUCT_TI_ACX100B }, 87 { PCI_VENDOR_TI, PCI_PRODUCT_TI_ACX111 }, 88 }; 89 90 int acx_cardbus_enable(struct acx_softc *); 91 void acx_cardbus_disable(struct acx_softc *); 92 void acx_cardbus_power(struct acx_softc *, int); 93 void acx_cardbus_setup(struct acx_cardbus_softc *); 94 95 int 96 acx_cardbus_match(struct device *parent, void *match, void *aux) 97 { 98 return (cardbus_matchbyid((struct cardbus_attach_args *)aux, 99 acx_cardbus_devices, 100 sizeof (acx_cardbus_devices) / sizeof (acx_cardbus_devices[0]))); 101 } 102 103 void 104 acx_cardbus_attach(struct device *parent, struct device *self, void *aux) 105 { 106 struct acx_cardbus_softc *csc = (struct acx_cardbus_softc *)self; 107 struct acx_softc *sc = &csc->sc_acx; 108 struct cardbus_attach_args *ca = aux; 109 cardbus_devfunc_t ct = ca->ca_ct; 110 bus_addr_t base; 111 int error, b1 = CARDBUS_BASE0_REG, b2 = CARDBUS_BASE1_REG; 112 113 sc->sc_dmat = ca->ca_dmat; 114 csc->sc_ct = ct; 115 csc->sc_tag = ca->ca_tag; 116 csc->sc_intrline = ca->ca_intrline; 117 csc->sc_pc = ca->ca_pc; 118 119 /* power management hooks */ 120 sc->sc_enable = acx_cardbus_enable; 121 sc->sc_disable = acx_cardbus_disable; 122 sc->sc_power = acx_cardbus_power; 123 124 if (PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_TI_ACX100A) { 125 /* first map I/O space as seen in the dragonfly code */ 126 error = Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG, 127 PCI_MAPREG_TYPE_IO, 0, &csc->sc_io_bt, &csc->sc_io_bh, 128 &base, &csc->sc_iomapsize); 129 if (error != 0) { 130 printf(": can't map i/o space\n"); 131 return; 132 } 133 csc->sc_iobar_val = base | PCI_MAPREG_TYPE_IO; 134 b1 = CARDBUS_BASE1_REG; 135 b2 = CARDBUS_BASE2_REG; 136 } 137 138 /* map control/status registers */ 139 error = Cardbus_mapreg_map(ct, b1, PCI_MAPREG_TYPE_MEM, 0, 140 &sc->sc_mem1_bt, &sc->sc_mem1_bh, &base, &csc->sc_mapsize1); 141 if (error != 0) { 142 printf(": can't map mem1 space\n"); 143 return; 144 } 145 146 csc->sc_bar1_val = base | PCI_MAPREG_TYPE_MEM; 147 148 /* map the other memory region */ 149 error = Cardbus_mapreg_map(ct, b2, PCI_MAPREG_TYPE_MEM, 0, 150 &sc->sc_mem2_bt, &sc->sc_mem2_bh, &base, &csc->sc_mapsize2); 151 if (error != 0) { 152 printf(": can't map mem2 space\n"); 153 return; 154 } 155 156 csc->sc_bar2_val = base | PCI_MAPREG_TYPE_MEM; 157 158 /* set up the PCI configuration registers */ 159 acx_cardbus_setup(csc); 160 161 printf(": irq %d\n", csc->sc_intrline); 162 163 if (PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_TI_ACX111) 164 acx111_set_param(sc); 165 else 166 acx100_set_param(sc); 167 168 error = acx_attach(sc); 169 csc->sc_acx_attached = error == 0; 170 171 Cardbus_function_disable(ct); 172 } 173 174 int 175 acx_cardbus_detach(struct device *self, int flags) 176 { 177 struct acx_cardbus_softc *csc = (struct acx_cardbus_softc *)self; 178 struct acx_softc *sc = &csc->sc_acx; 179 cardbus_devfunc_t ct = csc->sc_ct; 180 cardbus_chipset_tag_t cc = ct->ct_cc; 181 cardbus_function_tag_t cf = ct->ct_cf; 182 int error, b1 = CARDBUS_BASE0_REG, b2 = CARDBUS_BASE1_REG; 183 184 if (csc->sc_acx_attached) { 185 error = acx_detach(sc); 186 if (error != 0) 187 return (error); 188 } 189 190 /* unhook the interrupt handler */ 191 if (csc->sc_ih != NULL) { 192 cardbus_intr_disestablish(cc, cf, csc->sc_ih); 193 csc->sc_ih = NULL; 194 } 195 196 /* release bus space and close window */ 197 if (csc->sc_iomapsize) { 198 b1 = CARDBUS_BASE1_REG; 199 b2 = CARDBUS_BASE2_REG; 200 } 201 Cardbus_mapreg_unmap(ct, b1, sc->sc_mem1_bt, 202 sc->sc_mem1_bh, csc->sc_mapsize1); 203 Cardbus_mapreg_unmap(ct, b2, sc->sc_mem2_bt, 204 sc->sc_mem2_bh, csc->sc_mapsize2); 205 if (csc->sc_iomapsize) 206 Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, csc->sc_io_bt, 207 csc->sc_io_bh, csc->sc_iomapsize); 208 209 return (0); 210 } 211 212 int 213 acx_cardbus_enable(struct acx_softc *sc) 214 { 215 struct acx_cardbus_softc *csc; 216 int error; 217 218 csc = (struct acx_cardbus_softc *)sc; 219 cardbus_devfunc_t ct = csc->sc_ct; 220 cardbus_chipset_tag_t cc = ct->ct_cc; 221 cardbus_function_tag_t cf = ct->ct_cf; 222 223 /* power on the socket */ 224 error = Cardbus_function_enable(ct); 225 if (error) 226 return error; 227 228 /* setup the PCI configuration registers */ 229 acx_cardbus_setup(csc); 230 231 /* map and establish the interrupt handler */ 232 csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET, 233 acx_intr, sc, sc->sc_dev.dv_xname); 234 if (csc->sc_ih == NULL) { 235 printf("%s: could not establish interrupt at %d\n", 236 sc->sc_dev.dv_xname, csc->sc_intrline); 237 Cardbus_function_disable(ct); 238 return (1); 239 } 240 241 return (0); 242 } 243 244 void 245 acx_cardbus_disable(struct acx_softc *sc) 246 { 247 struct acx_cardbus_softc *csc = (struct acx_cardbus_softc *)sc; 248 cardbus_devfunc_t ct = csc->sc_ct; 249 cardbus_chipset_tag_t cc = ct->ct_cc; 250 cardbus_function_tag_t cf = ct->ct_cf; 251 252 /* unhook the interrupt handler */ 253 cardbus_intr_disestablish(cc, cf, csc->sc_ih); 254 csc->sc_ih = NULL; 255 256 /* power down the socket */ 257 Cardbus_function_disable(ct); 258 } 259 260 void 261 acx_cardbus_power(struct acx_softc *sc, int why) 262 { 263 struct acx_cardbus_softc *csc = (struct acx_cardbus_softc *)sc; 264 265 if (why == DVACT_RESUME) { 266 /* kick the PCI configuration registers */ 267 acx_cardbus_setup(csc); 268 } 269 } 270 271 void 272 acx_cardbus_setup(struct acx_cardbus_softc *csc) 273 { 274 cardbus_devfunc_t ct = csc->sc_ct; 275 cardbus_chipset_tag_t cc = ct->ct_cc; 276 pci_chipset_tag_t pc = csc->sc_pc; 277 cardbus_function_tag_t cf = ct->ct_cf; 278 pcireg_t reg; 279 int b1 = CARDBUS_BASE0_REG, b2 = CARDBUS_BASE1_REG; 280 281 if (csc->sc_iobar_val) { 282 pci_conf_write(pc, csc->sc_tag, CARDBUS_BASE0_REG, 283 csc->sc_iobar_val); 284 b1 = CARDBUS_BASE1_REG; 285 b2 = CARDBUS_BASE2_REG; 286 /* (*cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE); */ 287 } 288 289 /* program the BAR */ 290 pci_conf_write(pc, csc->sc_tag, b1, csc->sc_bar1_val); 291 pci_conf_write(pc, csc->sc_tag, b2, csc->sc_bar2_val); 292 293 /* make sure the right access type is on the cardbus bridge */ 294 (*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE); 295 (*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE); 296 297 /* enable the appropriate bits in the PCI CSR */ 298 reg = pci_conf_read(pc, csc->sc_tag, 299 PCI_COMMAND_STATUS_REG); 300 reg |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE; 301 #if 0 302 if (csc->sc_iobar_val) 303 reg |= PCI_COMMAND_IO_ENABLE; 304 #endif 305 pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG, 306 reg); 307 } 308