diff options
| author | Brooks Davis <brooks@one-eyed-alien.net> | 2021-01-25 21:45:03 +0000 |
|---|---|---|
| committer | Brooks Davis <brooks@FreeBSD.org> | 2021-01-25 21:45:03 +0000 |
| commit | bfc99943b04b46a6c1c885ce7bcc6f235b7422aa (patch) | |
| tree | f6090ce008f9b372fe3d2ad5ccecb3add60e4a07 /sys/dev/if_ndis | |
| parent | 1b109c69ed625ebf292c1d16f7a3efcab96722e5 (diff) | |
Diffstat (limited to 'sys/dev/if_ndis')
| -rw-r--r-- | sys/dev/if_ndis/if_ndis.c | 3423 | ||||
| -rw-r--r-- | sys/dev/if_ndis/if_ndis_pci.c | 357 | ||||
| -rw-r--r-- | sys/dev/if_ndis/if_ndis_usb.c | 240 | ||||
| -rw-r--r-- | sys/dev/if_ndis/if_ndisvar.h | 263 |
4 files changed, 0 insertions, 4283 deletions
diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c deleted file mode 100644 index 1a5e8eeed4be..000000000000 --- a/sys/dev/if_ndis/if_ndis.c +++ /dev/null @@ -1,3423 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul <wpaul@windriver.com>. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * WPA support originally contributed by Arvind Srinivasan <arvind@celar.us> - * then hacked upon mercilessly by my. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/sockio.h> -#include <sys/mbuf.h> -#include <sys/malloc.h> -#include <sys/endian.h> -#include <sys/priv.h> -#include <sys/kernel.h> -#include <sys/socket.h> -#include <sys/queue.h> -#include <sys/module.h> -#include <sys/proc.h> -#include <sys/sysctl.h> -#include <sys/kthread.h> -#include <sys/limits.h> - -#include <net/if.h> -#include <net/if_var.h> -#include <net/if_arp.h> -#include <net/ethernet.h> -#include <net/if_dl.h> -#include <net/if_media.h> -#include <net/if_types.h> -#include <net/route.h> - -#include <net/bpf.h> - -#include <machine/bus.h> -#include <machine/resource.h> -#include <sys/bus.h> -#include <sys/rman.h> - -#include <net80211/ieee80211_var.h> -#include <net80211/ieee80211_ioctl.h> -#include <net80211/ieee80211_regdomain.h> - -#include <dev/pci/pcireg.h> -#include <dev/pci/pcivar.h> -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> - -#include <compat/ndis/pe_var.h> -#include <compat/ndis/cfg_var.h> -#include <compat/ndis/resource_var.h> -#include <compat/ndis/ntoskrnl_var.h> -#include <compat/ndis/hal_var.h> -#include <compat/ndis/ndis_var.h> -#include <compat/ndis/usbd_var.h> -#include <dev/if_ndis/if_ndisvar.h> - -#define NDIS_DEBUG -#ifdef NDIS_DEBUG -#define DPRINTF(x) do { if (ndis_debug > 0) printf x; } while (0) -int ndis_debug = 0; -SYSCTL_INT(_debug, OID_AUTO, ndis, CTLFLAG_RW, &ndis_debug, 0, - "if_ndis debug level"); -#else -#define DPRINTF(x) -#endif - -SYSCTL_DECL(_hw_ndisusb); -int ndisusb_halt = 1; -SYSCTL_INT(_hw_ndisusb, OID_AUTO, halt, CTLFLAG_RW, &ndisusb_halt, 0, - "Halt NDIS USB driver when it's attached"); - -/* 0 - 30 dBm to mW conversion table */ -static const uint16_t dBm2mW[] = { - 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, - 3, 4, 4, 4, 5, 6, 6, 7, 8, 9, - 10, 11, 13, 14, 16, 18, 20, 22, 25, 28, - 32, 35, 40, 45, 50, 56, 63, 71, 79, 89, - 100, 112, 126, 141, 158, 178, 200, 224, 251, 282, - 316, 355, 398, 447, 501, 562, 631, 708, 794, 891, - 1000 -}; - -MODULE_DEPEND(ndis, ether, 1, 1, 1); -MODULE_DEPEND(ndis, wlan, 1, 1, 1); -MODULE_DEPEND(ndis, ndisapi, 1, 1, 1); - -MODULE_VERSION(ndis, 1); - -int ndis_attach (device_t); -int ndis_detach (device_t); -int ndis_suspend (device_t); -int ndis_resume (device_t); -void ndis_shutdown (device_t); - -int ndisdrv_modevent (module_t, int, void *); - -static void ndis_txeof (ndis_handle, ndis_packet *, ndis_status); -static void ndis_rxeof (ndis_handle, ndis_packet **, uint32_t); -static void ndis_rxeof_eth (ndis_handle, ndis_handle, char *, void *, - uint32_t, void *, uint32_t, uint32_t); -static void ndis_rxeof_done (ndis_handle); -static void ndis_rxeof_xfr (kdpc *, ndis_handle, void *, void *); -static void ndis_rxeof_xfr_done (ndis_handle, ndis_packet *, - uint32_t, uint32_t); -static void ndis_linksts (ndis_handle, ndis_status, void *, uint32_t); -static void ndis_linksts_done (ndis_handle); - -/* We need to wrap these functions for amd64. */ -static funcptr ndis_txeof_wrap; -static funcptr ndis_rxeof_wrap; -static funcptr ndis_rxeof_eth_wrap; -static funcptr ndis_rxeof_done_wrap; -static funcptr ndis_rxeof_xfr_wrap; -static funcptr ndis_rxeof_xfr_done_wrap; -static funcptr ndis_linksts_wrap; -static funcptr ndis_linksts_done_wrap; -static funcptr ndis_ticktask_wrap; -static funcptr ndis_ifstarttask_wrap; -static funcptr ndis_resettask_wrap; -static funcptr ndis_inputtask_wrap; - -static struct ieee80211vap *ndis_vap_create(struct ieee80211com *, - const char [IFNAMSIZ], int, enum ieee80211_opmode, int, - const uint8_t [IEEE80211_ADDR_LEN], - const uint8_t [IEEE80211_ADDR_LEN]); -static void ndis_vap_delete (struct ieee80211vap *); -static void ndis_tick (void *); -static void ndis_ticktask (device_object *, void *); -static int ndis_raw_xmit (struct ieee80211_node *, struct mbuf *, - const struct ieee80211_bpf_params *); -static void ndis_update_mcast (struct ieee80211com *); -static void ndis_update_promisc (struct ieee80211com *); -static void ndis_ifstart (struct ifnet *); -static void ndis_ifstarttask (device_object *, void *); -static void ndis_resettask (device_object *, void *); -static void ndis_inputtask (device_object *, void *); -static int ndis_ifioctl (struct ifnet *, u_long, caddr_t); -static int ndis_newstate (struct ieee80211vap *, enum ieee80211_state, - int); -static int ndis_nettype_chan (uint32_t); -static int ndis_nettype_mode (uint32_t); -static void ndis_scan (void *); -static void ndis_scan_results (struct ndis_softc *); -static void ndis_scan_start (struct ieee80211com *); -static void ndis_scan_end (struct ieee80211com *); -static void ndis_set_channel (struct ieee80211com *); -static void ndis_scan_curchan (struct ieee80211_scan_state *, unsigned long); -static void ndis_scan_mindwell (struct ieee80211_scan_state *); -static void ndis_init (void *); -static void ndis_stop (struct ndis_softc *); -static int ndis_ifmedia_upd (struct ifnet *); -static void ndis_ifmedia_sts (struct ifnet *, struct ifmediareq *); -static int ndis_get_bssid_list (struct ndis_softc *, - ndis_80211_bssid_list_ex **); -static int ndis_get_assoc (struct ndis_softc *, ndis_wlan_bssid_ex **); -static int ndis_probe_offload (struct ndis_softc *); -static int ndis_set_offload (struct ndis_softc *); -static void ndis_getstate_80211 (struct ndis_softc *); -static void ndis_setstate_80211 (struct ndis_softc *); -static void ndis_auth_and_assoc (struct ndis_softc *, struct ieee80211vap *); -static void ndis_media_status (struct ifnet *, struct ifmediareq *); -static int ndis_set_cipher (struct ndis_softc *, int); -static int ndis_set_wpa (struct ndis_softc *, void *, int); -static int ndis_add_key (struct ieee80211vap *, - const struct ieee80211_key *); -static int ndis_del_key (struct ieee80211vap *, - const struct ieee80211_key *); -static void ndis_setmulti (struct ndis_softc *); -static void ndis_map_sclist (void *, bus_dma_segment_t *, - int, bus_size_t, int); -static int ndis_ifattach(struct ndis_softc *); - -static int ndis_80211attach(struct ndis_softc *); -static int ndis_80211ioctl(struct ieee80211com *, u_long , void *); -static int ndis_80211transmit(struct ieee80211com *, struct mbuf *); -static void ndis_80211parent(struct ieee80211com *); - -static int ndisdrv_loaded = 0; - -/* - * This routine should call windrv_load() once for each driver - * image. This will do the relocation and dynalinking for the - * image, and create a Windows driver object which will be - * saved in our driver database. - */ -int -ndisdrv_modevent(mod, cmd, arg) - module_t mod; - int cmd; - void *arg; -{ - int error = 0; - - switch (cmd) { - case MOD_LOAD: - ndisdrv_loaded++; - if (ndisdrv_loaded > 1) - break; - windrv_wrap((funcptr)ndis_rxeof, &ndis_rxeof_wrap, - 3, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_rxeof_eth, &ndis_rxeof_eth_wrap, - 8, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_rxeof_done, &ndis_rxeof_done_wrap, - 1, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_rxeof_xfr, &ndis_rxeof_xfr_wrap, - 4, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_rxeof_xfr_done, - &ndis_rxeof_xfr_done_wrap, 4, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_txeof, &ndis_txeof_wrap, - 3, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_linksts, &ndis_linksts_wrap, - 4, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_linksts_done, - &ndis_linksts_done_wrap, 1, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_ticktask, &ndis_ticktask_wrap, - 2, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_ifstarttask, &ndis_ifstarttask_wrap, - 2, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_resettask, &ndis_resettask_wrap, - 2, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_inputtask, &ndis_inputtask_wrap, - 2, WINDRV_WRAP_STDCALL); - break; - case MOD_UNLOAD: - ndisdrv_loaded--; - if (ndisdrv_loaded > 0) - break; - /* fallthrough */ - case MOD_SHUTDOWN: - windrv_unwrap(ndis_rxeof_wrap); - windrv_unwrap(ndis_rxeof_eth_wrap); - windrv_unwrap(ndis_rxeof_done_wrap); - windrv_unwrap(ndis_rxeof_xfr_wrap); - windrv_unwrap(ndis_rxeof_xfr_done_wrap); - windrv_unwrap(ndis_txeof_wrap); - windrv_unwrap(ndis_linksts_wrap); - windrv_unwrap(ndis_linksts_done_wrap); - windrv_unwrap(ndis_ticktask_wrap); - windrv_unwrap(ndis_ifstarttask_wrap); - windrv_unwrap(ndis_resettask_wrap); - windrv_unwrap(ndis_inputtask_wrap); - break; - default: - error = EINVAL; - break; - } - - return (error); -} - -struct mclist_ctx { - uint8_t *mclist; - int mclistsz; -}; - -static u_int -ndis_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) -{ - struct mclist_ctx *ctx = arg; - - if (cnt < ctx->mclistsz) - bcopy(LLADDR(sdl), ctx->mclist + (ETHER_ADDR_LEN * cnt), - ETHER_ADDR_LEN); - return (1); -} - -/* - * Program the 64-bit multicast hash filter. - */ -static void -ndis_setmulti(sc) - struct ndis_softc *sc; -{ - struct ifnet *ifp; - struct mclist_ctx ctx; - int len, error; - - - if (!NDIS_INITIALIZED(sc)) - return; - - if (sc->ndis_80211) - return; - - ifp = sc->ifp; - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { - sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; - len = sizeof(sc->ndis_filter); - error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER, - &sc->ndis_filter, &len); - if (error) - device_printf(sc->ndis_dev, - "set allmulti failed: %d\n", error); - return; - } - - if (if_llmaddr_count(ifp) == 0) - return; - - len = sizeof(ctx.mclistsz); - ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &ctx.mclistsz, &len); - - ctx.mclist = malloc(ETHER_ADDR_LEN * ctx.mclistsz, M_TEMP, - M_NOWAIT | M_ZERO); - - if (ctx.mclist == NULL) { - sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; - goto out; - } - - sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST; - - len = if_foreach_llmaddr(ifp, ndis_copy_maddr, &ctx); - if (len > ctx.mclistsz) { - sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; - sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST; - goto out; - } - - len = len * ETHER_ADDR_LEN; - error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, ctx.mclist, &len); - if (error) { - device_printf(sc->ndis_dev, "set mclist failed: %d\n", error); - sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; - sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST; - } - -out: - free(ctx.mclist, M_TEMP); - - len = sizeof(sc->ndis_filter); - error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER, - &sc->ndis_filter, &len); - if (error) - device_printf(sc->ndis_dev, "set multi failed: %d\n", error); -} - -static int -ndis_set_offload(sc) - struct ndis_softc *sc; -{ - ndis_task_offload *nto; - ndis_task_offload_hdr *ntoh; - ndis_task_tcpip_csum *nttc; - struct ifnet *ifp; - int len, error; - - if (!NDIS_INITIALIZED(sc)) - return (EINVAL); - - if (sc->ndis_80211) - return (EINVAL); - /* See if there's anything to set. */ - - ifp = sc->ifp; - error = ndis_probe_offload(sc); - if (error) - return (error); - - if (sc->ndis_hwassist == 0 && ifp->if_capabilities == 0) - return (0); - - len = sizeof(ndis_task_offload_hdr) + sizeof(ndis_task_offload) + - sizeof(ndis_task_tcpip_csum); - - ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO); - - if (ntoh == NULL) - return (ENOMEM); - - ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION; - ntoh->ntoh_len = sizeof(ndis_task_offload_hdr); - ntoh->ntoh_offset_firsttask = sizeof(ndis_task_offload_hdr); - ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header); - ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3; - ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN; - - nto = (ndis_task_offload *)((char *)ntoh + - ntoh->ntoh_offset_firsttask); - - nto->nto_vers = NDIS_TASK_OFFLOAD_VERSION; - nto->nto_len = sizeof(ndis_task_offload); - nto->nto_task = NDIS_TASK_TCPIP_CSUM; - nto->nto_offset_nexttask = 0; - nto->nto_taskbuflen = sizeof(ndis_task_tcpip_csum); - - nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf; - - if (ifp->if_capenable & IFCAP_TXCSUM) - nttc->nttc_v4tx = sc->ndis_v4tx; - - if (ifp->if_capenable & IFCAP_RXCSUM) - nttc->nttc_v4rx = sc->ndis_v4rx; - - error = ndis_set_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len); - free(ntoh, M_TEMP); - - return (error); -} - -static int -ndis_probe_offload(sc) - struct ndis_softc *sc; -{ - ndis_task_offload *nto; - ndis_task_offload_hdr *ntoh; - ndis_task_tcpip_csum *nttc = NULL; - struct ifnet *ifp; - int len, error, dummy; - - ifp = sc->ifp; - - len = sizeof(dummy); - error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, &dummy, &len); - - if (error != ENOSPC) - return (error); - - ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO); - - if (ntoh == NULL) - return (ENOMEM); - - ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION; - ntoh->ntoh_len = sizeof(ndis_task_offload_hdr); - ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header); - ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3; - ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN; - - error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len); - - if (error) { - free(ntoh, M_TEMP); - return (error); - } - - if (ntoh->ntoh_vers != NDIS_TASK_OFFLOAD_VERSION) { - free(ntoh, M_TEMP); - return (EINVAL); - } - - nto = (ndis_task_offload *)((char *)ntoh + - ntoh->ntoh_offset_firsttask); - - while (1) { - switch (nto->nto_task) { - case NDIS_TASK_TCPIP_CSUM: - nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf; - break; - /* Don't handle these yet. */ - case NDIS_TASK_IPSEC: - case NDIS_TASK_TCP_LARGESEND: - default: - break; - } - if (nto->nto_offset_nexttask == 0) - break; - nto = (ndis_task_offload *)((char *)nto + - nto->nto_offset_nexttask); - } - - if (nttc == NULL) { - free(ntoh, M_TEMP); - return (ENOENT); - } - - sc->ndis_v4tx = nttc->nttc_v4tx; - sc->ndis_v4rx = nttc->nttc_v4rx; - - if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_IP_CSUM) - sc->ndis_hwassist |= CSUM_IP; - if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_TCP_CSUM) - sc->ndis_hwassist |= CSUM_TCP; - if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_UDP_CSUM) - sc->ndis_hwassist |= CSUM_UDP; - - if (sc->ndis_hwassist) - ifp->if_capabilities |= IFCAP_TXCSUM; - - if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_IP_CSUM) - ifp->if_capabilities |= IFCAP_RXCSUM; - if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_TCP_CSUM) - ifp->if_capabilities |= IFCAP_RXCSUM; - if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_UDP_CSUM) - ifp->if_capabilities |= IFCAP_RXCSUM; - - free(ntoh, M_TEMP); - return (0); -} - -static int -ndis_nettype_chan(uint32_t type) -{ - switch (type) { - case NDIS_80211_NETTYPE_11FH: return (IEEE80211_CHAN_FHSS); - case NDIS_80211_NETTYPE_11DS: return (IEEE80211_CHAN_B); - case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_CHAN_A); - case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_CHAN_G); - } - DPRINTF(("unknown channel nettype %d\n", type)); - return (IEEE80211_CHAN_B); /* Default to 11B chan */ -} - -static int -ndis_nettype_mode(uint32_t type) -{ - switch (type) { - case NDIS_80211_NETTYPE_11FH: return (IEEE80211_MODE_FH); - case NDIS_80211_NETTYPE_11DS: return (IEEE80211_MODE_11B); - case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_MODE_11A); - case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_MODE_11G); - } - DPRINTF(("unknown mode nettype %d\n", type)); - return (IEEE80211_MODE_AUTO); -} - -/* - * Attach the interface. Allocate softc structures, do ifmedia - * setup and ethernet/BPF attach. - */ -int -ndis_attach(device_t dev) -{ - struct ndis_softc *sc; - driver_object *pdrv; - device_object *pdo; - int error = 0, len; - int i; - - sc = device_get_softc(dev); - - mtx_init(&sc->ndis_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, - MTX_DEF); - KeInitializeSpinLock(&sc->ndis_rxlock); - KeInitializeSpinLock(&sc->ndisusb_tasklock); - KeInitializeSpinLock(&sc->ndisusb_xferdonelock); - InitializeListHead(&sc->ndis_shlist); - InitializeListHead(&sc->ndisusb_tasklist); - InitializeListHead(&sc->ndisusb_xferdonelist); - callout_init(&sc->ndis_stat_callout, 1); - mbufq_init(&sc->ndis_rxqueue, INT_MAX); /* XXXGL: sane maximum */ - - /* Create sysctl registry nodes */ - ndis_create_sysctls(sc); - - /* Find the PDO for this device instance. */ - - if (sc->ndis_iftype == PCIBus) - pdrv = windrv_lookup(0, "PCI Bus"); - else if (sc->ndis_iftype == PCMCIABus) - pdrv = windrv_lookup(0, "PCCARD Bus"); - else - pdrv = windrv_lookup(0, "USB Bus"); - pdo = windrv_find_pdo(pdrv, dev); - - /* - * Create a new functional device object for this - * device. This is what creates the miniport block - * for this device instance. - */ - - if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) { - device_printf(dev, "failed to create FDO!\n"); - error = ENXIO; - goto fail; - } - - /* Tell the user what version of the API the driver is using. */ - device_printf(dev, "NDIS API version: %d.%d\n", - sc->ndis_chars->nmc_version_major, - sc->ndis_chars->nmc_version_minor); - - /* Do resource conversion. */ - if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus) - ndis_convert_res(sc); - else - sc->ndis_block->nmb_rlist = NULL; - - /* Install our RX and TX interrupt handlers. */ - sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap; - sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap; - sc->ndis_block->nmb_ethrxindicate_func = ndis_rxeof_eth_wrap; - sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap; - sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap; - - /* Override the status handler so we can detect link changes. */ - sc->ndis_block->nmb_status_func = ndis_linksts_wrap; - sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap; - - /* Set up work item handlers. */ - sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); - sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); - sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); - sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); - sc->ndisusb_xferdoneitem = - IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); - sc->ndisusb_taskitem = - IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); - KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block); - - /* Call driver's init routine. */ - if (ndis_init_nic(sc)) { - device_printf(dev, "init handler failed\n"); - error = ENXIO; - goto fail; - } - - /* - * Figure out how big to make the TX buffer pool. - */ - len = sizeof(sc->ndis_maxpkts); - if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS, - &sc->ndis_maxpkts, &len)) { - device_printf(dev, "failed to get max TX packets\n"); - error = ENXIO; - goto fail; - } - - /* - * If this is a deserialized miniport, we don't have - * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result. - */ - if (!NDIS_SERIALIZED(sc->ndis_block)) - sc->ndis_maxpkts = NDIS_TXPKTS; - - /* Enforce some sanity, just in case. */ - - if (sc->ndis_maxpkts == 0) - sc->ndis_maxpkts = 10; - - sc->ndis_txarray = malloc(sizeof(ndis_packet *) * - sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO); - - /* Allocate a pool of ndis_packets for TX encapsulation. */ - - NdisAllocatePacketPool(&i, &sc->ndis_txpool, - sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET); - - if (i != NDIS_STATUS_SUCCESS) { - sc->ndis_txpool = NULL; - device_printf(dev, "failed to allocate TX packet pool"); - error = ENOMEM; - goto fail; - } - - sc->ndis_txpending = sc->ndis_maxpkts; - - sc->ndis_oidcnt = 0; - /* Get supported oid list. */ - ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt); - - /* If the NDIS module requested scatter/gather, init maps. */ - if (sc->ndis_sc) - ndis_init_dma(sc); - - /* - * See if the OID_802_11_CONFIGURATION OID is - * supported by this driver. If it is, then this an 802.11 - * wireless driver, and we should set up media for wireless. - */ - for (i = 0; i < sc->ndis_oidcnt; i++) - if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) { - sc->ndis_80211 = 1; - break; - } - - if (sc->ndis_80211) - error = ndis_80211attach(sc); - else - error = ndis_ifattach(sc); - -fail: - if (error) { - ndis_detach(dev); - return (error); - } - - if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0) - return (error); - - DPRINTF(("attach done.\n")); - /* We're done talking to the NIC for now; halt it. */ - ndis_halt_nic(sc); - DPRINTF(("halting done.\n")); - - return (error); -} - -static int -ndis_80211attach(struct ndis_softc *sc) -{ - struct ieee80211com *ic = &sc->ndis_ic; - ndis_80211_rates_ex rates; - struct ndis_80211_nettype_list *ntl; - uint32_t arg; - int mode, i, r, len, nonettypes = 1; - uint8_t bands[IEEE80211_MODE_BYTES] = { 0 }; - - callout_init(&sc->ndis_scan_callout, 1); - - ic->ic_softc = sc; - ic->ic_ioctl = ndis_80211ioctl; - ic->ic_name = device_get_nameunit(sc->ndis_dev); - ic->ic_opmode = IEEE80211_M_STA; - ic->ic_phytype = IEEE80211_T_DS; - ic->ic_caps = IEEE80211_C_8023ENCAP | - IEEE80211_C_STA | IEEE80211_C_IBSS; - setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO); - len = 0; - r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, NULL, &len); - if (r != ENOSPC) - goto nonettypes; - ntl = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); - r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, ntl, &len); - if (r != 0) { - free(ntl, M_DEVBUF); - goto nonettypes; - } - - for (i = 0; i < ntl->ntl_items; i++) { - mode = ndis_nettype_mode(ntl->ntl_type[i]); - if (mode) { - nonettypes = 0; - setbit(ic->ic_modecaps, mode); - setbit(bands, mode); - } else - device_printf(sc->ndis_dev, "Unknown nettype %d\n", - ntl->ntl_type[i]); - } - free(ntl, M_DEVBUF); -nonettypes: - /* Default to 11b channels if the card did not supply any */ - if (nonettypes) { - setbit(ic->ic_modecaps, IEEE80211_MODE_11B); - setbit(bands, IEEE80211_MODE_11B); - } - len = sizeof(rates); - bzero((char *)&rates, len); - r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len); - if (r != 0) - device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r); - /* - * Since the supported rates only up to 8 can be supported, - * if this is not 802.11b we're just going to be faking it - * all up to heck. - */ - -#define TESTSETRATE(x, y) \ - do { \ - int i; \ - for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \ - if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \ - break; \ - } \ - if (i == ic->ic_sup_rates[x].rs_nrates) { \ - ic->ic_sup_rates[x].rs_rates[i] = (y); \ - ic->ic_sup_rates[x].rs_nrates++; \ - } \ - } while (0) - -#define SETRATE(x, y) \ - ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y) -#define INCRATE(x) \ - ic->ic_sup_rates[x].rs_nrates++ - - ic->ic_curmode = IEEE80211_MODE_AUTO; - if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) - ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0; - if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) - ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0; - if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) - ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0; - for (i = 0; i < len; i++) { - switch (rates[i] & IEEE80211_RATE_VAL) { - case 2: - case 4: - case 11: - case 10: - case 22: - if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) { - /* Lazy-init 802.11b. */ - setbit(ic->ic_modecaps, IEEE80211_MODE_11B); - ic->ic_sup_rates[IEEE80211_MODE_11B]. - rs_nrates = 0; - } - SETRATE(IEEE80211_MODE_11B, rates[i]); - INCRATE(IEEE80211_MODE_11B); - break; - default: - if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) { - SETRATE(IEEE80211_MODE_11A, rates[i]); - INCRATE(IEEE80211_MODE_11A); - } - if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) { - SETRATE(IEEE80211_MODE_11G, rates[i]); - INCRATE(IEEE80211_MODE_11G); - } - break; - } - } - - /* - * If the hardware supports 802.11g, it most - * likely supports 802.11b and all of the - * 802.11b and 802.11g speeds, so maybe we can - * just cheat here. Just how in the heck do - * we detect turbo modes, though? - */ - if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) { - TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|2); - TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|4); - TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|11); - TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|22); - } - if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) { - TESTSETRATE(IEEE80211_MODE_11G, 48); - TESTSETRATE(IEEE80211_MODE_11G, 72); - TESTSETRATE(IEEE80211_MODE_11G, 96); - TESTSETRATE(IEEE80211_MODE_11G, 108); - } - if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) { - TESTSETRATE(IEEE80211_MODE_11A, 48); - TESTSETRATE(IEEE80211_MODE_11A, 72); - TESTSETRATE(IEEE80211_MODE_11A, 96); - TESTSETRATE(IEEE80211_MODE_11A, 108); - } - -#undef SETRATE -#undef INCRATE -#undef TESTSETRATE - - ieee80211_init_channels(ic, NULL, bands); - - /* - * To test for WPA support, we need to see if we can - * set AUTHENTICATION_MODE to WPA and read it back - * successfully. - */ - i = sizeof(arg); - arg = NDIS_80211_AUTHMODE_WPA; - r = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i); - if (r == 0) { - r = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i); - if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA) - ic->ic_caps |= IEEE80211_C_WPA; - } - - /* - * To test for supported ciphers, we set each - * available encryption type in descending order. - * If ENC3 works, then we have WEP, TKIP and AES. - * If only ENC2 works, then we have WEP and TKIP. - * If only ENC1 works, then we have just WEP. - */ - i = sizeof(arg); - arg = NDIS_80211_WEPSTAT_ENC3ENABLED; - r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i); - if (r == 0) { - ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP - | IEEE80211_CRYPTO_TKIP - | IEEE80211_CRYPTO_AES_CCM; - goto got_crypto; - } - arg = NDIS_80211_WEPSTAT_ENC2ENABLED; - r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i); - if (r == 0) { - ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP - | IEEE80211_CRYPTO_TKIP; - goto got_crypto; - } - arg = NDIS_80211_WEPSTAT_ENC1ENABLED; - r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i); - if (r == 0) - ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP; -got_crypto: - i = sizeof(arg); - r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i); - if (r == 0) - ic->ic_caps |= IEEE80211_C_PMGT; - - r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i); - if (r == 0) - ic->ic_caps |= IEEE80211_C_TXPMGT; - - /* - * Get station address from the driver. - */ - len = sizeof(ic->ic_macaddr); - ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &ic->ic_macaddr, &len); - - ieee80211_ifattach(ic); - ic->ic_raw_xmit = ndis_raw_xmit; - ic->ic_scan_start = ndis_scan_start; - ic->ic_scan_end = ndis_scan_end; - ic->ic_set_channel = ndis_set_channel; - ic->ic_scan_curchan = ndis_scan_curchan; - ic->ic_scan_mindwell = ndis_scan_mindwell; - ic->ic_bsschan = IEEE80211_CHAN_ANYC; - ic->ic_vap_create = ndis_vap_create; - ic->ic_vap_delete = ndis_vap_delete; - ic->ic_update_mcast = ndis_update_mcast; - ic->ic_update_promisc = ndis_update_promisc; - ic->ic_transmit = ndis_80211transmit; - ic->ic_parent = ndis_80211parent; - - if (bootverbose) - ieee80211_announce(ic); - - return (0); -} - -static int -ndis_ifattach(struct ndis_softc *sc) -{ - struct ifnet *ifp; - u_char eaddr[ETHER_ADDR_LEN]; - int len; - - ifp = if_alloc(IFT_ETHER); - if (ifp == NULL) - return (ENOSPC); - sc->ifp = ifp; - ifp->if_softc = sc; - - /* Check for task offload support. */ - ndis_probe_offload(sc); - - /* - * Get station address from the driver. - */ - len = sizeof(eaddr); - ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, eaddr, &len); - - if_initname(ifp, device_get_name(sc->ndis_dev), - device_get_unit(sc->ndis_dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = ndis_ifioctl; - ifp->if_start = ndis_ifstart; - ifp->if_init = ndis_init; - ifp->if_baudrate = 10000000; - IFQ_SET_MAXLEN(&ifp->if_snd, 50); - ifp->if_snd.ifq_drv_maxlen = 25; - IFQ_SET_READY(&ifp->if_snd); - ifp->if_capenable = ifp->if_capabilities; - ifp->if_hwassist = sc->ndis_hwassist; - - ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd, - ndis_ifmedia_sts); - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL); - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL); - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); - ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO); - ether_ifattach(ifp, eaddr); - - return (0); -} - -static struct ieee80211vap * -ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, - enum ieee80211_opmode opmode, int flags, - const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct ndis_vap *nvp; - struct ieee80211vap *vap; - - if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ - return NULL; - nvp = malloc(sizeof(struct ndis_vap), M_80211_VAP, M_WAITOK | M_ZERO); - vap = &nvp->vap; - ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); - /* override with driver methods */ - nvp->newstate = vap->iv_newstate; - vap->iv_newstate = ndis_newstate; - - /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status, - mac); - ic->ic_opmode = opmode; - /* install key handing routines */ - vap->iv_key_set = ndis_add_key; - vap->iv_key_delete = ndis_del_key; - return vap; -} - -static void -ndis_vap_delete(struct ieee80211vap *vap) -{ - struct ndis_vap *nvp = NDIS_VAP(vap); - struct ieee80211com *ic = vap->iv_ic; - struct ndis_softc *sc = ic->ic_softc; - - ndis_stop(sc); - callout_drain(&sc->ndis_scan_callout); - ieee80211_vap_detach(vap); - free(nvp, M_80211_VAP); -} - -/* - * Shutdown hardware and free up resources. This can be called any - * time after the mutex has been initialized. It is called in both - * the error case in attach and the normal detach case so it needs - * to be careful about only freeing resources that have actually been - * allocated. - */ -int -ndis_detach(device_t dev) -{ - struct ifnet *ifp; - struct ndis_softc *sc; - driver_object *drv; - - sc = device_get_softc(dev); - NDIS_LOCK(sc); - if (!sc->ndis_80211) - ifp = sc->ifp; - else - ifp = NULL; - if (ifp != NULL) - ifp->if_flags &= ~IFF_UP; - if (device_is_attached(dev)) { - NDIS_UNLOCK(sc); - ndis_stop(sc); - if (sc->ndis_80211) - ieee80211_ifdetach(&sc->ndis_ic); - else if (ifp != NULL) - ether_ifdetach(ifp); - } else - NDIS_UNLOCK(sc); - - if (sc->ndis_tickitem != NULL) - IoFreeWorkItem(sc->ndis_tickitem); - if (sc->ndis_startitem != NULL) - IoFreeWorkItem(sc->ndis_startitem); - if (sc->ndis_resetitem != NULL) - IoFreeWorkItem(sc->ndis_resetitem); - if (sc->ndis_inputitem != NULL) - IoFreeWorkItem(sc->ndis_inputitem); - if (sc->ndisusb_xferdoneitem != NULL) - IoFreeWorkItem(sc->ndisusb_xferdoneitem); - if (sc->ndisusb_taskitem != NULL) - IoFreeWorkItem(sc->ndisusb_taskitem); - - bus_generic_detach(dev); - ndis_unload_driver(sc); - - if (sc->ndis_irq) - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq); - if (sc->ndis_res_io) - bus_release_resource(dev, SYS_RES_IOPORT, - sc->ndis_io_rid, sc->ndis_res_io); - if (sc->ndis_res_mem) - bus_release_resource(dev, SYS_RES_MEMORY, - sc->ndis_mem_rid, sc->ndis_res_mem); - if (sc->ndis_res_altmem) - bus_release_resource(dev, SYS_RES_MEMORY, - sc->ndis_altmem_rid, sc->ndis_res_altmem); - - if (ifp != NULL) - if_free(ifp); - - if (sc->ndis_sc) - ndis_destroy_dma(sc); - - if (sc->ndis_txarray) - free(sc->ndis_txarray, M_DEVBUF); - - if (!sc->ndis_80211) - ifmedia_removeall(&sc->ifmedia); - - if (sc->ndis_txpool != NULL) - NdisFreePacketPool(sc->ndis_txpool); - - /* Destroy the PDO for this device. */ - - if (sc->ndis_iftype == PCIBus) - drv = windrv_lookup(0, "PCI Bus"); - else if (sc->ndis_iftype == PCMCIABus) - drv = windrv_lookup(0, "PCCARD Bus"); - else - drv = windrv_lookup(0, "USB Bus"); - if (drv == NULL) - panic("couldn't find driver object"); - windrv_destroy_pdo(drv, dev); - - if (sc->ndis_iftype == PCIBus) - bus_dma_tag_destroy(sc->ndis_parent_tag); - - return (0); -} - -int -ndis_suspend(dev) - device_t dev; -{ - struct ndis_softc *sc; - struct ifnet *ifp; - - sc = device_get_softc(dev); - ifp = sc->ifp; - -#ifdef notdef - if (NDIS_INITIALIZED(sc)) - ndis_stop(sc); -#endif - - return (0); -} - -int -ndis_resume(dev) - device_t dev; -{ - struct ndis_softc *sc; - struct ifnet *ifp; - - sc = device_get_softc(dev); - ifp = sc->ifp; - - if (NDIS_INITIALIZED(sc)) - ndis_init(sc); - - return (0); -} - -/* - * The following bunch of routines are here to support drivers that - * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism. - * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for - * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized - * miniports. - */ -static void -ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen) - ndis_handle adapter; - ndis_handle ctx; - char *addr; - void *hdr; - uint32_t hdrlen; - void *lookahead; - uint32_t lookaheadlen; - uint32_t pktlen; -{ - ndis_miniport_block *block; - uint8_t irql = 0; - uint32_t status; - ndis_buffer *b; - ndis_packet *p; - struct mbuf *m; - ndis_ethpriv *priv; - - block = adapter; - - m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); - if (m == NULL) - return; - - /* Save the data provided to us so far. */ - - m->m_len = lookaheadlen + hdrlen; - m->m_pkthdr.len = pktlen + hdrlen; - m->m_next = NULL; - m_copyback(m, 0, hdrlen, hdr); - m_copyback(m, hdrlen, lookaheadlen, lookahead); - - /* Now create a fake NDIS_PACKET to hold the data */ - - NdisAllocatePacket(&status, &p, block->nmb_rxpool); - - if (status != NDIS_STATUS_SUCCESS) { - m_freem(m); - return; - } - - p->np_m0 = m; - - b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL); - - if (b == NULL) { - NdisFreePacket(p); - m_freem(m); - return; - } - - p->np_private.npp_head = p->np_private.npp_tail = b; - p->np_private.npp_totlen = m->m_pkthdr.len; - - /* Save the packet RX context somewhere. */ - priv = (ndis_ethpriv *)&p->np_protocolreserved; - priv->nep_ctx = ctx; - - if (!NDIS_SERIALIZED(block)) - KeAcquireSpinLock(&block->nmb_lock, &irql); - - InsertTailList((&block->nmb_packetlist), (&p->np_list)); - - if (!NDIS_SERIALIZED(block)) - KeReleaseSpinLock(&block->nmb_lock, irql); -} - -/* - * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL - * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized - * miniports. - */ -static void -ndis_rxeof_done(adapter) - ndis_handle adapter; -{ - struct ndis_softc *sc; - ndis_miniport_block *block; - - block = adapter; - - /* Schedule transfer/RX of queued packets. */ - - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - - KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL); -} - -/* - * MiniportTransferData() handler, runs at DISPATCH_LEVEL. - */ -static void -ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2) - kdpc *dpc; - ndis_handle adapter; - void *sysarg1; - void *sysarg2; -{ - ndis_miniport_block *block; - struct ndis_softc *sc; - ndis_packet *p; - list_entry *l; - uint32_t status; - ndis_ethpriv *priv; - struct ifnet *ifp; - struct mbuf *m; - - block = adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - ifp = sc->ifp; - - KeAcquireSpinLockAtDpcLevel(&block->nmb_lock); - - l = block->nmb_packetlist.nle_flink; - while(!IsListEmpty(&block->nmb_packetlist)) { - l = RemoveHeadList((&block->nmb_packetlist)); - p = CONTAINING_RECORD(l, ndis_packet, np_list); - InitializeListHead((&p->np_list)); - - priv = (ndis_ethpriv *)&p->np_protocolreserved; - m = p->np_m0; - p->np_softc = sc; - p->np_m0 = NULL; - - KeReleaseSpinLockFromDpcLevel(&block->nmb_lock); - - status = MSCALL6(sc->ndis_chars->nmc_transferdata_func, - p, &p->np_private.npp_totlen, block, priv->nep_ctx, - m->m_len, m->m_pkthdr.len - m->m_len); - - KeAcquireSpinLockAtDpcLevel(&block->nmb_lock); - - /* - * If status is NDIS_STATUS_PENDING, do nothing and - * wait for a callback to the ndis_rxeof_xfr_done() - * handler. - */ - - m->m_len = m->m_pkthdr.len; - m->m_pkthdr.rcvif = ifp; - - if (status == NDIS_STATUS_SUCCESS) { - IoFreeMdl(p->np_private.npp_head); - NdisFreePacket(p); - KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock); - mbufq_enqueue(&sc->ndis_rxqueue, m); - KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock); - IoQueueWorkItem(sc->ndis_inputitem, - (io_workitem_func)ndis_inputtask_wrap, - WORKQUEUE_CRITICAL, sc); - } - - if (status == NDIS_STATUS_FAILURE) - m_freem(m); - - /* Advance to next packet */ - l = block->nmb_packetlist.nle_flink; - } - - KeReleaseSpinLockFromDpcLevel(&block->nmb_lock); -} - -/* - * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL. - */ -static void -ndis_rxeof_xfr_done(adapter, packet, status, len) - ndis_handle adapter; - ndis_packet *packet; - uint32_t status; - uint32_t len; -{ - ndis_miniport_block *block; - struct ndis_softc *sc; - struct ifnet *ifp; - struct mbuf *m; - - block = adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - ifp = sc->ifp; - - m = packet->np_m0; - IoFreeMdl(packet->np_private.npp_head); - NdisFreePacket(packet); - - if (status != NDIS_STATUS_SUCCESS) { - m_freem(m); - return; - } - - m->m_len = m->m_pkthdr.len; - m->m_pkthdr.rcvif = ifp; - KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock); - mbufq_enqueue(&sc->ndis_rxqueue, m); - KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock); - IoQueueWorkItem(sc->ndis_inputitem, - (io_workitem_func)ndis_inputtask_wrap, - WORKQUEUE_CRITICAL, sc); -} -/* - * A frame has been uploaded: pass the resulting mbuf chain up to - * the higher level protocols. - * - * When handling received NDIS packets, the 'status' field in the - * out-of-band portion of the ndis_packet has special meaning. In the - * most common case, the underlying NDIS driver will set this field - * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to - * take possession of it. We then change the status field to - * NDIS_STATUS_PENDING to tell the driver that we now own the packet, - * and that we will return it at some point in the future via the - * return packet handler. - * - * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES, - * this means the driver is running out of packet/buffer resources and - * wants to maintain ownership of the packet. In this case, we have to - * copy the packet data into local storage and let the driver keep the - * packet. - */ -static void -ndis_rxeof(adapter, packets, pktcnt) - ndis_handle adapter; - ndis_packet **packets; - uint32_t pktcnt; -{ - struct ndis_softc *sc; - ndis_miniport_block *block; - ndis_packet *p; - uint32_t s; - ndis_tcpip_csum *csum; - struct ifnet *ifp; - struct mbuf *m0, *m; - int i; - - block = (ndis_miniport_block *)adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - ifp = sc->ifp; - - /* - * There's a slim chance the driver may indicate some packets - * before we're completely ready to handle them. If we detect this, - * we need to return them to the miniport and ignore them. - */ - if (!sc->ndis_running) { - for (i = 0; i < pktcnt; i++) { - p = packets[i]; - if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) { - p->np_refcnt++; - ndis_return_packet(p); - } - } - return; - } - - for (i = 0; i < pktcnt; i++) { - p = packets[i]; - /* Stash the softc here so ptom can use it. */ - p->np_softc = sc; - if (ndis_ptom(&m0, p)) { - device_printf(sc->ndis_dev, "ptom failed\n"); - if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) - ndis_return_packet(p); - } else { -#ifdef notdef - if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) { - m = m_dup(m0, M_NOWAIT); - /* - * NOTE: we want to destroy the mbuf here, but - * we don't actually want to return it to the - * driver via the return packet handler. By - * bumping np_refcnt, we can prevent the - * ndis_return_packet() routine from actually - * doing anything. - */ - p->np_refcnt++; - m_freem(m0); - if (m == NULL) - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - else - m0 = m; - } else - p->np_oob.npo_status = NDIS_STATUS_PENDING; -#endif - m = m_dup(m0, M_NOWAIT); - if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) - p->np_refcnt++; - else - p->np_oob.npo_status = NDIS_STATUS_PENDING; - m_freem(m0); - if (m == NULL) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - continue; - } - m0 = m; - m0->m_pkthdr.rcvif = ifp; - - /* Deal with checksum offload. */ - - if (ifp->if_capenable & IFCAP_RXCSUM && - p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) { - s = (uintptr_t) - p->np_ext.npe_info[ndis_tcpipcsum_info]; - csum = (ndis_tcpip_csum *)&s; - if (csum->u.ntc_rxflags & - NDIS_RXCSUM_IP_PASSED) - m0->m_pkthdr.csum_flags |= - CSUM_IP_CHECKED|CSUM_IP_VALID; - if (csum->u.ntc_rxflags & - (NDIS_RXCSUM_TCP_PASSED | - NDIS_RXCSUM_UDP_PASSED)) { - m0->m_pkthdr.csum_flags |= - CSUM_DATA_VALID|CSUM_PSEUDO_HDR; - m0->m_pkthdr.csum_data = 0xFFFF; - } - } - - KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock); - mbufq_enqueue(&sc->ndis_rxqueue, m0); - KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock); - IoQueueWorkItem(sc->ndis_inputitem, - (io_workitem_func)ndis_inputtask_wrap, - WORKQUEUE_CRITICAL, sc); - } - } -} - -/* - * This routine is run at PASSIVE_LEVEL. We use this routine to pass - * packets into the stack in order to avoid calling (*ifp->if_input)() - * with any locks held (at DISPATCH_LEVEL, we'll be holding the - * 'dispatch level' per-cpu sleep lock). - */ -static void -ndis_inputtask(device_object *dobj, void *arg) -{ - ndis_miniport_block *block; - struct ndis_softc *sc = arg; - struct mbuf *m; - uint8_t irql; - - block = dobj->do_devext; - - KeAcquireSpinLock(&sc->ndis_rxlock, &irql); - while ((m = mbufq_dequeue(&sc->ndis_rxqueue)) != NULL) { - KeReleaseSpinLock(&sc->ndis_rxlock, irql); - if ((sc->ndis_80211 != 0)) { - struct ieee80211com *ic = &sc->ndis_ic; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - - if (vap != NULL) - vap->iv_deliver_data(vap, vap->iv_bss, m); - } else { - struct ifnet *ifp = sc->ifp; - - (*ifp->if_input)(ifp, m); - } - KeAcquireSpinLock(&sc->ndis_rxlock, &irql); - } - KeReleaseSpinLock(&sc->ndis_rxlock, irql); -} - -/* - * A frame was downloaded to the chip. It's safe for us to clean up - * the list buffers. - */ -static void -ndis_txeof(adapter, packet, status) - ndis_handle adapter; - ndis_packet *packet; - ndis_status status; - -{ - struct ndis_softc *sc; - ndis_miniport_block *block; - struct ifnet *ifp; - int idx; - struct mbuf *m; - - block = (ndis_miniport_block *)adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - ifp = sc->ifp; - - m = packet->np_m0; - idx = packet->np_txidx; - if (sc->ndis_sc) - bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]); - - ndis_free_packet(packet); - m_freem(m); - - NDIS_LOCK(sc); - sc->ndis_txarray[idx] = NULL; - sc->ndis_txpending++; - - if (!sc->ndis_80211) { - struct ifnet *ifp = sc->ifp; - if (status == NDIS_STATUS_SUCCESS) - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); - else - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - } - sc->ndis_tx_timer = 0; - - NDIS_UNLOCK(sc); - - if (!sc->ndis_80211) - IoQueueWorkItem(sc->ndis_startitem, - (io_workitem_func)ndis_ifstarttask_wrap, - WORKQUEUE_CRITICAL, sc); - DPRINTF(("%s: ndis_ifstarttask_wrap sc=%p\n", __func__, sc)); -} - -static void -ndis_linksts(adapter, status, sbuf, slen) - ndis_handle adapter; - ndis_status status; - void *sbuf; - uint32_t slen; -{ - ndis_miniport_block *block; - struct ndis_softc *sc; - - block = adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - sc->ndis_sts = status; - - /* Event list is all full up, drop this one. */ - - NDIS_LOCK(sc); - if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) { - NDIS_UNLOCK(sc); - return; - } - - /* Cache the event. */ - - if (slen) { - sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen, - M_TEMP, M_NOWAIT); - if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) { - NDIS_UNLOCK(sc); - return; - } - bcopy((char *)sbuf, - sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen); - } - sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status; - sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen; - NDIS_EVTINC(sc->ndis_evtpidx); - NDIS_UNLOCK(sc); -} - -static void -ndis_linksts_done(adapter) - ndis_handle adapter; -{ - ndis_miniport_block *block; - struct ndis_softc *sc; - struct ifnet *ifp; - - block = adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - ifp = sc->ifp; - - if (!NDIS_INITIALIZED(sc)) - return; - - switch (sc->ndis_sts) { - case NDIS_STATUS_MEDIA_CONNECT: - IoQueueWorkItem(sc->ndis_tickitem, - (io_workitem_func)ndis_ticktask_wrap, - WORKQUEUE_CRITICAL, sc); - if (!sc->ndis_80211) - IoQueueWorkItem(sc->ndis_startitem, - (io_workitem_func)ndis_ifstarttask_wrap, - WORKQUEUE_CRITICAL, sc); - break; - case NDIS_STATUS_MEDIA_DISCONNECT: - if (sc->ndis_link) - IoQueueWorkItem(sc->ndis_tickitem, - (io_workitem_func)ndis_ticktask_wrap, - WORKQUEUE_CRITICAL, sc); - break; - default: - break; - } -} - -static void -ndis_tick(xsc) - void *xsc; -{ - struct ndis_softc *sc; - - sc = xsc; - - if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) { - IoQueueWorkItem(sc->ndis_tickitem, - (io_workitem_func)ndis_ticktask_wrap, - WORKQUEUE_CRITICAL, sc); - sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs; - } - - if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) { - if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1); - device_printf(sc->ndis_dev, "watchdog timeout\n"); - - IoQueueWorkItem(sc->ndis_resetitem, - (io_workitem_func)ndis_resettask_wrap, - WORKQUEUE_CRITICAL, sc); - if (!sc->ndis_80211) - IoQueueWorkItem(sc->ndis_startitem, - (io_workitem_func)ndis_ifstarttask_wrap, - WORKQUEUE_CRITICAL, sc); - } - - callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc); -} - -static void -ndis_ticktask(device_object *d, void *xsc) -{ - struct ndis_softc *sc = xsc; - ndis_checkforhang_handler hangfunc; - uint8_t rval; - - NDIS_LOCK(sc); - if (!NDIS_INITIALIZED(sc)) { - NDIS_UNLOCK(sc); - return; - } - NDIS_UNLOCK(sc); - - hangfunc = sc->ndis_chars->nmc_checkhang_func; - - if (hangfunc != NULL) { - rval = MSCALL1(hangfunc, - sc->ndis_block->nmb_miniportadapterctx); - if (rval == TRUE) { - ndis_reset_nic(sc); - return; - } - } - - NDIS_LOCK(sc); - if (sc->ndis_link == 0 && - sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) { - sc->ndis_link = 1; - if (sc->ndis_80211 != 0) { - struct ieee80211com *ic = &sc->ndis_ic; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - - if (vap != NULL) { - NDIS_UNLOCK(sc); - ndis_getstate_80211(sc); - ieee80211_new_state(vap, IEEE80211_S_RUN, -1); - NDIS_LOCK(sc); - if_link_state_change(vap->iv_ifp, - LINK_STATE_UP); - } - } else - if_link_state_change(sc->ifp, LINK_STATE_UP); - } - - if (sc->ndis_link == 1 && - sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) { - sc->ndis_link = 0; - if (sc->ndis_80211 != 0) { - struct ieee80211com *ic = &sc->ndis_ic; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - - if (vap != NULL) { - NDIS_UNLOCK(sc); - ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); - NDIS_LOCK(sc); - if_link_state_change(vap->iv_ifp, - LINK_STATE_DOWN); - } - } else - if_link_state_change(sc->ifp, LINK_STATE_DOWN); - } - - NDIS_UNLOCK(sc); -} - -static void -ndis_map_sclist(arg, segs, nseg, mapsize, error) - void *arg; - bus_dma_segment_t *segs; - int nseg; - bus_size_t mapsize; - int error; - -{ - struct ndis_sc_list *sclist; - int i; - - if (error || arg == NULL) - return; - - sclist = arg; - - sclist->nsl_frags = nseg; - - for (i = 0; i < nseg; i++) { - sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr; - sclist->nsl_elements[i].nse_len = segs[i].ds_len; - } -} - -static int -ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, - const struct ieee80211_bpf_params *params) -{ - /* no support; just discard */ - m_freem(m); - ieee80211_free_node(ni); - return (0); -} - -static void -ndis_update_mcast(struct ieee80211com *ic) -{ - struct ndis_softc *sc = ic->ic_softc; - - ndis_setmulti(sc); -} - -static void -ndis_update_promisc(struct ieee80211com *ic) -{ - /* not supported */ -} - -static void -ndis_ifstarttask(device_object *d, void *arg) -{ - struct ndis_softc *sc = arg; - DPRINTF(("%s: sc=%p, ifp=%p\n", __func__, sc, sc->ifp)); - if (sc->ndis_80211) - return; - - struct ifnet *ifp = sc->ifp; - if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - ndis_ifstart(ifp); -} - -/* - * Main transmit routine. To make NDIS drivers happy, we need to - * transform mbuf chains into NDIS packets and feed them to the - * send packet routines. Most drivers allow you to send several - * packets at once (up to the maxpkts limit). Unfortunately, rather - * that accepting them in the form of a linked list, they expect - * a contiguous array of pointers to packets. - * - * For those drivers which use the NDIS scatter/gather DMA mechanism, - * we need to perform busdma work here. Those that use map registers - * will do the mapping themselves on a buffer by buffer basis. - */ -static void -ndis_ifstart(struct ifnet *ifp) -{ - struct ndis_softc *sc; - struct mbuf *m = NULL; - ndis_packet **p0 = NULL, *p = NULL; - ndis_tcpip_csum *csum; - int pcnt = 0, status; - - sc = ifp->if_softc; - - NDIS_LOCK(sc); - if (!sc->ndis_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) { - NDIS_UNLOCK(sc); - return; - } - - p0 = &sc->ndis_txarray[sc->ndis_txidx]; - - while(sc->ndis_txpending) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - - NdisAllocatePacket(&status, - &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool); - - if (status != NDIS_STATUS_SUCCESS) - break; - - if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) { - IFQ_DRV_PREPEND(&ifp->if_snd, m); - NDIS_UNLOCK(sc); - return; - } - - /* - * Save pointer to original mbuf - * so we can free it later. - */ - - p = sc->ndis_txarray[sc->ndis_txidx]; - p->np_txidx = sc->ndis_txidx; - p->np_m0 = m; - p->np_oob.npo_status = NDIS_STATUS_PENDING; - - /* - * Do scatter/gather processing, if driver requested it. - */ - if (sc->ndis_sc) { - bus_dmamap_load_mbuf(sc->ndis_ttag, - sc->ndis_tmaps[sc->ndis_txidx], m, - ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT); - bus_dmamap_sync(sc->ndis_ttag, - sc->ndis_tmaps[sc->ndis_txidx], - BUS_DMASYNC_PREREAD); - p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist; - } - - /* Handle checksum offload. */ - - if (ifp->if_capenable & IFCAP_TXCSUM && - m->m_pkthdr.csum_flags) { - csum = (ndis_tcpip_csum *) - &p->np_ext.npe_info[ndis_tcpipcsum_info]; - csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4; - if (m->m_pkthdr.csum_flags & CSUM_IP) - csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP; - if (m->m_pkthdr.csum_flags & CSUM_TCP) - csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP; - if (m->m_pkthdr.csum_flags & CSUM_UDP) - csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP; - p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP; - } - - NDIS_INC(sc); - sc->ndis_txpending--; - - pcnt++; - - /* - * If there's a BPF listener, bounce a copy of this frame - * to him. - */ - if (!sc->ndis_80211) /* XXX handle 80211 */ - BPF_MTAP(ifp, m); - - /* - * The array that p0 points to must appear contiguous, - * so we must not wrap past the end of sc->ndis_txarray[]. - * If it looks like we're about to wrap, break out here - * so the this batch of packets can be transmitted, then - * wait for txeof to ask us to send the rest. - */ - if (sc->ndis_txidx == 0) - break; - } - - if (pcnt == 0) { - NDIS_UNLOCK(sc); - return; - } - - if (sc->ndis_txpending == 0) - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - - /* - * Set a timeout in case the chip goes out to lunch. - */ - sc->ndis_tx_timer = 5; - - NDIS_UNLOCK(sc); - - /* - * According to NDIS documentation, if a driver exports - * a MiniportSendPackets() routine, we prefer that over - * a MiniportSend() routine (which sends just a single - * packet). - */ - if (sc->ndis_chars->nmc_sendmulti_func != NULL) - ndis_send_packets(sc, p0, pcnt); - else - ndis_send_packet(sc, p); - - return; -} - -static int -ndis_80211transmit(struct ieee80211com *ic, struct mbuf *m) -{ - struct ndis_softc *sc = ic->ic_softc; - ndis_packet **p0 = NULL, *p = NULL; - int status; - - NDIS_LOCK(sc); - if (!sc->ndis_link || !sc->ndis_running) { - NDIS_UNLOCK(sc); - return (ENXIO); - } - - if (sc->ndis_txpending == 0) { - NDIS_UNLOCK(sc); - return (ENOBUFS); - } - - p0 = &sc->ndis_txarray[sc->ndis_txidx]; - - NdisAllocatePacket(&status, - &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool); - - if (status != NDIS_STATUS_SUCCESS) { - NDIS_UNLOCK(sc); - return (ENOBUFS); - } - - if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) { - NDIS_UNLOCK(sc); - return (ENOBUFS); - } - - /* - * Save pointer to original mbuf - * so we can free it later. - */ - - p = sc->ndis_txarray[sc->ndis_txidx]; - p->np_txidx = sc->ndis_txidx; - p->np_m0 = m; - p->np_oob.npo_status = NDIS_STATUS_PENDING; - - /* - * Do scatter/gather processing, if driver requested it. - */ - if (sc->ndis_sc) { - bus_dmamap_load_mbuf(sc->ndis_ttag, - sc->ndis_tmaps[sc->ndis_txidx], m, - ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT); - bus_dmamap_sync(sc->ndis_ttag, - sc->ndis_tmaps[sc->ndis_txidx], - BUS_DMASYNC_PREREAD); - p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist; - } - - NDIS_INC(sc); - sc->ndis_txpending--; - - /* - * Set a timeout in case the chip goes out to lunch. - */ - sc->ndis_tx_timer = 5; - NDIS_UNLOCK(sc); - - /* - * According to NDIS documentation, if a driver exports - * a MiniportSendPackets() routine, we prefer that over - * a MiniportSend() routine (which sends just a single - * packet). - */ - if (sc->ndis_chars->nmc_sendmulti_func != NULL) - ndis_send_packets(sc, p0, 1); - else - ndis_send_packet(sc, p); - - return (0); -} - -static void -ndis_80211parent(struct ieee80211com *ic) -{ - struct ndis_softc *sc = ic->ic_softc; - - /*NDIS_LOCK(sc);*/ - if (ic->ic_nrunning > 0) { - if (!sc->ndis_running) - ndis_init(sc); - } else if (sc->ndis_running) - ndis_stop(sc); - /*NDIS_UNLOCK(sc);*/ -} - -static void -ndis_init(void *xsc) -{ - struct ndis_softc *sc = xsc; - int i, len, error; - - /* - * Avoid reintializing the link unnecessarily. - * This should be dealt with in a better way by - * fixing the upper layer modules so they don't - * call ifp->if_init() quite as often. - */ - if (sc->ndis_link) - return; - - /* - * Cancel pending I/O and free all RX/TX buffers. - */ - ndis_stop(sc); - - if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) { - error = ndis_init_nic(sc); - if (error != 0) { - device_printf(sc->ndis_dev, - "failed to initialize the device: %d\n", error); - return; - } - } - - /* Program the packet filter */ - sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED | - NDIS_PACKET_TYPE_BROADCAST; - - if (sc->ndis_80211) { - struct ieee80211com *ic = &sc->ndis_ic; - - if (ic->ic_promisc > 0) - sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; - } else { - struct ifnet *ifp = sc->ifp; - - if (ifp->if_flags & IFF_PROMISC) - sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; - } - - len = sizeof(sc->ndis_filter); - - error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER, - &sc->ndis_filter, &len); - - if (error) - device_printf(sc->ndis_dev, "set filter failed: %d\n", error); - - /* - * Set lookahead. - */ - if (sc->ndis_80211) - i = ETHERMTU; - else - i = sc->ifp->if_mtu; - len = sizeof(i); - ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len); - - /* - * Program the multicast filter, if necessary. - */ - ndis_setmulti(sc); - - /* Setup task offload. */ - ndis_set_offload(sc); - - NDIS_LOCK(sc); - - sc->ndis_txidx = 0; - sc->ndis_txpending = sc->ndis_maxpkts; - sc->ndis_link = 0; - - if (!sc->ndis_80211) { - if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN); - sc->ifp->if_drv_flags |= IFF_DRV_RUNNING; - sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - } - - sc->ndis_tx_timer = 0; - - /* - * Some drivers don't set this value. The NDIS spec says - * the default checkforhang timeout is "approximately 2 - * seconds." We use 3 seconds, because it seems for some - * drivers, exactly 2 seconds is too fast. - */ - if (sc->ndis_block->nmb_checkforhangsecs == 0) - sc->ndis_block->nmb_checkforhangsecs = 3; - - sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs; - callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc); - sc->ndis_running = 1; - NDIS_UNLOCK(sc); - - /* XXX force handling */ - if (sc->ndis_80211) - ieee80211_start_all(&sc->ndis_ic); /* start all vap's */ -} - -/* - * Set media options. - */ -static int -ndis_ifmedia_upd(ifp) - struct ifnet *ifp; -{ - struct ndis_softc *sc; - - sc = ifp->if_softc; - - if (NDIS_INITIALIZED(sc)) - ndis_init(sc); - - return (0); -} - -/* - * Report current media status. - */ -static void -ndis_ifmedia_sts(ifp, ifmr) - struct ifnet *ifp; - struct ifmediareq *ifmr; -{ - struct ndis_softc *sc; - uint32_t media_info; - ndis_media_state linkstate; - int len; - - ifmr->ifm_status = IFM_AVALID; - ifmr->ifm_active = IFM_ETHER; - sc = ifp->if_softc; - - if (!NDIS_INITIALIZED(sc)) - return; - - len = sizeof(linkstate); - ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS, - (void *)&linkstate, &len); - - len = sizeof(media_info); - ndis_get_info(sc, OID_GEN_LINK_SPEED, - (void *)&media_info, &len); - - if (linkstate == nmc_connected) - ifmr->ifm_status |= IFM_ACTIVE; - - switch (media_info) { - case 100000: - ifmr->ifm_active |= IFM_10_T; - break; - case 1000000: - ifmr->ifm_active |= IFM_100_TX; - break; - case 10000000: - ifmr->ifm_active |= IFM_1000_T; - break; - default: - device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info); - break; - } -} - -static int -ndis_set_cipher(struct ndis_softc *sc, int cipher) -{ - struct ieee80211com *ic = &sc->ndis_ic; - int rval = 0, len; - uint32_t arg, save; - - len = sizeof(arg); - - if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) { - if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP)) - return (ENOTSUP); - arg = NDIS_80211_WEPSTAT_ENC1ENABLED; - } - - if (cipher == WPA_CSE_TKIP) { - if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP)) - return (ENOTSUP); - arg = NDIS_80211_WEPSTAT_ENC2ENABLED; - } - - if (cipher == WPA_CSE_CCMP) { - if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM)) - return (ENOTSUP); - arg = NDIS_80211_WEPSTAT_ENC3ENABLED; - } - - DPRINTF(("Setting cipher to %d\n", arg)); - save = arg; - rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len); - - if (rval) - return (rval); - - /* Check that the cipher was set correctly. */ - - len = sizeof(save); - rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len); - - if (rval != 0 || arg != save) - return (ENODEV); - - return (0); -} - -/* - * WPA is hairy to set up. Do the work in a separate routine - * so we don't clutter the setstate function too much. - * Important yet undocumented fact: first we have to set the - * authentication mode, _then_ we enable the ciphers. If one - * of the WPA authentication modes isn't enabled, the driver - * might not permit the TKIP or AES ciphers to be selected. - */ -static int -ndis_set_wpa(sc, ie, ielen) - struct ndis_softc *sc; - void *ie; - int ielen; -{ - struct ieee80211_ie_wpa *w; - struct ndis_ie *n; - char *pos; - uint32_t arg; - int i; - - /* - * Apparently, the only way for us to know what ciphers - * and key management/authentication mode to use is for - * us to inspect the optional information element (IE) - * stored in the 802.11 state machine. This IE should be - * supplied by the WPA supplicant. - */ - - w = (struct ieee80211_ie_wpa *)ie; - - /* Check for the right kind of IE. */ - if (w->wpa_id != IEEE80211_ELEMID_VENDOR) { - DPRINTF(("Incorrect IE type %d\n", w->wpa_id)); - return (EINVAL); - } - - /* Skip over the ucast cipher OIDs. */ - pos = (char *)&w->wpa_uciphers[0]; - pos += w->wpa_uciphercnt * sizeof(struct ndis_ie); - - /* Skip over the authmode count. */ - pos += sizeof(u_int16_t); - - /* - * Check for the authentication modes. I'm - * pretty sure there's only supposed to be one. - */ - - n = (struct ndis_ie *)pos; - if (n->ni_val == WPA_ASE_NONE) - arg = NDIS_80211_AUTHMODE_WPANONE; - - if (n->ni_val == WPA_ASE_8021X_UNSPEC) - arg = NDIS_80211_AUTHMODE_WPA; - - if (n->ni_val == WPA_ASE_8021X_PSK) - arg = NDIS_80211_AUTHMODE_WPAPSK; - - DPRINTF(("Setting WPA auth mode to %d\n", arg)); - i = sizeof(arg); - if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i)) - return (ENOTSUP); - i = sizeof(arg); - ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i); - - /* Now configure the desired ciphers. */ - - /* First, set up the multicast group cipher. */ - n = (struct ndis_ie *)&w->wpa_mcipher[0]; - - if (ndis_set_cipher(sc, n->ni_val)) - return (ENOTSUP); - - /* Now start looking around for the unicast ciphers. */ - pos = (char *)&w->wpa_uciphers[0]; - n = (struct ndis_ie *)pos; - - for (i = 0; i < w->wpa_uciphercnt; i++) { - if (ndis_set_cipher(sc, n->ni_val)) - return (ENOTSUP); - n++; - } - - return (0); -} - -static void -ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr) -{ - struct ieee80211vap *vap = ifp->if_softc; - struct ndis_softc *sc = vap->iv_ic->ic_softc; - uint32_t txrate; - int len; - - if (!NDIS_INITIALIZED(sc)) - return; - - len = sizeof(txrate); - if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0) - vap->iv_bss->ni_txrate = txrate / 5000; - ieee80211_media_status(ifp, imr); -} - -static void -ndis_setstate_80211(struct ndis_softc *sc) -{ - struct ieee80211com *ic = &sc->ndis_ic; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - ndis_80211_macaddr bssid; - ndis_80211_config config; - int rval = 0, len; - uint32_t arg; - - if (!NDIS_INITIALIZED(sc)) { - DPRINTF(("%s: NDIS not initialized\n", __func__)); - return; - } - - /* Disassociate and turn off radio. */ - len = sizeof(arg); - arg = 1; - ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len); - - /* Set network infrastructure mode. */ - - len = sizeof(arg); - if (ic->ic_opmode == IEEE80211_M_IBSS) - arg = NDIS_80211_NET_INFRA_IBSS; - else - arg = NDIS_80211_NET_INFRA_BSS; - - rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len); - - if (rval) - device_printf (sc->ndis_dev, "set infra failed: %d\n", rval); - - /* Set power management */ - len = sizeof(arg); - if (vap->iv_flags & IEEE80211_F_PMGTON) - arg = NDIS_80211_POWERMODE_FAST_PSP; - else - arg = NDIS_80211_POWERMODE_CAM; - ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len); - - /* Set TX power */ - if ((ic->ic_caps & IEEE80211_C_TXPMGT) && - ic->ic_txpowlimit < nitems(dBm2mW)) { - arg = dBm2mW[ic->ic_txpowlimit]; - len = sizeof(arg); - ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len); - } - - /* - * Default encryption mode to off, authentication - * to open and privacy to 'accept everything.' - */ - len = sizeof(arg); - arg = NDIS_80211_WEPSTAT_DISABLED; - ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len); - - len = sizeof(arg); - arg = NDIS_80211_AUTHMODE_OPEN; - ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len); - - /* - * Note that OID_802_11_PRIVACY_FILTER is optional: - * not all drivers implement it. - */ - len = sizeof(arg); - arg = NDIS_80211_PRIVFILT_8021XWEP; - ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len); - - len = sizeof(config); - bzero((char *)&config, len); - config.nc_length = len; - config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh); - rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len); - - /* - * Some drivers expect us to initialize these values, so - * provide some defaults. - */ - - if (config.nc_beaconperiod == 0) - config.nc_beaconperiod = 100; - if (config.nc_atimwin == 0) - config.nc_atimwin = 100; - if (config.nc_fhconfig.ncf_dwelltime == 0) - config.nc_fhconfig.ncf_dwelltime = 200; - if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) { - int chan, chanflag; - - chan = ieee80211_chan2ieee(ic, ic->ic_bsschan); - chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ : - IEEE80211_CHAN_5GHZ; - if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) { - config.nc_dsconfig = - ic->ic_bsschan->ic_freq * 1000; - len = sizeof(config); - config.nc_length = len; - config.nc_fhconfig.ncf_length = - sizeof(ndis_80211_config_fh); - DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig)); - rval = ndis_set_info(sc, OID_802_11_CONFIGURATION, - &config, &len); - if (rval) - device_printf(sc->ndis_dev, "couldn't change " - "DS config to %ukHz: %d\n", - config.nc_dsconfig, rval); - } - } else if (rval) - device_printf(sc->ndis_dev, "couldn't retrieve " - "channel info: %d\n", rval); - - /* Set the BSSID to our value so the driver doesn't associate */ - len = IEEE80211_ADDR_LEN; - bcopy(vap->iv_myaddr, bssid, len); - DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":")); - rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len); - if (rval) - device_printf(sc->ndis_dev, - "setting BSSID failed: %d\n", rval); -} - -static void -ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap) -{ - struct ieee80211_node *ni = vap->iv_bss; - ndis_80211_ssid ssid; - ndis_80211_macaddr bssid; - ndis_80211_wep wep; - int i, rval = 0, len, error; - uint32_t arg; - - if (!NDIS_INITIALIZED(sc)) { - DPRINTF(("%s: NDIS not initialized\n", __func__)); - return; - } - - /* Initial setup */ - ndis_setstate_80211(sc); - - /* Set network infrastructure mode. */ - - len = sizeof(arg); - if (vap->iv_opmode == IEEE80211_M_IBSS) - arg = NDIS_80211_NET_INFRA_IBSS; - else - arg = NDIS_80211_NET_INFRA_BSS; - - rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len); - - if (rval) - device_printf (sc->ndis_dev, "set infra failed: %d\n", rval); - - /* Set RTS threshold */ - - len = sizeof(arg); - arg = vap->iv_rtsthreshold; - ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len); - - /* Set fragmentation threshold */ - - len = sizeof(arg); - arg = vap->iv_fragthreshold; - ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len); - - /* Set WEP */ - - if (vap->iv_flags & IEEE80211_F_PRIVACY && - !(vap->iv_flags & IEEE80211_F_WPA)) { - int keys_set = 0; - - if (ni->ni_authmode == IEEE80211_AUTH_SHARED) { - len = sizeof(arg); - arg = NDIS_80211_AUTHMODE_SHARED; - DPRINTF(("Setting shared auth\n")); - ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, - &arg, &len); - } - for (i = 0; i < IEEE80211_WEP_NKID; i++) { - if (vap->iv_nw_keys[i].wk_keylen) { - if (vap->iv_nw_keys[i].wk_cipher->ic_cipher != - IEEE80211_CIPHER_WEP) - continue; - bzero((char *)&wep, sizeof(wep)); - wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen; - - /* - * 5, 13 and 16 are the only valid - * key lengths. Anything in between - * will be zero padded out to the - * next highest boundary. - */ - if (vap->iv_nw_keys[i].wk_keylen < 5) - wep.nw_keylen = 5; - else if (vap->iv_nw_keys[i].wk_keylen > 5 && - vap->iv_nw_keys[i].wk_keylen < 13) - wep.nw_keylen = 13; - else if (vap->iv_nw_keys[i].wk_keylen > 13 && - vap->iv_nw_keys[i].wk_keylen < 16) - wep.nw_keylen = 16; - - wep.nw_keyidx = i; - wep.nw_length = (sizeof(uint32_t) * 3) - + wep.nw_keylen; - if (i == vap->iv_def_txkey) - wep.nw_keyidx |= NDIS_80211_WEPKEY_TX; - bcopy(vap->iv_nw_keys[i].wk_key, - wep.nw_keydata, wep.nw_length); - len = sizeof(wep); - DPRINTF(("Setting WEP key %d\n", i)); - rval = ndis_set_info(sc, - OID_802_11_ADD_WEP, &wep, &len); - if (rval) - device_printf(sc->ndis_dev, - "set wepkey failed: %d\n", rval); - keys_set++; - } - } - if (keys_set) { - DPRINTF(("Setting WEP on\n")); - arg = NDIS_80211_WEPSTAT_ENABLED; - len = sizeof(arg); - rval = ndis_set_info(sc, - OID_802_11_WEP_STATUS, &arg, &len); - if (rval) - device_printf(sc->ndis_dev, - "enable WEP failed: %d\n", rval); - if (vap->iv_flags & IEEE80211_F_DROPUNENC) - arg = NDIS_80211_PRIVFILT_8021XWEP; - else - arg = NDIS_80211_PRIVFILT_ACCEPTALL; - - len = sizeof(arg); - ndis_set_info(sc, - OID_802_11_PRIVACY_FILTER, &arg, &len); - } - } - - /* Set up WPA. */ - if ((vap->iv_flags & IEEE80211_F_WPA) && - vap->iv_appie_assocreq != NULL) { - struct ieee80211_appie *ie = vap->iv_appie_assocreq; - error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len); - if (error != 0) - device_printf(sc->ndis_dev, "WPA setup failed\n"); - } - -#ifdef notyet - /* Set network type. */ - - arg = 0; - - switch (vap->iv_curmode) { - case IEEE80211_MODE_11A: - arg = NDIS_80211_NETTYPE_11OFDM5; - break; - case IEEE80211_MODE_11B: - arg = NDIS_80211_NETTYPE_11DS; - break; - case IEEE80211_MODE_11G: - arg = NDIS_80211_NETTYPE_11OFDM24; - break; - default: - device_printf(sc->ndis_dev, "unknown mode: %d\n", - vap->iv_curmode); - } - - if (arg) { - DPRINTF(("Setting network type to %d\n", arg)); - len = sizeof(arg); - rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE, - &arg, &len); - if (rval) - device_printf(sc->ndis_dev, - "set nettype failed: %d\n", rval); - } -#endif - - /* - * If the user selected a specific BSSID, try - * to use that one. This is useful in the case where - * there are several APs in range with the same network - * name. To delete the BSSID, we use the broadcast - * address as the BSSID. - * Note that some drivers seem to allow setting a BSSID - * in ad-hoc mode, which has the effect of forcing the - * NIC to create an ad-hoc cell with a specific BSSID, - * instead of a randomly chosen one. However, the net80211 - * code makes the assumtion that the BSSID setting is invalid - * when you're in ad-hoc mode, so we don't allow that here. - */ - - len = IEEE80211_ADDR_LEN; - if (vap->iv_flags & IEEE80211_F_DESBSSID && - vap->iv_opmode != IEEE80211_M_IBSS) - bcopy(ni->ni_bssid, bssid, len); - else - bcopy(ieee80211broadcastaddr, bssid, len); - - DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":")); - rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len); - if (rval) - device_printf(sc->ndis_dev, - "setting BSSID failed: %d\n", rval); - - /* Set SSID -- always do this last. */ - -#ifdef NDIS_DEBUG - if (ndis_debug > 0) { - printf("Setting ESSID to "); - ieee80211_print_essid(ni->ni_essid, ni->ni_esslen); - printf("\n"); - } -#endif - - len = sizeof(ssid); - bzero((char *)&ssid, len); - ssid.ns_ssidlen = ni->ni_esslen; - if (ssid.ns_ssidlen == 0) { - ssid.ns_ssidlen = 1; - } else - bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen); - - rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len); - - if (rval) - device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval); - - return; -} - -static int -ndis_get_bssid_list(sc, bl) - struct ndis_softc *sc; - ndis_80211_bssid_list_ex **bl; -{ - int len, error; - - len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16); - *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO); - if (*bl == NULL) - return (ENOMEM); - - error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len); - if (error == ENOSPC) { - free(*bl, M_DEVBUF); - *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO); - if (*bl == NULL) - return (ENOMEM); - - error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len); - } - if (error) { - DPRINTF(("%s: failed to read\n", __func__)); - free(*bl, M_DEVBUF); - return (error); - } - - return (0); -} - -static int -ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc) -{ - struct ieee80211com *ic = &sc->ndis_ic; - struct ieee80211vap *vap; - struct ieee80211_node *ni; - ndis_80211_bssid_list_ex *bl; - ndis_wlan_bssid_ex *bs; - ndis_80211_macaddr bssid; - int i, len, error; - - if (!sc->ndis_link) - return (ENOENT); - - len = sizeof(bssid); - error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len); - if (error) { - device_printf(sc->ndis_dev, "failed to get bssid\n"); - return (ENOENT); - } - - vap = TAILQ_FIRST(&ic->ic_vaps); - ni = vap->iv_bss; - - error = ndis_get_bssid_list(sc, &bl); - if (error) - return (error); - - bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0]; - for (i = 0; i < bl->nblx_items; i++) { - if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) { - *assoc = malloc(bs->nwbx_len, M_TEMP, M_NOWAIT); - if (*assoc == NULL) { - free(bl, M_TEMP); - return (ENOMEM); - } - bcopy((char *)bs, (char *)*assoc, bs->nwbx_len); - free(bl, M_TEMP); - if (ic->ic_opmode == IEEE80211_M_STA) - ni->ni_associd = 1 | 0xc000; /* fake associd */ - return (0); - } - bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len); - } - - free(bl, M_TEMP); - return (ENOENT); -} - -static void -ndis_getstate_80211(struct ndis_softc *sc) -{ - struct ieee80211com *ic = &sc->ndis_ic; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct ieee80211_node *ni = vap->iv_bss; - ndis_wlan_bssid_ex *bs; - int rval, len, i = 0; - int chanflag; - uint32_t arg; - - if (!NDIS_INITIALIZED(sc)) - return; - - if ((rval = ndis_get_assoc(sc, &bs)) != 0) - return; - - /* We're associated, retrieve info on the current bssid. */ - ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype); - chanflag = ndis_nettype_chan(bs->nwbx_nettype); - IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr); - - /* Get SSID from current association info. */ - bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid, - bs->nwbx_ssid.ns_ssidlen); - ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen; - - if (ic->ic_caps & IEEE80211_C_PMGT) { - len = sizeof(arg); - rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len); - - if (rval) - device_printf(sc->ndis_dev, - "get power mode failed: %d\n", rval); - if (arg == NDIS_80211_POWERMODE_CAM) - vap->iv_flags &= ~IEEE80211_F_PMGTON; - else - vap->iv_flags |= IEEE80211_F_PMGTON; - } - - /* Get TX power */ - if (ic->ic_caps & IEEE80211_C_TXPMGT) { - len = sizeof(arg); - ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len); - for (i = 0; i < nitems(dBm2mW); i++) - if (dBm2mW[i] >= arg) - break; - ic->ic_txpowlimit = i; - } - - /* - * Use the current association information to reflect - * what channel we're on. - */ - ic->ic_curchan = ieee80211_find_channel(ic, - bs->nwbx_config.nc_dsconfig / 1000, chanflag); - if (ic->ic_curchan == NULL) - ic->ic_curchan = &ic->ic_channels[0]; - ni->ni_chan = ic->ic_curchan; - ic->ic_bsschan = ic->ic_curchan; - - free(bs, M_TEMP); - - /* - * Determine current authentication mode. - */ - len = sizeof(arg); - rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len); - if (rval) - device_printf(sc->ndis_dev, - "get authmode status failed: %d\n", rval); - else { - vap->iv_flags &= ~IEEE80211_F_WPA; - switch (arg) { - case NDIS_80211_AUTHMODE_OPEN: - ni->ni_authmode = IEEE80211_AUTH_OPEN; - break; - case NDIS_80211_AUTHMODE_SHARED: - ni->ni_authmode = IEEE80211_AUTH_SHARED; - break; - case NDIS_80211_AUTHMODE_AUTO: - ni->ni_authmode = IEEE80211_AUTH_AUTO; - break; - case NDIS_80211_AUTHMODE_WPA: - case NDIS_80211_AUTHMODE_WPAPSK: - case NDIS_80211_AUTHMODE_WPANONE: - ni->ni_authmode = IEEE80211_AUTH_WPA; - vap->iv_flags |= IEEE80211_F_WPA1; - break; - case NDIS_80211_AUTHMODE_WPA2: - case NDIS_80211_AUTHMODE_WPA2PSK: - ni->ni_authmode = IEEE80211_AUTH_WPA; - vap->iv_flags |= IEEE80211_F_WPA2; - break; - default: - ni->ni_authmode = IEEE80211_AUTH_NONE; - break; - } - } - - len = sizeof(arg); - rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len); - - if (rval) - device_printf(sc->ndis_dev, - "get wep status failed: %d\n", rval); - - if (arg == NDIS_80211_WEPSTAT_ENABLED) - vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC; - else - vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC); -} - -static int -ndis_ifioctl(ifp, command, data) - struct ifnet *ifp; - u_long command; - caddr_t data; -{ - struct ndis_softc *sc = ifp->if_softc; - struct ifreq *ifr = (struct ifreq *) data; - int i, error = 0; - - /*NDIS_LOCK(sc);*/ - - switch (command) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (sc->ndis_running && - ifp->if_flags & IFF_PROMISC && - !(sc->ndis_if_flags & IFF_PROMISC)) { - sc->ndis_filter |= - NDIS_PACKET_TYPE_PROMISCUOUS; - i = sizeof(sc->ndis_filter); - error = ndis_set_info(sc, - OID_GEN_CURRENT_PACKET_FILTER, - &sc->ndis_filter, &i); - } else if (sc->ndis_running && - !(ifp->if_flags & IFF_PROMISC) && - sc->ndis_if_flags & IFF_PROMISC) { - sc->ndis_filter &= - ~NDIS_PACKET_TYPE_PROMISCUOUS; - i = sizeof(sc->ndis_filter); - error = ndis_set_info(sc, - OID_GEN_CURRENT_PACKET_FILTER, - &sc->ndis_filter, &i); - } else - ndis_init(sc); - } else { - if (sc->ndis_running) - ndis_stop(sc); - } - sc->ndis_if_flags = ifp->if_flags; - error = 0; - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - ndis_setmulti(sc); - error = 0; - break; - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command); - break; - case SIOCSIFCAP: - ifp->if_capenable = ifr->ifr_reqcap; - if (ifp->if_capenable & IFCAP_TXCSUM) - ifp->if_hwassist = sc->ndis_hwassist; - else - ifp->if_hwassist = 0; - ndis_set_offload(sc); - break; - default: - error = ether_ioctl(ifp, command, data); - break; - } - - /*NDIS_UNLOCK(sc);*/ - - return(error); -} - -static int -ndis_80211ioctl(struct ieee80211com *ic, u_long cmd, void *data) -{ - struct ndis_softc *sc = ic->ic_softc; - struct ifreq *ifr = data; - struct ndis_oid_data oid; - struct ndis_evt evt; - void *oidbuf = NULL; - int error = 0; - - if ((error = priv_check(curthread, PRIV_DRIVER)) != 0) - return (error); - - switch (cmd) { - case SIOCGDRVSPEC: - case SIOCSDRVSPEC: - error = copyin(ifr_data_get_ptr(ifr), &oid, sizeof(oid)); - if (error) - break; - oidbuf = malloc(oid.len, M_TEMP, M_WAITOK | M_ZERO); - error = copyin((caddr_t)ifr_data_get_ptr(ifr) + sizeof(oid), - oidbuf, oid.len); - } - - if (error) { - free(oidbuf, M_TEMP); - return (error); - } - - switch (cmd) { - case SIOCGDRVSPEC: - error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len); - break; - case SIOCSDRVSPEC: - error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len); - break; - case SIOCGPRIVATE_0: - NDIS_LOCK(sc); - if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) { - error = ENOENT; - NDIS_UNLOCK(sc); - break; - } - error = copyin(ifr_data_get_ptr(ifr), &evt, sizeof(evt)); - if (error) { - NDIS_UNLOCK(sc); - break; - } - if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) { - error = ENOSPC; - NDIS_UNLOCK(sc); - break; - } - error = copyout(&sc->ndis_evt[sc->ndis_evtcidx], - ifr_data_get_ptr(ifr), sizeof(uint32_t) * 2); - if (error) { - NDIS_UNLOCK(sc); - break; - } - if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) { - error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, - (caddr_t)ifr_data_get_ptr(ifr) + - (sizeof(uint32_t) * 2), - sc->ndis_evt[sc->ndis_evtcidx].ne_len); - if (error) { - NDIS_UNLOCK(sc); - break; - } - free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP); - sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL; - } - sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0; - sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0; - NDIS_EVTINC(sc->ndis_evtcidx); - NDIS_UNLOCK(sc); - break; - default: - error = ENOTTY; - break; - } - - switch (cmd) { - case SIOCGDRVSPEC: - case SIOCSDRVSPEC: - error = copyout(&oid, ifr_data_get_ptr(ifr), sizeof(oid)); - if (error) - break; - error = copyout(oidbuf, - (caddr_t)ifr_data_get_ptr(ifr) + sizeof(oid), oid.len); - } - - free(oidbuf, M_TEMP); - - return (error); -} - -int -ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key) -{ - struct ndis_softc *sc = vap->iv_ic->ic_softc; - ndis_80211_key rkey; - int len, error = 0; - - bzero((char *)&rkey, sizeof(rkey)); - len = sizeof(rkey); - - rkey.nk_len = len; - rkey.nk_keyidx = key->wk_keyix; - - bcopy(vap->iv_ifp->if_broadcastaddr, - rkey.nk_bssid, IEEE80211_ADDR_LEN); - - error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len); - - if (error) - return (0); - - return (1); -} - -/* - * In theory this could be called for any key, but we'll - * only use it for WPA TKIP or AES keys. These need to be - * set after initial authentication with the AP. - */ -static int -ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key) -{ - struct ndis_softc *sc = vap->iv_ic->ic_softc; - ndis_80211_key rkey; - int len, error = 0; - - switch (key->wk_cipher->ic_cipher) { - case IEEE80211_CIPHER_TKIP: - - len = sizeof(ndis_80211_key); - bzero((char *)&rkey, sizeof(rkey)); - - rkey.nk_len = len; - rkey.nk_keylen = key->wk_keylen; - - if (key->wk_flags & IEEE80211_KEY_SWMIC) - rkey.nk_keylen += 16; - - /* key index - gets weird in NDIS */ - - if (key->wk_keyix != IEEE80211_KEYIX_NONE) - rkey.nk_keyidx = key->wk_keyix; - else - rkey.nk_keyidx = 0; - - if (key->wk_flags & IEEE80211_KEY_XMIT) - rkey.nk_keyidx |= 1 << 31; - - if (key->wk_flags & IEEE80211_KEY_GROUP) { - bcopy(ieee80211broadcastaddr, - rkey.nk_bssid, IEEE80211_ADDR_LEN); - } else { - bcopy(vap->iv_bss->ni_bssid, - rkey.nk_bssid, IEEE80211_ADDR_LEN); - /* pairwise key */ - rkey.nk_keyidx |= 1 << 30; - } - - /* need to set bit 29 based on keyrsc */ - rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */ - - if (rkey.nk_keyrsc) - rkey.nk_keyidx |= 1 << 29; - - if (key->wk_flags & IEEE80211_KEY_SWMIC) { - bcopy(key->wk_key, rkey.nk_keydata, 16); - bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8); - bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8); - } else - bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen); - - error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len); - break; - case IEEE80211_CIPHER_WEP: - error = 0; - break; - /* - * I don't know how to set up keys for the AES - * cipher yet. Is it the same as TKIP? - */ - case IEEE80211_CIPHER_AES_CCM: - default: - error = ENOTTY; - break; - } - - /* We need to return 1 for success, 0 for failure. */ - - if (error) - return (0); - - return (1); -} - -static void -ndis_resettask(d, arg) - device_object *d; - void *arg; -{ - struct ndis_softc *sc; - - sc = arg; - ndis_reset_nic(sc); -} - -/* - * Stop the adapter and free any mbufs allocated to the - * RX and TX lists. - */ -static void -ndis_stop(struct ndis_softc *sc) -{ - int i; - - callout_drain(&sc->ndis_stat_callout); - - NDIS_LOCK(sc); - sc->ndis_tx_timer = 0; - sc->ndis_link = 0; - if (!sc->ndis_80211) - sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - sc->ndis_running = 0; - NDIS_UNLOCK(sc); - - if (sc->ndis_iftype != PNPBus || - (sc->ndis_iftype == PNPBus && - !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) && - ndisusb_halt != 0)) - ndis_halt_nic(sc); - - NDIS_LOCK(sc); - for (i = 0; i < NDIS_EVENTS; i++) { - if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) { - free(sc->ndis_evt[i].ne_buf, M_TEMP); - sc->ndis_evt[i].ne_buf = NULL; - } - sc->ndis_evt[i].ne_sts = 0; - sc->ndis_evt[i].ne_len = 0; - } - sc->ndis_evtcidx = 0; - sc->ndis_evtpidx = 0; - NDIS_UNLOCK(sc); -} - -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ -void -ndis_shutdown(dev) - device_t dev; -{ - struct ndis_softc *sc; - - sc = device_get_softc(dev); - ndis_stop(sc); -} - -static int -ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) -{ - struct ndis_vap *nvp = NDIS_VAP(vap); - struct ieee80211com *ic = vap->iv_ic; - struct ndis_softc *sc = ic->ic_softc; - enum ieee80211_state ostate; - - DPRINTF(("%s: %s -> %s\n", __func__, - ieee80211_state_name[vap->iv_state], - ieee80211_state_name[nstate])); - - ostate = vap->iv_state; - vap->iv_state = nstate; - - switch (nstate) { - /* pass on to net80211 */ - case IEEE80211_S_INIT: - case IEEE80211_S_SCAN: - return nvp->newstate(vap, nstate, arg); - case IEEE80211_S_ASSOC: - if (ostate != IEEE80211_S_AUTH) { - IEEE80211_UNLOCK(ic); - ndis_auth_and_assoc(sc, vap); - IEEE80211_LOCK(ic); - } - break; - case IEEE80211_S_AUTH: - IEEE80211_UNLOCK(ic); - ndis_auth_and_assoc(sc, vap); - if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */ - ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0); - IEEE80211_LOCK(ic); - break; - default: - break; - } - return (0); -} - -static void -ndis_scan(void *arg) -{ - struct ieee80211vap *vap = arg; - - ieee80211_scan_done(vap); -} - -static void -ndis_scan_results(struct ndis_softc *sc) -{ - struct ieee80211com *ic = &sc->ndis_ic; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - ndis_80211_bssid_list_ex *bl; - ndis_wlan_bssid_ex *wb; - struct ieee80211_scanparams sp; - struct ieee80211_frame wh; - struct ieee80211_channel *saved_chan; - int i, j; - int rssi, noise, freq, chanflag; - uint8_t ssid[2+IEEE80211_NWID_LEN]; - uint8_t rates[2+IEEE80211_RATE_MAXSIZE]; - uint8_t *frm, *efrm; - - saved_chan = ic->ic_curchan; - noise = -96; - - if (ndis_get_bssid_list(sc, &bl)) - return; - - DPRINTF(("%s: %d results\n", __func__, bl->nblx_items)); - wb = &bl->nblx_bssid[0]; - for (i = 0; i < bl->nblx_items; i++) { - memset(&sp, 0, sizeof(sp)); - - memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2)); - memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3)); - rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise); - rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */ - if (wb->nwbx_privacy) - sp.capinfo |= IEEE80211_CAPINFO_PRIVACY; - sp.bintval = wb->nwbx_config.nc_beaconperiod; - switch (wb->nwbx_netinfra) { - case NDIS_80211_NET_INFRA_IBSS: - sp.capinfo |= IEEE80211_CAPINFO_IBSS; - break; - case NDIS_80211_NET_INFRA_BSS: - sp.capinfo |= IEEE80211_CAPINFO_ESS; - break; - } - sp.rates = &rates[0]; - for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) { - /* XXX - check units */ - if (wb->nwbx_supportedrates[j] == 0) - break; - rates[2 + j] = - wb->nwbx_supportedrates[j] & 0x7f; - } - rates[1] = j; - sp.ssid = (uint8_t *)&ssid[0]; - memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid, - wb->nwbx_ssid.ns_ssidlen); - sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen; - - chanflag = ndis_nettype_chan(wb->nwbx_nettype); - freq = wb->nwbx_config.nc_dsconfig / 1000; - sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag); - /* Hack ic->ic_curchan to be in sync with the scan result */ - ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag); - if (ic->ic_curchan == NULL) - ic->ic_curchan = &ic->ic_channels[0]; - - /* Process extended info from AP */ - if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) { - frm = (uint8_t *)&wb->nwbx_ies; - efrm = frm + wb->nwbx_ielen; - if (efrm - frm < 12) - goto done; - sp.tstamp = frm; frm += 8; - sp.bintval = le16toh(*(uint16_t *)frm); frm += 2; - sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2; - sp.ies = frm; - sp.ies_len = efrm - frm; - } -done: - DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n", - ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag, - rssi)); - ieee80211_add_scan(vap, ic->ic_curchan, &sp, &wh, 0, rssi, noise); - wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len); - } - free(bl, M_DEVBUF); - /* Restore the channel after messing with it */ - ic->ic_curchan = saved_chan; -} - -static void -ndis_scan_start(struct ieee80211com *ic) -{ - struct ndis_softc *sc = ic->ic_softc; - struct ieee80211vap *vap; - struct ieee80211_scan_state *ss; - ndis_80211_ssid ssid; - int error, len; - - ss = ic->ic_scan; - vap = TAILQ_FIRST(&ic->ic_vaps); - - if (!NDIS_INITIALIZED(sc)) { - DPRINTF(("%s: scan aborted\n", __func__)); - ieee80211_cancel_scan(vap); - return; - } - - len = sizeof(ssid); - bzero((char *)&ssid, len); - if (ss->ss_nssid == 0) - ssid.ns_ssidlen = 1; - else { - /* Perform a directed scan */ - ssid.ns_ssidlen = ss->ss_ssid[0].len; - bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen); - } - - error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len); - if (error) - DPRINTF(("%s: set ESSID failed\n", __func__)); - - len = 0; - error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len); - if (error) { - DPRINTF(("%s: scan command failed\n", __func__)); - ieee80211_cancel_scan(vap); - return; - } - /* Set a timer to collect the results */ - callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap); -} - -static void -ndis_set_channel(struct ieee80211com *ic) -{ - /* ignore */ -} - -static void -ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell) -{ - /* ignore */ -} - -static void -ndis_scan_mindwell(struct ieee80211_scan_state *ss) -{ - /* NB: don't try to abort scan; wait for firmware to finish */ -} - -static void -ndis_scan_end(struct ieee80211com *ic) -{ - struct ndis_softc *sc = ic->ic_softc; - - ndis_scan_results(sc); -} diff --git a/sys/dev/if_ndis/if_ndis_pci.c b/sys/dev/if_ndis/if_ndis_pci.c deleted file mode 100644 index cf1685a920ea..000000000000 --- a/sys/dev/if_ndis/if_ndis_pci.c +++ /dev/null @@ -1,357 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul <wpaul@windriver.com>. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/socket.h> -#include <sys/queue.h> -#include <sys/sysctl.h> - -#include <net/if.h> -#include <net/if_var.h> -#include <net/if_arp.h> -#include <net/if_media.h> -#include <net/ethernet.h> - -#include <machine/bus.h> -#include <machine/resource.h> -#include <sys/bus.h> -#include <sys/rman.h> - -#include <net80211/ieee80211_var.h> - -#include <dev/pci/pcireg.h> -#include <dev/pci/pcivar.h> -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> - -#include <compat/ndis/pe_var.h> -#include <compat/ndis/cfg_var.h> -#include <compat/ndis/resource_var.h> -#include <compat/ndis/ntoskrnl_var.h> -#include <compat/ndis/ndis_var.h> -#include <dev/if_ndis/if_ndisvar.h> - -MODULE_DEPEND(ndis, pci, 1, 1, 1); - -static int ndis_probe_pci (device_t); -static int ndis_attach_pci (device_t); -static struct resource_list *ndis_get_resource_list - (device_t, device_t); -static int ndis_devcompare (interface_type, - struct ndis_pci_type *, device_t); -extern int ndisdrv_modevent (module_t, int, void *); -extern int ndis_attach (device_t); -extern int ndis_shutdown (device_t); -extern int ndis_detach (device_t); -extern int ndis_suspend (device_t); -extern int ndis_resume (device_t); - -static device_method_t ndis_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ndis_probe_pci), - DEVMETHOD(device_attach, ndis_attach_pci), - DEVMETHOD(device_detach, ndis_detach), - DEVMETHOD(device_shutdown, ndis_shutdown), - DEVMETHOD(device_suspend, ndis_suspend), - DEVMETHOD(device_resume, ndis_resume), - - /* Bus interface */ - DEVMETHOD(bus_get_resource_list, ndis_get_resource_list), - - { 0, 0 } -}; - -static driver_t ndis_driver = { - "ndis", - ndis_methods, - sizeof(struct ndis_softc) -}; - -static devclass_t ndis_devclass; - -DRIVER_MODULE(ndis, pci, ndis_driver, ndis_devclass, ndisdrv_modevent, 0); - -static int -ndis_devcompare(bustype, t, dev) - interface_type bustype; - struct ndis_pci_type *t; - device_t dev; -{ - uint16_t vid, did; - uint32_t subsys; - - if (bustype != PCIBus) - return(FALSE); - - vid = pci_get_vendor(dev); - did = pci_get_device(dev); - subsys = pci_get_subdevice(dev); - subsys = (subsys << 16) | pci_get_subvendor(dev); - - while(t->ndis_name != NULL) { - if ((t->ndis_vid == vid) && (t->ndis_did == did) && - (t->ndis_subsys == subsys || t->ndis_subsys == 0)) { - device_set_desc(dev, t->ndis_name); - return(TRUE); - } - t++; - } - - return(FALSE); -} - -/* - * Probe for an NDIS device. Check the PCI vendor and device - * IDs against our list and return a device name if we find a match. - */ -static int -ndis_probe_pci(dev) - device_t dev; -{ - driver_object *drv; - struct drvdb_ent *db; - - drv = windrv_lookup(0, "PCI Bus"); - - if (drv == NULL) - return(ENXIO); - - db = windrv_match((matchfuncptr)ndis_devcompare, dev); - - if (db != NULL) { - /* Create PDO for this device instance */ - windrv_create_pdo(drv, dev); - return(0); - } - - return(ENXIO); -} - -/* - * Attach the interface. Allocate softc structures, do ifmedia - * setup and ethernet/BPF attach. - */ -static int -ndis_attach_pci(dev) - device_t dev; -{ - struct ndis_softc *sc; - int unit, error = 0, rid; - struct ndis_pci_type *t; - int devidx = 0, defidx = 0; - struct resource_list *rl; - struct resource_list_entry *rle; - struct drvdb_ent *db; - uint16_t vid, did; - uint32_t subsys; - - sc = device_get_softc(dev); - unit = device_get_unit(dev); - sc->ndis_dev = dev; - - db = windrv_match((matchfuncptr)ndis_devcompare, dev); - if (db == NULL) - return (ENXIO); - sc->ndis_dobj = db->windrv_object; - sc->ndis_regvals = db->windrv_regvals; - - /* - * Map control/status registers. - */ - - pci_enable_busmaster(dev); - - rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); - if (rl != NULL) { - STAILQ_FOREACH(rle, rl, link) { - switch (rle->type) { - case SYS_RES_IOPORT: - sc->ndis_io_rid = rle->rid; - sc->ndis_res_io = bus_alloc_resource_any(dev, - SYS_RES_IOPORT, &sc->ndis_io_rid, - RF_ACTIVE); - if (sc->ndis_res_io == NULL) { - device_printf(dev, - "couldn't map iospace\n"); - error = ENXIO; - goto fail; - } - break; - case SYS_RES_MEMORY: - if (sc->ndis_res_altmem != NULL && - sc->ndis_res_mem != NULL) { - device_printf(dev, - "too many memory resources\n"); - error = ENXIO; - goto fail; - } - if (sc->ndis_res_mem) { - sc->ndis_altmem_rid = rle->rid; - sc->ndis_res_altmem = - bus_alloc_resource_any(dev, - SYS_RES_MEMORY, - &sc->ndis_altmem_rid, - RF_ACTIVE); - if (sc->ndis_res_altmem == NULL) { - device_printf(dev, - "couldn't map alt " - "memory\n"); - error = ENXIO; - goto fail; - } - } else { - sc->ndis_mem_rid = rle->rid; - sc->ndis_res_mem = - bus_alloc_resource_any(dev, - SYS_RES_MEMORY, - &sc->ndis_mem_rid, - RF_ACTIVE); - if (sc->ndis_res_mem == NULL) { - device_printf(dev, - "couldn't map memory\n"); - error = ENXIO; - goto fail; - } - } - break; - case SYS_RES_IRQ: - rid = rle->rid; - sc->ndis_irq = bus_alloc_resource_any(dev, - SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE); - if (sc->ndis_irq == NULL) { - device_printf(dev, - "couldn't map interrupt\n"); - error = ENXIO; - goto fail; - } - break; - default: - break; - } - sc->ndis_rescnt++; - } - } - - /* - * If the BIOS did not set up an interrupt for this device, - * the resource traversal code above will fail to set up - * an IRQ resource. This is usually a bad thing, so try to - * force the allocation of an interrupt here. If one was - * not assigned to us by the BIOS, bus_alloc_resource() - * should route one for us. - */ - if (sc->ndis_irq == NULL) { - rid = 0; - sc->ndis_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &rid, RF_SHAREABLE | RF_ACTIVE); - if (sc->ndis_irq == NULL) { - device_printf(dev, "couldn't route interrupt\n"); - error = ENXIO; - goto fail; - } - sc->ndis_rescnt++; - } - - /* - * Allocate the parent bus DMA tag appropriate for PCI. - */ -#define NDIS_NSEG_NEW 32 - error = bus_dma_tag_create(bus_get_dma_tag(dev),/* PCI parent */ - 1, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - DFLTPHYS, NDIS_NSEG_NEW,/* maxsize, nsegments */ - BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */ - BUS_DMA_ALLOCNOW, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->ndis_parent_tag); - - if (error) - goto fail; - - sc->ndis_iftype = PCIBus; - - /* Figure out exactly which device we matched. */ - - vid = pci_get_vendor(dev); - did = pci_get_device(dev); - subsys = pci_get_subdevice(dev); - subsys = (subsys << 16) | pci_get_subvendor(dev); - - t = db->windrv_devlist; - - while(t->ndis_name != NULL) { - if (t->ndis_vid == vid && t->ndis_did == did) { - if (t->ndis_subsys == 0) - defidx = devidx; - else if (t->ndis_subsys == subsys) - break; - } - t++; - devidx++; - } - - if (t->ndis_name == NULL) - sc->ndis_devidx = defidx; - else - sc->ndis_devidx = devidx; - - error = ndis_attach(dev); - if (error == 0) - gone_in_dev(dev, 14, "ndis removed"); - - -fail: - return(error); -} - -static struct resource_list * -ndis_get_resource_list(dev, child) - device_t dev; - device_t child; -{ - struct ndis_softc *sc; - - sc = device_get_softc(dev); - return (BUS_GET_RESOURCE_LIST(device_get_parent(sc->ndis_dev), dev)); -} diff --git a/sys/dev/if_ndis/if_ndis_usb.c b/sys/dev/if_ndis/if_ndis_usb.c deleted file mode 100644 index 3364d3181532..000000000000 --- a/sys/dev/if_ndis/if_ndis_usb.c +++ /dev/null @@ -1,240 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2005 - * Bill Paul <wpaul@windriver.com>. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/sockio.h> -#include <sys/module.h> -#include <sys/malloc.h> -#include <sys/kernel.h> -#include <sys/socket.h> -#include <sys/sysctl.h> - -#include <net/if.h> -#include <net/if_var.h> -#include <net/if_arp.h> -#include <net/ethernet.h> -#include <net/if_dl.h> -#include <net/if_media.h> - -#include <net/bpf.h> - -#include <sys/bus.h> -#include <machine/bus.h> -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> - -#include <net80211/ieee80211_var.h> - -#include <compat/ndis/pe_var.h> -#include <compat/ndis/cfg_var.h> -#include <compat/ndis/resource_var.h> -#include <compat/ndis/ntoskrnl_var.h> -#include <compat/ndis/ndis_var.h> -#include <compat/ndis/usbd_var.h> -#include <dev/if_ndis/if_ndisvar.h> - -SYSCTL_NODE(_hw, OID_AUTO, ndisusb, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, - "NDIS USB driver parameters"); - -MODULE_DEPEND(ndis, usb, 1, 1, 1); - -static device_probe_t ndisusb_match; -static device_attach_t ndisusb_attach; -static device_detach_t ndisusb_detach; -static bus_get_resource_list_t ndis_get_resource_list; - -extern int ndisdrv_modevent (module_t, int, void *); -extern int ndis_attach (device_t); -extern int ndis_shutdown (device_t); -extern int ndis_detach (device_t); -extern int ndis_suspend (device_t); -extern int ndis_resume (device_t); - -extern unsigned char drv_data[]; - -static device_method_t ndis_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ndisusb_match), - DEVMETHOD(device_attach, ndisusb_attach), - DEVMETHOD(device_detach, ndisusb_detach), - DEVMETHOD(device_shutdown, ndis_shutdown), - - /* bus interface */ - DEVMETHOD(bus_get_resource_list, ndis_get_resource_list), - - DEVMETHOD_END -}; - -static driver_t ndis_driver = { - "ndis", - ndis_methods, - sizeof(struct ndis_softc) -}; - -static devclass_t ndis_devclass; - -DRIVER_MODULE(ndis, uhub, ndis_driver, ndis_devclass, ndisdrv_modevent, 0); - -static int -ndisusb_devcompare(interface_type bustype, struct ndis_usb_type *t, device_t dev) -{ - struct usb_attach_arg *uaa; - - if (bustype != PNPBus) - return (FALSE); - - uaa = device_get_ivars(dev); - - while (t->ndis_name != NULL) { - if ((uaa->info.idVendor == t->ndis_vid) && - (uaa->info.idProduct == t->ndis_did)) { - device_set_desc(dev, t->ndis_name); - return (TRUE); - } - t++; - } - - return (FALSE); -} - -static int -ndisusb_match(device_t self) -{ - struct drvdb_ent *db; - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->usb_mode != USB_MODE_HOST) - return (ENXIO); - if (uaa->info.bConfigIndex != NDISUSB_CONFIG_NO) - return (ENXIO); - if (uaa->info.bIfaceIndex != NDISUSB_IFACE_INDEX) - return (ENXIO); - - if (windrv_lookup(0, "USB Bus") == NULL) - return (ENXIO); - - db = windrv_match((matchfuncptr)ndisusb_devcompare, self); - if (db == NULL) - return (ENXIO); - uaa->driver_ivar = db; - - return (0); -} - -static int -ndisusb_attach(device_t self) -{ - const struct drvdb_ent *db; - struct ndisusb_softc *dummy = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - struct ndis_softc *sc; - struct ndis_usb_type *t; - driver_object *drv; - int devidx = 0; - - device_set_usb_desc(self); - db = uaa->driver_ivar; - sc = (struct ndis_softc *)dummy; - sc->ndis_dev = self; - mtx_init(&sc->ndisusb_mtx, "NDIS USB", MTX_NETWORK_LOCK, MTX_DEF); - sc->ndis_dobj = db->windrv_object; - sc->ndis_regvals = db->windrv_regvals; - sc->ndis_iftype = PNPBus; - sc->ndisusb_dev = uaa->device; - - /* Create PDO for this device instance */ - - drv = windrv_lookup(0, "USB Bus"); - windrv_create_pdo(drv, self); - - /* Figure out exactly which device we matched. */ - - t = db->windrv_devlist; - - while (t->ndis_name != NULL) { - if ((uaa->info.idVendor == t->ndis_vid) && - (uaa->info.idProduct == t->ndis_did)) { - sc->ndis_devidx = devidx; - break; - } - t++; - devidx++; - } - - if (ndis_attach(self) != 0) - return (ENXIO); - - gone_in_dev(self, 14, "ndis removed"); - - return (0); -} - -static int -ndisusb_detach(device_t self) -{ - int i; - struct ndis_softc *sc = device_get_softc(self); - struct ndisusb_ep *ne; - - sc->ndisusb_status |= NDISUSB_STATUS_DETACH; - - ndis_pnpevent_nic(self, NDIS_PNP_EVENT_SURPRISE_REMOVED); - - if (sc->ndisusb_status & NDISUSB_STATUS_SETUP_EP) { - usbd_transfer_unsetup(sc->ndisusb_dread_ep.ne_xfer, 1); - usbd_transfer_unsetup(sc->ndisusb_dwrite_ep.ne_xfer, 1); - } - for (i = 0; i < NDISUSB_ENDPT_MAX; i++) { - ne = &sc->ndisusb_ep[i]; - usbd_transfer_unsetup(ne->ne_xfer, 1); - } - - (void)ndis_detach(self); - - mtx_destroy(&sc->ndisusb_mtx); - return (0); -} - -static struct resource_list * -ndis_get_resource_list(device_t dev, device_t child) -{ - struct ndis_softc *sc; - - sc = device_get_softc(dev); - return (BUS_GET_RESOURCE_LIST(device_get_parent(sc->ndis_dev), dev)); -} diff --git a/sys/dev/if_ndis/if_ndisvar.h b/sys/dev/if_ndis/if_ndisvar.h deleted file mode 100644 index 0182e15f6e2a..000000000000 --- a/sys/dev/if_ndis/if_ndisvar.h +++ /dev/null @@ -1,263 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul <wpaul@windriver.com>. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#define NDIS_DEFAULT_NODENAME "FreeBSD NDIS node" -#define NDIS_NODENAME_LEN 32 - -/* For setting/getting OIDs from userspace. */ - -struct ndis_oid_data { - uint32_t oid; - uint32_t len; -#ifdef notdef - uint8_t data[1]; -#endif -}; - -struct ndis_pci_type { - uint16_t ndis_vid; - uint16_t ndis_did; - uint32_t ndis_subsys; - char *ndis_name; -}; - -struct ndis_pccard_type { - const char *ndis_vid; - const char *ndis_did; - char *ndis_name; -}; - -struct ndis_usb_type { - uint16_t ndis_vid; - uint16_t ndis_did; - char *ndis_name; -}; - -struct ndis_shmem { - list_entry ndis_list; - bus_dma_tag_t ndis_stag; - bus_dmamap_t ndis_smap; - void *ndis_saddr; - ndis_physaddr ndis_paddr; -}; - -struct ndis_cfglist { - ndis_cfg ndis_cfg; - struct sysctl_oid *ndis_oid; - TAILQ_ENTRY(ndis_cfglist) link; -}; - -/* - * Helper struct to make parsing information - * elements easier. - */ -struct ndis_ie { - uint8_t ni_oui[3]; - uint8_t ni_val; -}; - -TAILQ_HEAD(nch, ndis_cfglist); - -#define NDIS_INITIALIZED(sc) (sc->ndis_block->nmb_devicectx != NULL) - -#define NDIS_TXPKTS 64 -#define NDIS_INC(x) \ - (x)->ndis_txidx = ((x)->ndis_txidx + 1) % (x)->ndis_maxpkts - - -#define NDIS_EVENTS 4 -#define NDIS_EVTINC(x) (x) = ((x) + 1) % NDIS_EVENTS - -struct ndis_evt { - uint32_t ne_sts; - uint32_t ne_len; - char *ne_buf; -}; - -struct ndis_vap { - struct ieee80211vap vap; - - int (*newstate)(struct ieee80211vap *, - enum ieee80211_state, int); -}; -#define NDIS_VAP(vap) ((struct ndis_vap *)(vap)) - -#define NDISUSB_CONFIG_NO 0 -#define NDISUSB_IFACE_INDEX 0 -/* XXX at USB2 there's no USBD_NO_TIMEOUT macro anymore */ -#define NDISUSB_NO_TIMEOUT 0 -#define NDISUSB_INTR_TIMEOUT 1000 -#define NDISUSB_TX_TIMEOUT 10000 -struct ndisusb_xfer; -struct ndisusb_ep { - struct usb_xfer *ne_xfer[1]; - list_entry ne_active; - list_entry ne_pending; - kspin_lock ne_lock; - uint8_t ne_dirin; -}; -struct ndisusb_xfer { - struct ndisusb_ep *nx_ep; - void *nx_priv; - uint8_t *nx_urbbuf; - uint32_t nx_urbactlen; - uint32_t nx_urblen; - uint8_t nx_shortxfer; - list_entry nx_next; -}; -struct ndisusb_xferdone { - struct ndisusb_xfer *nd_xfer; - usb_error_t nd_status; - list_entry nd_donelist; -}; - -struct ndisusb_task { - unsigned nt_type; -#define NDISUSB_TASK_TSTART 0 -#define NDISUSB_TASK_IRPCANCEL 1 -#define NDISUSB_TASK_VENDOR 2 - void *nt_ctx; - list_entry nt_tasklist; -}; - -struct ndis_softc { -#define NDISUSB_GET_IFNET(ndis_softc) ( (ndis_softc)->ndis_80211 ? NULL : (ndis_softc)->ifp ) - u_int ndis_80211:1, - ndis_link:1, - ndis_running:1; - union { - struct { /* Ethernet */ - struct ifnet *ifp; - struct ifmedia ifmedia; - int ndis_if_flags; - }; - struct { /* Wireless */ - struct ieee80211com ndis_ic; - struct callout ndis_scan_callout; - int (*ndis_newstate)(struct ieee80211com *, - enum ieee80211_state, int); - }; - }; - u_long ndis_hwassist; - uint32_t ndis_v4tx; - uint32_t ndis_v4rx; - bus_space_handle_t ndis_bhandle; - bus_space_tag_t ndis_btag; - void *ndis_intrhand; - struct resource *ndis_irq; - struct resource *ndis_res; - struct resource *ndis_res_io; - int ndis_io_rid; - struct resource *ndis_res_mem; - int ndis_mem_rid; - struct resource *ndis_res_altmem; - int ndis_altmem_rid; - struct resource *ndis_res_am; /* attribute mem (pccard) */ - int ndis_am_rid; - struct resource *ndis_res_cm; /* common mem (pccard) */ - struct resource_list ndis_rl; - int ndis_rescnt; - struct mtx ndis_mtx; - uint8_t ndis_irql; - device_t ndis_dev; - int ndis_unit; - ndis_miniport_block *ndis_block; - ndis_miniport_characteristics *ndis_chars; - interface_type ndis_type; - struct callout ndis_stat_callout; - int ndis_maxpkts; - ndis_oid *ndis_oids; - int ndis_oidcnt; - int ndis_txidx; - int ndis_txpending; - ndis_packet **ndis_txarray; - ndis_handle ndis_txpool; - int ndis_sc; - ndis_cfg *ndis_regvals; - struct nch ndis_cfglist_head; - uint32_t ndis_sts; - uint32_t ndis_filter; - int ndis_skip; - int ndis_devidx; - interface_type ndis_iftype; - driver_object *ndis_dobj; - io_workitem *ndis_tickitem; - io_workitem *ndis_startitem; - io_workitem *ndis_resetitem; - io_workitem *ndis_inputitem; - kdpc ndis_rxdpc; - bus_dma_tag_t ndis_parent_tag; - list_entry ndis_shlist; - bus_dma_tag_t ndis_mtag; - bus_dma_tag_t ndis_ttag; - bus_dmamap_t *ndis_mmaps; - bus_dmamap_t *ndis_tmaps; - int ndis_mmapcnt; - struct ndis_evt ndis_evt[NDIS_EVENTS]; - int ndis_evtpidx; - int ndis_evtcidx; - struct mbufq ndis_rxqueue; - kspin_lock ndis_rxlock; - - int ndis_tx_timer; - int ndis_hang_timer; - - struct usb_device *ndisusb_dev; - struct mtx ndisusb_mtx; - struct ndisusb_ep ndisusb_dread_ep; - struct ndisusb_ep ndisusb_dwrite_ep; -#define NDISUSB_GET_ENDPT(addr) \ - ((UE_GET_DIR(addr) >> 7) | (UE_GET_ADDR(addr) << 1)) -#define NDISUSB_ENDPT_MAX ((UE_ADDR + 1) * 2) - struct ndisusb_ep ndisusb_ep[NDISUSB_ENDPT_MAX]; - io_workitem *ndisusb_xferdoneitem; - list_entry ndisusb_xferdonelist; - kspin_lock ndisusb_xferdonelock; - io_workitem *ndisusb_taskitem; - list_entry ndisusb_tasklist; - kspin_lock ndisusb_tasklock; - int ndisusb_status; -#define NDISUSB_STATUS_DETACH 0x1 -#define NDISUSB_STATUS_SETUP_EP 0x2 -}; - -#define NDIS_LOCK(_sc) mtx_lock(&(_sc)->ndis_mtx) -#define NDIS_UNLOCK(_sc) mtx_unlock(&(_sc)->ndis_mtx) -#define NDIS_LOCK_ASSERT(_sc, t) mtx_assert(&(_sc)->ndis_mtx, t) -#define NDISUSB_LOCK(_sc) mtx_lock(&(_sc)->ndisusb_mtx) -#define NDISUSB_UNLOCK(_sc) mtx_unlock(&(_sc)->ndisusb_mtx) -#define NDISUSB_LOCK_ASSERT(_sc, t) mtx_assert(&(_sc)->ndisusb_mtx, t) - |
