Bring in NDIS emulation support from FreeBSD-5. NDIS is a Windows device
authorMatthew Dillon <dillon@dragonflybsd.org>
Thu, 29 Jul 2004 20:51:36 +0000 (20:51 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Thu, 29 Jul 2004 20:51:36 +0000 (20:51 +0000)
driver API emulator.  The FreeBSD work was done by Bill Paul
<wpaul@windriver.com>, who has again proven himself to be a more insane
hacker then the rest of us.

Bring in IF_NDIS from FreeBSD-5.

Make a number of additional changes to the driver.  Windows API calls are not
compatible with standard gnu C.   The FreeBSD-5 NDIS code properly uses
__attribute__((__stdcall__)) to deal with the target-pops-argument-stack
issue but had terrible __asm hacks to deal with regargs.  Consolidate the
regargs support into a new header file, regcall.h, and use
__attribute__((__regparm__(3))) to formalize argument passing in registers.
Note that __regparm__(3) places three arguments in registers in the
following order: %eax, %edx, %ecx, but Windoz reg calls place registered
arguments in %ecx and %edx (and additional arguments go on the stack).
regcall.h provides macros to do the proper (I hope) translations.

DragonFly's kernel threads do not have proc structures.  Convert up all the
proc references to thread references.

Convert mutex ops into token ops.

Fix a number of prototypes, including one that was causing an internal
compiler error in gcc2.

Testing: Doesn't crash with Sony-TR3A Intel Centrino 2200 based wireless
chipset, is able to DHCP up the IP address, but cannot yet ping due
to an issue in the ARP code somewhere.
Taken from: FreeBSD-5 / Bill Paul

19 files changed:
sys/dev/netif/ndis/Makefile [new file with mode: 0644]
sys/dev/netif/ndis/if_ndis.c [new file with mode: 0644]
sys/dev/netif/ndis/if_ndis_pccard.c [new file with mode: 0644]
sys/dev/netif/ndis/if_ndis_pci.c [new file with mode: 0644]
sys/dev/netif/ndis/if_ndisvar.h [new file with mode: 0644]
sys/emulation/Makefile
sys/emulation/ndis/Makefile [new file with mode: 0644]
sys/emulation/ndis/cfg_var.h [new file with mode: 0644]
sys/emulation/ndis/hal_var.h [new file with mode: 0644]
sys/emulation/ndis/kern_ndis.c [new file with mode: 0644]
sys/emulation/ndis/ndis_var.h [new file with mode: 0644]
sys/emulation/ndis/ntoskrnl_var.h [new file with mode: 0644]
sys/emulation/ndis/pe_var.h [new file with mode: 0644]
sys/emulation/ndis/regcall.h [new file with mode: 0644]
sys/emulation/ndis/resource_var.h [new file with mode: 0644]
sys/emulation/ndis/subr_hal.c [new file with mode: 0644]
sys/emulation/ndis/subr_ndis.c [new file with mode: 0644]
sys/emulation/ndis/subr_ntoskrnl.c [new file with mode: 0644]
sys/emulation/ndis/subr_pe.c [new file with mode: 0644]

diff --git a/sys/dev/netif/ndis/Makefile b/sys/dev/netif/ndis/Makefile
new file mode 100644 (file)
index 0000000..0891d18
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# $DragonFly: src/sys/dev/netif/ndis/Makefile,v 1.1 2004/07/29 20:51:36 dillon Exp $
+
+KMOD=  if_ndis
+SRCS=  if_ndis.c if_ndis_pccard.c if_ndis_pci.c \
+       card_if.h device_if.h bus_if.h pci_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/dev/netif/ndis/if_ndis.c b/sys/dev/netif/ndis/if_ndis.c
new file mode 100644 (file)
index 0000000..8a5089d
--- /dev/null
@@ -0,0 +1,2131 @@
+/*
+ * 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: src/sys/dev/if_ndis/if_ndis.c,v 1.65 2004/07/07 17:46:30 wpaul Exp $
+ * $DragonFly: src/sys/dev/netif/ndis/if_ndis.c,v 1.1 2004/07/29 20:51:36 dillon Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/proc.h>
+#if __FreeBSD_version < 502113
+#include <sys/sysctl.h>
+#endif
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/route.h>
+
+#include <net/bpf.h>
+
+#include <machine/bus_memio.h>
+#include <machine/bus_pio.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <netproto/802_11/ieee80211_var.h>
+#include <netproto/802_11/ieee80211_ioctl.h>
+
+#include <netproto/802_11/if_wavelan_ieee.h>
+
+#include <bus/pci/pcireg.h>
+#include <bus/pci/pcivar.h>
+
+#include <sys/thread2.h>
+
+#include <emulation/ndis/regcall.h>
+#include <emulation/ndis/pe_var.h>
+#include <emulation/ndis/resource_var.h>
+#include <emulation/ndis/ntoskrnl_var.h>
+#include <emulation/ndis/hal_var.h>
+#include <emulation/ndis/ndis_var.h>
+#include <emulation/ndis/cfg_var.h>
+#include "if_ndisvar.h"
+
+#define NDIS_IMAGE
+#define NDIS_REGVALS
+
+#include "ndis_driver_data.h"
+
+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);
+
+static __stdcall void ndis_txeof       (ndis_handle,
+       ndis_packet *, ndis_status);
+static __stdcall void ndis_rxeof       (ndis_handle,
+       ndis_packet **, uint32_t);
+static __stdcall void ndis_linksts     (ndis_handle,
+       ndis_status, void *, uint32_t);
+static __stdcall void ndis_linksts_done        (ndis_handle);
+
+static void ndis_intr          (void *);
+static void ndis_intrtask      (void *);
+static void ndis_tick          (void *);
+static void ndis_ticktask      (void *);
+static void ndis_start         (struct ifnet *);
+static void ndis_starttask     (void *);
+static int ndis_ioctl          (struct ifnet *, u_long, caddr_t, struct ucred *);
+static int ndis_wi_ioctl_get   (struct ifnet *, u_long, caddr_t);
+static int ndis_wi_ioctl_set   (struct ifnet *, u_long, caddr_t);
+static void ndis_init          (void *);
+static void ndis_stop          (struct ndis_softc *);
+static void ndis_watchdog      (struct ifnet *);
+static int ndis_ifmedia_upd    (struct ifnet *);
+static void ndis_ifmedia_sts   (struct ifnet *, struct ifmediareq *);
+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_media_status  (struct ifnet *, struct ifmediareq *);
+
+static void ndis_setmulti      (struct ndis_softc *);
+static void ndis_map_sclist    (void *, bus_dma_segment_t *,
+       int, bus_size_t, int);
+
+/*
+ * Program the 64-bit multicast hash filter.
+ */
+static void
+ndis_setmulti(sc)
+       struct ndis_softc       *sc;
+{
+       struct ifnet            *ifp;
+       struct ifmultiaddr      *ifma;
+       int                     len, mclistsz, error;
+       uint8_t                 *mclist;
+
+       ifp = &sc->arpcom.ac_if;
+
+       if (!NDIS_INITIALIZED(sc))
+               return;
+
+       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 filter failed: %d\n", error);
+               return;
+       }
+
+       if (LIST_EMPTY(&ifp->if_multiaddrs))
+               return;
+
+       len = sizeof(mclistsz);
+       ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &mclistsz, &len);
+
+       mclist = malloc(ETHER_ADDR_LEN * mclistsz, M_TEMP, M_NOWAIT|M_ZERO);
+
+       if (mclist == NULL) {
+               sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
+               goto out;
+       }
+
+       sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
+
+       len = 0;
+       LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+               if (ifma->ifma_addr->sa_family != AF_LINK)
+                       continue;
+               bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
+                   mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN);
+               len++;
+               if (len > 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, 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(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 filter failed: %d\n", error);
+
+       return;
+}
+
+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;
+
+       ifp = &sc->arpcom.ac_if;
+
+       if (!NDIS_INITIALIZED(sc))
+               return(EINVAL);
+
+       /* See if there's anything to set. */
+
+       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->arpcom.ac_if;
+
+       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);
+}
+
+/*
+ * Attach the interface. Allocate softc structures, do ifmedia
+ * setup and ethernet/BPF attach.
+ */
+int
+ndis_attach(dev)
+       device_t                dev;
+{
+       u_char                  eaddr[ETHER_ADDR_LEN];
+       struct ndis_softc       *sc;
+       struct ifnet            *ifp = NULL;
+       void                    *img;
+       int                     error = 0, len;
+       int                     i;
+
+       sc = device_get_softc(dev);
+
+       NDIS_LOCK_INIT(&sc->ndis_lock);
+       NDIS_LOCK_INIT(&sc->ndis_intrlock);
+
+        /*
+        * Hook interrupt early, since calling the driver's
+        * init routine may trigger an interrupt.
+        */
+
+       error = bus_setup_intr(dev, sc->ndis_irq, INTR_TYPE_NET | INTR_MPSAFE,
+           ndis_intr, sc, &sc->ndis_intrhand);
+
+       if (error) {
+               device_printf(dev, "couldn't set up irq\n");
+               goto fail;
+       }
+
+       sc->ndis_regvals = ndis_regvals;
+
+#if __FreeBSD_version < 502113
+       sysctl_ctx_init(&sc->ndis_ctx);
+
+#endif
+       /* Create sysctl registry nodes */
+       ndis_create_sysctls(sc);
+
+       /* Set up driver image in memory. */
+       img = drv_data;
+       ndis_load_driver((vm_offset_t)img, sc);
+
+       /* 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. */
+       ndis_convert_res(sc);
+
+       /* Install our RX and TX interrupt handlers. */
+       sc->ndis_block.nmb_senddone_func = ndis_txeof;
+       sc->ndis_block.nmb_pktind_func = ndis_rxeof;
+
+       /* Call driver's init routine. */
+       if (ndis_init_nic(sc)) {
+               device_printf (dev, "init handler failed\n");
+               error = ENXIO;
+               goto fail;
+       }
+
+       /*
+        * Get station address from the driver.
+        */
+       len = sizeof(eaddr);
+       ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &eaddr, &len);
+
+       bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
+
+       /*
+        * Figure out of we're allowed to use multipacket sends
+        * with this driver, and if so, how many.
+        */
+
+       if (sc->ndis_chars.nmc_sendsingle_func &&
+           sc->ndis_chars.nmc_sendmulti_func == NULL) {
+               sc->ndis_maxpkts = 1;
+       } else {
+               len = sizeof(sc->ndis_maxpkts);
+               ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
+                   &sc->ndis_maxpkts, &len);
+       }
+
+       sc->ndis_txarray = malloc(sizeof(ndis_packet *) *
+           sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO);
+
+       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++;
+                       break;
+               }
+       }
+
+       /* Check for task offload support. */
+       ndis_probe_offload(sc);
+
+       ifp = &sc->arpcom.ac_if;
+       ifp->if_softc = sc;
+       if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+       ifp->if_mtu = ETHERMTU;
+       ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+       ifp->if_ioctl = ndis_ioctl;
+       ifp->if_start = ndis_start;
+       ifp->if_watchdog = ndis_watchdog;
+       ifp->if_init = ndis_init;
+       ifp->if_baudrate = 10000000;
+       ifp->if_snd.ifq_maxlen = 50;
+       ifp->if_capenable = ifp->if_capabilities;
+       ifp->if_hwassist = sc->ndis_hwassist;
+
+       /* Do media setup */
+       if (sc->ndis_80211) {
+               struct ieee80211com     *ic = (void *)ifp;
+               ndis_80211_rates_ex     rates;
+               struct ndis_80211_nettype_list *ntl;
+               uint32_t                arg;
+               int                     r;
+
+               ic->ic_phytype = IEEE80211_T_DS;
+               ic->ic_opmode = IEEE80211_M_STA;
+               ic->ic_caps = IEEE80211_C_IBSS;
+               ic->ic_state = IEEE80211_S_ASSOC;
+               ic->ic_modecaps = (1<<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++) {
+                       switch (ntl->ntl_type[i]) {
+                       case NDIS_80211_NETTYPE_11FH:
+                       case NDIS_80211_NETTYPE_11DS:
+                               ic->ic_modecaps |= (1<<IEEE80211_MODE_11B);
+                               break;
+                       case NDIS_80211_NETTYPE_11OFDM5:
+                               ic->ic_modecaps |= (1<<IEEE80211_MODE_11A);
+                               break;
+                       case NDIS_80211_NETTYPE_11OFDM24:
+                               ic->ic_modecaps |= (1<<IEEE80211_MODE_11G);
+                               break;
+                       default:
+                               break;
+                       }
+               }
+               free(ntl, M_DEVBUF);
+nonettypes:
+               len = sizeof(rates);
+               bzero((char *)&rates, len);
+               r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES,
+                   (void *)rates, &len);
+               if (r)
+                       device_printf (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 (ic->ic_modecaps & (1<<IEEE80211_MODE_11A))
+                       ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
+               if (ic->ic_modecaps & (1<<IEEE80211_MODE_11B))
+                       ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
+               if (ic->ic_modecaps & (1<<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 (!(ic->ic_modecaps &
+                                   (1<<IEEE80211_MODE_11B))) {
+                                       /* Lazy-init 802.11b. */
+                                       ic->ic_modecaps |=
+                                           (1<<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 (ic->ic_modecaps & (1<<IEEE80211_MODE_11A)) {
+                                       SETRATE(IEEE80211_MODE_11A, rates[i]);
+                                       INCRATE(IEEE80211_MODE_11A);
+                               }
+                               if (ic->ic_modecaps & (1<<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 (ic->ic_modecaps & (1<<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 (ic->ic_modecaps & (1<<IEEE80211_MODE_11G)) {
+                       TESTSETRATE(IEEE80211_MODE_11G, 47);
+                       TESTSETRATE(IEEE80211_MODE_11G, 72);
+                       TESTSETRATE(IEEE80211_MODE_11G, 96);
+                       TESTSETRATE(IEEE80211_MODE_11G, 108);
+               }
+               if (ic->ic_modecaps & (1<<IEEE80211_MODE_11A)) {
+                       TESTSETRATE(IEEE80211_MODE_11A, 47);
+                       TESTSETRATE(IEEE80211_MODE_11A, 72);
+                       TESTSETRATE(IEEE80211_MODE_11A, 96);
+                       TESTSETRATE(IEEE80211_MODE_11A, 108);
+               }
+#undef SETRATE
+#undef INCRATE
+               /*
+                * Taking yet more guesses here.
+                */
+               for (i = 1; i < IEEE80211_CHAN_MAX; i++) {
+                       int chanflag = 0;
+
+                       if (ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates)
+                               chanflag |= IEEE80211_CHAN_G;
+                       if (i <= 14)
+                               chanflag |= IEEE80211_CHAN_B;
+                       if (ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates &&
+                           i > 14)
+                               chanflag = IEEE80211_CHAN_A;
+                       if (chanflag == 0)
+                               break;
+                       ic->ic_channels[i].ic_freq =
+                           ieee80211_ieee2mhz(i, chanflag);
+                       ic->ic_channels[i].ic_flags = chanflag;
+               }
+
+               i = sizeof(arg);
+               r = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &i);
+               if (arg != NDIS_80211_WEPSTAT_NOTSUPPORTED)
+                       ic->ic_caps |= IEEE80211_C_WEP;
+               i = sizeof(arg);
+               r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
+               if (r == 0)
+                       ic->ic_caps |= IEEE80211_C_PMGT;
+               bcopy(eaddr, &ic->ic_myaddr, sizeof(eaddr));
+               ieee80211_ifattach(ifp);
+               ieee80211_media_init(ifp, ieee80211_media_change,
+                   ndis_media_status);
+               ic->ic_ibss_chan = IEEE80211_CHAN_ANYC;
+               ic->ic_bss->ni_chan = ic->ic_ibss_chan;
+       } else {
+               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);
+       }
+
+       /* Override the status handler so we can detect link changes. */
+       sc->ndis_block.nmb_status_func = ndis_linksts;
+       sc->ndis_block.nmb_statusdone_func = ndis_linksts_done;
+fail:
+       if (error)
+               ndis_detach(dev);
+       else
+               /* We're done talking to the NIC for now; halt it. */
+               ndis_halt_nic(sc);
+
+       return(error);
+}
+
+/*
+ * 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(dev)
+       device_t                dev;
+{
+       struct ndis_softc       *sc;
+       struct ifnet            *ifp;
+       NDIS_LOCK_INFO;
+
+       sc = device_get_softc(dev);
+       NDIS_LOCK(sc);
+       ifp = &sc->arpcom.ac_if;
+       ifp->if_flags &= ~IFF_UP;
+
+       if (device_is_attached(dev)) {
+               NDIS_UNLOCK(sc);
+               ndis_stop(sc);
+               if (sc->ndis_80211)
+                       ieee80211_ifdetach(ifp);
+               else
+                       ether_ifdetach(ifp);
+       } else
+               NDIS_UNLOCK(sc);
+
+       bus_generic_detach(dev);
+
+       if (sc->ndis_intrhand)
+               bus_teardown_intr(dev, sc->ndis_irq, sc->ndis_intrhand);
+       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 (sc->ndis_sc)
+               ndis_destroy_dma(sc);
+
+       ndis_unload_driver((void *)ifp);
+
+       if (sc->ndis_iftype == PCIBus)
+               bus_dma_tag_destroy(sc->ndis_parent_tag);
+
+#if __FreeBSD_version < 502113
+       sysctl_ctx_free(&sc->ndis_ctx);
+
+#endif
+       NDIS_LOCK_DESTROY(&sc->ndis_lock);
+       NDIS_LOCK_DESTROY(&sc->ndis_intrlock);
+
+       return(0);
+}
+
+int
+ndis_suspend(dev)
+       device_t                dev;
+{
+       struct ndis_softc       *sc;
+       struct ifnet            *ifp;
+
+       sc = device_get_softc(dev);
+       ifp = &sc->arpcom.ac_if;
+
+#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->arpcom.ac_if;
+
+       if (NDIS_INITIALIZED(sc))
+               ndis_init(sc);
+
+       return(0);
+}
+
+/*
+ * 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 posession 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.
+ */
+__stdcall 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 = (struct ndis_softc *)(block->nmb_ifp);
+       ifp = block->nmb_ifp;
+
+       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(sc, p);
+               } else {
+                       if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
+                               m = m_dup(m0, MB_DONTWAIT);
+                               /*
+                                * 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)
+                                       ifp->if_ierrors++;
+                               else
+                                       m0 = m;
+                       } else
+                               p->np_oob.npo_status = NDIS_STATUS_PENDING;
+                       m0->m_pkthdr.rcvif = ifp;
+                       ifp->if_ipackets++;
+
+                       /* 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;
+                               }
+                       }
+
+                       (*ifp->if_input)(ifp, m0);
+               }
+       }
+
+       return;
+}
+
+/*
+ * A frame was downloaded to the chip. It's safe for us to clean up
+ * the list buffers.
+ */
+__stdcall 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;
+       NDIS_LOCK_INFO;
+
+       block = (ndis_miniport_block *)adapter;
+       sc = (struct ndis_softc *)block->nmb_ifp;
+       ifp = block->nmb_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 (status == NDIS_STATUS_SUCCESS)
+               ifp->if_opackets++;
+       else
+               ifp->if_oerrors++;
+       ifp->if_timer = 0;
+       ifp->if_flags &= ~IFF_OACTIVE;
+       NDIS_UNLOCK(sc);
+
+       ndis_sched(ndis_starttask, ifp, NDIS_TASKQUEUE);
+
+       return;
+}
+
+__stdcall static void
+ndis_linksts(adapter, status, sbuf, slen)
+       ndis_handle             adapter;
+       ndis_status             status;
+       void                    *sbuf;
+       uint32_t                slen;
+{
+       ndis_miniport_block     *block;
+
+       block = adapter;
+       block->nmb_getstat = status;
+
+       return;
+}
+
+__stdcall static void
+ndis_linksts_done(adapter)
+       ndis_handle             adapter;
+{
+       ndis_miniport_block     *block;
+       struct ndis_softc       *sc;
+       struct ifnet            *ifp;
+
+       block = adapter;
+       ifp = block->nmb_ifp;
+       sc = ifp->if_softc;
+
+       if (!NDIS_INITIALIZED(sc))
+               return;
+
+       switch (block->nmb_getstat) {
+       case NDIS_STATUS_MEDIA_CONNECT:
+               ndis_sched(ndis_ticktask, sc, NDIS_TASKQUEUE);
+               ndis_sched(ndis_starttask, ifp, NDIS_TASKQUEUE);
+               break;
+       case NDIS_STATUS_MEDIA_DISCONNECT:
+               if (sc->ndis_link)
+                       ndis_sched(ndis_ticktask, sc, NDIS_TASKQUEUE);
+               break;
+       default:
+               break;
+       }
+
+       return;
+}
+
+static void
+ndis_intrtask(arg)
+       void                    *arg;
+{
+       struct ndis_softc       *sc;
+       struct ifnet            *ifp;
+       uint8_t                 irql;
+       NDIS_LOCK_INFO;
+
+       sc = arg;
+       ifp = &sc->arpcom.ac_if;
+
+       irql = FASTCALL1(hal_raise_irql, DISPATCH_LEVEL);
+       ndis_intrhand(sc);
+       FASTCALL1(hal_lower_irql, irql);
+       NDIS_INTRLOCK(sc);
+       ndis_enable_intr(sc);
+       NDIS_INTRUNLOCK(sc);
+
+       return;
+}
+
+static void
+ndis_intr(arg)
+       void                    *arg;
+{
+       struct ndis_softc       *sc;
+       struct ifnet            *ifp;
+       int                     is_our_intr = 0;
+       int                     call_isr = 0;
+       NDIS_LOCK_INFO;
+
+       sc = arg;
+       ifp = &sc->arpcom.ac_if;
+
+       if (sc->ndis_block.nmb_miniportadapterctx == NULL)
+               return;
+
+       NDIS_INTRLOCK(sc);
+       if (sc->ndis_block.nmb_interrupt->ni_isrreq == TRUE)
+               ndis_isr(sc, &is_our_intr, &call_isr);
+       else {
+               ndis_disable_intr(sc);
+               call_isr = 1;
+       }
+       NDIS_INTRUNLOCK(sc);
+
+       if ((is_our_intr || call_isr))
+               ndis_sched(ndis_intrtask, ifp, NDIS_SWI);
+
+       return;
+}
+
+static void
+ndis_tick(xsc)
+       void                    *xsc;
+{
+       struct ndis_softc       *sc;
+
+       sc = xsc;
+
+       ndis_sched(ndis_ticktask, sc, NDIS_TASKQUEUE);
+       sc->ndis_stat_ch = timeout(ndis_tick, sc, hz *
+           sc->ndis_block.nmb_checkforhangsecs);
+
+       return;
+}
+
+static void
+ndis_ticktask(xsc)
+       void                    *xsc;
+{
+       struct ndis_softc       *sc;
+       __stdcall ndis_checkforhang_handler hangfunc;
+       uint8_t                 rval;
+       ndis_media_state        linkstate;
+       int                     error, len;
+       NDIS_LOCK_INFO;
+
+       sc = xsc;
+
+       hangfunc = sc->ndis_chars.nmc_checkhang_func;
+
+       if (hangfunc != NULL) {
+               rval = hangfunc(sc->ndis_block.nmb_miniportadapterctx);
+               if (rval == TRUE) {
+                       ndis_reset_nic(sc);
+                       return;
+               }
+       }
+
+       len = sizeof(linkstate);
+       error = ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
+           (void *)&linkstate, &len);
+
+       NDIS_LOCK(sc);
+
+       if (sc->ndis_link == 0 && linkstate == nmc_connected) {
+               device_printf(sc->ndis_dev, "link up\n");
+               sc->ndis_link = 1;
+               NDIS_UNLOCK(sc);
+               if (sc->ndis_80211)
+                       ndis_getstate_80211(sc);
+               NDIS_LOCK(sc);
+#ifdef LINK_STATE_UP
+               sc->arpcom.ac_if.if_link_state = LINK_STATE_UP;
+               rt_ifmsg(&(sc->arpcom.ac_if));
+#endif /* LINK_STATE_UP */
+       }
+
+       if (sc->ndis_link == 1 && linkstate == nmc_disconnected) {
+               device_printf(sc->ndis_dev, "link down\n");
+               sc->ndis_link = 0;
+#ifdef LINK_STATE_DOWN
+               sc->arpcom.ac_if.if_link_state = LINK_STATE_DOWN;
+               rt_ifmsg(&(sc->arpcom.ac_if));
+#endif /* LINK_STATE_DOWN */
+       }
+
+       NDIS_UNLOCK(sc);
+
+       return;
+}
+
+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;
+       }
+
+       return;
+}
+
+static void
+ndis_starttask(arg)
+       void                    *arg;
+{
+       struct ifnet            *ifp;
+
+       ifp = arg;
+       if (ifp->if_snd.ifq_head != NULL)
+               ndis_start(ifp);
+       return;
+}
+
+/*
+ * 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_start(ifp)
+       struct ifnet            *ifp;
+{
+       struct ndis_softc       *sc;
+       struct mbuf             *m = NULL;
+       ndis_packet             **p0 = NULL, *p = NULL;
+       ndis_tcpip_csum         *csum;
+       int                     pcnt = 0;
+       NDIS_LOCK_INFO;
+
+       sc = ifp->if_softc;
+
+       NDIS_LOCK(sc);
+
+       if (!sc->ndis_link || ifp->if_flags & IFF_OACTIVE) {
+               NDIS_UNLOCK(sc);
+               return;
+       }
+
+       p0 = &sc->ndis_txarray[sc->ndis_txidx];
+
+       while(sc->ndis_txpending) {
+               IF_DEQUEUE(&ifp->if_snd, m);
+               if (m == NULL)
+                       break;
+
+               sc->ndis_txarray[sc->ndis_txidx] = NULL;
+
+               if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
+                       NDIS_UNLOCK(sc);
+                       IF_PREPEND(&ifp->if_snd, m);
+                       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.
+                */
+
+               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 (sc->ndis_txpending == 0)
+               ifp->if_flags |= IFF_OACTIVE;
+
+       /*
+        * Set a timeout in case the chip goes out to lunch.
+        */
+       ifp->if_timer = 5;
+
+       NDIS_UNLOCK(sc);
+
+       if (sc->ndis_maxpkts == 1)
+               ndis_send_packet(sc, p);
+       else
+               ndis_send_packets(sc, p0, pcnt);
+
+       return;
+}
+
+static void
+ndis_init(xsc)
+       void                    *xsc;
+{
+       struct ndis_softc       *sc = xsc;
+       struct ifnet            *ifp = &sc->arpcom.ac_if;
+       int                     i, error;
+       NDIS_LOCK_INFO;
+
+       /*
+        * 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 && sc->ndis_skip)
+               return;
+
+       /*
+        * Cancel pending I/O and free all RX/TX buffers.
+        */
+       ndis_stop(sc);
+       if (ndis_init_nic(sc))
+               return;
+
+       /* Init our MAC address */
+
+       /* Program the packet filter */
+
+       sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED;
+
+       if (ifp->if_flags & IFF_BROADCAST)
+               sc->ndis_filter |= NDIS_PACKET_TYPE_BROADCAST;
+
+       if (ifp->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);
+
+       if (error)
+               device_printf (sc->ndis_dev, "set filter failed: %d\n", error);
+
+       /*
+        * Program the multicast filter, if necessary.
+        */
+       ndis_setmulti(sc);
+
+       /* Setup task offload. */
+       ndis_set_offload(sc);
+
+       /* Enable interrupts. */
+       ndis_enable_intr(sc);
+
+       if (sc->ndis_80211)
+               ndis_setstate_80211(sc);
+
+       NDIS_LOCK(sc);
+
+       sc->ndis_txidx = 0;
+       sc->ndis_txpending = sc->ndis_maxpkts;
+       sc->ndis_link = 0;
+
+       ifp->if_flags |= IFF_RUNNING;
+       ifp->if_flags &= ~IFF_OACTIVE;
+
+       NDIS_UNLOCK(sc);
+
+       /*
+        * 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_stat_ch = timeout(ndis_tick, sc,
+           hz * sc->ndis_block.nmb_checkforhangsecs);
+
+       return;
+}
+
+/*
+ * 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                     error, len;
+
+       ifmr->ifm_status = IFM_AVALID;
+       ifmr->ifm_active = IFM_ETHER;
+       sc = ifp->if_softc;
+
+       if (!NDIS_INITIALIZED(sc))
+               return;
+
+       len = sizeof(linkstate);
+       error = ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
+           (void *)&linkstate, &len);
+
+       len = sizeof(media_info);
+       error = 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_TX;
+               break;
+       default:
+               device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
+               break;
+       }
+
+       return;
+}
+
+static void
+ndis_setstate_80211(sc)
+       struct ndis_softc       *sc;
+{
+       struct ieee80211com     *ic;
+       ndis_80211_ssid         ssid;
+       ndis_80211_config       config;
+       ndis_80211_wep          wep;
+       int                     i, rval = 0, len;
+       uint32_t                arg;
+       struct ifnet            *ifp;
+
+       ic = &sc->ic;
+       ifp = &sc->ic.ic_ac.ac_if;
+
+       if (!NDIS_INITIALIZED(sc))
+               return;
+
+       /* 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 WEP */
+
+#ifdef IEEE80211_F_WEPON
+       if (ic->ic_flags & IEEE80211_F_WEPON) {
+#else
+       if (ic->ic_wep_mode >= IEEE80211_WEP_ON) {
+#endif
+               for (i = 0; i < IEEE80211_WEP_NKID; i++) {
+                       if (ic->ic_nw_keys[i].wk_len) {
+                               bzero((char *)&wep, sizeof(wep));
+                               wep.nw_keylen = ic->ic_nw_keys[i].wk_len;
+#ifdef notdef
+                               /* 5 and 13 are the only valid key lengths */
+                               if (ic->ic_nw_keys[i].wk_len < 5)
+                                       wep.nw_keylen = 5;
+                               else if (ic->ic_nw_keys[i].wk_len > 5 &&
+                                    ic->ic_nw_keys[i].wk_len < 13)
+                                       wep.nw_keylen = 13;
+#endif
+                               wep.nw_keyidx = i;
+                               wep.nw_length = (sizeof(uint32_t) * 3)
+                                   + wep.nw_keylen;
+                               if (i == ic->ic_wep_txkey)
+                                       wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
+                               bcopy(ic->ic_nw_keys[i].wk_key,
+                                   wep.nw_keydata, wep.nw_length);
+                               len = sizeof(wep);
+                               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);
+                       }
+               }
+               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);
+#ifndef IEEE80211_F_WEPON
+               if (ic->ic_wep_mode != IEEE80211_WEP_8021X &&
+                   ic->ic_wep_mode != IEEE80211_WEP_ON)
+                       arg = NDIS_80211_PRIVFILT_ACCEPTALL;
+               else
+#endif
+                       arg = NDIS_80211_PRIVFILT_8021XWEP;
+               len = sizeof(arg);
+               rval = ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
+#ifdef IEEE80211_WEP_8021X /*IEEE80211_F_WEPON*/
+               /* Accept that we only have "shared" and 802.1x modes. */
+               if (rval == 0) {
+                       if (arg == NDIS_80211_PRIVFILT_ACCEPTALL)
+                               ic->ic_wep_mode = IEEE80211_WEP_MIXED;
+                       else
+                               ic->ic_wep_mode = IEEE80211_WEP_8021X;
+               }
+#endif
+               arg = NDIS_80211_AUTHMODE_OPEN;
+       } else {
+               arg = NDIS_80211_WEPSTAT_DISABLED;
+               len = sizeof(arg);
+               ndis_set_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
+               arg = NDIS_80211_AUTHMODE_OPEN;
+       }
+
+       len = sizeof(arg);
+       rval = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
+
+#ifdef notyet
+       if (rval)
+               device_printf (sc->ndis_dev, "set auth failed: %d\n", rval);
+#endif
+
+#ifdef notyet
+       /* Set network type. */
+
+       arg = 0;
+
+       switch (ic->ic_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",
+                   ic->ic_curmode);
+       }
+
+       if (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
+
+       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_ibss_chan != IEEE80211_CHAN_ANYC) { 
+               int chan, chanflag;
+
+               chan = ieee80211_chan2ieee(ic, ic->ic_ibss_chan);
+               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_ibss_chan->ic_freq * 1000;
+                       ic->ic_bss->ni_chan = ic->ic_ibss_chan;
+                       len = sizeof(config);
+                       config.nc_length = len;
+                       config.nc_fhconfig.ncf_length =
+                           sizeof(ndis_80211_config_fh);
+                       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 SSID -- always do this last. */
+
+       len = sizeof(ssid);
+       bzero((char *)&ssid, len);
+       ssid.ns_ssidlen = ic->ic_des_esslen;
+       if (ssid.ns_ssidlen == 0) {
+               ssid.ns_ssidlen = 1;
+       } else
+               bcopy(ic->ic_des_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 void
+ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
+{
+        struct ieee80211com *ic = (void *)ifp;
+        struct ieee80211_node *ni = NULL;
+
+        imr->ifm_status = IFM_AVALID;
+        imr->ifm_active = IFM_IEEE80211;
+        if (ic->ic_state == IEEE80211_S_RUN)
+                imr->ifm_status |= IFM_ACTIVE;
+        imr->ifm_active |= IFM_AUTO;
+        switch (ic->ic_opmode) {
+        case IEEE80211_M_STA:
+                ni = ic->ic_bss;
+                /* calculate rate subtype */
+                imr->ifm_active |= ieee80211_rate2media(ic,
+                        ni->ni_rates.rs_rates[ni->ni_txrate], ic->ic_curmode);
+                break;
+        case IEEE80211_M_IBSS:
+                ni = ic->ic_bss;
+                /* calculate rate subtype */
+                imr->ifm_active |= ieee80211_rate2media(ic,
+                        ni->ni_rates.rs_rates[ni->ni_txrate], ic->ic_curmode);
+                imr->ifm_active |= IFM_IEEE80211_ADHOC;
+                break;
+        case IEEE80211_M_AHDEMO:
+                /* should not come here */
+                break;
+        case IEEE80211_M_HOSTAP:
+                imr->ifm_active |= IFM_IEEE80211_HOSTAP;
+                break;
+        case IEEE80211_M_MONITOR:
+                imr->ifm_active |= IFM_IEEE80211_MONITOR;
+                break;
+        }
+        switch (ic->ic_curmode) {
+        case IEEE80211_MODE_11A:
+                imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11A);
+                break;
+        case IEEE80211_MODE_11B:
+                imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11B);
+                break;
+        case IEEE80211_MODE_11G:
+                imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11G);
+                break;
+        case IEEE80211_MODE_TURBO:
+                imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11A)
+                                |  IFM_IEEE80211_TURBO;
+                break;
+        }
+}
+
+static int
+ndis_get_assoc(sc, assoc)
+       struct ndis_softc       *sc;
+       ndis_wlan_bssid_ex      **assoc;
+{
+       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);
+       }
+       len = 0;
+       error = ndis_get_info(sc, OID_802_11_BSSID_LIST, NULL, &len);
+       if (error != ENOSPC) {
+               device_printf(sc->ndis_dev, "bssid_list failed\n");
+               return (error);
+       }
+
+       bl = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
+       error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl, &len);
+       if (error) {
+               free(bl, M_TEMP);
+               device_printf(sc->ndis_dev, "bssid_list failed\n");
+               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);
+                       return(0);
+               }       
+               bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
+       }
+
+       free(bl, M_TEMP);
+       return(ENOENT);
+}
+
+static void
+ndis_getstate_80211(sc)
+       struct ndis_softc       *sc;
+{
+       struct ieee80211com     *ic;
+       ndis_80211_ssid         ssid;
+       ndis_80211_config       config;
+       ndis_wlan_bssid_ex      *bs;
+       int                     rval, len, i = 0;
+       uint32_t                arg;
+       struct ifnet            *ifp;
+
+       ic = &sc->ic;
+       ifp = &sc->ic.ic_ac.ac_if;
+
+       if (!NDIS_INITIALIZED(sc))
+               return;
+
+       if (sc->ndis_link)
+               ic->ic_state = IEEE80211_S_RUN;
+       else
+               ic->ic_state = IEEE80211_S_ASSOC;
+
+
+       /*
+        * If we're associated, retrieve info on the current bssid.
+        */
+       if ((rval = ndis_get_assoc(sc, &bs)) == 0) {
+               switch(bs->nwbx_nettype) {
+               case NDIS_80211_NETTYPE_11FH:
+               case NDIS_80211_NETTYPE_11DS:
+                       ic->ic_curmode = IEEE80211_MODE_11B;
+                       break;
+               case NDIS_80211_NETTYPE_11OFDM5:
+                       ic->ic_curmode = IEEE80211_MODE_11A;
+                       break;
+               case NDIS_80211_NETTYPE_11OFDM24:
+                       ic->ic_curmode = IEEE80211_MODE_11G;
+                       break;
+               default:
+                       device_printf(sc->ndis_dev,
+                           "unknown nettype %d\n", arg);
+                       break;
+               }
+               free(bs, M_TEMP);
+       } else
+               return;
+
+       len = sizeof(ssid);
+       bzero((char *)&ssid, len);
+       rval = ndis_get_info(sc, OID_802_11_SSID, &ssid, &len);
+
+       if (rval)
+               device_printf (sc->ndis_dev, "get ssid failed: %d\n", rval);
+       bcopy(ssid.ns_ssid, ic->ic_bss->ni_essid, ssid.ns_ssidlen);
+       ic->ic_bss->ni_esslen = ssid.ns_ssidlen;
+
+       len = sizeof(arg);
+       rval = ndis_get_info(sc, OID_GEN_LINK_SPEED, &arg, &len);
+       if (rval)
+               device_printf (sc->ndis_dev, "get link speed failed: %d\n",
+                   rval);
+
+       if (ic->ic_modecaps & (1<<IEEE80211_MODE_11B)) {
+               ic->ic_bss->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11B];
+               for (i = 0; i < ic->ic_bss->ni_rates.rs_nrates; i++) {
+                       if ((ic->ic_bss->ni_rates.rs_rates[i] &
+                           IEEE80211_RATE_VAL) == arg / 5000)
+                               break;
+               }
+       }
+
+       if (i == ic->ic_bss->ni_rates.rs_nrates &&
+           ic->ic_modecaps & (1<<IEEE80211_MODE_11G)) {
+               ic->ic_bss->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11G];
+               for (i = 0; i < ic->ic_bss->ni_rates.rs_nrates; i++) {
+                       if ((ic->ic_bss->ni_rates.rs_rates[i] &
+                           IEEE80211_RATE_VAL) == arg / 5000)
+                               break;
+               }
+       }
+
+       if (i == ic->ic_bss->ni_rates.rs_nrates)
+               device_printf(sc->ndis_dev, "no matching rate for: %d\n",
+                   arg / 5000);
+       else
+               ic->ic_bss->ni_txrate = i;
+
+       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)
+                       ic->ic_flags &= ~IEEE80211_F_PMGTON;
+               else
+                       ic->ic_flags |= IEEE80211_F_PMGTON;
+       }
+
+       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);   
+       if (rval == 0) { 
+               int chan;
+
+               chan = ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0);
+               if (chan < 0 || chan >= IEEE80211_CHAN_MAX) {
+                       if (ifp->if_flags & IFF_DEBUG)
+                               device_printf(sc->ndis_dev, "current channel "
+                                   "(%uMHz) out of bounds\n", 
+                                   config.nc_dsconfig / 1000);
+                       ic->ic_bss->ni_chan = &ic->ic_channels[1];
+               } else
+                       ic->ic_bss->ni_chan = &ic->ic_channels[chan];
+       } else
+               device_printf(sc->ndis_dev, "couldn't retrieve "
+                   "channel info: %d\n", rval);
+
+/*
+       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)
+               ic->ic_flags |= IEEE80211_F_WEPON;
+       else
+               ic->ic_flags &= ~IEEE80211_F_WEPON;
+*/
+       return;
+}
+
+static int
+ndis_ioctl(ifp, command, data, cr)
+       struct ifnet            *ifp;
+       u_long                  command;
+       caddr_t                 data;
+       struct                  ucred *cr;
+{
+       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 (ifp->if_flags & IFF_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 (ifp->if_flags & IFF_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 (ifp->if_flags & IFF_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:
+               if (sc->ndis_80211) {
+                       error = ieee80211_ioctl(ifp, command, data, cr);
+                       if (error == ENETRESET) {
+                               ndis_setstate_80211(sc);
+                               /*ndis_init(sc);*/
+                               error = 0;
+                       }
+               } else
+                       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;
+       case SIOCGIFGENERIC:
+       case SIOCSIFGENERIC:
+               if (sc->ndis_80211 && NDIS_INITIALIZED(sc)) {
+                       if (command == SIOCGIFGENERIC)
+                               error = ndis_wi_ioctl_get(ifp, command, data);
+                       else
+                               error = ndis_wi_ioctl_set(ifp, command, data);
+               } else
+                       error = ENOTTY;
+               if (error != ENOTTY)
+                       break;
+       default:
+               sc->ndis_skip = 1;
+               if (sc->ndis_80211) {
+                       error = ieee80211_ioctl(ifp, command, data, cr);
+                       if (error == ENETRESET) {
+                               ndis_setstate_80211(sc);
+                               error = 0;
+                       }
+               } else
+                       error = ether_ioctl(ifp, command, data);
+               sc->ndis_skip = 0;
+               break;
+       }
+
+       /*NDIS_UNLOCK(sc);*/
+
+       return(error);
+}
+
+static int
+ndis_wi_ioctl_get(ifp, command, data)
+       struct ifnet            *ifp;
+       u_long                  command;
+       caddr_t                 data;
+{
+       struct wi_req           wreq;
+       struct ifreq            *ifr;
+       struct ndis_softc       *sc;
+       ndis_80211_bssid_list_ex *bl;
+       ndis_wlan_bssid_ex      *wb;
+       struct wi_apinfo        *api;
+       int                     error, i, j, len, maxaps;
+
+       sc = ifp->if_softc;
+       ifr = (struct ifreq *)data;
+       error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
+       if (error)
+               return (error);
+
+       switch (wreq.wi_type) {
+       case WI_RID_READ_APS:
+               len = 0;
+               error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN,
+                   NULL, &len);
+               if (error == 0)
+                       tsleep(&error, PPAUSE|PCATCH, "ssidscan", hz * 2);
+               len = 0;
+               error = ndis_get_info(sc, OID_802_11_BSSID_LIST, NULL, &len);
+               if (error != ENOSPC)
+                       break;
+               bl = malloc(len, M_DEVBUF, M_WAITOK|M_ZERO);
+               error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl, &len);
+               if (error) {
+                       free(bl, M_DEVBUF);
+                       break;
+               }
+               maxaps = (2 * wreq.wi_len - sizeof(int)) / sizeof(*api);
+               maxaps = MIN(maxaps, bl->nblx_items);
+               wreq.wi_len = (maxaps * sizeof(*api) + sizeof(int)) / 2;
+               *(int *)&wreq.wi_val = maxaps;
+               api = (struct wi_apinfo *)&((int *)&wreq.wi_val)[1];
+               wb = bl->nblx_bssid;
+               while (maxaps--) {
+                       bzero(api, sizeof(*api));
+                       bcopy(&wb->nwbx_macaddr, &api->bssid,
+                           sizeof(api->bssid));
+                       api->namelen = wb->nwbx_ssid.ns_ssidlen;
+                       bcopy(&wb->nwbx_ssid.ns_ssid, &api->name, api->namelen);
+                       if (wb->nwbx_privacy)
+                               api->capinfo |= IEEE80211_CAPINFO_PRIVACY;
+                       /* XXX Where can we get noise information? */
+                       api->signal = wb->nwbx_rssi + 149;      /* XXX */
+                       api->quality = api->signal;
+                       api->channel =
+                           ieee80211_mhz2ieee(wb->nwbx_config.nc_dsconfig /
+                           1000, 0);
+                       /* In "auto" infrastructure mode, this is useless. */
+                       if (wb->nwbx_netinfra == NDIS_80211_NET_INFRA_IBSS)
+                               api->capinfo |= IEEE80211_CAPINFO_IBSS;
+                       if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
+                               j = sizeof(ndis_80211_rates_ex);
+                               /* handle other extended things */
+                       } else
+                               j = sizeof(ndis_80211_rates);
+                       for (i = api->rate = 0; i < j; i++)
+                               api->rate = MAX(api->rate, 5 *
+                                   (wb->nwbx_supportedrates[i] & 0x7f));
+                       api++;
+                       wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
+               }
+               free(bl, M_DEVBUF);
+               error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
+               break;
+       default:
+               error = ENOTTY;
+               break;
+       }
+       return (error);
+}
+
+static int
+ndis_wi_ioctl_set(ifp, command, data)
+       struct ifnet            *ifp;
+       u_long                  command;
+       caddr_t                 data;
+{
+       struct wi_req           wreq;
+       struct ifreq            *ifr;
+       struct ndis_softc       *sc;
+       uint32_t                foo;
+       int                     error, len;
+
+       error = suser(curthread);
+       if (error)
+               return (error);
+
+       sc = ifp->if_softc;
+       ifr = (struct ifreq *)data;
+       error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
+       if (error)
+               return (error);
+
+       switch (wreq.wi_type) {
+       case WI_RID_SCAN_APS:
+       case WI_RID_SCAN_REQ:                   /* arguments ignored */
+               len = sizeof(foo);
+               foo = 0;
+               error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, &foo,
+                   &len);
+               break;
+       default:
+               error = ENOTTY;
+               break;
+       }
+       return (error);
+}
+
+static void
+ndis_watchdog(ifp)
+       struct ifnet            *ifp;
+{
+       struct ndis_softc               *sc;
+       NDIS_LOCK_INFO;
+
+       sc = ifp->if_softc;
+
+       NDIS_LOCK(sc);
+       ifp->if_oerrors++;
+       device_printf(sc->ndis_dev, "watchdog timeout\n");
+       NDIS_UNLOCK(sc);
+
+       ndis_reset_nic(sc);
+       ndis_sched(ndis_starttask, ifp, NDIS_TASKQUEUE);
+
+       return;
+}
+
+/*
+ * Stop the adapter and free any mbufs allocated to the
+ * RX and TX lists.
+ */
+static void
+ndis_stop(sc)
+       struct ndis_softc               *sc;
+{
+       struct ifnet            *ifp;
+       NDIS_LOCK_INFO;
+
+       ifp = &sc->arpcom.ac_if;
+       untimeout(ndis_tick, sc, sc->ndis_stat_ch);
+
+       ndis_halt_nic(sc);
+
+       NDIS_LOCK(sc);
+       ifp->if_timer = 0;
+       sc->ndis_link = 0;
+       ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+       NDIS_UNLOCK(sc);
+
+       return;
+}
+
+/*
+ * 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_shutdown_nic(sc);
+
+       return;
+}
diff --git a/sys/dev/netif/ndis/if_ndis_pccard.c b/sys/dev/netif/ndis/if_ndis_pccard.c
new file mode 100644 (file)
index 0000000..97fdfca
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * 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: src/sys/dev/if_ndis/if_ndis_pccard.c,v 1.6 2004/07/11 00:19:30 wpaul Exp $
+ * $DragonFly: src/sys/dev/netif/ndis/if_ndis_pccard.c,v 1.1 2004/07/29 20:51:36 dillon Exp $
+ */
+
+#include <sys/ctype.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_media.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <netproto/802_11/ieee80211_var.h>
+
+#include <emulation/ndis/regcall.h>
+#include <emulation/ndis/pe_var.h>
+#include <emulation/ndis/resource_var.h>
+#include <emulation/ndis/ntoskrnl_var.h>
+#include <emulation/ndis/ndis_var.h>
+#include <emulation/ndis/cfg_var.h>
+#include "if_ndisvar.h"
+
+#include <bus/pccard/pccardvar.h>
+#include "card_if.h"
+
+#include "ndis_driver_data.h"
+
+#ifdef NDIS_PCMCIA_DEV_TABLE 
+
+MODULE_DEPEND(ndis, pccard, 1, 1, 1);
+MODULE_DEPEND(ndis, ether, 1, 1, 1);
+MODULE_DEPEND(ndis, wlan, 1, 1, 1);
+MODULE_DEPEND(ndis, ndisapi, 1, 1, 1);
+
+/*
+ * Various supported device vendors/types and their names.
+ * These are defined in the ndis_driver_data.h file.
+ */
+static struct ndis_pccard_type ndis_devs[] = {
+#ifdef NDIS_PCMCIA_DEV_TABLE
+       NDIS_PCMCIA_DEV_TABLE
+#endif
+       { NULL, NULL, NULL }
+};
+
+static int ndis_probe_pccard   (device_t);
+static int ndis_attach_pccard  (device_t);
+static struct resource_list *ndis_get_resource_list
+                               (device_t, device_t);
+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_pccard),
+       DEVMETHOD(device_attach,        ndis_attach_pccard),
+       DEVMETHOD(device_detach,        ndis_detach),
+       DEVMETHOD(device_shutdown,      ndis_shutdown),
+       DEVMETHOD(device_suspend,       ndis_suspend),
+       DEVMETHOD(device_resume,        ndis_resume),
+
+       /* Bus interface. */
+
+       /*
+        * This is an awful kludge, but we need it becase pccard
+        * does not implement a bus_get_resource_list() method.
+        */
+
+       DEVMETHOD(bus_get_resource_list, ndis_get_resource_list),
+
+       { 0, 0 }
+};
+
+static driver_t ndis_driver = {
+#ifdef NDIS_DEVNAME
+       NDIS_DEVNAME,
+#else
+       "ndis",
+#endif
+       ndis_methods,
+       sizeof(struct ndis_softc)
+};
+
+static devclass_t ndis_devclass;
+
+#ifdef NDIS_MODNAME
+#define NDIS_MODNAME_OVERRIDE_PCMCIA(x)                                        \
+       DRIVER_MODULE(x, pccard, ndis_driver, ndis_devclass, 0, 0)
+NDIS_MODNAME_OVERRIDE_PCMCIA(NDIS_MODNAME);
+#else
+DRIVER_MODULE(ndis, pccard, ndis_driver, ndis_devclass, 0, 0);
+#endif
+
+/*
+ * 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_pccard(dev)
+       device_t                dev;
+{
+       struct ndis_pccard_type *t;
+       const char              *prodstr, *vendstr;
+       int                     error;
+
+       t = ndis_devs;
+
+       error = pccard_get_product_str(dev, &prodstr);
+       if (error)
+               return(error);
+       error = pccard_get_vendor_str(dev, &vendstr);
+       if (error)
+               return(error);
+
+       while(t->ndis_name != NULL) {
+               if (ndis_strcasecmp(vendstr, t->ndis_vid) == 0 &&
+                   ndis_strcasecmp(prodstr, t->ndis_did) == 0) {
+                       device_set_desc(dev, t->ndis_name);
+                       return(0);
+               }
+               t++;
+       }
+
+       return(ENXIO);
+}
+
+/*
+ * Attach the interface. Allocate softc structures, do ifmedia
+ * setup and ethernet/BPF attach.
+ */
+static int
+ndis_attach_pccard(dev)
+       device_t                dev;
+{
+       struct ndis_softc       *sc;
+       int                     unit, error = 0, rid;
+       struct ndis_pccard_type *t;
+       int                     devidx = 0;
+       const char              *prodstr, *vendstr;
+
+       sc = device_get_softc(dev);
+       unit = device_get_unit(dev);
+       sc->ndis_dev = dev;
+       resource_list_init(&sc->ndis_rl);
+
+       sc->ndis_io_rid = 0;
+       sc->ndis_res_io = bus_alloc_resource(dev,
+           SYS_RES_IOPORT, &sc->ndis_io_rid,
+           0, ~0, 1, RF_ACTIVE);
+       if (sc->ndis_res_io == NULL) {
+               device_printf(dev,
+                   "couldn't map iospace\n");
+               error = ENXIO;
+               goto fail;
+       }
+       sc->ndis_rescnt++;
+       resource_list_add(&sc->ndis_rl, SYS_RES_IOPORT, rid,
+           rman_get_start(sc->ndis_res_io), rman_get_end(sc->ndis_res_io),
+           rman_get_size(sc->ndis_res_io));
+
+       rid = 0;
+       sc->ndis_irq = bus_alloc_resource(dev,
+           SYS_RES_IRQ, &rid, 0, ~0, 1,
+           RF_SHAREABLE | RF_ACTIVE);
+       if (sc->ndis_irq == NULL) {
+               device_printf(dev,
+                   "couldn't map interrupt\n");
+               error = ENXIO;
+               goto fail;
+       }
+       sc->ndis_rescnt++;
+       resource_list_add(&sc->ndis_rl, SYS_RES_IRQ, rid,
+           rman_get_start(sc->ndis_irq), rman_get_start(sc->ndis_irq), 1);
+
+       sc->ndis_iftype = PCMCIABus;
+
+       /* Figure out exactly which device we matched. */
+
+       t = ndis_devs;
+
+       error = pccard_get_product_str(dev, &prodstr);
+       if (error)
+               return(error);
+       error = pccard_get_vendor_str(dev, &vendstr);
+       if (error)
+               return(error);
+
+       while(t->ndis_name != NULL) {
+               if (ndis_strcasecmp(vendstr, t->ndis_vid) == 0 &&
+                   ndis_strcasecmp(prodstr, t->ndis_did) == 0)
+                       break;
+               t++;
+               devidx++;
+       }
+
+       sc->ndis_devidx = devidx;
+
+       error = ndis_attach(dev);
+
+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 (&sc->ndis_rl);
+}
+
+#endif /* NDIS_PCI_DEV_TABLE */
+
+#define NDIS_AM_RID 3
+
+int
+ndis_alloc_amem(arg)
+       void                    *arg;
+{
+       struct ndis_softc       *sc;
+       int                     error, rid;
+
+       if (arg == NULL)
+               return(EINVAL);
+
+       sc = arg;
+       rid = NDIS_AM_RID;
+       sc->ndis_res_am = bus_alloc_resource(sc->ndis_dev, SYS_RES_MEMORY,
+           &rid, 0UL, ~0UL, 0x1000, RF_ACTIVE);
+
+       if (sc->ndis_res_am == NULL) {
+               device_printf(sc->ndis_dev,
+                   "failed to allocate attribute memory\n");
+               return(ENXIO);
+       }
+       sc->ndis_rescnt++;
+       resource_list_add(&sc->ndis_rl, SYS_RES_MEMORY, rid,
+           rman_get_start(sc->ndis_res_am), rman_get_end(sc->ndis_res_am),
+           rman_get_size(sc->ndis_res_am));
+
+       error = CARD_SET_MEMORY_OFFSET(device_get_parent(sc->ndis_dev),
+           sc->ndis_dev, rid, 0, NULL);
+
+       if (error) {
+               device_printf(sc->ndis_dev,
+                   "CARD_SET_MEMORY_OFFSET() returned 0x%x\n", error);
+               return(error);
+       }
+
+       error = CARD_SET_RES_FLAGS(device_get_parent(sc->ndis_dev),
+           sc->ndis_dev, SYS_RES_MEMORY, rid, PCCARD_A_MEM_ATTR);
+
+       if (error) {
+               device_printf(sc->ndis_dev,
+                   "CARD_SET_RES_FLAGS() returned 0x%x\n", error);
+               return(error);
+       }
+
+       sc->ndis_am_rid = rid;
+
+       return(0);
+}
+
+void
+ndis_free_amem(arg)
+       void                    *arg;
+{
+       struct ndis_softc       *sc;
+
+       if (arg == NULL)
+               return;
+
+       sc = arg;
+
+       if (sc->ndis_res_am != NULL)
+               bus_release_resource(sc->ndis_dev, SYS_RES_MEMORY,
+                   sc->ndis_am_rid, sc->ndis_res_am);
+       resource_list_free(&sc->ndis_rl);
+
+       return;
+}
diff --git a/sys/dev/netif/ndis/if_ndis_pci.c b/sys/dev/netif/ndis/if_ndis_pci.c
new file mode 100644 (file)
index 0000000..835cc3f
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+ * 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: src/sys/dev/if_ndis/if_ndis_pci.c,v 1.7 2004/07/11 00:19:30 wpaul Exp $
+ * $DragonFly: src/sys/dev/netif/ndis/if_ndis_pci.c,v 1.1 2004/07/29 20:51:36 dillon Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_media.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <netproto/802_11/ieee80211_var.h>
+
+#include <bus/pci/pcireg.h>
+#include <bus/pci/pcivar.h>
+
+#include <emulation/ndis/regcall.h>
+#include <emulation/ndis/pe_var.h>
+#include <emulation/ndis/resource_var.h>
+#include <emulation/ndis/ntoskrnl_var.h>
+#include <emulation/ndis/ndis_var.h>
+#include <emulation/ndis/cfg_var.h>
+#include "if_ndisvar.h"
+
+#include "ndis_driver_data.h"
+
+#ifdef NDIS_PCI_DEV_TABLE 
+
+MODULE_DEPEND(ndis, pci, 1, 1, 1);
+MODULE_DEPEND(ndis, ether, 1, 1, 1);
+MODULE_DEPEND(ndis, wlan, 1, 1, 1);
+MODULE_DEPEND(ndis, ndisapi, 1, 1, 1);
+
+/*
+ * Various supported device vendors/types and their names.
+ * These are defined in the ndis_driver_data.h file.
+ */
+static struct ndis_pci_type ndis_devs[] = {
+#ifdef NDIS_PCI_DEV_TABLE
+       NDIS_PCI_DEV_TABLE
+#endif
+       { 0, 0, 0, NULL }
+};
+
+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);
+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 = {
+#ifdef NDIS_DEVNAME
+       NDIS_DEVNAME,
+#else
+       "ndis",
+#endif
+       ndis_methods,
+       sizeof(struct ndis_softc)
+};
+
+static devclass_t ndis_devclass;
+
+#ifdef NDIS_MODNAME
+#define NDIS_MODNAME_OVERRIDE_PCI(x)                                   \
+       DRIVER_MODULE(x, pci, ndis_driver, ndis_devclass, 0, 0)
+#define NDIS_MODNAME_OVERRIDE_CARDBUS(x)                               \
+       DRIVER_MODULE(x, cardbus, ndis_driver, ndis_devclass, 0, 0)
+NDIS_MODNAME_OVERRIDE_PCI(NDIS_MODNAME);
+NDIS_MODNAME_OVERRIDE_CARDBUS(NDIS_MODNAME);
+#else
+DRIVER_MODULE(ndis, pci, ndis_driver, ndis_devclass, 0, 0);
+DRIVER_MODULE(ndis, cardbus, ndis_driver, ndis_devclass, 0, 0);
+#endif
+
+/*
+ * 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;
+{
+       struct ndis_pci_type    *t;
+
+       t = ndis_devs;
+
+       while(t->ndis_name != NULL) {
+               if ((pci_get_vendor(dev) == t->ndis_vid) &&
+                   (pci_get_device(dev) == t->ndis_did) &&
+                   ((pci_read_config(dev, PCIR_SUBVEND_0, 4) ==
+                   t->ndis_subsys) || t->ndis_subsys == 0)) {
+                       device_set_desc(dev, t->ndis_name);
+                       return(0);
+               }
+               t++;
+       }
+
+       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;
+
+       sc = device_get_softc(dev);
+       unit = device_get_unit(dev);
+       sc->ndis_dev = dev;
+
+       /*
+        * Map control/status registers.
+        */
+
+       pci_enable_busmaster(dev);
+
+       rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
+       if (rl != NULL) {
+               SLIST_FOREACH(rle, rl, link) {
+                       switch (rle->type) {
+                       case SYS_RES_IOPORT:
+                               sc->ndis_io_rid = rle->rid;
+                               sc->ndis_res_io = bus_alloc_resource(dev,
+                                   SYS_RES_IOPORT, &sc->ndis_io_rid,
+                                   0, ~0, 1, 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 (rle->rid == PCIR_BAR(2)) {
+                                       sc->ndis_altmem_rid = rle->rid;
+                                       sc->ndis_res_altmem =
+                                           bus_alloc_resource(dev,
+                                               SYS_RES_MEMORY,
+                                               &sc->ndis_altmem_rid,
+                                               0, ~0, 1, 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(dev,
+                                               SYS_RES_MEMORY,
+                                               &sc->ndis_mem_rid,
+                                               0, ~0, 1, 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(dev,
+                                   SYS_RES_IRQ, &rid, 0, ~0, 1,
+                                   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(dev, SYS_RES_IRQ,
+                   &rid, 0, ~0, 1, 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(NULL,        /* parent */
+                       1, 0,                   /* alignment, boundary */
+                       BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+                        BUS_SPACE_MAXADDR,     /* highaddr */
+                       NULL, NULL,             /* filter, filterarg */
+                       MAXBSIZE, NDIS_NSEG_NEW,/* maxsize, nsegments */
+                       BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
+                       BUS_DMA_ALLOCNOW,       /* flags */
+                       &sc->ndis_parent_tag);
+
+        if (error)
+                goto fail;
+
+       sc->ndis_iftype = PCIBus;
+
+       /* Figure out exactly which device we matched. */
+
+       t = ndis_devs;
+
+       while(t->ndis_name != NULL) {
+               if ((pci_get_vendor(dev) == t->ndis_vid) &&
+                   (pci_get_device(dev) == t->ndis_did)) {
+                       if (t->ndis_subsys == 0)
+                               defidx = devidx;
+                       else {
+                               if (t->ndis_subsys ==
+                                   pci_read_config(dev, PCIR_SUBVEND_0, 4))
+                                       break;
+                       }
+               }
+               t++;
+               devidx++;
+       }
+
+       if (ndis_devs[devidx].ndis_name == NULL)
+               sc->ndis_devidx = defidx;
+       else
+               sc->ndis_devidx = devidx;
+
+       error = ndis_attach(dev);
+
+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));
+}
+
+#endif /* NDIS_PCI_DEV_TABLE */
diff --git a/sys/dev/netif/ndis/if_ndisvar.h b/sys/dev/netif/ndis/if_ndisvar.h
new file mode 100644 (file)
index 0000000..0fb2af1
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * 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: src/sys/dev/if_ndis/if_ndisvar.h,v 1.15 2004/07/11 00:19:30 wpaul Exp $
+ * $DragonFly: src/sys/dev/netif/ndis/if_ndisvar.h,v 1.1 2004/07/29 20:51:36 dillon Exp $
+ */
+
+#define NDIS_DEFAULT_NODENAME  "FreeBSD NDIS node"
+#define NDIS_NODENAME_LEN      32
+
+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_shmem {
+       bus_dma_tag_t           ndis_stag;
+       bus_dmamap_t            ndis_smap;
+       void                    *ndis_saddr;
+       struct ndis_shmem       *ndis_next;
+};
+
+struct ndis_cfglist {
+       ndis_cfg                ndis_cfg;
+        TAILQ_ENTRY(ndis_cfglist)      link;
+};
+
+TAILQ_HEAD(nch, ndis_cfglist);
+
+#define NDIS_INITIALIZED(sc)   (sc->ndis_block.nmb_miniportadapterctx != NULL)
+
+#define NDIS_INC(x)            \
+       (x)->ndis_txidx = ((x)->ndis_txidx + 1) % (x)->ndis_maxpkts 
+
+#define arpcom ic.ic_ac
+
+struct ndis_softc {
+       struct ieee80211com     ic;             /* interface info */
+#ifdef notdef
+       struct ieee80211com     arpcom;         /* interface info */
+#endif
+       struct ifmedia          ifmedia;        /* media info */
+       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 lwkt_token       ndis_lock;
+       struct lwkt_token       ndis_intrlock;
+       device_t                ndis_dev;
+       int                     ndis_unit;
+       ndis_miniport_block     ndis_block;
+       ndis_miniport_characteristics   ndis_chars;
+       interface_type          ndis_type;
+       struct callout_handle   ndis_stat_ch;
+       int                     ndis_maxpkts;
+       ndis_oid                *ndis_oids;
+       int                     ndis_oidcnt;
+       int                     ndis_txidx;
+       int                     ndis_txpending;
+       ndis_packet             **ndis_txarray;
+       int                     ndis_sc;
+       ndis_cfg                *ndis_regvals;
+       struct nch              ndis_cfglist_head;
+       int                     ndis_80211;
+       int                     ndis_link;
+       uint32_t                ndis_filter;
+       int                     ndis_if_flags;
+       int                     ndis_skip;
+
+#if __FreeBSD_version < 502113
+       struct sysctl_ctx_list  ndis_ctx;
+       struct sysctl_oid       *ndis_tree;
+#endif
+       int                     ndis_devidx;
+       interface_type          ndis_iftype;
+
+       bus_dma_tag_t           ndis_parent_tag;
+       struct ndis_shmem       *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;
+};
+
+#define NDIS_LOCK_INFO         struct lwkt_tokref tokinfo
+#define NDIS_LOCK_INIT(tok)    lwkt_token_init(tok)
+#define NDIS_LOCK_DESTROY(tok) lwkt_token_uninit(tok)
+#define NDIS_LOCK(_sc)         lwkt_gettoken(&tokinfo, &(_sc)->ndis_lock)
+#define NDIS_INTRLOCK(_sc)     lwkt_gettoken(&tokinfo, &(_sc)->ndis_intrlock)
+#define NDIS_UNLOCK(_sc)       lwkt_reltoken(&tokinfo)
+#define NDIS_INTRUNLOCK(_sc)   lwkt_reltoken(&tokinfo)
+
index bb70cbf..32f462a 100644 (file)
@@ -1,6 +1,6 @@
-# $DragonFly: src/sys/emulation/Makefile,v 1.1 2003/08/15 07:32:28 dillon Exp $
+# $DragonFly: src/sys/emulation/Makefile,v 1.2 2004/07/29 20:51:32 dillon Exp $
 #
 
-SUBDIR=ibcs2 linux svr4
+SUBDIR=ibcs2 linux svr4 ndis
 
 .include <bsd.subdir.mk>
diff --git a/sys/emulation/ndis/Makefile b/sys/emulation/ndis/Makefile
new file mode 100644 (file)
index 0000000..8d42521
--- /dev/null
@@ -0,0 +1,9 @@
+# $DragonFly: src/sys/emulation/ndis/Makefile,v 1.1 2004/07/29 20:51:33 dillon Exp $
+#
+
+KMOD=  ndis
+SRCS=  subr_pe.c subr_ndis.c subr_hal.c subr_ntoskrnl.c kern_ndis.c
+SRCS+= opt_bdg.h device_if.h bus_if.h pci_if.h vnode_if.h
+
+.include <bsd.kmod.mk>
+
diff --git a/sys/emulation/ndis/cfg_var.h b/sys/emulation/ndis/cfg_var.h
new file mode 100644 (file)
index 0000000..1da6d61
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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: src/sys/compat/ndis/cfg_var.h,v 1.2 2003/12/18 03:51:21 wpaul Exp $
+ * $DragonFly: src/sys/emulation/ndis/cfg_var.h,v 1.1 2004/07/29 20:51:33 dillon Exp $
+ */
+
+#ifndef _CFG_VAR_H_
+#define _CFG_VAR_H_
+
+struct ndis_cfg {
+       char                    *nc_cfgkey;
+       char                    *nc_cfgdesc;
+       char                    nc_val[256];
+       int                     nc_idx;
+};
+
+typedef struct ndis_cfg ndis_cfg;
+
+#endif /* _CFG_VAR_H_ */
diff --git a/sys/emulation/ndis/hal_var.h b/sys/emulation/ndis/hal_var.h
new file mode 100644 (file)
index 0000000..738ab90
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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: src/sys/compat/ndis/hal_var.h,v 1.3 2004/04/14 07:48:02 wpaul Exp $
+ * $DragonFly: src/sys/emulation/ndis/hal_var.h,v 1.1 2004/07/29 20:51:33 dillon Exp $
+ */
+
+#ifndef _HAL_VAR_H_
+#define _HAL_VAR_H_
+
+#ifdef __amd64__
+#define NDIS_BUS_SPACE_IO      AMD64_BUS_SPACE_IO
+#define NDIS_BUS_SPACE_MEM     AMD64_BUS_SPACE_MEM
+#else
+#define NDIS_BUS_SPACE_IO      I386_BUS_SPACE_IO
+#define NDIS_BUS_SPACE_MEM     I386_BUS_SPACE_MEM
+#endif
+
+extern image_patch_table hal_functbl[];
+
+__BEGIN_DECLS
+__stdcall __regcall uint8_t hal_lock(REGARGS1(kspin_lock *lock));
+__stdcall __regcall void hal_unlock(REGARGS2(kspin_lock *lock, uint8_t newirql));
+__stdcall uint8_t hal_irql(void);
+__stdcall __regcall uint8_t hal_raise_irql(REGARGS1(uint8_t irql));
+__stdcall __regcall void hal_lower_irql(REGARGS1(uint8_t oldirql));
+__END_DECLS
+
+#endif /* _HAL_VAR_H_ */
+
+
diff --git a/sys/emulation/ndis/kern_ndis.c b/sys/emulation/ndis/kern_ndis.c
new file mode 100644 (file)
index 0000000..fa8d372
--- /dev/null
@@ -0,0 +1,1708 @@
+/*
+ * 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: src/sys/compat/ndis/kern_ndis.c,v 1.57 2004/07/11 00:19:30 wpaul Exp $
+ * $DragonFly: src/sys/emulation/ndis/kern_ndis.c,v 1.1 2004/07/29 20:51:33 dillon Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/unistd.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/callout.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/conf.h>
+
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/kthread.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+
+#include <netproto/802_11/ieee80211_var.h>
+#include <netproto/802_11/ieee80211_ioctl.h>
+
+#include "regcall.h"
+#include "pe_var.h"
+#include "resource_var.h"
+#include "ntoskrnl_var.h"
+#include "ndis_var.h"
+#include "hal_var.h"
+#include "cfg_var.h"
+#include <dev/netif/ndis/if_ndisvar.h>
+
+#define NDIS_DUMMY_PATH "\\\\some\\bogus\\path"
+
+__stdcall static void ndis_status_func(ndis_handle, ndis_status,
+       void *, uint32_t);
+__stdcall static void ndis_statusdone_func(ndis_handle);
+__stdcall static void ndis_setdone_func(ndis_handle, ndis_status);
+__stdcall static void ndis_getdone_func(ndis_handle, ndis_status);
+__stdcall static void ndis_resetdone_func(ndis_handle, ndis_status, uint8_t);
+__stdcall static void ndis_sendrsrcavail_func(ndis_handle);
+
+struct nd_head ndis_devhead;
+
+struct ndis_req {
+       void                    (*nr_func)(void *);
+       void                    *nr_arg;
+       int                     nr_exit;
+       STAILQ_ENTRY(ndis_req)  link;
+};
+
+struct ndisproc {
+       struct ndisqhead        *np_q;
+       struct thread           *np_td;
+       int                     np_state;
+};
+
+static void ndis_return(void *);
+static int ndis_create_kthreads(void);
+static void ndis_destroy_kthreads(void);
+static void ndis_stop_thread(int);
+static int ndis_enlarge_thrqueue(int);
+static int ndis_shrink_thrqueue(int);
+static void ndis_runq(void *);
+
+static MALLOC_DEFINE(M_NDIS_PACKET, "ndis_packet", "ndis packet slosh");
+static MALLOC_DEFINE(M_NDIS_BUFFER, "ndis_buffer", "ndis buffer slosh");
+struct lwkt_token ndis_thr_token;
+static STAILQ_HEAD(ndisqhead, ndis_req) ndis_ttodo;
+struct ndisqhead ndis_itodo;
+struct ndisqhead ndis_free;
+static int ndis_jobs = 32;
+
+static struct ndisproc ndis_tproc;
+static struct ndisproc ndis_iproc;
+
+/*
+ * This allows us to export our symbols to other modules.
+ * Note that we call ourselves 'ndisapi' to avoid a namespace
+ * collision with if_ndis.ko, which internally calls itself
+ * 'ndis.'
+ */
+static int
+ndis_modevent(module_t mod, int cmd, void *arg)
+{
+       int                     error = 0;
+
+       switch (cmd) {
+       case MOD_LOAD:
+               /* Initialize subsystems */
+               ndis_libinit();
+               ntoskrnl_libinit();
+
+               /* Initialize TX buffer UMA zone. */
+               ndis_create_kthreads();
+
+               TAILQ_INIT(&ndis_devhead);
+
+               break;
+       case MOD_SHUTDOWN:
+               /* stop kthreads */
+               ndis_destroy_kthreads();
+               if (TAILQ_FIRST(&ndis_devhead) == NULL) {
+                       /* Shut down subsystems */
+                       ndis_libfini();
+                       ntoskrnl_libfini();
+
+                       /* Remove zones */
+#if 0  /* YYY */
+                       malloc_uninit(M_NDIS_PACKET);
+                       malloc_uninit(M_NDIS_BUFFER);
+#endif
+               }
+               break;
+       case MOD_UNLOAD:
+               /* stop kthreads */
+               ndis_destroy_kthreads();
+
+               /* Shut down subsystems */
+               ndis_libfini();
+               ntoskrnl_libfini();
+
+               /* Remove zones */
+#if 0  /* YYY */
+               malloc_uninit(M_NDIS_PACKET);
+               malloc_uninit(M_NDIS_BUFFER);
+#endif
+               break;
+       default:
+               error = EINVAL;
+               break;
+       }
+
+       return(error);
+}
+DEV_MODULE(ndisapi, ndis_modevent, NULL);
+MODULE_VERSION(ndisapi, 1);
+
+/*
+ * We create two kthreads for the NDIS subsystem. One of them is a task
+ * queue for performing various odd jobs. The other is an swi thread
+ * reserved exclusively for running interrupt handlers. The reason we
+ * have our own task queue is that there are some cases where we may
+ * need to sleep for a significant amount of time, and if we were to
+ * use one of the taskqueue threads, we might delay the processing
+ * of other pending tasks which might need to run right away. We have
+ * a separate swi thread because we don't want our interrupt handling
+ * to be delayed either.
+ *
+ * By default there are 32 jobs available to start, and another 8
+ * are added to the free list each time a new device is created.
+ */
+
+static void
+ndis_runq(arg)
+       void                    *arg;
+{
+       struct ndis_req         *r = NULL, *die = NULL;
+       struct ndisproc         *p;
+       struct lwkt_tokref      tokref;
+
+       p = arg;
+
+       while (1) {
+
+               /* Sleep, but preserve our original priority. */
+               ndis_thsuspend(p->np_td, 0);
+
+               /* Look for any jobs on the work queue. */
+
+               lwkt_gettoken(&tokref, &ndis_thr_token);
+               p->np_state = NDIS_PSTATE_RUNNING;
+               while(STAILQ_FIRST(p->np_q) != NULL) {
+                       r = STAILQ_FIRST(p->np_q);
+                       STAILQ_REMOVE_HEAD(p->np_q, link);
+                       lwkt_reltoken(&tokref);
+
+                       /* Do the work. */
+
+                       if (r->nr_func != NULL)
+                               (*r->nr_func)(r->nr_arg);
+
+                       lwkt_gettoken(&tokref, &ndis_thr_token);
+                       STAILQ_INSERT_HEAD(&ndis_free, r, link);
+
+                       /* Check for a shutdown request */
+
+                       if (r->nr_exit == TRUE)
+                               die = r;
+               }
+               p->np_state = NDIS_PSTATE_SLEEPING;
+               lwkt_reltoken(&tokref);
+
+               /* Bail if we were told to shut down. */
+
+               if (die != NULL)
+                       break;
+       }
+
+       wakeup(die);
+       kthread_exit();
+}
+
+static int
+ndis_create_kthreads()
+{
+       struct ndis_req         *r;
+       int                     i, error = 0;
+
+       lwkt_token_init(&ndis_thr_token);
+
+       STAILQ_INIT(&ndis_ttodo);
+       STAILQ_INIT(&ndis_itodo);
+       STAILQ_INIT(&ndis_free);
+
+       for (i = 0; i < ndis_jobs; i++) {
+               r = malloc(sizeof(struct ndis_req), M_DEVBUF, M_WAITOK);
+               if (r == NULL) {
+                       error = ENOMEM;
+                       break;
+               }
+               STAILQ_INSERT_HEAD(&ndis_free, r, link);
+       }
+
+       if (error == 0) {
+               ndis_tproc.np_q = &ndis_ttodo;
+               ndis_tproc.np_state = NDIS_PSTATE_SLEEPING;
+               error = kthread_create_stk(ndis_runq, &ndis_tproc,
+                   &ndis_tproc.np_td, NDIS_KSTACK_PAGES * PAGE_SIZE,
+                   "ndis taskqueue");
+       }
+
+       if (error == 0) {
+               ndis_iproc.np_q = &ndis_itodo;
+               ndis_iproc.np_state = NDIS_PSTATE_SLEEPING;
+               error = kthread_create_stk(ndis_runq, &ndis_iproc,
+                   &ndis_iproc.np_td, NDIS_KSTACK_PAGES * PAGE_SIZE,
+                   "ndis swi");
+       }
+
+       if (error) {
+               while ((r = STAILQ_FIRST(&ndis_free)) != NULL) {
+                       STAILQ_REMOVE_HEAD(&ndis_free, link);
+                       free(r, M_DEVBUF);
+               }
+               return(error);
+       }
+
+       return(0);
+}
+
+static void
+ndis_destroy_kthreads()
+{
+       struct ndis_req         *r;
+
+       /* Stop the threads. */
+
+       ndis_stop_thread(NDIS_TASKQUEUE);
+       ndis_stop_thread(NDIS_SWI);
+
+       /* Destroy request structures. */
+
+       while ((r = STAILQ_FIRST(&ndis_free)) != NULL) {
+               STAILQ_REMOVE_HEAD(&ndis_free, link);
+               free(r, M_DEVBUF);
+       }
+
+       lwkt_token_uninit(&ndis_thr_token);
+
+       return;
+}
+
+static void
+ndis_stop_thread(t)
+       int                     t;
+{
+       struct ndis_req         *r;
+       struct ndisqhead        *q;
+       thread_t                td;
+       struct lwkt_tokref      tokref;
+
+       if (t == NDIS_TASKQUEUE) {
+               q = &ndis_ttodo;
+               td = ndis_tproc.np_td;
+       } else {
+               q = &ndis_itodo;
+               td = ndis_iproc.np_td;
+       }
+
+       /* Create and post a special 'exit' job. */
+
+       lwkt_gettoken(&tokref, &ndis_thr_token);
+       r = STAILQ_FIRST(&ndis_free);
+       STAILQ_REMOVE_HEAD(&ndis_free, link);
+       r->nr_func = NULL;
+       r->nr_arg = NULL;
+       r->nr_exit = TRUE;
+       STAILQ_INSERT_TAIL(q, r, link);
+       lwkt_reltoken(&tokref);
+
+       ndis_thresume(td);
+
+       /* wait for thread exit */
+
+       tsleep(r, PCATCH, "ndisthexit", hz * 60);
+
+       /* Now empty the job list. */
+
+       lwkt_gettoken(&tokref, &ndis_thr_token);
+       while ((r = STAILQ_FIRST(q)) != NULL) {
+               STAILQ_REMOVE_HEAD(q, link);
+               STAILQ_INSERT_HEAD(&ndis_free, r, link);
+       }
+       lwkt_reltoken(&tokref);
+
+       return;
+}
+
+static int
+ndis_enlarge_thrqueue(cnt)
+       int                     cnt;
+{
+       struct ndis_req         *r;
+       int                     i;
+       struct lwkt_tokref      tokref;
+
+       for (i = 0; i < cnt; i++) {
+               r = malloc(sizeof(struct ndis_req), M_DEVBUF, M_WAITOK);
+               if (r == NULL)
+                       return(ENOMEM);
+               lwkt_gettoken(&tokref, &ndis_thr_token);
+               STAILQ_INSERT_HEAD(&ndis_free, r, link);
+               ndis_jobs++;
+               lwkt_reltoken(&tokref);
+       }
+
+       return(0);
+}
+
+static int
+ndis_shrink_thrqueue(cnt)
+       int                     cnt;
+{
+       struct ndis_req         *r;
+       int                     i;
+       struct lwkt_tokref      tokref;
+
+       for (i = 0; i < cnt; i++) {
+               lwkt_gettoken(&tokref, &ndis_thr_token);
+               r = STAILQ_FIRST(&ndis_free);
+               if (r == NULL) {
+                       lwkt_reltoken(&tokref);
+                       return(ENOMEM);
+               }
+               STAILQ_REMOVE_HEAD(&ndis_free, link);
+               ndis_jobs--;
+               lwkt_reltoken(&tokref);
+               free(r, M_DEVBUF);
+       }
+
+       return(0);
+}
+
+int
+ndis_unsched(func, arg, t)
+       void                    (*func)(void *);
+       void                    *arg;
+       int                     t;
+{
+       struct ndis_req         *r;
+       struct ndisqhead        *q;
+       thread_t                td;
+       struct lwkt_tokref      tokref;
+
+       if (t == NDIS_TASKQUEUE) {
+               q = &ndis_ttodo;
+               td = ndis_tproc.np_td;
+       } else {
+               q = &ndis_itodo;
+               td = ndis_iproc.np_td;
+       }
+
+       lwkt_gettoken(&tokref, &ndis_thr_token);
+       STAILQ_FOREACH(r, q, link) {
+               if (r->nr_func == func && r->nr_arg == arg) {
+                       STAILQ_REMOVE(q, r, ndis_req, link);
+                       STAILQ_INSERT_HEAD(&ndis_free, r, link);
+                       lwkt_reltoken(&tokref);
+                       return(0);
+               }
+       }
+
+       lwkt_reltoken(&tokref);
+
+       return(ENOENT);
+}
+
+int
+ndis_sched(func, arg, t)
+       void                    (*func)(void *);
+       void                    *arg;
+       int                     t;
+{
+       struct ndis_req         *r;
+       struct ndisqhead        *q;
+       thread_t                td;
+       int                     s;
+       struct lwkt_tokref      tokref;
+
+       if (t == NDIS_TASKQUEUE) {
+               q = &ndis_ttodo;
+               td = ndis_tproc.np_td;
+       } else {
+               q = &ndis_itodo;
+               td = ndis_iproc.np_td;
+       }
+
+       lwkt_gettoken(&tokref, &ndis_thr_token);
+       /*
+        * Check to see if an instance of this job is already
+        * pending. If so, don't bother queuing it again.
+        */
+       STAILQ_FOREACH(r, q, link) {
+               if (r->nr_func == func && r->nr_arg == arg) {
+                       lwkt_reltoken(&tokref);
+                       return(0);
+               }
+       }
+       r = STAILQ_FIRST(&ndis_free);
+       if (r == NULL) {
+               lwkt_reltoken(&tokref);
+               return(EAGAIN);
+       }
+       STAILQ_REMOVE_HEAD(&ndis_free, link);
+       r->nr_func = func;
+       r->nr_arg = arg;
+       r->nr_exit = FALSE;
+       STAILQ_INSERT_TAIL(q, r, link);
+       if (t == NDIS_TASKQUEUE)
+               s = ndis_tproc.np_state;
+       else
+               s = ndis_iproc.np_state;
+       lwkt_reltoken(&tokref);
+
+       /*
+        * Post the job, but only if the thread is actually blocked
+        * on its own suspend call. If a driver queues up a job with
+        * NdisScheduleWorkItem() which happens to do a KeWaitForObject(),
+        * it may suspend there, and in that case we don't want to wake
+        * it up until KeWaitForObject() gets woken up on its own.
+        */
+       if (s == NDIS_PSTATE_SLEEPING)
+               ndis_thresume(td);
+
+       return(0);
+}
+
+int
+ndis_thsuspend(td, timo)
+       thread_t                td;
+       int                     timo;
+{
+       int                     error;
+
+       error = tsleep(td, 0, "ndissp", timo);
+       return(error);
+}
+
+void
+ndis_thresume(td)
+       struct thread           *td;
+{
+       wakeup(td);
+}
+
+__stdcall static void
+ndis_sendrsrcavail_func(adapter)
+       ndis_handle             adapter;
+{
+       return;
+}
+
+__stdcall static void
+ndis_status_func(adapter, status, sbuf, slen)
+       ndis_handle             adapter;
+       ndis_status             status;
+       void                    *sbuf;
+       uint32_t                slen;
+{
+       ndis_miniport_block     *block;
+       block = adapter;
+
+       if (block->nmb_ifp->if_flags & IFF_DEBUG)
+               device_printf (block->nmb_dev, "status: %x\n", status);
+       return;
+}
+
+__stdcall static void
+ndis_statusdone_func(adapter)
+       ndis_handle             adapter;
+{
+       ndis_miniport_block     *block;
+       block = adapter;
+       
+       if (block->nmb_ifp->if_flags & IFF_DEBUG)
+               device_printf (block->nmb_dev, "status complete\n");
+       return;
+}
+
+__stdcall static void
+ndis_setdone_func(adapter, status)
+       ndis_handle             adapter;
+       ndis_status             status;
+{
+       ndis_miniport_block     *block;
+       block = adapter;
+
+       block->nmb_setstat = status;
+       wakeup(&block->nmb_wkupdpctimer);
+       return;
+}
+
+__stdcall static void
+ndis_getdone_func(adapter, status)
+       ndis_handle             adapter;
+       ndis_status             status;
+{
+       ndis_miniport_block     *block;
+       block = adapter;
+
+       block->nmb_getstat = status;
+       wakeup(&block->nmb_wkupdpctimer);
+       return;
+}
+
+__stdcall static void
+ndis_resetdone_func(adapter, status, addressingreset)
+       ndis_handle             adapter;
+       ndis_status             status;
+       uint8_t                 addressingreset;
+{
+       ndis_miniport_block     *block;
+       block = adapter;
+
+       if (block->nmb_ifp->if_flags & IFF_DEBUG)
+               device_printf (block->nmb_dev, "reset done...\n");
+       wakeup(block->nmb_ifp);
+       return;
+}
+
+int
+ndis_create_sysctls(arg)
+       void                    *arg;
+{
+       struct ndis_softc       *sc;
+       ndis_cfg                *vals;
+       char                    buf[256];
+
+       if (arg == NULL)
+               return(EINVAL);
+
+       sc = arg;
+       vals = sc->ndis_regvals;
+
+       TAILQ_INIT(&sc->ndis_cfglist_head);
+
+#if __FreeBSD_version < 502113
+       /* Create the sysctl tree. */
+
+       sc->ndis_tree = SYSCTL_ADD_NODE(&sc->ndis_ctx,
+           SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
+           device_get_nameunit(sc->ndis_dev), CTLFLAG_RD, 0,
+           device_get_desc(sc->ndis_dev));
+
+#endif
+       /* Add the driver-specific registry keys. */
+
+       vals = sc->ndis_regvals;
+       while(1) {
+               if (vals->nc_cfgkey == NULL)
+                       break;
+               if (vals->nc_idx != sc->ndis_devidx) {
+                       vals++;
+                       continue;
+               }
+#if 1
+               SYSCTL_ADD_STRING(&sc->ndis_ctx,
+                   SYSCTL_CHILDREN(sc->ndis_tree),
+                   OID_AUTO, vals->nc_cfgkey,
+                   CTLFLAG_RW, vals->nc_val,
+                   sizeof(vals->nc_val),
+                   vals->nc_cfgdesc);
+#else
+               SYSCTL_ADD_STRING(device_get_sysctl_ctx(sc->ndis_dev),
+                   SYSCTL_CHILDREN(device_get_sysctl_tree(sc->ndis_dev)),
+                   OID_AUTO, vals->nc_cfgkey,
+                   CTLFLAG_RW, vals->nc_val,
+                   sizeof(vals->nc_val),
+                   vals->nc_cfgdesc);
+#endif
+               vals++;
+       }
+
+       /* Now add a couple of builtin keys. */
+
+       /*
+        * Environment can be either Windows (0) or WindowsNT (1).
+        * We qualify as the latter.
+        */
+       ndis_add_sysctl(sc, "Environment",
+           "Windows environment", "1", CTLFLAG_RD);
+
+       /* NDIS version should be 5.1. */
+       ndis_add_sysctl(sc, "NdisVersion",
+           "NDIS API Version", "0x00050001", CTLFLAG_RD);
+
+       /* Bus type (PCI, PCMCIA, etc...) */
+       sprintf(buf, "%d", (int)sc->ndis_iftype);
+       ndis_add_sysctl(sc, "BusType", "Bus Type", buf, CTLFLAG_RD);
+
+       if (sc->ndis_res_io != NULL) {
+               sprintf(buf, "0x%lx", rman_get_start(sc->ndis_res_io));
+               ndis_add_sysctl(sc, "IOBaseAddress",
+                   "Base I/O Address", buf, CTLFLAG_RD);
+       }
+
+       if (sc->ndis_irq != NULL) {
+               sprintf(buf, "%lu", rman_get_start(sc->ndis_irq));
+               ndis_add_sysctl(sc, "InterruptNumber",
+                   "Interrupt Number", buf, CTLFLAG_RD);
+       }
+
+       return(0);
+}
+
+int
+ndis_add_sysctl(arg, key, desc, val, flag)
+       void                    *arg;
+       char                    *key;
+       char                    *desc;
+       char                    *val;
+       int                     flag;
+{
+       struct ndis_softc       *sc;
+       struct ndis_cfglist     *cfg;
+       char                    descstr[256];
+
+       sc = arg;
+
+       cfg = malloc(sizeof(struct ndis_cfglist), M_DEVBUF, M_NOWAIT|M_ZERO);
+
+       if (cfg == NULL)
+               return(ENOMEM);
+
+       cfg->ndis_cfg.nc_cfgkey = strdup(key, M_DEVBUF);
+       if (desc == NULL) {
+               snprintf(descstr, sizeof(descstr), "%s (dynamic)", key);
+               cfg->ndis_cfg.nc_cfgdesc = strdup(descstr, M_DEVBUF);
+       } else
+               cfg->ndis_cfg.nc_cfgdesc = strdup(desc, M_DEVBUF);
+       strcpy(cfg->ndis_cfg.nc_val, val);
+
+       TAILQ_INSERT_TAIL(&sc->ndis_cfglist_head, cfg, link);
+
+#if 1
+       SYSCTL_ADD_STRING(&sc->ndis_ctx, SYSCTL_CHILDREN(sc->ndis_tree),
+           OID_AUTO, cfg->ndis_cfg.nc_cfgkey, flag,
+           cfg->ndis_cfg.nc_val, sizeof(cfg->ndis_cfg.nc_val),
+           cfg->ndis_cfg.nc_cfgdesc);
+#else
+       SYSCTL_ADD_STRING(device_get_sysctl_ctx(sc->ndis_dev),
+           SYSCTL_CHILDREN(device_get_sysctl_tree(sc->ndis_dev)),
+           OID_AUTO, cfg->ndis_cfg.nc_cfgkey, flag,
+           cfg->ndis_cfg.nc_val, sizeof(cfg->ndis_cfg.nc_val),
+           cfg->ndis_cfg.nc_cfgdesc);
+#endif
+
+       return(0);
+}
+
+int
+ndis_flush_sysctls(arg)
+       void                    *arg;
+{
+       struct ndis_softc       *sc;
+       struct ndis_cfglist     *cfg;
+
+       sc = arg;
+
+       while (!TAILQ_EMPTY(&sc->ndis_cfglist_head)) {
+               cfg = TAILQ_FIRST(&sc->ndis_cfglist_head);
+               TAILQ_REMOVE(&sc->ndis_cfglist_head, cfg, link);
+               free(cfg->ndis_cfg.nc_cfgkey, M_DEVBUF);
+               free(cfg->ndis_cfg.nc_cfgdesc, M_DEVBUF);
+               free(cfg, M_DEVBUF);
+       }
+
+       return(0);
+}
+
+static void
+ndis_return(arg)
+       void                    *arg;
+{
+       struct ndis_softc       *sc;
+       __stdcall ndis_return_handler   returnfunc;
+       ndis_handle             adapter;
+       ndis_packet             *p;
+       uint8_t                 irql;
+
+       p = arg;
+       sc = p->np_softc;
+       adapter = sc->ndis_block.nmb_miniportadapterctx;
+
+       if (adapter == NULL)
+               return;
+
+       returnfunc = sc->ndis_chars.nmc_return_packet_func;
+       irql = FASTCALL1(hal_raise_irql, DISPATCH_LEVEL);
+       returnfunc(adapter, p);
+       FASTCALL1(hal_lower_irql, irql);
+
+       return;
+}
+
+static void
+ndis_extref_packet(void *arg)
+{
+       ndis_packet     *p = arg;
+
+       ++p->np_refcnt;
+}
+
+static void
+ndis_extfree_packet(void *arg)
+{
+       ndis_packet     *p = arg;
+
+       if (p == NULL)
+               return;
+
+       /* Decrement refcount. */
+       p->np_refcnt--;
+
+       /* Release packet when refcount hits zero, otherwise return. */
+       if (p->np_refcnt)
+               return;
+
+       ndis_sched(ndis_return, p, NDIS_SWI);
+
+       return;
+}
+
+void
+ndis_return_packet(struct ndis_softc *sc, ndis_packet *p)
+{
+       ndis_extfree_packet(p);
+}
+
+void
+ndis_free_bufs(b0)
+       ndis_buffer             *b0;
+{
+       ndis_buffer             *next;
+
+       if (b0 == NULL)
+               return;
+
+       while(b0 != NULL) {
+               next = b0->nb_next;
+               free(b0, M_NDIS_BUFFER);
+               b0 = next;
+       }
+
+       return;
+}
+
+void
+ndis_free_packet(p)
+       ndis_packet             *p;
+{
+       if (p == NULL)
+               return;
+
+       ndis_free_bufs(p->np_private.npp_head);
+       free(p, M_NDIS_PACKET);
+
+       return;
+}
+
+int
+ndis_convert_res(arg)
+       void                    *arg;
+{
+       struct ndis_softc       *sc;
+       ndis_resource_list      *rl = NULL;
+       cm_partial_resource_desc        *prd = NULL;
+       ndis_miniport_block     *block;
+       device_t                dev;
+       struct resource_list    *brl;
+       struct resource_list    brl_rev;
+       struct resource_list_entry      *brle, *n;
+       int                     error = 0;
+
+       sc = arg;
+       block = &sc->ndis_block;
+       dev = sc->ndis_dev;
+
+       SLIST_INIT(&brl_rev);
+
+       rl = malloc(sizeof(ndis_resource_list) +
+           (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)),
+           M_DEVBUF, M_NOWAIT|M_ZERO);
+
+       if (rl == NULL)
+               return(ENOMEM);
+
+       rl->cprl_version = 5;
+       rl->cprl_version = 1;
+       rl->cprl_count = sc->ndis_rescnt;
+       prd = rl->cprl_partial_descs;
+
+       brl = BUS_GET_RESOURCE_LIST(dev, dev);
+
+       if (brl != NULL) {
+
+               /*
+                * We have a small problem. Some PCI devices have
+                * multiple I/O ranges. Windows orders them starting
+                * from lowest numbered BAR to highest. We discover
+                * them in that order too, but insert them into a singly
+                * linked list head first, which means when time comes
+                * to traverse the list, we enumerate them in reverse
+                * order. This screws up some drivers which expect the
+                * BARs to be in ascending order so that they can choose
+                * the "first" one as their register space. Unfortunately,
+                * in order to fix this, we have to create our own
+                * temporary list with the entries in reverse order.
+                */
+               SLIST_FOREACH(brle, brl, link) {
+                       n = malloc(sizeof(struct resource_list_entry),
+                           M_TEMP, M_NOWAIT);
+                       if (n == NULL) {
+                               error = ENOMEM;
+                               goto bad;
+                       }
+                       bcopy((char *)brle, (char *)n,
+                           sizeof(struct resource_list_entry));
+                       SLIST_INSERT_HEAD(&brl_rev, n, link);
+               }
+
+               SLIST_FOREACH(brle, &brl_rev, link) {
+                       switch (brle->type) {
+                       case SYS_RES_IOPORT:
+                               prd->cprd_type = CmResourceTypePort;
+                               prd->cprd_flags = CM_RESOURCE_PORT_IO;
+                               prd->cprd_sharedisp =
+                                   CmResourceShareDeviceExclusive;
+                               prd->u.cprd_port.cprd_start.np_quad =
+                                   brle->start;
+                               prd->u.cprd_port.cprd_len = brle->count;
+                               break;
+                       case SYS_RES_MEMORY:
+                               prd->cprd_type = CmResourceTypeMemory;
+                               prd->cprd_flags =
+                                   CM_RESOURCE_MEMORY_READ_WRITE;
+                               prd->cprd_sharedisp =
+                                   CmResourceShareDeviceExclusive;
+                               prd->u.cprd_port.cprd_start.np_quad =
+                                   brle->start;
+                               prd->u.cprd_port.cprd_len = brle->count;
+                               break;
+                       case SYS_RES_IRQ:
+                               prd->cprd_type = CmResourceTypeInterrupt;
+                               prd->cprd_flags = 0;
+                               prd->cprd_sharedisp =
+                                   CmResourceShareDeviceExclusive;
+                               prd->u.cprd_intr.cprd_level = brle->start;
+                               prd->u.cprd_intr.cprd_vector = brle->start;
+                               prd->u.cprd_intr.cprd_affinity = 0;
+                               break;
+                       default:
+                               break;
+                       }
+                       prd++;
+               }
+       }
+
+       block->nmb_rlist = rl;
+
+bad:
+
+       while (!SLIST_EMPTY(&brl_rev)) {
+               n = SLIST_FIRST(&brl_rev);
+               SLIST_REMOVE_HEAD(&brl_rev, link);
+               free (n, M_TEMP);
+       }
+
+       return(error);
+}
+
+/*
+ * Map an NDIS packet to an mbuf list. When an NDIS driver receives a
+ * packet, it will hand it to us in the form of an ndis_packet,
+ * which we need to convert to an mbuf that is then handed off
+ * to the stack. Note: we configure the mbuf list so that it uses
+ * the memory regions specified by the ndis_buffer structures in
+ * the ndis_packet as external storage. In most cases, this will
+ * point to a memory region allocated by the driver (either by
+ * ndis_malloc_withtag() or ndis_alloc_sharedmem()). We expect
+ * the driver to handle free()ing this region for is, so we set up
+ * a dummy no-op free handler for it.
+ */ 
+
+int
+ndis_ptom(m0, p)
+       struct mbuf             **m0;
+       ndis_packet             *p;
+{
+       struct mbuf             *m, *prev = NULL;
+       ndis_buffer             *buf;
+       ndis_packet_private     *priv;
+       uint32_t                totlen = 0;
+
+       if (p == NULL || m0 == NULL)
+               return(EINVAL);
+
+       priv = &p->np_private;
+       buf = priv->npp_head;
+       p->np_refcnt = 0;
+
+       for (buf = priv->npp_head; buf != NULL; buf = buf->nb_next) {
+               if (buf == priv->npp_head)
+                       MGETHDR(m, MB_DONTWAIT, MT_HEADER);
+               else
+                       MGET(m, MB_DONTWAIT, MT_DATA);
+               if (m == NULL) {
+                       m_freem(*m0);
+                       *m0 = NULL;
+                       return(ENOBUFS);
+               }
+               m->m_len = buf->nb_bytecount;
+               m->m_data = MDL_VA(buf);
+               m->m_ext.ext_nfree.new = ndis_extfree_packet;
+               m->m_ext.ext_nref.new = ndis_extref_packet;
+               m->m_ext.ext_arg = p;
+               m->m_ext.ext_buf = m->m_data;
+               m->m_ext.ext_size = m->m_len;
+               m->m_flags |= M_EXT;
+#if 0
+               MEXTADD(m, m->m_data, m->m_len, ndis_free_packet,
+                   p, 0, EXT_NDIS);
+#endif
+               p->np_refcnt++;
+               totlen += m->m_len;
+               if (m->m_flags & MT_HEADER)
+                       *m0 = m;
+               else
+                       prev->m_next = m;
+               prev = m;
+       }
+
+       (*m0)->m_pkthdr.len = totlen;
+
+       return(0);
+}
+
+/*
+ * Create an mbuf chain from an NDIS packet chain.
+ * This is used mainly when transmitting packets, where we need
+ * to turn an mbuf off an interface's send queue and transform it
+ * into an NDIS packet which will be fed into the NDIS driver's
+ * send routine.
+ *
+ * NDIS packets consist of two parts: an ndis_packet structure,
+ * which is vaguely analagous to the pkthdr portion of an mbuf,
+ * and one or more ndis_buffer structures, which define the
+ * actual memory segments in which the packet data resides.
+ * We need to allocate one ndis_buffer for each mbuf in a chain,
+ * plus one ndis_packet as the header.
+ */
+
+int
+ndis_mtop(m0, p)
+       struct mbuf             *m0;
+       ndis_packet             **p;
+{
+       struct mbuf             *m;
+       ndis_buffer             *buf = NULL, *prev = NULL;
+       ndis_packet_private     *priv;
+
+       if (p == NULL || m0 == NULL)
+               return(EINVAL);
+
+       /* If caller didn't supply a packet, make one. */
+       if (*p == NULL) {
+               *p = malloc(sizeof(ndis_packet), M_NDIS_PACKET, M_NOWAIT|M_ZERO);
+               if (*p == NULL)
+                       return(ENOMEM);
+       }
+       
+       priv = &(*p)->np_private;
+       priv->npp_totlen = m0->m_pkthdr.len;
+        priv->npp_packetooboffset = offsetof(ndis_packet, np_oob);
+       priv->npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS;
+
+       for (m = m0; m != NULL; m = m->m_next) {
+               if (m->m_len == 0)
+                       continue;
+               buf = malloc(sizeof(ndis_buffer), M_NDIS_BUFFER, M_NOWAIT|M_ZERO);
+               if (buf == NULL) {
+                       ndis_free_packet(*p);
+                       *p = NULL;
+                       return(ENOMEM);
+               }
+
+               MDL_INIT(buf, m->m_data, m->m_len);
+               if (priv->npp_head == NULL)
+                       priv->npp_head = buf;
+               else
+                       prev->nb_next = buf;
+               prev = buf;
+       }
+
+       priv->npp_tail = buf;
+       priv->npp_totlen = m0->m_pkthdr.len;
+
+       return(0);
+}
+
+int
+ndis_get_supported_oids(arg, oids, oidcnt)
+       void                    *arg;
+       ndis_oid                **oids;
+       int                     *oidcnt;
+{
+       int                     len, rval;
+       ndis_oid                *o;
+
+       if (arg == NULL || oids == NULL || oidcnt == NULL)
+               return(EINVAL);
+       len = 0;
+       ndis_get_info(arg, OID_GEN_SUPPORTED_LIST, NULL, &len);
+
+       o = malloc(len, M_DEVBUF, M_NOWAIT);
+       if (o == NULL)
+               return(ENOMEM);
+
+       rval = ndis_get_info(arg, OID_GEN_SUPPORTED_LIST, o, &len);
+
+       if (rval) {
+               free(o, M_DEVBUF);
+               return(rval);
+       }
+
+       *oids = o;
+       *oidcnt = len / 4;
+
+       return(0);
+}
+
+int
+ndis_set_info(arg, oid, buf, buflen)
+       void                    *arg;
+       ndis_oid                oid;
+       void                    *buf;
+       int                     *buflen;
+{
+       struct ndis_softc       *sc;
+       ndis_status             rval;
+       ndis_handle             adapter;
+       __stdcall ndis_setinfo_handler  setfunc;
+       uint32_t                byteswritten = 0, bytesneeded = 0;
+       int                     error;
+       uint8_t                 irql;
+       NDIS_INFO;
+
+       sc = arg;
+       NDIS_LOCK(sc);
+       setfunc = sc->ndis_chars.nmc_setinfo_func;
+       adapter = sc->ndis_block.nmb_miniportadapterctx;
+       NDIS_UNLOCK(sc);
+
+       if (adapter == NULL || setfunc == NULL)
+               return(ENXIO);
+
+       irql = FASTCALL1(hal_raise_irql, DISPATCH_LEVEL);
+       rval = setfunc(adapter, oid, buf, *buflen,
+           &byteswritten, &bytesneeded);
+       FASTCALL1(hal_lower_irql, irql);
+
+       if (rval == NDIS_STATUS_PENDING) {
+               error = tsleep(&sc->ndis_block.nmb_wkupdpctimer,
+                   0, "ndisset", 5 * hz);
+               rval = sc->ndis_block.nmb_setstat;
+       }
+
+       if (byteswritten)
+               *buflen = byteswritten;
+       if (bytesneeded)
+               *buflen = bytesneeded;
+
+       if (rval == NDIS_STATUS_INVALID_LENGTH)
+               return(ENOSPC);
+
+       if (rval == NDIS_STATUS_INVALID_OID)
+               return(EINVAL);
+
+       if (rval == NDIS_STATUS_NOT_SUPPORTED ||
+           rval == NDIS_STATUS_NOT_ACCEPTED)
+               return(ENOTSUP);
+
+       if (rval != NDIS_STATUS_SUCCESS)
+               return(ENODEV);
+
+       return(0);
+}
+
+typedef void (*ndis_senddone_func)(ndis_handle, ndis_packet *, ndis_status);
+
+int
+ndis_send_packets(arg, packets, cnt)
+       void                    *arg;
+       ndis_packet             **packets;
+       int                     cnt;
+{
+       struct ndis_softc       *sc;
+       ndis_handle             adapter;
+       __stdcall ndis_sendmulti_handler        sendfunc;
+       __stdcall ndis_senddone_func            senddonefunc;
+       int                     i;
+       ndis_packet             *p;
+       uint8_t                 irql;
+
+       sc = arg;
+       adapter = sc->ndis_block.nmb_miniportadapterctx;
+       if (adapter == NULL)
+               return(ENXIO);
+       sendfunc = sc->ndis_chars.nmc_sendmulti_func;
+       senddonefunc = sc->ndis_block.nmb_senddone_func;
+       irql = FASTCALL1(hal_raise_irql, DISPATCH_LEVEL);
+       sendfunc(adapter, packets, cnt);
+       FASTCALL1(hal_lower_irql, irql);
+
+       for (i = 0; i < cnt; i++) {
+               p = packets[i];
+               /*
+                * Either the driver already handed the packet to
+                * ndis_txeof() due to a failure, or it wants to keep
+                * it and release it asynchronously later. Skip to the
+                * next one.
+                */
+               if (p == NULL || p->np_oob.npo_status == NDIS_STATUS_PENDING)
+                       continue;
+               senddonefunc(&sc->ndis_block, p, p->np_oob.npo_status);
+       }
+
+       return(0);
+}
+
+int
+ndis_send_packet(arg, packet)
+       void                    *arg;
+       ndis_packet             *packet;
+{
+       struct ndis_softc       *sc;
+       ndis_handle             adapter;
+       ndis_status             status;
+       __stdcall ndis_sendsingle_handler       sendfunc;
+       __stdcall ndis_senddone_func            senddonefunc;
+       uint8_t                 irql;
+
+       sc = arg;
+       adapter = sc->ndis_block.nmb_miniportadapterctx;
+       if (adapter == NULL)
+               return(ENXIO);
+       sendfunc = sc->ndis_chars.nmc_sendsingle_func;
+       senddonefunc = sc->ndis_block.nmb_senddone_func;
+
+       irql = FASTCALL1(hal_raise_irql, DISPATCH_LEVEL);
+       status = sendfunc(adapter, packet, packet->np_private.npp_flags);
+       FASTCALL1(hal_lower_irql, irql);
+
+       if (status == NDIS_STATUS_PENDING)
+               return(0);
+
+       senddonefunc(&sc->ndis_block, packet, status);
+
+       return(0);
+}
+
+int
+ndis_init_dma(arg)
+       void                    *arg;
+{
+       struct ndis_softc       *sc;
+       int                     i, error;
+
+       sc = arg;
+
+       sc->ndis_tmaps = malloc(sizeof(bus_dmamap_t) * sc->ndis_maxpkts,
+           M_DEVBUF, M_NOWAIT|M_ZERO);
+
+       if (sc->ndis_tmaps == NULL)
+               return(ENOMEM);
+
+       for (i = 0; i < sc->ndis_maxpkts; i++) {
+               error = bus_dmamap_create(sc->ndis_ttag, 0,
+                   &sc->ndis_tmaps[i]);
+               if (error) {
+                       free(sc->ndis_tmaps, M_DEVBUF);
+                       return(ENODEV);
+               }
+       }
+
+       return(0);
+}
+
+int
+ndis_destroy_dma(arg)
+       void                    *arg;
+{
+       struct ndis_softc       *sc;
+       struct mbuf             *m;
+       ndis_packet             *p = NULL;
+       int                     i;
+
+       sc = arg;
+
+       for (i = 0; i < sc->ndis_maxpkts; i++) {
+               if (sc->ndis_txarray[i] != NULL) {
+                       p = sc->ndis_txarray[i];
+                       m = (struct mbuf *)p->np_rsvd[1];
+                       if (m != NULL)
+                               m_freem(m);
+                       ndis_free_packet(sc->ndis_txarray[i]);
+               }
+               bus_dmamap_destroy(sc->ndis_ttag, sc->ndis_tmaps[i]);
+       }
+
+       free(sc->ndis_tmaps, M_DEVBUF);
+
+       bus_dma_tag_destroy(sc->ndis_ttag);
+
+       return(0);
+}
+
+int
+ndis_reset_nic(arg)
+       void                    *arg;
+{
+       struct ndis_softc       *sc;
+       ndis_handle             adapter;
+       __stdcall ndis_reset_handler    resetfunc;
+       uint8_t                 addressing_reset;
+       struct ifnet            *ifp;
+       int                     rval;
+       uint8_t                 irql;
+       NDIS_INFO;
+
+       sc = arg;
+       ifp = &sc->arpcom.ac_if;
+       NDIS_LOCK(sc);
+       adapter = sc->ndis_block.nmb_miniportadapterctx;
+       resetfunc = sc->ndis_chars.nmc_reset_func;
+       NDIS_UNLOCK(sc);
+       if (adapter == NULL || resetfunc == NULL)
+               return(EIO);
+
+       irql = FASTCALL1(hal_raise_irql, DISPATCH_LEVEL);
+       rval = resetfunc(&addressing_reset, adapter);
+       FASTCALL1(hal_lower_irql, irql);
+
+       if (rval == NDIS_STATUS_PENDING) {
+               tsleep(sc, 0, "ndisrst", 0);
+       }
+
+       return(0);
+}
+
+int
+ndis_halt_nic(arg)
+       void                    *arg;
+{
+       struct ndis_softc       *sc;
+       ndis_handle             adapter;
+       __stdcall ndis_halt_handler     haltfunc;
+       struct ifnet            *ifp;
+       NDIS_INFO;
+
+       sc = arg;
+       ifp = &sc->arpcom.ac_if;
+
+       NDIS_LOCK(sc);
+       adapter = sc->ndis_block.nmb_miniportadapterctx;
+       if (adapter == NULL) {
+               NDIS_UNLOCK(sc);
+               return(EIO);
+       }
+
+       /*
+        * The adapter context is only valid after the init
+        * handler has been called, and is invalid once the
+        * halt handler has been called.
+        */
+
+       haltfunc = sc->ndis_chars.nmc_halt_func;
+       NDIS_UNLOCK(sc);
+
+       haltfunc(adapter);
+
+       NDIS_LOCK(sc);
+       sc->ndis_block.nmb_miniportadapterctx = NULL;
+       NDIS_UNLOCK(sc);
+
+       return(0);
+}
+
+int
+ndis_shutdown_nic(arg)
+       void                    *arg;
+{
+       struct ndis_softc       *sc;
+       ndis_handle             adapter;
+       __stdcall ndis_shutdown_handler shutdownfunc;
+       NDIS_INFO;
+
+       sc = arg;
+       NDIS_LOCK(sc);
+       adapter = sc->ndis_block.nmb_miniportadapterctx;
+       shutdownfunc = sc->ndis_chars.nmc_shutdown_handler;
+       NDIS_UNLOCK(sc);
+       if (adapter == NULL || shutdownfunc == NULL)
+               return(EIO);
+
+       if (sc->ndis_chars.nmc_rsvd0 == NULL)
+               shutdownfunc(adapter);
+       else
+               shutdownfunc(sc->ndis_chars.nmc_rsvd0);
+
+       ndis_shrink_thrqueue(8);
+       TAILQ_REMOVE(&ndis_devhead, &sc->ndis_block, link);
+
+       return(0);
+}
+
+int
+ndis_init_nic(arg)
+       void                    *arg;
+{
+       struct ndis_softc       *sc;
+       ndis_miniport_block     *block;
+        __stdcall ndis_init_handler    initfunc;
+       ndis_status             status, openstatus = 0;
+       ndis_medium             mediumarray[NdisMediumMax];
+       uint32_t                chosenmedium, i;
+       NDIS_INFO;
+
+       if (arg == NULL)
+               return(EINVAL);
+
+       sc = arg;
+       NDIS_LOCK(sc);
+       block = &sc->ndis_block;
+       initfunc = sc->ndis_chars.nmc_init_func;
+       NDIS_UNLOCK(sc);
+
+       TAILQ_INIT(&block->nmb_timerlist);
+
+       for (i = 0; i < NdisMediumMax; i++)
+               mediumarray[i] = i;
+
+        status = initfunc(&openstatus, &chosenmedium,
+            mediumarray, NdisMediumMax, block, block);
+
+       /*
+        * If the init fails, blow away the other exported routines
+        * we obtained from the driver so we can't call them later.
+        * If the init failed, none of these will work.
+        */
+       if (status != NDIS_STATUS_SUCCESS) {
+               NDIS_LOCK(sc);
+               sc->ndis_block.nmb_miniportadapterctx = NULL;
+               NDIS_UNLOCK(sc);
+               return(ENXIO);
+       }
+
+       return(0);
+}
+
+void
+ndis_enable_intr(arg)
+       void                    *arg;
+{
+       struct ndis_softc       *sc;
+       ndis_handle             adapter;
+       __stdcall ndis_enable_interrupts_handler        intrenbfunc;
+
+       sc = arg;
+       adapter = sc->ndis_block.nmb_miniportadapterctx;
+       intrenbfunc = sc->ndis_chars.nmc_enable_interrupts_func;
+       if (adapter == NULL || intrenbfunc == NULL)
+               return;
+       intrenbfunc(adapter);
+
+       return;
+}
+
+void
+ndis_disable_intr(arg)
+       void                    *arg;
+{
+       struct ndis_softc       *sc;
+       ndis_handle             adapter;
+       __stdcall ndis_disable_interrupts_handler       intrdisfunc;
+       NDIS_INFO;
+
+       sc = arg;
+       NDIS_LOCK(sc);
+       adapter = sc->ndis_block.nmb_miniportadapterctx;
+       intrdisfunc = sc->ndis_chars.nmc_disable_interrupts_func;
+       NDIS_UNLOCK(sc);
+       if (adapter == NULL || intrdisfunc == NULL)
+           return;
+       intrdisfunc(adapter);
+
+       return;
+}
+
+int
+ndis_isr(arg, ourintr, callhandler)
+       void                    *arg;
+       int                     *ourintr;
+       int                     *callhandler;
+{
+       struct ndis_softc       *sc;
+       ndis_handle             adapter;
+       __stdcall ndis_isr_handler      isrfunc;
+       uint8_t                 accepted, queue;
+
+       if (arg == NULL || ourintr == NULL || callhandler == NULL)
+               return(EINVAL);
+
+       sc = arg;
+       adapter = sc->ndis_block.nmb_miniportadapterctx;
+       isrfunc = sc->ndis_chars.nmc_isr_func;
+       if (adapter == NULL || isrfunc == NULL)
+               return(ENXIO);
+
+       isrfunc(&accepted, &queue, adapter);
+       *ourintr = accepted;
+       *callhandler = queue;
+
+       return(0);
+}
+
+int
+ndis_intrhand(arg)
+       void                    *arg;
+{
+       struct ndis_softc       *sc;
+       ndis_handle             adapter;
+       __stdcall ndis_interrupt_handler        intrfunc;
+       NDIS_INFO;
+
+       if (arg == NULL)
+               return(EINVAL);
+
+       sc = arg;
+       NDIS_LOCK(sc);
+       adapter = sc->ndis_block.nmb_miniportadapterctx;
+       intrfunc = sc->ndis_chars.nmc_interrupt_func;
+       NDIS_UNLOCK(sc);
+       if (adapter == NULL || intrfunc == NULL)
+               return(EINVAL);
+
+       intrfunc(adapter);
+
+       return(0);
+}
+
+int
+ndis_get_info(arg, oid, buf, buflen)
+       void                    *arg;
+       ndis_oid                oid;
+       void                    *buf;
+       int                     *buflen;
+{
+       struct ndis_softc       *sc;
+       ndis_status             rval;
+       ndis_handle             adapter;
+       ndis_queryinfo_handler  queryfunc;
+       uint32_t                byteswritten = 0, bytesneeded = 0;
+       int                     error;
+       uint8_t                 irql;
+       NDIS_INFO;
+
+       sc = arg;
+       NDIS_LOCK(sc);
+       queryfunc = sc->ndis_chars.nmc_queryinfo_func;
+       adapter = sc->ndis_block.nmb_miniportadapterctx;
+       NDIS_UNLOCK(sc);
+
+       if (adapter == NULL || queryfunc == NULL)
+               return(ENXIO);
+
+       irql = FASTCALL1(hal_raise_irql, DISPATCH_LEVEL);
+       rval = queryfunc(adapter, oid, buf, *buflen,
+           &byteswritten, &bytesneeded);
+       FASTCALL1(hal_lower_irql, irql);
+
+       /* Wait for requests that block. */
+
+       if (rval == NDIS_STATUS_PENDING) {
+               error = tsleep(&sc->ndis_block.nmb_wkupdpctimer,
+                   0, "ndisget", 5 * hz);
+               rval = sc->ndis_block.nmb_getstat;
+       }
+
+       if (byteswritten)
+               *buflen = byteswritten;
+       if (bytesneeded)
+               *buflen = bytesneeded;
+
+       if (rval == NDIS_STATUS_INVALID_LENGTH ||
+           rval == NDIS_STATUS_BUFFER_TOO_SHORT)
+               return(ENOSPC);
+
+       if (rval == NDIS_STATUS_INVALID_OID)
+               return(EINVAL);
+
+       if (rval == NDIS_STATUS_NOT_SUPPORTED ||
+           rval == NDIS_STATUS_NOT_ACCEPTED)
+               return(ENOTSUP);
+
+       if (rval != NDIS_STATUS_SUCCESS)
+               return(ENODEV);
+
+       return(0);
+}
+
+int
+ndis_unload_driver(arg)
+       void                    *arg;
+{
+       struct ndis_softc       *sc;
+
+       sc = arg;
+
+       free(sc->ndis_block.nmb_rlist, M_DEVBUF);
+
+       ndis_flush_sysctls(sc);
+
+       ndis_shrink_thrqueue(8);
+       TAILQ_REMOVE(&ndis_devhead, &sc->ndis_block, link);
+
+       return(0);
+}
+
+#define NDIS_LOADED            htonl(0x42534F44)
+
+int
+ndis_load_driver(img, arg)
+       vm_offset_t             img;
+       void                    *arg;
+{
+       __stdcall driver_entry  entry;
+       image_optional_header   opt_hdr;
+       image_import_descriptor imp_desc;
+       ndis_unicode_string     dummystr;
+        ndis_miniport_block     *block;
+       ndis_status             status;
+       int                     idx;
+       uint32_t                *ptr;
+       struct ndis_softc       *sc;
+
+       sc = arg;
+
+       /*
+        * Only perform the relocation/linking phase once
+        * since the binary image may be shared among multiple
+        * device instances.
+        */
+
+       ptr = (uint32_t *)(img + 8);
+       if (*ptr != NDIS_LOADED) {
+               /* Perform text relocation */
+               if (pe_relocate(img))
+                       return(ENOEXEC);
+
+               /* Dynamically link the NDIS.SYS routines -- required. */
+               if (pe_patch_imports(img, "NDIS", ndis_functbl))
+                       return(ENOEXEC);
+
+               /* Dynamically link the HAL.dll routines -- also required. */
+               if (pe_patch_imports(img, "HAL", hal_functbl))
+                       return(ENOEXEC);
+
+               /* Dynamically link ntoskrnl.exe -- optional. */
+               if (pe_get_import_descriptor(img,
+                   &imp_desc, "ntoskrnl") == 0) {
+                       if (pe_patch_imports(img,
+                           "ntoskrnl", ntoskrnl_functbl))
+                               return(ENOEXEC);
+               }
+               *ptr = NDIS_LOADED;
+       }
+
+        /* Locate the driver entry point */
+       pe_get_optional_header(img, &opt_hdr);
+       entry = (driver_entry)pe_translate_addr(img, opt_hdr.ioh_entryaddr);
+
+       dummystr.nus_len = strlen(NDIS_DUMMY_PATH) * 2;
+       dummystr.nus_maxlen = strlen(NDIS_DUMMY_PATH) * 2;
+       dummystr.nus_buf = NULL;
+       ndis_ascii_to_unicode(NDIS_DUMMY_PATH, &dummystr.nus_buf);
+
+       /*
+        * Now that we have the miniport driver characteristics,
+        * create an NDIS block and call the init handler.
+        * This will cause the driver to try to probe for
+        * a device.
+        */
+
+       block = &sc->ndis_block;
+
+       ptr = (uint32_t *)block;
+       for (idx = 0; idx < sizeof(ndis_miniport_block) / 4; idx++) {
+               *ptr = idx | 0xdead0000;
+               ptr++;
+       }
+
+       block->nmb_signature = (void *)0xcafebabe;
+       block->nmb_setdone_func = ndis_setdone_func;
+       block->nmb_querydone_func = ndis_getdone_func;
+       block->nmb_status_func = ndis_status_func;
+       block->nmb_statusdone_func = ndis_statusdone_func;
+       block->nmb_resetdone_func = ndis_resetdone_func;
+       block->nmb_sendrsrc_func = ndis_sendrsrcavail_func;
+
+       block->nmb_ifp = &sc->arpcom.ac_if;
+       block->nmb_dev = sc->ndis_dev;
+       block->nmb_img = img;
+       block->nmb_devobj.do_rsvd = block;
+
+       /*
+        * Now call the DriverEntry() routine. This will cause
+        * a callout to the NdisInitializeWrapper() and
+        * NdisMRegisterMiniport() routines.
+        */
+       status = entry(&block->nmb_devobj, &dummystr);
+
+       free (dummystr.nus_buf, M_DEVBUF);
+
+       if (status != NDIS_STATUS_SUCCESS)
+               return(ENODEV);
+
+       ndis_enlarge_thrqueue(8);
+
+       TAILQ_INSERT_TAIL(&ndis_devhead, block, link);
+
+       return(0);
+}
+
diff --git a/sys/emulation/ndis/ndis_var.h b/sys/emulation/ndis/ndis_var.h
new file mode 100644 (file)
index 0000000..ebbe112
--- /dev/null
@@ -0,0 +1,1530 @@
+/*
+ * 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: src/sys/compat/ndis/ndis_var.h,v 1.27 2004/07/11 00:19:30 wpaul Exp $
+ * $DragonFly: src/sys/emulation/ndis/ndis_var.h,v 1.1 2004/07/29 20:51:33 dillon Exp $
+ */
+
+#ifndef _NDIS_VAR_H_
+#define _NDIS_VAR_H_
+
+/* Forward declarations */
+struct ndis_miniport_block;
+struct ndis_mdriver_block;
+typedef struct ndis_miniport_block ndis_miniport_block;
+typedef struct ndis_mdriver_block ndis_mdriver_block;
+
+/* Base types */
+typedef uint32_t ndis_status;
+typedef void *ndis_handle;
+typedef uint32_t ndis_oid;
+typedef uint32_t ndis_error_code;
+typedef register_t ndis_kspin_lock;
+typedef uint8_t ndis_kirql;
+
+/*
+ * NDIS status codes (there are lots of them). The ones that
+ * don't seem to fit the pattern are actually mapped to generic
+ * NT status codes.
+ */
+
+#define NDIS_STATUS_SUCCESS            0
+#define NDIS_STATUS_PENDING            0x00000103
+#define NDIS_STATUS_NOT_RECOGNIZED     0x00010001
+#define NDIS_STATUS_NOT_COPIED         0x00010002
+#define NDIS_STATUS_NOT_ACCEPTED       0x00010003
+#define NDIS_STATUS_CALL_ACTIVE                0x00010007
+#define NDIS_STATUS_ONLINE             0x40010003
+#define NDIS_STATUS_RESET_START                0x40010004
+#define NDIS_STATUS_RESET_END          0x40010005
+#define NDIS_STATUS_RING_STATUS                0x40010006
+#define NDIS_STATUS_CLOSED             0x40010007
+#define NDIS_STATUS_WAN_LINE_UP                0x40010008
+#define NDIS_STATUS_WAN_LINE_DOWN      0x40010009
+#define NDIS_STATUS_WAN_FRAGMENT       0x4001000A
+#define NDIS_STATUS_MEDIA_CONNECT      0x4001000B
+#define NDIS_STATUS_MEDIA_DISCONNECT   0x4001000C
+#define NDIS_STATUS_HARDWARE_LINE_UP   0x4001000D
+#define NDIS_STATUS_HARDWARE_LINE_DOWN 0x4001000E
+#define NDIS_STATUS_INTERFACE_UP       0x4001000F
+#define NDIS_STATUS_INTERFACE_DOWN     0x40010010
+#define NDIS_STATUS_MEDIA_BUSY         0x40010011
+#define NDIS_STATUS_MEDIA_SPECIFIC_INDICATION  0x40010012
+#define NDIS_STATUS_WW_INDICATION NDIS_STATUS_MEDIA_SPECIFIC_INDICATION
+#define NDIS_STATUS_LINK_SPEED_CHANGE  0x40010013
+#define NDIS_STATUS_WAN_GET_STATS      0x40010014
+#define NDIS_STATUS_WAN_CO_FRAGMENT    0x40010015
+#define NDIS_STATUS_WAN_CO_LINKPARAMS  0x40010016
+#define NDIS_STATUS_NOT_RESETTABLE     0x80010001
+#define NDIS_STATUS_SOFT_ERRORS                0x80010003
+#define NDIS_STATUS_HARD_ERRORS                0x80010004
+#define NDIS_STATUS_BUFFER_OVERFLOW    0x80000005
+#define NDIS_STATUS_FAILURE            0xC0000001
+#define NDIS_STATUS_RESOURCES          0xC000009A
+#define NDIS_STATUS_CLOSING            0xC0010002
+#define NDIS_STATUS_BAD_VERSION                0xC0010004
+#define NDIS_STATUS_BAD_CHARACTERISTICS        0xC0010005
+#define NDIS_STATUS_ADAPTER_NOT_FOUND  0xC0010006
+#define NDIS_STATUS_OPEN_FAILED                0xC0010007
+#define NDIS_STATUS_DEVICE_FAILED      0xC0010008
+#define NDIS_STATUS_MULTICAST_FULL     0xC0010009
+#define NDIS_STATUS_MULTICAST_EXISTS   0xC001000A
+#define NDIS_STATUS_MULTICAST_NOT_FOUND        0xC001000B
+#define NDIS_STATUS_REQUEST_ABORTED    0xC001000C
+#define NDIS_STATUS_RESET_IN_PROGRESS  0xC001000D
+#define NDIS_STATUS_CLOSING_INDICATING 0xC001000E
+#define NDIS_STATUS_NOT_SUPPORTED      0xC00000BB
+#define NDIS_STATUS_INVALID_PACKET     0xC001000F
+#define NDIS_STATUS_OPEN_LIST_FULL     0xC0010010
+#define NDIS_STATUS_ADAPTER_NOT_READY  0xC0010011
+#define NDIS_STATUS_ADAPTER_NOT_OPEN   0xC0010012
+#define NDIS_STATUS_NOT_INDICATING     0xC0010013
+#define NDIS_STATUS_INVALID_LENGTH     0xC0010014
+#define NDIS_STATUS_INVALID_DATA       0xC0010015
+#define NDIS_STATUS_BUFFER_TOO_SHORT   0xC0010016
+#define NDIS_STATUS_INVALID_OID                0xC0010017
+#define NDIS_STATUS_ADAPTER_REMOVED    0xC0010018
+#define NDIS_STATUS_UNSUPPORTED_MEDIA  0xC0010019
+#define NDIS_STATUS_GROUP_ADDRESS_IN_USE       0xC001001A
+#define NDIS_STATUS_FILE_NOT_FOUND     0xC001001B
+#define NDIS_STATUS_ERROR_READING_FILE 0xC001001C
+#define NDIS_STATUS_ALREADY_MAPPED     0xC001001D
+#define NDIS_STATUS_RESOURCE_CONFLICT  0xC001001E
+#define NDIS_STATUS_NO_CABLE           0xC001001F
+#define NDIS_STATUS_INVALID_SAP                0xC0010020
+#define NDIS_STATUS_SAP_IN_USE         0xC0010021
+#define NDIS_STATUS_INVALID_ADDRESS    0xC0010022
+#define NDIS_STATUS_VC_NOT_ACTIVATED   0xC0010023
+#define NDIS_STATUS_DEST_OUT_OF_ORDER  0xC0010024
+#define NDIS_STATUS_VC_NOT_AVAILABLE   0xC0010025
+#define NDIS_STATUS_CELLRATE_NOT_AVAILABLE     0xC0010026
+#define NDIS_STATUS_INCOMPATABLE_QOS   0xC0010027
+#define NDIS_STATUS_AAL_PARAMS_UNSUPPORTED     0xC0010028
+#define NDIS_STATUS_NO_ROUTE_TO_DESTINATION    0xC0010029
+#define NDIS_STATUS_TOKEN_RING_OPEN_ERROR      0xC0011000
+#define NDIS_STATUS_INVALID_DEVICE_REQUEST     0xC0000010
+#define NDIS_STATUS_NETWORK_UNREACHABLE         0xC000023C
+
+/*
+ * NDIS event codes. They are usually reported to NdisWriteErrorLogEntry().
+ */
+
+#define EVENT_NDIS_RESOURCE_CONFLICT   0xC0001388
+#define EVENT_NDIS_OUT_OF_RESOURCE     0xC0001389
+#define EVENT_NDIS_HARDWARE_FAILURE    0xC000138A
+#define EVENT_NDIS_ADAPTER_NOT_FOUND   0xC000138B
+#define EVENT_NDIS_INTERRUPT_CONNECT   0xC000138C
+#define EVENT_NDIS_DRIVER_FAILURE      0xC000138D
+#define EVENT_NDIS_BAD_VERSION         0xC000138E
+#define EVENT_NDIS_TIMEOUT             0x8000138F
+#define EVENT_NDIS_NETWORK_ADDRESS     0xC0001390
+#define EVENT_NDIS_UNSUPPORTED_CONFIGURATION   0xC0001391
+#define EVENT_NDIS_INVALID_VALUE_FROM_ADAPTER  0xC0001392
+#define EVENT_NDIS_MISSING_CONFIGURATION_PARAMETER     0xC0001393
+#define EVENT_NDIS_BAD_IO_BASE_ADDRESS 0xC0001394
+#define EVENT_NDIS_RECEIVE_SPACE_SMALL 0x40001395
+#define EVENT_NDIS_ADAPTER_DISABLED    0x80001396
+#define EVENT_NDIS_IO_PORT_CONFLICT    0x80001397
+#define EVENT_NDIS_PORT_OR_DMA_CONFLICT        0x80001398
+#define EVENT_NDIS_MEMORY_CONFLICT     0x80001399
+#define EVENT_NDIS_INTERRUPT_CONFLICT  0x8000139A
+#define EVENT_NDIS_DMA_CONFLICT                0x8000139B
+#define EVENT_NDIS_INVALID_DOWNLOAD_FILE_ERROR 0xC000139C
+#define EVENT_NDIS_MAXRECEIVES_ERROR   0x8000139D
+#define EVENT_NDIS_MAXTRANSMITS_ERROR  0x8000139E
+#define EVENT_NDIS_MAXFRAMESIZE_ERROR  0x8000139F
+#define EVENT_NDIS_MAXINTERNALBUFS_ERROR       0x800013A0
+#define EVENT_NDIS_MAXMULTICAST_ERROR  0x800013A1
+#define EVENT_NDIS_PRODUCTID_ERROR     0x800013A2
+#define EVENT_NDIS_LOBE_FAILUE_ERROR   0x800013A3
+#define EVENT_NDIS_SIGNAL_LOSS_ERROR   0x800013A4
+#define EVENT_NDIS_REMOVE_RECEIVED_ERROR       0x800013A5
+#define EVENT_NDIS_TOKEN_RING_CORRECTION       0x400013A6
+#define EVENT_NDIS_ADAPTER_CHECK_ERROR 0xC00013A7
+#define EVENT_NDIS_RESET_FAILURE_ERROR 0x800013A8
+#define EVENT_NDIS_CABLE_DISCONNECTED_ERROR    0x800013A9
+#define EVENT_NDIS_RESET_FAILURE_CORRECTION    0x800013AA
+
+/*
+ * NDIS OIDs used by the queryinfo/setinfo routines.
+ * Some are required by all NDIS drivers, some are specific to
+ * a particular type of device, and some are purely optional.
+ * Unfortunately, one of the purely optional OIDs is the one
+ * that lets us set the MAC address of the device.
+ */
+
+/* Required OIDs */
+#define OID_GEN_SUPPORTED_LIST                 0x00010101
+#define OID_GEN_HARDWARE_STATUS                        0x00010102
+#define OID_GEN_MEDIA_SUPPORTED                        0x00010103
+#define OID_GEN_MEDIA_IN_USE                   0x00010104
+#define OID_GEN_MAXIMUM_LOOKAHEAD              0x00010105
+#define OID_GEN_MAXIMUM_FRAME_SIZE             0x00010106
+#define OID_GEN_LINK_SPEED                     0x00010107
+#define OID_GEN_TRANSMIT_BUFFER_SPACE          0x00010108
+#define OID_GEN_RECEIVE_BUFFER_SPACE           0x00010109
+#define OID_GEN_TRANSMIT_BLOCK_SIZE            0x0001010A
+#define OID_GEN_RECEIVE_BLOCK_SIZE             0x0001010B
+#define OID_GEN_VENDOR_ID                      0x0001010C
+#define OID_GEN_VENDOR_DESCRIPTION             0x0001010D
+#define OID_GEN_CURRENT_PACKET_FILTER          0x0001010E
+#define OID_GEN_CURRENT_LOOKAHEAD              0x0001010F
+#define OID_GEN_DRIVER_VERSION                 0x00010110
+#define OID_GEN_MAXIMUM_TOTAL_SIZE             0x00010111
+#define OID_GEN_PROTOCOL_OPTIONS               0x00010112
+#define OID_GEN_MAC_OPTIONS                    0x00010113
+#define OID_GEN_MEDIA_CONNECT_STATUS           0x00010114
+#define OID_GEN_MAXIMUM_SEND_PACKETS           0x00010115
+#define OID_GEN_VENDOR_DRIVER_VERSION          0x00010116
+#define OID_GEN_SUPPORTED_GUIDS                        0x00010117
+#define OID_GEN_NETWORK_LAYER_ADDRESSES                0x00010118      /* Set only */
+#define OID_GEN_TRANSPORT_HEADER_OFFSET                0x00010119      /* Set only */
+#define OID_GEN_MACHINE_NAME                   0x0001021A
+#define OID_GEN_RNDIS_CONFIG_PARAMETER         0x0001021B      /* Set only */
+#define OID_GEN_VLAN_ID                                0x0001021C
+
+/* Optional OIDs. */
+#define OID_GEN_MEDIA_CAPABILITIES             0x00010201
+#define OID_GEN_PHYSICAL_MEDIUM                        0x00010202
+
+/* Required statistics OIDs. */
+#define OID_GEN_XMIT_OK                                0x00020101
+#define OID_GEN_RCV_OK                         0x00020102
+#define OID_GEN_XMIT_ERROR                     0x00020103
+#define OID_GEN_RCV_ERROR                      0x00020104
+#define OID_GEN_RCV_NO_BUFFER                  0x00020105
+
+/* Optional OID statistics */
+#define OID_GEN_DIRECTED_BYTES_XMIT            0x00020201
+#define OID_GEN_DIRECTED_FRAMES_XMIT           0x00020202
+#define OID_GEN_MULTICAST_BYTES_XMIT           0x00020203
+#define OID_GEN_MULTICAST_FRAMES_XMIT          0x00020204
+#define OID_GEN_BROADCAST_BYTES_XMIT           0x00020205
+#define OID_GEN_BROADCAST_FRAMES_XMIT          0x00020206
+#define OID_GEN_DIRECTED_BYTES_RCV             0x00020207
+#define OID_GEN_DIRECTED_FRAMES_RCV            0x00020208
+#define OID_GEN_MULTICAST_BYTES_RCV            0x00020209
+#define OID_GEN_MULTICAST_FRAMES_RCV           0x0002020A
+#define OID_GEN_BROADCAST_BYTES_RCV            0x0002020B
+#define OID_GEN_BROADCAST_FRAMES_RCV           0x0002020C
+#define OID_GEN_RCV_CRC_ERROR                  0x0002020D
+#define OID_GEN_TRANSMIT_QUEUE_LENGTH          0x0002020E
+#define OID_GEN_GET_TIME_CAPS                  0x0002020F
+#define OID_GEN_GET_NETCARD_TIME               0x00020210
+#define OID_GEN_NETCARD_LOAD                   0x00020211
+#define OID_GEN_DEVICE_PROFILE                 0x00020212
+
+/* 802.3 (ethernet) OIDs */
+#define OID_802_3_PERMANENT_ADDRESS            0x01010101
+#define OID_802_3_CURRENT_ADDRESS              0x01010102
+#define OID_802_3_MULTICAST_LIST               0x01010103
+#define OID_802_3_MAXIMUM_LIST_SIZE            0x01010104
+#define OID_802_3_MAC_OPTIONS                  0x01010105
+#define NDIS_802_3_MAC_OPTION_PRIORITY         0x00000001
+#define OID_802_3_RCV_ERROR_ALIGNMENT          0x01020101
+#define OID_802_3_XMIT_ONE_COLLISION           0x01020102
+#define OID_802_3_XMIT_MORE_COLLISIONS         0x01020103
+#define OID_802_3_XMIT_DEFERRED                        0x01020201
+#define OID_802_3_XMIT_MAX_COLLISIONS          0x01020202
+#define OID_802_3_RCV_OVERRUN                  0x01020203
+#define OID_802_3_XMIT_UNDERRUN                        0x01020204
+#define OID_802_3_XMIT_HEARTBEAT_FAILURE       0x01020205
+#define OID_802_3_XMIT_TIMES_CRS_LOST          0x01020206
+#define OID_802_3_XMIT_LATE_COLLISIONS         0x01020207
+
+/* PnP and power management OIDs */
+#define OID_PNP_CAPABILITIES                   0xFD010100
+#define OID_PNP_SET_POWER                      0xFD010101
+#define OID_PNP_QUERY_POWER                    0xFD010102
+#define OID_PNP_ADD_WAKE_UP_PATTERN            0xFD010103
+#define OID_PNP_REMOVE_WAKE_UP_PATTERN         0xFD010104
+#define OID_PNP_WAKE_UP_PATTERN_LIST           0xFD010105
+#define OID_PNP_ENABLE_WAKE_UP                 0xFD010106
+
+/* PnP/PM Statistics (Optional). */
+#define OID_PNP_WAKE_UP_OK                     0xFD020200
+#define OID_PNP_WAKE_UP_ERROR                  0xFD020201
+
+/* The following bits are defined for OID_PNP_ENABLE_WAKE_UP */
+#define NDIS_PNP_WAKE_UP_MAGIC_PACKET          0x00000001
+#define NDIS_PNP_WAKE_UP_PATTERN_MATCH         0x00000002
+#define NDIS_PNP_WAKE_UP_LINK_CHANGE           0x00000004
+
+/* 802.11 OIDs */
+#define OID_802_11_BSSID                       0x0D010101
+#define OID_802_11_SSID                                0x0D010102
+#define OID_802_11_NETWORK_TYPES_SUPPORTED     0x0D010203
+#define OID_802_11_NETWORK_TYPE_IN_USE         0x0D010204
+#define OID_802_11_TX_POWER_LEVEL              0x0D010205
+#define OID_802_11_RSSI                                0x0D010206
+#define OID_802_11_RSSI_TRIGGER                        0x0D010207
+#define OID_802_11_INFRASTRUCTURE_MODE         0x0D010108
+#define OID_802_11_FRAGMENTATION_THRESHOLD     0x0D010209
+#define OID_802_11_RTS_THRESHOLD               0x0D01020A
+#define OID_802_11_NUMBER_OF_ANTENNAS          0x0D01020B
+#define OID_802_11_RX_ANTENNA_SELECTED         0x0D01020C
+#define OID_802_11_TX_ANTENNA_SELECTED         0x0D01020D
+#define OID_802_11_SUPPORTED_RATES             0x0D01020E
+#define OID_802_11_DESIRED_RATES               0x0D010210
+#define OID_802_11_CONFIGURATION               0x0D010211
+#define OID_802_11_STATISTICS                  0x0D020212
+#define OID_802_11_ADD_WEP                     0x0D010113
+#define OID_802_11_REMOVE_WEP                  0x0D010114
+#define OID_802_11_DISASSOCIATE                        0x0D010115
+#define OID_802_11_POWER_MODE                  0x0D010216
+#define OID_802_11_BSSID_LIST                  0x0D010217
+#define OID_802_11_AUTHENTICATION_MODE         0x0D010118
+#define OID_802_11_PRIVACY_FILTER              0x0D010119
+#define OID_802_11_BSSID_LIST_SCAN             0x0D01011A
+#define OID_802_11_WEP_STATUS                  0x0D01011B
+#define OID_802_11_ENCRYPTION_STATUS           OID_802_11_WEP_STATUS
+#define OID_802_11_RELOAD_DEFAULTS             0x0D01011C
+#define OID_802_11_ADD_KEY                     0x0D01011D
+#define OID_802_11_REMOVE_KEY                  0x0D01011E
+#define OID_802_11_ASSOCIATION_INFORMATION     0x0D01011F
+#define OID_802_11_TEST                                0x0D010120
+
+/* structures/definitions for 802.11 */
+#define NDIS_80211_NETTYPE_11FH                0x00000000
+#define NDIS_80211_NETTYPE_11DS                0x00000001
+#define NDIS_80211_NETTYPE_11OFDM5     0x00000002
+#define NDIS_80211_NETTYPE_11OFDM24    0x00000003
+
+struct ndis_80211_nettype_list {
+       uint32_t                ntl_items;
+       uint32_t                ntl_type[1];
+};
+
+#define NDIS_80211_POWERMODE_CAM       0x00000000
+#define NDIS_80211_POWERMODE_MAX_PSP   0x00000001
+#define NDIS_80211_POWERMODE_FAST_PSP  0x00000002
+
+typedef uint32_t ndis_80211_power;     /* Power in milliwatts */
+typedef uint32_t ndis_80211_rssi;      /* Signal strength in dBm */
+
+struct ndis_80211_config_fh {
+       uint32_t                ncf_length;
+       uint32_t                ncf_hoppatterh;
+       uint32_t                ncf_hopset;
+       uint32_t                ncf_dwelltime;
+};
+
+typedef struct ndis_80211_config_fh ndis_80211_config_fh;
+
+struct ndis_80211_config {
+       uint32_t                nc_length;
+       uint32_t                nc_beaconperiod;
+       uint32_t                nc_atimwin;
+       uint32_t                nc_dsconfig;
+       ndis_80211_config_fh    nc_fhconfig;
+};
+
+typedef struct ndis_80211_config ndis_80211_config;
+
+struct ndis_80211_stats {
+       uint32_t                ns_length;
+       uint64_t                ns_txfragcnt;
+       uint64_t                ns_txmcastcnt;
+       uint64_t                ns_failedcnt;
+       uint64_t                ns_retrycnt;
+       uint64_t                ns_multiretrycnt;
+       uint64_t                ns_rtssuccesscnt;
+       uint64_t                ns_rtsfailcnt;
+       uint64_t                ns_ackfailcnt;
+       uint64_t                ns_dupeframecnt;
+       uint64_t                ns_rxfragcnt;
+       uint64_t                ns_rxmcastcnt;
+       uint64_t                ns_fcserrcnt;
+};
+
+typedef struct ndis_80211_stats ndis_80211_stats;
+
+typedef uint32_t ndis_80211_key_idx;
+
+struct ndis_80211_wep {
+       uint32_t                nw_length;
+       uint32_t                nw_keyidx;
+       uint32_t                nw_keylen;
+       uint8_t                 nw_keydata[256];
+};
+
+typedef struct ndis_80211_wep ndis_80211_wep;
+
+#define NDIS_80211_WEPKEY_TX           0x80000000
+#define NDIS_80211_WEPKEY_PERCLIENT    0x40000000
+
+#define NDIS_80211_NET_INFRA_IBSS      0x00000000
+#define NDIS_80211_NET_INFRA_BSS       0x00000001
+#define NDIS_80211_NET_INFRA_AUTO      0x00000002
+
+#define NDIS_80211_AUTHMODE_OPEN       0x00000000
+#define NDIS_80211_AUTHMODE_SHARED     0x00000001
+#define NDIS_80211_AUTHMODE_AUTO       0x00000002
+#define NDIS_80211_AUTHMODE_WPA                0x00000003
+#define NDIS_80211_AUTHMODE_WPAPSK     0x00000004
+#define NDIS_80211_AUTHMODE_WPANONE    0x00000005
+
+typedef uint8_t ndis_80211_rates[8];
+typedef uint8_t ndis_80211_rates_ex[16];
+typedef uint8_t ndis_80211_macaddr[6];
+
+struct ndis_80211_ssid {
+       uint32_t                ns_ssidlen;
+       uint8_t                 ns_ssid[32];
+};
+
+typedef struct ndis_80211_ssid ndis_80211_ssid;
+
+struct ndis_wlan_bssid {
+       uint32_t                nwb_length;
+       ndis_80211_macaddr      nwb_macaddr;
+       uint8_t                 nwb_rsvd[2];
+       ndis_80211_ssid         nwb_ssid;
+       uint32_t                nwb_privacy;
+       ndis_80211_rssi         nwb_rssi;
+       uint32_t                nwb_nettype;
+       ndis_80211_config       nwb_config;
+       uint32_t                nwb_netinfra;
+       ndis_80211_rates        nwb_supportedrates;
+};
+
+typedef struct ndis_wlan_bssid ndis_wlan_bssid;
+
+struct ndis_80211_bssid_list {
+       uint32_t                nbl_items;
+       ndis_wlan_bssid         nbl_bssid[1];
+};
+
+typedef struct ndis_80211_bssid_list ndis_80211_bssid_list;
+
+struct ndis_wlan_bssid_ex {
+       uint32_t                nwbx_len;
+       ndis_80211_macaddr      nwbx_macaddr;
+       uint8_t                 nwbx_rsvd[2];
+       ndis_80211_ssid         nwbx_ssid;
+       uint32_t                nwbx_privacy;
+       ndis_80211_rssi         nwbx_rssi;
+       uint32_t                nwbx_nettype;
+       ndis_80211_config       nwbx_config;
+       uint32_t                nwbx_netinfra;
+       ndis_80211_rates_ex     nwbx_supportedrates;
+       uint32_t                nwbx_ielen;
+       uint32_t                nwbx_ies[1];
+};
+
+typedef struct ndis_wlan_bssid_ex ndis_wlan_bssid_ex;
+
+struct ndis_80211_bssid_list_ex {
+       uint32_t                nblx_items;
+       ndis_wlan_bssid_ex      nblx_bssid[1];
+};
+
+typedef struct ndis_80211_bssid_list_ex ndis_80211_bssid_list_ex;
+
+struct ndis_80211_fixed_ies {
+       uint8_t                 nfi_tstamp[8];
+       uint16_t                nfi_beaconint;
+       uint16_t                nfi_caps;
+};
+
+struct ndis_80211_variable_ies {
+       uint8_t                 nvi_elemid;
+       uint8_t                 nvi_len;
+       uint8_t                 nvi_data[1];
+};
+
+typedef uint32_t ndis_80211_fragthresh;
+typedef uint32_t ndis_80211_rtsthresh;
+typedef uint32_t ndis_80211_antenna;
+
+#define NDIS_80211_PRIVFILT_ACCEPTALL  0x00000000
+#define NDIS_80211_PRIVFILT_8021XWEP   0x00000001
+
+#define NDIS_80211_WEPSTAT_ENABLED     0x00000000
+#define NDIS_80211_WEPSTAT_ENC1ENABLED NDIS_80211_WEPSTAT_ENABLED
+#define NDIS_80211_WEPSTAT_DISABLED    0x00000001
+#define NDIS_80211_WEPSTAT_ENCDISABLED NDIS_80211_WEPSTAT_DISABLED
+#define NDIS_80211_WEPSTAT_KEYABSENT   0x00000002
+#define NDIS_80211_WEPSTAT_ENC1KEYABSENT       NDIS_80211_WEPSTAT_KEYABSENT
+#define NDIS_80211_WEPSTAT_NOTSUPPORTED        0x00000003
+#define NDIS_80211_WEPSTAT_ENCNOTSUPPORTED     NDIS_80211_WEPSTAT_NOTSUPPORTED
+#define NDIS_80211_WEPSTAT_ENC2ENABLED 0x00000004
+#define NDIS_80211_WEPSTAT_ENC2KEYABSENT       0x00000005
+#define NDIS_80211_WEPSTAT_ENC3ENABLED 0x00000006
+#define NDIS_80211_WEPSTAT_ENC3KEYABSENT       0x00000007
+
+#define NDIS_80211_RELOADDEFAULT_WEP   0x00000000
+
+#define NDIS_80211_STATUSTYPE_AUTH     0x00000000
+
+struct ndis_80211_status_indication {
+       uint32_t                nsi_type;
+};
+
+typedef struct ndis_80211_status_indication ndis_80211_status_indication;
+
+struct ndis_80211_auth_request {
+       uint32_t                nar_len;
+       ndis_80211_macaddr      nar_bssid;
+       uint32_t                nar_flags;
+};
+
+typedef struct ndis_80211_auth_request ndis_80211_auth_request;
+
+struct ndis_80211_key {
+       uint32_t                nk_len;
+       uint32_t                nk_keyidx;
+       uint32_t                nk_keylen;
+       ndis_80211_macaddr      nk_bssid;
+       uint64_t                nk_keyrsc;
+       uint8_t                 nk_keydata[256];
+};
+
+typedef struct ndis_80211_key ndis_80211_key;
+
+struct ndis_80211_remove_key {
+       uint32_t                nk_len;
+       uint32_t                nk_keyidx;
+       ndis_80211_macaddr      nk_bssid;
+};
+
+typedef struct ndis_80211_remove_key ndis_80211_remove_key;
+
+#define NDIS_80211_AI_REQFI_CAPABILITIES       0x00000001
+#define NDIS_80211_AI_REQFI_LISTENINTERVAL     0x00000002
+#define NDIS_80211_AI_REQFI_CURRENTAPADDRESS   0x00000004
+
+#define NDIS_80211_AI_RESFI_CAPABILITIES       0x00000001
+#define NDIS_80211_AI_RESFI_STATUSCODE         0x00000002
+#define NDIS_80211_AI_RESFI_ASSOCIATIONID      0x00000004
+
+struct ndis_80211_ai_reqfi {
+       uint16_t                naq_caps;
+       uint16_t                naq_listentint;
+       ndis_80211_macaddr      naq_currentapaddr;
+};
+
+typedef struct ndis_80211_ai_reqfi ndis_80211_ai_reqfi;
+
+struct ndis_80211_ai_resfi {
+       uint16_t                nas_caps;
+       uint16_t                nas_statuscode;
+       uint16_t                nas_associd;
+};
+
+typedef struct ndis_80211_ai_resfi ndis_80211_ai_resfi;
+
+struct ndis_80211_assoc_info {
+       uint32_t                nai_len;
+       uint16_t                nai_avail_req_fixed_ies;
+       ndis_80211_ai_reqfi     nai_req_fixed_ies;
+       uint32_t                nai_req_ielen;
+       uint32_t                nai_offset_req_ies;
+       uint16_t                nai_avail_resp_fixed_ies;
+       ndis_80211_ai_resfi     nai_resp_fixed_iex;
+       uint32_t                nai_resp_ielen;
+       uint32_t                nai_offset_resp_ies;
+};
+
+typedef struct ndis_80211_assoc_info ndis_80211_assoc_info;
+
+struct ndis_80211_auth_event {
+       ndis_80211_status_indication    nae_status;
+       ndis_80211_auth_request         nae_request[1];
+};
+
+typedef struct ndis_80211_auth_event ndis_80211_auth_event;
+
+struct ndis_80211_test {
+       uint32_t                nt_len;
+       uint32_t                nt_type;
+       union {
+               ndis_80211_auth_event   nt_authevent;
+               uint32_t                nt_rssitrigger;
+       } u;
+};
+
+typedef struct ndis_80211_test ndis_80211_test;
+
+/* TCP OIDs. */
+
+#define OID_TCP_TASK_OFFLOAD                   0xFC010201
+#define OID_TCP_TASK_IPSEC_ADD_SA              0xFC010202
+#define OID_TCP_TASK_IPSEC_DELETE_SA           0xFC010203
+#define OID_TCP_SAN_SUPPORT                    0xFC010204
+
+
+#define NDIS_TASK_OFFLOAD_VERSION 1
+
+#define NDIS_TASK_TCPIP_CSUM                   0x00000000
+#define NDIS_TASK_IPSEC                                0x00000001
+#define NDIS_TASK_TCP_LARGESEND                        0x00000002
+
+#define NDIS_ENCAP_UNSPEC                      0x00000000
+#define NDIS_ENCAP_NULL                                0x00000001
+#define NDIS_ENCAP_IEEE802_3                   0x00000002
+#define NDIS_ENCAP_IEEE802_5                   0x00000003
+#define NDIS_ENCAP_SNAP_ROUTED                 0x00000004
+#define NDIS_ENCAP_SNAP_BRIDGED                        0x00000005
+
+#define NDIS_ENCAPFLAG_FIXEDHDRLEN             0x00000001
+
+struct ndis_encap_fmt {
+       uint32_t                nef_encap;
+       uint32_t                nef_flags;
+       uint32_t                nef_encaphdrlen;
+};
+
+typedef struct ndis_encap_fmt ndis_encap_fmt;
+
+struct ndis_task_offload_hdr {
+       uint32_t                ntoh_vers;
+       uint32_t                ntoh_len;
+       uint32_t                ntoh_rsvd;
+       uint32_t                ntoh_offset_firsttask;
+       ndis_encap_fmt          ntoh_encapfmt;
+};
+
+typedef struct ndis_task_offload_hdr ndis_task_offload_hdr;
+
+struct ndis_task_offload {
+       uint32_t                nto_vers;
+       uint32_t                nto_len;
+       uint32_t                nto_task;
+       uint32_t                nto_offset_nexttask;
+       uint32_t                nto_taskbuflen;
+       uint8_t                 nto_taskbuf[1];
+};
+
+typedef struct ndis_task_offload ndis_task_offload;
+
+#define NDIS_TCPSUM_FLAGS_IP_OPTS      0x00000001
+#define NDIS_TCPSUM_FLAGS_TCP_OPTS     0x00000002
+#define NDIS_TCPSUM_FLAGS_TCP_CSUM     0x00000004
+#define NDIS_TCPSUM_FLAGS_UDP_CSUM     0x00000008
+#define NDIS_TCPSUM_FLAGS_IP_CSUM      0x00000010
+
+struct ndis_task_tcpip_csum {
+       uint32_t                nttc_v4tx;
+       uint32_t                nttc_v4rx;
+       uint32_t                nttc_v6tx;
+       uint32_t                nttc_v6rx;
+};
+
+typedef struct ndis_task_tcpip_csum ndis_task_tcpip_csum;
+
+struct ndis_task_tcp_largesend {
+       uint32_t                nttl_vers;
+       uint32_t                nttl_maxofflen;
+       uint32_t                nttl_minsegcnt;
+       uint8_t                 nttl_tcpopt;
+       uint8_t                 nttl_ipopt;
+};
+
+typedef struct ndis_task_tcp_largesend ndis_task_tcp_largesend;
+
+#define NDIS_IPSEC_AH_MD5              0x00000001
+#define NDIS_IPSEC_AH_SHA1             0x00000002
+#define NDIS_IPSEC_AH_TRANSPORT                0x00000004
+#define NDIS_IPSEC_AH_TUNNEL           0x00000008
+#define NDIS_IPSEC_AH_SEND             0x00000010
+#define NDIS_IPSEC_AH_RECEIVE          0x00000020
+
+#define NDIS_IPSEC_ESP_DES             0x00000001
+#define NDIS_IPSEC_ESP_RSVD            0x00000002
+#define NDIS_IPSEC_ESP_3DES            0x00000004
+#define NDIS_IPSEC_ESP_NULL            0x00000008
+#define NDIS_IPSEC_ESP_TRANSPORT       0x00000010
+#define NDIS_IPSEC_ESP_TUNNEL          0x00000020
+#define NDIS_IPSEC_ESP_SEND            0x00000040
+#define NDIS_IPSEC_ESP_RECEIVE         0x00000080
+
+struct ndis_task_ipsec {
+       uint32_t                nti_ah_esp_combined;
+       uint32_t                nti_ah_transport_tunnel_combined;
+       uint32_t                nti_v4_options;
+       uint32_t                nti_rsvd;
+       uint32_t                nti_v4ah;
+       uint32_t                nti_v4esp;
+};
+
+typedef struct ndis_task_ipsec ndis_task_ipsec;
+
+/*
+ * Attribures of NDIS drivers. Not all drivers support
+ * all attributes.
+ */
+
+#define NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT          0x00000002
+#define NDIS_ATTRIBUTE_IGNORE_TOKEN_RING_ERRORS                0x00000004
+#define NDIS_ATTRIBUTE_BUS_MASTER                      0x00000008
+#define NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER             0x00000010
+#define NDIS_ATTRIBUTE_DESERIALIZE                     0x00000020
+#define NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND              0x00000040
+#define NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK              0x00000080
+#define NDIS_ATTRIBUTE_NOT_CO_NDIS                     0x00000100
+#define NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS           0x00000200
+
+enum ndis_media_state {
+       nmc_connected,
+       nmc_disconnected
+};
+
+typedef enum ndis_media_state ndis_media_state;
+
+/* Ndis Packet Filter Bits (OID_GEN_CURRENT_PACKET_FILTER). */
+
+#define NDIS_PACKET_TYPE_DIRECTED               0x00000001
+#define NDIS_PACKET_TYPE_MULTICAST              0x00000002
+#define NDIS_PACKET_TYPE_ALL_MULTICAST          0x00000004
+#define NDIS_PACKET_TYPE_BROADCAST              0x00000008
+#define NDIS_PACKET_TYPE_SOURCE_ROUTING         0x00000010
+#define NDIS_PACKET_TYPE_PROMISCUOUS            0x00000020
+#define NDIS_PACKET_TYPE_SMT                    0x00000040
+#define NDIS_PACKET_TYPE_ALL_LOCAL              0x00000080
+#define NDIS_PACKET_TYPE_GROUP                  0x00001000
+#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL         0x00002000
+#define NDIS_PACKET_TYPE_FUNCTIONAL             0x00004000
+#define NDIS_PACKET_TYPE_MAC_FRAME              0x00008000
+
+
+/* Ndis MAC option bits (OID_GEN_MAC_OPTIONS). */
+
+#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA             0x00000001
+#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED              0x00000002
+#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND              0x00000004
+#define NDIS_MAC_OPTION_NO_LOOPBACK                     0x00000008
+#define NDIS_MAC_OPTION_FULL_DUPLEX                     0x00000010
+#define NDIS_MAC_OPTION_EOTX_INDICATION                 0x00000020
+#define NDIS_MAC_OPTION_8021P_PRIORITY                  0x00000040
+#define NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE  0x00000080
+#define NDIS_MAC_OPTION_RECEIVE_AT_DPC                  0x00000100
+#define NDIS_MAC_OPTION_8021Q_VLAN                      0x00000200
+#define NDIS_MAC_OPTION_RESERVED                        0x80000000
+
+#define NDIS_DMA_24BITS                0x00
+#define NDIS_DMA_32BITS                0x01
+#define NDIS_DMA_64BITS                0x02
+
+struct ndis_physaddr {
+       uint64_t                np_quad;
+#ifdef notdef
+       uint32_t                np_low;
+       uint32_t                np_high;
+#endif
+};
+
+typedef struct ndis_physaddr ndis_physaddr;
+
+struct ndis_ansi_string {
+       uint16_t                nas_len;
+       uint16_t                nas_maxlen;
+       char                    *nas_buf;
+};
+
+typedef struct ndis_ansi_string ndis_ansi_string;
+
+/*
+ * nus_buf is really a wchar_t *, but it's inconvenient to include
+ * all the necessary header goop needed to define it, and it's a
+ * pointer anyway, so for now, just make it a uint16_t *.
+ */
+struct ndis_unicode_string {
+       uint16_t                nus_len;
+       uint16_t                nus_maxlen;
+       uint16_t                *nus_buf;
+};
+
+typedef struct ndis_unicode_string ndis_unicode_string;
+
+
+enum ndis_parm_type {
+       ndis_parm_int,
+       ndis_parm_hexint,
+       ndis_parm_string,
+       ndis_parm_multistring,
+       ndis_parm_binary
+};
+
+typedef enum ndis_parm_type ndis_parm_type;
+
+struct ndis_binary_data {
+       uint16_t                nbd_len;
+       void                    *nbd_buf;
+};
+
+typedef struct ndis_binary_data ndis_binary_data;
+
+struct ndis_config_parm {
+       ndis_parm_type          ncp_type;
+       union {
+               uint32_t                ncp_intdata;
+               ndis_unicode_string     ncp_stringdata;
+               ndis_binary_data        ncp_binarydata;
+       } ncp_parmdata;
+};
+
+typedef struct ndis_config_parm ndis_config_parm;
+
+#ifdef notdef
+struct ndis_list_entry {
+       struct ndis_list_entry *nle_flink;
+       struct ndis_list_entry *nle_blink;
+};
+
+typedef struct ndis_list_entry ndis_list_entry;
+#endif
+
+struct ndis_bind_paths {
+       uint32_t                nbp_number;
+       ndis_unicode_string     nbp_paths[1];
+};
+
+typedef struct ndis_bind_paths ndis_bind_paths;
+
+#ifdef notdef
+struct dispatch_header {
+       uint8_t                 dh_type;
+       uint8_t                 dh_abs;
+       uint8_t                 dh_size;
+       uint8_t                 dh_inserted;
+       uint32_t                dh_sigstate;
+       list_entry              dh_waitlisthead;
+};
+#endif
+
+#define dispatch_header nt_dispatch_header
+
+struct ndis_ktimer {
+       struct dispatch_header  nk_header;
+       uint64_t                nk_duetime;
+       list_entry              nk_timerlistentry;
+       void                    *nk_dpc;
+       uint32_t                nk_period;
+};
+
+struct ndis_kevent {
+       struct dispatch_header  nk_header;
+};
+
+struct ndis_event {
+       struct nt_kevent        ne_event;
+};
+
+typedef struct ndis_event ndis_event;
+
+/* Kernel defered procedure call (i.e. timer callback) */
+
+struct ndis_kdpc;
+typedef void (*ndis_kdpc_func)(struct ndis_kdpc *, void *, void *, void *);
+
+struct ndis_kdpc {
+       uint16_t                nk_type;
+       uint8_t                 nk_num;
+       uint8_t                 nk_importance;
+       list_entry              nk_dpclistentry;
+       ndis_kdpc_func          nk_deferedfunc;
+       void                    *nk_deferredctx;
+       void                    *nk_sysarg1;
+       void                    *nk_sysarg2;
+       uint32_t                *nk_lock;
+};
+
+struct ndis_timer {
+       struct ktimer           nt_ktimer;
+       struct kdpc             nt_kdpc;
+};
+
+typedef struct ndis_timer ndis_timer;
+
+typedef void (*ndis_timer_function)(void *, void *, void *, void *);
+
+struct ndis_miniport_timer {
+       struct ktimer           nmt_ktimer;
+       struct kdpc             nmt_kdpc;
+       ndis_timer_function     nmt_timerfunc;
+       void                    *nmt_timerctx;
+       ndis_miniport_block     *nmt_block;
+       struct ndis_miniport_timer      *nmt_nexttimer;
+};
+
+typedef struct ndis_miniport_timer ndis_miniport_timer;
+
+struct ndis_spin_lock {
+       ndis_kspin_lock         nsl_spinlock;
+       ndis_kirql              nsl_kirql;
+};
+
+typedef struct ndis_spin_lock ndis_spin_lock;
+
+struct ndis_request {
+       uint8_t                 nr_macreserved[4*sizeof(void *)];
+       uint32_t                nr_requesttype;
+       union _ndis_data {
+               struct _ndis_query_information {
+                       ndis_oid        nr_oid;
+                       void            *nr_infobuf;
+                       uint32_t        nr_infobuflen;
+                       uint32_t        nr_byteswritten;
+                       uint32_t        nr_bytesneeded;
+               } ndis_query_information;
+               struct _ndis_set_information {
+                       ndis_oid        nr_oid;
+                       void            *nr_infobuf;
+                       uint32_t        nr_infobuflen;
+                       uint32_t        nr_byteswritten;
+                       uint32_t        nr_bytesneeded;
+               } ndis_set_information;
+       } ndis_data;
+       /* NDIS 5.0 extentions */
+       uint8_t                 nr_ndis_rsvd[9 * sizeof(void *)];
+       union {
+               uint8_t         nr_callmgr_rsvd[2 * sizeof(void *)];
+               uint8_t         nr_protocol_rsvd[2 * sizeof(void *)];
+       } u;
+       uint8_t                 nr_miniport_rsvd[2 * sizeof(void *)];
+};
+
+typedef struct ndis_request ndis_request;
+
+/*
+ * Filler, not used.
+ */
+struct ndis_miniport_interrupt {
+       void                    *ni_introbj;
+       ndis_kspin_lock         ni_dpccountlock;
+       void                    *ni_rsvd;
+       void                    *ni_isrfunc;
+       void                    *ni_dpcfunc;
+       struct ndis_kdpc        ni_dpc;
+       ndis_miniport_block     *ni_block;
+       uint8_t                 ni_dpccnt;
+       uint8_t                 ni_filler1;
+       struct ndis_kevent      ni_dpcsdoneevent;
+       uint8_t                 ni_shared;
+       uint8_t                 ni_isrreq;
+};
+
+typedef struct ndis_miniport_interrupt ndis_miniport_interrupt;
+
+enum ndis_interrupt_mode {
+       nim_level,
+       nim_latched
+};
+
+typedef enum ndis_interrupt_mode ndis_interrupt_mode;
+
+struct ndis_work_item;
+
+typedef void (*ndis_proc)(struct ndis_work_item *, void *);
+
+struct ndis_work_item {
+       void                    *nwi_ctx;
+       ndis_proc               nwi_func;
+       uint8_t                 nwi_wraprsvd[sizeof(void *) * 8];
+};
+
+typedef struct ndis_work_item ndis_work_item;
+
+struct ndis_buffer {
+       struct ndis_buffer      *nb_next;
+       uint16_t                nb_size;
+       uint16_t                nb_flags;
+       void                    *nb_process;
+       void                    *nb_mappedsystemva;
+       void                    *nb_startva;
+       uint32_t                nb_bytecount;
+       uint32_t                nb_byteoffset;
+};
+
+typedef struct ndis_buffer ndis_buffer;
+
+struct ndis_sc_element {
+       ndis_physaddr           nse_addr;
+       uint32_t                nse_len;
+       uint32_t                *nse_rsvd;
+};
+
+typedef struct ndis_sc_element ndis_sc_element;
+
+#define NDIS_MAXSEG            32
+#define NDIS_BUS_SPACE_SHARED_MAXADDR  0x3E7FFFFF
+
+struct ndis_sc_list {
+       uint32_t                nsl_frags;
+       uint32_t                *nsl_rsvd;
+       ndis_sc_element         nsl_elements[NDIS_MAXSEG];
+};
+
+typedef struct ndis_sc_list ndis_sc_list;
+
+struct ndis_tcpip_csum {
+       union {
+               uint32_t                ntc_txflags;
+               uint32_t                ntc_rxflags;
+               uint32_t                ntc_val;
+       } u;
+};
+
+typedef struct ndis_tcpip_csum ndis_tcpip_csum;
+
+#define NDIS_TXCSUM_DO_IPV4            0x00000001
+#define NDIS_TXCSUM_DO_IPV6            0x00000002
+#define NDIS_TXCSUM_DO_TCP             0x00000004
+#define NDIS_TXCSUM_DO_UDP             0x00000008
+#define NDIS_TXCSUM_DO_IP              0x00000010
+
+#define NDIS_RXCSUM_TCP_FAILED         0x00000001
+#define NDIS_RXCSUM_UDP_FAILED         0x00000002
+#define NDIS_RXCSUM_IP_FAILED          0x00000004
+#define NDIS_RXCSUM_TCP_PASSED         0x00000008
+#define NDIS_RXCSUM_UDP_PASSED         0x00000010
+#define NDIS_RXCSUM_IP_PASSED          0x00000020
+#define NDIS_RXCSUM_LOOPBACK           0x00000040
+
+struct ndis_vlan {
+       union {
+               struct {
+                       uint32_t                        nvt_userprio:3;
+                       uint32_t                        nvt_canformatid:1;
+                       uint32_t                        nvt_vlanid:12;
+                       uint32_t                        nvt_rsvd:16;
+               } nv_taghdr;
+       } u;
+};
+
+typedef struct ndis_vlan ndis_vlan;
+
+enum ndis_perpkt_info {
+       ndis_tcpipcsum_info,
+       ndis_ipsec_info,
+       ndis_largesend_info,
+       ndis_classhandle_info,
+       ndis_rsvd,
+       ndis_sclist_info,
+       ndis_ieee8021q_info,
+       ndis_originalpkt_info,
+        ndis_packetcancelid,
+       ndis_maxpkt_info
+};
+
+typedef enum ndis_perpkt_info ndis_perpkt_info;
+
+struct ndis_packet_extension {
+       void                    *npe_info[ndis_maxpkt_info];
+};
+
+typedef struct ndis_packet_extension ndis_packet_extension;
+
+struct ndis_packet_private {
+       uint32_t                npp_physcnt;
+       uint32_t                npp_totlen;
+       ndis_buffer             *npp_head;
+       ndis_buffer             *npp_tail;
+
+       void                    *npp_pool;
+       uint32_t                npp_count;
+       uint32_t                npp_flags;
+       uint8_t                 npp_validcounts;
+       uint8_t                 npp_ndispktflags;
+       uint16_t                npp_packetooboffset;
+};
+
+#define NDIS_FLAGS_PROTOCOL_ID_MASK             0x0000000F
+#define NDIS_FLAGS_MULTICAST_PACKET             0x00000010
+#define NDIS_FLAGS_RESERVED2                    0x00000020
+#define NDIS_FLAGS_RESERVED3                    0x00000040
+#define NDIS_FLAGS_DONT_LOOPBACK                0x00000080
+#define NDIS_FLAGS_IS_LOOPBACK_PACKET           0x00000100
+#define NDIS_FLAGS_LOOPBACK_ONLY                0x00000200
+#define NDIS_FLAGS_RESERVED4                    0x00000400
+#define NDIS_FLAGS_DOUBLE_BUFFERED              0x00000800
+#define NDIS_FLAGS_SENT_AT_DPC                  0x00001000
+#define NDIS_FLAGS_USES_SG_BUFFER_LIST          0x00002000
+
+#define NDIS_PACKET_WRAPPER_RESERVED                   0x3F
+#define NDIS_PACKET_CONTAINS_MEDIA_SPECIFIC_INFO       0x40
+#define NDIS_PACKET_ALLOCATED_BY_NDIS                  0x80
+
+#define NDIS_PROTOCOL_ID_DEFAULT        0x00
+#define NDIS_PROTOCOL_ID_TCP_IP         0x02
+#define NDIS_PROTOCOL_ID_IPX            0x06
+#define NDIS_PROTOCOL_ID_NBF            0x07
+#define NDIS_PROTOCOL_ID_MAX            0x0F
+#define NDIS_PROTOCOL_ID_MASK           0x0F
+
+typedef struct ndis_packet_private ndis_packet_private;
+
+enum ndis_classid {
+       ndis_class_802_3prio,
+       ndis_class_wirelesswan_mbx,
+       ndis_class_irda_packetinfo,
+       ndis_class_atm_aainfo
+};
+
+typedef enum ndis_classid ndis_classid;
+
+struct ndis_mediaspecific_info {
+       uint32_t                nmi_nextentoffset;
+       ndis_classid            nmi_classid;
+       uint32_t                nmi_size;
+       uint8_t                 nmi_classinfo[1];
+};
+
+typedef struct ndis_mediaspecific_info ndis_mediaspecific_info;
+
+struct ndis_packet_oob {
+       union {
+               uint64_t                npo_timetotx;
+               uint64_t                npo_timetxed;
+       } u;
+       uint64_t                        npo_timerxed;
+       uint32_t                        npo_hdrlen;
+       uint32_t                        npo_mediaspecific_len;
+       void                            *npo_mediaspecific;
+       ndis_status                     npo_status;
+};
+
+typedef struct ndis_packet_oob ndis_packet_oob;
+
+struct ndis_packet {
+       ndis_packet_private     np_private;
+       union {
+               /* For connectionless miniports. */
+               struct {
+                       uint8_t         np_miniport_rsvd[2 * sizeof(void *)];
+                       uint8_t         np_wrapper_rsvd[2 * sizeof(void *)];
+               } np_clrsvd;
+               /* For de-serialized miniports */
+               struct {
+                       uint8_t         np_miniport_rsvdex[3 * sizeof(void *)];
+                       uint8_t         np_wrapper_rsvdex[sizeof(void *)];
+               } np_dsrsvd;
+               struct {
+                       uint8_t         np_mac_rsvd[4 * sizeof(void *)];
+               } np_macrsvd;
+       } u;
+       uint32_t                *np_rsvd[2];
+
+       /*
+        * This next part is probably wrong, but we need some place
+        * to put the out of band data structure...
+        */
+       ndis_packet_oob         np_oob;
+       ndis_packet_extension   np_ext;
+       ndis_sc_list            np_sclist;
+
+       /* BSD-specific stuff which should be invisible to drivers. */
+
+       uint32_t                np_refcnt;
+       void                    *np_softc;
+       void                    *np_m0;
+       int                     np_txidx;
+};
+
+typedef struct ndis_packet ndis_packet;
+
+/* mbuf ext type for NDIS */
+#define EXT_NDIS               0x999
+
+/* mtx type for NDIS */
+#define MTX_NDIS_LOCK "NDIS lock"
+
+struct ndis_filterdbs {
+       union {
+               void                    *nf_ethdb;
+               void                    *nf_nulldb;
+       } u;
+       void                    *nf_trdb;
+       void                    *nf_fddidb;
+       void                    *nf_arcdb;
+};
+
+typedef struct ndis_filterdbs ndis_filterdbs;
+
+enum ndis_medium {
+    NdisMedium802_3,
+    NdisMedium802_5,
+    NdisMediumFddi,
+    NdisMediumWan,
+    NdisMediumLocalTalk,
+    NdisMediumDix,              /* defined for convenience, not a real medium */
+    NdisMediumArcnetRaw,
+    NdisMediumArcnet878_2,
+    NdisMediumAtm,
+    NdisMediumWirelessWan,
+    NdisMediumIrda,
+    NdisMediumBpc,
+    NdisMediumCoWan,
+    NdisMedium1394,
+    NdisMediumMax
+};
+
+typedef enum ndis_medium ndis_medium;
+/*
+enum interface_type {
+       InterfaceTypeUndefined = -1,
+       Internal,
+       Isa,
+       Eisa,
+       MicroChannel,
+       TurboChannel,
+       PCIBus,
+       VMEBus,
+       NuBus,
+       PCMCIABus,
+       CBus,
+       MPIBus,
+       MPSABus,
+       ProcessorInternal,
+       InternalPowerBus,
+       PNPISABus,
+       PNPBus,
+       MaximumInterfaceType
+};
+*/
+enum ndis_interface_type {
+       NdisInterfaceInternal = Internal,
+       NdisInterfaceIsa = Isa,
+       NdisInterfaceEisa = Eisa,
+       NdisInterfaceMca = MicroChannel,
+       NdisInterfaceTurboChannel = TurboChannel,
+       NdisInterfacePci = PCIBus,
+       NdisInterfacePcMcia = PCMCIABus
+};
+
+typedef enum ndis_interface_type ndis_interface_type;
+
+struct ndis_paddr_unit {
+       ndis_physaddr           npu_physaddr;
+       uint32_t                npu_len;
+};
+
+typedef struct ndis_paddr_unit ndis_paddr_unit;
+
+struct ndis_map_arg {
+       ndis_paddr_unit         *nma_fraglist;
+       int                     nma_cnt;
+       int                     nma_max;
+};
+
+/*
+ * Miniport characteristics were originally defined in the NDIS 3.0
+ * spec and then extended twice, in NDIS 4.0 and 5.0.
+ */
+
+struct ndis_miniport_characteristics {
+
+       /* NDIS 3.0 */
+
+       uint8_t                 nmc_version_major;
+       uint8_t                 nmc_version_minor;
+       uint16_t                nmc_pad;
+       uint32_t                nmc_rsvd;
+       void *                  nmc_checkhang_func;
+       void *                  nmc_disable_interrupts_func;
+       void *                  nmc_enable_interrupts_func;
+       void *                  nmc_halt_func;
+       void *                  nmc_interrupt_func;
+       void *                  nmc_init_func;
+       void *                  nmc_isr_func;
+       void *                  nmc_queryinfo_func;
+       void *                  nmc_reconfig_func;
+       void *                  nmc_reset_func;
+       void *                  nmc_sendsingle_func;
+       void *                  nmc_setinfo_func;
+       void *                  nmc_transferdata_func;
+
+       /* NDIS 4.0 extentions */
+
+       void *                  nmc_return_packet_func;
+       void *                  nmc_sendmulti_func;
+       void *                  nmc_allocate_complete_func;
+
+       /* NDIS 5.0 extensions */
+
+       void *                  nmc_cocreatevc_func;
+       void *                  nmc_codeletevc_func;
+       void *                  nmc_coactivatevc_func;
+       void *                  nmc_codeactivatevc_func;
+       void *                  nmc_comultisend_func;
+       void *                  nmc_corequest_func;
+
+       /* NDIS 5.1 extentions */
+
+       void *                  nmc_canceltxpkts_handler;
+       void *                  nmc_pnpevent_handler;
+       void *                  nmc_shutdown_handler;
+       void *                  nmc_rsvd0;
+       void *                  nmc_rsvd1;
+       void *                  nmc_rsvd2;
+       void *                  nmc_rsvd3;
+};
+
+typedef struct ndis_miniport_characteristics ndis_miniport_characteristics;
+
+struct ndis_driver_object {
+       char                    *ndo_ifname;
+       void                    *ndo_softc;
+       ndis_miniport_characteristics ndo_chars;
+};
+
+typedef struct ndis_driver_object ndis_driver_object;
+
+struct ndis_reference {
+       ndis_kspin_lock         nr_spinlock;
+       uint16_t                nr_refcnt;
+       uint8_t                 nr_closing;
+};
+
+typedef struct ndis_reference ndis_reference;
+
+struct ndis_timer_entry {
+       struct callout          nte_ch;
+       ndis_miniport_timer     *nte_timer;
+       TAILQ_ENTRY(ndis_timer_entry)   link;
+};
+
+TAILQ_HEAD(nte_head, ndis_timer_entry);
+
+struct ndis_fh {
+       void                    *nf_vp;
+       void                    *nf_map;
+       uint32_t                nf_maplen; 
+};
+
+typedef struct ndis_fh ndis_fh;
+
+/*
+ * The miniport block is basically the internal NDIS handle. We need
+ * to define this because, unfortunately, it is not entirely opaque
+ * to NDIS drivers. For one thing, it contains the function pointer
+ * to the NDIS packet receive handler, which is invoked out of the
+ * NDIS block via a macro rather than a function pointer. (The
+ * NdisMIndicateReceivePacket() routine is a macro rather than
+ * a function.) For another, the driver maintains a pointer to the
+ * miniport block and passes it as a handle to various NDIS functions.
+ * (The driver never really knows this because it's hidden behind
+ * an ndis_handle though.)
+ *
+ * The miniport block has two parts: the first part contains fields
+ * that must never change, since they are referenced by driver
+ * binaries through macros. The second part is ignored by the driver,
+ * but contains various things used internaly by NDIS.SYS. In our
+ * case, we define the first 'immutable' part exactly as it appears
+ * in Windows, but don't bother duplicating the Windows definitions
+ * for the second part. Instead, we replace them with a few BSD-specific
+ * things.
+ */
+
+struct ndis_miniport_block {
+       /*
+        * Windows-specific portion -- DO NOT MODIFY OR NDIS
+        * DRIVERS WILL NOT WORK.
+        */ 
+       void                    *nmb_signature; /* magic number */
+       ndis_miniport_block     *nmb_nextminiport;
+       ndis_mdriver_block      *nmb_driverhandle;
+       ndis_handle             nmb_miniportadapterctx;
+       ndis_unicode_string     nmb_name;
+       ndis_bind_paths         *nmb_bindpaths;
+       ndis_handle             nmb_openqueue;
+       ndis_reference          nmb_ref;
+       ndis_handle             nmb_devicectx;
+       uint8_t                 nmb_padding;
+       uint8_t                 nmb_lockacquired;
+       uint8_t                 nmb_pmodeopens;
+       uint8_t                 nmb_assignedcpu;
+       ndis_kspin_lock         nmb_lock;
+       ndis_request            *nmb_mediarequest;
+       ndis_miniport_interrupt *nmb_interrupt;
+       uint32_t                nmb_flags;
+       uint32_t                nmb_pnpflags;
+       list_entry              nmb_packetlist;
+       ndis_packet             *nmb_firstpendingtxpacket;
+       ndis_packet             *nmb_returnpacketqueue;
+       uint32_t                nmb_requestbuffer;
+       void                    *nmb_setmcastbuf;
+       ndis_miniport_block     *nmb_primaryminiport;
+       void                    *nmb_wrapperctx;
+       void                    *nmb_busdatactx;
+       uint32_t                nmb_pnpcaps;
+       cm_resource_list        *nmb_resources;
+       ndis_timer              nmb_wkupdpctimer;
+       ndis_unicode_string     nmb_basename;
+       ndis_unicode_string     nmb_symlinkname;
+       uint32_t                nmb_checkforhangsecs;
+       uint16_t                nmb_cfhticks;
+       uint16_t                nmb_cfhcurrticks;
+       ndis_status             nmb_resetstatus;
+       ndis_handle             nmb_resetopen;
+       ndis_filterdbs          nmb_filterdbs;
+       void                    *nmb_pktind_func;
+       void                    *nmb_senddone_func;
+       void                    *nmb_sendrsrc_func;
+       void                    *nmb_resetdone_func;
+       ndis_medium             nmb_medium;
+       uint32_t                nmb_busnum;
+       uint32_t                nmb_bustye;
+       uint32_t                nmb_adaptertype;
+       void                    *nmb_deviceobj;
+       void                    *nmb_physdeviceobj;
+       void                    *nmb_nextdeviceobj;
+       void                    *nmb_mapreg;
+       void                    *nmb_callmgraflist;
+       void                    *nmb_miniportthread;
+       void                    *nmb_setinfobuf;
+       uint16_t                nmb_setinfobuflen;
+       uint16_t                nmb_maxsendpkts;
+       ndis_status             nmb_fakestatus;
+       void                    *nmb_lockhandler;
+       ndis_unicode_string     *nmb_adapterinstancename;
+       void                    *nmb_timerqueue;
+       uint32_t                nmb_mactoptions;
+       ndis_request            *nmb_pendingreq;
+       uint32_t                nmb_maxlongaddrs;
+       uint32_t                nmb_maxshortaddrs;
+       uint32_t                nmb_currlookahead;
+       uint32_t                nmb_maxlookahead;
+       void                    *nmb_interrupt_func;
+       void                    *nmb_disableintr_func;
+       void                    *nmb_enableintr_func;
+       void                    *nmb_sendpkts_func;
+       void                    *nmb_deferredsend_func;
+       void                    *nmb_ethrxindicate_func;
+       void                    *nmb_txrxindicate_func;
+       void                    *nmb_fddirxindicate_func;
+       void                    *nmb_ethrxdone_func;
+       void                    *nmb_txrxdone_func;
+       void                    *nmb_fddirxcond_func;
+       void                    *nmb_status_func;
+       void                    *nmb_statusdone_func;
+       void                    *nmb_tdcond_func;
+       void                    *nmb_querydone_func;
+       void                    *nmb_setdone_func;
+       void                    *nmb_wantxdone_func;
+       void                    *nmb_wanrx_func;
+       void                    *nmb_wanrxdone_func;
+       /*
+        * End of windows-specific portion of miniport block. Everything
+        * below is BSD-specific.
+        */
+       struct ifnet            *nmb_ifp;
+       uint8_t                 nmb_dummybuf[128];
+       device_object           nmb_devobj;
+       ndis_config_parm        nmb_replyparm;
+       int                     nmb_pciidx;
+       device_t                nmb_dev;
+       ndis_resource_list      *nmb_rlist;
+       ndis_status             nmb_getstat;
+       ndis_status             nmb_setstat;
+       struct nte_head         nmb_timerlist;
+       vm_offset_t             nmb_img;
+       TAILQ_ENTRY(ndis_miniport_block)        link;
+};
+
+TAILQ_HEAD(nd_head, ndis_miniport_block);
+
+typedef ndis_status (*ndis_init_handler)(ndis_status *, uint32_t *,
+               ndis_medium *, uint32_t, ndis_handle, ndis_handle);
+typedef __stdcall ndis_status (*ndis_queryinfo_handler)(ndis_handle, ndis_oid,
+               void *, uint32_t, uint32_t *, uint32_t *);
+typedef ndis_status (*ndis_setinfo_handler)(ndis_handle, ndis_oid,
+               void *, uint32_t, uint32_t *, uint32_t *);
+typedef ndis_status (*ndis_sendsingle_handler)(ndis_handle,
+               ndis_packet *, uint32_t);
+typedef ndis_status (*ndis_sendmulti_handler)(ndis_handle,
+               ndis_packet **, uint32_t);
+typedef void (*ndis_isr_handler)(uint8_t *, uint8_t *, ndis_handle);
+typedef void (*ndis_interrupt_handler)(ndis_handle);
+typedef int (*ndis_reset_handler)(uint8_t *, ndis_handle);
+typedef void (*ndis_halt_handler)(ndis_handle);
+typedef void (*ndis_return_handler)(ndis_handle, ndis_packet *);
+typedef void (*ndis_enable_interrupts_handler)(ndis_handle);
+typedef void (*ndis_disable_interrupts_handler)(ndis_handle);
+typedef void (*ndis_shutdown_handler)(void *);
+typedef void (*ndis_allocdone_handler)(ndis_handle, void *,
+               ndis_physaddr *, uint32_t, void *);
+typedef uint8_t (*ndis_checkforhang_handler)(ndis_handle);
+
+typedef ndis_status (*driver_entry)(void *, ndis_unicode_string *);
+
+extern image_patch_table ndis_functbl[];
+
+#define NDIS_TASKQUEUE 1
+#define NDIS_SWI       2
+
+#define NDIS_PSTATE_RUNNING    1
+#define NDIS_PSTATE_SLEEPING   2
+
+__BEGIN_DECLS
+struct ndis_softc;
+
+extern int ndis_libinit(void);
+extern int ndis_libfini(void);
+extern int ndis_ascii_to_unicode(char *, uint16_t **);
+extern int ndis_unicode_to_ascii(uint16_t *, int, char **);
+extern int ndis_load_driver(vm_offset_t, void *);
+extern int ndis_unload_driver(void *);
+extern int ndis_mtop(struct mbuf *, ndis_packet **);
+extern int ndis_ptom(struct mbuf **, ndis_packet *);
+extern int ndis_get_info(void *, ndis_oid, void *, int *);
+extern int ndis_set_info(void *, ndis_oid, void *, int *);
+extern int ndis_get_supported_oids(void *, ndis_oid **, int *);
+extern int ndis_send_packets(void *, ndis_packet **, int);
+extern int ndis_send_packet(void *, ndis_packet *);
+extern int ndis_convert_res(void *);
+extern int ndis_alloc_amem(void *);
+extern void ndis_free_amem(void *);
+extern void ndis_free_packet(ndis_packet *);
+extern void ndis_free_bufs(ndis_buffer *);
+extern void ndis_return_packet(struct ndis_softc *sc, ndis_packet *p);
+extern int ndis_reset_nic(void *);
+extern int ndis_halt_nic(void *);
+extern int ndis_shutdown_nic(void *);
+extern int ndis_init_nic(void *);
+extern int ndis_isr(void *, int *, int *);
+extern int ndis_intrhand(void *);
+extern void ndis_enable_intr(void *);
+extern void ndis_disable_intr(void *);
+extern int ndis_init_dma(void *);
+extern int ndis_destroy_dma(void *);
+extern int ndis_create_sysctls(void *);
+extern int ndis_add_sysctl(void *, char *, char *, char *, int);
+extern int ndis_flush_sysctls(void *);
+extern int ndis_sched(void (*)(void *), void *, int);
+extern int ndis_unsched(void (*)(void *), void *, int);
+extern int ndis_thsuspend(struct thread *, int);
+extern void ndis_thresume(struct thread *);
+extern int ndis_strcasecmp(const char *, const char *);
+__END_DECLS
+
+#endif /* _NDIS_VAR_H_ */
diff --git a/sys/emulation/ndis/ntoskrnl_var.h b/sys/emulation/ndis/ntoskrnl_var.h
new file mode 100644 (file)
index 0000000..2033090
--- /dev/null
@@ -0,0 +1,521 @@
+/*
+ * 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: src/sys/compat/ndis/ntoskrnl_var.h,v 1.15 2004/04/20 02:27:38 wpaul Exp $
+ * $DragonFly: src/sys/emulation/ndis/ntoskrnl_var.h,v 1.1 2004/07/29 20:51:33 dillon Exp $
+ */
+
+#ifndef _NTOSKRNL_VAR_H_
+#define _NTOSKRNL_VAR_H_
+
+/* Note: assumes x86 page size of 4K. */
+#define PAGE_SHIFT     12
+#define SPAN_PAGES(ptr, len)                                   \
+       ((uint32_t)((((uintptr_t)(ptr) & (PAGE_SIZE -1)) +      \
+       (len) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
+#define PAGE_ALIGN(ptr)                                                \
+       ((void *)((uintptr_t)(ptr) & ~(PAGE_SIZE - 1)))
+#define BYTE_OFFSET(ptr)                                       \
+       ((uint32_t)((uintptr_t)(ptr) & (PAGE_SIZE - 1)))
+#define MDL_INIT(b, baseva, len)                                       \
+       (b)->nb_next = NULL;                                            \
+       (b)->nb_size = (uint16_t)(sizeof(struct ndis_buffer) +          \
+               (sizeof(uint32_t) * SPAN_PAGES((baseva), (len))));      \
+       (b)->nb_flags = 0;                                              \
+       (b)->nb_startva = (void *)PAGE_ALIGN((baseva));                 \
+       (b)->nb_byteoffset = BYTE_OFFSET((baseva));                     \
+       (b)->nb_bytecount = (uint32_t)(len);
+#define MDL_VA(b)                                              \
+       ((void *)((char *)((b)->nb_startva) + (b)->nb_byteoffset))
+
+#define WDM_MAJOR              1
+#define WDM_MINOR_WIN98                0x00
+#define WDM_MINOR_WINME                0x05
+#define WDM_MINOR_WIN2000      0x10
+#define WDM_MINOR_WINXP                0x20
+#define WDM_MINOR_WIN2003      0x30
+
+/*-
+ * The ndis_kspin_lock type is called KSPIN_LOCK in MS-Windows.
+ * According to the Windows DDK header files, KSPIN_LOCK is defined like this:
+ *     typedef ULONG_PTR KSPIN_LOCK;
+ *
+ * From basetsd.h (SDK, Feb. 2003):
+ *     typedef [public] unsigned __int3264 ULONG_PTR, *PULONG_PTR;
+ *     typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
+ *     typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR;
+ * 
+ * The keyword __int3264 specifies an integral type that has the following
+ * properties:
+ *     + It is 32-bit on 32-bit platforms
+ *     + It is 64-bit on 64-bit platforms
+ *     + It is 32-bit on the wire for backward compatibility.
+ *       It gets truncated on the sending side and extended appropriately
+ *       (signed or unsigned) on the receiving side.
+ *
+ * Thus register_t seems the proper mapping onto FreeBSD for spin locks.
+ */
+
+typedef register_t kspin_lock;
+
+struct slist_entry {
+       struct slist_entry      *sl_next;
+};
+
+typedef struct slist_entry slist_entry;
+
+union slist_header {
+       uint64_t                slh_align;
+       struct {
+               struct slist_entry      *slh_next;
+               uint16_t                slh_depth;
+               uint16_t                slh_seq;
+       } slh_list;
+};
+
+typedef union slist_header slist_header;
+
+struct list_entry {
+        struct list_entry *nle_flink;
+        struct list_entry *nle_blink;
+};
+
+typedef struct list_entry list_entry;
+
+#define INIT_LIST_HEAD(l)      \
+       l->nle_flink = l->nle_blink = l
+
+#define REMOVE_LIST_ENTRY(e)                   \
+       do {                                    \
+               list_entry              *b;     \
+               list_entry              *f;     \
+                                               \
+               f = e->nle_flink;               \
+               b = e->nle_blink;               \
+               b->nle_flink = f;               \
+               f->nle_blink = b;               \
+       } while (0)
+
+#define REMOVE_LIST_HEAD(l)                    \
+       do {                                    \
+               list_entry              *f;     \
+               list_entry              *e;     \
+                                               \
+               e = l->nle_flink;               \
+               f = e->nle_flink;               \
+               l->nle_flink = f;               \
+               f->nle_blink = l;               \
+       } while (0)
+
+#define REMOVE_LIST_TAIL(l)                    \
+       do {                                    \
+               list_entry              *b;     \
+               list_entry              *e;     \
+                                               \
+               e = l->nle_blink;               \
+               b = e->nle_blink;               \
+               l->nle_blink = b;               \
+               b->nle_flink = l;               \
+       } while (0)
+
+#define INSERT_LIST_TAIL(l, e)                 \
+       do {                                    \
+               list_entry              *b;     \
+                                               \
+               b = l->nle_blink;               \
+               e->nle_flink = l;               \
+               e->nle_blink = b;               \
+               b->nle_flink = e;               \
+               l->nle_blink = e;               \
+       } while (0)
+
+#define INSERT_LIST_HEAD(l, e)                 \
+       do {                                    \
+               list_entry              *f;     \
+                                               \
+               f = l->nle_flink;               \
+               e->nle_flink = f;               \
+               e->nle_blink = l;               \
+               f->nle_blink = e;               \
+               l->nle_flink = e;               \
+       } while (0)
+
+struct nt_dispatch_header {
+       uint8_t                 dh_type;
+       uint8_t                 dh_abs;
+       uint8_t                 dh_size;
+       uint8_t                 dh_inserted;
+       uint32_t                dh_sigstate;
+       list_entry              dh_waitlisthead;
+};
+
+typedef struct nt_dispatch_header nt_dispatch_header;
+
+#define OTYPE_EVENT            0
+#define OTYPE_MUTEX            1
+#define OTYPE_THREAD           2
+#define OTYPE_TIMER            3
+
+/* Windows dispatcher levels. */
+
+#define PASSIVE_LEVEL          0
+#define LOW_LEVEL              0
+#define APC_LEVEL              1
+#define DISPATCH_LEVEL         2
+#define DEVICE_LEVEL           (DISPATCH_LEVEL + 1)
+#define PROFILE_LEVEL          27
+#define CLOCK1_LEVEL           28
+#define CLOCK2_LEVEL           28
+#define IPI_LEVEL              29
+#define POWER_LEVEL            30
+#define HIGH_LEVEL             31
+
+#define SYNC_LEVEL_UP          DISPATCH_LEVEL
+#define SYNC_LEVEL_MP          (IPI_LEVEL - 1)
+
+#define AT_PASSIVE_LEVEL(td)           \
+       ((td)->td_proc->p_flag & P_KTHREAD == FALSE)
+
+#define AT_DISPATCH_LEVEL(td)          \
+       (lwkt_getpri(td) == TDPRI_INT_HIGH)
+
+struct nt_objref {
+       nt_dispatch_header      no_dh;
+       void                    *no_obj;
+       TAILQ_ENTRY(nt_objref)  link;
+};
+
+TAILQ_HEAD(nt_objref_head, nt_objref);
+
+typedef struct nt_objref nt_objref;
+
+#define EVENT_TYPE_NOTIFY      0
+#define EVENT_TYPE_SYNC                1
+
+/*
+ * We need to use the timeout()/untimeout() API for ktimers
+ * since timers can be initialized, but not destroyed (so
+ * malloc()ing our own callout structures would mean a leak,
+ * since there'd be no way to free() them). This means we
+ * need to use struct callout_handle, which is really just a
+ * pointer. To make it easier to deal with, we use a union
+ * to overlay the callout_handle over the k_timerlistentry.
+ * The latter is a list_entry, which is two pointers, so
+ * there's enough space available to hide a callout_handle
+ * there.
+ */
+
+struct ktimer {
+       nt_dispatch_header      k_header;
+       uint64_t                k_duetime;
+       union {
+               list_entry              k_timerlistentry;
+               struct callout_handle   k_handle;
+       } u;
+       void                    *k_dpc;
+       uint32_t                k_period;
+};
+
+#define k_timerlistentry       u.k_timerlistentry
+#define k_handle               u.k_handle
+
+typedef struct ktimer ktimer;
+
+struct nt_kevent {
+       nt_dispatch_header      k_header;
+};
+
+typedef struct nt_kevent nt_kevent;
+
+/* Kernel defered procedure call (i.e. timer callback) */
+
+struct kdpc;
+typedef void (*kdpc_func)(struct kdpc *, void *, void *, void *);
+
+struct kdpc {
+       uint16_t                k_type;
+       uint8_t                 k_num;
+       uint8_t                 k_importance;
+       list_entry              k_dpclistentry;
+       kdpc_func               k_deferedfunc;
+       void                    *k_deferredctx;
+       void                    *k_sysarg1;
+       void                    *k_sysarg2;
+       register_t              k_lock;
+};
+
+typedef struct kdpc kdpc;
+
+/*
+ * Note: the acquisition count is BSD-specific. The Microsoft
+ * documentation says that mutexes can be acquired recursively
+ * by a given thread, but that you must release the mutex as
+ * many times as you acquired it before it will be set to the
+ * signalled state (i.e. before any other threads waiting on
+ * the object will be woken up). However the Windows KMUTANT
+ * structure has no field for keeping track of the number of
+ * acquisitions, so we need to add one ourselves. As long as
+ * driver code treats the mutex as opaque, we should be ok.
+ */
+struct kmutant {
+       nt_dispatch_header      km_header;
+       union {
+               list_entry              km_listentry;
+               uint32_t                km_acquirecnt;
+       } u;
+       void                    *km_ownerthread;
+       uint8_t                 km_abandoned;
+       uint8_t                 km_apcdisable;
+};
+
+#define km_listentry           u.km_listentry
+#define km_acquirecnt          u.km_acquirecnt
+
+typedef struct kmutant kmutant;
+
+#define LOOKASIDE_DEPTH 256
+
+struct general_lookaside {
+       slist_header            gl_listhead;
+       uint16_t                gl_depth;
+       uint16_t                gl_maxdepth;
+       uint32_t                gl_totallocs;
+       union {
+               uint32_t                gl_allocmisses;
+               uint32_t                gl_allochits;
+       } u_a;
+       uint32_t                gl_totalfrees;
+       union {
+               uint32_t                gl_freemisses;
+               uint32_t                gl_freehits;
+       } u_m;
+       uint32_t                gl_type;
+       uint32_t                gl_tag;
+       uint32_t                gl_size;
+       void                    *gl_allocfunc;
+       void                    *gl_freefunc;
+       list_entry              gl_listent;
+       uint32_t                gl_lasttotallocs;
+       union {
+               uint32_t                gl_lastallocmisses;
+               uint32_t                gl_lastallochits;
+       } u_l;
+       uint32_t                gl_rsvd[2];
+};
+
+typedef struct general_lookaside general_lookaside;
+
+struct npaged_lookaside_list {
+       general_lookaside       nll_l;
+       kspin_lock              nll_obsoletelock;
+};
+
+typedef struct npaged_lookaside_list npaged_lookaside_list;
+typedef struct npaged_lookaside_list paged_lookaside_list;
+
+typedef void * (*lookaside_alloc_func)(uint32_t, size_t, uint32_t);
+typedef void (*lookaside_free_func)(void *);
+
+struct irp;
+
+struct kdevice_qentry {
+       list_entry              kqe_devlistent;
+       uint32_t                kqe_sortkey;
+       uint8_t                 kqe_inserted;
+};
+
+typedef struct kdevice_qentry kdevice_qentry;
+
+struct kdevice_queue {
+       uint16_t                kq_type;
+       uint16_t                kq_size;
+       list_entry              kq_devlisthead;
+       kspin_lock              kq_lock;
+       uint8_t                 kq_busy;
+};
+
+typedef struct kdevice_queue kdevice_queue;
+
+struct wait_ctx_block {
+       kdevice_qentry          wcb_waitqueue;
+       void                    *wcb_devfunc;
+       void                    *wcb_devctx;
+       uint32_t                wcb_mapregcnt;
+       void                    *wcb_devobj;
+       void                    *wcb_curirp;
+       void                    *wcb_bufchaindpc;
+};
+
+typedef struct wait_ctx_block wait_ctx_block;
+
+struct wait_block {
+       list_entry              wb_waitlist;
+       void                    *wb_kthread;
+       nt_dispatch_header      *wb_object;
+       struct wait_block       *wb_next;
+       uint16_t                wb_waitkey;
+       uint16_t                wb_waittype;
+};
+
+typedef struct wait_block wait_block;
+
+#define THREAD_WAIT_OBJECTS    3
+#define MAX_WAIT_OBJECTS       64
+
+#define WAITTYPE_ALL           0
+#define WAITTYPE_ANY           1
+
+struct thread_context {
+       void                    *tc_thrctx;
+       void                    *tc_thrfunc;
+};
+
+typedef struct thread_context thread_context;
+
+struct device_object {
+       uint16_t                do_type;
+       uint16_t                do_size;
+       uint32_t                do_refcnt;
+       struct device_object    *do_drvobj;
+       struct device_object    *do_nextdev;
+       struct device_object    *do_attacheddev;
+       struct irp              *do_currirp;
+       void                    *do_iotimer;
+       uint32_t                do_flags;
+       uint32_t                do_characteristics;
+       void                    *do_vpb;
+       void                    *do_devext;
+       uint8_t                 do_stacksize;
+       union {
+               list_entry              do_listent;
+               wait_ctx_block          do_wcb;
+       } queue;
+       uint32_t                do_alignreq;
+       kdevice_queue           do_devqueue;
+       struct kdpc             do_dpc;
+       uint32_t                do_activethreads;
+       void                    *do_securitydesc;
+       struct nt_kevent        do_devlock;
+       uint16_t                do_sectorsz;
+       uint16_t                do_spare1;
+       void                    *do_devobj_ext;
+       void                    *do_rsvd;
+};
+
+typedef struct device_object device_object;
+
+struct irp {
+       uint32_t                i_dummy;
+};
+
+typedef struct irp irp;
+
+typedef uint32_t (*driver_dispatch)(device_object *, irp *);
+
+#define DEVPROP_DEVICE_DESCRIPTION     0x00000000
+#define DEVPROP_HARDWARE_ID            0x00000001
+#define DEVPROP_COMPATIBLE_IDS         0x00000002
+#define DEVPROP_BOOTCONF               0x00000003
+#define DEVPROP_BOOTCONF_TRANSLATED    0x00000004
+#define DEVPROP_CLASS_NAME             0x00000005
+#define DEVPROP_CLASS_GUID             0x00000006
+#define DEVPROP_DRIVER_KEYNAME         0x00000007
+#define DEVPROP_MANUFACTURER           0x00000008
+#define DEVPROP_FRIENDLYNAME           0x00000009
+#define DEVPROP_LOCATION_INFO          0x0000000A
+#define DEVPROP_PHYSDEV_NAME           0x0000000B
+#define DEVPROP_BUSTYPE_GUID           0x0000000C
+#define DEVPROP_LEGACY_BUSTYPE         0x0000000D
+#define DEVPROP_BUS_NUMBER             0x0000000E
+#define DEVPROP_ENUMERATOR_NAME                0x0000000F
+#define DEVPROP_ADDRESS                        0x00000010
+#define DEVPROP_UINUMBER               0x00000011
+#define DEVPROP_INSTALL_STATE          0x00000012
+#define DEVPROP_REMOVAL_POLICY         0x00000013
+
+#define STATUS_SUCCESS                 0x00000000
+#define STATUS_USER_APC                        0x000000C0
+#define STATUS_KERNEL_APC              0x00000100
+#define STATUS_ALERTED                 0x00000101
+#define STATUS_TIMEOUT                 0x00000102
+#define STATUS_INVALID_PARAMETER       0xC000000D
+#define STATUS_INVALID_DEVICE_REQUEST  0xC0000010
+#define STATUS_BUFFER_TOO_SMALL                0xC0000023
+#define STATUS_MUTANT_NOT_OWNED                0xC0000046
+#define STATUS_INVALID_PARAMETER_2     0xC00000F0
+
+#define STATUS_WAIT_0                  0x00000000
+
+/*
+ * FreeBSD's kernel stack is 2 pages in size by default. The
+ * Windows stack is larger, so we need to give our threads more
+ * stack pages. 4 should be enough, we use 8 just to extra safe.
+ */
+#define NDIS_KSTACK_PAGES      8
+
+extern image_patch_table ntoskrnl_functbl[];
+
+__BEGIN_DECLS
+extern int ntoskrnl_libinit(void);
+extern int ntoskrnl_libfini(void);
+__stdcall extern void ntoskrnl_init_dpc(kdpc *, void *, void *);
+__stdcall extern uint8_t ntoskrnl_queue_dpc(kdpc *, void *, void *);
+__stdcall extern uint8_t ntoskrnl_dequeue_dpc(kdpc *);
+__stdcall extern void ntoskrnl_init_timer(ktimer *);
+__stdcall extern void ntoskrnl_init_timer_ex(ktimer *, uint32_t);
+__stdcall extern uint8_t ntoskrnl_set_timer(ktimer *, int64_t, kdpc *);  
+__stdcall extern uint8_t ntoskrnl_set_timer_ex(ktimer *, int64_t,
+       uint32_t, kdpc *);
+__stdcall extern uint8_t ntoskrnl_cancel_timer(ktimer *);
+__stdcall extern uint8_t ntoskrnl_read_timer(ktimer *);
+__stdcall extern uint32_t ntoskrnl_waitforobj(nt_dispatch_header *, uint32_t,
+       uint32_t, uint8_t, int64_t *);
+__stdcall extern void ntoskrnl_init_event(nt_kevent *, uint32_t, uint8_t);
+__stdcall extern void ntoskrnl_clear_event(nt_kevent *);
+__stdcall extern uint32_t ntoskrnl_read_event(nt_kevent *);
+__stdcall extern uint32_t ntoskrnl_set_event(nt_kevent *, uint32_t, uint8_t);
+__stdcall extern uint32_t ntoskrnl_reset_event(nt_kevent *);
+__stdcall __regcall void ntoskrnl_lock_dpc(REGARGS1(kspin_lock *lock));
+__stdcall __regcall void ntoskrnl_unlock_dpc(REGARGS1(kspin_lock *lock));
+
+/*
+ * On the Windows x86 arch, KeAcquireSpinLock() and KeReleaseSpinLock()
+ * routines live in the HAL. We try to imitate this behavior.
+ */
+#ifdef __i386__
+#define ntoskrnl_acquire_spinlock(a, b)                \
+       *(b) = FASTCALL(hal_lock, a, 0)
+#define ntoskrnl_release_spinlock(a, b)                \
+       FASTCALL(hal_unlock, a, b)
+#endif /* __i386__ */
+__END_DECLS
+
+#endif /* _NTOSKRNL_VAR_H_ */
diff --git a/sys/emulation/ndis/pe_var.h b/sys/emulation/ndis/pe_var.h
new file mode 100644 (file)
index 0000000..42fbb5e
--- /dev/null
@@ -0,0 +1,430 @@
+/*
+ * 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: src/sys/compat/ndis/pe_var.h,v 1.7 2004/04/14 07:48:02 wpaul Exp $
+ * $DragonFly: src/sys/emulation/ndis/pe_var.h,v 1.1 2004/07/29 20:51:34 dillon Exp $
+ */
+
+#ifndef _PE_VAR_H_
+#define _PE_VAR_H_
+
+/*
+ *  Image Format
+ */
+
+#define IMAGE_DOS_SIGNATURE                 0x5A4D      /* MZ */
+#define IMAGE_OS2_SIGNATURE                 0x454E      /* NE */
+#define IMAGE_OS2_SIGNATURE_LE              0x454C      /* LE */
+#define IMAGE_VXD_SIGNATURE                 0x454C      /* LE */
+#define IMAGE_NT_SIGNATURE                  0x00004550  /* PE00 */
+
+/*
+ * All PE files have one of these, just so if you attempt to
+ * run them, they'll print out a message telling you they can
+ * only be run in Windows.
+ */
+
+struct image_dos_header {
+       uint16_t        idh_magic;      /* Magic number */
+       uint16_t        idh_cblp;       /* Bytes on last page of file */
+       uint16_t        idh_cp;         /* Pages in file */
+       uint16_t        idh_crlc;       /* Relocations */
+       uint16_t        idh_cparhdr;    /* Size of header in paragraphs */
+       uint16_t        idh_minalloc;   /* Minimum extra paragraphs needed */
+       uint16_t        idh_maxalloc;   /* Maximum extra paragraphs needed */
+       uint16_t        idh_ss;         /* Initial (relative) SS value */
+       uint16_t        idh_sp;         /* Initial SP value */
+       uint16_t        idh_csum;       /* Checksum */
+       uint16_t        idh_ip;         /* Initial IP value */
+       uint16_t        idh_cs;         /* Initial (relative) CS value */
+       uint16_t        idh_lfarlc;     /* File address of relocation table */
+       uint16_t        idh_ovno;       /* Overlay number */
+       uint16_t        idh_rsvd1[4];   /* Reserved words */
+       uint16_t        idh_oemid;      /* OEM identifier (for idh_oeminfo) */
+       uint16_t        idh_oeminfo;    /* OEM information; oemid specific */
+       uint16_t        idh_rsvd2[10];  /* Reserved words */
+       uint32_t        idh_lfanew;     /* File address of new exe header */
+};
+
+typedef struct image_dos_header image_dos_header;
+
+/*
+ * File header format.
+ */
+
+struct image_file_header {
+       uint16_t        ifh_machine;            /* Machine type */
+       uint16_t        ifh_numsections;        /* # of sections */
+       uint32_t        ifh_timestamp;          /* Date/time stamp */
+       uint32_t        ifh_symtblptr;          /* Offset to symbol table */
+       uint32_t        ifh_numsyms;            /* # of symbols */
+       uint16_t        ifh_optionalhdrlen;     /* Size of optional header */
+       uint16_t        ifh_characteristics;    /* Characteristics */
+};
+
+typedef struct image_file_header image_file_header;
+
+/* Machine types */
+
+#define IMAGE_FILE_MACHINE_UNKNOWN      0
+#define IMAGE_FILE_MACHINE_I860         0x014d
+#define IMAGE_FILE_MACHINE_I386         0x014c
+#define IMAGE_FILE_MACHINE_R3000        0x0162
+#define IMAGE_FILE_MACHINE_R4000        0x0166
+#define IMAGE_FILE_MACHINE_R10000       0x0168
+#define IMAGE_FILE_MACHINE_WCEMIPSV2    0x0169
+#define IMAGE_FILE_MACHINE_ALPHA        0x0184
+#define IMAGE_FILE_MACHINE_SH3          0x01a2
+#define IMAGE_FILE_MACHINE_SH3DSP       0x01a3
+#define IMAGE_FILE_MACHINE_SH3E         0x01a4
+#define IMAGE_FILE_MACHINE_SH4          0x01a6
+#define IMAGE_FILE_MACHINE_SH5          0x01a8
+#define IMAGE_FILE_MACHINE_ARM          0x01c0
+#define IMAGE_FILE_MACHINE_THUMB        0x01c2
+#define IMAGE_FILE_MACHINE_AM33         0x01d3
+#define IMAGE_FILE_MACHINE_POWERPC      0x01f0
+#define IMAGE_FILE_MACHINE_POWERPCFP    0x01f1
+#define IMAGE_FILE_MACHINE_IA64         0x0200
+#define IMAGE_FILE_MACHINE_MIPS16       0x0266
+#define IMAGE_FILE_MACHINE_ALPHA64      0x0284
+#define IMAGE_FILE_MACHINE_MIPSFPU      0x0366
+#define IMAGE_FILE_MACHINE_MIPSFPU16    0x0466
+#define IMAGE_FILE_MACHINE_AXP64        IMAGE_FILE_MACHINE_ALPHA64
+#define IMAGE_FILE_MACHINE_TRICORE      0x0520
+#define IMAGE_FILE_MACHINE_CEF          0x0cef
+#define IMAGE_FILE_MACHINE_EBC          0x0ebc
+#define IMAGE_FILE_MACHINE_AMD64        0x8664
+#define IMAGE_FILE_MACHINE_M32R         0x9041
+#define IMAGE_FILE_MACHINE_CEE          0xc0ee
+
+/* Characteristics */
+
+#define IMAGE_FILE_RELOCS_STRIPPED      0x0001 /* No relocation info */
+#define IMAGE_FILE_EXECUTABLE_IMAGE     0x0002
+#define IMAGE_FILE_LINE_NUMS_STRIPPED   0x0004
+#define IMAGE_FILE_LOCAL_SYMS_STRIPPED  0x0008
+#define IMAGE_FILE_AGGRESIVE_WS_TRIM    0x0010
+#define IMAGE_FILE_LARGE_ADDRESS_AWARE  0x0020
+#define IMAGE_FILE_16BIT_MACHINE        0x0040
+#define IMAGE_FILE_BYTES_REVERSED_LO    0x0080
+#define IMAGE_FILE_32BIT_MACHINE        0x0100
+#define IMAGE_FILE_DEBUG_STRIPPED       0x0200
+#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP      0x0400
+#define IMAGE_FILE_NET_RUN_FROM_SWAP    0x0800
+#define IMAGE_FILE_SYSTEM               0x1000
+#define IMAGE_FILE_DLL                  0x2000
+#define IMAGE_FILE_UP_SYSTEM_ONLY       0x4000
+#define IMAGE_FILE_BYTES_REVERSED_HI    0x8000
+
+#define IMAGE_SIZEOF_FILE_HEADER             20
+
+/*
+ * Directory format.
+ */
+
+struct image_data_directory {
+       uint32_t                idd_vaddr;      /* virtual address */
+       uint32_t                idd_size;       /* size */
+};
+
+typedef struct image_data_directory image_data_directory;
+
+#define IMAGE_DIRECTORY_ENTRIES_MAX    16
+
+/*
+ * Optional header format.
+ */
+
+struct image_optional_header {
+
+       /* Standard fields */
+
+       uint16_t        ioh_magic;
+       uint8_t         ioh_linkerver_major;
+       uint8_t         ioh_linkerver_minor;
+       uint32_t        ioh_codesize;
+       uint32_t        ioh_datasize;
+       uint32_t        ioh_bsssize;
+       uint32_t        ioh_entryaddr;
+       uint32_t        ioh_codebaseaddr;
+       uint32_t        ioh_databaseaddr;
+
+       /* NT-specific fields */
+
+       uint32_t        ioh_imagebase;
+       uint32_t        ioh_sectalign;
+       uint32_t        ioh_filealign;
+       uint16_t        ioh_osver_major;
+       uint16_t        ioh_osver_minor;
+       uint16_t        ioh_imagever_major;
+       uint16_t        ioh_imagever_minor;
+       uint16_t        ioh_subsys_major;
+       uint16_t        ioh_subsys_minor;
+       uint32_t        ioh_win32ver;
+       uint32_t        ioh_imagesize;
+       uint32_t        ioh_headersize;
+       uint32_t        ioh_csum;
+       uint16_t        ioh_subsys;
+       uint16_t        ioh_dll_characteristics;
+       uint32_t        ioh_stackreservesize;
+       uint32_t        ioh_stackcommitsize;
+       uint32_t        ioh_heapreservesize;
+       uint32_t        ioh_heapcommitsize;
+       uint16_t        ioh_loaderflags;
+       uint32_t        ioh_rva_size_cnt;
+       image_data_directory    ioh_datadir[IMAGE_DIRECTORY_ENTRIES_MAX];
+};
+
+typedef struct image_optional_header image_optional_header;
+
+struct image_nt_header {
+       uint32_t                inh_signature;
+       image_file_header       inh_filehdr;
+       image_optional_header   inh_optionalhdr;
+};
+
+typedef struct image_nt_header image_nt_header;
+
+/* Directory Entries */
+
+#define IMAGE_DIRECTORY_ENTRY_EXPORT         0   /* Export Directory */
+#define IMAGE_DIRECTORY_ENTRY_IMPORT         1   /* Import Directory */
+#define IMAGE_DIRECTORY_ENTRY_RESOURCE       2   /* Resource Directory */
+#define IMAGE_DIRECTORY_ENTRY_EXCEPTION      3   /* Exception Directory */
+#define IMAGE_DIRECTORY_ENTRY_SECURITY       4   /* Security Directory */
+#define IMAGE_DIRECTORY_ENTRY_BASERELOC      5   /* Base Relocation Table */
+#define IMAGE_DIRECTORY_ENTRY_DEBUG          6   /* Debug Directory */
+#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT      7   /* Description String */
+#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR      8   /* Machine Value (MIPS GP) */
+#define IMAGE_DIRECTORY_ENTRY_TLS            9   /* TLS Directory */
+#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG   10   /* Load Configuration Directory */
+#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT  11   /* Bound Import Directory in headers */
+#define IMAGE_DIRECTORY_ENTRY_IAT           12   /* Import Address Table */
+#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT      13
+#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR    14
+
+/* Resource types */
+
+#define RT_CURSOR      1
+#define RT_BITMAP      2
+#define RT_ICON                3
+#define RT_MENU                4
+#define RT_DIALOG      5
+#define RT_STRING      6
+#define RT_FONTDIR     7
+#define RT_FONT                8
+#define RT_ACCELERATOR 9
+#define RT_RCDATA      10
+#define RT_MESSAGETABLE        11
+#define RT_GROUP_CURSOR        12
+#define RT_GROUP_ICON  14
+#define RT_VERSION     16
+#define RT_DLGINCLUDE  17
+#define RT_PLUGPLAY    19
+#define RT_VXD         20
+#define RT_ANICURSOR   21
+#define RT_ANIICON     22
+#define RT_HTML                23
+
+/*
+ * Section header format.
+ */
+
+#define IMAGE_SHORT_NAME_LEN                   8
+
+struct image_section_header {
+       uint8_t         ish_name[IMAGE_SHORT_NAME_LEN];
+       union {
+               uint32_t        ish_paddr;
+               uint32_t        ish_vsize;
+       } ish_misc;
+       uint32_t        ish_vaddr;
+       uint32_t        ish_rawdatasize;
+       uint32_t        ish_rawdataaddr;
+       uint32_t        ish_relocaddr;
+       uint32_t        ish_linenumaddr;
+       uint16_t        ish_numrelocs;
+       uint16_t        ish_numlinenums;
+       uint32_t        ish_characteristics;
+};
+
+typedef struct image_section_header image_section_header;
+
+#define IMAGE_SIZEOF_SECTION_HEADER          40
+
+/*
+ * Import format
+ */
+
+struct image_import_by_name {
+       uint16_t        iibn_hint;
+       u_int8_t        iibn_name[1];
+};
+
+#define IMAGE_ORDINAL_FLAG 0x80000000
+#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
+
+struct image_import_descriptor {
+       uint32_t        iid_import_name_table_addr;
+       uint32_t        iid_timestamp;
+       uint32_t        iid_forwardchain;
+       uint32_t        iid_nameaddr;
+       uint32_t        iid_import_address_table_addr;
+};
+
+typedef struct image_import_descriptor image_import_descriptor;
+
+struct image_base_reloc {
+       uint32_t        ibr_vaddr;
+       uint32_t        ibr_blocksize;
+       uint16_t        ibr_rel[1];
+};
+
+typedef struct image_base_reloc image_base_reloc;
+
+#define IMR_RELTYPE(x)         ((x >> 12) & 0xF)
+#define IMR_RELOFFSET(x)       (x & 0xFFF)
+
+/* generic relocation types */
+#define IMAGE_REL_BASED_ABSOLUTE                0
+#define IMAGE_REL_BASED_HIGH                    1
+#define IMAGE_REL_BASED_LOW                     2
+#define IMAGE_REL_BASED_HIGHLOW                 3
+#define IMAGE_REL_BASED_HIGHADJ                 4
+#define IMAGE_REL_BASED_MIPS_JMPADDR            5
+#define IMAGE_REL_BASED_SECTION                 6
+#define IMAGE_REL_BASED_REL                     7
+#define IMAGE_REL_BASED_MIPS_JMPADDR16          9
+#define IMAGE_REL_BASED_IA64_IMM64              9 /* yes, 9 too */
+#define IMAGE_REL_BASED_DIR64                   10
+#define IMAGE_REL_BASED_HIGH3ADJ                11
+
+struct image_resource_directory_entry {
+       uint32_t                irde_name;
+       uint32_t                irde_dataoff;
+};
+
+typedef struct image_resource_directory_entry image_resource_directory_entry;
+
+#define RESOURCE_NAME_STR      0x80000000
+#define RESOURCE_DIR_FLAG      0x80000000
+
+struct image_resource_directory {
+       uint32_t                ird_characteristics;
+       uint32_t                ird_timestamp;
+       uint16_t                ird_majorver;
+       uint16_t                ird_minorver;
+       uint16_t                ird_named_entries;
+       uint16_t                ird_id_entries;
+#ifdef notdef
+       image_resource_directory_entry  ird_entries[1];
+#endif
+};
+
+typedef struct image_resource_directory image_resource_directory;
+
+struct image_resource_directory_string {
+       uint16_t                irds_len;
+       char                    irds_name[1];
+};
+
+typedef struct image_resource_directory_string image_resource_directory_string;
+
+struct image_resource_directory_string_u {
+       uint16_t                irds_len;
+       char                    irds_name[1];
+};
+
+typedef struct image_resource_directory_string_u
+       image_resource_directory_string_u;
+
+struct image_resource_data_entry {
+       uint32_t                irde_offset;
+       uint32_t                irde_size;
+       uint32_t                irde_codepage;
+       uint32_t                irde_rsvd;
+};
+
+typedef struct image_resource_data_entry image_resource_data_entry;
+
+struct message_resource_data {
+       uint32_t                mrd_numblocks;
+#ifdef notdef
+       message_resource_block  mrd_blocks[1];
+#endif
+};
+
+typedef struct message_resource_data message_resource_data;
+
+struct message_resource_block {
+       uint32_t                mrb_lowid;
+       uint32_t                mrb_highid;
+       uint32_t                mrb_entryoff;
+};
+
+typedef struct message_resource_block message_resource_block;
+
+struct message_resource_entry {
+       uint16_t                mre_len;
+       uint16_t                mre_flags;
+       char                    mre_text[0];
+};
+
+typedef struct message_resource_entry message_resource_entry;
+
+#define MESSAGE_RESOURCE_UNICODE       0x0001
+
+struct image_patch_table {
+       char            *ipt_name;
+       void            (*ipt_func)(void);
+};
+
+typedef struct image_patch_table image_patch_table;
+
+__BEGIN_DECLS
+extern int pe_get_dos_header(vm_offset_t, image_dos_header *);
+extern int pe_is_nt_image(vm_offset_t);
+extern int pe_get_optional_header(vm_offset_t, image_optional_header *);
+extern int pe_get_file_header(vm_offset_t, image_file_header *);
+extern int pe_get_section_header(vm_offset_t, image_section_header *);
+extern int pe_numsections(vm_offset_t);
+extern vm_offset_t pe_imagebase(vm_offset_t);
+extern vm_offset_t pe_directory_offset(vm_offset_t, uint32_t);
+extern vm_offset_t pe_translate_addr (vm_offset_t, uint32_t);
+extern int pe_get_section(vm_offset_t, image_section_header *, const char *);
+extern int pe_relocate(vm_offset_t);
+extern int pe_get_import_descriptor(vm_offset_t, image_import_descriptor *, char *);
+extern int pe_patch_imports(vm_offset_t, char *, image_patch_table *);
+extern int pe_get_messagetable(vm_offset_t, message_resource_data **);
+extern int pe_get_message(vm_offset_t, uint32_t, char **, int *, uint16_t *);
+__END_DECLS
+
+#endif /* _PE_VAR_H_ */
diff --git a/sys/emulation/ndis/regcall.h b/sys/emulation/ndis/regcall.h
new file mode 100644 (file)
index 0000000..d96e1c6
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * 
+ * Copyright (c) 2004 The DragonFly Project.  All rights reserved.
+ * 
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon@backplane.com>
+ * 
+ * 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. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS 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.
+ * 
+ * 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: src/sys/compat/ndis/pe_var.h,v 1.7 2004/04/14 07:48:02 wpaul Exp $
+ * $DragonFly: src/sys/emulation/ndis/regcall.h,v 1.1 2004/07/29 20:51:34 dillon Exp $
+ */
+
+#ifndef _REGCALL_H_
+#define _REGCALL_H_
+
+/*
+ * Note: Windows uses the _stdcall calling convention. This means
+ * that the callback functions provided in the function table must
+ * be declared using __attribute__((__stdcall__)), otherwise the
+ * Windows code will likely screw up the %esp register and cause
+ * us to jump to an invalid address when it returns.   With the
+ * stdcall calling convention the target procedure is responsible for
+ * popping the call arguments.
+ *
+ * Note: Windows often passes arguments in registers.  In windows
+ * the order is: %ecx, %edx.  The regparm(3) attribute in GNU C will
+ * pass arguments in the order: %eax, %edx, %ecx, with any remaining
+ * arguments passed on the stack.
+ */
+
+#ifdef __amd64__
+#define        __stdcall
+#define __regcall
+#define REGARGS1(decl1)                decl1
+#define REGARGS2(decl1, decl2) decl1, decl2
+#define REGCALL1(arg1)         arg1
+#define REGCALL2(arg1, arg2)   arg1, arg2
+#else
+#define        __stdcall __attribute__((__stdcall__))
+#define __regcall __attribute__((__regparm__(3)))
+#define REGARGS1(decl1)                int dummy1, int dummy2, decl1
+#define REGARGS2(decl1, decl2) int dummy1, decl2, decl1
+#define REGCALL1(arg1)         0, 0, arg1
+#define REGCALL2(arg1, arg2)   0, arg2, arg1
+#endif
+
+
+/*
+ * This mess allows us to call a _fastcall style routine with our
+ * version of gcc, which lacks __attribute__((__fastcall__)). Only
+ * has meaning on x86; everywhere else, it's a no-op.
+ */
+
+#ifdef __i386__
+typedef __stdcall __regcall int (*fcall1)(REGARGS1(uint32_t));
+typedef __stdcall __regcall int (*fcall2)(REGARGS2(uint32_t, uint32_t));
+typedef __stdcall __regcall int (*fcall3)(REGARGS2(uint32_t, uint32_t), uint32_t);
+static __inline uint32_t 
+fastcall1(fcall1 f, uint32_t a)
+{
+       return(f(REGCALL1(a)));
+}
+
+static __inline uint32_t 
+fastcall2(fcall2 f, uint32_t a, uint32_t b)
+{
+       return(f(REGCALL2(a, b)));
+}
+
+static __inline uint32_t 
+fastcall3(fcall3 f, uint32_t a, uint32_t b, uint32_t c)
+{
+       return(f(REGCALL2(a, b), c));
+}
+
+#define FASTCALL1(f, a)                \
+       fastcall1((fcall1)(f), (uint32_t)(a))
+#define FASTCALL2(f, a, b)     \
+       fastcall2((fcall2)(f), (uint32_t)(a), (uint32_t)(b))
+#define FASTCALL3(f, a, b, c)  \
+       fastcall3((fcall3)(f), (uint32_t)(a), (uint32_t)(b), (uint32_t)(c))
+#else
+#define FASTCALL1(f, a) (f)((a))
+#define FASTCALL2(f, a, b) (f)((a), (b))
+#define FASTCALL3(f, a, b, c) (f)((a), (b), (c))
+#endif /* __i386__ */
+
+#endif
diff --git a/sys/emulation/ndis/resource_var.h b/sys/emulation/ndis/resource_var.h
new file mode 100644 (file)
index 0000000..b4f1ff8
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * $FreeBSD: src/sys/compat/ndis/resource_var.h,v 1.2 2004/03/29 02:15:29 wpaul Exp $
+ * $DragonFly: src/sys/emulation/ndis/resource_var.h,v 1.1 2004/07/29 20:51:34 dillon Exp $
+ */
+
+typedef int cm_resource_type;
+
+struct physaddr {
+       uint64_t                np_quad;
+};
+
+typedef struct physaddr physaddr;
+
+enum interface_type {
+        InterfaceTypeUndefined = -1,
+        Internal,
+        Isa,
+        Eisa,
+        MicroChannel,
+        TurboChannel,
+        PCIBus,
+        VMEBus,
+        NuBus,
+        PCMCIABus,
+        CBus,
+        MPIBus,
+        MPSABus,
+        ProcessorInternal,
+        InternalPowerBus,
+        PNPISABus,
+        PNPBus,
+        MaximumInterfaceType
+};
+
+typedef enum interface_type interface_type;
+
+#define CmResourceTypeNull                0   /* ResType_All or ResType_None (0x0000) */
+#define CmResourceTypePort                1   /* ResType_IO (0x0002) */
+#define CmResourceTypeInterrupt           2   /* ResType_IRQ (0x0004) */
+#define CmResourceTypeMemory              3   /* ResType_Mem (0x0001) */
+#define CmResourceTypeDma                 4   /* ResType_DMA (0x0003) */
+#define CmResourceTypeDeviceSpecific      5   /* ResType_ClassSpecific (0xFFFF) */
+#define CmResourceTypeBusNumber           6   /* ResType_BusNumber (0x0006) */
+#define CmResourceTypeMaximum             7
+#define CmResourceTypeNonArbitrated     128   /* Not arbitrated if 0x80 bit set */
+#define CmResourceTypeConfigData        128   /* ResType_Reserved (0x8000) */
+#define CmResourceTypeDevicePrivate     129   /* ResType_DevicePrivate (0x8001) */
+#define CmResourceTypePcCardConfig      130   /* ResType_PcCardConfig (0x8002) */
+
+enum cm_share_disposition {
+    CmResourceShareUndetermined = 0,    /* Reserved */
+    CmResourceShareDeviceExclusive,
+    CmResourceShareDriverExclusive,
+    CmResourceShareShared
+};
+
+typedef enum cm_share_disposition cm_share_disposition;
+
+/* Define the bit masks for Flags when type is CmResourceTypeInterrupt */
+
+#define CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE 0
+#define CM_RESOURCE_INTERRUPT_LATCHED         1
+
+/* Define the bit masks for Flags when type is CmResourceTypeMemory */
+
+#define CM_RESOURCE_MEMORY_READ_WRITE       0x0000
+#define CM_RESOURCE_MEMORY_READ_ONLY        0x0001
+#define CM_RESOURCE_MEMORY_WRITE_ONLY       0x0002
+#define CM_RESOURCE_MEMORY_PREFETCHABLE     0x0004
+
+#define CM_RESOURCE_MEMORY_COMBINEDWRITE    0x0008
+#define CM_RESOURCE_MEMORY_24               0x0010
+#define CM_RESOURCE_MEMORY_CACHEABLE        0x0020
+
+/* Define the bit masks for Flags when type is CmResourceTypePort */
+
+#define CM_RESOURCE_PORT_MEMORY                             0x0000
+#define CM_RESOURCE_PORT_IO                                 0x0001
+#define CM_RESOURCE_PORT_10_BIT_DECODE                      0x0004
+#define CM_RESOURCE_PORT_12_BIT_DECODE                      0x0008
+#define CM_RESOURCE_PORT_16_BIT_DECODE                      0x0010
+#define CM_RESOURCE_PORT_POSITIVE_DECODE                    0x0020
+#define CM_RESOURCE_PORT_PASSIVE_DECODE                     0x0040
+#define CM_RESOURCE_PORT_WINDOW_DECODE                      0x0080
+
+/* Define the bit masks for Flags when type is CmResourceTypeDma */
+
+#define CM_RESOURCE_DMA_8                   0x0000
+#define CM_RESOURCE_DMA_16                  0x0001
+#define CM_RESOURCE_DMA_32                  0x0002
+#define CM_RESOURCE_DMA_8_AND_16            0x0004
+#define CM_RESOURCE_DMA_BUS_MASTER          0x0008
+#define CM_RESOURCE_DMA_TYPE_A              0x0010
+#define CM_RESOURCE_DMA_TYPE_B              0x0020
+#define CM_RESOURCE_DMA_TYPE_F              0x0040
+
+struct cm_partial_resource_desc {
+       uint8_t                 cprd_type;
+       uint8_t                 cprd_sharedisp;
+       uint16_t                cprd_flags;
+       union {
+               struct {
+                       physaddr                cprd_start;
+                       uint32_t                cprd_len;
+               } cprd_generic;
+               struct {
+                       physaddr                cprd_start;
+                       uint32_t                cprd_len;
+               } cprd_port;
+               struct {
+                       uint32_t                cprd_level;
+                       uint32_t                cprd_vector;
+                       uint32_t                cprd_affinity;
+               } cprd_intr;
+               struct {
+                       physaddr                cprd_start;
+                       uint32_t                cprd_len;
+               } cprd_mem;
+               struct {
+                       uint32_t                cprd_chan;
+                       uint32_t                cprd_port;
+                       uint32_t                cprd_rsvd;
+               } cprd_dmachan;
+               struct {
+                       uint32_t                cprd_data[3];
+               } cprd_devpriv;
+               struct {
+                       uint32_t                cprd_datasize;
+                       uint32_t                cprd_rsvd1;
+                       uint32_t                cprd_rsvd2;
+               } cprd_devspec;
+       } u;
+};
+
+typedef struct cm_partial_resource_desc cm_partial_resource_desc;
+
+struct cm_partial_resource_list {
+       uint16_t                cprl_version;
+       uint16_t                cprl_revision;
+       uint32_t                cprl_count;
+       cm_partial_resource_desc        cprl_partial_descs[1];
+};
+
+typedef struct cm_partial_resource_list cm_partial_resource_list;
+
+struct cm_full_resource_list {
+       interface_type          cfrl_type;
+       uint32_t                cfrl_busnum;
+       cm_partial_resource_desc        cfrl_partiallist;
+};
+
+typedef struct cm_full_resource_list cm_full_resource_list;
+
+struct cm_resource_list {
+       uint32_t                crl_count;
+       cm_full_resource_list   crl_rlist;
+};
+
+typedef struct cm_resource_list cm_resource_list;
+
+typedef cm_partial_resource_list ndis_resource_list;
diff --git a/sys/emulation/ndis/subr_hal.c b/sys/emulation/ndis/subr_hal.c
new file mode 100644 (file)
index 0000000..4857702
--- /dev/null
@@ -0,0 +1,368 @@
+/*
+ * 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: src/sys/compat/ndis/subr_hal.c,v 1.12 2004/04/19 22:39:04 wpaul Exp $
+ * $DragonFly: src/sys/emulation/ndis/subr_hal.c,v 1.1 2004/07/29 20:51:34 dillon Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+
+#include <sys/callout.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+
+#include <sys/systm.h>
+#include <machine/clock.h>
+#include <machine/bus_memio.h>
+#include <machine/bus_pio.h>
+#include <machine/bus.h>
+
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/thread2.h>
+
+#include "regcall.h"
+#include "pe_var.h"
+#include "resource_var.h"
+#include "ntoskrnl_var.h"
+#include "ndis_var.h"
+#include "hal_var.h"
+
+#define FUNC void(*)(void)
+
+__stdcall static void hal_stall_exec_cpu(uint32_t);
+__stdcall static void hal_writeport_buf_ulong(uint32_t *,
+       uint32_t *, uint32_t);
+__stdcall static void hal_writeport_buf_ushort(uint16_t *,
+       uint16_t *, uint32_t);
+__stdcall static void hal_writeport_buf_uchar(uint8_t *,
+       uint8_t *, uint32_t);
+__stdcall static void hal_writeport_ulong(uint32_t *, uint32_t);
+__stdcall static void hal_writeport_ushort(uint16_t *, uint16_t);
+__stdcall static void hal_writeport_uchar(uint8_t *, uint8_t);
+__stdcall static uint32_t hal_readport_ulong(uint32_t *);
+__stdcall static uint16_t hal_readport_ushort(uint16_t *);
+__stdcall static uint8_t hal_readport_uchar(uint8_t *);
+__stdcall static void hal_readport_buf_ulong(uint32_t *,
+       uint32_t *, uint32_t);
+__stdcall static void hal_readport_buf_ushort(uint16_t *,
+       uint16_t *, uint32_t);
+__stdcall static void hal_readport_buf_uchar(uint8_t *,
+       uint8_t *, uint32_t);
+__stdcall static uint64_t hal_perfcount(uint64_t *);
+__stdcall static void dummy (void);
+
+extern struct mtx_pool *ndis_mtxpool;
+
+__stdcall static void
+hal_stall_exec_cpu(usecs)
+       uint32_t                usecs;
+{
+       DELAY(usecs);
+       return;
+}
+
+__stdcall static void
+hal_writeport_ulong(port, val)
+       uint32_t                *port;
+       uint32_t                val;
+{
+       bus_space_write_4(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port, val);
+       return;
+}
+
+__stdcall static void
+hal_writeport_ushort(port, val)
+       uint16_t                *port;
+       uint16_t                val;
+{
+       bus_space_write_2(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port, val);
+       return;
+}
+
+__stdcall static void
+hal_writeport_uchar(port, val)
+       uint8_t                 *port;
+       uint8_t                 val;
+{
+       bus_space_write_1(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port, val);
+       return;
+}
+
+__stdcall static void
+hal_writeport_buf_ulong(port, val, cnt)
+       uint32_t                *port;
+       uint32_t                *val;
+       uint32_t                cnt;
+{
+       bus_space_write_multi_4(NDIS_BUS_SPACE_IO, 0x0,
+           (bus_size_t)port, val, cnt);
+       return;
+}
+
+__stdcall static void
+hal_writeport_buf_ushort(port, val, cnt)
+       uint16_t                *port;
+       uint16_t                *val;
+       uint32_t                cnt;
+{
+       bus_space_write_multi_2(NDIS_BUS_SPACE_IO, 0x0,
+           (bus_size_t)port, val, cnt);
+       return;
+}
+
+__stdcall static void
+hal_writeport_buf_uchar(port, val, cnt)
+       uint8_t                 *port;
+       uint8_t                 *val;
+       uint32_t                cnt;
+{
+       bus_space_write_multi_1(NDIS_BUS_SPACE_IO, 0x0,
+           (bus_size_t)port, val, cnt);
+       return;
+}
+
+__stdcall static uint16_t
+hal_readport_ushort(port)
+       uint16_t                *port;
+{
+       return(bus_space_read_2(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port));
+}
+
+__stdcall static uint32_t
+hal_readport_ulong(port)
+       uint32_t                *port;
+{
+       return(bus_space_read_4(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port));
+}
+
+__stdcall static uint8_t
+hal_readport_uchar(port)
+       uint8_t                 *port;
+{
+       return(bus_space_read_1(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port));
+}
+
+__stdcall static void
+hal_readport_buf_ulong(port, val, cnt)
+       uint32_t                *port;
+       uint32_t                *val;
+       uint32_t                cnt;
+{
+       bus_space_read_multi_4(NDIS_BUS_SPACE_IO, 0x0,
+           (bus_size_t)port, val, cnt);
+       return;
+}
+
+__stdcall static void
+hal_readport_buf_ushort(port, val, cnt)
+       uint16_t                *port;
+       uint16_t                *val;
+       uint32_t                cnt;
+{
+       bus_space_read_multi_2(NDIS_BUS_SPACE_IO, 0x0,
+           (bus_size_t)port, val, cnt);
+       return;
+}
+
+__stdcall static void
+hal_readport_buf_uchar(port, val, cnt)
+       uint8_t                 *port;
+       uint8_t                 *val;
+       uint32_t                cnt;
+{
+       bus_space_read_multi_1(NDIS_BUS_SPACE_IO, 0x0,
+           (bus_size_t)port, val, cnt);
+       return;
+}
+
+/*
+ * The spinlock implementation in Windows differs from that of FreeBSD.
+ * The basic operation of spinlocks involves two steps: 1) spin in a
+ * tight loop while trying to acquire a lock, 2) after obtaining the
+ * lock, disable preemption. (Note that on uniprocessor systems, you're
+ * allowed to skip the first step and just lock out pre-emption, since
+ * it's not possible for you to be in contention with another running
+ * thread.) Later, you release the lock then re-enable preemption.
+ * The difference between Windows and FreeBSD lies in how preemption
+ * is disabled. In FreeBSD, it's done using critical_enter(), which on
+ * the x86 arch translates to a cli instruction. This masks off all
+ * interrupts, and effectively stops the scheduler from ever running
+ * so _nothing_ can execute except the current thread. In Windows,
+ * preemption is disabled by raising the processor IRQL to DISPATCH_LEVEL.
+ * This stops other threads from running, but does _not_ block device
+ * interrupts. This means ISRs can still run, and they can make other
+ * threads runable, but those other threads won't be able to execute
+ * until the current thread lowers the IRQL to something less than
+ * DISPATCH_LEVEL.
+ *
+ * In FreeBSD, ISRs run in interrupt threads, so to duplicate the
+ * Windows notion of IRQLs, we use the following rules:
+ *
+ * PASSIVE_LEVEL == normal kernel thread priority
+ * DISPATCH_LEVEL == lowest interrupt thread priotity (PI_SOFT)
+ * DEVICE_LEVEL == highest interrupt thread priority  (PI_REALTIME)
+ * HIGH_LEVEL == interrupts disabled (critical_enter())
+ *
+ * Be aware that, at least on the x86 arch, the Windows spinlock
+ * functions are divided up in peculiar ways. The actual spinlock
+ * functions are KfAcquireSpinLock() and KfReleaseSpinLock(), and
+ * they live in HAL.dll. Meanwhile, KeInitializeSpinLock(),
+ * KefAcquireSpinLockAtDpcLevel() and KefReleaseSpinLockFromDpcLevel()
+ * live in ntoskrnl.exe. Most Windows source code will call
+ * KeAcquireSpinLock() and KeReleaseSpinLock(), but these are just
+ * macros that call KfAcquireSpinLock() and KfReleaseSpinLock().
+ * KefAcquireSpinLockAtDpcLevel() and KefReleaseSpinLockFromDpcLevel()
+ * perform the lock aquisition/release functions without doing the
+ * IRQL manipulation, and are used when one is already running at
+ * DISPATCH_LEVEL. Make sense? Good.
+ *
+ * According to the Microsoft documentation, any thread that calls
+ * KeAcquireSpinLock() must be running at IRQL <= DISPATCH_LEVEL. If
+ * we detect someone trying to acquire a spinlock from DEVICE_LEVEL
+ * or HIGH_LEVEL, we panic.
+ */
+
+__stdcall __regcall uint8_t
+hal_lock(REGARGS1(kspin_lock *lock))
+{
+       uint8_t                 oldirql;
+
+       /* I am so going to hell for this. */
+       if (hal_irql() > DISPATCH_LEVEL)
+               panic("IRQL_NOT_LESS_THAN_OR_EQUAL");
+
+       oldirql = FASTCALL1(hal_raise_irql, DISPATCH_LEVEL);
+       FASTCALL1(ntoskrnl_lock_dpc, lock);
+
+       return(oldirql);
+}
+
+__stdcall __regcall void
+hal_unlock(REGARGS2(kspin_lock *lock, uint8_t newirql))
+{
+       FASTCALL1(ntoskrnl_unlock_dpc, lock);
+       FASTCALL1(hal_lower_irql, newirql);
+
+       return;
+}
+
+__stdcall uint8_t
+hal_irql(void)
+{
+       if (AT_DISPATCH_LEVEL(curthread))
+               return(DISPATCH_LEVEL);
+       return(PASSIVE_LEVEL);
+}
+
+__stdcall static uint64_t
+hal_perfcount(freq)
+       uint64_t                *freq;
+{
+       if (freq != NULL)
+               *freq = hz;
+
+       return((uint64_t)ticks);
+}
+
+__stdcall __regcall uint8_t
+hal_raise_irql(REGARGS1(uint8_t irql))
+{
+       uint8_t                 oldirql;
+
+       if (irql < hal_irql())
+               panic("IRQL_NOT_LESS_THAN");
+
+       if (hal_irql() == DISPATCH_LEVEL)
+               return(DISPATCH_LEVEL);
+
+       oldirql = lwkt_getpri_self();
+       lwkt_setpri_self(TDPRI_INT_HIGH);
+
+       return(oldirql);
+}
+
+__stdcall __regcall void 
+hal_lower_irql(REGARGS1(uint8_t oldirql))
+{
+       if (oldirql == DISPATCH_LEVEL)
+               return;
+
+       if (hal_irql() != DISPATCH_LEVEL)
+               panic("IRQL_NOT_GREATER_THAN");
+
+       lwkt_setpri_self(oldirql);
+}
+
+__stdcall
+static void dummy()
+{
+       printf ("hal dummy called...\n");
+       return;
+}
+
+image_patch_table hal_functbl[] = {
+       { "KeStallExecutionProcessor",  (FUNC)hal_stall_exec_cpu },
+       { "WRITE_PORT_ULONG",           (FUNC)hal_writeport_ulong },
+       { "WRITE_PORT_USHORT",          (FUNC)hal_writeport_ushort },
+       { "WRITE_PORT_UCHAR",           (FUNC)hal_writeport_uchar },
+       { "WRITE_PORT_BUFFER_ULONG",    (FUNC)hal_writeport_buf_ulong },
+       { "WRITE_PORT_BUFFER_USHORT",   (FUNC)hal_writeport_buf_ushort },
+       { "WRITE_PORT_BUFFER_UCHAR",    (FUNC)hal_writeport_buf_uchar },
+       { "READ_PORT_ULONG",            (FUNC)hal_readport_ulong },
+       { "READ_PORT_USHORT",           (FUNC)hal_readport_ushort },
+       { "READ_PORT_UCHAR",            (FUNC)hal_readport_uchar },
+       { "READ_PORT_BUFFER_ULONG",     (FUNC)hal_readport_buf_ulong },
+       { "READ_PORT_BUFFER_USHORT",    (FUNC)hal_readport_buf_ushort },
+       { "READ_PORT_BUFFER_UCHAR",     (FUNC)hal_readport_buf_uchar },
+       { "KfAcquireSpinLock",          (FUNC)hal_lock },
+       { "KfReleaseSpinLock",          (FUNC)hal_unlock },
+       { "KeGetCurrentIrql",           (FUNC)hal_irql },
+       { "KeQueryPerformanceCounter",  (FUNC)hal_perfcount },
+       { "KfLowerIrql",                (FUNC)hal_lower_irql },
+       { "KfRaiseIrql",                (FUNC)hal_raise_irql },
+
+       /*
+        * This last entry is a catch-all for any function we haven't
+        * implemented yet. The PE import list patching routine will
+        * use it for any function that doesn't have an explicit match
+        * in this table.
+        */
+
+       { NULL, (FUNC)dummy },
+
+       /* End of list. */
+
+       { NULL, NULL },
+};
diff --git a/sys/emulation/ndis/subr_ndis.c b/sys/emulation/ndis/subr_ndis.c
new file mode 100644 (file)
index 0000000..04b86b6
--- /dev/null
@@ -0,0 +1,3029 @@
+/*
+ * 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: src/sys/compat/ndis/subr_ndis.c,v 1.62 2004/07/11 00:19:30 wpaul Exp $
+ * $DragonFly: src/sys/emulation/ndis/subr_ndis.c,v 1.1 2004/07/29 20:51:34 dillon Exp $
+ */
+
+/*
+ * This file implements a translation layer between the BSD networking
+ * infrasturcture and Windows(R) NDIS network driver modules. A Windows
+ * NDIS driver calls into several functions in the NDIS.SYS Windows
+ * kernel module and exports a table of functions designed to be called
+ * by the NDIS subsystem. Using the PE loader, we can patch our own
+ * versions of the NDIS routines into a given Windows driver module and
+ * convince the driver that it is in fact running on Windows.
+ *
+ * We provide a table of all our implemented NDIS routines which is patched
+ * into the driver object code. All our exported routines must use the
+ * _stdcall calling convention, since that's what the Windows object code
+ * expects.
+ */
+
+
+#include <sys/ctype.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+
+#include <sys/callout.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/queue.h>
+#include <sys/proc.h>
+#include <sys/filedesc.h>
+#include <sys/namei.h>
+#include <sys/fcntl.h>
+#include <sys/vnode.h>
+#include <sys/kthread.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+
+#include <machine/atomic.h>
+#include <machine/bus_memio.h>
+#include <machine/bus_pio.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <machine/stdarg.h>
+
+#include <netproto/802_11/ieee80211_var.h>
+#include <netproto/802_11/ieee80211_ioctl.h>
+
+#include <bus/pci/pcireg.h>
+#include <bus/pci/pcivar.h>
+
+#include "regcall.h"
+#include "pe_var.h"
+#include "resource_var.h"
+#include "ntoskrnl_var.h"
+#include "hal_var.h"
+#include "ndis_var.h"
+#include "cfg_var.h"
+#include <dev/netif/ndis/if_ndisvar.h>
+
+#define FUNC void(*)(void)
+
+static char ndis_filepath[MAXPATHLEN];
+extern struct nd_head ndis_devhead;
+
+SYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath,
+        MAXPATHLEN, "Path used by NdisOpenFile() to search for files");
+
+__stdcall static void ndis_initwrap(ndis_handle *,
+       device_object *, void *, void *);
+__stdcall static ndis_status ndis_register_miniport(ndis_handle,
+       ndis_miniport_characteristics *, int);
+__stdcall static ndis_status ndis_malloc_withtag(void **, uint32_t, uint32_t);
+__stdcall static ndis_status ndis_malloc(void **,
+       uint32_t, uint32_t, ndis_physaddr);
+__stdcall static void ndis_free(void *, uint32_t, uint32_t);
+__stdcall static ndis_status ndis_setattr_ex(ndis_handle, ndis_handle,
+       uint32_t, uint32_t, ndis_interface_type);
+__stdcall static void ndis_open_cfg(ndis_status *, ndis_handle *, ndis_handle);
+__stdcall static void ndis_open_cfgbyidx(ndis_status *, ndis_handle,
+       uint32_t, ndis_unicode_string *, ndis_handle *);
+__stdcall static void ndis_open_cfgbyname(ndis_status *, ndis_handle,
+       ndis_unicode_string *, ndis_handle *);
+static ndis_status ndis_encode_parm(ndis_miniport_block *,
+       struct sysctl_oid *, ndis_parm_type, ndis_config_parm **);
+static ndis_status ndis_decode_parm(ndis_miniport_block *,
+       ndis_config_parm *, char *);
+__stdcall static void ndis_read_cfg(ndis_status *, ndis_config_parm **,
+       ndis_handle, ndis_unicode_string *, ndis_parm_type);
+__stdcall static void ndis_write_cfg(ndis_status *, ndis_handle,
+       ndis_unicode_string *, ndis_config_parm *);
+__stdcall static void ndis_close_cfg(ndis_handle);
+__stdcall static void ndis_create_lock(ndis_spin_lock *);
+__stdcall static void ndis_destroy_lock(ndis_spin_lock *);
+__stdcall static void ndis_lock(ndis_spin_lock *);
+__stdcall static void ndis_unlock(ndis_spin_lock *);
+__stdcall static void ndis_lock_dpr(ndis_spin_lock *);
+__stdcall static void ndis_unlock_dpr(ndis_spin_lock *);
+__stdcall static uint32_t ndis_read_pci(ndis_handle, uint32_t,
+       uint32_t, void *, uint32_t);
+__stdcall static uint32_t ndis_write_pci(ndis_handle, uint32_t,
+       uint32_t, void *, uint32_t);
+static void ndis_syslog(ndis_handle, ndis_error_code, uint32_t, ...);
+static void ndis_map_cb(void *, bus_dma_segment_t *, int, int);
+__stdcall static void ndis_vtophys_load(ndis_handle, ndis_buffer *,
+       uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *);
+__stdcall static void ndis_vtophys_unload(ndis_handle, ndis_buffer *, uint32_t);
+__stdcall static void ndis_create_timer(ndis_miniport_timer *, ndis_handle,
+       ndis_timer_function, void *);
+__stdcall static void ndis_init_timer(ndis_timer *,
+       ndis_timer_function, void *);
+__stdcall static void ndis_set_timer(ndis_timer *, uint32_t);
+__stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t);
+__stdcall static void ndis_cancel_timer(ndis_timer *, uint8_t *);
+__stdcall static void ndis_query_resources(ndis_status *, ndis_handle,
+       ndis_resource_list *, uint32_t *);
+__stdcall static ndis_status ndis_register_ioport(void **,
+       ndis_handle, uint32_t, uint32_t);
+__stdcall static void ndis_deregister_ioport(ndis_handle,
+       uint32_t, uint32_t, void *);
+__stdcall static void ndis_read_netaddr(ndis_status *, void **,
+       uint32_t *, ndis_handle);
+__stdcall static ndis_status ndis_mapreg_cnt(uint32_t, uint32_t *);
+__stdcall static ndis_status ndis_alloc_mapreg(ndis_handle,
+       uint32_t, uint8_t, uint32_t, uint32_t);
+__stdcall static void ndis_free_mapreg(ndis_handle);
+static void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int);
+__stdcall static void ndis_alloc_sharedmem(ndis_handle, uint32_t,
+       uint8_t, void **, ndis_physaddr *);
+static void ndis_asyncmem_complete(void *);
+__stdcall static ndis_status ndis_alloc_sharedmem_async(ndis_handle,
+       uint32_t, uint8_t, void *);
+__stdcall static void ndis_free_sharedmem(ndis_handle, uint32_t,
+       uint8_t, void *, ndis_physaddr);
+__stdcall static ndis_status ndis_map_iospace(void **, ndis_handle,
+       ndis_physaddr, uint32_t);
+__stdcall static void ndis_unmap_iospace(ndis_handle, void *, uint32_t);
+__stdcall static uint32_t ndis_cachefill(void);
+__stdcall static uint32_t ndis_dma_align(ndis_handle);
+__stdcall static ndis_status ndis_init_sc_dma(ndis_handle,
+       uint8_t, uint32_t);
+__stdcall static void ndis_alloc_packetpool(ndis_status *,
+       ndis_handle *, uint32_t, uint32_t);
+__stdcall static void ndis_ex_alloc_packetpool(ndis_status *,
+       ndis_handle *, uint32_t, uint32_t, uint32_t);
+__stdcall static uint32_t ndis_packetpool_use(ndis_handle);
+__stdcall static void ndis_free_packetpool(ndis_handle);
+__stdcall static void ndis_alloc_packet(ndis_status *,
+       ndis_packet **, ndis_handle);
+__stdcall static void ndis_release_packet(ndis_packet *);
+__stdcall static void ndis_unchain_headbuf(ndis_packet *, ndis_buffer **);
+__stdcall static void ndis_unchain_tailbuf(ndis_packet *, ndis_buffer **);
+__stdcall static void ndis_alloc_bufpool(ndis_status *,
+       ndis_handle *, uint32_t);
+__stdcall static void ndis_free_bufpool(ndis_handle);
+__stdcall static void ndis_alloc_buf(ndis_status *, ndis_buffer **,
+       ndis_handle, void *, uint32_t);
+__stdcall static void ndis_release_buf(ndis_buffer *);
+__stdcall static uint32_t ndis_buflen(ndis_buffer *);
+__stdcall static void ndis_query_buf(ndis_buffer *, void **, uint32_t *);
+__stdcall static void ndis_query_buf_safe(ndis_buffer *, void **,
+       uint32_t *, uint32_t);
+__stdcall static void *ndis_buf_vaddr(ndis_buffer *);
+__stdcall static void *ndis_buf_vaddr_safe(ndis_buffer *, uint32_t);
+__stdcall static void ndis_adjust_buflen(ndis_buffer *, int);
+__stdcall static uint32_t ndis_interlock_inc(uint32_t *);
+__stdcall static uint32_t ndis_interlock_dec(uint32_t *);
+__stdcall static void ndis_init_event(ndis_event *);
+__stdcall static void ndis_set_event(ndis_event *);
+__stdcall static void ndis_reset_event(ndis_event *);
+__stdcall static uint8_t ndis_wait_event(ndis_event *, uint32_t);
+__stdcall static ndis_status ndis_unicode2ansi(ndis_ansi_string *,
+       ndis_unicode_string *);
+__stdcall static ndis_status ndis_ansi2unicode(ndis_unicode_string *,
+       ndis_ansi_string *);
+__stdcall static ndis_status ndis_assign_pcirsrc(ndis_handle,
+       uint32_t, ndis_resource_list **);
+__stdcall static ndis_status ndis_register_intr(ndis_miniport_interrupt *,
+       ndis_handle, uint32_t, uint32_t, uint8_t,
+       uint8_t, ndis_interrupt_mode);
+__stdcall static void ndis_deregister_intr(ndis_miniport_interrupt *);
+__stdcall static void ndis_register_shutdown(ndis_handle, void *,
+       ndis_shutdown_handler);
+__stdcall static void ndis_deregister_shutdown(ndis_handle);
+__stdcall static uint32_t ndis_numpages(ndis_buffer *);
+__stdcall static void ndis_buf_physpages(ndis_buffer *, uint32_t *);
+__stdcall static void ndis_query_bufoffset(ndis_buffer *,
+       uint32_t *, uint32_t *);
+__stdcall static void ndis_sleep(uint32_t);
+__stdcall static uint32_t ndis_read_pccard_amem(ndis_handle,
+       uint32_t, void *, uint32_t);
+__stdcall static uint32_t ndis_write_pccard_amem(ndis_handle,
+       uint32_t, void *, uint32_t);
+__stdcall static list_entry *ndis_insert_head(list_entry *,
+       list_entry *, ndis_spin_lock *);
+__stdcall static list_entry *ndis_remove_head(list_entry *,
+       ndis_spin_lock *);
+__stdcall static list_entry *ndis_insert_tail(list_entry *,
+       list_entry *, ndis_spin_lock *);
+__stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *,
+       void *, void *);
+__stdcall static void ndis_time(uint64_t *);
+__stdcall static void ndis_uptime(uint32_t *);
+__stdcall static void ndis_init_string(ndis_unicode_string *, char *);
+__stdcall static void ndis_init_ansi_string(ndis_ansi_string *, char *);
+__stdcall static void ndis_init_unicode_string(ndis_unicode_string *,
+       uint16_t *);
+__stdcall static void ndis_free_string(ndis_unicode_string *);
+__stdcall static ndis_status ndis_remove_miniport(ndis_handle *);
+__stdcall static void ndis_termwrap(ndis_handle, void *);
+__stdcall static void ndis_get_devprop(ndis_handle, device_object **,
+       device_object **, device_object **, cm_resource_list *,
+       cm_resource_list *);
+__stdcall static void ndis_firstbuf(ndis_packet *, ndis_buffer **,
+       void **, uint32_t *, uint32_t *);
+__stdcall static void ndis_firstbuf_safe(ndis_packet *, ndis_buffer **,
+       void **, uint32_t *, uint32_t *, uint32_t);
+__stdcall static void ndis_open_file(ndis_status *, ndis_handle *, uint32_t *,
+       ndis_unicode_string *, ndis_physaddr);
+__stdcall static void ndis_map_file(ndis_status *, void **, ndis_handle);
+__stdcall static void ndis_unmap_file(ndis_handle);
+__stdcall static void ndis_close_file(ndis_handle);
+__stdcall static u_int8_t ndis_cpu_cnt(void);
+__stdcall static void ndis_ind_statusdone(ndis_handle);
+__stdcall static void ndis_ind_status(ndis_handle, ndis_status,
+        void *, uint32_t);
+static void ndis_workfunc(void *);
+__stdcall static ndis_status ndis_sched_workitem(ndis_work_item *);
+__stdcall static void ndis_pkt_to_pkt(ndis_packet *, uint32_t, uint32_t,
+       ndis_packet *, uint32_t, uint32_t *);
+__stdcall static void ndis_pkt_to_pkt_safe(ndis_packet *, uint32_t, uint32_t,
+       ndis_packet *, uint32_t, uint32_t *, uint32_t);
+__stdcall static ndis_status ndis_register_dev(ndis_handle,
+       ndis_unicode_string *, ndis_unicode_string *, driver_dispatch **,
+       void **, ndis_handle *);
+__stdcall static ndis_status ndis_deregister_dev(ndis_handle);
+__stdcall static ndis_status ndis_query_name(ndis_unicode_string *,
+       ndis_handle);
+__stdcall static void ndis_register_unload(ndis_handle, void *);
+__stdcall static void dummy(void);
+
+/*
+ * Some really old drivers do not properly check the return value
+ * from NdisAllocatePacket() and NdisAllocateBuffer() and will
+ * sometimes allocate few more buffers/packets that they originally
+ * requested when they created the pool. To prevent this from being
+ * a problem, we allocate a few extra buffers/packets beyond what
+ * the driver asks for. This #define controls how many.
+ */
+#define NDIS_POOL_EXTRA                16
+
+int
+ndis_libinit()
+{
+       strcpy(ndis_filepath, "/compat/ndis");
+       return(0);
+}
+
+int
+ndis_libfini()
+{
+       return(0);
+}
+
+/*
+ * NDIS deals with strings in unicode format, so we have
+ * do deal with them that way too. For now, we only handle
+ * conversion between unicode and ASCII since that's all
+ * that device drivers care about.
+ */
+
+int
+ndis_ascii_to_unicode(ascii, unicode)
+       char                    *ascii;
+       uint16_t                **unicode;
+{
+       uint16_t                *ustr;
+       int                     i;
+
+       if (*unicode == NULL)
+               *unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_WAITOK);
+
+       if (*unicode == NULL)
+               return(ENOMEM);
+       ustr = *unicode;
+       for (i = 0; i < strlen(ascii); i++) {
+               *ustr = (uint16_t)ascii[i];
+               ustr++;
+       }
+
+       return(0);
+}
+
+int
+ndis_unicode_to_ascii(unicode, ulen, ascii)
+       uint16_t                *unicode;
+       int                     ulen;
+       char                    **ascii;
+{
+       uint8_t                 *astr;
+       int                     i;
+
+       if (*ascii == NULL)
+               *ascii = malloc((ulen / 2) + 1, M_DEVBUF, M_WAITOK|M_ZERO);
+       if (*ascii == NULL)
+               return(ENOMEM);
+       astr = *ascii;
+       for (i = 0; i < ulen / 2; i++) {
+               *astr = (uint8_t)unicode[i];
+               astr++;
+       }
+
+       return(0);
+}
+
+__stdcall static void
+ndis_initwrap(wrapper, drv_obj, path, unused)
+       ndis_handle             *wrapper;
+       device_object           *drv_obj;
+       void                    *path;
+       void                    *unused;
+{
+       ndis_miniport_block     *block;
+
+       block = drv_obj->do_rsvd;
+       *wrapper = block;
+
+       return;
+}
+
+__stdcall static void
+ndis_termwrap(handle, syspec)
+       ndis_handle             handle;
+       void                    *syspec;
+{
+       return;
+}
+
+__stdcall static ndis_status
+ndis_register_miniport(handle, characteristics, len)
+       ndis_handle             handle;
+       ndis_miniport_characteristics *characteristics;
+       int                     len;
+{
+       ndis_miniport_block     *block;
+       struct ndis_softc       *sc;
+
+       block = (ndis_miniport_block *)handle;
+       sc = (struct ndis_softc *)block->nmb_ifp;
+       bcopy((char *)characteristics, (char *)&sc->ndis_chars,
+           sizeof(ndis_miniport_characteristics));
+       if (sc->ndis_chars.nmc_version_major < 5 ||
+           sc->ndis_chars.nmc_version_minor < 1) {
+               sc->ndis_chars.nmc_shutdown_handler = NULL;
+               sc->ndis_chars.nmc_canceltxpkts_handler = NULL;
+               sc->ndis_chars.nmc_pnpevent_handler = NULL;
+       }
+
+       return(NDIS_STATUS_SUCCESS);
+}
+
+__stdcall static ndis_status
+ndis_malloc_withtag(vaddr, len, tag)
+       void                    **vaddr;
+       uint32_t                len;
+       uint32_t                tag;
+{
+       void                    *mem;
+
+       mem = malloc(len, M_DEVBUF, M_NOWAIT);
+       if (mem == NULL)
+               return(NDIS_STATUS_RESOURCES);
+       *vaddr = mem;
+
+       return(NDIS_STATUS_SUCCESS);
+}
+
+__stdcall static ndis_status
+ndis_malloc(vaddr, len, flags, highaddr)
+       void                    **vaddr;
+       uint32_t                len;
+       uint32_t                flags;
+       ndis_physaddr           highaddr;
+{
+       void                    *mem;
+
+       mem = malloc(len, M_DEVBUF, M_NOWAIT);
+       if (mem == NULL)
+               return(NDIS_STATUS_RESOURCES);
+       *vaddr = mem;
+
+       return(NDIS_STATUS_SUCCESS);
+}
+
+__stdcall static void
+ndis_free(vaddr, len, flags)
+       void                    *vaddr;
+       uint32_t                len;
+       uint32_t                flags;
+{
+       if (len == 0)
+               return;
+       free(vaddr, M_DEVBUF);
+
+       return;
+}
+
+__stdcall static ndis_status
+ndis_setattr_ex(adapter_handle, adapter_ctx, hangsecs,
+                       flags, iftype)
+       ndis_handle                     adapter_handle;
+       ndis_handle                     adapter_ctx;
+       uint32_t                        hangsecs;
+       uint32_t                        flags;
+       ndis_interface_type             iftype;
+{
+       ndis_miniport_block             *block;
+
+       /*
+        * Save the adapter context, we need it for calling
+        * the driver's internal functions.
+        */
+       block = (ndis_miniport_block *)adapter_handle;
+       block->nmb_miniportadapterctx = adapter_ctx;
+       block->nmb_checkforhangsecs = hangsecs;
+       block->nmb_flags = flags;
+
+       return(NDIS_STATUS_SUCCESS);
+}
+
+__stdcall static void
+ndis_open_cfg(status, cfg, wrapctx)
+       ndis_status             *status;
+       ndis_handle             *cfg;
+       ndis_handle             wrapctx;
+{
+       *cfg = wrapctx;
+       *status = NDIS_STATUS_SUCCESS;
+       return;
+}
+
+__stdcall static void
+ndis_open_cfgbyname(status, cfg, subkey, subhandle)
+       ndis_status             *status;
+       ndis_handle             cfg;
+       ndis_unicode_string     *subkey;
+       ndis_handle             *subhandle;
+{
+       *subhandle = cfg;
+       *status = NDIS_STATUS_SUCCESS;
+       return;
+}
+
+__stdcall static void
+ndis_open_cfgbyidx(status, cfg, idx, subkey, subhandle)
+       ndis_status             *status;
+       ndis_handle             cfg;
+       uint32_t                idx;
+       ndis_unicode_string     *subkey;
+       ndis_handle             *subhandle;
+{
+       *status = NDIS_STATUS_FAILURE;
+       return;
+}
+
+static ndis_status
+ndis_encode_parm(block, oid, type, parm)
+       ndis_miniport_block     *block;
+        struct sysctl_oid      *oid;
+       ndis_parm_type          type;
+       ndis_config_parm        **parm;
+{
+       uint16_t                *unicode;
+       ndis_unicode_string     *ustr;
+       int                     base = 0;
+
+       unicode = (uint16_t *)&block->nmb_dummybuf;
+
+       switch(type) {
+       case ndis_parm_string:
+               ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode);
+               (*parm)->ncp_type = ndis_parm_string;
+               ustr = &(*parm)->ncp_parmdata.ncp_stringdata;
+               ustr->nus_len = strlen((char *)oid->oid_arg1) * 2;
+               ustr->nus_buf = unicode;
+               break;
+       case ndis_parm_int:
+               if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0)
+                       base = 16;
+               else
+                       base = 10;
+               (*parm)->ncp_type = ndis_parm_int;
+               (*parm)->ncp_parmdata.ncp_intdata =
+                   strtol((char *)oid->oid_arg1, NULL, base);
+               break;
+       case ndis_parm_hexint:
+               if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0)
+                       base = 16;
+               else
+                       base = 10;
+               (*parm)->ncp_type = ndis_parm_hexint;
+               (*parm)->ncp_parmdata.ncp_intdata =
+                   strtoul((char *)oid->oid_arg1, NULL, base);
+               break;
+       default:
+               return(NDIS_STATUS_FAILURE);
+               break;
+       }
+
+       return(NDIS_STATUS_SUCCESS);
+}
+
+int
+ndis_strcasecmp(s1, s2)
+        const char              *s1;
+        const char              *s2;
+{
+       char                    a, b;
+
+       /*
+        * In the kernel, toupper() is a macro. Have to be careful
+        * not to use pointer arithmetic when passing it arguments.
+        */
+
+       while(1) {
+               a = *s1;
+               b = *s2++;
+               if (toupper(a) != toupper(b))
+                       break;
+               if (*s1++ == 0)
+                       return(0);
+       }
+
+       return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
+}
+
+__stdcall static void
+ndis_read_cfg(status, parm, cfg, key, type)
+       ndis_status             *status;
+       ndis_config_parm        **parm;
+      &nbs