1 1.93 msaitoh /* $NetBSD: if_wi_pcmcia.c,v 1.93 2019/01/08 08:47:21 msaitoh Exp $ */ 2 1.1 ichiro 3 1.1 ichiro /*- 4 1.53 mycroft * Copyright (c) 2001, 2004 The NetBSD Foundation, Inc. 5 1.1 ichiro * All rights reserved. 6 1.1 ichiro * 7 1.1 ichiro * This code is derived from software contributed to The NetBSD Foundation 8 1.53 mycroft * by Ichiro FUKUHARA (ichiro (at) ichiro.org), and by Charles M. Hannum. 9 1.1 ichiro * 10 1.1 ichiro * Redistribution and use in source and binary forms, with or without 11 1.1 ichiro * modification, are permitted provided that the following conditions 12 1.1 ichiro * are met: 13 1.1 ichiro * 1. Redistributions of source code must retain the above copyright 14 1.1 ichiro * notice, this list of conditions and the following disclaimer. 15 1.1 ichiro * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 ichiro * notice, this list of conditions and the following disclaimer in the 17 1.1 ichiro * documentation and/or other materials provided with the distribution. 18 1.1 ichiro * 19 1.1 ichiro * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 ichiro * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 ichiro * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 ichiro * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 ichiro * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 ichiro * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 ichiro * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 ichiro * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 ichiro * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 ichiro * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 ichiro * POSSIBILITY OF SUCH DAMAGE. 30 1.1 ichiro */ 31 1.1 ichiro 32 1.1 ichiro /* 33 1.1 ichiro * PCMCIA attachment for Lucent & Intersil WaveLAN PCMCIA card 34 1.1 ichiro */ 35 1.12 lukem 36 1.12 lukem #include <sys/cdefs.h> 37 1.93 msaitoh __KERNEL_RCSID(0, "$NetBSD: if_wi_pcmcia.c,v 1.93 2019/01/08 08:47:21 msaitoh Exp $"); 38 1.1 ichiro 39 1.1 ichiro #include <sys/param.h> 40 1.1 ichiro #include <sys/systm.h> 41 1.1 ichiro #include <sys/callout.h> 42 1.1 ichiro #include <sys/device.h> 43 1.17 onoe #include <sys/proc.h> 44 1.1 ichiro #include <sys/socket.h> 45 1.1 ichiro 46 1.1 ichiro #include <net/if.h> 47 1.1 ichiro #include <net/if_ether.h> 48 1.1 ichiro #include <net/if_media.h> 49 1.35 dyoung 50 1.66 dyoung #include <net80211/ieee80211_netbsd.h> 51 1.35 dyoung #include <net80211/ieee80211_var.h> 52 1.37 dyoung #include <net80211/ieee80211_radiotap.h> 53 1.38 dyoung #include <net80211/ieee80211_rssadapt.h> 54 1.1 ichiro 55 1.76 ad #include <sys/cpu.h> 56 1.76 ad #include <sys/bus.h> 57 1.76 ad #include <sys/intr.h> 58 1.1 ichiro 59 1.1 ichiro #include <dev/ic/wi_ieee.h> 60 1.1 ichiro #include <dev/ic/wireg.h> 61 1.1 ichiro #include <dev/ic/wivar.h> 62 1.1 ichiro 63 1.1 ichiro #include <dev/pcmcia/pcmciareg.h> 64 1.1 ichiro #include <dev/pcmcia/pcmciavar.h> 65 1.1 ichiro #include <dev/pcmcia/pcmciadevs.h> 66 1.1 ichiro 67 1.80 ad #ifdef _MODULE 68 1.74 dsl #define WI_PCMCIA_SPECTRUM24T_FW 1 69 1.74 dsl #else 70 1.73 dsl #include <opt_if_wi_pcmcia.h> 71 1.74 dsl #endif 72 1.73 dsl 73 1.73 dsl #if WI_PCMCIA_SPECTRUM24T_FW 74 1.17 onoe #include <dev/microcode/wi/spectrum24t_cf.h> 75 1.73 dsl #endif 76 1.17 onoe 77 1.84 cegger static int wi_pcmcia_match(device_t, cfdata_t, void *); 78 1.60 perry static int wi_pcmcia_validate_config(struct pcmcia_config_entry *); 79 1.84 cegger static void wi_pcmcia_attach(device_t, device_t, void *); 80 1.84 cegger static int wi_pcmcia_detach(device_t, int); 81 1.86 christos static int wi_pcmcia_enable(device_t, int); 82 1.1 ichiro 83 1.73 dsl #if WI_PCMCIA_SPECTRUM24T_FW 84 1.17 onoe /* support to download firmware for symbol CF card */ 85 1.92 msaitoh static int wi_pcmcia_load_firm(struct wi_softc *, const void *, int, 86 1.92 msaitoh const void *, int); 87 1.92 msaitoh static int wi_pcmcia_write_firm(struct wi_softc *, const void *, int, 88 1.92 msaitoh const void *, int); 89 1.60 perry static int wi_pcmcia_set_hcr(struct wi_softc *, int); 90 1.73 dsl #endif 91 1.17 onoe 92 1.1 ichiro struct wi_pcmcia_softc { 93 1.1 ichiro struct wi_softc sc_wi; 94 1.1 ichiro 95 1.17 onoe int sc_symbol_cf; /* Spectrum24t CF card */ 96 1.52 mycroft 97 1.52 mycroft struct pcmcia_function *sc_pf; /* PCMCIA function */ 98 1.52 mycroft int sc_state; 99 1.52 mycroft #define WI_PCMCIA_ATTACHED 3 100 1.1 ichiro }; 101 1.1 ichiro 102 1.86 christos CFATTACH_DECL_NEW(wi_pcmcia, sizeof(struct wi_pcmcia_softc), 103 1.29 thorpej wi_pcmcia_match, wi_pcmcia_attach, wi_pcmcia_detach, wi_activate); 104 1.1 ichiro 105 1.56 mycroft static const struct pcmcia_product wi_pcmcia_products[] = { 106 1.47 mycroft { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 107 1.42 mycroft PCMCIA_CIS_SMC_2632W }, 108 1.42 mycroft 109 1.47 mycroft { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 110 1.42 mycroft PCMCIA_CIS_NANOSPEED_PRISM2 }, 111 1.42 mycroft 112 1.47 mycroft { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 113 1.42 mycroft PCMCIA_CIS_NEC_CMZ_RT_WP }, 114 1.42 mycroft 115 1.47 mycroft { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 116 1.42 mycroft PCMCIA_CIS_NTT_ME_WLAN }, 117 1.42 mycroft 118 1.47 mycroft { PCMCIA_VENDOR_LUCENT, PCMCIA_PRODUCT_LUCENT_HERMES, 119 1.47 mycroft PCMCIA_CIS_INVALID }, 120 1.47 mycroft 121 1.47 mycroft { PCMCIA_VENDOR_LUCENT, PCMCIA_PRODUCT_LUCENT_HERMES2, 122 1.47 mycroft PCMCIA_CIS_INVALID }, 123 1.42 mycroft 124 1.42 mycroft { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CRWE737A, 125 1.42 mycroft PCMCIA_CIS_3COM_3CRWE737A }, 126 1.42 mycroft 127 1.91 pgoyette { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CRWE777A, 128 1.91 pgoyette PCMCIA_CIS_3COM_3CRWE777A }, 129 1.91 pgoyette 130 1.67 dyoung { PCMCIA_VENDOR_ALVARION, 131 1.67 dyoung PCMCIA_PRODUCT_ALVARION_BREEZENET, 132 1.67 dyoung PCMCIA_CIS_ALVARION_BREEZENET }, 133 1.67 dyoung 134 1.42 mycroft { PCMCIA_VENDOR_COREGA, PCMCIA_PRODUCT_COREGA_WIRELESS_LAN_PCC_11, 135 1.42 mycroft PCMCIA_CIS_COREGA_WIRELESS_LAN_PCC_11 }, 136 1.42 mycroft 137 1.42 mycroft { PCMCIA_VENDOR_COREGA, PCMCIA_PRODUCT_COREGA_WIRELESS_LAN_PCCA_11, 138 1.42 mycroft PCMCIA_CIS_COREGA_WIRELESS_LAN_PCCA_11 }, 139 1.42 mycroft 140 1.42 mycroft { PCMCIA_VENDOR_COREGA, PCMCIA_PRODUCT_COREGA_WIRELESS_LAN_PCCB_11, 141 1.42 mycroft PCMCIA_CIS_COREGA_WIRELESS_LAN_PCCB_11 }, 142 1.42 mycroft 143 1.42 mycroft { PCMCIA_VENDOR_COREGA, PCMCIA_PRODUCT_COREGA_WIRELESS_LAN_PCCL_11, 144 1.42 mycroft PCMCIA_CIS_COREGA_WIRELESS_LAN_PCCL_11 }, 145 1.42 mycroft 146 1.42 mycroft { PCMCIA_VENDOR_COREGA, PCMCIA_PRODUCT_COREGA_WIRELESS_LAN_WLCFL_11, 147 1.42 mycroft PCMCIA_CIS_COREGA_WIRELESS_LAN_WLCFL_11 }, 148 1.42 mycroft 149 1.42 mycroft { PCMCIA_VENDOR_INTEL, PCMCIA_PRODUCT_INTEL_PRO_WLAN_2011, 150 1.42 mycroft PCMCIA_CIS_INTEL_PRO_WLAN_2011 }, 151 1.42 mycroft 152 1.59 imp { PCMCIA_VENDOR_INTERSIL2, PCMCIA_PRODUCT_INTERSIL2_PRISM2, 153 1.59 imp PCMCIA_CIS_INTERSIL2_PRISM2 }, 154 1.42 mycroft 155 1.59 imp { PCMCIA_VENDOR_INTERSIL2, PCMCIA_PRODUCT_GEMTEK_WLAN, 156 1.42 mycroft PCMCIA_CIS_GEMTEK_WLAN }, 157 1.42 mycroft 158 1.42 mycroft { PCMCIA_VENDOR_SAMSUNG, PCMCIA_PRODUCT_SAMSUNG_SWL_2000N, 159 1.42 mycroft PCMCIA_CIS_SAMSUNG_SWL_2000N }, 160 1.42 mycroft 161 1.42 mycroft { PCMCIA_VENDOR_ELSA, PCMCIA_PRODUCT_ELSA_XI300_IEEE, 162 1.42 mycroft PCMCIA_CIS_ELSA_XI300_IEEE }, 163 1.42 mycroft 164 1.42 mycroft { PCMCIA_VENDOR_ELSA, PCMCIA_PRODUCT_ELSA_XI325_IEEE, 165 1.42 mycroft PCMCIA_CIS_ELSA_XI325_IEEE }, 166 1.42 mycroft 167 1.42 mycroft { PCMCIA_VENDOR_ELSA, PCMCIA_PRODUCT_ELSA_XI800_IEEE, 168 1.42 mycroft PCMCIA_CIS_ELSA_XI800_IEEE }, 169 1.42 mycroft 170 1.64 martin { PCMCIA_VENDOR_ELSA, PCMCIA_PRODUCT_ELSA_SMC2531WB, 171 1.64 martin PCMCIA_CIS_ELSA_SMC2531WB }, 172 1.64 martin 173 1.42 mycroft { PCMCIA_VENDOR_COMPAQ, PCMCIA_PRODUCT_COMPAQ_NC5004, 174 1.42 mycroft PCMCIA_CIS_COMPAQ_NC5004 }, 175 1.42 mycroft 176 1.42 mycroft { PCMCIA_VENDOR_CONTEC, PCMCIA_PRODUCT_CONTEC_FX_DS110_PCC, 177 1.42 mycroft PCMCIA_CIS_CONTEC_FX_DS110_PCC }, 178 1.42 mycroft 179 1.42 mycroft { PCMCIA_VENDOR_TDK, PCMCIA_PRODUCT_TDK_LAK_CD011WL, 180 1.42 mycroft PCMCIA_CIS_TDK_LAK_CD011WL }, 181 1.42 mycroft 182 1.42 mycroft { PCMCIA_VENDOR_IODATA2, PCMCIA_PRODUCT_IODATA2_WNB11PCM, 183 1.42 mycroft PCMCIA_CIS_IODATA2_WNB11PCM }, 184 1.42 mycroft 185 1.42 mycroft { PCMCIA_VENDOR_IODATA2, PCMCIA_PRODUCT_IODATA2_WCF12, 186 1.42 mycroft PCMCIA_CIS_IODATA2_WCF12 }, 187 1.42 mycroft 188 1.42 mycroft { PCMCIA_VENDOR_BUFFALO, PCMCIA_PRODUCT_BUFFALO_WLI_PCM_S11, 189 1.42 mycroft PCMCIA_CIS_BUFFALO_WLI_PCM_S11 }, 190 1.42 mycroft 191 1.42 mycroft { PCMCIA_VENDOR_BUFFALO, PCMCIA_PRODUCT_BUFFALO_WLI_CF_S11G, 192 1.42 mycroft PCMCIA_CIS_BUFFALO_WLI_CF_S11G }, 193 1.42 mycroft 194 1.42 mycroft { PCMCIA_VENDOR_EMTAC, PCMCIA_PRODUCT_EMTAC_WLAN, 195 1.42 mycroft PCMCIA_CIS_EMTAC_WLAN }, 196 1.42 mycroft 197 1.59 imp { PCMCIA_VENDOR_INTERSIL, PCMCIA_PRODUCT_INTERSIL_ISL37100P, 198 1.59 imp PCMCIA_CIS_INTERSIL_ISL37100P }, 199 1.59 imp 200 1.59 imp { PCMCIA_VENDOR_INTERSIL, PCMCIA_PRODUCT_INTERSIL_ISL37110P, 201 1.59 imp PCMCIA_CIS_INTERSIL_ISL37110P }, 202 1.59 imp 203 1.59 imp { PCMCIA_VENDOR_INTERSIL, PCMCIA_PRODUCT_INTERSIL_ISL37300P, 204 1.59 imp PCMCIA_CIS_INTERSIL_ISL37300P }, 205 1.42 mycroft 206 1.45 mycroft { PCMCIA_VENDOR_SIMPLETECH, PCMCIA_PRODUCT_SIMPLETECH_SPECTRUM24, 207 1.45 mycroft PCMCIA_CIS_SIMPLETECH_SPECTRUM24 }, 208 1.42 mycroft 209 1.42 mycroft { PCMCIA_VENDOR_ERICSSON, PCMCIA_PRODUCT_ERICSSON_WIRELESSLAN, 210 1.42 mycroft PCMCIA_CIS_ERICSSON_WIRELESSLAN }, 211 1.42 mycroft 212 1.42 mycroft { PCMCIA_VENDOR_SYMBOL, PCMCIA_PRODUCT_SYMBOL_LA4100, 213 1.42 mycroft PCMCIA_CIS_SYMBOL_LA4100 }, 214 1.42 mycroft 215 1.42 mycroft { PCMCIA_VENDOR_LINKSYS2, PCMCIA_PRODUCT_LINKSYS2_IWN, 216 1.42 mycroft PCMCIA_CIS_NANOSPEED_PRISM2 }, 217 1.42 mycroft 218 1.42 mycroft { PCMCIA_VENDOR_LINKSYS2, PCMCIA_PRODUCT_LINKSYS2_IWN3, 219 1.42 mycroft PCMCIA_CIS_LINKSYS2_IWN3 }, 220 1.42 mycroft 221 1.42 mycroft { PCMCIA_VENDOR_LINKSYS2, PCMCIA_PRODUCT_LINKSYS2_WCF11, 222 1.42 mycroft PCMCIA_CIS_LINKSYS2_WCF11 }, 223 1.42 mycroft 224 1.62 christos { PCMCIA_VENDOR_MICROSOFT, PCMCIA_PRODUCT_MICROSOFT_MN_520, 225 1.62 christos PCMCIA_CIS_MICROSOFT_MN_520 }, 226 1.62 christos 227 1.42 mycroft { PCMCIA_VENDOR_PLANEX, PCMCIA_PRODUCT_PLANEX_GWNS11H, 228 1.42 mycroft PCMCIA_CIS_PLANEX_GWNS11H }, 229 1.42 mycroft 230 1.42 mycroft { PCMCIA_VENDOR_BAY, PCMCIA_PRODUCT_BAY_EMOBILITY_11B, 231 1.42 mycroft PCMCIA_CIS_BAY_EMOBILITY_11B }, 232 1.42 mycroft 233 1.42 mycroft { PCMCIA_VENDOR_ACTIONTEC, PCMCIA_PRODUCT_ACTIONTEC_PRISM, 234 1.42 mycroft PCMCIA_CIS_ACTIONTEC_PRISM }, 235 1.42 mycroft 236 1.42 mycroft { PCMCIA_VENDOR_DLINK_2, PCMCIA_PRODUCT_DLINK_DWL650H, 237 1.42 mycroft PCMCIA_CIS_DLINK_DWL650H }, 238 1.42 mycroft 239 1.42 mycroft { PCMCIA_VENDOR_FUJITSU, PCMCIA_PRODUCT_FUJITSU_WL110, 240 1.42 mycroft PCMCIA_CIS_FUJITSU_WL110 }, 241 1.42 mycroft 242 1.42 mycroft { PCMCIA_VENDOR_ARTEM, PCMCIA_PRODUCT_ARTEM_ONAIR, 243 1.42 mycroft PCMCIA_CIS_ARTEM_ONAIR }, 244 1.44 mycroft 245 1.44 mycroft { PCMCIA_VENDOR_ASUSTEK, PCMCIA_PRODUCT_ASUSTEK_WL_100, 246 1.44 mycroft PCMCIA_CIS_ASUSTEK_WL_100 }, 247 1.63 martin 248 1.63 martin { PCMCIA_VENDOR_PROXIM, PCMCIA_PRODUCT_PROXIM_RANGELANDS_8430, 249 1.63 martin PCMCIA_CIS_PROXIM_RANGELANDS_8430 }, 250 1.69 scottr 251 1.69 scottr { PCMCIA_VENDOR_SIEMENS, PCMCIA_PRODUCT_SIEMENS_SS1021, 252 1.69 scottr PCMCIA_CIS_SIEMENS_SS1021 }, 253 1.1 ichiro }; 254 1.56 mycroft static const size_t wi_pcmcia_nproducts = 255 1.56 mycroft sizeof(wi_pcmcia_products) / sizeof(wi_pcmcia_products[0]); 256 1.1 ichiro 257 1.1 ichiro static int 258 1.86 christos wi_pcmcia_match(device_t parent, cfdata_t match, void *aux) 259 1.1 ichiro { 260 1.1 ichiro struct pcmcia_attach_args *pa = aux; 261 1.1 ichiro 262 1.56 mycroft if (pcmcia_product_lookup(pa, wi_pcmcia_products, wi_pcmcia_nproducts, 263 1.56 mycroft sizeof(wi_pcmcia_products[0]), NULL)) 264 1.88 dyoung return 1; 265 1.88 dyoung return 0; 266 1.1 ichiro } 267 1.1 ichiro 268 1.1 ichiro static int 269 1.86 christos wi_pcmcia_enable(device_t self, int onoff) 270 1.1 ichiro { 271 1.86 christos struct wi_pcmcia_softc *psc = device_private(self); 272 1.86 christos struct wi_softc *sc = &psc->sc_wi; 273 1.1 ichiro struct pcmcia_function *pf = psc->sc_pf; 274 1.54 mycroft int error; 275 1.1 ichiro 276 1.86 christos if (onoff) { 277 1.86 christos /* establish the interrupt. */ 278 1.86 christos sc->sc_ih = pcmcia_intr_establish(pf, IPL_NET, wi_intr, sc); 279 1.89 dyoung if (sc->sc_ih == NULL) 280 1.86 christos return EIO; 281 1.86 christos 282 1.86 christos error = pcmcia_function_enable(pf); 283 1.86 christos if (error) { 284 1.86 christos pcmcia_intr_disestablish(pf, sc->sc_ih); 285 1.89 dyoung sc->sc_ih = NULL; 286 1.86 christos return EIO; 287 1.86 christos } 288 1.54 mycroft 289 1.86 christos if (psc->sc_symbol_cf) { 290 1.73 dsl #if WI_PCMCIA_SPECTRUM24T_FW 291 1.86 christos if (wi_pcmcia_load_firm(sc, 292 1.86 christos spectrum24t_primsym, sizeof(spectrum24t_primsym), 293 1.86 christos spectrum24t_secsym, sizeof(spectrum24t_secsym))) { 294 1.86 christos aprint_error_dev(sc->sc_dev, 295 1.86 christos "couldn't load firmware\n"); 296 1.86 christos wi_pcmcia_enable(self, 0); 297 1.86 christos return EIO; 298 1.86 christos } 299 1.73 dsl #else 300 1.86 christos aprint_error_dev(sc->sc_dev, 301 1.86 christos "firmware load not configured\n"); 302 1.86 christos return EIO; 303 1.73 dsl #endif 304 1.86 christos } 305 1.86 christos DELAY(1000); 306 1.86 christos } else { 307 1.86 christos pcmcia_function_disable(psc->sc_pf); 308 1.87 dyoung if (sc->sc_ih != NULL) { 309 1.87 dyoung pcmcia_intr_disestablish(psc->sc_pf, sc->sc_ih); 310 1.87 dyoung sc->sc_ih = NULL; 311 1.87 dyoung } 312 1.17 onoe } 313 1.58 mycroft 314 1.86 christos return 0; 315 1.1 ichiro } 316 1.1 ichiro 317 1.52 mycroft static int 318 1.81 dsl wi_pcmcia_validate_config(struct pcmcia_config_entry *cfe) 319 1.52 mycroft { 320 1.52 mycroft if (cfe->iftype != PCMCIA_IFTYPE_IO || 321 1.52 mycroft cfe->num_iospace != 1 || 322 1.52 mycroft cfe->iospace[0].length < WI_IOSIZE) 323 1.88 dyoung return EINVAL; 324 1.52 mycroft cfe->num_memspace = 0; 325 1.88 dyoung return 0; 326 1.52 mycroft } 327 1.52 mycroft 328 1.1 ichiro static void 329 1.86 christos wi_pcmcia_attach(device_t parent, device_t self, void *aux) 330 1.1 ichiro { 331 1.90 christos struct wi_pcmcia_softc *psc = device_private(self); 332 1.1 ichiro struct wi_softc *sc = &psc->sc_wi; 333 1.1 ichiro struct pcmcia_attach_args *pa = aux; 334 1.1 ichiro struct pcmcia_config_entry *cfe; 335 1.47 mycroft int haveaddr; 336 1.52 mycroft int error; 337 1.1 ichiro 338 1.75 uwe aprint_naive("\n"); 339 1.75 uwe 340 1.86 christos sc->sc_dev = self; 341 1.1 ichiro psc->sc_pf = pa->pf; 342 1.1 ichiro 343 1.52 mycroft error = pcmcia_function_configure(pa->pf, wi_pcmcia_validate_config); 344 1.52 mycroft if (error) { 345 1.92 msaitoh aprint_error_dev(self, "configure failed, error=%d\n", error); 346 1.52 mycroft return; 347 1.1 ichiro } 348 1.1 ichiro 349 1.52 mycroft cfe = pa->pf->cfe; 350 1.52 mycroft sc->sc_iot = cfe->iospace[0].handle.iot; 351 1.52 mycroft sc->sc_ioh = cfe->iospace[0].handle.ioh; 352 1.50 mycroft 353 1.56 mycroft if (pa->manufacturer == PCMCIA_VENDOR_SYMBOL && 354 1.56 mycroft pa->product == PCMCIA_PRODUCT_SYMBOL_LA4100) 355 1.17 onoe psc->sc_symbol_cf = 1; 356 1.30 onoe /* 357 1.30 onoe * XXX: Sony PEGA-WL100 CF card has a same vendor/product id as 358 1.30 onoe * Intel PCMCIA card. It may be incorrect to detect by the 359 1.30 onoe * initial value of COR register. 360 1.30 onoe */ 361 1.56 mycroft if (pa->manufacturer == PCMCIA_VENDOR_INTEL && 362 1.56 mycroft pa->product == PCMCIA_PRODUCT_INTEL_PRO_WLAN_2011 && 363 1.30 onoe CSR_READ_2(sc, WI_COR) == WI_COR_IOMODE) 364 1.30 onoe psc->sc_symbol_cf = 1; 365 1.30 onoe 366 1.86 christos error = wi_pcmcia_enable(self, 1); 367 1.54 mycroft if (error) 368 1.52 mycroft goto fail; 369 1.61 perry 370 1.50 mycroft sc->sc_pci = 0; 371 1.50 mycroft sc->sc_enable = wi_pcmcia_enable; 372 1.1 ichiro 373 1.78 cegger printf("%s:", device_xname(self)); 374 1.46 mycroft 375 1.47 mycroft haveaddr = pa->pf->pf_funce_lan_nidlen == IEEE80211_ADDR_LEN; 376 1.47 mycroft if (wi_attach(sc, haveaddr ? pa->pf->pf_funce_lan_nid : 0) != 0) { 377 1.78 cegger aprint_error_dev(self, "failed to attach controller\n"); 378 1.52 mycroft goto fail2; 379 1.1 ichiro } 380 1.1 ichiro 381 1.85 tsutsui if (pmf_device_register(self, NULL, NULL)) 382 1.85 tsutsui pmf_class_network_register(self, &sc->sc_if); 383 1.85 tsutsui else 384 1.77 jmcneill aprint_error_dev(self, "couldn't establish power handler\n"); 385 1.1 ichiro 386 1.86 christos wi_pcmcia_enable(self, 0); 387 1.52 mycroft psc->sc_state = WI_PCMCIA_ATTACHED; 388 1.1 ichiro return; 389 1.1 ichiro 390 1.52 mycroft fail2: 391 1.86 christos wi_pcmcia_enable(self, 0); 392 1.52 mycroft fail: 393 1.52 mycroft pcmcia_function_unconfigure(pa->pf); 394 1.1 ichiro } 395 1.1 ichiro 396 1.1 ichiro static int 397 1.84 cegger wi_pcmcia_detach(device_t self, int flags) 398 1.1 ichiro { 399 1.86 christos struct wi_pcmcia_softc *psc = device_private(self); 400 1.87 dyoung struct wi_softc *sc = &psc->sc_wi; 401 1.1 ichiro int error; 402 1.1 ichiro 403 1.52 mycroft if (psc->sc_state != WI_PCMCIA_ATTACHED) 404 1.88 dyoung return 0; 405 1.1 ichiro 406 1.1 ichiro error = wi_detach(&psc->sc_wi); 407 1.1 ichiro if (error != 0) 408 1.88 dyoung return error; 409 1.1 ichiro 410 1.87 dyoung if (sc->sc_ih != NULL) 411 1.87 dyoung pcmcia_intr_disestablish(psc->sc_pf, sc->sc_ih); 412 1.87 dyoung 413 1.52 mycroft pcmcia_function_unconfigure(psc->sc_pf); 414 1.1 ichiro 415 1.88 dyoung return 0; 416 1.1 ichiro } 417 1.1 ichiro 418 1.17 onoe /* 419 1.17 onoe * Special routines to download firmware for Symbol CF card. 420 1.17 onoe * XXX: This should be modified generic into any PRISM-2 based card. 421 1.17 onoe */ 422 1.17 onoe 423 1.17 onoe #define WI_SBCF_PDIADDR 0x3100 424 1.17 onoe 425 1.17 onoe /* unaligned load little endian */ 426 1.17 onoe #define GETLE32(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24)) 427 1.17 onoe #define GETLE16(p) ((p)[0] | ((p)[1]<<8)) 428 1.17 onoe 429 1.73 dsl #if WI_PCMCIA_SPECTRUM24T_FW 430 1.17 onoe static int 431 1.86 christos wi_pcmcia_load_firm(struct wi_softc *sc, const void *primsym, int primlen, 432 1.86 christos const void *secsym, int seclen) 433 1.17 onoe { 434 1.17 onoe u_int8_t ebuf[256]; 435 1.17 onoe int i; 436 1.17 onoe 437 1.17 onoe /* load primary code and run it */ 438 1.17 onoe wi_pcmcia_set_hcr(sc, WI_HCR_EEHOLD); 439 1.17 onoe if (wi_pcmcia_write_firm(sc, primsym, primlen, NULL, 0)) 440 1.17 onoe return EIO; 441 1.17 onoe wi_pcmcia_set_hcr(sc, WI_HCR_RUN); 442 1.17 onoe for (i = 0; ; i++) { 443 1.17 onoe if (i == 10) 444 1.17 onoe return ETIMEDOUT; 445 1.17 onoe tsleep(sc, PWAIT, "wiinit", 1); 446 1.17 onoe if (CSR_READ_2(sc, WI_CNTL) == WI_CNTL_AUX_ENA_STAT) 447 1.17 onoe break; 448 1.17 onoe /* write the magic key value to unlock aux port */ 449 1.17 onoe CSR_WRITE_2(sc, WI_PARAM0, WI_AUX_KEY0); 450 1.17 onoe CSR_WRITE_2(sc, WI_PARAM1, WI_AUX_KEY1); 451 1.17 onoe CSR_WRITE_2(sc, WI_PARAM2, WI_AUX_KEY2); 452 1.17 onoe CSR_WRITE_2(sc, WI_CNTL, WI_CNTL_AUX_ENA_CNTL); 453 1.17 onoe } 454 1.17 onoe 455 1.17 onoe /* issue read EEPROM command: XXX copied from wi_cmd() */ 456 1.17 onoe CSR_WRITE_2(sc, WI_PARAM0, 0); 457 1.17 onoe CSR_WRITE_2(sc, WI_PARAM1, 0); 458 1.17 onoe CSR_WRITE_2(sc, WI_PARAM2, 0); 459 1.17 onoe CSR_WRITE_2(sc, WI_COMMAND, WI_CMD_READEE); 460 1.93 msaitoh for (i = 0; i < WI_TIMEOUT; i++) { 461 1.93 msaitoh if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD) 462 1.93 msaitoh break; 463 1.93 msaitoh DELAY(1); 464 1.93 msaitoh } 465 1.93 msaitoh CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD); 466 1.17 onoe 467 1.17 onoe CSR_WRITE_2(sc, WI_AUX_PAGE, WI_SBCF_PDIADDR / WI_AUX_PGSZ); 468 1.17 onoe CSR_WRITE_2(sc, WI_AUX_OFFSET, WI_SBCF_PDIADDR % WI_AUX_PGSZ); 469 1.17 onoe CSR_READ_MULTI_STREAM_2(sc, WI_AUX_DATA, 470 1.17 onoe (u_int16_t *)ebuf, sizeof(ebuf) / 2); 471 1.17 onoe if (GETLE16(ebuf) > sizeof(ebuf)) 472 1.17 onoe return EIO; 473 1.17 onoe if (wi_pcmcia_write_firm(sc, secsym, seclen, ebuf + 4, GETLE16(ebuf))) 474 1.17 onoe return EIO; 475 1.17 onoe return 0; 476 1.17 onoe } 477 1.17 onoe 478 1.17 onoe static int 479 1.86 christos wi_pcmcia_write_firm(struct wi_softc *sc, const void *buf, int buflen, 480 1.86 christos const void *ebuf, int ebuflen) 481 1.17 onoe { 482 1.17 onoe const u_int8_t *p, *ep, *q, *eq; 483 1.65 itohy char *endp; 484 1.17 onoe u_int32_t addr, id, eid; 485 1.17 onoe int i, len, elen, nblk, pdrlen; 486 1.17 onoe 487 1.17 onoe /* 488 1.17 onoe * Parse the header of the firmware image. 489 1.17 onoe */ 490 1.17 onoe p = buf; 491 1.17 onoe ep = p + buflen; 492 1.17 onoe while (p < ep && *p++ != ' '); /* FILE: */ 493 1.17 onoe while (p < ep && *p++ != ' '); /* filename */ 494 1.17 onoe while (p < ep && *p++ != ' '); /* type of the firmware */ 495 1.65 itohy nblk = strtoul(p, &endp, 10); 496 1.65 itohy p = (void *)endp; 497 1.65 itohy pdrlen = strtoul(p + 1, &endp, 10); 498 1.65 itohy p = (void *)endp; 499 1.17 onoe while (p < ep && *p++ != 0x1a); /* skip rest of header */ 500 1.17 onoe 501 1.17 onoe /* 502 1.17 onoe * Block records: address[4], length[2], data[length]; 503 1.17 onoe */ 504 1.17 onoe for (i = 0; i < nblk; i++) { 505 1.17 onoe addr = GETLE32(p); p += 4; 506 1.17 onoe len = GETLE16(p); p += 2; 507 1.17 onoe CSR_WRITE_2(sc, WI_AUX_PAGE, addr / WI_AUX_PGSZ); 508 1.17 onoe CSR_WRITE_2(sc, WI_AUX_OFFSET, addr % WI_AUX_PGSZ); 509 1.17 onoe CSR_WRITE_MULTI_STREAM_2(sc, WI_AUX_DATA, 510 1.17 onoe (const u_int16_t *)p, len / 2); 511 1.17 onoe p += len; 512 1.17 onoe } 513 1.61 perry 514 1.17 onoe /* 515 1.17 onoe * PDR: id[4], address[4], length[4]; 516 1.17 onoe */ 517 1.17 onoe for (i = 0; i < pdrlen; ) { 518 1.17 onoe id = GETLE32(p); p += 4; i += 4; 519 1.17 onoe addr = GETLE32(p); p += 4; i += 4; 520 1.17 onoe len = GETLE32(p); p += 4; i += 4; 521 1.17 onoe /* replace PDR entry with the values from EEPROM, if any */ 522 1.17 onoe for (q = ebuf, eq = q + ebuflen; q < eq; q += elen * 2) { 523 1.17 onoe elen = GETLE16(q); q += 2; 524 1.17 onoe eid = GETLE16(q); q += 2; 525 1.17 onoe elen--; /* elen includes eid */ 526 1.17 onoe if (eid == 0) 527 1.17 onoe break; 528 1.17 onoe if (eid != id) 529 1.17 onoe continue; 530 1.17 onoe CSR_WRITE_2(sc, WI_AUX_PAGE, addr / WI_AUX_PGSZ); 531 1.17 onoe CSR_WRITE_2(sc, WI_AUX_OFFSET, addr % WI_AUX_PGSZ); 532 1.17 onoe CSR_WRITE_MULTI_STREAM_2(sc, WI_AUX_DATA, 533 1.17 onoe (const u_int16_t *)q, len / 2); 534 1.17 onoe break; 535 1.17 onoe } 536 1.17 onoe } 537 1.17 onoe return 0; 538 1.17 onoe } 539 1.17 onoe 540 1.17 onoe static int 541 1.81 dsl wi_pcmcia_set_hcr(struct wi_softc *sc, int mode) 542 1.17 onoe { 543 1.17 onoe u_int16_t hcr; 544 1.17 onoe 545 1.17 onoe CSR_WRITE_2(sc, WI_COR, WI_COR_RESET); 546 1.17 onoe tsleep(sc, PWAIT, "wiinit", 1); 547 1.17 onoe hcr = CSR_READ_2(sc, WI_HCR); 548 1.17 onoe hcr = (hcr & WI_HCR_4WIRE) | (mode & ~WI_HCR_4WIRE); 549 1.17 onoe CSR_WRITE_2(sc, WI_HCR, hcr); 550 1.17 onoe tsleep(sc, PWAIT, "wiinit", 1); 551 1.17 onoe CSR_WRITE_2(sc, WI_COR, WI_COR_IOMODE); 552 1.17 onoe tsleep(sc, PWAIT, "wiinit", 1); 553 1.17 onoe return 0; 554 1.1 ichiro } 555 1.73 dsl #endif 556