if_ndis.c revision 144888
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 33#include <sys/cdefs.h> 34__FBSDID("$FreeBSD: head/sys/dev/if_ndis/if_ndis.c 144888 2005-04-11 02:02:35Z wpaul $"); 35 36#include "opt_bdg.h" 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/sockio.h> 41#include <sys/mbuf.h> 42#include <sys/malloc.h> 43#include <sys/kernel.h> 44#include <sys/socket.h> 45#include <sys/queue.h> 46#include <sys/module.h> 47#include <sys/proc.h> 48#if __FreeBSD_version < 502113 49#include <sys/sysctl.h> 50#endif 51 52#include <net/if.h> 53#include <net/if_arp.h> 54#include <net/ethernet.h> 55#include <net/if_dl.h> 56#include <net/if_media.h> 57#include <net/route.h> 58 59#include <net/bpf.h> 60 61#include <machine/bus_memio.h> 62#include <machine/bus_pio.h> 63#include <machine/bus.h> 64#include <machine/resource.h> 65#include <sys/bus.h> 66#include <sys/rman.h> 67 68#include <net80211/ieee80211_var.h> 69#include <net80211/ieee80211_ioctl.h> 70 71#include <dev/wi/if_wavelan_ieee.h> 72 73#include <dev/pci/pcireg.h> 74#include <dev/pci/pcivar.h> 75 76#include <compat/ndis/pe_var.h> 77#include <compat/ndis/resource_var.h> 78#include <compat/ndis/ntoskrnl_var.h> 79#include <compat/ndis/hal_var.h> 80#include <compat/ndis/ndis_var.h> 81#include <compat/ndis/cfg_var.h> 82#include <dev/if_ndis/if_ndisvar.h> 83 84#define NDIS_IMAGE 85#define NDIS_REGVALS 86 87#include "ndis_driver_data.h" 88 89int ndis_attach (device_t); 90int ndis_detach (device_t); 91int ndis_suspend (device_t); 92int ndis_resume (device_t); 93void ndis_shutdown (device_t); 94 95int ndisdrv_modevent (module_t, int, void *); 96 97static void ndis_txeof (ndis_handle, ndis_packet *, ndis_status); 98static void ndis_rxeof (ndis_handle, ndis_packet **, uint32_t); 99static void ndis_linksts (ndis_handle, ndis_status, void *, uint32_t); 100static void ndis_linksts_done (ndis_handle); 101 102/* We need to wrap these functions for amd64. */ 103 104static funcptr ndis_txeof_wrap; 105static funcptr ndis_rxeof_wrap; 106static funcptr ndis_linksts_wrap; 107static funcptr ndis_linksts_done_wrap; 108 109static void ndis_intr (void *); 110static void ndis_tick (void *); 111static void ndis_ticktask (void *); 112static void ndis_start (struct ifnet *); 113static void ndis_starttask (void *); 114static int ndis_ioctl (struct ifnet *, u_long, caddr_t); 115static int ndis_wi_ioctl_get (struct ifnet *, u_long, caddr_t); 116static int ndis_wi_ioctl_set (struct ifnet *, u_long, caddr_t); 117static int ndis_80211_ioctl_get (struct ifnet *, u_long, caddr_t); 118static int ndis_80211_ioctl_set (struct ifnet *, u_long, caddr_t); 119static void ndis_init (void *); 120static void ndis_stop (struct ndis_softc *); 121static void ndis_watchdog (struct ifnet *); 122static int ndis_ifmedia_upd (struct ifnet *); 123static void ndis_ifmedia_sts (struct ifnet *, struct ifmediareq *); 124static int ndis_get_assoc (struct ndis_softc *, ndis_wlan_bssid_ex **); 125static int ndis_probe_offload (struct ndis_softc *); 126static int ndis_set_offload (struct ndis_softc *); 127static void ndis_getstate_80211 (struct ndis_softc *); 128static void ndis_setstate_80211 (struct ndis_softc *); 129static void ndis_media_status (struct ifnet *, struct ifmediareq *); 130 131static void ndis_setmulti (struct ndis_softc *); 132static void ndis_map_sclist (void *, bus_dma_segment_t *, 133 int, bus_size_t, int); 134 135static int ndisdrv_loaded = 0; 136 137/* 138 * This routine should call windrv_load() once for each driver 139 * image. This will do the relocation and dynalinking for the 140 * image, and create a Windows driver object which will be 141 * saved in our driver database. 142 */ 143 144int 145ndisdrv_modevent(mod, cmd, arg) 146 module_t mod; 147 int cmd; 148 void *arg; 149{ 150 int error = 0; 151 152 switch (cmd) { 153 case MOD_LOAD: 154 ndisdrv_loaded++; 155 if (ndisdrv_loaded > 1) 156 break; 157 if (windrv_load(mod, (vm_offset_t)drv_data, 0)) 158 return(EINVAL); 159 windrv_wrap((funcptr)ndis_rxeof, &ndis_rxeof_wrap, 160 3, WINDRV_WRAP_STDCALL); 161 windrv_wrap((funcptr)ndis_txeof, &ndis_txeof_wrap, 162 3, WINDRV_WRAP_STDCALL); 163 windrv_wrap((funcptr)ndis_linksts, &ndis_linksts_wrap, 164 4, WINDRV_WRAP_STDCALL); 165 windrv_wrap((funcptr)ndis_linksts_done, 166 &ndis_linksts_done_wrap, 1, WINDRV_WRAP_STDCALL); 167 break; 168 case MOD_UNLOAD: 169 ndisdrv_loaded--; 170 if (ndisdrv_loaded > 0) 171 break; 172 windrv_unload(mod, (vm_offset_t)drv_data, 0); 173 windrv_unwrap(ndis_rxeof_wrap); 174 windrv_unwrap(ndis_txeof_wrap); 175 windrv_unwrap(ndis_linksts_wrap); 176 windrv_unwrap(ndis_linksts_done_wrap); 177 break; 178 case MOD_SHUTDOWN: 179 windrv_unwrap(ndis_rxeof_wrap); 180 windrv_unwrap(ndis_txeof_wrap); 181 windrv_unwrap(ndis_linksts_wrap); 182 windrv_unwrap(ndis_linksts_done_wrap); 183 break; 184 default: 185 error = EINVAL; 186 break; 187 } 188 189 return (error); 190} 191 192/* 193 * Program the 64-bit multicast hash filter. 194 */ 195static void 196ndis_setmulti(sc) 197 struct ndis_softc *sc; 198{ 199 struct ifnet *ifp; 200 struct ifmultiaddr *ifma; 201 int len, mclistsz, error; 202 uint8_t *mclist; 203 204 ifp = &sc->arpcom.ac_if; 205 206 if (!NDIS_INITIALIZED(sc)) 207 return; 208 209 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { 210 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; 211 len = sizeof(sc->ndis_filter); 212 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER, 213 &sc->ndis_filter, &len); 214 if (error) 215 device_printf (sc->ndis_dev, 216 "set filter failed: %d\n", error); 217 return; 218 } 219 220 if (TAILQ_EMPTY(&ifp->if_multiaddrs)) 221 return; 222 223 len = sizeof(mclistsz); 224 ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &mclistsz, &len); 225 226 mclist = malloc(ETHER_ADDR_LEN * mclistsz, M_TEMP, M_NOWAIT|M_ZERO); 227 228 if (mclist == NULL) { 229 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; 230 goto out; 231 } 232 233 sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST; 234 235 len = 0; 236 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 237 if (ifma->ifma_addr->sa_family != AF_LINK) 238 continue; 239 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 240 mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN); 241 len++; 242 if (len > mclistsz) { 243 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; 244 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST; 245 goto out; 246 } 247 } 248 249 len = len * ETHER_ADDR_LEN; 250 error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len); 251 if (error) { 252 device_printf (sc->ndis_dev, "set mclist failed: %d\n", error); 253 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; 254 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST; 255 } 256 257out: 258 free(mclist, M_TEMP); 259 260 len = sizeof(sc->ndis_filter); 261 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER, 262 &sc->ndis_filter, &len); 263 if (error) 264 device_printf (sc->ndis_dev, "set filter failed: %d\n", error); 265 266 return; 267} 268 269static int 270ndis_set_offload(sc) 271 struct ndis_softc *sc; 272{ 273 ndis_task_offload *nto; 274 ndis_task_offload_hdr *ntoh; 275 ndis_task_tcpip_csum *nttc; 276 struct ifnet *ifp; 277 int len, error; 278 279 ifp = &sc->arpcom.ac_if; 280 281 if (!NDIS_INITIALIZED(sc)) 282 return(EINVAL); 283 284 /* See if there's anything to set. */ 285 286 error = ndis_probe_offload(sc); 287 if (error) 288 return(error); 289 290 if (sc->ndis_hwassist == 0 && ifp->if_capabilities == 0) 291 return(0); 292 293 len = sizeof(ndis_task_offload_hdr) + sizeof(ndis_task_offload) + 294 sizeof(ndis_task_tcpip_csum); 295 296 ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO); 297 298 if (ntoh == NULL) 299 return(ENOMEM); 300 301 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION; 302 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr); 303 ntoh->ntoh_offset_firsttask = sizeof(ndis_task_offload_hdr); 304 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header); 305 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3; 306 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN; 307 308 nto = (ndis_task_offload *)((char *)ntoh + 309 ntoh->ntoh_offset_firsttask); 310 311 nto->nto_vers = NDIS_TASK_OFFLOAD_VERSION; 312 nto->nto_len = sizeof(ndis_task_offload); 313 nto->nto_task = NDIS_TASK_TCPIP_CSUM; 314 nto->nto_offset_nexttask = 0; 315 nto->nto_taskbuflen = sizeof(ndis_task_tcpip_csum); 316 317 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf; 318 319 if (ifp->if_capenable & IFCAP_TXCSUM) 320 nttc->nttc_v4tx = sc->ndis_v4tx; 321 322 if (ifp->if_capenable & IFCAP_RXCSUM) 323 nttc->nttc_v4rx = sc->ndis_v4rx; 324 325 error = ndis_set_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len); 326 free(ntoh, M_TEMP); 327 328 return(error); 329} 330 331static int 332ndis_probe_offload(sc) 333 struct ndis_softc *sc; 334{ 335 ndis_task_offload *nto; 336 ndis_task_offload_hdr *ntoh; 337 ndis_task_tcpip_csum *nttc = NULL; 338 struct ifnet *ifp; 339 int len, error, dummy; 340 341 ifp = &sc->arpcom.ac_if; 342 343 len = sizeof(dummy); 344 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, &dummy, &len); 345 346 if (error != ENOSPC) 347 return(error); 348 349 ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO); 350 351 if (ntoh == NULL) 352 return(ENOMEM); 353 354 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION; 355 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr); 356 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header); 357 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3; 358 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN; 359 360 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len); 361 362 if (error) { 363 free(ntoh, M_TEMP); 364 return(error); 365 } 366 367 if (ntoh->ntoh_vers != NDIS_TASK_OFFLOAD_VERSION) { 368 free(ntoh, M_TEMP); 369 return(EINVAL); 370 } 371 372 nto = (ndis_task_offload *)((char *)ntoh + 373 ntoh->ntoh_offset_firsttask); 374 375 while (1) { 376 switch (nto->nto_task) { 377 case NDIS_TASK_TCPIP_CSUM: 378 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf; 379 break; 380 /* Don't handle these yet. */ 381 case NDIS_TASK_IPSEC: 382 case NDIS_TASK_TCP_LARGESEND: 383 default: 384 break; 385 } 386 if (nto->nto_offset_nexttask == 0) 387 break; 388 nto = (ndis_task_offload *)((char *)nto + 389 nto->nto_offset_nexttask); 390 } 391 392 if (nttc == NULL) { 393 free(ntoh, M_TEMP); 394 return(ENOENT); 395 } 396 397 sc->ndis_v4tx = nttc->nttc_v4tx; 398 sc->ndis_v4rx = nttc->nttc_v4rx; 399 400 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_IP_CSUM) 401 sc->ndis_hwassist |= CSUM_IP; 402 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_TCP_CSUM) 403 sc->ndis_hwassist |= CSUM_TCP; 404 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_UDP_CSUM) 405 sc->ndis_hwassist |= CSUM_UDP; 406 407 if (sc->ndis_hwassist) 408 ifp->if_capabilities |= IFCAP_TXCSUM; 409 410 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_IP_CSUM) 411 ifp->if_capabilities |= IFCAP_RXCSUM; 412 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_TCP_CSUM) 413 ifp->if_capabilities |= IFCAP_RXCSUM; 414 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_UDP_CSUM) 415 ifp->if_capabilities |= IFCAP_RXCSUM; 416 417 free(ntoh, M_TEMP); 418 return(0); 419} 420 421/* 422 * Attach the interface. Allocate softc structures, do ifmedia 423 * setup and ethernet/BPF attach. 424 */ 425int 426ndis_attach(dev) 427 device_t dev; 428{ 429 u_char eaddr[ETHER_ADDR_LEN]; 430 struct ndis_softc *sc; 431 driver_object *drv; 432 driver_object *pdrv; 433 device_object *pdo; 434 struct ifnet *ifp = NULL; 435 void *img; 436 int error = 0, len; 437 int i; 438 439 sc = device_get_softc(dev); 440 441 mtx_init(&sc->ndis_mtx, "ndis softc lock", 442 MTX_NETWORK_LOCK, MTX_DEF); 443 444 /* 445 * Hook interrupt early, since calling the driver's 446 * init routine may trigger an interrupt. Note that 447 * we don't need to do any explicit interrupt setup 448 * for USB. 449 */ 450 451 if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus) { 452 error = bus_setup_intr(dev, sc->ndis_irq, 453 INTR_TYPE_NET | INTR_MPSAFE, 454 ndis_intr, sc, &sc->ndis_intrhand); 455 456 if (error) { 457 device_printf(dev, "couldn't set up irq\n"); 458 goto fail; 459 } 460 } 461 462 if (sc->ndis_iftype == PCMCIABus) { 463 error = ndis_alloc_amem(sc); 464 if (error) { 465 device_printf(dev, "failed to allocate " 466 "attribute memory\n"); 467 goto fail; 468 } 469 } 470 471 sc->ndis_regvals = ndis_regvals; 472 473#if __FreeBSD_version < 502113 474 sysctl_ctx_init(&sc->ndis_ctx); 475 476#endif 477 /* Create sysctl registry nodes */ 478 ndis_create_sysctls(sc); 479 480 /* Find the PDO for this device instance. */ 481 482 if (sc->ndis_iftype == PCIBus) 483 pdrv = windrv_lookup(0, "PCI Bus"); 484 else if (sc->ndis_iftype == PCMCIABus) 485 pdrv = windrv_lookup(0, "PCCARD Bus"); 486 else 487 pdrv = windrv_lookup(0, "USB Bus"); 488 pdo = windrv_find_pdo(pdrv, dev); 489 490 /* 491 * Create a new functional device object for this 492 * device. This is what creates the miniport block 493 * for this device instance. 494 */ 495 496 img = drv_data; 497 498 drv = windrv_lookup((vm_offset_t)img, NULL); 499 500 if (drv == NULL) { 501 device_printf(dev, "failed to find driver_object!\n"); 502 error = ENXIO; 503 goto fail; 504 } 505 506 if (NdisAddDevice(drv, pdo) != STATUS_SUCCESS) { 507 device_printf(dev, "failed to create FDO!\n"); 508 error = ENXIO; 509 goto fail; 510 } 511 512 /* Tell the user what version of the API the driver is using. */ 513 device_printf(dev, "NDIS API version: %d.%d\n", 514 sc->ndis_chars->nmc_version_major, 515 sc->ndis_chars->nmc_version_minor); 516 517 /* Do resource conversion. */ 518 if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus) 519 ndis_convert_res(sc); 520 else 521 sc->ndis_block->nmb_rlist = NULL; 522 523 /* Install our RX and TX interrupt handlers. */ 524 sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap; 525 sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap; 526 527 /* Call driver's init routine. */ 528 if (ndis_init_nic(sc)) { 529 device_printf (dev, "init handler failed\n"); 530 error = ENXIO; 531 goto fail; 532 } 533 534 /* 535 * Get station address from the driver. 536 */ 537 len = sizeof(eaddr); 538 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &eaddr, &len); 539 540 bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); 541 542 /* 543 * Figure out if we're allowed to use multipacket sends 544 * with this driver, and if so, how many. 545 */ 546 547 if (sc->ndis_chars->nmc_sendsingle_func && 548 sc->ndis_chars->nmc_sendmulti_func == NULL) { 549 sc->ndis_maxpkts = 1; 550 } else { 551 len = sizeof(sc->ndis_maxpkts); 552 ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS, 553 &sc->ndis_maxpkts, &len); 554 } 555 556 sc->ndis_txarray = malloc(sizeof(ndis_packet *) * 557 sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO); 558 559 /* Allocate a pool of ndis_packets for TX encapsulation. */ 560 561 NdisAllocatePacketPool(&i, &sc->ndis_txpool, 562 sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET); 563 564 if (i != NDIS_STATUS_SUCCESS) { 565 sc->ndis_txpool = NULL; 566 device_printf(dev, "failed to allocate TX packet pool"); 567 error = ENOMEM; 568 goto fail; 569 } 570 571 sc->ndis_txpending = sc->ndis_maxpkts; 572 573 sc->ndis_oidcnt = 0; 574 /* Get supported oid list. */ 575 ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt); 576 577 /* If the NDIS module requested scatter/gather, init maps. */ 578 if (sc->ndis_sc) 579 ndis_init_dma(sc); 580 581 /* 582 * See if the OID_802_11_CONFIGURATION OID is 583 * supported by this driver. If it is, then this an 802.11 584 * wireless driver, and we should set up media for wireless. 585 */ 586 for (i = 0; i < sc->ndis_oidcnt; i++) { 587 if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) { 588 sc->ndis_80211++; 589 break; 590 } 591 } 592 593 /* Check for task offload support. */ 594 ndis_probe_offload(sc); 595 596 ifp = &sc->arpcom.ac_if; 597 ifp->if_softc = sc; 598 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 599 ifp->if_mtu = ETHERMTU; 600 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 601 ifp->if_ioctl = ndis_ioctl; 602 ifp->if_start = ndis_start; 603 ifp->if_watchdog = ndis_watchdog; 604 ifp->if_init = ndis_init; 605 ifp->if_baudrate = 10000000; 606#if __FreeBSD_version < 502114 607 ifp->if_snd.ifq_maxlen = 50; 608#else 609 IFQ_SET_MAXLEN(&ifp->if_snd, 50); 610 ifp->if_snd.ifq_drv_maxlen = 25; 611 IFQ_SET_READY(&ifp->if_snd); 612#endif 613 ifp->if_capenable = ifp->if_capabilities; 614 ifp->if_hwassist = sc->ndis_hwassist; 615 616 /* Do media setup */ 617 if (sc->ndis_80211) { 618 struct ieee80211com *ic = (void *)&sc->ic; 619 ndis_80211_rates_ex rates; 620 struct ndis_80211_nettype_list *ntl; 621 uint32_t arg; 622 int r; 623 624 ic->ic_ifp = ifp; 625 ic->ic_phytype = IEEE80211_T_DS; 626 ic->ic_opmode = IEEE80211_M_STA; 627 ic->ic_caps = IEEE80211_C_IBSS; 628 ic->ic_state = IEEE80211_S_ASSOC; 629 ic->ic_modecaps = (1<<IEEE80211_MODE_AUTO); 630 len = 0; 631 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, 632 NULL, &len); 633 if (r != ENOSPC) 634 goto nonettypes; 635 ntl = malloc(len, M_DEVBUF, M_WAITOK|M_ZERO); 636 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, 637 ntl, &len); 638 if (r != 0) { 639 free(ntl, M_DEVBUF); 640 goto nonettypes; 641 } 642 643 for (i = 0; i < ntl->ntl_items; i++) { 644 switch (ntl->ntl_type[i]) { 645 case NDIS_80211_NETTYPE_11FH: 646 case NDIS_80211_NETTYPE_11DS: 647 ic->ic_modecaps |= (1<<IEEE80211_MODE_11B); 648 break; 649 case NDIS_80211_NETTYPE_11OFDM5: 650 ic->ic_modecaps |= (1<<IEEE80211_MODE_11A); 651 break; 652 case NDIS_80211_NETTYPE_11OFDM24: 653 ic->ic_modecaps |= (1<<IEEE80211_MODE_11G); 654 break; 655 default: 656 break; 657 } 658 } 659 free(ntl, M_DEVBUF); 660nonettypes: 661 len = sizeof(rates); 662 bzero((char *)&rates, len); 663 r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, 664 (void *)rates, &len); 665 if (r) 666 device_printf (dev, "get rates failed: 0x%x\n", r); 667 /* 668 * Since the supported rates only up to 8 can be supported, 669 * if this is not 802.11b we're just going to be faking it 670 * all up to heck. 671 */ 672 673#define TESTSETRATE(x, y) \ 674 do { \ 675 int i; \ 676 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \ 677 if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \ 678 break; \ 679 } \ 680 if (i == ic->ic_sup_rates[x].rs_nrates) { \ 681 ic->ic_sup_rates[x].rs_rates[i] = (y); \ 682 ic->ic_sup_rates[x].rs_nrates++; \ 683 } \ 684 } while (0) 685 686#define SETRATE(x, y) \ 687 ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y) 688#define INCRATE(x) \ 689 ic->ic_sup_rates[x].rs_nrates++ 690 691 ic->ic_curmode = IEEE80211_MODE_AUTO; 692 if (ic->ic_modecaps & (1<<IEEE80211_MODE_11A)) 693 ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0; 694 if (ic->ic_modecaps & (1<<IEEE80211_MODE_11B)) 695 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0; 696 if (ic->ic_modecaps & (1<<IEEE80211_MODE_11G)) 697 ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0; 698 for (i = 0; i < len; i++) { 699 switch (rates[i] & IEEE80211_RATE_VAL) { 700 case 2: 701 case 4: 702 case 11: 703 case 10: 704 case 22: 705 if (!(ic->ic_modecaps & 706 (1<<IEEE80211_MODE_11B))) { 707 /* Lazy-init 802.11b. */ 708 ic->ic_modecaps |= 709 (1<<IEEE80211_MODE_11B); 710 ic->ic_sup_rates[IEEE80211_MODE_11B]. 711 rs_nrates = 0; 712 } 713 SETRATE(IEEE80211_MODE_11B, rates[i]); 714 INCRATE(IEEE80211_MODE_11B); 715 break; 716 default: 717 if (ic->ic_modecaps & (1<<IEEE80211_MODE_11A)) { 718 SETRATE(IEEE80211_MODE_11A, rates[i]); 719 INCRATE(IEEE80211_MODE_11A); 720 } 721 if (ic->ic_modecaps & (1<<IEEE80211_MODE_11G)) { 722 SETRATE(IEEE80211_MODE_11G, rates[i]); 723 INCRATE(IEEE80211_MODE_11G); 724 } 725 break; 726 } 727 } 728 729 /* 730 * If the hardware supports 802.11g, it most 731 * likely supports 802.11b and all of the 732 * 802.11b and 802.11g speeds, so maybe we can 733 * just cheat here. Just how in the heck do 734 * we detect turbo modes, though? 735 */ 736 if (ic->ic_modecaps & (1<<IEEE80211_MODE_11B)) { 737 TESTSETRATE(IEEE80211_MODE_11B, 738 IEEE80211_RATE_BASIC|2); 739 TESTSETRATE(IEEE80211_MODE_11B, 740 IEEE80211_RATE_BASIC|4); 741 TESTSETRATE(IEEE80211_MODE_11B, 742 IEEE80211_RATE_BASIC|11); 743 TESTSETRATE(IEEE80211_MODE_11B, 744 IEEE80211_RATE_BASIC|22); 745 } 746 if (ic->ic_modecaps & (1<<IEEE80211_MODE_11G)) { 747 TESTSETRATE(IEEE80211_MODE_11G, 47); 748 TESTSETRATE(IEEE80211_MODE_11G, 72); 749 TESTSETRATE(IEEE80211_MODE_11G, 96); 750 TESTSETRATE(IEEE80211_MODE_11G, 108); 751 } 752 if (ic->ic_modecaps & (1<<IEEE80211_MODE_11A)) { 753 TESTSETRATE(IEEE80211_MODE_11A, 47); 754 TESTSETRATE(IEEE80211_MODE_11A, 72); 755 TESTSETRATE(IEEE80211_MODE_11A, 96); 756 TESTSETRATE(IEEE80211_MODE_11A, 108); 757 } 758#undef SETRATE 759#undef INCRATE 760 /* 761 * Taking yet more guesses here. 762 */ 763 for (i = 1; i < IEEE80211_CHAN_MAX; i++) { 764 int chanflag = 0; 765 766 if (ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates) 767 chanflag |= IEEE80211_CHAN_G; 768 if (i <= 14) 769 chanflag |= IEEE80211_CHAN_B; 770 if (ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates && 771 i > 14) 772 chanflag = IEEE80211_CHAN_A; 773 if (chanflag == 0) 774 break; 775 ic->ic_channels[i].ic_freq = 776 ieee80211_ieee2mhz(i, chanflag); 777 ic->ic_channels[i].ic_flags = chanflag; 778 } 779 780 i = sizeof(arg); 781 r = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &i); 782 if (arg != NDIS_80211_WEPSTAT_NOTSUPPORTED) 783 ic->ic_caps |= IEEE80211_C_WEP; 784 i = sizeof(arg); 785 r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i); 786 if (r == 0) 787 ic->ic_caps |= IEEE80211_C_PMGT; 788 bcopy(eaddr, &ic->ic_myaddr, sizeof(eaddr)); 789 ieee80211_ifattach(ic); 790 ieee80211_media_init(ic, ieee80211_media_change, 791 ndis_media_status); 792 ic->ic_ibss_chan = IEEE80211_CHAN_ANYC; 793 ic->ic_bss->ni_chan = ic->ic_ibss_chan; 794 } else { 795 ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd, 796 ndis_ifmedia_sts); 797 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL); 798 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); 799 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL); 800 ifmedia_add(&sc->ifmedia, 801 IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); 802 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); 803 ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO); 804 ether_ifattach(ifp, eaddr); 805 } 806 807 /* Override the status handler so we can detect link changes. */ 808 sc->ndis_block->nmb_status_func = ndis_linksts_wrap; 809 sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap; 810fail: 811 if (error) 812 ndis_detach(dev); 813 else 814 /* We're done talking to the NIC for now; halt it. */ 815 ndis_halt_nic(sc); 816 817 return(error); 818} 819 820/* 821 * Shutdown hardware and free up resources. This can be called any 822 * time after the mutex has been initialized. It is called in both 823 * the error case in attach and the normal detach case so it needs 824 * to be careful about only freeing resources that have actually been 825 * allocated. 826 */ 827int 828ndis_detach(dev) 829 device_t dev; 830{ 831 struct ndis_softc *sc; 832 struct ifnet *ifp; 833 driver_object *drv; 834 835 sc = device_get_softc(dev); 836 KASSERT(mtx_initialized(&sc->ndis_mtx), 837 ("ndis mutex not initialized")); 838 NDIS_LOCK(sc); 839 ifp = &sc->arpcom.ac_if; 840 ifp->if_flags &= ~IFF_UP; 841 842 if (device_is_attached(dev)) { 843 NDIS_UNLOCK(sc); 844 ndis_stop(sc); 845 if (sc->ndis_80211) 846 ieee80211_ifdetach(&sc->ic); 847 else 848 ether_ifdetach(ifp); 849 } else 850 NDIS_UNLOCK(sc); 851 852 bus_generic_detach(dev); 853 854 if (sc->ndis_intrhand) 855 bus_teardown_intr(dev, sc->ndis_irq, sc->ndis_intrhand); 856 if (sc->ndis_irq) 857 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq); 858 if (sc->ndis_res_io) 859 bus_release_resource(dev, SYS_RES_IOPORT, 860 sc->ndis_io_rid, sc->ndis_res_io); 861 if (sc->ndis_res_mem) 862 bus_release_resource(dev, SYS_RES_MEMORY, 863 sc->ndis_mem_rid, sc->ndis_res_mem); 864 if (sc->ndis_res_altmem) 865 bus_release_resource(dev, SYS_RES_MEMORY, 866 sc->ndis_altmem_rid, sc->ndis_res_altmem); 867 868 if (sc->ndis_iftype == PCMCIABus) 869 ndis_free_amem(sc); 870 871 if (sc->ndis_sc) 872 ndis_destroy_dma(sc); 873 874 if (sc->ndis_txarray) 875 free(sc->ndis_txarray, M_DEVBUF); 876 877 if (!sc->ndis_80211) 878 ifmedia_removeall(&sc->ifmedia); 879 880 if (sc->ndis_txpool != NULL) 881 NdisFreePacketPool(sc->ndis_txpool); 882 883 ndis_unload_driver(sc); 884 885 /* Destroy the PDO for this device. */ 886 887 if (sc->ndis_iftype == PCIBus) 888 drv = windrv_lookup(0, "PCI Bus"); 889 else if (sc->ndis_iftype == PCMCIABus) 890 drv = windrv_lookup(0, "PCCARD Bus"); 891 else 892 drv = windrv_lookup(0, "USB Bus"); 893 if (drv == NULL) 894 panic("couldn't find driver object"); 895 windrv_destroy_pdo(drv, dev); 896 897 if (sc->ndis_iftype == PCIBus) 898 bus_dma_tag_destroy(sc->ndis_parent_tag); 899 900#if __FreeBSD_version < 502113 901 sysctl_ctx_free(&sc->ndis_ctx); 902#endif 903 904 mtx_destroy(&sc->ndis_mtx); 905 906 return(0); 907} 908 909int 910ndis_suspend(dev) 911 device_t dev; 912{ 913 struct ndis_softc *sc; 914 struct ifnet *ifp; 915 916 sc = device_get_softc(dev); 917 ifp = &sc->arpcom.ac_if; 918 919#ifdef notdef 920 if (NDIS_INITIALIZED(sc)) 921 ndis_stop(sc); 922#endif 923 924 return(0); 925} 926 927int 928ndis_resume(dev) 929 device_t dev; 930{ 931 struct ndis_softc *sc; 932 struct ifnet *ifp; 933 934 sc = device_get_softc(dev); 935 ifp = &sc->arpcom.ac_if; 936 937 if (NDIS_INITIALIZED(sc)) 938 ndis_init(sc); 939 940 return(0); 941} 942 943/* 944 * A frame has been uploaded: pass the resulting mbuf chain up to 945 * the higher level protocols. 946 * 947 * When handling received NDIS packets, the 'status' field in the 948 * out-of-band portion of the ndis_packet has special meaning. In the 949 * most common case, the underlying NDIS driver will set this field 950 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to 951 * take posession of it. We then change the status field to 952 * NDIS_STATUS_PENDING to tell the driver that we now own the packet, 953 * and that we will return it at some point in the future via the 954 * return packet handler. 955 * 956 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES, 957 * this means the driver is running out of packet/buffer resources and 958 * wants to maintain ownership of the packet. In this case, we have to 959 * copy the packet data into local storage and let the driver keep the 960 * packet. 961 */ 962static void 963ndis_rxeof(adapter, packets, pktcnt) 964 ndis_handle adapter; 965 ndis_packet **packets; 966 uint32_t pktcnt; 967{ 968 struct ndis_softc *sc; 969 ndis_miniport_block *block; 970 ndis_packet *p; 971 uint32_t s; 972 ndis_tcpip_csum *csum; 973 struct ifnet *ifp; 974 struct mbuf *m0, *m; 975 int i; 976 977 block = (ndis_miniport_block *)adapter; 978 sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 979 ifp = &sc->arpcom.ac_if; 980 981 for (i = 0; i < pktcnt; i++) { 982 p = packets[i]; 983 /* Stash the softc here so ptom can use it. */ 984 p->np_softc = sc; 985 if (ndis_ptom(&m0, p)) { 986 device_printf (sc->ndis_dev, "ptom failed\n"); 987 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) 988 ndis_return_packet(sc, p); 989 } else { 990 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) { 991 m = m_dup(m0, M_DONTWAIT); 992 /* 993 * NOTE: we want to destroy the mbuf here, but 994 * we don't actually want to return it to the 995 * driver via the return packet handler. By 996 * bumping np_refcnt, we can prevent the 997 * ndis_return_packet() routine from actually 998 * doing anything. 999 */ 1000 p->np_refcnt++; 1001 m_freem(m0); 1002 if (m == NULL) 1003 ifp->if_ierrors++; 1004 else 1005 m0 = m; 1006 } else 1007 p->np_oob.npo_status = NDIS_STATUS_PENDING; 1008 m0->m_pkthdr.rcvif = ifp; 1009 ifp->if_ipackets++; 1010 1011 /* Deal with checksum offload. */ 1012 1013 if (ifp->if_capenable & IFCAP_RXCSUM && 1014 p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) { 1015 s = (uintptr_t) 1016 p->np_ext.npe_info[ndis_tcpipcsum_info]; 1017 csum = (ndis_tcpip_csum *)&s; 1018 if (csum->u.ntc_rxflags & 1019 NDIS_RXCSUM_IP_PASSED) 1020 m0->m_pkthdr.csum_flags |= 1021 CSUM_IP_CHECKED|CSUM_IP_VALID; 1022 if (csum->u.ntc_rxflags & 1023 (NDIS_RXCSUM_TCP_PASSED | 1024 NDIS_RXCSUM_UDP_PASSED)) { 1025 m0->m_pkthdr.csum_flags |= 1026 CSUM_DATA_VALID|CSUM_PSEUDO_HDR; 1027 m0->m_pkthdr.csum_data = 0xFFFF; 1028 } 1029 } 1030 1031 (*ifp->if_input)(ifp, m0); 1032 } 1033 } 1034 1035 return; 1036} 1037 1038/* 1039 * A frame was downloaded to the chip. It's safe for us to clean up 1040 * the list buffers. 1041 */ 1042static void 1043ndis_txeof(adapter, packet, status) 1044 ndis_handle adapter; 1045 ndis_packet *packet; 1046 ndis_status status; 1047 1048{ 1049 struct ndis_softc *sc; 1050 ndis_miniport_block *block; 1051 struct ifnet *ifp; 1052 int idx; 1053 struct mbuf *m; 1054 1055 block = (ndis_miniport_block *)adapter; 1056 sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1057 ifp = &sc->arpcom.ac_if; 1058 1059 m = packet->np_m0; 1060 idx = packet->np_txidx; 1061 if (sc->ndis_sc) 1062 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]); 1063 1064 ndis_free_packet(packet); 1065 m_freem(m); 1066 1067 NDIS_LOCK(sc); 1068 sc->ndis_txarray[idx] = NULL; 1069 sc->ndis_txpending++; 1070 1071 if (status == NDIS_STATUS_SUCCESS) 1072 ifp->if_opackets++; 1073 else 1074 ifp->if_oerrors++; 1075 ifp->if_timer = 0; 1076 ifp->if_flags &= ~IFF_OACTIVE; 1077 NDIS_UNLOCK(sc); 1078 1079 ndis_sched(ndis_starttask, ifp, NDIS_TASKQUEUE); 1080 1081 return; 1082} 1083 1084static void 1085ndis_linksts(adapter, status, sbuf, slen) 1086 ndis_handle adapter; 1087 ndis_status status; 1088 void *sbuf; 1089 uint32_t slen; 1090{ 1091 ndis_miniport_block *block; 1092 struct ndis_softc *sc; 1093 1094 block = adapter; 1095 sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1096 1097 block->nmb_getstat = status; 1098 1099 return; 1100} 1101 1102static void 1103ndis_linksts_done(adapter) 1104 ndis_handle adapter; 1105{ 1106 ndis_miniport_block *block; 1107 struct ndis_softc *sc; 1108 struct ifnet *ifp; 1109 1110 block = adapter; 1111 sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1112 ifp = &sc->arpcom.ac_if; 1113 1114 if (!NDIS_INITIALIZED(sc)) 1115 return; 1116 1117 switch (block->nmb_getstat) { 1118 case NDIS_STATUS_MEDIA_CONNECT: 1119 ndis_sched(ndis_ticktask, sc, NDIS_TASKQUEUE); 1120 ndis_sched(ndis_starttask, ifp, NDIS_TASKQUEUE); 1121 break; 1122 case NDIS_STATUS_MEDIA_DISCONNECT: 1123 if (sc->ndis_link) 1124 ndis_sched(ndis_ticktask, sc, NDIS_TASKQUEUE); 1125 break; 1126 default: 1127 break; 1128 } 1129 1130 return; 1131} 1132 1133static void 1134ndis_intr(arg) 1135 void *arg; 1136{ 1137 struct ndis_softc *sc; 1138 struct ifnet *ifp; 1139 int is_our_intr = 0; 1140 int call_isr = 0; 1141 uint8_t irql; 1142 ndis_miniport_interrupt *intr; 1143 1144 sc = arg; 1145 ifp = &sc->arpcom.ac_if; 1146 intr = sc->ndis_block->nmb_interrupt; 1147 1148 if (sc->ndis_block->nmb_miniportadapterctx == NULL) 1149 return; 1150 1151 KeAcquireSpinLock(&intr->ni_dpccountlock, &irql); 1152 if (sc->ndis_block->nmb_interrupt->ni_isrreq == TRUE) 1153 ndis_isr(sc, &is_our_intr, &call_isr); 1154 else { 1155 ndis_disable_intr(sc); 1156 call_isr = 1; 1157 } 1158 KeReleaseSpinLock(&intr->ni_dpccountlock, irql); 1159 1160 if ((is_our_intr || call_isr)) 1161 IoRequestDpc(sc->ndis_block->nmb_deviceobj, NULL, sc); 1162 1163 return; 1164} 1165 1166static void 1167ndis_tick(xsc) 1168 void *xsc; 1169{ 1170 struct ndis_softc *sc; 1171 1172 mtx_unlock(&Giant); 1173 1174 sc = xsc; 1175 1176 ndis_sched(ndis_ticktask, sc, NDIS_TASKQUEUE); 1177 sc->ndis_stat_ch = timeout(ndis_tick, sc, hz * 1178 sc->ndis_block->nmb_checkforhangsecs); 1179 1180 mtx_lock(&Giant); 1181 1182 return; 1183} 1184 1185static void 1186ndis_ticktask(xsc) 1187 void *xsc; 1188{ 1189 struct ndis_softc *sc; 1190 ndis_checkforhang_handler hangfunc; 1191 uint8_t rval; 1192 ndis_media_state linkstate; 1193 int error, len; 1194 1195 sc = xsc; 1196 1197 hangfunc = sc->ndis_chars->nmc_checkhang_func; 1198 1199 if (hangfunc != NULL) { 1200 rval = MSCALL1(hangfunc, 1201 sc->ndis_block->nmb_miniportadapterctx); 1202 if (rval == TRUE) { 1203 ndis_reset_nic(sc); 1204 return; 1205 } 1206 } 1207 1208 len = sizeof(linkstate); 1209 error = ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS, 1210 (void *)&linkstate, &len); 1211 1212 NDIS_LOCK(sc); 1213 1214 if (sc->ndis_link == 0 && linkstate == nmc_connected) { 1215 device_printf(sc->ndis_dev, "link up\n"); 1216 sc->ndis_link = 1; 1217 NDIS_UNLOCK(sc); 1218 if (sc->ndis_80211) 1219 ndis_getstate_80211(sc); 1220 NDIS_LOCK(sc); 1221#ifdef LINK_STATE_UP 1222 sc->arpcom.ac_if.if_link_state = LINK_STATE_UP; 1223 rt_ifmsg(&(sc->arpcom.ac_if)); 1224#endif /* LINK_STATE_UP */ 1225 } 1226 1227 if (sc->ndis_link == 1 && linkstate == nmc_disconnected) { 1228 device_printf(sc->ndis_dev, "link down\n"); 1229 sc->ndis_link = 0; 1230#ifdef LINK_STATE_DOWN 1231 sc->arpcom.ac_if.if_link_state = LINK_STATE_DOWN; 1232 rt_ifmsg(&(sc->arpcom.ac_if)); 1233#endif /* LINK_STATE_DOWN */ 1234 } 1235 1236 NDIS_UNLOCK(sc); 1237 1238 return; 1239} 1240 1241static void 1242ndis_map_sclist(arg, segs, nseg, mapsize, error) 1243 void *arg; 1244 bus_dma_segment_t *segs; 1245 int nseg; 1246 bus_size_t mapsize; 1247 int error; 1248 1249{ 1250 struct ndis_sc_list *sclist; 1251 int i; 1252 1253 if (error || arg == NULL) 1254 return; 1255 1256 sclist = arg; 1257 1258 sclist->nsl_frags = nseg; 1259 1260 for (i = 0; i < nseg; i++) { 1261 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr; 1262 sclist->nsl_elements[i].nse_len = segs[i].ds_len; 1263 } 1264 1265 return; 1266} 1267 1268static void 1269ndis_starttask(arg) 1270 void *arg; 1271{ 1272 struct ifnet *ifp; 1273 1274 ifp = arg; 1275#if __FreeBSD_version < 502114 1276 if (ifp->if_snd.ifq_head != NULL) 1277#else 1278 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1279#endif 1280 ndis_start(ifp); 1281 return; 1282} 1283 1284/* 1285 * Main transmit routine. To make NDIS drivers happy, we need to 1286 * transform mbuf chains into NDIS packets and feed them to the 1287 * send packet routines. Most drivers allow you to send several 1288 * packets at once (up to the maxpkts limit). Unfortunately, rather 1289 * that accepting them in the form of a linked list, they expect 1290 * a contiguous array of pointers to packets. 1291 * 1292 * For those drivers which use the NDIS scatter/gather DMA mechanism, 1293 * we need to perform busdma work here. Those that use map registers 1294 * will do the mapping themselves on a buffer by buffer basis. 1295 */ 1296 1297static void 1298ndis_start(ifp) 1299 struct ifnet *ifp; 1300{ 1301 struct ndis_softc *sc; 1302 struct mbuf *m = NULL; 1303 ndis_packet **p0 = NULL, *p = NULL; 1304 ndis_tcpip_csum *csum; 1305 int pcnt = 0, status; 1306 1307 sc = ifp->if_softc; 1308 1309 NDIS_LOCK(sc); 1310 1311 if (!sc->ndis_link || ifp->if_flags & IFF_OACTIVE) { 1312 NDIS_UNLOCK(sc); 1313 return; 1314 } 1315 1316 p0 = &sc->ndis_txarray[sc->ndis_txidx]; 1317 1318 while(sc->ndis_txpending) { 1319#if __FreeBSD_version < 502114 1320 IF_DEQUEUE(&ifp->if_snd, m); 1321#else 1322 IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 1323#endif 1324 if (m == NULL) 1325 break; 1326 1327 NdisAllocatePacket(&status, 1328 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool); 1329 1330 if (status != NDIS_STATUS_SUCCESS) 1331 break; 1332 1333 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) { 1334#if __FreeBSD_version >= 502114 1335 IFQ_DRV_PREPEND(&ifp->if_snd, m); 1336#endif 1337 NDIS_UNLOCK(sc); 1338#if __FreeBSD_version < 502114 1339 IF_PREPEND(&ifp->if_snd, m); 1340#endif 1341 return; 1342 } 1343 1344 /* 1345 * Save pointer to original mbuf 1346 * so we can free it later. 1347 */ 1348 1349 p = sc->ndis_txarray[sc->ndis_txidx]; 1350 p->np_txidx = sc->ndis_txidx; 1351 p->np_m0 = m; 1352 p->np_oob.npo_status = NDIS_STATUS_PENDING; 1353 1354 /* 1355 * Do scatter/gather processing, if driver requested it. 1356 */ 1357 if (sc->ndis_sc) { 1358 bus_dmamap_load_mbuf(sc->ndis_ttag, 1359 sc->ndis_tmaps[sc->ndis_txidx], m, 1360 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT); 1361 bus_dmamap_sync(sc->ndis_ttag, 1362 sc->ndis_tmaps[sc->ndis_txidx], 1363 BUS_DMASYNC_PREREAD); 1364 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist; 1365 } 1366 1367 /* Handle checksum offload. */ 1368 1369 if (ifp->if_capenable & IFCAP_TXCSUM && 1370 m->m_pkthdr.csum_flags) { 1371 csum = (ndis_tcpip_csum *) 1372 &p->np_ext.npe_info[ndis_tcpipcsum_info]; 1373 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4; 1374 if (m->m_pkthdr.csum_flags & CSUM_IP) 1375 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP; 1376 if (m->m_pkthdr.csum_flags & CSUM_TCP) 1377 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP; 1378 if (m->m_pkthdr.csum_flags & CSUM_UDP) 1379 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP; 1380 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP; 1381 } 1382 1383 NDIS_INC(sc); 1384 sc->ndis_txpending--; 1385 1386 pcnt++; 1387 1388 /* 1389 * If there's a BPF listener, bounce a copy of this frame 1390 * to him. 1391 */ 1392 1393 BPF_MTAP(ifp, m); 1394 1395 /* 1396 * The array that p0 points to must appear contiguous, 1397 * so we must not wrap past the end of sc->ndis_txarray[]. 1398 * If it looks like we're about to wrap, break out here 1399 * so the this batch of packets can be transmitted, then 1400 * wait for txeof to ask us to send the rest. 1401 */ 1402 1403 if (sc->ndis_txidx == 0) 1404 break; 1405 } 1406 1407 if (pcnt == 0) { 1408 NDIS_UNLOCK(sc); 1409 return; 1410 } 1411 1412 if (sc->ndis_txpending == 0) 1413 ifp->if_flags |= IFF_OACTIVE; 1414 1415 /* 1416 * Set a timeout in case the chip goes out to lunch. 1417 */ 1418 ifp->if_timer = 5; 1419 1420 NDIS_UNLOCK(sc); 1421 1422 if (sc->ndis_maxpkts == 1) 1423 ndis_send_packet(sc, p); 1424 else 1425 ndis_send_packets(sc, p0, pcnt); 1426 1427 return; 1428} 1429 1430static void 1431ndis_init(xsc) 1432 void *xsc; 1433{ 1434 struct ndis_softc *sc = xsc; 1435 struct ifnet *ifp = &sc->arpcom.ac_if; 1436 int i, error; 1437 1438 /* 1439 * Avoid reintializing the link unnecessarily. 1440 * This should be dealt with in a better way by 1441 * fixing the upper layer modules so they don't 1442 * call ifp->if_init() quite as often. 1443 */ 1444 if (sc->ndis_link && sc->ndis_skip) 1445 return; 1446 1447 /* 1448 * Cancel pending I/O and free all RX/TX buffers. 1449 */ 1450 ndis_stop(sc); 1451 if (ndis_init_nic(sc)) 1452 return; 1453 1454 /* Init our MAC address */ 1455 1456 /* Program the packet filter */ 1457 1458 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED; 1459 1460 if (ifp->if_flags & IFF_BROADCAST) 1461 sc->ndis_filter |= NDIS_PACKET_TYPE_BROADCAST; 1462 1463 if (ifp->if_flags & IFF_PROMISC) 1464 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; 1465 1466 i = sizeof(sc->ndis_filter); 1467 1468 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER, 1469 &sc->ndis_filter, &i); 1470 1471 if (error) 1472 device_printf (sc->ndis_dev, "set filter failed: %d\n", error); 1473 1474 /* 1475 * Program the multicast filter, if necessary. 1476 */ 1477 ndis_setmulti(sc); 1478 1479 /* Setup task offload. */ 1480 ndis_set_offload(sc); 1481 1482 /* Enable interrupts. */ 1483 ndis_enable_intr(sc); 1484 1485 if (sc->ndis_80211) 1486 ndis_setstate_80211(sc); 1487 1488 NDIS_LOCK(sc); 1489 1490 sc->ndis_txidx = 0; 1491 sc->ndis_txpending = sc->ndis_maxpkts; 1492 sc->ndis_link = 0; 1493 1494 ifp->if_flags |= IFF_RUNNING; 1495 ifp->if_flags &= ~IFF_OACTIVE; 1496 1497 NDIS_UNLOCK(sc); 1498 1499 /* 1500 * Some drivers don't set this value. The NDIS spec says 1501 * the default checkforhang timeout is "approximately 2 1502 * seconds." We use 3 seconds, because it seems for some 1503 * drivers, exactly 2 seconds is too fast. 1504 */ 1505 1506 if (sc->ndis_block->nmb_checkforhangsecs == 0) 1507 sc->ndis_block->nmb_checkforhangsecs = 3; 1508 1509 sc->ndis_stat_ch = timeout(ndis_tick, sc, 1510 hz * sc->ndis_block->nmb_checkforhangsecs); 1511 1512 return; 1513} 1514 1515/* 1516 * Set media options. 1517 */ 1518static int 1519ndis_ifmedia_upd(ifp) 1520 struct ifnet *ifp; 1521{ 1522 struct ndis_softc *sc; 1523 1524 sc = ifp->if_softc; 1525 1526 if (NDIS_INITIALIZED(sc)) 1527 ndis_init(sc); 1528 1529 return(0); 1530} 1531 1532/* 1533 * Report current media status. 1534 */ 1535static void 1536ndis_ifmedia_sts(ifp, ifmr) 1537 struct ifnet *ifp; 1538 struct ifmediareq *ifmr; 1539{ 1540 struct ndis_softc *sc; 1541 uint32_t media_info; 1542 ndis_media_state linkstate; 1543 int error, len; 1544 1545 ifmr->ifm_status = IFM_AVALID; 1546 ifmr->ifm_active = IFM_ETHER; 1547 sc = ifp->if_softc; 1548 1549 if (!NDIS_INITIALIZED(sc)) 1550 return; 1551 1552 len = sizeof(linkstate); 1553 error = ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS, 1554 (void *)&linkstate, &len); 1555 1556 len = sizeof(media_info); 1557 error = ndis_get_info(sc, OID_GEN_LINK_SPEED, 1558 (void *)&media_info, &len); 1559 1560 if (linkstate == nmc_connected) 1561 ifmr->ifm_status |= IFM_ACTIVE; 1562 1563 switch(media_info) { 1564 case 100000: 1565 ifmr->ifm_active |= IFM_10_T; 1566 break; 1567 case 1000000: 1568 ifmr->ifm_active |= IFM_100_TX; 1569 break; 1570 case 10000000: 1571 ifmr->ifm_active |= IFM_1000_T; 1572 break; 1573 default: 1574 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info); 1575 break; 1576 } 1577 1578 return; 1579} 1580 1581static void 1582ndis_setstate_80211(sc) 1583 struct ndis_softc *sc; 1584{ 1585 struct ieee80211com *ic; 1586 ndis_80211_ssid ssid; 1587 ndis_80211_config config; 1588 ndis_80211_wep wep; 1589 int i, rval = 0, len; 1590 uint32_t arg; 1591 struct ifnet *ifp; 1592 1593 ic = &sc->ic; 1594 ifp = &sc->arpcom.ac_if; 1595 1596 if (!NDIS_INITIALIZED(sc)) 1597 return; 1598 1599 /* Set network infrastructure mode. */ 1600 1601 len = sizeof(arg); 1602 if (ic->ic_opmode == IEEE80211_M_IBSS) 1603 arg = NDIS_80211_NET_INFRA_IBSS; 1604 else 1605 arg = NDIS_80211_NET_INFRA_BSS; 1606 1607 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len); 1608 1609 if (rval) 1610 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval); 1611 1612 /* Set WEP */ 1613 1614#ifdef IEEE80211_F_PRIVACY 1615 if (ic->ic_flags & IEEE80211_F_PRIVACY) { 1616#else 1617 if (ic->ic_wep_mode >= IEEE80211_WEP_ON) { 1618#endif 1619 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1620 if (ic->ic_nw_keys[i].wk_keylen) { 1621 bzero((char *)&wep, sizeof(wep)); 1622 wep.nw_keylen = ic->ic_nw_keys[i].wk_keylen; 1623#ifdef notdef 1624 /* 5 and 13 are the only valid key lengths */ 1625 if (ic->ic_nw_keys[i].wk_keylen < 5) 1626 wep.nw_keylen = 5; 1627 else if (ic->ic_nw_keys[i].wk_keylen > 5 && 1628 ic->ic_nw_keys[i].wk_keylen < 13) 1629 wep.nw_keylen = 13; 1630#endif 1631 wep.nw_keyidx = i; 1632 wep.nw_length = (sizeof(uint32_t) * 3) 1633 + wep.nw_keylen; 1634 if (i == ic->ic_def_txkey) 1635 wep.nw_keyidx |= NDIS_80211_WEPKEY_TX; 1636 bcopy(ic->ic_nw_keys[i].wk_key, 1637 wep.nw_keydata, wep.nw_length); 1638 len = sizeof(wep); 1639 rval = ndis_set_info(sc, 1640 OID_802_11_ADD_WEP, &wep, &len); 1641 if (rval) 1642 device_printf(sc->ndis_dev, 1643 "set wepkey failed: %d\n", rval); 1644 } 1645 } 1646 arg = NDIS_80211_WEPSTAT_ENABLED; 1647 len = sizeof(arg); 1648 rval = ndis_set_info(sc, OID_802_11_WEP_STATUS, &arg, &len); 1649 if (rval) 1650 device_printf(sc->ndis_dev, 1651 "enable WEP failed: %d\n", rval); 1652#ifndef IEEE80211_F_WEPON 1653#if 0 1654 if (ic->ic_wep_mode != IEEE80211_WEP_8021X && 1655 ic->ic_wep_mode != IEEE80211_WEP_ON) 1656 arg = NDIS_80211_PRIVFILT_ACCEPTALL; 1657 else 1658#endif 1659#endif 1660 arg = NDIS_80211_PRIVFILT_8021XWEP; 1661 len = sizeof(arg); 1662 rval = ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len); 1663#ifdef IEEE80211_WEP_8021X /*IEEE80211_F_WEPON*/ 1664 /* Accept that we only have "shared" and 802.1x modes. */ 1665 if (rval == 0) { 1666 if (arg == NDIS_80211_PRIVFILT_ACCEPTALL) 1667 ic->ic_wep_mode = IEEE80211_WEP_MIXED; 1668 else 1669 ic->ic_wep_mode = IEEE80211_WEP_8021X; 1670 } 1671#endif 1672 arg = NDIS_80211_AUTHMODE_OPEN; 1673 } else { 1674 arg = NDIS_80211_WEPSTAT_DISABLED; 1675 len = sizeof(arg); 1676 ndis_set_info(sc, OID_802_11_WEP_STATUS, &arg, &len); 1677 arg = NDIS_80211_AUTHMODE_OPEN; 1678 } 1679 1680 len = sizeof(arg); 1681 rval = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len); 1682 1683#ifdef notyet 1684 if (rval) 1685 device_printf (sc->ndis_dev, "set auth failed: %d\n", rval); 1686#endif 1687 1688#ifdef notyet 1689 /* Set network type. */ 1690 1691 arg = 0; 1692 1693 switch (ic->ic_curmode) { 1694 case IEEE80211_MODE_11A: 1695 arg = NDIS_80211_NETTYPE_11OFDM5; 1696 break; 1697 case IEEE80211_MODE_11B: 1698 arg = NDIS_80211_NETTYPE_11DS; 1699 break; 1700 case IEEE80211_MODE_11G: 1701 arg = NDIS_80211_NETTYPE_11OFDM24; 1702 break; 1703 default: 1704 device_printf(sc->ndis_dev, "unknown mode: %d\n", 1705 ic->ic_curmode); 1706 } 1707 1708 if (arg) { 1709 len = sizeof(arg); 1710 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE, 1711 &arg, &len); 1712 if (rval) 1713 device_printf (sc->ndis_dev, 1714 "set nettype failed: %d\n", rval); 1715 } 1716#endif 1717 1718 len = sizeof(config); 1719 bzero((char *)&config, len); 1720 config.nc_length = len; 1721 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh); 1722 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len); 1723 1724 /* 1725 * Some drivers expect us to initialize these values, so 1726 * provide some defaults. 1727 */ 1728 if (config.nc_beaconperiod == 0) 1729 config.nc_beaconperiod = 100; 1730 if (config.nc_atimwin == 0) 1731 config.nc_atimwin = 100; 1732 if (config.nc_fhconfig.ncf_dwelltime == 0) 1733 config.nc_fhconfig.ncf_dwelltime = 200; 1734 1735 if (rval == 0 && ic->ic_ibss_chan != IEEE80211_CHAN_ANYC) { 1736 int chan, chanflag; 1737 1738 chan = ieee80211_chan2ieee(ic, ic->ic_ibss_chan); 1739 chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ : 1740 IEEE80211_CHAN_5GHZ; 1741 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) { 1742 config.nc_dsconfig = 1743 ic->ic_ibss_chan->ic_freq * 1000; 1744 ic->ic_bss->ni_chan = ic->ic_ibss_chan; 1745 len = sizeof(config); 1746 config.nc_length = len; 1747 config.nc_fhconfig.ncf_length = 1748 sizeof(ndis_80211_config_fh); 1749 rval = ndis_set_info(sc, OID_802_11_CONFIGURATION, 1750 &config, &len); 1751 if (rval) 1752 device_printf(sc->ndis_dev, "couldn't change " 1753 "DS config to %ukHz: %d\n", 1754 config.nc_dsconfig, rval); 1755 } 1756 } else if (rval) 1757 device_printf(sc->ndis_dev, "couldn't retrieve " 1758 "channel info: %d\n", rval); 1759 1760 /* Set SSID -- always do this last. */ 1761 1762 len = sizeof(ssid); 1763 bzero((char *)&ssid, len); 1764 ssid.ns_ssidlen = ic->ic_des_esslen; 1765 if (ssid.ns_ssidlen == 0) { 1766 ssid.ns_ssidlen = 1; 1767 } else 1768 bcopy(ic->ic_des_essid, ssid.ns_ssid, ssid.ns_ssidlen); 1769 rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len); 1770 1771 if (rval) 1772 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval); 1773 1774 return; 1775} 1776 1777static void 1778ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr) 1779{ 1780 struct ieee80211com *ic = &((struct ndis_softc *)ifp->if_softc)->ic; 1781 struct ieee80211_node *ni = NULL; 1782 1783 imr->ifm_status = IFM_AVALID; 1784 imr->ifm_active = IFM_IEEE80211; 1785 if (ic->ic_state == IEEE80211_S_RUN) 1786 imr->ifm_status |= IFM_ACTIVE; 1787 imr->ifm_active |= IFM_AUTO; 1788 switch (ic->ic_opmode) { 1789 case IEEE80211_M_STA: 1790 ni = ic->ic_bss; 1791 /* calculate rate subtype */ 1792 imr->ifm_active |= ieee80211_rate2media(ic, 1793 ni->ni_rates.rs_rates[ni->ni_txrate], ic->ic_curmode); 1794 break; 1795 case IEEE80211_M_IBSS: 1796 ni = ic->ic_bss; 1797 /* calculate rate subtype */ 1798 imr->ifm_active |= ieee80211_rate2media(ic, 1799 ni->ni_rates.rs_rates[ni->ni_txrate], ic->ic_curmode); 1800 imr->ifm_active |= IFM_IEEE80211_ADHOC; 1801 break; 1802 case IEEE80211_M_AHDEMO: 1803 /* should not come here */ 1804 break; 1805 case IEEE80211_M_HOSTAP: 1806 imr->ifm_active |= IFM_IEEE80211_HOSTAP; 1807 break; 1808 case IEEE80211_M_MONITOR: 1809 imr->ifm_active |= IFM_IEEE80211_MONITOR; 1810 break; 1811 } 1812 switch (ic->ic_curmode) { 1813 case IEEE80211_MODE_11A: 1814 imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11A); 1815 break; 1816 case IEEE80211_MODE_11B: 1817 imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11B); 1818 break; 1819 case IEEE80211_MODE_11G: 1820 imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11G); 1821 break; 1822 case IEEE80211_MODE_TURBO_A: 1823 imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11A) 1824 | IFM_IEEE80211_TURBO; 1825 break; 1826 } 1827} 1828 1829static int 1830ndis_get_assoc(sc, assoc) 1831 struct ndis_softc *sc; 1832 ndis_wlan_bssid_ex **assoc; 1833{ 1834 ndis_80211_bssid_list_ex *bl; 1835 ndis_wlan_bssid_ex *bs; 1836 ndis_80211_macaddr bssid; 1837 int i, len, error; 1838 1839 if (!sc->ndis_link) 1840 return(ENOENT); 1841 1842 len = sizeof(bssid); 1843 error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len); 1844 if (error) { 1845 device_printf(sc->ndis_dev, "failed to get bssid\n"); 1846 return(ENOENT); 1847 } 1848 len = 0; 1849 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, NULL, &len); 1850 if (error != ENOSPC) { 1851 device_printf(sc->ndis_dev, "bssid_list failed\n"); 1852 return (error); 1853 } 1854 1855 bl = malloc(len, M_TEMP, M_NOWAIT|M_ZERO); 1856 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl, &len); 1857 if (error) { 1858 free(bl, M_TEMP); 1859 device_printf(sc->ndis_dev, "bssid_list failed\n"); 1860 return (error); 1861 } 1862 1863 bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0]; 1864 for (i = 0; i < bl->nblx_items; i++) { 1865 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) { 1866 *assoc = malloc(bs->nwbx_len, M_TEMP, M_NOWAIT); 1867 if (*assoc == NULL) { 1868 free(bl, M_TEMP); 1869 return(ENOMEM); 1870 } 1871 bcopy((char *)bs, (char *)*assoc, bs->nwbx_len); 1872 free(bl, M_TEMP); 1873 return(0); 1874 } 1875 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len); 1876 } 1877 1878 free(bl, M_TEMP); 1879 return(ENOENT); 1880} 1881 1882static void 1883ndis_getstate_80211(sc) 1884 struct ndis_softc *sc; 1885{ 1886 struct ieee80211com *ic; 1887 ndis_80211_ssid ssid; 1888 ndis_80211_config config; 1889 ndis_wlan_bssid_ex *bs; 1890 int rval, len, i = 0; 1891 uint32_t arg; 1892 struct ifnet *ifp; 1893 1894 ic = &sc->ic; 1895 ifp = &sc->arpcom.ac_if; 1896 1897 if (!NDIS_INITIALIZED(sc)) 1898 return; 1899 1900 if (sc->ndis_link) 1901 ic->ic_state = IEEE80211_S_RUN; 1902 else 1903 ic->ic_state = IEEE80211_S_ASSOC; 1904 1905 1906 /* 1907 * If we're associated, retrieve info on the current bssid. 1908 */ 1909 if ((rval = ndis_get_assoc(sc, &bs)) == 0) { 1910 switch(bs->nwbx_nettype) { 1911 case NDIS_80211_NETTYPE_11FH: 1912 case NDIS_80211_NETTYPE_11DS: 1913 ic->ic_curmode = IEEE80211_MODE_11B; 1914 break; 1915 case NDIS_80211_NETTYPE_11OFDM5: 1916 ic->ic_curmode = IEEE80211_MODE_11A; 1917 break; 1918 case NDIS_80211_NETTYPE_11OFDM24: 1919 ic->ic_curmode = IEEE80211_MODE_11G; 1920 break; 1921 default: 1922 device_printf(sc->ndis_dev, 1923 "unknown nettype %d\n", arg); 1924 break; 1925 } 1926 IEEE80211_ADDR_COPY(ic->ic_bss->ni_bssid, bs->nwbx_macaddr); 1927 free(bs, M_TEMP); 1928 } else 1929 return; 1930 1931 len = sizeof(ssid); 1932 bzero((char *)&ssid, len); 1933 rval = ndis_get_info(sc, OID_802_11_SSID, &ssid, &len); 1934 1935 if (rval) 1936 device_printf (sc->ndis_dev, "get ssid failed: %d\n", rval); 1937 bcopy(ssid.ns_ssid, ic->ic_bss->ni_essid, ssid.ns_ssidlen); 1938 ic->ic_bss->ni_esslen = ssid.ns_ssidlen; 1939 1940 len = sizeof(arg); 1941 rval = ndis_get_info(sc, OID_GEN_LINK_SPEED, &arg, &len); 1942 if (rval) 1943 device_printf (sc->ndis_dev, "get link speed failed: %d\n", 1944 rval); 1945 1946 if (ic->ic_modecaps & (1<<IEEE80211_MODE_11B)) { 1947 ic->ic_bss->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11B]; 1948 for (i = 0; i < ic->ic_bss->ni_rates.rs_nrates; i++) { 1949 if ((ic->ic_bss->ni_rates.rs_rates[i] & 1950 IEEE80211_RATE_VAL) == arg / 5000) 1951 break; 1952 } 1953 } 1954 1955 if (i == ic->ic_bss->ni_rates.rs_nrates && 1956 ic->ic_modecaps & (1<<IEEE80211_MODE_11G)) { 1957 ic->ic_bss->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11G]; 1958 for (i = 0; i < ic->ic_bss->ni_rates.rs_nrates; i++) { 1959 if ((ic->ic_bss->ni_rates.rs_rates[i] & 1960 IEEE80211_RATE_VAL) == arg / 5000) 1961 break; 1962 } 1963 } 1964 1965 if (i == ic->ic_bss->ni_rates.rs_nrates) 1966 device_printf(sc->ndis_dev, "no matching rate for: %d\n", 1967 arg / 5000); 1968 else 1969 ic->ic_bss->ni_txrate = i; 1970 1971 if (ic->ic_caps & IEEE80211_C_PMGT) { 1972 len = sizeof(arg); 1973 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len); 1974 1975 if (rval) 1976 device_printf(sc->ndis_dev, 1977 "get power mode failed: %d\n", rval); 1978 if (arg == NDIS_80211_POWERMODE_CAM) 1979 ic->ic_flags &= ~IEEE80211_F_PMGTON; 1980 else 1981 ic->ic_flags |= IEEE80211_F_PMGTON; 1982 } 1983 1984 len = sizeof(config); 1985 bzero((char *)&config, len); 1986 config.nc_length = len; 1987 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh); 1988 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len); 1989 if (rval == 0) { 1990 int chan; 1991 1992 chan = ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0); 1993 if (chan < 0 || chan >= IEEE80211_CHAN_MAX) { 1994 if (ifp->if_flags & IFF_DEBUG) 1995 device_printf(sc->ndis_dev, "current channel " 1996 "(%uMHz) out of bounds\n", 1997 config.nc_dsconfig / 1000); 1998 ic->ic_bss->ni_chan = &ic->ic_channels[1]; 1999 } else 2000 ic->ic_bss->ni_chan = &ic->ic_channels[chan]; 2001 } else 2002 device_printf(sc->ndis_dev, "couldn't retrieve " 2003 "channel info: %d\n", rval); 2004 2005/* 2006 len = sizeof(arg); 2007 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len); 2008 2009 if (rval) 2010 device_printf (sc->ndis_dev, 2011 "get wep status failed: %d\n", rval); 2012 2013 if (arg == NDIS_80211_WEPSTAT_ENABLED) 2014 ic->ic_flags |= IEEE80211_F_WEPON; 2015 else 2016 ic->ic_flags &= ~IEEE80211_F_WEPON; 2017*/ 2018 return; 2019} 2020 2021static int 2022ndis_ioctl(ifp, command, data) 2023 struct ifnet *ifp; 2024 u_long command; 2025 caddr_t data; 2026{ 2027 struct ndis_softc *sc = ifp->if_softc; 2028 struct ifreq *ifr = (struct ifreq *) data; 2029 int i, error = 0; 2030 2031 /*NDIS_LOCK(sc);*/ 2032 2033 switch(command) { 2034 case SIOCSIFFLAGS: 2035 if (ifp->if_flags & IFF_UP) { 2036 if (ifp->if_flags & IFF_RUNNING && 2037 ifp->if_flags & IFF_PROMISC && 2038 !(sc->ndis_if_flags & IFF_PROMISC)) { 2039 sc->ndis_filter |= 2040 NDIS_PACKET_TYPE_PROMISCUOUS; 2041 i = sizeof(sc->ndis_filter); 2042 error = ndis_set_info(sc, 2043 OID_GEN_CURRENT_PACKET_FILTER, 2044 &sc->ndis_filter, &i); 2045 } else if (ifp->if_flags & IFF_RUNNING && 2046 !(ifp->if_flags & IFF_PROMISC) && 2047 sc->ndis_if_flags & IFF_PROMISC) { 2048 sc->ndis_filter &= 2049 ~NDIS_PACKET_TYPE_PROMISCUOUS; 2050 i = sizeof(sc->ndis_filter); 2051 error = ndis_set_info(sc, 2052 OID_GEN_CURRENT_PACKET_FILTER, 2053 &sc->ndis_filter, &i); 2054 } else 2055 ndis_init(sc); 2056 } else { 2057 if (ifp->if_flags & IFF_RUNNING) 2058 ndis_stop(sc); 2059 } 2060 sc->ndis_if_flags = ifp->if_flags; 2061 error = 0; 2062 break; 2063 case SIOCADDMULTI: 2064 case SIOCDELMULTI: 2065 ndis_setmulti(sc); 2066 error = 0; 2067 break; 2068 case SIOCGIFMEDIA: 2069 case SIOCSIFMEDIA: 2070 if (sc->ndis_80211) { 2071 error = ieee80211_ioctl(&sc->ic, command, data); 2072 if (error == ENETRESET) { 2073 ndis_setstate_80211(sc); 2074 /*ndis_init(sc);*/ 2075 error = 0; 2076 } 2077 } else 2078 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command); 2079 break; 2080 case SIOCSIFCAP: 2081 ifp->if_capenable = ifr->ifr_reqcap; 2082 if (ifp->if_capenable & IFCAP_TXCSUM) 2083 ifp->if_hwassist = sc->ndis_hwassist; 2084 else 2085 ifp->if_hwassist = 0; 2086 ndis_set_offload(sc); 2087 break; 2088 case SIOCG80211: 2089 if (sc->ndis_80211) 2090 error = ndis_80211_ioctl_get(ifp, command, data); 2091 else 2092 error = ENOTTY; 2093 break; 2094 case SIOCS80211: 2095 if (sc->ndis_80211) 2096 error = ndis_80211_ioctl_set(ifp, command, data); 2097 else 2098 error = ENOTTY; 2099 break; 2100 case SIOCGIFGENERIC: 2101 case SIOCSIFGENERIC: 2102 if (sc->ndis_80211 && NDIS_INITIALIZED(sc)) { 2103 if (command == SIOCGIFGENERIC) 2104 error = ndis_wi_ioctl_get(ifp, command, data); 2105 else 2106 error = ndis_wi_ioctl_set(ifp, command, data); 2107 } else 2108 error = ENOTTY; 2109 if (error != ENOTTY) 2110 break; 2111 default: 2112 sc->ndis_skip = 1; 2113 if (sc->ndis_80211) { 2114 error = ieee80211_ioctl(&sc->ic, command, data); 2115 if (error == ENETRESET) { 2116 ndis_setstate_80211(sc); 2117 error = 0; 2118 } 2119 } else 2120 error = ether_ioctl(ifp, command, data); 2121 sc->ndis_skip = 0; 2122 break; 2123 } 2124 2125 /*NDIS_UNLOCK(sc);*/ 2126 2127 return(error); 2128} 2129 2130static int 2131ndis_wi_ioctl_get(ifp, command, data) 2132 struct ifnet *ifp; 2133 u_long command; 2134 caddr_t data; 2135{ 2136 struct wi_req wreq; 2137 struct ifreq *ifr; 2138 struct ndis_softc *sc; 2139 ndis_80211_bssid_list_ex *bl; 2140 ndis_wlan_bssid_ex *wb; 2141 struct wi_apinfo *api; 2142 int error, i, j, len, maxaps; 2143 2144 sc = ifp->if_softc; 2145 ifr = (struct ifreq *)data; 2146 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 2147 if (error) 2148 return (error); 2149 2150 switch (wreq.wi_type) { 2151 case WI_RID_READ_APS: 2152 len = 0; 2153 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, 2154 NULL, &len); 2155 if (error == 0) 2156 tsleep(&error, PPAUSE|PCATCH, "ssidscan", hz * 2); 2157 len = 0; 2158 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, NULL, &len); 2159 if (error != ENOSPC) 2160 break; 2161 bl = malloc(len, M_DEVBUF, M_WAITOK|M_ZERO); 2162 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl, &len); 2163 if (error) { 2164 free(bl, M_DEVBUF); 2165 break; 2166 } 2167 maxaps = (2 * wreq.wi_len - sizeof(int)) / sizeof(*api); 2168 maxaps = MIN(maxaps, bl->nblx_items); 2169 wreq.wi_len = (maxaps * sizeof(*api) + sizeof(int)) / 2; 2170 *(int *)&wreq.wi_val = maxaps; 2171 api = (struct wi_apinfo *)&((int *)&wreq.wi_val)[1]; 2172 wb = bl->nblx_bssid; 2173 while (maxaps--) { 2174 bzero(api, sizeof(*api)); 2175 bcopy(&wb->nwbx_macaddr, &api->bssid, 2176 sizeof(api->bssid)); 2177 api->namelen = wb->nwbx_ssid.ns_ssidlen; 2178 bcopy(&wb->nwbx_ssid.ns_ssid, &api->name, api->namelen); 2179 if (wb->nwbx_privacy) 2180 api->capinfo |= IEEE80211_CAPINFO_PRIVACY; 2181 /* XXX Where can we get noise information? */ 2182 api->signal = wb->nwbx_rssi + 149; /* XXX */ 2183 api->quality = api->signal; 2184 api->channel = 2185 ieee80211_mhz2ieee(wb->nwbx_config.nc_dsconfig / 2186 1000, 0); 2187 /* In "auto" infrastructure mode, this is useless. */ 2188 if (wb->nwbx_netinfra == NDIS_80211_NET_INFRA_IBSS) 2189 api->capinfo |= IEEE80211_CAPINFO_IBSS; 2190 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) { 2191 j = sizeof(ndis_80211_rates_ex); 2192 /* handle other extended things */ 2193 } else 2194 j = sizeof(ndis_80211_rates); 2195 for (i = api->rate = 0; i < j; i++) 2196 api->rate = MAX(api->rate, 5 * 2197 (wb->nwbx_supportedrates[i] & 0x7f)); 2198 api++; 2199 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len); 2200 } 2201 free(bl, M_DEVBUF); 2202 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); 2203 break; 2204 default: 2205 error = ENOTTY; 2206 break; 2207 } 2208 return (error); 2209} 2210 2211static int 2212ndis_wi_ioctl_set(ifp, command, data) 2213 struct ifnet *ifp; 2214 u_long command; 2215 caddr_t data; 2216{ 2217 struct wi_req wreq; 2218 struct ifreq *ifr; 2219 struct ndis_softc *sc; 2220 uint32_t foo; 2221 int error, len; 2222 2223 error = suser(curthread); 2224 if (error) 2225 return (error); 2226 2227 sc = ifp->if_softc; 2228 ifr = (struct ifreq *)data; 2229 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 2230 if (error) 2231 return (error); 2232 2233 switch (wreq.wi_type) { 2234 case WI_RID_SCAN_APS: 2235 case WI_RID_SCAN_REQ: /* arguments ignored */ 2236 len = sizeof(foo); 2237 foo = 0; 2238 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, &foo, 2239 &len); 2240 break; 2241 default: 2242 error = ENOTTY; 2243 break; 2244 } 2245 return (error); 2246} 2247 2248static int 2249ndis_80211_ioctl_get(struct ifnet *ifp, u_long command, caddr_t data) 2250{ 2251 struct ndis_softc *sc; 2252 struct ieee80211req *ireq; 2253 ndis_80211_bssid_list_ex *bl; 2254 ndis_wlan_bssid_ex *wb; 2255 struct ieee80211req_scan_result *sr, *bsr; 2256 int error, len, i, j; 2257 char *cp; 2258 uint8_t nodename[IEEE80211_NWID_LEN]; 2259 uint16_t nodename_u[IEEE80211_NWID_LEN + 1]; 2260 char *acode; 2261 2262 sc = ifp->if_softc; 2263 ireq = (struct ieee80211req *) data; 2264 2265 switch (ireq->i_type) { 2266 case IEEE80211_IOC_SCAN_RESULTS: 2267 len = 0; 2268 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, NULL, &len); 2269 if (error != ENOSPC) 2270 break; 2271 bl = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 2272 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl, &len); 2273 if (error) { 2274 free(bl, M_DEVBUF); 2275 break; 2276 } 2277 sr = bsr = malloc(ireq->i_len, M_DEVBUF, M_WAITOK | M_ZERO); 2278 wb = bl->nblx_bssid; 2279 len = 0; 2280 for (i = 0; i < bl->nblx_items; i++) { 2281 /* 2282 * Check if we have enough space left for this ap 2283 */ 2284 j = roundup(sizeof(*sr) + wb->nwbx_ssid.ns_ssidlen 2285 + wb->nwbx_ielen - 2286 sizeof(struct ndis_80211_fixed_ies), 2287 sizeof(uint32_t)); 2288 if (len + j > ireq->i_len) 2289 break; 2290 bcopy(&wb->nwbx_macaddr, &sr->isr_bssid, 2291 sizeof(sr->isr_bssid)); 2292 if (wb->nwbx_privacy) 2293 sr->isr_capinfo |= IEEE80211_CAPINFO_PRIVACY; 2294 sr->isr_rssi = wb->nwbx_rssi + 200; 2295 sr->isr_freq = wb->nwbx_config.nc_dsconfig / 1000; 2296 sr->isr_intval = wb->nwbx_config.nc_beaconperiod; 2297 switch (wb->nwbx_netinfra) { 2298 case NDIS_80211_NET_INFRA_IBSS: 2299 sr->isr_capinfo |= IEEE80211_CAPINFO_IBSS; 2300 break; 2301 case NDIS_80211_NET_INFRA_BSS: 2302 sr->isr_capinfo |= IEEE80211_CAPINFO_ESS; 2303 break; 2304 } 2305 for (j = 0; j < sizeof(sr->isr_rates); j++) { 2306 /* XXX - check units */ 2307 if (wb->nwbx_supportedrates[j] == 0) 2308 break; 2309 sr->isr_rates[j] = 2310 wb->nwbx_supportedrates[j] & 0x7f; 2311 } 2312 sr->isr_nrates = j; 2313 sr->isr_ssid_len = wb->nwbx_ssid.ns_ssidlen; 2314 cp = (char *)sr + sizeof(*sr); 2315 bcopy(&wb->nwbx_ssid.ns_ssid, cp, sr->isr_ssid_len); 2316 cp += sr->isr_ssid_len; 2317 sr->isr_ie_len = wb->nwbx_ielen 2318 - sizeof(struct ndis_80211_fixed_ies); 2319 bcopy((char *)wb->nwbx_ies + 2320 sizeof(struct ndis_80211_fixed_ies), 2321 cp, sr->isr_ie_len); 2322 sr->isr_len = roundup(sizeof(*sr) + sr->isr_ssid_len 2323 + sr->isr_ie_len, sizeof(uint32_t)); 2324 len += sr->isr_len; 2325 sr = (struct ieee80211req_scan_result *)((char *)sr + 2326 sr->isr_len); 2327 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len); 2328 } 2329 ireq->i_len = len; 2330 error = copyout(bsr, ireq->i_data, len); 2331 free(bl, M_DEVBUF); 2332 free(bsr, M_DEVBUF); 2333 break; 2334 case IEEE80211_IOC_STATIONNAME: 2335 error = ndis_get_info(sc, OID_GEN_MACHINE_NAME, 2336 &nodename_u, &len); 2337 if (error) 2338 break; 2339 acode = nodename; 2340 bzero((char *)nodename, IEEE80211_NWID_LEN); 2341 ndis_unicode_to_ascii(nodename_u, len, &acode); 2342 ireq->i_len = len / 2 + 1; 2343 error = copyout(acode, ireq->i_data, ireq->i_len); 2344 break; 2345 default: 2346 error = ieee80211_ioctl(&sc->ic, command, data); 2347 } 2348 2349 return(error); 2350} 2351 2352static int 2353ndis_80211_ioctl_set(struct ifnet *ifp, u_long command, caddr_t data) 2354{ 2355 struct ndis_softc *sc; 2356 struct ieee80211req *ireq; 2357 int error, len; 2358 uint8_t nodename[IEEE80211_NWID_LEN]; 2359 uint16_t nodename_u[IEEE80211_NWID_LEN + 1]; 2360 uint16_t *ucode; 2361 2362 sc = ifp->if_softc; 2363 ireq = (struct ieee80211req *) data; 2364 2365 switch (ireq->i_type) { 2366 case IEEE80211_IOC_SCAN_REQ: 2367 len = 0; 2368 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, 2369 NULL, &len); 2370 tsleep(&error, PPAUSE|PCATCH, "ssidscan", hz * 2); 2371 rt_ieee80211msg(ifp, RTM_IEEE80211_SCAN, NULL, 0); 2372 break; 2373 case IEEE80211_IOC_STATIONNAME: 2374 error = suser(curthread); 2375 if (error) 2376 break; 2377 if (ireq->i_val != 0 || 2378 ireq->i_len > IEEE80211_NWID_LEN) { 2379 error = EINVAL; 2380 break; 2381 } 2382 bzero((char *)nodename, IEEE80211_NWID_LEN); 2383 error = copyin(ireq->i_data, nodename, ireq->i_len); 2384 if (error) 2385 break; 2386 ucode = nodename_u; 2387 ndis_ascii_to_unicode((char *)nodename, &ucode); 2388 len = ireq->i_len * 2; 2389 error = ndis_set_info(sc, OID_GEN_MACHINE_NAME, 2390 &nodename_u, &len); 2391 break; 2392 default: 2393 error = ieee80211_ioctl(&sc->ic, command, data); 2394 if (error == ENETRESET) { 2395 ndis_setstate_80211(sc); 2396 error = 0; 2397 } 2398 } 2399 2400 return(error); 2401} 2402 2403static void 2404ndis_watchdog(ifp) 2405 struct ifnet *ifp; 2406{ 2407 struct ndis_softc *sc; 2408 2409 sc = ifp->if_softc; 2410 2411 NDIS_LOCK(sc); 2412 ifp->if_oerrors++; 2413 device_printf(sc->ndis_dev, "watchdog timeout\n"); 2414 NDIS_UNLOCK(sc); 2415 2416 ndis_sched((void(*)(void *))ndis_reset_nic, sc, NDIS_TASKQUEUE); 2417 ndis_sched(ndis_starttask, ifp, NDIS_TASKQUEUE); 2418 2419 return; 2420} 2421 2422/* 2423 * Stop the adapter and free any mbufs allocated to the 2424 * RX and TX lists. 2425 */ 2426static void 2427ndis_stop(sc) 2428 struct ndis_softc *sc; 2429{ 2430 struct ifnet *ifp; 2431 2432 ifp = &sc->arpcom.ac_if; 2433 untimeout(ndis_tick, sc, sc->ndis_stat_ch); 2434 2435 ndis_halt_nic(sc); 2436 2437 NDIS_LOCK(sc); 2438 ifp->if_timer = 0; 2439 sc->ndis_link = 0; 2440 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 2441 NDIS_UNLOCK(sc); 2442 2443 return; 2444} 2445 2446/* 2447 * Stop all chip I/O so that the kernel's probe routines don't 2448 * get confused by errant DMAs when rebooting. 2449 */ 2450void 2451ndis_shutdown(dev) 2452 device_t dev; 2453{ 2454 struct ndis_softc *sc; 2455 2456 sc = device_get_softc(dev); 2457 ndis_shutdown_nic(sc); 2458 2459 return; 2460} 2461