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