aboutsummaryrefslogtreecommitdiff
path: root/sys/compat
diff options
context:
space:
mode:
Diffstat (limited to 'sys/compat')
-rw-r--r--sys/compat/ndis/cfg_var.h46
-rw-r--r--sys/compat/ndis/hal_var.h40
-rw-r--r--sys/compat/ndis/kern_ndis.c1049
-rw-r--r--sys/compat/ndis/ndis_var.h1174
-rw-r--r--sys/compat/ndis/ntoskrnl_var.h105
-rw-r--r--sys/compat/ndis/pe_var.h330
-rw-r--r--sys/compat/ndis/resource_var.h160
-rw-r--r--sys/compat/ndis/subr_hal.c152
-rw-r--r--sys/compat/ndis/subr_ndis.c1930
-rw-r--r--sys/compat/ndis/subr_ntoskrnl.c497
-rw-r--r--sys/compat/ndis/subr_pe.c537
11 files changed, 6020 insertions, 0 deletions
diff --git a/sys/compat/ndis/cfg_var.h b/sys/compat/ndis/cfg_var.h
new file mode 100644
index 000000000000..831239c54804
--- /dev/null
+++ b/sys/compat/ndis/cfg_var.h
@@ -0,0 +1,46 @@
+/*
+ * 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$
+ */
+
+#ifndef _CFG_VAR_H_
+#define _CFG_VAR_H_
+
+struct ndis_cfg {
+ char *nc_cfgkey;
+ char *nc_cfgdesc;
+ char nc_val[256];
+};
+
+typedef struct ndis_cfg ndis_cfg;
+
+#endif /* _CFG_VAR_H_ */
diff --git a/sys/compat/ndis/hal_var.h b/sys/compat/ndis/hal_var.h
new file mode 100644
index 000000000000..d18ae3e6102f
--- /dev/null
+++ b/sys/compat/ndis/hal_var.h
@@ -0,0 +1,40 @@
+/*
+ * 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$
+ */
+
+#ifndef _HAL_VAR_H_
+#define _HAL_VAR_H_
+
+extern image_patch_table hal_functbl[];
+
+#endif /* _HAL_VAR_H_ */
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c
new file mode 100644
index 000000000000..b36831f17ce1
--- /dev/null
+++ b/sys/compat/ndis/kern_ndis.c
@@ -0,0 +1,1049 @@
+/*
+ * Copyright (c) 2003
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/callout.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/conf.h>
+
+#include <sys/kernel.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 <dev/pccard/pccardvar.h>
+#include "card_if.h"
+
+#include <compat/ndis/pe_var.h>
+#include <compat/ndis/resource_var.h>
+#include <compat/ndis/ndis_var.h>
+#include <compat/ndis/hal_var.h>
+#include <compat/ndis/ntoskrnl_var.h>
+#include <compat/ndis/cfg_var.h>
+#include <dev/if_ndis/if_ndisvar.h>
+
+#define __stdcall __attribute__((__stdcall__))
+#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_resetdone_func(ndis_handle, ndis_status, uint8_t);
+
+/*
+ * 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)
+{
+ return(0);
+}
+DEV_MODULE(ndisapi, ndis_modevent, NULL);
+MODULE_VERSION(ndisapi, 1);
+
+
+__stdcall static void
+ndis_status_func(adapter, status, sbuf, slen)
+ ndis_handle adapter;
+ ndis_status status;
+ void *sbuf;
+ uint32_t slen;
+{
+ printf ("status: %x\n", status);
+ return;
+}
+
+__stdcall static void
+ndis_statusdone_func(adapter)
+ ndis_handle adapter;
+{
+ printf ("status complete\n");
+ return;
+}
+
+__stdcall static void
+ndis_setdone_func(adapter, status)
+ ndis_handle adapter;
+ ndis_status status;
+{
+ printf ("Setup done... %x\n", status);
+ return;
+}
+
+__stdcall static void
+ndis_resetdone_func(adapter, status, addressingreset)
+ ndis_handle adapter;
+ ndis_status status;
+ uint8_t addressingreset;
+{
+ printf ("reset done...\n");
+ return;
+}
+
+#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) {
+ printf("ndis%d: failed to allocate attribute memory\n",
+ sc->ndis_unit);
+ return(ENXIO);
+ }
+
+ error = CARD_SET_MEMORY_OFFSET(device_get_parent(sc->ndis_dev),
+ sc->ndis_dev, rid, 0, NULL);
+
+ if (error) {
+ printf("ndis%d: CARD_SET_MEMORY_OFFSET() returned 0x%x\n",
+ sc->ndis_unit, 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) {
+ printf("ndis%d: CARD_SET_RES_FLAGS() returned 0x%x\n",
+ sc->ndis_unit, error);
+ return(error);
+ }
+
+ return(0);
+}
+
+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);
+
+ /* 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));
+
+ /* Add the driver-specific registry keys. */
+
+ vals = sc->ndis_regvals;
+ while(1) {
+ if (vals->nc_cfgkey == NULL)
+ break;
+ 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);
+ 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\n", (int)sc->ndis_iftype);
+ ndis_add_sysctl(sc, "BusType", "Bus Type", buf, CTLFLAG_RD);
+
+ if (sc->ndis_res_io != NULL) {
+ sprintf(buf, "0x%lx\n", 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\n", 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);
+
+ 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);
+
+ 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);
+}
+
+void
+ndis_return_packet(packet, arg)
+ void *packet;
+ void *arg;
+{
+ struct ndis_softc *sc;
+ ndis_handle adapter;
+ __stdcall ndis_return_handler returnfunc;
+
+ if (arg == NULL || packet == NULL)
+ return;
+
+ sc = arg;
+ returnfunc = sc->ndis_chars.nmc_return_packet_func;
+ adapter = sc->ndis_block.nmb_miniportadapterctx;
+ if (returnfunc == NULL)
+ ndis_free_packet((ndis_packet *)packet);
+ else
+ returnfunc(adapter, (ndis_packet *)packet);
+ return;
+}
+
+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_DEVBUF);
+ 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_DEVBUF);
+
+ 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;
+
+ sc = arg;
+ block = &sc->ndis_block;
+
+ 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;
+ if (sc->ndis_res_io) {
+ prd->cprd_type = CmResourceTypePort;
+ prd->u.cprd_port.cprd_start.np_quad =
+ rman_get_start(sc->ndis_res_io);
+ prd->u.cprd_port.cprd_len =
+ rman_get_size(sc->ndis_res_io);
+ prd++;
+ }
+
+ if (sc->ndis_res_mem) {
+ prd->cprd_type = CmResourceTypeMemory;
+ prd->u.cprd_mem.cprd_start.np_quad =
+ rman_get_start(sc->ndis_res_mem);
+ prd->u.cprd_mem.cprd_len =
+ rman_get_size(sc->ndis_res_mem);
+ prd++;
+ }
+
+ if (sc->ndis_irq) {
+ prd->cprd_type = CmResourceTypeInterrupt;
+ prd->u.cprd_intr.cprd_level =
+ rman_get_start(sc->ndis_irq);
+ prd->u.cprd_intr.cprd_vector =
+ rman_get_start(sc->ndis_irq);
+ prd->u.cprd_intr.cprd_affinity = 0;
+ }
+
+ block->nmb_rlist = rl;
+
+ return(0);
+}
+
+/*
+ * 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;
+
+ for (buf = priv->npp_head; buf != NULL; buf = buf->nb_next) {
+ if (buf == priv->npp_head)
+ MGETHDR(m, M_DONTWAIT, MT_HEADER);
+ else
+ MGET(m, M_DONTWAIT, MT_DATA);
+ if (m == NULL) {
+ m_freem(*m0);
+ *m0 = NULL;
+ return(ENOBUFS);
+ }
+
+ /*
+ * Note: there's some hackery going on here. We want
+ * to mate the mbufs to the buffers in the NDIS packet,
+ * but we don't mark the mbufs with the M_EXT flag to
+ * indicate external storage. This is because we don't
+ * want anything special done to free the buffers.
+ * Depending on the circumstances, the caller may want
+ * the entire packet to be released, buffers and all,
+ * by calling ndis_return_packet(), or ndis_free_packet().
+ * We leave it up to the caller to do the MEXTADD() to
+ * set up the free mechanism in the first mbuf of the
+ * chain.
+ */
+ if (buf->nb_size)
+ m->m_len = buf->nb_size;
+ else
+ m->m_len = buf->nb_bytecount;
+ m->m_data = buf->nb_mappedsystemva;
+ 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_DEVBUF, 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);
+
+ for (m = m0; m != NULL; m = m->m_next) {
+ if (m->m_len == NULL)
+ continue;
+
+ buf = malloc(sizeof(ndis_buffer), M_DEVBUF, M_NOWAIT|M_ZERO);
+ if (buf == NULL) {
+ ndis_free_packet(*p);
+ *p = NULL;
+ return(ENOMEM);
+ }
+
+ buf->nb_bytecount = m->m_len;
+ buf->nb_mappedsystemva = m->m_data;
+ if (priv->npp_head == NULL)
+ priv->npp_head = buf;
+ else
+ prev->nb_next = buf;
+ prev = buf;
+ }
+
+ priv->npp_tail = buf;
+
+ 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;
+
+ sc = arg;
+ setfunc = sc->ndis_chars.nmc_setinfo_func;
+ adapter = sc->ndis_block.nmb_miniportadapterctx;
+
+ rval = setfunc(adapter, oid, buf, *buflen,
+ &byteswritten, &bytesneeded);
+
+ 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_PENDING)
+ return(EAGAIN);
+
+ return(0);
+}
+
+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;
+
+ sc = arg;
+ adapter = sc->ndis_block.nmb_miniportadapterctx;
+ sendfunc = sc->ndis_chars.nmc_sendmulti_func;
+ sendfunc(adapter, packets, cnt);
+
+ 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);
+
+ sc->ndis_mbufs = malloc(sizeof(struct mbuf) * sc->ndis_maxpkts,
+ M_DEVBUF, M_NOWAIT|M_ZERO);
+
+ if (sc->ndis_mbufs == NULL) {
+ free(sc->ndis_tmaps, M_DEVBUF);
+ 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);
+ free(sc->ndis_mbufs, M_DEVBUF);
+ return(ENODEV);
+ }
+ }
+
+ return(0);
+}
+
+int
+ndis_destroy_dma(arg)
+ void *arg;
+{
+ struct ndis_softc *sc;
+ int i;
+
+ sc = arg;
+
+ for (i = 0; i < sc->ndis_maxpkts; i++) {
+ if (sc->ndis_mbufs[i] != NULL)
+ m_freem(sc->ndis_mbufs[i]);
+ bus_dmamap_destroy(sc->ndis_ttag, sc->ndis_tmaps[i]);
+ }
+
+ free(sc->ndis_tmaps, M_DEVBUF);
+ free(sc->ndis_mbufs, 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;
+
+ sc = arg;
+ ifp = &sc->arpcom.ac_if;
+ adapter = sc->ndis_block.nmb_miniportadapterctx;
+ if (adapter == NULL)
+ return(EIO);
+ resetfunc = sc->ndis_chars.nmc_reset_func;
+
+ if (resetfunc == NULL)
+ return(EINVAL);
+
+ resetfunc(&addressing_reset, adapter);
+
+ return(0);
+}
+
+int
+ndis_halt_nic(arg)
+ void *arg;
+{
+ struct ndis_softc *sc;
+ ndis_handle adapter;
+ __stdcall ndis_halt_handler haltfunc;
+ struct ifnet *ifp;
+
+ sc = arg;
+ ifp = &sc->arpcom.ac_if;
+ adapter = sc->ndis_block.nmb_miniportadapterctx;
+ if (adapter == NULL)
+ return(EIO);
+ haltfunc = sc->ndis_chars.nmc_halt_func;
+
+ if (haltfunc == NULL)
+ return(EINVAL);
+
+ haltfunc(adapter);
+
+ /*
+ * The adapter context is only valid after the init
+ * handler has been called, and is invalid once the
+ * halt handler has been called.
+ */
+
+ sc->ndis_block.nmb_miniportadapterctx = NULL;
+
+ return(0);
+}
+
+int
+ndis_shutdown_nic(arg)
+ void *arg;
+{
+ struct ndis_softc *sc;
+ ndis_handle adapter;
+ __stdcall ndis_shutdown_handler shutdownfunc;
+
+
+ sc = arg;
+ adapter = sc->ndis_block.nmb_miniportadapterctx;
+ if (adapter == NULL)
+ return(EIO);
+ shutdownfunc = sc->ndis_chars.nmc_shutdown_handler;
+
+ if (shutdownfunc == NULL)
+ return(EINVAL);
+
+ shutdownfunc(sc->ndis_chars.nmc_rsvd0);
+
+ 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;
+
+ if (arg == NULL)
+ return(EINVAL);
+
+ sc = arg;
+ block = &sc->ndis_block;
+ initfunc = sc->ndis_chars.nmc_init_func;
+
+ 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) {
+ bzero((char *)&sc->ndis_chars,
+ sizeof(ndis_miniport_characteristics));
+ 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;
+ if (adapter == NULL)
+ return;
+ intrenbfunc = sc->ndis_chars.nmc_enable_interrupts_func;
+ if (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;
+
+ sc = arg;
+ adapter = sc->ndis_block.nmb_miniportadapterctx;
+ if (adapter == NULL)
+ return;
+ intrdisfunc = sc->ndis_chars.nmc_disable_interrupts_func;
+ if (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;
+ 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;
+
+ if (arg == NULL)
+ return(EINVAL);
+
+ sc = arg;
+ adapter = sc->ndis_block.nmb_miniportadapterctx;
+ intrfunc = sc->ndis_chars.nmc_interrupt_func;
+ 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;
+ __stdcall ndis_queryinfo_handler queryfunc;
+ uint32_t byteswritten = 0, bytesneeded = 0;
+
+ sc = arg;
+ queryfunc = sc->ndis_chars.nmc_queryinfo_func;
+ adapter = sc->ndis_block.nmb_miniportadapterctx;
+
+ rval = queryfunc(adapter, oid, buf, *buflen,
+ &byteswritten, &bytesneeded);
+
+ 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_PENDING)
+ return(EAGAIN);
+
+ 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_libfini();
+ ntoskrnl_libfini();
+
+ return(0);
+}
+
+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_driver_object drv;
+ ndis_miniport_block *block;
+ ndis_status status;
+ int idx;
+ uint32_t *ptr;
+ struct ndis_softc *sc;
+
+ sc = arg;
+
+ /* 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);
+ }
+
+ /* Initialize subsystems */
+ ndis_libinit();
+ ntoskrnl_libinit();
+
+ /* Locate the driver entry point */
+ pe_get_optional_header(img, &opt_hdr);
+ entry = (driver_entry)pe_translate_addr(img, opt_hdr.ioh_entryaddr);
+
+ /*
+ * Now call the DriverEntry() routine. This will cause
+ * a callout to the NdisInitializeWrapper() and
+ * NdisMRegisterMiniport() routines.
+ */
+ dummystr.nus_len = strlen(NDIS_DUMMY_PATH);
+ dummystr.nus_maxlen = strlen(NDIS_DUMMY_PATH);
+ dummystr.nus_buf = NULL;
+ ndis_ascii_to_unicode(NDIS_DUMMY_PATH, &dummystr.nus_buf);
+ drv.ndo_ifname = "ndis0";
+
+ status = entry(&drv, &dummystr);
+
+ free (dummystr.nus_buf, M_DEVBUF);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ return(ENODEV);
+
+ /*
+ * 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;
+ bcopy((char *)&drv.ndo_chars, (char *)&sc->ndis_chars,
+ sizeof(ndis_miniport_characteristics));
+
+ /*block->nmb_signature = 0xcafebabe;*/
+
+ 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_status_func = ndis_status_func;
+ block->nmb_statusdone_func = ndis_statusdone_func;
+ block->nmb_resetdone_func = ndis_resetdone_func;
+
+ block->nmb_ifp = &sc->arpcom.ac_if;
+ block->nmb_dev = sc->ndis_dev;
+
+ return(0);
+}
diff --git a/sys/compat/ndis/ndis_var.h b/sys/compat/ndis/ndis_var.h
new file mode 100644
index 000000000000..78bcfd2c9b7e
--- /dev/null
+++ b/sys/compat/ndis/ndis_var.h
@@ -0,0 +1,1174 @@
+/*
+ * 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$
+ */
+
+#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 uint32_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_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_RELOAD_DEFAULTS 0x0D01011C
+
+/* structures/definitions for 802.11 */
+#define NDIS_80211_NETTYPE_11FH 0x00000000
+#define NDIS_80211_NETTYPE_11DS 0x00000001
+
+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;
+ uint32_t nw_keydata[1];
+};
+
+typedef struct ndis_80211_wep ndis_80211_wep;
+
+#define NDIS_80211_NET_INFRA_BSS 0x00000000
+#define NDIS_80211_NET_INFRA_IBSS 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
+
+typedef uint8_t ndis_80211_rates[8];
+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;
+
+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_DISABLED 0x00000001
+#define NDIS_80211_WEPSTAT_KEYABSENT 0x00000002
+#define NDIS_80211_WEPSTAT_NOTSUPPORTED 0x00000003
+
+#define NDIS_80211_RELOADDEFAULT_WEP 0x00000000
+
+/*
+ * 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;
+
+struct ndis_list_entry {
+ struct ndis_list_entry *nle_flink;
+ struct ndis_list_entry *nle_blink;
+};
+
+typedef struct ndis_list_entry ndis_list_entry;
+
+struct ndis_bind_paths {
+ uint32_t nbp_number;
+ ndis_unicode_string nbp_paths[1];
+};
+
+typedef struct ndis_bind_paths ndis_bind_paths;
+
+struct dispatch_header {
+ uint8_t dh_type;
+ uint8_t dh_abs;
+ uint8_t dh_size;
+ uint8_t dh_inserted;
+ uint32_t dh_sigstate;
+ ndis_list_entry dh_waitlisthead;
+};
+
+struct ndis_ktimer {
+ struct dispatch_header nk_header;
+ uint64_t nk_duetime;
+ ndis_list_entry nk_timerlistentry;
+ void *nk_dpc;
+ uint32_t nk_period;
+};
+
+struct ndis_kevent {
+ struct dispatch_header nk_header;
+};
+
+struct ndis_event {
+ struct ndis_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;
+ ndis_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 ndis_ktimer nt_timer;
+ struct ndis_kdpc nt_dpc;
+};
+
+typedef struct ndis_timer ndis_timer;
+
+typedef void (*ndis_timer_function)(void *, void *, void *, void *);
+
+struct ndis_miniport_timer {
+ struct ndis_ktimer nmt_ktimer;
+ struct ndis_kdpc nmt_dpc;
+ ndis_timer_function nmt_timerfunc;
+ void *nmt_timerctx;
+ 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_spin_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_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
+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;
+
+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_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 {
+ struct {
+ uint8_t np_miniport_rsvd[2 * sizeof(void *)];
+ uint8_t np_wrapper_rsvd[2 * sizeof(void *)];
+ } np_rsvd;
+ struct {
+ uint8_t np_miniport_rsvdex[3 * sizeof(void *)];
+ uint8_t np_wrapper_rsvdex[sizeof(void *)];
+ } np_rsvdrx;
+ struct {
+ uint8_t np_mac_rsvd[4 * sizeof(void *)];
+ } np_macrsvd;
+ } u;
+ uint32_t *np_rsvd[2];
+ uint8_t np_proto_rsvd[1];
+
+ /*
+ * 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;
+};
+
+typedef struct ndis_packet ndis_packet;
+
+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;
+
+/*
+ * 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;
+ ndis_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];
+ ndis_config_parm nmb_replyparm;
+ int nmb_pciidx;
+ device_t nmb_dev;
+ ndis_resource_list *nmb_rlist;
+};
+
+typedef ndis_status (*ndis_init_handler)(ndis_status *, uint32_t *,
+ ndis_medium *, uint32_t, ndis_handle, ndis_handle);
+typedef 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 void (*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[];
+
+__BEGIN_DECLS
+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_packet(ndis_packet *);
+extern void ndis_free_bufs(ndis_buffer *);
+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_return_packet(void *, 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 *);
+__END_DECLS
+
+#endif /* _NDIS_VAR_H_ */
diff --git a/sys/compat/ndis/ntoskrnl_var.h b/sys/compat/ndis/ntoskrnl_var.h
new file mode 100644
index 000000000000..236d6fd3610c
--- /dev/null
+++ b/sys/compat/ndis/ntoskrnl_var.h
@@ -0,0 +1,105 @@
+/*
+ * 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$
+ */
+
+#ifndef _NTOSKRNL_VAR_H_
+#define _NTOSKRNL_VAR_H_
+
+typedef uint32_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 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;
+ 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 *);
+
+
+extern image_patch_table ntoskrnl_functbl[];
+
+__BEGIN_DECLS
+extern int ntoskrnl_libinit(void);
+extern int ntoskrnl_libfini(void);
+__END_DECLS
+
+#endif /* _NTOSKRNL_VAR_H_ */
diff --git a/sys/compat/ndis/pe_var.h b/sys/compat/ndis/pe_var.h
new file mode 100644
index 000000000000..a0a2cc9a535d
--- /dev/null
+++ b/sys/compat/ndis/pe_var.h
@@ -0,0 +1,330 @@
+/*
+ * 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$
+ */
+
+#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
+
+/*
+ * 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_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 *);
+__END_DECLS
+
+#endif /* _PE_VAR_H_ */
diff --git a/sys/compat/ndis/resource_var.h b/sys/compat/ndis/resource_var.h
new file mode 100644
index 000000000000..079193bf351c
--- /dev/null
+++ b/sys/compat/ndis/resource_var.h
@@ -0,0 +1,160 @@
+
+/*
+ * $FreeBSD$
+ */
+
+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;
+ 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/compat/ndis/subr_hal.c b/sys/compat/ndis/subr_hal.c
new file mode 100644
index 000000000000..442b7ef47de1
--- /dev/null
+++ b/sys/compat/ndis/subr_hal.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2003
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+
+#include <sys/callout.h>
+#include <sys/kernel.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 <compat/ndis/pe_var.h>
+#include <compat/ndis/hal_var.h>
+
+#define __stdcall __attribute__((__stdcall__))
+#define FUNC void(*)(void)
+
+__stdcall static void hal_stall_exec_cpu(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 dummy (void);
+
+__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(I386_BUS_SPACE_IO, 0x0, (uint32_t)port, val);
+ return;
+}
+
+__stdcall static void
+hal_writeport_ushort(port, val)
+ uint16_t *port;
+ uint16_t val;
+{
+ bus_space_write_2(I386_BUS_SPACE_IO, 0x0, (uint32_t)port, val);
+ return;
+}
+
+__stdcall static void
+hal_writeport_uchar(port, val)
+ uint8_t *port;
+ uint8_t val;
+{
+ bus_space_write_1(I386_BUS_SPACE_IO, 0x0, (uint32_t)port, val);
+ return;
+}
+
+__stdcall static uint16_t
+hal_readport_ushort(port)
+ uint16_t *port;
+{
+ return(bus_space_read_2(I386_BUS_SPACE_IO, 0x0, (uint32_t)port));
+}
+
+__stdcall static uint32_t
+hal_readport_ulong(port)
+ uint32_t *port;
+{
+ return(bus_space_read_4(I386_BUS_SPACE_IO, 0x0, (uint32_t)port));
+}
+
+__stdcall static uint8_t
+hal_readport_uchar(port)
+ uint8_t *port;
+{
+ return(bus_space_read_1(I386_BUS_SPACE_IO, 0x0, (uint32_t)port));
+}
+
+__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 },
+ { "READ_PORT_ULONG", (FUNC)hal_readport_ulong },
+ { "READ_PORT_USHORT", (FUNC)hal_readport_ushort },
+ { "READ_PORT_UCHAR", (FUNC)hal_readport_uchar },
+
+ /*
+ * 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/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c
new file mode 100644
index 000000000000..f45b6029cfd5
--- /dev/null
+++ b/sys/compat/ndis/subr_ndis.c
@@ -0,0 +1,1930 @@
+/*
+ * Copyright (c) 2003
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * 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/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/mutex.h>
+#include <sys/socket.h>
+#include <sys/sysctl.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/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 <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <compat/ndis/pe_var.h>
+#include <compat/ndis/resource_var.h>
+#include <compat/ndis/ndis_var.h>
+#include <compat/ndis/cfg_var.h>
+#include <dev/if_ndis/if_ndisvar.h>
+
+#define __stdcall __attribute__((__stdcall__))
+#define FUNC void(*)(void)
+
+static struct mtx ndis_interlock;
+static int ndis_inits = 0;
+
+__stdcall static void ndis_initwrap(ndis_handle,
+ ndis_driver_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);
+static ndis_status ndis_encode_parm(ndis_miniport_block *,
+ struct sysctl_oid *, ndis_parm_type, ndis_config_parm **);
+__stdcall static void ndis_read_cfg(ndis_status *, ndis_config_parm **,
+ ndis_handle, ndis_unicode_string *, ndis_parm_type);
+__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 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 *);
+static void ndis_timercall(void *);
+__stdcall static void ndis_set_timer(ndis_miniport_timer *, uint32_t);
+static void ndis_tick(void *);
+__stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t);
+__stdcall static void ndis_cancel_timer(ndis_miniport_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_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 *);
+__stdcall static void 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_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 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_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_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_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 ndis_list_entry *ndis_insert_head(ndis_list_entry *,
+ ndis_list_entry *, ndis_spin_lock *);
+__stdcall static ndis_list_entry *ndis_remove_head(ndis_list_entry *,
+ ndis_spin_lock *);
+__stdcall static ndis_list_entry *ndis_insert_tail(ndis_list_entry *,
+ ndis_list_entry *, ndis_spin_lock *);
+__stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *,
+ void *, void *);
+__stdcall static void dummy(void);
+
+
+int
+ndis_libinit()
+{
+ if (ndis_inits) {
+ ndis_inits++;
+ return(0);
+ }
+
+ mtx_init(&ndis_interlock, "ndislock", MTX_NETWORK_LOCK,
+ MTX_DEF | MTX_RECURSE | MTX_DUPOK);
+
+ ndis_inits++;
+ return(0);
+}
+
+int
+ndis_libfini()
+{
+ if (ndis_inits != 1) {
+ ndis_inits--;
+ return(0);
+ }
+
+ mtx_destroy(&ndis_interlock);
+ ndis_inits--;
+
+ 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, M_DEVBUF, M_WAITOK);
+
+ if (*ascii == NULL)
+ return(ENOMEM);
+ astr = *ascii;
+ for (i = 0; i < ulen; i++) {
+ *astr = (uint8_t)unicode[i];
+ astr++;
+ }
+
+ return(0);
+}
+
+__stdcall static void
+ndis_initwrap(wrapper, drv_obj, path, unused)
+ ndis_handle wrapper;
+ ndis_driver_object *drv_obj;
+ void *path;
+ void *unused;
+{
+ ndis_driver_object **drv;
+
+ drv = wrapper;
+ *drv = drv_obj;
+
+ return;
+}
+
+__stdcall static ndis_status
+ndis_register_miniport(handle, characteristics, len)
+ ndis_handle handle;
+ ndis_miniport_characteristics *characteristics;
+ int len;
+{
+ ndis_driver_object *drv;
+
+ drv = handle;
+ bcopy((char *)characteristics, (char *)&drv->ndo_chars,
+ sizeof(ndis_miniport_characteristics));
+ 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;
+
+ 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;
+}
+
+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;
+
+ 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:
+ (*parm)->ncp_type = ndis_parm_int;
+ (*parm)->ncp_parmdata.ncp_intdata =
+ strtol((char *)oid->oid_arg1, NULL, 10);
+ break;
+ case ndis_parm_hexint:
+ (*parm)->ncp_type = ndis_parm_hexint;
+ (*parm)->ncp_parmdata.ncp_intdata =
+ strtoul((char *)oid->oid_arg1, NULL, 16);
+ break;
+ default:
+ return(NDIS_STATUS_FAILURE);
+ break;
+ }
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+__stdcall static void
+ndis_read_cfg(status, parm, cfg, key, type)
+ ndis_status *status;
+ ndis_config_parm **parm;
+ ndis_handle cfg;
+ ndis_unicode_string *key;
+ ndis_parm_type type;
+{
+ char *keystr = NULL;
+ uint16_t *unicode;
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ struct sysctl_oid *oidp;
+ struct sysctl_ctx_entry *e;
+
+ block = (ndis_miniport_block *)cfg;
+ sc = (struct ndis_softc *)block->nmb_ifp;
+
+ ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
+
+ *parm = &block->nmb_replyparm;
+ bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm));
+ unicode = (uint16_t *)&block->nmb_dummybuf;
+
+ /*
+ * See if registry key is already in a list of known keys
+ * included with the driver.
+ */
+ TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
+ oidp = e->entry;
+ if (strcmp(oidp->oid_name, keystr) == 0) {
+ *status = ndis_encode_parm(block, oidp, type, parm);
+ free(keystr, M_DEVBUF);
+ return;
+ }
+ }
+
+ /*
+ * If the key didn't match, add it to the list of dynamically
+ * created ones. Sometimes, drivers refer to registry keys
+ * that aren't documented in their .INF files. These keys
+ * are supposed to be created by some sort of utility or
+ * control panel snap-in that comes with the driver software.
+ * Sometimes it's useful to be able to manipulate these.
+ * If the driver requests the key in the form of a string,
+ * make its default value an empty string, otherwise default
+ * it to "0".
+ */
+
+ if (type == ndis_parm_int || type == ndis_parm_hexint)
+ ndis_add_sysctl(sc, keystr, NULL, "0", CTLFLAG_RW);
+ else
+ ndis_add_sysctl(sc, keystr, NULL, "", CTLFLAG_RW);
+
+ free(keystr, M_DEVBUF);
+ *status = NDIS_STATUS_FAILURE;
+ return;
+}
+
+__stdcall static void
+ndis_close_cfg(cfg)
+ ndis_handle cfg;
+{
+ return;
+}
+
+__stdcall static void
+ndis_create_lock(lock)
+ ndis_spin_lock *lock;
+{
+ struct mtx *mtx;
+
+ mtx = malloc(sizeof(struct mtx), M_DEVBUF, M_NOWAIT|M_ZERO);
+ if (mtx == NULL)
+ return;
+ mtx_init(mtx, "ndislock", MTX_NETWORK_LOCK,
+ MTX_DEF | MTX_RECURSE | MTX_DUPOK);
+ lock->nsl_spinlock = (ndis_kspin_lock)mtx;
+
+ return;
+}
+
+__stdcall static void
+ndis_destroy_lock(lock)
+ ndis_spin_lock *lock;
+{
+ struct mtx *ndis_mtx;
+
+ ndis_mtx = (struct mtx *)lock->nsl_spinlock;
+ mtx_destroy(ndis_mtx);
+ free(ndis_mtx, M_DEVBUF);
+
+ return;
+}
+
+__stdcall static void
+ndis_lock(lock)
+ ndis_spin_lock *lock;
+{
+ if (lock == NULL)
+ return;
+ mtx_lock((struct mtx *)lock->nsl_spinlock);
+
+ return;
+}
+
+__stdcall static void
+ndis_unlock(lock)
+ ndis_spin_lock *lock;
+{
+ if (lock == NULL)
+ return;
+ mtx_unlock((struct mtx *)lock->nsl_spinlock);
+
+ return;
+}
+
+__stdcall static uint32_t
+ndis_read_pci(adapter, slot, offset, buf, len)
+ ndis_handle adapter;
+ uint32_t slot;
+ uint32_t offset;
+ void *buf;
+ uint32_t len;
+{
+ ndis_miniport_block *block;
+ int i;
+ char *dest;
+
+ block = (ndis_miniport_block *)adapter;
+ dest = buf;
+ if (block == NULL || block->nmb_dev == NULL)
+ return(0);
+
+ for (i = 0; i < len; i++)
+ dest[i] = pci_read_config(block->nmb_dev, i + offset, 1);
+
+ return(len);
+}
+
+__stdcall static uint32_t
+ndis_write_pci(adapter, slot, offset, buf, len)
+ ndis_handle adapter;
+ uint32_t slot;
+ uint32_t offset;
+ void *buf;
+ uint32_t len;
+{
+ ndis_miniport_block *block;
+ int i;
+ char *dest;
+
+ block = (ndis_miniport_block *)adapter;
+ dest = buf;
+
+ if (block == NULL || block->nmb_dev == NULL)
+ return(0);
+
+ for (i = 0; i < len; i++)
+ pci_write_config(block->nmb_dev, i + offset, dest[i], 1);
+
+ return(len);
+}
+
+/*
+ * The errorlog routine uses a variable argument list, so we
+ * have to declare it this way.
+ */
+static void
+ndis_syslog(ndis_handle adapter, ndis_error_code code,
+ uint32_t numerrors, ...)
+{
+ ndis_miniport_block *block;
+ va_list ap;
+ int i;
+
+ block = (ndis_miniport_block *)adapter;
+
+ printf ("NDIS ERROR: %x\n", code);
+ printf ("NDIS NUMERRORS: %x\n", numerrors);
+
+ va_start(ap, numerrors);
+ for (i = 0; i < numerrors; i++)
+ printf ("argptr: %p\n", va_arg(ap, void *));
+ va_end(ap);
+
+ return;
+}
+
+static void
+ndis_map_cb(arg, segs, nseg, error)
+ void *arg;
+ bus_dma_segment_t *segs;
+ int nseg;
+ int error;
+{
+ struct ndis_map_arg *ctx;
+ int i;
+
+ if (error)
+ return;
+
+ ctx = arg;
+
+ for (i = 0; i < nseg; i++) {
+ ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr;
+ ctx->nma_fraglist[i].npu_len = segs[i].ds_len;
+ }
+
+ ctx->nma_cnt = nseg;
+
+ return;
+}
+
+__stdcall static void
+ndis_vtophys_load(adapter, buf, mapreg, writedev, addrarray, arraysize)
+ ndis_handle adapter;
+ ndis_buffer *buf;
+ uint32_t mapreg;
+ uint8_t writedev;
+ ndis_paddr_unit *addrarray;
+ uint32_t *arraysize;
+{
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ struct ndis_map_arg nma;
+ bus_dmamap_t map;
+ int error;
+
+ if (adapter == NULL)
+ return;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = (struct ndis_softc *)(block->nmb_ifp);
+
+ if (mapreg > sc->ndis_mmapcnt)
+ return;
+
+ map = sc->ndis_mmaps[mapreg];
+ nma.nma_fraglist = addrarray;
+
+ error = bus_dmamap_load(sc->ndis_mtag, map,
+ buf->nb_mappedsystemva, buf->nb_bytecount, ndis_map_cb,
+ (void *)&nma, BUS_DMA_NOWAIT);
+
+ if (error)
+ return;
+
+ bus_dmamap_sync(sc->ndis_mtag, map,
+ writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
+
+ *arraysize = nma.nma_cnt;
+
+ return;
+}
+
+__stdcall static void
+ndis_vtophys_unload(adapter, buf, mapreg)
+ ndis_handle adapter;
+ ndis_buffer *buf;
+ uint32_t mapreg;
+{
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ bus_dmamap_t map;
+
+ if (adapter == NULL)
+ return;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = (struct ndis_softc *)(block->nmb_ifp);
+
+ if (mapreg > sc->ndis_mmapcnt)
+ return;
+
+ map = sc->ndis_mmaps[mapreg];
+
+ bus_dmamap_sync(sc->ndis_mtag, map,
+ BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+
+ bus_dmamap_unload(sc->ndis_mtag, map);
+
+ return;
+}
+
+__stdcall static void
+ndis_create_timer(timer, handle, func, ctx)
+ ndis_miniport_timer *timer;
+ ndis_handle *handle;
+ ndis_timer_function func;
+ void *ctx;
+{
+ struct callout_handle *ch;
+
+ ch = (struct callout_handle *)&timer->nmt_dpc;
+ callout_handle_init(ch);
+ timer->nmt_timerfunc = func;
+ timer->nmt_timerctx = ctx;
+
+ return;
+}
+
+/*
+ * The driver's timer callout is __stdcall function, so we need this
+ * intermediate step.
+ */
+
+static void
+ndis_timercall(arg)
+ void *arg;
+{
+ ndis_miniport_timer *timer;
+ __stdcall ndis_timer_function timerfunc;
+
+ timer = arg;
+
+ timerfunc = timer->nmt_timerfunc;
+ timerfunc(NULL, timer->nmt_timerctx, NULL, NULL);
+
+ return;
+}
+
+/*
+ * Windows specifies timeouts in milliseconds. We specify timeouts
+ * in hz. Trying to compute a tenth of a second based on hz is tricky.
+ * so we approximate. Note that we abuse the dpc portion of the
+ * miniport timer structure to hold the UNIX callout handle.
+ */
+__stdcall static void
+ndis_set_timer(timer, msecs)
+ ndis_miniport_timer *timer;
+ uint32_t msecs;
+{
+ struct callout_handle *ch;
+ struct timeval tv;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = msecs * 1000;
+
+ ch = (struct callout_handle *)&timer->nmt_dpc;
+ timer->nmt_dpc.nk_sysarg2 = ndis_timercall;
+ *ch = timeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, (void *)timer,
+ tvtohz(&tv));
+
+ return;
+}
+
+static void
+ndis_tick(arg)
+ void *arg;
+{
+ ndis_miniport_timer *timer;
+ struct callout_handle *ch;
+ __stdcall ndis_timer_function timerfunc;
+ struct timeval tv;
+
+ timer = arg;
+
+ timerfunc = timer->nmt_timerfunc;
+ timerfunc(NULL, timer->nmt_timerctx, NULL, NULL);
+
+ /* Automatically reload timer. */
+
+ tv.tv_sec = 0;
+ tv.tv_usec = timer->nmt_ktimer.nk_period * 1000;
+ ch = (struct callout_handle *)&timer->nmt_dpc;
+ timer->nmt_dpc.nk_sysarg2 = ndis_tick;
+ *ch = timeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, timer,
+ tvtohz(&tv));
+
+ return;
+}
+
+__stdcall static void
+ndis_set_periodic_timer(timer, msecs)
+ ndis_miniport_timer *timer;
+ uint32_t msecs;
+{
+ struct callout_handle *ch;
+ struct timeval tv;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = msecs * 1000;
+
+ timer->nmt_ktimer.nk_period = msecs;
+ ch = (struct callout_handle *)&timer->nmt_dpc;
+ timer->nmt_dpc.nk_sysarg2 = ndis_tick;
+ *ch = timeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, timer,
+ tvtohz(&tv));
+
+ return;
+}
+
+__stdcall static void
+ndis_cancel_timer(timer, cancelled)
+ ndis_miniport_timer *timer;
+ uint8_t *cancelled;
+{
+ struct callout_handle *ch;
+
+ ch = (struct callout_handle *)&timer->nmt_dpc;
+ untimeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, timer, *ch);
+
+ return;
+}
+
+__stdcall static void
+ndis_query_resources(status, adapter, list, buflen)
+ ndis_status *status;
+ ndis_handle adapter;
+ ndis_resource_list *list;
+ uint32_t *buflen;
+{
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = (struct ndis_softc *)block->nmb_ifp;
+
+ *buflen = sizeof(ndis_resource_list) +
+ (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1));
+
+ bcopy((char *)block->nmb_rlist, (char *)list, *buflen);
+ *status = NDIS_STATUS_SUCCESS;
+ return;
+}
+
+__stdcall static ndis_status
+ndis_register_ioport(offset, adapter, port, numports)
+ void **offset;
+ ndis_handle adapter;
+ uint32_t port;
+ uint32_t numports;
+{
+ struct ndis_miniport_block *block;
+ struct ndis_softc *sc;
+
+ if (adapter == NULL)
+ return(NDIS_STATUS_FAILURE);
+
+ block = (ndis_miniport_block *)adapter;
+ sc = (struct ndis_softc *)(block->nmb_ifp);
+
+ if (sc->ndis_res_io == NULL)
+ return(NDIS_STATUS_FAILURE);
+
+ if (rman_get_size(sc->ndis_res_io) != numports)
+ return(NDIS_STATUS_INVALID_LENGTH);
+
+ *offset = (void *)rman_get_start(sc->ndis_res_io);
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+__stdcall static void
+ndis_deregister_ioport(adapter, port, numports, offset)
+ ndis_handle adapter;
+ uint32_t port;
+ uint32_t numports;
+ void *offset;
+{
+ return;
+}
+
+__stdcall static void
+ndis_read_netaddr(status, addr, addrlen, adapter)
+ ndis_status *status;
+ void **addr;
+ uint32_t *addrlen;
+ ndis_handle adapter;
+{
+ struct ndis_softc *sc;
+ ndis_miniport_block *block;
+ uint8_t empty[] = { 0, 0, 0, 0, 0, 0 };
+
+ block = (ndis_miniport_block *)adapter;
+ sc = (struct ndis_softc *)block->nmb_ifp;
+
+ if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0)
+ *status = NDIS_STATUS_FAILURE;
+ else {
+ *addr = sc->arpcom.ac_enaddr;
+ *addrlen = ETHER_ADDR_LEN;
+ *status = NDIS_STATUS_SUCCESS;
+ }
+
+ return;
+}
+
+__stdcall static ndis_status
+ndis_alloc_mapreg(adapter, dmachannel, dmasize, physmapneeded, maxmap)
+ ndis_handle adapter;
+ uint32_t dmachannel;
+ uint8_t dmasize;
+ uint32_t physmapneeded;
+ uint32_t maxmap;
+{
+ struct ndis_softc *sc;
+ ndis_miniport_block *block;
+ int error, i, nseg = NDIS_MAXSEG;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = (struct ndis_softc *)block->nmb_ifp;
+
+ sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded,
+ M_DEVBUF, M_NOWAIT|M_ZERO);
+
+ if (sc->ndis_mmaps == NULL)
+ return(NDIS_STATUS_RESOURCES);
+
+ error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
+ NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW,
+ NULL, NULL, &sc->ndis_mtag);
+
+ if (error) {
+ free(sc->ndis_mmaps, M_DEVBUF);
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ for (i = 0; i < physmapneeded; i++)
+ bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]);
+
+ sc->ndis_mmapcnt = physmapneeded;
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+__stdcall static void
+ndis_free_mapreg(adapter)
+ ndis_handle adapter;
+{
+ struct ndis_softc *sc;
+ ndis_miniport_block *block;
+ int i;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = (struct ndis_softc *)block->nmb_ifp;
+
+ for (i = 0; i < sc->ndis_mmapcnt; i++)
+ bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]);
+
+ free(sc->ndis_mmaps, M_DEVBUF);
+
+ bus_dma_tag_destroy(sc->ndis_mtag);
+
+ return;
+}
+
+static void
+ndis_mapshared_cb(arg, segs, nseg, error)
+ void *arg;
+ bus_dma_segment_t *segs;
+ int nseg;
+ int error;
+{
+ ndis_physaddr *p;
+
+ if (error || nseg > 1)
+ return;
+
+ p = arg;
+
+ p->np_quad = segs[0].ds_addr;
+
+ return;
+}
+
+/*
+ * This maps to bus_dmamem_alloc().
+ */
+__stdcall static void
+ndis_alloc_sharedmem(adapter, len, cached, vaddr, paddr)
+ ndis_handle adapter;
+ uint32_t len;
+ uint8_t cached;
+ void **vaddr;
+ ndis_physaddr *paddr;
+{
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ struct ndis_shmem *sh;
+ int error;
+
+ if (adapter == NULL)
+ return;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = (struct ndis_softc *)(block->nmb_ifp);
+
+ sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO);
+ if (sh == NULL)
+ return;
+
+ error = bus_dma_tag_create(sc->ndis_parent_tag, 64,
+ 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
+ NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL,
+ &sh->ndis_stag);
+
+ if (error) {
+ free(sh, M_DEVBUF);
+ return;
+ }
+
+ error = bus_dmamem_alloc(sh->ndis_stag, vaddr,
+ BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap);
+
+ if (error) {
+ bus_dma_tag_destroy(sh->ndis_stag);
+ free(sh, M_DEVBUF);
+ return;
+ }
+
+ error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr,
+ len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT);
+
+ if (error) {
+ bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap);
+ bus_dma_tag_destroy(sh->ndis_stag);
+ free(sh, M_DEVBUF);
+ return;
+ }
+
+ sh->ndis_saddr = *vaddr;
+ sh->ndis_next = sc->ndis_shlist;
+ sc->ndis_shlist = sh;
+
+ return;
+}
+
+__stdcall static void
+ndis_alloc_sharedmem_async(adapter, len, cached, ctx)
+ ndis_handle adapter;
+ uint32_t len;
+ uint8_t cached;
+ void *ctx;
+{
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ void *vaddr;
+ ndis_physaddr paddr;
+ __stdcall ndis_allocdone_handler donefunc;
+
+ if (adapter == NULL)
+ return;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = (struct ndis_softc *)(block->nmb_ifp);
+ donefunc = sc->ndis_chars.nmc_allocate_complete_func;
+
+ ndis_alloc_sharedmem(adapter, len, cached, &vaddr, &paddr);
+ donefunc(adapter, vaddr, &paddr, len, ctx);
+
+ return;
+}
+
+__stdcall static void
+ndis_free_sharedmem(adapter, len, cached, vaddr, paddr)
+ ndis_handle adapter;
+ uint32_t len;
+ uint8_t cached;
+ void *vaddr;
+ ndis_physaddr paddr;
+{
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ struct ndis_shmem *sh, *prev;
+
+ if (vaddr == NULL || adapter == NULL)
+ return;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = (struct ndis_softc *)(block->nmb_ifp);
+ sh = prev = sc->ndis_shlist;
+
+ while (sh) {
+ if (sh->ndis_saddr == vaddr)
+ break;
+ prev = sh;
+ sh = sh->ndis_next;
+ }
+
+ bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap);
+ bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap);
+ bus_dma_tag_destroy(sh->ndis_stag);
+
+ if (sh == sc->ndis_shlist)
+ sc->ndis_shlist = sh->ndis_next;
+ else
+ prev->ndis_next = sh->ndis_next;
+
+ free(sh, M_DEVBUF);
+
+ return;
+}
+
+__stdcall static ndis_status
+ndis_map_iospace(vaddr, adapter, paddr, len)
+ void **vaddr;
+ ndis_handle adapter;
+ ndis_physaddr paddr;
+ uint32_t len;
+{
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+
+ if (adapter == NULL)
+ return(NDIS_STATUS_FAILURE);
+
+ block = (ndis_miniport_block *)adapter;
+ sc = (struct ndis_softc *)(block->nmb_ifp);
+
+ if (sc->ndis_res_mem == NULL)
+ return(NDIS_STATUS_FAILURE);
+
+ *vaddr = (void *)rman_get_virtual(sc->ndis_res_mem);
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+__stdcall static void
+ndis_unmap_iospace(adapter, vaddr, len)
+ ndis_handle adapter;
+ void *vaddr;
+ uint32_t len;
+{
+ return;
+}
+
+__stdcall static uint32_t
+ndis_cachefill(void)
+{
+ return(128);
+}
+
+__stdcall static uint32_t
+ndis_dma_align(handle)
+ ndis_handle handle;
+{
+ return(128);
+}
+
+/*
+ * NDIS has two methods for dealing with NICs that support DMA.
+ * One is to just pass packets to the driver and let it call
+ * NdisMStartBufferPhysicalMapping() to map each buffer in the packet
+ * all by itself, and the other is to let the NDIS library handle the
+ * buffer mapping internally, and hand the driver an already populated
+ * scatter/gather fragment list. If the driver calls
+ * NdisMInitializeScatterGatherDma(), it wants to use the latter
+ * method.
+ */
+
+__stdcall static ndis_status
+ndis_init_sc_dma(adapter, is64, maxphysmap)
+ ndis_handle adapter;
+ uint8_t is64;
+ uint32_t maxphysmap;
+{
+ struct ndis_softc *sc;
+ ndis_miniport_block *block;
+ int error;
+
+ if (adapter == NULL)
+ return(NDIS_STATUS_FAILURE);
+ block = (ndis_miniport_block *)adapter;
+ sc = (struct ndis_softc *)block->nmb_ifp;
+
+ /* Don't do this twice. */
+ if (sc->ndis_sc == 1)
+ return(NDIS_STATUS_SUCCESS);
+
+ error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW,
+ NULL, NULL, &sc->ndis_ttag);
+
+ sc->ndis_sc = 1;
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+__stdcall static void
+ndis_alloc_packetpool(status, pool, descnum, protrsvdlen)
+ ndis_status *status;
+ ndis_handle *pool;
+ uint32_t descnum;
+ uint32_t protrsvdlen;
+{
+ ndis_packet *cur;
+ int i;
+
+ *pool = malloc(sizeof(ndis_packet) * (descnum + 1),
+ M_DEVBUF, M_NOWAIT|M_ZERO);
+
+ if (pool == NULL) {
+ *status = NDIS_STATUS_RESOURCES;
+ return;
+ }
+
+ cur = (ndis_packet *)*pool;
+ cur->np_private.npp_flags = 0x1; /* mark the head of the list */
+ for (i = 0; i < descnum; i++) {
+ cur->np_private.npp_head = (ndis_handle)(cur + 1);
+ cur++;
+ }
+
+ *status = NDIS_STATUS_SUCCESS;
+ return;
+}
+
+__stdcall static void
+ndis_ex_alloc_packetpool(status, pool, descnum, oflowdescnum, protrsvdlen)
+ ndis_status *status;
+ ndis_handle *pool;
+ uint32_t descnum;
+ uint32_t oflowdescnum;
+ uint32_t protrsvdlen;
+{
+ return(ndis_alloc_packetpool(status, pool,
+ descnum + oflowdescnum, protrsvdlen));
+}
+
+__stdcall static uint32_t
+ndis_packetpool_use(pool)
+ ndis_handle pool;
+{
+ ndis_packet *head;
+
+ head = (ndis_packet *)pool;
+
+ return(head->np_private.npp_count);
+}
+
+__stdcall static void
+ndis_free_packetpool(pool)
+ ndis_handle pool;
+{
+ free(pool, M_DEVBUF);
+ return;
+}
+
+__stdcall static void
+ndis_alloc_packet(status, packet, pool)
+ ndis_status *status;
+ ndis_packet **packet;
+ ndis_handle pool;
+{
+ ndis_packet *head, *pkt;
+
+ head = (ndis_packet *)pool;
+
+ if (head->np_private.npp_flags != 0x1) {
+ *status = NDIS_STATUS_FAILURE;
+ return;
+ }
+
+ pkt = (ndis_packet *)head->np_private.npp_head;
+
+ if (pkt == NULL) {
+ *status = NDIS_STATUS_RESOURCES;
+ return;
+ }
+
+ head->np_private.npp_head = pkt->np_private.npp_head;
+
+ pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL;
+ /* Save pointer to the pool. */
+ pkt->np_private.npp_pool = head;
+
+ /* Set the oob offset pointer. Lots of things expect this. */
+ pkt->np_private.npp_packetooboffset =
+ offsetof(ndis_packet, np_oob);
+
+ *packet = pkt;
+
+ head->np_private.npp_count++;
+ *status = NDIS_STATUS_SUCCESS;
+ return;
+}
+
+__stdcall static void
+ndis_release_packet(packet)
+ ndis_packet *packet;
+{
+ ndis_packet *head;
+
+ if (packet == NULL || packet->np_private.npp_pool == NULL)
+ return;
+
+ head = packet->np_private.npp_pool;
+ if (head->np_private.npp_flags != 0x1)
+ return;
+
+ packet->np_private.npp_head = head->np_private.npp_head;
+ head->np_private.npp_head = (ndis_buffer *)packet;
+ head->np_private.npp_count--;
+
+ return;
+}
+
+__stdcall static void
+ndis_unchain_headbuf(packet, buf)
+ ndis_packet *packet;
+ ndis_buffer **buf;
+{
+ ndis_packet_private *priv;
+
+ if (packet == NULL || buf == NULL)
+ return;
+
+ priv = &packet->np_private;
+
+ priv->npp_validcounts = FALSE;
+
+ if (priv->npp_head == priv->npp_tail) {
+ *buf = priv->npp_head;
+ priv->npp_head = priv->npp_tail = NULL;
+ } else {
+ *buf = priv->npp_head;
+ priv->npp_head = (*buf)->nb_next;
+ }
+
+ return;
+}
+
+/*
+ * The NDIS "buffer" manipulation functions are somewhat misnamed.
+ * They don't really allocate buffers: they allocate buffer mappings.
+ * The idea is you reserve a chunk of DMA-able memory using
+ * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer()
+ * to obtain the virtual address of the DMA-able region.
+ * ndis_alloc_bufpool() is analagous to bus_dma_tag_create().
+ */
+
+__stdcall static void
+ndis_alloc_bufpool(status, pool, descnum)
+ ndis_status *status;
+ ndis_handle *pool;
+ uint32_t descnum;
+{
+ ndis_buffer *cur;
+ int i;
+
+ *pool = malloc(sizeof(ndis_buffer) * (descnum + 1),
+ M_DEVBUF, M_NOWAIT|M_ZERO);
+
+ if (pool == NULL) {
+ *status = NDIS_STATUS_RESOURCES;
+ return;
+ }
+
+ cur = (ndis_buffer *)*pool;
+ cur->nb_flags = 0x1; /* mark the head of the list */
+ for (i = 0; i < descnum; i++) {
+ cur->nb_next = cur + 1;
+ cur++;
+ }
+
+ *status = NDIS_STATUS_SUCCESS;
+ return;
+}
+
+__stdcall static void
+ndis_free_bufpool(pool)
+ ndis_handle pool;
+{
+ free(pool, M_DEVBUF);
+ return;
+}
+
+/*
+ * This maps to a bus_dmamap_create() and bus_dmamap_load().
+ */
+__stdcall static void
+ndis_alloc_buf(status, buffer, pool, vaddr, len)
+ ndis_status *status;
+ ndis_buffer **buffer;
+ ndis_handle pool;
+ void *vaddr;
+ uint32_t len;
+{
+ ndis_buffer *head, *buf;
+
+ head = (ndis_buffer *)pool;
+ if (head->nb_flags != 0x1) {
+ *status = NDIS_STATUS_FAILURE;
+ return;
+ }
+
+ buf = head->nb_next;
+
+ if (buf == NULL) {
+ *status = NDIS_STATUS_RESOURCES;
+ return;
+ }
+
+ head->nb_next = buf->nb_next;
+
+ /* Save pointer to the pool. */
+ buf->nb_process = head;
+
+ buf->nb_mappedsystemva = vaddr;
+ buf->nb_size = len;
+ buf->nb_next = NULL;
+
+ *buffer = buf;
+
+ *status = NDIS_STATUS_SUCCESS;
+ return;
+}
+
+__stdcall static void
+ndis_release_buf(buf)
+ ndis_buffer *buf;
+{
+ ndis_buffer *head;
+
+ if (buf == NULL || buf->nb_process == NULL)
+ return;
+
+ head = buf->nb_process;
+
+ if (head->nb_flags != 0x1)
+ return;
+
+ buf->nb_next = head->nb_next;
+ head->nb_next = buf;
+
+ return;
+}
+
+/* Get the virtual address and length of a buffer */
+
+__stdcall static void
+ndis_query_buf(buf, vaddr, len)
+ ndis_buffer *buf;
+ void **vaddr;
+ uint32_t *len;
+{
+ *vaddr = buf->nb_mappedsystemva;
+ *len = buf->nb_bytecount;
+
+ return;
+}
+
+/* Same as above -- we don't care about the priority. */
+
+__stdcall static void
+ndis_query_buf_safe(buf, vaddr, len, prio)
+ ndis_buffer *buf;
+ void **vaddr;
+ uint32_t *len;
+ uint32_t prio;
+{
+ *vaddr = buf->nb_mappedsystemva;
+ *len = buf->nb_bytecount;
+
+ return;
+}
+
+__stdcall static void
+ndis_adjust_buflen(buf, len)
+ ndis_buffer *buf;
+ int len;
+{
+ if (buf->nb_bytecount > len)
+ return;
+ buf->nb_bytecount = len;
+
+ return;
+}
+
+__stdcall static uint32_t
+ndis_interlock_inc(addend)
+ uint32_t *addend;
+{
+ mtx_lock(&ndis_interlock);
+ *addend++;
+ mtx_unlock(&ndis_interlock);
+ return(*addend);
+}
+
+__stdcall static uint32_t
+ndis_interlock_dec(addend)
+ uint32_t *addend;
+{
+ mtx_lock(&ndis_interlock);
+ *addend--;
+ mtx_unlock(&ndis_interlock);
+ return(*addend);
+}
+
+__stdcall static void
+ndis_init_event(event)
+ ndis_event *event;
+{
+ event->ne_event.nk_header.dh_sigstate = FALSE;
+ return;
+}
+
+__stdcall static void
+ndis_set_event(event)
+ ndis_event *event;
+{
+ event->ne_event.nk_header.dh_sigstate = TRUE;
+ wakeup(event);
+ return;
+}
+
+__stdcall static void
+ndis_reset_event(event)
+ ndis_event *event;
+{
+ event->ne_event.nk_header.dh_sigstate = FALSE;
+ wakeup(event);
+ return;
+}
+
+__stdcall static uint8_t
+ndis_wait_event(event, msecs)
+ ndis_event *event;
+ uint32_t msecs;
+{
+ int error;
+ struct timeval tv;
+
+ if (event->ne_event.nk_header.dh_sigstate == TRUE)
+ return(TRUE);
+
+ tv.tv_sec = 0;
+ tv.tv_usec = msecs * 1000;
+
+ error = tsleep(event, PPAUSE|PCATCH, "ndis", tvtohz(&tv));
+
+ return(event->ne_event.nk_header.dh_sigstate);
+}
+
+__stdcall static ndis_status
+ndis_unicode2ansi(dstr, sstr)
+ ndis_ansi_string *dstr;
+ ndis_unicode_string *sstr;
+{
+ ndis_unicode_to_ascii(sstr->nus_buf, sstr->nus_len, &dstr->nas_buf);
+ dstr->nas_len = strlen(dstr->nas_buf);
+ printf ("unicode 2 ansi...\n");
+ return (NDIS_STATUS_SUCCESS);
+}
+
+__stdcall static ndis_status
+ndis_assign_pcirsrc(adapter, slot, list)
+ ndis_handle adapter;
+ uint32_t slot;
+ ndis_resource_list **list;
+{
+ ndis_miniport_block *block;
+
+ if (adapter == NULL || list == NULL)
+ return (NDIS_STATUS_FAILURE);
+
+ block = (ndis_miniport_block *)adapter;
+ *list = block->nmb_rlist;
+
+ printf ("assign PCI resources...\n");
+ return (NDIS_STATUS_SUCCESS);
+}
+
+__stdcall static ndis_status
+ndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode)
+ ndis_miniport_interrupt *intr;
+ ndis_handle adapter;
+ uint32_t ivec;
+ uint32_t ilevel;
+ uint8_t reqisr;
+ uint8_t shared;
+ ndis_interrupt_mode imode;
+{
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+__stdcall static void
+ndis_deregister_intr(intr)
+ ndis_miniport_interrupt *intr;
+{
+ return;
+}
+
+__stdcall static void
+ndis_register_shutdown(adapter, shutdownctx, shutdownfunc)
+ ndis_handle adapter;
+ void *shutdownctx;
+ ndis_shutdown_handler shutdownfunc;
+{
+ ndis_miniport_block *block;
+ ndis_miniport_characteristics *chars;
+ struct ndis_softc *sc;
+
+ if (adapter == NULL)
+ return;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = (struct ndis_softc *)block->nmb_ifp;
+ chars = &sc->ndis_chars;
+
+ chars->nmc_shutdown_handler = shutdownfunc;
+ chars->nmc_rsvd0 = shutdownctx;
+
+ return;
+}
+
+__stdcall static void
+ndis_deregister_shutdown(adapter)
+ ndis_handle adapter;
+{
+ ndis_miniport_block *block;
+ ndis_miniport_characteristics *chars;
+ struct ndis_softc *sc;
+
+ if (adapter == NULL)
+ return;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = (struct ndis_softc *)block->nmb_ifp;
+ chars = &sc->ndis_chars;
+
+ chars->nmc_shutdown_handler = NULL;
+ chars->nmc_rsvd0 = NULL;
+
+ return;
+}
+
+__stdcall static uint32_t
+ndis_numpages(buf)
+ ndis_buffer *buf;
+{
+ return(howmany(buf->nb_bytecount, PAGE_SIZE));
+}
+
+__stdcall static void
+ndis_query_bufoffset(buf, off, len)
+ ndis_buffer *buf;
+ uint32_t *off;
+ uint32_t *len;
+{
+ *off = (uint32_t)buf->nb_mappedsystemva & (PAGE_SIZE - 1);
+ *len = buf->nb_bytecount;
+
+ return;
+}
+
+__stdcall static void
+ndis_sleep(usecs)
+ uint32_t usecs;
+{
+ struct timeval tv;
+ uint32_t dummy;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = usecs;
+
+ tsleep(&dummy, PPAUSE|PCATCH, "ndis", tvtohz(&tv));
+ return;
+}
+
+__stdcall static uint32_t
+ndis_read_pccard_amem(handle, offset, buf, len)
+ ndis_handle handle;
+ uint32_t offset;
+ void *buf;
+ uint32_t len;
+{
+ struct ndis_softc *sc;
+ ndis_miniport_block *block;
+ bus_space_handle_t bh;
+ bus_space_tag_t bt;
+ char *dest;
+ int i;
+
+ if (handle == NULL)
+ return(0);
+
+ block = (ndis_miniport_block *)handle;
+ sc = (struct ndis_softc *)block->nmb_ifp;
+ dest = buf;
+
+ bh = rman_get_bushandle(sc->ndis_res_am);
+ bt = rman_get_bustag(sc->ndis_res_am);
+
+ for (i = 0; i < len; i++)
+ dest[i] = bus_space_read_1(bt, bh, (offset * 2) + (i * 2));
+
+ return(i);
+}
+
+__stdcall static uint32_t
+ndis_write_pccard_amem(handle, offset, buf, len)
+ ndis_handle handle;
+ uint32_t offset;
+ void *buf;
+ uint32_t len;
+{
+ struct ndis_softc *sc;
+ ndis_miniport_block *block;
+ bus_space_handle_t bh;
+ bus_space_tag_t bt;
+ char *src;
+ int i;
+
+ if (handle == NULL)
+ return(0);
+
+ block = (ndis_miniport_block *)handle;
+ sc = (struct ndis_softc *)block->nmb_ifp;
+ src = buf;
+
+ bh = rman_get_bushandle(sc->ndis_res_am);
+ bt = rman_get_bustag(sc->ndis_res_am);
+
+ for (i = 0; i < len; i++)
+ bus_space_write_1(bt, bh, (offset * 2) + (i * 2), src[i]);
+
+ return(i);
+}
+
+__stdcall static ndis_list_entry *
+ndis_insert_head(head, entry, lock)
+ ndis_list_entry *head;
+ ndis_list_entry *entry;
+ ndis_spin_lock *lock;
+{
+ ndis_list_entry *flink;
+
+ mtx_lock_spin((struct mtx *)lock->nsl_spinlock);
+ flink = head->nle_flink;
+ entry->nle_flink = flink;
+ entry->nle_blink = head;
+ flink->nle_blink = entry;
+ head->nle_flink = entry;
+ mtx_unlock_spin((struct mtx *)lock->nsl_spinlock);
+
+ return(flink);
+}
+
+__stdcall static ndis_list_entry *
+ndis_remove_head(head, lock)
+ ndis_list_entry *head;
+ ndis_spin_lock *lock;
+{
+ ndis_list_entry *flink;
+ ndis_list_entry *entry;
+
+ mtx_lock_spin((struct mtx *)lock->nsl_spinlock);
+ entry = head->nle_flink;
+ flink = entry->nle_flink;
+ head->nle_flink = flink;
+ flink->nle_blink = head;
+ mtx_unlock_spin((struct mtx *)lock->nsl_spinlock);
+
+ return(entry);
+}
+
+__stdcall static ndis_list_entry *
+ndis_insert_tail(head, entry, lock)
+ ndis_list_entry *head;
+ ndis_list_entry *entry;
+ ndis_spin_lock *lock;
+{
+ ndis_list_entry *blink;
+
+ mtx_lock_spin((struct mtx *)lock->nsl_spinlock);
+ blink = head->nle_blink;
+ entry->nle_flink = head;
+ entry->nle_blink = blink;
+ blink->nle_flink = entry;
+ head->nle_blink = entry;
+ mtx_unlock_spin((struct mtx *)lock->nsl_spinlock);
+
+ return(blink);
+}
+
+__stdcall static uint8_t
+ndis_sync_with_intr(intr, syncfunc, syncctx)
+ ndis_miniport_interrupt *intr;
+ void *syncfunc;
+ void *syncctx;
+{
+ __stdcall uint8_t (*sync)(void *);
+
+ if (syncfunc == NULL || syncctx == NULL)
+ return(0);
+
+ sync = syncfunc;
+ return(sync(syncctx));
+}
+
+__stdcall static void
+dummy()
+{
+ printf ("NDIS dummy called...\n");
+ return;
+}
+
+image_patch_table ndis_functbl[] = {
+ { "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr },
+ { "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async },
+ { "NdisInterlockedInsertHeadList", (FUNC)ndis_insert_head },
+ { "NdisInterlockedInsertTailList", (FUNC)ndis_insert_tail },
+ { "NdisInterlockedRemoveHeadList", (FUNC)ndis_remove_head },
+ { "NdisInitializeWrapper", (FUNC)ndis_initwrap },
+ { "NdisMRegisterMiniport", (FUNC)ndis_register_miniport },
+ { "NdisAllocateMemoryWithTag", (FUNC)ndis_malloc_withtag },
+ { "NdisAllocateMemory", (FUNC)ndis_malloc },
+ { "NdisMSetAttributesEx", (FUNC)ndis_setattr_ex },
+ { "NdisCloseConfiguration", (FUNC)ndis_close_cfg },
+ { "NdisReadConfiguration", (FUNC)ndis_read_cfg },
+ { "NdisOpenConfiguration", (FUNC)ndis_open_cfg },
+ { "NdisReleaseSpinLock", (FUNC)ndis_unlock },
+ { "NdisDprAcquireSpinLock", (FUNC)ndis_lock },
+ { "NdisDprReleaseSpinLock", (FUNC)ndis_unlock },
+ { "NdisAcquireSpinLock", (FUNC)ndis_lock },
+ { "NdisAllocateSpinLock", (FUNC)ndis_create_lock },
+ { "NdisFreeSpinLock", (FUNC)ndis_destroy_lock },
+ { "NdisFreeMemory", (FUNC)ndis_free },
+ { "NdisReadPciSlotInformation", (FUNC)ndis_read_pci },
+ { "NdisWritePciSlotInformation",(FUNC)ndis_write_pci },
+ { "NdisWriteErrorLogEntry", (FUNC)ndis_syslog },
+ { "NdisMStartBufferPhysicalMapping", (FUNC)ndis_vtophys_load },
+ { "NdisMCompleteBufferPhysicalMapping", (FUNC)ndis_vtophys_unload },
+ { "NdisMInitializeTimer", (FUNC)ndis_create_timer },
+ { "NdisSetTimer", (FUNC)ndis_set_timer },
+ { "NdisMCancelTimer", (FUNC)ndis_cancel_timer },
+ { "NdisMSetPeriodicTimer", (FUNC)ndis_set_periodic_timer },
+ { "NdisMQueryAdapterResources", (FUNC)ndis_query_resources },
+ { "NdisMRegisterIoPortRange", (FUNC)ndis_register_ioport },
+ { "NdisMDeregisterIoPortRange", (FUNC)ndis_deregister_ioport },
+ { "NdisReadNetworkAddress", (FUNC)ndis_read_netaddr },
+ { "NdisMAllocateMapRegisters", (FUNC)ndis_alloc_mapreg },
+ { "NdisMFreeMapRegisters", (FUNC)ndis_free_mapreg },
+ { "NdisMAllocateSharedMemory", (FUNC)ndis_alloc_sharedmem },
+ { "NdisMMapIoSpace", (FUNC)ndis_map_iospace },
+ { "NdisMUnmapIoSpace", (FUNC)ndis_unmap_iospace },
+ { "NdisGetCacheFillSize", (FUNC)ndis_cachefill },
+ { "NdisMGetDmaAlignment", (FUNC)ndis_dma_align },
+ { "NdisMInitializeScatterGatherDma", (FUNC)ndis_init_sc_dma },
+ { "NdisAllocatePacketPool", (FUNC)ndis_alloc_packetpool },
+ { "NdisAllocatePacketPoolEx", (FUNC)ndis_ex_alloc_packetpool },
+ { "NdisAllocatePacket", (FUNC)ndis_alloc_packet },
+ { "NdisFreePacket", (FUNC)ndis_release_packet },
+ { "NdisFreePacketPool", (FUNC)ndis_free_packetpool },
+ { "NdisAllocateBufferPool", (FUNC)ndis_alloc_bufpool },
+ { "NdisAllocateBuffer", (FUNC)ndis_alloc_buf },
+ { "NdisQueryBuffer", (FUNC)ndis_query_buf },
+ { "NdisQueryBufferSafe", (FUNC)ndis_query_buf_safe },
+ { "NdisFreeBuffer", (FUNC)ndis_release_buf },
+ { "NdisFreeBufferPool", (FUNC)ndis_free_bufpool },
+ { "NdisInterlockedIncrement", (FUNC)ndis_interlock_inc },
+ { "NdisInterlockedDecrement", (FUNC)ndis_interlock_dec },
+ { "NdisInitializeEvent", (FUNC)ndis_init_event },
+ { "NdisSetEvent", (FUNC)ndis_set_event },
+ { "NdisResetEvent", (FUNC)ndis_reset_event },
+ { "NdisWaitEvent", (FUNC)ndis_wait_event },
+ { "NdisUnicodeStringToAnsiString", (FUNC)ndis_unicode2ansi },
+ { "NdisMPciAssignResources", (FUNC)ndis_assign_pcirsrc },
+ { "NdisMFreeSharedMemory", (FUNC)ndis_free_sharedmem },
+ { "NdisMRegisterInterrupt", (FUNC)ndis_register_intr },
+ { "NdisMDeregisterInterrupt", (FUNC)ndis_deregister_intr },
+ { "NdisMRegisterAdapterShutdownHandler", (FUNC)ndis_register_shutdown },
+ { "NdisMDeregisterAdapterShutdownHandler", (FUNC)ndis_deregister_shutdown },
+ { "NDIS_BUFFER_TO_SPAN_PAGES", (FUNC)ndis_numpages },
+ { "NdisQueryBufferOffset", (FUNC)ndis_query_bufoffset },
+ { "NdisAdjustBufferLength", (FUNC)ndis_adjust_buflen },
+ { "NdisPacketPoolUsage", (FUNC)ndis_packetpool_use },
+ { "NdisMSleep", (FUNC)ndis_sleep },
+ { "NdisUnchainBufferAtFront", (FUNC)ndis_unchain_headbuf },
+ { "NdisReadPcmciaAttributeMemory", (FUNC)ndis_read_pccard_amem },
+ { "NdisWritePcmciaAttributeMemory", (FUNC)ndis_write_pccard_amem },
+
+ /*
+ * 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/compat/ndis/subr_ntoskrnl.c b/sys/compat/ndis/subr_ntoskrnl.c
new file mode 100644
index 000000000000..04399c750fd9
--- /dev/null
+++ b/sys/compat/ndis/subr_ntoskrnl.c
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2003
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <sys/callout.h>
+#include <sys/kernel.h>
+
+#include <machine/clock.h>
+#include <machine/bus_memio.h>
+#include <machine/bus_pio.h>
+#include <machine/bus.h>
+#include <machine/stdarg.h>
+
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <compat/ndis/pe_var.h>
+#include <compat/ndis/resource_var.h>
+#include <compat/ndis/ndis_var.h>
+#include <compat/ndis/ntoskrnl_var.h>
+
+#define __stdcall __attribute__((__stdcall__))
+#define FUNC void(*)(void)
+
+__stdcall static uint32_t ntoskrnl_unicode_equal(ndis_unicode_string *,
+ ndis_unicode_string *, uint32_t);
+__stdcall static void *ntoskrnl_iobuildsynchfsdreq(uint32_t, void *,
+ void *, uint32_t, uint32_t *, void *, void *);
+__stdcall static uint32_t ntoskrnl_iofcalldriver(void *, void *);
+__stdcall static uint32_t ntoskrnl_waitforobj(void *, uint32_t,
+ uint32_t, uint8_t, void *);
+__stdcall static void ntoskrnl_initevent(void *, uint32_t, uint8_t);
+__stdcall static void ntoskrnl_writereg_ushort(uint16_t *, uint16_t);
+__stdcall static uint16_t ntoskrnl_readreg_ushort(uint16_t *);
+__stdcall static void ntoskrnl_writereg_ulong(uint32_t *, uint32_t);
+__stdcall static uint32_t ntoskrnl_readreg_ulong(uint32_t *);
+__stdcall static void ntoskrnl_writereg_uchar(uint8_t *, uint8_t);
+__stdcall static uint8_t ntoskrnl_readreg_uchar(uint8_t *);
+__stdcall static int64_t _allmul(int64_t, int64_t);
+__stdcall static int64_t _alldiv(int64_t, int64_t);
+__stdcall static int64_t _allrem(int64_t, int64_t);
+__stdcall static int64_t _allshr(int64_t, int);
+__stdcall static int64_t _allshl(int64_t, int);
+__stdcall static uint64_t _aullmul(uint64_t, uint64_t);
+__stdcall static uint64_t _aulldiv(uint64_t, uint64_t);
+__stdcall static uint64_t _aullrem(uint64_t, uint64_t);
+__stdcall static uint64_t _aullshr(uint64_t, int);
+__stdcall static uint64_t _aullshl(uint64_t, int);
+__stdcall static void *ntoskrnl_allocfunc(uint32_t, size_t, uint32_t);
+__stdcall static void ntoskrnl_freefunc(void *);
+__stdcall static void ntoskrnl_init_lookaside(paged_lookaside_list *,
+ lookaside_alloc_func *, lookaside_free_func *,
+ uint32_t, size_t, uint32_t, uint16_t);
+__stdcall static void ntoskrnl_delete_lookaside(paged_lookaside_list *);
+__stdcall static void ntoskrnl_init_nplookaside(npaged_lookaside_list *,
+ lookaside_alloc_func *, lookaside_free_func *,
+ uint32_t, size_t, uint32_t, uint16_t);
+__stdcall static void ntoskrnl_delete_nplookaside(npaged_lookaside_list *);
+static slist_entry *ntoskrnl_push_slist(slist_entry *, slist_entry *);
+static slist_entry *ntoskrnl_pop_slist(slist_entry *);
+__stdcall static void dummy(void);
+
+static struct mtx ntoskrnl_interlock;
+static int ntoskrnl_inits = 0;
+
+int
+ntoskrnl_libinit()
+{
+ if (ntoskrnl_inits) {
+ ntoskrnl_inits++;
+ return(0);
+ }
+
+ mtx_init(&ntoskrnl_interlock, "ntoskrnllock", MTX_NETWORK_LOCK,
+ MTX_DEF | MTX_RECURSE);
+
+ ntoskrnl_inits++;
+ return(0);
+}
+
+int
+ntoskrnl_libfini()
+{
+ if (ntoskrnl_inits != 1) {
+ ntoskrnl_inits--;
+ return(0);
+ }
+
+ mtx_destroy(&ntoskrnl_interlock);
+ ntoskrnl_inits--;
+
+ return(0);
+}
+
+__stdcall static uint32_t
+ntoskrnl_unicode_equal(str1, str2, casesensitive)
+ ndis_unicode_string *str1;
+ ndis_unicode_string *str2;
+ uint32_t casesensitive;
+{
+ char *astr1 = NULL, *astr2 = NULL;
+ int rval = 1;
+
+ ndis_unicode_to_ascii(str1->nus_buf, str2->nus_len, &astr1);
+ ndis_unicode_to_ascii(str2->nus_buf, str2->nus_len, &astr2);
+
+ if (casesensitive)
+ rval = strcmp(astr1, astr2);
+#ifdef notdef
+ else
+ rval = strcasecmp(astr1, astr2);
+#endif
+
+ free(astr1, M_DEVBUF);
+ free(astr2, M_DEVBUF);
+
+ return(rval);
+}
+
+__stdcall static void *
+ntoskrnl_iobuildsynchfsdreq(func, dobj, buf, len, off, event, status)
+ uint32_t func;
+ void *dobj;
+ void *buf;
+ uint32_t len;
+ uint32_t *off;
+ void *event;
+ void *status;
+{
+ return(NULL);
+}
+
+__stdcall static uint32_t
+ntoskrnl_iofcalldriver(dobj, irp)
+ void *dobj;
+ void *irp;
+{
+ return(0);
+}
+
+__stdcall static uint32_t
+ntoskrnl_waitforobj(obj, reason, mode, alertable, timeout)
+ void *obj;
+ uint32_t reason;
+ uint32_t mode;
+ uint8_t alertable;
+ void *timeout;
+{
+ return(0);
+}
+
+__stdcall static void
+ntoskrnl_initevent(event, type, state)
+ void *event;
+ uint32_t type;
+ uint8_t state;
+{
+ return;
+}
+
+__stdcall static void
+ntoskrnl_writereg_ushort(reg, val)
+ uint16_t *reg;
+ uint16_t val;
+{
+ bus_space_write_2(I386_BUS_SPACE_MEM, 0x0, (uint32_t)reg, val);
+ return;
+}
+
+__stdcall static uint16_t
+ntoskrnl_readreg_ushort(reg)
+ uint16_t *reg;
+{
+ return(bus_space_read_2(I386_BUS_SPACE_MEM, 0x0, (uint32_t)reg));
+}
+
+__stdcall static void
+ntoskrnl_writereg_ulong(reg, val)
+ uint32_t *reg;
+ uint32_t val;
+{
+ bus_space_write_4(I386_BUS_SPACE_MEM, 0x0, (uint32_t)reg, val);
+ return;
+}
+
+__stdcall static uint32_t
+ntoskrnl_readreg_ulong(reg)
+ uint32_t *reg;
+{
+ return(bus_space_read_4(I386_BUS_SPACE_MEM, 0x0, (uint32_t)reg));
+}
+
+__stdcall static uint8_t
+ntoskrnl_readreg_uchar(reg)
+ uint8_t *reg;
+{
+ return(bus_space_read_1(I386_BUS_SPACE_MEM, 0x0, (uint32_t)reg));
+}
+
+__stdcall static void
+ntoskrnl_writereg_uchar(reg, val)
+ uint8_t *reg;
+ uint8_t val;
+{
+ bus_space_write_1(I386_BUS_SPACE_MEM, 0x0, (uint32_t)reg, val);
+ return;
+}
+
+__stdcall static int64_t
+_allmul(a, b)
+ int64_t a;
+ int64_t b;
+{
+ return (a * b);
+}
+
+__stdcall static int64_t
+_alldiv(a, b)
+ int64_t a;
+ int64_t b;
+{
+ return (a / b);
+}
+
+__stdcall static int64_t
+_allrem(a, b)
+ int64_t a;
+ int64_t b;
+{
+ return (a % b);
+}
+
+__stdcall static uint64_t
+_aullmul(a, b)
+ uint64_t a;
+ uint64_t b;
+{
+ return (a * b);
+}
+
+__stdcall static uint64_t
+_aulldiv(a, b)
+ uint64_t a;
+ uint64_t b;
+{
+ return (a / b);
+}
+
+__stdcall static uint64_t
+_aullrem(a, b)
+ uint64_t a;
+ uint64_t b;
+{
+ return (a % b);
+}
+
+__stdcall static int64_t
+_allshl(a, b)
+ int64_t a;
+ int b;
+{
+ return (a << b);
+}
+
+__stdcall static uint64_t
+_aullshl(a, b)
+ uint64_t a;
+ int b;
+{
+ return (a << b);
+}
+
+__stdcall static int64_t
+_allshr(a, b)
+ int64_t a;
+ int b;
+{
+ return (a >> b);
+}
+
+__stdcall static uint64_t
+_aullshr(a, b)
+ uint64_t a;
+ int b;
+{
+ return (a >> b);
+}
+
+__stdcall static void *
+ntoskrnl_allocfunc(pooltype, size, tag)
+ uint32_t pooltype;
+ size_t size;
+ uint32_t tag;
+{
+ return(malloc(size, M_DEVBUF, M_NOWAIT));
+}
+
+__stdcall static void
+ntoskrnl_freefunc(buf)
+ void *buf;
+{
+ free(buf, M_DEVBUF);
+}
+
+__stdcall static void
+ntoskrnl_init_lookaside(lookaside, allocfunc, freefunc,
+ flags, size, tag, depth)
+ paged_lookaside_list *lookaside;
+ lookaside_alloc_func *allocfunc;
+ lookaside_free_func *freefunc;
+ uint32_t flags;
+ size_t size;
+ uint32_t tag;
+ uint16_t depth;
+{
+ lookaside->nll_l.gl_size = size;
+ lookaside->nll_l.gl_tag = tag;
+ if (allocfunc == NULL)
+ lookaside->nll_l.gl_allocfunc = ntoskrnl_allocfunc;
+ else
+ lookaside->nll_l.gl_allocfunc = allocfunc;
+
+ if (freefunc == NULL)
+ lookaside->nll_l.gl_freefunc = ntoskrnl_freefunc;
+ else
+ lookaside->nll_l.gl_freefunc = freefunc;
+
+ return;
+}
+
+__stdcall static void
+ntoskrnl_delete_lookaside(lookaside)
+ paged_lookaside_list *lookaside;
+{
+ return;
+}
+
+__stdcall static void
+ntoskrnl_init_nplookaside(lookaside, allocfunc, freefunc,
+ flags, size, tag, depth)
+ npaged_lookaside_list *lookaside;
+ lookaside_alloc_func *allocfunc;
+ lookaside_free_func *freefunc;
+ uint32_t flags;
+ size_t size;
+ uint32_t tag;
+ uint16_t depth;
+{
+ lookaside->nll_l.gl_size = size;
+ lookaside->nll_l.gl_tag = tag;
+ if (allocfunc == NULL)
+ lookaside->nll_l.gl_allocfunc = ntoskrnl_allocfunc;
+ else
+ lookaside->nll_l.gl_allocfunc = allocfunc;
+
+ if (freefunc == NULL)
+ lookaside->nll_l.gl_freefunc = ntoskrnl_freefunc;
+ else
+ lookaside->nll_l.gl_freefunc = freefunc;
+
+ return;
+}
+
+__stdcall static void
+ntoskrnl_delete_nplookaside(lookaside)
+ npaged_lookaside_list *lookaside;
+{
+ return;
+}
+
+/*
+ * Note: the interlocked slist push and pop routines are
+ * declared to be _fastcall in Windows, which means they
+ * use the _cdecl calling convention here.
+ */
+static slist_entry *
+ntoskrnl_push_slist(head, entry)
+ slist_entry *head;
+ slist_entry *entry;
+{
+ slist_entry *oldhead;
+ mtx_lock(&ntoskrnl_interlock);
+ oldhead = head->sl_next;
+ entry->sl_next = head->sl_next;
+ head->sl_next = entry;
+ mtx_unlock(&ntoskrnl_interlock);
+ return(oldhead);
+}
+
+static slist_entry *
+ntoskrnl_pop_slist(head)
+ slist_entry *head;
+{
+ slist_entry *first;
+ mtx_lock(&ntoskrnl_interlock);
+ first = head->sl_next;
+ if (first != NULL)
+ head->sl_next = first->sl_next;
+ mtx_unlock(&ntoskrnl_interlock);
+ return(first);
+}
+
+__stdcall static void
+dummy()
+{
+ printf ("ntoskrnl dummy called...\n");
+ return;
+}
+
+
+image_patch_table ntoskrnl_functbl[] = {
+ { "RtlEqualUnicodeString", (FUNC)ntoskrnl_unicode_equal },
+ { "sprintf", (FUNC)sprintf },
+ { "DbgPrint", (FUNC)printf },
+ { "strncmp", (FUNC)strncmp },
+ { "strcmp", (FUNC)strcmp },
+ { "strncpy", (FUNC)strncpy },
+ { "strcpy", (FUNC)strcpy },
+ { "IofCallDriver", (FUNC)ntoskrnl_iofcalldriver },
+ { "IoBuildSynchronousFsdRequest", (FUNC)ntoskrnl_iobuildsynchfsdreq },
+ { "KeWaitForSingleObject", (FUNC)ntoskrnl_waitforobj },
+ { "KeInitializeEvent", (FUNC)ntoskrnl_initevent },
+ { "_allmul", (FUNC)_allmul },
+ { "_alldiv", (FUNC)_alldiv },
+ { "_allrem", (FUNC)_allrem },
+ { "_allshr", (FUNC)_allshr },
+ { "_allshl", (FUNC)_allshl },
+ { "_aullmul", (FUNC)_aullmul },
+ { "_aulldiv", (FUNC)_aulldiv },
+ { "_aullrem", (FUNC)_aullrem },
+ { "_aullushr", (FUNC)_aullshr },
+ { "_aullshl", (FUNC)_aullshl },
+ { "WRITE_REGISTER_USHORT", (FUNC)ntoskrnl_writereg_ushort },
+ { "READ_REGISTER_USHORT", (FUNC)ntoskrnl_readreg_ushort },
+ { "WRITE_REGISTER_ULONG", (FUNC)ntoskrnl_writereg_ulong },
+ { "READ_REGISTER_ULONG", (FUNC)ntoskrnl_readreg_ulong },
+ { "READ_REGISTER_UCHAR", (FUNC)ntoskrnl_readreg_uchar },
+ { "WRITE_REGISTER_UCHAR", (FUNC)ntoskrnl_writereg_uchar },
+ { "ExInitializePagedLookasideList", (FUNC)ntoskrnl_init_lookaside },
+ { "ExDeletePagedLookasideList", (FUNC)ntoskrnl_delete_lookaside },
+ { "ExInitializeNPagedLookasideList", (FUNC)ntoskrnl_init_nplookaside },
+ { "ExDeleteNPagedLookasideList", (FUNC)ntoskrnl_delete_nplookaside },
+ { "InterlockedPopEntrySList", (FUNC)ntoskrnl_pop_slist },
+ { "InterlockedPushEntrySList", (FUNC)ntoskrnl_push_slist },
+
+ /*
+ * 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/compat/ndis/subr_pe.c b/sys/compat/ndis/subr_pe.c
new file mode 100644
index 000000000000..8a2ae5b8b52b
--- /dev/null
+++ b/sys/compat/ndis/subr_pe.c
@@ -0,0 +1,537 @@
+/*
+ * Copyright (c) 2003
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * This file contains routines for relocating and dynamically linking
+ * executable object code files in the Windows(r) PE (Portable Executable)
+ * format. In Windows, anything with a .EXE, .DLL or .SYS extention is
+ * considered an executable, and all such files have some structures in
+ * common. The PE format was apparently based largely on COFF but has
+ * mutated significantly over time. We are mainly concerned with .SYS files,
+ * so this module implements only enough routines to be able to parse the
+ * headers and sections of a .SYS object file and perform the necessary
+ * relocations and jump table patching to allow us to call into it
+ * (and to have it call back to us). Note that while this module
+ * can handle fixups for imported symbols, it knows nothing about
+ * exporting them.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#ifdef _KERNEL
+#include <sys/systm.h>
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#endif
+
+#include <compat/ndis/pe_var.h>
+
+static u_int32_t pe_functbl_match(image_patch_table *, char *);
+
+/*
+ * Check for an MS-DOS executable header. All Windows binaries
+ * have a small MS-DOS executable prepended to them to print out
+ * the "This program requires Windows" message. Even .SYS files
+ * have this header, in spite of the fact that you're can't actually
+ * run them directly.
+ */
+
+int
+pe_get_dos_header(imgbase, hdr)
+ vm_offset_t imgbase;
+ image_dos_header *hdr;
+{
+ uint16_t signature;
+
+ if (imgbase == NULL || hdr == NULL)
+ return (EINVAL);
+
+ signature = *(uint16_t *)imgbase;
+ if (signature != IMAGE_DOS_SIGNATURE)
+ return (ENOEXEC);
+
+ bcopy ((char *)imgbase, (char *)hdr, sizeof(image_dos_header));
+
+ return(0);
+}
+
+/*
+ * Verify that this image has a Windows NT PE signature.
+ */
+
+int
+pe_is_nt_image(imgbase)
+ vm_offset_t imgbase;
+{
+ uint32_t signature;
+ image_dos_header *dos_hdr;
+
+ if (imgbase == NULL)
+ return (EINVAL);
+
+ signature = *(uint16_t *)imgbase;
+ if (signature == IMAGE_DOS_SIGNATURE) {
+ dos_hdr = (image_dos_header *)imgbase;
+ signature = *(uint32_t *)(imgbase + dos_hdr->idh_lfanew);
+ if (signature == IMAGE_NT_SIGNATURE)
+ return(0);
+ }
+
+ return(ENOEXEC);
+}
+
+/*
+ * Return a copy of the optional header. This contains the
+ * executable entry point and the directory listing which we
+ * need to find the relocations and imports later.
+ */
+
+int
+pe_get_optional_header(imgbase, hdr)
+ vm_offset_t imgbase;
+ image_optional_header *hdr;
+{
+ image_dos_header *dos_hdr;
+ image_nt_header *nt_hdr;
+
+ if (imgbase == NULL || hdr == NULL)
+ return(EINVAL);
+
+ if (pe_is_nt_image(imgbase))
+ return (EINVAL);
+
+ dos_hdr = (image_dos_header *)(imgbase);
+ nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
+
+ bcopy ((char *)&nt_hdr->inh_optionalhdr, (char *)hdr,
+ sizeof(image_optional_header));
+
+ return(0);
+}
+
+/*
+ * Return a copy of the file header. Contains the number of
+ * sections in this image.
+ */
+
+int
+pe_get_file_header(imgbase, hdr)
+ vm_offset_t imgbase;
+ image_file_header *hdr;
+{
+ image_dos_header *dos_hdr;
+ image_nt_header *nt_hdr;
+
+ if (imgbase == NULL || hdr == NULL)
+ return(EINVAL);
+
+ if (pe_is_nt_image(imgbase))
+ return (EINVAL);
+
+ dos_hdr = (image_dos_header *)imgbase;
+ nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
+
+ bcopy ((char *)&nt_hdr->inh_filehdr, (char *)hdr,
+ sizeof(image_file_header));
+
+ return(0);
+}
+
+/*
+ * Return the header of the first section in this image (usually
+ * .text).
+ */
+
+int
+pe_get_section_header(imgbase, hdr)
+ vm_offset_t imgbase;
+ image_section_header *hdr;
+{
+ image_dos_header *dos_hdr;
+ image_nt_header *nt_hdr;
+ image_section_header *sect_hdr;
+
+ if (imgbase == NULL || hdr == NULL)
+ return(EINVAL);
+
+ if (pe_is_nt_image(imgbase))
+ return (EINVAL);
+
+ dos_hdr = (image_dos_header *)imgbase;
+ nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
+ sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr +
+ sizeof(image_nt_header));
+
+ bcopy ((char *)sect_hdr, (char *)hdr, sizeof(image_section_header));
+
+ return(0);
+}
+
+/*
+ * Return the number of sections in this executable, or 0 on error.
+ */
+
+int
+pe_numsections(imgbase)
+ vm_offset_t imgbase;
+{
+ image_file_header file_hdr;
+
+ if (pe_get_file_header(imgbase, &file_hdr))
+ return(0);
+
+ return (file_hdr.ifh_numsections);
+}
+
+/*
+ * Return the base address that this image was linked for.
+ * This helps us calculate relocation addresses later.
+ */
+
+vm_offset_t
+pe_imagebase(imgbase)
+ vm_offset_t imgbase;
+{
+ image_optional_header optional_hdr;
+
+ if (pe_get_optional_header(imgbase, &optional_hdr))
+ return(0);
+
+ return (optional_hdr.ioh_imagebase);
+}
+
+/*
+ * Return the offset of a given directory structure within the
+ * image. Directories reside within sections.
+ */
+
+vm_offset_t
+pe_directory_offset(imgbase, diridx)
+ vm_offset_t imgbase;
+ uint32_t diridx;
+{
+ image_optional_header opt_hdr;
+ vm_offset_t dir;
+
+ if (pe_get_optional_header(imgbase, &opt_hdr))
+ return(0);
+
+ if (diridx >= opt_hdr.ioh_rva_size_cnt)
+ return(0);
+
+ dir = opt_hdr.ioh_datadir[diridx].idd_vaddr;
+
+ return(pe_translate_addr(imgbase, dir));
+}
+
+vm_offset_t
+pe_translate_addr(imgbase, rva)
+ vm_offset_t imgbase;
+ uint32_t rva;
+{
+ image_optional_header opt_hdr;
+ image_section_header *sect_hdr;
+ image_dos_header *dos_hdr;
+ image_nt_header *nt_hdr;
+ int i = 0, sections, fixedlen;
+
+ if (pe_get_optional_header(imgbase, &opt_hdr))
+ return(0);
+
+ sections = pe_numsections(imgbase);
+
+ dos_hdr = (image_dos_header *)imgbase;
+ nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
+ sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr +
+ sizeof(image_nt_header));
+
+ /*
+ * The test here is to see if the RVA falls somewhere
+ * inside the section, based on the section's start RVA
+ * and its length. However it seems sometimes the
+ * virtual length isn't enough to cover the entire
+ * area of the section. We fudge by taking into account
+ * the section alignment and rounding the section length
+ * up to a page boundary.
+ */
+ while (i++ < sections) {
+ fixedlen = sect_hdr->ish_misc.ish_vsize;
+ fixedlen += ((opt_hdr.ioh_sectalign - 1) -
+ sect_hdr->ish_misc.ish_vsize) &
+ (opt_hdr.ioh_sectalign - 1);
+ if (sect_hdr->ish_vaddr <= (u_int32_t)rva &&
+ (sect_hdr->ish_vaddr + fixedlen) >
+ (u_int32_t)rva)
+ break;
+ sect_hdr++;
+ }
+
+ if (i > sections)
+ return(0);
+
+ return((vm_offset_t)(imgbase + rva - sect_hdr->ish_vaddr +
+ sect_hdr->ish_rawdataaddr));
+}
+
+/*
+ * Get the section header for a particular section. Note that
+ * section names can be anything, but there are some standard
+ * ones (.text, .data, .rdata, .reloc).
+ */
+
+int
+pe_get_section(imgbase, hdr, name)
+ vm_offset_t imgbase;
+ image_section_header *hdr;
+ const char *name;
+{
+ image_dos_header *dos_hdr;
+ image_nt_header *nt_hdr;
+ image_section_header *sect_hdr;
+
+ int i, sections;
+
+ if (imgbase == NULL || hdr == NULL)
+ return(EINVAL);
+
+ if (pe_is_nt_image(imgbase))
+ return (EINVAL);
+
+ sections = pe_numsections(imgbase);
+
+ dos_hdr = (image_dos_header *)imgbase;
+ nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
+ sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr +
+ sizeof(image_nt_header));
+
+ for (i = 0; i < sections; i++) {
+ if (!strcmp ((char *)&sect_hdr->ish_name, name)) {
+ bcopy((char *)sect_hdr, (char *)hdr,
+ sizeof(image_section_header));
+ return(0);
+ } else
+ sect_hdr++;
+ }
+
+ return (ENOEXEC);
+}
+
+/*
+ * Apply the base relocations to this image. The relocation table
+ * resides within the .reloc section. Relocations are specified in
+ * blocks which refer to a particular page. We apply the relocations
+ * one page block at a time.
+ */
+
+int
+pe_relocate(imgbase)
+ vm_offset_t imgbase;
+{
+ image_section_header sect;
+ image_base_reloc *relhdr;
+ uint16_t rel, *sloc;
+ uint32_t base, delta, *lloc;
+ int i, count;
+ vm_offset_t txt;
+
+ base = pe_imagebase(imgbase);
+ pe_get_section(imgbase, &sect, ".text");
+ txt = pe_translate_addr(imgbase, sect.ish_vaddr);
+ delta = (uint32_t)(txt) - base - sect.ish_vaddr;
+
+ pe_get_section(imgbase, &sect, ".reloc");
+
+ relhdr = (image_base_reloc *)(imgbase + sect.ish_rawdataaddr);
+
+ do {
+ count = (relhdr->ibr_blocksize -
+ (sizeof(uint32_t) * 2)) / sizeof(uint16_t);
+ for (i = 0; i < count; i++) {
+ rel = relhdr->ibr_rel[i];
+ switch (IMR_RELTYPE(rel)) {
+ case IMAGE_REL_BASED_ABSOLUTE:
+ break;
+ case IMAGE_REL_BASED_HIGHLOW:
+ lloc = (uint32_t *)pe_translate_addr(imgbase,
+ relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
+ *lloc = pe_translate_addr(imgbase,
+ (*lloc - base));
+ break;
+ case IMAGE_REL_BASED_HIGH:
+ sloc = (uint16_t *)pe_translate_addr(imgbase,
+ relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
+ *sloc += (delta & 0xFFFF0000) >> 16;
+ break;
+ case IMAGE_REL_BASED_LOW:
+ sloc = (uint16_t *)pe_translate_addr(imgbase,
+ relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
+ *sloc += (delta & 0xFFFF);
+ break;
+ default:
+ printf ("[%d]reloc type: %d\n",i,
+ IMR_RELTYPE(rel));
+ break;
+ }
+ }
+ relhdr = (image_base_reloc *)((vm_offset_t)relhdr +
+ relhdr->ibr_blocksize);
+ } while (relhdr->ibr_blocksize);
+
+ return(0);
+}
+
+/*
+ * Return the import descriptor for a particular module. An image
+ * may be linked against several modules, typically HAL.dll, ntoskrnl.exe
+ * and NDIS.SYS. For each module, there is a list of imported function
+ * names and their addresses.
+ */
+
+int
+pe_get_import_descriptor(imgbase, desc, module)
+ vm_offset_t imgbase;
+ image_import_descriptor *desc;
+ char *module;
+{
+ vm_offset_t offset;
+ image_import_descriptor *imp_desc;
+ char *modname;
+
+ if (imgbase == NULL || module == NULL || desc == NULL)
+ return(EINVAL);
+
+ offset = pe_directory_offset(imgbase, IMAGE_DIRECTORY_ENTRY_IMPORT);
+ if (offset == 0)
+ return (ENOENT);
+
+ imp_desc = (void *)offset;
+
+ while (imp_desc->iid_nameaddr) {
+ modname = (char *)pe_translate_addr(imgbase,
+ imp_desc->iid_nameaddr);
+ if (!strncmp(module, modname, strlen(module))) {
+ bcopy((char *)imp_desc, (char *)desc,
+ sizeof(image_import_descriptor));
+ return(0);
+ }
+ imp_desc++;
+ }
+
+ return (ENOENT);
+}
+
+/*
+ * Find the function that matches a particular name. This doesn't
+ * need to be particularly speedy since it's only run when loading
+ * a module for the first time.
+ */
+
+static vm_offset_t
+pe_functbl_match(functbl, name)
+ image_patch_table *functbl;
+ char *name;
+{
+ image_patch_table *p;
+
+ if (functbl == NULL || name == NULL)
+ return(0);
+
+ p = functbl;
+
+ while (p->ipt_name != NULL) {
+ if (!strcmp(p->ipt_name, name))
+ return((uint32_t)p->ipt_func);
+ p++;
+ }
+ printf ("no match for %s\n", name);
+ return((vm_offset_t)p->ipt_func);
+}
+
+/*
+ * Patch the imported function addresses for a given module.
+ * The caller must specify the module name and provide a table
+ * of function pointers that will be patched into the jump table.
+ * Note that there are actually two copies of the jump table: one
+ * copy is left alone. In a .SYS file, the jump tables are usually
+ * merged into the INIT segment.
+ *
+ * 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.
+ */
+
+int
+pe_patch_imports(imgbase, module, functbl)
+ vm_offset_t imgbase;
+ char *module;
+ image_patch_table *functbl;
+{
+ image_import_descriptor imp_desc;
+ char *fname;
+ vm_offset_t *nptr, *fptr;
+ vm_offset_t func;
+
+ if (imgbase == NULL || module == NULL || functbl == NULL)
+ return(EINVAL);
+
+ if (pe_get_import_descriptor(imgbase, &imp_desc, module))
+ return(ENOEXEC);
+
+ nptr = (vm_offset_t *)pe_translate_addr(imgbase,
+ imp_desc.iid_import_name_table_addr);
+ fptr = (vm_offset_t *)pe_translate_addr(imgbase,
+ imp_desc.iid_import_address_table_addr);
+
+ while (nptr != NULL && pe_translate_addr(imgbase, *nptr) != NULL) {
+ fname = (char *)pe_translate_addr(imgbase, (*nptr) + 2);
+ func = pe_functbl_match(functbl, fname);
+ if (func)
+ *fptr = func;
+#ifdef notdef
+ if (*fptr == 0)
+ return(ENOENT);
+#endif
+ nptr++;
+ fptr++;
+ }
+
+ return(0);
+}