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