Deleted Added
full compact
if_ndis.c (298307) if_ndis.c (298818)
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 * WPA support originally contributed by Arvind Srinivasan <arvind@celar.us>
33 * then hacked upon mercilessly by my.
34 */
35
36#include <sys/cdefs.h>
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 * WPA support originally contributed by Arvind Srinivasan <arvind@celar.us>
33 * then hacked upon mercilessly by my.
34 */
35
36#include <sys/cdefs.h>
37__FBSDID("$FreeBSD: head/sys/dev/if_ndis/if_ndis.c 298307 2016-04-19 23:37:24Z pfg $");
37__FBSDID("$FreeBSD: head/sys/dev/if_ndis/if_ndis.c 298818 2016-04-29 22:14:11Z avos $");
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/sockio.h>
42#include <sys/mbuf.h>
43#include <sys/malloc.h>
44#include <sys/endian.h>
45#include <sys/priv.h>
46#include <sys/kernel.h>
47#include <sys/socket.h>
48#include <sys/queue.h>
49#include <sys/module.h>
50#include <sys/proc.h>
51#include <sys/sysctl.h>
52#include <sys/kthread.h>
53#include <sys/limits.h>
54
55#include <net/if.h>
56#include <net/if_var.h>
57#include <net/if_arp.h>
58#include <net/ethernet.h>
59#include <net/if_dl.h>
60#include <net/if_media.h>
61#include <net/if_types.h>
62#include <net/route.h>
63
64#include <net/bpf.h>
65
66#include <machine/bus.h>
67#include <machine/resource.h>
68#include <sys/bus.h>
69#include <sys/rman.h>
70
71#include <net80211/ieee80211_var.h>
72#include <net80211/ieee80211_ioctl.h>
73#include <net80211/ieee80211_regdomain.h>
74
75#include <dev/pci/pcireg.h>
76#include <dev/pci/pcivar.h>
77#include <dev/usb/usb.h>
78#include <dev/usb/usbdi.h>
79
80#include <compat/ndis/pe_var.h>
81#include <compat/ndis/cfg_var.h>
82#include <compat/ndis/resource_var.h>
83#include <compat/ndis/ntoskrnl_var.h>
84#include <compat/ndis/hal_var.h>
85#include <compat/ndis/ndis_var.h>
86#include <compat/ndis/usbd_var.h>
87#include <dev/if_ndis/if_ndisvar.h>
88
89#define NDIS_DEBUG
90#ifdef NDIS_DEBUG
91#define DPRINTF(x) do { if (ndis_debug > 0) printf x; } while (0)
92int ndis_debug = 0;
93SYSCTL_INT(_debug, OID_AUTO, ndis, CTLFLAG_RW, &ndis_debug, 0,
94 "if_ndis debug level");
95#else
96#define DPRINTF(x)
97#endif
98
99SYSCTL_DECL(_hw_ndisusb);
100int ndisusb_halt = 1;
101SYSCTL_INT(_hw_ndisusb, OID_AUTO, halt, CTLFLAG_RW, &ndisusb_halt, 0,
102 "Halt NDIS USB driver when it's attached");
103
104/* 0 - 30 dBm to mW conversion table */
105static const uint16_t dBm2mW[] = {
106 1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
107 3, 4, 4, 4, 5, 6, 6, 7, 8, 9,
108 10, 11, 13, 14, 16, 18, 20, 22, 25, 28,
109 32, 35, 40, 45, 50, 56, 63, 71, 79, 89,
110 100, 112, 126, 141, 158, 178, 200, 224, 251, 282,
111 316, 355, 398, 447, 501, 562, 631, 708, 794, 891,
112 1000
113};
114
115MODULE_DEPEND(ndis, ether, 1, 1, 1);
116MODULE_DEPEND(ndis, wlan, 1, 1, 1);
117MODULE_DEPEND(ndis, ndisapi, 1, 1, 1);
118
119MODULE_VERSION(ndis, 1);
120
121int ndis_attach (device_t);
122int ndis_detach (device_t);
123int ndis_suspend (device_t);
124int ndis_resume (device_t);
125void ndis_shutdown (device_t);
126
127int ndisdrv_modevent (module_t, int, void *);
128
129static void ndis_txeof (ndis_handle, ndis_packet *, ndis_status);
130static void ndis_rxeof (ndis_handle, ndis_packet **, uint32_t);
131static void ndis_rxeof_eth (ndis_handle, ndis_handle, char *, void *,
132 uint32_t, void *, uint32_t, uint32_t);
133static void ndis_rxeof_done (ndis_handle);
134static void ndis_rxeof_xfr (kdpc *, ndis_handle, void *, void *);
135static void ndis_rxeof_xfr_done (ndis_handle, ndis_packet *,
136 uint32_t, uint32_t);
137static void ndis_linksts (ndis_handle, ndis_status, void *, uint32_t);
138static void ndis_linksts_done (ndis_handle);
139
140/* We need to wrap these functions for amd64. */
141static funcptr ndis_txeof_wrap;
142static funcptr ndis_rxeof_wrap;
143static funcptr ndis_rxeof_eth_wrap;
144static funcptr ndis_rxeof_done_wrap;
145static funcptr ndis_rxeof_xfr_wrap;
146static funcptr ndis_rxeof_xfr_done_wrap;
147static funcptr ndis_linksts_wrap;
148static funcptr ndis_linksts_done_wrap;
149static funcptr ndis_ticktask_wrap;
150static funcptr ndis_starttask_wrap;
151static funcptr ndis_resettask_wrap;
152static funcptr ndis_inputtask_wrap;
153
154static struct ieee80211vap *ndis_vap_create(struct ieee80211com *,
155 const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
156 const uint8_t [IEEE80211_ADDR_LEN],
157 const uint8_t [IEEE80211_ADDR_LEN]);
158static void ndis_vap_delete (struct ieee80211vap *);
159static void ndis_tick (void *);
160static void ndis_ticktask (device_object *, void *);
161static int ndis_raw_xmit (struct ieee80211_node *, struct mbuf *,
162 const struct ieee80211_bpf_params *);
163static void ndis_update_mcast (struct ieee80211com *);
164static void ndis_update_promisc (struct ieee80211com *);
165static void ndis_start (struct ifnet *);
166static void ndis_starttask (device_object *, void *);
167static void ndis_resettask (device_object *, void *);
168static void ndis_inputtask (device_object *, void *);
169static int ndis_ioctl (struct ifnet *, u_long, caddr_t);
170static int ndis_newstate (struct ieee80211vap *, enum ieee80211_state,
171 int);
172static int ndis_nettype_chan (uint32_t);
173static int ndis_nettype_mode (uint32_t);
174static void ndis_scan (void *);
175static void ndis_scan_results (struct ndis_softc *);
176static void ndis_scan_start (struct ieee80211com *);
177static void ndis_scan_end (struct ieee80211com *);
178static void ndis_set_channel (struct ieee80211com *);
179static void ndis_scan_curchan (struct ieee80211_scan_state *, unsigned long);
180static void ndis_scan_mindwell (struct ieee80211_scan_state *);
181static void ndis_init (void *);
182static void ndis_stop (struct ndis_softc *);
183static int ndis_ifmedia_upd (struct ifnet *);
184static void ndis_ifmedia_sts (struct ifnet *, struct ifmediareq *);
185static int ndis_get_bssid_list (struct ndis_softc *,
186 ndis_80211_bssid_list_ex **);
187static int ndis_get_assoc (struct ndis_softc *, ndis_wlan_bssid_ex **);
188static int ndis_probe_offload (struct ndis_softc *);
189static int ndis_set_offload (struct ndis_softc *);
190static void ndis_getstate_80211 (struct ndis_softc *);
191static void ndis_setstate_80211 (struct ndis_softc *);
192static void ndis_auth_and_assoc (struct ndis_softc *, struct ieee80211vap *);
193static void ndis_media_status (struct ifnet *, struct ifmediareq *);
194static int ndis_set_cipher (struct ndis_softc *, int);
195static int ndis_set_wpa (struct ndis_softc *, void *, int);
196static int ndis_add_key (struct ieee80211vap *,
197 const struct ieee80211_key *);
198static int ndis_del_key (struct ieee80211vap *,
199 const struct ieee80211_key *);
200static void ndis_setmulti (struct ndis_softc *);
201static void ndis_map_sclist (void *, bus_dma_segment_t *,
202 int, bus_size_t, int);
203static int ndis_ifattach(struct ndis_softc *);
204
205static int ndis_80211attach(struct ndis_softc *);
206static int ndis_80211ioctl(struct ieee80211com *, u_long , void *);
207static int ndis_80211transmit(struct ieee80211com *, struct mbuf *);
208static void ndis_80211parent(struct ieee80211com *);
209
210static int ndisdrv_loaded = 0;
211
212/*
213 * This routine should call windrv_load() once for each driver
214 * image. This will do the relocation and dynalinking for the
215 * image, and create a Windows driver object which will be
216 * saved in our driver database.
217 */
218int
219ndisdrv_modevent(mod, cmd, arg)
220 module_t mod;
221 int cmd;
222 void *arg;
223{
224 int error = 0;
225
226 switch (cmd) {
227 case MOD_LOAD:
228 ndisdrv_loaded++;
229 if (ndisdrv_loaded > 1)
230 break;
231 windrv_wrap((funcptr)ndis_rxeof, &ndis_rxeof_wrap,
232 3, WINDRV_WRAP_STDCALL);
233 windrv_wrap((funcptr)ndis_rxeof_eth, &ndis_rxeof_eth_wrap,
234 8, WINDRV_WRAP_STDCALL);
235 windrv_wrap((funcptr)ndis_rxeof_done, &ndis_rxeof_done_wrap,
236 1, WINDRV_WRAP_STDCALL);
237 windrv_wrap((funcptr)ndis_rxeof_xfr, &ndis_rxeof_xfr_wrap,
238 4, WINDRV_WRAP_STDCALL);
239 windrv_wrap((funcptr)ndis_rxeof_xfr_done,
240 &ndis_rxeof_xfr_done_wrap, 4, WINDRV_WRAP_STDCALL);
241 windrv_wrap((funcptr)ndis_txeof, &ndis_txeof_wrap,
242 3, WINDRV_WRAP_STDCALL);
243 windrv_wrap((funcptr)ndis_linksts, &ndis_linksts_wrap,
244 4, WINDRV_WRAP_STDCALL);
245 windrv_wrap((funcptr)ndis_linksts_done,
246 &ndis_linksts_done_wrap, 1, WINDRV_WRAP_STDCALL);
247 windrv_wrap((funcptr)ndis_ticktask, &ndis_ticktask_wrap,
248 2, WINDRV_WRAP_STDCALL);
249 windrv_wrap((funcptr)ndis_starttask, &ndis_starttask_wrap,
250 2, WINDRV_WRAP_STDCALL);
251 windrv_wrap((funcptr)ndis_resettask, &ndis_resettask_wrap,
252 2, WINDRV_WRAP_STDCALL);
253 windrv_wrap((funcptr)ndis_inputtask, &ndis_inputtask_wrap,
254 2, WINDRV_WRAP_STDCALL);
255 break;
256 case MOD_UNLOAD:
257 ndisdrv_loaded--;
258 if (ndisdrv_loaded > 0)
259 break;
260 /* fallthrough */
261 case MOD_SHUTDOWN:
262 windrv_unwrap(ndis_rxeof_wrap);
263 windrv_unwrap(ndis_rxeof_eth_wrap);
264 windrv_unwrap(ndis_rxeof_done_wrap);
265 windrv_unwrap(ndis_rxeof_xfr_wrap);
266 windrv_unwrap(ndis_rxeof_xfr_done_wrap);
267 windrv_unwrap(ndis_txeof_wrap);
268 windrv_unwrap(ndis_linksts_wrap);
269 windrv_unwrap(ndis_linksts_done_wrap);
270 windrv_unwrap(ndis_ticktask_wrap);
271 windrv_unwrap(ndis_starttask_wrap);
272 windrv_unwrap(ndis_resettask_wrap);
273 windrv_unwrap(ndis_inputtask_wrap);
274 break;
275 default:
276 error = EINVAL;
277 break;
278 }
279
280 return (error);
281}
282
283/*
284 * Program the 64-bit multicast hash filter.
285 */
286static void
287ndis_setmulti(sc)
288 struct ndis_softc *sc;
289{
290 struct ifnet *ifp;
291 struct ifmultiaddr *ifma;
292 int len, mclistsz, error;
293 uint8_t *mclist;
294
295 ifp = sc->ifp;
296
297 if (!NDIS_INITIALIZED(sc))
298 return;
299
300 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
301 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
302 len = sizeof(sc->ndis_filter);
303 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
304 &sc->ndis_filter, &len);
305 if (error)
306 device_printf(sc->ndis_dev,
307 "set allmulti failed: %d\n", error);
308 return;
309 }
310
311 if (TAILQ_EMPTY(&ifp->if_multiaddrs))
312 return;
313
314 len = sizeof(mclistsz);
315 ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &mclistsz, &len);
316
317 mclist = malloc(ETHER_ADDR_LEN * mclistsz, M_TEMP, M_NOWAIT|M_ZERO);
318
319 if (mclist == NULL) {
320 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
321 goto out;
322 }
323
324 sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
325
326 len = 0;
327 if_maddr_rlock(ifp);
328 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
329 if (ifma->ifma_addr->sa_family != AF_LINK)
330 continue;
331 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
332 mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN);
333 len++;
334 if (len > mclistsz) {
335 if_maddr_runlock(ifp);
336 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
337 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
338 goto out;
339 }
340 }
341 if_maddr_runlock(ifp);
342
343 len = len * ETHER_ADDR_LEN;
344 error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len);
345 if (error) {
346 device_printf(sc->ndis_dev, "set mclist failed: %d\n", error);
347 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
348 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
349 }
350
351out:
352 free(mclist, M_TEMP);
353
354 len = sizeof(sc->ndis_filter);
355 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
356 &sc->ndis_filter, &len);
357 if (error)
358 device_printf(sc->ndis_dev, "set multi failed: %d\n", error);
359}
360
361static int
362ndis_set_offload(sc)
363 struct ndis_softc *sc;
364{
365 ndis_task_offload *nto;
366 ndis_task_offload_hdr *ntoh;
367 ndis_task_tcpip_csum *nttc;
368 struct ifnet *ifp;
369 int len, error;
370
371 ifp = sc->ifp;
372
373 if (!NDIS_INITIALIZED(sc))
374 return (EINVAL);
375
376 /* See if there's anything to set. */
377
378 error = ndis_probe_offload(sc);
379 if (error)
380 return (error);
381
382 if (sc->ndis_hwassist == 0 && ifp->if_capabilities == 0)
383 return (0);
384
385 len = sizeof(ndis_task_offload_hdr) + sizeof(ndis_task_offload) +
386 sizeof(ndis_task_tcpip_csum);
387
388 ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
389
390 if (ntoh == NULL)
391 return (ENOMEM);
392
393 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
394 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
395 ntoh->ntoh_offset_firsttask = sizeof(ndis_task_offload_hdr);
396 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
397 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
398 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
399
400 nto = (ndis_task_offload *)((char *)ntoh +
401 ntoh->ntoh_offset_firsttask);
402
403 nto->nto_vers = NDIS_TASK_OFFLOAD_VERSION;
404 nto->nto_len = sizeof(ndis_task_offload);
405 nto->nto_task = NDIS_TASK_TCPIP_CSUM;
406 nto->nto_offset_nexttask = 0;
407 nto->nto_taskbuflen = sizeof(ndis_task_tcpip_csum);
408
409 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
410
411 if (ifp->if_capenable & IFCAP_TXCSUM)
412 nttc->nttc_v4tx = sc->ndis_v4tx;
413
414 if (ifp->if_capenable & IFCAP_RXCSUM)
415 nttc->nttc_v4rx = sc->ndis_v4rx;
416
417 error = ndis_set_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
418 free(ntoh, M_TEMP);
419
420 return (error);
421}
422
423static int
424ndis_probe_offload(sc)
425 struct ndis_softc *sc;
426{
427 ndis_task_offload *nto;
428 ndis_task_offload_hdr *ntoh;
429 ndis_task_tcpip_csum *nttc = NULL;
430 struct ifnet *ifp;
431 int len, error, dummy;
432
433 ifp = sc->ifp;
434
435 len = sizeof(dummy);
436 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, &dummy, &len);
437
438 if (error != ENOSPC)
439 return (error);
440
441 ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
442
443 if (ntoh == NULL)
444 return (ENOMEM);
445
446 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
447 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
448 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
449 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
450 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
451
452 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
453
454 if (error) {
455 free(ntoh, M_TEMP);
456 return (error);
457 }
458
459 if (ntoh->ntoh_vers != NDIS_TASK_OFFLOAD_VERSION) {
460 free(ntoh, M_TEMP);
461 return (EINVAL);
462 }
463
464 nto = (ndis_task_offload *)((char *)ntoh +
465 ntoh->ntoh_offset_firsttask);
466
467 while (1) {
468 switch (nto->nto_task) {
469 case NDIS_TASK_TCPIP_CSUM:
470 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
471 break;
472 /* Don't handle these yet. */
473 case NDIS_TASK_IPSEC:
474 case NDIS_TASK_TCP_LARGESEND:
475 default:
476 break;
477 }
478 if (nto->nto_offset_nexttask == 0)
479 break;
480 nto = (ndis_task_offload *)((char *)nto +
481 nto->nto_offset_nexttask);
482 }
483
484 if (nttc == NULL) {
485 free(ntoh, M_TEMP);
486 return (ENOENT);
487 }
488
489 sc->ndis_v4tx = nttc->nttc_v4tx;
490 sc->ndis_v4rx = nttc->nttc_v4rx;
491
492 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_IP_CSUM)
493 sc->ndis_hwassist |= CSUM_IP;
494 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
495 sc->ndis_hwassist |= CSUM_TCP;
496 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
497 sc->ndis_hwassist |= CSUM_UDP;
498
499 if (sc->ndis_hwassist)
500 ifp->if_capabilities |= IFCAP_TXCSUM;
501
502 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_IP_CSUM)
503 ifp->if_capabilities |= IFCAP_RXCSUM;
504 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
505 ifp->if_capabilities |= IFCAP_RXCSUM;
506 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
507 ifp->if_capabilities |= IFCAP_RXCSUM;
508
509 free(ntoh, M_TEMP);
510 return (0);
511}
512
513static int
514ndis_nettype_chan(uint32_t type)
515{
516 switch (type) {
517 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_CHAN_FHSS);
518 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_CHAN_B);
519 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_CHAN_A);
520 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_CHAN_G);
521 }
522 DPRINTF(("unknown channel nettype %d\n", type));
523 return (IEEE80211_CHAN_B); /* Default to 11B chan */
524}
525
526static int
527ndis_nettype_mode(uint32_t type)
528{
529 switch (type) {
530 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_MODE_FH);
531 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_MODE_11B);
532 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_MODE_11A);
533 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_MODE_11G);
534 }
535 DPRINTF(("unknown mode nettype %d\n", type));
536 return (IEEE80211_MODE_AUTO);
537}
538
539/*
540 * Attach the interface. Allocate softc structures, do ifmedia
541 * setup and ethernet/BPF attach.
542 */
543int
544ndis_attach(device_t dev)
545{
546 struct ndis_softc *sc;
547 driver_object *pdrv;
548 device_object *pdo;
549 int error = 0, len;
550 int i;
551
552 sc = device_get_softc(dev);
553
554 mtx_init(&sc->ndis_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
555 MTX_DEF);
556 KeInitializeSpinLock(&sc->ndis_rxlock);
557 KeInitializeSpinLock(&sc->ndisusb_tasklock);
558 KeInitializeSpinLock(&sc->ndisusb_xferdonelock);
559 InitializeListHead(&sc->ndis_shlist);
560 InitializeListHead(&sc->ndisusb_tasklist);
561 InitializeListHead(&sc->ndisusb_xferdonelist);
562 callout_init(&sc->ndis_stat_callout, 1);
563 mbufq_init(&sc->ndis_rxqueue, INT_MAX); /* XXXGL: sane maximum */
564
565 if (sc->ndis_iftype == PCMCIABus) {
566 error = ndis_alloc_amem(sc);
567 if (error) {
568 device_printf(dev, "failed to allocate "
569 "attribute memory\n");
570 goto fail;
571 }
572 }
573
574 /* Create sysctl registry nodes */
575 ndis_create_sysctls(sc);
576
577 /* Find the PDO for this device instance. */
578
579 if (sc->ndis_iftype == PCIBus)
580 pdrv = windrv_lookup(0, "PCI Bus");
581 else if (sc->ndis_iftype == PCMCIABus)
582 pdrv = windrv_lookup(0, "PCCARD Bus");
583 else
584 pdrv = windrv_lookup(0, "USB Bus");
585 pdo = windrv_find_pdo(pdrv, dev);
586
587 /*
588 * Create a new functional device object for this
589 * device. This is what creates the miniport block
590 * for this device instance.
591 */
592
593 if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) {
594 device_printf(dev, "failed to create FDO!\n");
595 error = ENXIO;
596 goto fail;
597 }
598
599 /* Tell the user what version of the API the driver is using. */
600 device_printf(dev, "NDIS API version: %d.%d\n",
601 sc->ndis_chars->nmc_version_major,
602 sc->ndis_chars->nmc_version_minor);
603
604 /* Do resource conversion. */
605 if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus)
606 ndis_convert_res(sc);
607 else
608 sc->ndis_block->nmb_rlist = NULL;
609
610 /* Install our RX and TX interrupt handlers. */
611 sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap;
612 sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap;
613 sc->ndis_block->nmb_ethrxindicate_func = ndis_rxeof_eth_wrap;
614 sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap;
615 sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap;
616
617 /* Override the status handler so we can detect link changes. */
618 sc->ndis_block->nmb_status_func = ndis_linksts_wrap;
619 sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap;
620
621 /* Set up work item handlers. */
622 sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
623 sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
624 sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
625 sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
626 sc->ndisusb_xferdoneitem =
627 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
628 sc->ndisusb_taskitem =
629 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
630 KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block);
631
632 /* Call driver's init routine. */
633 if (ndis_init_nic(sc)) {
634 device_printf(dev, "init handler failed\n");
635 error = ENXIO;
636 goto fail;
637 }
638
639 /*
640 * Figure out how big to make the TX buffer pool.
641 */
642 len = sizeof(sc->ndis_maxpkts);
643 if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
644 &sc->ndis_maxpkts, &len)) {
645 device_printf(dev, "failed to get max TX packets\n");
646 error = ENXIO;
647 goto fail;
648 }
649
650 /*
651 * If this is a deserialized miniport, we don't have
652 * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result.
653 */
654 if (!NDIS_SERIALIZED(sc->ndis_block))
655 sc->ndis_maxpkts = NDIS_TXPKTS;
656
657 /* Enforce some sanity, just in case. */
658
659 if (sc->ndis_maxpkts == 0)
660 sc->ndis_maxpkts = 10;
661
662 sc->ndis_txarray = malloc(sizeof(ndis_packet *) *
663 sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO);
664
665 /* Allocate a pool of ndis_packets for TX encapsulation. */
666
667 NdisAllocatePacketPool(&i, &sc->ndis_txpool,
668 sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET);
669
670 if (i != NDIS_STATUS_SUCCESS) {
671 sc->ndis_txpool = NULL;
672 device_printf(dev, "failed to allocate TX packet pool");
673 error = ENOMEM;
674 goto fail;
675 }
676
677 sc->ndis_txpending = sc->ndis_maxpkts;
678
679 sc->ndis_oidcnt = 0;
680 /* Get supported oid list. */
681 ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt);
682
683 /* If the NDIS module requested scatter/gather, init maps. */
684 if (sc->ndis_sc)
685 ndis_init_dma(sc);
686
687 /*
688 * See if the OID_802_11_CONFIGURATION OID is
689 * supported by this driver. If it is, then this an 802.11
690 * wireless driver, and we should set up media for wireless.
691 */
692 for (i = 0; i < sc->ndis_oidcnt; i++)
693 if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) {
694 sc->ndis_80211 = 1;
695 break;
696 }
697
698 if (sc->ndis_80211)
699 error = ndis_80211attach(sc);
700 else
701 error = ndis_ifattach(sc);
702
703fail:
704 if (error) {
705 ndis_detach(dev);
706 return (error);
707 }
708
709 if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
710 return (error);
711
712 DPRINTF(("attach done.\n"));
713 /* We're done talking to the NIC for now; halt it. */
714 ndis_halt_nic(sc);
715 DPRINTF(("halting done.\n"));
716
717 return (error);
718}
719
720static int
721ndis_80211attach(struct ndis_softc *sc)
722{
723 struct ieee80211com *ic = &sc->ndis_ic;
724 ndis_80211_rates_ex rates;
725 struct ndis_80211_nettype_list *ntl;
726 uint32_t arg;
727 int mode, i, r, len, nonettypes = 1;
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/sockio.h>
42#include <sys/mbuf.h>
43#include <sys/malloc.h>
44#include <sys/endian.h>
45#include <sys/priv.h>
46#include <sys/kernel.h>
47#include <sys/socket.h>
48#include <sys/queue.h>
49#include <sys/module.h>
50#include <sys/proc.h>
51#include <sys/sysctl.h>
52#include <sys/kthread.h>
53#include <sys/limits.h>
54
55#include <net/if.h>
56#include <net/if_var.h>
57#include <net/if_arp.h>
58#include <net/ethernet.h>
59#include <net/if_dl.h>
60#include <net/if_media.h>
61#include <net/if_types.h>
62#include <net/route.h>
63
64#include <net/bpf.h>
65
66#include <machine/bus.h>
67#include <machine/resource.h>
68#include <sys/bus.h>
69#include <sys/rman.h>
70
71#include <net80211/ieee80211_var.h>
72#include <net80211/ieee80211_ioctl.h>
73#include <net80211/ieee80211_regdomain.h>
74
75#include <dev/pci/pcireg.h>
76#include <dev/pci/pcivar.h>
77#include <dev/usb/usb.h>
78#include <dev/usb/usbdi.h>
79
80#include <compat/ndis/pe_var.h>
81#include <compat/ndis/cfg_var.h>
82#include <compat/ndis/resource_var.h>
83#include <compat/ndis/ntoskrnl_var.h>
84#include <compat/ndis/hal_var.h>
85#include <compat/ndis/ndis_var.h>
86#include <compat/ndis/usbd_var.h>
87#include <dev/if_ndis/if_ndisvar.h>
88
89#define NDIS_DEBUG
90#ifdef NDIS_DEBUG
91#define DPRINTF(x) do { if (ndis_debug > 0) printf x; } while (0)
92int ndis_debug = 0;
93SYSCTL_INT(_debug, OID_AUTO, ndis, CTLFLAG_RW, &ndis_debug, 0,
94 "if_ndis debug level");
95#else
96#define DPRINTF(x)
97#endif
98
99SYSCTL_DECL(_hw_ndisusb);
100int ndisusb_halt = 1;
101SYSCTL_INT(_hw_ndisusb, OID_AUTO, halt, CTLFLAG_RW, &ndisusb_halt, 0,
102 "Halt NDIS USB driver when it's attached");
103
104/* 0 - 30 dBm to mW conversion table */
105static const uint16_t dBm2mW[] = {
106 1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
107 3, 4, 4, 4, 5, 6, 6, 7, 8, 9,
108 10, 11, 13, 14, 16, 18, 20, 22, 25, 28,
109 32, 35, 40, 45, 50, 56, 63, 71, 79, 89,
110 100, 112, 126, 141, 158, 178, 200, 224, 251, 282,
111 316, 355, 398, 447, 501, 562, 631, 708, 794, 891,
112 1000
113};
114
115MODULE_DEPEND(ndis, ether, 1, 1, 1);
116MODULE_DEPEND(ndis, wlan, 1, 1, 1);
117MODULE_DEPEND(ndis, ndisapi, 1, 1, 1);
118
119MODULE_VERSION(ndis, 1);
120
121int ndis_attach (device_t);
122int ndis_detach (device_t);
123int ndis_suspend (device_t);
124int ndis_resume (device_t);
125void ndis_shutdown (device_t);
126
127int ndisdrv_modevent (module_t, int, void *);
128
129static void ndis_txeof (ndis_handle, ndis_packet *, ndis_status);
130static void ndis_rxeof (ndis_handle, ndis_packet **, uint32_t);
131static void ndis_rxeof_eth (ndis_handle, ndis_handle, char *, void *,
132 uint32_t, void *, uint32_t, uint32_t);
133static void ndis_rxeof_done (ndis_handle);
134static void ndis_rxeof_xfr (kdpc *, ndis_handle, void *, void *);
135static void ndis_rxeof_xfr_done (ndis_handle, ndis_packet *,
136 uint32_t, uint32_t);
137static void ndis_linksts (ndis_handle, ndis_status, void *, uint32_t);
138static void ndis_linksts_done (ndis_handle);
139
140/* We need to wrap these functions for amd64. */
141static funcptr ndis_txeof_wrap;
142static funcptr ndis_rxeof_wrap;
143static funcptr ndis_rxeof_eth_wrap;
144static funcptr ndis_rxeof_done_wrap;
145static funcptr ndis_rxeof_xfr_wrap;
146static funcptr ndis_rxeof_xfr_done_wrap;
147static funcptr ndis_linksts_wrap;
148static funcptr ndis_linksts_done_wrap;
149static funcptr ndis_ticktask_wrap;
150static funcptr ndis_starttask_wrap;
151static funcptr ndis_resettask_wrap;
152static funcptr ndis_inputtask_wrap;
153
154static struct ieee80211vap *ndis_vap_create(struct ieee80211com *,
155 const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
156 const uint8_t [IEEE80211_ADDR_LEN],
157 const uint8_t [IEEE80211_ADDR_LEN]);
158static void ndis_vap_delete (struct ieee80211vap *);
159static void ndis_tick (void *);
160static void ndis_ticktask (device_object *, void *);
161static int ndis_raw_xmit (struct ieee80211_node *, struct mbuf *,
162 const struct ieee80211_bpf_params *);
163static void ndis_update_mcast (struct ieee80211com *);
164static void ndis_update_promisc (struct ieee80211com *);
165static void ndis_start (struct ifnet *);
166static void ndis_starttask (device_object *, void *);
167static void ndis_resettask (device_object *, void *);
168static void ndis_inputtask (device_object *, void *);
169static int ndis_ioctl (struct ifnet *, u_long, caddr_t);
170static int ndis_newstate (struct ieee80211vap *, enum ieee80211_state,
171 int);
172static int ndis_nettype_chan (uint32_t);
173static int ndis_nettype_mode (uint32_t);
174static void ndis_scan (void *);
175static void ndis_scan_results (struct ndis_softc *);
176static void ndis_scan_start (struct ieee80211com *);
177static void ndis_scan_end (struct ieee80211com *);
178static void ndis_set_channel (struct ieee80211com *);
179static void ndis_scan_curchan (struct ieee80211_scan_state *, unsigned long);
180static void ndis_scan_mindwell (struct ieee80211_scan_state *);
181static void ndis_init (void *);
182static void ndis_stop (struct ndis_softc *);
183static int ndis_ifmedia_upd (struct ifnet *);
184static void ndis_ifmedia_sts (struct ifnet *, struct ifmediareq *);
185static int ndis_get_bssid_list (struct ndis_softc *,
186 ndis_80211_bssid_list_ex **);
187static int ndis_get_assoc (struct ndis_softc *, ndis_wlan_bssid_ex **);
188static int ndis_probe_offload (struct ndis_softc *);
189static int ndis_set_offload (struct ndis_softc *);
190static void ndis_getstate_80211 (struct ndis_softc *);
191static void ndis_setstate_80211 (struct ndis_softc *);
192static void ndis_auth_and_assoc (struct ndis_softc *, struct ieee80211vap *);
193static void ndis_media_status (struct ifnet *, struct ifmediareq *);
194static int ndis_set_cipher (struct ndis_softc *, int);
195static int ndis_set_wpa (struct ndis_softc *, void *, int);
196static int ndis_add_key (struct ieee80211vap *,
197 const struct ieee80211_key *);
198static int ndis_del_key (struct ieee80211vap *,
199 const struct ieee80211_key *);
200static void ndis_setmulti (struct ndis_softc *);
201static void ndis_map_sclist (void *, bus_dma_segment_t *,
202 int, bus_size_t, int);
203static int ndis_ifattach(struct ndis_softc *);
204
205static int ndis_80211attach(struct ndis_softc *);
206static int ndis_80211ioctl(struct ieee80211com *, u_long , void *);
207static int ndis_80211transmit(struct ieee80211com *, struct mbuf *);
208static void ndis_80211parent(struct ieee80211com *);
209
210static int ndisdrv_loaded = 0;
211
212/*
213 * This routine should call windrv_load() once for each driver
214 * image. This will do the relocation and dynalinking for the
215 * image, and create a Windows driver object which will be
216 * saved in our driver database.
217 */
218int
219ndisdrv_modevent(mod, cmd, arg)
220 module_t mod;
221 int cmd;
222 void *arg;
223{
224 int error = 0;
225
226 switch (cmd) {
227 case MOD_LOAD:
228 ndisdrv_loaded++;
229 if (ndisdrv_loaded > 1)
230 break;
231 windrv_wrap((funcptr)ndis_rxeof, &ndis_rxeof_wrap,
232 3, WINDRV_WRAP_STDCALL);
233 windrv_wrap((funcptr)ndis_rxeof_eth, &ndis_rxeof_eth_wrap,
234 8, WINDRV_WRAP_STDCALL);
235 windrv_wrap((funcptr)ndis_rxeof_done, &ndis_rxeof_done_wrap,
236 1, WINDRV_WRAP_STDCALL);
237 windrv_wrap((funcptr)ndis_rxeof_xfr, &ndis_rxeof_xfr_wrap,
238 4, WINDRV_WRAP_STDCALL);
239 windrv_wrap((funcptr)ndis_rxeof_xfr_done,
240 &ndis_rxeof_xfr_done_wrap, 4, WINDRV_WRAP_STDCALL);
241 windrv_wrap((funcptr)ndis_txeof, &ndis_txeof_wrap,
242 3, WINDRV_WRAP_STDCALL);
243 windrv_wrap((funcptr)ndis_linksts, &ndis_linksts_wrap,
244 4, WINDRV_WRAP_STDCALL);
245 windrv_wrap((funcptr)ndis_linksts_done,
246 &ndis_linksts_done_wrap, 1, WINDRV_WRAP_STDCALL);
247 windrv_wrap((funcptr)ndis_ticktask, &ndis_ticktask_wrap,
248 2, WINDRV_WRAP_STDCALL);
249 windrv_wrap((funcptr)ndis_starttask, &ndis_starttask_wrap,
250 2, WINDRV_WRAP_STDCALL);
251 windrv_wrap((funcptr)ndis_resettask, &ndis_resettask_wrap,
252 2, WINDRV_WRAP_STDCALL);
253 windrv_wrap((funcptr)ndis_inputtask, &ndis_inputtask_wrap,
254 2, WINDRV_WRAP_STDCALL);
255 break;
256 case MOD_UNLOAD:
257 ndisdrv_loaded--;
258 if (ndisdrv_loaded > 0)
259 break;
260 /* fallthrough */
261 case MOD_SHUTDOWN:
262 windrv_unwrap(ndis_rxeof_wrap);
263 windrv_unwrap(ndis_rxeof_eth_wrap);
264 windrv_unwrap(ndis_rxeof_done_wrap);
265 windrv_unwrap(ndis_rxeof_xfr_wrap);
266 windrv_unwrap(ndis_rxeof_xfr_done_wrap);
267 windrv_unwrap(ndis_txeof_wrap);
268 windrv_unwrap(ndis_linksts_wrap);
269 windrv_unwrap(ndis_linksts_done_wrap);
270 windrv_unwrap(ndis_ticktask_wrap);
271 windrv_unwrap(ndis_starttask_wrap);
272 windrv_unwrap(ndis_resettask_wrap);
273 windrv_unwrap(ndis_inputtask_wrap);
274 break;
275 default:
276 error = EINVAL;
277 break;
278 }
279
280 return (error);
281}
282
283/*
284 * Program the 64-bit multicast hash filter.
285 */
286static void
287ndis_setmulti(sc)
288 struct ndis_softc *sc;
289{
290 struct ifnet *ifp;
291 struct ifmultiaddr *ifma;
292 int len, mclistsz, error;
293 uint8_t *mclist;
294
295 ifp = sc->ifp;
296
297 if (!NDIS_INITIALIZED(sc))
298 return;
299
300 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
301 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
302 len = sizeof(sc->ndis_filter);
303 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
304 &sc->ndis_filter, &len);
305 if (error)
306 device_printf(sc->ndis_dev,
307 "set allmulti failed: %d\n", error);
308 return;
309 }
310
311 if (TAILQ_EMPTY(&ifp->if_multiaddrs))
312 return;
313
314 len = sizeof(mclistsz);
315 ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &mclistsz, &len);
316
317 mclist = malloc(ETHER_ADDR_LEN * mclistsz, M_TEMP, M_NOWAIT|M_ZERO);
318
319 if (mclist == NULL) {
320 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
321 goto out;
322 }
323
324 sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
325
326 len = 0;
327 if_maddr_rlock(ifp);
328 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
329 if (ifma->ifma_addr->sa_family != AF_LINK)
330 continue;
331 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
332 mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN);
333 len++;
334 if (len > mclistsz) {
335 if_maddr_runlock(ifp);
336 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
337 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
338 goto out;
339 }
340 }
341 if_maddr_runlock(ifp);
342
343 len = len * ETHER_ADDR_LEN;
344 error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len);
345 if (error) {
346 device_printf(sc->ndis_dev, "set mclist failed: %d\n", error);
347 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
348 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
349 }
350
351out:
352 free(mclist, M_TEMP);
353
354 len = sizeof(sc->ndis_filter);
355 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
356 &sc->ndis_filter, &len);
357 if (error)
358 device_printf(sc->ndis_dev, "set multi failed: %d\n", error);
359}
360
361static int
362ndis_set_offload(sc)
363 struct ndis_softc *sc;
364{
365 ndis_task_offload *nto;
366 ndis_task_offload_hdr *ntoh;
367 ndis_task_tcpip_csum *nttc;
368 struct ifnet *ifp;
369 int len, error;
370
371 ifp = sc->ifp;
372
373 if (!NDIS_INITIALIZED(sc))
374 return (EINVAL);
375
376 /* See if there's anything to set. */
377
378 error = ndis_probe_offload(sc);
379 if (error)
380 return (error);
381
382 if (sc->ndis_hwassist == 0 && ifp->if_capabilities == 0)
383 return (0);
384
385 len = sizeof(ndis_task_offload_hdr) + sizeof(ndis_task_offload) +
386 sizeof(ndis_task_tcpip_csum);
387
388 ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
389
390 if (ntoh == NULL)
391 return (ENOMEM);
392
393 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
394 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
395 ntoh->ntoh_offset_firsttask = sizeof(ndis_task_offload_hdr);
396 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
397 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
398 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
399
400 nto = (ndis_task_offload *)((char *)ntoh +
401 ntoh->ntoh_offset_firsttask);
402
403 nto->nto_vers = NDIS_TASK_OFFLOAD_VERSION;
404 nto->nto_len = sizeof(ndis_task_offload);
405 nto->nto_task = NDIS_TASK_TCPIP_CSUM;
406 nto->nto_offset_nexttask = 0;
407 nto->nto_taskbuflen = sizeof(ndis_task_tcpip_csum);
408
409 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
410
411 if (ifp->if_capenable & IFCAP_TXCSUM)
412 nttc->nttc_v4tx = sc->ndis_v4tx;
413
414 if (ifp->if_capenable & IFCAP_RXCSUM)
415 nttc->nttc_v4rx = sc->ndis_v4rx;
416
417 error = ndis_set_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
418 free(ntoh, M_TEMP);
419
420 return (error);
421}
422
423static int
424ndis_probe_offload(sc)
425 struct ndis_softc *sc;
426{
427 ndis_task_offload *nto;
428 ndis_task_offload_hdr *ntoh;
429 ndis_task_tcpip_csum *nttc = NULL;
430 struct ifnet *ifp;
431 int len, error, dummy;
432
433 ifp = sc->ifp;
434
435 len = sizeof(dummy);
436 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, &dummy, &len);
437
438 if (error != ENOSPC)
439 return (error);
440
441 ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
442
443 if (ntoh == NULL)
444 return (ENOMEM);
445
446 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
447 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
448 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
449 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
450 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
451
452 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
453
454 if (error) {
455 free(ntoh, M_TEMP);
456 return (error);
457 }
458
459 if (ntoh->ntoh_vers != NDIS_TASK_OFFLOAD_VERSION) {
460 free(ntoh, M_TEMP);
461 return (EINVAL);
462 }
463
464 nto = (ndis_task_offload *)((char *)ntoh +
465 ntoh->ntoh_offset_firsttask);
466
467 while (1) {
468 switch (nto->nto_task) {
469 case NDIS_TASK_TCPIP_CSUM:
470 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
471 break;
472 /* Don't handle these yet. */
473 case NDIS_TASK_IPSEC:
474 case NDIS_TASK_TCP_LARGESEND:
475 default:
476 break;
477 }
478 if (nto->nto_offset_nexttask == 0)
479 break;
480 nto = (ndis_task_offload *)((char *)nto +
481 nto->nto_offset_nexttask);
482 }
483
484 if (nttc == NULL) {
485 free(ntoh, M_TEMP);
486 return (ENOENT);
487 }
488
489 sc->ndis_v4tx = nttc->nttc_v4tx;
490 sc->ndis_v4rx = nttc->nttc_v4rx;
491
492 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_IP_CSUM)
493 sc->ndis_hwassist |= CSUM_IP;
494 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
495 sc->ndis_hwassist |= CSUM_TCP;
496 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
497 sc->ndis_hwassist |= CSUM_UDP;
498
499 if (sc->ndis_hwassist)
500 ifp->if_capabilities |= IFCAP_TXCSUM;
501
502 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_IP_CSUM)
503 ifp->if_capabilities |= IFCAP_RXCSUM;
504 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
505 ifp->if_capabilities |= IFCAP_RXCSUM;
506 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
507 ifp->if_capabilities |= IFCAP_RXCSUM;
508
509 free(ntoh, M_TEMP);
510 return (0);
511}
512
513static int
514ndis_nettype_chan(uint32_t type)
515{
516 switch (type) {
517 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_CHAN_FHSS);
518 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_CHAN_B);
519 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_CHAN_A);
520 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_CHAN_G);
521 }
522 DPRINTF(("unknown channel nettype %d\n", type));
523 return (IEEE80211_CHAN_B); /* Default to 11B chan */
524}
525
526static int
527ndis_nettype_mode(uint32_t type)
528{
529 switch (type) {
530 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_MODE_FH);
531 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_MODE_11B);
532 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_MODE_11A);
533 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_MODE_11G);
534 }
535 DPRINTF(("unknown mode nettype %d\n", type));
536 return (IEEE80211_MODE_AUTO);
537}
538
539/*
540 * Attach the interface. Allocate softc structures, do ifmedia
541 * setup and ethernet/BPF attach.
542 */
543int
544ndis_attach(device_t dev)
545{
546 struct ndis_softc *sc;
547 driver_object *pdrv;
548 device_object *pdo;
549 int error = 0, len;
550 int i;
551
552 sc = device_get_softc(dev);
553
554 mtx_init(&sc->ndis_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
555 MTX_DEF);
556 KeInitializeSpinLock(&sc->ndis_rxlock);
557 KeInitializeSpinLock(&sc->ndisusb_tasklock);
558 KeInitializeSpinLock(&sc->ndisusb_xferdonelock);
559 InitializeListHead(&sc->ndis_shlist);
560 InitializeListHead(&sc->ndisusb_tasklist);
561 InitializeListHead(&sc->ndisusb_xferdonelist);
562 callout_init(&sc->ndis_stat_callout, 1);
563 mbufq_init(&sc->ndis_rxqueue, INT_MAX); /* XXXGL: sane maximum */
564
565 if (sc->ndis_iftype == PCMCIABus) {
566 error = ndis_alloc_amem(sc);
567 if (error) {
568 device_printf(dev, "failed to allocate "
569 "attribute memory\n");
570 goto fail;
571 }
572 }
573
574 /* Create sysctl registry nodes */
575 ndis_create_sysctls(sc);
576
577 /* Find the PDO for this device instance. */
578
579 if (sc->ndis_iftype == PCIBus)
580 pdrv = windrv_lookup(0, "PCI Bus");
581 else if (sc->ndis_iftype == PCMCIABus)
582 pdrv = windrv_lookup(0, "PCCARD Bus");
583 else
584 pdrv = windrv_lookup(0, "USB Bus");
585 pdo = windrv_find_pdo(pdrv, dev);
586
587 /*
588 * Create a new functional device object for this
589 * device. This is what creates the miniport block
590 * for this device instance.
591 */
592
593 if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) {
594 device_printf(dev, "failed to create FDO!\n");
595 error = ENXIO;
596 goto fail;
597 }
598
599 /* Tell the user what version of the API the driver is using. */
600 device_printf(dev, "NDIS API version: %d.%d\n",
601 sc->ndis_chars->nmc_version_major,
602 sc->ndis_chars->nmc_version_minor);
603
604 /* Do resource conversion. */
605 if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus)
606 ndis_convert_res(sc);
607 else
608 sc->ndis_block->nmb_rlist = NULL;
609
610 /* Install our RX and TX interrupt handlers. */
611 sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap;
612 sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap;
613 sc->ndis_block->nmb_ethrxindicate_func = ndis_rxeof_eth_wrap;
614 sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap;
615 sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap;
616
617 /* Override the status handler so we can detect link changes. */
618 sc->ndis_block->nmb_status_func = ndis_linksts_wrap;
619 sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap;
620
621 /* Set up work item handlers. */
622 sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
623 sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
624 sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
625 sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
626 sc->ndisusb_xferdoneitem =
627 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
628 sc->ndisusb_taskitem =
629 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
630 KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block);
631
632 /* Call driver's init routine. */
633 if (ndis_init_nic(sc)) {
634 device_printf(dev, "init handler failed\n");
635 error = ENXIO;
636 goto fail;
637 }
638
639 /*
640 * Figure out how big to make the TX buffer pool.
641 */
642 len = sizeof(sc->ndis_maxpkts);
643 if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
644 &sc->ndis_maxpkts, &len)) {
645 device_printf(dev, "failed to get max TX packets\n");
646 error = ENXIO;
647 goto fail;
648 }
649
650 /*
651 * If this is a deserialized miniport, we don't have
652 * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result.
653 */
654 if (!NDIS_SERIALIZED(sc->ndis_block))
655 sc->ndis_maxpkts = NDIS_TXPKTS;
656
657 /* Enforce some sanity, just in case. */
658
659 if (sc->ndis_maxpkts == 0)
660 sc->ndis_maxpkts = 10;
661
662 sc->ndis_txarray = malloc(sizeof(ndis_packet *) *
663 sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO);
664
665 /* Allocate a pool of ndis_packets for TX encapsulation. */
666
667 NdisAllocatePacketPool(&i, &sc->ndis_txpool,
668 sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET);
669
670 if (i != NDIS_STATUS_SUCCESS) {
671 sc->ndis_txpool = NULL;
672 device_printf(dev, "failed to allocate TX packet pool");
673 error = ENOMEM;
674 goto fail;
675 }
676
677 sc->ndis_txpending = sc->ndis_maxpkts;
678
679 sc->ndis_oidcnt = 0;
680 /* Get supported oid list. */
681 ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt);
682
683 /* If the NDIS module requested scatter/gather, init maps. */
684 if (sc->ndis_sc)
685 ndis_init_dma(sc);
686
687 /*
688 * See if the OID_802_11_CONFIGURATION OID is
689 * supported by this driver. If it is, then this an 802.11
690 * wireless driver, and we should set up media for wireless.
691 */
692 for (i = 0; i < sc->ndis_oidcnt; i++)
693 if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) {
694 sc->ndis_80211 = 1;
695 break;
696 }
697
698 if (sc->ndis_80211)
699 error = ndis_80211attach(sc);
700 else
701 error = ndis_ifattach(sc);
702
703fail:
704 if (error) {
705 ndis_detach(dev);
706 return (error);
707 }
708
709 if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
710 return (error);
711
712 DPRINTF(("attach done.\n"));
713 /* We're done talking to the NIC for now; halt it. */
714 ndis_halt_nic(sc);
715 DPRINTF(("halting done.\n"));
716
717 return (error);
718}
719
720static int
721ndis_80211attach(struct ndis_softc *sc)
722{
723 struct ieee80211com *ic = &sc->ndis_ic;
724 ndis_80211_rates_ex rates;
725 struct ndis_80211_nettype_list *ntl;
726 uint32_t arg;
727 int mode, i, r, len, nonettypes = 1;
728 uint8_t bands[howmany(IEEE80211_MODE_MAX, 8)] = { 0 };
728 uint8_t bands[IEEE80211_MODE_BYTES] = { 0 };
729
730 callout_init(&sc->ndis_scan_callout, 1);
731
732 ic->ic_softc = sc;
733 ic->ic_ioctl = ndis_80211ioctl;
734 ic->ic_name = device_get_nameunit(sc->ndis_dev);
735 ic->ic_opmode = IEEE80211_M_STA;
736 ic->ic_phytype = IEEE80211_T_DS;
737 ic->ic_caps = IEEE80211_C_8023ENCAP |
738 IEEE80211_C_STA | IEEE80211_C_IBSS;
739 setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
740 len = 0;
741 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, NULL, &len);
742 if (r != ENOSPC)
743 goto nonettypes;
744 ntl = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
745 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, ntl, &len);
746 if (r != 0) {
747 free(ntl, M_DEVBUF);
748 goto nonettypes;
749 }
750
751 for (i = 0; i < ntl->ntl_items; i++) {
752 mode = ndis_nettype_mode(ntl->ntl_type[i]);
753 if (mode) {
754 nonettypes = 0;
755 setbit(ic->ic_modecaps, mode);
756 setbit(bands, mode);
757 } else
758 device_printf(sc->ndis_dev, "Unknown nettype %d\n",
759 ntl->ntl_type[i]);
760 }
761 free(ntl, M_DEVBUF);
762nonettypes:
763 /* Default to 11b channels if the card did not supply any */
764 if (nonettypes) {
765 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
766 setbit(bands, IEEE80211_MODE_11B);
767 }
768 len = sizeof(rates);
769 bzero((char *)&rates, len);
770 r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len);
771 if (r != 0)
772 device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r);
773 /*
774 * Since the supported rates only up to 8 can be supported,
775 * if this is not 802.11b we're just going to be faking it
776 * all up to heck.
777 */
778
779#define TESTSETRATE(x, y) \
780 do { \
781 int i; \
782 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \
783 if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \
784 break; \
785 } \
786 if (i == ic->ic_sup_rates[x].rs_nrates) { \
787 ic->ic_sup_rates[x].rs_rates[i] = (y); \
788 ic->ic_sup_rates[x].rs_nrates++; \
789 } \
790 } while (0)
791
792#define SETRATE(x, y) \
793 ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
794#define INCRATE(x) \
795 ic->ic_sup_rates[x].rs_nrates++
796
797 ic->ic_curmode = IEEE80211_MODE_AUTO;
798 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A))
799 ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
800 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B))
801 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
802 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G))
803 ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
804 for (i = 0; i < len; i++) {
805 switch (rates[i] & IEEE80211_RATE_VAL) {
806 case 2:
807 case 4:
808 case 11:
809 case 10:
810 case 22:
811 if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) {
812 /* Lazy-init 802.11b. */
813 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
814 ic->ic_sup_rates[IEEE80211_MODE_11B].
815 rs_nrates = 0;
816 }
817 SETRATE(IEEE80211_MODE_11B, rates[i]);
818 INCRATE(IEEE80211_MODE_11B);
819 break;
820 default:
821 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
822 SETRATE(IEEE80211_MODE_11A, rates[i]);
823 INCRATE(IEEE80211_MODE_11A);
824 }
825 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
826 SETRATE(IEEE80211_MODE_11G, rates[i]);
827 INCRATE(IEEE80211_MODE_11G);
828 }
829 break;
830 }
831 }
832
833 /*
834 * If the hardware supports 802.11g, it most
835 * likely supports 802.11b and all of the
836 * 802.11b and 802.11g speeds, so maybe we can
837 * just cheat here. Just how in the heck do
838 * we detect turbo modes, though?
839 */
840 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) {
841 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|2);
842 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|4);
843 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|11);
844 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|22);
845 }
846 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
847 TESTSETRATE(IEEE80211_MODE_11G, 48);
848 TESTSETRATE(IEEE80211_MODE_11G, 72);
849 TESTSETRATE(IEEE80211_MODE_11G, 96);
850 TESTSETRATE(IEEE80211_MODE_11G, 108);
851 }
852 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
853 TESTSETRATE(IEEE80211_MODE_11A, 48);
854 TESTSETRATE(IEEE80211_MODE_11A, 72);
855 TESTSETRATE(IEEE80211_MODE_11A, 96);
856 TESTSETRATE(IEEE80211_MODE_11A, 108);
857 }
858
859#undef SETRATE
860#undef INCRATE
861#undef TESTSETRATE
862
863 ieee80211_init_channels(ic, NULL, bands);
864
865 /*
866 * To test for WPA support, we need to see if we can
867 * set AUTHENTICATION_MODE to WPA and read it back
868 * successfully.
869 */
870 i = sizeof(arg);
871 arg = NDIS_80211_AUTHMODE_WPA;
872 r = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
873 if (r == 0) {
874 r = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
875 if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA)
876 ic->ic_caps |= IEEE80211_C_WPA;
877 }
878
879 /*
880 * To test for supported ciphers, we set each
881 * available encryption type in descending order.
882 * If ENC3 works, then we have WEP, TKIP and AES.
883 * If only ENC2 works, then we have WEP and TKIP.
884 * If only ENC1 works, then we have just WEP.
885 */
886 i = sizeof(arg);
887 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
888 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
889 if (r == 0) {
890 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
891 | IEEE80211_CRYPTO_TKIP
892 | IEEE80211_CRYPTO_AES_CCM;
893 goto got_crypto;
894 }
895 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
896 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
897 if (r == 0) {
898 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
899 | IEEE80211_CRYPTO_TKIP;
900 goto got_crypto;
901 }
902 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
903 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
904 if (r == 0)
905 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
906got_crypto:
907 i = sizeof(arg);
908 r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
909 if (r == 0)
910 ic->ic_caps |= IEEE80211_C_PMGT;
911
912 r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
913 if (r == 0)
914 ic->ic_caps |= IEEE80211_C_TXPMGT;
915
916 /*
917 * Get station address from the driver.
918 */
919 len = sizeof(ic->ic_macaddr);
920 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &ic->ic_macaddr, &len);
921
922 ieee80211_ifattach(ic);
923 ic->ic_raw_xmit = ndis_raw_xmit;
924 ic->ic_scan_start = ndis_scan_start;
925 ic->ic_scan_end = ndis_scan_end;
926 ic->ic_set_channel = ndis_set_channel;
927 ic->ic_scan_curchan = ndis_scan_curchan;
928 ic->ic_scan_mindwell = ndis_scan_mindwell;
929 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
930 ic->ic_vap_create = ndis_vap_create;
931 ic->ic_vap_delete = ndis_vap_delete;
932 ic->ic_update_mcast = ndis_update_mcast;
933 ic->ic_update_promisc = ndis_update_promisc;
934 ic->ic_transmit = ndis_80211transmit;
935 ic->ic_parent = ndis_80211parent;
936
937 if (bootverbose)
938 ieee80211_announce(ic);
939
940 return (0);
941}
942
943static int
944ndis_ifattach(struct ndis_softc *sc)
945{
946 struct ifnet *ifp;
947 u_char eaddr[ETHER_ADDR_LEN];
948 int len;
949
950 ifp = if_alloc(IFT_ETHER);
951 if (ifp == NULL)
952 return (ENOSPC);
953 sc->ifp = ifp;
954 ifp->if_softc = sc;
955
956 /* Check for task offload support. */
957 ndis_probe_offload(sc);
958
959 /*
960 * Get station address from the driver.
961 */
962 len = sizeof(eaddr);
963 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, eaddr, &len);
964
965 if_initname(ifp, device_get_name(sc->ndis_dev),
966 device_get_unit(sc->ndis_dev));
967 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
968 ifp->if_ioctl = ndis_ioctl;
969 ifp->if_start = ndis_start;
970 ifp->if_init = ndis_init;
971 ifp->if_baudrate = 10000000;
972 IFQ_SET_MAXLEN(&ifp->if_snd, 50);
973 ifp->if_snd.ifq_drv_maxlen = 25;
974 IFQ_SET_READY(&ifp->if_snd);
975 ifp->if_capenable = ifp->if_capabilities;
976 ifp->if_hwassist = sc->ndis_hwassist;
977
978 ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
979 ndis_ifmedia_sts);
980 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
981 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
982 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
983 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
984 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
985 ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
986 ether_ifattach(ifp, eaddr);
987
988 return (0);
989}
990
991static struct ieee80211vap *
992ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
993 enum ieee80211_opmode opmode, int flags,
994 const uint8_t bssid[IEEE80211_ADDR_LEN],
995 const uint8_t mac[IEEE80211_ADDR_LEN])
996{
997 struct ndis_vap *nvp;
998 struct ieee80211vap *vap;
999
1000 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
1001 return NULL;
1002 nvp = malloc(sizeof(struct ndis_vap), M_80211_VAP, M_WAITOK | M_ZERO);
1003 vap = &nvp->vap;
1004 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
1005 /* override with driver methods */
1006 nvp->newstate = vap->iv_newstate;
1007 vap->iv_newstate = ndis_newstate;
1008
1009 /* complete setup */
1010 ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status,
1011 mac);
1012 ic->ic_opmode = opmode;
1013 /* install key handing routines */
1014 vap->iv_key_set = ndis_add_key;
1015 vap->iv_key_delete = ndis_del_key;
1016 return vap;
1017}
1018
1019static void
1020ndis_vap_delete(struct ieee80211vap *vap)
1021{
1022 struct ndis_vap *nvp = NDIS_VAP(vap);
1023 struct ieee80211com *ic = vap->iv_ic;
1024 struct ndis_softc *sc = ic->ic_softc;
1025
1026 ndis_stop(sc);
1027 callout_drain(&sc->ndis_scan_callout);
1028 ieee80211_vap_detach(vap);
1029 free(nvp, M_80211_VAP);
1030}
1031
1032/*
1033 * Shutdown hardware and free up resources. This can be called any
1034 * time after the mutex has been initialized. It is called in both
1035 * the error case in attach and the normal detach case so it needs
1036 * to be careful about only freeing resources that have actually been
1037 * allocated.
1038 */
1039int
1040ndis_detach(device_t dev)
1041{
1042 struct ifnet *ifp;
1043 struct ndis_softc *sc;
1044 driver_object *drv;
1045
1046 sc = device_get_softc(dev);
1047 NDIS_LOCK(sc);
1048 if (!sc->ndis_80211)
1049 ifp = sc->ifp;
1050 else
1051 ifp = NULL;
1052 if (ifp != NULL)
1053 ifp->if_flags &= ~IFF_UP;
1054 if (device_is_attached(dev)) {
1055 NDIS_UNLOCK(sc);
1056 ndis_stop(sc);
1057 if (sc->ndis_80211)
1058 ieee80211_ifdetach(&sc->ndis_ic);
1059 else if (ifp != NULL)
1060 ether_ifdetach(ifp);
1061 } else
1062 NDIS_UNLOCK(sc);
1063
1064 if (sc->ndis_tickitem != NULL)
1065 IoFreeWorkItem(sc->ndis_tickitem);
1066 if (sc->ndis_startitem != NULL)
1067 IoFreeWorkItem(sc->ndis_startitem);
1068 if (sc->ndis_resetitem != NULL)
1069 IoFreeWorkItem(sc->ndis_resetitem);
1070 if (sc->ndis_inputitem != NULL)
1071 IoFreeWorkItem(sc->ndis_inputitem);
1072 if (sc->ndisusb_xferdoneitem != NULL)
1073 IoFreeWorkItem(sc->ndisusb_xferdoneitem);
1074 if (sc->ndisusb_taskitem != NULL)
1075 IoFreeWorkItem(sc->ndisusb_taskitem);
1076
1077 bus_generic_detach(dev);
1078 ndis_unload_driver(sc);
1079
1080 if (sc->ndis_irq)
1081 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
1082 if (sc->ndis_res_io)
1083 bus_release_resource(dev, SYS_RES_IOPORT,
1084 sc->ndis_io_rid, sc->ndis_res_io);
1085 if (sc->ndis_res_mem)
1086 bus_release_resource(dev, SYS_RES_MEMORY,
1087 sc->ndis_mem_rid, sc->ndis_res_mem);
1088 if (sc->ndis_res_altmem)
1089 bus_release_resource(dev, SYS_RES_MEMORY,
1090 sc->ndis_altmem_rid, sc->ndis_res_altmem);
1091
1092 if (ifp != NULL)
1093 if_free(ifp);
1094
1095 if (sc->ndis_iftype == PCMCIABus)
1096 ndis_free_amem(sc);
1097
1098 if (sc->ndis_sc)
1099 ndis_destroy_dma(sc);
1100
1101 if (sc->ndis_txarray)
1102 free(sc->ndis_txarray, M_DEVBUF);
1103
1104 if (!sc->ndis_80211)
1105 ifmedia_removeall(&sc->ifmedia);
1106
1107 if (sc->ndis_txpool != NULL)
1108 NdisFreePacketPool(sc->ndis_txpool);
1109
1110 /* Destroy the PDO for this device. */
1111
1112 if (sc->ndis_iftype == PCIBus)
1113 drv = windrv_lookup(0, "PCI Bus");
1114 else if (sc->ndis_iftype == PCMCIABus)
1115 drv = windrv_lookup(0, "PCCARD Bus");
1116 else
1117 drv = windrv_lookup(0, "USB Bus");
1118 if (drv == NULL)
1119 panic("couldn't find driver object");
1120 windrv_destroy_pdo(drv, dev);
1121
1122 if (sc->ndis_iftype == PCIBus)
1123 bus_dma_tag_destroy(sc->ndis_parent_tag);
1124
1125 return (0);
1126}
1127
1128int
1129ndis_suspend(dev)
1130 device_t dev;
1131{
1132 struct ndis_softc *sc;
1133 struct ifnet *ifp;
1134
1135 sc = device_get_softc(dev);
1136 ifp = sc->ifp;
1137
1138#ifdef notdef
1139 if (NDIS_INITIALIZED(sc))
1140 ndis_stop(sc);
1141#endif
1142
1143 return (0);
1144}
1145
1146int
1147ndis_resume(dev)
1148 device_t dev;
1149{
1150 struct ndis_softc *sc;
1151 struct ifnet *ifp;
1152
1153 sc = device_get_softc(dev);
1154 ifp = sc->ifp;
1155
1156 if (NDIS_INITIALIZED(sc))
1157 ndis_init(sc);
1158
1159 return (0);
1160}
1161
1162/*
1163 * The following bunch of routines are here to support drivers that
1164 * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism.
1165 * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for
1166 * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1167 * miniports.
1168 */
1169static void
1170ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen)
1171 ndis_handle adapter;
1172 ndis_handle ctx;
1173 char *addr;
1174 void *hdr;
1175 uint32_t hdrlen;
1176 void *lookahead;
1177 uint32_t lookaheadlen;
1178 uint32_t pktlen;
1179{
1180 ndis_miniport_block *block;
1181 uint8_t irql = 0;
1182 uint32_t status;
1183 ndis_buffer *b;
1184 ndis_packet *p;
1185 struct mbuf *m;
1186 ndis_ethpriv *priv;
1187
1188 block = adapter;
1189
1190 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1191 if (m == NULL)
1192 return;
1193
1194 /* Save the data provided to us so far. */
1195
1196 m->m_len = lookaheadlen + hdrlen;
1197 m->m_pkthdr.len = pktlen + hdrlen;
1198 m->m_next = NULL;
1199 m_copyback(m, 0, hdrlen, hdr);
1200 m_copyback(m, hdrlen, lookaheadlen, lookahead);
1201
1202 /* Now create a fake NDIS_PACKET to hold the data */
1203
1204 NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1205
1206 if (status != NDIS_STATUS_SUCCESS) {
1207 m_freem(m);
1208 return;
1209 }
1210
1211 p->np_m0 = m;
1212
1213 b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1214
1215 if (b == NULL) {
1216 NdisFreePacket(p);
1217 m_freem(m);
1218 return;
1219 }
1220
1221 p->np_private.npp_head = p->np_private.npp_tail = b;
1222 p->np_private.npp_totlen = m->m_pkthdr.len;
1223
1224 /* Save the packet RX context somewhere. */
1225 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1226 priv->nep_ctx = ctx;
1227
1228 if (!NDIS_SERIALIZED(block))
1229 KeAcquireSpinLock(&block->nmb_lock, &irql);
1230
1231 InsertTailList((&block->nmb_packetlist), (&p->np_list));
1232
1233 if (!NDIS_SERIALIZED(block))
1234 KeReleaseSpinLock(&block->nmb_lock, irql);
1235}
1236
1237/*
1238 * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1239 * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1240 * miniports.
1241 */
1242static void
1243ndis_rxeof_done(adapter)
1244 ndis_handle adapter;
1245{
1246 struct ndis_softc *sc;
1247 ndis_miniport_block *block;
1248
1249 block = adapter;
1250
1251 /* Schedule transfer/RX of queued packets. */
1252
1253 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1254
1255 KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1256}
1257
1258/*
1259 * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1260 */
1261static void
1262ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2)
1263 kdpc *dpc;
1264 ndis_handle adapter;
1265 void *sysarg1;
1266 void *sysarg2;
1267{
1268 ndis_miniport_block *block;
1269 struct ndis_softc *sc;
1270 ndis_packet *p;
1271 list_entry *l;
1272 uint32_t status;
1273 ndis_ethpriv *priv;
1274 struct ifnet *ifp;
1275 struct mbuf *m;
1276
1277 block = adapter;
1278 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1279 ifp = sc->ifp;
1280
1281 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1282
1283 l = block->nmb_packetlist.nle_flink;
1284 while(!IsListEmpty(&block->nmb_packetlist)) {
1285 l = RemoveHeadList((&block->nmb_packetlist));
1286 p = CONTAINING_RECORD(l, ndis_packet, np_list);
1287 InitializeListHead((&p->np_list));
1288
1289 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1290 m = p->np_m0;
1291 p->np_softc = sc;
1292 p->np_m0 = NULL;
1293
1294 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1295
1296 status = MSCALL6(sc->ndis_chars->nmc_transferdata_func,
1297 p, &p->np_private.npp_totlen, block, priv->nep_ctx,
1298 m->m_len, m->m_pkthdr.len - m->m_len);
1299
1300 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1301
1302 /*
1303 * If status is NDIS_STATUS_PENDING, do nothing and
1304 * wait for a callback to the ndis_rxeof_xfr_done()
1305 * handler.
1306 */
1307
1308 m->m_len = m->m_pkthdr.len;
1309 m->m_pkthdr.rcvif = ifp;
1310
1311 if (status == NDIS_STATUS_SUCCESS) {
1312 IoFreeMdl(p->np_private.npp_head);
1313 NdisFreePacket(p);
1314 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1315 mbufq_enqueue(&sc->ndis_rxqueue, m);
1316 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1317 IoQueueWorkItem(sc->ndis_inputitem,
1318 (io_workitem_func)ndis_inputtask_wrap,
1319 WORKQUEUE_CRITICAL, sc);
1320 }
1321
1322 if (status == NDIS_STATUS_FAILURE)
1323 m_freem(m);
1324
1325 /* Advance to next packet */
1326 l = block->nmb_packetlist.nle_flink;
1327 }
1328
1329 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1330}
1331
1332/*
1333 * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1334 */
1335static void
1336ndis_rxeof_xfr_done(adapter, packet, status, len)
1337 ndis_handle adapter;
1338 ndis_packet *packet;
1339 uint32_t status;
1340 uint32_t len;
1341{
1342 ndis_miniport_block *block;
1343 struct ndis_softc *sc;
1344 struct ifnet *ifp;
1345 struct mbuf *m;
1346
1347 block = adapter;
1348 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1349 ifp = sc->ifp;
1350
1351 m = packet->np_m0;
1352 IoFreeMdl(packet->np_private.npp_head);
1353 NdisFreePacket(packet);
1354
1355 if (status != NDIS_STATUS_SUCCESS) {
1356 m_freem(m);
1357 return;
1358 }
1359
1360 m->m_len = m->m_pkthdr.len;
1361 m->m_pkthdr.rcvif = ifp;
1362 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1363 mbufq_enqueue(&sc->ndis_rxqueue, m);
1364 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1365 IoQueueWorkItem(sc->ndis_inputitem,
1366 (io_workitem_func)ndis_inputtask_wrap,
1367 WORKQUEUE_CRITICAL, sc);
1368}
1369/*
1370 * A frame has been uploaded: pass the resulting mbuf chain up to
1371 * the higher level protocols.
1372 *
1373 * When handling received NDIS packets, the 'status' field in the
1374 * out-of-band portion of the ndis_packet has special meaning. In the
1375 * most common case, the underlying NDIS driver will set this field
1376 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1377 * take posession of it. We then change the status field to
1378 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1379 * and that we will return it at some point in the future via the
1380 * return packet handler.
1381 *
1382 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1383 * this means the driver is running out of packet/buffer resources and
1384 * wants to maintain ownership of the packet. In this case, we have to
1385 * copy the packet data into local storage and let the driver keep the
1386 * packet.
1387 */
1388static void
1389ndis_rxeof(adapter, packets, pktcnt)
1390 ndis_handle adapter;
1391 ndis_packet **packets;
1392 uint32_t pktcnt;
1393{
1394 struct ndis_softc *sc;
1395 ndis_miniport_block *block;
1396 ndis_packet *p;
1397 uint32_t s;
1398 ndis_tcpip_csum *csum;
1399 struct ifnet *ifp;
1400 struct mbuf *m0, *m;
1401 int i;
1402
1403 block = (ndis_miniport_block *)adapter;
1404 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1405 ifp = sc->ifp;
1406
1407 /*
1408 * There's a slim chance the driver may indicate some packets
1409 * before we're completely ready to handle them. If we detect this,
1410 * we need to return them to the miniport and ignore them.
1411 */
1412 if (!sc->ndis_running) {
1413 for (i = 0; i < pktcnt; i++) {
1414 p = packets[i];
1415 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1416 p->np_refcnt++;
1417 (void)ndis_return_packet(NULL ,p, block);
1418 }
1419 }
1420 return;
1421 }
1422
1423 for (i = 0; i < pktcnt; i++) {
1424 p = packets[i];
1425 /* Stash the softc here so ptom can use it. */
1426 p->np_softc = sc;
1427 if (ndis_ptom(&m0, p)) {
1428 device_printf(sc->ndis_dev, "ptom failed\n");
1429 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
1430 (void)ndis_return_packet(NULL, p, block);
1431 } else {
1432#ifdef notdef
1433 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1434 m = m_dup(m0, M_NOWAIT);
1435 /*
1436 * NOTE: we want to destroy the mbuf here, but
1437 * we don't actually want to return it to the
1438 * driver via the return packet handler. By
1439 * bumping np_refcnt, we can prevent the
1440 * ndis_return_packet() routine from actually
1441 * doing anything.
1442 */
1443 p->np_refcnt++;
1444 m_freem(m0);
1445 if (m == NULL)
1446 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1447 else
1448 m0 = m;
1449 } else
1450 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1451#endif
1452 m = m_dup(m0, M_NOWAIT);
1453 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1454 p->np_refcnt++;
1455 else
1456 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1457 m_freem(m0);
1458 if (m == NULL) {
1459 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1460 continue;
1461 }
1462 m0 = m;
1463 m0->m_pkthdr.rcvif = ifp;
1464
1465 /* Deal with checksum offload. */
1466
1467 if (ifp->if_capenable & IFCAP_RXCSUM &&
1468 p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1469 s = (uintptr_t)
1470 p->np_ext.npe_info[ndis_tcpipcsum_info];
1471 csum = (ndis_tcpip_csum *)&s;
1472 if (csum->u.ntc_rxflags &
1473 NDIS_RXCSUM_IP_PASSED)
1474 m0->m_pkthdr.csum_flags |=
1475 CSUM_IP_CHECKED|CSUM_IP_VALID;
1476 if (csum->u.ntc_rxflags &
1477 (NDIS_RXCSUM_TCP_PASSED |
1478 NDIS_RXCSUM_UDP_PASSED)) {
1479 m0->m_pkthdr.csum_flags |=
1480 CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
1481 m0->m_pkthdr.csum_data = 0xFFFF;
1482 }
1483 }
1484
1485 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1486 mbufq_enqueue(&sc->ndis_rxqueue, m0);
1487 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1488 IoQueueWorkItem(sc->ndis_inputitem,
1489 (io_workitem_func)ndis_inputtask_wrap,
1490 WORKQUEUE_CRITICAL, sc);
1491 }
1492 }
1493}
1494
1495/*
1496 * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1497 * packets into the stack in order to avoid calling (*ifp->if_input)()
1498 * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1499 * 'dispatch level' per-cpu sleep lock).
1500 */
1501static void
1502ndis_inputtask(device_object *dobj, void *arg)
1503{
1504 ndis_miniport_block *block;
1505 struct ndis_softc *sc = arg;
1506 struct mbuf *m;
1507 uint8_t irql;
1508
1509 block = dobj->do_devext;
1510
1511 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1512 while ((m = mbufq_dequeue(&sc->ndis_rxqueue)) != NULL) {
1513 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1514 if ((sc->ndis_80211 != 0)) {
1515 struct ieee80211com *ic = &sc->ndis_ic;
1516 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1517
1518 if (vap != NULL)
1519 vap->iv_deliver_data(vap, vap->iv_bss, m);
1520 } else {
1521 struct ifnet *ifp = sc->ifp;
1522
1523 (*ifp->if_input)(ifp, m);
1524 }
1525 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1526 }
1527 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1528}
1529
1530/*
1531 * A frame was downloaded to the chip. It's safe for us to clean up
1532 * the list buffers.
1533 */
1534static void
1535ndis_txeof(adapter, packet, status)
1536 ndis_handle adapter;
1537 ndis_packet *packet;
1538 ndis_status status;
1539
1540{
1541 struct ndis_softc *sc;
1542 ndis_miniport_block *block;
1543 struct ifnet *ifp;
1544 int idx;
1545 struct mbuf *m;
1546
1547 block = (ndis_miniport_block *)adapter;
1548 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1549 ifp = sc->ifp;
1550
1551 m = packet->np_m0;
1552 idx = packet->np_txidx;
1553 if (sc->ndis_sc)
1554 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1555
1556 ndis_free_packet(packet);
1557 m_freem(m);
1558
1559 NDIS_LOCK(sc);
1560 sc->ndis_txarray[idx] = NULL;
1561 sc->ndis_txpending++;
1562
1563 if (status == NDIS_STATUS_SUCCESS)
1564 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
1565 else
1566 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1567
1568 sc->ndis_tx_timer = 0;
1569 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1570
1571 NDIS_UNLOCK(sc);
1572
1573 IoQueueWorkItem(sc->ndis_startitem,
1574 (io_workitem_func)ndis_starttask_wrap,
1575 WORKQUEUE_CRITICAL, ifp);
1576}
1577
1578static void
1579ndis_linksts(adapter, status, sbuf, slen)
1580 ndis_handle adapter;
1581 ndis_status status;
1582 void *sbuf;
1583 uint32_t slen;
1584{
1585 ndis_miniport_block *block;
1586 struct ndis_softc *sc;
1587
1588 block = adapter;
1589 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1590 sc->ndis_sts = status;
1591
1592 /* Event list is all full up, drop this one. */
1593
1594 NDIS_LOCK(sc);
1595 if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1596 NDIS_UNLOCK(sc);
1597 return;
1598 }
1599
1600 /* Cache the event. */
1601
1602 if (slen) {
1603 sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen,
1604 M_TEMP, M_NOWAIT);
1605 if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1606 NDIS_UNLOCK(sc);
1607 return;
1608 }
1609 bcopy((char *)sbuf,
1610 sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1611 }
1612 sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status;
1613 sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen;
1614 NDIS_EVTINC(sc->ndis_evtpidx);
1615 NDIS_UNLOCK(sc);
1616}
1617
1618static void
1619ndis_linksts_done(adapter)
1620 ndis_handle adapter;
1621{
1622 ndis_miniport_block *block;
1623 struct ndis_softc *sc;
1624 struct ifnet *ifp;
1625
1626 block = adapter;
1627 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1628 ifp = sc->ifp;
1629
1630 if (!NDIS_INITIALIZED(sc))
1631 return;
1632
1633 switch (sc->ndis_sts) {
1634 case NDIS_STATUS_MEDIA_CONNECT:
1635 IoQueueWorkItem(sc->ndis_tickitem,
1636 (io_workitem_func)ndis_ticktask_wrap,
1637 WORKQUEUE_CRITICAL, sc);
1638 IoQueueWorkItem(sc->ndis_startitem,
1639 (io_workitem_func)ndis_starttask_wrap,
1640 WORKQUEUE_CRITICAL, ifp);
1641 break;
1642 case NDIS_STATUS_MEDIA_DISCONNECT:
1643 if (sc->ndis_link)
1644 IoQueueWorkItem(sc->ndis_tickitem,
1645 (io_workitem_func)ndis_ticktask_wrap,
1646 WORKQUEUE_CRITICAL, sc);
1647 break;
1648 default:
1649 break;
1650 }
1651}
1652
1653static void
1654ndis_tick(xsc)
1655 void *xsc;
1656{
1657 struct ndis_softc *sc;
1658
1659 sc = xsc;
1660
1661 if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) {
1662 IoQueueWorkItem(sc->ndis_tickitem,
1663 (io_workitem_func)ndis_ticktask_wrap,
1664 WORKQUEUE_CRITICAL, sc);
1665 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1666 }
1667
1668 if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) {
1669 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
1670 device_printf(sc->ndis_dev, "watchdog timeout\n");
1671
1672 IoQueueWorkItem(sc->ndis_resetitem,
1673 (io_workitem_func)ndis_resettask_wrap,
1674 WORKQUEUE_CRITICAL, sc);
1675 IoQueueWorkItem(sc->ndis_startitem,
1676 (io_workitem_func)ndis_starttask_wrap,
1677 WORKQUEUE_CRITICAL, sc->ifp);
1678 }
1679
1680 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1681}
1682
1683static void
1684ndis_ticktask(device_object *d, void *xsc)
1685{
1686 struct ndis_softc *sc = xsc;
1687 ndis_checkforhang_handler hangfunc;
1688 uint8_t rval;
1689
1690 NDIS_LOCK(sc);
1691 if (!NDIS_INITIALIZED(sc)) {
1692 NDIS_UNLOCK(sc);
1693 return;
1694 }
1695 NDIS_UNLOCK(sc);
1696
1697 hangfunc = sc->ndis_chars->nmc_checkhang_func;
1698
1699 if (hangfunc != NULL) {
1700 rval = MSCALL1(hangfunc,
1701 sc->ndis_block->nmb_miniportadapterctx);
1702 if (rval == TRUE) {
1703 ndis_reset_nic(sc);
1704 return;
1705 }
1706 }
1707
1708 NDIS_LOCK(sc);
1709 if (sc->ndis_link == 0 &&
1710 sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
1711 sc->ndis_link = 1;
1712 if (sc->ndis_80211 != 0) {
1713 struct ieee80211com *ic = &sc->ndis_ic;
1714 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1715
1716 if (vap != NULL) {
1717 NDIS_UNLOCK(sc);
1718 ndis_getstate_80211(sc);
1719 ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1720 NDIS_LOCK(sc);
1721 if_link_state_change(vap->iv_ifp,
1722 LINK_STATE_UP);
1723 }
1724 } else
1725 if_link_state_change(sc->ifp, LINK_STATE_UP);
1726 }
1727
1728 if (sc->ndis_link == 1 &&
1729 sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1730 sc->ndis_link = 0;
1731 if (sc->ndis_80211 != 0) {
1732 struct ieee80211com *ic = &sc->ndis_ic;
1733 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1734
1735 if (vap != NULL) {
1736 NDIS_UNLOCK(sc);
1737 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1738 NDIS_LOCK(sc);
1739 if_link_state_change(vap->iv_ifp,
1740 LINK_STATE_DOWN);
1741 }
1742 } else
1743 if_link_state_change(sc->ifp, LINK_STATE_DOWN);
1744 }
1745
1746 NDIS_UNLOCK(sc);
1747}
1748
1749static void
1750ndis_map_sclist(arg, segs, nseg, mapsize, error)
1751 void *arg;
1752 bus_dma_segment_t *segs;
1753 int nseg;
1754 bus_size_t mapsize;
1755 int error;
1756
1757{
1758 struct ndis_sc_list *sclist;
1759 int i;
1760
1761 if (error || arg == NULL)
1762 return;
1763
1764 sclist = arg;
1765
1766 sclist->nsl_frags = nseg;
1767
1768 for (i = 0; i < nseg; i++) {
1769 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1770 sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1771 }
1772}
1773
1774static int
1775ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1776 const struct ieee80211_bpf_params *params)
1777{
1778 /* no support; just discard */
1779 m_freem(m);
1780 ieee80211_free_node(ni);
1781 return (0);
1782}
1783
1784static void
1785ndis_update_mcast(struct ieee80211com *ic)
1786{
1787 struct ndis_softc *sc = ic->ic_softc;
1788
1789 ndis_setmulti(sc);
1790}
1791
1792static void
1793ndis_update_promisc(struct ieee80211com *ic)
1794{
1795 /* not supported */
1796}
1797
1798static void
1799ndis_starttask(d, arg)
1800 device_object *d;
1801 void *arg;
1802{
1803 struct ifnet *ifp;
1804
1805 ifp = arg;
1806
1807 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1808 ndis_start(ifp);
1809}
1810
1811/*
1812 * Main transmit routine. To make NDIS drivers happy, we need to
1813 * transform mbuf chains into NDIS packets and feed them to the
1814 * send packet routines. Most drivers allow you to send several
1815 * packets at once (up to the maxpkts limit). Unfortunately, rather
1816 * that accepting them in the form of a linked list, they expect
1817 * a contiguous array of pointers to packets.
1818 *
1819 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1820 * we need to perform busdma work here. Those that use map registers
1821 * will do the mapping themselves on a buffer by buffer basis.
1822 */
1823static void
1824ndis_start(ifp)
1825 struct ifnet *ifp;
1826{
1827 struct ndis_softc *sc;
1828 struct mbuf *m = NULL;
1829 ndis_packet **p0 = NULL, *p = NULL;
1830 ndis_tcpip_csum *csum;
1831 int pcnt = 0, status;
1832
1833 sc = ifp->if_softc;
1834
1835 NDIS_LOCK(sc);
1836 if (!sc->ndis_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) {
1837 NDIS_UNLOCK(sc);
1838 return;
1839 }
1840
1841 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1842
1843 while(sc->ndis_txpending) {
1844 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1845 if (m == NULL)
1846 break;
1847
1848 NdisAllocatePacket(&status,
1849 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1850
1851 if (status != NDIS_STATUS_SUCCESS)
1852 break;
1853
1854 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1855 IFQ_DRV_PREPEND(&ifp->if_snd, m);
1856 NDIS_UNLOCK(sc);
1857 return;
1858 }
1859
1860 /*
1861 * Save pointer to original mbuf
1862 * so we can free it later.
1863 */
1864
1865 p = sc->ndis_txarray[sc->ndis_txidx];
1866 p->np_txidx = sc->ndis_txidx;
1867 p->np_m0 = m;
1868 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1869
1870 /*
1871 * Do scatter/gather processing, if driver requested it.
1872 */
1873 if (sc->ndis_sc) {
1874 bus_dmamap_load_mbuf(sc->ndis_ttag,
1875 sc->ndis_tmaps[sc->ndis_txidx], m,
1876 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1877 bus_dmamap_sync(sc->ndis_ttag,
1878 sc->ndis_tmaps[sc->ndis_txidx],
1879 BUS_DMASYNC_PREREAD);
1880 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1881 }
1882
1883 /* Handle checksum offload. */
1884
1885 if (ifp->if_capenable & IFCAP_TXCSUM &&
1886 m->m_pkthdr.csum_flags) {
1887 csum = (ndis_tcpip_csum *)
1888 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1889 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1890 if (m->m_pkthdr.csum_flags & CSUM_IP)
1891 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1892 if (m->m_pkthdr.csum_flags & CSUM_TCP)
1893 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1894 if (m->m_pkthdr.csum_flags & CSUM_UDP)
1895 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1896 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1897 }
1898
1899 NDIS_INC(sc);
1900 sc->ndis_txpending--;
1901
1902 pcnt++;
1903
1904 /*
1905 * If there's a BPF listener, bounce a copy of this frame
1906 * to him.
1907 */
1908 if (!sc->ndis_80211) /* XXX handle 80211 */
1909 BPF_MTAP(ifp, m);
1910
1911 /*
1912 * The array that p0 points to must appear contiguous,
1913 * so we must not wrap past the end of sc->ndis_txarray[].
1914 * If it looks like we're about to wrap, break out here
1915 * so the this batch of packets can be transmitted, then
1916 * wait for txeof to ask us to send the rest.
1917 */
1918 if (sc->ndis_txidx == 0)
1919 break;
1920 }
1921
1922 if (pcnt == 0) {
1923 NDIS_UNLOCK(sc);
1924 return;
1925 }
1926
1927 if (sc->ndis_txpending == 0)
1928 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1929
1930 /*
1931 * Set a timeout in case the chip goes out to lunch.
1932 */
1933 sc->ndis_tx_timer = 5;
1934
1935 NDIS_UNLOCK(sc);
1936
1937 /*
1938 * According to NDIS documentation, if a driver exports
1939 * a MiniportSendPackets() routine, we prefer that over
1940 * a MiniportSend() routine (which sends just a single
1941 * packet).
1942 */
1943 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1944 ndis_send_packets(sc, p0, pcnt);
1945 else
1946 ndis_send_packet(sc, p);
1947
1948 return;
1949}
1950
1951static int
1952ndis_80211transmit(struct ieee80211com *ic, struct mbuf *m)
1953{
1954 struct ndis_softc *sc = ic->ic_softc;
1955 ndis_packet **p0 = NULL, *p = NULL;
1956 int status;
1957
1958 NDIS_LOCK(sc);
1959 if (!sc->ndis_link || !sc->ndis_running) {
1960 NDIS_UNLOCK(sc);
1961 return (ENXIO);
1962 }
1963
1964 if (sc->ndis_txpending == 0) {
1965 NDIS_UNLOCK(sc);
1966 return (ENOBUFS);
1967 }
1968
1969 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1970
1971 NdisAllocatePacket(&status,
1972 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1973
1974 if (status != NDIS_STATUS_SUCCESS) {
1975 NDIS_UNLOCK(sc);
1976 return (ENOBUFS);
1977 }
1978
1979 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1980 NDIS_UNLOCK(sc);
1981 return (ENOBUFS);
1982 }
1983
1984 /*
1985 * Save pointer to original mbuf
1986 * so we can free it later.
1987 */
1988
1989 p = sc->ndis_txarray[sc->ndis_txidx];
1990 p->np_txidx = sc->ndis_txidx;
1991 p->np_m0 = m;
1992 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1993
1994 /*
1995 * Do scatter/gather processing, if driver requested it.
1996 */
1997 if (sc->ndis_sc) {
1998 bus_dmamap_load_mbuf(sc->ndis_ttag,
1999 sc->ndis_tmaps[sc->ndis_txidx], m,
2000 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
2001 bus_dmamap_sync(sc->ndis_ttag,
2002 sc->ndis_tmaps[sc->ndis_txidx],
2003 BUS_DMASYNC_PREREAD);
2004 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
2005 }
2006
2007 NDIS_INC(sc);
2008 sc->ndis_txpending--;
2009
2010 /*
2011 * Set a timeout in case the chip goes out to lunch.
2012 */
2013 sc->ndis_tx_timer = 5;
2014 NDIS_UNLOCK(sc);
2015
2016 /*
2017 * According to NDIS documentation, if a driver exports
2018 * a MiniportSendPackets() routine, we prefer that over
2019 * a MiniportSend() routine (which sends just a single
2020 * packet).
2021 */
2022 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
2023 ndis_send_packets(sc, p0, 1);
2024 else
2025 ndis_send_packet(sc, p);
2026
2027 return (0);
2028}
2029
2030static void
2031ndis_80211parent(struct ieee80211com *ic)
2032{
2033 struct ndis_softc *sc = ic->ic_softc;
2034
2035 /*NDIS_LOCK(sc);*/
2036 if (ic->ic_nrunning > 0) {
2037 if (!sc->ndis_running)
2038 ndis_init(sc);
2039 } else if (sc->ndis_running)
2040 ndis_stop(sc);
2041 /*NDIS_UNLOCK(sc);*/
2042}
2043
2044static void
2045ndis_init(void *xsc)
2046{
2047 struct ndis_softc *sc = xsc;
2048 int i, len, error;
2049
2050 /*
2051 * Avoid reintializing the link unnecessarily.
2052 * This should be dealt with in a better way by
2053 * fixing the upper layer modules so they don't
2054 * call ifp->if_init() quite as often.
2055 */
2056 if (sc->ndis_link)
2057 return;
2058
2059 /*
2060 * Cancel pending I/O and free all RX/TX buffers.
2061 */
2062 ndis_stop(sc);
2063
2064 if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
2065 error = ndis_init_nic(sc);
2066 if (error != 0) {
2067 device_printf(sc->ndis_dev,
2068 "failed to initialize the device: %d\n", error);
2069 return;
2070 }
2071 }
2072
2073 /* Program the packet filter */
2074 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED |
2075 NDIS_PACKET_TYPE_BROADCAST;
2076
2077 if (sc->ndis_80211) {
2078 struct ieee80211com *ic = &sc->ndis_ic;
2079
2080 if (ic->ic_promisc > 0)
2081 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2082 } else {
2083 struct ifnet *ifp = sc->ifp;
2084
2085 if (ifp->if_flags & IFF_PROMISC)
2086 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2087 }
2088
2089 len = sizeof(sc->ndis_filter);
2090
2091 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
2092 &sc->ndis_filter, &len);
2093
2094 if (error)
2095 device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
2096
2097 /*
2098 * Set lookahead.
2099 */
2100 if (sc->ndis_80211)
2101 i = ETHERMTU;
2102 else
2103 i = sc->ifp->if_mtu;
2104 len = sizeof(i);
2105 ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
2106
2107 /*
2108 * Program the multicast filter, if necessary.
2109 */
2110 ndis_setmulti(sc);
2111
2112 /* Setup task offload. */
2113 ndis_set_offload(sc);
2114
2115 NDIS_LOCK(sc);
2116
2117 sc->ndis_txidx = 0;
2118 sc->ndis_txpending = sc->ndis_maxpkts;
2119 sc->ndis_link = 0;
2120
2121 if (!sc->ndis_80211) {
2122 if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN);
2123 sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
2124 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2125 }
2126
2127 sc->ndis_tx_timer = 0;
2128
2129 /*
2130 * Some drivers don't set this value. The NDIS spec says
2131 * the default checkforhang timeout is "approximately 2
2132 * seconds." We use 3 seconds, because it seems for some
2133 * drivers, exactly 2 seconds is too fast.
2134 */
2135 if (sc->ndis_block->nmb_checkforhangsecs == 0)
2136 sc->ndis_block->nmb_checkforhangsecs = 3;
2137
2138 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
2139 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
2140 sc->ndis_running = 1;
2141 NDIS_UNLOCK(sc);
2142
2143 /* XXX force handling */
2144 if (sc->ndis_80211)
2145 ieee80211_start_all(&sc->ndis_ic); /* start all vap's */
2146}
2147
2148/*
2149 * Set media options.
2150 */
2151static int
2152ndis_ifmedia_upd(ifp)
2153 struct ifnet *ifp;
2154{
2155 struct ndis_softc *sc;
2156
2157 sc = ifp->if_softc;
2158
2159 if (NDIS_INITIALIZED(sc))
2160 ndis_init(sc);
2161
2162 return (0);
2163}
2164
2165/*
2166 * Report current media status.
2167 */
2168static void
2169ndis_ifmedia_sts(ifp, ifmr)
2170 struct ifnet *ifp;
2171 struct ifmediareq *ifmr;
2172{
2173 struct ndis_softc *sc;
2174 uint32_t media_info;
2175 ndis_media_state linkstate;
2176 int len;
2177
2178 ifmr->ifm_status = IFM_AVALID;
2179 ifmr->ifm_active = IFM_ETHER;
2180 sc = ifp->if_softc;
2181
2182 if (!NDIS_INITIALIZED(sc))
2183 return;
2184
2185 len = sizeof(linkstate);
2186 ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2187 (void *)&linkstate, &len);
2188
2189 len = sizeof(media_info);
2190 ndis_get_info(sc, OID_GEN_LINK_SPEED,
2191 (void *)&media_info, &len);
2192
2193 if (linkstate == nmc_connected)
2194 ifmr->ifm_status |= IFM_ACTIVE;
2195
2196 switch (media_info) {
2197 case 100000:
2198 ifmr->ifm_active |= IFM_10_T;
2199 break;
2200 case 1000000:
2201 ifmr->ifm_active |= IFM_100_TX;
2202 break;
2203 case 10000000:
2204 ifmr->ifm_active |= IFM_1000_T;
2205 break;
2206 default:
2207 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2208 break;
2209 }
2210}
2211
2212static int
2213ndis_set_cipher(struct ndis_softc *sc, int cipher)
2214{
2215 struct ieee80211com *ic = &sc->ndis_ic;
2216 int rval = 0, len;
2217 uint32_t arg, save;
2218
2219 len = sizeof(arg);
2220
2221 if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2222 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2223 return (ENOTSUP);
2224 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2225 }
2226
2227 if (cipher == WPA_CSE_TKIP) {
2228 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2229 return (ENOTSUP);
2230 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2231 }
2232
2233 if (cipher == WPA_CSE_CCMP) {
2234 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2235 return (ENOTSUP);
2236 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2237 }
2238
2239 DPRINTF(("Setting cipher to %d\n", arg));
2240 save = arg;
2241 rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2242
2243 if (rval)
2244 return (rval);
2245
2246 /* Check that the cipher was set correctly. */
2247
2248 len = sizeof(save);
2249 rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2250
2251 if (rval != 0 || arg != save)
2252 return (ENODEV);
2253
2254 return (0);
2255}
2256
2257/*
2258 * WPA is hairy to set up. Do the work in a separate routine
2259 * so we don't clutter the setstate function too much.
2260 * Important yet undocumented fact: first we have to set the
2261 * authentication mode, _then_ we enable the ciphers. If one
2262 * of the WPA authentication modes isn't enabled, the driver
2263 * might not permit the TKIP or AES ciphers to be selected.
2264 */
2265static int
2266ndis_set_wpa(sc, ie, ielen)
2267 struct ndis_softc *sc;
2268 void *ie;
2269 int ielen;
2270{
2271 struct ieee80211_ie_wpa *w;
2272 struct ndis_ie *n;
2273 char *pos;
2274 uint32_t arg;
2275 int i;
2276
2277 /*
2278 * Apparently, the only way for us to know what ciphers
2279 * and key management/authentication mode to use is for
2280 * us to inspect the optional information element (IE)
2281 * stored in the 802.11 state machine. This IE should be
2282 * supplied by the WPA supplicant.
2283 */
2284
2285 w = (struct ieee80211_ie_wpa *)ie;
2286
2287 /* Check for the right kind of IE. */
2288 if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2289 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2290 return (EINVAL);
2291 }
2292
2293 /* Skip over the ucast cipher OIDs. */
2294 pos = (char *)&w->wpa_uciphers[0];
2295 pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2296
2297 /* Skip over the authmode count. */
2298 pos += sizeof(u_int16_t);
2299
2300 /*
2301 * Check for the authentication modes. I'm
2302 * pretty sure there's only supposed to be one.
2303 */
2304
2305 n = (struct ndis_ie *)pos;
2306 if (n->ni_val == WPA_ASE_NONE)
2307 arg = NDIS_80211_AUTHMODE_WPANONE;
2308
2309 if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2310 arg = NDIS_80211_AUTHMODE_WPA;
2311
2312 if (n->ni_val == WPA_ASE_8021X_PSK)
2313 arg = NDIS_80211_AUTHMODE_WPAPSK;
2314
2315 DPRINTF(("Setting WPA auth mode to %d\n", arg));
2316 i = sizeof(arg);
2317 if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2318 return (ENOTSUP);
2319 i = sizeof(arg);
2320 ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2321
2322 /* Now configure the desired ciphers. */
2323
2324 /* First, set up the multicast group cipher. */
2325 n = (struct ndis_ie *)&w->wpa_mcipher[0];
2326
2327 if (ndis_set_cipher(sc, n->ni_val))
2328 return (ENOTSUP);
2329
2330 /* Now start looking around for the unicast ciphers. */
2331 pos = (char *)&w->wpa_uciphers[0];
2332 n = (struct ndis_ie *)pos;
2333
2334 for (i = 0; i < w->wpa_uciphercnt; i++) {
2335 if (ndis_set_cipher(sc, n->ni_val))
2336 return (ENOTSUP);
2337 n++;
2338 }
2339
2340 return (0);
2341}
2342
2343static void
2344ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2345{
2346 struct ieee80211vap *vap = ifp->if_softc;
2347 struct ndis_softc *sc = vap->iv_ic->ic_softc;
2348 uint32_t txrate;
2349 int len;
2350
2351 if (!NDIS_INITIALIZED(sc))
2352 return;
2353
2354 len = sizeof(txrate);
2355 if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0)
2356 vap->iv_bss->ni_txrate = txrate / 5000;
2357 ieee80211_media_status(ifp, imr);
2358}
2359
2360static void
2361ndis_setstate_80211(struct ndis_softc *sc)
2362{
2363 struct ieee80211com *ic = &sc->ndis_ic;
2364 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2365 ndis_80211_macaddr bssid;
2366 ndis_80211_config config;
2367 int rval = 0, len;
2368 uint32_t arg;
2369
2370 if (!NDIS_INITIALIZED(sc)) {
2371 DPRINTF(("%s: NDIS not initialized\n", __func__));
2372 return;
2373 }
2374
2375 /* Disassociate and turn off radio. */
2376 len = sizeof(arg);
2377 arg = 1;
2378 ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2379
2380 /* Set network infrastructure mode. */
2381
2382 len = sizeof(arg);
2383 if (ic->ic_opmode == IEEE80211_M_IBSS)
2384 arg = NDIS_80211_NET_INFRA_IBSS;
2385 else
2386 arg = NDIS_80211_NET_INFRA_BSS;
2387
2388 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2389
2390 if (rval)
2391 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2392
2393 /* Set power management */
2394 len = sizeof(arg);
2395 if (vap->iv_flags & IEEE80211_F_PMGTON)
2396 arg = NDIS_80211_POWERMODE_FAST_PSP;
2397 else
2398 arg = NDIS_80211_POWERMODE_CAM;
2399 ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2400
2401 /* Set TX power */
2402 if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2403 ic->ic_txpowlimit < nitems(dBm2mW)) {
2404 arg = dBm2mW[ic->ic_txpowlimit];
2405 len = sizeof(arg);
2406 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2407 }
2408
2409 /*
2410 * Default encryption mode to off, authentication
2411 * to open and privacy to 'accept everything.'
2412 */
2413 len = sizeof(arg);
2414 arg = NDIS_80211_WEPSTAT_DISABLED;
2415 ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2416
2417 len = sizeof(arg);
2418 arg = NDIS_80211_AUTHMODE_OPEN;
2419 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2420
2421 /*
2422 * Note that OID_802_11_PRIVACY_FILTER is optional:
2423 * not all drivers implement it.
2424 */
2425 len = sizeof(arg);
2426 arg = NDIS_80211_PRIVFILT_8021XWEP;
2427 ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2428
2429 len = sizeof(config);
2430 bzero((char *)&config, len);
2431 config.nc_length = len;
2432 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2433 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
2434
2435 /*
2436 * Some drivers expect us to initialize these values, so
2437 * provide some defaults.
2438 */
2439
2440 if (config.nc_beaconperiod == 0)
2441 config.nc_beaconperiod = 100;
2442 if (config.nc_atimwin == 0)
2443 config.nc_atimwin = 100;
2444 if (config.nc_fhconfig.ncf_dwelltime == 0)
2445 config.nc_fhconfig.ncf_dwelltime = 200;
2446 if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
2447 int chan, chanflag;
2448
2449 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2450 chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ :
2451 IEEE80211_CHAN_5GHZ;
2452 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2453 config.nc_dsconfig =
2454 ic->ic_bsschan->ic_freq * 1000;
2455 len = sizeof(config);
2456 config.nc_length = len;
2457 config.nc_fhconfig.ncf_length =
2458 sizeof(ndis_80211_config_fh);
2459 DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2460 rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2461 &config, &len);
2462 if (rval)
2463 device_printf(sc->ndis_dev, "couldn't change "
2464 "DS config to %ukHz: %d\n",
2465 config.nc_dsconfig, rval);
2466 }
2467 } else if (rval)
2468 device_printf(sc->ndis_dev, "couldn't retrieve "
2469 "channel info: %d\n", rval);
2470
2471 /* Set the BSSID to our value so the driver doesn't associate */
2472 len = IEEE80211_ADDR_LEN;
2473 bcopy(vap->iv_myaddr, bssid, len);
2474 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2475 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2476 if (rval)
2477 device_printf(sc->ndis_dev,
2478 "setting BSSID failed: %d\n", rval);
2479}
2480
2481static void
2482ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap)
2483{
2484 struct ieee80211_node *ni = vap->iv_bss;
2485 ndis_80211_ssid ssid;
2486 ndis_80211_macaddr bssid;
2487 ndis_80211_wep wep;
2488 int i, rval = 0, len, error;
2489 uint32_t arg;
2490
2491 if (!NDIS_INITIALIZED(sc)) {
2492 DPRINTF(("%s: NDIS not initialized\n", __func__));
2493 return;
2494 }
2495
2496 /* Initial setup */
2497 ndis_setstate_80211(sc);
2498
2499 /* Set network infrastructure mode. */
2500
2501 len = sizeof(arg);
2502 if (vap->iv_opmode == IEEE80211_M_IBSS)
2503 arg = NDIS_80211_NET_INFRA_IBSS;
2504 else
2505 arg = NDIS_80211_NET_INFRA_BSS;
2506
2507 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2508
2509 if (rval)
2510 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2511
2512 /* Set RTS threshold */
2513
2514 len = sizeof(arg);
2515 arg = vap->iv_rtsthreshold;
2516 ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2517
2518 /* Set fragmentation threshold */
2519
2520 len = sizeof(arg);
2521 arg = vap->iv_fragthreshold;
2522 ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2523
2524 /* Set WEP */
2525
2526 if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2527 !(vap->iv_flags & IEEE80211_F_WPA)) {
2528 int keys_set = 0;
2529
2530 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2531 len = sizeof(arg);
2532 arg = NDIS_80211_AUTHMODE_SHARED;
2533 DPRINTF(("Setting shared auth\n"));
2534 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2535 &arg, &len);
2536 }
2537 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2538 if (vap->iv_nw_keys[i].wk_keylen) {
2539 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2540 IEEE80211_CIPHER_WEP)
2541 continue;
2542 bzero((char *)&wep, sizeof(wep));
2543 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2544
2545 /*
2546 * 5, 13 and 16 are the only valid
2547 * key lengths. Anything in between
2548 * will be zero padded out to the
2549 * next highest boundary.
2550 */
2551 if (vap->iv_nw_keys[i].wk_keylen < 5)
2552 wep.nw_keylen = 5;
2553 else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2554 vap->iv_nw_keys[i].wk_keylen < 13)
2555 wep.nw_keylen = 13;
2556 else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2557 vap->iv_nw_keys[i].wk_keylen < 16)
2558 wep.nw_keylen = 16;
2559
2560 wep.nw_keyidx = i;
2561 wep.nw_length = (sizeof(uint32_t) * 3)
2562 + wep.nw_keylen;
2563 if (i == vap->iv_def_txkey)
2564 wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2565 bcopy(vap->iv_nw_keys[i].wk_key,
2566 wep.nw_keydata, wep.nw_length);
2567 len = sizeof(wep);
2568 DPRINTF(("Setting WEP key %d\n", i));
2569 rval = ndis_set_info(sc,
2570 OID_802_11_ADD_WEP, &wep, &len);
2571 if (rval)
2572 device_printf(sc->ndis_dev,
2573 "set wepkey failed: %d\n", rval);
2574 keys_set++;
2575 }
2576 }
2577 if (keys_set) {
2578 DPRINTF(("Setting WEP on\n"));
2579 arg = NDIS_80211_WEPSTAT_ENABLED;
2580 len = sizeof(arg);
2581 rval = ndis_set_info(sc,
2582 OID_802_11_WEP_STATUS, &arg, &len);
2583 if (rval)
2584 device_printf(sc->ndis_dev,
2585 "enable WEP failed: %d\n", rval);
2586 if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2587 arg = NDIS_80211_PRIVFILT_8021XWEP;
2588 else
2589 arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2590
2591 len = sizeof(arg);
2592 ndis_set_info(sc,
2593 OID_802_11_PRIVACY_FILTER, &arg, &len);
2594 }
2595 }
2596
2597 /* Set up WPA. */
2598 if ((vap->iv_flags & IEEE80211_F_WPA) &&
2599 vap->iv_appie_assocreq != NULL) {
2600 struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2601 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2602 if (error != 0)
2603 device_printf(sc->ndis_dev, "WPA setup failed\n");
2604 }
2605
2606#ifdef notyet
2607 /* Set network type. */
2608
2609 arg = 0;
2610
2611 switch (vap->iv_curmode) {
2612 case IEEE80211_MODE_11A:
2613 arg = NDIS_80211_NETTYPE_11OFDM5;
2614 break;
2615 case IEEE80211_MODE_11B:
2616 arg = NDIS_80211_NETTYPE_11DS;
2617 break;
2618 case IEEE80211_MODE_11G:
2619 arg = NDIS_80211_NETTYPE_11OFDM24;
2620 break;
2621 default:
2622 device_printf(sc->ndis_dev, "unknown mode: %d\n",
2623 vap->iv_curmode);
2624 }
2625
2626 if (arg) {
2627 DPRINTF(("Setting network type to %d\n", arg));
2628 len = sizeof(arg);
2629 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2630 &arg, &len);
2631 if (rval)
2632 device_printf(sc->ndis_dev,
2633 "set nettype failed: %d\n", rval);
2634 }
2635#endif
2636
2637 /*
2638 * If the user selected a specific BSSID, try
2639 * to use that one. This is useful in the case where
2640 * there are several APs in range with the same network
2641 * name. To delete the BSSID, we use the broadcast
2642 * address as the BSSID.
2643 * Note that some drivers seem to allow setting a BSSID
2644 * in ad-hoc mode, which has the effect of forcing the
2645 * NIC to create an ad-hoc cell with a specific BSSID,
2646 * instead of a randomly chosen one. However, the net80211
2647 * code makes the assumtion that the BSSID setting is invalid
2648 * when you're in ad-hoc mode, so we don't allow that here.
2649 */
2650
2651 len = IEEE80211_ADDR_LEN;
2652 if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2653 vap->iv_opmode != IEEE80211_M_IBSS)
2654 bcopy(ni->ni_bssid, bssid, len);
2655 else
2656 bcopy(ieee80211broadcastaddr, bssid, len);
2657
2658 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2659 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2660 if (rval)
2661 device_printf(sc->ndis_dev,
2662 "setting BSSID failed: %d\n", rval);
2663
2664 /* Set SSID -- always do this last. */
2665
2666#ifdef NDIS_DEBUG
2667 if (ndis_debug > 0) {
2668 printf("Setting ESSID to ");
2669 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2670 printf("\n");
2671 }
2672#endif
2673
2674 len = sizeof(ssid);
2675 bzero((char *)&ssid, len);
2676 ssid.ns_ssidlen = ni->ni_esslen;
2677 if (ssid.ns_ssidlen == 0) {
2678 ssid.ns_ssidlen = 1;
2679 } else
2680 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2681
2682 rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2683
2684 if (rval)
2685 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2686
2687 return;
2688}
2689
2690static int
2691ndis_get_bssid_list(sc, bl)
2692 struct ndis_softc *sc;
2693 ndis_80211_bssid_list_ex **bl;
2694{
2695 int len, error;
2696
2697 len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2698 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2699 if (*bl == NULL)
2700 return (ENOMEM);
2701
2702 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2703 if (error == ENOSPC) {
2704 free(*bl, M_DEVBUF);
2705 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2706 if (*bl == NULL)
2707 return (ENOMEM);
2708
2709 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2710 }
2711 if (error) {
2712 DPRINTF(("%s: failed to read\n", __func__));
2713 free(*bl, M_DEVBUF);
2714 return (error);
2715 }
2716
2717 return (0);
2718}
2719
2720static int
2721ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc)
2722{
2723 struct ieee80211com *ic = &sc->ndis_ic;
2724 struct ieee80211vap *vap;
2725 struct ieee80211_node *ni;
2726 ndis_80211_bssid_list_ex *bl;
2727 ndis_wlan_bssid_ex *bs;
2728 ndis_80211_macaddr bssid;
2729 int i, len, error;
2730
2731 if (!sc->ndis_link)
2732 return (ENOENT);
2733
2734 len = sizeof(bssid);
2735 error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2736 if (error) {
2737 device_printf(sc->ndis_dev, "failed to get bssid\n");
2738 return (ENOENT);
2739 }
2740
2741 vap = TAILQ_FIRST(&ic->ic_vaps);
2742 ni = vap->iv_bss;
2743
2744 error = ndis_get_bssid_list(sc, &bl);
2745 if (error)
2746 return (error);
2747
2748 bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2749 for (i = 0; i < bl->nblx_items; i++) {
2750 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2751 *assoc = malloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2752 if (*assoc == NULL) {
2753 free(bl, M_TEMP);
2754 return (ENOMEM);
2755 }
2756 bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2757 free(bl, M_TEMP);
2758 if (ic->ic_opmode == IEEE80211_M_STA)
2759 ni->ni_associd = 1 | 0xc000; /* fake associd */
2760 return (0);
2761 }
2762 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2763 }
2764
2765 free(bl, M_TEMP);
2766 return (ENOENT);
2767}
2768
2769static void
2770ndis_getstate_80211(struct ndis_softc *sc)
2771{
2772 struct ieee80211com *ic = &sc->ndis_ic;
2773 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2774 struct ieee80211_node *ni = vap->iv_bss;
2775 ndis_wlan_bssid_ex *bs;
2776 int rval, len, i = 0;
2777 int chanflag;
2778 uint32_t arg;
2779
2780 if (!NDIS_INITIALIZED(sc))
2781 return;
2782
2783 if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2784 return;
2785
2786 /* We're associated, retrieve info on the current bssid. */
2787 ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2788 chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2789 IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2790
2791 /* Get SSID from current association info. */
2792 bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2793 bs->nwbx_ssid.ns_ssidlen);
2794 ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2795
2796 if (ic->ic_caps & IEEE80211_C_PMGT) {
2797 len = sizeof(arg);
2798 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2799
2800 if (rval)
2801 device_printf(sc->ndis_dev,
2802 "get power mode failed: %d\n", rval);
2803 if (arg == NDIS_80211_POWERMODE_CAM)
2804 vap->iv_flags &= ~IEEE80211_F_PMGTON;
2805 else
2806 vap->iv_flags |= IEEE80211_F_PMGTON;
2807 }
2808
2809 /* Get TX power */
2810 if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2811 len = sizeof(arg);
2812 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2813 for (i = 0; i < nitems(dBm2mW); i++)
2814 if (dBm2mW[i] >= arg)
2815 break;
2816 ic->ic_txpowlimit = i;
2817 }
2818
2819 /*
2820 * Use the current association information to reflect
2821 * what channel we're on.
2822 */
2823 ic->ic_curchan = ieee80211_find_channel(ic,
2824 bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2825 if (ic->ic_curchan == NULL)
2826 ic->ic_curchan = &ic->ic_channels[0];
2827 ni->ni_chan = ic->ic_curchan;
2828 ic->ic_bsschan = ic->ic_curchan;
2829
2830 free(bs, M_TEMP);
2831
2832 /*
2833 * Determine current authentication mode.
2834 */
2835 len = sizeof(arg);
2836 rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2837 if (rval)
2838 device_printf(sc->ndis_dev,
2839 "get authmode status failed: %d\n", rval);
2840 else {
2841 vap->iv_flags &= ~IEEE80211_F_WPA;
2842 switch (arg) {
2843 case NDIS_80211_AUTHMODE_OPEN:
2844 ni->ni_authmode = IEEE80211_AUTH_OPEN;
2845 break;
2846 case NDIS_80211_AUTHMODE_SHARED:
2847 ni->ni_authmode = IEEE80211_AUTH_SHARED;
2848 break;
2849 case NDIS_80211_AUTHMODE_AUTO:
2850 ni->ni_authmode = IEEE80211_AUTH_AUTO;
2851 break;
2852 case NDIS_80211_AUTHMODE_WPA:
2853 case NDIS_80211_AUTHMODE_WPAPSK:
2854 case NDIS_80211_AUTHMODE_WPANONE:
2855 ni->ni_authmode = IEEE80211_AUTH_WPA;
2856 vap->iv_flags |= IEEE80211_F_WPA1;
2857 break;
2858 case NDIS_80211_AUTHMODE_WPA2:
2859 case NDIS_80211_AUTHMODE_WPA2PSK:
2860 ni->ni_authmode = IEEE80211_AUTH_WPA;
2861 vap->iv_flags |= IEEE80211_F_WPA2;
2862 break;
2863 default:
2864 ni->ni_authmode = IEEE80211_AUTH_NONE;
2865 break;
2866 }
2867 }
2868
2869 len = sizeof(arg);
2870 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2871
2872 if (rval)
2873 device_printf(sc->ndis_dev,
2874 "get wep status failed: %d\n", rval);
2875
2876 if (arg == NDIS_80211_WEPSTAT_ENABLED)
2877 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2878 else
2879 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2880}
2881
2882static int
2883ndis_ioctl(ifp, command, data)
2884 struct ifnet *ifp;
2885 u_long command;
2886 caddr_t data;
2887{
2888 struct ndis_softc *sc = ifp->if_softc;
2889 struct ifreq *ifr = (struct ifreq *) data;
2890 int i, error = 0;
2891
2892 /*NDIS_LOCK(sc);*/
2893
2894 switch (command) {
2895 case SIOCSIFFLAGS:
2896 if (ifp->if_flags & IFF_UP) {
2897 if (sc->ndis_running &&
2898 ifp->if_flags & IFF_PROMISC &&
2899 !(sc->ndis_if_flags & IFF_PROMISC)) {
2900 sc->ndis_filter |=
2901 NDIS_PACKET_TYPE_PROMISCUOUS;
2902 i = sizeof(sc->ndis_filter);
2903 error = ndis_set_info(sc,
2904 OID_GEN_CURRENT_PACKET_FILTER,
2905 &sc->ndis_filter, &i);
2906 } else if (sc->ndis_running &&
2907 !(ifp->if_flags & IFF_PROMISC) &&
2908 sc->ndis_if_flags & IFF_PROMISC) {
2909 sc->ndis_filter &=
2910 ~NDIS_PACKET_TYPE_PROMISCUOUS;
2911 i = sizeof(sc->ndis_filter);
2912 error = ndis_set_info(sc,
2913 OID_GEN_CURRENT_PACKET_FILTER,
2914 &sc->ndis_filter, &i);
2915 } else
2916 ndis_init(sc);
2917 } else {
2918 if (sc->ndis_running)
2919 ndis_stop(sc);
2920 }
2921 sc->ndis_if_flags = ifp->if_flags;
2922 error = 0;
2923 break;
2924 case SIOCADDMULTI:
2925 case SIOCDELMULTI:
2926 ndis_setmulti(sc);
2927 error = 0;
2928 break;
2929 case SIOCGIFMEDIA:
2930 case SIOCSIFMEDIA:
2931 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2932 break;
2933 case SIOCSIFCAP:
2934 ifp->if_capenable = ifr->ifr_reqcap;
2935 if (ifp->if_capenable & IFCAP_TXCSUM)
2936 ifp->if_hwassist = sc->ndis_hwassist;
2937 else
2938 ifp->if_hwassist = 0;
2939 ndis_set_offload(sc);
2940 break;
2941 default:
2942 error = ether_ioctl(ifp, command, data);
2943 break;
2944 }
2945
2946 /*NDIS_UNLOCK(sc);*/
2947
2948 return(error);
2949}
2950
2951static int
2952ndis_80211ioctl(struct ieee80211com *ic, u_long cmd, void *data)
2953{
2954 struct ndis_softc *sc = ic->ic_softc;
2955 struct ifreq *ifr = data;
2956 struct ndis_oid_data oid;
2957 struct ndis_evt evt;
2958 void *oidbuf = NULL;
2959 int error = 0;
2960
2961 if ((error = priv_check(curthread, PRIV_DRIVER)) != 0)
2962 return (error);
2963
2964 switch (cmd) {
2965 case SIOCGDRVSPEC:
2966 case SIOCSDRVSPEC:
2967 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2968 if (error)
2969 break;
2970 oidbuf = malloc(oid.len, M_TEMP, M_WAITOK | M_ZERO);
2971 error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2972 }
2973
2974 if (error) {
2975 free(oidbuf, M_TEMP);
2976 return (error);
2977 }
2978
2979 switch (cmd) {
2980 case SIOCGDRVSPEC:
2981 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2982 break;
2983 case SIOCSDRVSPEC:
2984 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2985 break;
2986 case SIOCGPRIVATE_0:
2987 NDIS_LOCK(sc);
2988 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
2989 error = ENOENT;
2990 NDIS_UNLOCK(sc);
2991 break;
2992 }
2993 error = copyin(ifr->ifr_data, &evt, sizeof(evt));
2994 if (error) {
2995 NDIS_UNLOCK(sc);
2996 break;
2997 }
2998 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2999 error = ENOSPC;
3000 NDIS_UNLOCK(sc);
3001 break;
3002 }
3003 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
3004 ifr->ifr_data, sizeof(uint32_t) * 2);
3005 if (error) {
3006 NDIS_UNLOCK(sc);
3007 break;
3008 }
3009 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3010 error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
3011 ifr->ifr_data + (sizeof(uint32_t) * 2),
3012 sc->ndis_evt[sc->ndis_evtcidx].ne_len);
3013 if (error) {
3014 NDIS_UNLOCK(sc);
3015 break;
3016 }
3017 free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
3018 sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
3019 }
3020 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
3021 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
3022 NDIS_EVTINC(sc->ndis_evtcidx);
3023 NDIS_UNLOCK(sc);
3024 break;
3025 default:
3026 error = ENOTTY;
3027 break;
3028 }
3029
3030 switch (cmd) {
3031 case SIOCGDRVSPEC:
3032 case SIOCSDRVSPEC:
3033 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
3034 if (error)
3035 break;
3036 error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
3037 }
3038
3039 free(oidbuf, M_TEMP);
3040
3041 return (error);
3042}
3043
3044int
3045ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3046{
3047 struct ndis_softc *sc = vap->iv_ic->ic_softc;
3048 ndis_80211_key rkey;
3049 int len, error = 0;
3050
3051 bzero((char *)&rkey, sizeof(rkey));
3052 len = sizeof(rkey);
3053
3054 rkey.nk_len = len;
3055 rkey.nk_keyidx = key->wk_keyix;
3056
3057 bcopy(vap->iv_ifp->if_broadcastaddr,
3058 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3059
3060 error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
3061
3062 if (error)
3063 return (0);
3064
3065 return (1);
3066}
3067
3068/*
3069 * In theory this could be called for any key, but we'll
3070 * only use it for WPA TKIP or AES keys. These need to be
3071 * set after initial authentication with the AP.
3072 */
3073static int
3074ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3075{
3076 struct ndis_softc *sc = vap->iv_ic->ic_softc;
3077 ndis_80211_key rkey;
3078 int len, error = 0;
3079
3080 switch (key->wk_cipher->ic_cipher) {
3081 case IEEE80211_CIPHER_TKIP:
3082
3083 len = sizeof(ndis_80211_key);
3084 bzero((char *)&rkey, sizeof(rkey));
3085
3086 rkey.nk_len = len;
3087 rkey.nk_keylen = key->wk_keylen;
3088
3089 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3090 rkey.nk_keylen += 16;
3091
3092 /* key index - gets weird in NDIS */
3093
3094 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3095 rkey.nk_keyidx = key->wk_keyix;
3096 else
3097 rkey.nk_keyidx = 0;
3098
3099 if (key->wk_flags & IEEE80211_KEY_XMIT)
3100 rkey.nk_keyidx |= 1 << 31;
3101
3102 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3103 bcopy(ieee80211broadcastaddr,
3104 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3105 } else {
3106 bcopy(vap->iv_bss->ni_bssid,
3107 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3108 /* pairwise key */
3109 rkey.nk_keyidx |= 1 << 30;
3110 }
3111
3112 /* need to set bit 29 based on keyrsc */
3113 rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */
3114
3115 if (rkey.nk_keyrsc)
3116 rkey.nk_keyidx |= 1 << 29;
3117
3118 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3119 bcopy(key->wk_key, rkey.nk_keydata, 16);
3120 bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3121 bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3122 } else
3123 bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3124
3125 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3126 break;
3127 case IEEE80211_CIPHER_WEP:
3128 error = 0;
3129 break;
3130 /*
3131 * I don't know how to set up keys for the AES
3132 * cipher yet. Is it the same as TKIP?
3133 */
3134 case IEEE80211_CIPHER_AES_CCM:
3135 default:
3136 error = ENOTTY;
3137 break;
3138 }
3139
3140 /* We need to return 1 for success, 0 for failure. */
3141
3142 if (error)
3143 return (0);
3144
3145 return (1);
3146}
3147
3148static void
3149ndis_resettask(d, arg)
3150 device_object *d;
3151 void *arg;
3152{
3153 struct ndis_softc *sc;
3154
3155 sc = arg;
3156 ndis_reset_nic(sc);
3157}
3158
3159/*
3160 * Stop the adapter and free any mbufs allocated to the
3161 * RX and TX lists.
3162 */
3163static void
3164ndis_stop(struct ndis_softc *sc)
3165{
3166 int i;
3167
3168 callout_drain(&sc->ndis_stat_callout);
3169
3170 NDIS_LOCK(sc);
3171 sc->ndis_tx_timer = 0;
3172 sc->ndis_link = 0;
3173 if (!sc->ndis_80211)
3174 sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3175 sc->ndis_running = 0;
3176 NDIS_UNLOCK(sc);
3177
3178 if (sc->ndis_iftype != PNPBus ||
3179 (sc->ndis_iftype == PNPBus &&
3180 !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3181 ndisusb_halt != 0))
3182 ndis_halt_nic(sc);
3183
3184 NDIS_LOCK(sc);
3185 for (i = 0; i < NDIS_EVENTS; i++) {
3186 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3187 free(sc->ndis_evt[i].ne_buf, M_TEMP);
3188 sc->ndis_evt[i].ne_buf = NULL;
3189 }
3190 sc->ndis_evt[i].ne_sts = 0;
3191 sc->ndis_evt[i].ne_len = 0;
3192 }
3193 sc->ndis_evtcidx = 0;
3194 sc->ndis_evtpidx = 0;
3195 NDIS_UNLOCK(sc);
3196}
3197
3198/*
3199 * Stop all chip I/O so that the kernel's probe routines don't
3200 * get confused by errant DMAs when rebooting.
3201 */
3202void
3203ndis_shutdown(dev)
3204 device_t dev;
3205{
3206 struct ndis_softc *sc;
3207
3208 sc = device_get_softc(dev);
3209 ndis_stop(sc);
3210}
3211
3212static int
3213ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3214{
3215 struct ndis_vap *nvp = NDIS_VAP(vap);
3216 struct ieee80211com *ic = vap->iv_ic;
3217 struct ndis_softc *sc = ic->ic_softc;
3218 enum ieee80211_state ostate;
3219
3220 DPRINTF(("%s: %s -> %s\n", __func__,
3221 ieee80211_state_name[vap->iv_state],
3222 ieee80211_state_name[nstate]));
3223
3224 ostate = vap->iv_state;
3225 vap->iv_state = nstate;
3226
3227 switch (nstate) {
3228 /* pass on to net80211 */
3229 case IEEE80211_S_INIT:
3230 case IEEE80211_S_SCAN:
3231 return nvp->newstate(vap, nstate, arg);
3232 case IEEE80211_S_ASSOC:
3233 if (ostate != IEEE80211_S_AUTH) {
3234 IEEE80211_UNLOCK(ic);
3235 ndis_auth_and_assoc(sc, vap);
3236 IEEE80211_LOCK(ic);
3237 }
3238 break;
3239 case IEEE80211_S_AUTH:
3240 IEEE80211_UNLOCK(ic);
3241 ndis_auth_and_assoc(sc, vap);
3242 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3243 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3244 IEEE80211_LOCK(ic);
3245 break;
3246 default:
3247 break;
3248 }
3249 return (0);
3250}
3251
3252static void
3253ndis_scan(void *arg)
3254{
3255 struct ieee80211vap *vap = arg;
3256
3257 ieee80211_scan_done(vap);
3258}
3259
3260static void
3261ndis_scan_results(struct ndis_softc *sc)
3262{
3263 struct ieee80211com *ic = &sc->ndis_ic;
3264 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
3265 ndis_80211_bssid_list_ex *bl;
3266 ndis_wlan_bssid_ex *wb;
3267 struct ieee80211_scanparams sp;
3268 struct ieee80211_frame wh;
3269 struct ieee80211_channel *saved_chan;
3270 int i, j;
3271 int rssi, noise, freq, chanflag;
3272 uint8_t ssid[2+IEEE80211_NWID_LEN];
3273 uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3274 uint8_t *frm, *efrm;
3275
3276 saved_chan = ic->ic_curchan;
3277 noise = -96;
3278
3279 if (ndis_get_bssid_list(sc, &bl))
3280 return;
3281
3282 DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3283 wb = &bl->nblx_bssid[0];
3284 for (i = 0; i < bl->nblx_items; i++) {
3285 memset(&sp, 0, sizeof(sp));
3286
3287 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3288 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3289 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3290 rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */
3291 if (wb->nwbx_privacy)
3292 sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3293 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3294 switch (wb->nwbx_netinfra) {
3295 case NDIS_80211_NET_INFRA_IBSS:
3296 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3297 break;
3298 case NDIS_80211_NET_INFRA_BSS:
3299 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3300 break;
3301 }
3302 sp.rates = &rates[0];
3303 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3304 /* XXX - check units */
3305 if (wb->nwbx_supportedrates[j] == 0)
3306 break;
3307 rates[2 + j] =
3308 wb->nwbx_supportedrates[j] & 0x7f;
3309 }
3310 rates[1] = j;
3311 sp.ssid = (uint8_t *)&ssid[0];
3312 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3313 wb->nwbx_ssid.ns_ssidlen);
3314 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3315
3316 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3317 freq = wb->nwbx_config.nc_dsconfig / 1000;
3318 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3319 /* Hack ic->ic_curchan to be in sync with the scan result */
3320 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3321 if (ic->ic_curchan == NULL)
3322 ic->ic_curchan = &ic->ic_channels[0];
3323
3324 /* Process extended info from AP */
3325 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3326 frm = (uint8_t *)&wb->nwbx_ies;
3327 efrm = frm + wb->nwbx_ielen;
3328 if (efrm - frm < 12)
3329 goto done;
3330 sp.tstamp = frm; frm += 8;
3331 sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3332 sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3333 sp.ies = frm;
3334 sp.ies_len = efrm - frm;
3335 }
3336done:
3337 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3338 ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag,
3339 rssi));
3340 ieee80211_add_scan(vap, ic->ic_curchan, &sp, &wh, 0, rssi, noise);
3341 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3342 }
3343 free(bl, M_DEVBUF);
3344 /* Restore the channel after messing with it */
3345 ic->ic_curchan = saved_chan;
3346}
3347
3348static void
3349ndis_scan_start(struct ieee80211com *ic)
3350{
3351 struct ndis_softc *sc = ic->ic_softc;
3352 struct ieee80211vap *vap;
3353 struct ieee80211_scan_state *ss;
3354 ndis_80211_ssid ssid;
3355 int error, len;
3356
3357 ss = ic->ic_scan;
3358 vap = TAILQ_FIRST(&ic->ic_vaps);
3359
3360 if (!NDIS_INITIALIZED(sc)) {
3361 DPRINTF(("%s: scan aborted\n", __func__));
3362 ieee80211_cancel_scan(vap);
3363 return;
3364 }
3365
3366 len = sizeof(ssid);
3367 bzero((char *)&ssid, len);
3368 if (ss->ss_nssid == 0)
3369 ssid.ns_ssidlen = 1;
3370 else {
3371 /* Perform a directed scan */
3372 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3373 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3374 }
3375
3376 error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3377 if (error)
3378 DPRINTF(("%s: set ESSID failed\n", __func__));
3379
3380 len = 0;
3381 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3382 if (error) {
3383 DPRINTF(("%s: scan command failed\n", __func__));
3384 ieee80211_cancel_scan(vap);
3385 return;
3386 }
3387 /* Set a timer to collect the results */
3388 callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3389}
3390
3391static void
3392ndis_set_channel(struct ieee80211com *ic)
3393{
3394 /* ignore */
3395}
3396
3397static void
3398ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3399{
3400 /* ignore */
3401}
3402
3403static void
3404ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3405{
3406 /* NB: don't try to abort scan; wait for firmware to finish */
3407}
3408
3409static void
3410ndis_scan_end(struct ieee80211com *ic)
3411{
3412 struct ndis_softc *sc = ic->ic_softc;
3413
3414 ndis_scan_results(sc);
3415}
729
730 callout_init(&sc->ndis_scan_callout, 1);
731
732 ic->ic_softc = sc;
733 ic->ic_ioctl = ndis_80211ioctl;
734 ic->ic_name = device_get_nameunit(sc->ndis_dev);
735 ic->ic_opmode = IEEE80211_M_STA;
736 ic->ic_phytype = IEEE80211_T_DS;
737 ic->ic_caps = IEEE80211_C_8023ENCAP |
738 IEEE80211_C_STA | IEEE80211_C_IBSS;
739 setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
740 len = 0;
741 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, NULL, &len);
742 if (r != ENOSPC)
743 goto nonettypes;
744 ntl = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
745 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, ntl, &len);
746 if (r != 0) {
747 free(ntl, M_DEVBUF);
748 goto nonettypes;
749 }
750
751 for (i = 0; i < ntl->ntl_items; i++) {
752 mode = ndis_nettype_mode(ntl->ntl_type[i]);
753 if (mode) {
754 nonettypes = 0;
755 setbit(ic->ic_modecaps, mode);
756 setbit(bands, mode);
757 } else
758 device_printf(sc->ndis_dev, "Unknown nettype %d\n",
759 ntl->ntl_type[i]);
760 }
761 free(ntl, M_DEVBUF);
762nonettypes:
763 /* Default to 11b channels if the card did not supply any */
764 if (nonettypes) {
765 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
766 setbit(bands, IEEE80211_MODE_11B);
767 }
768 len = sizeof(rates);
769 bzero((char *)&rates, len);
770 r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len);
771 if (r != 0)
772 device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r);
773 /*
774 * Since the supported rates only up to 8 can be supported,
775 * if this is not 802.11b we're just going to be faking it
776 * all up to heck.
777 */
778
779#define TESTSETRATE(x, y) \
780 do { \
781 int i; \
782 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \
783 if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \
784 break; \
785 } \
786 if (i == ic->ic_sup_rates[x].rs_nrates) { \
787 ic->ic_sup_rates[x].rs_rates[i] = (y); \
788 ic->ic_sup_rates[x].rs_nrates++; \
789 } \
790 } while (0)
791
792#define SETRATE(x, y) \
793 ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
794#define INCRATE(x) \
795 ic->ic_sup_rates[x].rs_nrates++
796
797 ic->ic_curmode = IEEE80211_MODE_AUTO;
798 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A))
799 ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
800 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B))
801 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
802 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G))
803 ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
804 for (i = 0; i < len; i++) {
805 switch (rates[i] & IEEE80211_RATE_VAL) {
806 case 2:
807 case 4:
808 case 11:
809 case 10:
810 case 22:
811 if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) {
812 /* Lazy-init 802.11b. */
813 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
814 ic->ic_sup_rates[IEEE80211_MODE_11B].
815 rs_nrates = 0;
816 }
817 SETRATE(IEEE80211_MODE_11B, rates[i]);
818 INCRATE(IEEE80211_MODE_11B);
819 break;
820 default:
821 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
822 SETRATE(IEEE80211_MODE_11A, rates[i]);
823 INCRATE(IEEE80211_MODE_11A);
824 }
825 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
826 SETRATE(IEEE80211_MODE_11G, rates[i]);
827 INCRATE(IEEE80211_MODE_11G);
828 }
829 break;
830 }
831 }
832
833 /*
834 * If the hardware supports 802.11g, it most
835 * likely supports 802.11b and all of the
836 * 802.11b and 802.11g speeds, so maybe we can
837 * just cheat here. Just how in the heck do
838 * we detect turbo modes, though?
839 */
840 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) {
841 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|2);
842 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|4);
843 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|11);
844 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|22);
845 }
846 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
847 TESTSETRATE(IEEE80211_MODE_11G, 48);
848 TESTSETRATE(IEEE80211_MODE_11G, 72);
849 TESTSETRATE(IEEE80211_MODE_11G, 96);
850 TESTSETRATE(IEEE80211_MODE_11G, 108);
851 }
852 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
853 TESTSETRATE(IEEE80211_MODE_11A, 48);
854 TESTSETRATE(IEEE80211_MODE_11A, 72);
855 TESTSETRATE(IEEE80211_MODE_11A, 96);
856 TESTSETRATE(IEEE80211_MODE_11A, 108);
857 }
858
859#undef SETRATE
860#undef INCRATE
861#undef TESTSETRATE
862
863 ieee80211_init_channels(ic, NULL, bands);
864
865 /*
866 * To test for WPA support, we need to see if we can
867 * set AUTHENTICATION_MODE to WPA and read it back
868 * successfully.
869 */
870 i = sizeof(arg);
871 arg = NDIS_80211_AUTHMODE_WPA;
872 r = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
873 if (r == 0) {
874 r = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
875 if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA)
876 ic->ic_caps |= IEEE80211_C_WPA;
877 }
878
879 /*
880 * To test for supported ciphers, we set each
881 * available encryption type in descending order.
882 * If ENC3 works, then we have WEP, TKIP and AES.
883 * If only ENC2 works, then we have WEP and TKIP.
884 * If only ENC1 works, then we have just WEP.
885 */
886 i = sizeof(arg);
887 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
888 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
889 if (r == 0) {
890 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
891 | IEEE80211_CRYPTO_TKIP
892 | IEEE80211_CRYPTO_AES_CCM;
893 goto got_crypto;
894 }
895 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
896 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
897 if (r == 0) {
898 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
899 | IEEE80211_CRYPTO_TKIP;
900 goto got_crypto;
901 }
902 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
903 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
904 if (r == 0)
905 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
906got_crypto:
907 i = sizeof(arg);
908 r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
909 if (r == 0)
910 ic->ic_caps |= IEEE80211_C_PMGT;
911
912 r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
913 if (r == 0)
914 ic->ic_caps |= IEEE80211_C_TXPMGT;
915
916 /*
917 * Get station address from the driver.
918 */
919 len = sizeof(ic->ic_macaddr);
920 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &ic->ic_macaddr, &len);
921
922 ieee80211_ifattach(ic);
923 ic->ic_raw_xmit = ndis_raw_xmit;
924 ic->ic_scan_start = ndis_scan_start;
925 ic->ic_scan_end = ndis_scan_end;
926 ic->ic_set_channel = ndis_set_channel;
927 ic->ic_scan_curchan = ndis_scan_curchan;
928 ic->ic_scan_mindwell = ndis_scan_mindwell;
929 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
930 ic->ic_vap_create = ndis_vap_create;
931 ic->ic_vap_delete = ndis_vap_delete;
932 ic->ic_update_mcast = ndis_update_mcast;
933 ic->ic_update_promisc = ndis_update_promisc;
934 ic->ic_transmit = ndis_80211transmit;
935 ic->ic_parent = ndis_80211parent;
936
937 if (bootverbose)
938 ieee80211_announce(ic);
939
940 return (0);
941}
942
943static int
944ndis_ifattach(struct ndis_softc *sc)
945{
946 struct ifnet *ifp;
947 u_char eaddr[ETHER_ADDR_LEN];
948 int len;
949
950 ifp = if_alloc(IFT_ETHER);
951 if (ifp == NULL)
952 return (ENOSPC);
953 sc->ifp = ifp;
954 ifp->if_softc = sc;
955
956 /* Check for task offload support. */
957 ndis_probe_offload(sc);
958
959 /*
960 * Get station address from the driver.
961 */
962 len = sizeof(eaddr);
963 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, eaddr, &len);
964
965 if_initname(ifp, device_get_name(sc->ndis_dev),
966 device_get_unit(sc->ndis_dev));
967 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
968 ifp->if_ioctl = ndis_ioctl;
969 ifp->if_start = ndis_start;
970 ifp->if_init = ndis_init;
971 ifp->if_baudrate = 10000000;
972 IFQ_SET_MAXLEN(&ifp->if_snd, 50);
973 ifp->if_snd.ifq_drv_maxlen = 25;
974 IFQ_SET_READY(&ifp->if_snd);
975 ifp->if_capenable = ifp->if_capabilities;
976 ifp->if_hwassist = sc->ndis_hwassist;
977
978 ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
979 ndis_ifmedia_sts);
980 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
981 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
982 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
983 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
984 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
985 ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
986 ether_ifattach(ifp, eaddr);
987
988 return (0);
989}
990
991static struct ieee80211vap *
992ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
993 enum ieee80211_opmode opmode, int flags,
994 const uint8_t bssid[IEEE80211_ADDR_LEN],
995 const uint8_t mac[IEEE80211_ADDR_LEN])
996{
997 struct ndis_vap *nvp;
998 struct ieee80211vap *vap;
999
1000 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
1001 return NULL;
1002 nvp = malloc(sizeof(struct ndis_vap), M_80211_VAP, M_WAITOK | M_ZERO);
1003 vap = &nvp->vap;
1004 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
1005 /* override with driver methods */
1006 nvp->newstate = vap->iv_newstate;
1007 vap->iv_newstate = ndis_newstate;
1008
1009 /* complete setup */
1010 ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status,
1011 mac);
1012 ic->ic_opmode = opmode;
1013 /* install key handing routines */
1014 vap->iv_key_set = ndis_add_key;
1015 vap->iv_key_delete = ndis_del_key;
1016 return vap;
1017}
1018
1019static void
1020ndis_vap_delete(struct ieee80211vap *vap)
1021{
1022 struct ndis_vap *nvp = NDIS_VAP(vap);
1023 struct ieee80211com *ic = vap->iv_ic;
1024 struct ndis_softc *sc = ic->ic_softc;
1025
1026 ndis_stop(sc);
1027 callout_drain(&sc->ndis_scan_callout);
1028 ieee80211_vap_detach(vap);
1029 free(nvp, M_80211_VAP);
1030}
1031
1032/*
1033 * Shutdown hardware and free up resources. This can be called any
1034 * time after the mutex has been initialized. It is called in both
1035 * the error case in attach and the normal detach case so it needs
1036 * to be careful about only freeing resources that have actually been
1037 * allocated.
1038 */
1039int
1040ndis_detach(device_t dev)
1041{
1042 struct ifnet *ifp;
1043 struct ndis_softc *sc;
1044 driver_object *drv;
1045
1046 sc = device_get_softc(dev);
1047 NDIS_LOCK(sc);
1048 if (!sc->ndis_80211)
1049 ifp = sc->ifp;
1050 else
1051 ifp = NULL;
1052 if (ifp != NULL)
1053 ifp->if_flags &= ~IFF_UP;
1054 if (device_is_attached(dev)) {
1055 NDIS_UNLOCK(sc);
1056 ndis_stop(sc);
1057 if (sc->ndis_80211)
1058 ieee80211_ifdetach(&sc->ndis_ic);
1059 else if (ifp != NULL)
1060 ether_ifdetach(ifp);
1061 } else
1062 NDIS_UNLOCK(sc);
1063
1064 if (sc->ndis_tickitem != NULL)
1065 IoFreeWorkItem(sc->ndis_tickitem);
1066 if (sc->ndis_startitem != NULL)
1067 IoFreeWorkItem(sc->ndis_startitem);
1068 if (sc->ndis_resetitem != NULL)
1069 IoFreeWorkItem(sc->ndis_resetitem);
1070 if (sc->ndis_inputitem != NULL)
1071 IoFreeWorkItem(sc->ndis_inputitem);
1072 if (sc->ndisusb_xferdoneitem != NULL)
1073 IoFreeWorkItem(sc->ndisusb_xferdoneitem);
1074 if (sc->ndisusb_taskitem != NULL)
1075 IoFreeWorkItem(sc->ndisusb_taskitem);
1076
1077 bus_generic_detach(dev);
1078 ndis_unload_driver(sc);
1079
1080 if (sc->ndis_irq)
1081 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
1082 if (sc->ndis_res_io)
1083 bus_release_resource(dev, SYS_RES_IOPORT,
1084 sc->ndis_io_rid, sc->ndis_res_io);
1085 if (sc->ndis_res_mem)
1086 bus_release_resource(dev, SYS_RES_MEMORY,
1087 sc->ndis_mem_rid, sc->ndis_res_mem);
1088 if (sc->ndis_res_altmem)
1089 bus_release_resource(dev, SYS_RES_MEMORY,
1090 sc->ndis_altmem_rid, sc->ndis_res_altmem);
1091
1092 if (ifp != NULL)
1093 if_free(ifp);
1094
1095 if (sc->ndis_iftype == PCMCIABus)
1096 ndis_free_amem(sc);
1097
1098 if (sc->ndis_sc)
1099 ndis_destroy_dma(sc);
1100
1101 if (sc->ndis_txarray)
1102 free(sc->ndis_txarray, M_DEVBUF);
1103
1104 if (!sc->ndis_80211)
1105 ifmedia_removeall(&sc->ifmedia);
1106
1107 if (sc->ndis_txpool != NULL)
1108 NdisFreePacketPool(sc->ndis_txpool);
1109
1110 /* Destroy the PDO for this device. */
1111
1112 if (sc->ndis_iftype == PCIBus)
1113 drv = windrv_lookup(0, "PCI Bus");
1114 else if (sc->ndis_iftype == PCMCIABus)
1115 drv = windrv_lookup(0, "PCCARD Bus");
1116 else
1117 drv = windrv_lookup(0, "USB Bus");
1118 if (drv == NULL)
1119 panic("couldn't find driver object");
1120 windrv_destroy_pdo(drv, dev);
1121
1122 if (sc->ndis_iftype == PCIBus)
1123 bus_dma_tag_destroy(sc->ndis_parent_tag);
1124
1125 return (0);
1126}
1127
1128int
1129ndis_suspend(dev)
1130 device_t dev;
1131{
1132 struct ndis_softc *sc;
1133 struct ifnet *ifp;
1134
1135 sc = device_get_softc(dev);
1136 ifp = sc->ifp;
1137
1138#ifdef notdef
1139 if (NDIS_INITIALIZED(sc))
1140 ndis_stop(sc);
1141#endif
1142
1143 return (0);
1144}
1145
1146int
1147ndis_resume(dev)
1148 device_t dev;
1149{
1150 struct ndis_softc *sc;
1151 struct ifnet *ifp;
1152
1153 sc = device_get_softc(dev);
1154 ifp = sc->ifp;
1155
1156 if (NDIS_INITIALIZED(sc))
1157 ndis_init(sc);
1158
1159 return (0);
1160}
1161
1162/*
1163 * The following bunch of routines are here to support drivers that
1164 * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism.
1165 * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for
1166 * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1167 * miniports.
1168 */
1169static void
1170ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen)
1171 ndis_handle adapter;
1172 ndis_handle ctx;
1173 char *addr;
1174 void *hdr;
1175 uint32_t hdrlen;
1176 void *lookahead;
1177 uint32_t lookaheadlen;
1178 uint32_t pktlen;
1179{
1180 ndis_miniport_block *block;
1181 uint8_t irql = 0;
1182 uint32_t status;
1183 ndis_buffer *b;
1184 ndis_packet *p;
1185 struct mbuf *m;
1186 ndis_ethpriv *priv;
1187
1188 block = adapter;
1189
1190 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1191 if (m == NULL)
1192 return;
1193
1194 /* Save the data provided to us so far. */
1195
1196 m->m_len = lookaheadlen + hdrlen;
1197 m->m_pkthdr.len = pktlen + hdrlen;
1198 m->m_next = NULL;
1199 m_copyback(m, 0, hdrlen, hdr);
1200 m_copyback(m, hdrlen, lookaheadlen, lookahead);
1201
1202 /* Now create a fake NDIS_PACKET to hold the data */
1203
1204 NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1205
1206 if (status != NDIS_STATUS_SUCCESS) {
1207 m_freem(m);
1208 return;
1209 }
1210
1211 p->np_m0 = m;
1212
1213 b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1214
1215 if (b == NULL) {
1216 NdisFreePacket(p);
1217 m_freem(m);
1218 return;
1219 }
1220
1221 p->np_private.npp_head = p->np_private.npp_tail = b;
1222 p->np_private.npp_totlen = m->m_pkthdr.len;
1223
1224 /* Save the packet RX context somewhere. */
1225 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1226 priv->nep_ctx = ctx;
1227
1228 if (!NDIS_SERIALIZED(block))
1229 KeAcquireSpinLock(&block->nmb_lock, &irql);
1230
1231 InsertTailList((&block->nmb_packetlist), (&p->np_list));
1232
1233 if (!NDIS_SERIALIZED(block))
1234 KeReleaseSpinLock(&block->nmb_lock, irql);
1235}
1236
1237/*
1238 * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1239 * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1240 * miniports.
1241 */
1242static void
1243ndis_rxeof_done(adapter)
1244 ndis_handle adapter;
1245{
1246 struct ndis_softc *sc;
1247 ndis_miniport_block *block;
1248
1249 block = adapter;
1250
1251 /* Schedule transfer/RX of queued packets. */
1252
1253 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1254
1255 KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1256}
1257
1258/*
1259 * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1260 */
1261static void
1262ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2)
1263 kdpc *dpc;
1264 ndis_handle adapter;
1265 void *sysarg1;
1266 void *sysarg2;
1267{
1268 ndis_miniport_block *block;
1269 struct ndis_softc *sc;
1270 ndis_packet *p;
1271 list_entry *l;
1272 uint32_t status;
1273 ndis_ethpriv *priv;
1274 struct ifnet *ifp;
1275 struct mbuf *m;
1276
1277 block = adapter;
1278 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1279 ifp = sc->ifp;
1280
1281 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1282
1283 l = block->nmb_packetlist.nle_flink;
1284 while(!IsListEmpty(&block->nmb_packetlist)) {
1285 l = RemoveHeadList((&block->nmb_packetlist));
1286 p = CONTAINING_RECORD(l, ndis_packet, np_list);
1287 InitializeListHead((&p->np_list));
1288
1289 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1290 m = p->np_m0;
1291 p->np_softc = sc;
1292 p->np_m0 = NULL;
1293
1294 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1295
1296 status = MSCALL6(sc->ndis_chars->nmc_transferdata_func,
1297 p, &p->np_private.npp_totlen, block, priv->nep_ctx,
1298 m->m_len, m->m_pkthdr.len - m->m_len);
1299
1300 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1301
1302 /*
1303 * If status is NDIS_STATUS_PENDING, do nothing and
1304 * wait for a callback to the ndis_rxeof_xfr_done()
1305 * handler.
1306 */
1307
1308 m->m_len = m->m_pkthdr.len;
1309 m->m_pkthdr.rcvif = ifp;
1310
1311 if (status == NDIS_STATUS_SUCCESS) {
1312 IoFreeMdl(p->np_private.npp_head);
1313 NdisFreePacket(p);
1314 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1315 mbufq_enqueue(&sc->ndis_rxqueue, m);
1316 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1317 IoQueueWorkItem(sc->ndis_inputitem,
1318 (io_workitem_func)ndis_inputtask_wrap,
1319 WORKQUEUE_CRITICAL, sc);
1320 }
1321
1322 if (status == NDIS_STATUS_FAILURE)
1323 m_freem(m);
1324
1325 /* Advance to next packet */
1326 l = block->nmb_packetlist.nle_flink;
1327 }
1328
1329 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1330}
1331
1332/*
1333 * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1334 */
1335static void
1336ndis_rxeof_xfr_done(adapter, packet, status, len)
1337 ndis_handle adapter;
1338 ndis_packet *packet;
1339 uint32_t status;
1340 uint32_t len;
1341{
1342 ndis_miniport_block *block;
1343 struct ndis_softc *sc;
1344 struct ifnet *ifp;
1345 struct mbuf *m;
1346
1347 block = adapter;
1348 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1349 ifp = sc->ifp;
1350
1351 m = packet->np_m0;
1352 IoFreeMdl(packet->np_private.npp_head);
1353 NdisFreePacket(packet);
1354
1355 if (status != NDIS_STATUS_SUCCESS) {
1356 m_freem(m);
1357 return;
1358 }
1359
1360 m->m_len = m->m_pkthdr.len;
1361 m->m_pkthdr.rcvif = ifp;
1362 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1363 mbufq_enqueue(&sc->ndis_rxqueue, m);
1364 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1365 IoQueueWorkItem(sc->ndis_inputitem,
1366 (io_workitem_func)ndis_inputtask_wrap,
1367 WORKQUEUE_CRITICAL, sc);
1368}
1369/*
1370 * A frame has been uploaded: pass the resulting mbuf chain up to
1371 * the higher level protocols.
1372 *
1373 * When handling received NDIS packets, the 'status' field in the
1374 * out-of-band portion of the ndis_packet has special meaning. In the
1375 * most common case, the underlying NDIS driver will set this field
1376 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1377 * take posession of it. We then change the status field to
1378 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1379 * and that we will return it at some point in the future via the
1380 * return packet handler.
1381 *
1382 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1383 * this means the driver is running out of packet/buffer resources and
1384 * wants to maintain ownership of the packet. In this case, we have to
1385 * copy the packet data into local storage and let the driver keep the
1386 * packet.
1387 */
1388static void
1389ndis_rxeof(adapter, packets, pktcnt)
1390 ndis_handle adapter;
1391 ndis_packet **packets;
1392 uint32_t pktcnt;
1393{
1394 struct ndis_softc *sc;
1395 ndis_miniport_block *block;
1396 ndis_packet *p;
1397 uint32_t s;
1398 ndis_tcpip_csum *csum;
1399 struct ifnet *ifp;
1400 struct mbuf *m0, *m;
1401 int i;
1402
1403 block = (ndis_miniport_block *)adapter;
1404 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1405 ifp = sc->ifp;
1406
1407 /*
1408 * There's a slim chance the driver may indicate some packets
1409 * before we're completely ready to handle them. If we detect this,
1410 * we need to return them to the miniport and ignore them.
1411 */
1412 if (!sc->ndis_running) {
1413 for (i = 0; i < pktcnt; i++) {
1414 p = packets[i];
1415 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1416 p->np_refcnt++;
1417 (void)ndis_return_packet(NULL ,p, block);
1418 }
1419 }
1420 return;
1421 }
1422
1423 for (i = 0; i < pktcnt; i++) {
1424 p = packets[i];
1425 /* Stash the softc here so ptom can use it. */
1426 p->np_softc = sc;
1427 if (ndis_ptom(&m0, p)) {
1428 device_printf(sc->ndis_dev, "ptom failed\n");
1429 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
1430 (void)ndis_return_packet(NULL, p, block);
1431 } else {
1432#ifdef notdef
1433 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1434 m = m_dup(m0, M_NOWAIT);
1435 /*
1436 * NOTE: we want to destroy the mbuf here, but
1437 * we don't actually want to return it to the
1438 * driver via the return packet handler. By
1439 * bumping np_refcnt, we can prevent the
1440 * ndis_return_packet() routine from actually
1441 * doing anything.
1442 */
1443 p->np_refcnt++;
1444 m_freem(m0);
1445 if (m == NULL)
1446 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1447 else
1448 m0 = m;
1449 } else
1450 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1451#endif
1452 m = m_dup(m0, M_NOWAIT);
1453 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1454 p->np_refcnt++;
1455 else
1456 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1457 m_freem(m0);
1458 if (m == NULL) {
1459 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1460 continue;
1461 }
1462 m0 = m;
1463 m0->m_pkthdr.rcvif = ifp;
1464
1465 /* Deal with checksum offload. */
1466
1467 if (ifp->if_capenable & IFCAP_RXCSUM &&
1468 p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1469 s = (uintptr_t)
1470 p->np_ext.npe_info[ndis_tcpipcsum_info];
1471 csum = (ndis_tcpip_csum *)&s;
1472 if (csum->u.ntc_rxflags &
1473 NDIS_RXCSUM_IP_PASSED)
1474 m0->m_pkthdr.csum_flags |=
1475 CSUM_IP_CHECKED|CSUM_IP_VALID;
1476 if (csum->u.ntc_rxflags &
1477 (NDIS_RXCSUM_TCP_PASSED |
1478 NDIS_RXCSUM_UDP_PASSED)) {
1479 m0->m_pkthdr.csum_flags |=
1480 CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
1481 m0->m_pkthdr.csum_data = 0xFFFF;
1482 }
1483 }
1484
1485 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1486 mbufq_enqueue(&sc->ndis_rxqueue, m0);
1487 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1488 IoQueueWorkItem(sc->ndis_inputitem,
1489 (io_workitem_func)ndis_inputtask_wrap,
1490 WORKQUEUE_CRITICAL, sc);
1491 }
1492 }
1493}
1494
1495/*
1496 * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1497 * packets into the stack in order to avoid calling (*ifp->if_input)()
1498 * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1499 * 'dispatch level' per-cpu sleep lock).
1500 */
1501static void
1502ndis_inputtask(device_object *dobj, void *arg)
1503{
1504 ndis_miniport_block *block;
1505 struct ndis_softc *sc = arg;
1506 struct mbuf *m;
1507 uint8_t irql;
1508
1509 block = dobj->do_devext;
1510
1511 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1512 while ((m = mbufq_dequeue(&sc->ndis_rxqueue)) != NULL) {
1513 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1514 if ((sc->ndis_80211 != 0)) {
1515 struct ieee80211com *ic = &sc->ndis_ic;
1516 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1517
1518 if (vap != NULL)
1519 vap->iv_deliver_data(vap, vap->iv_bss, m);
1520 } else {
1521 struct ifnet *ifp = sc->ifp;
1522
1523 (*ifp->if_input)(ifp, m);
1524 }
1525 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1526 }
1527 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1528}
1529
1530/*
1531 * A frame was downloaded to the chip. It's safe for us to clean up
1532 * the list buffers.
1533 */
1534static void
1535ndis_txeof(adapter, packet, status)
1536 ndis_handle adapter;
1537 ndis_packet *packet;
1538 ndis_status status;
1539
1540{
1541 struct ndis_softc *sc;
1542 ndis_miniport_block *block;
1543 struct ifnet *ifp;
1544 int idx;
1545 struct mbuf *m;
1546
1547 block = (ndis_miniport_block *)adapter;
1548 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1549 ifp = sc->ifp;
1550
1551 m = packet->np_m0;
1552 idx = packet->np_txidx;
1553 if (sc->ndis_sc)
1554 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1555
1556 ndis_free_packet(packet);
1557 m_freem(m);
1558
1559 NDIS_LOCK(sc);
1560 sc->ndis_txarray[idx] = NULL;
1561 sc->ndis_txpending++;
1562
1563 if (status == NDIS_STATUS_SUCCESS)
1564 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
1565 else
1566 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1567
1568 sc->ndis_tx_timer = 0;
1569 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1570
1571 NDIS_UNLOCK(sc);
1572
1573 IoQueueWorkItem(sc->ndis_startitem,
1574 (io_workitem_func)ndis_starttask_wrap,
1575 WORKQUEUE_CRITICAL, ifp);
1576}
1577
1578static void
1579ndis_linksts(adapter, status, sbuf, slen)
1580 ndis_handle adapter;
1581 ndis_status status;
1582 void *sbuf;
1583 uint32_t slen;
1584{
1585 ndis_miniport_block *block;
1586 struct ndis_softc *sc;
1587
1588 block = adapter;
1589 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1590 sc->ndis_sts = status;
1591
1592 /* Event list is all full up, drop this one. */
1593
1594 NDIS_LOCK(sc);
1595 if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1596 NDIS_UNLOCK(sc);
1597 return;
1598 }
1599
1600 /* Cache the event. */
1601
1602 if (slen) {
1603 sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen,
1604 M_TEMP, M_NOWAIT);
1605 if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1606 NDIS_UNLOCK(sc);
1607 return;
1608 }
1609 bcopy((char *)sbuf,
1610 sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1611 }
1612 sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status;
1613 sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen;
1614 NDIS_EVTINC(sc->ndis_evtpidx);
1615 NDIS_UNLOCK(sc);
1616}
1617
1618static void
1619ndis_linksts_done(adapter)
1620 ndis_handle adapter;
1621{
1622 ndis_miniport_block *block;
1623 struct ndis_softc *sc;
1624 struct ifnet *ifp;
1625
1626 block = adapter;
1627 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1628 ifp = sc->ifp;
1629
1630 if (!NDIS_INITIALIZED(sc))
1631 return;
1632
1633 switch (sc->ndis_sts) {
1634 case NDIS_STATUS_MEDIA_CONNECT:
1635 IoQueueWorkItem(sc->ndis_tickitem,
1636 (io_workitem_func)ndis_ticktask_wrap,
1637 WORKQUEUE_CRITICAL, sc);
1638 IoQueueWorkItem(sc->ndis_startitem,
1639 (io_workitem_func)ndis_starttask_wrap,
1640 WORKQUEUE_CRITICAL, ifp);
1641 break;
1642 case NDIS_STATUS_MEDIA_DISCONNECT:
1643 if (sc->ndis_link)
1644 IoQueueWorkItem(sc->ndis_tickitem,
1645 (io_workitem_func)ndis_ticktask_wrap,
1646 WORKQUEUE_CRITICAL, sc);
1647 break;
1648 default:
1649 break;
1650 }
1651}
1652
1653static void
1654ndis_tick(xsc)
1655 void *xsc;
1656{
1657 struct ndis_softc *sc;
1658
1659 sc = xsc;
1660
1661 if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) {
1662 IoQueueWorkItem(sc->ndis_tickitem,
1663 (io_workitem_func)ndis_ticktask_wrap,
1664 WORKQUEUE_CRITICAL, sc);
1665 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1666 }
1667
1668 if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) {
1669 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
1670 device_printf(sc->ndis_dev, "watchdog timeout\n");
1671
1672 IoQueueWorkItem(sc->ndis_resetitem,
1673 (io_workitem_func)ndis_resettask_wrap,
1674 WORKQUEUE_CRITICAL, sc);
1675 IoQueueWorkItem(sc->ndis_startitem,
1676 (io_workitem_func)ndis_starttask_wrap,
1677 WORKQUEUE_CRITICAL, sc->ifp);
1678 }
1679
1680 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1681}
1682
1683static void
1684ndis_ticktask(device_object *d, void *xsc)
1685{
1686 struct ndis_softc *sc = xsc;
1687 ndis_checkforhang_handler hangfunc;
1688 uint8_t rval;
1689
1690 NDIS_LOCK(sc);
1691 if (!NDIS_INITIALIZED(sc)) {
1692 NDIS_UNLOCK(sc);
1693 return;
1694 }
1695 NDIS_UNLOCK(sc);
1696
1697 hangfunc = sc->ndis_chars->nmc_checkhang_func;
1698
1699 if (hangfunc != NULL) {
1700 rval = MSCALL1(hangfunc,
1701 sc->ndis_block->nmb_miniportadapterctx);
1702 if (rval == TRUE) {
1703 ndis_reset_nic(sc);
1704 return;
1705 }
1706 }
1707
1708 NDIS_LOCK(sc);
1709 if (sc->ndis_link == 0 &&
1710 sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
1711 sc->ndis_link = 1;
1712 if (sc->ndis_80211 != 0) {
1713 struct ieee80211com *ic = &sc->ndis_ic;
1714 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1715
1716 if (vap != NULL) {
1717 NDIS_UNLOCK(sc);
1718 ndis_getstate_80211(sc);
1719 ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1720 NDIS_LOCK(sc);
1721 if_link_state_change(vap->iv_ifp,
1722 LINK_STATE_UP);
1723 }
1724 } else
1725 if_link_state_change(sc->ifp, LINK_STATE_UP);
1726 }
1727
1728 if (sc->ndis_link == 1 &&
1729 sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1730 sc->ndis_link = 0;
1731 if (sc->ndis_80211 != 0) {
1732 struct ieee80211com *ic = &sc->ndis_ic;
1733 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1734
1735 if (vap != NULL) {
1736 NDIS_UNLOCK(sc);
1737 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1738 NDIS_LOCK(sc);
1739 if_link_state_change(vap->iv_ifp,
1740 LINK_STATE_DOWN);
1741 }
1742 } else
1743 if_link_state_change(sc->ifp, LINK_STATE_DOWN);
1744 }
1745
1746 NDIS_UNLOCK(sc);
1747}
1748
1749static void
1750ndis_map_sclist(arg, segs, nseg, mapsize, error)
1751 void *arg;
1752 bus_dma_segment_t *segs;
1753 int nseg;
1754 bus_size_t mapsize;
1755 int error;
1756
1757{
1758 struct ndis_sc_list *sclist;
1759 int i;
1760
1761 if (error || arg == NULL)
1762 return;
1763
1764 sclist = arg;
1765
1766 sclist->nsl_frags = nseg;
1767
1768 for (i = 0; i < nseg; i++) {
1769 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1770 sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1771 }
1772}
1773
1774static int
1775ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1776 const struct ieee80211_bpf_params *params)
1777{
1778 /* no support; just discard */
1779 m_freem(m);
1780 ieee80211_free_node(ni);
1781 return (0);
1782}
1783
1784static void
1785ndis_update_mcast(struct ieee80211com *ic)
1786{
1787 struct ndis_softc *sc = ic->ic_softc;
1788
1789 ndis_setmulti(sc);
1790}
1791
1792static void
1793ndis_update_promisc(struct ieee80211com *ic)
1794{
1795 /* not supported */
1796}
1797
1798static void
1799ndis_starttask(d, arg)
1800 device_object *d;
1801 void *arg;
1802{
1803 struct ifnet *ifp;
1804
1805 ifp = arg;
1806
1807 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1808 ndis_start(ifp);
1809}
1810
1811/*
1812 * Main transmit routine. To make NDIS drivers happy, we need to
1813 * transform mbuf chains into NDIS packets and feed them to the
1814 * send packet routines. Most drivers allow you to send several
1815 * packets at once (up to the maxpkts limit). Unfortunately, rather
1816 * that accepting them in the form of a linked list, they expect
1817 * a contiguous array of pointers to packets.
1818 *
1819 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1820 * we need to perform busdma work here. Those that use map registers
1821 * will do the mapping themselves on a buffer by buffer basis.
1822 */
1823static void
1824ndis_start(ifp)
1825 struct ifnet *ifp;
1826{
1827 struct ndis_softc *sc;
1828 struct mbuf *m = NULL;
1829 ndis_packet **p0 = NULL, *p = NULL;
1830 ndis_tcpip_csum *csum;
1831 int pcnt = 0, status;
1832
1833 sc = ifp->if_softc;
1834
1835 NDIS_LOCK(sc);
1836 if (!sc->ndis_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) {
1837 NDIS_UNLOCK(sc);
1838 return;
1839 }
1840
1841 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1842
1843 while(sc->ndis_txpending) {
1844 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1845 if (m == NULL)
1846 break;
1847
1848 NdisAllocatePacket(&status,
1849 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1850
1851 if (status != NDIS_STATUS_SUCCESS)
1852 break;
1853
1854 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1855 IFQ_DRV_PREPEND(&ifp->if_snd, m);
1856 NDIS_UNLOCK(sc);
1857 return;
1858 }
1859
1860 /*
1861 * Save pointer to original mbuf
1862 * so we can free it later.
1863 */
1864
1865 p = sc->ndis_txarray[sc->ndis_txidx];
1866 p->np_txidx = sc->ndis_txidx;
1867 p->np_m0 = m;
1868 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1869
1870 /*
1871 * Do scatter/gather processing, if driver requested it.
1872 */
1873 if (sc->ndis_sc) {
1874 bus_dmamap_load_mbuf(sc->ndis_ttag,
1875 sc->ndis_tmaps[sc->ndis_txidx], m,
1876 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1877 bus_dmamap_sync(sc->ndis_ttag,
1878 sc->ndis_tmaps[sc->ndis_txidx],
1879 BUS_DMASYNC_PREREAD);
1880 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1881 }
1882
1883 /* Handle checksum offload. */
1884
1885 if (ifp->if_capenable & IFCAP_TXCSUM &&
1886 m->m_pkthdr.csum_flags) {
1887 csum = (ndis_tcpip_csum *)
1888 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1889 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1890 if (m->m_pkthdr.csum_flags & CSUM_IP)
1891 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1892 if (m->m_pkthdr.csum_flags & CSUM_TCP)
1893 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1894 if (m->m_pkthdr.csum_flags & CSUM_UDP)
1895 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1896 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1897 }
1898
1899 NDIS_INC(sc);
1900 sc->ndis_txpending--;
1901
1902 pcnt++;
1903
1904 /*
1905 * If there's a BPF listener, bounce a copy of this frame
1906 * to him.
1907 */
1908 if (!sc->ndis_80211) /* XXX handle 80211 */
1909 BPF_MTAP(ifp, m);
1910
1911 /*
1912 * The array that p0 points to must appear contiguous,
1913 * so we must not wrap past the end of sc->ndis_txarray[].
1914 * If it looks like we're about to wrap, break out here
1915 * so the this batch of packets can be transmitted, then
1916 * wait for txeof to ask us to send the rest.
1917 */
1918 if (sc->ndis_txidx == 0)
1919 break;
1920 }
1921
1922 if (pcnt == 0) {
1923 NDIS_UNLOCK(sc);
1924 return;
1925 }
1926
1927 if (sc->ndis_txpending == 0)
1928 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1929
1930 /*
1931 * Set a timeout in case the chip goes out to lunch.
1932 */
1933 sc->ndis_tx_timer = 5;
1934
1935 NDIS_UNLOCK(sc);
1936
1937 /*
1938 * According to NDIS documentation, if a driver exports
1939 * a MiniportSendPackets() routine, we prefer that over
1940 * a MiniportSend() routine (which sends just a single
1941 * packet).
1942 */
1943 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1944 ndis_send_packets(sc, p0, pcnt);
1945 else
1946 ndis_send_packet(sc, p);
1947
1948 return;
1949}
1950
1951static int
1952ndis_80211transmit(struct ieee80211com *ic, struct mbuf *m)
1953{
1954 struct ndis_softc *sc = ic->ic_softc;
1955 ndis_packet **p0 = NULL, *p = NULL;
1956 int status;
1957
1958 NDIS_LOCK(sc);
1959 if (!sc->ndis_link || !sc->ndis_running) {
1960 NDIS_UNLOCK(sc);
1961 return (ENXIO);
1962 }
1963
1964 if (sc->ndis_txpending == 0) {
1965 NDIS_UNLOCK(sc);
1966 return (ENOBUFS);
1967 }
1968
1969 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1970
1971 NdisAllocatePacket(&status,
1972 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1973
1974 if (status != NDIS_STATUS_SUCCESS) {
1975 NDIS_UNLOCK(sc);
1976 return (ENOBUFS);
1977 }
1978
1979 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1980 NDIS_UNLOCK(sc);
1981 return (ENOBUFS);
1982 }
1983
1984 /*
1985 * Save pointer to original mbuf
1986 * so we can free it later.
1987 */
1988
1989 p = sc->ndis_txarray[sc->ndis_txidx];
1990 p->np_txidx = sc->ndis_txidx;
1991 p->np_m0 = m;
1992 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1993
1994 /*
1995 * Do scatter/gather processing, if driver requested it.
1996 */
1997 if (sc->ndis_sc) {
1998 bus_dmamap_load_mbuf(sc->ndis_ttag,
1999 sc->ndis_tmaps[sc->ndis_txidx], m,
2000 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
2001 bus_dmamap_sync(sc->ndis_ttag,
2002 sc->ndis_tmaps[sc->ndis_txidx],
2003 BUS_DMASYNC_PREREAD);
2004 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
2005 }
2006
2007 NDIS_INC(sc);
2008 sc->ndis_txpending--;
2009
2010 /*
2011 * Set a timeout in case the chip goes out to lunch.
2012 */
2013 sc->ndis_tx_timer = 5;
2014 NDIS_UNLOCK(sc);
2015
2016 /*
2017 * According to NDIS documentation, if a driver exports
2018 * a MiniportSendPackets() routine, we prefer that over
2019 * a MiniportSend() routine (which sends just a single
2020 * packet).
2021 */
2022 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
2023 ndis_send_packets(sc, p0, 1);
2024 else
2025 ndis_send_packet(sc, p);
2026
2027 return (0);
2028}
2029
2030static void
2031ndis_80211parent(struct ieee80211com *ic)
2032{
2033 struct ndis_softc *sc = ic->ic_softc;
2034
2035 /*NDIS_LOCK(sc);*/
2036 if (ic->ic_nrunning > 0) {
2037 if (!sc->ndis_running)
2038 ndis_init(sc);
2039 } else if (sc->ndis_running)
2040 ndis_stop(sc);
2041 /*NDIS_UNLOCK(sc);*/
2042}
2043
2044static void
2045ndis_init(void *xsc)
2046{
2047 struct ndis_softc *sc = xsc;
2048 int i, len, error;
2049
2050 /*
2051 * Avoid reintializing the link unnecessarily.
2052 * This should be dealt with in a better way by
2053 * fixing the upper layer modules so they don't
2054 * call ifp->if_init() quite as often.
2055 */
2056 if (sc->ndis_link)
2057 return;
2058
2059 /*
2060 * Cancel pending I/O and free all RX/TX buffers.
2061 */
2062 ndis_stop(sc);
2063
2064 if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
2065 error = ndis_init_nic(sc);
2066 if (error != 0) {
2067 device_printf(sc->ndis_dev,
2068 "failed to initialize the device: %d\n", error);
2069 return;
2070 }
2071 }
2072
2073 /* Program the packet filter */
2074 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED |
2075 NDIS_PACKET_TYPE_BROADCAST;
2076
2077 if (sc->ndis_80211) {
2078 struct ieee80211com *ic = &sc->ndis_ic;
2079
2080 if (ic->ic_promisc > 0)
2081 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2082 } else {
2083 struct ifnet *ifp = sc->ifp;
2084
2085 if (ifp->if_flags & IFF_PROMISC)
2086 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2087 }
2088
2089 len = sizeof(sc->ndis_filter);
2090
2091 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
2092 &sc->ndis_filter, &len);
2093
2094 if (error)
2095 device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
2096
2097 /*
2098 * Set lookahead.
2099 */
2100 if (sc->ndis_80211)
2101 i = ETHERMTU;
2102 else
2103 i = sc->ifp->if_mtu;
2104 len = sizeof(i);
2105 ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
2106
2107 /*
2108 * Program the multicast filter, if necessary.
2109 */
2110 ndis_setmulti(sc);
2111
2112 /* Setup task offload. */
2113 ndis_set_offload(sc);
2114
2115 NDIS_LOCK(sc);
2116
2117 sc->ndis_txidx = 0;
2118 sc->ndis_txpending = sc->ndis_maxpkts;
2119 sc->ndis_link = 0;
2120
2121 if (!sc->ndis_80211) {
2122 if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN);
2123 sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
2124 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2125 }
2126
2127 sc->ndis_tx_timer = 0;
2128
2129 /*
2130 * Some drivers don't set this value. The NDIS spec says
2131 * the default checkforhang timeout is "approximately 2
2132 * seconds." We use 3 seconds, because it seems for some
2133 * drivers, exactly 2 seconds is too fast.
2134 */
2135 if (sc->ndis_block->nmb_checkforhangsecs == 0)
2136 sc->ndis_block->nmb_checkforhangsecs = 3;
2137
2138 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
2139 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
2140 sc->ndis_running = 1;
2141 NDIS_UNLOCK(sc);
2142
2143 /* XXX force handling */
2144 if (sc->ndis_80211)
2145 ieee80211_start_all(&sc->ndis_ic); /* start all vap's */
2146}
2147
2148/*
2149 * Set media options.
2150 */
2151static int
2152ndis_ifmedia_upd(ifp)
2153 struct ifnet *ifp;
2154{
2155 struct ndis_softc *sc;
2156
2157 sc = ifp->if_softc;
2158
2159 if (NDIS_INITIALIZED(sc))
2160 ndis_init(sc);
2161
2162 return (0);
2163}
2164
2165/*
2166 * Report current media status.
2167 */
2168static void
2169ndis_ifmedia_sts(ifp, ifmr)
2170 struct ifnet *ifp;
2171 struct ifmediareq *ifmr;
2172{
2173 struct ndis_softc *sc;
2174 uint32_t media_info;
2175 ndis_media_state linkstate;
2176 int len;
2177
2178 ifmr->ifm_status = IFM_AVALID;
2179 ifmr->ifm_active = IFM_ETHER;
2180 sc = ifp->if_softc;
2181
2182 if (!NDIS_INITIALIZED(sc))
2183 return;
2184
2185 len = sizeof(linkstate);
2186 ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2187 (void *)&linkstate, &len);
2188
2189 len = sizeof(media_info);
2190 ndis_get_info(sc, OID_GEN_LINK_SPEED,
2191 (void *)&media_info, &len);
2192
2193 if (linkstate == nmc_connected)
2194 ifmr->ifm_status |= IFM_ACTIVE;
2195
2196 switch (media_info) {
2197 case 100000:
2198 ifmr->ifm_active |= IFM_10_T;
2199 break;
2200 case 1000000:
2201 ifmr->ifm_active |= IFM_100_TX;
2202 break;
2203 case 10000000:
2204 ifmr->ifm_active |= IFM_1000_T;
2205 break;
2206 default:
2207 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2208 break;
2209 }
2210}
2211
2212static int
2213ndis_set_cipher(struct ndis_softc *sc, int cipher)
2214{
2215 struct ieee80211com *ic = &sc->ndis_ic;
2216 int rval = 0, len;
2217 uint32_t arg, save;
2218
2219 len = sizeof(arg);
2220
2221 if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2222 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2223 return (ENOTSUP);
2224 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2225 }
2226
2227 if (cipher == WPA_CSE_TKIP) {
2228 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2229 return (ENOTSUP);
2230 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2231 }
2232
2233 if (cipher == WPA_CSE_CCMP) {
2234 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2235 return (ENOTSUP);
2236 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2237 }
2238
2239 DPRINTF(("Setting cipher to %d\n", arg));
2240 save = arg;
2241 rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2242
2243 if (rval)
2244 return (rval);
2245
2246 /* Check that the cipher was set correctly. */
2247
2248 len = sizeof(save);
2249 rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2250
2251 if (rval != 0 || arg != save)
2252 return (ENODEV);
2253
2254 return (0);
2255}
2256
2257/*
2258 * WPA is hairy to set up. Do the work in a separate routine
2259 * so we don't clutter the setstate function too much.
2260 * Important yet undocumented fact: first we have to set the
2261 * authentication mode, _then_ we enable the ciphers. If one
2262 * of the WPA authentication modes isn't enabled, the driver
2263 * might not permit the TKIP or AES ciphers to be selected.
2264 */
2265static int
2266ndis_set_wpa(sc, ie, ielen)
2267 struct ndis_softc *sc;
2268 void *ie;
2269 int ielen;
2270{
2271 struct ieee80211_ie_wpa *w;
2272 struct ndis_ie *n;
2273 char *pos;
2274 uint32_t arg;
2275 int i;
2276
2277 /*
2278 * Apparently, the only way for us to know what ciphers
2279 * and key management/authentication mode to use is for
2280 * us to inspect the optional information element (IE)
2281 * stored in the 802.11 state machine. This IE should be
2282 * supplied by the WPA supplicant.
2283 */
2284
2285 w = (struct ieee80211_ie_wpa *)ie;
2286
2287 /* Check for the right kind of IE. */
2288 if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2289 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2290 return (EINVAL);
2291 }
2292
2293 /* Skip over the ucast cipher OIDs. */
2294 pos = (char *)&w->wpa_uciphers[0];
2295 pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2296
2297 /* Skip over the authmode count. */
2298 pos += sizeof(u_int16_t);
2299
2300 /*
2301 * Check for the authentication modes. I'm
2302 * pretty sure there's only supposed to be one.
2303 */
2304
2305 n = (struct ndis_ie *)pos;
2306 if (n->ni_val == WPA_ASE_NONE)
2307 arg = NDIS_80211_AUTHMODE_WPANONE;
2308
2309 if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2310 arg = NDIS_80211_AUTHMODE_WPA;
2311
2312 if (n->ni_val == WPA_ASE_8021X_PSK)
2313 arg = NDIS_80211_AUTHMODE_WPAPSK;
2314
2315 DPRINTF(("Setting WPA auth mode to %d\n", arg));
2316 i = sizeof(arg);
2317 if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2318 return (ENOTSUP);
2319 i = sizeof(arg);
2320 ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2321
2322 /* Now configure the desired ciphers. */
2323
2324 /* First, set up the multicast group cipher. */
2325 n = (struct ndis_ie *)&w->wpa_mcipher[0];
2326
2327 if (ndis_set_cipher(sc, n->ni_val))
2328 return (ENOTSUP);
2329
2330 /* Now start looking around for the unicast ciphers. */
2331 pos = (char *)&w->wpa_uciphers[0];
2332 n = (struct ndis_ie *)pos;
2333
2334 for (i = 0; i < w->wpa_uciphercnt; i++) {
2335 if (ndis_set_cipher(sc, n->ni_val))
2336 return (ENOTSUP);
2337 n++;
2338 }
2339
2340 return (0);
2341}
2342
2343static void
2344ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2345{
2346 struct ieee80211vap *vap = ifp->if_softc;
2347 struct ndis_softc *sc = vap->iv_ic->ic_softc;
2348 uint32_t txrate;
2349 int len;
2350
2351 if (!NDIS_INITIALIZED(sc))
2352 return;
2353
2354 len = sizeof(txrate);
2355 if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0)
2356 vap->iv_bss->ni_txrate = txrate / 5000;
2357 ieee80211_media_status(ifp, imr);
2358}
2359
2360static void
2361ndis_setstate_80211(struct ndis_softc *sc)
2362{
2363 struct ieee80211com *ic = &sc->ndis_ic;
2364 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2365 ndis_80211_macaddr bssid;
2366 ndis_80211_config config;
2367 int rval = 0, len;
2368 uint32_t arg;
2369
2370 if (!NDIS_INITIALIZED(sc)) {
2371 DPRINTF(("%s: NDIS not initialized\n", __func__));
2372 return;
2373 }
2374
2375 /* Disassociate and turn off radio. */
2376 len = sizeof(arg);
2377 arg = 1;
2378 ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2379
2380 /* Set network infrastructure mode. */
2381
2382 len = sizeof(arg);
2383 if (ic->ic_opmode == IEEE80211_M_IBSS)
2384 arg = NDIS_80211_NET_INFRA_IBSS;
2385 else
2386 arg = NDIS_80211_NET_INFRA_BSS;
2387
2388 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2389
2390 if (rval)
2391 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2392
2393 /* Set power management */
2394 len = sizeof(arg);
2395 if (vap->iv_flags & IEEE80211_F_PMGTON)
2396 arg = NDIS_80211_POWERMODE_FAST_PSP;
2397 else
2398 arg = NDIS_80211_POWERMODE_CAM;
2399 ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2400
2401 /* Set TX power */
2402 if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2403 ic->ic_txpowlimit < nitems(dBm2mW)) {
2404 arg = dBm2mW[ic->ic_txpowlimit];
2405 len = sizeof(arg);
2406 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2407 }
2408
2409 /*
2410 * Default encryption mode to off, authentication
2411 * to open and privacy to 'accept everything.'
2412 */
2413 len = sizeof(arg);
2414 arg = NDIS_80211_WEPSTAT_DISABLED;
2415 ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2416
2417 len = sizeof(arg);
2418 arg = NDIS_80211_AUTHMODE_OPEN;
2419 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2420
2421 /*
2422 * Note that OID_802_11_PRIVACY_FILTER is optional:
2423 * not all drivers implement it.
2424 */
2425 len = sizeof(arg);
2426 arg = NDIS_80211_PRIVFILT_8021XWEP;
2427 ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2428
2429 len = sizeof(config);
2430 bzero((char *)&config, len);
2431 config.nc_length = len;
2432 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2433 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
2434
2435 /*
2436 * Some drivers expect us to initialize these values, so
2437 * provide some defaults.
2438 */
2439
2440 if (config.nc_beaconperiod == 0)
2441 config.nc_beaconperiod = 100;
2442 if (config.nc_atimwin == 0)
2443 config.nc_atimwin = 100;
2444 if (config.nc_fhconfig.ncf_dwelltime == 0)
2445 config.nc_fhconfig.ncf_dwelltime = 200;
2446 if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
2447 int chan, chanflag;
2448
2449 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2450 chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ :
2451 IEEE80211_CHAN_5GHZ;
2452 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2453 config.nc_dsconfig =
2454 ic->ic_bsschan->ic_freq * 1000;
2455 len = sizeof(config);
2456 config.nc_length = len;
2457 config.nc_fhconfig.ncf_length =
2458 sizeof(ndis_80211_config_fh);
2459 DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2460 rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2461 &config, &len);
2462 if (rval)
2463 device_printf(sc->ndis_dev, "couldn't change "
2464 "DS config to %ukHz: %d\n",
2465 config.nc_dsconfig, rval);
2466 }
2467 } else if (rval)
2468 device_printf(sc->ndis_dev, "couldn't retrieve "
2469 "channel info: %d\n", rval);
2470
2471 /* Set the BSSID to our value so the driver doesn't associate */
2472 len = IEEE80211_ADDR_LEN;
2473 bcopy(vap->iv_myaddr, bssid, len);
2474 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2475 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2476 if (rval)
2477 device_printf(sc->ndis_dev,
2478 "setting BSSID failed: %d\n", rval);
2479}
2480
2481static void
2482ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap)
2483{
2484 struct ieee80211_node *ni = vap->iv_bss;
2485 ndis_80211_ssid ssid;
2486 ndis_80211_macaddr bssid;
2487 ndis_80211_wep wep;
2488 int i, rval = 0, len, error;
2489 uint32_t arg;
2490
2491 if (!NDIS_INITIALIZED(sc)) {
2492 DPRINTF(("%s: NDIS not initialized\n", __func__));
2493 return;
2494 }
2495
2496 /* Initial setup */
2497 ndis_setstate_80211(sc);
2498
2499 /* Set network infrastructure mode. */
2500
2501 len = sizeof(arg);
2502 if (vap->iv_opmode == IEEE80211_M_IBSS)
2503 arg = NDIS_80211_NET_INFRA_IBSS;
2504 else
2505 arg = NDIS_80211_NET_INFRA_BSS;
2506
2507 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2508
2509 if (rval)
2510 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2511
2512 /* Set RTS threshold */
2513
2514 len = sizeof(arg);
2515 arg = vap->iv_rtsthreshold;
2516 ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2517
2518 /* Set fragmentation threshold */
2519
2520 len = sizeof(arg);
2521 arg = vap->iv_fragthreshold;
2522 ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2523
2524 /* Set WEP */
2525
2526 if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2527 !(vap->iv_flags & IEEE80211_F_WPA)) {
2528 int keys_set = 0;
2529
2530 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2531 len = sizeof(arg);
2532 arg = NDIS_80211_AUTHMODE_SHARED;
2533 DPRINTF(("Setting shared auth\n"));
2534 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2535 &arg, &len);
2536 }
2537 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2538 if (vap->iv_nw_keys[i].wk_keylen) {
2539 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2540 IEEE80211_CIPHER_WEP)
2541 continue;
2542 bzero((char *)&wep, sizeof(wep));
2543 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2544
2545 /*
2546 * 5, 13 and 16 are the only valid
2547 * key lengths. Anything in between
2548 * will be zero padded out to the
2549 * next highest boundary.
2550 */
2551 if (vap->iv_nw_keys[i].wk_keylen < 5)
2552 wep.nw_keylen = 5;
2553 else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2554 vap->iv_nw_keys[i].wk_keylen < 13)
2555 wep.nw_keylen = 13;
2556 else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2557 vap->iv_nw_keys[i].wk_keylen < 16)
2558 wep.nw_keylen = 16;
2559
2560 wep.nw_keyidx = i;
2561 wep.nw_length = (sizeof(uint32_t) * 3)
2562 + wep.nw_keylen;
2563 if (i == vap->iv_def_txkey)
2564 wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2565 bcopy(vap->iv_nw_keys[i].wk_key,
2566 wep.nw_keydata, wep.nw_length);
2567 len = sizeof(wep);
2568 DPRINTF(("Setting WEP key %d\n", i));
2569 rval = ndis_set_info(sc,
2570 OID_802_11_ADD_WEP, &wep, &len);
2571 if (rval)
2572 device_printf(sc->ndis_dev,
2573 "set wepkey failed: %d\n", rval);
2574 keys_set++;
2575 }
2576 }
2577 if (keys_set) {
2578 DPRINTF(("Setting WEP on\n"));
2579 arg = NDIS_80211_WEPSTAT_ENABLED;
2580 len = sizeof(arg);
2581 rval = ndis_set_info(sc,
2582 OID_802_11_WEP_STATUS, &arg, &len);
2583 if (rval)
2584 device_printf(sc->ndis_dev,
2585 "enable WEP failed: %d\n", rval);
2586 if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2587 arg = NDIS_80211_PRIVFILT_8021XWEP;
2588 else
2589 arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2590
2591 len = sizeof(arg);
2592 ndis_set_info(sc,
2593 OID_802_11_PRIVACY_FILTER, &arg, &len);
2594 }
2595 }
2596
2597 /* Set up WPA. */
2598 if ((vap->iv_flags & IEEE80211_F_WPA) &&
2599 vap->iv_appie_assocreq != NULL) {
2600 struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2601 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2602 if (error != 0)
2603 device_printf(sc->ndis_dev, "WPA setup failed\n");
2604 }
2605
2606#ifdef notyet
2607 /* Set network type. */
2608
2609 arg = 0;
2610
2611 switch (vap->iv_curmode) {
2612 case IEEE80211_MODE_11A:
2613 arg = NDIS_80211_NETTYPE_11OFDM5;
2614 break;
2615 case IEEE80211_MODE_11B:
2616 arg = NDIS_80211_NETTYPE_11DS;
2617 break;
2618 case IEEE80211_MODE_11G:
2619 arg = NDIS_80211_NETTYPE_11OFDM24;
2620 break;
2621 default:
2622 device_printf(sc->ndis_dev, "unknown mode: %d\n",
2623 vap->iv_curmode);
2624 }
2625
2626 if (arg) {
2627 DPRINTF(("Setting network type to %d\n", arg));
2628 len = sizeof(arg);
2629 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2630 &arg, &len);
2631 if (rval)
2632 device_printf(sc->ndis_dev,
2633 "set nettype failed: %d\n", rval);
2634 }
2635#endif
2636
2637 /*
2638 * If the user selected a specific BSSID, try
2639 * to use that one. This is useful in the case where
2640 * there are several APs in range with the same network
2641 * name. To delete the BSSID, we use the broadcast
2642 * address as the BSSID.
2643 * Note that some drivers seem to allow setting a BSSID
2644 * in ad-hoc mode, which has the effect of forcing the
2645 * NIC to create an ad-hoc cell with a specific BSSID,
2646 * instead of a randomly chosen one. However, the net80211
2647 * code makes the assumtion that the BSSID setting is invalid
2648 * when you're in ad-hoc mode, so we don't allow that here.
2649 */
2650
2651 len = IEEE80211_ADDR_LEN;
2652 if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2653 vap->iv_opmode != IEEE80211_M_IBSS)
2654 bcopy(ni->ni_bssid, bssid, len);
2655 else
2656 bcopy(ieee80211broadcastaddr, bssid, len);
2657
2658 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2659 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2660 if (rval)
2661 device_printf(sc->ndis_dev,
2662 "setting BSSID failed: %d\n", rval);
2663
2664 /* Set SSID -- always do this last. */
2665
2666#ifdef NDIS_DEBUG
2667 if (ndis_debug > 0) {
2668 printf("Setting ESSID to ");
2669 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2670 printf("\n");
2671 }
2672#endif
2673
2674 len = sizeof(ssid);
2675 bzero((char *)&ssid, len);
2676 ssid.ns_ssidlen = ni->ni_esslen;
2677 if (ssid.ns_ssidlen == 0) {
2678 ssid.ns_ssidlen = 1;
2679 } else
2680 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2681
2682 rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2683
2684 if (rval)
2685 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2686
2687 return;
2688}
2689
2690static int
2691ndis_get_bssid_list(sc, bl)
2692 struct ndis_softc *sc;
2693 ndis_80211_bssid_list_ex **bl;
2694{
2695 int len, error;
2696
2697 len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2698 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2699 if (*bl == NULL)
2700 return (ENOMEM);
2701
2702 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2703 if (error == ENOSPC) {
2704 free(*bl, M_DEVBUF);
2705 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2706 if (*bl == NULL)
2707 return (ENOMEM);
2708
2709 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2710 }
2711 if (error) {
2712 DPRINTF(("%s: failed to read\n", __func__));
2713 free(*bl, M_DEVBUF);
2714 return (error);
2715 }
2716
2717 return (0);
2718}
2719
2720static int
2721ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc)
2722{
2723 struct ieee80211com *ic = &sc->ndis_ic;
2724 struct ieee80211vap *vap;
2725 struct ieee80211_node *ni;
2726 ndis_80211_bssid_list_ex *bl;
2727 ndis_wlan_bssid_ex *bs;
2728 ndis_80211_macaddr bssid;
2729 int i, len, error;
2730
2731 if (!sc->ndis_link)
2732 return (ENOENT);
2733
2734 len = sizeof(bssid);
2735 error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2736 if (error) {
2737 device_printf(sc->ndis_dev, "failed to get bssid\n");
2738 return (ENOENT);
2739 }
2740
2741 vap = TAILQ_FIRST(&ic->ic_vaps);
2742 ni = vap->iv_bss;
2743
2744 error = ndis_get_bssid_list(sc, &bl);
2745 if (error)
2746 return (error);
2747
2748 bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2749 for (i = 0; i < bl->nblx_items; i++) {
2750 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2751 *assoc = malloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2752 if (*assoc == NULL) {
2753 free(bl, M_TEMP);
2754 return (ENOMEM);
2755 }
2756 bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2757 free(bl, M_TEMP);
2758 if (ic->ic_opmode == IEEE80211_M_STA)
2759 ni->ni_associd = 1 | 0xc000; /* fake associd */
2760 return (0);
2761 }
2762 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2763 }
2764
2765 free(bl, M_TEMP);
2766 return (ENOENT);
2767}
2768
2769static void
2770ndis_getstate_80211(struct ndis_softc *sc)
2771{
2772 struct ieee80211com *ic = &sc->ndis_ic;
2773 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2774 struct ieee80211_node *ni = vap->iv_bss;
2775 ndis_wlan_bssid_ex *bs;
2776 int rval, len, i = 0;
2777 int chanflag;
2778 uint32_t arg;
2779
2780 if (!NDIS_INITIALIZED(sc))
2781 return;
2782
2783 if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2784 return;
2785
2786 /* We're associated, retrieve info on the current bssid. */
2787 ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2788 chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2789 IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2790
2791 /* Get SSID from current association info. */
2792 bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2793 bs->nwbx_ssid.ns_ssidlen);
2794 ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2795
2796 if (ic->ic_caps & IEEE80211_C_PMGT) {
2797 len = sizeof(arg);
2798 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2799
2800 if (rval)
2801 device_printf(sc->ndis_dev,
2802 "get power mode failed: %d\n", rval);
2803 if (arg == NDIS_80211_POWERMODE_CAM)
2804 vap->iv_flags &= ~IEEE80211_F_PMGTON;
2805 else
2806 vap->iv_flags |= IEEE80211_F_PMGTON;
2807 }
2808
2809 /* Get TX power */
2810 if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2811 len = sizeof(arg);
2812 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2813 for (i = 0; i < nitems(dBm2mW); i++)
2814 if (dBm2mW[i] >= arg)
2815 break;
2816 ic->ic_txpowlimit = i;
2817 }
2818
2819 /*
2820 * Use the current association information to reflect
2821 * what channel we're on.
2822 */
2823 ic->ic_curchan = ieee80211_find_channel(ic,
2824 bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2825 if (ic->ic_curchan == NULL)
2826 ic->ic_curchan = &ic->ic_channels[0];
2827 ni->ni_chan = ic->ic_curchan;
2828 ic->ic_bsschan = ic->ic_curchan;
2829
2830 free(bs, M_TEMP);
2831
2832 /*
2833 * Determine current authentication mode.
2834 */
2835 len = sizeof(arg);
2836 rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2837 if (rval)
2838 device_printf(sc->ndis_dev,
2839 "get authmode status failed: %d\n", rval);
2840 else {
2841 vap->iv_flags &= ~IEEE80211_F_WPA;
2842 switch (arg) {
2843 case NDIS_80211_AUTHMODE_OPEN:
2844 ni->ni_authmode = IEEE80211_AUTH_OPEN;
2845 break;
2846 case NDIS_80211_AUTHMODE_SHARED:
2847 ni->ni_authmode = IEEE80211_AUTH_SHARED;
2848 break;
2849 case NDIS_80211_AUTHMODE_AUTO:
2850 ni->ni_authmode = IEEE80211_AUTH_AUTO;
2851 break;
2852 case NDIS_80211_AUTHMODE_WPA:
2853 case NDIS_80211_AUTHMODE_WPAPSK:
2854 case NDIS_80211_AUTHMODE_WPANONE:
2855 ni->ni_authmode = IEEE80211_AUTH_WPA;
2856 vap->iv_flags |= IEEE80211_F_WPA1;
2857 break;
2858 case NDIS_80211_AUTHMODE_WPA2:
2859 case NDIS_80211_AUTHMODE_WPA2PSK:
2860 ni->ni_authmode = IEEE80211_AUTH_WPA;
2861 vap->iv_flags |= IEEE80211_F_WPA2;
2862 break;
2863 default:
2864 ni->ni_authmode = IEEE80211_AUTH_NONE;
2865 break;
2866 }
2867 }
2868
2869 len = sizeof(arg);
2870 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2871
2872 if (rval)
2873 device_printf(sc->ndis_dev,
2874 "get wep status failed: %d\n", rval);
2875
2876 if (arg == NDIS_80211_WEPSTAT_ENABLED)
2877 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2878 else
2879 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2880}
2881
2882static int
2883ndis_ioctl(ifp, command, data)
2884 struct ifnet *ifp;
2885 u_long command;
2886 caddr_t data;
2887{
2888 struct ndis_softc *sc = ifp->if_softc;
2889 struct ifreq *ifr = (struct ifreq *) data;
2890 int i, error = 0;
2891
2892 /*NDIS_LOCK(sc);*/
2893
2894 switch (command) {
2895 case SIOCSIFFLAGS:
2896 if (ifp->if_flags & IFF_UP) {
2897 if (sc->ndis_running &&
2898 ifp->if_flags & IFF_PROMISC &&
2899 !(sc->ndis_if_flags & IFF_PROMISC)) {
2900 sc->ndis_filter |=
2901 NDIS_PACKET_TYPE_PROMISCUOUS;
2902 i = sizeof(sc->ndis_filter);
2903 error = ndis_set_info(sc,
2904 OID_GEN_CURRENT_PACKET_FILTER,
2905 &sc->ndis_filter, &i);
2906 } else if (sc->ndis_running &&
2907 !(ifp->if_flags & IFF_PROMISC) &&
2908 sc->ndis_if_flags & IFF_PROMISC) {
2909 sc->ndis_filter &=
2910 ~NDIS_PACKET_TYPE_PROMISCUOUS;
2911 i = sizeof(sc->ndis_filter);
2912 error = ndis_set_info(sc,
2913 OID_GEN_CURRENT_PACKET_FILTER,
2914 &sc->ndis_filter, &i);
2915 } else
2916 ndis_init(sc);
2917 } else {
2918 if (sc->ndis_running)
2919 ndis_stop(sc);
2920 }
2921 sc->ndis_if_flags = ifp->if_flags;
2922 error = 0;
2923 break;
2924 case SIOCADDMULTI:
2925 case SIOCDELMULTI:
2926 ndis_setmulti(sc);
2927 error = 0;
2928 break;
2929 case SIOCGIFMEDIA:
2930 case SIOCSIFMEDIA:
2931 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2932 break;
2933 case SIOCSIFCAP:
2934 ifp->if_capenable = ifr->ifr_reqcap;
2935 if (ifp->if_capenable & IFCAP_TXCSUM)
2936 ifp->if_hwassist = sc->ndis_hwassist;
2937 else
2938 ifp->if_hwassist = 0;
2939 ndis_set_offload(sc);
2940 break;
2941 default:
2942 error = ether_ioctl(ifp, command, data);
2943 break;
2944 }
2945
2946 /*NDIS_UNLOCK(sc);*/
2947
2948 return(error);
2949}
2950
2951static int
2952ndis_80211ioctl(struct ieee80211com *ic, u_long cmd, void *data)
2953{
2954 struct ndis_softc *sc = ic->ic_softc;
2955 struct ifreq *ifr = data;
2956 struct ndis_oid_data oid;
2957 struct ndis_evt evt;
2958 void *oidbuf = NULL;
2959 int error = 0;
2960
2961 if ((error = priv_check(curthread, PRIV_DRIVER)) != 0)
2962 return (error);
2963
2964 switch (cmd) {
2965 case SIOCGDRVSPEC:
2966 case SIOCSDRVSPEC:
2967 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2968 if (error)
2969 break;
2970 oidbuf = malloc(oid.len, M_TEMP, M_WAITOK | M_ZERO);
2971 error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2972 }
2973
2974 if (error) {
2975 free(oidbuf, M_TEMP);
2976 return (error);
2977 }
2978
2979 switch (cmd) {
2980 case SIOCGDRVSPEC:
2981 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2982 break;
2983 case SIOCSDRVSPEC:
2984 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2985 break;
2986 case SIOCGPRIVATE_0:
2987 NDIS_LOCK(sc);
2988 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
2989 error = ENOENT;
2990 NDIS_UNLOCK(sc);
2991 break;
2992 }
2993 error = copyin(ifr->ifr_data, &evt, sizeof(evt));
2994 if (error) {
2995 NDIS_UNLOCK(sc);
2996 break;
2997 }
2998 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2999 error = ENOSPC;
3000 NDIS_UNLOCK(sc);
3001 break;
3002 }
3003 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
3004 ifr->ifr_data, sizeof(uint32_t) * 2);
3005 if (error) {
3006 NDIS_UNLOCK(sc);
3007 break;
3008 }
3009 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3010 error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
3011 ifr->ifr_data + (sizeof(uint32_t) * 2),
3012 sc->ndis_evt[sc->ndis_evtcidx].ne_len);
3013 if (error) {
3014 NDIS_UNLOCK(sc);
3015 break;
3016 }
3017 free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
3018 sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
3019 }
3020 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
3021 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
3022 NDIS_EVTINC(sc->ndis_evtcidx);
3023 NDIS_UNLOCK(sc);
3024 break;
3025 default:
3026 error = ENOTTY;
3027 break;
3028 }
3029
3030 switch (cmd) {
3031 case SIOCGDRVSPEC:
3032 case SIOCSDRVSPEC:
3033 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
3034 if (error)
3035 break;
3036 error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
3037 }
3038
3039 free(oidbuf, M_TEMP);
3040
3041 return (error);
3042}
3043
3044int
3045ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3046{
3047 struct ndis_softc *sc = vap->iv_ic->ic_softc;
3048 ndis_80211_key rkey;
3049 int len, error = 0;
3050
3051 bzero((char *)&rkey, sizeof(rkey));
3052 len = sizeof(rkey);
3053
3054 rkey.nk_len = len;
3055 rkey.nk_keyidx = key->wk_keyix;
3056
3057 bcopy(vap->iv_ifp->if_broadcastaddr,
3058 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3059
3060 error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
3061
3062 if (error)
3063 return (0);
3064
3065 return (1);
3066}
3067
3068/*
3069 * In theory this could be called for any key, but we'll
3070 * only use it for WPA TKIP or AES keys. These need to be
3071 * set after initial authentication with the AP.
3072 */
3073static int
3074ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3075{
3076 struct ndis_softc *sc = vap->iv_ic->ic_softc;
3077 ndis_80211_key rkey;
3078 int len, error = 0;
3079
3080 switch (key->wk_cipher->ic_cipher) {
3081 case IEEE80211_CIPHER_TKIP:
3082
3083 len = sizeof(ndis_80211_key);
3084 bzero((char *)&rkey, sizeof(rkey));
3085
3086 rkey.nk_len = len;
3087 rkey.nk_keylen = key->wk_keylen;
3088
3089 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3090 rkey.nk_keylen += 16;
3091
3092 /* key index - gets weird in NDIS */
3093
3094 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3095 rkey.nk_keyidx = key->wk_keyix;
3096 else
3097 rkey.nk_keyidx = 0;
3098
3099 if (key->wk_flags & IEEE80211_KEY_XMIT)
3100 rkey.nk_keyidx |= 1 << 31;
3101
3102 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3103 bcopy(ieee80211broadcastaddr,
3104 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3105 } else {
3106 bcopy(vap->iv_bss->ni_bssid,
3107 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3108 /* pairwise key */
3109 rkey.nk_keyidx |= 1 << 30;
3110 }
3111
3112 /* need to set bit 29 based on keyrsc */
3113 rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */
3114
3115 if (rkey.nk_keyrsc)
3116 rkey.nk_keyidx |= 1 << 29;
3117
3118 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3119 bcopy(key->wk_key, rkey.nk_keydata, 16);
3120 bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3121 bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3122 } else
3123 bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3124
3125 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3126 break;
3127 case IEEE80211_CIPHER_WEP:
3128 error = 0;
3129 break;
3130 /*
3131 * I don't know how to set up keys for the AES
3132 * cipher yet. Is it the same as TKIP?
3133 */
3134 case IEEE80211_CIPHER_AES_CCM:
3135 default:
3136 error = ENOTTY;
3137 break;
3138 }
3139
3140 /* We need to return 1 for success, 0 for failure. */
3141
3142 if (error)
3143 return (0);
3144
3145 return (1);
3146}
3147
3148static void
3149ndis_resettask(d, arg)
3150 device_object *d;
3151 void *arg;
3152{
3153 struct ndis_softc *sc;
3154
3155 sc = arg;
3156 ndis_reset_nic(sc);
3157}
3158
3159/*
3160 * Stop the adapter and free any mbufs allocated to the
3161 * RX and TX lists.
3162 */
3163static void
3164ndis_stop(struct ndis_softc *sc)
3165{
3166 int i;
3167
3168 callout_drain(&sc->ndis_stat_callout);
3169
3170 NDIS_LOCK(sc);
3171 sc->ndis_tx_timer = 0;
3172 sc->ndis_link = 0;
3173 if (!sc->ndis_80211)
3174 sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3175 sc->ndis_running = 0;
3176 NDIS_UNLOCK(sc);
3177
3178 if (sc->ndis_iftype != PNPBus ||
3179 (sc->ndis_iftype == PNPBus &&
3180 !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3181 ndisusb_halt != 0))
3182 ndis_halt_nic(sc);
3183
3184 NDIS_LOCK(sc);
3185 for (i = 0; i < NDIS_EVENTS; i++) {
3186 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3187 free(sc->ndis_evt[i].ne_buf, M_TEMP);
3188 sc->ndis_evt[i].ne_buf = NULL;
3189 }
3190 sc->ndis_evt[i].ne_sts = 0;
3191 sc->ndis_evt[i].ne_len = 0;
3192 }
3193 sc->ndis_evtcidx = 0;
3194 sc->ndis_evtpidx = 0;
3195 NDIS_UNLOCK(sc);
3196}
3197
3198/*
3199 * Stop all chip I/O so that the kernel's probe routines don't
3200 * get confused by errant DMAs when rebooting.
3201 */
3202void
3203ndis_shutdown(dev)
3204 device_t dev;
3205{
3206 struct ndis_softc *sc;
3207
3208 sc = device_get_softc(dev);
3209 ndis_stop(sc);
3210}
3211
3212static int
3213ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3214{
3215 struct ndis_vap *nvp = NDIS_VAP(vap);
3216 struct ieee80211com *ic = vap->iv_ic;
3217 struct ndis_softc *sc = ic->ic_softc;
3218 enum ieee80211_state ostate;
3219
3220 DPRINTF(("%s: %s -> %s\n", __func__,
3221 ieee80211_state_name[vap->iv_state],
3222 ieee80211_state_name[nstate]));
3223
3224 ostate = vap->iv_state;
3225 vap->iv_state = nstate;
3226
3227 switch (nstate) {
3228 /* pass on to net80211 */
3229 case IEEE80211_S_INIT:
3230 case IEEE80211_S_SCAN:
3231 return nvp->newstate(vap, nstate, arg);
3232 case IEEE80211_S_ASSOC:
3233 if (ostate != IEEE80211_S_AUTH) {
3234 IEEE80211_UNLOCK(ic);
3235 ndis_auth_and_assoc(sc, vap);
3236 IEEE80211_LOCK(ic);
3237 }
3238 break;
3239 case IEEE80211_S_AUTH:
3240 IEEE80211_UNLOCK(ic);
3241 ndis_auth_and_assoc(sc, vap);
3242 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3243 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3244 IEEE80211_LOCK(ic);
3245 break;
3246 default:
3247 break;
3248 }
3249 return (0);
3250}
3251
3252static void
3253ndis_scan(void *arg)
3254{
3255 struct ieee80211vap *vap = arg;
3256
3257 ieee80211_scan_done(vap);
3258}
3259
3260static void
3261ndis_scan_results(struct ndis_softc *sc)
3262{
3263 struct ieee80211com *ic = &sc->ndis_ic;
3264 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
3265 ndis_80211_bssid_list_ex *bl;
3266 ndis_wlan_bssid_ex *wb;
3267 struct ieee80211_scanparams sp;
3268 struct ieee80211_frame wh;
3269 struct ieee80211_channel *saved_chan;
3270 int i, j;
3271 int rssi, noise, freq, chanflag;
3272 uint8_t ssid[2+IEEE80211_NWID_LEN];
3273 uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3274 uint8_t *frm, *efrm;
3275
3276 saved_chan = ic->ic_curchan;
3277 noise = -96;
3278
3279 if (ndis_get_bssid_list(sc, &bl))
3280 return;
3281
3282 DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3283 wb = &bl->nblx_bssid[0];
3284 for (i = 0; i < bl->nblx_items; i++) {
3285 memset(&sp, 0, sizeof(sp));
3286
3287 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3288 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3289 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3290 rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */
3291 if (wb->nwbx_privacy)
3292 sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3293 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3294 switch (wb->nwbx_netinfra) {
3295 case NDIS_80211_NET_INFRA_IBSS:
3296 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3297 break;
3298 case NDIS_80211_NET_INFRA_BSS:
3299 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3300 break;
3301 }
3302 sp.rates = &rates[0];
3303 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3304 /* XXX - check units */
3305 if (wb->nwbx_supportedrates[j] == 0)
3306 break;
3307 rates[2 + j] =
3308 wb->nwbx_supportedrates[j] & 0x7f;
3309 }
3310 rates[1] = j;
3311 sp.ssid = (uint8_t *)&ssid[0];
3312 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3313 wb->nwbx_ssid.ns_ssidlen);
3314 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3315
3316 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3317 freq = wb->nwbx_config.nc_dsconfig / 1000;
3318 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3319 /* Hack ic->ic_curchan to be in sync with the scan result */
3320 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3321 if (ic->ic_curchan == NULL)
3322 ic->ic_curchan = &ic->ic_channels[0];
3323
3324 /* Process extended info from AP */
3325 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3326 frm = (uint8_t *)&wb->nwbx_ies;
3327 efrm = frm + wb->nwbx_ielen;
3328 if (efrm - frm < 12)
3329 goto done;
3330 sp.tstamp = frm; frm += 8;
3331 sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3332 sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3333 sp.ies = frm;
3334 sp.ies_len = efrm - frm;
3335 }
3336done:
3337 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3338 ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag,
3339 rssi));
3340 ieee80211_add_scan(vap, ic->ic_curchan, &sp, &wh, 0, rssi, noise);
3341 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3342 }
3343 free(bl, M_DEVBUF);
3344 /* Restore the channel after messing with it */
3345 ic->ic_curchan = saved_chan;
3346}
3347
3348static void
3349ndis_scan_start(struct ieee80211com *ic)
3350{
3351 struct ndis_softc *sc = ic->ic_softc;
3352 struct ieee80211vap *vap;
3353 struct ieee80211_scan_state *ss;
3354 ndis_80211_ssid ssid;
3355 int error, len;
3356
3357 ss = ic->ic_scan;
3358 vap = TAILQ_FIRST(&ic->ic_vaps);
3359
3360 if (!NDIS_INITIALIZED(sc)) {
3361 DPRINTF(("%s: scan aborted\n", __func__));
3362 ieee80211_cancel_scan(vap);
3363 return;
3364 }
3365
3366 len = sizeof(ssid);
3367 bzero((char *)&ssid, len);
3368 if (ss->ss_nssid == 0)
3369 ssid.ns_ssidlen = 1;
3370 else {
3371 /* Perform a directed scan */
3372 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3373 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3374 }
3375
3376 error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3377 if (error)
3378 DPRINTF(("%s: set ESSID failed\n", __func__));
3379
3380 len = 0;
3381 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3382 if (error) {
3383 DPRINTF(("%s: scan command failed\n", __func__));
3384 ieee80211_cancel_scan(vap);
3385 return;
3386 }
3387 /* Set a timer to collect the results */
3388 callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3389}
3390
3391static void
3392ndis_set_channel(struct ieee80211com *ic)
3393{
3394 /* ignore */
3395}
3396
3397static void
3398ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3399{
3400 /* ignore */
3401}
3402
3403static void
3404ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3405{
3406 /* NB: don't try to abort scan; wait for firmware to finish */
3407}
3408
3409static void
3410ndis_scan_end(struct ieee80211com *ic)
3411{
3412 struct ndis_softc *sc = ic->ic_softc;
3413
3414 ndis_scan_results(sc);
3415}