3 * Bill Paul <wpaul@windriver.com>. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
32 * $FreeBSD: head/sys/dev/if_ndis/if_ndis.c 298955 2016-05-03 03:41:25Z pfg $
34 * WPA support originally contributed by Arvind Srinivasan <arvind@celar.us>
35 * then hacked upon mercilessly by me.
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/sockio.h>
42 #include <sys/malloc.h>
43 #include <sys/endian.h>
45 #include <sys/kernel.h>
46 #include <sys/socket.h>
47 #include <sys/queue.h>
48 #include <sys/module.h>
50 #include <sys/sysctl.h>
51 #include <sys/kthread.h>
52 #include <sys/limits.h>
55 #include <net/if_var.h>
56 #include <net/if_arp.h>
57 #include <net/ethernet.h>
58 #include <net/if_dl.h>
59 #include <net/if_media.h>
60 #include <net/if_types.h>
61 #include <net/route.h>
64 #include <net/ifq_var.h>
66 #if !defined(__DragonFly__)
67 #include <machine/bus.h>
68 #include <machine/resource.h>
73 #if defined(__DragonFly__)
74 #include <netproto/802_11/ieee80211_var.h>
75 #include <netproto/802_11/ieee80211_ioctl.h>
76 #include <netproto/802_11/ieee80211_regdomain.h>
78 #include <net80211/ieee80211_var.h>
79 #include <net80211/ieee80211_ioctl.h>
80 #include <net80211/ieee80211_regdomain.h>
83 #if defined(__DragonFly__)
84 #include <bus/pci/pcireg.h>
85 #include <bus/pci/pcivar.h>
86 #include <bus/u4b/usb.h>
87 #include <bus/u4b/usbdi.h>
89 #include <dev/pci/pcireg.h>
90 #include <dev/pci/pcivar.h>
91 #include <dev/usb/usb.h>
92 #include <dev/usb/usbdi.h>
95 #if defined(__DragonFly__)
96 #include <emulation/ndis/pe_var.h>
97 #include <emulation/ndis/cfg_var.h>
98 #include <emulation/ndis/resource_var.h>
99 #include <emulation/ndis/ntoskrnl_var.h>
100 #include <emulation/ndis/hal_var.h>
101 #include <emulation/ndis/ndis_var.h>
102 #include <emulation/ndis/u4bd_var.h>
103 #include <dev/netif/ndis/if_ndisvar.h>
105 #include <compat/ndis/pe_var.h>
106 #include <compat/ndis/cfg_var.h>
107 #include <compat/ndis/resource_var.h>
108 #include <compat/ndis/ntoskrnl_var.h>
109 #include <compat/ndis/hal_var.h>
110 #include <compat/ndis/ndis_var.h>
111 #include <compat/ndis/usbd_var.h>
112 #include <dev/if_ndis/if_ndisvar.h>
117 #define DPRINTF(x) do { if (ndis_debug > 0) kprintf x; } while (0)
119 SYSCTL_INT(_debug
, OID_AUTO
, ndis
, CTLFLAG_RW
, &ndis_debug
, 0,
120 "if_ndis debug level");
125 SYSCTL_DECL(_hw_ndisusb
);
126 int ndisusb_halt
= 1;
127 SYSCTL_INT(_hw_ndisusb
, OID_AUTO
, halt
, CTLFLAG_RW
, &ndisusb_halt
, 0,
128 "Halt NDIS USB driver when it's attached");
130 /* 0 - 30 dBm to mW conversion table */
131 static const uint16_t dBm2mW
[] = {
132 1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
133 3, 4, 4, 4, 5, 6, 6, 7, 8, 9,
134 10, 11, 13, 14, 16, 18, 20, 22, 25, 28,
135 32, 35, 40, 45, 50, 56, 63, 71, 79, 89,
136 100, 112, 126, 141, 158, 178, 200, 224, 251, 282,
137 316, 355, 398, 447, 501, 562, 631, 708, 794, 891,
141 MODULE_DEPEND(if_ndis
, ether
, 1, 1, 1);
142 MODULE_DEPEND(if_ndis
, wlan
, 1, 1, 1);
143 MODULE_DEPEND(if_ndis
, ndis
, 1, 1, 1);
145 MODULE_VERSION(if_ndis
, 1);
147 int ndis_attach (device_t
);
148 int ndis_detach (device_t
);
149 int ndis_suspend (device_t
);
150 int ndis_resume (device_t
);
151 void ndis_shutdown (device_t
);
153 int ndisdrv_modevent (module_t
, int, void *);
155 static void ndis_txeof (ndis_handle
, ndis_packet
*, ndis_status
);
156 static void ndis_rxeof (ndis_handle
, ndis_packet
**, uint32_t);
157 static void ndis_rxeof_eth (ndis_handle
, ndis_handle
, char *, void *,
158 uint32_t, void *, uint32_t, uint32_t);
159 static void ndis_rxeof_done (ndis_handle
);
160 static void ndis_rxeof_xfr (kdpc
*, ndis_handle
, void *, void *);
161 static void ndis_rxeof_xfr_done (ndis_handle
, ndis_packet
*,
163 static void ndis_linksts (ndis_handle
, ndis_status
, void *, uint32_t);
164 static void ndis_linksts_done (ndis_handle
);
166 /* We need to wrap these functions for amd64. */
167 static funcptr ndis_txeof_wrap
;
168 static funcptr ndis_rxeof_wrap
;
169 static funcptr ndis_rxeof_eth_wrap
;
170 static funcptr ndis_rxeof_done_wrap
;
171 static funcptr ndis_rxeof_xfr_wrap
;
172 static funcptr ndis_rxeof_xfr_done_wrap
;
173 static funcptr ndis_linksts_wrap
;
174 static funcptr ndis_linksts_done_wrap
;
175 static funcptr ndis_ticktask_wrap
;
176 static funcptr ndis_starttask_wrap
;
177 static funcptr ndis_resettask_wrap
;
178 static funcptr ndis_inputtask_wrap
;
180 static struct ieee80211vap
*ndis_vap_create(struct ieee80211com
*,
181 const char [IFNAMSIZ
], int, enum ieee80211_opmode
, int,
182 const uint8_t [IEEE80211_ADDR_LEN
],
183 const uint8_t [IEEE80211_ADDR_LEN
]);
184 static void ndis_vap_delete (struct ieee80211vap
*);
185 static void ndis_tick (void *);
186 static void ndis_ticktask (device_object
*, void *);
187 static int ndis_raw_xmit (struct ieee80211_node
*, struct mbuf
*,
188 const struct ieee80211_bpf_params
*);
189 static void ndis_update_mcast (struct ieee80211com
*);
190 static void ndis_update_promisc (struct ieee80211com
*);
191 static void ndis_start (struct ifnet
*ifp
, struct ifaltq_subque
*ifsq
);
192 static void ndis_starttask (device_object
*, void *);
193 static void ndis_resettask (device_object
*, void *);
194 static void ndis_inputtask (device_object
*, void *);
195 static int ndis_ioctl (struct ifnet
*, u_long
, caddr_t
, struct ucred
*);
196 static int ndis_newstate (struct ieee80211vap
*, enum ieee80211_state
,
198 static int ndis_nettype_chan (uint32_t);
199 static int ndis_nettype_mode (uint32_t);
200 static void ndis_scan (void *);
201 static void ndis_scan_results (struct ndis_softc
*);
202 static void ndis_scan_start (struct ieee80211com
*);
203 static void ndis_scan_end (struct ieee80211com
*);
204 static void ndis_set_channel (struct ieee80211com
*);
205 static void ndis_scan_curchan (struct ieee80211_scan_state
*, unsigned long);
206 static void ndis_scan_mindwell (struct ieee80211_scan_state
*);
207 static void ndis_init (void *);
208 static void ndis_stop (struct ndis_softc
*);
209 static int ndis_ifmedia_upd (struct ifnet
*);
210 static void ndis_ifmedia_sts (struct ifnet
*, struct ifmediareq
*);
211 static int ndis_get_bssid_list (struct ndis_softc
*,
212 ndis_80211_bssid_list_ex
**);
213 static int ndis_get_assoc (struct ndis_softc
*, ndis_wlan_bssid_ex
**);
214 static int ndis_probe_offload (struct ndis_softc
*);
215 static int ndis_set_offload (struct ndis_softc
*);
216 static void ndis_getstate_80211 (struct ndis_softc
*);
217 static void ndis_setstate_80211 (struct ndis_softc
*);
218 static void ndis_auth_and_assoc (struct ndis_softc
*, struct ieee80211vap
*);
219 static void ndis_media_status (struct ifnet
*, struct ifmediareq
*);
220 static int ndis_set_cipher (struct ndis_softc
*, int);
221 static int ndis_set_wpa (struct ndis_softc
*, void *, int);
222 static int ndis_add_key (struct ieee80211vap
*,
223 const struct ieee80211_key
*);
224 static int ndis_del_key (struct ieee80211vap
*,
225 const struct ieee80211_key
*);
226 static void ndis_setmulti (struct ndis_softc
*);
227 static void ndis_map_sclist (void *, bus_dma_segment_t
*,
228 int, bus_size_t
, int);
229 static int ndis_ifattach(struct ndis_softc
*);
231 static int ndis_80211attach(struct ndis_softc
*);
232 static int ndis_80211ioctl(struct ieee80211com
*, u_long
, void *);
233 static int ndis_80211transmit(struct ieee80211com
*, struct mbuf
*);
234 static void ndis_80211parent(struct ieee80211com
*);
236 static int ndisdrv_loaded
= 0;
239 * This routine should call windrv_load() once for each driver
240 * image. This will do the relocation and dynalinking for the
241 * image, and create a Windows driver object which will be
242 * saved in our driver database.
245 ndisdrv_modevent(module_t mod
, int cmd
, void *arg
)
252 if (ndisdrv_loaded
> 1)
254 windrv_wrap((funcptr
)ndis_rxeof
, &ndis_rxeof_wrap
,
255 3, WINDRV_WRAP_STDCALL
);
256 windrv_wrap((funcptr
)ndis_rxeof_eth
, &ndis_rxeof_eth_wrap
,
257 8, WINDRV_WRAP_STDCALL
);
258 windrv_wrap((funcptr
)ndis_rxeof_done
, &ndis_rxeof_done_wrap
,
259 1, WINDRV_WRAP_STDCALL
);
260 windrv_wrap((funcptr
)ndis_rxeof_xfr
, &ndis_rxeof_xfr_wrap
,
261 4, WINDRV_WRAP_STDCALL
);
262 windrv_wrap((funcptr
)ndis_rxeof_xfr_done
,
263 &ndis_rxeof_xfr_done_wrap
, 4, WINDRV_WRAP_STDCALL
);
264 windrv_wrap((funcptr
)ndis_txeof
, &ndis_txeof_wrap
,
265 3, WINDRV_WRAP_STDCALL
);
266 windrv_wrap((funcptr
)ndis_linksts
, &ndis_linksts_wrap
,
267 4, WINDRV_WRAP_STDCALL
);
268 windrv_wrap((funcptr
)ndis_linksts_done
,
269 &ndis_linksts_done_wrap
, 1, WINDRV_WRAP_STDCALL
);
270 windrv_wrap((funcptr
)ndis_ticktask
, &ndis_ticktask_wrap
,
271 2, WINDRV_WRAP_STDCALL
);
272 windrv_wrap((funcptr
)ndis_starttask
, &ndis_starttask_wrap
,
273 2, WINDRV_WRAP_STDCALL
);
274 windrv_wrap((funcptr
)ndis_resettask
, &ndis_resettask_wrap
,
275 2, WINDRV_WRAP_STDCALL
);
276 windrv_wrap((funcptr
)ndis_inputtask
, &ndis_inputtask_wrap
,
277 2, WINDRV_WRAP_STDCALL
);
281 if (ndisdrv_loaded
> 0)
285 windrv_unwrap(ndis_rxeof_wrap
);
286 windrv_unwrap(ndis_rxeof_eth_wrap
);
287 windrv_unwrap(ndis_rxeof_done_wrap
);
288 windrv_unwrap(ndis_rxeof_xfr_wrap
);
289 windrv_unwrap(ndis_rxeof_xfr_done_wrap
);
290 windrv_unwrap(ndis_txeof_wrap
);
291 windrv_unwrap(ndis_linksts_wrap
);
292 windrv_unwrap(ndis_linksts_done_wrap
);
293 windrv_unwrap(ndis_ticktask_wrap
);
294 windrv_unwrap(ndis_starttask_wrap
);
295 windrv_unwrap(ndis_resettask_wrap
);
296 windrv_unwrap(ndis_inputtask_wrap
);
307 * Program the 64-bit multicast hash filter.
310 ndis_setmulti(struct ndis_softc
*sc
)
313 struct ifmultiaddr
*ifma
;
314 int len
, mclistsz
, error
;
319 if (!NDIS_INITIALIZED(sc
))
322 if (ifp
->if_flags
& IFF_ALLMULTI
|| ifp
->if_flags
& IFF_PROMISC
) {
323 sc
->ndis_filter
|= NDIS_PACKET_TYPE_ALL_MULTICAST
;
324 len
= sizeof(sc
->ndis_filter
);
325 error
= ndis_set_info(sc
, OID_GEN_CURRENT_PACKET_FILTER
,
326 &sc
->ndis_filter
, &len
);
328 device_printf(sc
->ndis_dev
,
329 "set allmulti failed: %d\n", error
);
333 if (TAILQ_EMPTY(&ifp
->if_multiaddrs
))
336 len
= sizeof(mclistsz
);
337 ndis_get_info(sc
, OID_802_3_MAXIMUM_LIST_SIZE
, &mclistsz
, &len
);
339 mclist
= kmalloc(ETHER_ADDR_LEN
* mclistsz
, M_TEMP
, M_INTWAIT
|M_ZERO
);
341 if (mclist
== NULL
) {
342 sc
->ndis_filter
|= NDIS_PACKET_TYPE_ALL_MULTICAST
;
346 sc
->ndis_filter
|= NDIS_PACKET_TYPE_MULTICAST
;
349 #if 0 /* XXX swildner */
352 TAILQ_FOREACH(ifma
, &ifp
->if_multiaddrs
, ifma_link
) {
353 if (ifma
->ifma_addr
->sa_family
!= AF_LINK
)
355 bcopy(LLADDR((struct sockaddr_dl
*)ifma
->ifma_addr
),
356 mclist
+ (ETHER_ADDR_LEN
* len
), ETHER_ADDR_LEN
);
358 if (len
> mclistsz
) {
359 #if 0 /* XXX swildner */
360 if_maddr_runlock(ifp
);
362 sc
->ndis_filter
|= NDIS_PACKET_TYPE_ALL_MULTICAST
;
363 sc
->ndis_filter
&= ~NDIS_PACKET_TYPE_MULTICAST
;
367 #if 0 /* XXX swildner */
368 if_maddr_runlock(ifp
);
371 len
= len
* ETHER_ADDR_LEN
;
372 error
= ndis_set_info(sc
, OID_802_3_MULTICAST_LIST
, mclist
, &len
);
374 device_printf(sc
->ndis_dev
, "set mclist failed: %d\n", error
);
375 sc
->ndis_filter
|= NDIS_PACKET_TYPE_ALL_MULTICAST
;
376 sc
->ndis_filter
&= ~NDIS_PACKET_TYPE_MULTICAST
;
380 kfree(mclist
, M_TEMP
);
382 len
= sizeof(sc
->ndis_filter
);
383 error
= ndis_set_info(sc
, OID_GEN_CURRENT_PACKET_FILTER
,
384 &sc
->ndis_filter
, &len
);
386 device_printf(sc
->ndis_dev
, "set multi failed: %d\n", error
);
390 ndis_set_offload(struct ndis_softc
*sc
)
392 ndis_task_offload
*nto
;
393 ndis_task_offload_hdr
*ntoh
;
394 ndis_task_tcpip_csum
*nttc
;
400 if (!NDIS_INITIALIZED(sc
))
403 /* See if there's anything to set. */
405 error
= ndis_probe_offload(sc
);
409 if (sc
->ndis_hwassist
== 0 && ifp
->if_capabilities
== 0)
412 len
= sizeof(ndis_task_offload_hdr
) + sizeof(ndis_task_offload
) +
413 sizeof(ndis_task_tcpip_csum
);
415 ntoh
= kmalloc(len
, M_TEMP
, M_INTWAIT
|M_ZERO
);
420 ntoh
->ntoh_vers
= NDIS_TASK_OFFLOAD_VERSION
;
421 ntoh
->ntoh_len
= sizeof(ndis_task_offload_hdr
);
422 ntoh
->ntoh_offset_firsttask
= sizeof(ndis_task_offload_hdr
);
423 ntoh
->ntoh_encapfmt
.nef_encaphdrlen
= sizeof(struct ether_header
);
424 ntoh
->ntoh_encapfmt
.nef_encap
= NDIS_ENCAP_IEEE802_3
;
425 ntoh
->ntoh_encapfmt
.nef_flags
= NDIS_ENCAPFLAG_FIXEDHDRLEN
;
427 nto
= (ndis_task_offload
*)((char *)ntoh
+
428 ntoh
->ntoh_offset_firsttask
);
430 nto
->nto_vers
= NDIS_TASK_OFFLOAD_VERSION
;
431 nto
->nto_len
= sizeof(ndis_task_offload
);
432 nto
->nto_task
= NDIS_TASK_TCPIP_CSUM
;
433 nto
->nto_offset_nexttask
= 0;
434 nto
->nto_taskbuflen
= sizeof(ndis_task_tcpip_csum
);
436 nttc
= (ndis_task_tcpip_csum
*)nto
->nto_taskbuf
;
438 if (ifp
->if_capenable
& IFCAP_TXCSUM
)
439 nttc
->nttc_v4tx
= sc
->ndis_v4tx
;
441 if (ifp
->if_capenable
& IFCAP_RXCSUM
)
442 nttc
->nttc_v4rx
= sc
->ndis_v4rx
;
444 error
= ndis_set_info(sc
, OID_TCP_TASK_OFFLOAD
, ntoh
, &len
);
451 ndis_probe_offload(struct ndis_softc
*sc
)
453 ndis_task_offload
*nto
;
454 ndis_task_offload_hdr
*ntoh
;
455 ndis_task_tcpip_csum
*nttc
= NULL
;
457 int len
, error
, dummy
;
462 error
= ndis_get_info(sc
, OID_TCP_TASK_OFFLOAD
, &dummy
, &len
);
467 ntoh
= kmalloc(len
, M_TEMP
, M_INTWAIT
|M_ZERO
);
472 ntoh
->ntoh_vers
= NDIS_TASK_OFFLOAD_VERSION
;
473 ntoh
->ntoh_len
= sizeof(ndis_task_offload_hdr
);
474 ntoh
->ntoh_encapfmt
.nef_encaphdrlen
= sizeof(struct ether_header
);
475 ntoh
->ntoh_encapfmt
.nef_encap
= NDIS_ENCAP_IEEE802_3
;
476 ntoh
->ntoh_encapfmt
.nef_flags
= NDIS_ENCAPFLAG_FIXEDHDRLEN
;
478 error
= ndis_get_info(sc
, OID_TCP_TASK_OFFLOAD
, ntoh
, &len
);
485 if (ntoh
->ntoh_vers
!= NDIS_TASK_OFFLOAD_VERSION
) {
490 nto
= (ndis_task_offload
*)((char *)ntoh
+
491 ntoh
->ntoh_offset_firsttask
);
494 switch (nto
->nto_task
) {
495 case NDIS_TASK_TCPIP_CSUM
:
496 nttc
= (ndis_task_tcpip_csum
*)nto
->nto_taskbuf
;
498 /* Don't handle these yet. */
499 case NDIS_TASK_IPSEC
:
500 case NDIS_TASK_TCP_LARGESEND
:
504 if (nto
->nto_offset_nexttask
== 0)
506 nto
= (ndis_task_offload
*)((char *)nto
+
507 nto
->nto_offset_nexttask
);
515 sc
->ndis_v4tx
= nttc
->nttc_v4tx
;
516 sc
->ndis_v4rx
= nttc
->nttc_v4rx
;
518 if (nttc
->nttc_v4tx
& NDIS_TCPSUM_FLAGS_IP_CSUM
)
519 sc
->ndis_hwassist
|= CSUM_IP
;
520 if (nttc
->nttc_v4tx
& NDIS_TCPSUM_FLAGS_TCP_CSUM
)
521 sc
->ndis_hwassist
|= CSUM_TCP
;
522 if (nttc
->nttc_v4tx
& NDIS_TCPSUM_FLAGS_UDP_CSUM
)
523 sc
->ndis_hwassist
|= CSUM_UDP
;
525 if (sc
->ndis_hwassist
)
526 ifp
->if_capabilities
|= IFCAP_TXCSUM
;
528 if (nttc
->nttc_v4rx
& NDIS_TCPSUM_FLAGS_IP_CSUM
)
529 ifp
->if_capabilities
|= IFCAP_RXCSUM
;
530 if (nttc
->nttc_v4rx
& NDIS_TCPSUM_FLAGS_TCP_CSUM
)
531 ifp
->if_capabilities
|= IFCAP_RXCSUM
;
532 if (nttc
->nttc_v4rx
& NDIS_TCPSUM_FLAGS_UDP_CSUM
)
533 ifp
->if_capabilities
|= IFCAP_RXCSUM
;
540 ndis_nettype_chan(uint32_t type
)
543 case NDIS_80211_NETTYPE_11FH
: return (IEEE80211_CHAN_FHSS
);
544 case NDIS_80211_NETTYPE_11DS
: return (IEEE80211_CHAN_B
);
545 case NDIS_80211_NETTYPE_11OFDM5
: return (IEEE80211_CHAN_A
);
546 case NDIS_80211_NETTYPE_11OFDM24
: return (IEEE80211_CHAN_G
);
548 DPRINTF(("unknown channel nettype %d\n", type
));
549 return (IEEE80211_CHAN_B
); /* Default to 11B chan */
553 ndis_nettype_mode(uint32_t type
)
556 case NDIS_80211_NETTYPE_11FH
: return (IEEE80211_MODE_FH
);
557 case NDIS_80211_NETTYPE_11DS
: return (IEEE80211_MODE_11B
);
558 case NDIS_80211_NETTYPE_11OFDM5
: return (IEEE80211_MODE_11A
);
559 case NDIS_80211_NETTYPE_11OFDM24
: return (IEEE80211_MODE_11G
);
561 DPRINTF(("unknown mode nettype %d\n", type
));
562 return (IEEE80211_MODE_AUTO
);
566 * Attach the interface. Allocate softc structures, do ifmedia
567 * setup and ethernet/BPF attach.
570 ndis_attach(device_t dev
)
572 struct ndis_softc
*sc
;
578 sc
= device_get_softc(dev
);
580 #if defined(__DragonFly__)
581 lockinit(&sc
->ndis_lock
, "network driver", 0, LK_CANRECURSE
);
583 mtx_init(&sc
->ndis_mtx
, device_get_nameunit(dev
), MTX_NETWORK_LOCK
,
586 KeInitializeSpinLock(&sc
->ndis_rxlock
);
587 KeInitializeSpinLock(&sc
->ndisusb_tasklock
);
588 KeInitializeSpinLock(&sc
->ndisusb_xferdonelock
);
589 InitializeListHead(&sc
->ndis_shlist
);
590 InitializeListHead(&sc
->ndisusb_tasklist
);
591 InitializeListHead(&sc
->ndisusb_xferdonelist
);
592 #if defined(__DragonFly__)
593 callout_init_mp(&sc
->ndis_stat_callout
);
595 callout_init(&sc
->ndis_stat_callout
, 1);
597 mbufq_init(&sc
->ndis_rxqueue
, INT_MAX
); /* XXXGL: sane maximum */
599 if (sc
->ndis_iftype
== PCMCIABus
) {
600 error
= ndis_alloc_amem(sc
);
602 device_printf(dev
, "failed to allocate "
603 "attribute memory\n");
608 /* Create sysctl registry nodes */
609 ndis_create_sysctls(sc
);
611 /* Find the PDO for this device instance. */
613 if (sc
->ndis_iftype
== PCIBus
)
614 pdrv
= windrv_lookup(0, "PCI Bus");
615 else if (sc
->ndis_iftype
== PCMCIABus
)
616 pdrv
= windrv_lookup(0, "PCCARD Bus");
618 pdrv
= windrv_lookup(0, "USB Bus");
619 pdo
= windrv_find_pdo(pdrv
, dev
);
622 * Create a new functional device object for this
623 * device. This is what creates the miniport block
624 * for this device instance.
627 if (NdisAddDevice(sc
->ndis_dobj
, pdo
) != STATUS_SUCCESS
) {
628 device_printf(dev
, "failed to create FDO!\n");
633 /* Tell the user what version of the API the driver is using. */
634 device_printf(dev
, "NDIS API version: %d.%d\n",
635 sc
->ndis_chars
->nmc_version_major
,
636 sc
->ndis_chars
->nmc_version_minor
);
638 /* Do resource conversion. */
639 if (sc
->ndis_iftype
== PCMCIABus
|| sc
->ndis_iftype
== PCIBus
)
640 ndis_convert_res(sc
);
642 sc
->ndis_block
->nmb_rlist
= NULL
;
644 /* Install our RX and TX interrupt handlers. */
645 sc
->ndis_block
->nmb_senddone_func
= ndis_txeof_wrap
;
646 sc
->ndis_block
->nmb_pktind_func
= ndis_rxeof_wrap
;
647 sc
->ndis_block
->nmb_ethrxindicate_func
= ndis_rxeof_eth_wrap
;
648 sc
->ndis_block
->nmb_ethrxdone_func
= ndis_rxeof_done_wrap
;
649 sc
->ndis_block
->nmb_tdcond_func
= ndis_rxeof_xfr_done_wrap
;
651 /* Override the status handler so we can detect link changes. */
652 sc
->ndis_block
->nmb_status_func
= ndis_linksts_wrap
;
653 sc
->ndis_block
->nmb_statusdone_func
= ndis_linksts_done_wrap
;
655 /* Set up work item handlers. */
656 sc
->ndis_tickitem
= IoAllocateWorkItem(sc
->ndis_block
->nmb_deviceobj
);
657 sc
->ndis_startitem
= IoAllocateWorkItem(sc
->ndis_block
->nmb_deviceobj
);
658 sc
->ndis_resetitem
= IoAllocateWorkItem(sc
->ndis_block
->nmb_deviceobj
);
659 sc
->ndis_inputitem
= IoAllocateWorkItem(sc
->ndis_block
->nmb_deviceobj
);
660 sc
->ndisusb_xferdoneitem
=
661 IoAllocateWorkItem(sc
->ndis_block
->nmb_deviceobj
);
662 sc
->ndisusb_taskitem
=
663 IoAllocateWorkItem(sc
->ndis_block
->nmb_deviceobj
);
664 KeInitializeDpc(&sc
->ndis_rxdpc
, ndis_rxeof_xfr_wrap
, sc
->ndis_block
);
666 /* Call driver's init routine. */
667 if (ndis_init_nic(sc
)) {
668 device_printf(dev
, "init handler failed\n");
674 * Figure out how big to make the TX buffer pool.
676 len
= sizeof(sc
->ndis_maxpkts
);
677 if (ndis_get_info(sc
, OID_GEN_MAXIMUM_SEND_PACKETS
,
678 &sc
->ndis_maxpkts
, &len
)) {
679 device_printf(dev
, "failed to get max TX packets\n");
685 * If this is a deserialized miniport, we don't have
686 * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result.
688 if (!NDIS_SERIALIZED(sc
->ndis_block
))
689 sc
->ndis_maxpkts
= NDIS_TXPKTS
;
691 /* Enforce some sanity, just in case. */
693 if (sc
->ndis_maxpkts
== 0)
694 sc
->ndis_maxpkts
= 10;
696 sc
->ndis_txarray
= kmalloc(sizeof(ndis_packet
*) *
697 sc
->ndis_maxpkts
, M_DEVBUF
, M_INTWAIT
|M_ZERO
);
699 /* Allocate a pool of ndis_packets for TX encapsulation. */
701 NdisAllocatePacketPool(&i
, &sc
->ndis_txpool
,
702 sc
->ndis_maxpkts
, PROTOCOL_RESERVED_SIZE_IN_PACKET
);
704 if (i
!= NDIS_STATUS_SUCCESS
) {
705 sc
->ndis_txpool
= NULL
;
706 device_printf(dev
, "failed to allocate TX packet pool");
711 sc
->ndis_txpending
= sc
->ndis_maxpkts
;
714 /* Get supported oid list. */
715 ndis_get_supported_oids(sc
, &sc
->ndis_oids
, &sc
->ndis_oidcnt
);
717 /* If the NDIS module requested scatter/gather, init maps. */
722 * See if the OID_802_11_CONFIGURATION OID is
723 * supported by this driver. If it is, then this an 802.11
724 * wireless driver, and we should set up media for wireless.
726 for (i
= 0; i
< sc
->ndis_oidcnt
; i
++)
727 if (sc
->ndis_oids
[i
] == OID_802_11_CONFIGURATION
) {
733 error
= ndis_80211attach(sc
);
735 error
= ndis_ifattach(sc
);
743 if (sc
->ndis_iftype
== PNPBus
&& ndisusb_halt
== 0)
746 DPRINTF(("attach done.\n"));
747 /* We're done talking to the NIC for now; halt it. */
749 DPRINTF(("halting done.\n"));
755 ndis_80211attach(struct ndis_softc
*sc
)
757 struct ieee80211com
*ic
= &sc
->ndis_ic
;
758 ndis_80211_rates_ex rates
;
759 struct ndis_80211_nettype_list
*ntl
;
761 int mode
, i
, r
, len
, nonettypes
= 1;
762 uint8_t bands
[IEEE80211_MODE_BYTES
] = { 0 };
764 #if defined(__DragonFly__)
765 callout_init_mp(&sc
->ndis_scan_callout
);
767 callout_init(&sc
->ndis_scan_callout
, 1);
771 ic
->ic_ioctl
= ndis_80211ioctl
;
772 ic
->ic_name
= device_get_nameunit(sc
->ndis_dev
);
773 ic
->ic_opmode
= IEEE80211_M_STA
;
774 ic
->ic_phytype
= IEEE80211_T_DS
;
775 ic
->ic_caps
= IEEE80211_C_8023ENCAP
|
776 IEEE80211_C_STA
| IEEE80211_C_IBSS
;
777 setbit(ic
->ic_modecaps
, IEEE80211_MODE_AUTO
);
779 r
= ndis_get_info(sc
, OID_802_11_NETWORK_TYPES_SUPPORTED
, NULL
, &len
);
782 ntl
= kmalloc(len
, M_DEVBUF
, M_WAITOK
| M_ZERO
);
783 r
= ndis_get_info(sc
, OID_802_11_NETWORK_TYPES_SUPPORTED
, ntl
, &len
);
785 kfree(ntl
, M_DEVBUF
);
789 for (i
= 0; i
< ntl
->ntl_items
; i
++) {
790 mode
= ndis_nettype_mode(ntl
->ntl_type
[i
]);
793 setbit(ic
->ic_modecaps
, mode
);
796 device_printf(sc
->ndis_dev
, "Unknown nettype %d\n",
799 kfree(ntl
, M_DEVBUF
);
801 /* Default to 11b channels if the card did not supply any */
803 setbit(ic
->ic_modecaps
, IEEE80211_MODE_11B
);
804 setbit(bands
, IEEE80211_MODE_11B
);
807 bzero((char *)&rates
, len
);
808 r
= ndis_get_info(sc
, OID_802_11_SUPPORTED_RATES
, (void *)rates
, &len
);
810 device_printf(sc
->ndis_dev
, "get rates failed: 0x%x\n", r
);
812 * Since the supported rates only up to 8 can be supported,
813 * if this is not 802.11b we're just going to be faking it
817 #define TESTSETRATE(x, y) \
820 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \
821 if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \
824 if (i == ic->ic_sup_rates[x].rs_nrates) { \
825 ic->ic_sup_rates[x].rs_rates[i] = (y); \
826 ic->ic_sup_rates[x].rs_nrates++; \
830 #define SETRATE(x, y) \
831 ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
833 ic->ic_sup_rates[x].rs_nrates++
835 ic
->ic_curmode
= IEEE80211_MODE_AUTO
;
836 if (isset(ic
->ic_modecaps
, IEEE80211_MODE_11A
))
837 ic
->ic_sup_rates
[IEEE80211_MODE_11A
].rs_nrates
= 0;
838 if (isset(ic
->ic_modecaps
, IEEE80211_MODE_11B
))
839 ic
->ic_sup_rates
[IEEE80211_MODE_11B
].rs_nrates
= 0;
840 if (isset(ic
->ic_modecaps
, IEEE80211_MODE_11G
))
841 ic
->ic_sup_rates
[IEEE80211_MODE_11G
].rs_nrates
= 0;
842 for (i
= 0; i
< len
; i
++) {
843 switch (rates
[i
] & IEEE80211_RATE_VAL
) {
849 if (isclr(ic
->ic_modecaps
, IEEE80211_MODE_11B
)) {
850 /* Lazy-init 802.11b. */
851 setbit(ic
->ic_modecaps
, IEEE80211_MODE_11B
);
852 ic
->ic_sup_rates
[IEEE80211_MODE_11B
].
855 SETRATE(IEEE80211_MODE_11B
, rates
[i
]);
856 INCRATE(IEEE80211_MODE_11B
);
859 if (isset(ic
->ic_modecaps
, IEEE80211_MODE_11A
)) {
860 SETRATE(IEEE80211_MODE_11A
, rates
[i
]);
861 INCRATE(IEEE80211_MODE_11A
);
863 if (isset(ic
->ic_modecaps
, IEEE80211_MODE_11G
)) {
864 SETRATE(IEEE80211_MODE_11G
, rates
[i
]);
865 INCRATE(IEEE80211_MODE_11G
);
872 * If the hardware supports 802.11g, it most
873 * likely supports 802.11b and all of the
874 * 802.11b and 802.11g speeds, so maybe we can
875 * just cheat here. Just how in the heck do
876 * we detect turbo modes, though?
878 if (isset(ic
->ic_modecaps
, IEEE80211_MODE_11B
)) {
879 TESTSETRATE(IEEE80211_MODE_11B
, IEEE80211_RATE_BASIC
|2);
880 TESTSETRATE(IEEE80211_MODE_11B
, IEEE80211_RATE_BASIC
|4);
881 TESTSETRATE(IEEE80211_MODE_11B
, IEEE80211_RATE_BASIC
|11);
882 TESTSETRATE(IEEE80211_MODE_11B
, IEEE80211_RATE_BASIC
|22);
884 if (isset(ic
->ic_modecaps
, IEEE80211_MODE_11G
)) {
885 TESTSETRATE(IEEE80211_MODE_11G
, 48);
886 TESTSETRATE(IEEE80211_MODE_11G
, 72);
887 TESTSETRATE(IEEE80211_MODE_11G
, 96);
888 TESTSETRATE(IEEE80211_MODE_11G
, 108);
890 if (isset(ic
->ic_modecaps
, IEEE80211_MODE_11A
)) {
891 TESTSETRATE(IEEE80211_MODE_11A
, 48);
892 TESTSETRATE(IEEE80211_MODE_11A
, 72);
893 TESTSETRATE(IEEE80211_MODE_11A
, 96);
894 TESTSETRATE(IEEE80211_MODE_11A
, 108);
901 ieee80211_init_channels(ic
, NULL
, bands
);
904 * To test for WPA support, we need to see if we can
905 * set AUTHENTICATION_MODE to WPA and read it back
909 arg
= NDIS_80211_AUTHMODE_WPA
;
910 r
= ndis_set_info(sc
, OID_802_11_AUTHENTICATION_MODE
, &arg
, &i
);
912 r
= ndis_get_info(sc
, OID_802_11_AUTHENTICATION_MODE
, &arg
, &i
);
913 if (r
== 0 && arg
== NDIS_80211_AUTHMODE_WPA
)
914 ic
->ic_caps
|= IEEE80211_C_WPA
;
918 * To test for supported ciphers, we set each
919 * available encryption type in descending order.
920 * If ENC3 works, then we have WEP, TKIP and AES.
921 * If only ENC2 works, then we have WEP and TKIP.
922 * If only ENC1 works, then we have just WEP.
925 arg
= NDIS_80211_WEPSTAT_ENC3ENABLED
;
926 r
= ndis_set_info(sc
, OID_802_11_ENCRYPTION_STATUS
, &arg
, &i
);
928 ic
->ic_cryptocaps
|= IEEE80211_CRYPTO_WEP
929 | IEEE80211_CRYPTO_TKIP
930 | IEEE80211_CRYPTO_AES_CCM
;
933 arg
= NDIS_80211_WEPSTAT_ENC2ENABLED
;
934 r
= ndis_set_info(sc
, OID_802_11_ENCRYPTION_STATUS
, &arg
, &i
);
936 ic
->ic_cryptocaps
|= IEEE80211_CRYPTO_WEP
937 | IEEE80211_CRYPTO_TKIP
;
940 arg
= NDIS_80211_WEPSTAT_ENC1ENABLED
;
941 r
= ndis_set_info(sc
, OID_802_11_ENCRYPTION_STATUS
, &arg
, &i
);
943 ic
->ic_cryptocaps
|= IEEE80211_CRYPTO_WEP
;
946 r
= ndis_get_info(sc
, OID_802_11_POWER_MODE
, &arg
, &i
);
948 ic
->ic_caps
|= IEEE80211_C_PMGT
;
950 r
= ndis_get_info(sc
, OID_802_11_TX_POWER_LEVEL
, &arg
, &i
);
952 ic
->ic_caps
|= IEEE80211_C_TXPMGT
;
955 * Get station address from the driver.
957 len
= sizeof(ic
->ic_macaddr
);
958 ndis_get_info(sc
, OID_802_3_CURRENT_ADDRESS
, &ic
->ic_macaddr
, &len
);
960 ieee80211_ifattach(ic
);
961 ic
->ic_raw_xmit
= ndis_raw_xmit
;
962 ic
->ic_scan_start
= ndis_scan_start
;
963 ic
->ic_scan_end
= ndis_scan_end
;
964 ic
->ic_set_channel
= ndis_set_channel
;
965 ic
->ic_scan_curchan
= ndis_scan_curchan
;
966 ic
->ic_scan_mindwell
= ndis_scan_mindwell
;
967 ic
->ic_bsschan
= IEEE80211_CHAN_ANYC
;
968 ic
->ic_vap_create
= ndis_vap_create
;
969 ic
->ic_vap_delete
= ndis_vap_delete
;
970 ic
->ic_update_mcast
= ndis_update_mcast
;
971 ic
->ic_update_promisc
= ndis_update_promisc
;
972 ic
->ic_transmit
= ndis_80211transmit
;
973 ic
->ic_parent
= ndis_80211parent
;
976 ieee80211_announce(ic
);
982 ndis_ifattach(struct ndis_softc
*sc
)
985 u_char eaddr
[ETHER_ADDR_LEN
];
988 ifp
= if_alloc(IFT_ETHER
);
994 /* Check for task offload support. */
995 ndis_probe_offload(sc
);
998 * Get station address from the driver.
1000 len
= sizeof(eaddr
);
1001 ndis_get_info(sc
, OID_802_3_CURRENT_ADDRESS
, eaddr
, &len
);
1003 if_initname(ifp
, device_get_name(sc
->ndis_dev
),
1004 device_get_unit(sc
->ndis_dev
));
1005 ifp
->if_flags
= IFF_BROADCAST
| IFF_SIMPLEX
| IFF_MULTICAST
;
1006 ifp
->if_ioctl
= ndis_ioctl
;
1007 ifp
->if_start
= ndis_start
;
1008 ifp
->if_init
= ndis_init
;
1009 ifp
->if_baudrate
= 10000000;
1010 #if defined(__DragonFly__)
1011 ifq_set_maxlen(&ifp
->if_snd
, 50);
1012 /* ifq_set_ready(&ifp->if_snd); */
1014 IFQ_SET_MAXLEN(&ifp
->if_snd
, 50);
1015 ifp
->if_snd
.ifq_drv_maxlen
= 25;
1016 IFQ_SET_READY(&ifp
->if_snd
);
1018 ifp
->if_capenable
= ifp
->if_capabilities
;
1019 ifp
->if_hwassist
= sc
->ndis_hwassist
;
1021 ifmedia_init(&sc
->ifmedia
, IFM_IMASK
, ndis_ifmedia_upd
,
1023 ifmedia_add(&sc
->ifmedia
, IFM_ETHER
|IFM_10_T
, 0, NULL
);
1024 ifmedia_add(&sc
->ifmedia
, IFM_ETHER
|IFM_10_T
|IFM_FDX
, 0, NULL
);
1025 ifmedia_add(&sc
->ifmedia
, IFM_ETHER
|IFM_100_TX
, 0, NULL
);
1026 ifmedia_add(&sc
->ifmedia
, IFM_ETHER
|IFM_100_TX
|IFM_FDX
, 0, NULL
);
1027 ifmedia_add(&sc
->ifmedia
, IFM_ETHER
|IFM_AUTO
, 0, NULL
);
1028 ifmedia_set(&sc
->ifmedia
, IFM_ETHER
|IFM_AUTO
);
1029 #if defined(__DragonFly__)
1030 ether_ifattach(ifp
, eaddr
, NULL
);
1032 ether_ifattach(ifp
, eaddr
);
1038 static struct ieee80211vap
*
1039 ndis_vap_create(struct ieee80211com
*ic
, const char name
[IFNAMSIZ
], int unit
,
1040 enum ieee80211_opmode opmode
, int flags
,
1041 const uint8_t bssid
[IEEE80211_ADDR_LEN
],
1042 const uint8_t mac
[IEEE80211_ADDR_LEN
])
1044 struct ndis_vap
*nvp
;
1045 struct ieee80211vap
*vap
;
1047 if (!TAILQ_EMPTY(&ic
->ic_vaps
)) /* only one at a time */
1049 nvp
= kmalloc(sizeof(struct ndis_vap
), M_80211_VAP
, M_WAITOK
| M_ZERO
);
1051 ieee80211_vap_setup(ic
, vap
, name
, unit
, opmode
, flags
, bssid
);
1052 /* override with driver methods */
1053 nvp
->newstate
= vap
->iv_newstate
;
1054 vap
->iv_newstate
= ndis_newstate
;
1056 /* complete setup */
1057 ieee80211_vap_attach(vap
, ieee80211_media_change
, ndis_media_status
,
1059 ic
->ic_opmode
= opmode
;
1060 /* install key handing routines */
1061 vap
->iv_key_set
= ndis_add_key
;
1062 vap
->iv_key_delete
= ndis_del_key
;
1067 ndis_vap_delete(struct ieee80211vap
*vap
)
1069 struct ndis_vap
*nvp
= NDIS_VAP(vap
);
1070 struct ieee80211com
*ic
= vap
->iv_ic
;
1071 struct ndis_softc
*sc
= ic
->ic_softc
;
1074 callout_drain(&sc
->ndis_scan_callout
);
1075 ieee80211_vap_detach(vap
);
1076 kfree(nvp
, M_80211_VAP
);
1080 * Shutdown hardware and free up resources. This can be called any
1081 * time after the mutex has been initialized. It is called in both
1082 * the error case in attach and the normal detach case so it needs
1083 * to be careful about only freeing resources that have actually been
1087 ndis_detach(device_t dev
)
1090 struct ndis_softc
*sc
;
1093 sc
= device_get_softc(dev
);
1095 if (!sc
->ndis_80211
)
1100 ifp
->if_flags
&= ~IFF_UP
;
1101 if (device_is_attached(dev
)) {
1105 ieee80211_ifdetach(&sc
->ndis_ic
);
1106 else if (ifp
!= NULL
)
1107 ether_ifdetach(ifp
);
1111 if (sc
->ndis_tickitem
!= NULL
)
1112 IoFreeWorkItem(sc
->ndis_tickitem
);
1113 if (sc
->ndis_startitem
!= NULL
)
1114 IoFreeWorkItem(sc
->ndis_startitem
);
1115 if (sc
->ndis_resetitem
!= NULL
)
1116 IoFreeWorkItem(sc
->ndis_resetitem
);
1117 if (sc
->ndis_inputitem
!= NULL
)
1118 IoFreeWorkItem(sc
->ndis_inputitem
);
1119 if (sc
->ndisusb_xferdoneitem
!= NULL
)
1120 IoFreeWorkItem(sc
->ndisusb_xferdoneitem
);
1121 if (sc
->ndisusb_taskitem
!= NULL
)
1122 IoFreeWorkItem(sc
->ndisusb_taskitem
);
1124 bus_generic_detach(dev
);
1125 ndis_unload_driver(sc
);
1128 bus_release_resource(dev
, SYS_RES_IRQ
, 0, sc
->ndis_irq
);
1129 if (sc
->ndis_res_io
)
1130 bus_release_resource(dev
, SYS_RES_IOPORT
,
1131 sc
->ndis_io_rid
, sc
->ndis_res_io
);
1132 if (sc
->ndis_res_mem
)
1133 bus_release_resource(dev
, SYS_RES_MEMORY
,
1134 sc
->ndis_mem_rid
, sc
->ndis_res_mem
);
1135 if (sc
->ndis_res_altmem
)
1136 bus_release_resource(dev
, SYS_RES_MEMORY
,
1137 sc
->ndis_altmem_rid
, sc
->ndis_res_altmem
);
1142 if (sc
->ndis_iftype
== PCMCIABus
)
1146 ndis_destroy_dma(sc
);
1148 if (sc
->ndis_txarray
)
1149 kfree(sc
->ndis_txarray
, M_DEVBUF
);
1151 if (!sc
->ndis_80211
)
1152 ifmedia_removeall(&sc
->ifmedia
);
1154 if (sc
->ndis_txpool
!= NULL
)
1155 NdisFreePacketPool(sc
->ndis_txpool
);
1157 /* Destroy the PDO for this device. */
1159 if (sc
->ndis_iftype
== PCIBus
)
1160 drv
= windrv_lookup(0, "PCI Bus");
1161 else if (sc
->ndis_iftype
== PCMCIABus
)
1162 drv
= windrv_lookup(0, "PCCARD Bus");
1164 drv
= windrv_lookup(0, "USB Bus");
1166 panic("couldn't find driver object");
1167 windrv_destroy_pdo(drv
, dev
);
1169 if (sc
->ndis_iftype
== PCIBus
)
1170 bus_dma_tag_destroy(sc
->ndis_parent_tag
);
1176 ndis_suspend(device_t dev
)
1179 struct ndis_softc
*sc
;
1182 sc
= device_get_softc(dev
);
1185 if (NDIS_INITIALIZED(sc
))
1192 ndis_resume(device_t dev
)
1194 struct ndis_softc
*sc
;
1197 sc
= device_get_softc(dev
);
1200 if (NDIS_INITIALIZED(sc
))
1207 * The following bunch of routines are here to support drivers that
1208 * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism.
1209 * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for
1210 * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1214 ndis_rxeof_eth(ndis_handle adapter
, ndis_handle ctx
, char *addr
, void *hdr
,
1215 uint32_t hdrlen
, void *lookahead
, uint32_t lookaheadlen
, uint32_t pktlen
)
1217 ndis_miniport_block
*block
;
1227 m
= m_getcl(M_NOWAIT
, MT_DATA
, M_PKTHDR
);
1231 /* Save the data provided to us so far. */
1233 m
->m_len
= lookaheadlen
+ hdrlen
;
1234 m
->m_pkthdr
.len
= pktlen
+ hdrlen
;
1236 m_copyback(m
, 0, hdrlen
, hdr
);
1237 m_copyback(m
, hdrlen
, lookaheadlen
, lookahead
);
1239 /* Now create a fake NDIS_PACKET to hold the data */
1241 NdisAllocatePacket(&status
, &p
, block
->nmb_rxpool
);
1243 if (status
!= NDIS_STATUS_SUCCESS
) {
1250 b
= IoAllocateMdl(m
->m_data
, m
->m_pkthdr
.len
, FALSE
, FALSE
, NULL
);
1258 p
->np_private
.npp_head
= p
->np_private
.npp_tail
= b
;
1259 p
->np_private
.npp_totlen
= m
->m_pkthdr
.len
;
1261 /* Save the packet RX context somewhere. */
1262 priv
= (ndis_ethpriv
*)&p
->np_protocolreserved
;
1263 priv
->nep_ctx
= ctx
;
1265 if (!NDIS_SERIALIZED(block
))
1266 KeAcquireSpinLock(&block
->nmb_lock
, &irql
);
1268 InsertTailList((&block
->nmb_packetlist
), (&p
->np_list
));
1270 if (!NDIS_SERIALIZED(block
))
1271 KeReleaseSpinLock(&block
->nmb_lock
, irql
);
1275 * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1276 * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1280 ndis_rxeof_done(ndis_handle adapter
)
1282 struct ndis_softc
*sc
;
1283 ndis_miniport_block
*block
;
1287 /* Schedule transfer/RX of queued packets. */
1289 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
1291 KeInsertQueueDpc(&sc
->ndis_rxdpc
, NULL
, NULL
);
1295 * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1298 ndis_rxeof_xfr(kdpc
*dpc
, ndis_handle adapter
, void *sysarg1
, void *sysarg2
)
1300 ndis_miniport_block
*block
;
1301 struct ndis_softc
*sc
;
1310 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
1313 KeAcquireSpinLockAtDpcLevel(&block
->nmb_lock
);
1315 l
= block
->nmb_packetlist
.nle_flink
;
1316 while(!IsListEmpty(&block
->nmb_packetlist
)) {
1317 l
= RemoveHeadList((&block
->nmb_packetlist
));
1318 p
= CONTAINING_RECORD(l
, ndis_packet
, np_list
);
1319 InitializeListHead((&p
->np_list
));
1321 priv
= (ndis_ethpriv
*)&p
->np_protocolreserved
;
1326 KeReleaseSpinLockFromDpcLevel(&block
->nmb_lock
);
1328 status
= MSCALL6(sc
->ndis_chars
->nmc_transferdata_func
,
1329 p
, &p
->np_private
.npp_totlen
, block
, priv
->nep_ctx
,
1330 m
->m_len
, m
->m_pkthdr
.len
- m
->m_len
);
1332 KeAcquireSpinLockAtDpcLevel(&block
->nmb_lock
);
1335 * If status is NDIS_STATUS_PENDING, do nothing and
1336 * wait for a callback to the ndis_rxeof_xfr_done()
1340 m
->m_len
= m
->m_pkthdr
.len
;
1341 m
->m_pkthdr
.rcvif
= ifp
;
1343 if (status
== NDIS_STATUS_SUCCESS
) {
1344 IoFreeMdl(p
->np_private
.npp_head
);
1346 KeAcquireSpinLockAtDpcLevel(&sc
->ndis_rxlock
);
1347 mbufq_enqueue(&sc
->ndis_rxqueue
, m
);
1348 KeReleaseSpinLockFromDpcLevel(&sc
->ndis_rxlock
);
1349 IoQueueWorkItem(sc
->ndis_inputitem
,
1350 (io_workitem_func
)ndis_inputtask_wrap
,
1351 WORKQUEUE_CRITICAL
, sc
);
1354 if (status
== NDIS_STATUS_FAILURE
)
1357 /* Advance to next packet */
1358 l
= block
->nmb_packetlist
.nle_flink
;
1361 KeReleaseSpinLockFromDpcLevel(&block
->nmb_lock
);
1365 * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1368 ndis_rxeof_xfr_done(ndis_handle adapter
, ndis_packet
*packet
, uint32_t status
,
1371 ndis_miniport_block
*block
;
1372 struct ndis_softc
*sc
;
1377 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
1381 IoFreeMdl(packet
->np_private
.npp_head
);
1382 NdisFreePacket(packet
);
1384 if (status
!= NDIS_STATUS_SUCCESS
) {
1389 m
->m_len
= m
->m_pkthdr
.len
;
1390 m
->m_pkthdr
.rcvif
= ifp
;
1391 KeAcquireSpinLockAtDpcLevel(&sc
->ndis_rxlock
);
1392 mbufq_enqueue(&sc
->ndis_rxqueue
, m
);
1393 KeReleaseSpinLockFromDpcLevel(&sc
->ndis_rxlock
);
1394 IoQueueWorkItem(sc
->ndis_inputitem
,
1395 (io_workitem_func
)ndis_inputtask_wrap
,
1396 WORKQUEUE_CRITICAL
, sc
);
1399 * A frame has been uploaded: pass the resulting mbuf chain up to
1400 * the higher level protocols.
1402 * When handling received NDIS packets, the 'status' field in the
1403 * out-of-band portion of the ndis_packet has special meaning. In the
1404 * most common case, the underlying NDIS driver will set this field
1405 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1406 * take possession of it. We then change the status field to
1407 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1408 * and that we will return it at some point in the future via the
1409 * return packet handler.
1411 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1412 * this means the driver is running out of packet/buffer resources and
1413 * wants to maintain ownership of the packet. In this case, we have to
1414 * copy the packet data into local storage and let the driver keep the
1418 ndis_rxeof(ndis_handle adapter
, ndis_packet
**packets
, uint32_t pktcnt
)
1420 struct ndis_softc
*sc
;
1421 ndis_miniport_block
*block
;
1424 ndis_tcpip_csum
*csum
;
1426 struct mbuf
*m0
, *m
;
1429 block
= (ndis_miniport_block
*)adapter
;
1430 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
1434 * There's a slim chance the driver may indicate some packets
1435 * before we're completely ready to handle them. If we detect this,
1436 * we need to return them to the miniport and ignore them.
1438 if (!sc
->ndis_running
) {
1439 for (i
= 0; i
< pktcnt
; i
++) {
1441 if (p
->np_oob
.npo_status
== NDIS_STATUS_SUCCESS
) {
1443 #if defined(__DragonFly__)
1444 ndis_return_packet(p
);
1446 (void)ndis_return_packet(NULL
, p
, block
);
1453 for (i
= 0; i
< pktcnt
; i
++) {
1455 /* Stash the softc here so ptom can use it. */
1457 if (ndis_ptom(&m0
, p
)) {
1458 device_printf(sc
->ndis_dev
, "ptom failed\n");
1459 if (p
->np_oob
.npo_status
== NDIS_STATUS_SUCCESS
) {
1460 #if defined(__DragonFly__)
1461 ndis_return_packet(p
);
1463 (void)ndis_return_packet(NULL
, p
, block
);
1468 if (p
->np_oob
.npo_status
== NDIS_STATUS_RESOURCES
) {
1469 m
= m_dup(m0
, M_NOWAIT
);
1471 * NOTE: we want to destroy the mbuf here, but
1472 * we don't actually want to return it to the
1473 * driver via the return packet handler. By
1474 * bumping np_refcnt, we can prevent the
1475 * ndis_return_packet() routine from actually
1481 if_inc_counter(ifp
, IFCOUNTER_IERRORS
, 1);
1485 p
->np_oob
.npo_status
= NDIS_STATUS_PENDING
;
1487 m
= m_dup(m0
, M_NOWAIT
);
1488 if (p
->np_oob
.npo_status
== NDIS_STATUS_RESOURCES
)
1491 p
->np_oob
.npo_status
= NDIS_STATUS_PENDING
;
1494 if_inc_counter(ifp
, IFCOUNTER_IERRORS
, 1);
1498 m0
->m_pkthdr
.rcvif
= ifp
;
1500 /* Deal with checksum offload. */
1502 if (ifp
->if_capenable
& IFCAP_RXCSUM
&&
1503 p
->np_ext
.npe_info
[ndis_tcpipcsum_info
] != NULL
) {
1505 p
->np_ext
.npe_info
[ndis_tcpipcsum_info
];
1506 csum
= (ndis_tcpip_csum
*)&s
;
1507 if (csum
->u
.ntc_rxflags
&
1508 NDIS_RXCSUM_IP_PASSED
)
1509 m0
->m_pkthdr
.csum_flags
|=
1510 CSUM_IP_CHECKED
|CSUM_IP_VALID
;
1511 if (csum
->u
.ntc_rxflags
&
1512 (NDIS_RXCSUM_TCP_PASSED
|
1513 NDIS_RXCSUM_UDP_PASSED
)) {
1514 m0
->m_pkthdr
.csum_flags
|=
1515 CSUM_DATA_VALID
|CSUM_PSEUDO_HDR
;
1516 m0
->m_pkthdr
.csum_data
= 0xFFFF;
1520 KeAcquireSpinLockAtDpcLevel(&sc
->ndis_rxlock
);
1521 mbufq_enqueue(&sc
->ndis_rxqueue
, m0
);
1522 KeReleaseSpinLockFromDpcLevel(&sc
->ndis_rxlock
);
1523 IoQueueWorkItem(sc
->ndis_inputitem
,
1524 (io_workitem_func
)ndis_inputtask_wrap
,
1525 WORKQUEUE_CRITICAL
, sc
);
1531 * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1532 * packets into the stack in order to avoid calling (*ifp->if_input)()
1533 * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1534 * 'dispatch level' per-cpu sleep lock).
1537 ndis_inputtask(device_object
*dobj
, void *arg
)
1539 ndis_miniport_block
*block
;
1540 struct ndis_softc
*sc
= arg
;
1544 block
= dobj
->do_devext
;
1546 KeAcquireSpinLock(&sc
->ndis_rxlock
, &irql
);
1547 while ((m
= mbufq_dequeue(&sc
->ndis_rxqueue
)) != NULL
) {
1548 KeReleaseSpinLock(&sc
->ndis_rxlock
, irql
);
1549 if ((sc
->ndis_80211
!= 0)) {
1550 struct ieee80211com
*ic
= &sc
->ndis_ic
;
1551 struct ieee80211vap
*vap
= TAILQ_FIRST(&ic
->ic_vaps
);
1554 vap
->iv_deliver_data(vap
, vap
->iv_bss
, m
);
1556 struct ifnet
*ifp
= sc
->ifp
;
1558 #if defined(__DragonFly__)
1559 ifp
->if_input(ifp
, m
, NULL
, -1);
1561 (*ifp
->if_input
)(ifp
, m
);
1564 KeAcquireSpinLock(&sc
->ndis_rxlock
, &irql
);
1566 KeReleaseSpinLock(&sc
->ndis_rxlock
, irql
);
1570 * A frame was downloaded to the chip. It's safe for us to clean up
1574 ndis_txeof(ndis_handle adapter
, ndis_packet
*packet
, ndis_status status
)
1576 struct ndis_softc
*sc
;
1577 ndis_miniport_block
*block
;
1582 block
= (ndis_miniport_block
*)adapter
;
1583 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
1587 idx
= packet
->np_txidx
;
1589 bus_dmamap_unload(sc
->ndis_ttag
, sc
->ndis_tmaps
[idx
]);
1591 ndis_free_packet(packet
);
1595 sc
->ndis_txarray
[idx
] = NULL
;
1596 sc
->ndis_txpending
++;
1598 if (status
== NDIS_STATUS_SUCCESS
)
1599 if_inc_counter(ifp
, IFCOUNTER_OPACKETS
, 1);
1601 if_inc_counter(ifp
, IFCOUNTER_OERRORS
, 1);
1603 sc
->ndis_tx_timer
= 0;
1604 #if defined(__DragonFly__)
1605 ifq_clr_oactive(&sc
->ifp
->if_snd
);
1607 ifp
->if_drv_flags
&= ~IFF_DRV_OACTIVE
;
1612 IoQueueWorkItem(sc
->ndis_startitem
,
1613 (io_workitem_func
)ndis_starttask_wrap
,
1614 WORKQUEUE_CRITICAL
, ifp
);
1618 ndis_linksts(ndis_handle adapter
, ndis_status status
, void *sbuf
,
1621 ndis_miniport_block
*block
;
1622 struct ndis_softc
*sc
;
1625 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
1626 sc
->ndis_sts
= status
;
1628 /* Event list is all full up, drop this one. */
1631 if (sc
->ndis_evt
[sc
->ndis_evtpidx
].ne_sts
) {
1636 /* Cache the event. */
1639 sc
->ndis_evt
[sc
->ndis_evtpidx
].ne_buf
= kmalloc(slen
,
1641 if (sc
->ndis_evt
[sc
->ndis_evtpidx
].ne_buf
== NULL
) {
1646 sc
->ndis_evt
[sc
->ndis_evtpidx
].ne_buf
, slen
);
1648 sc
->ndis_evt
[sc
->ndis_evtpidx
].ne_sts
= status
;
1649 sc
->ndis_evt
[sc
->ndis_evtpidx
].ne_len
= slen
;
1650 NDIS_EVTINC(sc
->ndis_evtpidx
);
1655 ndis_linksts_done(ndis_handle adapter
)
1657 ndis_miniport_block
*block
;
1658 struct ndis_softc
*sc
;
1662 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
1665 if (!NDIS_INITIALIZED(sc
))
1668 switch (sc
->ndis_sts
) {
1669 case NDIS_STATUS_MEDIA_CONNECT
:
1670 IoQueueWorkItem(sc
->ndis_tickitem
,
1671 (io_workitem_func
)ndis_ticktask_wrap
,
1672 WORKQUEUE_CRITICAL
, sc
);
1673 IoQueueWorkItem(sc
->ndis_startitem
,
1674 (io_workitem_func
)ndis_starttask_wrap
,
1675 WORKQUEUE_CRITICAL
, ifp
);
1677 case NDIS_STATUS_MEDIA_DISCONNECT
:
1679 IoQueueWorkItem(sc
->ndis_tickitem
,
1680 (io_workitem_func
)ndis_ticktask_wrap
,
1681 WORKQUEUE_CRITICAL
, sc
);
1689 ndis_tick(void *xsc
)
1691 struct ndis_softc
*sc
;
1695 if (sc
->ndis_hang_timer
&& --sc
->ndis_hang_timer
== 0) {
1696 IoQueueWorkItem(sc
->ndis_tickitem
,
1697 (io_workitem_func
)ndis_ticktask_wrap
,
1698 WORKQUEUE_CRITICAL
, sc
);
1699 sc
->ndis_hang_timer
= sc
->ndis_block
->nmb_checkforhangsecs
;
1702 if (sc
->ndis_tx_timer
&& --sc
->ndis_tx_timer
== 0) {
1703 if_inc_counter(sc
->ifp
, IFCOUNTER_OERRORS
, 1);
1704 device_printf(sc
->ndis_dev
, "watchdog timeout\n");
1706 IoQueueWorkItem(sc
->ndis_resetitem
,
1707 (io_workitem_func
)ndis_resettask_wrap
,
1708 WORKQUEUE_CRITICAL
, sc
);
1709 IoQueueWorkItem(sc
->ndis_startitem
,
1710 (io_workitem_func
)ndis_starttask_wrap
,
1711 WORKQUEUE_CRITICAL
, sc
->ifp
);
1714 callout_reset(&sc
->ndis_stat_callout
, hz
, ndis_tick
, sc
);
1718 ndis_ticktask(device_object
*d
, void *xsc
)
1720 struct ndis_softc
*sc
= xsc
;
1721 ndis_checkforhang_handler hangfunc
;
1725 if (!NDIS_INITIALIZED(sc
)) {
1731 hangfunc
= sc
->ndis_chars
->nmc_checkhang_func
;
1733 if (hangfunc
!= NULL
) {
1734 rval
= MSCALL1(hangfunc
,
1735 sc
->ndis_block
->nmb_miniportadapterctx
);
1743 if (sc
->ndis_link
== 0 &&
1744 sc
->ndis_sts
== NDIS_STATUS_MEDIA_CONNECT
) {
1746 if (sc
->ndis_80211
!= 0) {
1747 struct ieee80211com
*ic
= &sc
->ndis_ic
;
1748 struct ieee80211vap
*vap
= TAILQ_FIRST(&ic
->ic_vaps
);
1752 ndis_getstate_80211(sc
);
1753 ieee80211_new_state(vap
, IEEE80211_S_RUN
, -1);
1755 #if defined(__DragonFly__)
1756 vap
->iv_ifp
->if_link_state
= LINK_STATE_UP
;
1757 if_link_state_change(vap
->iv_ifp
);
1759 if_link_state_change(vap
->iv_ifp
,
1764 #if defined(__DragonFly__)
1765 sc
->ifp
->if_link_state
= LINK_STATE_UP
;
1766 if_link_state_change(sc
->ifp
);
1768 if_link_state_change(sc
->ifp
, LINK_STATE_UP
);
1773 if (sc
->ndis_link
== 1 &&
1774 sc
->ndis_sts
== NDIS_STATUS_MEDIA_DISCONNECT
) {
1776 if (sc
->ndis_80211
!= 0) {
1777 struct ieee80211com
*ic
= &sc
->ndis_ic
;
1778 struct ieee80211vap
*vap
= TAILQ_FIRST(&ic
->ic_vaps
);
1782 ieee80211_new_state(vap
, IEEE80211_S_SCAN
, 0);
1784 #if defined(__DragonFly__)
1785 vap
->iv_ifp
->if_link_state
= LINK_STATE_DOWN
;
1786 if_link_state_change(vap
->iv_ifp
);
1788 if_link_state_change(vap
->iv_ifp
,
1793 #if defined(__DragonFly__)
1794 sc
->ifp
->if_link_state
= LINK_STATE_DOWN
;
1795 if_link_state_change(sc
->ifp
);
1797 if_link_state_change(sc
->ifp
, LINK_STATE_DOWN
);
1806 ndis_map_sclist(void *arg
, bus_dma_segment_t
*segs
, int nseg
,
1807 bus_size_t mapsize
, int error
)
1809 struct ndis_sc_list
*sclist
;
1812 if (error
|| arg
== NULL
)
1817 sclist
->nsl_frags
= nseg
;
1819 for (i
= 0; i
< nseg
; i
++) {
1820 sclist
->nsl_elements
[i
].nse_addr
.np_quad
= segs
[i
].ds_addr
;
1821 sclist
->nsl_elements
[i
].nse_len
= segs
[i
].ds_len
;
1826 ndis_raw_xmit(struct ieee80211_node
*ni
, struct mbuf
*m
,
1827 const struct ieee80211_bpf_params
*params
)
1829 /* no support; just discard */
1831 ieee80211_free_node(ni
);
1836 ndis_update_mcast(struct ieee80211com
*ic
)
1838 struct ndis_softc
*sc
= ic
->ic_softc
;
1844 ndis_update_promisc(struct ieee80211com
*ic
)
1850 ndis_starttask(device_object
*d
, void *arg
)
1856 #if defined(__DragonFly__)
1857 if (!ifq_is_empty(&ifp
->if_snd
))
1860 if (!IFQ_DRV_IS_EMPTY(&ifp
->if_snd
))
1866 * Main transmit routine. To make NDIS drivers happy, we need to
1867 * transform mbuf chains into NDIS packets and feed them to the
1868 * send packet routines. Most drivers allow you to send several
1869 * packets at once (up to the maxpkts limit). Unfortunately, rather
1870 * that accepting them in the form of a linked list, they expect
1871 * a contiguous array of pointers to packets.
1873 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1874 * we need to perform busdma work here. Those that use map registers
1875 * will do the mapping themselves on a buffer by buffer basis.
1878 ndis_start(struct ifnet
*ifp
, struct ifaltq_subque
*ifsq
)
1880 struct ndis_softc
*sc
;
1881 struct mbuf
*m
= NULL
;
1882 ndis_packet
**p0
= NULL
, *p
= NULL
;
1883 ndis_tcpip_csum
*csum
;
1884 int pcnt
= 0, status
;
1889 #if defined(__DragonFly__)
1890 if (!sc
->ndis_link
|| ifq_is_oactive(&ifp
->if_snd
)) {
1892 if (!sc
->ndis_link
|| ifp
->if_drv_flags
& IFF_DRV_OACTIVE
) {
1898 p0
= &sc
->ndis_txarray
[sc
->ndis_txidx
];
1900 while(sc
->ndis_txpending
) {
1901 #if defined(__DragonFly__)
1902 m
= ifq_dequeue(&ifp
->if_snd
);
1904 IFQ_DRV_DEQUEUE(&ifp
->if_snd
, m
);
1909 NdisAllocatePacket(&status
,
1910 &sc
->ndis_txarray
[sc
->ndis_txidx
], sc
->ndis_txpool
);
1912 if (status
!= NDIS_STATUS_SUCCESS
)
1915 if (ndis_mtop(m
, &sc
->ndis_txarray
[sc
->ndis_txidx
])) {
1916 #if defined(__DragonFly__)
1917 ifq_prepend(&ifp
->if_snd
, m
);
1919 IFQ_DRV_PREPEND(&ifp
->if_snd
, m
);
1926 * Save pointer to original mbuf
1927 * so we can free it later.
1930 p
= sc
->ndis_txarray
[sc
->ndis_txidx
];
1931 p
->np_txidx
= sc
->ndis_txidx
;
1933 p
->np_oob
.npo_status
= NDIS_STATUS_PENDING
;
1936 * Do scatter/gather processing, if driver requested it.
1939 bus_dmamap_load_mbuf(sc
->ndis_ttag
,
1940 sc
->ndis_tmaps
[sc
->ndis_txidx
], m
,
1941 ndis_map_sclist
, &p
->np_sclist
, BUS_DMA_NOWAIT
);
1942 bus_dmamap_sync(sc
->ndis_ttag
,
1943 sc
->ndis_tmaps
[sc
->ndis_txidx
],
1944 BUS_DMASYNC_PREREAD
);
1945 p
->np_ext
.npe_info
[ndis_sclist_info
] = &p
->np_sclist
;
1948 /* Handle checksum offload. */
1950 if (ifp
->if_capenable
& IFCAP_TXCSUM
&&
1951 m
->m_pkthdr
.csum_flags
) {
1952 csum
= (ndis_tcpip_csum
*)
1953 &p
->np_ext
.npe_info
[ndis_tcpipcsum_info
];
1954 csum
->u
.ntc_txflags
= NDIS_TXCSUM_DO_IPV4
;
1955 if (m
->m_pkthdr
.csum_flags
& CSUM_IP
)
1956 csum
->u
.ntc_txflags
|= NDIS_TXCSUM_DO_IP
;
1957 if (m
->m_pkthdr
.csum_flags
& CSUM_TCP
)
1958 csum
->u
.ntc_txflags
|= NDIS_TXCSUM_DO_TCP
;
1959 if (m
->m_pkthdr
.csum_flags
& CSUM_UDP
)
1960 csum
->u
.ntc_txflags
|= NDIS_TXCSUM_DO_UDP
;
1961 p
->np_private
.npp_flags
= NDIS_PROTOCOL_ID_TCP_IP
;
1965 sc
->ndis_txpending
--;
1970 * If there's a BPF listener, bounce a copy of this frame
1973 if (!sc
->ndis_80211
) /* XXX handle 80211 */
1977 * The array that p0 points to must appear contiguous,
1978 * so we must not wrap past the end of sc->ndis_txarray[].
1979 * If it looks like we're about to wrap, break out here
1980 * so the this batch of packets can be transmitted, then
1981 * wait for txeof to ask us to send the rest.
1983 if (sc
->ndis_txidx
== 0)
1992 if (sc
->ndis_txpending
== 0) {
1993 #if defined(__DragonFly__)
1994 ifq_set_oactive(&ifp
->if_snd
);
1996 ifp
->if_drv_flags
|= IFF_DRV_OACTIVE
;
2001 * Set a timeout in case the chip goes out to lunch.
2003 sc
->ndis_tx_timer
= 5;
2008 * According to NDIS documentation, if a driver exports
2009 * a MiniportSendPackets() routine, we prefer that over
2010 * a MiniportSend() routine (which sends just a single
2013 if (sc
->ndis_chars
->nmc_sendmulti_func
!= NULL
)
2014 ndis_send_packets(sc
, p0
, pcnt
);
2016 ndis_send_packet(sc
, p
);
2022 ndis_80211transmit(struct ieee80211com
*ic
, struct mbuf
*m
)
2024 struct ndis_softc
*sc
= ic
->ic_softc
;
2025 ndis_packet
**p0
= NULL
, *p
= NULL
;
2029 if (!sc
->ndis_link
|| !sc
->ndis_running
) {
2034 if (sc
->ndis_txpending
== 0) {
2039 p0
= &sc
->ndis_txarray
[sc
->ndis_txidx
];
2041 NdisAllocatePacket(&status
,
2042 &sc
->ndis_txarray
[sc
->ndis_txidx
], sc
->ndis_txpool
);
2044 if (status
!= NDIS_STATUS_SUCCESS
) {
2049 if (ndis_mtop(m
, &sc
->ndis_txarray
[sc
->ndis_txidx
])) {
2055 * Save pointer to original mbuf
2056 * so we can free it later.
2059 p
= sc
->ndis_txarray
[sc
->ndis_txidx
];
2060 p
->np_txidx
= sc
->ndis_txidx
;
2062 p
->np_oob
.npo_status
= NDIS_STATUS_PENDING
;
2065 * Do scatter/gather processing, if driver requested it.
2068 bus_dmamap_load_mbuf(sc
->ndis_ttag
,
2069 sc
->ndis_tmaps
[sc
->ndis_txidx
], m
,
2070 ndis_map_sclist
, &p
->np_sclist
, BUS_DMA_NOWAIT
);
2071 bus_dmamap_sync(sc
->ndis_ttag
,
2072 sc
->ndis_tmaps
[sc
->ndis_txidx
],
2073 BUS_DMASYNC_PREREAD
);
2074 p
->np_ext
.npe_info
[ndis_sclist_info
] = &p
->np_sclist
;
2078 sc
->ndis_txpending
--;
2081 * Set a timeout in case the chip goes out to lunch.
2083 sc
->ndis_tx_timer
= 5;
2087 * According to NDIS documentation, if a driver exports
2088 * a MiniportSendPackets() routine, we prefer that over
2089 * a MiniportSend() routine (which sends just a single
2092 if (sc
->ndis_chars
->nmc_sendmulti_func
!= NULL
)
2093 ndis_send_packets(sc
, p0
, 1);
2095 ndis_send_packet(sc
, p
);
2101 ndis_80211parent(struct ieee80211com
*ic
)
2103 struct ndis_softc
*sc
= ic
->ic_softc
;
2106 if (ic
->ic_nrunning
> 0) {
2107 if (!sc
->ndis_running
)
2109 } else if (sc
->ndis_running
)
2111 /*NDIS_UNLOCK(sc);*/
2115 ndis_init(void *xsc
)
2117 struct ndis_softc
*sc
= xsc
;
2121 * Avoid reintializing the link unnecessarily.
2122 * This should be dealt with in a better way by
2123 * fixing the upper layer modules so they don't
2124 * call ifp->if_init() quite as often.
2130 * Cancel pending I/O and free all RX/TX buffers.
2134 if (!(sc
->ndis_iftype
== PNPBus
&& ndisusb_halt
== 0)) {
2135 error
= ndis_init_nic(sc
);
2137 device_printf(sc
->ndis_dev
,
2138 "failed to initialize the device: %d\n", error
);
2143 /* Program the packet filter */
2144 sc
->ndis_filter
= NDIS_PACKET_TYPE_DIRECTED
|
2145 NDIS_PACKET_TYPE_BROADCAST
;
2147 if (sc
->ndis_80211
) {
2148 struct ieee80211com
*ic
= &sc
->ndis_ic
;
2150 if (ic
->ic_promisc
> 0)
2151 sc
->ndis_filter
|= NDIS_PACKET_TYPE_PROMISCUOUS
;
2153 struct ifnet
*ifp
= sc
->ifp
;
2155 if (ifp
->if_flags
& IFF_PROMISC
)
2156 sc
->ndis_filter
|= NDIS_PACKET_TYPE_PROMISCUOUS
;
2159 len
= sizeof(sc
->ndis_filter
);
2161 error
= ndis_set_info(sc
, OID_GEN_CURRENT_PACKET_FILTER
,
2162 &sc
->ndis_filter
, &len
);
2165 device_printf(sc
->ndis_dev
, "set filter failed: %d\n", error
);
2173 i
= sc
->ifp
->if_mtu
;
2175 ndis_set_info(sc
, OID_GEN_CURRENT_LOOKAHEAD
, &i
, &len
);
2178 * Program the multicast filter, if necessary.
2182 /* Setup task offload. */
2183 ndis_set_offload(sc
);
2188 sc
->ndis_txpending
= sc
->ndis_maxpkts
;
2191 if (!sc
->ndis_80211
) {
2192 #if defined(__DragonFly__)
2193 sc
->ifp
->if_link_state
= LINK_STATE_UNKNOWN
;
2194 if_link_state_change(sc
->ifp
);
2195 sc
->ifp
->if_flags
|= IFF_RUNNING
;
2196 ifq_clr_oactive(&sc
->ifp
->if_snd
);
2198 if_link_state_change(sc
->ifp
, LINK_STATE_UNKNOWN
);
2199 sc
->ifp
->if_drv_flags
|= IFF_DRV_RUNNING
;
2200 sc
->ifp
->if_drv_flags
&= ~IFF_DRV_OACTIVE
;
2204 sc
->ndis_tx_timer
= 0;
2207 * Some drivers don't set this value. The NDIS spec says
2208 * the default checkforhang timeout is "approximately 2
2209 * seconds." We use 3 seconds, because it seems for some
2210 * drivers, exactly 2 seconds is too fast.
2212 if (sc
->ndis_block
->nmb_checkforhangsecs
== 0)
2213 sc
->ndis_block
->nmb_checkforhangsecs
= 3;
2215 sc
->ndis_hang_timer
= sc
->ndis_block
->nmb_checkforhangsecs
;
2216 callout_reset(&sc
->ndis_stat_callout
, hz
, ndis_tick
, sc
);
2217 sc
->ndis_running
= 1;
2220 /* XXX force handling */
2222 ieee80211_start_all(&sc
->ndis_ic
); /* start all vap's */
2226 * Set media options.
2229 ndis_ifmedia_upd(struct ifnet
*ifp
)
2231 struct ndis_softc
*sc
;
2235 if (NDIS_INITIALIZED(sc
))
2242 * Report current media status.
2245 ndis_ifmedia_sts(struct ifnet
*ifp
, struct ifmediareq
*ifmr
)
2247 struct ndis_softc
*sc
;
2248 uint32_t media_info
;
2249 ndis_media_state linkstate
;
2252 ifmr
->ifm_status
= IFM_AVALID
;
2253 ifmr
->ifm_active
= IFM_ETHER
;
2256 if (!NDIS_INITIALIZED(sc
))
2259 len
= sizeof(linkstate
);
2260 ndis_get_info(sc
, OID_GEN_MEDIA_CONNECT_STATUS
,
2261 (void *)&linkstate
, &len
);
2263 len
= sizeof(media_info
);
2264 ndis_get_info(sc
, OID_GEN_LINK_SPEED
,
2265 (void *)&media_info
, &len
);
2267 if (linkstate
== nmc_connected
)
2268 ifmr
->ifm_status
|= IFM_ACTIVE
;
2270 switch (media_info
) {
2272 ifmr
->ifm_active
|= IFM_10_T
;
2275 ifmr
->ifm_active
|= IFM_100_TX
;
2278 ifmr
->ifm_active
|= IFM_1000_T
;
2281 device_printf(sc
->ndis_dev
, "unknown speed: %d\n", media_info
);
2287 ndis_set_cipher(struct ndis_softc
*sc
, int cipher
)
2289 struct ieee80211com
*ic
= &sc
->ndis_ic
;
2295 if (cipher
== WPA_CSE_WEP40
|| cipher
== WPA_CSE_WEP104
) {
2296 if (!(ic
->ic_cryptocaps
& IEEE80211_CRYPTO_WEP
))
2298 arg
= NDIS_80211_WEPSTAT_ENC1ENABLED
;
2301 if (cipher
== WPA_CSE_TKIP
) {
2302 if (!(ic
->ic_cryptocaps
& IEEE80211_CRYPTO_TKIP
))
2304 arg
= NDIS_80211_WEPSTAT_ENC2ENABLED
;
2307 if (cipher
== WPA_CSE_CCMP
) {
2308 if (!(ic
->ic_cryptocaps
& IEEE80211_CRYPTO_AES_CCM
))
2310 arg
= NDIS_80211_WEPSTAT_ENC3ENABLED
;
2313 DPRINTF(("Setting cipher to %d\n", arg
));
2315 rval
= ndis_set_info(sc
, OID_802_11_ENCRYPTION_STATUS
, &arg
, &len
);
2320 /* Check that the cipher was set correctly. */
2323 rval
= ndis_get_info(sc
, OID_802_11_ENCRYPTION_STATUS
, &arg
, &len
);
2325 if (rval
!= 0 || arg
!= save
)
2332 * WPA is hairy to set up. Do the work in a separate routine
2333 * so we don't clutter the setstate function too much.
2334 * Important yet undocumented fact: first we have to set the
2335 * authentication mode, _then_ we enable the ciphers. If one
2336 * of the WPA authentication modes isn't enabled, the driver
2337 * might not permit the TKIP or AES ciphers to be selected.
2340 ndis_set_wpa(struct ndis_softc
*sc
, void *ie
, int ielen
)
2342 struct ieee80211_ie_wpa
*w
;
2349 * Apparently, the only way for us to know what ciphers
2350 * and key management/authentication mode to use is for
2351 * us to inspect the optional information element (IE)
2352 * stored in the 802.11 state machine. This IE should be
2353 * supplied by the WPA supplicant.
2356 w
= (struct ieee80211_ie_wpa
*)ie
;
2358 /* Check for the right kind of IE. */
2359 if (w
->wpa_id
!= IEEE80211_ELEMID_VENDOR
) {
2360 DPRINTF(("Incorrect IE type %d\n", w
->wpa_id
));
2364 /* Skip over the ucast cipher OIDs. */
2365 pos
= (char *)&w
->wpa_uciphers
[0];
2366 pos
+= w
->wpa_uciphercnt
* sizeof(struct ndis_ie
);
2368 /* Skip over the authmode count. */
2369 pos
+= sizeof(u_int16_t
);
2372 * Check for the authentication modes. I'm
2373 * pretty sure there's only supposed to be one.
2376 n
= (struct ndis_ie
*)pos
;
2377 if (n
->ni_val
== WPA_ASE_NONE
)
2378 arg
= NDIS_80211_AUTHMODE_WPANONE
;
2380 if (n
->ni_val
== WPA_ASE_8021X_UNSPEC
)
2381 arg
= NDIS_80211_AUTHMODE_WPA
;
2383 if (n
->ni_val
== WPA_ASE_8021X_PSK
)
2384 arg
= NDIS_80211_AUTHMODE_WPAPSK
;
2386 DPRINTF(("Setting WPA auth mode to %d\n", arg
));
2388 if (ndis_set_info(sc
, OID_802_11_AUTHENTICATION_MODE
, &arg
, &i
))
2391 ndis_get_info(sc
, OID_802_11_AUTHENTICATION_MODE
, &arg
, &i
);
2393 /* Now configure the desired ciphers. */
2395 /* First, set up the multicast group cipher. */
2396 n
= (struct ndis_ie
*)&w
->wpa_mcipher
[0];
2398 if (ndis_set_cipher(sc
, n
->ni_val
))
2401 /* Now start looking around for the unicast ciphers. */
2402 pos
= (char *)&w
->wpa_uciphers
[0];
2403 n
= (struct ndis_ie
*)pos
;
2405 for (i
= 0; i
< w
->wpa_uciphercnt
; i
++) {
2406 if (ndis_set_cipher(sc
, n
->ni_val
))
2415 ndis_media_status(struct ifnet
*ifp
, struct ifmediareq
*imr
)
2417 struct ieee80211vap
*vap
= ifp
->if_softc
;
2418 struct ndis_softc
*sc
= vap
->iv_ic
->ic_softc
;
2422 if (!NDIS_INITIALIZED(sc
))
2425 len
= sizeof(txrate
);
2426 if (ndis_get_info(sc
, OID_GEN_LINK_SPEED
, &txrate
, &len
) == 0)
2427 vap
->iv_bss
->ni_txrate
= txrate
/ 5000;
2428 ieee80211_media_status(ifp
, imr
);
2432 ndis_setstate_80211(struct ndis_softc
*sc
)
2434 struct ieee80211com
*ic
= &sc
->ndis_ic
;
2435 struct ieee80211vap
*vap
= TAILQ_FIRST(&ic
->ic_vaps
);
2436 ndis_80211_macaddr bssid
;
2437 ndis_80211_config config
;
2441 if (!NDIS_INITIALIZED(sc
)) {
2442 DPRINTF(("%s: NDIS not initialized\n", __func__
));
2446 /* Disassociate and turn off radio. */
2449 ndis_set_info(sc
, OID_802_11_DISASSOCIATE
, &arg
, &len
);
2451 /* Set network infrastructure mode. */
2454 if (ic
->ic_opmode
== IEEE80211_M_IBSS
)
2455 arg
= NDIS_80211_NET_INFRA_IBSS
;
2457 arg
= NDIS_80211_NET_INFRA_BSS
;
2459 rval
= ndis_set_info(sc
, OID_802_11_INFRASTRUCTURE_MODE
, &arg
, &len
);
2462 device_printf (sc
->ndis_dev
, "set infra failed: %d\n", rval
);
2464 /* Set power management */
2466 if (vap
->iv_flags
& IEEE80211_F_PMGTON
)
2467 arg
= NDIS_80211_POWERMODE_FAST_PSP
;
2469 arg
= NDIS_80211_POWERMODE_CAM
;
2470 ndis_set_info(sc
, OID_802_11_POWER_MODE
, &arg
, &len
);
2473 if ((ic
->ic_caps
& IEEE80211_C_TXPMGT
) &&
2474 ic
->ic_txpowlimit
< nitems(dBm2mW
)) {
2475 arg
= dBm2mW
[ic
->ic_txpowlimit
];
2477 ndis_set_info(sc
, OID_802_11_TX_POWER_LEVEL
, &arg
, &len
);
2481 * Default encryption mode to off, authentication
2482 * to open and privacy to 'accept everything.'
2485 arg
= NDIS_80211_WEPSTAT_DISABLED
;
2486 ndis_set_info(sc
, OID_802_11_ENCRYPTION_STATUS
, &arg
, &len
);
2489 arg
= NDIS_80211_AUTHMODE_OPEN
;
2490 ndis_set_info(sc
, OID_802_11_AUTHENTICATION_MODE
, &arg
, &len
);
2493 * Note that OID_802_11_PRIVACY_FILTER is optional:
2494 * not all drivers implement it.
2497 arg
= NDIS_80211_PRIVFILT_8021XWEP
;
2498 ndis_set_info(sc
, OID_802_11_PRIVACY_FILTER
, &arg
, &len
);
2500 len
= sizeof(config
);
2501 bzero((char *)&config
, len
);
2502 config
.nc_length
= len
;
2503 config
.nc_fhconfig
.ncf_length
= sizeof(ndis_80211_config_fh
);
2504 rval
= ndis_get_info(sc
, OID_802_11_CONFIGURATION
, &config
, &len
);
2507 * Some drivers expect us to initialize these values, so
2508 * provide some defaults.
2511 if (config
.nc_beaconperiod
== 0)
2512 config
.nc_beaconperiod
= 100;
2513 if (config
.nc_atimwin
== 0)
2514 config
.nc_atimwin
= 100;
2515 if (config
.nc_fhconfig
.ncf_dwelltime
== 0)
2516 config
.nc_fhconfig
.ncf_dwelltime
= 200;
2517 if (rval
== 0 && ic
->ic_bsschan
!= IEEE80211_CHAN_ANYC
) {
2520 chan
= ieee80211_chan2ieee(ic
, ic
->ic_bsschan
);
2521 chanflag
= config
.nc_dsconfig
> 2500000 ? IEEE80211_CHAN_2GHZ
:
2522 IEEE80211_CHAN_5GHZ
;
2523 if (chan
!= ieee80211_mhz2ieee(config
.nc_dsconfig
/ 1000, 0)) {
2524 config
.nc_dsconfig
=
2525 ic
->ic_bsschan
->ic_freq
* 1000;
2526 len
= sizeof(config
);
2527 config
.nc_length
= len
;
2528 config
.nc_fhconfig
.ncf_length
=
2529 sizeof(ndis_80211_config_fh
);
2530 DPRINTF(("Setting channel to %ukHz\n", config
.nc_dsconfig
));
2531 rval
= ndis_set_info(sc
, OID_802_11_CONFIGURATION
,
2534 device_printf(sc
->ndis_dev
, "couldn't change "
2535 "DS config to %ukHz: %d\n",
2536 config
.nc_dsconfig
, rval
);
2539 device_printf(sc
->ndis_dev
, "couldn't retrieve "
2540 "channel info: %d\n", rval
);
2542 /* Set the BSSID to our value so the driver doesn't associate */
2543 len
= IEEE80211_ADDR_LEN
;
2544 bcopy(vap
->iv_myaddr
, bssid
, len
);
2545 #if defined(__DragonFly__)
2546 DPRINTF(("Setting BSSID to %s\n", ether_sprintf(bssid
)));
2548 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid
, ":"));
2550 rval
= ndis_set_info(sc
, OID_802_11_BSSID
, &bssid
, &len
);
2552 device_printf(sc
->ndis_dev
,
2553 "setting BSSID failed: %d\n", rval
);
2557 ndis_auth_and_assoc(struct ndis_softc
*sc
, struct ieee80211vap
*vap
)
2559 struct ieee80211_node
*ni
= vap
->iv_bss
;
2560 ndis_80211_ssid ssid
;
2561 ndis_80211_macaddr bssid
;
2563 int i
, rval
= 0, len
, error
;
2566 if (!NDIS_INITIALIZED(sc
)) {
2567 DPRINTF(("%s: NDIS not initialized\n", __func__
));
2572 ndis_setstate_80211(sc
);
2574 /* Set network infrastructure mode. */
2577 if (vap
->iv_opmode
== IEEE80211_M_IBSS
)
2578 arg
= NDIS_80211_NET_INFRA_IBSS
;
2580 arg
= NDIS_80211_NET_INFRA_BSS
;
2582 rval
= ndis_set_info(sc
, OID_802_11_INFRASTRUCTURE_MODE
, &arg
, &len
);
2585 device_printf (sc
->ndis_dev
, "set infra failed: %d\n", rval
);
2587 /* Set RTS threshold */
2590 arg
= vap
->iv_rtsthreshold
;
2591 ndis_set_info(sc
, OID_802_11_RTS_THRESHOLD
, &arg
, &len
);
2593 /* Set fragmentation threshold */
2596 arg
= vap
->iv_fragthreshold
;
2597 ndis_set_info(sc
, OID_802_11_FRAGMENTATION_THRESHOLD
, &arg
, &len
);
2601 if (vap
->iv_flags
& IEEE80211_F_PRIVACY
&&
2602 !(vap
->iv_flags
& IEEE80211_F_WPA
)) {
2605 if (ni
->ni_authmode
== IEEE80211_AUTH_SHARED
) {
2607 arg
= NDIS_80211_AUTHMODE_SHARED
;
2608 DPRINTF(("Setting shared auth\n"));
2609 ndis_set_info(sc
, OID_802_11_AUTHENTICATION_MODE
,
2612 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
2613 if (vap
->iv_nw_keys
[i
].wk_keylen
) {
2614 if (vap
->iv_nw_keys
[i
].wk_cipher
->ic_cipher
!=
2615 IEEE80211_CIPHER_WEP
)
2617 bzero((char *)&wep
, sizeof(wep
));
2618 wep
.nw_keylen
= vap
->iv_nw_keys
[i
].wk_keylen
;
2621 * 5, 13 and 16 are the only valid
2622 * key lengths. Anything in between
2623 * will be zero padded out to the
2624 * next highest boundary.
2626 if (vap
->iv_nw_keys
[i
].wk_keylen
< 5)
2628 else if (vap
->iv_nw_keys
[i
].wk_keylen
> 5 &&
2629 vap
->iv_nw_keys
[i
].wk_keylen
< 13)
2631 else if (vap
->iv_nw_keys
[i
].wk_keylen
> 13 &&
2632 vap
->iv_nw_keys
[i
].wk_keylen
< 16)
2636 wep
.nw_length
= (sizeof(uint32_t) * 3)
2638 if (i
== vap
->iv_def_txkey
)
2639 wep
.nw_keyidx
|= NDIS_80211_WEPKEY_TX
;
2640 bcopy(vap
->iv_nw_keys
[i
].wk_key
,
2641 wep
.nw_keydata
, wep
.nw_length
);
2643 DPRINTF(("Setting WEP key %d\n", i
));
2644 rval
= ndis_set_info(sc
,
2645 OID_802_11_ADD_WEP
, &wep
, &len
);
2647 device_printf(sc
->ndis_dev
,
2648 "set wepkey failed: %d\n", rval
);
2653 DPRINTF(("Setting WEP on\n"));
2654 arg
= NDIS_80211_WEPSTAT_ENABLED
;
2656 rval
= ndis_set_info(sc
,
2657 OID_802_11_WEP_STATUS
, &arg
, &len
);
2659 device_printf(sc
->ndis_dev
,
2660 "enable WEP failed: %d\n", rval
);
2661 if (vap
->iv_flags
& IEEE80211_F_DROPUNENC
)
2662 arg
= NDIS_80211_PRIVFILT_8021XWEP
;
2664 arg
= NDIS_80211_PRIVFILT_ACCEPTALL
;
2668 OID_802_11_PRIVACY_FILTER
, &arg
, &len
);
2673 if ((vap
->iv_flags
& IEEE80211_F_WPA
) &&
2674 vap
->iv_appie_assocreq
!= NULL
) {
2675 struct ieee80211_appie
*ie
= vap
->iv_appie_assocreq
;
2676 error
= ndis_set_wpa(sc
, ie
->ie_data
, ie
->ie_len
);
2678 device_printf(sc
->ndis_dev
, "WPA setup failed\n");
2682 /* Set network type. */
2686 switch (vap
->iv_curmode
) {
2687 case IEEE80211_MODE_11A
:
2688 arg
= NDIS_80211_NETTYPE_11OFDM5
;
2690 case IEEE80211_MODE_11B
:
2691 arg
= NDIS_80211_NETTYPE_11DS
;
2693 case IEEE80211_MODE_11G
:
2694 arg
= NDIS_80211_NETTYPE_11OFDM24
;
2697 device_printf(sc
->ndis_dev
, "unknown mode: %d\n",
2702 DPRINTF(("Setting network type to %d\n", arg
));
2704 rval
= ndis_set_info(sc
, OID_802_11_NETWORK_TYPE_IN_USE
,
2707 device_printf(sc
->ndis_dev
,
2708 "set nettype failed: %d\n", rval
);
2713 * If the user selected a specific BSSID, try
2714 * to use that one. This is useful in the case where
2715 * there are several APs in range with the same network
2716 * name. To delete the BSSID, we use the broadcast
2717 * address as the BSSID.
2718 * Note that some drivers seem to allow setting a BSSID
2719 * in ad-hoc mode, which has the effect of forcing the
2720 * NIC to create an ad-hoc cell with a specific BSSID,
2721 * instead of a randomly chosen one. However, the net80211
2722 * code makes the assumtion that the BSSID setting is invalid
2723 * when you're in ad-hoc mode, so we don't allow that here.
2726 len
= IEEE80211_ADDR_LEN
;
2727 if (vap
->iv_flags
& IEEE80211_F_DESBSSID
&&
2728 vap
->iv_opmode
!= IEEE80211_M_IBSS
)
2729 bcopy(ni
->ni_bssid
, bssid
, len
);
2731 bcopy(ieee80211broadcastaddr
, bssid
, len
);
2733 #if defined(__DragonFly__)
2734 DPRINTF(("Setting BSSID to %s\n", ether_sprintf(bssid
)));
2736 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid
, ":"));
2738 rval
= ndis_set_info(sc
, OID_802_11_BSSID
, &bssid
, &len
);
2740 device_printf(sc
->ndis_dev
,
2741 "setting BSSID failed: %d\n", rval
);
2743 /* Set SSID -- always do this last. */
2746 if (ndis_debug
> 0) {
2747 kprintf("Setting ESSID to ");
2748 ieee80211_print_essid(ni
->ni_essid
, ni
->ni_esslen
);
2754 bzero((char *)&ssid
, len
);
2755 ssid
.ns_ssidlen
= ni
->ni_esslen
;
2756 if (ssid
.ns_ssidlen
== 0) {
2757 ssid
.ns_ssidlen
= 1;
2759 bcopy(ni
->ni_essid
, ssid
.ns_ssid
, ssid
.ns_ssidlen
);
2761 rval
= ndis_set_info(sc
, OID_802_11_SSID
, &ssid
, &len
);
2764 device_printf (sc
->ndis_dev
, "set ssid failed: %d\n", rval
);
2770 ndis_get_bssid_list(struct ndis_softc
*sc
, ndis_80211_bssid_list_ex
**bl
)
2774 len
= sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex
) * 16);
2775 *bl
= kmalloc(len
, M_DEVBUF
, M_INTWAIT
| M_ZERO
);
2779 error
= ndis_get_info(sc
, OID_802_11_BSSID_LIST
, *bl
, &len
);
2780 if (error
== ENOSPC
) {
2781 kfree(*bl
, M_DEVBUF
);
2782 *bl
= kmalloc(len
, M_DEVBUF
, M_INTWAIT
| M_ZERO
);
2786 error
= ndis_get_info(sc
, OID_802_11_BSSID_LIST
, *bl
, &len
);
2789 DPRINTF(("%s: failed to read\n", __func__
));
2790 kfree(*bl
, M_DEVBUF
);
2798 ndis_get_assoc(struct ndis_softc
*sc
, ndis_wlan_bssid_ex
**assoc
)
2800 struct ieee80211com
*ic
= &sc
->ndis_ic
;
2801 struct ieee80211vap
*vap
;
2802 struct ieee80211_node
*ni
;
2803 ndis_80211_bssid_list_ex
*bl
;
2804 ndis_wlan_bssid_ex
*bs
;
2805 ndis_80211_macaddr bssid
;
2811 len
= sizeof(bssid
);
2812 error
= ndis_get_info(sc
, OID_802_11_BSSID
, &bssid
, &len
);
2814 device_printf(sc
->ndis_dev
, "failed to get bssid\n");
2818 vap
= TAILQ_FIRST(&ic
->ic_vaps
);
2821 error
= ndis_get_bssid_list(sc
, &bl
);
2825 bs
= (ndis_wlan_bssid_ex
*)&bl
->nblx_bssid
[0];
2826 for (i
= 0; i
< bl
->nblx_items
; i
++) {
2827 if (bcmp(bs
->nwbx_macaddr
, bssid
, sizeof(bssid
)) == 0) {
2828 *assoc
= kmalloc(bs
->nwbx_len
, M_TEMP
, M_INTWAIT
);
2829 if (*assoc
== NULL
) {
2833 bcopy((char *)bs
, (char *)*assoc
, bs
->nwbx_len
);
2835 if (ic
->ic_opmode
== IEEE80211_M_STA
)
2836 ni
->ni_associd
= 1 | 0xc000; /* fake associd */
2839 bs
= (ndis_wlan_bssid_ex
*)((char *)bs
+ bs
->nwbx_len
);
2847 ndis_getstate_80211(struct ndis_softc
*sc
)
2849 struct ieee80211com
*ic
= &sc
->ndis_ic
;
2850 struct ieee80211vap
*vap
= TAILQ_FIRST(&ic
->ic_vaps
);
2851 struct ieee80211_node
*ni
= vap
->iv_bss
;
2852 ndis_wlan_bssid_ex
*bs
;
2853 int rval
, len
, i
= 0;
2857 if (!NDIS_INITIALIZED(sc
))
2860 if ((rval
= ndis_get_assoc(sc
, &bs
)) != 0)
2863 /* We're associated, retrieve info on the current bssid. */
2864 ic
->ic_curmode
= ndis_nettype_mode(bs
->nwbx_nettype
);
2865 chanflag
= ndis_nettype_chan(bs
->nwbx_nettype
);
2866 IEEE80211_ADDR_COPY(ni
->ni_bssid
, bs
->nwbx_macaddr
);
2868 /* Get SSID from current association info. */
2869 bcopy(bs
->nwbx_ssid
.ns_ssid
, ni
->ni_essid
,
2870 bs
->nwbx_ssid
.ns_ssidlen
);
2871 ni
->ni_esslen
= bs
->nwbx_ssid
.ns_ssidlen
;
2873 if (ic
->ic_caps
& IEEE80211_C_PMGT
) {
2875 rval
= ndis_get_info(sc
, OID_802_11_POWER_MODE
, &arg
, &len
);
2878 device_printf(sc
->ndis_dev
,
2879 "get power mode failed: %d\n", rval
);
2880 if (arg
== NDIS_80211_POWERMODE_CAM
)
2881 vap
->iv_flags
&= ~IEEE80211_F_PMGTON
;
2883 vap
->iv_flags
|= IEEE80211_F_PMGTON
;
2887 if (ic
->ic_caps
& IEEE80211_C_TXPMGT
) {
2889 ndis_get_info(sc
, OID_802_11_TX_POWER_LEVEL
, &arg
, &len
);
2890 for (i
= 0; i
< nitems(dBm2mW
); i
++)
2891 if (dBm2mW
[i
] >= arg
)
2893 ic
->ic_txpowlimit
= i
;
2897 * Use the current association information to reflect
2898 * what channel we're on.
2900 ic
->ic_curchan
= ieee80211_find_channel(ic
,
2901 bs
->nwbx_config
.nc_dsconfig
/ 1000, chanflag
);
2902 if (ic
->ic_curchan
== NULL
)
2903 ic
->ic_curchan
= &ic
->ic_channels
[0];
2904 ni
->ni_chan
= ic
->ic_curchan
;
2905 ic
->ic_bsschan
= ic
->ic_curchan
;
2910 * Determine current authentication mode.
2913 rval
= ndis_get_info(sc
, OID_802_11_AUTHENTICATION_MODE
, &arg
, &len
);
2915 device_printf(sc
->ndis_dev
,
2916 "get authmode status failed: %d\n", rval
);
2918 vap
->iv_flags
&= ~IEEE80211_F_WPA
;
2920 case NDIS_80211_AUTHMODE_OPEN
:
2921 ni
->ni_authmode
= IEEE80211_AUTH_OPEN
;
2923 case NDIS_80211_AUTHMODE_SHARED
:
2924 ni
->ni_authmode
= IEEE80211_AUTH_SHARED
;
2926 case NDIS_80211_AUTHMODE_AUTO
:
2927 ni
->ni_authmode
= IEEE80211_AUTH_AUTO
;
2929 case NDIS_80211_AUTHMODE_WPA
:
2930 case NDIS_80211_AUTHMODE_WPAPSK
:
2931 case NDIS_80211_AUTHMODE_WPANONE
:
2932 ni
->ni_authmode
= IEEE80211_AUTH_WPA
;
2933 vap
->iv_flags
|= IEEE80211_F_WPA1
;
2935 case NDIS_80211_AUTHMODE_WPA2
:
2936 case NDIS_80211_AUTHMODE_WPA2PSK
:
2937 ni
->ni_authmode
= IEEE80211_AUTH_WPA
;
2938 vap
->iv_flags
|= IEEE80211_F_WPA2
;
2941 ni
->ni_authmode
= IEEE80211_AUTH_NONE
;
2947 rval
= ndis_get_info(sc
, OID_802_11_WEP_STATUS
, &arg
, &len
);
2950 device_printf(sc
->ndis_dev
,
2951 "get wep status failed: %d\n", rval
);
2953 if (arg
== NDIS_80211_WEPSTAT_ENABLED
)
2954 vap
->iv_flags
|= IEEE80211_F_PRIVACY
|IEEE80211_F_DROPUNENC
;
2956 vap
->iv_flags
&= ~(IEEE80211_F_PRIVACY
|IEEE80211_F_DROPUNENC
);
2960 ndis_ioctl(struct ifnet
*ifp
, u_long command
, caddr_t data
, struct ucred
*cr
)
2962 struct ndis_softc
*sc
= ifp
->if_softc
;
2963 struct ifreq
*ifr
= (struct ifreq
*) data
;
2970 if (ifp
->if_flags
& IFF_UP
) {
2971 if (sc
->ndis_running
&&
2972 ifp
->if_flags
& IFF_PROMISC
&&
2973 !(sc
->ndis_if_flags
& IFF_PROMISC
)) {
2975 NDIS_PACKET_TYPE_PROMISCUOUS
;
2976 i
= sizeof(sc
->ndis_filter
);
2977 error
= ndis_set_info(sc
,
2978 OID_GEN_CURRENT_PACKET_FILTER
,
2979 &sc
->ndis_filter
, &i
);
2980 } else if (sc
->ndis_running
&&
2981 !(ifp
->if_flags
& IFF_PROMISC
) &&
2982 sc
->ndis_if_flags
& IFF_PROMISC
) {
2984 ~NDIS_PACKET_TYPE_PROMISCUOUS
;
2985 i
= sizeof(sc
->ndis_filter
);
2986 error
= ndis_set_info(sc
,
2987 OID_GEN_CURRENT_PACKET_FILTER
,
2988 &sc
->ndis_filter
, &i
);
2992 if (sc
->ndis_running
)
2995 sc
->ndis_if_flags
= ifp
->if_flags
;
3005 error
= ifmedia_ioctl(ifp
, ifr
, &sc
->ifmedia
, command
);
3008 ifp
->if_capenable
= ifr
->ifr_reqcap
;
3009 if (ifp
->if_capenable
& IFCAP_TXCSUM
)
3010 ifp
->if_hwassist
= sc
->ndis_hwassist
;
3012 ifp
->if_hwassist
= 0;
3013 ndis_set_offload(sc
);
3016 error
= ether_ioctl(ifp
, command
, data
);
3020 /*NDIS_UNLOCK(sc);*/
3026 ndis_80211ioctl(struct ieee80211com
*ic
, u_long cmd
, void *data
)
3028 struct ndis_softc
*sc
= ic
->ic_softc
;
3029 struct ifreq
*ifr
= data
;
3030 struct ndis_oid_data oid
;
3031 struct ndis_evt evt
;
3032 void *oidbuf
= NULL
;
3035 if ((error
= priv_check(curthread
, PRIV_DRIVER
)) != 0)
3041 error
= copyin(ifr
->ifr_data
, &oid
, sizeof(oid
));
3044 oidbuf
= kmalloc(oid
.len
, M_TEMP
, M_WAITOK
| M_ZERO
);
3045 error
= copyin((char *)ifr
->ifr_data
+ sizeof(oid
), oidbuf
, oid
.len
);
3049 kfree(oidbuf
, M_TEMP
);
3055 error
= ndis_get_info(sc
, oid
.oid
, oidbuf
, &oid
.len
);
3058 error
= ndis_set_info(sc
, oid
.oid
, oidbuf
, &oid
.len
);
3060 case SIOCGPRIVATE_0
:
3062 if (sc
->ndis_evt
[sc
->ndis_evtcidx
].ne_sts
== 0) {
3067 error
= copyin(ifr
->ifr_data
, &evt
, sizeof(evt
));
3072 if (evt
.ne_len
< sc
->ndis_evt
[sc
->ndis_evtcidx
].ne_len
) {
3077 error
= copyout(&sc
->ndis_evt
[sc
->ndis_evtcidx
],
3078 ifr
->ifr_data
, sizeof(uint32_t) * 2);
3083 if (sc
->ndis_evt
[sc
->ndis_evtcidx
].ne_len
) {
3084 error
= copyout(sc
->ndis_evt
[sc
->ndis_evtcidx
].ne_buf
,
3085 (caddr_t
)ifr
->ifr_data
+ (sizeof(uint32_t) * 2),
3086 sc
->ndis_evt
[sc
->ndis_evtcidx
].ne_len
);
3091 kfree(sc
->ndis_evt
[sc
->ndis_evtcidx
].ne_buf
, M_TEMP
);
3092 sc
->ndis_evt
[sc
->ndis_evtcidx
].ne_buf
= NULL
;
3094 sc
->ndis_evt
[sc
->ndis_evtcidx
].ne_len
= 0;
3095 sc
->ndis_evt
[sc
->ndis_evtcidx
].ne_sts
= 0;
3096 NDIS_EVTINC(sc
->ndis_evtcidx
);
3107 error
= copyout(&oid
, ifr
->ifr_data
, sizeof(oid
));
3110 error
= copyout(oidbuf
, (char *)ifr
->ifr_data
+ sizeof(oid
), oid
.len
);
3113 kfree(oidbuf
, M_TEMP
);
3119 ndis_del_key(struct ieee80211vap
*vap
, const struct ieee80211_key
*key
)
3121 struct ndis_softc
*sc
= vap
->iv_ic
->ic_softc
;
3122 ndis_80211_key rkey
;
3125 bzero((char *)&rkey
, sizeof(rkey
));
3129 rkey
.nk_keyidx
= key
->wk_keyix
;
3131 bcopy(vap
->iv_ifp
->if_broadcastaddr
,
3132 rkey
.nk_bssid
, IEEE80211_ADDR_LEN
);
3134 error
= ndis_set_info(sc
, OID_802_11_REMOVE_KEY
, &rkey
, &len
);
3143 * In theory this could be called for any key, but we'll
3144 * only use it for WPA TKIP or AES keys. These need to be
3145 * set after initial authentication with the AP.
3148 ndis_add_key(struct ieee80211vap
*vap
, const struct ieee80211_key
*key
)
3150 struct ndis_softc
*sc
= vap
->iv_ic
->ic_softc
;
3151 ndis_80211_key rkey
;
3154 switch (key
->wk_cipher
->ic_cipher
) {
3155 case IEEE80211_CIPHER_TKIP
:
3157 len
= sizeof(ndis_80211_key
);
3158 bzero((char *)&rkey
, sizeof(rkey
));
3161 rkey
.nk_keylen
= key
->wk_keylen
;
3163 if (key
->wk_flags
& IEEE80211_KEY_SWMIC
)
3164 rkey
.nk_keylen
+= 16;
3166 /* key index - gets weird in NDIS */
3168 if (key
->wk_keyix
!= IEEE80211_KEYIX_NONE
)
3169 rkey
.nk_keyidx
= key
->wk_keyix
;
3173 if (key
->wk_flags
& IEEE80211_KEY_XMIT
)
3174 rkey
.nk_keyidx
|= 1 << 31;
3176 if (key
->wk_flags
& IEEE80211_KEY_GROUP
) {
3177 bcopy(ieee80211broadcastaddr
,
3178 rkey
.nk_bssid
, IEEE80211_ADDR_LEN
);
3180 bcopy(vap
->iv_bss
->ni_bssid
,
3181 rkey
.nk_bssid
, IEEE80211_ADDR_LEN
);
3183 rkey
.nk_keyidx
|= 1 << 30;
3186 /* need to set bit 29 based on keyrsc */
3187 rkey
.nk_keyrsc
= key
->wk_keyrsc
[0]; /* XXX need tid */
3190 rkey
.nk_keyidx
|= 1 << 29;
3192 if (key
->wk_flags
& IEEE80211_KEY_SWMIC
) {
3193 bcopy(key
->wk_key
, rkey
.nk_keydata
, 16);
3194 bcopy(key
->wk_key
+ 24, rkey
.nk_keydata
+ 16, 8);
3195 bcopy(key
->wk_key
+ 16, rkey
.nk_keydata
+ 24, 8);
3197 bcopy(key
->wk_key
, rkey
.nk_keydata
, key
->wk_keylen
);
3199 error
= ndis_set_info(sc
, OID_802_11_ADD_KEY
, &rkey
, &len
);
3201 case IEEE80211_CIPHER_WEP
:
3205 * I don't know how to set up keys for the AES
3206 * cipher yet. Is it the same as TKIP?
3208 case IEEE80211_CIPHER_AES_CCM
:
3214 /* We need to return 1 for success, 0 for failure. */
3223 ndis_resettask(device_object
*d
, void *arg
)
3225 struct ndis_softc
*sc
;
3232 * Stop the adapter and free any mbufs allocated to the
3236 ndis_stop(struct ndis_softc
*sc
)
3240 callout_drain(&sc
->ndis_stat_callout
);
3243 sc
->ndis_tx_timer
= 0;
3245 if (!sc
->ndis_80211
) {
3246 #if defined(__DragonFly__)
3247 sc
->ifp
->if_flags
&= ~IFF_RUNNING
;
3248 ifq_clr_oactive(&sc
->ifp
->if_snd
);
3250 sc
->ifp
->if_drv_flags
&= ~(IFF_DRV_RUNNING
| IFF_DRV_OACTIVE
);
3253 sc
->ndis_running
= 0;
3256 if (sc
->ndis_iftype
!= PNPBus
||
3257 (sc
->ndis_iftype
== PNPBus
&&
3258 !(sc
->ndisusb_status
& NDISUSB_STATUS_DETACH
) &&
3263 for (i
= 0; i
< NDIS_EVENTS
; i
++) {
3264 if (sc
->ndis_evt
[i
].ne_sts
&& sc
->ndis_evt
[i
].ne_buf
!= NULL
) {
3265 kfree(sc
->ndis_evt
[i
].ne_buf
, M_TEMP
);
3266 sc
->ndis_evt
[i
].ne_buf
= NULL
;
3268 sc
->ndis_evt
[i
].ne_sts
= 0;
3269 sc
->ndis_evt
[i
].ne_len
= 0;
3271 sc
->ndis_evtcidx
= 0;
3272 sc
->ndis_evtpidx
= 0;
3277 * Stop all chip I/O so that the kernel's probe routines don't
3278 * get confused by errant DMAs when rebooting.
3281 ndis_shutdown(device_t dev
)
3283 struct ndis_softc
*sc
;
3285 sc
= device_get_softc(dev
);
3290 ndis_newstate(struct ieee80211vap
*vap
, enum ieee80211_state nstate
, int arg
)
3292 struct ndis_vap
*nvp
= NDIS_VAP(vap
);
3293 struct ieee80211com
*ic
= vap
->iv_ic
;
3294 struct ndis_softc
*sc
= ic
->ic_softc
;
3295 enum ieee80211_state ostate
;
3297 DPRINTF(("%s: %s -> %s\n", __func__
,
3298 ieee80211_state_name
[vap
->iv_state
],
3299 ieee80211_state_name
[nstate
]));
3301 ostate
= vap
->iv_state
;
3302 vap
->iv_state
= nstate
;
3305 /* pass on to net80211 */
3306 case IEEE80211_S_INIT
:
3307 case IEEE80211_S_SCAN
:
3308 return nvp
->newstate(vap
, nstate
, arg
);
3309 case IEEE80211_S_ASSOC
:
3310 if (ostate
!= IEEE80211_S_AUTH
) {
3311 IEEE80211_UNLOCK(ic
);
3312 ndis_auth_and_assoc(sc
, vap
);
3316 case IEEE80211_S_AUTH
:
3317 IEEE80211_UNLOCK(ic
);
3318 ndis_auth_and_assoc(sc
, vap
);
3319 if (vap
->iv_state
== IEEE80211_S_AUTH
) /* XXX */
3320 ieee80211_new_state(vap
, IEEE80211_S_ASSOC
, 0);
3330 ndis_scan(void *arg
)
3332 struct ieee80211vap
*vap
= arg
;
3334 ieee80211_scan_done(vap
);
3338 ndis_scan_results(struct ndis_softc
*sc
)
3340 struct ieee80211com
*ic
= &sc
->ndis_ic
;
3341 struct ieee80211vap
*vap
= TAILQ_FIRST(&ic
->ic_vaps
);
3342 ndis_80211_bssid_list_ex
*bl
;
3343 ndis_wlan_bssid_ex
*wb
;
3344 struct ieee80211_scanparams sp
;
3345 struct ieee80211_frame wh
;
3346 struct ieee80211_channel
*saved_chan
;
3348 int rssi
, noise
, freq
, chanflag
;
3349 uint8_t ssid
[2+IEEE80211_NWID_LEN
];
3350 uint8_t rates
[2+IEEE80211_RATE_MAXSIZE
];
3351 uint8_t *frm
, *efrm
;
3353 saved_chan
= ic
->ic_curchan
;
3356 if (ndis_get_bssid_list(sc
, &bl
))
3359 DPRINTF(("%s: %d results\n", __func__
, bl
->nblx_items
));
3360 wb
= &bl
->nblx_bssid
[0];
3361 for (i
= 0; i
< bl
->nblx_items
; i
++) {
3362 memset(&sp
, 0, sizeof(sp
));
3364 memcpy(wh
.i_addr2
, wb
->nwbx_macaddr
, sizeof(wh
.i_addr2
));
3365 memcpy(wh
.i_addr3
, wb
->nwbx_macaddr
, sizeof(wh
.i_addr3
));
3366 rssi
= 100 * (wb
->nwbx_rssi
- noise
) / (-32 - noise
);
3367 rssi
= max(0, min(rssi
, 100)); /* limit 0 <= rssi <= 100 */
3368 if (wb
->nwbx_privacy
)
3369 sp
.capinfo
|= IEEE80211_CAPINFO_PRIVACY
;
3370 sp
.bintval
= wb
->nwbx_config
.nc_beaconperiod
;
3371 switch (wb
->nwbx_netinfra
) {
3372 case NDIS_80211_NET_INFRA_IBSS
:
3373 sp
.capinfo
|= IEEE80211_CAPINFO_IBSS
;
3375 case NDIS_80211_NET_INFRA_BSS
:
3376 sp
.capinfo
|= IEEE80211_CAPINFO_ESS
;
3379 sp
.rates
= &rates
[0];
3380 for (j
= 0; j
< IEEE80211_RATE_MAXSIZE
; j
++) {
3381 /* XXX - check units */
3382 if (wb
->nwbx_supportedrates
[j
] == 0)
3385 wb
->nwbx_supportedrates
[j
] & 0x7f;
3388 sp
.ssid
= (uint8_t *)&ssid
[0];
3389 memcpy(sp
.ssid
+ 2, &wb
->nwbx_ssid
.ns_ssid
,
3390 wb
->nwbx_ssid
.ns_ssidlen
);
3391 sp
.ssid
[1] = wb
->nwbx_ssid
.ns_ssidlen
;
3393 chanflag
= ndis_nettype_chan(wb
->nwbx_nettype
);
3394 freq
= wb
->nwbx_config
.nc_dsconfig
/ 1000;
3395 sp
.chan
= sp
.bchan
= ieee80211_mhz2ieee(freq
, chanflag
);
3396 /* Hack ic->ic_curchan to be in sync with the scan result */
3397 ic
->ic_curchan
= ieee80211_find_channel(ic
, freq
, chanflag
);
3398 if (ic
->ic_curchan
== NULL
)
3399 ic
->ic_curchan
= &ic
->ic_channels
[0];
3401 /* Process extended info from AP */
3402 if (wb
->nwbx_len
> sizeof(ndis_wlan_bssid
)) {
3403 frm
= (uint8_t *)&wb
->nwbx_ies
;
3404 efrm
= frm
+ wb
->nwbx_ielen
;
3405 if (efrm
- frm
< 12)
3407 sp
.tstamp
= frm
; frm
+= 8;
3408 sp
.bintval
= le16toh(*(uint16_t *)frm
); frm
+= 2;
3409 sp
.capinfo
= le16toh(*(uint16_t *)frm
); frm
+= 2;
3411 sp
.ies_len
= efrm
- frm
;
3414 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3415 ether_sprintf(wb
->nwbx_macaddr
), freq
, sp
.bchan
, chanflag
,
3417 ieee80211_add_scan(vap
, ic
->ic_curchan
, &sp
, &wh
, 0, rssi
, noise
);
3418 wb
= (ndis_wlan_bssid_ex
*)((char *)wb
+ wb
->nwbx_len
);
3420 kfree(bl
, M_DEVBUF
);
3421 /* Restore the channel after messing with it */
3422 ic
->ic_curchan
= saved_chan
;
3426 ndis_scan_start(struct ieee80211com
*ic
)
3428 struct ndis_softc
*sc
= ic
->ic_softc
;
3429 struct ieee80211vap
*vap
;
3430 struct ieee80211_scan_state
*ss
;
3431 ndis_80211_ssid ssid
;
3435 vap
= TAILQ_FIRST(&ic
->ic_vaps
);
3437 if (!NDIS_INITIALIZED(sc
)) {
3438 DPRINTF(("%s: scan aborted\n", __func__
));
3439 ieee80211_cancel_scan(vap
);
3444 bzero((char *)&ssid
, len
);
3445 if (ss
->ss_nssid
== 0)
3446 ssid
.ns_ssidlen
= 1;
3448 /* Perform a directed scan */
3449 ssid
.ns_ssidlen
= ss
->ss_ssid
[0].len
;
3450 bcopy(ss
->ss_ssid
[0].ssid
, ssid
.ns_ssid
, ssid
.ns_ssidlen
);
3453 error
= ndis_set_info(sc
, OID_802_11_SSID
, &ssid
, &len
);
3455 DPRINTF(("%s: set ESSID failed\n", __func__
));
3458 error
= ndis_set_info(sc
, OID_802_11_BSSID_LIST_SCAN
, NULL
, &len
);
3460 DPRINTF(("%s: scan command failed\n", __func__
));
3461 ieee80211_cancel_scan(vap
);
3464 /* Set a timer to collect the results */
3465 callout_reset(&sc
->ndis_scan_callout
, hz
* 3, ndis_scan
, vap
);
3469 ndis_set_channel(struct ieee80211com
*ic
)
3475 ndis_scan_curchan(struct ieee80211_scan_state
*ss
, unsigned long maxdwell
)
3481 ndis_scan_mindwell(struct ieee80211_scan_state
*ss
)
3483 /* NB: don't try to abort scan; wait for firmware to finish */
3487 ndis_scan_end(struct ieee80211com
*ic
)
3489 struct ndis_softc
*sc
= ic
->ic_softc
;
3491 ndis_scan_results(sc
);