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