3 * Bill Paul <wpaul@windriver.com>. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
32 * $FreeBSD: src/sys/dev/if_ndis/if_ndis.c,v 1.65 2004/07/07 17:46:30 wpaul Exp $
33 * $DragonFly: src/sys/dev/netif/ndis/if_ndis.c,v 1.23 2008/08/17 04:32:34 sephe Exp $
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/sockio.h>
40 #include <sys/malloc.h>
41 #include <sys/kernel.h>
42 #include <sys/socket.h>
43 #include <sys/queue.h>
46 #include <sys/sysctl.h>
49 #include <sys/serialize.h>
50 #include <sys/thread2.h>
53 #include <net/ifq_var.h>
54 #include <net/if_arp.h>
55 #include <net/ethernet.h>
56 #include <net/if_dl.h>
57 #include <net/if_media.h>
58 #include <net/route.h>
62 #include <netproto/802_11/ieee80211_var.h>
63 #include <netproto/802_11/ieee80211_ioctl.h>
65 #include <netproto/802_11/if_wavelan_ieee.h>
67 #include <bus/pci/pcireg.h>
68 #include <bus/pci/pcivar.h>
70 #include <emulation/ndis/regcall.h>
71 #include <emulation/ndis/pe_var.h>
72 #include <emulation/ndis/resource_var.h>
73 #include <emulation/ndis/ntoskrnl_var.h>
74 #include <emulation/ndis/hal_var.h>
75 #include <emulation/ndis/ndis_var.h>
76 #include <emulation/ndis/cfg_var.h>
77 #include "if_ndisvar.h"
82 #include "ndis_driver_data.h"
84 int ndis_attach (device_t
);
85 int ndis_detach (device_t
);
86 int ndis_suspend (device_t
);
87 int ndis_resume (device_t
);
88 void ndis_shutdown (device_t
);
90 static __stdcall
void ndis_txeof (ndis_handle
,
91 ndis_packet
*, ndis_status
);
92 static __stdcall
void ndis_rxeof (ndis_handle
,
93 ndis_packet
**, uint32_t);
94 static __stdcall
void ndis_linksts (ndis_handle
,
95 ndis_status
, void *, uint32_t);
96 static __stdcall
void ndis_linksts_done (ndis_handle
);
98 static void ndis_intr (void *);
99 static void ndis_intrtask (void *);
100 static void ndis_tick (void *);
101 static void ndis_ticktask (void *);
102 static void ndis_start (struct ifnet
*);
103 static void ndis_starttask (void *);
104 static int ndis_ioctl (struct ifnet
*, u_long
, caddr_t
, struct ucred
*);
105 static int ndis_wi_ioctl_get (struct ifnet
*, u_long
, caddr_t
);
106 static int ndis_wi_ioctl_set (struct ifnet
*, u_long
, caddr_t
);
107 static void ndis_init (void *);
108 static void ndis_stop (struct ndis_softc
*);
109 static void ndis_watchdog (struct ifnet
*);
110 static int ndis_ifmedia_upd (struct ifnet
*);
111 static void ndis_ifmedia_sts (struct ifnet
*, struct ifmediareq
*);
112 static int ndis_get_assoc (struct ndis_softc
*, ndis_wlan_bssid_ex
**);
113 static int ndis_probe_offload (struct ndis_softc
*);
114 static int ndis_set_offload (struct ndis_softc
*);
115 static void ndis_getstate_80211 (struct ndis_softc
*);
116 static void ndis_setstate_80211 (struct ndis_softc
*);
117 static void ndis_media_status (struct ifnet
*, struct ifmediareq
*);
119 static void ndis_setmulti (struct ndis_softc
*);
120 static void ndis_map_sclist (void *, bus_dma_segment_t
*,
121 int, bus_size_t
, int);
124 * Program the 64-bit multicast hash filter.
127 ndis_setmulti(struct ndis_softc
*sc
)
130 struct ifmultiaddr
*ifma
;
131 int len
, mclistsz
, error
;
134 ifp
= &sc
->arpcom
.ac_if
;
136 if (!NDIS_INITIALIZED(sc
))
139 if (ifp
->if_flags
& IFF_ALLMULTI
|| ifp
->if_flags
& IFF_PROMISC
) {
140 sc
->ndis_filter
|= NDIS_PACKET_TYPE_ALL_MULTICAST
;
141 len
= sizeof(sc
->ndis_filter
);
142 error
= ndis_set_info(sc
, OID_GEN_CURRENT_PACKET_FILTER
,
143 &sc
->ndis_filter
, &len
);
145 device_printf (sc
->ndis_dev
,
146 "set filter failed: %d\n", error
);
150 if (LIST_EMPTY(&ifp
->if_multiaddrs
))
153 len
= sizeof(mclistsz
);
154 ndis_get_info(sc
, OID_802_3_MAXIMUM_LIST_SIZE
, &mclistsz
, &len
);
156 mclist
= kmalloc(ETHER_ADDR_LEN
* mclistsz
, M_TEMP
, M_NOWAIT
|M_ZERO
);
158 if (mclist
== NULL
) {
159 sc
->ndis_filter
|= NDIS_PACKET_TYPE_ALL_MULTICAST
;
163 sc
->ndis_filter
|= NDIS_PACKET_TYPE_MULTICAST
;
166 LIST_FOREACH(ifma
, &ifp
->if_multiaddrs
, ifma_link
) {
167 if (ifma
->ifma_addr
->sa_family
!= AF_LINK
)
169 bcopy(LLADDR((struct sockaddr_dl
*)ifma
->ifma_addr
),
170 mclist
+ (ETHER_ADDR_LEN
* len
), ETHER_ADDR_LEN
);
172 if (len
> mclistsz
) {
173 sc
->ndis_filter
|= NDIS_PACKET_TYPE_ALL_MULTICAST
;
174 sc
->ndis_filter
&= ~NDIS_PACKET_TYPE_MULTICAST
;
179 len
= len
* ETHER_ADDR_LEN
;
180 error
= ndis_set_info(sc
, OID_802_3_MULTICAST_LIST
, mclist
, &len
);
182 device_printf (sc
->ndis_dev
, "set mclist failed: %d\n", error
);
183 sc
->ndis_filter
|= NDIS_PACKET_TYPE_ALL_MULTICAST
;
184 sc
->ndis_filter
&= ~NDIS_PACKET_TYPE_MULTICAST
;
188 kfree(mclist
, M_TEMP
);
190 len
= sizeof(sc
->ndis_filter
);
191 error
= ndis_set_info(sc
, OID_GEN_CURRENT_PACKET_FILTER
,
192 &sc
->ndis_filter
, &len
);
194 device_printf (sc
->ndis_dev
, "set filter failed: %d\n", error
);
198 ndis_set_offload(struct ndis_softc
*sc
)
200 ndis_task_offload
*nto
;
201 ndis_task_offload_hdr
*ntoh
;
202 ndis_task_tcpip_csum
*nttc
;
206 ifp
= &sc
->arpcom
.ac_if
;
208 if (!NDIS_INITIALIZED(sc
))
211 /* See if there's anything to set. */
213 error
= ndis_probe_offload(sc
);
217 if (sc
->ndis_hwassist
== 0 && ifp
->if_capabilities
== 0)
220 len
= sizeof(ndis_task_offload_hdr
) + sizeof(ndis_task_offload
) +
221 sizeof(ndis_task_tcpip_csum
);
223 ntoh
= kmalloc(len
, M_TEMP
, M_NOWAIT
|M_ZERO
);
228 ntoh
->ntoh_vers
= NDIS_TASK_OFFLOAD_VERSION
;
229 ntoh
->ntoh_len
= sizeof(ndis_task_offload_hdr
);
230 ntoh
->ntoh_offset_firsttask
= sizeof(ndis_task_offload_hdr
);
231 ntoh
->ntoh_encapfmt
.nef_encaphdrlen
= sizeof(struct ether_header
);
232 ntoh
->ntoh_encapfmt
.nef_encap
= NDIS_ENCAP_IEEE802_3
;
233 ntoh
->ntoh_encapfmt
.nef_flags
= NDIS_ENCAPFLAG_FIXEDHDRLEN
;
235 nto
= (ndis_task_offload
*)((char *)ntoh
+
236 ntoh
->ntoh_offset_firsttask
);
238 nto
->nto_vers
= NDIS_TASK_OFFLOAD_VERSION
;
239 nto
->nto_len
= sizeof(ndis_task_offload
);
240 nto
->nto_task
= NDIS_TASK_TCPIP_CSUM
;
241 nto
->nto_offset_nexttask
= 0;
242 nto
->nto_taskbuflen
= sizeof(ndis_task_tcpip_csum
);
244 nttc
= (ndis_task_tcpip_csum
*)nto
->nto_taskbuf
;
246 if (ifp
->if_capenable
& IFCAP_TXCSUM
)
247 nttc
->nttc_v4tx
= sc
->ndis_v4tx
;
249 if (ifp
->if_capenable
& IFCAP_RXCSUM
)
250 nttc
->nttc_v4rx
= sc
->ndis_v4rx
;
252 error
= ndis_set_info(sc
, OID_TCP_TASK_OFFLOAD
, ntoh
, &len
);
259 ndis_probe_offload(struct ndis_softc
*sc
)
261 ndis_task_offload
*nto
;
262 ndis_task_offload_hdr
*ntoh
;
263 ndis_task_tcpip_csum
*nttc
= NULL
;
265 int len
, error
, dummy
;
267 ifp
= &sc
->arpcom
.ac_if
;
270 error
= ndis_get_info(sc
, OID_TCP_TASK_OFFLOAD
, &dummy
, &len
);
275 ntoh
= kmalloc(len
, M_TEMP
, M_NOWAIT
|M_ZERO
);
280 ntoh
->ntoh_vers
= NDIS_TASK_OFFLOAD_VERSION
;
281 ntoh
->ntoh_len
= sizeof(ndis_task_offload_hdr
);
282 ntoh
->ntoh_encapfmt
.nef_encaphdrlen
= sizeof(struct ether_header
);
283 ntoh
->ntoh_encapfmt
.nef_encap
= NDIS_ENCAP_IEEE802_3
;
284 ntoh
->ntoh_encapfmt
.nef_flags
= NDIS_ENCAPFLAG_FIXEDHDRLEN
;
286 error
= ndis_get_info(sc
, OID_TCP_TASK_OFFLOAD
, ntoh
, &len
);
293 if (ntoh
->ntoh_vers
!= NDIS_TASK_OFFLOAD_VERSION
) {
298 nto
= (ndis_task_offload
*)((char *)ntoh
+
299 ntoh
->ntoh_offset_firsttask
);
302 switch (nto
->nto_task
) {
303 case NDIS_TASK_TCPIP_CSUM
:
304 nttc
= (ndis_task_tcpip_csum
*)nto
->nto_taskbuf
;
306 /* Don't handle these yet. */
307 case NDIS_TASK_IPSEC
:
308 case NDIS_TASK_TCP_LARGESEND
:
312 if (nto
->nto_offset_nexttask
== 0)
314 nto
= (ndis_task_offload
*)((char *)nto
+
315 nto
->nto_offset_nexttask
);
323 sc
->ndis_v4tx
= nttc
->nttc_v4tx
;
324 sc
->ndis_v4rx
= nttc
->nttc_v4rx
;
326 if (nttc
->nttc_v4tx
& NDIS_TCPSUM_FLAGS_IP_CSUM
)
327 sc
->ndis_hwassist
|= CSUM_IP
;
328 if (nttc
->nttc_v4tx
& NDIS_TCPSUM_FLAGS_TCP_CSUM
)
329 sc
->ndis_hwassist
|= CSUM_TCP
;
330 if (nttc
->nttc_v4tx
& NDIS_TCPSUM_FLAGS_UDP_CSUM
)
331 sc
->ndis_hwassist
|= CSUM_UDP
;
333 if (sc
->ndis_hwassist
)
334 ifp
->if_capabilities
|= IFCAP_TXCSUM
;
336 if (nttc
->nttc_v4rx
& NDIS_TCPSUM_FLAGS_IP_CSUM
)
337 ifp
->if_capabilities
|= IFCAP_RXCSUM
;
338 if (nttc
->nttc_v4rx
& NDIS_TCPSUM_FLAGS_TCP_CSUM
)
339 ifp
->if_capabilities
|= IFCAP_RXCSUM
;
340 if (nttc
->nttc_v4rx
& NDIS_TCPSUM_FLAGS_UDP_CSUM
)
341 ifp
->if_capabilities
|= IFCAP_RXCSUM
;
348 * Attach the interface. Allocate softc structures, do ifmedia
349 * setup and ethernet/BPF attach.
352 ndis_attach(device_t dev
)
354 u_char eaddr
[ETHER_ADDR_LEN
];
355 struct ndis_softc
*sc
;
361 sc
= device_get_softc(dev
);
363 callout_init(&sc
->ndis_stat_timer
);
365 sc
->ndis_regvals
= ndis_regvals
;
367 #if __FreeBSD_version < 502113
368 sysctl_ctx_init(&sc
->ndis_ctx
);
371 /* Create sysctl registry nodes */
372 ndis_create_sysctls(sc
);
374 /* Set up driver image in memory. */
376 ndis_load_driver((vm_offset_t
)img
, sc
);
378 /* Tell the user what version of the API the driver is using. */
379 device_printf(dev
, "NDIS API version: %d.%d\n",
380 sc
->ndis_chars
.nmc_version_major
,
381 sc
->ndis_chars
.nmc_version_minor
);
383 /* Do resource conversion. */
384 ndis_convert_res(sc
);
386 /* Install our RX and TX interrupt handlers. */
387 sc
->ndis_block
.nmb_senddone_func
= ndis_txeof
;
388 sc
->ndis_block
.nmb_pktind_func
= ndis_rxeof
;
390 /* Call driver's init routine. */
391 if (ndis_init_nic(sc
)) {
392 device_printf (dev
, "init handler failed\n");
398 * Get station address from the driver.
401 ndis_get_info(sc
, OID_802_3_CURRENT_ADDRESS
, &eaddr
, &len
);
403 bcopy(eaddr
, (char *)&sc
->arpcom
.ac_enaddr
, ETHER_ADDR_LEN
);
406 * Figure out of we're allowed to use multipacket sends
407 * with this driver, and if so, how many.
410 if (sc
->ndis_chars
.nmc_sendsingle_func
&&
411 sc
->ndis_chars
.nmc_sendmulti_func
== NULL
) {
412 sc
->ndis_maxpkts
= 1;
414 len
= sizeof(sc
->ndis_maxpkts
);
415 ndis_get_info(sc
, OID_GEN_MAXIMUM_SEND_PACKETS
,
416 &sc
->ndis_maxpkts
, &len
);
419 sc
->ndis_txarray
= kmalloc(sizeof(ndis_packet
*) *
420 sc
->ndis_maxpkts
, M_DEVBUF
, M_WAITOK
|M_ZERO
);
422 sc
->ndis_txpending
= sc
->ndis_maxpkts
;
425 /* Get supported oid list. */
426 ndis_get_supported_oids(sc
, &sc
->ndis_oids
, &sc
->ndis_oidcnt
);
428 /* If the NDIS module requested scatter/gather, init maps. */
433 * See if the OID_802_11_CONFIGURATION OID is
434 * supported by this driver. If it is, then this an 802.11
435 * wireless driver, and we should set up media for wireless.
437 for (i
= 0; i
< sc
->ndis_oidcnt
; i
++) {
438 if (sc
->ndis_oids
[i
] == OID_802_11_CONFIGURATION
) {
444 /* Check for task offload support. */
445 ndis_probe_offload(sc
);
447 ifp
= &sc
->arpcom
.ac_if
;
449 if_initname(ifp
, device_get_name(dev
), device_get_unit(dev
));
450 ifp
->if_mtu
= ETHERMTU
;
451 ifp
->if_flags
= IFF_BROADCAST
| IFF_SIMPLEX
| IFF_MULTICAST
;
452 ifp
->if_ioctl
= ndis_ioctl
;
453 ifp
->if_start
= ndis_start
;
454 ifp
->if_watchdog
= ndis_watchdog
;
455 ifp
->if_init
= ndis_init
;
456 ifp
->if_baudrate
= 10000000;
457 ifq_set_maxlen(&ifp
->if_snd
, 50);
458 ifq_set_ready(&ifp
->if_snd
);
459 ifp
->if_capenable
= ifp
->if_capabilities
;
460 ifp
->if_hwassist
= sc
->ndis_hwassist
;
463 if (sc
->ndis_80211
) {
464 struct ieee80211com
*ic
= (void *)ifp
;
465 ndis_80211_rates_ex rates
;
466 struct ndis_80211_nettype_list
*ntl
;
470 ic
->ic_phytype
= IEEE80211_T_DS
;
471 ic
->ic_opmode
= IEEE80211_M_STA
;
472 ic
->ic_caps
= IEEE80211_C_IBSS
;
473 ic
->ic_state
= IEEE80211_S_ASSOC
;
474 ic
->ic_modecaps
= (1<<IEEE80211_MODE_AUTO
);
476 r
= ndis_get_info(sc
, OID_802_11_NETWORK_TYPES_SUPPORTED
,
480 ntl
= kmalloc(len
, M_DEVBUF
, M_WAITOK
|M_ZERO
);
481 r
= ndis_get_info(sc
, OID_802_11_NETWORK_TYPES_SUPPORTED
,
484 kfree(ntl
, M_DEVBUF
);
488 for (i
= 0; i
< ntl
->ntl_items
; i
++) {
489 switch (ntl
->ntl_type
[i
]) {
490 case NDIS_80211_NETTYPE_11FH
:
491 case NDIS_80211_NETTYPE_11DS
:
492 ic
->ic_modecaps
|= (1<<IEEE80211_MODE_11B
);
494 case NDIS_80211_NETTYPE_11OFDM5
:
495 ic
->ic_modecaps
|= (1<<IEEE80211_MODE_11A
);
497 case NDIS_80211_NETTYPE_11OFDM24
:
498 ic
->ic_modecaps
|= (1<<IEEE80211_MODE_11G
);
504 kfree(ntl
, M_DEVBUF
);
507 bzero((char *)&rates
, len
);
508 r
= ndis_get_info(sc
, OID_802_11_SUPPORTED_RATES
,
509 (void *)rates
, &len
);
511 device_printf (dev
, "get rates failed: 0x%x\n", r
);
513 * Since the supported rates only up to 8 can be supported,
514 * if this is not 802.11b we're just going to be faking it
518 #define TESTSETRATE(x, y) \
521 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \
522 if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \
525 if (i == ic->ic_sup_rates[x].rs_nrates) { \
526 ic->ic_sup_rates[x].rs_rates[i] = (y); \
527 ic->ic_sup_rates[x].rs_nrates++; \
531 #define SETRATE(x, y) \
532 ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
534 ic->ic_sup_rates[x].rs_nrates++
536 ic
->ic_curmode
= IEEE80211_MODE_AUTO
;
537 if (ic
->ic_modecaps
& (1<<IEEE80211_MODE_11A
))
538 ic
->ic_sup_rates
[IEEE80211_MODE_11A
].rs_nrates
= 0;
539 if (ic
->ic_modecaps
& (1<<IEEE80211_MODE_11B
))
540 ic
->ic_sup_rates
[IEEE80211_MODE_11B
].rs_nrates
= 0;
541 if (ic
->ic_modecaps
& (1<<IEEE80211_MODE_11G
))
542 ic
->ic_sup_rates
[IEEE80211_MODE_11G
].rs_nrates
= 0;
543 for (i
= 0; i
< len
; i
++) {
544 switch (rates
[i
] & IEEE80211_RATE_VAL
) {
550 if (!(ic
->ic_modecaps
&
551 (1<<IEEE80211_MODE_11B
))) {
552 /* Lazy-init 802.11b. */
554 (1<<IEEE80211_MODE_11B
);
555 ic
->ic_sup_rates
[IEEE80211_MODE_11B
].
558 SETRATE(IEEE80211_MODE_11B
, rates
[i
]);
559 INCRATE(IEEE80211_MODE_11B
);
562 if (ic
->ic_modecaps
& (1<<IEEE80211_MODE_11A
)) {
563 SETRATE(IEEE80211_MODE_11A
, rates
[i
]);
564 INCRATE(IEEE80211_MODE_11A
);
566 if (ic
->ic_modecaps
& (1<<IEEE80211_MODE_11G
)) {
567 SETRATE(IEEE80211_MODE_11G
, rates
[i
]);
568 INCRATE(IEEE80211_MODE_11G
);
575 * If the hardware supports 802.11g, it most
576 * likely supports 802.11b and all of the
577 * 802.11b and 802.11g speeds, so maybe we can
578 * just cheat here. Just how in the heck do
579 * we detect turbo modes, though?
581 if (ic
->ic_modecaps
& (1<<IEEE80211_MODE_11B
)) {
582 TESTSETRATE(IEEE80211_MODE_11B
,
583 IEEE80211_RATE_BASIC
|2);
584 TESTSETRATE(IEEE80211_MODE_11B
,
585 IEEE80211_RATE_BASIC
|4);
586 TESTSETRATE(IEEE80211_MODE_11B
,
587 IEEE80211_RATE_BASIC
|11);
588 TESTSETRATE(IEEE80211_MODE_11B
,
589 IEEE80211_RATE_BASIC
|22);
591 if (ic
->ic_modecaps
& (1<<IEEE80211_MODE_11G
)) {
592 TESTSETRATE(IEEE80211_MODE_11G
, 47);
593 TESTSETRATE(IEEE80211_MODE_11G
, 72);
594 TESTSETRATE(IEEE80211_MODE_11G
, 96);
595 TESTSETRATE(IEEE80211_MODE_11G
, 108);
597 if (ic
->ic_modecaps
& (1<<IEEE80211_MODE_11A
)) {
598 TESTSETRATE(IEEE80211_MODE_11A
, 47);
599 TESTSETRATE(IEEE80211_MODE_11A
, 72);
600 TESTSETRATE(IEEE80211_MODE_11A
, 96);
601 TESTSETRATE(IEEE80211_MODE_11A
, 108);
606 * Taking yet more guesses here.
608 for (i
= 1; i
< IEEE80211_CHAN_MAX
; i
++) {
611 if (ic
->ic_sup_rates
[IEEE80211_MODE_11G
].rs_nrates
)
612 chanflag
|= IEEE80211_CHAN_G
;
614 chanflag
|= IEEE80211_CHAN_B
;
615 if (ic
->ic_sup_rates
[IEEE80211_MODE_11A
].rs_nrates
&&
617 chanflag
= IEEE80211_CHAN_A
;
620 ic
->ic_channels
[i
].ic_freq
=
621 ieee80211_ieee2mhz(i
, chanflag
);
622 ic
->ic_channels
[i
].ic_flags
= chanflag
;
626 r
= ndis_get_info(sc
, OID_802_11_WEP_STATUS
, &arg
, &i
);
627 if (arg
!= NDIS_80211_WEPSTAT_NOTSUPPORTED
)
628 ic
->ic_caps
|= IEEE80211_C_WEP
;
630 r
= ndis_get_info(sc
, OID_802_11_POWER_MODE
, &arg
, &i
);
632 ic
->ic_caps
|= IEEE80211_C_PMGT
;
633 bcopy(eaddr
, &ic
->ic_myaddr
, sizeof(eaddr
));
634 ieee80211_ifattach(ic
);
635 ieee80211_media_init(ic
, ieee80211_media_change
,
637 ic
->ic_ibss_chan
= IEEE80211_CHAN_ANYC
;
638 ic
->ic_bss
->ni_chan
= ic
->ic_ibss_chan
;
640 ifmedia_init(&sc
->ifmedia
, IFM_IMASK
, ndis_ifmedia_upd
,
642 ifmedia_add(&sc
->ifmedia
, IFM_ETHER
|IFM_10_T
, 0, NULL
);
643 ifmedia_add(&sc
->ifmedia
, IFM_ETHER
|IFM_10_T
|IFM_FDX
, 0, NULL
);
644 ifmedia_add(&sc
->ifmedia
, IFM_ETHER
|IFM_100_TX
, 0, NULL
);
645 ifmedia_add(&sc
->ifmedia
,
646 IFM_ETHER
|IFM_100_TX
|IFM_FDX
, 0, NULL
);
647 ifmedia_add(&sc
->ifmedia
, IFM_ETHER
|IFM_AUTO
, 0, NULL
);
648 ifmedia_set(&sc
->ifmedia
, IFM_ETHER
|IFM_AUTO
);
649 ether_ifattach(ifp
, eaddr
, NULL
);
653 error
= bus_setup_intr(dev
, sc
->ndis_irq
, INTR_MPSAFE
,
658 device_printf(dev
, "couldn't set up irq\n");
664 /* Override the status handler so we can detect link changes. */
665 sc
->ndis_block
.nmb_status_func
= ndis_linksts
;
666 sc
->ndis_block
.nmb_statusdone_func
= ndis_linksts_done
;
671 /* We're done talking to the NIC for now; halt it. */
678 * Shutdown hardware and free up resources. This can be called any
679 * time after the mutex has been initialized. It is called in both
680 * the error case in attach and the normal detach case so it needs
681 * to be careful about only freeing resources that have actually been
685 ndis_detach(device_t dev
)
687 struct ndis_softc
*sc
;
690 sc
= device_get_softc(dev
);
691 ifp
= &sc
->arpcom
.ac_if
;
693 ifp
->if_flags
&= ~IFF_UP
;
695 if (device_is_attached(dev
)) {
696 lwkt_serialize_enter(ifp
->if_serializer
);
698 bus_teardown_intr(dev
, sc
->ndis_irq
, sc
->ndis_intrhand
);
699 lwkt_serialize_exit(ifp
->if_serializer
);
702 ieee80211_ifdetach(&sc
->ic
);
706 bus_generic_detach(dev
);
709 bus_release_resource(dev
, SYS_RES_IRQ
, 0, sc
->ndis_irq
);
711 bus_release_resource(dev
, SYS_RES_IOPORT
,
712 sc
->ndis_io_rid
, sc
->ndis_res_io
);
713 if (sc
->ndis_res_mem
)
714 bus_release_resource(dev
, SYS_RES_MEMORY
,
715 sc
->ndis_mem_rid
, sc
->ndis_res_mem
);
716 if (sc
->ndis_res_altmem
)
717 bus_release_resource(dev
, SYS_RES_MEMORY
,
718 sc
->ndis_altmem_rid
, sc
->ndis_res_altmem
);
721 ndis_destroy_dma(sc
);
723 ndis_unload_driver((void *)ifp
);
725 if (sc
->ndis_iftype
== PCIBus
)
726 bus_dma_tag_destroy(sc
->ndis_parent_tag
);
728 #if __FreeBSD_version < 502113
729 sysctl_ctx_free(&sc
->ndis_ctx
);
735 ndis_suspend(device_t dev
)
737 struct ndis_softc
*sc
;
740 sc
= device_get_softc(dev
);
741 ifp
= &sc
->arpcom
.ac_if
;
742 lwkt_serialize_enter(ifp
->if_serializer
);
745 if (NDIS_INITIALIZED(sc
))
748 lwkt_serialize_exit(ifp
->if_serializer
);
753 ndis_resume(device_t dev
)
755 struct ndis_softc
*sc
;
758 sc
= device_get_softc(dev
);
759 ifp
= &sc
->arpcom
.ac_if
;
761 lwkt_serialize_enter(ifp
->if_serializer
);
762 if (NDIS_INITIALIZED(sc
))
764 lwkt_serialize_exit(ifp
->if_serializer
);
770 * A frame has been uploaded: pass the resulting mbuf chain up to
771 * the higher level protocols.
773 * When handling received NDIS packets, the 'status' field in the
774 * out-of-band portion of the ndis_packet has special meaning. In the
775 * most common case, the underlying NDIS driver will set this field
776 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
777 * take posession of it. We then change the status field to
778 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
779 * and that we will return it at some point in the future via the
780 * return packet handler.
782 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
783 * this means the driver is running out of packet/buffer resources and
784 * wants to maintain ownership of the packet. In this case, we have to
785 * copy the packet data into local storage and let the driver keep the
788 __stdcall
static void
789 ndis_rxeof(ndis_handle adapter
, ndis_packet
**packets
, uint32_t pktcnt
)
791 struct ndis_softc
*sc
;
792 ndis_miniport_block
*block
;
795 ndis_tcpip_csum
*csum
;
800 block
= (ndis_miniport_block
*)adapter
;
801 sc
= (struct ndis_softc
*)(block
->nmb_ifp
);
802 ifp
= block
->nmb_ifp
;
804 for (i
= 0; i
< pktcnt
; i
++) {
806 /* Stash the softc here so ptom can use it. */
808 if (ndis_ptom(&m0
, p
)) {
809 device_printf (sc
->ndis_dev
, "ptom failed\n");
810 if (p
->np_oob
.npo_status
== NDIS_STATUS_SUCCESS
)
811 ndis_return_packet(sc
, p
);
813 if (p
->np_oob
.npo_status
== NDIS_STATUS_RESOURCES
) {
814 m
= m_dup(m0
, MB_DONTWAIT
);
816 * NOTE: we want to destroy the mbuf here, but
817 * we don't actually want to return it to the
818 * driver via the return packet handler. By
819 * bumping np_refcnt, we can prevent the
820 * ndis_return_packet() routine from actually
830 p
->np_oob
.npo_status
= NDIS_STATUS_PENDING
;
831 m0
->m_pkthdr
.rcvif
= ifp
;
834 /* Deal with checksum offload. */
836 if (ifp
->if_capenable
& IFCAP_RXCSUM
&&
837 p
->np_ext
.npe_info
[ndis_tcpipcsum_info
] != NULL
) {
839 p
->np_ext
.npe_info
[ndis_tcpipcsum_info
];
840 csum
= (ndis_tcpip_csum
*)&s
;
841 if (csum
->u
.ntc_rxflags
&
842 NDIS_RXCSUM_IP_PASSED
)
843 m0
->m_pkthdr
.csum_flags
|=
844 CSUM_IP_CHECKED
|CSUM_IP_VALID
;
845 if (csum
->u
.ntc_rxflags
&
846 (NDIS_RXCSUM_TCP_PASSED
|
847 NDIS_RXCSUM_UDP_PASSED
)) {
848 m0
->m_pkthdr
.csum_flags
|=
849 CSUM_DATA_VALID
|CSUM_PSEUDO_HDR
|
850 CSUM_FRAG_NOT_CHECKED
;
851 m0
->m_pkthdr
.csum_data
= 0xFFFF;
855 ifp
->if_input(ifp
, m0
);
861 * A frame was downloaded to the chip. It's safe for us to clean up
864 __stdcall
static void
865 ndis_txeof(ndis_handle adapter
, ndis_packet
*packet
, ndis_status status
)
867 struct ndis_softc
*sc
;
868 ndis_miniport_block
*block
;
873 block
= (ndis_miniport_block
*)adapter
;
874 sc
= (struct ndis_softc
*)block
->nmb_ifp
;
875 ifp
= block
->nmb_ifp
;
878 idx
= packet
->np_txidx
;
880 bus_dmamap_unload(sc
->ndis_ttag
, sc
->ndis_tmaps
[idx
]);
882 ndis_free_packet(packet
);
885 sc
->ndis_txarray
[idx
] = NULL
;
886 sc
->ndis_txpending
++;
888 if (status
== NDIS_STATUS_SUCCESS
)
893 ifp
->if_flags
&= ~IFF_OACTIVE
;
895 ndis_sched(ndis_starttask
, ifp
, NDIS_TASKQUEUE
);
898 __stdcall
static void
899 ndis_linksts(ndis_handle adapter
, ndis_status status
, void *sbuf
, uint32_t slen
)
901 ndis_miniport_block
*block
;
904 block
->nmb_getstat
= status
;
907 __stdcall
static void
908 ndis_linksts_done(ndis_handle adapter
)
910 ndis_miniport_block
*block
;
911 struct ndis_softc
*sc
;
915 ifp
= block
->nmb_ifp
;
918 if (!NDIS_INITIALIZED(sc
))
921 switch (block
->nmb_getstat
) {
922 case NDIS_STATUS_MEDIA_CONNECT
:
923 ndis_sched(ndis_ticktask
, sc
, NDIS_TASKQUEUE
);
924 ndis_sched(ndis_starttask
, ifp
, NDIS_TASKQUEUE
);
926 case NDIS_STATUS_MEDIA_DISCONNECT
:
928 ndis_sched(ndis_ticktask
, sc
, NDIS_TASKQUEUE
);
936 ndis_intrtask(void *arg
)
938 struct ndis_softc
*sc
;
943 ifp
= &sc
->arpcom
.ac_if
;
945 lwkt_serialize_enter(ifp
->if_serializer
);
946 irql
= FASTCALL1(hal_raise_irql
, DISPATCH_LEVEL
);
948 FASTCALL1(hal_lower_irql
, irql
);
949 ndis_enable_intr(sc
);
950 lwkt_serialize_exit(ifp
->if_serializer
);
956 struct ndis_softc
*sc
;
962 ifp
= &sc
->arpcom
.ac_if
;
964 if (sc
->ndis_block
.nmb_miniportadapterctx
== NULL
)
967 if (sc
->ndis_block
.nmb_interrupt
->ni_isrreq
== TRUE
)
968 ndis_isr(sc
, &is_our_intr
, &call_isr
);
970 ndis_disable_intr(sc
);
974 if ((is_our_intr
|| call_isr
))
975 ndis_sched(ndis_intrtask
, ifp
, NDIS_SWI
);
981 struct ndis_softc
*sc
;
985 ndis_sched(ndis_ticktask
, sc
, NDIS_TASKQUEUE
);
986 callout_reset(&sc
->ndis_stat_timer
,
987 hz
*sc
->ndis_block
.nmb_checkforhangsecs
, ndis_tick
, sc
);
991 ndis_ticktask(void *xsc
)
993 struct ndis_softc
*sc
;
995 __stdcall ndis_checkforhang_handler hangfunc
;
997 ndis_media_state linkstate
;
1001 ifp
= &sc
->arpcom
.ac_if
;
1003 lwkt_serialize_enter(ifp
->if_serializer
);
1004 hangfunc
= sc
->ndis_chars
.nmc_checkhang_func
;
1006 if (hangfunc
!= NULL
) {
1007 rval
= hangfunc(sc
->ndis_block
.nmb_miniportadapterctx
);
1010 lwkt_serialize_exit(ifp
->if_serializer
);
1015 len
= sizeof(linkstate
);
1016 error
= ndis_get_info(sc
, OID_GEN_MEDIA_CONNECT_STATUS
,
1017 (void *)&linkstate
, &len
);
1019 if (sc
->ndis_link
== 0 && linkstate
== nmc_connected
) {
1020 device_printf(sc
->ndis_dev
, "link up\n");
1023 ndis_getstate_80211(sc
);
1024 #ifdef LINK_STATE_UP
1025 sc
->arpcom
.ac_if
.if_link_state
= LINK_STATE_UP
;
1026 rt_ifmsg(&(sc
->arpcom
.ac_if
));
1027 #endif /* LINK_STATE_UP */
1030 if (sc
->ndis_link
== 1 && linkstate
== nmc_disconnected
) {
1031 device_printf(sc
->ndis_dev
, "link down\n");
1033 #ifdef LINK_STATE_DOWN
1034 sc
->arpcom
.ac_if
.if_link_state
= LINK_STATE_DOWN
;
1035 rt_ifmsg(&(sc
->arpcom
.ac_if
));
1036 #endif /* LINK_STATE_DOWN */
1039 lwkt_serialize_exit(ifp
->if_serializer
);
1043 ndis_map_sclist(void *arg
, bus_dma_segment_t
*segs
, int nseg
,
1044 bus_size_t mapsize
, int error
)
1046 struct ndis_sc_list
*sclist
;
1049 if (error
|| arg
== NULL
)
1054 sclist
->nsl_frags
= nseg
;
1056 for (i
= 0; i
< nseg
; i
++) {
1057 sclist
->nsl_elements
[i
].nse_addr
.np_quad
= segs
[i
].ds_addr
;
1058 sclist
->nsl_elements
[i
].nse_len
= segs
[i
].ds_len
;
1063 ndis_starttask(void *arg
)
1068 if (!ifq_is_empty(&ifp
->if_snd
))
1073 * Main transmit routine. To make NDIS drivers happy, we need to
1074 * transform mbuf chains into NDIS packets and feed them to the
1075 * send packet routines. Most drivers allow you to send several
1076 * packets at once (up to the maxpkts limit). Unfortunately, rather
1077 * that accepting them in the form of a linked list, they expect
1078 * a contiguous array of pointers to packets.
1080 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1081 * we need to perform busdma work here. Those that use map registers
1082 * will do the mapping themselves on a buffer by buffer basis.
1086 ndis_start(struct ifnet
*ifp
)
1088 struct ndis_softc
*sc
;
1089 struct mbuf
*m
= NULL
;
1090 ndis_packet
**p0
= NULL
, *p
= NULL
;
1091 ndis_tcpip_csum
*csum
;
1096 if (!sc
->ndis_link
|| ifp
->if_flags
& IFF_OACTIVE
) {
1100 p0
= &sc
->ndis_txarray
[sc
->ndis_txidx
];
1102 while(sc
->ndis_txpending
) {
1103 m
= ifq_dequeue(&ifp
->if_snd
, NULL
);
1107 sc
->ndis_txarray
[sc
->ndis_txidx
] = NULL
;
1109 if (ndis_mtop(m
, &sc
->ndis_txarray
[sc
->ndis_txidx
])) {
1115 * Save pointer to original mbuf
1116 * so we can free it later.
1119 p
= sc
->ndis_txarray
[sc
->ndis_txidx
];
1120 p
->np_txidx
= sc
->ndis_txidx
;
1122 p
->np_oob
.npo_status
= NDIS_STATUS_PENDING
;
1125 * Do scatter/gather processing, if driver requested it.
1128 bus_dmamap_load_mbuf(sc
->ndis_ttag
,
1129 sc
->ndis_tmaps
[sc
->ndis_txidx
], m
,
1130 ndis_map_sclist
, &p
->np_sclist
, BUS_DMA_NOWAIT
);
1131 bus_dmamap_sync(sc
->ndis_ttag
,
1132 sc
->ndis_tmaps
[sc
->ndis_txidx
],
1133 BUS_DMASYNC_PREREAD
);
1134 p
->np_ext
.npe_info
[ndis_sclist_info
] = &p
->np_sclist
;
1137 /* Handle checksum offload. */
1139 if (ifp
->if_capenable
& IFCAP_TXCSUM
&&
1140 m
->m_pkthdr
.csum_flags
) {
1141 csum
= (ndis_tcpip_csum
*)
1142 &p
->np_ext
.npe_info
[ndis_tcpipcsum_info
];
1143 csum
->u
.ntc_txflags
= NDIS_TXCSUM_DO_IPV4
;
1144 if (m
->m_pkthdr
.csum_flags
& CSUM_IP
)
1145 csum
->u
.ntc_txflags
|= NDIS_TXCSUM_DO_IP
;
1146 if (m
->m_pkthdr
.csum_flags
& CSUM_TCP
)
1147 csum
->u
.ntc_txflags
|= NDIS_TXCSUM_DO_TCP
;
1148 if (m
->m_pkthdr
.csum_flags
& CSUM_UDP
)
1149 csum
->u
.ntc_txflags
|= NDIS_TXCSUM_DO_UDP
;
1150 p
->np_private
.npp_flags
= NDIS_PROTOCOL_ID_TCP_IP
;
1154 sc
->ndis_txpending
--;
1159 * If there's a BPF listener, bounce a copy of this frame
1166 * The array that p0 points to must appear contiguous,
1167 * so we must not wrap past the end of sc->ndis_txarray[].
1168 * If it looks like we're about to wrap, break out here
1169 * so the this batch of packets can be transmitted, then
1170 * wait for txeof to ask us to send the rest.
1173 if (sc
->ndis_txidx
== 0)
1181 if (sc
->ndis_txpending
== 0)
1182 ifp
->if_flags
|= IFF_OACTIVE
;
1185 * Set a timeout in case the chip goes out to lunch.
1189 if (sc
->ndis_maxpkts
== 1)
1190 ndis_send_packet(sc
, p
);
1192 ndis_send_packets(sc
, p0
, pcnt
);
1196 ndis_init(void *xsc
)
1198 struct ndis_softc
*sc
= xsc
;
1199 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
1203 * Avoid reintializing the link unnecessarily.
1204 * This should be dealt with in a better way by
1205 * fixing the upper layer modules so they don't
1206 * call ifp->if_init() quite as often.
1208 if (sc
->ndis_link
&& sc
->ndis_skip
)
1212 * Cancel pending I/O and free all RX/TX buffers.
1215 if (ndis_init_nic(sc
))
1218 /* Init our MAC address */
1220 /* Program the packet filter */
1222 sc
->ndis_filter
= NDIS_PACKET_TYPE_DIRECTED
;
1224 if (ifp
->if_flags
& IFF_BROADCAST
)
1225 sc
->ndis_filter
|= NDIS_PACKET_TYPE_BROADCAST
;
1227 if (ifp
->if_flags
& IFF_PROMISC
)
1228 sc
->ndis_filter
|= NDIS_PACKET_TYPE_PROMISCUOUS
;
1230 i
= sizeof(sc
->ndis_filter
);
1232 error
= ndis_set_info(sc
, OID_GEN_CURRENT_PACKET_FILTER
,
1233 &sc
->ndis_filter
, &i
);
1236 device_printf (sc
->ndis_dev
, "set filter failed: %d\n", error
);
1239 * Program the multicast filter, if necessary.
1243 /* Setup task offload. */
1244 ndis_set_offload(sc
);
1246 /* Enable interrupts. */
1247 ndis_enable_intr(sc
);
1250 ndis_setstate_80211(sc
);
1253 sc
->ndis_txpending
= sc
->ndis_maxpkts
;
1256 ifp
->if_flags
|= IFF_RUNNING
;
1257 ifp
->if_flags
&= ~IFF_OACTIVE
;
1260 * Some drivers don't set this value. The NDIS spec says
1261 * the default checkforhang timeout is "approximately 2
1262 * seconds." We use 3 seconds, because it seems for some
1263 * drivers, exactly 2 seconds is too fast.
1266 if (sc
->ndis_block
.nmb_checkforhangsecs
== 0)
1267 sc
->ndis_block
.nmb_checkforhangsecs
= 3;
1269 callout_reset(&sc
->ndis_stat_timer
,
1270 hz
* sc
->ndis_block
.nmb_checkforhangsecs
, ndis_tick
, sc
);
1274 * Set media options.
1277 ndis_ifmedia_upd(struct ifnet
*ifp
)
1279 struct ndis_softc
*sc
;
1283 if (NDIS_INITIALIZED(sc
))
1290 * Report current media status.
1293 ndis_ifmedia_sts(struct ifnet
*ifp
, struct ifmediareq
*ifmr
)
1295 struct ndis_softc
*sc
;
1296 uint32_t media_info
;
1297 ndis_media_state linkstate
;
1300 ifmr
->ifm_status
= IFM_AVALID
;
1301 ifmr
->ifm_active
= IFM_ETHER
;
1304 if (!NDIS_INITIALIZED(sc
))
1307 len
= sizeof(linkstate
);
1308 error
= ndis_get_info(sc
, OID_GEN_MEDIA_CONNECT_STATUS
,
1309 (void *)&linkstate
, &len
);
1311 len
= sizeof(media_info
);
1312 error
= ndis_get_info(sc
, OID_GEN_LINK_SPEED
,
1313 (void *)&media_info
, &len
);
1315 if (linkstate
== nmc_connected
)
1316 ifmr
->ifm_status
|= IFM_ACTIVE
;
1318 switch(media_info
) {
1320 ifmr
->ifm_active
|= IFM_10_T
;
1323 ifmr
->ifm_active
|= IFM_100_TX
;
1326 ifmr
->ifm_active
|= IFM_1000_T
;
1329 device_printf(sc
->ndis_dev
, "unknown speed: %d\n", media_info
);
1335 ndis_setstate_80211(struct ndis_softc
*sc
)
1337 struct ieee80211com
*ic
;
1338 ndis_80211_ssid ssid
;
1339 ndis_80211_config config
;
1341 int i
, rval
= 0, len
;
1346 ifp
= &sc
->ic
.ic_ac
.ac_if
;
1348 if (!NDIS_INITIALIZED(sc
))
1351 /* Set network infrastructure mode. */
1354 if (ic
->ic_opmode
== IEEE80211_M_IBSS
)
1355 arg
= NDIS_80211_NET_INFRA_IBSS
;
1357 arg
= NDIS_80211_NET_INFRA_BSS
;
1359 rval
= ndis_set_info(sc
, OID_802_11_INFRASTRUCTURE_MODE
, &arg
, &len
);
1362 device_printf (sc
->ndis_dev
, "set infra failed: %d\n", rval
);
1366 #ifdef IEEE80211_F_PRIVACY
1367 if (ic
->ic_flags
& IEEE80211_F_PRIVACY
) {
1369 if (ic
->ic_wep_mode
>= IEEE80211_WEP_ON
) {
1371 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
1372 if (ic
->ic_nw_keys
[i
].wk_keylen
) {
1373 bzero((char *)&wep
, sizeof(wep
));
1374 wep
.nw_keylen
= ic
->ic_nw_keys
[i
].wk_keylen
;
1376 /* 5 and 13 are the only valid key lengths */
1377 if (ic
->ic_nw_keys
[i
].wk_len
< 5)
1379 else if (ic
->ic_nw_keys
[i
].wk_len
> 5 &&
1380 ic
->ic_nw_keys
[i
].wk_len
< 13)
1384 wep
.nw_length
= (sizeof(uint32_t) * 3)
1386 if (i
== ic
->ic_def_txkey
)
1387 wep
.nw_keyidx
|= NDIS_80211_WEPKEY_TX
;
1388 bcopy(ic
->ic_nw_keys
[i
].wk_key
,
1389 wep
.nw_keydata
, wep
.nw_length
);
1391 rval
= ndis_set_info(sc
,
1392 OID_802_11_ADD_WEP
, &wep
, &len
);
1394 device_printf(sc
->ndis_dev
,
1395 "set wepkey failed: %d\n", rval
);
1398 arg
= NDIS_80211_WEPSTAT_ENABLED
;
1400 rval
= ndis_set_info(sc
, OID_802_11_WEP_STATUS
, &arg
, &len
);
1402 device_printf(sc
->ndis_dev
,
1403 "enable WEP failed: %d\n", rval
);
1404 #ifndef IEEE80211_F_PRIVACY
1405 if (ic
->ic_wep_mode
!= IEEE80211_WEP_8021X
&&
1406 ic
->ic_wep_mode
!= IEEE80211_WEP_ON
)
1407 arg
= NDIS_80211_PRIVFILT_ACCEPTALL
;
1410 arg
= NDIS_80211_PRIVFILT_8021XWEP
;
1412 rval
= ndis_set_info(sc
, OID_802_11_PRIVACY_FILTER
, &arg
, &len
);
1413 #ifdef IEEE80211_WEP_8021X /*IEEE80211_F_WEPON*/
1414 /* Accept that we only have "shared" and 802.1x modes. */
1416 if (arg
== NDIS_80211_PRIVFILT_ACCEPTALL
)
1417 ic
->ic_wep_mode
= IEEE80211_WEP_MIXED
;
1419 ic
->ic_wep_mode
= IEEE80211_WEP_8021X
;
1422 arg
= NDIS_80211_AUTHMODE_OPEN
;
1424 arg
= NDIS_80211_WEPSTAT_DISABLED
;
1426 ndis_set_info(sc
, OID_802_11_WEP_STATUS
, &arg
, &len
);
1427 arg
= NDIS_80211_AUTHMODE_OPEN
;
1431 rval
= ndis_set_info(sc
, OID_802_11_AUTHENTICATION_MODE
, &arg
, &len
);
1435 device_printf (sc
->ndis_dev
, "set auth failed: %d\n", rval
);
1439 /* Set network type. */
1443 switch (ic
->ic_curmode
) {
1444 case IEEE80211_MODE_11A
:
1445 arg
= NDIS_80211_NETTYPE_11OFDM5
;
1447 case IEEE80211_MODE_11B
:
1448 arg
= NDIS_80211_NETTYPE_11DS
;
1450 case IEEE80211_MODE_11G
:
1451 arg
= NDIS_80211_NETTYPE_11OFDM24
;
1454 device_printf(sc
->ndis_dev
, "unknown mode: %d\n",
1460 rval
= ndis_set_info(sc
, OID_802_11_NETWORK_TYPE_IN_USE
,
1463 device_printf (sc
->ndis_dev
,
1464 "set nettype failed: %d\n", rval
);
1468 len
= sizeof(config
);
1469 bzero((char *)&config
, len
);
1470 config
.nc_length
= len
;
1471 config
.nc_fhconfig
.ncf_length
= sizeof(ndis_80211_config_fh
);
1472 rval
= ndis_get_info(sc
, OID_802_11_CONFIGURATION
, &config
, &len
);
1475 * Some drivers expect us to initialize these values, so
1476 * provide some defaults.
1478 if (config
.nc_beaconperiod
== 0)
1479 config
.nc_beaconperiod
= 100;
1480 if (config
.nc_atimwin
== 0)
1481 config
.nc_atimwin
= 100;
1482 if (config
.nc_fhconfig
.ncf_dwelltime
== 0)
1483 config
.nc_fhconfig
.ncf_dwelltime
= 200;
1485 if (rval
== 0 && ic
->ic_ibss_chan
!= IEEE80211_CHAN_ANYC
) {
1488 chan
= ieee80211_chan2ieee(ic
, ic
->ic_ibss_chan
);
1489 chanflag
= config
.nc_dsconfig
> 2500000 ? IEEE80211_CHAN_2GHZ
:
1490 IEEE80211_CHAN_5GHZ
;
1491 if (chan
!= ieee80211_mhz2ieee(config
.nc_dsconfig
/ 1000, 0)) {
1492 config
.nc_dsconfig
=
1493 ic
->ic_ibss_chan
->ic_freq
* 1000;
1494 ic
->ic_bss
->ni_chan
= ic
->ic_ibss_chan
;
1495 len
= sizeof(config
);
1496 config
.nc_length
= len
;
1497 config
.nc_fhconfig
.ncf_length
=
1498 sizeof(ndis_80211_config_fh
);
1499 rval
= ndis_set_info(sc
, OID_802_11_CONFIGURATION
,
1502 device_printf(sc
->ndis_dev
, "couldn't change "
1503 "DS config to %ukHz: %d\n",
1504 config
.nc_dsconfig
, rval
);
1507 device_printf(sc
->ndis_dev
, "couldn't retrieve "
1508 "channel info: %d\n", rval
);
1510 /* Set SSID -- always do this last. */
1513 bzero((char *)&ssid
, len
);
1514 ssid
.ns_ssidlen
= ic
->ic_des_esslen
;
1515 if (ssid
.ns_ssidlen
== 0) {
1516 ssid
.ns_ssidlen
= 1;
1518 bcopy(ic
->ic_des_essid
, ssid
.ns_ssid
, ssid
.ns_ssidlen
);
1519 rval
= ndis_set_info(sc
, OID_802_11_SSID
, &ssid
, &len
);
1522 device_printf (sc
->ndis_dev
, "set ssid failed: %d\n", rval
);
1526 ndis_media_status(struct ifnet
*ifp
, struct ifmediareq
*imr
)
1528 struct ieee80211com
*ic
= (void *)ifp
; /* XXX */
1529 struct ieee80211_node
*ni
= NULL
;
1531 imr
->ifm_status
= IFM_AVALID
;
1532 imr
->ifm_active
= IFM_IEEE80211
;
1533 if (ic
->ic_state
== IEEE80211_S_RUN
)
1534 imr
->ifm_status
|= IFM_ACTIVE
;
1535 imr
->ifm_active
|= IFM_AUTO
;
1536 switch (ic
->ic_opmode
) {
1537 case IEEE80211_M_STA
:
1539 /* calculate rate subtype */
1540 imr
->ifm_active
|= ieee80211_rate2media(ic
,
1541 ni
->ni_rates
.rs_rates
[ni
->ni_txrate
], ic
->ic_curmode
);
1543 case IEEE80211_M_IBSS
:
1545 /* calculate rate subtype */
1546 imr
->ifm_active
|= ieee80211_rate2media(ic
,
1547 ni
->ni_rates
.rs_rates
[ni
->ni_txrate
], ic
->ic_curmode
);
1548 imr
->ifm_active
|= IFM_IEEE80211_ADHOC
;
1550 case IEEE80211_M_AHDEMO
:
1551 /* should not come here */
1553 case IEEE80211_M_HOSTAP
:
1554 imr
->ifm_active
|= IFM_IEEE80211_HOSTAP
;
1556 case IEEE80211_M_MONITOR
:
1557 imr
->ifm_active
|= IFM_IEEE80211_MONITOR
;
1560 switch (ic
->ic_curmode
) {
1561 case IEEE80211_MODE_11A
:
1562 imr
->ifm_active
|= IFM_MAKEMODE(IFM_IEEE80211_11A
);
1564 case IEEE80211_MODE_11B
:
1565 imr
->ifm_active
|= IFM_MAKEMODE(IFM_IEEE80211_11B
);
1567 case IEEE80211_MODE_11G
:
1568 imr
->ifm_active
|= IFM_MAKEMODE(IFM_IEEE80211_11G
);
1570 case IEEE80211_MODE_TURBO_A
:
1571 imr
->ifm_active
|= IFM_MAKEMODE(IFM_IEEE80211_11A
)
1572 | IFM_IEEE80211_TURBO
;
1578 ndis_get_assoc(struct ndis_softc
*sc
, ndis_wlan_bssid_ex
**assoc
)
1580 ndis_80211_bssid_list_ex
*bl
;
1581 ndis_wlan_bssid_ex
*bs
;
1582 ndis_80211_macaddr bssid
;
1588 len
= sizeof(bssid
);
1589 error
= ndis_get_info(sc
, OID_802_11_BSSID
, &bssid
, &len
);
1591 device_printf(sc
->ndis_dev
, "failed to get bssid\n");
1595 error
= ndis_get_info(sc
, OID_802_11_BSSID_LIST
, NULL
, &len
);
1596 if (error
!= ENOSPC
) {
1597 device_printf(sc
->ndis_dev
, "bssid_list failed\n");
1601 bl
= kmalloc(len
, M_TEMP
, M_NOWAIT
|M_ZERO
);
1604 error
= ndis_get_info(sc
, OID_802_11_BSSID_LIST
, bl
, &len
);
1607 device_printf(sc
->ndis_dev
, "bssid_list failed\n");
1611 bs
= (ndis_wlan_bssid_ex
*)&bl
->nblx_bssid
[0];
1612 for (i
= 0; i
< bl
->nblx_items
; i
++) {
1613 if (bcmp(bs
->nwbx_macaddr
, bssid
, sizeof(bssid
)) == 0) {
1614 *assoc
= kmalloc(bs
->nwbx_len
, M_TEMP
, M_NOWAIT
);
1615 if (*assoc
== NULL
) {
1619 bcopy((char *)bs
, (char *)*assoc
, bs
->nwbx_len
);
1623 bs
= (ndis_wlan_bssid_ex
*)((char *)bs
+ bs
->nwbx_len
);
1631 ndis_getstate_80211(struct ndis_softc
*sc
)
1633 struct ieee80211com
*ic
;
1634 ndis_80211_ssid ssid
;
1635 ndis_80211_config config
;
1636 ndis_wlan_bssid_ex
*bs
;
1637 int rval
, len
, i
= 0;
1642 ifp
= &sc
->ic
.ic_ac
.ac_if
;
1644 if (!NDIS_INITIALIZED(sc
))
1648 ic
->ic_state
= IEEE80211_S_RUN
;
1650 ic
->ic_state
= IEEE80211_S_ASSOC
;
1654 * If we're associated, retrieve info on the current bssid.
1656 if ((rval
= ndis_get_assoc(sc
, &bs
)) == 0) {
1657 switch(bs
->nwbx_nettype
) {
1658 case NDIS_80211_NETTYPE_11FH
:
1659 case NDIS_80211_NETTYPE_11DS
:
1660 ic
->ic_curmode
= IEEE80211_MODE_11B
;
1662 case NDIS_80211_NETTYPE_11OFDM5
:
1663 ic
->ic_curmode
= IEEE80211_MODE_11A
;
1665 case NDIS_80211_NETTYPE_11OFDM24
:
1666 ic
->ic_curmode
= IEEE80211_MODE_11G
;
1669 device_printf(sc
->ndis_dev
,
1670 "unknown nettype %d\n", arg
);
1679 bzero((char *)&ssid
, len
);
1680 rval
= ndis_get_info(sc
, OID_802_11_SSID
, &ssid
, &len
);
1683 device_printf (sc
->ndis_dev
, "get ssid failed: %d\n", rval
);
1684 bcopy(ssid
.ns_ssid
, ic
->ic_bss
->ni_essid
, ssid
.ns_ssidlen
);
1685 ic
->ic_bss
->ni_esslen
= ssid
.ns_ssidlen
;
1688 rval
= ndis_get_info(sc
, OID_GEN_LINK_SPEED
, &arg
, &len
);
1690 device_printf (sc
->ndis_dev
, "get link speed failed: %d\n",
1693 if (ic
->ic_modecaps
& (1<<IEEE80211_MODE_11B
)) {
1694 ic
->ic_bss
->ni_rates
= ic
->ic_sup_rates
[IEEE80211_MODE_11B
];
1695 for (i
= 0; i
< ic
->ic_bss
->ni_rates
.rs_nrates
; i
++) {
1696 if ((ic
->ic_bss
->ni_rates
.rs_rates
[i
] &
1697 IEEE80211_RATE_VAL
) == arg
/ 5000)
1702 if (i
== ic
->ic_bss
->ni_rates
.rs_nrates
&&
1703 ic
->ic_modecaps
& (1<<IEEE80211_MODE_11G
)) {
1704 ic
->ic_bss
->ni_rates
= ic
->ic_sup_rates
[IEEE80211_MODE_11G
];
1705 for (i
= 0; i
< ic
->ic_bss
->ni_rates
.rs_nrates
; i
++) {
1706 if ((ic
->ic_bss
->ni_rates
.rs_rates
[i
] &
1707 IEEE80211_RATE_VAL
) == arg
/ 5000)
1712 if (i
== ic
->ic_bss
->ni_rates
.rs_nrates
)
1713 device_printf(sc
->ndis_dev
, "no matching rate for: %d\n",
1716 ic
->ic_bss
->ni_txrate
= i
;
1718 if (ic
->ic_caps
& IEEE80211_C_PMGT
) {
1720 rval
= ndis_get_info(sc
, OID_802_11_POWER_MODE
, &arg
, &len
);
1723 device_printf(sc
->ndis_dev
,
1724 "get power mode failed: %d\n", rval
);
1725 if (arg
== NDIS_80211_POWERMODE_CAM
)
1726 ic
->ic_flags
&= ~IEEE80211_F_PMGTON
;
1728 ic
->ic_flags
|= IEEE80211_F_PMGTON
;
1731 len
= sizeof(config
);
1732 bzero((char *)&config
, len
);
1733 config
.nc_length
= len
;
1734 config
.nc_fhconfig
.ncf_length
= sizeof(ndis_80211_config_fh
);
1735 rval
= ndis_get_info(sc
, OID_802_11_CONFIGURATION
, &config
, &len
);
1739 chan
= ieee80211_mhz2ieee(config
.nc_dsconfig
/ 1000, 0);
1740 if (chan
< 0 || chan
>= IEEE80211_CHAN_MAX
) {
1741 if (ifp
->if_flags
& IFF_DEBUG
)
1742 device_printf(sc
->ndis_dev
, "current channel "
1743 "(%uMHz) out of bounds\n",
1744 config
.nc_dsconfig
/ 1000);
1745 ic
->ic_bss
->ni_chan
= &ic
->ic_channels
[1];
1747 ic
->ic_bss
->ni_chan
= &ic
->ic_channels
[chan
];
1749 device_printf(sc
->ndis_dev
, "couldn't retrieve "
1750 "channel info: %d\n", rval
);
1754 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
1757 device_printf (sc->ndis_dev,
1758 "get wep status failed: %d\n", rval);
1760 if (arg == NDIS_80211_WEPSTAT_ENABLED)
1761 ic->ic_flags |= IEEE80211_F_WEPON;
1763 ic->ic_flags &= ~IEEE80211_F_WEPON;
1768 ndis_ioctl(struct ifnet
*ifp
, u_long command
, caddr_t data
, struct ucred
*cr
)
1770 struct ndis_softc
*sc
= ifp
->if_softc
;
1771 struct ifreq
*ifr
= (struct ifreq
*) data
;
1776 if (ifp
->if_flags
& IFF_UP
) {
1777 if (ifp
->if_flags
& IFF_RUNNING
&&
1778 ifp
->if_flags
& IFF_PROMISC
&&
1779 !(sc
->ndis_if_flags
& IFF_PROMISC
)) {
1781 NDIS_PACKET_TYPE_PROMISCUOUS
;
1782 i
= sizeof(sc
->ndis_filter
);
1783 error
= ndis_set_info(sc
,
1784 OID_GEN_CURRENT_PACKET_FILTER
,
1785 &sc
->ndis_filter
, &i
);
1786 } else if (ifp
->if_flags
& IFF_RUNNING
&&
1787 !(ifp
->if_flags
& IFF_PROMISC
) &&
1788 sc
->ndis_if_flags
& IFF_PROMISC
) {
1790 ~NDIS_PACKET_TYPE_PROMISCUOUS
;
1791 i
= sizeof(sc
->ndis_filter
);
1792 error
= ndis_set_info(sc
,
1793 OID_GEN_CURRENT_PACKET_FILTER
,
1794 &sc
->ndis_filter
, &i
);
1798 if (ifp
->if_flags
& IFF_RUNNING
)
1801 sc
->ndis_if_flags
= ifp
->if_flags
;
1811 if (sc
->ndis_80211
) {
1812 error
= ieee80211_ioctl(&sc
->ic
, command
, data
, cr
);
1813 if (error
== ENETRESET
) {
1814 ndis_setstate_80211(sc
);
1819 error
= ifmedia_ioctl(ifp
, ifr
, &sc
->ifmedia
, command
);
1822 ifp
->if_capenable
= ifr
->ifr_reqcap
;
1823 if (ifp
->if_capenable
& IFCAP_TXCSUM
)
1824 ifp
->if_hwassist
= sc
->ndis_hwassist
;
1826 ifp
->if_hwassist
= 0;
1827 ndis_set_offload(sc
);
1829 case SIOCGIFGENERIC
:
1830 case SIOCSIFGENERIC
:
1831 if (sc
->ndis_80211
&& NDIS_INITIALIZED(sc
)) {
1832 if (command
== SIOCGIFGENERIC
)
1833 error
= ndis_wi_ioctl_get(ifp
, command
, data
);
1835 error
= ndis_wi_ioctl_set(ifp
, command
, data
);
1838 if (error
!= ENOTTY
)
1842 if (sc
->ndis_80211
) {
1843 error
= ieee80211_ioctl(&sc
->ic
, command
, data
, cr
);
1844 if (error
== ENETRESET
) {
1845 ndis_setstate_80211(sc
);
1849 error
= ether_ioctl(ifp
, command
, data
);
1857 ndis_wi_ioctl_get(struct ifnet
*ifp
, u_long command
, caddr_t data
)
1861 struct ndis_softc
*sc
;
1862 ndis_80211_bssid_list_ex
*bl
;
1863 ndis_wlan_bssid_ex
*wb
;
1864 struct wi_apinfo
*api
;
1865 int error
, i
, j
, len
, maxaps
;
1868 ifr
= (struct ifreq
*)data
;
1869 error
= copyin(ifr
->ifr_data
, &wreq
, sizeof(wreq
));
1873 switch (wreq
.wi_type
) {
1874 case WI_RID_READ_APS
:
1876 error
= ndis_set_info(sc
, OID_802_11_BSSID_LIST_SCAN
,
1879 tsleep(&error
, PCATCH
, "ssidscan", hz
* 2);
1881 error
= ndis_get_info(sc
, OID_802_11_BSSID_LIST
, NULL
, &len
);
1882 if (error
!= ENOSPC
)
1884 bl
= kmalloc(len
, M_DEVBUF
, M_WAITOK
|M_ZERO
);
1885 error
= ndis_get_info(sc
, OID_802_11_BSSID_LIST
, bl
, &len
);
1887 kfree(bl
, M_DEVBUF
);
1890 maxaps
= (2 * wreq
.wi_len
- sizeof(int)) / sizeof(*api
);
1891 maxaps
= MIN(maxaps
, bl
->nblx_items
);
1892 wreq
.wi_len
= (maxaps
* sizeof(*api
) + sizeof(int)) / 2;
1893 *(int *)&wreq
.wi_val
= maxaps
;
1894 api
= (struct wi_apinfo
*)&((int *)&wreq
.wi_val
)[1];
1895 wb
= bl
->nblx_bssid
;
1897 bzero(api
, sizeof(*api
));
1898 bcopy(&wb
->nwbx_macaddr
, &api
->bssid
,
1899 sizeof(api
->bssid
));
1900 api
->namelen
= wb
->nwbx_ssid
.ns_ssidlen
;
1901 bcopy(&wb
->nwbx_ssid
.ns_ssid
, &api
->name
, api
->namelen
);
1902 if (wb
->nwbx_privacy
)
1903 api
->capinfo
|= IEEE80211_CAPINFO_PRIVACY
;
1904 /* XXX Where can we get noise information? */
1905 api
->signal
= wb
->nwbx_rssi
+ 149; /* XXX */
1906 api
->quality
= api
->signal
;
1908 ieee80211_mhz2ieee(wb
->nwbx_config
.nc_dsconfig
/
1910 /* In "auto" infrastructure mode, this is useless. */
1911 if (wb
->nwbx_netinfra
== NDIS_80211_NET_INFRA_IBSS
)
1912 api
->capinfo
|= IEEE80211_CAPINFO_IBSS
;
1913 if (wb
->nwbx_len
> sizeof(ndis_wlan_bssid
)) {
1914 j
= sizeof(ndis_80211_rates_ex
);
1915 /* handle other extended things */
1917 j
= sizeof(ndis_80211_rates
);
1918 for (i
= api
->rate
= 0; i
< j
; i
++)
1919 api
->rate
= MAX(api
->rate
, 5 *
1920 (wb
->nwbx_supportedrates
[i
] & 0x7f));
1922 wb
= (ndis_wlan_bssid_ex
*)((char *)wb
+ wb
->nwbx_len
);
1924 kfree(bl
, M_DEVBUF
);
1925 error
= copyout(&wreq
, ifr
->ifr_data
, sizeof(wreq
));
1935 ndis_wi_ioctl_set(struct ifnet
*ifp
, u_long command
, caddr_t data
)
1939 struct ndis_softc
*sc
;
1943 error
= priv_check(curthread
, PRIV_ROOT
);
1948 ifr
= (struct ifreq
*)data
;
1949 error
= copyin(ifr
->ifr_data
, &wreq
, sizeof(wreq
));
1953 switch (wreq
.wi_type
) {
1954 case WI_RID_SCAN_APS
:
1955 case WI_RID_SCAN_REQ
: /* arguments ignored */
1958 error
= ndis_set_info(sc
, OID_802_11_BSSID_LIST_SCAN
, &foo
,
1969 ndis_watchdog(struct ifnet
*ifp
)
1971 struct ndis_softc
*sc
;
1976 device_printf(sc
->ndis_dev
, "watchdog timeout\n");
1979 ndis_sched(ndis_starttask
, ifp
, NDIS_TASKQUEUE
);
1983 * Stop the adapter and free any mbufs allocated to the
1987 ndis_stop(struct ndis_softc
*sc
)
1991 ifp
= &sc
->arpcom
.ac_if
;
1992 callout_stop(&sc
->ndis_stat_timer
);
1998 ifp
->if_flags
&= ~(IFF_RUNNING
| IFF_OACTIVE
);
2002 * Stop all chip I/O so that the kernel's probe routines don't
2003 * get confused by errant DMAs when rebooting.
2006 ndis_shutdown(device_t dev
)
2008 struct ndis_softc
*sc
;
2011 sc
= device_get_softc(dev
);
2012 ifp
= &sc
->arpcom
.ac_if
;
2013 lwkt_serialize_enter(ifp
->if_serializer
);
2014 ndis_shutdown_nic(sc
);
2015 lwkt_serialize_exit(ifp
->if_serializer
);