1 /* $OpenBSD: bwfm.c,v 1.91 2021/10/23 12:48:17 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2010-2016 Broadcom Corporation 4 * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se> 5 * 6 * Permission to use, copy, modify, and/or 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/systm.h> 23 #include <sys/buf.h> 24 #include <sys/kernel.h> 25 #include <sys/malloc.h> 26 #include <sys/device.h> 27 #include <sys/queue.h> 28 #include <sys/socket.h> 29 #include <sys/sockio.h> 30 31 #if defined(__HAVE_FDT) 32 #include <machine/fdt.h> 33 #include <dev/ofw/openfirm.h> 34 #endif 35 36 #if NBPFILTER > 0 37 #include <net/bpf.h> 38 #endif 39 #include <net/if.h> 40 #include <net/if_dl.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 48 #include <dev/ic/bwfmvar.h> 49 #include <dev/ic/bwfmreg.h> 50 51 /* #define BWFM_DEBUG */ 52 #ifdef BWFM_DEBUG 53 #define DPRINTF(x) do { if (bwfm_debug > 0) printf x; } while (0) 54 #define DPRINTFN(n, x) do { if (bwfm_debug >= (n)) printf x; } while (0) 55 static int bwfm_debug = 1; 56 #else 57 #define DPRINTF(x) do { ; } while (0) 58 #define DPRINTFN(n, x) do { ; } while (0) 59 #endif 60 61 #define DEVNAME(sc) ((sc)->sc_dev.dv_xname) 62 63 void bwfm_start(struct ifnet *); 64 void bwfm_init(struct ifnet *); 65 void bwfm_stop(struct ifnet *); 66 void bwfm_iff(struct bwfm_softc *); 67 void bwfm_watchdog(struct ifnet *); 68 void bwfm_update_node(void *, struct ieee80211_node *); 69 void bwfm_update_nodes(struct bwfm_softc *); 70 int bwfm_ioctl(struct ifnet *, u_long, caddr_t); 71 int bwfm_media_change(struct ifnet *); 72 73 void bwfm_process_clm_blob(struct bwfm_softc *); 74 75 int bwfm_chip_attach(struct bwfm_softc *); 76 void bwfm_chip_detach(struct bwfm_softc *); 77 struct bwfm_core *bwfm_chip_get_core_idx(struct bwfm_softc *, int, int); 78 struct bwfm_core *bwfm_chip_get_core(struct bwfm_softc *, int); 79 struct bwfm_core *bwfm_chip_get_pmu(struct bwfm_softc *); 80 int bwfm_chip_ai_isup(struct bwfm_softc *, struct bwfm_core *); 81 void bwfm_chip_ai_disable(struct bwfm_softc *, struct bwfm_core *, 82 uint32_t, uint32_t); 83 void bwfm_chip_ai_reset(struct bwfm_softc *, struct bwfm_core *, 84 uint32_t, uint32_t, uint32_t); 85 void bwfm_chip_dmp_erom_scan(struct bwfm_softc *); 86 int bwfm_chip_dmp_get_regaddr(struct bwfm_softc *, uint32_t *, 87 uint32_t *, uint32_t *); 88 int bwfm_chip_cr4_set_active(struct bwfm_softc *, uint32_t); 89 void bwfm_chip_cr4_set_passive(struct bwfm_softc *); 90 int bwfm_chip_ca7_set_active(struct bwfm_softc *, uint32_t); 91 void bwfm_chip_ca7_set_passive(struct bwfm_softc *); 92 int bwfm_chip_cm3_set_active(struct bwfm_softc *); 93 void bwfm_chip_cm3_set_passive(struct bwfm_softc *); 94 void bwfm_chip_socram_ramsize(struct bwfm_softc *, struct bwfm_core *); 95 void bwfm_chip_sysmem_ramsize(struct bwfm_softc *, struct bwfm_core *); 96 void bwfm_chip_tcm_ramsize(struct bwfm_softc *, struct bwfm_core *); 97 void bwfm_chip_tcm_rambase(struct bwfm_softc *); 98 99 int bwfm_proto_bcdc_query_dcmd(struct bwfm_softc *, int, 100 int, char *, size_t *); 101 int bwfm_proto_bcdc_set_dcmd(struct bwfm_softc *, int, 102 int, char *, size_t); 103 void bwfm_proto_bcdc_rx(struct bwfm_softc *, struct mbuf *, 104 struct mbuf_list *); 105 int bwfm_proto_bcdc_txctl(struct bwfm_softc *, int, char *, size_t *); 106 void bwfm_proto_bcdc_rxctl(struct bwfm_softc *, char *, size_t); 107 108 int bwfm_fwvar_cmd_get_data(struct bwfm_softc *, int, void *, size_t); 109 int bwfm_fwvar_cmd_set_data(struct bwfm_softc *, int, void *, size_t); 110 int bwfm_fwvar_cmd_get_int(struct bwfm_softc *, int, uint32_t *); 111 int bwfm_fwvar_cmd_set_int(struct bwfm_softc *, int, uint32_t); 112 int bwfm_fwvar_var_get_data(struct bwfm_softc *, char *, void *, size_t); 113 int bwfm_fwvar_var_set_data(struct bwfm_softc *, char *, void *, size_t); 114 int bwfm_fwvar_var_get_int(struct bwfm_softc *, char *, uint32_t *); 115 int bwfm_fwvar_var_set_int(struct bwfm_softc *, char *, uint32_t); 116 117 uint32_t bwfm_chan2spec(struct bwfm_softc *, struct ieee80211_channel *); 118 uint32_t bwfm_chan2spec_d11n(struct bwfm_softc *, struct ieee80211_channel *); 119 uint32_t bwfm_chan2spec_d11ac(struct bwfm_softc *, struct ieee80211_channel *); 120 uint32_t bwfm_spec2chan(struct bwfm_softc *, uint32_t); 121 uint32_t bwfm_spec2chan_d11n(struct bwfm_softc *, uint32_t); 122 uint32_t bwfm_spec2chan_d11ac(struct bwfm_softc *, uint32_t); 123 124 void bwfm_connect(struct bwfm_softc *); 125 #ifndef IEEE80211_STA_ONLY 126 void bwfm_hostap(struct bwfm_softc *); 127 #endif 128 void bwfm_scan(struct bwfm_softc *); 129 void bwfm_scan_abort(struct bwfm_softc *); 130 131 void bwfm_task(void *); 132 void bwfm_do_async(struct bwfm_softc *, 133 void (*)(struct bwfm_softc *, void *), void *, int); 134 135 int bwfm_set_key(struct ieee80211com *, struct ieee80211_node *, 136 struct ieee80211_key *); 137 void bwfm_delete_key(struct ieee80211com *, struct ieee80211_node *, 138 struct ieee80211_key *); 139 int bwfm_send_mgmt(struct ieee80211com *, struct ieee80211_node *, 140 int, int, int); 141 int bwfm_newstate(struct ieee80211com *, enum ieee80211_state, int); 142 143 void bwfm_set_key_cb(struct bwfm_softc *, void *); 144 void bwfm_delete_key_cb(struct bwfm_softc *, void *); 145 void bwfm_rx_event_cb(struct bwfm_softc *, struct mbuf *); 146 147 struct mbuf *bwfm_newbuf(void); 148 #ifndef IEEE80211_STA_ONLY 149 void bwfm_rx_auth_ind(struct bwfm_softc *, struct bwfm_event *, size_t); 150 void bwfm_rx_assoc_ind(struct bwfm_softc *, struct bwfm_event *, size_t, int); 151 void bwfm_rx_deauth_ind(struct bwfm_softc *, struct bwfm_event *, size_t); 152 void bwfm_rx_disassoc_ind(struct bwfm_softc *, struct bwfm_event *, size_t); 153 void bwfm_rx_leave_ind(struct bwfm_softc *, struct bwfm_event *, size_t, int); 154 #endif 155 void bwfm_rx_event(struct bwfm_softc *, struct mbuf *); 156 void bwfm_scan_node(struct bwfm_softc *, struct bwfm_bss_info *, size_t); 157 158 extern void ieee80211_node2req(struct ieee80211com *, 159 const struct ieee80211_node *, struct ieee80211_nodereq *); 160 extern void ieee80211_req2node(struct ieee80211com *, 161 const struct ieee80211_nodereq *, struct ieee80211_node *); 162 163 uint8_t bwfm_2ghz_channels[] = { 164 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 165 }; 166 uint8_t bwfm_5ghz_channels[] = { 167 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, 100, 104, 108, 112, 168 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169 }; 170 171 struct bwfm_proto_ops bwfm_proto_bcdc_ops = { 172 .proto_query_dcmd = bwfm_proto_bcdc_query_dcmd, 173 .proto_set_dcmd = bwfm_proto_bcdc_set_dcmd, 174 .proto_rx = bwfm_proto_bcdc_rx, 175 .proto_rxctl = bwfm_proto_bcdc_rxctl, 176 }; 177 178 struct cfdriver bwfm_cd = { 179 NULL, "bwfm", DV_IFNET 180 }; 181 182 void 183 bwfm_attach(struct bwfm_softc *sc) 184 { 185 struct ieee80211com *ic = &sc->sc_ic; 186 struct ifnet *ifp = &ic->ic_if; 187 188 TAILQ_INIT(&sc->sc_bcdc_rxctlq); 189 190 /* Init host async commands ring. */ 191 sc->sc_cmdq.cur = sc->sc_cmdq.next = sc->sc_cmdq.queued = 0; 192 sc->sc_taskq = taskq_create(DEVNAME(sc), 1, IPL_SOFTNET, 0); 193 task_set(&sc->sc_task, bwfm_task, sc); 194 ml_init(&sc->sc_evml); 195 196 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ 197 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ 198 ic->ic_state = IEEE80211_S_INIT; 199 200 ic->ic_caps = 201 #ifndef IEEE80211_STA_ONLY 202 IEEE80211_C_HOSTAP | /* Access Point */ 203 #endif 204 IEEE80211_C_RSN | /* WPA/RSN */ 205 IEEE80211_C_SCANALL | /* device scans all channels at once */ 206 IEEE80211_C_SCANALLBAND; /* device scans all bands at once */ 207 208 /* IBSS channel undefined for now. */ 209 ic->ic_ibss_chan = &ic->ic_channels[0]; 210 211 ifp->if_softc = sc; 212 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 213 ifp->if_ioctl = bwfm_ioctl; 214 ifp->if_start = bwfm_start; 215 ifp->if_watchdog = bwfm_watchdog; 216 memcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ); 217 218 if_attach(ifp); 219 ieee80211_ifattach(ifp); 220 221 sc->sc_newstate = ic->ic_newstate; 222 ic->ic_newstate = bwfm_newstate; 223 ic->ic_send_mgmt = bwfm_send_mgmt; 224 ic->ic_set_key = bwfm_set_key; 225 ic->ic_delete_key = bwfm_delete_key; 226 227 ieee80211_media_init(ifp, bwfm_media_change, ieee80211_media_status); 228 } 229 230 void 231 bwfm_attachhook(struct device *self) 232 { 233 struct bwfm_softc *sc = (struct bwfm_softc *)self; 234 235 if (sc->sc_bus_ops->bs_preinit != NULL && 236 sc->sc_bus_ops->bs_preinit(sc)) 237 return; 238 if (bwfm_preinit(sc)) 239 return; 240 sc->sc_initialized = 1; 241 } 242 243 int 244 bwfm_preinit(struct bwfm_softc *sc) 245 { 246 struct ieee80211com *ic = &sc->sc_ic; 247 struct ifnet *ifp = &ic->ic_if; 248 int i, j, nbands, nmode, vhtmode; 249 uint32_t bandlist[3], tmp; 250 251 if (sc->sc_initialized) 252 return 0; 253 254 if (bwfm_fwvar_cmd_get_int(sc, BWFM_C_GET_VERSION, &tmp)) { 255 printf("%s: could not read io type\n", DEVNAME(sc)); 256 return 1; 257 } else 258 sc->sc_io_type = tmp; 259 if (bwfm_fwvar_var_get_data(sc, "cur_etheraddr", ic->ic_myaddr, 260 sizeof(ic->ic_myaddr))) { 261 printf("%s: could not read mac address\n", DEVNAME(sc)); 262 return 1; 263 } 264 265 printf("%s: address %s\n", DEVNAME(sc), ether_sprintf(ic->ic_myaddr)); 266 267 bwfm_process_clm_blob(sc); 268 269 if (bwfm_fwvar_var_get_int(sc, "nmode", &nmode)) 270 nmode = 0; 271 if (bwfm_fwvar_var_get_int(sc, "vhtmode", &vhtmode)) 272 vhtmode = 0; 273 if (bwfm_fwvar_cmd_get_data(sc, BWFM_C_GET_BANDLIST, bandlist, 274 sizeof(bandlist))) { 275 printf("%s: couldn't get supported band list\n", DEVNAME(sc)); 276 return 1; 277 } 278 nbands = letoh32(bandlist[0]); 279 for (i = 1; i <= nbands && i < nitems(bandlist); i++) { 280 switch (letoh32(bandlist[i])) { 281 case BWFM_BAND_2G: 282 DPRINTF(("%s: 2G HT %d VHT %d\n", 283 DEVNAME(sc), nmode, vhtmode)); 284 ic->ic_sup_rates[IEEE80211_MODE_11B] = 285 ieee80211_std_rateset_11b; 286 ic->ic_sup_rates[IEEE80211_MODE_11G] = 287 ieee80211_std_rateset_11g; 288 289 for (j = 0; j < nitems(bwfm_2ghz_channels); j++) { 290 uint8_t chan = bwfm_2ghz_channels[j]; 291 ic->ic_channels[chan].ic_freq = 292 ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ); 293 ic->ic_channels[chan].ic_flags = 294 IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | 295 IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; 296 if (nmode) 297 ic->ic_channels[chan].ic_flags |= 298 IEEE80211_CHAN_HT; 299 /* VHT is 5GHz only */ 300 } 301 break; 302 case BWFM_BAND_5G: 303 DPRINTF(("%s: 5G HT %d VHT %d\n", 304 DEVNAME(sc), nmode, vhtmode)); 305 ic->ic_sup_rates[IEEE80211_MODE_11A] = 306 ieee80211_std_rateset_11a; 307 308 for (j = 0; j < nitems(bwfm_5ghz_channels); j++) { 309 uint8_t chan = bwfm_5ghz_channels[j]; 310 ic->ic_channels[chan].ic_freq = 311 ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ); 312 ic->ic_channels[chan].ic_flags = 313 IEEE80211_CHAN_A; 314 if (nmode) 315 ic->ic_channels[chan].ic_flags |= 316 IEEE80211_CHAN_HT; 317 if (vhtmode) 318 ic->ic_channels[chan].ic_flags |= 319 IEEE80211_CHAN_VHT; 320 } 321 break; 322 default: 323 printf("%s: unsupported band 0x%x\n", DEVNAME(sc), 324 letoh32(bandlist[i])); 325 break; 326 } 327 } 328 329 /* Configure channel information obtained from firmware. */ 330 ieee80211_channel_init(ifp); 331 332 /* Configure MAC address. */ 333 if (if_setlladdr(ifp, ic->ic_myaddr)) 334 printf("%s: could not set MAC address\n", DEVNAME(sc)); 335 336 ieee80211_media_init(ifp, bwfm_media_change, ieee80211_media_status); 337 return 0; 338 } 339 340 void 341 bwfm_cleanup(struct bwfm_softc *sc) 342 { 343 bwfm_chip_detach(sc); 344 sc->sc_initialized = 0; 345 } 346 347 int 348 bwfm_detach(struct bwfm_softc *sc, int flags) 349 { 350 struct ieee80211com *ic = &sc->sc_ic; 351 struct ifnet *ifp = &ic->ic_if; 352 353 task_del(sc->sc_taskq, &sc->sc_task); 354 taskq_destroy(sc->sc_taskq); 355 ieee80211_ifdetach(ifp); 356 if_detach(ifp); 357 358 bwfm_cleanup(sc); 359 return 0; 360 } 361 362 int 363 bwfm_activate(struct bwfm_softc *sc, int act) 364 { 365 struct ieee80211com *ic = &sc->sc_ic; 366 struct ifnet *ifp = &ic->ic_if; 367 368 switch (act) { 369 case DVACT_QUIESCE: 370 if (ifp->if_flags & IFF_UP) 371 bwfm_stop(ifp); 372 break; 373 case DVACT_WAKEUP: 374 if (ifp->if_flags & IFF_UP) 375 bwfm_init(ifp); 376 break; 377 default: 378 break; 379 } 380 381 return 0; 382 } 383 384 void 385 bwfm_start(struct ifnet *ifp) 386 { 387 struct bwfm_softc *sc = ifp->if_softc; 388 struct mbuf *m; 389 390 if (!(ifp->if_flags & IFF_RUNNING)) 391 return; 392 if (ifq_is_oactive(&ifp->if_snd)) 393 return; 394 if (ifq_empty(&ifp->if_snd)) 395 return; 396 397 /* TODO: return if no link? */ 398 399 for (;;) { 400 if (sc->sc_bus_ops->bs_txcheck(sc)) { 401 ifq_set_oactive(&ifp->if_snd); 402 break; 403 } 404 405 m = ifq_dequeue(&ifp->if_snd); 406 if (m == NULL) 407 break; 408 409 if (sc->sc_bus_ops->bs_txdata(sc, m) != 0) { 410 ifp->if_oerrors++; 411 m_freem(m); 412 continue; 413 } 414 415 #if NBPFILTER > 0 416 if (ifp->if_bpf) 417 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); 418 #endif 419 } 420 } 421 422 void 423 bwfm_init(struct ifnet *ifp) 424 { 425 struct bwfm_softc *sc = ifp->if_softc; 426 struct ieee80211com *ic = &sc->sc_ic; 427 uint8_t evmask[BWFM_EVENT_MASK_LEN]; 428 struct bwfm_join_pref_params join_pref[2]; 429 int pm; 430 431 if (!sc->sc_initialized) { 432 if (sc->sc_bus_ops->bs_preinit != NULL && 433 sc->sc_bus_ops->bs_preinit(sc)) { 434 printf("%s: could not init bus\n", DEVNAME(sc)); 435 return; 436 } 437 if (bwfm_preinit(sc)) { 438 printf("%s: could not init\n", DEVNAME(sc)); 439 return; 440 } 441 sc->sc_initialized = 1; 442 } 443 444 /* Select default channel */ 445 ic->ic_bss->ni_chan = ic->ic_ibss_chan; 446 447 if (bwfm_fwvar_var_set_int(sc, "mpc", 1)) { 448 printf("%s: could not set mpc\n", DEVNAME(sc)); 449 return; 450 } 451 452 /* Select target by RSSI (boost on 5GHz) */ 453 join_pref[0].type = BWFM_JOIN_PREF_RSSI_DELTA; 454 join_pref[0].len = 2; 455 join_pref[0].rssi_gain = BWFM_JOIN_PREF_RSSI_BOOST; 456 join_pref[0].band = BWFM_JOIN_PREF_BAND_5G; 457 join_pref[1].type = BWFM_JOIN_PREF_RSSI; 458 join_pref[1].len = 2; 459 join_pref[1].rssi_gain = 0; 460 join_pref[1].band = 0; 461 if (bwfm_fwvar_var_set_data(sc, "join_pref", join_pref, 462 sizeof(join_pref))) { 463 printf("%s: could not set join pref\n", DEVNAME(sc)); 464 return; 465 } 466 467 #define BWFM_EVENT(event) evmask[(event) / 8] |= 1 << ((event) % 8) 468 memset(evmask, 0, sizeof(evmask)); 469 switch (ic->ic_opmode) { 470 case IEEE80211_M_STA: 471 BWFM_EVENT(BWFM_E_IF); 472 BWFM_EVENT(BWFM_E_LINK); 473 BWFM_EVENT(BWFM_E_AUTH); 474 BWFM_EVENT(BWFM_E_ASSOC); 475 BWFM_EVENT(BWFM_E_DEAUTH); 476 BWFM_EVENT(BWFM_E_DISASSOC); 477 BWFM_EVENT(BWFM_E_ESCAN_RESULT); 478 break; 479 #ifndef IEEE80211_STA_ONLY 480 case IEEE80211_M_HOSTAP: 481 BWFM_EVENT(BWFM_E_AUTH_IND); 482 BWFM_EVENT(BWFM_E_ASSOC_IND); 483 BWFM_EVENT(BWFM_E_REASSOC_IND); 484 BWFM_EVENT(BWFM_E_DEAUTH_IND); 485 BWFM_EVENT(BWFM_E_DISASSOC_IND); 486 BWFM_EVENT(BWFM_E_ESCAN_RESULT); 487 break; 488 #endif 489 default: 490 break; 491 } 492 #undef BWFM_EVENT 493 494 if (bwfm_fwvar_var_set_data(sc, "event_msgs", evmask, sizeof(evmask))) { 495 printf("%s: could not set event mask\n", DEVNAME(sc)); 496 return; 497 } 498 499 if (bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_SCAN_CHANNEL_TIME, 500 BWFM_DEFAULT_SCAN_CHANNEL_TIME)) { 501 printf("%s: could not set scan channel time\n", DEVNAME(sc)); 502 return; 503 } 504 if (bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_SCAN_UNASSOC_TIME, 505 BWFM_DEFAULT_SCAN_UNASSOC_TIME)) { 506 printf("%s: could not set scan unassoc time\n", DEVNAME(sc)); 507 return; 508 } 509 if (bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_SCAN_PASSIVE_TIME, 510 BWFM_DEFAULT_SCAN_PASSIVE_TIME)) { 511 printf("%s: could not set scan passive time\n", DEVNAME(sc)); 512 return; 513 } 514 515 /* 516 * Use CAM (constantly awake) when we are running as AP, 517 * otherwise use fast power saving. 518 */ 519 pm = BWFM_PM_FAST_PS; 520 #ifndef IEEE80211_STA_ONLY 521 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 522 pm = BWFM_PM_CAM; 523 #endif 524 if (bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_PM, pm)) { 525 printf("%s: could not set power\n", DEVNAME(sc)); 526 return; 527 } 528 529 bwfm_fwvar_var_set_int(sc, "txbf", 1); 530 bwfm_fwvar_cmd_set_int(sc, BWFM_C_UP, 0); 531 bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_INFRA, 1); 532 bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_AP, 0); 533 534 /* Disable all offloading (ARP, NDP, TCP/UDP cksum). */ 535 bwfm_fwvar_var_set_int(sc, "arp_ol", 0); 536 bwfm_fwvar_var_set_int(sc, "arpoe", 0); 537 bwfm_fwvar_var_set_int(sc, "ndoe", 0); 538 bwfm_fwvar_var_set_int(sc, "toe", 0); 539 540 /* 541 * The firmware supplicant can handle the WPA handshake for 542 * us, but we honestly want to do this ourselves, so disable 543 * the firmware supplicant and let our stack handle it. 544 */ 545 bwfm_fwvar_var_set_int(sc, "sup_wpa", 0); 546 547 bwfm_iff(sc); 548 549 ifp->if_flags |= IFF_RUNNING; 550 ifq_clr_oactive(&ifp->if_snd); 551 552 ieee80211_begin_scan(ifp); 553 } 554 555 void 556 bwfm_stop(struct ifnet *ifp) 557 { 558 struct bwfm_softc *sc = ifp->if_softc; 559 struct ieee80211com *ic = &sc->sc_ic; 560 struct bwfm_join_params join; 561 562 sc->sc_tx_timer = 0; 563 ifp->if_timer = 0; 564 ifp->if_flags &= ~IFF_RUNNING; 565 ifq_clr_oactive(&ifp->if_snd); 566 567 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 568 569 memset(&join, 0, sizeof(join)); 570 bwfm_fwvar_cmd_set_data(sc, BWFM_C_SET_SSID, &join, sizeof(join)); 571 bwfm_fwvar_cmd_set_int(sc, BWFM_C_DOWN, 1); 572 bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_AP, 0); 573 bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_INFRA, 0); 574 bwfm_fwvar_cmd_set_int(sc, BWFM_C_UP, 1); 575 bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_PM, BWFM_PM_FAST_PS); 576 577 if (sc->sc_bus_ops->bs_stop) 578 sc->sc_bus_ops->bs_stop(sc); 579 } 580 581 void 582 bwfm_iff(struct bwfm_softc *sc) 583 { 584 struct arpcom *ac = &sc->sc_ic.ic_ac; 585 struct ifnet *ifp = &ac->ac_if; 586 struct ether_multi *enm; 587 struct ether_multistep step; 588 size_t mcastlen; 589 char *mcast; 590 int i = 0; 591 592 mcastlen = sizeof(uint32_t) + ac->ac_multicnt * ETHER_ADDR_LEN; 593 mcast = malloc(mcastlen, M_TEMP, M_WAITOK); 594 htolem32((uint32_t *)mcast, ac->ac_multicnt); 595 596 ifp->if_flags &= ~IFF_ALLMULTI; 597 if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) { 598 ifp->if_flags |= IFF_ALLMULTI; 599 } else { 600 ETHER_FIRST_MULTI(step, ac, enm); 601 while (enm != NULL) { 602 memcpy(mcast + sizeof(uint32_t) + i * ETHER_ADDR_LEN, 603 enm->enm_addrlo, ETHER_ADDR_LEN); 604 ETHER_NEXT_MULTI(step, enm); 605 i++; 606 } 607 } 608 609 bwfm_fwvar_var_set_data(sc, "mcast_list", mcast, mcastlen); 610 bwfm_fwvar_var_set_int(sc, "allmulti", 611 !!(ifp->if_flags & IFF_ALLMULTI)); 612 bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_PROMISC, 613 !!(ifp->if_flags & IFF_PROMISC)); 614 615 free(mcast, M_TEMP, mcastlen); 616 } 617 618 void 619 bwfm_watchdog(struct ifnet *ifp) 620 { 621 struct bwfm_softc *sc = ifp->if_softc; 622 623 ifp->if_timer = 0; 624 625 if (sc->sc_tx_timer > 0) { 626 if (--sc->sc_tx_timer == 0) { 627 printf("%s: device timeout\n", DEVNAME(sc)); 628 ifp->if_oerrors++; 629 return; 630 } 631 ifp->if_timer = 1; 632 } 633 ieee80211_watchdog(ifp); 634 } 635 636 /* 637 * Tx-rate to MCS conversion might lie since some rates map to multiple MCS. 638 * But this is the best we can do given that firmware only reports kbit/s. 639 */ 640 641 void 642 bwfm_rate2vhtmcs(int *mcs, int *ss, uint32_t txrate) 643 { 644 const struct ieee80211_vht_rateset *rs; 645 int i, j; 646 647 *mcs = -1; 648 *ss = -1; 649 /* TODO: Select specific ratesets based on BSS channel width. */ 650 for (i = 0; i < IEEE80211_VHT_NUM_RATESETS; i++) { 651 rs = &ieee80211_std_ratesets_11ac[i]; 652 for (j = 0; j < rs->nrates; j++) { 653 if (rs->rates[j] == txrate / 500) { 654 *mcs = j; 655 *ss = rs->num_ss; 656 return; 657 } 658 } 659 } 660 } 661 662 int 663 bwfm_rate2htmcs(uint32_t txrate) 664 { 665 const struct ieee80211_ht_rateset *rs; 666 int i, j; 667 668 /* TODO: Select specific ratesets based on BSS channel width. */ 669 for (i = 0; i < IEEE80211_HT_NUM_RATESETS; i++) { 670 rs = &ieee80211_std_ratesets_11n[i]; 671 for (j = 0; j < rs->nrates; j++) { 672 if (rs->rates[j] == txrate / 500) 673 return rs->min_mcs + j; 674 } 675 } 676 677 return -1; 678 } 679 680 void 681 bwfm_update_node(void *arg, struct ieee80211_node *ni) 682 { 683 struct bwfm_softc *sc = arg; 684 struct ieee80211com *ic = &sc->sc_ic; 685 struct bwfm_sta_info sta; 686 uint32_t flags; 687 int8_t rssi; 688 uint32_t txrate; 689 int i; 690 691 memset(&sta, 0, sizeof(sta)); 692 memcpy((uint8_t *)&sta, ni->ni_macaddr, sizeof(ni->ni_macaddr)); 693 694 if (bwfm_fwvar_var_get_data(sc, "sta_info", &sta, sizeof(sta))) 695 return; 696 697 if (!IEEE80211_ADDR_EQ(ni->ni_macaddr, sta.ea)) 698 return; 699 700 if (le16toh(sta.ver) < 4) 701 return; 702 703 flags = le32toh(sta.flags); 704 if ((flags & BWFM_STA_SCBSTATS) == 0) 705 return; 706 707 rssi = 0; 708 for (i = 0; i < BWFM_ANT_MAX; i++) { 709 if (sta.rssi[i] >= 0) 710 continue; 711 if (rssi == 0 || sta.rssi[i] > rssi) 712 rssi = sta.rssi[i]; 713 } 714 if (rssi) 715 ni->ni_rssi = rssi; 716 717 txrate = le32toh(sta.tx_rate); /* in kbit/s */ 718 if (txrate == 0xffffffff) /* Seen this happening during association. */ 719 return; 720 721 if ((le32toh(sta.flags) & BWFM_STA_VHT_CAP)) { 722 int mcs, ss; 723 /* Tell net80211 that firmware has negotiated 11ac. */ 724 ni->ni_flags |= IEEE80211_NODE_VHT; 725 ni->ni_flags |= IEEE80211_NODE_HT; /* VHT implies HT support */ 726 if (ic->ic_curmode < IEEE80211_MODE_11AC) 727 ieee80211_setmode(ic, IEEE80211_MODE_11AC); 728 bwfm_rate2vhtmcs(&mcs, &ss, txrate); 729 if (mcs >= 0) { 730 ni->ni_txmcs = mcs; 731 ni->ni_vht_ss = ss; 732 } else { 733 ni->ni_txmcs = 0; 734 ni->ni_vht_ss = 1; 735 } 736 } else if ((le32toh(sta.flags) & BWFM_STA_N_CAP)) { 737 int mcs; 738 /* Tell net80211 that firmware has negotiated 11n. */ 739 ni->ni_flags |= IEEE80211_NODE_HT; 740 if (ic->ic_curmode < IEEE80211_MODE_11N) 741 ieee80211_setmode(ic, IEEE80211_MODE_11N); 742 mcs = bwfm_rate2htmcs(txrate); 743 ni->ni_txmcs = (mcs >= 0 ? mcs : 0); 744 } else { 745 /* We're in 11a/g mode. Map to a legacy rate. */ 746 for (i = 0; i < ni->ni_rates.rs_nrates; i++) { 747 uint8_t rate = ni->ni_rates.rs_rates[i]; 748 rate &= IEEE80211_RATE_VAL; 749 if (rate == txrate / 500) { 750 ni->ni_txrate = i; 751 break; 752 } 753 } 754 } 755 } 756 757 void 758 bwfm_update_nodes(struct bwfm_softc *sc) 759 { 760 struct ieee80211com *ic = &sc->sc_ic; 761 struct ieee80211_node *ni; 762 763 switch (ic->ic_opmode) { 764 case IEEE80211_M_STA: 765 bwfm_update_node(sc, ic->ic_bss); 766 /* Update cached copy in the nodes tree as well. */ 767 ni = ieee80211_find_node(ic, ic->ic_bss->ni_macaddr); 768 if (ni) { 769 ni->ni_rssi = ic->ic_bss->ni_rssi; 770 } 771 break; 772 #ifndef IEEE80211_STA_ONLY 773 case IEEE80211_M_HOSTAP: 774 ieee80211_iterate_nodes(ic, bwfm_update_node, sc); 775 break; 776 #endif 777 default: 778 break; 779 } 780 } 781 782 int 783 bwfm_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 784 { 785 struct bwfm_softc *sc = ifp->if_softc; 786 struct ieee80211com *ic = &sc->sc_ic; 787 struct ifreq *ifr; 788 int s, error = 0; 789 790 s = splnet(); 791 switch (cmd) { 792 case SIOCSIFADDR: 793 ifp->if_flags |= IFF_UP; 794 /* FALLTHROUGH */ 795 case SIOCSIFFLAGS: 796 if (ifp->if_flags & IFF_UP) { 797 if (!(ifp->if_flags & IFF_RUNNING)) 798 bwfm_init(ifp); 799 } else { 800 if (ifp->if_flags & IFF_RUNNING) 801 bwfm_stop(ifp); 802 } 803 break; 804 case SIOCADDMULTI: 805 case SIOCDELMULTI: 806 ifr = (struct ifreq *)data; 807 error = (cmd == SIOCADDMULTI) ? 808 ether_addmulti(ifr, &ic->ic_ac) : 809 ether_delmulti(ifr, &ic->ic_ac); 810 if (error == ENETRESET) { 811 bwfm_iff(sc); 812 error = 0; 813 } 814 break; 815 case SIOCGIFMEDIA: 816 case SIOCG80211NODE: 817 case SIOCG80211ALLNODES: 818 if (ic->ic_state == IEEE80211_S_RUN) 819 bwfm_update_nodes(sc); 820 /* fall through */ 821 default: 822 error = ieee80211_ioctl(ifp, cmd, data); 823 } 824 if (error == ENETRESET) { 825 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == 826 (IFF_UP | IFF_RUNNING)) { 827 bwfm_stop(ifp); 828 bwfm_init(ifp); 829 } 830 error = 0; 831 } 832 splx(s); 833 return error; 834 } 835 836 int 837 bwfm_media_change(struct ifnet *ifp) 838 { 839 int error; 840 841 error = ieee80211_media_change(ifp); 842 if (error != ENETRESET) 843 return error; 844 845 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == 846 (IFF_UP | IFF_RUNNING)) { 847 bwfm_stop(ifp); 848 bwfm_init(ifp); 849 } 850 return error; 851 } 852 853 /* Chip initialization (SDIO, PCIe) */ 854 int 855 bwfm_chip_attach(struct bwfm_softc *sc) 856 { 857 struct bwfm_core *core; 858 int need_socram = 0; 859 int has_socram = 0; 860 int cpu_found = 0; 861 uint32_t val; 862 863 LIST_INIT(&sc->sc_chip.ch_list); 864 865 if (sc->sc_buscore_ops->bc_prepare(sc) != 0) { 866 printf("%s: failed buscore prepare\n", DEVNAME(sc)); 867 return 1; 868 } 869 870 val = sc->sc_buscore_ops->bc_read(sc, 871 BWFM_CHIP_BASE + BWFM_CHIP_REG_CHIPID); 872 sc->sc_chip.ch_chip = BWFM_CHIP_CHIPID_ID(val); 873 sc->sc_chip.ch_chiprev = BWFM_CHIP_CHIPID_REV(val); 874 875 if ((sc->sc_chip.ch_chip > 0xa000) || (sc->sc_chip.ch_chip < 0x4000)) 876 snprintf(sc->sc_chip.ch_name, sizeof(sc->sc_chip.ch_name), 877 "%d", sc->sc_chip.ch_chip); 878 else 879 snprintf(sc->sc_chip.ch_name, sizeof(sc->sc_chip.ch_name), 880 "%x", sc->sc_chip.ch_chip); 881 882 switch (BWFM_CHIP_CHIPID_TYPE(val)) 883 { 884 case BWFM_CHIP_CHIPID_TYPE_SOCI_SB: 885 printf("%s: SoC interconnect SB not implemented\n", 886 DEVNAME(sc)); 887 return 1; 888 case BWFM_CHIP_CHIPID_TYPE_SOCI_AI: 889 sc->sc_chip.ch_core_isup = bwfm_chip_ai_isup; 890 sc->sc_chip.ch_core_disable = bwfm_chip_ai_disable; 891 sc->sc_chip.ch_core_reset = bwfm_chip_ai_reset; 892 bwfm_chip_dmp_erom_scan(sc); 893 break; 894 default: 895 printf("%s: SoC interconnect %d unknown\n", 896 DEVNAME(sc), BWFM_CHIP_CHIPID_TYPE(val)); 897 return 1; 898 } 899 900 LIST_FOREACH(core, &sc->sc_chip.ch_list, co_link) { 901 DPRINTF(("%s: 0x%x:%-2d base 0x%08x wrap 0x%08x\n", 902 DEVNAME(sc), core->co_id, core->co_rev, 903 core->co_base, core->co_wrapbase)); 904 905 switch (core->co_id) { 906 case BWFM_AGENT_CORE_ARM_CM3: 907 need_socram = 1; 908 /* FALLTHROUGH */ 909 case BWFM_AGENT_CORE_ARM_CR4: 910 case BWFM_AGENT_CORE_ARM_CA7: 911 cpu_found = 1; 912 break; 913 case BWFM_AGENT_INTERNAL_MEM: 914 has_socram = 1; 915 break; 916 default: 917 break; 918 } 919 } 920 921 if (!cpu_found) { 922 printf("%s: CPU core not detected\n", DEVNAME(sc)); 923 return 1; 924 } 925 if (need_socram && !has_socram) { 926 printf("%s: RAM core not provided\n", DEVNAME(sc)); 927 return 1; 928 } 929 930 bwfm_chip_set_passive(sc); 931 932 if (sc->sc_buscore_ops->bc_reset) { 933 sc->sc_buscore_ops->bc_reset(sc); 934 bwfm_chip_set_passive(sc); 935 } 936 937 if ((core = bwfm_chip_get_core(sc, BWFM_AGENT_CORE_ARM_CR4)) != NULL) { 938 bwfm_chip_tcm_ramsize(sc, core); 939 bwfm_chip_tcm_rambase(sc); 940 } else if ((core = bwfm_chip_get_core(sc, BWFM_AGENT_SYS_MEM)) != NULL) { 941 bwfm_chip_sysmem_ramsize(sc, core); 942 bwfm_chip_tcm_rambase(sc); 943 } else if ((core = bwfm_chip_get_core(sc, BWFM_AGENT_INTERNAL_MEM)) != NULL) { 944 bwfm_chip_socram_ramsize(sc, core); 945 } 946 947 core = bwfm_chip_get_core(sc, BWFM_AGENT_CORE_CHIPCOMMON); 948 sc->sc_chip.ch_cc_caps = sc->sc_buscore_ops->bc_read(sc, 949 core->co_base + BWFM_CHIP_REG_CAPABILITIES); 950 sc->sc_chip.ch_cc_caps_ext = sc->sc_buscore_ops->bc_read(sc, 951 core->co_base + BWFM_CHIP_REG_CAPABILITIES_EXT); 952 953 core = bwfm_chip_get_pmu(sc); 954 if (sc->sc_chip.ch_cc_caps & BWFM_CHIP_REG_CAPABILITIES_PMU) { 955 sc->sc_chip.ch_pmucaps = sc->sc_buscore_ops->bc_read(sc, 956 core->co_base + BWFM_CHIP_REG_PMUCAPABILITIES); 957 sc->sc_chip.ch_pmurev = sc->sc_chip.ch_pmucaps & 958 BWFM_CHIP_REG_PMUCAPABILITIES_REV_MASK; 959 } 960 961 if (sc->sc_buscore_ops->bc_setup) 962 sc->sc_buscore_ops->bc_setup(sc); 963 964 return 0; 965 } 966 967 void 968 bwfm_chip_detach(struct bwfm_softc *sc) 969 { 970 struct bwfm_core *core, *tmp; 971 972 LIST_FOREACH_SAFE(core, &sc->sc_chip.ch_list, co_link, tmp) { 973 LIST_REMOVE(core, co_link); 974 free(core, M_DEVBUF, sizeof(*core)); 975 } 976 } 977 978 struct bwfm_core * 979 bwfm_chip_get_core_idx(struct bwfm_softc *sc, int id, int idx) 980 { 981 struct bwfm_core *core; 982 983 LIST_FOREACH(core, &sc->sc_chip.ch_list, co_link) { 984 if (core->co_id == id && idx-- == 0) 985 return core; 986 } 987 988 return NULL; 989 } 990 991 struct bwfm_core * 992 bwfm_chip_get_core(struct bwfm_softc *sc, int id) 993 { 994 return bwfm_chip_get_core_idx(sc, id, 0); 995 } 996 997 struct bwfm_core * 998 bwfm_chip_get_pmu(struct bwfm_softc *sc) 999 { 1000 struct bwfm_core *cc, *pmu; 1001 1002 cc = bwfm_chip_get_core(sc, BWFM_AGENT_CORE_CHIPCOMMON); 1003 if (cc->co_rev >= 35 && sc->sc_chip.ch_cc_caps_ext & 1004 BWFM_CHIP_REG_CAPABILITIES_EXT_AOB_PRESENT) { 1005 pmu = bwfm_chip_get_core(sc, BWFM_AGENT_CORE_PMU); 1006 if (pmu) 1007 return pmu; 1008 } 1009 1010 return cc; 1011 } 1012 1013 /* Functions for the AI interconnect */ 1014 int 1015 bwfm_chip_ai_isup(struct bwfm_softc *sc, struct bwfm_core *core) 1016 { 1017 uint32_t ioctl, reset; 1018 1019 ioctl = sc->sc_buscore_ops->bc_read(sc, 1020 core->co_wrapbase + BWFM_AGENT_IOCTL); 1021 reset = sc->sc_buscore_ops->bc_read(sc, 1022 core->co_wrapbase + BWFM_AGENT_RESET_CTL); 1023 1024 if (((ioctl & (BWFM_AGENT_IOCTL_FGC | BWFM_AGENT_IOCTL_CLK)) == 1025 BWFM_AGENT_IOCTL_CLK) && 1026 ((reset & BWFM_AGENT_RESET_CTL_RESET) == 0)) 1027 return 1; 1028 1029 return 0; 1030 } 1031 1032 void 1033 bwfm_chip_ai_disable(struct bwfm_softc *sc, struct bwfm_core *core, 1034 uint32_t prereset, uint32_t reset) 1035 { 1036 uint32_t val; 1037 int i; 1038 1039 val = sc->sc_buscore_ops->bc_read(sc, 1040 core->co_wrapbase + BWFM_AGENT_RESET_CTL); 1041 if ((val & BWFM_AGENT_RESET_CTL_RESET) == 0) { 1042 1043 sc->sc_buscore_ops->bc_write(sc, 1044 core->co_wrapbase + BWFM_AGENT_IOCTL, 1045 prereset | BWFM_AGENT_IOCTL_FGC | BWFM_AGENT_IOCTL_CLK); 1046 sc->sc_buscore_ops->bc_read(sc, 1047 core->co_wrapbase + BWFM_AGENT_IOCTL); 1048 1049 sc->sc_buscore_ops->bc_write(sc, 1050 core->co_wrapbase + BWFM_AGENT_RESET_CTL, 1051 BWFM_AGENT_RESET_CTL_RESET); 1052 delay(20); 1053 1054 for (i = 300; i > 0; i--) { 1055 if (sc->sc_buscore_ops->bc_read(sc, 1056 core->co_wrapbase + BWFM_AGENT_RESET_CTL) == 1057 BWFM_AGENT_RESET_CTL_RESET) 1058 break; 1059 } 1060 if (i == 0) 1061 printf("%s: timeout on core reset\n", DEVNAME(sc)); 1062 } 1063 1064 sc->sc_buscore_ops->bc_write(sc, 1065 core->co_wrapbase + BWFM_AGENT_IOCTL, 1066 reset | BWFM_AGENT_IOCTL_FGC | BWFM_AGENT_IOCTL_CLK); 1067 sc->sc_buscore_ops->bc_read(sc, 1068 core->co_wrapbase + BWFM_AGENT_IOCTL); 1069 } 1070 1071 void 1072 bwfm_chip_ai_reset(struct bwfm_softc *sc, struct bwfm_core *core, 1073 uint32_t prereset, uint32_t reset, uint32_t postreset) 1074 { 1075 struct bwfm_core *core2 = NULL; 1076 int i; 1077 1078 if (core->co_id == BWFM_AGENT_CORE_80211) 1079 core2 = bwfm_chip_get_core_idx(sc, BWFM_AGENT_CORE_80211, 1); 1080 1081 bwfm_chip_ai_disable(sc, core, prereset, reset); 1082 if (core2) 1083 bwfm_chip_ai_disable(sc, core2, prereset, reset); 1084 1085 for (i = 50; i > 0; i--) { 1086 if ((sc->sc_buscore_ops->bc_read(sc, 1087 core->co_wrapbase + BWFM_AGENT_RESET_CTL) & 1088 BWFM_AGENT_RESET_CTL_RESET) == 0) 1089 break; 1090 sc->sc_buscore_ops->bc_write(sc, 1091 core->co_wrapbase + BWFM_AGENT_RESET_CTL, 0); 1092 delay(60); 1093 } 1094 if (i == 0) 1095 printf("%s: timeout on core reset\n", DEVNAME(sc)); 1096 if (core2) { 1097 for (i = 50; i > 0; i--) { 1098 if ((sc->sc_buscore_ops->bc_read(sc, 1099 core2->co_wrapbase + BWFM_AGENT_RESET_CTL) & 1100 BWFM_AGENT_RESET_CTL_RESET) == 0) 1101 break; 1102 sc->sc_buscore_ops->bc_write(sc, 1103 core2->co_wrapbase + BWFM_AGENT_RESET_CTL, 0); 1104 delay(60); 1105 } 1106 if (i == 0) 1107 printf("%s: timeout on core reset\n", DEVNAME(sc)); 1108 } 1109 1110 sc->sc_buscore_ops->bc_write(sc, 1111 core->co_wrapbase + BWFM_AGENT_IOCTL, 1112 postreset | BWFM_AGENT_IOCTL_CLK); 1113 sc->sc_buscore_ops->bc_read(sc, 1114 core->co_wrapbase + BWFM_AGENT_IOCTL); 1115 if (core2) { 1116 sc->sc_buscore_ops->bc_write(sc, 1117 core2->co_wrapbase + BWFM_AGENT_IOCTL, 1118 postreset | BWFM_AGENT_IOCTL_CLK); 1119 sc->sc_buscore_ops->bc_read(sc, 1120 core2->co_wrapbase + BWFM_AGENT_IOCTL); 1121 } 1122 } 1123 1124 void 1125 bwfm_chip_dmp_erom_scan(struct bwfm_softc *sc) 1126 { 1127 uint32_t erom, val, base, wrap; 1128 uint8_t type = 0; 1129 uint16_t id; 1130 uint8_t nmw, nsw, rev; 1131 struct bwfm_core *core; 1132 1133 erom = sc->sc_buscore_ops->bc_read(sc, 1134 BWFM_CHIP_BASE + BWFM_CHIP_REG_EROMPTR); 1135 while (type != BWFM_DMP_DESC_EOT) { 1136 val = sc->sc_buscore_ops->bc_read(sc, erom); 1137 type = val & BWFM_DMP_DESC_MASK; 1138 erom += 4; 1139 1140 if (type != BWFM_DMP_DESC_COMPONENT) 1141 continue; 1142 1143 id = (val & BWFM_DMP_COMP_PARTNUM) 1144 >> BWFM_DMP_COMP_PARTNUM_S; 1145 1146 val = sc->sc_buscore_ops->bc_read(sc, erom); 1147 type = val & BWFM_DMP_DESC_MASK; 1148 erom += 4; 1149 1150 if (type != BWFM_DMP_DESC_COMPONENT) { 1151 printf("%s: not component descriptor\n", DEVNAME(sc)); 1152 return; 1153 } 1154 1155 nmw = (val & BWFM_DMP_COMP_NUM_MWRAP) 1156 >> BWFM_DMP_COMP_NUM_MWRAP_S; 1157 nsw = (val & BWFM_DMP_COMP_NUM_SWRAP) 1158 >> BWFM_DMP_COMP_NUM_SWRAP_S; 1159 rev = (val & BWFM_DMP_COMP_REVISION) 1160 >> BWFM_DMP_COMP_REVISION_S; 1161 1162 if (nmw + nsw == 0 && id != BWFM_AGENT_CORE_PMU && 1163 id != BWFM_AGENT_CORE_GCI) 1164 continue; 1165 1166 if (bwfm_chip_dmp_get_regaddr(sc, &erom, &base, &wrap)) 1167 continue; 1168 1169 core = malloc(sizeof(*core), M_DEVBUF, M_WAITOK); 1170 core->co_id = id; 1171 core->co_base = base; 1172 core->co_wrapbase = wrap; 1173 core->co_rev = rev; 1174 LIST_INSERT_HEAD(&sc->sc_chip.ch_list, core, co_link); 1175 } 1176 } 1177 1178 int 1179 bwfm_chip_dmp_get_regaddr(struct bwfm_softc *sc, uint32_t *erom, 1180 uint32_t *base, uint32_t *wrap) 1181 { 1182 uint8_t type = 0, mpnum = 0; 1183 uint8_t stype, sztype, wraptype; 1184 uint32_t val; 1185 1186 *base = 0; 1187 *wrap = 0; 1188 1189 val = sc->sc_buscore_ops->bc_read(sc, *erom); 1190 type = val & BWFM_DMP_DESC_MASK; 1191 if (type == BWFM_DMP_DESC_MASTER_PORT) { 1192 mpnum = (val & BWFM_DMP_MASTER_PORT_NUM) 1193 >> BWFM_DMP_MASTER_PORT_NUM_S; 1194 wraptype = BWFM_DMP_SLAVE_TYPE_MWRAP; 1195 *erom += 4; 1196 } else if ((type & ~BWFM_DMP_DESC_ADDRSIZE_GT32) == 1197 BWFM_DMP_DESC_ADDRESS) 1198 wraptype = BWFM_DMP_SLAVE_TYPE_SWRAP; 1199 else 1200 return 1; 1201 1202 do { 1203 do { 1204 val = sc->sc_buscore_ops->bc_read(sc, *erom); 1205 type = val & BWFM_DMP_DESC_MASK; 1206 if (type == BWFM_DMP_DESC_COMPONENT) 1207 return 0; 1208 if (type == BWFM_DMP_DESC_EOT) 1209 return 1; 1210 *erom += 4; 1211 } while ((type & ~BWFM_DMP_DESC_ADDRSIZE_GT32) != 1212 BWFM_DMP_DESC_ADDRESS); 1213 1214 if (type & BWFM_DMP_DESC_ADDRSIZE_GT32) 1215 *erom += 4; 1216 1217 sztype = (val & BWFM_DMP_SLAVE_SIZE_TYPE) 1218 >> BWFM_DMP_SLAVE_SIZE_TYPE_S; 1219 if (sztype == BWFM_DMP_SLAVE_SIZE_DESC) { 1220 val = sc->sc_buscore_ops->bc_read(sc, *erom); 1221 type = val & BWFM_DMP_DESC_MASK; 1222 if (type & BWFM_DMP_DESC_ADDRSIZE_GT32) 1223 *erom += 8; 1224 else 1225 *erom += 4; 1226 } 1227 if (sztype != BWFM_DMP_SLAVE_SIZE_4K && 1228 sztype != BWFM_DMP_SLAVE_SIZE_8K) 1229 continue; 1230 1231 stype = (val & BWFM_DMP_SLAVE_TYPE) >> BWFM_DMP_SLAVE_TYPE_S; 1232 if (*base == 0 && stype == BWFM_DMP_SLAVE_TYPE_SLAVE) 1233 *base = val & BWFM_DMP_SLAVE_ADDR_BASE; 1234 if (*wrap == 0 && stype == wraptype) 1235 *wrap = val & BWFM_DMP_SLAVE_ADDR_BASE; 1236 } while (*base == 0 || *wrap == 0); 1237 1238 return 0; 1239 } 1240 1241 /* Core configuration */ 1242 int 1243 bwfm_chip_set_active(struct bwfm_softc *sc, uint32_t rstvec) 1244 { 1245 if (bwfm_chip_get_core(sc, BWFM_AGENT_CORE_ARM_CR4) != NULL) 1246 return bwfm_chip_cr4_set_active(sc, rstvec); 1247 if (bwfm_chip_get_core(sc, BWFM_AGENT_CORE_ARM_CA7) != NULL) 1248 return bwfm_chip_ca7_set_active(sc, rstvec); 1249 if (bwfm_chip_get_core(sc, BWFM_AGENT_CORE_ARM_CM3) != NULL) 1250 return bwfm_chip_cm3_set_active(sc); 1251 return 1; 1252 } 1253 1254 void 1255 bwfm_chip_set_passive(struct bwfm_softc *sc) 1256 { 1257 if (bwfm_chip_get_core(sc, BWFM_AGENT_CORE_ARM_CR4) != NULL) { 1258 bwfm_chip_cr4_set_passive(sc); 1259 return; 1260 } 1261 if (bwfm_chip_get_core(sc, BWFM_AGENT_CORE_ARM_CA7) != NULL) { 1262 bwfm_chip_ca7_set_passive(sc); 1263 return; 1264 } 1265 if (bwfm_chip_get_core(sc, BWFM_AGENT_CORE_ARM_CM3) != NULL) { 1266 bwfm_chip_cm3_set_passive(sc); 1267 return; 1268 } 1269 } 1270 1271 int 1272 bwfm_chip_cr4_set_active(struct bwfm_softc *sc, uint32_t rstvec) 1273 { 1274 struct bwfm_core *core; 1275 1276 sc->sc_buscore_ops->bc_activate(sc, rstvec); 1277 core = bwfm_chip_get_core(sc, BWFM_AGENT_CORE_ARM_CR4); 1278 sc->sc_chip.ch_core_reset(sc, core, 1279 BWFM_AGENT_IOCTL_ARMCR4_CPUHALT, 0, 0); 1280 1281 return 0; 1282 } 1283 1284 void 1285 bwfm_chip_cr4_set_passive(struct bwfm_softc *sc) 1286 { 1287 struct bwfm_core *core; 1288 uint32_t val; 1289 1290 core = bwfm_chip_get_core(sc, BWFM_AGENT_CORE_ARM_CR4); 1291 val = sc->sc_buscore_ops->bc_read(sc, 1292 core->co_wrapbase + BWFM_AGENT_IOCTL); 1293 sc->sc_chip.ch_core_reset(sc, core, 1294 val & BWFM_AGENT_IOCTL_ARMCR4_CPUHALT, 1295 BWFM_AGENT_IOCTL_ARMCR4_CPUHALT, 1296 BWFM_AGENT_IOCTL_ARMCR4_CPUHALT); 1297 1298 core = bwfm_chip_get_core(sc, BWFM_AGENT_CORE_80211); 1299 sc->sc_chip.ch_core_reset(sc, core, BWFM_AGENT_D11_IOCTL_PHYRESET | 1300 BWFM_AGENT_D11_IOCTL_PHYCLOCKEN, BWFM_AGENT_D11_IOCTL_PHYCLOCKEN, 1301 BWFM_AGENT_D11_IOCTL_PHYCLOCKEN); 1302 } 1303 1304 int 1305 bwfm_chip_ca7_set_active(struct bwfm_softc *sc, uint32_t rstvec) 1306 { 1307 struct bwfm_core *core; 1308 1309 sc->sc_buscore_ops->bc_activate(sc, rstvec); 1310 core = bwfm_chip_get_core(sc, BWFM_AGENT_CORE_ARM_CA7); 1311 sc->sc_chip.ch_core_reset(sc, core, 1312 BWFM_AGENT_IOCTL_ARMCR4_CPUHALT, 0, 0); 1313 1314 return 0; 1315 } 1316 1317 void 1318 bwfm_chip_ca7_set_passive(struct bwfm_softc *sc) 1319 { 1320 struct bwfm_core *core; 1321 uint32_t val; 1322 1323 core = bwfm_chip_get_core(sc, BWFM_AGENT_CORE_ARM_CA7); 1324 val = sc->sc_buscore_ops->bc_read(sc, 1325 core->co_wrapbase + BWFM_AGENT_IOCTL); 1326 sc->sc_chip.ch_core_reset(sc, core, 1327 val & BWFM_AGENT_IOCTL_ARMCR4_CPUHALT, 1328 BWFM_AGENT_IOCTL_ARMCR4_CPUHALT, 1329 BWFM_AGENT_IOCTL_ARMCR4_CPUHALT); 1330 1331 core = bwfm_chip_get_core(sc, BWFM_AGENT_CORE_80211); 1332 sc->sc_chip.ch_core_reset(sc, core, BWFM_AGENT_D11_IOCTL_PHYRESET | 1333 BWFM_AGENT_D11_IOCTL_PHYCLOCKEN, BWFM_AGENT_D11_IOCTL_PHYCLOCKEN, 1334 BWFM_AGENT_D11_IOCTL_PHYCLOCKEN); 1335 } 1336 1337 int 1338 bwfm_chip_cm3_set_active(struct bwfm_softc *sc) 1339 { 1340 struct bwfm_core *core; 1341 1342 core = bwfm_chip_get_core(sc, BWFM_AGENT_INTERNAL_MEM); 1343 if (!sc->sc_chip.ch_core_isup(sc, core)) 1344 return 1; 1345 1346 sc->sc_buscore_ops->bc_activate(sc, 0); 1347 1348 core = bwfm_chip_get_core(sc, BWFM_AGENT_CORE_ARM_CM3); 1349 sc->sc_chip.ch_core_reset(sc, core, 0, 0, 0); 1350 1351 return 0; 1352 } 1353 1354 void 1355 bwfm_chip_cm3_set_passive(struct bwfm_softc *sc) 1356 { 1357 struct bwfm_core *core; 1358 1359 core = bwfm_chip_get_core(sc, BWFM_AGENT_CORE_ARM_CM3); 1360 sc->sc_chip.ch_core_disable(sc, core, 0, 0); 1361 core = bwfm_chip_get_core(sc, BWFM_AGENT_CORE_80211); 1362 sc->sc_chip.ch_core_reset(sc, core, BWFM_AGENT_D11_IOCTL_PHYRESET | 1363 BWFM_AGENT_D11_IOCTL_PHYCLOCKEN, BWFM_AGENT_D11_IOCTL_PHYCLOCKEN, 1364 BWFM_AGENT_D11_IOCTL_PHYCLOCKEN); 1365 core = bwfm_chip_get_core(sc, BWFM_AGENT_INTERNAL_MEM); 1366 sc->sc_chip.ch_core_reset(sc, core, 0, 0, 0); 1367 1368 if (sc->sc_chip.ch_chip == BRCM_CC_43430_CHIP_ID) { 1369 sc->sc_buscore_ops->bc_write(sc, 1370 core->co_base + BWFM_SOCRAM_BANKIDX, 3); 1371 sc->sc_buscore_ops->bc_write(sc, 1372 core->co_base + BWFM_SOCRAM_BANKPDA, 0); 1373 } 1374 } 1375 1376 int 1377 bwfm_chip_sr_capable(struct bwfm_softc *sc) 1378 { 1379 struct bwfm_core *core; 1380 uint32_t reg; 1381 1382 if (sc->sc_chip.ch_pmurev < 17) 1383 return 0; 1384 1385 switch (sc->sc_chip.ch_chip) { 1386 case BRCM_CC_4345_CHIP_ID: 1387 case BRCM_CC_4354_CHIP_ID: 1388 case BRCM_CC_4356_CHIP_ID: 1389 core = bwfm_chip_get_pmu(sc); 1390 sc->sc_buscore_ops->bc_write(sc, core->co_base + 1391 BWFM_CHIP_REG_CHIPCONTROL_ADDR, 3); 1392 reg = sc->sc_buscore_ops->bc_read(sc, core->co_base + 1393 BWFM_CHIP_REG_CHIPCONTROL_DATA); 1394 return (reg & (1 << 2)) != 0; 1395 case BRCM_CC_43241_CHIP_ID: 1396 case BRCM_CC_4335_CHIP_ID: 1397 case BRCM_CC_4339_CHIP_ID: 1398 core = bwfm_chip_get_pmu(sc); 1399 sc->sc_buscore_ops->bc_write(sc, core->co_base + 1400 BWFM_CHIP_REG_CHIPCONTROL_ADDR, 3); 1401 reg = sc->sc_buscore_ops->bc_read(sc, core->co_base + 1402 BWFM_CHIP_REG_CHIPCONTROL_DATA); 1403 return reg != 0; 1404 case BRCM_CC_43430_CHIP_ID: 1405 core = bwfm_chip_get_core(sc, BWFM_AGENT_CORE_CHIPCOMMON); 1406 reg = sc->sc_buscore_ops->bc_read(sc, core->co_base + 1407 BWFM_CHIP_REG_SR_CONTROL1); 1408 return reg != 0; 1409 case BRCM_CC_4378_CHIP_ID: 1410 return 0; 1411 default: 1412 core = bwfm_chip_get_pmu(sc); 1413 reg = sc->sc_buscore_ops->bc_read(sc, core->co_base + 1414 BWFM_CHIP_REG_PMUCAPABILITIES_EXT); 1415 if ((reg & BWFM_CHIP_REG_PMUCAPABILITIES_SR_SUPP) == 0) 1416 return 0; 1417 1418 reg = sc->sc_buscore_ops->bc_read(sc, core->co_base + 1419 BWFM_CHIP_REG_RETENTION_CTL); 1420 return (reg & (BWFM_CHIP_REG_RETENTION_CTL_MACPHY_DIS | 1421 BWFM_CHIP_REG_RETENTION_CTL_LOGIC_DIS)) == 0; 1422 } 1423 } 1424 1425 /* RAM size helpers */ 1426 void 1427 bwfm_chip_socram_ramsize(struct bwfm_softc *sc, struct bwfm_core *core) 1428 { 1429 uint32_t coreinfo, nb, lss, banksize, bankinfo; 1430 uint32_t ramsize = 0, srsize = 0; 1431 int i; 1432 1433 if (!sc->sc_chip.ch_core_isup(sc, core)) 1434 sc->sc_chip.ch_core_reset(sc, core, 0, 0, 0); 1435 1436 coreinfo = sc->sc_buscore_ops->bc_read(sc, 1437 core->co_base + BWFM_SOCRAM_COREINFO); 1438 nb = (coreinfo & BWFM_SOCRAM_COREINFO_SRNB_MASK) 1439 >> BWFM_SOCRAM_COREINFO_SRNB_SHIFT; 1440 1441 if (core->co_rev <= 7 || core->co_rev == 12) { 1442 banksize = coreinfo & BWFM_SOCRAM_COREINFO_SRBSZ_MASK; 1443 lss = (coreinfo & BWFM_SOCRAM_COREINFO_LSS_MASK) 1444 >> BWFM_SOCRAM_COREINFO_LSS_SHIFT; 1445 if (lss != 0) 1446 nb--; 1447 ramsize = nb * (1 << (banksize + BWFM_SOCRAM_COREINFO_SRBSZ_BASE)); 1448 if (lss != 0) 1449 ramsize += (1 << ((lss - 1) + BWFM_SOCRAM_COREINFO_SRBSZ_BASE)); 1450 } else { 1451 for (i = 0; i < nb; i++) { 1452 sc->sc_buscore_ops->bc_write(sc, 1453 core->co_base + BWFM_SOCRAM_BANKIDX, 1454 (BWFM_SOCRAM_BANKIDX_MEMTYPE_RAM << 1455 BWFM_SOCRAM_BANKIDX_MEMTYPE_SHIFT) | i); 1456 bankinfo = sc->sc_buscore_ops->bc_read(sc, 1457 core->co_base + BWFM_SOCRAM_BANKINFO); 1458 banksize = ((bankinfo & BWFM_SOCRAM_BANKINFO_SZMASK) + 1) 1459 * BWFM_SOCRAM_BANKINFO_SZBASE; 1460 ramsize += banksize; 1461 if (bankinfo & BWFM_SOCRAM_BANKINFO_RETNTRAM_MASK) 1462 srsize += banksize; 1463 } 1464 } 1465 1466 switch (sc->sc_chip.ch_chip) { 1467 case BRCM_CC_4334_CHIP_ID: 1468 if (sc->sc_chip.ch_chiprev < 2) 1469 srsize = 32 * 1024; 1470 break; 1471 case BRCM_CC_43430_CHIP_ID: 1472 srsize = 64 * 1024; 1473 break; 1474 default: 1475 break; 1476 } 1477 1478 sc->sc_chip.ch_ramsize = ramsize; 1479 sc->sc_chip.ch_srsize = srsize; 1480 } 1481 1482 void 1483 bwfm_chip_sysmem_ramsize(struct bwfm_softc *sc, struct bwfm_core *core) 1484 { 1485 uint32_t coreinfo, nb, banksize, bankinfo; 1486 uint32_t ramsize = 0; 1487 int i; 1488 1489 if (!sc->sc_chip.ch_core_isup(sc, core)) 1490 sc->sc_chip.ch_core_reset(sc, core, 0, 0, 0); 1491 1492 coreinfo = sc->sc_buscore_ops->bc_read(sc, 1493 core->co_base + BWFM_SOCRAM_COREINFO); 1494 nb = (coreinfo & BWFM_SOCRAM_COREINFO_SRNB_MASK) 1495 >> BWFM_SOCRAM_COREINFO_SRNB_SHIFT; 1496 1497 for (i = 0; i < nb; i++) { 1498 sc->sc_buscore_ops->bc_write(sc, 1499 core->co_base + BWFM_SOCRAM_BANKIDX, 1500 (BWFM_SOCRAM_BANKIDX_MEMTYPE_RAM << 1501 BWFM_SOCRAM_BANKIDX_MEMTYPE_SHIFT) | i); 1502 bankinfo = sc->sc_buscore_ops->bc_read(sc, 1503 core->co_base + BWFM_SOCRAM_BANKINFO); 1504 banksize = ((bankinfo & BWFM_SOCRAM_BANKINFO_SZMASK) + 1) 1505 * BWFM_SOCRAM_BANKINFO_SZBASE; 1506 ramsize += banksize; 1507 } 1508 1509 sc->sc_chip.ch_ramsize = ramsize; 1510 } 1511 1512 void 1513 bwfm_chip_tcm_ramsize(struct bwfm_softc *sc, struct bwfm_core *core) 1514 { 1515 uint32_t cap, nab, nbb, totb, bxinfo, ramsize = 0; 1516 int i; 1517 1518 cap = sc->sc_buscore_ops->bc_read(sc, core->co_base + BWFM_ARMCR4_CAP); 1519 nab = (cap & BWFM_ARMCR4_CAP_TCBANB_MASK) >> BWFM_ARMCR4_CAP_TCBANB_SHIFT; 1520 nbb = (cap & BWFM_ARMCR4_CAP_TCBBNB_MASK) >> BWFM_ARMCR4_CAP_TCBBNB_SHIFT; 1521 totb = nab + nbb; 1522 1523 for (i = 0; i < totb; i++) { 1524 sc->sc_buscore_ops->bc_write(sc, 1525 core->co_base + BWFM_ARMCR4_BANKIDX, i); 1526 bxinfo = sc->sc_buscore_ops->bc_read(sc, 1527 core->co_base + BWFM_ARMCR4_BANKINFO); 1528 ramsize += ((bxinfo & BWFM_ARMCR4_BANKINFO_BSZ_MASK) + 1) * 1529 BWFM_ARMCR4_BANKINFO_BSZ_MULT; 1530 } 1531 1532 sc->sc_chip.ch_ramsize = ramsize; 1533 } 1534 1535 void 1536 bwfm_chip_tcm_rambase(struct bwfm_softc *sc) 1537 { 1538 switch (sc->sc_chip.ch_chip) { 1539 case BRCM_CC_4345_CHIP_ID: 1540 sc->sc_chip.ch_rambase = 0x198000; 1541 break; 1542 case BRCM_CC_4335_CHIP_ID: 1543 case BRCM_CC_4339_CHIP_ID: 1544 case BRCM_CC_4350_CHIP_ID: 1545 case BRCM_CC_4354_CHIP_ID: 1546 case BRCM_CC_4356_CHIP_ID: 1547 case BRCM_CC_43567_CHIP_ID: 1548 case BRCM_CC_43569_CHIP_ID: 1549 case BRCM_CC_43570_CHIP_ID: 1550 case BRCM_CC_4358_CHIP_ID: 1551 case BRCM_CC_43602_CHIP_ID: 1552 case BRCM_CC_4371_CHIP_ID: 1553 sc->sc_chip.ch_rambase = 0x180000; 1554 break; 1555 case BRCM_CC_4359_CHIP_ID: 1556 if (sc->sc_chip.ch_chiprev < 9) 1557 sc->sc_chip.ch_rambase = 0x180000; 1558 else 1559 sc->sc_chip.ch_rambase = 0x160000; 1560 break; 1561 case BRCM_CC_43465_CHIP_ID: 1562 case BRCM_CC_43525_CHIP_ID: 1563 case BRCM_CC_4365_CHIP_ID: 1564 case BRCM_CC_4366_CHIP_ID: 1565 sc->sc_chip.ch_rambase = 0x200000; 1566 break; 1567 case CY_CC_4373_CHIP_ID: 1568 sc->sc_chip.ch_rambase = 0x160000; 1569 break; 1570 case BRCM_CC_4378_CHIP_ID: 1571 sc->sc_chip.ch_rambase = 0x352000; 1572 break; 1573 default: 1574 printf("%s: unknown chip: %d\n", DEVNAME(sc), 1575 sc->sc_chip.ch_chip); 1576 break; 1577 } 1578 } 1579 1580 /* BCDC protocol implementation */ 1581 int 1582 bwfm_proto_bcdc_query_dcmd(struct bwfm_softc *sc, int ifidx, 1583 int cmd, char *buf, size_t *len) 1584 { 1585 struct bwfm_proto_bcdc_dcmd *dcmd; 1586 size_t size = sizeof(dcmd->hdr) + *len; 1587 int ret = 1, reqid; 1588 1589 reqid = sc->sc_bcdc_reqid++; 1590 1591 if (*len > sizeof(dcmd->buf)) 1592 return ret; 1593 1594 dcmd = malloc(size, M_TEMP, M_WAITOK | M_ZERO); 1595 dcmd->hdr.cmd = htole32(cmd); 1596 dcmd->hdr.len = htole32(*len); 1597 dcmd->hdr.flags |= BWFM_BCDC_DCMD_GET; 1598 dcmd->hdr.flags |= BWFM_BCDC_DCMD_ID_SET(reqid); 1599 dcmd->hdr.flags |= BWFM_BCDC_DCMD_IF_SET(ifidx); 1600 dcmd->hdr.flags = htole32(dcmd->hdr.flags); 1601 memcpy(&dcmd->buf, buf, *len); 1602 1603 if (bwfm_proto_bcdc_txctl(sc, reqid, (char *)dcmd, &size)) { 1604 DPRINTF(("%s: tx failed\n", DEVNAME(sc))); 1605 return ret; 1606 } 1607 1608 if (buf) { 1609 *len = min(*len, size); 1610 memcpy(buf, dcmd->buf, *len); 1611 } 1612 1613 if (dcmd->hdr.flags & BWFM_BCDC_DCMD_ERROR) 1614 ret = dcmd->hdr.status; 1615 else 1616 ret = 0; 1617 free(dcmd, M_TEMP, size); 1618 return ret; 1619 } 1620 1621 int 1622 bwfm_proto_bcdc_set_dcmd(struct bwfm_softc *sc, int ifidx, 1623 int cmd, char *buf, size_t len) 1624 { 1625 struct bwfm_proto_bcdc_dcmd *dcmd; 1626 size_t size = sizeof(dcmd->hdr) + len; 1627 int ret = 1, reqid; 1628 1629 reqid = sc->sc_bcdc_reqid++; 1630 1631 if (len > sizeof(dcmd->buf)) 1632 return ret; 1633 1634 dcmd = malloc(size, M_TEMP, M_WAITOK | M_ZERO); 1635 dcmd->hdr.cmd = htole32(cmd); 1636 dcmd->hdr.len = htole32(len); 1637 dcmd->hdr.flags |= BWFM_BCDC_DCMD_SET; 1638 dcmd->hdr.flags |= BWFM_BCDC_DCMD_ID_SET(reqid); 1639 dcmd->hdr.flags |= BWFM_BCDC_DCMD_IF_SET(ifidx); 1640 dcmd->hdr.flags = htole32(dcmd->hdr.flags); 1641 memcpy(&dcmd->buf, buf, len); 1642 1643 if (bwfm_proto_bcdc_txctl(sc, reqid, (char *)dcmd, &size)) { 1644 DPRINTF(("%s: txctl failed\n", DEVNAME(sc))); 1645 return ret; 1646 } 1647 1648 if (dcmd->hdr.flags & BWFM_BCDC_DCMD_ERROR) 1649 ret = dcmd->hdr.status; 1650 else 1651 ret = 0; 1652 free(dcmd, M_TEMP, size); 1653 return ret; 1654 } 1655 1656 int 1657 bwfm_proto_bcdc_txctl(struct bwfm_softc *sc, int reqid, char *buf, size_t *len) 1658 { 1659 struct bwfm_proto_bcdc_ctl *ctl, *tmp; 1660 int timeout = 0; 1661 1662 ctl = malloc(sizeof(*ctl), M_TEMP, M_WAITOK|M_ZERO); 1663 ctl->reqid = reqid; 1664 ctl->buf = buf; 1665 ctl->len = *len; 1666 1667 if (sc->sc_bus_ops->bs_txctl(sc, ctl)) { 1668 DPRINTF(("%s: tx failed\n", DEVNAME(sc))); 1669 return 1; 1670 } 1671 1672 if (tsleep_nsec(ctl, PWAIT, "bwfm", SEC_TO_NSEC(1))) 1673 timeout = 1; 1674 1675 TAILQ_FOREACH_SAFE(ctl, &sc->sc_bcdc_rxctlq, next, tmp) { 1676 if (ctl->reqid != reqid) 1677 continue; 1678 if (ctl->done) { 1679 TAILQ_REMOVE(&sc->sc_bcdc_rxctlq, ctl, next); 1680 *len = ctl->len; 1681 free(ctl, M_TEMP, sizeof(*ctl)); 1682 return 0; 1683 } 1684 if (timeout) { 1685 TAILQ_REMOVE(&sc->sc_bcdc_rxctlq, ctl, next); 1686 DPRINTF(("%s: timeout waiting for txctl response\n", 1687 DEVNAME(sc))); 1688 free(ctl->buf, M_TEMP, ctl->len); 1689 free(ctl, M_TEMP, sizeof(*ctl)); 1690 return 1; 1691 } 1692 break; 1693 } 1694 1695 DPRINTF(("%s: did%s find txctl metadata (timeout %d)\n", 1696 DEVNAME(sc), ctl == NULL ? " not": "", timeout)); 1697 return 1; 1698 } 1699 1700 void 1701 bwfm_proto_bcdc_rxctl(struct bwfm_softc *sc, char *buf, size_t len) 1702 { 1703 struct bwfm_proto_bcdc_dcmd *dcmd; 1704 struct bwfm_proto_bcdc_ctl *ctl, *tmp; 1705 1706 if (len < sizeof(dcmd->hdr)) 1707 return; 1708 1709 dcmd = (struct bwfm_proto_bcdc_dcmd *)buf; 1710 dcmd->hdr.cmd = letoh32(dcmd->hdr.cmd); 1711 dcmd->hdr.len = letoh32(dcmd->hdr.len); 1712 dcmd->hdr.flags = letoh32(dcmd->hdr.flags); 1713 dcmd->hdr.status = letoh32(dcmd->hdr.status); 1714 1715 TAILQ_FOREACH_SAFE(ctl, &sc->sc_bcdc_rxctlq, next, tmp) { 1716 if (ctl->reqid != BWFM_BCDC_DCMD_ID_GET(dcmd->hdr.flags)) 1717 continue; 1718 if (ctl->len != len) { 1719 free(ctl->buf, M_TEMP, ctl->len); 1720 free(ctl, M_TEMP, sizeof(*ctl)); 1721 return; 1722 } 1723 memcpy(ctl->buf, buf, len); 1724 ctl->done = 1; 1725 wakeup(ctl); 1726 return; 1727 } 1728 } 1729 1730 void 1731 bwfm_proto_bcdc_rx(struct bwfm_softc *sc, struct mbuf *m, struct mbuf_list *ml) 1732 { 1733 struct bwfm_proto_bcdc_hdr *hdr; 1734 1735 hdr = mtod(m, struct bwfm_proto_bcdc_hdr *); 1736 if (m->m_len < sizeof(*hdr)) { 1737 m_freem(m); 1738 return; 1739 } 1740 if (m->m_len < sizeof(*hdr) + (hdr->data_offset << 2)) { 1741 m_freem(m); 1742 return; 1743 } 1744 m_adj(m, sizeof(*hdr) + (hdr->data_offset << 2)); 1745 1746 bwfm_rx(sc, m, ml); 1747 } 1748 1749 /* FW Variable code */ 1750 int 1751 bwfm_fwvar_cmd_get_data(struct bwfm_softc *sc, int cmd, void *data, size_t len) 1752 { 1753 return sc->sc_proto_ops->proto_query_dcmd(sc, 0, cmd, data, &len); 1754 } 1755 1756 int 1757 bwfm_fwvar_cmd_set_data(struct bwfm_softc *sc, int cmd, void *data, size_t len) 1758 { 1759 return sc->sc_proto_ops->proto_set_dcmd(sc, 0, cmd, data, len); 1760 } 1761 1762 int 1763 bwfm_fwvar_cmd_get_int(struct bwfm_softc *sc, int cmd, uint32_t *data) 1764 { 1765 int ret; 1766 ret = bwfm_fwvar_cmd_get_data(sc, cmd, data, sizeof(*data)); 1767 *data = letoh32(*data); 1768 return ret; 1769 } 1770 1771 int 1772 bwfm_fwvar_cmd_set_int(struct bwfm_softc *sc, int cmd, uint32_t data) 1773 { 1774 data = htole32(data); 1775 return bwfm_fwvar_cmd_set_data(sc, cmd, &data, sizeof(data)); 1776 } 1777 1778 int 1779 bwfm_fwvar_var_get_data(struct bwfm_softc *sc, char *name, void *data, size_t len) 1780 { 1781 char *buf; 1782 int ret; 1783 1784 buf = malloc(strlen(name) + 1 + len, M_TEMP, M_WAITOK); 1785 memcpy(buf, name, strlen(name) + 1); 1786 memcpy(buf + strlen(name) + 1, data, len); 1787 ret = bwfm_fwvar_cmd_get_data(sc, BWFM_C_GET_VAR, 1788 buf, strlen(name) + 1 + len); 1789 memcpy(data, buf, len); 1790 free(buf, M_TEMP, strlen(name) + 1 + len); 1791 return ret; 1792 } 1793 1794 int 1795 bwfm_fwvar_var_set_data(struct bwfm_softc *sc, char *name, void *data, size_t len) 1796 { 1797 char *buf; 1798 int ret; 1799 1800 buf = malloc(strlen(name) + 1 + len, M_TEMP, M_WAITOK); 1801 memcpy(buf, name, strlen(name) + 1); 1802 memcpy(buf + strlen(name) + 1, data, len); 1803 ret = bwfm_fwvar_cmd_set_data(sc, BWFM_C_SET_VAR, 1804 buf, strlen(name) + 1 + len); 1805 free(buf, M_TEMP, strlen(name) + 1 + len); 1806 return ret; 1807 } 1808 1809 int 1810 bwfm_fwvar_var_get_int(struct bwfm_softc *sc, char *name, uint32_t *data) 1811 { 1812 int ret; 1813 ret = bwfm_fwvar_var_get_data(sc, name, data, sizeof(*data)); 1814 *data = letoh32(*data); 1815 return ret; 1816 } 1817 1818 int 1819 bwfm_fwvar_var_set_int(struct bwfm_softc *sc, char *name, uint32_t data) 1820 { 1821 data = htole32(data); 1822 return bwfm_fwvar_var_set_data(sc, name, &data, sizeof(data)); 1823 } 1824 1825 /* Channel parameters */ 1826 uint32_t 1827 bwfm_chan2spec(struct bwfm_softc *sc, struct ieee80211_channel *c) 1828 { 1829 if (sc->sc_io_type == BWFM_IO_TYPE_D11N) 1830 return bwfm_chan2spec_d11n(sc, c); 1831 else 1832 return bwfm_chan2spec_d11ac(sc, c); 1833 } 1834 1835 uint32_t 1836 bwfm_chan2spec_d11n(struct bwfm_softc *sc, struct ieee80211_channel *c) 1837 { 1838 uint32_t chanspec; 1839 1840 chanspec = ieee80211_mhz2ieee(c->ic_freq, 0) & BWFM_CHANSPEC_CHAN_MASK; 1841 chanspec |= BWFM_CHANSPEC_D11N_SB_N; 1842 chanspec |= BWFM_CHANSPEC_D11N_BW_20; 1843 if (IEEE80211_IS_CHAN_2GHZ(c)) 1844 chanspec |= BWFM_CHANSPEC_D11N_BND_2G; 1845 if (IEEE80211_IS_CHAN_5GHZ(c)) 1846 chanspec |= BWFM_CHANSPEC_D11N_BND_5G; 1847 1848 return chanspec; 1849 } 1850 1851 uint32_t 1852 bwfm_chan2spec_d11ac(struct bwfm_softc *sc, struct ieee80211_channel *c) 1853 { 1854 uint32_t chanspec; 1855 1856 chanspec = ieee80211_mhz2ieee(c->ic_freq, 0) & BWFM_CHANSPEC_CHAN_MASK; 1857 chanspec |= BWFM_CHANSPEC_D11AC_SB_LLL; 1858 chanspec |= BWFM_CHANSPEC_D11AC_BW_20; 1859 if (IEEE80211_IS_CHAN_2GHZ(c)) 1860 chanspec |= BWFM_CHANSPEC_D11AC_BND_2G; 1861 if (IEEE80211_IS_CHAN_5GHZ(c)) 1862 chanspec |= BWFM_CHANSPEC_D11AC_BND_5G; 1863 1864 return chanspec; 1865 } 1866 1867 uint32_t 1868 bwfm_spec2chan(struct bwfm_softc *sc, uint32_t chanspec) 1869 { 1870 if (sc->sc_io_type == BWFM_IO_TYPE_D11N) 1871 return bwfm_spec2chan_d11n(sc, chanspec); 1872 else 1873 return bwfm_spec2chan_d11ac(sc, chanspec); 1874 } 1875 1876 uint32_t 1877 bwfm_spec2chan_d11n(struct bwfm_softc *sc, uint32_t chanspec) 1878 { 1879 uint32_t chanidx; 1880 1881 chanidx = chanspec & BWFM_CHANSPEC_CHAN_MASK; 1882 1883 switch (chanspec & BWFM_CHANSPEC_D11N_BW_MASK) { 1884 case BWFM_CHANSPEC_D11N_BW_40: 1885 switch (chanspec & BWFM_CHANSPEC_D11N_SB_MASK) { 1886 case BWFM_CHANSPEC_D11N_SB_L: 1887 chanidx -= 2; 1888 break; 1889 case BWFM_CHANSPEC_D11N_SB_U: 1890 chanidx += 2; 1891 break; 1892 default: 1893 break; 1894 } 1895 break; 1896 default: 1897 break; 1898 } 1899 1900 return chanidx; 1901 } 1902 1903 uint32_t 1904 bwfm_spec2chan_d11ac(struct bwfm_softc *sc, uint32_t chanspec) 1905 { 1906 uint32_t chanidx; 1907 1908 chanidx = chanspec & BWFM_CHANSPEC_CHAN_MASK; 1909 1910 switch (chanspec & BWFM_CHANSPEC_D11AC_BW_MASK) { 1911 case BWFM_CHANSPEC_D11AC_BW_40: 1912 switch (chanspec & BWFM_CHANSPEC_D11AC_SB_MASK) { 1913 case BWFM_CHANSPEC_D11AC_SB_LLL: 1914 chanidx -= 2; 1915 break; 1916 case BWFM_CHANSPEC_D11AC_SB_LLU: 1917 chanidx += 2; 1918 break; 1919 default: 1920 break; 1921 } 1922 break; 1923 case BWFM_CHANSPEC_D11AC_BW_80: 1924 switch (chanspec & BWFM_CHANSPEC_D11AC_SB_MASK) { 1925 case BWFM_CHANSPEC_D11AC_SB_LLL: 1926 chanidx -= 6; 1927 break; 1928 case BWFM_CHANSPEC_D11AC_SB_LLU: 1929 chanidx -= 2; 1930 break; 1931 case BWFM_CHANSPEC_D11AC_SB_LUL: 1932 chanidx += 2; 1933 break; 1934 case BWFM_CHANSPEC_D11AC_SB_LUU: 1935 chanidx += 6; 1936 break; 1937 default: 1938 break; 1939 } 1940 break; 1941 default: 1942 break; 1943 } 1944 1945 return chanidx; 1946 } 1947 1948 /* 802.11 code */ 1949 void 1950 bwfm_connect(struct bwfm_softc *sc) 1951 { 1952 struct ieee80211com *ic = &sc->sc_ic; 1953 struct bwfm_ext_join_params *params; 1954 uint8_t buf[64]; /* XXX max WPA/RSN/WMM IE length */ 1955 uint8_t *frm; 1956 1957 /* 1958 * OPEN: Open or WPA/WPA2 on newer Chips/Firmware. 1959 * SHARED KEY: WEP. 1960 * AUTO: Automatic, probably for older Chips/Firmware. 1961 */ 1962 if (ic->ic_flags & IEEE80211_F_RSNON) { 1963 uint32_t wsec = 0; 1964 uint32_t wpa = 0; 1965 1966 /* tell firmware to add WPA/RSN IE to (re)assoc request */ 1967 if (ic->ic_bss->ni_rsnprotos == IEEE80211_PROTO_RSN) 1968 frm = ieee80211_add_rsn(buf, ic, ic->ic_bss); 1969 else 1970 frm = ieee80211_add_wpa(buf, ic, ic->ic_bss); 1971 bwfm_fwvar_var_set_data(sc, "wpaie", buf, frm - buf); 1972 1973 if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA) { 1974 if (ic->ic_rsnakms & IEEE80211_AKM_PSK) 1975 wpa |= BWFM_WPA_AUTH_WPA_PSK; 1976 if (ic->ic_rsnakms & IEEE80211_AKM_8021X) 1977 wpa |= BWFM_WPA_AUTH_WPA_UNSPECIFIED; 1978 } 1979 if (ic->ic_rsnprotos & IEEE80211_PROTO_RSN) { 1980 if (ic->ic_rsnakms & IEEE80211_AKM_PSK) 1981 wpa |= BWFM_WPA_AUTH_WPA2_PSK; 1982 if (ic->ic_rsnakms & IEEE80211_AKM_SHA256_PSK) 1983 wpa |= BWFM_WPA_AUTH_WPA2_PSK_SHA256; 1984 if (ic->ic_rsnakms & IEEE80211_AKM_8021X) 1985 wpa |= BWFM_WPA_AUTH_WPA2_UNSPECIFIED; 1986 if (ic->ic_rsnakms & IEEE80211_AKM_SHA256_8021X) 1987 wpa |= BWFM_WPA_AUTH_WPA2_1X_SHA256; 1988 } 1989 if (ic->ic_rsnciphers & IEEE80211_WPA_CIPHER_TKIP || 1990 ic->ic_rsngroupcipher & IEEE80211_WPA_CIPHER_TKIP) 1991 wsec |= BWFM_WSEC_TKIP; 1992 if (ic->ic_rsnciphers & IEEE80211_WPA_CIPHER_CCMP || 1993 ic->ic_rsngroupcipher & IEEE80211_WPA_CIPHER_CCMP) 1994 wsec |= BWFM_WSEC_AES; 1995 1996 bwfm_fwvar_var_set_int(sc, "wpa_auth", wpa); 1997 bwfm_fwvar_var_set_int(sc, "wsec", wsec); 1998 } else { 1999 bwfm_fwvar_var_set_int(sc, "wpa_auth", BWFM_WPA_AUTH_DISABLED); 2000 bwfm_fwvar_var_set_int(sc, "wsec", BWFM_WSEC_NONE); 2001 } 2002 bwfm_fwvar_var_set_int(sc, "auth", BWFM_AUTH_OPEN); 2003 bwfm_fwvar_var_set_int(sc, "mfp", BWFM_MFP_NONE); 2004 2005 if (ic->ic_des_esslen && ic->ic_des_esslen <= BWFM_MAX_SSID_LEN) { 2006 params = malloc(sizeof(*params), M_TEMP, M_WAITOK | M_ZERO); 2007 memcpy(params->ssid.ssid, ic->ic_des_essid, ic->ic_des_esslen); 2008 params->ssid.len = htole32(ic->ic_des_esslen); 2009 memcpy(params->assoc.bssid, ic->ic_bss->ni_bssid, 2010 sizeof(params->assoc.bssid)); 2011 params->scan.scan_type = -1; 2012 params->scan.nprobes = htole32(-1); 2013 params->scan.active_time = htole32(-1); 2014 params->scan.passive_time = htole32(-1); 2015 params->scan.home_time = htole32(-1); 2016 if (bwfm_fwvar_var_set_data(sc, "join", params, sizeof(*params))) { 2017 struct bwfm_join_params join; 2018 memset(&join, 0, sizeof(join)); 2019 memcpy(join.ssid.ssid, ic->ic_des_essid, 2020 ic->ic_des_esslen); 2021 join.ssid.len = htole32(ic->ic_des_esslen); 2022 memcpy(join.assoc.bssid, ic->ic_bss->ni_bssid, 2023 sizeof(join.assoc.bssid)); 2024 bwfm_fwvar_cmd_set_data(sc, BWFM_C_SET_SSID, &join, 2025 sizeof(join)); 2026 } 2027 free(params, M_TEMP, sizeof(*params)); 2028 } 2029 } 2030 2031 #ifndef IEEE80211_STA_ONLY 2032 void 2033 bwfm_hostap(struct bwfm_softc *sc) 2034 { 2035 struct ieee80211com *ic = &sc->sc_ic; 2036 struct ieee80211_node *ni = ic->ic_bss; 2037 struct bwfm_join_params join; 2038 2039 /* 2040 * OPEN: Open or WPA/WPA2 on newer Chips/Firmware. 2041 * SHARED KEY: WEP. 2042 * AUTO: Automatic, probably for older Chips/Firmware. 2043 */ 2044 if (ic->ic_flags & IEEE80211_F_RSNON) { 2045 uint32_t wsec = 0; 2046 uint32_t wpa = 0; 2047 2048 /* TODO: Turn off if replay counter set */ 2049 if (ni->ni_rsnprotos & IEEE80211_PROTO_RSN) 2050 bwfm_fwvar_var_set_int(sc, "wme_bss_disable", 1); 2051 2052 if (ni->ni_rsnprotos & IEEE80211_PROTO_WPA) { 2053 if (ni->ni_rsnakms & IEEE80211_AKM_PSK) 2054 wpa |= BWFM_WPA_AUTH_WPA_PSK; 2055 if (ni->ni_rsnakms & IEEE80211_AKM_8021X) 2056 wpa |= BWFM_WPA_AUTH_WPA_UNSPECIFIED; 2057 } 2058 if (ni->ni_rsnprotos & IEEE80211_PROTO_RSN) { 2059 if (ni->ni_rsnakms & IEEE80211_AKM_PSK) 2060 wpa |= BWFM_WPA_AUTH_WPA2_PSK; 2061 if (ni->ni_rsnakms & IEEE80211_AKM_SHA256_PSK) 2062 wpa |= BWFM_WPA_AUTH_WPA2_PSK_SHA256; 2063 if (ni->ni_rsnakms & IEEE80211_AKM_8021X) 2064 wpa |= BWFM_WPA_AUTH_WPA2_UNSPECIFIED; 2065 if (ni->ni_rsnakms & IEEE80211_AKM_SHA256_8021X) 2066 wpa |= BWFM_WPA_AUTH_WPA2_1X_SHA256; 2067 } 2068 if (ni->ni_rsnciphers & IEEE80211_WPA_CIPHER_TKIP || 2069 ni->ni_rsngroupcipher & IEEE80211_WPA_CIPHER_TKIP) 2070 wsec |= BWFM_WSEC_TKIP; 2071 if (ni->ni_rsnciphers & IEEE80211_WPA_CIPHER_CCMP || 2072 ni->ni_rsngroupcipher & IEEE80211_WPA_CIPHER_CCMP) 2073 wsec |= BWFM_WSEC_AES; 2074 2075 bwfm_fwvar_var_set_int(sc, "wpa_auth", wpa); 2076 bwfm_fwvar_var_set_int(sc, "wsec", wsec); 2077 } else { 2078 bwfm_fwvar_var_set_int(sc, "wpa_auth", BWFM_WPA_AUTH_DISABLED); 2079 bwfm_fwvar_var_set_int(sc, "wsec", BWFM_WSEC_NONE); 2080 } 2081 bwfm_fwvar_var_set_int(sc, "auth", BWFM_AUTH_OPEN); 2082 bwfm_fwvar_var_set_int(sc, "mfp", BWFM_MFP_NONE); 2083 2084 bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_INFRA, 1); 2085 bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_AP, 1); 2086 bwfm_fwvar_var_set_int(sc, "chanspec", 2087 bwfm_chan2spec(sc, ic->ic_bss->ni_chan)); 2088 bwfm_fwvar_cmd_set_int(sc, BWFM_C_UP, 1); 2089 2090 memset(&join, 0, sizeof(join)); 2091 memcpy(join.ssid.ssid, ic->ic_des_essid, ic->ic_des_esslen); 2092 join.ssid.len = htole32(ic->ic_des_esslen); 2093 memset(join.assoc.bssid, 0xff, sizeof(join.assoc.bssid)); 2094 bwfm_fwvar_cmd_set_data(sc, BWFM_C_SET_SSID, &join, sizeof(join)); 2095 bwfm_fwvar_var_set_int(sc, "closednet", 2096 (ic->ic_userflags & IEEE80211_F_HIDENWID) != 0); 2097 } 2098 #endif 2099 2100 void 2101 bwfm_scan(struct bwfm_softc *sc) 2102 { 2103 struct ieee80211com *ic = &sc->sc_ic; 2104 struct bwfm_escan_params *params; 2105 uint32_t nssid = 0, nchan = 0; 2106 size_t params_size, chan_size, ssid_size; 2107 struct bwfm_ssid *ssid; 2108 2109 if (ic->ic_flags & IEEE80211_F_ASCAN && 2110 ic->ic_des_esslen && ic->ic_des_esslen <= BWFM_MAX_SSID_LEN) 2111 nssid = 1; 2112 2113 chan_size = roundup(nchan * sizeof(uint16_t), sizeof(uint32_t)); 2114 ssid_size = sizeof(struct bwfm_ssid) * nssid; 2115 params_size = sizeof(*params) + chan_size + ssid_size; 2116 2117 params = malloc(params_size, M_TEMP, M_WAITOK | M_ZERO); 2118 ssid = (struct bwfm_ssid *) 2119 (((uint8_t *)params) + sizeof(*params) + chan_size); 2120 2121 memset(params->scan_params.bssid, 0xff, 2122 sizeof(params->scan_params.bssid)); 2123 params->scan_params.bss_type = 2; 2124 params->scan_params.scan_type = BWFM_SCANTYPE_PASSIVE; 2125 params->scan_params.nprobes = htole32(-1); 2126 params->scan_params.active_time = htole32(-1); 2127 params->scan_params.passive_time = htole32(-1); 2128 params->scan_params.home_time = htole32(-1); 2129 params->version = htole32(BWFM_ESCAN_REQ_VERSION); 2130 params->action = htole16(WL_ESCAN_ACTION_START); 2131 params->sync_id = htole16(0x1234); 2132 2133 if (ic->ic_flags & IEEE80211_F_ASCAN && 2134 ic->ic_des_esslen && ic->ic_des_esslen <= BWFM_MAX_SSID_LEN) { 2135 params->scan_params.scan_type = BWFM_SCANTYPE_ACTIVE; 2136 ssid->len = htole32(ic->ic_des_esslen); 2137 memcpy(ssid->ssid, ic->ic_des_essid, ic->ic_des_esslen); 2138 } 2139 2140 params->scan_params.channel_num = htole32( 2141 nssid << BWFM_CHANNUM_NSSID_SHIFT | 2142 nchan << BWFM_CHANNUM_NCHAN_SHIFT); 2143 2144 #if 0 2145 /* Scan a specific channel */ 2146 params->scan_params.channel_list[0] = htole16( 2147 (1 & 0xff) << 0 | 2148 (3 & 0x3) << 8 | 2149 (2 & 0x3) << 10 | 2150 (2 & 0x3) << 12 2151 ); 2152 #endif 2153 2154 bwfm_fwvar_var_set_data(sc, "escan", params, params_size); 2155 free(params, M_TEMP, params_size); 2156 } 2157 2158 void 2159 bwfm_scan_abort(struct bwfm_softc *sc) 2160 { 2161 struct bwfm_escan_params *params; 2162 size_t params_size; 2163 2164 params_size = sizeof(*params) + sizeof(uint16_t); 2165 params = malloc(params_size, M_TEMP, M_WAITOK | M_ZERO); 2166 memset(params->scan_params.bssid, 0xff, 2167 sizeof(params->scan_params.bssid)); 2168 params->scan_params.bss_type = 2; 2169 params->scan_params.scan_type = BWFM_SCANTYPE_PASSIVE; 2170 params->scan_params.nprobes = htole32(-1); 2171 params->scan_params.active_time = htole32(-1); 2172 params->scan_params.passive_time = htole32(-1); 2173 params->scan_params.home_time = htole32(-1); 2174 params->version = htole32(BWFM_ESCAN_REQ_VERSION); 2175 params->action = htole16(WL_ESCAN_ACTION_START); 2176 params->sync_id = htole16(0x1234); 2177 params->scan_params.channel_num = htole32(1); 2178 params->scan_params.channel_list[0] = htole16(-1); 2179 bwfm_fwvar_var_set_data(sc, "escan", params, params_size); 2180 free(params, M_TEMP, params_size); 2181 } 2182 2183 struct mbuf * 2184 bwfm_newbuf(void) 2185 { 2186 struct mbuf *m; 2187 2188 MGETHDR(m, M_DONTWAIT, MT_DATA); 2189 if (m == NULL) 2190 return (NULL); 2191 2192 MCLGET(m, M_DONTWAIT); 2193 if (!(m->m_flags & M_EXT)) { 2194 m_freem(m); 2195 return (NULL); 2196 } 2197 2198 m->m_len = m->m_pkthdr.len = MCLBYTES; 2199 2200 return (m); 2201 } 2202 2203 void 2204 bwfm_rx(struct bwfm_softc *sc, struct mbuf *m, struct mbuf_list *ml) 2205 { 2206 struct ieee80211com *ic = &sc->sc_ic; 2207 struct ifnet *ifp = &ic->ic_if; 2208 struct ieee80211_node *ni; 2209 struct bwfm_event *e; 2210 2211 #ifdef __STRICT_ALIGNMENT 2212 /* Remaining data is an ethernet packet, so align. */ 2213 if ((mtod(m, paddr_t) & 0x3) != ETHER_ALIGN) { 2214 struct mbuf *m0; 2215 m0 = m_dup_pkt(m, ETHER_ALIGN, M_WAITOK); 2216 m_freem(m); 2217 if (m0 == NULL) { 2218 ifp->if_ierrors++; 2219 return; 2220 } 2221 m = m0; 2222 } 2223 #endif 2224 2225 e = mtod(m, struct bwfm_event *); 2226 if (m->m_len >= sizeof(e->ehdr) && 2227 ntohs(e->ehdr.ether_type) == BWFM_ETHERTYPE_LINK_CTL && 2228 memcmp(BWFM_BRCM_OUI, e->hdr.oui, sizeof(e->hdr.oui)) == 0 && 2229 ntohs(e->hdr.usr_subtype) == BWFM_BRCM_SUBTYPE_EVENT) { 2230 bwfm_rx_event(sc, m); 2231 return; 2232 } 2233 2234 /* Drop network packets if we are not in RUN state. */ 2235 if (ic->ic_state != IEEE80211_S_RUN) { 2236 m_freem(m); 2237 return; 2238 } 2239 2240 if ((ic->ic_flags & IEEE80211_F_RSNON) && 2241 m->m_len >= sizeof(e->ehdr) && 2242 ntohs(e->ehdr.ether_type) == ETHERTYPE_PAE) { 2243 ifp->if_ipackets++; 2244 #if NBPFILTER > 0 2245 if (ifp->if_bpf) 2246 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); 2247 #endif 2248 #ifndef IEEE80211_STA_ONLY 2249 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 2250 ni = ieee80211_find_node(ic, 2251 (void *)&e->ehdr.ether_shost); 2252 if (ni == NULL) { 2253 m_freem(m); 2254 return; 2255 } 2256 } else 2257 #endif 2258 ni = ic->ic_bss; 2259 ieee80211_eapol_key_input(ic, m, ni); 2260 } else 2261 ml_enqueue(ml, m); 2262 } 2263 2264 #ifndef IEEE80211_STA_ONLY 2265 void 2266 bwfm_rx_auth_ind(struct bwfm_softc *sc, struct bwfm_event *e, size_t len) 2267 { 2268 struct ieee80211com *ic = &sc->sc_ic; 2269 struct ifnet *ifp = &ic->ic_if; 2270 struct ieee80211_rxinfo rxi; 2271 struct ieee80211_frame *wh; 2272 struct mbuf *m; 2273 uint32_t pktlen, ieslen; 2274 2275 /* Build a fake beacon frame to let net80211 do all the parsing. */ 2276 ieslen = betoh32(e->msg.datalen); 2277 pktlen = sizeof(*wh) + ieslen + 6; 2278 if (pktlen > MCLBYTES) 2279 return; 2280 m = bwfm_newbuf(); 2281 if (m == NULL) 2282 return; 2283 wh = mtod(m, struct ieee80211_frame *); 2284 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | 2285 IEEE80211_FC0_SUBTYPE_AUTH; 2286 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; 2287 *(uint16_t *)wh->i_dur = 0; 2288 IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr); 2289 IEEE80211_ADDR_COPY(wh->i_addr2, &e->msg.addr); 2290 IEEE80211_ADDR_COPY(wh->i_addr3, ic->ic_bss->ni_bssid); 2291 *(uint16_t *)wh->i_seq = 0; 2292 ((uint16_t *)(&wh[1]))[0] = IEEE80211_AUTH_ALG_OPEN; 2293 ((uint16_t *)(&wh[1]))[1] = IEEE80211_AUTH_OPEN_REQUEST; 2294 ((uint16_t *)(&wh[1]))[2] = 0; 2295 2296 /* Finalize mbuf. */ 2297 m->m_pkthdr.len = m->m_len = pktlen; 2298 rxi.rxi_flags = 0; 2299 rxi.rxi_rssi = 0; 2300 rxi.rxi_tstamp = 0; 2301 ieee80211_input(ifp, m, ic->ic_bss, &rxi); 2302 } 2303 2304 void 2305 bwfm_rx_assoc_ind(struct bwfm_softc *sc, struct bwfm_event *e, size_t len, 2306 int reassoc) 2307 { 2308 struct ieee80211com *ic = &sc->sc_ic; 2309 struct ifnet *ifp = &ic->ic_if; 2310 struct ieee80211_rxinfo rxi; 2311 struct ieee80211_frame *wh; 2312 struct ieee80211_node *ni; 2313 struct mbuf *m; 2314 uint32_t pktlen, ieslen; 2315 2316 /* Build a fake beacon frame to let net80211 do all the parsing. */ 2317 ieslen = betoh32(e->msg.datalen); 2318 pktlen = sizeof(*wh) + ieslen + 4; 2319 if (reassoc) 2320 pktlen += IEEE80211_ADDR_LEN; 2321 if (pktlen > MCLBYTES) 2322 return; 2323 m = bwfm_newbuf(); 2324 if (m == NULL) 2325 return; 2326 wh = mtod(m, struct ieee80211_frame *); 2327 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT; 2328 if (reassoc) 2329 wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_REASSOC_REQ; 2330 else 2331 wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_ASSOC_REQ; 2332 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; 2333 *(uint16_t *)wh->i_dur = 0; 2334 IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr); 2335 IEEE80211_ADDR_COPY(wh->i_addr2, &e->msg.addr); 2336 IEEE80211_ADDR_COPY(wh->i_addr3, ic->ic_bss->ni_bssid); 2337 *(uint16_t *)wh->i_seq = 0; 2338 ((uint16_t *)(&wh[1]))[0] = IEEE80211_CAPINFO_ESS; /* XXX */ 2339 ((uint16_t *)(&wh[1]))[1] = 100; /* XXX */ 2340 if (reassoc) { 2341 memset(((uint8_t *)&wh[1]) + 4, 0, IEEE80211_ADDR_LEN); 2342 memcpy(((uint8_t *)&wh[1]) + 4 + IEEE80211_ADDR_LEN, 2343 &e[1], ieslen); 2344 } else 2345 memcpy(((uint8_t *)&wh[1]) + 4, &e[1], ieslen); 2346 2347 /* Finalize mbuf. */ 2348 m->m_pkthdr.len = m->m_len = pktlen; 2349 ni = ieee80211_find_node(ic, wh->i_addr2); 2350 if (ni == NULL) { 2351 m_freem(m); 2352 return; 2353 } 2354 rxi.rxi_flags = 0; 2355 rxi.rxi_rssi = 0; 2356 rxi.rxi_tstamp = 0; 2357 ieee80211_input(ifp, m, ni, &rxi); 2358 } 2359 2360 void 2361 bwfm_rx_deauth_ind(struct bwfm_softc *sc, struct bwfm_event *e, size_t len) 2362 { 2363 bwfm_rx_leave_ind(sc, e, len, IEEE80211_FC0_SUBTYPE_DEAUTH); 2364 } 2365 2366 void 2367 bwfm_rx_disassoc_ind(struct bwfm_softc *sc, struct bwfm_event *e, size_t len) 2368 { 2369 bwfm_rx_leave_ind(sc, e, len, IEEE80211_FC0_SUBTYPE_DISASSOC); 2370 } 2371 2372 void 2373 bwfm_rx_leave_ind(struct bwfm_softc *sc, struct bwfm_event *e, size_t len, 2374 int subtype) 2375 { 2376 struct ieee80211com *ic = &sc->sc_ic; 2377 struct ifnet *ifp = &ic->ic_if; 2378 struct ieee80211_rxinfo rxi; 2379 struct ieee80211_frame *wh; 2380 struct ieee80211_node *ni; 2381 struct mbuf *m; 2382 uint32_t pktlen; 2383 2384 /* Build a fake beacon frame to let net80211 do all the parsing. */ 2385 pktlen = sizeof(*wh) + 2; 2386 if (pktlen > MCLBYTES) 2387 return; 2388 m = bwfm_newbuf(); 2389 if (m == NULL) 2390 return; 2391 wh = mtod(m, struct ieee80211_frame *); 2392 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | 2393 subtype; 2394 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; 2395 *(uint16_t *)wh->i_dur = 0; 2396 IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr); 2397 IEEE80211_ADDR_COPY(wh->i_addr2, &e->msg.addr); 2398 IEEE80211_ADDR_COPY(wh->i_addr3, ic->ic_bss->ni_bssid); 2399 *(uint16_t *)wh->i_seq = 0; 2400 memset((uint8_t *)&wh[1], 0, 2); 2401 2402 /* Finalize mbuf. */ 2403 m->m_pkthdr.len = m->m_len = pktlen; 2404 ni = ieee80211_find_node(ic, wh->i_addr2); 2405 if (ni == NULL) { 2406 m_freem(m); 2407 return; 2408 } 2409 rxi.rxi_flags = 0; 2410 rxi.rxi_rssi = 0; 2411 rxi.rxi_tstamp = 0; 2412 ieee80211_input(ifp, m, ni, &rxi); 2413 } 2414 #endif 2415 2416 void 2417 bwfm_rx_event(struct bwfm_softc *sc, struct mbuf *m) 2418 { 2419 int s; 2420 2421 s = splnet(); 2422 ml_enqueue(&sc->sc_evml, m); 2423 splx(s); 2424 2425 task_add(sc->sc_taskq, &sc->sc_task); 2426 } 2427 2428 void 2429 bwfm_rx_event_cb(struct bwfm_softc *sc, struct mbuf *m) 2430 { 2431 struct ieee80211com *ic = &sc->sc_ic; 2432 struct ifnet *ifp = &ic->ic_if; 2433 struct bwfm_event *e = mtod(m, void *); 2434 size_t len = m->m_len; 2435 2436 if (ntohl(e->msg.event_type) >= BWFM_E_LAST) { 2437 m_freem(m); 2438 return; 2439 } 2440 2441 switch (ntohl(e->msg.event_type)) { 2442 case BWFM_E_ESCAN_RESULT: { 2443 struct bwfm_escan_results *res; 2444 struct bwfm_bss_info *bss; 2445 size_t reslen; 2446 int i; 2447 /* Abort event triggered by SCAN -> INIT */ 2448 if (ic->ic_state == IEEE80211_S_INIT && 2449 ntohl(e->msg.status) == BWFM_E_STATUS_ABORT) 2450 break; 2451 if (ic->ic_state != IEEE80211_S_SCAN) { 2452 DPRINTF(("%s: scan result (%u) while not in SCAN\n", 2453 DEVNAME(sc), ntohl(e->msg.status))); 2454 break; 2455 } 2456 if (ntohl(e->msg.status) != BWFM_E_STATUS_SUCCESS && 2457 ntohl(e->msg.status) != BWFM_E_STATUS_PARTIAL) { 2458 DPRINTF(("%s: unexpected scan result (%u)\n", 2459 DEVNAME(sc), ntohl(e->msg.status))); 2460 break; 2461 } 2462 if (ntohl(e->msg.status) == BWFM_E_STATUS_SUCCESS) { 2463 ieee80211_end_scan(ifp); 2464 break; 2465 } 2466 len -= sizeof(*e); 2467 if (len < sizeof(*res)) { 2468 DPRINTF(("%s: results too small\n", DEVNAME(sc))); 2469 m_freem(m); 2470 return; 2471 } 2472 reslen = len; 2473 res = malloc(len, M_TEMP, M_WAITOK); 2474 memcpy(res, (void *)&e[1], len); 2475 if (len < letoh32(res->buflen)) { 2476 DPRINTF(("%s: results too small\n", DEVNAME(sc))); 2477 free(res, M_TEMP, reslen); 2478 m_freem(m); 2479 return; 2480 } 2481 len -= sizeof(*res); 2482 if (len < letoh16(res->bss_count) * sizeof(struct bwfm_bss_info)) { 2483 DPRINTF(("%s: results too small\n", DEVNAME(sc))); 2484 free(res, M_TEMP, reslen); 2485 m_freem(m); 2486 return; 2487 } 2488 bss = &res->bss_info[0]; 2489 for (i = 0; i < letoh16(res->bss_count); i++) { 2490 bwfm_scan_node(sc, &res->bss_info[i], len); 2491 len -= sizeof(*bss) + letoh32(bss->length); 2492 bss = (void *)((char *)bss) + letoh32(bss->length); 2493 if (len <= 0) 2494 break; 2495 } 2496 free(res, M_TEMP, reslen); 2497 break; 2498 } 2499 case BWFM_E_AUTH: 2500 if (ntohl(e->msg.status) == BWFM_E_STATUS_SUCCESS && 2501 ic->ic_state == IEEE80211_S_AUTH) 2502 ieee80211_new_state(ic, IEEE80211_S_ASSOC, -1); 2503 else 2504 ieee80211_begin_scan(ifp); 2505 break; 2506 case BWFM_E_ASSOC: 2507 if (ntohl(e->msg.status) == BWFM_E_STATUS_SUCCESS && 2508 ic->ic_state == IEEE80211_S_ASSOC) 2509 ieee80211_new_state(ic, IEEE80211_S_RUN, -1); 2510 else if (ntohl(e->msg.status) != BWFM_E_STATUS_UNSOLICITED) 2511 ieee80211_begin_scan(ifp); 2512 break; 2513 case BWFM_E_DEAUTH: 2514 case BWFM_E_DISASSOC: 2515 if (ic->ic_state > IEEE80211_S_SCAN) 2516 ieee80211_begin_scan(ifp); 2517 break; 2518 case BWFM_E_LINK: 2519 if (ntohl(e->msg.status) == BWFM_E_STATUS_SUCCESS && 2520 ntohl(e->msg.reason) == 0) 2521 break; 2522 /* Link status has changed */ 2523 if (ic->ic_state > IEEE80211_S_SCAN) 2524 ieee80211_begin_scan(ifp); 2525 break; 2526 #ifndef IEEE80211_STA_ONLY 2527 case BWFM_E_AUTH_IND: 2528 bwfm_rx_auth_ind(sc, e, len); 2529 break; 2530 case BWFM_E_ASSOC_IND: 2531 bwfm_rx_assoc_ind(sc, e, len, 0); 2532 break; 2533 case BWFM_E_REASSOC_IND: 2534 bwfm_rx_assoc_ind(sc, e, len, 1); 2535 break; 2536 case BWFM_E_DEAUTH_IND: 2537 bwfm_rx_deauth_ind(sc, e, len); 2538 break; 2539 case BWFM_E_DISASSOC_IND: 2540 bwfm_rx_disassoc_ind(sc, e, len); 2541 break; 2542 #endif 2543 default: 2544 DPRINTF(("%s: len %lu datalen %u code %u status %u" 2545 " reason %u\n", __func__, len, ntohl(e->msg.datalen), 2546 ntohl(e->msg.event_type), ntohl(e->msg.status), 2547 ntohl(e->msg.reason))); 2548 break; 2549 } 2550 2551 m_freem(m); 2552 } 2553 2554 void 2555 bwfm_scan_node(struct bwfm_softc *sc, struct bwfm_bss_info *bss, size_t len) 2556 { 2557 struct ieee80211com *ic = &sc->sc_ic; 2558 struct ifnet *ifp = &ic->ic_if; 2559 struct ieee80211_frame *wh; 2560 struct ieee80211_node *ni; 2561 struct ieee80211_rxinfo rxi; 2562 struct ieee80211_channel *bss_chan; 2563 uint8_t saved_bssid[IEEE80211_ADDR_LEN] = { 0 }; 2564 struct mbuf *m; 2565 uint32_t pktlen, ieslen; 2566 uint16_t iesoff; 2567 int chanidx; 2568 2569 iesoff = letoh16(bss->ie_offset); 2570 ieslen = letoh32(bss->ie_length); 2571 if (ieslen > len - iesoff) 2572 return; 2573 2574 /* Build a fake beacon frame to let net80211 do all the parsing. */ 2575 pktlen = sizeof(*wh) + ieslen + 12; 2576 if (pktlen > MCLBYTES) 2577 return; 2578 m = bwfm_newbuf(); 2579 if (m == NULL) 2580 return; 2581 wh = mtod(m, struct ieee80211_frame *); 2582 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | 2583 IEEE80211_FC0_SUBTYPE_BEACON; 2584 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; 2585 *(uint16_t *)wh->i_dur = 0; 2586 IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr); 2587 IEEE80211_ADDR_COPY(wh->i_addr2, bss->bssid); 2588 IEEE80211_ADDR_COPY(wh->i_addr3, bss->bssid); 2589 *(uint16_t *)wh->i_seq = 0; 2590 memset(&wh[1], 0, 12); 2591 ((uint16_t *)(&wh[1]))[4] = bss->beacon_period; 2592 ((uint16_t *)(&wh[1]))[5] = bss->capability; 2593 memcpy(((uint8_t *)&wh[1]) + 12, ((uint8_t *)bss) + iesoff, ieslen); 2594 2595 /* Finalize mbuf. */ 2596 m->m_pkthdr.len = m->m_len = pktlen; 2597 ni = ieee80211_find_rxnode(ic, wh); 2598 if (ni == ic->ic_bss) { 2599 /* 2600 * We may switch ic_bss's channel during scans. 2601 * Record the current channel so we can restore it later. 2602 */ 2603 bss_chan = ni->ni_chan; 2604 IEEE80211_ADDR_COPY(&saved_bssid, ni->ni_macaddr); 2605 } 2606 /* Channel mask equals IEEE80211_CHAN_MAX */ 2607 chanidx = bwfm_spec2chan(sc, letoh32(bss->chanspec)); 2608 ni->ni_chan = &ic->ic_channels[chanidx]; 2609 /* Supply RSSI */ 2610 rxi.rxi_flags = 0; 2611 rxi.rxi_rssi = (int16_t)letoh16(bss->rssi); 2612 rxi.rxi_tstamp = 0; 2613 ieee80211_input(ifp, m, ni, &rxi); 2614 /* 2615 * ieee80211_input() might have changed our BSS. 2616 * Restore ic_bss's channel if we are still in the same BSS. 2617 */ 2618 if (ni == ic->ic_bss && IEEE80211_ADDR_EQ(saved_bssid, ni->ni_macaddr)) 2619 ni->ni_chan = bss_chan; 2620 /* Node is no longer needed. */ 2621 ieee80211_release_node(ic, ni); 2622 } 2623 2624 void 2625 bwfm_task(void *arg) 2626 { 2627 struct bwfm_softc *sc = arg; 2628 struct bwfm_host_cmd_ring *ring = &sc->sc_cmdq; 2629 struct bwfm_host_cmd *cmd; 2630 struct mbuf *m; 2631 int s; 2632 2633 s = splnet(); 2634 while (ring->next != ring->cur) { 2635 cmd = &ring->cmd[ring->next]; 2636 splx(s); 2637 cmd->cb(sc, cmd->data); 2638 s = splnet(); 2639 ring->queued--; 2640 ring->next = (ring->next + 1) % BWFM_HOST_CMD_RING_COUNT; 2641 } 2642 splx(s); 2643 2644 s = splnet(); 2645 while ((m = ml_dequeue(&sc->sc_evml)) != NULL) { 2646 splx(s); 2647 bwfm_rx_event_cb(sc, m); 2648 s = splnet(); 2649 } 2650 splx(s); 2651 } 2652 2653 void 2654 bwfm_do_async(struct bwfm_softc *sc, 2655 void (*cb)(struct bwfm_softc *, void *), void *arg, int len) 2656 { 2657 struct bwfm_host_cmd_ring *ring = &sc->sc_cmdq; 2658 struct bwfm_host_cmd *cmd; 2659 int s; 2660 2661 s = splnet(); 2662 KASSERT(ring->queued < BWFM_HOST_CMD_RING_COUNT); 2663 if (ring->queued >= BWFM_HOST_CMD_RING_COUNT) { 2664 splx(s); 2665 return; 2666 } 2667 cmd = &ring->cmd[ring->cur]; 2668 cmd->cb = cb; 2669 KASSERT(len <= sizeof(cmd->data)); 2670 memcpy(cmd->data, arg, len); 2671 ring->cur = (ring->cur + 1) % BWFM_HOST_CMD_RING_COUNT; 2672 ring->queued++; 2673 task_add(sc->sc_taskq, &sc->sc_task); 2674 splx(s); 2675 } 2676 2677 int 2678 bwfm_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni, 2679 int type, int arg1, int arg2) 2680 { 2681 #ifdef BWFM_DEBUG 2682 struct bwfm_softc *sc = ic->ic_softc; 2683 DPRINTF(("%s: %s\n", DEVNAME(sc), __func__)); 2684 #endif 2685 return 0; 2686 } 2687 2688 int 2689 bwfm_set_key(struct ieee80211com *ic, struct ieee80211_node *ni, 2690 struct ieee80211_key *k) 2691 { 2692 struct bwfm_softc *sc = ic->ic_softc; 2693 struct bwfm_cmd_key cmd; 2694 2695 cmd.ni = ni; 2696 cmd.k = k; 2697 bwfm_do_async(sc, bwfm_set_key_cb, &cmd, sizeof(cmd)); 2698 sc->sc_key_tasks++; 2699 return EBUSY; 2700 } 2701 2702 void 2703 bwfm_set_key_cb(struct bwfm_softc *sc, void *arg) 2704 { 2705 struct bwfm_cmd_key *cmd = arg; 2706 struct ieee80211_key *k = cmd->k; 2707 struct ieee80211_node *ni = cmd->ni; 2708 struct ieee80211com *ic = &sc->sc_ic; 2709 struct bwfm_wsec_key key; 2710 uint32_t wsec, wsec_enable; 2711 int ext_key = 0; 2712 2713 sc->sc_key_tasks--; 2714 2715 if ((k->k_flags & IEEE80211_KEY_GROUP) == 0 && 2716 k->k_cipher != IEEE80211_CIPHER_WEP40 && 2717 k->k_cipher != IEEE80211_CIPHER_WEP104) 2718 ext_key = 1; 2719 2720 memset(&key, 0, sizeof(key)); 2721 if (ext_key && !IEEE80211_IS_MULTICAST(ni->ni_macaddr)) 2722 memcpy(key.ea, ni->ni_macaddr, sizeof(key.ea)); 2723 key.index = htole32(k->k_id); 2724 key.len = htole32(k->k_len); 2725 memcpy(key.data, k->k_key, sizeof(key.data)); 2726 if (!ext_key) 2727 key.flags = htole32(BWFM_WSEC_PRIMARY_KEY); 2728 2729 switch (k->k_cipher) { 2730 case IEEE80211_CIPHER_WEP40: 2731 key.algo = htole32(BWFM_CRYPTO_ALGO_WEP1); 2732 wsec_enable = BWFM_WSEC_WEP; 2733 break; 2734 case IEEE80211_CIPHER_WEP104: 2735 key.algo = htole32(BWFM_CRYPTO_ALGO_WEP128); 2736 wsec_enable = BWFM_WSEC_WEP; 2737 break; 2738 case IEEE80211_CIPHER_TKIP: 2739 key.algo = htole32(BWFM_CRYPTO_ALGO_TKIP); 2740 wsec_enable = BWFM_WSEC_TKIP; 2741 break; 2742 case IEEE80211_CIPHER_CCMP: 2743 key.algo = htole32(BWFM_CRYPTO_ALGO_AES_CCM); 2744 wsec_enable = BWFM_WSEC_AES; 2745 break; 2746 default: 2747 printf("%s: cipher %x not supported\n", DEVNAME(sc), 2748 k->k_cipher); 2749 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 2750 return; 2751 } 2752 2753 delay(100); 2754 2755 bwfm_fwvar_var_set_data(sc, "wsec_key", &key, sizeof(key)); 2756 bwfm_fwvar_var_get_int(sc, "wsec", &wsec); 2757 wsec |= wsec_enable; 2758 bwfm_fwvar_var_set_int(sc, "wsec", wsec); 2759 2760 if (sc->sc_key_tasks == 0) { 2761 DPRINTF(("%s: marking port %s valid\n", DEVNAME(sc), 2762 ether_sprintf(cmd->ni->ni_macaddr))); 2763 cmd->ni->ni_port_valid = 1; 2764 ieee80211_set_link_state(ic, LINK_STATE_UP); 2765 } 2766 } 2767 2768 void 2769 bwfm_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni, 2770 struct ieee80211_key *k) 2771 { 2772 struct bwfm_softc *sc = ic->ic_softc; 2773 struct bwfm_cmd_key cmd; 2774 2775 cmd.ni = ni; 2776 cmd.k = k; 2777 bwfm_do_async(sc, bwfm_delete_key_cb, &cmd, sizeof(cmd)); 2778 } 2779 2780 void 2781 bwfm_delete_key_cb(struct bwfm_softc *sc, void *arg) 2782 { 2783 struct bwfm_cmd_key *cmd = arg; 2784 struct ieee80211_key *k = cmd->k; 2785 struct bwfm_wsec_key key; 2786 2787 memset(&key, 0, sizeof(key)); 2788 key.index = htole32(k->k_id); 2789 key.flags = htole32(BWFM_WSEC_PRIMARY_KEY); 2790 bwfm_fwvar_var_set_data(sc, "wsec_key", &key, sizeof(key)); 2791 } 2792 2793 int 2794 bwfm_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 2795 { 2796 struct bwfm_softc *sc = ic->ic_softc; 2797 struct ifnet *ifp = &ic->ic_if; 2798 int s; 2799 2800 s = splnet(); 2801 2802 switch (nstate) { 2803 case IEEE80211_S_INIT: 2804 if (ic->ic_state == IEEE80211_S_SCAN) 2805 bwfm_scan_abort(sc); 2806 break; 2807 case IEEE80211_S_SCAN: 2808 #ifndef IEEE80211_STA_ONLY 2809 /* Don't start a scan if we already have a channel. */ 2810 if (ic->ic_state == IEEE80211_S_INIT && 2811 ic->ic_opmode == IEEE80211_M_HOSTAP && 2812 ic->ic_des_chan != IEEE80211_CHAN_ANYC) { 2813 break; 2814 } 2815 #endif 2816 /* If we tried to connect, abort. */ 2817 if (ic->ic_state > IEEE80211_S_SCAN) 2818 bwfm_fwvar_cmd_set_data(sc, BWFM_C_DISASSOC, NULL, 0); 2819 /* Initiate scan. */ 2820 bwfm_scan(sc); 2821 if (ifp->if_flags & IFF_DEBUG) 2822 printf("%s: %s -> %s\n", DEVNAME(sc), 2823 ieee80211_state_name[ic->ic_state], 2824 ieee80211_state_name[nstate]); 2825 /* No need to do this again. */ 2826 if (ic->ic_state == IEEE80211_S_SCAN) { 2827 splx(s); 2828 return 0; 2829 } 2830 ieee80211_set_link_state(ic, LINK_STATE_DOWN); 2831 ieee80211_free_allnodes(ic, 1); 2832 ic->ic_state = nstate; 2833 splx(s); 2834 return 0; 2835 case IEEE80211_S_AUTH: 2836 ic->ic_bss->ni_rsn_supp_state = RSNA_SUPP_INITIALIZE; 2837 bwfm_connect(sc); 2838 if (ifp->if_flags & IFF_DEBUG) 2839 printf("%s: %s -> %s\n", DEVNAME(sc), 2840 ieee80211_state_name[ic->ic_state], 2841 ieee80211_state_name[nstate]); 2842 ic->ic_state = nstate; 2843 if (ic->ic_flags & IEEE80211_F_RSNON) 2844 ic->ic_bss->ni_rsn_supp_state = RSNA_SUPP_PTKSTART; 2845 splx(s); 2846 return 0; 2847 #ifndef IEEE80211_STA_ONLY 2848 case IEEE80211_S_RUN: 2849 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 2850 bwfm_hostap(sc); 2851 break; 2852 #endif 2853 default: 2854 break; 2855 } 2856 sc->sc_newstate(ic, nstate, arg); 2857 splx(s); 2858 return 0; 2859 } 2860 2861 int 2862 bwfm_nvram_convert(int node, u_char **bufp, size_t *sizep, size_t *newlenp) 2863 { 2864 u_char *src, *dst, *end = *bufp + *sizep, *newbuf; 2865 size_t count = 0, newsize, pad; 2866 uint32_t token; 2867 int skip = 0; 2868 2869 /* 2870 * Allocate a new buffer with enough space for the MAC 2871 * address, padding and final token. 2872 */ 2873 newsize = *sizep + 64; 2874 newbuf = malloc(newsize, M_DEVBUF, M_NOWAIT); 2875 if (newbuf == NULL) 2876 return 1; 2877 2878 for (src = *bufp, dst = newbuf; src != end; ++src) { 2879 if (*src == '\n') { 2880 if (count > 0) 2881 *dst++ = '\0'; 2882 count = 0; 2883 skip = 0; 2884 continue; 2885 } 2886 if (skip) 2887 continue; 2888 if (*src == '#' && count == 0) { 2889 skip = 1; 2890 continue; 2891 } 2892 if (*src == '\r') 2893 continue; 2894 *dst++ = *src; 2895 ++count; 2896 } 2897 2898 #if defined(__HAVE_FDT) 2899 /* 2900 * Append MAC address if one is provided in the device tree. 2901 * This is needed on Apple Silicon Macs. 2902 */ 2903 if (node) { 2904 u_char enaddr[ETHER_ADDR_LEN]; 2905 char macaddr[32]; 2906 2907 if (OF_getprop(node, "local-mac-address", 2908 enaddr, sizeof(enaddr))) { 2909 snprintf(macaddr, sizeof(macaddr), 2910 "macaddr=%02x:%02x:%02x:%02x:%02x:%02x", 2911 enaddr[0], enaddr[1], enaddr[2], enaddr[3], 2912 enaddr[4], enaddr[5]); 2913 if (*dst) 2914 *dst++ = '\0'; 2915 memcpy(dst, macaddr, strlen(macaddr)); 2916 dst += strlen(macaddr); 2917 } 2918 } 2919 #endif 2920 2921 count = dst - newbuf; 2922 pad = roundup(count + 1, 4) - count; 2923 2924 memset(dst, 0, pad); 2925 count += pad; 2926 dst += pad; 2927 2928 token = (count / 4) & 0xffff; 2929 token |= ~token << 16; 2930 token = htole32(token); 2931 2932 memcpy(dst, &token, sizeof(token)); 2933 count += sizeof(token); 2934 2935 free(*bufp, M_DEVBUF, *sizep); 2936 *bufp = newbuf; 2937 *sizep = newsize; 2938 *newlenp = count; 2939 return 0; 2940 } 2941 2942 void 2943 bwfm_process_clm_blob(struct bwfm_softc *sc) 2944 { 2945 struct bwfm_dload_data *data; 2946 size_t off, remain, len; 2947 2948 if (sc->sc_clm == NULL || sc->sc_clmsize == 0) 2949 return; 2950 2951 off = 0; 2952 remain = sc->sc_clmsize; 2953 data = malloc(sizeof(*data) + BWFM_DLOAD_MAX_LEN, M_TEMP, M_WAITOK); 2954 2955 while (remain) { 2956 len = min(remain, BWFM_DLOAD_MAX_LEN); 2957 2958 data->flag = htole16(BWFM_DLOAD_FLAG_HANDLER_VER_1); 2959 if (off == 0) 2960 data->flag |= htole16(BWFM_DLOAD_FLAG_BEGIN); 2961 if (remain < BWFM_DLOAD_MAX_LEN) 2962 data->flag |= htole16(BWFM_DLOAD_FLAG_END); 2963 data->type = htole16(BWFM_DLOAD_TYPE_CLM); 2964 data->len = htole32(len); 2965 data->crc = 0; 2966 memcpy(data->data, sc->sc_clm + off, len); 2967 2968 if (bwfm_fwvar_var_set_data(sc, "clmload", data, 2969 sizeof(*data) + len)) { 2970 printf("%s: could not load CLM blob\n", DEVNAME(sc)); 2971 goto out; 2972 } 2973 2974 off += len; 2975 remain -= len; 2976 } 2977 2978 out: 2979 free(data, M_TEMP, sizeof(*data) + BWFM_DLOAD_MAX_LEN); 2980 free(sc->sc_clm, M_DEVBUF, sc->sc_clmsize); 2981 sc->sc_clm = NULL; 2982 sc->sc_clmsize = 0; 2983 } 2984 2985 #if defined(__HAVE_FDT) 2986 const char * 2987 bwfm_sysname(void) 2988 { 2989 static char sysfw[128]; 2990 int len; 2991 char *p; 2992 2993 len = OF_getprop(OF_peer(0), "compatible", sysfw, sizeof(sysfw)); 2994 if (len > 0 && len < sizeof(sysfw)) { 2995 sysfw[len] = '\0'; 2996 if ((p = strchr(sysfw, '/')) != NULL) 2997 *p = '\0'; 2998 return sysfw; 2999 } 3000 return NULL; 3001 } 3002 #else 3003 const char * 3004 bwfm_sysname(void) 3005 { 3006 return NULL; 3007 } 3008 #endif 3009 3010 int 3011 bwfm_loadfirmware(struct bwfm_softc *sc, const char *chip, const char *bus, 3012 u_char **ucode, size_t *size, u_char **nvram, size_t *nvsize, size_t *nvlen) 3013 { 3014 const char *sysname = NULL; 3015 char name[128]; 3016 int r; 3017 3018 *ucode = *nvram = NULL; 3019 *size = *nvsize = *nvlen = 0; 3020 3021 sysname = bwfm_sysname(); 3022 3023 if (sysname != NULL) { 3024 r = snprintf(name, sizeof(name), "brcmfmac%s%s.%s.bin", chip, 3025 bus, sysname); 3026 if ((r > 0 && r < sizeof(name)) && 3027 loadfirmware(name, ucode, size) != 0) 3028 *size = 0; 3029 } 3030 if (*size == 0) { 3031 snprintf(name, sizeof(name), "brcmfmac%s%s.bin", chip, bus); 3032 if (loadfirmware(name, ucode, size) != 0) { 3033 snprintf(name, sizeof(name), "brcmfmac%s%s%s%s.bin", chip, bus, 3034 sysname ? "." : "", sysname ? sysname : ""); 3035 printf("%s: failed loadfirmware of file %s\n", 3036 DEVNAME(sc), name); 3037 return 1; 3038 } 3039 } 3040 3041 /* .txt needs to be processed first */ 3042 if (sysname != NULL) { 3043 r = snprintf(name, sizeof(name), "brcmfmac%s%s.%s.txt", chip, 3044 bus, sysname); 3045 if (r > 0 && r < sizeof(name)) 3046 loadfirmware(name, nvram, nvsize); 3047 } 3048 3049 if (*nvsize == 0) { 3050 snprintf(name, sizeof(name), "brcmfmac%s%s.txt", chip, bus); 3051 loadfirmware(name, nvram, nvsize); 3052 } 3053 3054 if (*nvsize != 0) { 3055 if (bwfm_nvram_convert(sc->sc_node, nvram, nvsize, nvlen)) { 3056 printf("%s: failed to process file %s\n", 3057 DEVNAME(sc), name); 3058 free(*ucode, M_DEVBUF, *size); 3059 free(*nvram, M_DEVBUF, *nvsize); 3060 return 1; 3061 } 3062 } 3063 3064 /* .nvram is the pre-processed version */ 3065 if (*nvlen == 0) { 3066 snprintf(name, sizeof(name), "brcmfmac%s%s.nvram", chip, bus); 3067 if (loadfirmware(name, nvram, nvsize) == 0) 3068 *nvlen = *nvsize; 3069 } 3070 3071 if (*nvlen == 0 && strcmp(bus, "-sdio") == 0) { 3072 snprintf(name, sizeof(name), "brcmfmac%s%s%s%s.txt", chip, bus, 3073 sysname ? "." : "", sysname ? sysname : ""); 3074 printf("%s: failed loadfirmware of file %s\n", 3075 DEVNAME(sc), name); 3076 free(*ucode, M_DEVBUF, *size); 3077 return 1; 3078 } 3079 3080 if (sysname != NULL) { 3081 r = snprintf(name, sizeof(name), "brcmfmac%s%s.%s.clm_blob", 3082 chip, bus, sysname); 3083 if (r > 0 && r < sizeof(name)) 3084 loadfirmware(name, &sc->sc_clm, &sc->sc_clmsize); 3085 } 3086 if (sc->sc_clmsize == 0) { 3087 snprintf(name, sizeof(name), "brcmfmac%s%s.clm_blob", chip, bus); 3088 loadfirmware(name, &sc->sc_clm, &sc->sc_clmsize); 3089 } 3090 3091 return 0; 3092 } 3093