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