diff options
-rw-r--r-- | sys/compat/ndis/kern_ndis.c | 268 | ||||
-rw-r--r-- | sys/compat/ndis/kern_windrv.c | 416 | ||||
-rw-r--r-- | sys/compat/ndis/ndis_var.h | 15 | ||||
-rw-r--r-- | sys/compat/ndis/ntoskrnl_var.h | 171 | ||||
-rw-r--r-- | sys/compat/ndis/subr_hal.c | 25 | ||||
-rw-r--r-- | sys/compat/ndis/subr_ndis.c | 204 | ||||
-rw-r--r-- | sys/compat/ndis/subr_ntoskrnl.c | 588 | ||||
-rw-r--r-- | sys/conf/files.i386 | 1 | ||||
-rw-r--r-- | sys/dev/if_ndis/if_ndis.c | 112 | ||||
-rw-r--r-- | sys/dev/if_ndis/if_ndis_pccard.c | 17 | ||||
-rw-r--r-- | sys/dev/if_ndis/if_ndis_pci.c | 22 | ||||
-rw-r--r-- | sys/dev/if_ndis/if_ndisvar.h | 7 | ||||
-rw-r--r-- | sys/modules/ndis/Makefile | 1 | ||||
-rw-r--r-- | usr.sbin/ndiscvt/ndiscvt.c | 1 |
14 files changed, 1489 insertions, 359 deletions
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c index f6db9c7..f93bf4e 100644 --- a/sys/compat/ndis/kern_ndis.c +++ b/sys/compat/ndis/kern_ndis.c @@ -125,6 +125,7 @@ static struct ndisproc ndis_iproc; * collision with if_ndis.ko, which internally calls itself * 'ndis.' */ + static int ndis_modevent(module_t mod, int cmd, void *arg) { @@ -133,6 +134,7 @@ ndis_modevent(module_t mod, int cmd, void *arg) switch (cmd) { case MOD_LOAD: /* Initialize subsystems */ + windrv_libinit(); ndis_libinit(); ntoskrnl_libinit(); @@ -169,6 +171,7 @@ ndis_modevent(module_t mod, int cmd, void *arg) /* Shut down subsystems */ ndis_libfini(); ntoskrnl_libfini(); + windrv_libfini(); /* Remove zones */ uma_zdestroy(ndis_packet_zone); @@ -542,10 +545,14 @@ ndis_status_func(adapter, status, sbuf, slen) uint32_t slen; { ndis_miniport_block *block; - block = adapter; + struct ndis_softc *sc; + struct ifnet *ifp; - if (block->nmb_ifp->if_flags & IFF_DEBUG) - device_printf (block->nmb_dev, "status: %x\n", status); + block = adapter; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); + ifp = &sc->arpcom.ac_if; + if (ifp->if_flags & IFF_DEBUG) + device_printf (sc->ndis_dev, "status: %x\n", status); return; } @@ -554,10 +561,14 @@ ndis_statusdone_func(adapter) ndis_handle adapter; { ndis_miniport_block *block; + struct ndis_softc *sc; + struct ifnet *ifp; + block = adapter; - - if (block->nmb_ifp->if_flags & IFF_DEBUG) - device_printf (block->nmb_dev, "status complete\n"); + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); + ifp = &sc->arpcom.ac_if; + if (ifp->if_flags & IFF_DEBUG) + device_printf (sc->ndis_dev, "status complete\n"); return; } @@ -594,11 +605,16 @@ ndis_resetdone_func(adapter, status, addressingreset) uint8_t addressingreset; { ndis_miniport_block *block; + struct ndis_softc *sc; + struct ifnet *ifp; + block = adapter; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); + ifp = &sc->arpcom.ac_if; - if (block->nmb_ifp->if_flags & IFF_DEBUG) - device_printf (block->nmb_dev, "reset done...\n"); - wakeup(block->nmb_ifp); + if (ifp->if_flags & IFF_DEBUG) + device_printf (sc->ndis_dev, "reset done...\n"); + wakeup(ifp); return; } @@ -780,12 +796,12 @@ ndis_return(arg) p = arg; sc = p->np_softc; - adapter = sc->ndis_block.nmb_miniportadapterctx; + adapter = sc->ndis_block->nmb_miniportadapterctx; if (adapter == NULL) return; - returnfunc = sc->ndis_chars.nmc_return_packet_func; + returnfunc = sc->ndis_chars->nmc_return_packet_func; irql = KeRaiseIrql(DISPATCH_LEVEL); returnfunc(adapter, p); KeLowerIrql(irql); @@ -863,7 +879,7 @@ ndis_convert_res(arg) int error = 0; sc = arg; - block = &sc->ndis_block; + block = sc->ndis_block; dev = sc->ndis_dev; SLIST_INIT(&brl_rev); @@ -1129,25 +1145,25 @@ ndis_set_info(arg, oid, buf, buflen) sc = arg; NDIS_LOCK(sc); - setfunc = sc->ndis_chars.nmc_setinfo_func; - adapter = sc->ndis_block.nmb_miniportadapterctx; + setfunc = sc->ndis_chars->nmc_setinfo_func; + adapter = sc->ndis_block->nmb_miniportadapterctx; NDIS_UNLOCK(sc); if (adapter == NULL || setfunc == NULL) return(ENXIO); - KeAcquireSpinLock(&sc->ndis_block.nmb_lock, &irql); + KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql); rval = setfunc(adapter, oid, buf, *buflen, &byteswritten, &bytesneeded); - KeReleaseSpinLock(&sc->ndis_block.nmb_lock, irql); + KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql); if (rval == NDIS_STATUS_PENDING) { mtx_lock(&ndis_req_mtx); - error = msleep(&sc->ndis_block.nmb_setstat, + error = msleep(&sc->ndis_block->nmb_setstat, &ndis_req_mtx, curthread->td_priority|PDROP, "ndisset", 5 * hz); - rval = sc->ndis_block.nmb_setstat; + rval = sc->ndis_block->nmb_setstat; } if (byteswritten) @@ -1188,11 +1204,11 @@ ndis_send_packets(arg, packets, cnt) uint8_t irql; sc = arg; - adapter = sc->ndis_block.nmb_miniportadapterctx; + adapter = sc->ndis_block->nmb_miniportadapterctx; if (adapter == NULL) return(ENXIO); - sendfunc = sc->ndis_chars.nmc_sendmulti_func; - senddonefunc = sc->ndis_block.nmb_senddone_func; + sendfunc = sc->ndis_chars->nmc_sendmulti_func; + senddonefunc = sc->ndis_block->nmb_senddone_func; irql = KeRaiseIrql(DISPATCH_LEVEL); sendfunc(adapter, packets, cnt); KeLowerIrql(irql); @@ -1207,7 +1223,7 @@ ndis_send_packets(arg, packets, cnt) */ if (p == NULL || p->np_oob.npo_status == NDIS_STATUS_PENDING) continue; - senddonefunc(&sc->ndis_block, p, p->np_oob.npo_status); + senddonefunc(sc->ndis_block, p, p->np_oob.npo_status); } return(0); @@ -1226,11 +1242,11 @@ ndis_send_packet(arg, packet) uint8_t irql; sc = arg; - adapter = sc->ndis_block.nmb_miniportadapterctx; + adapter = sc->ndis_block->nmb_miniportadapterctx; if (adapter == NULL) return(ENXIO); - sendfunc = sc->ndis_chars.nmc_sendsingle_func; - senddonefunc = sc->ndis_block.nmb_senddone_func; + sendfunc = sc->ndis_chars->nmc_sendsingle_func; + senddonefunc = sc->ndis_block->nmb_senddone_func; irql = KeRaiseIrql(DISPATCH_LEVEL); status = sendfunc(adapter, packet, packet->np_private.npp_flags); @@ -1239,7 +1255,7 @@ ndis_send_packet(arg, packet) if (status == NDIS_STATUS_PENDING) return(0); - senddonefunc(&sc->ndis_block, packet, status); + senddonefunc(sc->ndis_block, packet, status); return(0); } @@ -1315,8 +1331,8 @@ ndis_reset_nic(arg) sc = arg; ifp = &sc->arpcom.ac_if; NDIS_LOCK(sc); - adapter = sc->ndis_block.nmb_miniportadapterctx; - resetfunc = sc->ndis_chars.nmc_reset_func; + adapter = sc->ndis_block->nmb_miniportadapterctx; + resetfunc = sc->ndis_chars->nmc_reset_func; NDIS_UNLOCK(sc); if (adapter == NULL || resetfunc == NULL) return(EIO); @@ -1347,7 +1363,7 @@ ndis_halt_nic(arg) ifp = &sc->arpcom.ac_if; NDIS_LOCK(sc); - adapter = sc->ndis_block.nmb_miniportadapterctx; + adapter = sc->ndis_block->nmb_miniportadapterctx; if (adapter == NULL) { NDIS_UNLOCK(sc); return(EIO); @@ -1359,13 +1375,13 @@ ndis_halt_nic(arg) * halt handler has been called. */ - haltfunc = sc->ndis_chars.nmc_halt_func; + haltfunc = sc->ndis_chars->nmc_halt_func; NDIS_UNLOCK(sc); haltfunc(adapter); NDIS_LOCK(sc); - sc->ndis_block.nmb_miniportadapterctx = NULL; + sc->ndis_block->nmb_miniportadapterctx = NULL; NDIS_UNLOCK(sc); return(0); @@ -1381,19 +1397,19 @@ ndis_shutdown_nic(arg) sc = arg; NDIS_LOCK(sc); - adapter = sc->ndis_block.nmb_miniportadapterctx; - shutdownfunc = sc->ndis_chars.nmc_shutdown_handler; + adapter = sc->ndis_block->nmb_miniportadapterctx; + shutdownfunc = sc->ndis_chars->nmc_shutdown_handler; NDIS_UNLOCK(sc); if (adapter == NULL || shutdownfunc == NULL) return(EIO); - if (sc->ndis_chars.nmc_rsvd0 == NULL) + if (sc->ndis_chars->nmc_rsvd0 == NULL) shutdownfunc(adapter); else - shutdownfunc(sc->ndis_chars.nmc_rsvd0); + shutdownfunc(sc->ndis_chars->nmc_rsvd0); ndis_shrink_thrqueue(8); - TAILQ_REMOVE(&ndis_devhead, &sc->ndis_block, link); + TAILQ_REMOVE(&ndis_devhead, sc->ndis_block, link); return(0); } @@ -1414,8 +1430,8 @@ ndis_init_nic(arg) sc = arg; NDIS_LOCK(sc); - block = &sc->ndis_block; - initfunc = sc->ndis_chars.nmc_init_func; + block = sc->ndis_block; + initfunc = sc->ndis_chars->nmc_init_func; NDIS_UNLOCK(sc); TAILQ_INIT(&block->nmb_timerlist); @@ -1433,7 +1449,7 @@ ndis_init_nic(arg) */ if (status != NDIS_STATUS_SUCCESS) { NDIS_LOCK(sc); - sc->ndis_block.nmb_miniportadapterctx = NULL; + sc->ndis_block->nmb_miniportadapterctx = NULL; NDIS_UNLOCK(sc); return(ENXIO); } @@ -1450,8 +1466,8 @@ ndis_enable_intr(arg) __stdcall ndis_enable_interrupts_handler intrenbfunc; sc = arg; - adapter = sc->ndis_block.nmb_miniportadapterctx; - intrenbfunc = sc->ndis_chars.nmc_enable_interrupts_func; + adapter = sc->ndis_block->nmb_miniportadapterctx; + intrenbfunc = sc->ndis_chars->nmc_enable_interrupts_func; if (adapter == NULL || intrenbfunc == NULL) return; intrenbfunc(adapter); @@ -1468,10 +1484,8 @@ ndis_disable_intr(arg) __stdcall ndis_disable_interrupts_handler intrdisfunc; sc = arg; - NDIS_LOCK(sc); - adapter = sc->ndis_block.nmb_miniportadapterctx; - intrdisfunc = sc->ndis_chars.nmc_disable_interrupts_func; - NDIS_UNLOCK(sc); + adapter = sc->ndis_block->nmb_miniportadapterctx; + intrdisfunc = sc->ndis_chars->nmc_disable_interrupts_func; if (adapter == NULL || intrdisfunc == NULL) return; intrdisfunc(adapter); @@ -1494,8 +1508,8 @@ ndis_isr(arg, ourintr, callhandler) return(EINVAL); sc = arg; - adapter = sc->ndis_block.nmb_miniportadapterctx; - isrfunc = sc->ndis_chars.nmc_isr_func; + adapter = sc->ndis_block->nmb_miniportadapterctx; + isrfunc = sc->ndis_chars->nmc_isr_func; if (adapter == NULL || isrfunc == NULL) return(ENXIO); @@ -1519,8 +1533,8 @@ ndis_intrhand(arg) sc = arg; NDIS_LOCK(sc); - adapter = sc->ndis_block.nmb_miniportadapterctx; - intrfunc = sc->ndis_chars.nmc_interrupt_func; + adapter = sc->ndis_block->nmb_miniportadapterctx; + intrfunc = sc->ndis_chars->nmc_interrupt_func; NDIS_UNLOCK(sc); if (adapter == NULL || intrfunc == NULL) return(EINVAL); @@ -1547,27 +1561,27 @@ ndis_get_info(arg, oid, buf, buflen) sc = arg; NDIS_LOCK(sc); - queryfunc = sc->ndis_chars.nmc_queryinfo_func; - adapter = sc->ndis_block.nmb_miniportadapterctx; + queryfunc = sc->ndis_chars->nmc_queryinfo_func; + adapter = sc->ndis_block->nmb_miniportadapterctx; NDIS_UNLOCK(sc); if (adapter == NULL || queryfunc == NULL) return(ENXIO); - KeAcquireSpinLock(&sc->ndis_block.nmb_lock, &irql); + KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql); rval = queryfunc(adapter, oid, buf, *buflen, &byteswritten, &bytesneeded); - KeReleaseSpinLock(&sc->ndis_block.nmb_lock, irql); + KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql); /* Wait for requests that block. */ if (rval == NDIS_STATUS_PENDING) { mtx_lock(&ndis_req_mtx); - error = msleep(&sc->ndis_block.nmb_getstat, + error = msleep(&sc->ndis_block->nmb_getstat, &ndis_req_mtx, curthread->td_priority|PDROP, "ndisget", 5 * hz); - rval = sc->ndis_block.nmb_getstat; + rval = sc->ndis_block->nmb_getstat; } if (byteswritten) @@ -1592,96 +1606,39 @@ ndis_get_info(arg, oid, buf, buflen) return(0); } -int -ndis_unload_driver(arg) - void *arg; +__stdcall uint32_t +NdisAddDevice(drv, pdo) + driver_object *drv; + device_object *pdo; { + device_object *fdo; + ndis_miniport_block *block; struct ndis_softc *sc; + uint32_t status; - sc = arg; - - free(sc->ndis_block.nmb_rlist, M_DEVBUF); - - ndis_flush_sysctls(sc); - - ndis_shrink_thrqueue(8); - TAILQ_REMOVE(&ndis_devhead, &sc->ndis_block, link); - - return(0); -} - -#define NDIS_LOADED htonl(0x42534F44) - -int -ndis_load_driver(img, arg) - vm_offset_t img; - void *arg; -{ - driver_entry entry; - image_optional_header opt_hdr; - image_import_descriptor imp_desc; - ndis_unicode_string dummystr; - ndis_miniport_block *block; - ndis_status status; - int idx; - uint32_t *ptr; - struct ndis_softc *sc; - - sc = arg; + status = IoCreateDevice(drv, sizeof(ndis_miniport_block), NULL, + FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo); - /* - * Only perform the relocation/linking phase once - * since the binary image may be shared among multiple - * device instances. - */ - - ptr = (uint32_t *)(img + 8); - if (*ptr != NDIS_LOADED) { - /* Perform text relocation */ - if (pe_relocate(img)) - return(ENOEXEC); - - /* Dynamically link the NDIS.SYS routines -- required. */ - if (pe_patch_imports(img, "NDIS", ndis_functbl)) - return(ENOEXEC); - - /* Dynamically link the HAL.dll routines -- also required. */ - if (pe_patch_imports(img, "HAL", hal_functbl)) - return(ENOEXEC); - - /* Dynamically link ntoskrnl.exe -- optional. */ - if (pe_get_import_descriptor(img, - &imp_desc, "ntoskrnl") == 0) { - if (pe_patch_imports(img, - "ntoskrnl", ntoskrnl_functbl)) - return(ENOEXEC); - } - *ptr = NDIS_LOADED; - } + if (status != STATUS_SUCCESS) + return(status); - /* Locate the driver entry point */ - pe_get_optional_header(img, &opt_hdr); - entry = (driver_entry)pe_translate_addr(img, opt_hdr.ioh_entryaddr); - - dummystr.nus_len = strlen(NDIS_DUMMY_PATH) * 2; - dummystr.nus_maxlen = strlen(NDIS_DUMMY_PATH) * 2; - dummystr.nus_buf = NULL; - ndis_ascii_to_unicode(NDIS_DUMMY_PATH, &dummystr.nus_buf); + block = fdo->do_devext; + block->nmb_deviceobj = fdo; + block->nmb_physdeviceobj = pdo; + block->nmb_nextdeviceobj = IoAttachDeviceToDeviceStack(fdo, pdo); + KeInitializeSpinLock(&block->nmb_lock); /* - * 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; + * Stash pointers to the miniport block and miniport + * characteristics info in the if_ndis softc so the + * UNIX wrapper driver can get to them later. + */ - ptr = (uint32_t *)block; - for (idx = 0; idx < sizeof(ndis_miniport_block) / 4; idx++) { - *ptr = idx | 0xdead0000; - ptr++; - } + sc = device_get_softc(pdo->do_devext); + sc->ndis_block = block; + sc->ndis_chars = IoGetDriverObjectExtension(drv, (void *)1); + + /* Finish up BSD-specific setup. */ block->nmb_signature = (void *)0xcafebabe; block->nmb_setdone_func = ndis_setdone_func; @@ -1691,27 +1648,32 @@ ndis_load_driver(img, arg) block->nmb_resetdone_func = ndis_resetdone_func; block->nmb_sendrsrc_func = ndis_sendrsrcavail_func; - block->nmb_ifp = &sc->arpcom.ac_if; - block->nmb_dev = sc->ndis_dev; - block->nmb_img = img; - block->nmb_devobj.do_rsvd = block; + ndis_enlarge_thrqueue(8); - /* - * Now call the DriverEntry() routine. This will cause - * a callout to the NdisInitializeWrapper() and - * NdisMRegisterMiniport() routines. - */ - status = entry(&block->nmb_devobj, &dummystr); + TAILQ_INSERT_TAIL(&ndis_devhead, block, link); - free (dummystr.nus_buf, M_DEVBUF); + return (STATUS_SUCCESS); +} - if (status != NDIS_STATUS_SUCCESS) - return(ENODEV); +int +ndis_unload_driver(arg) + void *arg; +{ + struct ndis_softc *sc; + device_object *fdo; - ndis_enlarge_thrqueue(8); + sc = arg; - TAILQ_INSERT_TAIL(&ndis_devhead, block, link); - KeInitializeSpinLock(&block->nmb_lock); + free(sc->ndis_block->nmb_rlist, M_DEVBUF); + + ndis_flush_sysctls(sc); + + ndis_shrink_thrqueue(8); + TAILQ_REMOVE(&ndis_devhead, sc->ndis_block, link); + + fdo = sc->ndis_block->nmb_deviceobj; + IoDetachDevice(sc->ndis_block->nmb_nextdeviceobj); + IoDeleteDevice(fdo); return(0); } diff --git a/sys/compat/ndis/kern_windrv.c b/sys/compat/ndis/kern_windrv.c new file mode 100644 index 0000000..f298b99 --- /dev/null +++ b/sys/compat/ndis/kern_windrv.c @@ -0,0 +1,416 @@ +/*- + * Copyright (c) 2005 + * Bill Paul <wpaul@windriver.com>. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/unistd.h> +#include <sys/types.h> + +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/module.h> +#include <sys/conf.h> +#include <sys/mbuf.h> +#include <sys/bus.h> + +#include <sys/queue.h> + +#include <compat/ndis/pe_var.h> +#include <compat/ndis/cfg_var.h> +#include <compat/ndis/resource_var.h> +#include <compat/ndis/ntoskrnl_var.h> +#include <compat/ndis/ndis_var.h> +#include <compat/ndis/hal_var.h> + +struct windrv_type { + uint16_t windrv_vid; /* for PCI or USB */ + uint16_t windrv_did; /* for PCI or USB */ + uint32_t windrv_subsys; /* for PCI */ + char *windrv_vname; /* for pccard */ + char *windrv_dname; /* for pccard */ + char *windrv_name; /* for pccard, PCI or USB */ +}; + +struct drvdb_ent { + driver_object *windrv_object; + struct windrv_type *windrv_devlist; + ndis_cfg *windrv_regvals; + STAILQ_ENTRY(drvdb_ent) link; +}; + +struct mtx drvdb_mtx; +static STAILQ_HEAD(drvdb, drvdb_ent) drvdb_head; + +static driver_object fake_pci_driver; /* serves both PCI and cardbus */ +static driver_object fake_pccard_driver; + + +#define DUMMY_REGISTRY_PATH "\\\\some\\bogus\\path" + +int +windrv_libinit(void) +{ + STAILQ_INIT(&drvdb_head); + mtx_init(&drvdb_mtx, "Windows driver DB lock", + "Windows internal lock", MTX_DEF); + + /* + * PCI and pccard devices don't need to use IRPs to + * interact with their bus drivers (usually), so our + * emulated PCI and pccard drivers are just stubs. + * USB devices, on the other hand, do all their I/O + * by exchanging IRPs with the USB bus driver, so + * for that we need to provide emulator dispatcher + * routines, which are in a separate module. + */ + + windrv_bus_attach(&fake_pci_driver, "PCI Bus"); + windrv_bus_attach(&fake_pccard_driver, "PCCARD Bus"); + + return(0); +} + +int +windrv_libfini(void) +{ + struct drvdb_ent *d; + + mtx_lock(&drvdb_mtx); + while(STAILQ_FIRST(&drvdb_head) != NULL) { + d = STAILQ_FIRST(&drvdb_head); + STAILQ_REMOVE_HEAD(&drvdb_head, link); + free(d, M_DEVBUF); + } + mtx_unlock(&drvdb_mtx); + + free(fake_pci_driver.dro_drivername.us_buf, M_DEVBUF); + free(fake_pccard_driver.dro_drivername.us_buf, M_DEVBUF); + + mtx_destroy(&drvdb_mtx); + return(0); +} + +/* + * Given the address of a driver image, find its corresponding + * driver_object. + */ + +driver_object * +windrv_lookup(img) + vm_offset_t img; +{ + struct drvdb_ent *d; + + mtx_lock(&drvdb_mtx); + STAILQ_FOREACH(d, &drvdb_head, link) { + if (d->windrv_object->dro_driverstart == (void *)img) { + mtx_unlock(&drvdb_mtx); + return(d->windrv_object); + } + } + mtx_unlock(&drvdb_mtx); + + return(NULL); +} + +/* + * Remove a driver_object from our datatabase and destroy it. Throw + * away any custom driver extension info that may have been added. + */ + +int +windrv_unload(mod, img, len) + module_t mod; + vm_offset_t img; + int len; +{ + struct drvdb_ent *d, *r = NULL; + driver_object *drv; + list_entry *e, *c; + + mtx_lock(&drvdb_mtx); + STAILQ_FOREACH(d, &drvdb_head, link) { + if (d->windrv_object->dro_driverstart == (void *)img) { + r = d; + STAILQ_REMOVE(&drvdb_head, d, drvdb_ent, link); + break; + } + } + mtx_unlock(&drvdb_mtx); + + if (r == NULL) + return (ENOENT); + + /* + * Destroy any custom extensions that may have been added. + */ + drv = r->windrv_object; + e = drv->dro_driverext->dre_usrext.nle_flink; + while (e != &drv->dro_driverext->dre_usrext) { + c = e->nle_flink; + REMOVE_LIST_HEAD((&drv->dro_driverext->dre_usrext)); + ExFreePool(c); + e = e->nle_flink; + } + + /* Free the driver extension */ + free(drv->dro_driverext, M_DEVBUF); + + /* Free the driver name */ + free(drv->dro_drivername.us_buf, M_DEVBUF); + + /* Free driver object */ + free(drv, M_DEVBUF); + + /* Free our DB handle */ + free(r, M_DEVBUF); + + return(0); +} + +/* + * Loader routine for actual Windows driver modules, ultimately + * calls the driver's DriverEntry() routine. + */ + +int +windrv_load(mod, img, len) + module_t mod; + vm_offset_t img; + int len; +{ + image_import_descriptor imp_desc; + image_optional_header opt_hdr; + driver_entry entry; + struct drvdb_ent *new; + struct driver_object *dobj; + int status; + + /* + * First step: try to relocate and dynalink the executable + * driver image. + */ + + /* 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); + } + + /* Dynamically link USBD.SYS -- optional */ +#ifdef notyet + if (pe_get_import_descriptor(img, &imp_desc, "USBD") == 0) { + if (pe_patch_imports(img, "USBD", ntoskrnl_functbl)) + return(ENOEXEC); + } +#endif + + /* Next step: find the driver entry point. */ + + pe_get_optional_header(img, &opt_hdr); + entry = (driver_entry)pe_translate_addr(img, opt_hdr.ioh_entryaddr); + + /* Next step: allocate and store a driver object. */ + + new = malloc(sizeof(struct drvdb_ent), M_DEVBUF, M_NOWAIT); + if (new == NULL) + return (ENOMEM); + + dobj = malloc(sizeof(device_object), M_DEVBUF, M_NOWAIT|M_ZERO); + if (dobj == NULL) { + free (new, M_DEVBUF); + return (ENOMEM); + } + + /* Allocate a driver extension structure too. */ + + dobj->dro_driverext = malloc(sizeof(driver_extension), + M_DEVBUF, M_NOWAIT|M_ZERO); + + if (dobj->dro_driverext == NULL) { + free(new, M_DEVBUF); + free(dobj, M_DEVBUF); + return(ENOMEM); + } + + INIT_LIST_HEAD((&dobj->dro_driverext->dre_usrext)); + + dobj->dro_driverstart = (void *)img; + dobj->dro_driversize = len; + + dobj->dro_drivername.us_len = strlen(DUMMY_REGISTRY_PATH) * 2; + dobj->dro_drivername.us_maxlen = strlen(DUMMY_REGISTRY_PATH) * 2; + dobj->dro_drivername.us_buf = NULL; + ndis_ascii_to_unicode(DUMMY_REGISTRY_PATH, + &dobj->dro_drivername.us_buf); + + new->windrv_object = dobj; + + /* Now call the DriverEntry() function. */ + + status = entry(dobj, &dobj->dro_drivername); + + if (status != STATUS_SUCCESS) { + free(dobj->dro_drivername.us_buf, M_DEVBUF); + free(dobj, M_DEVBUF); + free(new, M_DEVBUF); + return(ENODEV); + } + + mtx_lock(&drvdb_mtx); + STAILQ_INSERT_HEAD(&drvdb_head, new, link); + mtx_unlock(&drvdb_mtx); + + return (0); +} + +/* + * Make a new Physical Device Object for a device that was + * detected/plugged in. For us, the PDO is just a way to + * get at the device_t. + */ + +int +windrv_create_pdo(drv, bsddev) + driver_object *drv; + device_t bsddev; +{ + device_object *dev; + + /* + * This is a new physical device object, which technically + * is the "top of the stack." Consequently, we don't do + * an IoAttachDeviceToDeviceStack() here. + */ + + mtx_lock(&drvdb_mtx); + IoCreateDevice(drv, 0, NULL, FILE_DEVICE_UNKNOWN, 0, FALSE, &dev); + mtx_unlock(&drvdb_mtx); + + /* Stash pointer to our BSD device handle. */ + + dev->do_devext = bsddev; + + return(STATUS_SUCCESS); +} + +void +windrv_destroy_pdo(drv, bsddev) + driver_object *drv; + device_t bsddev; +{ + device_object *pdo; + + pdo = windrv_find_pdo(drv, bsddev); + + /* Remove reference to device_t */ + + pdo->do_devext = NULL; + + mtx_lock(&drvdb_mtx); + IoDeleteDevice(pdo); + mtx_unlock(&drvdb_mtx); + + return; +} + +/* + * Given a device_t, find the corresponding PDO in a driver's + * device list. + */ + +device_object * +windrv_find_pdo(drv, bsddev) + driver_object *drv; + device_t bsddev; +{ + device_object *pdo; + + mtx_lock(&drvdb_mtx); + pdo = drv->dro_devobj; + if (pdo->do_devext != bsddev) { + mtx_unlock(&drvdb_mtx); + panic("PDO wasn't first device in list"); + } + mtx_unlock(&drvdb_mtx); + + return(pdo); +} + +/* + * Add an internally emulated driver to the database. We need this + * to set up an emulated bus driver so that it can receive IRPs. + */ + +int +windrv_bus_attach(drv, name) + driver_object *drv; + char *name; +{ + struct drvdb_ent *new; + + new = malloc(sizeof(struct drvdb_ent), M_DEVBUF, M_NOWAIT); + if (new == NULL) + return (ENOMEM); + + drv->dro_drivername.us_len = strlen(name) * 2; + drv->dro_drivername.us_maxlen = strlen(name) * 2; + drv->dro_drivername.us_buf = NULL; + ndis_ascii_to_unicode(name, &drv->dro_drivername.us_buf); + + new->windrv_object = drv; + new->windrv_devlist = NULL; + new->windrv_regvals = NULL; + + mtx_lock(&drvdb_mtx); + STAILQ_INSERT_HEAD(&drvdb_head, new, link); + mtx_unlock(&drvdb_mtx); + + return(0); +} diff --git a/sys/compat/ndis/ndis_var.h b/sys/compat/ndis/ndis_var.h index 8761abb..b4eaf5a 100644 --- a/sys/compat/ndis/ndis_var.h +++ b/sys/compat/ndis/ndis_var.h @@ -751,6 +751,7 @@ struct ndis_ansi_string { typedef struct ndis_ansi_string ndis_ansi_string; +#ifdef notdef /* * 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 @@ -761,9 +762,10 @@ struct ndis_unicode_string { uint16_t nus_maxlen; uint16_t *nus_buf; }; - typedef struct ndis_unicode_string ndis_unicode_string; +#endif +typedef unicode_string ndis_unicode_string; enum ndis_parm_type { ndis_parm_int, @@ -1398,11 +1400,11 @@ struct ndis_miniport_block { void *nmb_resetdone_func; ndis_medium nmb_medium; uint32_t nmb_busnum; - uint32_t nmb_bustye; + uint32_t nmb_bustype; uint32_t nmb_adaptertype; - void *nmb_deviceobj; - void *nmb_physdeviceobj; - void *nmb_nextdeviceobj; + device_object *nmb_deviceobj; /* Functional device */ + device_object *nmb_physdeviceobj; /* Physical device */ + device_object *nmb_nextdeviceobj; /* Next dev in stack */ void *nmb_mapreg; void *nmb_callmgraflist; void *nmb_miniportthread; @@ -1480,7 +1482,7 @@ typedef void (*ndis_allocdone_handler)(ndis_handle, void *, ndis_physaddr *, uint32_t, void *); typedef uint8_t (*ndis_checkforhang_handler)(ndis_handle); -typedef __stdcall ndis_status (*driver_entry)(void *, ndis_unicode_string *); +typedef __stdcall ndis_status (*driver_entry)(void *, unicode_string *); extern image_patch_table ndis_functbl[]; @@ -1529,6 +1531,7 @@ extern int ndis_thsuspend(struct proc *, int); extern void ndis_thresume(struct proc *); extern int ndis_strcasecmp(const char *, const char *); extern int ndis_strncasecmp(const char *, const char *, size_t); +__stdcall extern uint32_t NdisAddDevice(driver_object *, device_object *); __END_DECLS #endif /* _NDIS_VAR_H_ */ diff --git a/sys/compat/ndis/ntoskrnl_var.h b/sys/compat/ndis/ntoskrnl_var.h index bc1f5f3..f1c0766 100644 --- a/sys/compat/ndis/ntoskrnl_var.h +++ b/sys/compat/ndis/ntoskrnl_var.h @@ -194,7 +194,7 @@ struct list_entry { typedef struct list_entry list_entry; #define INIT_LIST_HEAD(l) \ - l->nle_flink = l->nle_blink = l + (l)->nle_flink = (l)->nle_blink = (l) #define REMOVE_LIST_ENTRY(e) \ do { \ @@ -236,8 +236,8 @@ typedef struct list_entry list_entry; b = l->nle_blink; \ e->nle_flink = l; \ e->nle_blink = b; \ - b->nle_flink = e; \ - l->nle_blink = e; \ + b->nle_flink = (e); \ + l->nle_blink = (e); \ } while (0) #define INSERT_LIST_HEAD(l, e) \ @@ -498,10 +498,25 @@ struct driver_extension { void *dre_adddevicefunc; uint32_t dre_reinitcnt; unicode_string dre_srvname; + + /* + * Drivers are allowed to add one or more custom extensions + * to the driver object, but there's no special pointer + * for them. Hang them off here for now. + */ + + list_entry dre_usrext; }; typedef struct driver_extension driver_extension; +struct custom_extension { + list_entry ce_list; + void *ce_clid; +}; + +typedef struct custom_extension custom_extension; + /* * In Windows, there are Physical Device Objects (PDOs) and * Functional Device Objects (FDOs). Physical Device Objects are @@ -522,7 +537,7 @@ struct device_object { uint16_t do_type; uint16_t do_size; uint32_t do_refcnt; - struct device_object *do_drvobj; + struct driver_object *do_drvobj; struct device_object *do_nextdev; struct device_object *do_attacheddev; struct irp *do_currirp; @@ -531,6 +546,7 @@ struct device_object { uint32_t do_characteristics; void *do_vpb; void *do_devext; + uint32_t do_devtype; uint8_t do_stacksize; union { list_entry do_listent; @@ -714,6 +730,8 @@ struct io_status_block { } u; register_t isb_info; }; +#define isb_status u.isb_status +#define isb_ptr u.isb_ptr typedef struct io_status_block io_status_block; @@ -736,6 +754,9 @@ struct kapc { typedef struct kapc kapc; +typedef __stdcall uint32_t (*completion_func)(device_object *, + struct irp *, void *); + struct io_stack_location { uint8_t isl_major; uint8_t isl_minor; @@ -763,7 +784,7 @@ struct io_stack_location { void *isl_devobj; void *isl_fileobj; - void *isl_completionfunc; + completion_func isl_completionfunc; void *isl_completionctx; }; @@ -797,7 +818,7 @@ struct irp { uint8_t irp_apcenv; uint8_t irp_allocflags; io_status_block *irp_usriostat; - nt_kevent irp_userevent; + nt_kevent *irp_usrevent; union { struct { void *irp_apcfunc; @@ -839,12 +860,22 @@ struct irp { typedef struct irp irp; +#define IoSizeOfIrp(ssize) \ + ((uint16_t) (sizeof(irp) + ((ssize) * (sizeof(io_stack_location))))) + + #define IoGetCurrentIrpStackLocation(irp) \ (irp)->irp_tail.irp_overlay.irp_csl #define IoGetNextIrpStackLocation(irp) \ ((irp)->irp_tail.irp_overlay.irp_csl - 1) +#define IoSetNextIrpStackLocation(irp) \ + do { \ + irp->irp_currentstackloc--; \ + irp->irp_tail.irp_overlay.irp_csl--; \ + } while(0) + #define IoSetCompletionRoutine(irp, func, ctx, ok, err, cancel) \ do { \ io_stack_location *s; \ @@ -852,17 +883,14 @@ typedef struct irp irp; s->isl_completionfunc = (func); \ s->isl_completionctx = (ctx); \ s->isl_ctl = 0; \ - if (ok) irp->ctl = SL_INVOKE_ON_SUCCESS; \ - if (err) irp->ctl |= SL_INVOKE_ON_ERROR; \ - if (cancel) irp->ctl |= SL_INVOKE_ON_CANCEL; \ + if (ok) s->isl_ctl = SL_INVOKE_ON_SUCCESS; \ + if (err) s->isl_ctl |= SL_INVOKE_ON_ERROR; \ + if (cancel) s->isl_ctl |= SL_INVOKE_ON_CANCEL; \ } while(0) #define IoMarkIrpPending(irp) \ IoGetCurrentIrpStackLocation(irp)->isl_ctl |= SL_PENDING_RETURNED -#define IoSizeOfIrp(s) \ - ((uint16_t) (sizeof(itp) + ((s) * (sizeof(io_stack_location))))) - #define IoCopyCurrentIrpStackLocationToNext(irp) \ do { \ io_stack_location *src, *dst; \ @@ -878,7 +906,7 @@ typedef struct irp irp; (irp)->irp_tail.irp_overlay.irp_csl++; \ } while(0) -typedef uint32_t (*driver_dispatch)(device_object *, irp *); +typedef __stdcall uint32_t (*driver_dispatch)(device_object *, irp *); /* * The driver_object is allocated once for each driver that's loaded @@ -898,14 +926,14 @@ struct driver_object { void *dro_driverstart; uint32_t dro_driversize; void *dro_driversection; - driver_extension dro_driverext; + driver_extension *dro_driverext; unicode_string dro_drivername; unicode_string *dro_hwdb; void *dro_pfastiodispatch; void *dro_driverinitfunc; void *dro_driverstartiofunc; void *dro_driverunloadfunc; - void *dro_dispatch[IRP_MJ_MAXIMUM_FUNCTION + 1]; + driver_dispatch dro_dispatch[IRP_MJ_MAXIMUM_FUNCTION + 1]; }; typedef struct driver_object driver_object; @@ -931,6 +959,81 @@ typedef struct driver_object driver_object; #define DEVPROP_INSTALL_STATE 0x00000012 #define DEVPROP_REMOVAL_POLICY 0x00000013 +/* Various supported device types (used with IoCreateDevice()) */ + +#define FILE_DEVICE_BEEP 0x00000001 +#define FILE_DEVICE_CD_ROM 0x00000002 +#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003 +#define FILE_DEVICE_CONTROLLER 0x00000004 +#define FILE_DEVICE_DATALINK 0x00000005 +#define FILE_DEVICE_DFS 0x00000006 +#define FILE_DEVICE_DISK 0x00000007 +#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008 +#define FILE_DEVICE_FILE_SYSTEM 0x00000009 +#define FILE_DEVICE_INPORT_PORT 0x0000000A +#define FILE_DEVICE_KEYBOARD 0x0000000B +#define FILE_DEVICE_MAILSLOT 0x0000000C +#define FILE_DEVICE_MIDI_IN 0x0000000D +#define FILE_DEVICE_MIDI_OUT 0x0000000E +#define FILE_DEVICE_MOUSE 0x0000000F +#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010 +#define FILE_DEVICE_NAMED_PIPE 0x00000011 +#define FILE_DEVICE_NETWORK 0x00000012 +#define FILE_DEVICE_NETWORK_BROWSER 0x00000013 +#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014 +#define FILE_DEVICE_NULL 0x00000015 +#define FILE_DEVICE_PARALLEL_PORT 0x00000016 +#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017 +#define FILE_DEVICE_PRINTER 0x00000018 +#define FILE_DEVICE_SCANNER 0x00000019 +#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001A +#define FILE_DEVICE_SERIAL_PORT 0x0000001B +#define FILE_DEVICE_SCREEN 0x0000001C +#define FILE_DEVICE_SOUND 0x0000001D +#define FILE_DEVICE_STREAMS 0x0000001E +#define FILE_DEVICE_TAPE 0x0000001F +#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020 +#define FILE_DEVICE_TRANSPORT 0x00000021 +#define FILE_DEVICE_UNKNOWN 0x00000022 +#define FILE_DEVICE_VIDEO 0x00000023 +#define FILE_DEVICE_VIRTUAL_DISK 0x00000024 +#define FILE_DEVICE_WAVE_IN 0x00000025 +#define FILE_DEVICE_WAVE_OUT 0x00000026 +#define FILE_DEVICE_8042_PORT 0x00000027 +#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028 +#define FILE_DEVICE_BATTERY 0x00000029 +#define FILE_DEVICE_BUS_EXTENDER 0x0000002A +#define FILE_DEVICE_MODEM 0x0000002B +#define FILE_DEVICE_VDM 0x0000002C +#define FILE_DEVICE_MASS_STORAGE 0x0000002D +#define FILE_DEVICE_SMB 0x0000002E +#define FILE_DEVICE_KS 0x0000002F +#define FILE_DEVICE_CHANGER 0x00000030 +#define FILE_DEVICE_SMARTCARD 0x00000031 +#define FILE_DEVICE_ACPI 0x00000032 +#define FILE_DEVICE_DVD 0x00000033 +#define FILE_DEVICE_FULLSCREEN_VIDEO 0x00000034 +#define FILE_DEVICE_DFS_FILE_SYSTEM 0x00000035 +#define FILE_DEVICE_DFS_VOLUME 0x00000036 +#define FILE_DEVICE_SERENUM 0x00000037 +#define FILE_DEVICE_TERMSRV 0x00000038 +#define FILE_DEVICE_KSEC 0x00000039 +#define FILE_DEVICE_FIPS 0x0000003A + +/* Device characteristics */ + +#define FILE_REMOVABLE_MEDIA 0x00000001 +#define FILE_READ_ONLY_DEVICE 0x00000002 +#define FILE_FLOPPY_DISKETTE 0x00000004 +#define FILE_WRITE_ONCE_MEDIA 0x00000008 +#define FILE_REMOTE_DEVICE 0x00000010 +#define FILE_DEVICE_IS_MOUNTED 0x00000020 +#define FILE_VIRTUAL_VOLUME 0x00000040 +#define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080 +#define FILE_DEVICE_SECURE_OPEN 0x00000100 + +/* Status codes */ + #define STATUS_SUCCESS 0x00000000 #define STATUS_USER_APC 0x000000C0 #define STATUS_KERNEL_APC 0x00000100 @@ -938,12 +1041,25 @@ typedef struct driver_object driver_object; #define STATUS_TIMEOUT 0x00000102 #define STATUS_INVALID_PARAMETER 0xC000000D #define STATUS_INVALID_DEVICE_REQUEST 0xC0000010 +#define STATUS_MORE_PROCESSING_REQUIRED 0xC0000016 #define STATUS_BUFFER_TOO_SMALL 0xC0000023 #define STATUS_MUTANT_NOT_OWNED 0xC0000046 #define STATUS_INVALID_PARAMETER_2 0xC00000F0 +#define STATUS_INSUFFICIENT_RESOURCES 0xC000009A #define STATUS_WAIT_0 0x00000000 +/* Memory pool types, for ExAllocatePoolWithTag() */ + +#define NonPagedPool 0x00000000 +#define PagedPool 0x00000001 +#define NonPagedPoolMustSucceed 0x00000002 +#define DontUseThisType 0x00000003 +#define NonPagedPoolCacheAligned 0x00000004 +#define PagedPoolCacheAligned 0x00000005 +#define NonPagedPoolCacheAlignedMustS 0x00000006 +#define MaxPoolType 0x00000007 + /* * FreeBSD's kernel stack is 2 pages in size by default. The * Windows stack is larger, so we need to give our threads more @@ -954,6 +1070,16 @@ typedef struct driver_object driver_object; extern image_patch_table ntoskrnl_functbl[]; __BEGIN_DECLS +extern int windrv_libinit(void); +extern int windrv_libfini(void); +extern driver_object *windrv_lookup(vm_offset_t); +extern int windrv_load(module_t, vm_offset_t, int); +extern int windrv_unload(module_t, vm_offset_t, int); +extern int windrv_create_pdo(driver_object *, device_t); +extern void windrv_destroy_pdo(driver_object *, device_t); +extern device_object *windrv_find_pdo(driver_object *, device_t); +extern int windrv_bus_attach(driver_object *, char *); + extern int ntoskrnl_libinit(void); extern int ntoskrnl_libfini(void); __stdcall extern void KeInitializeDpc(kdpc *, void *, void *); @@ -962,8 +1088,7 @@ __stdcall extern uint8_t KeRemoveQueueDpc(kdpc *); __stdcall extern void KeInitializeTimer(ktimer *); __stdcall extern void KeInitializeTimerEx(ktimer *, uint32_t); __stdcall extern uint8_t KeSetTimer(ktimer *, int64_t, kdpc *); -__stdcall extern uint8_t KeSetTimerEx(ktimer *, int64_t, - uint32_t, kdpc *); +__stdcall extern uint8_t KeSetTimerEx(ktimer *, int64_t, uint32_t, kdpc *); __stdcall extern uint8_t KeCancelTimer(ktimer *); __stdcall extern uint8_t KeReadStateTimer(ktimer *); __stdcall extern uint32_t KeWaitForSingleObject(nt_dispatch_header *, uint32_t, @@ -976,8 +1101,20 @@ __stdcall extern uint32_t KeResetEvent(nt_kevent *); __fastcall extern void KefAcquireSpinLockAtDpcLevel(REGARGS1(kspin_lock *)); __fastcall extern void KefReleaseSpinLockFromDpcLevel(REGARGS1(kspin_lock *)); __stdcall extern void KeInitializeSpinLock(kspin_lock *); +__stdcall extern void *ExAllocatePoolWithTag(uint32_t, size_t, uint32_t); +__stdcall extern void ExFreePool(void *); +__stdcall extern uint32_t IoAllocateDriverObjectExtension(driver_object *, + void *, uint32_t, void **); +__stdcall extern void *IoGetDriverObjectExtension(driver_object *, void *); +__stdcall extern uint32_t IoCreateDevice(driver_object *, uint32_t, + unicode_string *, uint32_t, uint32_t, uint8_t, device_object **); +__stdcall extern void IoDeleteDevice(device_object *); +__stdcall extern device_object *IoGetAttachedDevice(device_object *); __fastcall extern uint32_t IofCallDriver(REGARGS2(device_object *, irp *)); __fastcall extern void IofCompleteRequest(REGARGS2(irp *, uint8_t)); +__stdcall extern void IoDetachDevice(device_object *); +__stdcall extern device_object *IoAttachDeviceToDeviceStack(device_object *, + device_object *); #define IoCallDriver(a, b) FASTCALL2(IofCallDriver, a, b) #define IoCompleteRequest(a, b) FASTCALL2(IofCompleteRequest, a, b) diff --git a/sys/compat/ndis/subr_hal.c b/sys/compat/ndis/subr_hal.c index 81dcade..b72613c 100644 --- a/sys/compat/ndis/subr_hal.c +++ b/sys/compat/ndis/subr_hal.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include <sys/mutex.h> #include <sys/proc.h> #include <sys/sched.h> +#include <sys/module.h> #include <sys/systm.h> #include <machine/clock.h> @@ -223,13 +224,19 @@ READ_PORT_BUFFER_UCHAR(port, val, cnt) * until the current thread lowers the IRQL to something less than * DISPATCH_LEVEL. * - * In FreeBSD, ISRs run in interrupt threads, so to duplicate the - * Windows notion of IRQLs, we use the following rules: + * There's another commonly used IRQL in Windows, which is APC_LEVEL. + * An APC is an Asynchronous Procedure Call, which differs from a DPC + * (Defered Procedure Call) in that a DPC is queued up to run in + * another thread, while an APC runs in the thread that scheduled + * it (similar to a signal handler in a UNIX process). We don't + * actually support the notion of APCs in FreeBSD, so for now, the + * only IRQLs we're interested in are DISPATCH_LEVEL and PASSIVE_LEVEL. * - * PASSIVE_LEVEL == normal kernel thread priority - * DISPATCH_LEVEL == lowest interrupt thread priotity (PI_SOFT) - * DEVICE_LEVEL == highest interrupt thread priority (PI_REALTIME) - * HIGH_LEVEL == interrupts disabled (critical_enter()) + * To simulate DISPATCH_LEVEL, we raise the current thread's priority + * to PI_REALTIME, which is the highest we can give it. This should, + * if I understand things correctly, prevent anything except for an + * interrupt thread from preempting us. PASSIVE_LEVEL is basically + * everything else. * * Be aware that, at least on the x86 arch, the Windows spinlock * functions are divided up in peculiar ways. The actual spinlock @@ -306,6 +313,9 @@ KfRaiseIrql(REGARGS1(uint8_t irql)) mtx_lock_spin(&sched_lock); oldirql = curthread->td_base_pri; sched_prio(curthread, PI_REALTIME); +#if __FreeBSD_version < 600000 + curthread->td_base_pri = PI_REALTIME; +#endif mtx_unlock_spin(&sched_lock); return(oldirql); @@ -321,6 +331,9 @@ KfLowerIrql(REGARGS1(uint8_t oldirql)) panic("IRQL_NOT_GREATER_THAN"); mtx_lock_spin(&sched_lock); +#if __FreeBSD_version < 600000 + curthread->td_base_pri = oldirql; +#endif sched_prio(curthread, oldirql); mtx_unlock_spin(&sched_lock); diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c index b7267d5..f5b5972 100644 --- a/sys/compat/ndis/subr_ndis.c +++ b/sys/compat/ndis/subr_ndis.c @@ -113,7 +113,7 @@ SYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath, MAXPATHLEN, "Path used by NdisOpenFile() to search for files"); __stdcall static void NdisInitializeWrapper(ndis_handle *, - device_object *, void *, void *); + driver_object *, void *, void *); __stdcall static ndis_status NdisMRegisterMiniport(ndis_handle, ndis_miniport_characteristics *, int); __stdcall static ndis_status NdisAllocateMemoryWithTag(void **, @@ -367,17 +367,39 @@ ndis_unicode_to_ascii(unicode, ulen, ascii) return(0); } +/* + * This routine does the messy Windows Driver Model device attachment + * stuff on behalf of NDIS drivers. We register our own AddDevice + * routine here + */ __stdcall static void -NdisInitializeWrapper(wrapper, drv_obj, path, unused) +NdisInitializeWrapper(wrapper, drv, path, unused) ndis_handle *wrapper; - device_object *drv_obj; + driver_object *drv; void *path; void *unused; { - ndis_miniport_block *block; + /* + * As of yet, I haven't come up with a compelling + * reason to define a private NDIS wrapper structure, + * so we use a pointer to the driver object as the + * wrapper handle. The driver object has the miniport + * characteristics struct for this driver hung off it + * via IoAllocateDriverObjectExtension(), and that's + * really all the private data we need. + */ - block = drv_obj->do_rsvd; - *wrapper = block; + *wrapper = drv; + + /* + * If this was really Windows, we'd be registering dispatch + * routines for the NDIS miniport module here, but we're + * not Windows so all we really need to do is set up an + * AddDevice function that'll be invoked when a new device + * instance appears. + */ + + drv->dro_driverext->dre_adddevicefunc = NdisAddDevice; return; } @@ -387,6 +409,7 @@ NdisTerminateWrapper(handle, syspec) ndis_handle handle; void *syspec; { + /* Nothing to see here, move along. */ return; } @@ -396,18 +419,34 @@ NdisMRegisterMiniport(handle, characteristics, len) ndis_miniport_characteristics *characteristics; int len; { - ndis_miniport_block *block; - struct ndis_softc *sc; + ndis_miniport_characteristics *ch = NULL; + driver_object *drv; - block = (ndis_miniport_block *)handle; - sc = (struct ndis_softc *)block->nmb_ifp; - bcopy((char *)characteristics, (char *)&sc->ndis_chars, - sizeof(ndis_miniport_characteristics)); - if (sc->ndis_chars.nmc_version_major < 5 || - sc->ndis_chars.nmc_version_minor < 1) { - sc->ndis_chars.nmc_shutdown_handler = NULL; - sc->ndis_chars.nmc_canceltxpkts_handler = NULL; - sc->ndis_chars.nmc_pnpevent_handler = NULL; + drv = (driver_object *)handle; + + /* + * We need to save the NDIS miniport characteristics + * somewhere. This data is per-driver, not per-device + * (all devices handled by the same driver have the + * same characteristics) so we hook it onto the driver + * object using IoAllocateDriverObjectExtension(). + * The extra extension info is automagically deleted when + * the driver is unloaded (see windrv_unload()). + */ + + if (IoAllocateDriverObjectExtension(drv, (void *)1, + sizeof(ndis_miniport_characteristics), (void **)&ch) != + STATUS_SUCCESS) + return(NDIS_STATUS_RESOURCES); + + bzero((char *)ch, sizeof(ndis_miniport_characteristics)); + + bcopy((char *)characteristics, (char *)ch, len); + + if (ch->nmc_version_major < 5 || ch->nmc_version_minor < 1) { + ch->nmc_shutdown_handler = NULL; + ch->nmc_canceltxpkts_handler = NULL; + ch->nmc_pnpevent_handler = NULL; } return(NDIS_STATUS_SUCCESS); @@ -421,7 +460,7 @@ NdisAllocateMemoryWithTag(vaddr, len, tag) { void *mem; - mem = malloc(len, M_DEVBUF, M_NOWAIT); + mem = ExAllocatePoolWithTag(NonPagedPool, len, tag); if (mem == NULL) return(NDIS_STATUS_RESOURCES); *vaddr = mem; @@ -438,7 +477,7 @@ NdisAllocateMemory(vaddr, len, flags, highaddr) { void *mem; - mem = malloc(len, M_DEVBUF, M_NOWAIT); + mem = ExAllocatePoolWithTag(NonPagedPool, len, 0); if (mem == NULL) return(NDIS_STATUS_RESOURCES); *vaddr = mem; @@ -454,7 +493,8 @@ NdisFreeMemory(vaddr, len, flags) { if (len == 0) return; - free(vaddr, M_DEVBUF); + + ExFreePool(vaddr); return; } @@ -490,6 +530,7 @@ NdisOpenConfiguration(status, cfg, wrapctx) { *cfg = wrapctx; *status = NDIS_STATUS_SUCCESS; + return; } @@ -535,8 +576,8 @@ ndis_encode_parm(block, oid, type, parm) 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; + ustr->us_len = strlen((char *)oid->oid_arg1) * 2; + ustr->us_buf = unicode; break; case ndis_parm_int: if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) @@ -627,14 +668,14 @@ NdisReadConfiguration(status, parm, cfg, key, type) struct sysctl_ctx_entry *e; block = (ndis_miniport_block *)cfg; - sc = (struct ndis_softc *)block->nmb_ifp; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - if (key->nus_len == 0 || key->nus_buf == NULL) { + if (key->us_len == 0 || key->us_buf == NULL) { *status = NDIS_STATUS_FAILURE; return; } - ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr); + ndis_unicode_to_ascii(key->us_buf, key->us_len, &keystr); *parm = &block->nmb_replyparm; bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm)); @@ -698,7 +739,7 @@ ndis_decode_parm(block, parm, val) switch(parm->ncp_type) { case ndis_parm_string: ustr = &parm->ncp_parmdata.ncp_stringdata; - ndis_unicode_to_ascii(ustr->nus_buf, ustr->nus_len, &astr); + ndis_unicode_to_ascii(ustr->us_buf, ustr->us_len, &astr); bcopy(astr, val, 254); free(astr, M_DEVBUF); break; @@ -730,9 +771,9 @@ NdisWriteConfiguration(status, cfg, key, parm) char val[256]; block = (ndis_miniport_block *)cfg; - sc = (struct ndis_softc *)block->nmb_ifp; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr); + ndis_unicode_to_ascii(key->us_buf, key->us_len, &keystr); /* Decode the parameter into a string. */ bzero(val, sizeof(val)); @@ -863,14 +904,16 @@ NdisReadPciSlotInformation(adapter, slot, offset, buf, len) ndis_miniport_block *block; int i; char *dest; + device_t dev; block = (ndis_miniport_block *)adapter; dest = buf; - if (block == NULL || block->nmb_dev == NULL) + if (block == NULL) return(0); + dev = block->nmb_physdeviceobj->do_devext; for (i = 0; i < len; i++) - dest[i] = pci_read_config(block->nmb_dev, i + offset, 1); + dest[i] = pci_read_config(dev, i + offset, 1); return(len); } @@ -886,15 +929,17 @@ NdisWritePciSlotInformation(adapter, slot, offset, buf, len) ndis_miniport_block *block; int i; char *dest; + device_t dev; block = (ndis_miniport_block *)adapter; dest = buf; - if (block == NULL || block->nmb_dev == NULL) + if (block == NULL) return(0); + dev = block->nmb_physdeviceobj->do_devext; for (i = 0; i < len; i++) - pci_write_config(block->nmb_dev, i + offset, dest[i], 1); + pci_write_config(dev, i + offset, dest[i], 1); return(len); } @@ -914,9 +959,10 @@ NdisWriteErrorLogEntry(ndis_handle adapter, ndis_error_code code, char *str = NULL, *ustr = NULL; uint16_t flags; char msgbuf[ERRMSGLEN]; - + device_t dev; block = (ndis_miniport_block *)adapter; + dev = block->nmb_physdeviceobj->do_devext; error = pe_get_message(block->nmb_img, code, &str, &i, &flags); if (error == 0 && flags & MESSAGE_RESOURCE_UNICODE) { @@ -925,13 +971,13 @@ NdisWriteErrorLogEntry(ndis_handle adapter, ndis_error_code code, ((i / 2)) > (ERRMSGLEN - 1) ? ERRMSGLEN : i, &ustr); str = ustr; } - device_printf (block->nmb_dev, "NDIS ERROR: %x (%s)\n", code, + device_printf (dev, "NDIS ERROR: %x (%s)\n", code, str == NULL ? "unknown error" : str); - device_printf (block->nmb_dev, "NDIS NUMERRORS: %x\n", numerrors); + device_printf (dev, "NDIS NUMERRORS: %x\n", numerrors); va_start(ap, numerrors); for (i = 0; i < numerrors; i++) - device_printf (block->nmb_dev, "argptr: %p\n", + device_printf (dev, "argptr: %p\n", va_arg(ap, void *)); va_end(ap); @@ -982,7 +1028,7 @@ NdisMStartBufferPhysicalMapping(adapter, buf, mapreg, writedev, addrarray, array return; block = (ndis_miniport_block *)adapter; - sc = (struct ndis_softc *)(block->nmb_ifp); + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); if (mapreg > sc->ndis_mmapcnt) return; @@ -1019,7 +1065,7 @@ NdisMCompleteBufferPhysicalMapping(adapter, buf, mapreg) return; block = (ndis_miniport_block *)adapter; - sc = (struct ndis_softc *)(block->nmb_ifp); + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); if (mapreg > sc->ndis_mmapcnt) return; @@ -1136,7 +1182,7 @@ NdisMQueryAdapterResources(status, adapter, list, buflen) int rsclen; block = (ndis_miniport_block *)adapter; - sc = (struct ndis_softc *)block->nmb_ifp; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); rsclen = sizeof(ndis_resource_list) + (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)); @@ -1165,7 +1211,7 @@ NdisMRegisterIoPortRange(offset, adapter, port, numports) return(NDIS_STATUS_FAILURE); block = (ndis_miniport_block *)adapter; - sc = (struct ndis_softc *)(block->nmb_ifp); + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); if (sc->ndis_res_io == NULL) return(NDIS_STATUS_FAILURE); @@ -1201,7 +1247,7 @@ NdisReadNetworkAddress(status, addr, addrlen, adapter) uint8_t empty[] = { 0, 0, 0, 0, 0, 0 }; block = (ndis_miniport_block *)adapter; - sc = (struct ndis_softc *)block->nmb_ifp; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0) *status = NDIS_STATUS_FAILURE; @@ -1236,7 +1282,7 @@ NdisMAllocateMapRegisters(adapter, dmachannel, dmasize, physmapneeded, maxmap) int error, i, nseg = NDIS_MAXSEG; block = (ndis_miniport_block *)adapter; - sc = (struct ndis_softc *)block->nmb_ifp; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded, M_DEVBUF, M_NOWAIT|M_ZERO); @@ -1271,7 +1317,7 @@ NdisMFreeMapRegisters(adapter) int i; block = (ndis_miniport_block *)adapter; - sc = (struct ndis_softc *)block->nmb_ifp; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); for (i = 0; i < sc->ndis_mmapcnt; i++) bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]); @@ -1322,7 +1368,7 @@ NdisMAllocateSharedMemory(adapter, len, cached, vaddr, paddr) return; block = (ndis_miniport_block *)adapter; - sc = (struct ndis_softc *)(block->nmb_ifp); + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO); if (sh == NULL) @@ -1398,12 +1444,12 @@ ndis_asyncmem_complete(arg) w = arg; block = (ndis_miniport_block *)w->na_adapter; - sc = (struct ndis_softc *)(block->nmb_ifp); + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); vaddr = NULL; paddr.np_quad = 0; - donefunc = sc->ndis_chars.nmc_allocate_complete_func; + donefunc = sc->ndis_chars->nmc_allocate_complete_func; NdisMAllocateSharedMemory(w->na_adapter, w->na_len, w->na_cached, &vaddr, &paddr); donefunc(w->na_adapter, vaddr, &paddr, w->na_len, w->na_ctx); @@ -1463,7 +1509,7 @@ NdisMFreeSharedMemory(adapter, len, cached, vaddr, paddr) return; block = (ndis_miniport_block *)adapter; - sc = (struct ndis_softc *)(block->nmb_ifp); + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); sh = prev = sc->ndis_shlist; while (sh) { @@ -1501,7 +1547,7 @@ NdisMMapIoSpace(vaddr, adapter, paddr, len) return(NDIS_STATUS_FAILURE); block = (ndis_miniport_block *)adapter; - sc = (struct ndis_softc *)(block->nmb_ifp); + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); if (sc->ndis_res_mem != NULL && paddr.np_quad == rman_get_start(sc->ndis_res_mem)) @@ -1564,7 +1610,7 @@ NdisMInitializeScatterGatherDma(adapter, is64, maxphysmap) if (adapter == NULL) return(NDIS_STATUS_FAILURE); block = (ndis_miniport_block *)adapter; - sc = (struct ndis_softc *)block->nmb_ifp; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); /* Don't do this twice. */ if (sc->ndis_sc == 1) @@ -2083,8 +2129,8 @@ NdisUnicodeStringToAnsiString(dstr, sstr) { if (dstr == NULL || sstr == NULL) return(NDIS_STATUS_FAILURE); - if (ndis_unicode_to_ascii(sstr->nus_buf, - sstr->nus_len, &dstr->nas_buf)) + if (ndis_unicode_to_ascii(sstr->us_buf, + sstr->us_len, &dstr->nas_buf)) return(NDIS_STATUS_FAILURE); dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf); return (NDIS_STATUS_SUCCESS); @@ -2103,11 +2149,11 @@ NdisAnsiStringToUnicodeString(dstr, sstr) return(NDIS_STATUS_FAILURE); strncpy(str, sstr->nas_buf, sstr->nas_len); *(str + sstr->nas_len) = '\0'; - if (ndis_ascii_to_unicode(str, &dstr->nus_buf)) { + if (ndis_ascii_to_unicode(str, &dstr->us_buf)) { free(str, M_DEVBUF); return(NDIS_STATUS_FAILURE); } - dstr->nus_len = dstr->nus_maxlen = sstr->nas_len * 2; + dstr->us_len = dstr->us_maxlen = sstr->nas_len * 2; free(str, M_DEVBUF); return (NDIS_STATUS_SUCCESS); } @@ -2147,6 +2193,7 @@ NdisMRegisterInterrupt(intr, adapter, ivec, ilevel, reqisr, shared, imode) intr->ni_isrreq = reqisr; intr->ni_shared = shared; block->nmb_interrupt = intr; + return(NDIS_STATUS_SUCCESS); } @@ -2171,8 +2218,8 @@ NdisMRegisterAdapterShutdownHandler(adapter, shutdownctx, shutdownfunc) return; block = (ndis_miniport_block *)adapter; - sc = (struct ndis_softc *)block->nmb_ifp; - chars = &sc->ndis_chars; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); + chars = sc->ndis_chars; chars->nmc_shutdown_handler = shutdownfunc; chars->nmc_rsvd0 = shutdownctx; @@ -2192,8 +2239,8 @@ NdisMDeregisterAdapterShutdownHandler(adapter) return; block = (ndis_miniport_block *)adapter; - sc = (struct ndis_softc *)block->nmb_ifp; - chars = &sc->ndis_chars; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); + chars = sc->ndis_chars; chars->nmc_shutdown_handler = NULL; chars->nmc_rsvd0 = NULL; @@ -2272,7 +2319,7 @@ NdisReadPcmciaAttributeMemory(handle, offset, buf, len) return(0); block = (ndis_miniport_block *)handle; - sc = (struct ndis_softc *)block->nmb_ifp; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); dest = buf; bh = rman_get_bushandle(sc->ndis_res_am); @@ -2302,7 +2349,7 @@ NdisWritePcmciaAttributeMemory(handle, offset, buf, len) return(0); block = (ndis_miniport_block *)handle; - sc = (struct ndis_softc *)block->nmb_ifp; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); src = buf; bh = rman_get_bushandle(sc->ndis_res_am); @@ -2383,7 +2430,7 @@ NdisMSynchronizeWithInterrupt(intr, syncfunc, syncctx) if (syncfunc == NULL || syncctx == NULL) return(0); - sc = (struct ndis_softc *)intr->ni_block->nmb_ifp; + sc = device_get_softc(intr->ni_block->nmb_physdeviceobj->do_devext); sync = syncfunc; mtx_lock(&sc->ndis_intrmtx); rval = sync(syncctx); @@ -2432,10 +2479,10 @@ NdisInitializeString(dst, src) ndis_unicode_string *u; u = dst; - u->nus_buf = NULL; - if (ndis_ascii_to_unicode(src, &u->nus_buf)) + u->us_buf = NULL; + if (ndis_ascii_to_unicode(src, &u->us_buf)) return; - u->nus_len = u->nus_maxlen = strlen(src) * 2; + u->us_len = u->us_maxlen = strlen(src) * 2; return; } @@ -2445,8 +2492,8 @@ NdisFreeString(str) { if (str == NULL) return; - if (str->nus_buf != NULL) - free(str->nus_buf, M_DEVBUF); + if (str->us_buf != NULL) + free(str->us_buf, M_DEVBUF); free(str, M_DEVBUF); return; } @@ -2491,14 +2538,14 @@ NdisInitUnicodeString(dst, src) if (u == NULL) return; if (src == NULL) { - u->nus_len = u->nus_maxlen = 0; - u->nus_buf = NULL; + u->us_len = u->us_maxlen = 0; + u->us_buf = NULL; } else { i = 0; while(src[i] != 0) i++; - u->nus_buf = src; - u->nus_len = u->nus_maxlen = i * 2; + u->us_buf = src; + u->us_len = u->us_maxlen = i * 2; } return; @@ -2518,9 +2565,11 @@ __stdcall static void NdisMGetDeviceProperty(adapter, phydevobj, block = (ndis_miniport_block *)adapter; if (phydevobj != NULL) - *phydevobj = &block->nmb_devobj; + *phydevobj = block->nmb_physdeviceobj; if (funcdevobj != NULL) - *funcdevobj = &block->nmb_devobj; + *funcdevobj = block->nmb_deviceobj; + if (nextdevobj != NULL) + *nextdevobj = block->nmb_nextdeviceobj; return; } @@ -2617,8 +2666,8 @@ NdisOpenFile(status, filehandle, filelength, filename, highestaddr) linker_file_t head, lf; caddr_t kldstart, kldend; - ndis_unicode_to_ascii(filename->nus_buf, - filename->nus_len, &afilename); + ndis_unicode_to_ascii(filename->us_buf, + filename->us_len, &afilename); fh = malloc(sizeof(ndis_fh), M_TEMP, M_NOWAIT); if (fh == NULL) { @@ -3010,7 +3059,7 @@ NdisMRegisterDevice(handle, devname, symname, majorfuncs, devobj, devhandle) ndis_miniport_block *block; block = (ndis_miniport_block *)handle; - *devobj = &block->nmb_devobj; + *devobj = block->nmb_deviceobj; *devhandle = handle; return(NDIS_STATUS_SUCCESS); @@ -3029,11 +3078,14 @@ NdisMQueryAdapterInstanceName(name, handle) ndis_handle handle; { ndis_miniport_block *block; + device_t dev; block = (ndis_miniport_block *)handle; + dev = block->nmb_physdeviceobj->do_devext; + ndis_ascii_to_unicode(__DECONST(char *, - device_get_nameunit(block->nmb_dev)), &name->nus_buf); - name->nus_len = strlen(device_get_nameunit(block->nmb_dev)) * 2; + device_get_nameunit(dev)), &name->us_buf); + name->us_len = strlen(device_get_nameunit(dev)) * 2; return(NDIS_STATUS_SUCCESS); } diff --git a/sys/compat/ndis/subr_ntoskrnl.c b/sys/compat/ndis/subr_ntoskrnl.c index b3df9c4..f793f2a 100644 --- a/sys/compat/ndis/subr_ntoskrnl.c +++ b/sys/compat/ndis/subr_ntoskrnl.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/proc.h> #include <sys/kthread.h> +#include <sys/module.h> #include <machine/atomic.h> #include <machine/clock.h> @@ -81,8 +82,18 @@ __stdcall static ndis_status RtlUnicodeStringToAnsiString(ndis_ansi_string *, ndis_unicode_string *, uint8_t); __stdcall static ndis_status RtlAnsiStringToUnicodeString(ndis_unicode_string *, ndis_ansi_string *, uint8_t); -__stdcall static void *IoBuildSynchronousFsdRequest(uint32_t, void *, - void *, uint32_t, uint32_t *, void *, void *); +__stdcall static irp *IoBuildSynchronousFsdRequest(uint32_t, device_object *, + void *, uint32_t, uint64_t *, nt_kevent *, io_status_block *); +__stdcall static irp *IoBuildAsynchronousFsdRequest(uint32_t, + device_object *, void *, uint32_t, uint64_t *, io_status_block *); +__stdcall static irp *IoBuildDeviceIoControlRequest(uint32_t, + device_object *, void *, uint32_t, void *, uint32_t, + uint8_t, nt_kevent *, io_status_block *); +__stdcall static irp *IoAllocateIrp(uint8_t, uint8_t); +__stdcall static void IoReuseIrp(irp *, uint32_t); +__stdcall static void IoFreeIrp(irp *); +__stdcall static void IoInitializeIrp(irp *, uint16_t, uint8_t); +__stdcall static irp *IoMakeAssociatedIrp(irp *, uint8_t); __stdcall static uint32_t KeWaitForMultipleObjects(uint32_t, nt_dispatch_header **, uint32_t, uint32_t, uint32_t, uint8_t, int64_t *, wait_block *); @@ -105,8 +116,6 @@ __stdcall static uint64_t _aulldiv(uint64_t, uint64_t); __stdcall static uint64_t _aullrem(uint64_t, uint64_t); __regparm static uint64_t _aullshr(uint64_t, uint8_t); __regparm static uint64_t _aullshl(uint64_t, uint8_t); -__stdcall static void *ntoskrnl_allocfunc(uint32_t, size_t, uint32_t); -__stdcall static void ntoskrnl_freefunc(void *); static slist_entry *ntoskrnl_pushsl(slist_header *, slist_entry *); static slist_entry *ntoskrnl_popsl(slist_header *); __stdcall static void ExInitializePagedLookasideList(paged_lookaside_list *, @@ -203,16 +212,16 @@ RtlEqualUnicodeString(str1, str2, caseinsensitive) { int i; - if (str1->nus_len != str2->nus_len) + if (str1->us_len != str2->us_len) return(FALSE); - for (i = 0; i < str1->nus_len; i++) { + for (i = 0; i < str1->us_len; i++) { if (caseinsensitive == TRUE) { - if (toupper((char)(str1->nus_buf[i] & 0xFF)) != - toupper((char)(str2->nus_buf[i] & 0xFF))) + if (toupper((char)(str1->us_buf[i] & 0xFF)) != + toupper((char)(str2->us_buf[i] & 0xFF))) return(FALSE); } else { - if (str1->nus_buf[i] != str2->nus_buf[i]) + if (str1->us_buf[i] != str2->us_buf[i]) return(FALSE); } } @@ -226,11 +235,11 @@ RtlCopyUnicodeString(dest, src) ndis_unicode_string *src; { - if (dest->nus_maxlen >= src->nus_len) - dest->nus_len = src->nus_len; + if (dest->us_maxlen >= src->us_len) + dest->us_len = src->us_len; else - dest->nus_len = dest->nus_maxlen; - memcpy(dest->nus_buf, src->nus_buf, dest->nus_len); + dest->us_len = dest->us_maxlen; + memcpy(dest->us_buf, src->us_buf, dest->us_len); return; } @@ -246,15 +255,15 @@ RtlUnicodeStringToAnsiString(dest, src, allocate) return(NDIS_STATUS_FAILURE); if (allocate == TRUE) { - if (ndis_unicode_to_ascii(src->nus_buf, src->nus_len, &astr)) + if (ndis_unicode_to_ascii(src->us_buf, src->us_len, &astr)) return(NDIS_STATUS_FAILURE); dest->nas_buf = astr; dest->nas_len = dest->nas_maxlen = strlen(astr); } else { - dest->nas_len = src->nus_len / 2; /* XXX */ + dest->nas_len = src->us_len / 2; /* XXX */ if (dest->nas_maxlen < dest->nas_len) dest->nas_len = dest->nas_maxlen; - ndis_unicode_to_ascii(src->nus_buf, dest->nas_len * 2, + ndis_unicode_to_ascii(src->us_buf, dest->nas_len * 2, &dest->nas_buf); } return (NDIS_STATUS_SUCCESS); @@ -274,39 +283,478 @@ RtlAnsiStringToUnicodeString(dest, src, allocate) if (allocate == TRUE) { if (ndis_ascii_to_unicode(src->nas_buf, &ustr)) return(NDIS_STATUS_FAILURE); - dest->nus_buf = ustr; - dest->nus_len = dest->nus_maxlen = strlen(src->nas_buf) * 2; + dest->us_buf = ustr; + dest->us_len = dest->us_maxlen = strlen(src->nas_buf) * 2; } else { - dest->nus_len = src->nas_len * 2; /* XXX */ - if (dest->nus_maxlen < dest->nus_len) - dest->nus_len = dest->nus_maxlen; - ndis_ascii_to_unicode(src->nas_buf, &dest->nus_buf); + dest->us_len = src->nas_len * 2; /* XXX */ + if (dest->us_maxlen < dest->us_len) + dest->us_len = dest->us_maxlen; + ndis_ascii_to_unicode(src->nas_buf, &dest->us_buf); } return (NDIS_STATUS_SUCCESS); } -__stdcall static void * +__stdcall void * +ExAllocatePoolWithTag(pooltype, len, tag) + uint32_t pooltype; + size_t len; + uint32_t tag; +{ + void *buf; + + buf = malloc(len, M_DEVBUF, M_NOWAIT); + if (buf == NULL) + return(NULL); + return(buf); +} + +__stdcall void +ExFreePool(buf) + void *buf; +{ + free(buf, M_DEVBUF); + return; +} + +__stdcall uint32_t +IoAllocateDriverObjectExtension(drv, clid, extlen, ext) + driver_object *drv; + void *clid; + uint32_t extlen; + void **ext; +{ + custom_extension *ce; + + ce = ExAllocatePoolWithTag(NonPagedPool, sizeof(custom_extension) + + extlen, 0); + + if (ce == NULL) + return(STATUS_INSUFFICIENT_RESOURCES); + + ce->ce_clid = clid; + INSERT_LIST_TAIL((&drv->dro_driverext->dre_usrext), (&ce->ce_list)); + + *ext = (void *)(ce + 1); + + return(STATUS_SUCCESS); +} + +__stdcall void * +IoGetDriverObjectExtension(drv, clid) + driver_object *drv; + void *clid; +{ + list_entry *e; + custom_extension *ce; + + e = drv->dro_driverext->dre_usrext.nle_flink; + while (e != &drv->dro_driverext->dre_usrext) { + ce = (custom_extension *)e; + if (ce->ce_clid == clid) + return((void *)(ce + 1)); + e = e->nle_flink; + } + + return(NULL); +} + + +__stdcall uint32_t +IoCreateDevice(drv, devextlen, devname, devtype, devchars, exclusive, newdev) + driver_object *drv; + uint32_t devextlen; + unicode_string *devname; + uint32_t devtype; + uint32_t devchars; + uint8_t exclusive; + device_object **newdev; +{ + device_object *dev; + + dev = ExAllocatePoolWithTag(NonPagedPool, sizeof(device_object), 0); + if (dev == NULL) + return(STATUS_INSUFFICIENT_RESOURCES); + + dev->do_type = devtype; + dev->do_drvobj = drv; + dev->do_currirp = NULL; + dev->do_flags = 0; + + if (devextlen) { + dev->do_devext = ExAllocatePoolWithTag(NonPagedPool, + devextlen, 0); + + if (dev->do_devext == NULL) { + ExFreePool(dev); + return(STATUS_INSUFFICIENT_RESOURCES); + } + } else + dev->do_devext = NULL; + + dev->do_size = sizeof(device_object) + devextlen; + dev->do_refcnt = 1; + dev->do_attacheddev = NULL; + dev->do_nextdev = NULL; + dev->do_devtype = devtype; + dev->do_stacksize = 1; + dev->do_alignreq = 1; + dev->do_characteristics = devchars; + dev->do_iotimer = NULL; + KeInitializeEvent(&dev->do_devlock, EVENT_TYPE_SYNC, TRUE); + + /* + * Vpd is used for disk/tape devices, + * but we don't support those. (Yet.) + */ + dev->do_vpb = NULL; + + dev->do_devobj_ext = ExAllocatePoolWithTag(NonPagedPool, + sizeof(devobj_extension), 0); + + if (dev->do_devobj_ext == NULL) { + if (dev->do_devext != NULL) + ExFreePool(dev->do_devext); + ExFreePool(dev); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + dev->do_devobj_ext->dve_type = 0; + dev->do_devobj_ext->dve_size = sizeof(devobj_extension); + dev->do_devobj_ext->dve_devobj = dev; + + /* + * Attach this device to the driver object's list + * of devices. Note: this is not the same as attaching + * the device to the device stack. The driver's AddDevice + * routine must explicitly call IoAddDeviceToDeviceStack() + * to do that. + */ + + if (drv->dro_devobj == NULL) { + drv->dro_devobj = dev; + dev->do_nextdev = NULL; + } else { + dev->do_nextdev = drv->dro_devobj; + drv->dro_devobj = dev; + } + + *newdev = dev; + + return(STATUS_SUCCESS); +} + +__stdcall void +IoDeleteDevice(dev) + device_object *dev; +{ + device_object *prev; + + if (dev == NULL) + return; + + if (dev->do_devobj_ext != NULL) + ExFreePool(dev->do_devobj_ext); + + if (dev->do_devext != NULL) + ExFreePool(dev->do_devext); + + /* Unlink the device from the driver's device list. */ + + prev = dev->do_drvobj->dro_devobj; + if (prev == dev) + dev->do_drvobj->dro_devobj = dev->do_nextdev; + else { + while (prev->do_nextdev != dev) + prev = prev->do_nextdev; + prev->do_nextdev = dev->do_nextdev; + } + + ExFreePool(dev); + + return; +} + +__stdcall device_object * +IoGetAttachedDevice(dev) + device_object *dev; +{ + device_object *d; + + if (dev == NULL) + return (NULL); + + d = dev; + + while (d->do_attacheddev != NULL) + d = d->do_attacheddev; + + return (d); +} + +__stdcall static irp * IoBuildSynchronousFsdRequest(func, dobj, buf, len, off, event, status) uint32_t func; - void *dobj; + device_object *dobj; + void *buf; + uint32_t len; + uint64_t *off; + nt_kevent *event; + io_status_block *status; +{ + return(NULL); +} + +__stdcall static irp * +IoBuildAsynchronousFsdRequest(func, dobj, buf, len, off, status) + uint32_t func; + device_object *dobj; void *buf; uint32_t len; - uint32_t *off; - void *event; - void *status; + uint64_t *off; + io_status_block *status; { return(NULL); } - + +__stdcall static irp * +IoBuildDeviceIoControlRequest(iocode, dobj, ibuf, ilen, obuf, olen, + isinternal, event, status) + uint32_t iocode; + device_object *dobj; + void *ibuf; + uint32_t ilen; + void *obuf; + uint32_t olen; + uint8_t isinternal; + nt_kevent *event; + io_status_block *status; +{ + return (NULL); +} + +__stdcall static irp * +IoAllocateIrp(stsize, chargequota) + uint8_t stsize; + uint8_t chargequota; +{ + irp *i; + + i = ExAllocatePoolWithTag(NonPagedPool, IoSizeOfIrp(stsize), 0); + if (i == NULL) + return (NULL); + + IoInitializeIrp(i, IoSizeOfIrp(stsize), stsize); + + return (NULL); +} + +__stdcall static irp * +IoMakeAssociatedIrp(ip, stsize) + irp *ip; + uint8_t stsize; +{ + irp *associrp; + + associrp = IoAllocateIrp(stsize, FALSE); + if (associrp == NULL) + return(NULL); + + mtx_lock(&ntoskrnl_dispatchlock); + associrp->irp_flags |= IRP_ASSOCIATED_IRP; + associrp->irp_tail.irp_overlay.irp_thread = + ip->irp_tail.irp_overlay.irp_thread; + associrp->irp_assoc.irp_master = ip; + mtx_unlock(&ntoskrnl_dispatchlock); + + return(associrp); +} + +__stdcall static void +IoFreeIrp(ip) + irp *ip; +{ + ExFreePool(ip); + return; +} + +__stdcall static void +IoInitializeIrp(io, psize, ssize) + irp *io; + uint16_t psize; + uint8_t ssize; +{ + bzero((char *)io, sizeof(irp)); + io->irp_size = psize; + io->irp_stackcnt = ssize; + io->irp_currentstackloc = ssize; + INIT_LIST_HEAD(&io->irp_thlist); + io->irp_tail.irp_overlay.irp_csl = + (io_stack_location *)(io + 1) + ssize; + + return; +} + +__stdcall static void +IoReuseIrp(ip, status) + irp *ip; + uint32_t status; +{ + uint8_t allocflags; + + allocflags = ip->irp_allocflags; + IoInitializeIrp(ip, ip->irp_size, ip->irp_stackcnt); + ip->irp_iostat.isb_status = status; + ip->irp_allocflags = allocflags; + + return; +} + __fastcall uint32_t IofCallDriver(REGARGS2(device_object *dobj, irp *ip)) { - return(0); + driver_object *drvobj; + io_stack_location *sl; + uint32_t status; + driver_dispatch disp; + + drvobj = dobj->do_drvobj; + + if (ip->irp_currentstackloc <= 0) + panic("IoCallDriver(): out of stack locations"); + + IoSetNextIrpStackLocation(ip); + sl = IoGetCurrentIrpStackLocation(ip); + + sl->isl_devobj = dobj; + + disp = drvobj->dro_dispatch[sl->isl_major]; + status = disp(dobj, ip); + + return(status); } __fastcall void IofCompleteRequest(REGARGS2(irp *ip, uint8_t prioboost)) { + uint32_t i; + uint32_t status; + device_object *dobj; + io_stack_location *sl; + completion_func cf; + + ip->irp_pendingreturned = + IoGetCurrentIrpStackLocation(ip)->isl_ctl & SL_PENDING_RETURNED; + sl = (io_stack_location *)(ip + 1); + + for (i = ip->irp_currentstackloc; i < (uint32_t)ip->irp_stackcnt; i++) { + if (ip->irp_currentstackloc < ip->irp_stackcnt - 1) { + IoSkipCurrentIrpStackLocation(ip); + dobj = IoGetCurrentIrpStackLocation(ip)->isl_devobj; + } else + dobj = NULL; + + if (sl[i].isl_completionfunc != NULL && + ((ip->irp_iostat.isb_status == STATUS_SUCCESS && + sl->isl_ctl & SL_INVOKE_ON_SUCCESS) || + (ip->irp_iostat.isb_status != STATUS_SUCCESS && + sl->isl_ctl & SL_INVOKE_ON_ERROR) || + (ip->irp_cancel == TRUE && + sl->isl_ctl & SL_INVOKE_ON_CANCEL))) { + cf = sl->isl_completionfunc; + status = cf(dobj, ip, sl->isl_completionctx); + if (status == STATUS_MORE_PROCESSING_REQUIRED) + return; + } + + if (IoGetCurrentIrpStackLocation(ip)->isl_ctl & + SL_PENDING_RETURNED) + ip->irp_pendingreturned = TRUE; + } + + /* Handle any associated IRPs. */ + + if (ip->irp_flags & IRP_ASSOCIATED_IRP) { + uint32_t masterirpcnt; + irp *masterirp; + mdl *m; + + masterirp = ip->irp_assoc.irp_master; + masterirpcnt = FASTCALL1(InterlockedDecrement, + masterirp->irp_assoc.irp_irpcnt); + + while ((m = ip->irp_mdl) != NULL) { + ip->irp_mdl = m->mdl_next; + IoFreeMdl(m); + } + IoFreeIrp(ip); + if (masterirpcnt == 0) + IoCompleteRequest(masterirp, IO_NO_INCREMENT); + return; + } + + /* With any luck, these conditions will never arise. */ + + if (ip->irp_flags & (IRP_PAGING_IO|IRP_CLOSE_OPERATION)) { + if (ip->irp_usriostat != NULL) + *ip->irp_usriostat = ip->irp_iostat; + if (ip->irp_usrevent != NULL) + KeSetEvent(ip->irp_usrevent, prioboost, FALSE); + if (ip->irp_flags & IRP_PAGING_IO) { + if (ip->irp_mdl != NULL) + IoFreeMdl(ip->irp_mdl); + IoFreeIrp(ip); + } + } + + return; +} + +__stdcall device_object * +IoAttachDeviceToDeviceStack(src, dst) + device_object *src; + device_object *dst; +{ + device_object *attached; + + mtx_lock(&ntoskrnl_dispatchlock); + + attached = IoGetAttachedDevice(dst); + attached->do_attacheddev = src; + src->do_attacheddev = NULL; + src->do_stacksize = attached->do_stacksize + 1; + + mtx_unlock(&ntoskrnl_dispatchlock); + + return(attached); +} + +__stdcall void +IoDetachDevice(topdev) + device_object *topdev; +{ + device_object *tail; + + mtx_lock(&ntoskrnl_dispatchlock); + + /* First, break the chain. */ + tail = topdev->do_attacheddev; + if (tail == NULL) { + mtx_unlock(&ntoskrnl_dispatchlock); + return; + } + topdev->do_attacheddev = tail->do_attacheddev; + topdev->do_refcnt--; + + /* Now reduce the stacksize count for the tail objects. */ + + tail = topdev->do_attacheddev; + while (tail != NULL) { + tail->do_stacksize--; + tail = tail->do_attacheddev; + } + + mtx_unlock(&ntoskrnl_dispatchlock); + return; } @@ -830,23 +1278,6 @@ ntoskrnl_popsl(head) return(first); } -__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); - return; -} - __stdcall static void ExInitializePagedLookasideList(lookaside, allocfunc, freefunc, flags, size, tag, depth) @@ -866,12 +1297,12 @@ ExInitializePagedLookasideList(lookaside, allocfunc, freefunc, lookaside->nll_l.gl_size = size; lookaside->nll_l.gl_tag = tag; if (allocfunc == NULL) - lookaside->nll_l.gl_allocfunc = ntoskrnl_allocfunc; + lookaside->nll_l.gl_allocfunc = ExAllocatePoolWithTag; else lookaside->nll_l.gl_allocfunc = allocfunc; if (freefunc == NULL) - lookaside->nll_l.gl_freefunc = ntoskrnl_freefunc; + lookaside->nll_l.gl_freefunc = ExFreePool; else lookaside->nll_l.gl_freefunc = freefunc; @@ -916,12 +1347,12 @@ ExInitializeNPagedLookasideList(lookaside, allocfunc, freefunc, lookaside->nll_l.gl_size = size; lookaside->nll_l.gl_tag = tag; if (allocfunc == NULL) - lookaside->nll_l.gl_allocfunc = ntoskrnl_allocfunc; + lookaside->nll_l.gl_allocfunc = ExAllocatePoolWithTag; else lookaside->nll_l.gl_allocfunc = allocfunc; if (freefunc == NULL) - lookaside->nll_l.gl_freefunc = ntoskrnl_freefunc; + lookaside->nll_l.gl_freefunc = ExFreePool; else lookaside->nll_l.gl_freefunc = freefunc; @@ -1057,7 +1488,8 @@ IoAllocateMdl(vaddr, len, secondarybuf, chargequota, iopkt) { mdl *m; - m = malloc(MmSizeOfMdl(vaddr, len), M_DEVBUF, M_NOWAIT|M_ZERO); + m = ExAllocatePoolWithTag(NonPagedPool, + MmSizeOfMdl(vaddr, len), 0); if (m == NULL) return (NULL); @@ -1235,14 +1667,14 @@ RtlInitUnicodeString(dst, src) if (u == NULL) return; if (src == NULL) { - u->nus_len = u->nus_maxlen = 0; - u->nus_buf = NULL; + u->us_len = u->us_maxlen = 0; + u->us_buf = NULL; } else { i = 0; while(src[i] != 0) i++; - u->nus_buf = src; - u->nus_len = u->nus_maxlen = i * 2; + u->us_buf = src; + u->us_len = u->us_maxlen = i * 2; } return; @@ -1259,8 +1691,8 @@ RtlUnicodeStringToInteger(ustr, base, val) char abuf[64]; char *astr; - uchr = ustr->nus_buf; - len = ustr->nus_len; + uchr = ustr->us_buf; + len = ustr->us_len; bzero(abuf, sizeof(abuf)); if ((char)((*uchr) & 0xFF) == '-') { @@ -1306,10 +1738,10 @@ __stdcall static void RtlFreeUnicodeString(ustr) ndis_unicode_string *ustr; { - if (ustr->nus_buf == NULL) + if (ustr->us_buf == NULL) return; - free(ustr->nus_buf, M_DEVBUF); - ustr->nus_buf = NULL; + free(ustr->us_buf, M_DEVBUF); + ustr->us_buf = NULL; return; } @@ -1374,15 +1806,16 @@ IoGetDeviceProperty(devobj, regprop, buflen, prop, reslen) void *prop; uint32_t *reslen; { - ndis_miniport_block *block; + driver_object *drv; + uint16_t **name; - block = devobj->do_rsvd; + drv = devobj->do_drvobj; switch (regprop) { case DEVPROP_DRIVER_KEYNAME: - ndis_ascii_to_unicode(__DECONST(char *, - device_get_nameunit(block->nmb_dev)), (uint16_t **)&prop); - *reslen = strlen(device_get_nameunit(block->nmb_dev)) * 2; + name = prop; + *name = drv->dro_drivername.us_buf; + *reslen = drv->dro_drivername.us_len; break; default: return(STATUS_INVALID_PARAMETER_2); @@ -1746,11 +2179,17 @@ KeInitializeDpc(dpc, dpcfunc, dpcctx) void *dpcfunc; void *dpcctx; { + uint8_t irql; + if (dpc == NULL) return; + KeInitializeSpinLock(&dpc->k_lock); + + KeAcquireSpinLock(&dpc->k_lock, &irql); dpc->k_deferedfunc = dpcfunc; dpc->k_deferredctx = dpcctx; + KeReleaseSpinLock(&dpc->k_lock, irql); return; } @@ -1761,8 +2200,13 @@ KeInsertQueueDpc(dpc, sysarg1, sysarg2) void *sysarg1; void *sysarg2; { + uint8_t irql; + + KeAcquireSpinLock(&dpc->k_lock, &irql); dpc->k_sysarg1 = sysarg1; dpc->k_sysarg2 = sysarg2; + KeReleaseSpinLock(&dpc->k_lock, irql); + if (ndis_sched(ntoskrnl_run_dpc, dpc, NDIS_SWI)) return(FALSE); @@ -1896,9 +2340,23 @@ image_patch_table ntoskrnl_functbl[] = { IMPORT_FUNC(memcpy), IMPORT_FUNC_MAP(memmove, memset), IMPORT_FUNC(memset), + IMPORT_FUNC(IoAllocateDriverObjectExtension), + IMPORT_FUNC(IoGetDriverObjectExtension), IMPORT_FUNC(IofCallDriver), IMPORT_FUNC(IofCompleteRequest), + IMPORT_FUNC(IoCreateDevice), + IMPORT_FUNC(IoDeleteDevice), + IMPORT_FUNC(IoGetAttachedDevice), + IMPORT_FUNC(IoAttachDeviceToDeviceStack), + IMPORT_FUNC(IoDetachDevice), IMPORT_FUNC(IoBuildSynchronousFsdRequest), + IMPORT_FUNC(IoBuildAsynchronousFsdRequest), + IMPORT_FUNC(IoBuildDeviceIoControlRequest), + IMPORT_FUNC(IoAllocateIrp), + IMPORT_FUNC(IoReuseIrp), + IMPORT_FUNC(IoMakeAssociatedIrp), + IMPORT_FUNC(IoFreeIrp), + IMPORT_FUNC(IoInitializeIrp), IMPORT_FUNC(KeWaitForSingleObject), IMPORT_FUNC(KeWaitForMultipleObjects), IMPORT_FUNC(_allmul), diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 25f8f22..03ac732 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -80,6 +80,7 @@ compat/linux/linux_sysctl.c optional compat_linux compat/linux/linux_uid16.c optional compat_linux compat/linux/linux_util.c optional compat_linux compat/ndis/kern_ndis.c optional ndisapi pci +compat/ndis/kern_windrv.c optional ndisapi pci compat/ndis/subr_hal.c optional ndisapi pci compat/ndis/subr_ndis.c optional ndisapi pci compat/ndis/subr_ntoskrnl.c optional ndisapi pci diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c index c6223db..aed5e4b 100644 --- a/sys/dev/if_ndis/if_ndis.c +++ b/sys/dev/if_ndis/if_ndis.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/socket.h> #include <sys/queue.h> +#include <sys/module.h> #if __FreeBSD_version < 502113 #include <sys/sysctl.h> #endif @@ -90,6 +91,8 @@ int ndis_suspend (device_t); int ndis_resume (device_t); void ndis_shutdown (device_t); +int ndisdrv_modevent (module_t, int, void *); + static __stdcall void ndis_txeof (ndis_handle, ndis_packet *, ndis_status); static __stdcall void ndis_rxeof (ndis_handle, @@ -123,7 +126,45 @@ static void ndis_setmulti (struct ndis_softc *); static void ndis_map_sclist (void *, bus_dma_segment_t *, int, bus_size_t, int); -extern struct mtx_pool *ndis_mtxpool; +static int ndisdrv_loaded = 0; + +/* + * This routine should call windrv_load() once for each driver + * image. This will do the relocation and dynalinking for the + * image, and create a Windows driver object which will be + * saved in our driver database. + */ + +int +ndisdrv_modevent(mod, cmd, arg) + module_t mod; + int cmd; + void *arg; +{ + int error = 0; + + switch (cmd) { + case MOD_LOAD: + ndisdrv_loaded++; + if (ndisdrv_loaded > 1) + break; + windrv_load(mod, (vm_offset_t)drv_data, 0); + break; + case MOD_UNLOAD: + ndisdrv_loaded--; + if (ndisdrv_loaded > 0) + break; + windrv_unload(mod, (vm_offset_t)drv_data, 0); + break; + case MOD_SHUTDOWN: + break; + default: + error = EINVAL; + break; + } + + return (error); +} /* * Program the 64-bit multicast hash filter. @@ -364,6 +405,8 @@ ndis_attach(dev) { u_char eaddr[ETHER_ADDR_LEN]; struct ndis_softc *sc; + driver_object *drv; + device_object *pdo; struct ifnet *ifp = NULL; void *img; int error = 0, len; @@ -407,21 +450,32 @@ ndis_attach(dev) /* Create sysctl registry nodes */ ndis_create_sysctls(sc); - /* Set up driver image in memory. */ + /* + * Create a new functional device object for this + * device. This is what creates the miniport block + * for this device instance. + */ + img = drv_data; - ndis_load_driver((vm_offset_t)img, sc); + drv = windrv_lookup((vm_offset_t)img); + pdo = windrv_find_pdo(drv, dev); + if (NdisAddDevice(drv, pdo) != STATUS_SUCCESS) { + device_printf(dev, "failed to create FDO!\n"); + error = ENXIO; + goto fail; + } /* Tell the user what version of the API the driver is using. */ device_printf(dev, "NDIS API version: %d.%d\n", - sc->ndis_chars.nmc_version_major, - sc->ndis_chars.nmc_version_minor); + sc->ndis_chars->nmc_version_major, + sc->ndis_chars->nmc_version_minor); /* Do resource conversion. */ ndis_convert_res(sc); /* Install our RX and TX interrupt handlers. */ - sc->ndis_block.nmb_senddone_func = ndis_txeof; - sc->ndis_block.nmb_pktind_func = ndis_rxeof; + sc->ndis_block->nmb_senddone_func = ndis_txeof; + sc->ndis_block->nmb_pktind_func = ndis_rxeof; /* Call driver's init routine. */ if (ndis_init_nic(sc)) { @@ -443,8 +497,8 @@ ndis_attach(dev) * with this driver, and if so, how many. */ - if (sc->ndis_chars.nmc_sendsingle_func && - sc->ndis_chars.nmc_sendmulti_func == NULL) { + if (sc->ndis_chars->nmc_sendsingle_func && + sc->ndis_chars->nmc_sendmulti_func == NULL) { sc->ndis_maxpkts = 1; } else { len = sizeof(sc->ndis_maxpkts); @@ -692,8 +746,8 @@ nonettypes: } /* Override the status handler so we can detect link changes. */ - sc->ndis_block.nmb_status_func = ndis_linksts; - sc->ndis_block.nmb_statusdone_func = ndis_linksts_done; + sc->ndis_block->nmb_status_func = ndis_linksts; + sc->ndis_block->nmb_statusdone_func = ndis_linksts_done; fail: if (error) ndis_detach(dev); @@ -717,6 +771,7 @@ ndis_detach(dev) { struct ndis_softc *sc; struct ifnet *ifp; + driver_object *drv; sc = device_get_softc(dev); KASSERT(mtx_initialized(&sc->ndis_mtx), @@ -767,6 +822,13 @@ ndis_detach(dev) ndis_unload_driver(sc); + /* Destroy the PDO for this device. */ + + drv = windrv_lookup((vm_offset_t)drv_data); + if (drv == NULL) + panic("couldn't find driver object"); + windrv_destroy_pdo(drv, dev); + if (sc->ndis_iftype == PCIBus) bus_dma_tag_destroy(sc->ndis_parent_tag); @@ -849,8 +911,8 @@ ndis_rxeof(adapter, packets, pktcnt) int i; block = (ndis_miniport_block *)adapter; - sc = (struct ndis_softc *)(block->nmb_ifp->if_softc); - ifp = block->nmb_ifp; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); + ifp = &sc->arpcom.ac_if; for (i = 0; i < pktcnt; i++) { p = packets[i]; @@ -927,8 +989,8 @@ ndis_txeof(adapter, packet, status) struct mbuf *m; block = (ndis_miniport_block *)adapter; - sc = (struct ndis_softc *)block->nmb_ifp->if_softc; - ifp = block->nmb_ifp; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); + ifp = &sc->arpcom.ac_if; m = packet->np_m0; idx = packet->np_txidx; @@ -979,8 +1041,8 @@ ndis_linksts_done(adapter) struct ifnet *ifp; block = adapter; - ifp = block->nmb_ifp; - sc = ifp->if_softc; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); + ifp = &sc->arpcom.ac_if; NDIS_LOCK(sc); if (!NDIS_INITIALIZED(sc)) { @@ -1038,11 +1100,11 @@ ndis_intr(arg) sc = arg; ifp = &sc->arpcom.ac_if; - if (sc->ndis_block.nmb_miniportadapterctx == NULL) + if (sc->ndis_block->nmb_miniportadapterctx == NULL) return; mtx_lock(&sc->ndis_intrmtx); - if (sc->ndis_block.nmb_interrupt->ni_isrreq == TRUE) + if (sc->ndis_block->nmb_interrupt->ni_isrreq == TRUE) ndis_isr(sc, &is_our_intr, &call_isr); else { ndis_disable_intr(sc); @@ -1068,7 +1130,7 @@ ndis_tick(xsc) ndis_sched(ndis_ticktask, sc, NDIS_TASKQUEUE); sc->ndis_stat_ch = timeout(ndis_tick, sc, hz * - sc->ndis_block.nmb_checkforhangsecs); + sc->ndis_block->nmb_checkforhangsecs); mtx_lock(&Giant); @@ -1087,10 +1149,10 @@ ndis_ticktask(xsc) sc = xsc; - hangfunc = sc->ndis_chars.nmc_checkhang_func; + hangfunc = sc->ndis_chars->nmc_checkhang_func; if (hangfunc != NULL) { - rval = hangfunc(sc->ndis_block.nmb_miniportadapterctx); + rval = hangfunc(sc->ndis_block->nmb_miniportadapterctx); if (rval == TRUE) { ndis_reset_nic(sc); return; @@ -1391,11 +1453,11 @@ ndis_init(xsc) * drivers, exactly 2 seconds is too fast. */ - if (sc->ndis_block.nmb_checkforhangsecs == 0) - sc->ndis_block.nmb_checkforhangsecs = 3; + if (sc->ndis_block->nmb_checkforhangsecs == 0) + sc->ndis_block->nmb_checkforhangsecs = 3; sc->ndis_stat_ch = timeout(ndis_tick, sc, - hz * sc->ndis_block.nmb_checkforhangsecs); + hz * sc->ndis_block->nmb_checkforhangsecs); return; } diff --git a/sys/dev/if_ndis/if_ndis_pccard.c b/sys/dev/if_ndis/if_ndis_pccard.c index 0786b01..c3c42eb 100644 --- a/sys/dev/if_ndis/if_ndis_pccard.c +++ b/sys/dev/if_ndis/if_ndis_pccard.c @@ -87,13 +87,14 @@ static int ndis_probe_pccard (device_t); static int ndis_attach_pccard (device_t); static struct resource_list *ndis_get_resource_list (device_t, device_t); +extern int ndisdrv_modevent (module_t, int, void *); extern int ndis_attach (device_t); extern int ndis_shutdown (device_t); extern int ndis_detach (device_t); extern int ndis_suspend (device_t); extern int ndis_resume (device_t); -extern struct mtx_pool *ndis_mtxpool; +extern unsigned char drv_data[]; static device_method_t ndis_methods[] = { /* Device interface */ @@ -130,10 +131,11 @@ static devclass_t ndis_devclass; #ifdef NDIS_MODNAME #define NDIS_MODNAME_OVERRIDE_PCMCIA(x) \ - DRIVER_MODULE(x, pccard, ndis_driver, ndis_devclass, 0, 0) + DRIVER_MODULE(x, pccard, ndis_driver, ndis_devclass, \ + ndisdrv_modevent, 0) NDIS_MODNAME_OVERRIDE_PCMCIA(NDIS_MODNAME); #else -DRIVER_MODULE(ndis, pccard, ndis_driver, ndis_devclass, 0, 0); +DRIVER_MODULE(ndis, pccard, ndis_driver, ndis_devclass, ndisdrv_modevent, 0); #endif /* @@ -147,6 +149,13 @@ ndis_probe_pccard(dev) struct ndis_pccard_type *t; const char *prodstr, *vendstr; int error; + driver_object *drv; + vm_offset_t img; + + img = (vm_offset_t)drv_data; + drv = windrv_lookup(img); + if (drv == NULL) + return(ENXIO); t = ndis_devs; @@ -161,6 +170,8 @@ ndis_probe_pccard(dev) if (ndis_strcasecmp(vendstr, t->ndis_vid) == 0 && ndis_strcasecmp(prodstr, t->ndis_did) == 0) { device_set_desc(dev, t->ndis_name); + /* Create PDO for this device instance */ + windrv_create_pdo(drv, dev); return(0); } t++; diff --git a/sys/dev/if_ndis/if_ndis_pci.c b/sys/dev/if_ndis/if_ndis_pci.c index 8af48f4..f24ec70 100644 --- a/sys/dev/if_ndis/if_ndis_pci.c +++ b/sys/dev/if_ndis/if_ndis_pci.c @@ -86,13 +86,14 @@ static int ndis_probe_pci (device_t); static int ndis_attach_pci (device_t); static struct resource_list *ndis_get_resource_list (device_t, device_t); +extern int ndisdrv_modevent (module_t, int, void *); extern int ndis_attach (device_t); extern int ndis_shutdown (device_t); extern int ndis_detach (device_t); extern int ndis_suspend (device_t); extern int ndis_resume (device_t); -extern struct mtx_pool *ndis_mtxpool; +extern unsigned char drv_data[]; static device_method_t ndis_methods[] = { /* Device interface */ @@ -123,14 +124,15 @@ static devclass_t ndis_devclass; #ifdef NDIS_MODNAME #define NDIS_MODNAME_OVERRIDE_PCI(x) \ - DRIVER_MODULE(x, pci, ndis_driver, ndis_devclass, 0, 0) + DRIVER_MODULE(x, pci, ndis_driver, ndis_devclass, ndisdrv_modevent, 0) #define NDIS_MODNAME_OVERRIDE_CARDBUS(x) \ - DRIVER_MODULE(x, cardbus, ndis_driver, ndis_devclass, 0, 0) + DRIVER_MODULE(x, cardbus, ndis_driver, ndis_devclass, \ + ndisdrv_modevent, 0) NDIS_MODNAME_OVERRIDE_PCI(NDIS_MODNAME); NDIS_MODNAME_OVERRIDE_CARDBUS(NDIS_MODNAME); #else -DRIVER_MODULE(ndis, pci, ndis_driver, ndis_devclass, 0, 0); -DRIVER_MODULE(ndis, cardbus, ndis_driver, ndis_devclass, 0, 0); +DRIVER_MODULE(ndis, pci, ndis_driver, ndis_devclass, ndisdrv_modevent, 0); +DRIVER_MODULE(ndis, cardbus, ndis_driver, ndis_devclass, ndisdrv_modevent, 0); #endif /* @@ -142,8 +144,15 @@ ndis_probe_pci(dev) device_t dev; { struct ndis_pci_type *t; + driver_object *drv; + vm_offset_t img; t = ndis_devs; + img = (vm_offset_t)drv_data; + drv = windrv_lookup(img); + + if (drv == NULL) + return(ENXIO); while(t->ndis_name != NULL) { if ((pci_get_vendor(dev) == t->ndis_vid) && @@ -151,6 +160,9 @@ ndis_probe_pci(dev) ((pci_read_config(dev, PCIR_SUBVEND_0, 4) == t->ndis_subsys) || t->ndis_subsys == 0)) { device_set_desc(dev, t->ndis_name); + + /* Create PDO for this device instance */ + windrv_create_pdo(drv, dev); return(0); } t++; diff --git a/sys/dev/if_ndis/if_ndisvar.h b/sys/dev/if_ndis/if_ndisvar.h index 8da9b39..6736024 100644 --- a/sys/dev/if_ndis/if_ndisvar.h +++ b/sys/dev/if_ndis/if_ndisvar.h @@ -62,7 +62,7 @@ struct ndis_cfglist { TAILQ_HEAD(nch, ndis_cfglist); -#define NDIS_INITIALIZED(sc) (sc->ndis_block.nmb_miniportadapterctx != NULL) +#define NDIS_INITIALIZED(sc) (sc->ndis_block->nmb_miniportadapterctx != NULL) #define NDIS_INC(x) \ (x)->ndis_txidx = ((x)->ndis_txidx + 1) % (x)->ndis_maxpkts @@ -97,8 +97,8 @@ struct ndis_softc { struct mtx ndis_intrmtx; device_t ndis_dev; int ndis_unit; - ndis_miniport_block ndis_block; - ndis_miniport_characteristics ndis_chars; + ndis_miniport_block *ndis_block; + ndis_miniport_characteristics *ndis_chars; interface_type ndis_type; struct callout_handle ndis_stat_ch; int ndis_maxpkts; @@ -130,6 +130,7 @@ struct ndis_softc { bus_dmamap_t *ndis_mmaps; bus_dmamap_t *ndis_tmaps; int ndis_mmapcnt; + device_object *ndis_pdo; }; #define NDIS_LOCK(_sc) mtx_lock(&(_sc)->ndis_mtx) diff --git a/sys/modules/ndis/Makefile b/sys/modules/ndis/Makefile index 9d5380b..0090a45 100644 --- a/sys/modules/ndis/Makefile +++ b/sys/modules/ndis/Makefile @@ -4,6 +4,7 @@ KMOD= ndis SRCS= subr_pe.c subr_ndis.c subr_hal.c subr_ntoskrnl.c kern_ndis.c +SRCS+= kern_windrv.c SRCS+= opt_bdg.h device_if.h bus_if.h pci_if.h vnode_if.h .include <bsd.kmod.mk> diff --git a/usr.sbin/ndiscvt/ndiscvt.c b/usr.sbin/ndiscvt/ndiscvt.c index a24711e..b7a3d5c 100644 --- a/usr.sbin/ndiscvt/ndiscvt.c +++ b/usr.sbin/ndiscvt/ndiscvt.c @@ -386,6 +386,7 @@ main(int argc, char *argv[]) fprintf(outfp, "\nextern unsigned char drv_data[];\n\n"); fprintf(outfp, "__asm__(\".data\");\n"); + fprintf(outfp, "__asm__(\".globl drv_data\");\n"); fprintf(outfp, "__asm__(\".type drv_data, @object\");\n"); fprintf(outfp, "__asm__(\".size drv_data, %d\");\n", fsize); fprintf(outfp, "__asm__(\"drv_data:\");\n"); |