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