if_ndis.c revision 330897
1/*- 2 * SPDX-License-Identifier: BSD-4-Clause 3 * 4 * Copyright (c) 2003 5 * Bill Paul <wpaul@windriver.com>. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Bill Paul. 18 * 4. Neither the name of the author nor the names of any co-contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 32 * THE POSSIBILITY OF SUCH DAMAGE. 33 * 34 * WPA support originally contributed by Arvind Srinivasan <arvind@celar.us> 35 * then hacked upon mercilessly by my. 36 */ 37 38#include <sys/cdefs.h> 39__FBSDID("$FreeBSD: stable/11/sys/dev/if_ndis/if_ndis.c 330897 2018-03-14 03:19:51Z eadler $"); 40 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/sockio.h> 44#include <sys/mbuf.h> 45#include <sys/malloc.h> 46#include <sys/endian.h> 47#include <sys/priv.h> 48#include <sys/kernel.h> 49#include <sys/socket.h> 50#include <sys/queue.h> 51#include <sys/module.h> 52#include <sys/proc.h> 53#include <sys/sysctl.h> 54#include <sys/kthread.h> 55#include <sys/limits.h> 56 57#include <net/if.h> 58#include <net/if_var.h> 59#include <net/if_arp.h> 60#include <net/ethernet.h> 61#include <net/if_dl.h> 62#include <net/if_media.h> 63#include <net/if_types.h> 64#include <net/route.h> 65 66#include <net/bpf.h> 67 68#include <machine/bus.h> 69#include <machine/resource.h> 70#include <sys/bus.h> 71#include <sys/rman.h> 72 73#include <net80211/ieee80211_var.h> 74#include <net80211/ieee80211_ioctl.h> 75#include <net80211/ieee80211_regdomain.h> 76 77#include <dev/pci/pcireg.h> 78#include <dev/pci/pcivar.h> 79#include <dev/usb/usb.h> 80#include <dev/usb/usbdi.h> 81 82#include <compat/ndis/pe_var.h> 83#include <compat/ndis/cfg_var.h> 84#include <compat/ndis/resource_var.h> 85#include <compat/ndis/ntoskrnl_var.h> 86#include <compat/ndis/hal_var.h> 87#include <compat/ndis/ndis_var.h> 88#include <compat/ndis/usbd_var.h> 89#include <dev/if_ndis/if_ndisvar.h> 90 91#define NDIS_DEBUG 92#ifdef NDIS_DEBUG 93#define DPRINTF(x) do { if (ndis_debug > 0) printf x; } while (0) 94int ndis_debug = 0; 95SYSCTL_INT(_debug, OID_AUTO, ndis, CTLFLAG_RW, &ndis_debug, 0, 96 "if_ndis debug level"); 97#else 98#define DPRINTF(x) 99#endif 100 101SYSCTL_DECL(_hw_ndisusb); 102int ndisusb_halt = 1; 103SYSCTL_INT(_hw_ndisusb, OID_AUTO, halt, CTLFLAG_RW, &ndisusb_halt, 0, 104 "Halt NDIS USB driver when it's attached"); 105 106/* 0 - 30 dBm to mW conversion table */ 107static const uint16_t dBm2mW[] = { 108 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 109 3, 4, 4, 4, 5, 6, 6, 7, 8, 9, 110 10, 11, 13, 14, 16, 18, 20, 22, 25, 28, 111 32, 35, 40, 45, 50, 56, 63, 71, 79, 89, 112 100, 112, 126, 141, 158, 178, 200, 224, 251, 282, 113 316, 355, 398, 447, 501, 562, 631, 708, 794, 891, 114 1000 115}; 116 117MODULE_DEPEND(ndis, ether, 1, 1, 1); 118MODULE_DEPEND(ndis, wlan, 1, 1, 1); 119MODULE_DEPEND(ndis, ndisapi, 1, 1, 1); 120 121MODULE_VERSION(ndis, 1); 122 123int ndis_attach (device_t); 124int ndis_detach (device_t); 125int ndis_suspend (device_t); 126int ndis_resume (device_t); 127void ndis_shutdown (device_t); 128 129int ndisdrv_modevent (module_t, int, void *); 130 131static void ndis_txeof (ndis_handle, ndis_packet *, ndis_status); 132static void ndis_rxeof (ndis_handle, ndis_packet **, uint32_t); 133static void ndis_rxeof_eth (ndis_handle, ndis_handle, char *, void *, 134 uint32_t, void *, uint32_t, uint32_t); 135static void ndis_rxeof_done (ndis_handle); 136static void ndis_rxeof_xfr (kdpc *, ndis_handle, void *, void *); 137static void ndis_rxeof_xfr_done (ndis_handle, ndis_packet *, 138 uint32_t, uint32_t); 139static void ndis_linksts (ndis_handle, ndis_status, void *, uint32_t); 140static void ndis_linksts_done (ndis_handle); 141 142/* We need to wrap these functions for amd64. */ 143static funcptr ndis_txeof_wrap; 144static funcptr ndis_rxeof_wrap; 145static funcptr ndis_rxeof_eth_wrap; 146static funcptr ndis_rxeof_done_wrap; 147static funcptr ndis_rxeof_xfr_wrap; 148static funcptr ndis_rxeof_xfr_done_wrap; 149static funcptr ndis_linksts_wrap; 150static funcptr ndis_linksts_done_wrap; 151static funcptr ndis_ticktask_wrap; 152static funcptr ndis_ifstarttask_wrap; 153static funcptr ndis_resettask_wrap; 154static funcptr ndis_inputtask_wrap; 155 156static struct ieee80211vap *ndis_vap_create(struct ieee80211com *, 157 const char [IFNAMSIZ], int, enum ieee80211_opmode, int, 158 const uint8_t [IEEE80211_ADDR_LEN], 159 const uint8_t [IEEE80211_ADDR_LEN]); 160static void ndis_vap_delete (struct ieee80211vap *); 161static void ndis_tick (void *); 162static void ndis_ticktask (device_object *, void *); 163static int ndis_raw_xmit (struct ieee80211_node *, struct mbuf *, 164 const struct ieee80211_bpf_params *); 165static void ndis_update_mcast (struct ieee80211com *); 166static void ndis_update_promisc (struct ieee80211com *); 167static void ndis_ifstart (struct ifnet *); 168static void ndis_ifstarttask (device_object *, void *); 169static void ndis_resettask (device_object *, void *); 170static void ndis_inputtask (device_object *, void *); 171static int ndis_ifioctl (struct ifnet *, u_long, caddr_t); 172static int ndis_newstate (struct ieee80211vap *, enum ieee80211_state, 173 int); 174static int ndis_nettype_chan (uint32_t); 175static int ndis_nettype_mode (uint32_t); 176static void ndis_scan (void *); 177static void ndis_scan_results (struct ndis_softc *); 178static void ndis_scan_start (struct ieee80211com *); 179static void ndis_scan_end (struct ieee80211com *); 180static void ndis_set_channel (struct ieee80211com *); 181static void ndis_scan_curchan (struct ieee80211_scan_state *, unsigned long); 182static void ndis_scan_mindwell (struct ieee80211_scan_state *); 183static void ndis_init (void *); 184static void ndis_stop (struct ndis_softc *); 185static int ndis_ifmedia_upd (struct ifnet *); 186static void ndis_ifmedia_sts (struct ifnet *, struct ifmediareq *); 187static int ndis_get_bssid_list (struct ndis_softc *, 188 ndis_80211_bssid_list_ex **); 189static int ndis_get_assoc (struct ndis_softc *, ndis_wlan_bssid_ex **); 190static int ndis_probe_offload (struct ndis_softc *); 191static int ndis_set_offload (struct ndis_softc *); 192static void ndis_getstate_80211 (struct ndis_softc *); 193static void ndis_setstate_80211 (struct ndis_softc *); 194static void ndis_auth_and_assoc (struct ndis_softc *, struct ieee80211vap *); 195static void ndis_media_status (struct ifnet *, struct ifmediareq *); 196static int ndis_set_cipher (struct ndis_softc *, int); 197static int ndis_set_wpa (struct ndis_softc *, void *, int); 198static int ndis_add_key (struct ieee80211vap *, 199 const struct ieee80211_key *); 200static int ndis_del_key (struct ieee80211vap *, 201 const struct ieee80211_key *); 202static void ndis_setmulti (struct ndis_softc *); 203static void ndis_map_sclist (void *, bus_dma_segment_t *, 204 int, bus_size_t, int); 205static int ndis_ifattach(struct ndis_softc *); 206 207static int ndis_80211attach(struct ndis_softc *); 208static int ndis_80211ioctl(struct ieee80211com *, u_long , void *); 209static int ndis_80211transmit(struct ieee80211com *, struct mbuf *); 210static void ndis_80211parent(struct ieee80211com *); 211 212static int ndisdrv_loaded = 0; 213 214/* 215 * This routine should call windrv_load() once for each driver 216 * image. This will do the relocation and dynalinking for the 217 * image, and create a Windows driver object which will be 218 * saved in our driver database. 219 */ 220int 221ndisdrv_modevent(mod, cmd, arg) 222 module_t mod; 223 int cmd; 224 void *arg; 225{ 226 int error = 0; 227 228 switch (cmd) { 229 case MOD_LOAD: 230 ndisdrv_loaded++; 231 if (ndisdrv_loaded > 1) 232 break; 233 windrv_wrap((funcptr)ndis_rxeof, &ndis_rxeof_wrap, 234 3, WINDRV_WRAP_STDCALL); 235 windrv_wrap((funcptr)ndis_rxeof_eth, &ndis_rxeof_eth_wrap, 236 8, WINDRV_WRAP_STDCALL); 237 windrv_wrap((funcptr)ndis_rxeof_done, &ndis_rxeof_done_wrap, 238 1, WINDRV_WRAP_STDCALL); 239 windrv_wrap((funcptr)ndis_rxeof_xfr, &ndis_rxeof_xfr_wrap, 240 4, WINDRV_WRAP_STDCALL); 241 windrv_wrap((funcptr)ndis_rxeof_xfr_done, 242 &ndis_rxeof_xfr_done_wrap, 4, WINDRV_WRAP_STDCALL); 243 windrv_wrap((funcptr)ndis_txeof, &ndis_txeof_wrap, 244 3, WINDRV_WRAP_STDCALL); 245 windrv_wrap((funcptr)ndis_linksts, &ndis_linksts_wrap, 246 4, WINDRV_WRAP_STDCALL); 247 windrv_wrap((funcptr)ndis_linksts_done, 248 &ndis_linksts_done_wrap, 1, WINDRV_WRAP_STDCALL); 249 windrv_wrap((funcptr)ndis_ticktask, &ndis_ticktask_wrap, 250 2, WINDRV_WRAP_STDCALL); 251 windrv_wrap((funcptr)ndis_ifstarttask, &ndis_ifstarttask_wrap, 252 2, WINDRV_WRAP_STDCALL); 253 windrv_wrap((funcptr)ndis_resettask, &ndis_resettask_wrap, 254 2, WINDRV_WRAP_STDCALL); 255 windrv_wrap((funcptr)ndis_inputtask, &ndis_inputtask_wrap, 256 2, WINDRV_WRAP_STDCALL); 257 break; 258 case MOD_UNLOAD: 259 ndisdrv_loaded--; 260 if (ndisdrv_loaded > 0) 261 break; 262 /* fallthrough */ 263 case MOD_SHUTDOWN: 264 windrv_unwrap(ndis_rxeof_wrap); 265 windrv_unwrap(ndis_rxeof_eth_wrap); 266 windrv_unwrap(ndis_rxeof_done_wrap); 267 windrv_unwrap(ndis_rxeof_xfr_wrap); 268 windrv_unwrap(ndis_rxeof_xfr_done_wrap); 269 windrv_unwrap(ndis_txeof_wrap); 270 windrv_unwrap(ndis_linksts_wrap); 271 windrv_unwrap(ndis_linksts_done_wrap); 272 windrv_unwrap(ndis_ticktask_wrap); 273 windrv_unwrap(ndis_ifstarttask_wrap); 274 windrv_unwrap(ndis_resettask_wrap); 275 windrv_unwrap(ndis_inputtask_wrap); 276 break; 277 default: 278 error = EINVAL; 279 break; 280 } 281 282 return (error); 283} 284 285/* 286 * Program the 64-bit multicast hash filter. 287 */ 288static void 289ndis_setmulti(sc) 290 struct ndis_softc *sc; 291{ 292 struct ifnet *ifp; 293 struct ifmultiaddr *ifma; 294 int len, mclistsz, error; 295 uint8_t *mclist; 296 297 298 if (!NDIS_INITIALIZED(sc)) 299 return; 300 301 if (sc->ndis_80211) 302 return; 303 304 ifp = sc->ifp; 305 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { 306 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; 307 len = sizeof(sc->ndis_filter); 308 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER, 309 &sc->ndis_filter, &len); 310 if (error) 311 device_printf(sc->ndis_dev, 312 "set allmulti failed: %d\n", error); 313 return; 314 } 315 316 if (TAILQ_EMPTY(&ifp->if_multiaddrs)) 317 return; 318 319 len = sizeof(mclistsz); 320 ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &mclistsz, &len); 321 322 mclist = malloc(ETHER_ADDR_LEN * mclistsz, M_TEMP, M_NOWAIT|M_ZERO); 323 324 if (mclist == NULL) { 325 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; 326 goto out; 327 } 328 329 sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST; 330 331 len = 0; 332 if_maddr_rlock(ifp); 333 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 334 if (ifma->ifma_addr->sa_family != AF_LINK) 335 continue; 336 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 337 mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN); 338 len++; 339 if (len > mclistsz) { 340 if_maddr_runlock(ifp); 341 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; 342 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST; 343 goto out; 344 } 345 } 346 if_maddr_runlock(ifp); 347 348 len = len * ETHER_ADDR_LEN; 349 error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len); 350 if (error) { 351 device_printf(sc->ndis_dev, "set mclist failed: %d\n", error); 352 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; 353 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST; 354 } 355 356out: 357 free(mclist, M_TEMP); 358 359 len = sizeof(sc->ndis_filter); 360 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER, 361 &sc->ndis_filter, &len); 362 if (error) 363 device_printf(sc->ndis_dev, "set multi failed: %d\n", error); 364} 365 366static int 367ndis_set_offload(sc) 368 struct ndis_softc *sc; 369{ 370 ndis_task_offload *nto; 371 ndis_task_offload_hdr *ntoh; 372 ndis_task_tcpip_csum *nttc; 373 struct ifnet *ifp; 374 int len, error; 375 376 if (!NDIS_INITIALIZED(sc)) 377 return (EINVAL); 378 379 if (sc->ndis_80211) 380 return (EINVAL); 381 /* See if there's anything to set. */ 382 383 ifp = sc->ifp; 384 error = ndis_probe_offload(sc); 385 if (error) 386 return (error); 387 388 if (sc->ndis_hwassist == 0 && ifp->if_capabilities == 0) 389 return (0); 390 391 len = sizeof(ndis_task_offload_hdr) + sizeof(ndis_task_offload) + 392 sizeof(ndis_task_tcpip_csum); 393 394 ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO); 395 396 if (ntoh == NULL) 397 return (ENOMEM); 398 399 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION; 400 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr); 401 ntoh->ntoh_offset_firsttask = sizeof(ndis_task_offload_hdr); 402 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header); 403 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3; 404 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN; 405 406 nto = (ndis_task_offload *)((char *)ntoh + 407 ntoh->ntoh_offset_firsttask); 408 409 nto->nto_vers = NDIS_TASK_OFFLOAD_VERSION; 410 nto->nto_len = sizeof(ndis_task_offload); 411 nto->nto_task = NDIS_TASK_TCPIP_CSUM; 412 nto->nto_offset_nexttask = 0; 413 nto->nto_taskbuflen = sizeof(ndis_task_tcpip_csum); 414 415 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf; 416 417 if (ifp->if_capenable & IFCAP_TXCSUM) 418 nttc->nttc_v4tx = sc->ndis_v4tx; 419 420 if (ifp->if_capenable & IFCAP_RXCSUM) 421 nttc->nttc_v4rx = sc->ndis_v4rx; 422 423 error = ndis_set_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len); 424 free(ntoh, M_TEMP); 425 426 return (error); 427} 428 429static int 430ndis_probe_offload(sc) 431 struct ndis_softc *sc; 432{ 433 ndis_task_offload *nto; 434 ndis_task_offload_hdr *ntoh; 435 ndis_task_tcpip_csum *nttc = NULL; 436 struct ifnet *ifp; 437 int len, error, dummy; 438 439 ifp = sc->ifp; 440 441 len = sizeof(dummy); 442 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, &dummy, &len); 443 444 if (error != ENOSPC) 445 return (error); 446 447 ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO); 448 449 if (ntoh == NULL) 450 return (ENOMEM); 451 452 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION; 453 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr); 454 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header); 455 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3; 456 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN; 457 458 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len); 459 460 if (error) { 461 free(ntoh, M_TEMP); 462 return (error); 463 } 464 465 if (ntoh->ntoh_vers != NDIS_TASK_OFFLOAD_VERSION) { 466 free(ntoh, M_TEMP); 467 return (EINVAL); 468 } 469 470 nto = (ndis_task_offload *)((char *)ntoh + 471 ntoh->ntoh_offset_firsttask); 472 473 while (1) { 474 switch (nto->nto_task) { 475 case NDIS_TASK_TCPIP_CSUM: 476 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf; 477 break; 478 /* Don't handle these yet. */ 479 case NDIS_TASK_IPSEC: 480 case NDIS_TASK_TCP_LARGESEND: 481 default: 482 break; 483 } 484 if (nto->nto_offset_nexttask == 0) 485 break; 486 nto = (ndis_task_offload *)((char *)nto + 487 nto->nto_offset_nexttask); 488 } 489 490 if (nttc == NULL) { 491 free(ntoh, M_TEMP); 492 return (ENOENT); 493 } 494 495 sc->ndis_v4tx = nttc->nttc_v4tx; 496 sc->ndis_v4rx = nttc->nttc_v4rx; 497 498 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_IP_CSUM) 499 sc->ndis_hwassist |= CSUM_IP; 500 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_TCP_CSUM) 501 sc->ndis_hwassist |= CSUM_TCP; 502 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_UDP_CSUM) 503 sc->ndis_hwassist |= CSUM_UDP; 504 505 if (sc->ndis_hwassist) 506 ifp->if_capabilities |= IFCAP_TXCSUM; 507 508 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_IP_CSUM) 509 ifp->if_capabilities |= IFCAP_RXCSUM; 510 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_TCP_CSUM) 511 ifp->if_capabilities |= IFCAP_RXCSUM; 512 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_UDP_CSUM) 513 ifp->if_capabilities |= IFCAP_RXCSUM; 514 515 free(ntoh, M_TEMP); 516 return (0); 517} 518 519static int 520ndis_nettype_chan(uint32_t type) 521{ 522 switch (type) { 523 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_CHAN_FHSS); 524 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_CHAN_B); 525 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_CHAN_A); 526 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_CHAN_G); 527 } 528 DPRINTF(("unknown channel nettype %d\n", type)); 529 return (IEEE80211_CHAN_B); /* Default to 11B chan */ 530} 531 532static int 533ndis_nettype_mode(uint32_t type) 534{ 535 switch (type) { 536 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_MODE_FH); 537 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_MODE_11B); 538 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_MODE_11A); 539 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_MODE_11G); 540 } 541 DPRINTF(("unknown mode nettype %d\n", type)); 542 return (IEEE80211_MODE_AUTO); 543} 544 545/* 546 * Attach the interface. Allocate softc structures, do ifmedia 547 * setup and ethernet/BPF attach. 548 */ 549int 550ndis_attach(device_t dev) 551{ 552 struct ndis_softc *sc; 553 driver_object *pdrv; 554 device_object *pdo; 555 int error = 0, len; 556 int i; 557 558 sc = device_get_softc(dev); 559 560 mtx_init(&sc->ndis_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 561 MTX_DEF); 562 KeInitializeSpinLock(&sc->ndis_rxlock); 563 KeInitializeSpinLock(&sc->ndisusb_tasklock); 564 KeInitializeSpinLock(&sc->ndisusb_xferdonelock); 565 InitializeListHead(&sc->ndis_shlist); 566 InitializeListHead(&sc->ndisusb_tasklist); 567 InitializeListHead(&sc->ndisusb_xferdonelist); 568 callout_init(&sc->ndis_stat_callout, 1); 569 mbufq_init(&sc->ndis_rxqueue, INT_MAX); /* XXXGL: sane maximum */ 570 571 if (sc->ndis_iftype == PCMCIABus) { 572 error = ndis_alloc_amem(sc); 573 if (error) { 574 device_printf(dev, "failed to allocate " 575 "attribute memory\n"); 576 goto fail; 577 } 578 } 579 580 /* Create sysctl registry nodes */ 581 ndis_create_sysctls(sc); 582 583 /* Find the PDO for this device instance. */ 584 585 if (sc->ndis_iftype == PCIBus) 586 pdrv = windrv_lookup(0, "PCI Bus"); 587 else if (sc->ndis_iftype == PCMCIABus) 588 pdrv = windrv_lookup(0, "PCCARD Bus"); 589 else 590 pdrv = windrv_lookup(0, "USB Bus"); 591 pdo = windrv_find_pdo(pdrv, dev); 592 593 /* 594 * Create a new functional device object for this 595 * device. This is what creates the miniport block 596 * for this device instance. 597 */ 598 599 if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) { 600 device_printf(dev, "failed to create FDO!\n"); 601 error = ENXIO; 602 goto fail; 603 } 604 605 /* Tell the user what version of the API the driver is using. */ 606 device_printf(dev, "NDIS API version: %d.%d\n", 607 sc->ndis_chars->nmc_version_major, 608 sc->ndis_chars->nmc_version_minor); 609 610 /* Do resource conversion. */ 611 if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus) 612 ndis_convert_res(sc); 613 else 614 sc->ndis_block->nmb_rlist = NULL; 615 616 /* Install our RX and TX interrupt handlers. */ 617 sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap; 618 sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap; 619 sc->ndis_block->nmb_ethrxindicate_func = ndis_rxeof_eth_wrap; 620 sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap; 621 sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap; 622 623 /* Override the status handler so we can detect link changes. */ 624 sc->ndis_block->nmb_status_func = ndis_linksts_wrap; 625 sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap; 626 627 /* Set up work item handlers. */ 628 sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); 629 sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); 630 sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); 631 sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); 632 sc->ndisusb_xferdoneitem = 633 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); 634 sc->ndisusb_taskitem = 635 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); 636 KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block); 637 638 /* Call driver's init routine. */ 639 if (ndis_init_nic(sc)) { 640 device_printf(dev, "init handler failed\n"); 641 error = ENXIO; 642 goto fail; 643 } 644 645 /* 646 * Figure out how big to make the TX buffer pool. 647 */ 648 len = sizeof(sc->ndis_maxpkts); 649 if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS, 650 &sc->ndis_maxpkts, &len)) { 651 device_printf(dev, "failed to get max TX packets\n"); 652 error = ENXIO; 653 goto fail; 654 } 655 656 /* 657 * If this is a deserialized miniport, we don't have 658 * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result. 659 */ 660 if (!NDIS_SERIALIZED(sc->ndis_block)) 661 sc->ndis_maxpkts = NDIS_TXPKTS; 662 663 /* Enforce some sanity, just in case. */ 664 665 if (sc->ndis_maxpkts == 0) 666 sc->ndis_maxpkts = 10; 667 668 sc->ndis_txarray = malloc(sizeof(ndis_packet *) * 669 sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO); 670 671 /* Allocate a pool of ndis_packets for TX encapsulation. */ 672 673 NdisAllocatePacketPool(&i, &sc->ndis_txpool, 674 sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET); 675 676 if (i != NDIS_STATUS_SUCCESS) { 677 sc->ndis_txpool = NULL; 678 device_printf(dev, "failed to allocate TX packet pool"); 679 error = ENOMEM; 680 goto fail; 681 } 682 683 sc->ndis_txpending = sc->ndis_maxpkts; 684 685 sc->ndis_oidcnt = 0; 686 /* Get supported oid list. */ 687 ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt); 688 689 /* If the NDIS module requested scatter/gather, init maps. */ 690 if (sc->ndis_sc) 691 ndis_init_dma(sc); 692 693 /* 694 * See if the OID_802_11_CONFIGURATION OID is 695 * supported by this driver. If it is, then this an 802.11 696 * wireless driver, and we should set up media for wireless. 697 */ 698 for (i = 0; i < sc->ndis_oidcnt; i++) 699 if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) { 700 sc->ndis_80211 = 1; 701 break; 702 } 703 704 if (sc->ndis_80211) 705 error = ndis_80211attach(sc); 706 else 707 error = ndis_ifattach(sc); 708 709fail: 710 if (error) { 711 ndis_detach(dev); 712 return (error); 713 } 714 715 if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0) 716 return (error); 717 718 DPRINTF(("attach done.\n")); 719 /* We're done talking to the NIC for now; halt it. */ 720 ndis_halt_nic(sc); 721 DPRINTF(("halting done.\n")); 722 723 return (error); 724} 725 726static int 727ndis_80211attach(struct ndis_softc *sc) 728{ 729 struct ieee80211com *ic = &sc->ndis_ic; 730 ndis_80211_rates_ex rates; 731 struct ndis_80211_nettype_list *ntl; 732 uint32_t arg; 733 int mode, i, r, len, nonettypes = 1; 734 uint8_t bands[IEEE80211_MODE_BYTES] = { 0 }; 735 736 callout_init(&sc->ndis_scan_callout, 1); 737 738 ic->ic_softc = sc; 739 ic->ic_ioctl = ndis_80211ioctl; 740 ic->ic_name = device_get_nameunit(sc->ndis_dev); 741 ic->ic_opmode = IEEE80211_M_STA; 742 ic->ic_phytype = IEEE80211_T_DS; 743 ic->ic_caps = IEEE80211_C_8023ENCAP | 744 IEEE80211_C_STA | IEEE80211_C_IBSS; 745 setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO); 746 len = 0; 747 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, NULL, &len); 748 if (r != ENOSPC) 749 goto nonettypes; 750 ntl = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 751 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, ntl, &len); 752 if (r != 0) { 753 free(ntl, M_DEVBUF); 754 goto nonettypes; 755 } 756 757 for (i = 0; i < ntl->ntl_items; i++) { 758 mode = ndis_nettype_mode(ntl->ntl_type[i]); 759 if (mode) { 760 nonettypes = 0; 761 setbit(ic->ic_modecaps, mode); 762 setbit(bands, mode); 763 } else 764 device_printf(sc->ndis_dev, "Unknown nettype %d\n", 765 ntl->ntl_type[i]); 766 } 767 free(ntl, M_DEVBUF); 768nonettypes: 769 /* Default to 11b channels if the card did not supply any */ 770 if (nonettypes) { 771 setbit(ic->ic_modecaps, IEEE80211_MODE_11B); 772 setbit(bands, IEEE80211_MODE_11B); 773 } 774 len = sizeof(rates); 775 bzero((char *)&rates, len); 776 r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len); 777 if (r != 0) 778 device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r); 779 /* 780 * Since the supported rates only up to 8 can be supported, 781 * if this is not 802.11b we're just going to be faking it 782 * all up to heck. 783 */ 784 785#define TESTSETRATE(x, y) \ 786 do { \ 787 int i; \ 788 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \ 789 if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \ 790 break; \ 791 } \ 792 if (i == ic->ic_sup_rates[x].rs_nrates) { \ 793 ic->ic_sup_rates[x].rs_rates[i] = (y); \ 794 ic->ic_sup_rates[x].rs_nrates++; \ 795 } \ 796 } while (0) 797 798#define SETRATE(x, y) \ 799 ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y) 800#define INCRATE(x) \ 801 ic->ic_sup_rates[x].rs_nrates++ 802 803 ic->ic_curmode = IEEE80211_MODE_AUTO; 804 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) 805 ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0; 806 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) 807 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0; 808 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) 809 ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0; 810 for (i = 0; i < len; i++) { 811 switch (rates[i] & IEEE80211_RATE_VAL) { 812 case 2: 813 case 4: 814 case 11: 815 case 10: 816 case 22: 817 if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) { 818 /* Lazy-init 802.11b. */ 819 setbit(ic->ic_modecaps, IEEE80211_MODE_11B); 820 ic->ic_sup_rates[IEEE80211_MODE_11B]. 821 rs_nrates = 0; 822 } 823 SETRATE(IEEE80211_MODE_11B, rates[i]); 824 INCRATE(IEEE80211_MODE_11B); 825 break; 826 default: 827 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) { 828 SETRATE(IEEE80211_MODE_11A, rates[i]); 829 INCRATE(IEEE80211_MODE_11A); 830 } 831 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) { 832 SETRATE(IEEE80211_MODE_11G, rates[i]); 833 INCRATE(IEEE80211_MODE_11G); 834 } 835 break; 836 } 837 } 838 839 /* 840 * If the hardware supports 802.11g, it most 841 * likely supports 802.11b and all of the 842 * 802.11b and 802.11g speeds, so maybe we can 843 * just cheat here. Just how in the heck do 844 * we detect turbo modes, though? 845 */ 846 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) { 847 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|2); 848 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|4); 849 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|11); 850 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|22); 851 } 852 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) { 853 TESTSETRATE(IEEE80211_MODE_11G, 48); 854 TESTSETRATE(IEEE80211_MODE_11G, 72); 855 TESTSETRATE(IEEE80211_MODE_11G, 96); 856 TESTSETRATE(IEEE80211_MODE_11G, 108); 857 } 858 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) { 859 TESTSETRATE(IEEE80211_MODE_11A, 48); 860 TESTSETRATE(IEEE80211_MODE_11A, 72); 861 TESTSETRATE(IEEE80211_MODE_11A, 96); 862 TESTSETRATE(IEEE80211_MODE_11A, 108); 863 } 864 865#undef SETRATE 866#undef INCRATE 867#undef TESTSETRATE 868 869 ieee80211_init_channels(ic, NULL, bands); 870 871 /* 872 * To test for WPA support, we need to see if we can 873 * set AUTHENTICATION_MODE to WPA and read it back 874 * successfully. 875 */ 876 i = sizeof(arg); 877 arg = NDIS_80211_AUTHMODE_WPA; 878 r = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i); 879 if (r == 0) { 880 r = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i); 881 if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA) 882 ic->ic_caps |= IEEE80211_C_WPA; 883 } 884 885 /* 886 * To test for supported ciphers, we set each 887 * available encryption type in descending order. 888 * If ENC3 works, then we have WEP, TKIP and AES. 889 * If only ENC2 works, then we have WEP and TKIP. 890 * If only ENC1 works, then we have just WEP. 891 */ 892 i = sizeof(arg); 893 arg = NDIS_80211_WEPSTAT_ENC3ENABLED; 894 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i); 895 if (r == 0) { 896 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP 897 | IEEE80211_CRYPTO_TKIP 898 | IEEE80211_CRYPTO_AES_CCM; 899 goto got_crypto; 900 } 901 arg = NDIS_80211_WEPSTAT_ENC2ENABLED; 902 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i); 903 if (r == 0) { 904 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP 905 | IEEE80211_CRYPTO_TKIP; 906 goto got_crypto; 907 } 908 arg = NDIS_80211_WEPSTAT_ENC1ENABLED; 909 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i); 910 if (r == 0) 911 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP; 912got_crypto: 913 i = sizeof(arg); 914 r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i); 915 if (r == 0) 916 ic->ic_caps |= IEEE80211_C_PMGT; 917 918 r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i); 919 if (r == 0) 920 ic->ic_caps |= IEEE80211_C_TXPMGT; 921 922 /* 923 * Get station address from the driver. 924 */ 925 len = sizeof(ic->ic_macaddr); 926 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &ic->ic_macaddr, &len); 927 928 ieee80211_ifattach(ic); 929 ic->ic_raw_xmit = ndis_raw_xmit; 930 ic->ic_scan_start = ndis_scan_start; 931 ic->ic_scan_end = ndis_scan_end; 932 ic->ic_set_channel = ndis_set_channel; 933 ic->ic_scan_curchan = ndis_scan_curchan; 934 ic->ic_scan_mindwell = ndis_scan_mindwell; 935 ic->ic_bsschan = IEEE80211_CHAN_ANYC; 936 ic->ic_vap_create = ndis_vap_create; 937 ic->ic_vap_delete = ndis_vap_delete; 938 ic->ic_update_mcast = ndis_update_mcast; 939 ic->ic_update_promisc = ndis_update_promisc; 940 ic->ic_transmit = ndis_80211transmit; 941 ic->ic_parent = ndis_80211parent; 942 943 if (bootverbose) 944 ieee80211_announce(ic); 945 946 return (0); 947} 948 949static int 950ndis_ifattach(struct ndis_softc *sc) 951{ 952 struct ifnet *ifp; 953 u_char eaddr[ETHER_ADDR_LEN]; 954 int len; 955 956 ifp = if_alloc(IFT_ETHER); 957 if (ifp == NULL) 958 return (ENOSPC); 959 sc->ifp = ifp; 960 ifp->if_softc = sc; 961 962 /* Check for task offload support. */ 963 ndis_probe_offload(sc); 964 965 /* 966 * Get station address from the driver. 967 */ 968 len = sizeof(eaddr); 969 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, eaddr, &len); 970 971 if_initname(ifp, device_get_name(sc->ndis_dev), 972 device_get_unit(sc->ndis_dev)); 973 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 974 ifp->if_ioctl = ndis_ifioctl; 975 ifp->if_start = ndis_ifstart; 976 ifp->if_init = ndis_init; 977 ifp->if_baudrate = 10000000; 978 IFQ_SET_MAXLEN(&ifp->if_snd, 50); 979 ifp->if_snd.ifq_drv_maxlen = 25; 980 IFQ_SET_READY(&ifp->if_snd); 981 ifp->if_capenable = ifp->if_capabilities; 982 ifp->if_hwassist = sc->ndis_hwassist; 983 984 ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd, 985 ndis_ifmedia_sts); 986 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL); 987 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); 988 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL); 989 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); 990 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); 991 ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO); 992 ether_ifattach(ifp, eaddr); 993 994 return (0); 995} 996 997static struct ieee80211vap * 998ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, 999 enum ieee80211_opmode opmode, int flags, 1000 const uint8_t bssid[IEEE80211_ADDR_LEN], 1001 const uint8_t mac[IEEE80211_ADDR_LEN]) 1002{ 1003 struct ndis_vap *nvp; 1004 struct ieee80211vap *vap; 1005 1006 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ 1007 return NULL; 1008 nvp = malloc(sizeof(struct ndis_vap), M_80211_VAP, M_WAITOK | M_ZERO); 1009 vap = &nvp->vap; 1010 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); 1011 /* override with driver methods */ 1012 nvp->newstate = vap->iv_newstate; 1013 vap->iv_newstate = ndis_newstate; 1014 1015 /* complete setup */ 1016 ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status, 1017 mac); 1018 ic->ic_opmode = opmode; 1019 /* install key handing routines */ 1020 vap->iv_key_set = ndis_add_key; 1021 vap->iv_key_delete = ndis_del_key; 1022 return vap; 1023} 1024 1025static void 1026ndis_vap_delete(struct ieee80211vap *vap) 1027{ 1028 struct ndis_vap *nvp = NDIS_VAP(vap); 1029 struct ieee80211com *ic = vap->iv_ic; 1030 struct ndis_softc *sc = ic->ic_softc; 1031 1032 ndis_stop(sc); 1033 callout_drain(&sc->ndis_scan_callout); 1034 ieee80211_vap_detach(vap); 1035 free(nvp, M_80211_VAP); 1036} 1037 1038/* 1039 * Shutdown hardware and free up resources. This can be called any 1040 * time after the mutex has been initialized. It is called in both 1041 * the error case in attach and the normal detach case so it needs 1042 * to be careful about only freeing resources that have actually been 1043 * allocated. 1044 */ 1045int 1046ndis_detach(device_t dev) 1047{ 1048 struct ifnet *ifp; 1049 struct ndis_softc *sc; 1050 driver_object *drv; 1051 1052 sc = device_get_softc(dev); 1053 NDIS_LOCK(sc); 1054 if (!sc->ndis_80211) 1055 ifp = sc->ifp; 1056 else 1057 ifp = NULL; 1058 if (ifp != NULL) 1059 ifp->if_flags &= ~IFF_UP; 1060 if (device_is_attached(dev)) { 1061 NDIS_UNLOCK(sc); 1062 ndis_stop(sc); 1063 if (sc->ndis_80211) 1064 ieee80211_ifdetach(&sc->ndis_ic); 1065 else if (ifp != NULL) 1066 ether_ifdetach(ifp); 1067 } else 1068 NDIS_UNLOCK(sc); 1069 1070 if (sc->ndis_tickitem != NULL) 1071 IoFreeWorkItem(sc->ndis_tickitem); 1072 if (sc->ndis_startitem != NULL) 1073 IoFreeWorkItem(sc->ndis_startitem); 1074 if (sc->ndis_resetitem != NULL) 1075 IoFreeWorkItem(sc->ndis_resetitem); 1076 if (sc->ndis_inputitem != NULL) 1077 IoFreeWorkItem(sc->ndis_inputitem); 1078 if (sc->ndisusb_xferdoneitem != NULL) 1079 IoFreeWorkItem(sc->ndisusb_xferdoneitem); 1080 if (sc->ndisusb_taskitem != NULL) 1081 IoFreeWorkItem(sc->ndisusb_taskitem); 1082 1083 bus_generic_detach(dev); 1084 ndis_unload_driver(sc); 1085 1086 if (sc->ndis_irq) 1087 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq); 1088 if (sc->ndis_res_io) 1089 bus_release_resource(dev, SYS_RES_IOPORT, 1090 sc->ndis_io_rid, sc->ndis_res_io); 1091 if (sc->ndis_res_mem) 1092 bus_release_resource(dev, SYS_RES_MEMORY, 1093 sc->ndis_mem_rid, sc->ndis_res_mem); 1094 if (sc->ndis_res_altmem) 1095 bus_release_resource(dev, SYS_RES_MEMORY, 1096 sc->ndis_altmem_rid, sc->ndis_res_altmem); 1097 1098 if (ifp != NULL) 1099 if_free(ifp); 1100 1101 if (sc->ndis_iftype == PCMCIABus) 1102 ndis_free_amem(sc); 1103 1104 if (sc->ndis_sc) 1105 ndis_destroy_dma(sc); 1106 1107 if (sc->ndis_txarray) 1108 free(sc->ndis_txarray, M_DEVBUF); 1109 1110 if (!sc->ndis_80211) 1111 ifmedia_removeall(&sc->ifmedia); 1112 1113 if (sc->ndis_txpool != NULL) 1114 NdisFreePacketPool(sc->ndis_txpool); 1115 1116 /* Destroy the PDO for this device. */ 1117 1118 if (sc->ndis_iftype == PCIBus) 1119 drv = windrv_lookup(0, "PCI Bus"); 1120 else if (sc->ndis_iftype == PCMCIABus) 1121 drv = windrv_lookup(0, "PCCARD Bus"); 1122 else 1123 drv = windrv_lookup(0, "USB Bus"); 1124 if (drv == NULL) 1125 panic("couldn't find driver object"); 1126 windrv_destroy_pdo(drv, dev); 1127 1128 if (sc->ndis_iftype == PCIBus) 1129 bus_dma_tag_destroy(sc->ndis_parent_tag); 1130 1131 return (0); 1132} 1133 1134int 1135ndis_suspend(dev) 1136 device_t dev; 1137{ 1138 struct ndis_softc *sc; 1139 struct ifnet *ifp; 1140 1141 sc = device_get_softc(dev); 1142 ifp = sc->ifp; 1143 1144#ifdef notdef 1145 if (NDIS_INITIALIZED(sc)) 1146 ndis_stop(sc); 1147#endif 1148 1149 return (0); 1150} 1151 1152int 1153ndis_resume(dev) 1154 device_t dev; 1155{ 1156 struct ndis_softc *sc; 1157 struct ifnet *ifp; 1158 1159 sc = device_get_softc(dev); 1160 ifp = sc->ifp; 1161 1162 if (NDIS_INITIALIZED(sc)) 1163 ndis_init(sc); 1164 1165 return (0); 1166} 1167 1168/* 1169 * The following bunch of routines are here to support drivers that 1170 * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism. 1171 * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for 1172 * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized 1173 * miniports. 1174 */ 1175static void 1176ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen) 1177 ndis_handle adapter; 1178 ndis_handle ctx; 1179 char *addr; 1180 void *hdr; 1181 uint32_t hdrlen; 1182 void *lookahead; 1183 uint32_t lookaheadlen; 1184 uint32_t pktlen; 1185{ 1186 ndis_miniport_block *block; 1187 uint8_t irql = 0; 1188 uint32_t status; 1189 ndis_buffer *b; 1190 ndis_packet *p; 1191 struct mbuf *m; 1192 ndis_ethpriv *priv; 1193 1194 block = adapter; 1195 1196 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 1197 if (m == NULL) 1198 return; 1199 1200 /* Save the data provided to us so far. */ 1201 1202 m->m_len = lookaheadlen + hdrlen; 1203 m->m_pkthdr.len = pktlen + hdrlen; 1204 m->m_next = NULL; 1205 m_copyback(m, 0, hdrlen, hdr); 1206 m_copyback(m, hdrlen, lookaheadlen, lookahead); 1207 1208 /* Now create a fake NDIS_PACKET to hold the data */ 1209 1210 NdisAllocatePacket(&status, &p, block->nmb_rxpool); 1211 1212 if (status != NDIS_STATUS_SUCCESS) { 1213 m_freem(m); 1214 return; 1215 } 1216 1217 p->np_m0 = m; 1218 1219 b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL); 1220 1221 if (b == NULL) { 1222 NdisFreePacket(p); 1223 m_freem(m); 1224 return; 1225 } 1226 1227 p->np_private.npp_head = p->np_private.npp_tail = b; 1228 p->np_private.npp_totlen = m->m_pkthdr.len; 1229 1230 /* Save the packet RX context somewhere. */ 1231 priv = (ndis_ethpriv *)&p->np_protocolreserved; 1232 priv->nep_ctx = ctx; 1233 1234 if (!NDIS_SERIALIZED(block)) 1235 KeAcquireSpinLock(&block->nmb_lock, &irql); 1236 1237 InsertTailList((&block->nmb_packetlist), (&p->np_list)); 1238 1239 if (!NDIS_SERIALIZED(block)) 1240 KeReleaseSpinLock(&block->nmb_lock, irql); 1241} 1242 1243/* 1244 * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL 1245 * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized 1246 * miniports. 1247 */ 1248static void 1249ndis_rxeof_done(adapter) 1250 ndis_handle adapter; 1251{ 1252 struct ndis_softc *sc; 1253 ndis_miniport_block *block; 1254 1255 block = adapter; 1256 1257 /* Schedule transfer/RX of queued packets. */ 1258 1259 sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1260 1261 KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL); 1262} 1263 1264/* 1265 * MiniportTransferData() handler, runs at DISPATCH_LEVEL. 1266 */ 1267static void 1268ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2) 1269 kdpc *dpc; 1270 ndis_handle adapter; 1271 void *sysarg1; 1272 void *sysarg2; 1273{ 1274 ndis_miniport_block *block; 1275 struct ndis_softc *sc; 1276 ndis_packet *p; 1277 list_entry *l; 1278 uint32_t status; 1279 ndis_ethpriv *priv; 1280 struct ifnet *ifp; 1281 struct mbuf *m; 1282 1283 block = adapter; 1284 sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1285 ifp = sc->ifp; 1286 1287 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock); 1288 1289 l = block->nmb_packetlist.nle_flink; 1290 while(!IsListEmpty(&block->nmb_packetlist)) { 1291 l = RemoveHeadList((&block->nmb_packetlist)); 1292 p = CONTAINING_RECORD(l, ndis_packet, np_list); 1293 InitializeListHead((&p->np_list)); 1294 1295 priv = (ndis_ethpriv *)&p->np_protocolreserved; 1296 m = p->np_m0; 1297 p->np_softc = sc; 1298 p->np_m0 = NULL; 1299 1300 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock); 1301 1302 status = MSCALL6(sc->ndis_chars->nmc_transferdata_func, 1303 p, &p->np_private.npp_totlen, block, priv->nep_ctx, 1304 m->m_len, m->m_pkthdr.len - m->m_len); 1305 1306 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock); 1307 1308 /* 1309 * If status is NDIS_STATUS_PENDING, do nothing and 1310 * wait for a callback to the ndis_rxeof_xfr_done() 1311 * handler. 1312 */ 1313 1314 m->m_len = m->m_pkthdr.len; 1315 m->m_pkthdr.rcvif = ifp; 1316 1317 if (status == NDIS_STATUS_SUCCESS) { 1318 IoFreeMdl(p->np_private.npp_head); 1319 NdisFreePacket(p); 1320 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock); 1321 mbufq_enqueue(&sc->ndis_rxqueue, m); 1322 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock); 1323 IoQueueWorkItem(sc->ndis_inputitem, 1324 (io_workitem_func)ndis_inputtask_wrap, 1325 WORKQUEUE_CRITICAL, sc); 1326 } 1327 1328 if (status == NDIS_STATUS_FAILURE) 1329 m_freem(m); 1330 1331 /* Advance to next packet */ 1332 l = block->nmb_packetlist.nle_flink; 1333 } 1334 1335 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock); 1336} 1337 1338/* 1339 * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL. 1340 */ 1341static void 1342ndis_rxeof_xfr_done(adapter, packet, status, len) 1343 ndis_handle adapter; 1344 ndis_packet *packet; 1345 uint32_t status; 1346 uint32_t len; 1347{ 1348 ndis_miniport_block *block; 1349 struct ndis_softc *sc; 1350 struct ifnet *ifp; 1351 struct mbuf *m; 1352 1353 block = adapter; 1354 sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1355 ifp = sc->ifp; 1356 1357 m = packet->np_m0; 1358 IoFreeMdl(packet->np_private.npp_head); 1359 NdisFreePacket(packet); 1360 1361 if (status != NDIS_STATUS_SUCCESS) { 1362 m_freem(m); 1363 return; 1364 } 1365 1366 m->m_len = m->m_pkthdr.len; 1367 m->m_pkthdr.rcvif = ifp; 1368 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock); 1369 mbufq_enqueue(&sc->ndis_rxqueue, m); 1370 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock); 1371 IoQueueWorkItem(sc->ndis_inputitem, 1372 (io_workitem_func)ndis_inputtask_wrap, 1373 WORKQUEUE_CRITICAL, sc); 1374} 1375/* 1376 * A frame has been uploaded: pass the resulting mbuf chain up to 1377 * the higher level protocols. 1378 * 1379 * When handling received NDIS packets, the 'status' field in the 1380 * out-of-band portion of the ndis_packet has special meaning. In the 1381 * most common case, the underlying NDIS driver will set this field 1382 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to 1383 * take possession of it. We then change the status field to 1384 * NDIS_STATUS_PENDING to tell the driver that we now own the packet, 1385 * and that we will return it at some point in the future via the 1386 * return packet handler. 1387 * 1388 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES, 1389 * this means the driver is running out of packet/buffer resources and 1390 * wants to maintain ownership of the packet. In this case, we have to 1391 * copy the packet data into local storage and let the driver keep the 1392 * packet. 1393 */ 1394static void 1395ndis_rxeof(adapter, packets, pktcnt) 1396 ndis_handle adapter; 1397 ndis_packet **packets; 1398 uint32_t pktcnt; 1399{ 1400 struct ndis_softc *sc; 1401 ndis_miniport_block *block; 1402 ndis_packet *p; 1403 uint32_t s; 1404 ndis_tcpip_csum *csum; 1405 struct ifnet *ifp; 1406 struct mbuf *m0, *m; 1407 int i; 1408 1409 block = (ndis_miniport_block *)adapter; 1410 sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1411 ifp = sc->ifp; 1412 1413 /* 1414 * There's a slim chance the driver may indicate some packets 1415 * before we're completely ready to handle them. If we detect this, 1416 * we need to return them to the miniport and ignore them. 1417 */ 1418 if (!sc->ndis_running) { 1419 for (i = 0; i < pktcnt; i++) { 1420 p = packets[i]; 1421 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) { 1422 p->np_refcnt++; 1423 (void)ndis_return_packet(NULL ,p, block); 1424 } 1425 } 1426 return; 1427 } 1428 1429 for (i = 0; i < pktcnt; i++) { 1430 p = packets[i]; 1431 /* Stash the softc here so ptom can use it. */ 1432 p->np_softc = sc; 1433 if (ndis_ptom(&m0, p)) { 1434 device_printf(sc->ndis_dev, "ptom failed\n"); 1435 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) 1436 (void)ndis_return_packet(NULL, p, block); 1437 } else { 1438#ifdef notdef 1439 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) { 1440 m = m_dup(m0, M_NOWAIT); 1441 /* 1442 * NOTE: we want to destroy the mbuf here, but 1443 * we don't actually want to return it to the 1444 * driver via the return packet handler. By 1445 * bumping np_refcnt, we can prevent the 1446 * ndis_return_packet() routine from actually 1447 * doing anything. 1448 */ 1449 p->np_refcnt++; 1450 m_freem(m0); 1451 if (m == NULL) 1452 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 1453 else 1454 m0 = m; 1455 } else 1456 p->np_oob.npo_status = NDIS_STATUS_PENDING; 1457#endif 1458 m = m_dup(m0, M_NOWAIT); 1459 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) 1460 p->np_refcnt++; 1461 else 1462 p->np_oob.npo_status = NDIS_STATUS_PENDING; 1463 m_freem(m0); 1464 if (m == NULL) { 1465 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 1466 continue; 1467 } 1468 m0 = m; 1469 m0->m_pkthdr.rcvif = ifp; 1470 1471 /* Deal with checksum offload. */ 1472 1473 if (ifp->if_capenable & IFCAP_RXCSUM && 1474 p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) { 1475 s = (uintptr_t) 1476 p->np_ext.npe_info[ndis_tcpipcsum_info]; 1477 csum = (ndis_tcpip_csum *)&s; 1478 if (csum->u.ntc_rxflags & 1479 NDIS_RXCSUM_IP_PASSED) 1480 m0->m_pkthdr.csum_flags |= 1481 CSUM_IP_CHECKED|CSUM_IP_VALID; 1482 if (csum->u.ntc_rxflags & 1483 (NDIS_RXCSUM_TCP_PASSED | 1484 NDIS_RXCSUM_UDP_PASSED)) { 1485 m0->m_pkthdr.csum_flags |= 1486 CSUM_DATA_VALID|CSUM_PSEUDO_HDR; 1487 m0->m_pkthdr.csum_data = 0xFFFF; 1488 } 1489 } 1490 1491 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock); 1492 mbufq_enqueue(&sc->ndis_rxqueue, m0); 1493 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock); 1494 IoQueueWorkItem(sc->ndis_inputitem, 1495 (io_workitem_func)ndis_inputtask_wrap, 1496 WORKQUEUE_CRITICAL, sc); 1497 } 1498 } 1499} 1500 1501/* 1502 * This routine is run at PASSIVE_LEVEL. We use this routine to pass 1503 * packets into the stack in order to avoid calling (*ifp->if_input)() 1504 * with any locks held (at DISPATCH_LEVEL, we'll be holding the 1505 * 'dispatch level' per-cpu sleep lock). 1506 */ 1507static void 1508ndis_inputtask(device_object *dobj, void *arg) 1509{ 1510 ndis_miniport_block *block; 1511 struct ndis_softc *sc = arg; 1512 struct mbuf *m; 1513 uint8_t irql; 1514 1515 block = dobj->do_devext; 1516 1517 KeAcquireSpinLock(&sc->ndis_rxlock, &irql); 1518 while ((m = mbufq_dequeue(&sc->ndis_rxqueue)) != NULL) { 1519 KeReleaseSpinLock(&sc->ndis_rxlock, irql); 1520 if ((sc->ndis_80211 != 0)) { 1521 struct ieee80211com *ic = &sc->ndis_ic; 1522 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); 1523 1524 if (vap != NULL) 1525 vap->iv_deliver_data(vap, vap->iv_bss, m); 1526 } else { 1527 struct ifnet *ifp = sc->ifp; 1528 1529 (*ifp->if_input)(ifp, m); 1530 } 1531 KeAcquireSpinLock(&sc->ndis_rxlock, &irql); 1532 } 1533 KeReleaseSpinLock(&sc->ndis_rxlock, irql); 1534} 1535 1536/* 1537 * A frame was downloaded to the chip. It's safe for us to clean up 1538 * the list buffers. 1539 */ 1540static void 1541ndis_txeof(adapter, packet, status) 1542 ndis_handle adapter; 1543 ndis_packet *packet; 1544 ndis_status status; 1545 1546{ 1547 struct ndis_softc *sc; 1548 ndis_miniport_block *block; 1549 struct ifnet *ifp; 1550 int idx; 1551 struct mbuf *m; 1552 1553 block = (ndis_miniport_block *)adapter; 1554 sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1555 ifp = sc->ifp; 1556 1557 m = packet->np_m0; 1558 idx = packet->np_txidx; 1559 if (sc->ndis_sc) 1560 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]); 1561 1562 ndis_free_packet(packet); 1563 m_freem(m); 1564 1565 NDIS_LOCK(sc); 1566 sc->ndis_txarray[idx] = NULL; 1567 sc->ndis_txpending++; 1568 1569 if (!sc->ndis_80211) { 1570 struct ifnet *ifp = sc->ifp; 1571 if (status == NDIS_STATUS_SUCCESS) 1572 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 1573 else 1574 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 1575 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1576 } 1577 sc->ndis_tx_timer = 0; 1578 1579 NDIS_UNLOCK(sc); 1580 1581 if (!sc->ndis_80211) 1582 IoQueueWorkItem(sc->ndis_startitem, 1583 (io_workitem_func)ndis_ifstarttask_wrap, 1584 WORKQUEUE_CRITICAL, sc); 1585 DPRINTF(("%s: ndis_ifstarttask_wrap sc=%p\n", __func__, sc)); 1586} 1587 1588static void 1589ndis_linksts(adapter, status, sbuf, slen) 1590 ndis_handle adapter; 1591 ndis_status status; 1592 void *sbuf; 1593 uint32_t slen; 1594{ 1595 ndis_miniport_block *block; 1596 struct ndis_softc *sc; 1597 1598 block = adapter; 1599 sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1600 sc->ndis_sts = status; 1601 1602 /* Event list is all full up, drop this one. */ 1603 1604 NDIS_LOCK(sc); 1605 if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) { 1606 NDIS_UNLOCK(sc); 1607 return; 1608 } 1609 1610 /* Cache the event. */ 1611 1612 if (slen) { 1613 sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen, 1614 M_TEMP, M_NOWAIT); 1615 if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) { 1616 NDIS_UNLOCK(sc); 1617 return; 1618 } 1619 bcopy((char *)sbuf, 1620 sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen); 1621 } 1622 sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status; 1623 sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen; 1624 NDIS_EVTINC(sc->ndis_evtpidx); 1625 NDIS_UNLOCK(sc); 1626} 1627 1628static void 1629ndis_linksts_done(adapter) 1630 ndis_handle adapter; 1631{ 1632 ndis_miniport_block *block; 1633 struct ndis_softc *sc; 1634 struct ifnet *ifp; 1635 1636 block = adapter; 1637 sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1638 ifp = sc->ifp; 1639 1640 if (!NDIS_INITIALIZED(sc)) 1641 return; 1642 1643 switch (sc->ndis_sts) { 1644 case NDIS_STATUS_MEDIA_CONNECT: 1645 IoQueueWorkItem(sc->ndis_tickitem, 1646 (io_workitem_func)ndis_ticktask_wrap, 1647 WORKQUEUE_CRITICAL, sc); 1648 if (!sc->ndis_80211) 1649 IoQueueWorkItem(sc->ndis_startitem, 1650 (io_workitem_func)ndis_ifstarttask_wrap, 1651 WORKQUEUE_CRITICAL, sc); 1652 break; 1653 case NDIS_STATUS_MEDIA_DISCONNECT: 1654 if (sc->ndis_link) 1655 IoQueueWorkItem(sc->ndis_tickitem, 1656 (io_workitem_func)ndis_ticktask_wrap, 1657 WORKQUEUE_CRITICAL, sc); 1658 break; 1659 default: 1660 break; 1661 } 1662} 1663 1664static void 1665ndis_tick(xsc) 1666 void *xsc; 1667{ 1668 struct ndis_softc *sc; 1669 1670 sc = xsc; 1671 1672 if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) { 1673 IoQueueWorkItem(sc->ndis_tickitem, 1674 (io_workitem_func)ndis_ticktask_wrap, 1675 WORKQUEUE_CRITICAL, sc); 1676 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs; 1677 } 1678 1679 if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) { 1680 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1); 1681 device_printf(sc->ndis_dev, "watchdog timeout\n"); 1682 1683 IoQueueWorkItem(sc->ndis_resetitem, 1684 (io_workitem_func)ndis_resettask_wrap, 1685 WORKQUEUE_CRITICAL, sc); 1686 if (!sc->ndis_80211) 1687 IoQueueWorkItem(sc->ndis_startitem, 1688 (io_workitem_func)ndis_ifstarttask_wrap, 1689 WORKQUEUE_CRITICAL, sc); 1690 } 1691 1692 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc); 1693} 1694 1695static void 1696ndis_ticktask(device_object *d, void *xsc) 1697{ 1698 struct ndis_softc *sc = xsc; 1699 ndis_checkforhang_handler hangfunc; 1700 uint8_t rval; 1701 1702 NDIS_LOCK(sc); 1703 if (!NDIS_INITIALIZED(sc)) { 1704 NDIS_UNLOCK(sc); 1705 return; 1706 } 1707 NDIS_UNLOCK(sc); 1708 1709 hangfunc = sc->ndis_chars->nmc_checkhang_func; 1710 1711 if (hangfunc != NULL) { 1712 rval = MSCALL1(hangfunc, 1713 sc->ndis_block->nmb_miniportadapterctx); 1714 if (rval == TRUE) { 1715 ndis_reset_nic(sc); 1716 return; 1717 } 1718 } 1719 1720 NDIS_LOCK(sc); 1721 if (sc->ndis_link == 0 && 1722 sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) { 1723 sc->ndis_link = 1; 1724 if (sc->ndis_80211 != 0) { 1725 struct ieee80211com *ic = &sc->ndis_ic; 1726 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); 1727 1728 if (vap != NULL) { 1729 NDIS_UNLOCK(sc); 1730 ndis_getstate_80211(sc); 1731 ieee80211_new_state(vap, IEEE80211_S_RUN, -1); 1732 NDIS_LOCK(sc); 1733 if_link_state_change(vap->iv_ifp, 1734 LINK_STATE_UP); 1735 } 1736 } else 1737 if_link_state_change(sc->ifp, LINK_STATE_UP); 1738 } 1739 1740 if (sc->ndis_link == 1 && 1741 sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) { 1742 sc->ndis_link = 0; 1743 if (sc->ndis_80211 != 0) { 1744 struct ieee80211com *ic = &sc->ndis_ic; 1745 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); 1746 1747 if (vap != NULL) { 1748 NDIS_UNLOCK(sc); 1749 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); 1750 NDIS_LOCK(sc); 1751 if_link_state_change(vap->iv_ifp, 1752 LINK_STATE_DOWN); 1753 } 1754 } else 1755 if_link_state_change(sc->ifp, LINK_STATE_DOWN); 1756 } 1757 1758 NDIS_UNLOCK(sc); 1759} 1760 1761static void 1762ndis_map_sclist(arg, segs, nseg, mapsize, error) 1763 void *arg; 1764 bus_dma_segment_t *segs; 1765 int nseg; 1766 bus_size_t mapsize; 1767 int error; 1768 1769{ 1770 struct ndis_sc_list *sclist; 1771 int i; 1772 1773 if (error || arg == NULL) 1774 return; 1775 1776 sclist = arg; 1777 1778 sclist->nsl_frags = nseg; 1779 1780 for (i = 0; i < nseg; i++) { 1781 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr; 1782 sclist->nsl_elements[i].nse_len = segs[i].ds_len; 1783 } 1784} 1785 1786static int 1787ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, 1788 const struct ieee80211_bpf_params *params) 1789{ 1790 /* no support; just discard */ 1791 m_freem(m); 1792 ieee80211_free_node(ni); 1793 return (0); 1794} 1795 1796static void 1797ndis_update_mcast(struct ieee80211com *ic) 1798{ 1799 struct ndis_softc *sc = ic->ic_softc; 1800 1801 ndis_setmulti(sc); 1802} 1803 1804static void 1805ndis_update_promisc(struct ieee80211com *ic) 1806{ 1807 /* not supported */ 1808} 1809 1810static void 1811ndis_ifstarttask(device_object *d, void *arg) 1812{ 1813 struct ndis_softc *sc = arg; 1814 DPRINTF(("%s: sc=%p, ifp=%p\n", __func__, sc, sc->ifp)); 1815 if (sc->ndis_80211) 1816 return; 1817 1818 struct ifnet *ifp = sc->ifp; 1819 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1820 ndis_ifstart(ifp); 1821} 1822 1823/* 1824 * Main transmit routine. To make NDIS drivers happy, we need to 1825 * transform mbuf chains into NDIS packets and feed them to the 1826 * send packet routines. Most drivers allow you to send several 1827 * packets at once (up to the maxpkts limit). Unfortunately, rather 1828 * that accepting them in the form of a linked list, they expect 1829 * a contiguous array of pointers to packets. 1830 * 1831 * For those drivers which use the NDIS scatter/gather DMA mechanism, 1832 * we need to perform busdma work here. Those that use map registers 1833 * will do the mapping themselves on a buffer by buffer basis. 1834 */ 1835static void 1836ndis_ifstart(struct ifnet *ifp) 1837{ 1838 struct ndis_softc *sc; 1839 struct mbuf *m = NULL; 1840 ndis_packet **p0 = NULL, *p = NULL; 1841 ndis_tcpip_csum *csum; 1842 int pcnt = 0, status; 1843 1844 sc = ifp->if_softc; 1845 1846 NDIS_LOCK(sc); 1847 if (!sc->ndis_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) { 1848 NDIS_UNLOCK(sc); 1849 return; 1850 } 1851 1852 p0 = &sc->ndis_txarray[sc->ndis_txidx]; 1853 1854 while(sc->ndis_txpending) { 1855 IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 1856 if (m == NULL) 1857 break; 1858 1859 NdisAllocatePacket(&status, 1860 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool); 1861 1862 if (status != NDIS_STATUS_SUCCESS) 1863 break; 1864 1865 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) { 1866 IFQ_DRV_PREPEND(&ifp->if_snd, m); 1867 NDIS_UNLOCK(sc); 1868 return; 1869 } 1870 1871 /* 1872 * Save pointer to original mbuf 1873 * so we can free it later. 1874 */ 1875 1876 p = sc->ndis_txarray[sc->ndis_txidx]; 1877 p->np_txidx = sc->ndis_txidx; 1878 p->np_m0 = m; 1879 p->np_oob.npo_status = NDIS_STATUS_PENDING; 1880 1881 /* 1882 * Do scatter/gather processing, if driver requested it. 1883 */ 1884 if (sc->ndis_sc) { 1885 bus_dmamap_load_mbuf(sc->ndis_ttag, 1886 sc->ndis_tmaps[sc->ndis_txidx], m, 1887 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT); 1888 bus_dmamap_sync(sc->ndis_ttag, 1889 sc->ndis_tmaps[sc->ndis_txidx], 1890 BUS_DMASYNC_PREREAD); 1891 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist; 1892 } 1893 1894 /* Handle checksum offload. */ 1895 1896 if (ifp->if_capenable & IFCAP_TXCSUM && 1897 m->m_pkthdr.csum_flags) { 1898 csum = (ndis_tcpip_csum *) 1899 &p->np_ext.npe_info[ndis_tcpipcsum_info]; 1900 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4; 1901 if (m->m_pkthdr.csum_flags & CSUM_IP) 1902 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP; 1903 if (m->m_pkthdr.csum_flags & CSUM_TCP) 1904 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP; 1905 if (m->m_pkthdr.csum_flags & CSUM_UDP) 1906 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP; 1907 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP; 1908 } 1909 1910 NDIS_INC(sc); 1911 sc->ndis_txpending--; 1912 1913 pcnt++; 1914 1915 /* 1916 * If there's a BPF listener, bounce a copy of this frame 1917 * to him. 1918 */ 1919 if (!sc->ndis_80211) /* XXX handle 80211 */ 1920 BPF_MTAP(ifp, m); 1921 1922 /* 1923 * The array that p0 points to must appear contiguous, 1924 * so we must not wrap past the end of sc->ndis_txarray[]. 1925 * If it looks like we're about to wrap, break out here 1926 * so the this batch of packets can be transmitted, then 1927 * wait for txeof to ask us to send the rest. 1928 */ 1929 if (sc->ndis_txidx == 0) 1930 break; 1931 } 1932 1933 if (pcnt == 0) { 1934 NDIS_UNLOCK(sc); 1935 return; 1936 } 1937 1938 if (sc->ndis_txpending == 0) 1939 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1940 1941 /* 1942 * Set a timeout in case the chip goes out to lunch. 1943 */ 1944 sc->ndis_tx_timer = 5; 1945 1946 NDIS_UNLOCK(sc); 1947 1948 /* 1949 * According to NDIS documentation, if a driver exports 1950 * a MiniportSendPackets() routine, we prefer that over 1951 * a MiniportSend() routine (which sends just a single 1952 * packet). 1953 */ 1954 if (sc->ndis_chars->nmc_sendmulti_func != NULL) 1955 ndis_send_packets(sc, p0, pcnt); 1956 else 1957 ndis_send_packet(sc, p); 1958 1959 return; 1960} 1961 1962static int 1963ndis_80211transmit(struct ieee80211com *ic, struct mbuf *m) 1964{ 1965 struct ndis_softc *sc = ic->ic_softc; 1966 ndis_packet **p0 = NULL, *p = NULL; 1967 int status; 1968 1969 NDIS_LOCK(sc); 1970 if (!sc->ndis_link || !sc->ndis_running) { 1971 NDIS_UNLOCK(sc); 1972 return (ENXIO); 1973 } 1974 1975 if (sc->ndis_txpending == 0) { 1976 NDIS_UNLOCK(sc); 1977 return (ENOBUFS); 1978 } 1979 1980 p0 = &sc->ndis_txarray[sc->ndis_txidx]; 1981 1982 NdisAllocatePacket(&status, 1983 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool); 1984 1985 if (status != NDIS_STATUS_SUCCESS) { 1986 NDIS_UNLOCK(sc); 1987 return (ENOBUFS); 1988 } 1989 1990 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) { 1991 NDIS_UNLOCK(sc); 1992 return (ENOBUFS); 1993 } 1994 1995 /* 1996 * Save pointer to original mbuf 1997 * so we can free it later. 1998 */ 1999 2000 p = sc->ndis_txarray[sc->ndis_txidx]; 2001 p->np_txidx = sc->ndis_txidx; 2002 p->np_m0 = m; 2003 p->np_oob.npo_status = NDIS_STATUS_PENDING; 2004 2005 /* 2006 * Do scatter/gather processing, if driver requested it. 2007 */ 2008 if (sc->ndis_sc) { 2009 bus_dmamap_load_mbuf(sc->ndis_ttag, 2010 sc->ndis_tmaps[sc->ndis_txidx], m, 2011 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT); 2012 bus_dmamap_sync(sc->ndis_ttag, 2013 sc->ndis_tmaps[sc->ndis_txidx], 2014 BUS_DMASYNC_PREREAD); 2015 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist; 2016 } 2017 2018 NDIS_INC(sc); 2019 sc->ndis_txpending--; 2020 2021 /* 2022 * Set a timeout in case the chip goes out to lunch. 2023 */ 2024 sc->ndis_tx_timer = 5; 2025 NDIS_UNLOCK(sc); 2026 2027 /* 2028 * According to NDIS documentation, if a driver exports 2029 * a MiniportSendPackets() routine, we prefer that over 2030 * a MiniportSend() routine (which sends just a single 2031 * packet). 2032 */ 2033 if (sc->ndis_chars->nmc_sendmulti_func != NULL) 2034 ndis_send_packets(sc, p0, 1); 2035 else 2036 ndis_send_packet(sc, p); 2037 2038 return (0); 2039} 2040 2041static void 2042ndis_80211parent(struct ieee80211com *ic) 2043{ 2044 struct ndis_softc *sc = ic->ic_softc; 2045 2046 /*NDIS_LOCK(sc);*/ 2047 if (ic->ic_nrunning > 0) { 2048 if (!sc->ndis_running) 2049 ndis_init(sc); 2050 } else if (sc->ndis_running) 2051 ndis_stop(sc); 2052 /*NDIS_UNLOCK(sc);*/ 2053} 2054 2055static void 2056ndis_init(void *xsc) 2057{ 2058 struct ndis_softc *sc = xsc; 2059 int i, len, error; 2060 2061 /* 2062 * Avoid reintializing the link unnecessarily. 2063 * This should be dealt with in a better way by 2064 * fixing the upper layer modules so they don't 2065 * call ifp->if_init() quite as often. 2066 */ 2067 if (sc->ndis_link) 2068 return; 2069 2070 /* 2071 * Cancel pending I/O and free all RX/TX buffers. 2072 */ 2073 ndis_stop(sc); 2074 2075 if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) { 2076 error = ndis_init_nic(sc); 2077 if (error != 0) { 2078 device_printf(sc->ndis_dev, 2079 "failed to initialize the device: %d\n", error); 2080 return; 2081 } 2082 } 2083 2084 /* Program the packet filter */ 2085 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED | 2086 NDIS_PACKET_TYPE_BROADCAST; 2087 2088 if (sc->ndis_80211) { 2089 struct ieee80211com *ic = &sc->ndis_ic; 2090 2091 if (ic->ic_promisc > 0) 2092 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; 2093 } else { 2094 struct ifnet *ifp = sc->ifp; 2095 2096 if (ifp->if_flags & IFF_PROMISC) 2097 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; 2098 } 2099 2100 len = sizeof(sc->ndis_filter); 2101 2102 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER, 2103 &sc->ndis_filter, &len); 2104 2105 if (error) 2106 device_printf(sc->ndis_dev, "set filter failed: %d\n", error); 2107 2108 /* 2109 * Set lookahead. 2110 */ 2111 if (sc->ndis_80211) 2112 i = ETHERMTU; 2113 else 2114 i = sc->ifp->if_mtu; 2115 len = sizeof(i); 2116 ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len); 2117 2118 /* 2119 * Program the multicast filter, if necessary. 2120 */ 2121 ndis_setmulti(sc); 2122 2123 /* Setup task offload. */ 2124 ndis_set_offload(sc); 2125 2126 NDIS_LOCK(sc); 2127 2128 sc->ndis_txidx = 0; 2129 sc->ndis_txpending = sc->ndis_maxpkts; 2130 sc->ndis_link = 0; 2131 2132 if (!sc->ndis_80211) { 2133 if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN); 2134 sc->ifp->if_drv_flags |= IFF_DRV_RUNNING; 2135 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2136 } 2137 2138 sc->ndis_tx_timer = 0; 2139 2140 /* 2141 * Some drivers don't set this value. The NDIS spec says 2142 * the default checkforhang timeout is "approximately 2 2143 * seconds." We use 3 seconds, because it seems for some 2144 * drivers, exactly 2 seconds is too fast. 2145 */ 2146 if (sc->ndis_block->nmb_checkforhangsecs == 0) 2147 sc->ndis_block->nmb_checkforhangsecs = 3; 2148 2149 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs; 2150 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc); 2151 sc->ndis_running = 1; 2152 NDIS_UNLOCK(sc); 2153 2154 /* XXX force handling */ 2155 if (sc->ndis_80211) 2156 ieee80211_start_all(&sc->ndis_ic); /* start all vap's */ 2157} 2158 2159/* 2160 * Set media options. 2161 */ 2162static int 2163ndis_ifmedia_upd(ifp) 2164 struct ifnet *ifp; 2165{ 2166 struct ndis_softc *sc; 2167 2168 sc = ifp->if_softc; 2169 2170 if (NDIS_INITIALIZED(sc)) 2171 ndis_init(sc); 2172 2173 return (0); 2174} 2175 2176/* 2177 * Report current media status. 2178 */ 2179static void 2180ndis_ifmedia_sts(ifp, ifmr) 2181 struct ifnet *ifp; 2182 struct ifmediareq *ifmr; 2183{ 2184 struct ndis_softc *sc; 2185 uint32_t media_info; 2186 ndis_media_state linkstate; 2187 int len; 2188 2189 ifmr->ifm_status = IFM_AVALID; 2190 ifmr->ifm_active = IFM_ETHER; 2191 sc = ifp->if_softc; 2192 2193 if (!NDIS_INITIALIZED(sc)) 2194 return; 2195 2196 len = sizeof(linkstate); 2197 ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS, 2198 (void *)&linkstate, &len); 2199 2200 len = sizeof(media_info); 2201 ndis_get_info(sc, OID_GEN_LINK_SPEED, 2202 (void *)&media_info, &len); 2203 2204 if (linkstate == nmc_connected) 2205 ifmr->ifm_status |= IFM_ACTIVE; 2206 2207 switch (media_info) { 2208 case 100000: 2209 ifmr->ifm_active |= IFM_10_T; 2210 break; 2211 case 1000000: 2212 ifmr->ifm_active |= IFM_100_TX; 2213 break; 2214 case 10000000: 2215 ifmr->ifm_active |= IFM_1000_T; 2216 break; 2217 default: 2218 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info); 2219 break; 2220 } 2221} 2222 2223static int 2224ndis_set_cipher(struct ndis_softc *sc, int cipher) 2225{ 2226 struct ieee80211com *ic = &sc->ndis_ic; 2227 int rval = 0, len; 2228 uint32_t arg, save; 2229 2230 len = sizeof(arg); 2231 2232 if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) { 2233 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP)) 2234 return (ENOTSUP); 2235 arg = NDIS_80211_WEPSTAT_ENC1ENABLED; 2236 } 2237 2238 if (cipher == WPA_CSE_TKIP) { 2239 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP)) 2240 return (ENOTSUP); 2241 arg = NDIS_80211_WEPSTAT_ENC2ENABLED; 2242 } 2243 2244 if (cipher == WPA_CSE_CCMP) { 2245 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM)) 2246 return (ENOTSUP); 2247 arg = NDIS_80211_WEPSTAT_ENC3ENABLED; 2248 } 2249 2250 DPRINTF(("Setting cipher to %d\n", arg)); 2251 save = arg; 2252 rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len); 2253 2254 if (rval) 2255 return (rval); 2256 2257 /* Check that the cipher was set correctly. */ 2258 2259 len = sizeof(save); 2260 rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len); 2261 2262 if (rval != 0 || arg != save) 2263 return (ENODEV); 2264 2265 return (0); 2266} 2267 2268/* 2269 * WPA is hairy to set up. Do the work in a separate routine 2270 * so we don't clutter the setstate function too much. 2271 * Important yet undocumented fact: first we have to set the 2272 * authentication mode, _then_ we enable the ciphers. If one 2273 * of the WPA authentication modes isn't enabled, the driver 2274 * might not permit the TKIP or AES ciphers to be selected. 2275 */ 2276static int 2277ndis_set_wpa(sc, ie, ielen) 2278 struct ndis_softc *sc; 2279 void *ie; 2280 int ielen; 2281{ 2282 struct ieee80211_ie_wpa *w; 2283 struct ndis_ie *n; 2284 char *pos; 2285 uint32_t arg; 2286 int i; 2287 2288 /* 2289 * Apparently, the only way for us to know what ciphers 2290 * and key management/authentication mode to use is for 2291 * us to inspect the optional information element (IE) 2292 * stored in the 802.11 state machine. This IE should be 2293 * supplied by the WPA supplicant. 2294 */ 2295 2296 w = (struct ieee80211_ie_wpa *)ie; 2297 2298 /* Check for the right kind of IE. */ 2299 if (w->wpa_id != IEEE80211_ELEMID_VENDOR) { 2300 DPRINTF(("Incorrect IE type %d\n", w->wpa_id)); 2301 return (EINVAL); 2302 } 2303 2304 /* Skip over the ucast cipher OIDs. */ 2305 pos = (char *)&w->wpa_uciphers[0]; 2306 pos += w->wpa_uciphercnt * sizeof(struct ndis_ie); 2307 2308 /* Skip over the authmode count. */ 2309 pos += sizeof(u_int16_t); 2310 2311 /* 2312 * Check for the authentication modes. I'm 2313 * pretty sure there's only supposed to be one. 2314 */ 2315 2316 n = (struct ndis_ie *)pos; 2317 if (n->ni_val == WPA_ASE_NONE) 2318 arg = NDIS_80211_AUTHMODE_WPANONE; 2319 2320 if (n->ni_val == WPA_ASE_8021X_UNSPEC) 2321 arg = NDIS_80211_AUTHMODE_WPA; 2322 2323 if (n->ni_val == WPA_ASE_8021X_PSK) 2324 arg = NDIS_80211_AUTHMODE_WPAPSK; 2325 2326 DPRINTF(("Setting WPA auth mode to %d\n", arg)); 2327 i = sizeof(arg); 2328 if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i)) 2329 return (ENOTSUP); 2330 i = sizeof(arg); 2331 ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i); 2332 2333 /* Now configure the desired ciphers. */ 2334 2335 /* First, set up the multicast group cipher. */ 2336 n = (struct ndis_ie *)&w->wpa_mcipher[0]; 2337 2338 if (ndis_set_cipher(sc, n->ni_val)) 2339 return (ENOTSUP); 2340 2341 /* Now start looking around for the unicast ciphers. */ 2342 pos = (char *)&w->wpa_uciphers[0]; 2343 n = (struct ndis_ie *)pos; 2344 2345 for (i = 0; i < w->wpa_uciphercnt; i++) { 2346 if (ndis_set_cipher(sc, n->ni_val)) 2347 return (ENOTSUP); 2348 n++; 2349 } 2350 2351 return (0); 2352} 2353 2354static void 2355ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr) 2356{ 2357 struct ieee80211vap *vap = ifp->if_softc; 2358 struct ndis_softc *sc = vap->iv_ic->ic_softc; 2359 uint32_t txrate; 2360 int len; 2361 2362 if (!NDIS_INITIALIZED(sc)) 2363 return; 2364 2365 len = sizeof(txrate); 2366 if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0) 2367 vap->iv_bss->ni_txrate = txrate / 5000; 2368 ieee80211_media_status(ifp, imr); 2369} 2370 2371static void 2372ndis_setstate_80211(struct ndis_softc *sc) 2373{ 2374 struct ieee80211com *ic = &sc->ndis_ic; 2375 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); 2376 ndis_80211_macaddr bssid; 2377 ndis_80211_config config; 2378 int rval = 0, len; 2379 uint32_t arg; 2380 2381 if (!NDIS_INITIALIZED(sc)) { 2382 DPRINTF(("%s: NDIS not initialized\n", __func__)); 2383 return; 2384 } 2385 2386 /* Disassociate and turn off radio. */ 2387 len = sizeof(arg); 2388 arg = 1; 2389 ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len); 2390 2391 /* Set network infrastructure mode. */ 2392 2393 len = sizeof(arg); 2394 if (ic->ic_opmode == IEEE80211_M_IBSS) 2395 arg = NDIS_80211_NET_INFRA_IBSS; 2396 else 2397 arg = NDIS_80211_NET_INFRA_BSS; 2398 2399 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len); 2400 2401 if (rval) 2402 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval); 2403 2404 /* Set power management */ 2405 len = sizeof(arg); 2406 if (vap->iv_flags & IEEE80211_F_PMGTON) 2407 arg = NDIS_80211_POWERMODE_FAST_PSP; 2408 else 2409 arg = NDIS_80211_POWERMODE_CAM; 2410 ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len); 2411 2412 /* Set TX power */ 2413 if ((ic->ic_caps & IEEE80211_C_TXPMGT) && 2414 ic->ic_txpowlimit < nitems(dBm2mW)) { 2415 arg = dBm2mW[ic->ic_txpowlimit]; 2416 len = sizeof(arg); 2417 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len); 2418 } 2419 2420 /* 2421 * Default encryption mode to off, authentication 2422 * to open and privacy to 'accept everything.' 2423 */ 2424 len = sizeof(arg); 2425 arg = NDIS_80211_WEPSTAT_DISABLED; 2426 ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len); 2427 2428 len = sizeof(arg); 2429 arg = NDIS_80211_AUTHMODE_OPEN; 2430 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len); 2431 2432 /* 2433 * Note that OID_802_11_PRIVACY_FILTER is optional: 2434 * not all drivers implement it. 2435 */ 2436 len = sizeof(arg); 2437 arg = NDIS_80211_PRIVFILT_8021XWEP; 2438 ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len); 2439 2440 len = sizeof(config); 2441 bzero((char *)&config, len); 2442 config.nc_length = len; 2443 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh); 2444 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len); 2445 2446 /* 2447 * Some drivers expect us to initialize these values, so 2448 * provide some defaults. 2449 */ 2450 2451 if (config.nc_beaconperiod == 0) 2452 config.nc_beaconperiod = 100; 2453 if (config.nc_atimwin == 0) 2454 config.nc_atimwin = 100; 2455 if (config.nc_fhconfig.ncf_dwelltime == 0) 2456 config.nc_fhconfig.ncf_dwelltime = 200; 2457 if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) { 2458 int chan, chanflag; 2459 2460 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan); 2461 chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ : 2462 IEEE80211_CHAN_5GHZ; 2463 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) { 2464 config.nc_dsconfig = 2465 ic->ic_bsschan->ic_freq * 1000; 2466 len = sizeof(config); 2467 config.nc_length = len; 2468 config.nc_fhconfig.ncf_length = 2469 sizeof(ndis_80211_config_fh); 2470 DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig)); 2471 rval = ndis_set_info(sc, OID_802_11_CONFIGURATION, 2472 &config, &len); 2473 if (rval) 2474 device_printf(sc->ndis_dev, "couldn't change " 2475 "DS config to %ukHz: %d\n", 2476 config.nc_dsconfig, rval); 2477 } 2478 } else if (rval) 2479 device_printf(sc->ndis_dev, "couldn't retrieve " 2480 "channel info: %d\n", rval); 2481 2482 /* Set the BSSID to our value so the driver doesn't associate */ 2483 len = IEEE80211_ADDR_LEN; 2484 bcopy(vap->iv_myaddr, bssid, len); 2485 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":")); 2486 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len); 2487 if (rval) 2488 device_printf(sc->ndis_dev, 2489 "setting BSSID failed: %d\n", rval); 2490} 2491 2492static void 2493ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap) 2494{ 2495 struct ieee80211_node *ni = vap->iv_bss; 2496 ndis_80211_ssid ssid; 2497 ndis_80211_macaddr bssid; 2498 ndis_80211_wep wep; 2499 int i, rval = 0, len, error; 2500 uint32_t arg; 2501 2502 if (!NDIS_INITIALIZED(sc)) { 2503 DPRINTF(("%s: NDIS not initialized\n", __func__)); 2504 return; 2505 } 2506 2507 /* Initial setup */ 2508 ndis_setstate_80211(sc); 2509 2510 /* Set network infrastructure mode. */ 2511 2512 len = sizeof(arg); 2513 if (vap->iv_opmode == IEEE80211_M_IBSS) 2514 arg = NDIS_80211_NET_INFRA_IBSS; 2515 else 2516 arg = NDIS_80211_NET_INFRA_BSS; 2517 2518 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len); 2519 2520 if (rval) 2521 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval); 2522 2523 /* Set RTS threshold */ 2524 2525 len = sizeof(arg); 2526 arg = vap->iv_rtsthreshold; 2527 ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len); 2528 2529 /* Set fragmentation threshold */ 2530 2531 len = sizeof(arg); 2532 arg = vap->iv_fragthreshold; 2533 ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len); 2534 2535 /* Set WEP */ 2536 2537 if (vap->iv_flags & IEEE80211_F_PRIVACY && 2538 !(vap->iv_flags & IEEE80211_F_WPA)) { 2539 int keys_set = 0; 2540 2541 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) { 2542 len = sizeof(arg); 2543 arg = NDIS_80211_AUTHMODE_SHARED; 2544 DPRINTF(("Setting shared auth\n")); 2545 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, 2546 &arg, &len); 2547 } 2548 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 2549 if (vap->iv_nw_keys[i].wk_keylen) { 2550 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher != 2551 IEEE80211_CIPHER_WEP) 2552 continue; 2553 bzero((char *)&wep, sizeof(wep)); 2554 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen; 2555 2556 /* 2557 * 5, 13 and 16 are the only valid 2558 * key lengths. Anything in between 2559 * will be zero padded out to the 2560 * next highest boundary. 2561 */ 2562 if (vap->iv_nw_keys[i].wk_keylen < 5) 2563 wep.nw_keylen = 5; 2564 else if (vap->iv_nw_keys[i].wk_keylen > 5 && 2565 vap->iv_nw_keys[i].wk_keylen < 13) 2566 wep.nw_keylen = 13; 2567 else if (vap->iv_nw_keys[i].wk_keylen > 13 && 2568 vap->iv_nw_keys[i].wk_keylen < 16) 2569 wep.nw_keylen = 16; 2570 2571 wep.nw_keyidx = i; 2572 wep.nw_length = (sizeof(uint32_t) * 3) 2573 + wep.nw_keylen; 2574 if (i == vap->iv_def_txkey) 2575 wep.nw_keyidx |= NDIS_80211_WEPKEY_TX; 2576 bcopy(vap->iv_nw_keys[i].wk_key, 2577 wep.nw_keydata, wep.nw_length); 2578 len = sizeof(wep); 2579 DPRINTF(("Setting WEP key %d\n", i)); 2580 rval = ndis_set_info(sc, 2581 OID_802_11_ADD_WEP, &wep, &len); 2582 if (rval) 2583 device_printf(sc->ndis_dev, 2584 "set wepkey failed: %d\n", rval); 2585 keys_set++; 2586 } 2587 } 2588 if (keys_set) { 2589 DPRINTF(("Setting WEP on\n")); 2590 arg = NDIS_80211_WEPSTAT_ENABLED; 2591 len = sizeof(arg); 2592 rval = ndis_set_info(sc, 2593 OID_802_11_WEP_STATUS, &arg, &len); 2594 if (rval) 2595 device_printf(sc->ndis_dev, 2596 "enable WEP failed: %d\n", rval); 2597 if (vap->iv_flags & IEEE80211_F_DROPUNENC) 2598 arg = NDIS_80211_PRIVFILT_8021XWEP; 2599 else 2600 arg = NDIS_80211_PRIVFILT_ACCEPTALL; 2601 2602 len = sizeof(arg); 2603 ndis_set_info(sc, 2604 OID_802_11_PRIVACY_FILTER, &arg, &len); 2605 } 2606 } 2607 2608 /* Set up WPA. */ 2609 if ((vap->iv_flags & IEEE80211_F_WPA) && 2610 vap->iv_appie_assocreq != NULL) { 2611 struct ieee80211_appie *ie = vap->iv_appie_assocreq; 2612 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len); 2613 if (error != 0) 2614 device_printf(sc->ndis_dev, "WPA setup failed\n"); 2615 } 2616 2617#ifdef notyet 2618 /* Set network type. */ 2619 2620 arg = 0; 2621 2622 switch (vap->iv_curmode) { 2623 case IEEE80211_MODE_11A: 2624 arg = NDIS_80211_NETTYPE_11OFDM5; 2625 break; 2626 case IEEE80211_MODE_11B: 2627 arg = NDIS_80211_NETTYPE_11DS; 2628 break; 2629 case IEEE80211_MODE_11G: 2630 arg = NDIS_80211_NETTYPE_11OFDM24; 2631 break; 2632 default: 2633 device_printf(sc->ndis_dev, "unknown mode: %d\n", 2634 vap->iv_curmode); 2635 } 2636 2637 if (arg) { 2638 DPRINTF(("Setting network type to %d\n", arg)); 2639 len = sizeof(arg); 2640 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE, 2641 &arg, &len); 2642 if (rval) 2643 device_printf(sc->ndis_dev, 2644 "set nettype failed: %d\n", rval); 2645 } 2646#endif 2647 2648 /* 2649 * If the user selected a specific BSSID, try 2650 * to use that one. This is useful in the case where 2651 * there are several APs in range with the same network 2652 * name. To delete the BSSID, we use the broadcast 2653 * address as the BSSID. 2654 * Note that some drivers seem to allow setting a BSSID 2655 * in ad-hoc mode, which has the effect of forcing the 2656 * NIC to create an ad-hoc cell with a specific BSSID, 2657 * instead of a randomly chosen one. However, the net80211 2658 * code makes the assumtion that the BSSID setting is invalid 2659 * when you're in ad-hoc mode, so we don't allow that here. 2660 */ 2661 2662 len = IEEE80211_ADDR_LEN; 2663 if (vap->iv_flags & IEEE80211_F_DESBSSID && 2664 vap->iv_opmode != IEEE80211_M_IBSS) 2665 bcopy(ni->ni_bssid, bssid, len); 2666 else 2667 bcopy(ieee80211broadcastaddr, bssid, len); 2668 2669 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":")); 2670 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len); 2671 if (rval) 2672 device_printf(sc->ndis_dev, 2673 "setting BSSID failed: %d\n", rval); 2674 2675 /* Set SSID -- always do this last. */ 2676 2677#ifdef NDIS_DEBUG 2678 if (ndis_debug > 0) { 2679 printf("Setting ESSID to "); 2680 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen); 2681 printf("\n"); 2682 } 2683#endif 2684 2685 len = sizeof(ssid); 2686 bzero((char *)&ssid, len); 2687 ssid.ns_ssidlen = ni->ni_esslen; 2688 if (ssid.ns_ssidlen == 0) { 2689 ssid.ns_ssidlen = 1; 2690 } else 2691 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen); 2692 2693 rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len); 2694 2695 if (rval) 2696 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval); 2697 2698 return; 2699} 2700 2701static int 2702ndis_get_bssid_list(sc, bl) 2703 struct ndis_softc *sc; 2704 ndis_80211_bssid_list_ex **bl; 2705{ 2706 int len, error; 2707 2708 len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16); 2709 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO); 2710 if (*bl == NULL) 2711 return (ENOMEM); 2712 2713 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len); 2714 if (error == ENOSPC) { 2715 free(*bl, M_DEVBUF); 2716 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO); 2717 if (*bl == NULL) 2718 return (ENOMEM); 2719 2720 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len); 2721 } 2722 if (error) { 2723 DPRINTF(("%s: failed to read\n", __func__)); 2724 free(*bl, M_DEVBUF); 2725 return (error); 2726 } 2727 2728 return (0); 2729} 2730 2731static int 2732ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc) 2733{ 2734 struct ieee80211com *ic = &sc->ndis_ic; 2735 struct ieee80211vap *vap; 2736 struct ieee80211_node *ni; 2737 ndis_80211_bssid_list_ex *bl; 2738 ndis_wlan_bssid_ex *bs; 2739 ndis_80211_macaddr bssid; 2740 int i, len, error; 2741 2742 if (!sc->ndis_link) 2743 return (ENOENT); 2744 2745 len = sizeof(bssid); 2746 error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len); 2747 if (error) { 2748 device_printf(sc->ndis_dev, "failed to get bssid\n"); 2749 return (ENOENT); 2750 } 2751 2752 vap = TAILQ_FIRST(&ic->ic_vaps); 2753 ni = vap->iv_bss; 2754 2755 error = ndis_get_bssid_list(sc, &bl); 2756 if (error) 2757 return (error); 2758 2759 bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0]; 2760 for (i = 0; i < bl->nblx_items; i++) { 2761 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) { 2762 *assoc = malloc(bs->nwbx_len, M_TEMP, M_NOWAIT); 2763 if (*assoc == NULL) { 2764 free(bl, M_TEMP); 2765 return (ENOMEM); 2766 } 2767 bcopy((char *)bs, (char *)*assoc, bs->nwbx_len); 2768 free(bl, M_TEMP); 2769 if (ic->ic_opmode == IEEE80211_M_STA) 2770 ni->ni_associd = 1 | 0xc000; /* fake associd */ 2771 return (0); 2772 } 2773 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len); 2774 } 2775 2776 free(bl, M_TEMP); 2777 return (ENOENT); 2778} 2779 2780static void 2781ndis_getstate_80211(struct ndis_softc *sc) 2782{ 2783 struct ieee80211com *ic = &sc->ndis_ic; 2784 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); 2785 struct ieee80211_node *ni = vap->iv_bss; 2786 ndis_wlan_bssid_ex *bs; 2787 int rval, len, i = 0; 2788 int chanflag; 2789 uint32_t arg; 2790 2791 if (!NDIS_INITIALIZED(sc)) 2792 return; 2793 2794 if ((rval = ndis_get_assoc(sc, &bs)) != 0) 2795 return; 2796 2797 /* We're associated, retrieve info on the current bssid. */ 2798 ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype); 2799 chanflag = ndis_nettype_chan(bs->nwbx_nettype); 2800 IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr); 2801 2802 /* Get SSID from current association info. */ 2803 bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid, 2804 bs->nwbx_ssid.ns_ssidlen); 2805 ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen; 2806 2807 if (ic->ic_caps & IEEE80211_C_PMGT) { 2808 len = sizeof(arg); 2809 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len); 2810 2811 if (rval) 2812 device_printf(sc->ndis_dev, 2813 "get power mode failed: %d\n", rval); 2814 if (arg == NDIS_80211_POWERMODE_CAM) 2815 vap->iv_flags &= ~IEEE80211_F_PMGTON; 2816 else 2817 vap->iv_flags |= IEEE80211_F_PMGTON; 2818 } 2819 2820 /* Get TX power */ 2821 if (ic->ic_caps & IEEE80211_C_TXPMGT) { 2822 len = sizeof(arg); 2823 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len); 2824 for (i = 0; i < nitems(dBm2mW); i++) 2825 if (dBm2mW[i] >= arg) 2826 break; 2827 ic->ic_txpowlimit = i; 2828 } 2829 2830 /* 2831 * Use the current association information to reflect 2832 * what channel we're on. 2833 */ 2834 ic->ic_curchan = ieee80211_find_channel(ic, 2835 bs->nwbx_config.nc_dsconfig / 1000, chanflag); 2836 if (ic->ic_curchan == NULL) 2837 ic->ic_curchan = &ic->ic_channels[0]; 2838 ni->ni_chan = ic->ic_curchan; 2839 ic->ic_bsschan = ic->ic_curchan; 2840 2841 free(bs, M_TEMP); 2842 2843 /* 2844 * Determine current authentication mode. 2845 */ 2846 len = sizeof(arg); 2847 rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len); 2848 if (rval) 2849 device_printf(sc->ndis_dev, 2850 "get authmode status failed: %d\n", rval); 2851 else { 2852 vap->iv_flags &= ~IEEE80211_F_WPA; 2853 switch (arg) { 2854 case NDIS_80211_AUTHMODE_OPEN: 2855 ni->ni_authmode = IEEE80211_AUTH_OPEN; 2856 break; 2857 case NDIS_80211_AUTHMODE_SHARED: 2858 ni->ni_authmode = IEEE80211_AUTH_SHARED; 2859 break; 2860 case NDIS_80211_AUTHMODE_AUTO: 2861 ni->ni_authmode = IEEE80211_AUTH_AUTO; 2862 break; 2863 case NDIS_80211_AUTHMODE_WPA: 2864 case NDIS_80211_AUTHMODE_WPAPSK: 2865 case NDIS_80211_AUTHMODE_WPANONE: 2866 ni->ni_authmode = IEEE80211_AUTH_WPA; 2867 vap->iv_flags |= IEEE80211_F_WPA1; 2868 break; 2869 case NDIS_80211_AUTHMODE_WPA2: 2870 case NDIS_80211_AUTHMODE_WPA2PSK: 2871 ni->ni_authmode = IEEE80211_AUTH_WPA; 2872 vap->iv_flags |= IEEE80211_F_WPA2; 2873 break; 2874 default: 2875 ni->ni_authmode = IEEE80211_AUTH_NONE; 2876 break; 2877 } 2878 } 2879 2880 len = sizeof(arg); 2881 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len); 2882 2883 if (rval) 2884 device_printf(sc->ndis_dev, 2885 "get wep status failed: %d\n", rval); 2886 2887 if (arg == NDIS_80211_WEPSTAT_ENABLED) 2888 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC; 2889 else 2890 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC); 2891} 2892 2893static int 2894ndis_ifioctl(ifp, command, data) 2895 struct ifnet *ifp; 2896 u_long command; 2897 caddr_t data; 2898{ 2899 struct ndis_softc *sc = ifp->if_softc; 2900 struct ifreq *ifr = (struct ifreq *) data; 2901 int i, error = 0; 2902 2903 /*NDIS_LOCK(sc);*/ 2904 2905 switch (command) { 2906 case SIOCSIFFLAGS: 2907 if (ifp->if_flags & IFF_UP) { 2908 if (sc->ndis_running && 2909 ifp->if_flags & IFF_PROMISC && 2910 !(sc->ndis_if_flags & IFF_PROMISC)) { 2911 sc->ndis_filter |= 2912 NDIS_PACKET_TYPE_PROMISCUOUS; 2913 i = sizeof(sc->ndis_filter); 2914 error = ndis_set_info(sc, 2915 OID_GEN_CURRENT_PACKET_FILTER, 2916 &sc->ndis_filter, &i); 2917 } else if (sc->ndis_running && 2918 !(ifp->if_flags & IFF_PROMISC) && 2919 sc->ndis_if_flags & IFF_PROMISC) { 2920 sc->ndis_filter &= 2921 ~NDIS_PACKET_TYPE_PROMISCUOUS; 2922 i = sizeof(sc->ndis_filter); 2923 error = ndis_set_info(sc, 2924 OID_GEN_CURRENT_PACKET_FILTER, 2925 &sc->ndis_filter, &i); 2926 } else 2927 ndis_init(sc); 2928 } else { 2929 if (sc->ndis_running) 2930 ndis_stop(sc); 2931 } 2932 sc->ndis_if_flags = ifp->if_flags; 2933 error = 0; 2934 break; 2935 case SIOCADDMULTI: 2936 case SIOCDELMULTI: 2937 ndis_setmulti(sc); 2938 error = 0; 2939 break; 2940 case SIOCGIFMEDIA: 2941 case SIOCSIFMEDIA: 2942 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command); 2943 break; 2944 case SIOCSIFCAP: 2945 ifp->if_capenable = ifr->ifr_reqcap; 2946 if (ifp->if_capenable & IFCAP_TXCSUM) 2947 ifp->if_hwassist = sc->ndis_hwassist; 2948 else 2949 ifp->if_hwassist = 0; 2950 ndis_set_offload(sc); 2951 break; 2952 default: 2953 error = ether_ioctl(ifp, command, data); 2954 break; 2955 } 2956 2957 /*NDIS_UNLOCK(sc);*/ 2958 2959 return(error); 2960} 2961 2962static int 2963ndis_80211ioctl(struct ieee80211com *ic, u_long cmd, void *data) 2964{ 2965 struct ndis_softc *sc = ic->ic_softc; 2966 struct ifreq *ifr = data; 2967 struct ndis_oid_data oid; 2968 struct ndis_evt evt; 2969 void *oidbuf = NULL; 2970 int error = 0; 2971 2972 if ((error = priv_check(curthread, PRIV_DRIVER)) != 0) 2973 return (error); 2974 2975 switch (cmd) { 2976 case SIOCGDRVSPEC: 2977 case SIOCSDRVSPEC: 2978 error = copyin(ifr->ifr_data, &oid, sizeof(oid)); 2979 if (error) 2980 break; 2981 oidbuf = malloc(oid.len, M_TEMP, M_WAITOK | M_ZERO); 2982 error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len); 2983 } 2984 2985 if (error) { 2986 free(oidbuf, M_TEMP); 2987 return (error); 2988 } 2989 2990 switch (cmd) { 2991 case SIOCGDRVSPEC: 2992 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len); 2993 break; 2994 case SIOCSDRVSPEC: 2995 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len); 2996 break; 2997 case SIOCGPRIVATE_0: 2998 NDIS_LOCK(sc); 2999 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) { 3000 error = ENOENT; 3001 NDIS_UNLOCK(sc); 3002 break; 3003 } 3004 error = copyin(ifr->ifr_data, &evt, sizeof(evt)); 3005 if (error) { 3006 NDIS_UNLOCK(sc); 3007 break; 3008 } 3009 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) { 3010 error = ENOSPC; 3011 NDIS_UNLOCK(sc); 3012 break; 3013 } 3014 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx], 3015 ifr->ifr_data, sizeof(uint32_t) * 2); 3016 if (error) { 3017 NDIS_UNLOCK(sc); 3018 break; 3019 } 3020 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) { 3021 error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, 3022 ifr->ifr_data + (sizeof(uint32_t) * 2), 3023 sc->ndis_evt[sc->ndis_evtcidx].ne_len); 3024 if (error) { 3025 NDIS_UNLOCK(sc); 3026 break; 3027 } 3028 free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP); 3029 sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL; 3030 } 3031 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0; 3032 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0; 3033 NDIS_EVTINC(sc->ndis_evtcidx); 3034 NDIS_UNLOCK(sc); 3035 break; 3036 default: 3037 error = ENOTTY; 3038 break; 3039 } 3040 3041 switch (cmd) { 3042 case SIOCGDRVSPEC: 3043 case SIOCSDRVSPEC: 3044 error = copyout(&oid, ifr->ifr_data, sizeof(oid)); 3045 if (error) 3046 break; 3047 error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len); 3048 } 3049 3050 free(oidbuf, M_TEMP); 3051 3052 return (error); 3053} 3054 3055int 3056ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key) 3057{ 3058 struct ndis_softc *sc = vap->iv_ic->ic_softc; 3059 ndis_80211_key rkey; 3060 int len, error = 0; 3061 3062 bzero((char *)&rkey, sizeof(rkey)); 3063 len = sizeof(rkey); 3064 3065 rkey.nk_len = len; 3066 rkey.nk_keyidx = key->wk_keyix; 3067 3068 bcopy(vap->iv_ifp->if_broadcastaddr, 3069 rkey.nk_bssid, IEEE80211_ADDR_LEN); 3070 3071 error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len); 3072 3073 if (error) 3074 return (0); 3075 3076 return (1); 3077} 3078 3079/* 3080 * In theory this could be called for any key, but we'll 3081 * only use it for WPA TKIP or AES keys. These need to be 3082 * set after initial authentication with the AP. 3083 */ 3084static int 3085ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key) 3086{ 3087 struct ndis_softc *sc = vap->iv_ic->ic_softc; 3088 ndis_80211_key rkey; 3089 int len, error = 0; 3090 3091 switch (key->wk_cipher->ic_cipher) { 3092 case IEEE80211_CIPHER_TKIP: 3093 3094 len = sizeof(ndis_80211_key); 3095 bzero((char *)&rkey, sizeof(rkey)); 3096 3097 rkey.nk_len = len; 3098 rkey.nk_keylen = key->wk_keylen; 3099 3100 if (key->wk_flags & IEEE80211_KEY_SWMIC) 3101 rkey.nk_keylen += 16; 3102 3103 /* key index - gets weird in NDIS */ 3104 3105 if (key->wk_keyix != IEEE80211_KEYIX_NONE) 3106 rkey.nk_keyidx = key->wk_keyix; 3107 else 3108 rkey.nk_keyidx = 0; 3109 3110 if (key->wk_flags & IEEE80211_KEY_XMIT) 3111 rkey.nk_keyidx |= 1 << 31; 3112 3113 if (key->wk_flags & IEEE80211_KEY_GROUP) { 3114 bcopy(ieee80211broadcastaddr, 3115 rkey.nk_bssid, IEEE80211_ADDR_LEN); 3116 } else { 3117 bcopy(vap->iv_bss->ni_bssid, 3118 rkey.nk_bssid, IEEE80211_ADDR_LEN); 3119 /* pairwise key */ 3120 rkey.nk_keyidx |= 1 << 30; 3121 } 3122 3123 /* need to set bit 29 based on keyrsc */ 3124 rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */ 3125 3126 if (rkey.nk_keyrsc) 3127 rkey.nk_keyidx |= 1 << 29; 3128 3129 if (key->wk_flags & IEEE80211_KEY_SWMIC) { 3130 bcopy(key->wk_key, rkey.nk_keydata, 16); 3131 bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8); 3132 bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8); 3133 } else 3134 bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen); 3135 3136 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len); 3137 break; 3138 case IEEE80211_CIPHER_WEP: 3139 error = 0; 3140 break; 3141 /* 3142 * I don't know how to set up keys for the AES 3143 * cipher yet. Is it the same as TKIP? 3144 */ 3145 case IEEE80211_CIPHER_AES_CCM: 3146 default: 3147 error = ENOTTY; 3148 break; 3149 } 3150 3151 /* We need to return 1 for success, 0 for failure. */ 3152 3153 if (error) 3154 return (0); 3155 3156 return (1); 3157} 3158 3159static void 3160ndis_resettask(d, arg) 3161 device_object *d; 3162 void *arg; 3163{ 3164 struct ndis_softc *sc; 3165 3166 sc = arg; 3167 ndis_reset_nic(sc); 3168} 3169 3170/* 3171 * Stop the adapter and free any mbufs allocated to the 3172 * RX and TX lists. 3173 */ 3174static void 3175ndis_stop(struct ndis_softc *sc) 3176{ 3177 int i; 3178 3179 callout_drain(&sc->ndis_stat_callout); 3180 3181 NDIS_LOCK(sc); 3182 sc->ndis_tx_timer = 0; 3183 sc->ndis_link = 0; 3184 if (!sc->ndis_80211) 3185 sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 3186 sc->ndis_running = 0; 3187 NDIS_UNLOCK(sc); 3188 3189 if (sc->ndis_iftype != PNPBus || 3190 (sc->ndis_iftype == PNPBus && 3191 !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) && 3192 ndisusb_halt != 0)) 3193 ndis_halt_nic(sc); 3194 3195 NDIS_LOCK(sc); 3196 for (i = 0; i < NDIS_EVENTS; i++) { 3197 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) { 3198 free(sc->ndis_evt[i].ne_buf, M_TEMP); 3199 sc->ndis_evt[i].ne_buf = NULL; 3200 } 3201 sc->ndis_evt[i].ne_sts = 0; 3202 sc->ndis_evt[i].ne_len = 0; 3203 } 3204 sc->ndis_evtcidx = 0; 3205 sc->ndis_evtpidx = 0; 3206 NDIS_UNLOCK(sc); 3207} 3208 3209/* 3210 * Stop all chip I/O so that the kernel's probe routines don't 3211 * get confused by errant DMAs when rebooting. 3212 */ 3213void 3214ndis_shutdown(dev) 3215 device_t dev; 3216{ 3217 struct ndis_softc *sc; 3218 3219 sc = device_get_softc(dev); 3220 ndis_stop(sc); 3221} 3222 3223static int 3224ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) 3225{ 3226 struct ndis_vap *nvp = NDIS_VAP(vap); 3227 struct ieee80211com *ic = vap->iv_ic; 3228 struct ndis_softc *sc = ic->ic_softc; 3229 enum ieee80211_state ostate; 3230 3231 DPRINTF(("%s: %s -> %s\n", __func__, 3232 ieee80211_state_name[vap->iv_state], 3233 ieee80211_state_name[nstate])); 3234 3235 ostate = vap->iv_state; 3236 vap->iv_state = nstate; 3237 3238 switch (nstate) { 3239 /* pass on to net80211 */ 3240 case IEEE80211_S_INIT: 3241 case IEEE80211_S_SCAN: 3242 return nvp->newstate(vap, nstate, arg); 3243 case IEEE80211_S_ASSOC: 3244 if (ostate != IEEE80211_S_AUTH) { 3245 IEEE80211_UNLOCK(ic); 3246 ndis_auth_and_assoc(sc, vap); 3247 IEEE80211_LOCK(ic); 3248 } 3249 break; 3250 case IEEE80211_S_AUTH: 3251 IEEE80211_UNLOCK(ic); 3252 ndis_auth_and_assoc(sc, vap); 3253 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */ 3254 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0); 3255 IEEE80211_LOCK(ic); 3256 break; 3257 default: 3258 break; 3259 } 3260 return (0); 3261} 3262 3263static void 3264ndis_scan(void *arg) 3265{ 3266 struct ieee80211vap *vap = arg; 3267 3268 ieee80211_scan_done(vap); 3269} 3270 3271static void 3272ndis_scan_results(struct ndis_softc *sc) 3273{ 3274 struct ieee80211com *ic = &sc->ndis_ic; 3275 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); 3276 ndis_80211_bssid_list_ex *bl; 3277 ndis_wlan_bssid_ex *wb; 3278 struct ieee80211_scanparams sp; 3279 struct ieee80211_frame wh; 3280 struct ieee80211_channel *saved_chan; 3281 int i, j; 3282 int rssi, noise, freq, chanflag; 3283 uint8_t ssid[2+IEEE80211_NWID_LEN]; 3284 uint8_t rates[2+IEEE80211_RATE_MAXSIZE]; 3285 uint8_t *frm, *efrm; 3286 3287 saved_chan = ic->ic_curchan; 3288 noise = -96; 3289 3290 if (ndis_get_bssid_list(sc, &bl)) 3291 return; 3292 3293 DPRINTF(("%s: %d results\n", __func__, bl->nblx_items)); 3294 wb = &bl->nblx_bssid[0]; 3295 for (i = 0; i < bl->nblx_items; i++) { 3296 memset(&sp, 0, sizeof(sp)); 3297 3298 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2)); 3299 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3)); 3300 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise); 3301 rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */ 3302 if (wb->nwbx_privacy) 3303 sp.capinfo |= IEEE80211_CAPINFO_PRIVACY; 3304 sp.bintval = wb->nwbx_config.nc_beaconperiod; 3305 switch (wb->nwbx_netinfra) { 3306 case NDIS_80211_NET_INFRA_IBSS: 3307 sp.capinfo |= IEEE80211_CAPINFO_IBSS; 3308 break; 3309 case NDIS_80211_NET_INFRA_BSS: 3310 sp.capinfo |= IEEE80211_CAPINFO_ESS; 3311 break; 3312 } 3313 sp.rates = &rates[0]; 3314 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) { 3315 /* XXX - check units */ 3316 if (wb->nwbx_supportedrates[j] == 0) 3317 break; 3318 rates[2 + j] = 3319 wb->nwbx_supportedrates[j] & 0x7f; 3320 } 3321 rates[1] = j; 3322 sp.ssid = (uint8_t *)&ssid[0]; 3323 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid, 3324 wb->nwbx_ssid.ns_ssidlen); 3325 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen; 3326 3327 chanflag = ndis_nettype_chan(wb->nwbx_nettype); 3328 freq = wb->nwbx_config.nc_dsconfig / 1000; 3329 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag); 3330 /* Hack ic->ic_curchan to be in sync with the scan result */ 3331 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag); 3332 if (ic->ic_curchan == NULL) 3333 ic->ic_curchan = &ic->ic_channels[0]; 3334 3335 /* Process extended info from AP */ 3336 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) { 3337 frm = (uint8_t *)&wb->nwbx_ies; 3338 efrm = frm + wb->nwbx_ielen; 3339 if (efrm - frm < 12) 3340 goto done; 3341 sp.tstamp = frm; frm += 8; 3342 sp.bintval = le16toh(*(uint16_t *)frm); frm += 2; 3343 sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2; 3344 sp.ies = frm; 3345 sp.ies_len = efrm - frm; 3346 } 3347done: 3348 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n", 3349 ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag, 3350 rssi)); 3351 ieee80211_add_scan(vap, ic->ic_curchan, &sp, &wh, 0, rssi, noise); 3352 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len); 3353 } 3354 free(bl, M_DEVBUF); 3355 /* Restore the channel after messing with it */ 3356 ic->ic_curchan = saved_chan; 3357} 3358 3359static void 3360ndis_scan_start(struct ieee80211com *ic) 3361{ 3362 struct ndis_softc *sc = ic->ic_softc; 3363 struct ieee80211vap *vap; 3364 struct ieee80211_scan_state *ss; 3365 ndis_80211_ssid ssid; 3366 int error, len; 3367 3368 ss = ic->ic_scan; 3369 vap = TAILQ_FIRST(&ic->ic_vaps); 3370 3371 if (!NDIS_INITIALIZED(sc)) { 3372 DPRINTF(("%s: scan aborted\n", __func__)); 3373 ieee80211_cancel_scan(vap); 3374 return; 3375 } 3376 3377 len = sizeof(ssid); 3378 bzero((char *)&ssid, len); 3379 if (ss->ss_nssid == 0) 3380 ssid.ns_ssidlen = 1; 3381 else { 3382 /* Perform a directed scan */ 3383 ssid.ns_ssidlen = ss->ss_ssid[0].len; 3384 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen); 3385 } 3386 3387 error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len); 3388 if (error) 3389 DPRINTF(("%s: set ESSID failed\n", __func__)); 3390 3391 len = 0; 3392 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len); 3393 if (error) { 3394 DPRINTF(("%s: scan command failed\n", __func__)); 3395 ieee80211_cancel_scan(vap); 3396 return; 3397 } 3398 /* Set a timer to collect the results */ 3399 callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap); 3400} 3401 3402static void 3403ndis_set_channel(struct ieee80211com *ic) 3404{ 3405 /* ignore */ 3406} 3407 3408static void 3409ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell) 3410{ 3411 /* ignore */ 3412} 3413 3414static void 3415ndis_scan_mindwell(struct ieee80211_scan_state *ss) 3416{ 3417 /* NB: don't try to abort scan; wait for firmware to finish */ 3418} 3419 3420static void 3421ndis_scan_end(struct ieee80211com *ic) 3422{ 3423 struct ndis_softc *sc = ic->ic_softc; 3424 3425 ndis_scan_results(sc); 3426} 3427