diff options
author | wpaul <wpaul@FreeBSD.org> | 2005-02-08 17:23:25 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 2005-02-08 17:23:25 +0000 |
commit | df89b626983fe6b8b3366ad0147e35b1a6a8fd37 (patch) | |
tree | 508b01687ab62847ee4114b92f273c0cdbd4da49 /sys | |
parent | 81617011cd4fc0a322fee7174006255fc9f5e82c (diff) | |
download | FreeBSD-src-df89b626983fe6b8b3366ad0147e35b1a6a8fd37.zip FreeBSD-src-df89b626983fe6b8b3366ad0147e35b1a6a8fd37.tar.gz |
Next step on the road to IRPs: create and use an imitation of the
Windows DRIVER_OBJECT and DEVICE_OBJECT mechanism so that we can
simulate driver stacking.
In Windows, each loaded driver image is attached to a DRIVER_OBJECT
structure. Windows uses the registry to match up a given vendor/device
ID combination with a corresponding DRIVER_OBJECT. When a driver image
is first loaded, its DriverEntry() routine is invoked, which sets up
the AddDevice() function pointer in the DRIVER_OBJECT and creates
a dispatch table (based on IRP major codes). When a Windows bus driver
detects a new device, it creates a Physical Device Object (PDO) for
it. This is a DEVICE_OBJECT structure, with semantics analagous to
that of a device_t in FreeBSD. The Windows PNP manager will invoke
the driver's AddDevice() function and pass it pointers to the DRIVER_OBJECT
and the PDO.
The AddDevice() function then creates a new DRIVER_OBJECT structure of
its own. This is known as the Functional Device Object (FDO) and
corresponds roughly to a private softc instance. The driver uses
IoAttachDeviceToDeviceStack() to add this device object to the
driver stack for this PDO. Subsequent drivers (called filter drivers
in Windows-speak) can be loaded which add themselves to the stack.
When someone issues an IRP to a device, it travel along the stack
passing through several possible filter drivers until it reaches
the functional driver (which actually knows how to talk to the hardware)
at which point it will be completed. This is how Windows achieves
driver layering.
Project Evil now simulates most of this. if_ndis now has a modevent
handler which will use MOD_LOAD and MOD_UNLOAD events to drive the
creation and destruction of DRIVER_OBJECTs. (The load event also
does the relocation/dynalinking of the image.) We don't have a registry,
so the DRIVER_OBJECTS are stored in a linked list for now. Eventually,
the list entry will contain the vendor/device ID list extracted from
the .INF file. When ndis_probe() is called and detectes a supported
device, it will create a PDO for the device instance and attach it
to the DRIVER_OBJECT just as in Windows. ndis_attach() will then call
our NdisAddDevice() handler to create the FDO. The NDIS miniport block
is now a device extension hung off the FDO, just as it is in Windows.
The miniport characteristics table is now an extension hung off the
DRIVER_OBJECT as well (the characteristics are the same for all devices
handled by a given driver, so they don't need to be per-instance.)
We also do an IoAttachDeviceToDeviceStack() to put the FDO on the
stack for the PDO. There are a couple of fake bus drivers created
for the PCI and pccard buses. Eventually, there will be one for USB,
which will actually accept USB IRP.s
Things should still work just as before, only now we do things in
the proper order and maintain the correct framework to support passing
IRPs between drivers.
Various changes:
- corrected the comments about IRQL handling in subr_hal.c to more
accurately reflect reality
- update ndiscvt to make the drv_data symbol in ndis_driver_data.h a
global so that if_ndis_pci.o and/or if_ndis_pccard.o can see it.
- Obtain the softc pointer from the miniport block by referencing
the PDO rather than a private pointer of our own (nmb_ifp is no
longer used)
- implement IoAttachDeviceToDeviceStack(), IoDetachDevice(),
IoGetAttachedDevice(), IoAllocateDriverObjectExtension(),
IoGetDriverObjectExtension(), IoCreateDevice(), IoDeleteDevice(),
IoAllocateIrp(), IoReuseIrp(), IoMakeAssociatedIrp(), IoFreeIrp(),
IoInitializeIrp()
- fix a few mistakes in the driver_object and device_object definitions
- add a new module, kern_windrv.c, to handle the driver registration
and relocation/dynalinkign duties (which don't really belong in
kern_ndis.c).
- made ndis_block and ndis_chars in the ndis_softc stucture pointers
and modified all references to it
- fixed NdisMRegisterMiniport() and NdisInitializeWrapper() so they
work correctly with the new driver_object mechanism
- changed ndis_attach() to call NdisAddDevice() instead of ndis_load_driver()
(which is now deprecated)
- used ExAllocatePoolWithTag()/ExFreePool() in lookaside list routines
instead of kludged up alloc/free routines
- added kern_windrv.c to sys/modules/ndis/Makefile and files.i386.
Diffstat (limited to 'sys')
-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 |
13 files changed, 1488 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> |