From bfc99943b04b46a6c1c885ce7bcc6f235b7422aa Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Mon, 25 Jan 2021 21:45:03 +0000 Subject: [PATCH] ndis(4): remove as previous announced nids(4) was a clever idea in the early 2000's when the market was flooded with 10/100 NICs with Windows-only drivers, but that hasn't been the case for ages and the driver has had no meaningful maintenance in ages. It only supports Windows-XP era drivers. Also remove: - ndis support from wpa_supplicant - ndiscvt(8) Reviewed By: emaste, bcr (manpages) Differential Revision: https://reviews.freebsd.org/D27609 --- ObsoleteFiles.inc | 9 + share/man/man4/Makefile | 4 - share/man/man4/ndis.4 | 155 - sys/compat/ndis/cfg_var.h | 49 - sys/compat/ndis/hal_var.h | 55 - sys/compat/ndis/kern_ndis.c | 1447 ------ sys/compat/ndis/kern_windrv.c | 1170 ----- sys/compat/ndis/ndis_var.h | 1763 -------- sys/compat/ndis/ntoskrnl_var.h | 1517 ------- sys/compat/ndis/pe_var.h | 555 --- sys/compat/ndis/resource_var.h | 201 - sys/compat/ndis/subr_hal.c | 482 -- sys/compat/ndis/subr_ndis.c | 3372 -------------- sys/compat/ndis/subr_ntoskrnl.c | 4446 ------------------- sys/compat/ndis/subr_pe.c | 644 --- sys/compat/ndis/subr_usbd.c | 1461 ------ sys/compat/ndis/usbd_var.h | 224 - sys/compat/ndis/winx32_wrap.S | 385 -- sys/compat/ndis/winx64_wrap.S | 179 - sys/conf/files.amd64 | 1 - sys/conf/files.i386 | 1 - sys/conf/files.x86 | 10 - sys/dev/if_ndis/if_ndis.c | 3423 -------------- sys/dev/if_ndis/if_ndis_pci.c | 357 -- sys/dev/if_ndis/if_ndis_usb.c | 240 - sys/dev/if_ndis/if_ndisvar.h | 263 -- sys/modules/Makefile | 4 - sys/modules/if_ndis/Makefile | 10 - targets/pseudo/userland/Makefile.depend | 3 - tools/build/mk/OptionalObsoleteFiles.inc | 8 - tools/kerneldoc/subsys/Doxyfile-dev_if_ndis | 21 - usr.sbin/Makefile.amd64 | 3 - usr.sbin/Makefile.i386 | 3 - usr.sbin/ndiscvt/Makefile | 27 - usr.sbin/ndiscvt/Makefile.depend | 19 - usr.sbin/ndiscvt/inf-parse.y | 112 - usr.sbin/ndiscvt/inf-token.l | 134 - usr.sbin/ndiscvt/inf.c | 920 ---- usr.sbin/ndiscvt/inf.h | 61 - usr.sbin/ndiscvt/ndiscvt.8 | 283 -- usr.sbin/ndiscvt/ndiscvt.c | 436 -- usr.sbin/ndiscvt/ndisgen.8 | 86 - usr.sbin/ndiscvt/ndisgen.sh | 556 --- usr.sbin/ndiscvt/windrv_stub.c | 268 -- usr.sbin/wpa/Makefile | 1 - usr.sbin/wpa/ndis_events/Makefile | 8 - usr.sbin/wpa/ndis_events/Makefile.depend | 18 - usr.sbin/wpa/ndis_events/ndis_events.8 | 135 - usr.sbin/wpa/ndis_events/ndis_events.c | 353 -- usr.sbin/wpa/wpa_supplicant/Makefile | 6 +- usr.sbin/wpa/wpa_supplicant/Packet32.c | 415 -- usr.sbin/wpa/wpa_supplicant/Packet32.h | 69 - usr.sbin/wpa/wpa_supplicant/ntddndis.h | 31 - 53 files changed, 11 insertions(+), 26392 deletions(-) delete mode 100644 share/man/man4/ndis.4 delete mode 100644 sys/compat/ndis/cfg_var.h delete mode 100644 sys/compat/ndis/hal_var.h delete mode 100644 sys/compat/ndis/kern_ndis.c delete mode 100644 sys/compat/ndis/kern_windrv.c delete mode 100644 sys/compat/ndis/ndis_var.h delete mode 100644 sys/compat/ndis/ntoskrnl_var.h delete mode 100644 sys/compat/ndis/pe_var.h delete mode 100644 sys/compat/ndis/resource_var.h delete mode 100644 sys/compat/ndis/subr_hal.c delete mode 100644 sys/compat/ndis/subr_ndis.c delete mode 100644 sys/compat/ndis/subr_ntoskrnl.c delete mode 100644 sys/compat/ndis/subr_pe.c delete mode 100644 sys/compat/ndis/subr_usbd.c delete mode 100644 sys/compat/ndis/usbd_var.h delete mode 100644 sys/compat/ndis/winx32_wrap.S delete mode 100644 sys/compat/ndis/winx64_wrap.S delete mode 100644 sys/dev/if_ndis/if_ndis.c delete mode 100644 sys/dev/if_ndis/if_ndis_pci.c delete mode 100644 sys/dev/if_ndis/if_ndis_usb.c delete mode 100644 sys/dev/if_ndis/if_ndisvar.h delete mode 100644 sys/modules/if_ndis/Makefile delete mode 100644 tools/kerneldoc/subsys/Doxyfile-dev_if_ndis delete mode 100644 usr.sbin/ndiscvt/Makefile delete mode 100644 usr.sbin/ndiscvt/Makefile.depend delete mode 100644 usr.sbin/ndiscvt/inf-parse.y delete mode 100644 usr.sbin/ndiscvt/inf-token.l delete mode 100644 usr.sbin/ndiscvt/inf.c delete mode 100644 usr.sbin/ndiscvt/inf.h delete mode 100644 usr.sbin/ndiscvt/ndiscvt.8 delete mode 100644 usr.sbin/ndiscvt/ndiscvt.c delete mode 100644 usr.sbin/ndiscvt/ndisgen.8 delete mode 100644 usr.sbin/ndiscvt/ndisgen.sh delete mode 100644 usr.sbin/ndiscvt/windrv_stub.c delete mode 100644 usr.sbin/wpa/ndis_events/Makefile delete mode 100644 usr.sbin/wpa/ndis_events/Makefile.depend delete mode 100644 usr.sbin/wpa/ndis_events/ndis_events.8 delete mode 100644 usr.sbin/wpa/ndis_events/ndis_events.c delete mode 100644 usr.sbin/wpa/wpa_supplicant/Packet32.c delete mode 100644 usr.sbin/wpa/wpa_supplicant/Packet32.h delete mode 100644 usr.sbin/wpa/wpa_supplicant/ntddndis.h diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 1d0766ec894a..29cf25e152e6 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -36,6 +36,15 @@ # xargs -n1 | sort | uniq -d; # done +# 20210125: ndis driver support removed +OLD_FILES+=usr/sbin/ndiscvt +OLD_FILES+=usr/sbin/ndisgen +OLD_FILES+=usr/share/man/man4/ndis.4.gz +OLD_FILES+=usr/share/man/man4/if_ndis.4.gz +OLD_FILES+=usr/share/man/man8/ndiscvt.8.gz +OLD_FILES+=usr/share/man/man8/ndisgen.8.gz +OLD_FILES+=usr/share/misc/windrv_stub.c + # 20210116: if_wl_wavelan.h removed .if ${TARGET_ARCH} == "i386" OLD_FILES+=usr/include/machine/if_wl_wavelan.h diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 10034a72d608..65f8bc817db3 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -325,7 +325,6 @@ MAN= aac.4 \ mx25l.4 \ mxge.4 \ my.4 \ - ${_ndis.4} \ net80211.4 \ netdump.4 \ netfpga10g_nf10bmac.4 \ @@ -715,7 +714,6 @@ MLINKS+=msk.4 if_msk.4 MLINKS+=mwl.4 if_mwl.4 MLINKS+=mxge.4 if_mxge.4 MLINKS+=my.4 if_my.4 -MLINKS+=${_ndis.4} ${_if_ndis.4} MLINKS+=netfpga10g_nf10bmac.4 if_nf10bmac.4 MLINKS+=netintro.4 net.4 \ netintro.4 networking.4 @@ -815,7 +813,6 @@ _hwpstate_intel.4= hwpstate_intel.4 _i8254.4= i8254.4 _ichwd.4= ichwd.4 _if_bxe.4= if_bxe.4 -_if_ndis.4= if_ndis.4 _if_nfe.4= if_nfe.4 _if_urtw.4= if_urtw.4 _if_vmx.4= if_vmx.4 @@ -826,7 +823,6 @@ _io.4= io.4 _itwd.4= itwd.4 _linux.4= linux.4 _nda.4= nda.4 -_ndis.4= ndis.4 _nfe.4= nfe.4 _nfsmb.4= nfsmb.4 _if_ntb.4= if_ntb.4 diff --git a/share/man/man4/ndis.4 b/share/man/man4/ndis.4 deleted file mode 100644 index 0a1ae39bff62..000000000000 --- a/share/man/man4/ndis.4 +++ /dev/null @@ -1,155 +0,0 @@ -.\" Copyright (c) 2003 -.\" Bill Paul . All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by Bill Paul. -.\" 4. Neither the name of the author nor the names of any co-contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD -.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -.\" THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd March 14, 2010 -.Dt NDIS 4 -.Os -.Sh NAME -.Nm ndis -.Nd NDIS miniport driver wrapper -.Sh SYNOPSIS -.Cd "options NDISAPI" -.Cd "device ndis" -.Cd "device wlan" -.Sh DESCRIPTION -The -.Nm -driver is a wrapper designed to allow binary -.Tn Windows\[rg] -NDIS miniport -network drivers to be used with -.Fx . -The -.Nm -driver is provided in source code form and must be combined with -the -.Tn Windows\[rg] -driver supplied with your network adapter. -The -.Nm -driver uses the -.Nm ndisapi -kernel subsystem to relocate and link the -.Tn Windows\[rg] -binary so -that it can be used in conjunction with native code. -The -.Nm ndisapi -subsystem provides an interface between the NDIS API and the -.Fx -networking infrastructure. -The -.Tn Windows\[rg] -driver is essentially -fooled into thinking it is running on -.Tn Windows\[rg] . -Note that this -means the -.Nm -driver is only useful on x86 machines. -.Pp -To build a functional driver, the user must have a copy of the -driver distribution media for his or her card. -From this distribution, -the user must extract two files: the -.Pa .SYS -file containing the driver -binary code, and its companion -.Pa .INF -file, which contains the -definitions for driver-specific registry keys and other installation -data such as device identifiers. -These two files can be converted -into a kernel module file using the -.Xr ndisgen 8 -utility. -This file contains a binary image of the driver plus -registry key data. -When the -.Nm -driver loads, it will create -.Xr sysctl 3 -nodes for each registry key extracted from the -.Pa .INF -file. -.Pp -The -.Nm -driver is designed to support mainly Ethernet and wireless -network devices with PCI and USB bus attachments. -(Cardbus devices are also supported as PCI.) -It can -support many different media types and speeds. -One limitation -however, is that there is no consistent way to learn if an -Ethernet device is operating in full or half duplex mode. -The NDIS API allows for a generic means for determining link -state and speed, but not the duplex setting. -There may be -driver-specific registry keys to control the media setting -which can be configured via the -.Xr sysctl 8 -command. -.Sh DEPRECATION NOTICE -This driver is scheduled for removal prior to the release of -.Fx 14.0 -.Sh DIAGNOSTICS -.Bl -diag -.It "ndis%d: watchdog timeout" -A packet was queued for transmission and a transmit command was -issued, however the device failed to acknowledge the transmission -before a timeout expired. -.El -.Sh SEE ALSO -.Xr altq 4 , -.Xr arp 4 , -.Xr netintro 4 , -.Xr ng_ether 4 , -.Xr ifconfig 8 , -.Xr ndis_events 8 , -.Xr ndiscvt 8 , -.Xr ndisgen 8 , -.Xr wpa_supplicant 8 -.Rs -.%T "NDIS 5.1 specification" -.%U http://www.microsoft.com -.Re -.Sh HISTORY -The -.Nm -device driver first appeared in -.Fx 5.3 . -.Sh AUTHORS -The -.Nm -driver was written by -.An Bill Paul Aq Mt wpaul@windriver.com . diff --git a/sys/compat/ndis/cfg_var.h b/sys/compat/ndis/cfg_var.h deleted file mode 100644 index ff40a85926be..000000000000 --- a/sys/compat/ndis/cfg_var.h +++ /dev/null @@ -1,49 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul . All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _CFG_VAR_H_ -#define _CFG_VAR_H_ - -struct ndis_cfg { - char *nc_cfgkey; - char *nc_cfgdesc; - char nc_val[256]; - int nc_idx; -}; - -typedef struct ndis_cfg ndis_cfg; - -#endif /* _CFG_VAR_H_ */ diff --git a/sys/compat/ndis/hal_var.h b/sys/compat/ndis/hal_var.h deleted file mode 100644 index f8864e2e7071..000000000000 --- a/sys/compat/ndis/hal_var.h +++ /dev/null @@ -1,55 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul . All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _HAL_VAR_H_ -#define _HAL_VAR_H_ - -#define NDIS_BUS_SPACE_IO X86_BUS_SPACE_IO -#define NDIS_BUS_SPACE_MEM X86_BUS_SPACE_MEM - -extern image_patch_table hal_functbl[]; - -__BEGIN_DECLS -extern int hal_libinit(void); -extern int hal_libfini(void); -extern uint8_t KfAcquireSpinLock(kspin_lock *); -extern void KfReleaseSpinLock(kspin_lock *, uint8_t); -extern uint8_t KfRaiseIrql(uint8_t); -extern void KfLowerIrql(uint8_t); -extern uint8_t KeGetCurrentIrql(void); -__END_DECLS - -#endif /* _HAL_VAR_H_ */ diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c deleted file mode 100644 index 153849fa1cf6..000000000000 --- a/sys/compat/ndis/kern_ndis.c +++ /dev/null @@ -1,1447 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul . 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#define NDIS_DUMMY_PATH "\\\\some\\bogus\\path" -#define NDIS_FLAG_RDONLY 1 - -static void ndis_status_func(ndis_handle, ndis_status, void *, uint32_t); -static void ndis_statusdone_func(ndis_handle); -static void ndis_setdone_func(ndis_handle, ndis_status); -static void ndis_getdone_func(ndis_handle, ndis_status); -static void ndis_resetdone_func(ndis_handle, ndis_status, uint8_t); -static void ndis_sendrsrcavail_func(ndis_handle); -static void ndis_intrsetup(kdpc *, device_object *, - irp *, struct ndis_softc *); -static void ndis_return(device_object *, void *); - -static image_patch_table kernndis_functbl[] = { - IMPORT_SFUNC(ndis_status_func, 4), - IMPORT_SFUNC(ndis_statusdone_func, 1), - IMPORT_SFUNC(ndis_setdone_func, 2), - IMPORT_SFUNC(ndis_getdone_func, 2), - IMPORT_SFUNC(ndis_resetdone_func, 3), - IMPORT_SFUNC(ndis_sendrsrcavail_func, 1), - IMPORT_SFUNC(ndis_intrsetup, 4), - IMPORT_SFUNC(ndis_return, 1), - { NULL, NULL, NULL } -}; - -static struct nd_head ndis_devhead; - -/* - * This allows us to export our symbols to other modules. - * Note that we call ourselves 'ndisapi' to avoid a namespace - * collision with if_ndis.ko, which internally calls itself - * 'ndis.' - * - * Note: some of the subsystems depend on each other, so the - * order in which they're started is important. The order of - * importance is: - * - * HAL - spinlocks and IRQL manipulation - * ntoskrnl - DPC and workitem threads, object waiting - * windrv - driver/device registration - * - * The HAL should also be the last thing shut down, since - * the ntoskrnl subsystem will use spinlocks right up until - * the DPC and workitem threads are terminated. - */ - -static int -ndis_modevent(module_t mod, int cmd, void *arg) -{ - int error = 0; - image_patch_table *patch; - - switch (cmd) { - case MOD_LOAD: - /* Initialize subsystems */ - hal_libinit(); - ntoskrnl_libinit(); - windrv_libinit(); - ndis_libinit(); - usbd_libinit(); - - patch = kernndis_functbl; - while (patch->ipt_func != NULL) { - windrv_wrap((funcptr)patch->ipt_func, - (funcptr *)&patch->ipt_wrap, - patch->ipt_argcnt, patch->ipt_ftype); - patch++; - } - - TAILQ_INIT(&ndis_devhead); - break; - case MOD_SHUTDOWN: - if (TAILQ_FIRST(&ndis_devhead) == NULL) { - /* Shut down subsystems */ - ndis_libfini(); - usbd_libfini(); - windrv_libfini(); - ntoskrnl_libfini(); - hal_libfini(); - - patch = kernndis_functbl; - while (patch->ipt_func != NULL) { - windrv_unwrap(patch->ipt_wrap); - patch++; - } - } - break; - case MOD_UNLOAD: - /* Shut down subsystems */ - ndis_libfini(); - usbd_libfini(); - windrv_libfini(); - ntoskrnl_libfini(); - hal_libfini(); - - patch = kernndis_functbl; - while (patch->ipt_func != NULL) { - windrv_unwrap(patch->ipt_wrap); - patch++; - } - - break; - default: - error = EINVAL; - break; - } - - return (error); -} -DEV_MODULE(ndisapi, ndis_modevent, NULL); -MODULE_VERSION(ndisapi, 1); - -static void -ndis_sendrsrcavail_func(adapter) - ndis_handle adapter; -{ -} - -static void -ndis_status_func(adapter, status, sbuf, slen) - ndis_handle adapter; - ndis_status status; - void *sbuf; - uint32_t slen; -{ - ndis_miniport_block *block; - struct ndis_softc *sc; - struct ifnet *ifp; - - block = adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - ifp = NDISUSB_GET_IFNET(sc); - if ( ifp && ifp->if_flags & IFF_DEBUG) - device_printf(sc->ndis_dev, "status: %x\n", status); -} - -static void -ndis_statusdone_func(adapter) - ndis_handle adapter; -{ - ndis_miniport_block *block; - struct ndis_softc *sc; - struct ifnet *ifp; - - block = adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - ifp = NDISUSB_GET_IFNET(sc); - if (ifp && ifp->if_flags & IFF_DEBUG) - device_printf(sc->ndis_dev, "status complete\n"); -} - -static void -ndis_setdone_func(adapter, status) - ndis_handle adapter; - ndis_status status; -{ - ndis_miniport_block *block; - block = adapter; - - block->nmb_setstat = status; - KeSetEvent(&block->nmb_setevent, IO_NO_INCREMENT, FALSE); -} - -static void -ndis_getdone_func(adapter, status) - ndis_handle adapter; - ndis_status status; -{ - ndis_miniport_block *block; - block = adapter; - - block->nmb_getstat = status; - KeSetEvent(&block->nmb_getevent, IO_NO_INCREMENT, FALSE); -} - -static void -ndis_resetdone_func(ndis_handle adapter, ndis_status status, - 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 = NDISUSB_GET_IFNET(sc); - - if (ifp && ifp->if_flags & IFF_DEBUG) - device_printf(sc->ndis_dev, "reset done...\n"); - KeSetEvent(&block->nmb_resetevent, IO_NO_INCREMENT, FALSE); -} - -int -ndis_create_sysctls(arg) - void *arg; -{ - struct ndis_softc *sc; - ndis_cfg *vals; - char buf[256]; - struct sysctl_oid *oidp; - struct sysctl_ctx_entry *e; - - if (arg == NULL) - return (EINVAL); - - sc = arg; - /* - device_printf(sc->ndis_dev, "ndis_create_sysctls() sc=%p\n", sc); - */ - vals = sc->ndis_regvals; - - TAILQ_INIT(&sc->ndis_cfglist_head); - - /* Add the driver-specific registry keys. */ - - while(1) { - if (vals->nc_cfgkey == NULL) - break; - - if (vals->nc_idx != sc->ndis_devidx) { - vals++; - continue; - } - - /* See if we already have a sysctl with this name */ - - oidp = NULL; - TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) { - oidp = e->entry; - if (strcasecmp(oidp->oid_name, vals->nc_cfgkey) == 0) - break; - oidp = NULL; - } - - if (oidp != NULL) { - vals++; - continue; - } - - ndis_add_sysctl(sc, vals->nc_cfgkey, vals->nc_cfgdesc, - vals->nc_val, CTLFLAG_RW); - vals++; - } - - /* Now add a couple of builtin keys. */ - - /* - * Environment can be either Windows (0) or WindowsNT (1). - * We qualify as the latter. - */ - ndis_add_sysctl(sc, "Environment", - "Windows environment", "1", NDIS_FLAG_RDONLY); - - /* NDIS version should be 5.1. */ - ndis_add_sysctl(sc, "NdisVersion", - "NDIS API Version", "0x00050001", NDIS_FLAG_RDONLY); - - /* - * Some miniport drivers rely on the existence of the SlotNumber, - * NetCfgInstanceId and DriverDesc keys. - */ - ndis_add_sysctl(sc, "SlotNumber", "Slot Numer", "01", NDIS_FLAG_RDONLY); - ndis_add_sysctl(sc, "NetCfgInstanceId", "NetCfgInstanceId", - "{12345678-1234-5678-CAFE0-123456789ABC}", NDIS_FLAG_RDONLY); - ndis_add_sysctl(sc, "DriverDesc", "Driver Description", - "NDIS Network Adapter", NDIS_FLAG_RDONLY); - - /* Bus type (PCI, PCMCIA, etc...) */ - sprintf(buf, "%d", (int)sc->ndis_iftype); - ndis_add_sysctl(sc, "BusType", "Bus Type", buf, NDIS_FLAG_RDONLY); - - if (sc->ndis_res_io != NULL) { - sprintf(buf, "0x%jx", rman_get_start(sc->ndis_res_io)); - ndis_add_sysctl(sc, "IOBaseAddress", - "Base I/O Address", buf, NDIS_FLAG_RDONLY); - } - - if (sc->ndis_irq != NULL) { - sprintf(buf, "%ju", rman_get_start(sc->ndis_irq)); - ndis_add_sysctl(sc, "InterruptNumber", - "Interrupt Number", buf, NDIS_FLAG_RDONLY); - } - - return (0); -} - -int -ndis_add_sysctl(arg, key, desc, val, flag_rdonly) - void *arg; - char *key; - char *desc; - char *val; - int flag_rdonly; -{ - struct ndis_softc *sc; - struct ndis_cfglist *cfg; - char descstr[256]; - - sc = arg; - - cfg = malloc(sizeof(struct ndis_cfglist), M_DEVBUF, M_NOWAIT|M_ZERO); - - if (cfg == NULL) { - printf("failed for %s\n", key); - return (ENOMEM); - } - - cfg->ndis_cfg.nc_cfgkey = strdup(key, M_DEVBUF); - if (desc == NULL) { - snprintf(descstr, sizeof(descstr), "%s (dynamic)", key); - cfg->ndis_cfg.nc_cfgdesc = strdup(descstr, M_DEVBUF); - } else - cfg->ndis_cfg.nc_cfgdesc = strdup(desc, M_DEVBUF); - strcpy(cfg->ndis_cfg.nc_val, val); - - TAILQ_INSERT_TAIL(&sc->ndis_cfglist_head, cfg, link); - - if (flag_rdonly != 0) { - cfg->ndis_oid = - SYSCTL_ADD_STRING(device_get_sysctl_ctx(sc->ndis_dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(sc->ndis_dev)), - OID_AUTO, cfg->ndis_cfg.nc_cfgkey, CTLFLAG_RD, - cfg->ndis_cfg.nc_val, sizeof(cfg->ndis_cfg.nc_val), - cfg->ndis_cfg.nc_cfgdesc); - } else { - cfg->ndis_oid = - SYSCTL_ADD_STRING(device_get_sysctl_ctx(sc->ndis_dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(sc->ndis_dev)), - OID_AUTO, cfg->ndis_cfg.nc_cfgkey, CTLFLAG_RW, - cfg->ndis_cfg.nc_val, sizeof(cfg->ndis_cfg.nc_val), - cfg->ndis_cfg.nc_cfgdesc); - } - return (0); -} - -/* - * Somewhere, somebody decided "hey, let's automatically create - * a sysctl tree for each device instance as it's created -- it'll - * make life so much easier!" Lies. Why must they turn the kernel - * into a house of lies? - */ - -int -ndis_flush_sysctls(arg) - void *arg; -{ - struct ndis_softc *sc; - struct ndis_cfglist *cfg; - struct sysctl_ctx_list *clist; - - sc = arg; - - clist = device_get_sysctl_ctx(sc->ndis_dev); - - while (!TAILQ_EMPTY(&sc->ndis_cfglist_head)) { - cfg = TAILQ_FIRST(&sc->ndis_cfglist_head); - TAILQ_REMOVE(&sc->ndis_cfglist_head, cfg, link); - sysctl_ctx_entry_del(clist, cfg->ndis_oid); - sysctl_remove_oid(cfg->ndis_oid, 1, 0); - free(cfg->ndis_cfg.nc_cfgkey, M_DEVBUF); - free(cfg->ndis_cfg.nc_cfgdesc, M_DEVBUF); - free(cfg, M_DEVBUF); - } - - return (0); -} - -void * -ndis_get_routine_address(functbl, name) - struct image_patch_table *functbl; - char *name; -{ - int i; - - for (i = 0; functbl[i].ipt_name != NULL; i++) - if (strcmp(name, functbl[i].ipt_name) == 0) - return (functbl[i].ipt_wrap); - return (NULL); -} - -static void -ndis_return(dobj, arg) - device_object *dobj; - void *arg; -{ - ndis_miniport_block *block; - ndis_miniport_characteristics *ch; - ndis_return_handler returnfunc; - ndis_handle adapter; - ndis_packet *p; - uint8_t irql; - list_entry *l; - - block = arg; - ch = IoGetDriverObjectExtension(dobj->do_drvobj, (void *)1); - - p = arg; - adapter = block->nmb_miniportadapterctx; - - if (adapter == NULL) - return; - - returnfunc = ch->nmc_return_packet_func; - - KeAcquireSpinLock(&block->nmb_returnlock, &irql); - while (!IsListEmpty(&block->nmb_returnlist)) { - l = RemoveHeadList((&block->nmb_returnlist)); - p = CONTAINING_RECORD(l, ndis_packet, np_list); - InitializeListHead((&p->np_list)); - KeReleaseSpinLock(&block->nmb_returnlock, irql); - MSCALL2(returnfunc, adapter, p); - KeAcquireSpinLock(&block->nmb_returnlock, &irql); - } - KeReleaseSpinLock(&block->nmb_returnlock, irql); -} - -static void -ndis_ext_free(struct mbuf *m) -{ - - return (ndis_return_packet(m->m_ext.ext_arg1)); -} - -void -ndis_return_packet(ndis_packet *p) -{ - ndis_miniport_block *block; - - if (p == NULL) - return; - - /* Decrement refcount. */ - p->np_refcnt--; - - /* Release packet when refcount hits zero, otherwise return. */ - if (p->np_refcnt) - return; - - block = ((struct ndis_softc *)p->np_softc)->ndis_block; - - KeAcquireSpinLockAtDpcLevel(&block->nmb_returnlock); - InitializeListHead((&p->np_list)); - InsertHeadList((&block->nmb_returnlist), (&p->np_list)); - KeReleaseSpinLockFromDpcLevel(&block->nmb_returnlock); - - IoQueueWorkItem(block->nmb_returnitem, - (io_workitem_func)kernndis_functbl[7].ipt_wrap, - WORKQUEUE_CRITICAL, block); -} - -void -ndis_free_bufs(b0) - ndis_buffer *b0; -{ - ndis_buffer *next; - - if (b0 == NULL) - return; - - while(b0 != NULL) { - next = b0->mdl_next; - IoFreeMdl(b0); - b0 = next; - } -} - -void -ndis_free_packet(p) - ndis_packet *p; -{ - if (p == NULL) - return; - - ndis_free_bufs(p->np_private.npp_head); - NdisFreePacket(p); -} - -int -ndis_convert_res(arg) - void *arg; -{ - struct ndis_softc *sc; - ndis_resource_list *rl = NULL; - cm_partial_resource_desc *prd = NULL; - ndis_miniport_block *block; - device_t dev; - struct resource_list *brl; - struct resource_list_entry *brle; - int error = 0; - - sc = arg; - block = sc->ndis_block; - dev = sc->ndis_dev; - - rl = malloc(sizeof(ndis_resource_list) + - (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)), - M_DEVBUF, M_NOWAIT|M_ZERO); - - if (rl == NULL) - return (ENOMEM); - - rl->cprl_version = 5; - rl->cprl_revision = 1; - rl->cprl_count = sc->ndis_rescnt; - prd = rl->cprl_partial_descs; - - brl = BUS_GET_RESOURCE_LIST(dev, dev); - - if (brl != NULL) { - STAILQ_FOREACH(brle, brl, link) { - switch (brle->type) { - case SYS_RES_IOPORT: - prd->cprd_type = CmResourceTypePort; - prd->cprd_flags = CM_RESOURCE_PORT_IO; - prd->cprd_sharedisp = - CmResourceShareDeviceExclusive; - prd->u.cprd_port.cprd_start.np_quad = - brle->start; - prd->u.cprd_port.cprd_len = brle->count; - break; - case SYS_RES_MEMORY: - prd->cprd_type = CmResourceTypeMemory; - prd->cprd_flags = - CM_RESOURCE_MEMORY_READ_WRITE; - prd->cprd_sharedisp = - CmResourceShareDeviceExclusive; - prd->u.cprd_mem.cprd_start.np_quad = - brle->start; - prd->u.cprd_mem.cprd_len = brle->count; - break; - case SYS_RES_IRQ: - prd->cprd_type = CmResourceTypeInterrupt; - prd->cprd_flags = 0; - /* - * Always mark interrupt resources as - * shared, since in our implementation, - * they will be. - */ - prd->cprd_sharedisp = - CmResourceShareShared; - prd->u.cprd_intr.cprd_level = brle->start; - prd->u.cprd_intr.cprd_vector = brle->start; - prd->u.cprd_intr.cprd_affinity = 0; - break; - default: - break; - } - prd++; - } - } - - block->nmb_rlist = rl; - - return (error); -} - -/* - * Map an NDIS packet to an mbuf list. When an NDIS driver receives a - * packet, it will hand it to us in the form of an ndis_packet, - * which we need to convert to an mbuf that is then handed off - * to the stack. Note: we configure the mbuf list so that it uses - * the memory regions specified by the ndis_buffer structures in - * the ndis_packet as external storage. In most cases, this will - * point to a memory region allocated by the driver (either by - * ndis_malloc_withtag() or ndis_alloc_sharedmem()). We expect - * the driver to handle free()ing this region for is, so we set up - * a dummy no-op free handler for it. - */ - -int -ndis_ptom(m0, p) - struct mbuf **m0; - ndis_packet *p; -{ - struct mbuf *m = NULL, *prev = NULL; - ndis_buffer *buf; - ndis_packet_private *priv; - uint32_t totlen = 0; - struct ifnet *ifp; - struct ether_header *eh; - int diff; - - if (p == NULL || m0 == NULL) - return (EINVAL); - - priv = &p->np_private; - buf = priv->npp_head; - p->np_refcnt = 0; - - for (buf = priv->npp_head; buf != NULL; buf = buf->mdl_next) { - if (buf == priv->npp_head) - m = m_gethdr(M_NOWAIT, MT_DATA); - else - m = m_get(M_NOWAIT, MT_DATA); - if (m == NULL) { - m_freem(*m0); - *m0 = NULL; - return (ENOBUFS); - } - m->m_len = MmGetMdlByteCount(buf); - m_extadd(m, MmGetMdlVirtualAddress(buf), m->m_len, - ndis_ext_free, p, NULL, 0, EXT_NDIS); - p->np_refcnt++; - - totlen += m->m_len; - if (m->m_flags & M_PKTHDR) - *m0 = m; - else - prev->m_next = m; - prev = m; - } - - /* - * This is a hack to deal with the Marvell 8335 driver - * which, when associated with an AP in WPA-PSK mode, - * seems to overpad its frames by 8 bytes. I don't know - * that the extra 8 bytes are for, and they're not there - * in open mode, so for now clamp the frame size at 1514 - * until I can figure out how to deal with this properly, - * otherwise if_ethersubr() will spank us by discarding - * the 'oversize' frames. - */ - - eh = mtod((*m0), struct ether_header *); - ifp = NDISUSB_GET_IFNET((struct ndis_softc *)p->np_softc); - if (ifp && totlen > ETHER_MAX_FRAME(ifp, eh->ether_type, FALSE)) { - diff = totlen - ETHER_MAX_FRAME(ifp, eh->ether_type, FALSE); - totlen -= diff; - m->m_len -= diff; - } - (*m0)->m_pkthdr.len = totlen; - - return (0); -} - -/* - * Create an NDIS packet from an mbuf chain. - * This is used mainly when transmitting packets, where we need - * to turn an mbuf off an interface's send queue and transform it - * into an NDIS packet which will be fed into the NDIS driver's - * send routine. - * - * NDIS packets consist of two parts: an ndis_packet structure, - * which is vaguely analogous to the pkthdr portion of an mbuf, - * and one or more ndis_buffer structures, which define the - * actual memory segments in which the packet data resides. - * We need to allocate one ndis_buffer for each mbuf in a chain, - * plus one ndis_packet as the header. - */ - -int -ndis_mtop(m0, p) - struct mbuf *m0; - ndis_packet **p; -{ - struct mbuf *m; - ndis_buffer *buf = NULL, *prev = NULL; - ndis_packet_private *priv; - - if (p == NULL || *p == NULL || m0 == NULL) - return (EINVAL); - - priv = &(*p)->np_private; - priv->npp_totlen = m0->m_pkthdr.len; - - for (m = m0; m != NULL; m = m->m_next) { - if (m->m_len == 0) - continue; - buf = IoAllocateMdl(m->m_data, m->m_len, FALSE, FALSE, NULL); - if (buf == NULL) { - ndis_free_packet(*p); - *p = NULL; - return (ENOMEM); - } - MmBuildMdlForNonPagedPool(buf); - - if (priv->npp_head == NULL) - priv->npp_head = buf; - else - prev->mdl_next = buf; - prev = buf; - } - - priv->npp_tail = buf; - - return (0); -} - -int -ndis_get_supported_oids(arg, oids, oidcnt) - void *arg; - ndis_oid **oids; - int *oidcnt; -{ - int len, rval; - ndis_oid *o; - - if (arg == NULL || oids == NULL || oidcnt == NULL) - return (EINVAL); - len = 0; - ndis_get_info(arg, OID_GEN_SUPPORTED_LIST, NULL, &len); - - o = malloc(len, M_DEVBUF, M_NOWAIT); - if (o == NULL) - return (ENOMEM); - - rval = ndis_get_info(arg, OID_GEN_SUPPORTED_LIST, o, &len); - - if (rval) { - free(o, M_DEVBUF); - return (rval); - } - - *oids = o; - *oidcnt = len / 4; - - return (0); -} - -int -ndis_set_info(arg, oid, buf, buflen) - void *arg; - ndis_oid oid; - void *buf; - int *buflen; -{ - struct ndis_softc *sc; - ndis_status rval; - ndis_handle adapter; - ndis_setinfo_handler setfunc; - uint32_t byteswritten = 0, bytesneeded = 0; - uint8_t irql; - uint64_t duetime; - - /* - * According to the NDIS spec, MiniportQueryInformation() - * and MiniportSetInformation() requests are handled serially: - * once one request has been issued, we must wait for it to - * finish before allowing another request to proceed. - */ - - sc = arg; - - KeResetEvent(&sc->ndis_block->nmb_setevent); - - KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql); - - if (sc->ndis_block->nmb_pendingreq != NULL) { - KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql); - panic("ndis_set_info() called while other request pending"); - } else - sc->ndis_block->nmb_pendingreq = (ndis_request *)sc; - - setfunc = sc->ndis_chars->nmc_setinfo_func; - adapter = sc->ndis_block->nmb_miniportadapterctx; - - if (adapter == NULL || setfunc == NULL || - sc->ndis_block->nmb_devicectx == NULL) { - sc->ndis_block->nmb_pendingreq = NULL; - KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql); - return (ENXIO); - } - - rval = MSCALL6(setfunc, adapter, oid, buf, *buflen, - &byteswritten, &bytesneeded); - - sc->ndis_block->nmb_pendingreq = NULL; - - KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql); - - if (rval == NDIS_STATUS_PENDING) { - /* Wait up to 5 seconds. */ - duetime = (5 * 1000000) * -10; - KeWaitForSingleObject(&sc->ndis_block->nmb_setevent, - 0, 0, FALSE, &duetime); - rval = sc->ndis_block->nmb_setstat; - } - - if (byteswritten) - *buflen = byteswritten; - if (bytesneeded) - *buflen = bytesneeded; - - if (rval == NDIS_STATUS_INVALID_LENGTH) - return (ENOSPC); - - if (rval == NDIS_STATUS_INVALID_OID) - return (EINVAL); - - if (rval == NDIS_STATUS_NOT_SUPPORTED || - rval == NDIS_STATUS_NOT_ACCEPTED) - return (ENOTSUP); - - if (rval != NDIS_STATUS_SUCCESS) - return (ENODEV); - - return (0); -} - -typedef void (*ndis_senddone_func)(ndis_handle, ndis_packet *, ndis_status); - -int -ndis_send_packets(arg, packets, cnt) - void *arg; - ndis_packet **packets; - int cnt; -{ - struct ndis_softc *sc; - ndis_handle adapter; - ndis_sendmulti_handler sendfunc; - ndis_senddone_func senddonefunc; - int i; - ndis_packet *p; - uint8_t irql = 0; - - sc = arg; - adapter = sc->ndis_block->nmb_miniportadapterctx; - if (adapter == NULL) - return (ENXIO); - sendfunc = sc->ndis_chars->nmc_sendmulti_func; - senddonefunc = sc->ndis_block->nmb_senddone_func; - - if (NDIS_SERIALIZED(sc->ndis_block)) - KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql); - - MSCALL3(sendfunc, adapter, packets, cnt); - - for (i = 0; i < cnt; i++) { - p = packets[i]; - /* - * Either the driver already handed the packet to - * ndis_txeof() due to a failure, or it wants to keep - * it and release it asynchronously later. Skip to the - * next one. - */ - if (p == NULL || p->np_oob.npo_status == NDIS_STATUS_PENDING) - continue; - MSCALL3(senddonefunc, sc->ndis_block, p, p->np_oob.npo_status); - } - - if (NDIS_SERIALIZED(sc->ndis_block)) - KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql); - - return (0); -} - -int -ndis_send_packet(arg, packet) - void *arg; - ndis_packet *packet; -{ - struct ndis_softc *sc; - ndis_handle adapter; - ndis_status status; - ndis_sendsingle_handler sendfunc; - ndis_senddone_func senddonefunc; - uint8_t irql = 0; - - sc = arg; - adapter = sc->ndis_block->nmb_miniportadapterctx; - if (adapter == NULL) - return (ENXIO); - sendfunc = sc->ndis_chars->nmc_sendsingle_func; - senddonefunc = sc->ndis_block->nmb_senddone_func; - - if (NDIS_SERIALIZED(sc->ndis_block)) - KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql); - status = MSCALL3(sendfunc, adapter, packet, - packet->np_private.npp_flags); - - if (status == NDIS_STATUS_PENDING) { - if (NDIS_SERIALIZED(sc->ndis_block)) - KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql); - return (0); - } - - MSCALL3(senddonefunc, sc->ndis_block, packet, status); - - if (NDIS_SERIALIZED(sc->ndis_block)) - KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql); - - return (0); -} - -int -ndis_init_dma(arg) - void *arg; -{ - struct ndis_softc *sc; - int i, error; - - sc = arg; - - sc->ndis_tmaps = malloc(sizeof(bus_dmamap_t) * sc->ndis_maxpkts, - M_DEVBUF, M_NOWAIT|M_ZERO); - - if (sc->ndis_tmaps == NULL) - return (ENOMEM); - - for (i = 0; i < sc->ndis_maxpkts; i++) { - error = bus_dmamap_create(sc->ndis_ttag, 0, - &sc->ndis_tmaps[i]); - if (error) { - free(sc->ndis_tmaps, M_DEVBUF); - return (ENODEV); - } - } - - return (0); -} - -int -ndis_destroy_dma(arg) - void *arg; -{ - struct ndis_softc *sc; - struct mbuf *m; - ndis_packet *p = NULL; - int i; - - sc = arg; - - for (i = 0; i < sc->ndis_maxpkts; i++) { - if (sc->ndis_txarray[i] != NULL) { - p = sc->ndis_txarray[i]; - m = (struct mbuf *)p->np_rsvd[1]; - if (m != NULL) - m_freem(m); - ndis_free_packet(sc->ndis_txarray[i]); - } - bus_dmamap_destroy(sc->ndis_ttag, sc->ndis_tmaps[i]); - } - - free(sc->ndis_tmaps, M_DEVBUF); - - bus_dma_tag_destroy(sc->ndis_ttag); - - return (0); -} - -int -ndis_reset_nic(arg) - void *arg; -{ - struct ndis_softc *sc; - ndis_handle adapter; - ndis_reset_handler resetfunc; - uint8_t addressing_reset; - int rval; - uint8_t irql = 0; - - sc = arg; - - NDIS_LOCK(sc); - adapter = sc->ndis_block->nmb_miniportadapterctx; - resetfunc = sc->ndis_chars->nmc_reset_func; - - if (adapter == NULL || resetfunc == NULL || - sc->ndis_block->nmb_devicectx == NULL) { - NDIS_UNLOCK(sc); - return (EIO); - } - - NDIS_UNLOCK(sc); - - KeResetEvent(&sc->ndis_block->nmb_resetevent); - - if (NDIS_SERIALIZED(sc->ndis_block)) - KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql); - - rval = MSCALL2(resetfunc, &addressing_reset, adapter); - - if (NDIS_SERIALIZED(sc->ndis_block)) - KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql); - - if (rval == NDIS_STATUS_PENDING) - KeWaitForSingleObject(&sc->ndis_block->nmb_resetevent, - 0, 0, FALSE, NULL); - - return (0); -} - -int -ndis_halt_nic(arg) - void *arg; -{ - struct ndis_softc *sc; - ndis_handle adapter; - ndis_halt_handler haltfunc; - ndis_miniport_block *block; - int empty = 0; - uint8_t irql; - - sc = arg; - block = sc->ndis_block; - - if (!cold) - KeFlushQueuedDpcs(); - - /* - * Wait for all packets to be returned. - */ - - while (1) { - KeAcquireSpinLock(&block->nmb_returnlock, &irql); - empty = IsListEmpty(&block->nmb_returnlist); - KeReleaseSpinLock(&block->nmb_returnlock, irql); - if (empty) - break; - NdisMSleep(1000); - } - - NDIS_LOCK(sc); - adapter = sc->ndis_block->nmb_miniportadapterctx; - if (adapter == NULL) { - NDIS_UNLOCK(sc); - return (EIO); - } - - sc->ndis_block->nmb_devicectx = NULL; - - /* - * The adapter context is only valid after the init - * handler has been called, and is invalid once the - * halt handler has been called. - */ - - haltfunc = sc->ndis_chars->nmc_halt_func; - NDIS_UNLOCK(sc); - - MSCALL1(haltfunc, adapter); - - NDIS_LOCK(sc); - sc->ndis_block->nmb_miniportadapterctx = NULL; - NDIS_UNLOCK(sc); - - return (0); -} - -int -ndis_shutdown_nic(arg) - void *arg; -{ - struct ndis_softc *sc; - ndis_handle adapter; - ndis_shutdown_handler shutdownfunc; - - sc = arg; - NDIS_LOCK(sc); - adapter = sc->ndis_block->nmb_miniportadapterctx; - shutdownfunc = sc->ndis_chars->nmc_shutdown_handler; - NDIS_UNLOCK(sc); - if (adapter == NULL || shutdownfunc == NULL) - return (EIO); - - if (sc->ndis_chars->nmc_rsvd0 == NULL) - MSCALL1(shutdownfunc, adapter); - else - MSCALL1(shutdownfunc, sc->ndis_chars->nmc_rsvd0); - - TAILQ_REMOVE(&ndis_devhead, sc->ndis_block, link); - - return (0); -} - -int -ndis_pnpevent_nic(arg, type) - void *arg; - int type; -{ - device_t dev; - struct ndis_softc *sc; - ndis_handle adapter; - ndis_pnpevent_handler pnpeventfunc; - - dev = arg; - sc = device_get_softc(arg); - NDIS_LOCK(sc); - adapter = sc->ndis_block->nmb_miniportadapterctx; - pnpeventfunc = sc->ndis_chars->nmc_pnpevent_handler; - NDIS_UNLOCK(sc); - if (adapter == NULL || pnpeventfunc == NULL) - return (EIO); - - if (sc->ndis_chars->nmc_rsvd0 == NULL) - MSCALL4(pnpeventfunc, adapter, type, NULL, 0); - else - MSCALL4(pnpeventfunc, sc->ndis_chars->nmc_rsvd0, type, NULL, 0); - - return (0); -} - -int -ndis_init_nic(arg) - void *arg; -{ - struct ndis_softc *sc; - ndis_miniport_block *block; - ndis_init_handler initfunc; - ndis_status status, openstatus = 0; - ndis_medium mediumarray[NdisMediumMax]; - uint32_t chosenmedium, i; - - if (arg == NULL) - return (EINVAL); - - sc = arg; - NDIS_LOCK(sc); - block = sc->ndis_block; - initfunc = sc->ndis_chars->nmc_init_func; - NDIS_UNLOCK(sc); - - sc->ndis_block->nmb_timerlist = NULL; - - for (i = 0; i < NdisMediumMax; i++) - mediumarray[i] = i; - - status = MSCALL6(initfunc, &openstatus, &chosenmedium, - mediumarray, NdisMediumMax, block, block); - - /* - * If the init fails, blow away the other exported routines - * we obtained from the driver so we can't call them later. - * If the init failed, none of these will work. - */ - if (status != NDIS_STATUS_SUCCESS) { - NDIS_LOCK(sc); - sc->ndis_block->nmb_miniportadapterctx = NULL; - NDIS_UNLOCK(sc); - return (ENXIO); - } - - /* - * This may look really goofy, but apparently it is possible - * to halt a miniport too soon after it's been initialized. - * After MiniportInitialize() finishes, pause for 1 second - * to give the chip a chance to handle any short-lived timers - * that were set in motion. If we call MiniportHalt() too soon, - * some of the timers may not be cancelled, because the driver - * expects them to fire before the halt is called. - */ - - pause("ndwait", hz); - - NDIS_LOCK(sc); - sc->ndis_block->nmb_devicectx = sc; - NDIS_UNLOCK(sc); - - return (0); -} - -static void -ndis_intrsetup(dpc, dobj, ip, sc) - kdpc *dpc; - device_object *dobj; - irp *ip; - struct ndis_softc *sc; -{ - ndis_miniport_interrupt *intr; - - intr = sc->ndis_block->nmb_interrupt; - - /* Sanity check. */ - - if (intr == NULL) - return; - - KeAcquireSpinLockAtDpcLevel(&intr->ni_dpccountlock); - KeResetEvent(&intr->ni_dpcevt); - if (KeInsertQueueDpc(&intr->ni_dpc, NULL, NULL) == TRUE) - intr->ni_dpccnt++; - KeReleaseSpinLockFromDpcLevel(&intr->ni_dpccountlock); -} - -int -ndis_get_info(arg, oid, buf, buflen) - void *arg; - ndis_oid oid; - void *buf; - int *buflen; -{ - struct ndis_softc *sc; - ndis_status rval; - ndis_handle adapter; - ndis_queryinfo_handler queryfunc; - uint32_t byteswritten = 0, bytesneeded = 0; - uint8_t irql; - uint64_t duetime; - - sc = arg; - - KeResetEvent(&sc->ndis_block->nmb_getevent); - - KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql); - - if (sc->ndis_block->nmb_pendingreq != NULL) { - KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql); - panic("ndis_get_info() called while other request pending"); - } else - sc->ndis_block->nmb_pendingreq = (ndis_request *)sc; - - queryfunc = sc->ndis_chars->nmc_queryinfo_func; - adapter = sc->ndis_block->nmb_miniportadapterctx; - - if (adapter == NULL || queryfunc == NULL || - sc->ndis_block->nmb_devicectx == NULL) { - sc->ndis_block->nmb_pendingreq = NULL; - KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql); - return (ENXIO); - } - - rval = MSCALL6(queryfunc, adapter, oid, buf, *buflen, - &byteswritten, &bytesneeded); - - sc->ndis_block->nmb_pendingreq = NULL; - - KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql); - - /* Wait for requests that block. */ - - if (rval == NDIS_STATUS_PENDING) { - /* Wait up to 5 seconds. */ - duetime = (5 * 1000000) * -10; - KeWaitForSingleObject(&sc->ndis_block->nmb_getevent, - 0, 0, FALSE, &duetime); - rval = sc->ndis_block->nmb_getstat; - } - - if (byteswritten) - *buflen = byteswritten; - if (bytesneeded) - *buflen = bytesneeded; - - if (rval == NDIS_STATUS_INVALID_LENGTH || - rval == NDIS_STATUS_BUFFER_TOO_SHORT) - return (ENOSPC); - - if (rval == NDIS_STATUS_INVALID_OID) - return (EINVAL); - - if (rval == NDIS_STATUS_NOT_SUPPORTED || - rval == NDIS_STATUS_NOT_ACCEPTED) - return (ENOTSUP); - - if (rval != NDIS_STATUS_SUCCESS) - return (ENODEV); - - return (0); -} - -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; - int error; - - sc = device_get_softc(pdo->do_devext); - - if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus) { - error = bus_setup_intr(sc->ndis_dev, sc->ndis_irq, - INTR_TYPE_NET | INTR_MPSAFE, - NULL, ntoskrnl_intr, NULL, &sc->ndis_intrhand); - if (error) - return (NDIS_STATUS_FAILURE); - } - - status = IoCreateDevice(drv, sizeof(ndis_miniport_block), NULL, - FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo); - - if (status != STATUS_SUCCESS) - return (status); - - block = fdo->do_devext; - - block->nmb_filterdbs.nf_ethdb = block; - block->nmb_deviceobj = fdo; - block->nmb_physdeviceobj = pdo; - block->nmb_nextdeviceobj = IoAttachDeviceToDeviceStack(fdo, pdo); - KeInitializeSpinLock(&block->nmb_lock); - KeInitializeSpinLock(&block->nmb_returnlock); - KeInitializeEvent(&block->nmb_getevent, EVENT_TYPE_NOTIFY, TRUE); - KeInitializeEvent(&block->nmb_setevent, EVENT_TYPE_NOTIFY, TRUE); - KeInitializeEvent(&block->nmb_resetevent, EVENT_TYPE_NOTIFY, TRUE); - InitializeListHead(&block->nmb_parmlist); - InitializeListHead(&block->nmb_returnlist); - block->nmb_returnitem = IoAllocateWorkItem(fdo); - - /* - * 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. - */ - sc->ndis_block = block; - sc->ndis_chars = IoGetDriverObjectExtension(drv, (void *)1); - - /* - * If the driver has a MiniportTransferData() function, - * we should allocate a private RX packet pool. - */ - - if (sc->ndis_chars->nmc_transferdata_func != NULL) { - NdisAllocatePacketPool(&status, &block->nmb_rxpool, - 32, PROTOCOL_RESERVED_SIZE_IN_PACKET); - if (status != NDIS_STATUS_SUCCESS) { - IoDetachDevice(block->nmb_nextdeviceobj); - IoDeleteDevice(fdo); - return (status); - } - InitializeListHead((&block->nmb_packetlist)); - } - - /* Give interrupt handling priority over timers. */ - IoInitializeDpcRequest(fdo, kernndis_functbl[6].ipt_wrap); - KeSetImportanceDpc(&fdo->do_dpc, KDPC_IMPORTANCE_HIGH); - - /* Finish up BSD-specific setup. */ - - block->nmb_signature = (void *)0xcafebabe; - block->nmb_status_func = kernndis_functbl[0].ipt_wrap; - block->nmb_statusdone_func = kernndis_functbl[1].ipt_wrap; - block->nmb_setdone_func = kernndis_functbl[2].ipt_wrap; - block->nmb_querydone_func = kernndis_functbl[3].ipt_wrap; - block->nmb_resetdone_func = kernndis_functbl[4].ipt_wrap; - block->nmb_sendrsrc_func = kernndis_functbl[5].ipt_wrap; - block->nmb_pendingreq = NULL; - - TAILQ_INSERT_TAIL(&ndis_devhead, block, link); - - return (STATUS_SUCCESS); -} - -int -ndis_unload_driver(arg) - void *arg; -{ - struct ndis_softc *sc; - device_object *fdo; - - sc = arg; - - if (sc->ndis_intrhand) - bus_teardown_intr(sc->ndis_dev, - sc->ndis_irq, sc->ndis_intrhand); - - if (sc->ndis_block->nmb_rlist != NULL) - free(sc->ndis_block->nmb_rlist, M_DEVBUF); - - ndis_flush_sysctls(sc); - - TAILQ_REMOVE(&ndis_devhead, sc->ndis_block, link); - - if (sc->ndis_chars->nmc_transferdata_func != NULL) - NdisFreePacketPool(sc->ndis_block->nmb_rxpool); - fdo = sc->ndis_block->nmb_deviceobj; - IoFreeWorkItem(sc->ndis_block->nmb_returnitem); - 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 deleted file mode 100644 index 9ca7953a9384..000000000000 --- a/sys/compat/ndis/kern_windrv.c +++ /dev/null @@ -1,1170 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2005 - * Bill Paul . 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef __i386__ -#include -#endif - -#ifdef __amd64__ -#include -#endif - -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef __amd64__ -struct fpu_cc_ent { - struct fpu_kern_ctx *ctx; - LIST_ENTRY(fpu_cc_ent) entries; -}; -static LIST_HEAD(fpu_ctx_free, fpu_cc_ent) fpu_free_head = - LIST_HEAD_INITIALIZER(fpu_free_head); -static LIST_HEAD(fpu_ctx_busy, fpu_cc_ent) fpu_busy_head = - LIST_HEAD_INITIALIZER(fpu_busy_head); -static struct mtx fpu_free_mtx; -static struct mtx fpu_busy_mtx; -#endif - -static 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; - -#ifdef __i386__ -static void x86_oldldt(void *); -static void x86_newldt(void *); - -struct tid { - void *tid_except_list; /* 0x00 */ - uint32_t tid_oldfs; /* 0x04 */ - uint32_t tid_selector; /* 0x08 */ - struct tid *tid_self; /* 0x0C */ - int tid_cpu; /* 0x10 */ -}; - -static struct tid *my_tids; -#endif /* __i386__ */ - -#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); - -#ifdef __amd64__ - LIST_INIT(&fpu_free_head); - LIST_INIT(&fpu_busy_head); - mtx_init(&fpu_free_mtx, "free fpu context list lock", NULL, MTX_DEF); - mtx_init(&fpu_busy_mtx, "busy fpu context list lock", NULL, MTX_DEF); -#endif - - /* - * 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"); - -#ifdef __i386__ - - /* - * In order to properly support SMP machines, we have - * to modify the GDT on each CPU, since we never know - * on which one we'll end up running. - */ - - my_tids = ExAllocatePoolWithTag(NonPagedPool, - sizeof(struct tid) * mp_ncpus, 0); - if (my_tids == NULL) - panic("failed to allocate thread info blocks"); - smp_rendezvous(NULL, x86_newldt, NULL, NULL); -#endif - return (0); -} - -int -windrv_libfini(void) -{ - struct drvdb_ent *d; -#ifdef __amd64__ - struct fpu_cc_ent *ent; -#endif - - 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); - - RtlFreeUnicodeString(&fake_pci_driver.dro_drivername); - RtlFreeUnicodeString(&fake_pccard_driver.dro_drivername); - - mtx_destroy(&drvdb_mtx); - -#ifdef __i386__ - smp_rendezvous(NULL, x86_oldldt, NULL, NULL); - ExFreePool(my_tids); -#endif -#ifdef __amd64__ - while ((ent = LIST_FIRST(&fpu_free_head)) != NULL) { - LIST_REMOVE(ent, entries); - fpu_kern_free_ctx(ent->ctx); - free(ent, M_DEVBUF); - } - mtx_destroy(&fpu_free_mtx); - - ent = LIST_FIRST(&fpu_busy_head); - KASSERT(ent == NULL, ("busy fpu context list is not empty")); - mtx_destroy(&fpu_busy_mtx); -#endif - return (0); -} - -/* - * Given the address of a driver image, find its corresponding - * driver_object. - */ - -driver_object * -windrv_lookup(img, name) - vm_offset_t img; - char *name; -{ - struct drvdb_ent *d; - unicode_string us; - ansi_string as; - - bzero((char *)&us, sizeof(us)); - - /* Damn unicode. */ - - if (name != NULL) { - RtlInitAnsiString(&as, name); - if (RtlAnsiStringToUnicodeString(&us, &as, TRUE)) - return (NULL); - } - - mtx_lock(&drvdb_mtx); - STAILQ_FOREACH(d, &drvdb_head, link) { - if (d->windrv_object->dro_driverstart == (void *)img || - (bcmp((char *)d->windrv_object->dro_drivername.us_buf, - (char *)us.us_buf, us.us_len) == 0 && us.us_len)) { - mtx_unlock(&drvdb_mtx); - if (name != NULL) - ExFreePool(us.us_buf); - return (d->windrv_object); - } - } - mtx_unlock(&drvdb_mtx); - - if (name != NULL) - RtlFreeUnicodeString(&us); - - return (NULL); -} - -struct drvdb_ent * -windrv_match(matchfunc, ctx) - matchfuncptr matchfunc; - void *ctx; -{ - struct drvdb_ent *d; - int match; - - mtx_lock(&drvdb_mtx); - STAILQ_FOREACH(d, &drvdb_head, link) { - if (d->windrv_devlist == NULL) - continue; - match = matchfunc(d->windrv_bustype, d->windrv_devlist, ctx); - if (match == TRUE) { - mtx_unlock(&drvdb_mtx); - return (d); - } - } - 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 *db, *r = NULL; - driver_object *drv; - device_object *d, *pdo; - device_t dev; - list_entry *e; - - drv = windrv_lookup(img, NULL); - - /* - * When we unload a driver image, we need to force a - * detach of any devices that might be using it. We - * need the PDOs of all attached devices for this. - * Getting at them is a little hard. We basically - * have to walk the device lists of all our bus - * drivers. - */ - - mtx_lock(&drvdb_mtx); - STAILQ_FOREACH(db, &drvdb_head, link) { - /* - * Fake bus drivers have no devlist info. - * If this driver has devlist info, it's - * a loaded Windows driver and has no PDOs, - * so skip it. - */ - if (db->windrv_devlist != NULL) - continue; - pdo = db->windrv_object->dro_devobj; - while (pdo != NULL) { - d = pdo->do_attacheddev; - if (d->do_drvobj != drv) { - pdo = pdo->do_nextdev; - continue; - } - dev = pdo->do_devext; - pdo = pdo->do_nextdev; - mtx_unlock(&drvdb_mtx); - device_detach(dev); - mtx_lock(&drvdb_mtx); - } - } - - STAILQ_FOREACH(db, &drvdb_head, link) { - if (db->windrv_object->dro_driverstart == (void *)img) { - r = db; - STAILQ_REMOVE(&drvdb_head, db, drvdb_ent, link); - break; - } - } - mtx_unlock(&drvdb_mtx); - - if (r == NULL) - return (ENOENT); - - if (drv == NULL) - return (ENOENT); - - /* - * Destroy any custom extensions that may have been added. - */ - drv = r->windrv_object; - while (!IsListEmpty(&drv->dro_driverext->dre_usrext)) { - e = RemoveHeadList(&drv->dro_driverext->dre_usrext); - ExFreePool(e); - } - - /* Free the driver extension */ - free(drv->dro_driverext, M_DEVBUF); - - /* Free the driver name */ - RtlFreeUnicodeString(&drv->dro_drivername); - - /* Free driver object */ - free(drv, M_DEVBUF); - - /* Free our DB handle */ - free(r, M_DEVBUF); - - return (0); -} - -#define WINDRV_LOADED htonl(0x42534F44) - -#ifdef __amd64__ -static void -patch_user_shared_data_address(vm_offset_t img, size_t len) -{ - unsigned long i, n, max_addr, *addr; - - n = len - sizeof(unsigned long); - max_addr = KI_USER_SHARED_DATA + sizeof(kuser_shared_data); - for (i = 0; i < n; i++) { - addr = (unsigned long *)(img + i); - if (*addr >= KI_USER_SHARED_DATA && *addr < max_addr) { - *addr -= KI_USER_SHARED_DATA; - *addr += (unsigned long)&kuser_shared_data; - } - } -} -#endif - -/* - * Loader routine for actual Windows driver modules, ultimately - * calls the driver's DriverEntry() routine. - */ - -int -windrv_load(mod, img, len, bustype, devlist, regvals) - module_t mod; - vm_offset_t img; - int len; - interface_type bustype; - void *devlist; - ndis_cfg *regvals; -{ - image_import_descriptor imp_desc; - image_optional_header opt_hdr; - driver_entry entry; - struct drvdb_ent *new; - struct driver_object *drv; - int status; - uint32_t *ptr; - ansi_string as; - - /* - * First step: try to relocate and dynalink the executable - * driver image. - */ - - ptr = (uint32_t *)(img + 8); - if (*ptr == WINDRV_LOADED) - goto skipreloc; - - /* 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 -- optional. */ - if (pe_get_import_descriptor(img, &imp_desc, "HAL") == 0) { - 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); - } - -#ifdef __amd64__ - patch_user_shared_data_address(img, len); -#endif - - /* Dynamically link USBD.SYS -- optional */ - if (pe_get_import_descriptor(img, &imp_desc, "USBD") == 0) { - if (pe_patch_imports(img, "USBD", usbd_functbl)) - return (ENOEXEC); - } - - *ptr = WINDRV_LOADED; - -skipreloc: - - /* 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|M_ZERO); - if (new == NULL) - return (ENOMEM); - - drv = malloc(sizeof(driver_object), M_DEVBUF, M_NOWAIT|M_ZERO); - if (drv == NULL) { - free (new, M_DEVBUF); - return (ENOMEM); - } - - /* Allocate a driver extension structure too. */ - - drv->dro_driverext = malloc(sizeof(driver_extension), - M_DEVBUF, M_NOWAIT|M_ZERO); - - if (drv->dro_driverext == NULL) { - free(new, M_DEVBUF); - free(drv, M_DEVBUF); - return (ENOMEM); - } - - InitializeListHead((&drv->dro_driverext->dre_usrext)); - - drv->dro_driverstart = (void *)img; - drv->dro_driversize = len; - - RtlInitAnsiString(&as, DUMMY_REGISTRY_PATH); - if (RtlAnsiStringToUnicodeString(&drv->dro_drivername, &as, TRUE)) { - free(new, M_DEVBUF); - free(drv, M_DEVBUF); - return (ENOMEM); - } - - new->windrv_object = drv; - new->windrv_regvals = regvals; - new->windrv_devlist = devlist; - new->windrv_bustype = bustype; - - /* Now call the DriverEntry() function. */ - - status = MSCALL2(entry, drv, &drv->dro_drivername); - - if (status != STATUS_SUCCESS) { - RtlFreeUnicodeString(&drv->dro_drivername); - free(drv, 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); -} - -/* - * 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; - while (pdo != NULL) { - if (pdo->do_devext == bsddev) { - mtx_unlock(&drvdb_mtx); - return (pdo); - } - pdo = pdo->do_nextdev; - } - mtx_unlock(&drvdb_mtx); - - return (NULL); -} - -/* - * 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; - ansi_string as; - - new = malloc(sizeof(struct drvdb_ent), M_DEVBUF, M_NOWAIT|M_ZERO); - if (new == NULL) - return (ENOMEM); - - RtlInitAnsiString(&as, name); - if (RtlAnsiStringToUnicodeString(&drv->dro_drivername, &as, TRUE)) - { - free(new, M_DEVBUF); - return (ENOMEM); - } - - /* - * Set up a fake image pointer to avoid false matches - * in windrv_lookup(). - */ - drv->dro_driverstart = (void *)0xFFFFFFFF; - - 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); -} - -#ifdef __amd64__ - -extern void x86_64_wrap(void); -extern void x86_64_wrap_call(void); -extern void x86_64_wrap_end(void); - -int -windrv_wrap(func, wrap, argcnt, ftype) - funcptr func; - funcptr *wrap; - int argcnt; - int ftype; -{ - funcptr p; - vm_offset_t *calladdr; - vm_offset_t wrapstart, wrapend, wrapcall; - - wrapstart = (vm_offset_t)&x86_64_wrap; - wrapend = (vm_offset_t)&x86_64_wrap_end; - wrapcall = (vm_offset_t)&x86_64_wrap_call; - - /* Allocate a new wrapper instance. */ - - p = malloc((wrapend - wrapstart), M_DEVBUF, M_NOWAIT); - if (p == NULL) - return (ENOMEM); - - /* Copy over the code. */ - - bcopy((char *)wrapstart, p, (wrapend - wrapstart)); - - /* Insert the function address into the new wrapper instance. */ - - calladdr = (uint64_t *)((char *)p + (wrapcall - wrapstart) + 2); - *calladdr = (vm_offset_t)func; - - *wrap = p; - - return (0); -} - -static struct fpu_cc_ent * -request_fpu_cc_ent(void) -{ - struct fpu_cc_ent *ent; - - mtx_lock(&fpu_free_mtx); - if ((ent = LIST_FIRST(&fpu_free_head)) != NULL) { - LIST_REMOVE(ent, entries); - mtx_unlock(&fpu_free_mtx); - mtx_lock(&fpu_busy_mtx); - LIST_INSERT_HEAD(&fpu_busy_head, ent, entries); - mtx_unlock(&fpu_busy_mtx); - return (ent); - } - mtx_unlock(&fpu_free_mtx); - - if ((ent = malloc(sizeof(struct fpu_cc_ent), M_DEVBUF, M_NOWAIT | - M_ZERO)) != NULL) { - ent->ctx = fpu_kern_alloc_ctx(FPU_KERN_NORMAL | - FPU_KERN_NOWAIT); - if (ent->ctx != NULL) { - mtx_lock(&fpu_busy_mtx); - LIST_INSERT_HEAD(&fpu_busy_head, ent, entries); - mtx_unlock(&fpu_busy_mtx); - } else { - free(ent, M_DEVBUF); - ent = NULL; - } - } - - return (ent); -} - -static void -release_fpu_cc_ent(struct fpu_cc_ent *ent) -{ - mtx_lock(&fpu_busy_mtx); - LIST_REMOVE(ent, entries); - mtx_unlock(&fpu_busy_mtx); - mtx_lock(&fpu_free_mtx); - LIST_INSERT_HEAD(&fpu_free_head, ent, entries); - mtx_unlock(&fpu_free_mtx); -} - -uint64_t -_x86_64_call1(void *fn, uint64_t a) -{ - struct fpu_cc_ent *ent; - uint64_t ret; - - if ((ent = request_fpu_cc_ent()) == NULL) - return (ENOMEM); - fpu_kern_enter(curthread, ent->ctx, FPU_KERN_NORMAL); - ret = x86_64_call1(fn, a); - fpu_kern_leave(curthread, ent->ctx); - release_fpu_cc_ent(ent); - - return (ret); -} - -uint64_t -_x86_64_call2(void *fn, uint64_t a, uint64_t b) -{ - struct fpu_cc_ent *ent; - uint64_t ret; - - if ((ent = request_fpu_cc_ent()) == NULL) - return (ENOMEM); - fpu_kern_enter(curthread, ent->ctx, FPU_KERN_NORMAL); - ret = x86_64_call2(fn, a, b); - fpu_kern_leave(curthread, ent->ctx); - release_fpu_cc_ent(ent); - - return (ret); -} - -uint64_t -_x86_64_call3(void *fn, uint64_t a, uint64_t b, uint64_t c) -{ - struct fpu_cc_ent *ent; - uint64_t ret; - - if ((ent = request_fpu_cc_ent()) == NULL) - return (ENOMEM); - fpu_kern_enter(curthread, ent->ctx, FPU_KERN_NORMAL); - ret = x86_64_call3(fn, a, b, c); - fpu_kern_leave(curthread, ent->ctx); - release_fpu_cc_ent(ent); - - return (ret); -} - -uint64_t -_x86_64_call4(void *fn, uint64_t a, uint64_t b, uint64_t c, uint64_t d) -{ - struct fpu_cc_ent *ent; - uint64_t ret; - - if ((ent = request_fpu_cc_ent()) == NULL) - return (ENOMEM); - fpu_kern_enter(curthread, ent->ctx, FPU_KERN_NORMAL); - ret = x86_64_call4(fn, a, b, c, d); - fpu_kern_leave(curthread, ent->ctx); - release_fpu_cc_ent(ent); - - return (ret); -} - -uint64_t -_x86_64_call5(void *fn, uint64_t a, uint64_t b, uint64_t c, uint64_t d, - uint64_t e) -{ - struct fpu_cc_ent *ent; - uint64_t ret; - - if ((ent = request_fpu_cc_ent()) == NULL) - return (ENOMEM); - fpu_kern_enter(curthread, ent->ctx, FPU_KERN_NORMAL); - ret = x86_64_call5(fn, a, b, c, d, e); - fpu_kern_leave(curthread, ent->ctx); - release_fpu_cc_ent(ent); - - return (ret); -} - -uint64_t -_x86_64_call6(void *fn, uint64_t a, uint64_t b, uint64_t c, uint64_t d, - uint64_t e, uint64_t f) -{ - struct fpu_cc_ent *ent; - uint64_t ret; - - if ((ent = request_fpu_cc_ent()) == NULL) - return (ENOMEM); - fpu_kern_enter(curthread, ent->ctx, FPU_KERN_NORMAL); - ret = x86_64_call6(fn, a, b, c, d, e, f); - fpu_kern_leave(curthread, ent->ctx); - release_fpu_cc_ent(ent); - - return (ret); -} -#endif /* __amd64__ */ - -#ifdef __i386__ - -struct x86desc { - uint16_t x_lolimit; - uint16_t x_base0; - uint8_t x_base1; - uint8_t x_flags; - uint8_t x_hilimit; - uint8_t x_base2; -}; - -struct gdt { - uint16_t limit; - void *base; -} __attribute__((__packed__)); - -extern uint16_t x86_getfs(void); -extern void x86_setfs(uint16_t); -extern void *x86_gettid(void); -extern void x86_critical_enter(void); -extern void x86_critical_exit(void); -extern void x86_getldt(struct gdt *, uint16_t *); -extern void x86_setldt(struct gdt *, uint16_t); - -#define SEL_LDT 4 /* local descriptor table */ -#define SEL_TO_FS(x) (((x) << 3)) - -/* - * FreeBSD 6.0 and later has a special GDT segment reserved - * specifically for us, so if GNDIS_SEL is defined, use that. - * If not, use GTGATE_SEL, which is uninitialized and infrequently - * used. - */ - -#ifdef GNDIS_SEL -#define FREEBSD_EMPTYSEL GNDIS_SEL -#else -#define FREEBSD_EMPTYSEL GTGATE_SEL /* slot 7 */ -#endif - -/* - * The meanings of various bits in a descriptor vary a little - * depending on whether the descriptor will be used as a - * code, data or system descriptor. (And that in turn depends - * on which segment register selects the descriptor.) - * We're only trying to create a data segment, so the definitions - * below are the ones that apply to a data descriptor. - */ - -#define SEGFLAGLO_PRESENT 0x80 /* segment is present */ -#define SEGFLAGLO_PRIVLVL 0x60 /* privlevel needed for this seg */ -#define SEGFLAGLO_CD 0x10 /* 1 = code/data, 0 = system */ -#define SEGFLAGLO_MBZ 0x08 /* must be zero */ -#define SEGFLAGLO_EXPANDDOWN 0x04 /* limit expands down */ -#define SEGFLAGLO_WRITEABLE 0x02 /* segment is writeable */ -#define SEGGLAGLO_ACCESSED 0x01 /* segment has been accessed */ - -#define SEGFLAGHI_GRAN 0x80 /* granularity, 1 = byte, 0 = page */ -#define SEGFLAGHI_BIG 0x40 /* 1 = 32 bit stack, 0 = 16 bit */ - -/* - * Context switch from UNIX to Windows. Save the existing value - * of %fs for this processor, then change it to point to our - * fake TID. Note that it is also possible to pin ourselves - * to our current CPU, though I'm not sure this is really - * necessary. It depends on whether or not an interrupt might - * preempt us while Windows code is running and we wind up - * scheduled onto another CPU as a result. So far, it doesn't - * seem like this is what happens. - */ - -void -ctxsw_utow(void) -{ - struct tid *t; - - t = &my_tids[curthread->td_oncpu]; - - /* - * Ugly hack. During system bootstrap (cold == 1), only CPU 0 - * is running. So if we were loaded at bootstrap, only CPU 0 - * will have our special GDT entry. This is a problem for SMP - * systems, so to deal with this, we check here to make sure - * the TID for this processor has been initialized, and if it - * hasn't, we need to do it right now or else things will - * explode. - */ - - if (t->tid_self != t) - x86_newldt(NULL); - - x86_critical_enter(); - t->tid_oldfs = x86_getfs(); - t->tid_cpu = curthread->td_oncpu; - sched_pin(); - x86_setfs(SEL_TO_FS(t->tid_selector)); - x86_critical_exit(); - - /* Now entering Windows land, population: you. */ -} - -/* - * Context switch from Windows back to UNIX. Restore %fs to - * its previous value. This always occurs after a call to - * ctxsw_utow(). - */ - -void -ctxsw_wtou(void) -{ - struct tid *t; - - x86_critical_enter(); - t = x86_gettid(); - x86_setfs(t->tid_oldfs); - sched_unpin(); - x86_critical_exit(); - - /* Welcome back to UNIX land, we missed you. */ - -#ifdef EXTRA_SANITY - if (t->tid_cpu != curthread->td_oncpu) - panic("ctxsw GOT MOVED TO OTHER CPU!"); -#endif -} - -static int windrv_wrap_stdcall(funcptr, funcptr *, int); -static int windrv_wrap_fastcall(funcptr, funcptr *, int); -static int windrv_wrap_regparm(funcptr, funcptr *); - -extern void x86_fastcall_wrap(void); -extern void x86_fastcall_wrap_call(void); -extern void x86_fastcall_wrap_arg(void); -extern void x86_fastcall_wrap_end(void); - -static int -windrv_wrap_fastcall(func, wrap, argcnt) - funcptr func; - funcptr *wrap; - int8_t argcnt; -{ - funcptr p; - vm_offset_t *calladdr; - uint8_t *argaddr; - vm_offset_t wrapstart, wrapend, wrapcall, wraparg; - - wrapstart = (vm_offset_t)&x86_fastcall_wrap; - wrapend = (vm_offset_t)&x86_fastcall_wrap_end; - wrapcall = (vm_offset_t)&x86_fastcall_wrap_call; - wraparg = (vm_offset_t)&x86_fastcall_wrap_arg; - - /* Allocate a new wrapper instance. */ - - p = malloc((wrapend - wrapstart), M_DEVBUF, M_NOWAIT); - if (p == NULL) - return (ENOMEM); - - /* Copy over the code. */ - - bcopy((char *)wrapstart, p, (wrapend - wrapstart)); - - /* Insert the function address into the new wrapper instance. */ - - calladdr = (vm_offset_t *)((char *)p + ((wrapcall - wrapstart) + 1)); - *calladdr = (vm_offset_t)func; - - argcnt -= 2; - if (argcnt < 1) - argcnt = 0; - - argaddr = (u_int8_t *)((char *)p + ((wraparg - wrapstart) + 1)); - *argaddr = argcnt * sizeof(uint32_t); - - *wrap = p; - - return (0); -} - -extern void x86_stdcall_wrap(void); -extern void x86_stdcall_wrap_call(void); -extern void x86_stdcall_wrap_arg(void); -extern void x86_stdcall_wrap_end(void); - -static int -windrv_wrap_stdcall(func, wrap, argcnt) - funcptr func; - funcptr *wrap; - uint8_t argcnt; -{ - funcptr p; - vm_offset_t *calladdr; - uint8_t *argaddr; - vm_offset_t wrapstart, wrapend, wrapcall, wraparg; - - wrapstart = (vm_offset_t)&x86_stdcall_wrap; - wrapend = (vm_offset_t)&x86_stdcall_wrap_end; - wrapcall = (vm_offset_t)&x86_stdcall_wrap_call; - wraparg = (vm_offset_t)&x86_stdcall_wrap_arg; - - /* Allocate a new wrapper instance. */ - - p = malloc((wrapend - wrapstart), M_DEVBUF, M_NOWAIT); - if (p == NULL) - return (ENOMEM); - - /* Copy over the code. */ - - bcopy((char *)wrapstart, p, (wrapend - wrapstart)); - - /* Insert the function address into the new wrapper instance. */ - - calladdr = (vm_offset_t *)((char *)p + ((wrapcall - wrapstart) + 1)); - *calladdr = (vm_offset_t)func; - - argaddr = (u_int8_t *)((char *)p + ((wraparg - wrapstart) + 1)); - *argaddr = argcnt * sizeof(uint32_t); - - *wrap = p; - - return (0); -} - -extern void x86_regparm_wrap(void); -extern void x86_regparm_wrap_call(void); -extern void x86_regparm_wrap_end(void); - -static int -windrv_wrap_regparm(func, wrap) - funcptr func; - funcptr *wrap; -{ - funcptr p; - vm_offset_t *calladdr; - vm_offset_t wrapstart, wrapend, wrapcall; - - wrapstart = (vm_offset_t)&x86_regparm_wrap; - wrapend = (vm_offset_t)&x86_regparm_wrap_end; - wrapcall = (vm_offset_t)&x86_regparm_wrap_call; - - /* Allocate a new wrapper instance. */ - - p = malloc((wrapend - wrapstart), M_DEVBUF, M_NOWAIT); - if (p == NULL) - return (ENOMEM); - - /* Copy over the code. */ - - bcopy(x86_regparm_wrap, p, (wrapend - wrapstart)); - - /* Insert the function address into the new wrapper instance. */ - - calladdr = (vm_offset_t *)((char *)p + ((wrapcall - wrapstart) + 1)); - *calladdr = (vm_offset_t)func; - - *wrap = p; - - return (0); -} - -int -windrv_wrap(func, wrap, argcnt, ftype) - funcptr func; - funcptr *wrap; - int argcnt; - int ftype; -{ - switch(ftype) { - case WINDRV_WRAP_FASTCALL: - return (windrv_wrap_fastcall(func, wrap, argcnt)); - case WINDRV_WRAP_STDCALL: - return (windrv_wrap_stdcall(func, wrap, argcnt)); - case WINDRV_WRAP_REGPARM: - return (windrv_wrap_regparm(func, wrap)); - case WINDRV_WRAP_CDECL: - return (windrv_wrap_stdcall(func, wrap, 0)); - default: - break; - } - - return (EINVAL); -} - -static void -x86_oldldt(dummy) - void *dummy; -{ - struct x86desc *gdt; - struct gdt gtable; - uint16_t ltable; - - mtx_lock_spin(&dt_lock); - - /* Grab location of existing GDT. */ - - x86_getldt(>able, <able); - - /* Find the slot we updated. */ - - gdt = gtable.base; - gdt += FREEBSD_EMPTYSEL; - - /* Empty it out. */ - - bzero((char *)gdt, sizeof(struct x86desc)); - - /* Restore GDT. */ - - x86_setldt(>able, ltable); - - mtx_unlock_spin(&dt_lock); -} - -static void -x86_newldt(dummy) - void *dummy; -{ - struct gdt gtable; - uint16_t ltable; - struct x86desc *l; - struct thread *t; - - t = curthread; - - mtx_lock_spin(&dt_lock); - - /* Grab location of existing GDT. */ - - x86_getldt(>able, <able); - - /* Get pointer to the GDT table. */ - - l = gtable.base; - - /* Get pointer to empty slot */ - - l += FREEBSD_EMPTYSEL; - - /* Initialize TID for this CPU. */ - - my_tids[t->td_oncpu].tid_selector = FREEBSD_EMPTYSEL; - my_tids[t->td_oncpu].tid_self = &my_tids[t->td_oncpu]; - - /* Set up new GDT entry. */ - - l->x_lolimit = sizeof(struct tid); - l->x_hilimit = SEGFLAGHI_GRAN|SEGFLAGHI_BIG; - l->x_base0 = (vm_offset_t)(&my_tids[t->td_oncpu]) & 0xFFFF; - l->x_base1 = ((vm_offset_t)(&my_tids[t->td_oncpu]) >> 16) & 0xFF; - l->x_base2 = ((vm_offset_t)(&my_tids[t->td_oncpu]) >> 24) & 0xFF; - l->x_flags = SEGFLAGLO_PRESENT|SEGFLAGLO_CD|SEGFLAGLO_WRITEABLE; - - /* Update the GDT. */ - - x86_setldt(>able, ltable); - - mtx_unlock_spin(&dt_lock); - - /* Whew. */ -} - -#endif /* __i386__ */ - -int -windrv_unwrap(func) - funcptr func; -{ - free(func, M_DEVBUF); - - return (0); -} diff --git a/sys/compat/ndis/ndis_var.h b/sys/compat/ndis/ndis_var.h deleted file mode 100644 index 7af490e35e56..000000000000 --- a/sys/compat/ndis/ndis_var.h +++ /dev/null @@ -1,1763 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul . All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _NDIS_VAR_H_ -#define _NDIS_VAR_H_ - -/* Forward declarations */ -struct ndis_miniport_block; -struct ndis_mdriver_block; -typedef struct ndis_miniport_block ndis_miniport_block; -typedef struct ndis_mdriver_block ndis_mdriver_block; - -/* Base types */ -typedef uint32_t ndis_status; -typedef void *ndis_handle; -typedef uint32_t ndis_oid; -typedef uint32_t ndis_error_code; -typedef register_t ndis_kspin_lock; -typedef uint8_t ndis_kirql; - -/* - * NDIS status codes (there are lots of them). The ones that - * don't seem to fit the pattern are actually mapped to generic - * NT status codes. - */ - -#define NDIS_STATUS_SUCCESS 0 -#define NDIS_STATUS_PENDING 0x00000103 -#define NDIS_STATUS_NOT_RECOGNIZED 0x00010001 -#define NDIS_STATUS_NOT_COPIED 0x00010002 -#define NDIS_STATUS_NOT_ACCEPTED 0x00010003 -#define NDIS_STATUS_CALL_ACTIVE 0x00010007 -#define NDIS_STATUS_ONLINE 0x40010003 -#define NDIS_STATUS_RESET_START 0x40010004 -#define NDIS_STATUS_RESET_END 0x40010005 -#define NDIS_STATUS_RING_STATUS 0x40010006 -#define NDIS_STATUS_CLOSED 0x40010007 -#define NDIS_STATUS_WAN_LINE_UP 0x40010008 -#define NDIS_STATUS_WAN_LINE_DOWN 0x40010009 -#define NDIS_STATUS_WAN_FRAGMENT 0x4001000A -#define NDIS_STATUS_MEDIA_CONNECT 0x4001000B -#define NDIS_STATUS_MEDIA_DISCONNECT 0x4001000C -#define NDIS_STATUS_HARDWARE_LINE_UP 0x4001000D -#define NDIS_STATUS_HARDWARE_LINE_DOWN 0x4001000E -#define NDIS_STATUS_INTERFACE_UP 0x4001000F -#define NDIS_STATUS_INTERFACE_DOWN 0x40010010 -#define NDIS_STATUS_MEDIA_BUSY 0x40010011 -#define NDIS_STATUS_MEDIA_SPECIFIC_INDICATION 0x40010012 -#define NDIS_STATUS_WW_INDICATION NDIS_STATUS_MEDIA_SPECIFIC_INDICATION -#define NDIS_STATUS_LINK_SPEED_CHANGE 0x40010013 -#define NDIS_STATUS_WAN_GET_STATS 0x40010014 -#define NDIS_STATUS_WAN_CO_FRAGMENT 0x40010015 -#define NDIS_STATUS_WAN_CO_LINKPARAMS 0x40010016 -#define NDIS_STATUS_NOT_RESETTABLE 0x80010001 -#define NDIS_STATUS_SOFT_ERRORS 0x80010003 -#define NDIS_STATUS_HARD_ERRORS 0x80010004 -#define NDIS_STATUS_BUFFER_OVERFLOW 0x80000005 -#define NDIS_STATUS_FAILURE 0xC0000001 -#define NDIS_STATUS_RESOURCES 0xC000009A -#define NDIS_STATUS_CLOSING 0xC0010002 -#define NDIS_STATUS_BAD_VERSION 0xC0010004 -#define NDIS_STATUS_BAD_CHARACTERISTICS 0xC0010005 -#define NDIS_STATUS_ADAPTER_NOT_FOUND 0xC0010006 -#define NDIS_STATUS_OPEN_FAILED 0xC0010007 -#define NDIS_STATUS_DEVICE_FAILED 0xC0010008 -#define NDIS_STATUS_MULTICAST_FULL 0xC0010009 -#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A -#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B -#define NDIS_STATUS_REQUEST_ABORTED 0xC001000C -#define NDIS_STATUS_RESET_IN_PROGRESS 0xC001000D -#define NDIS_STATUS_CLOSING_INDICATING 0xC001000E -#define NDIS_STATUS_NOT_SUPPORTED 0xC00000BB -#define NDIS_STATUS_INVALID_PACKET 0xC001000F -#define NDIS_STATUS_OPEN_LIST_FULL 0xC0010010 -#define NDIS_STATUS_ADAPTER_NOT_READY 0xC0010011 -#define NDIS_STATUS_ADAPTER_NOT_OPEN 0xC0010012 -#define NDIS_STATUS_NOT_INDICATING 0xC0010013 -#define NDIS_STATUS_INVALID_LENGTH 0xC0010014 -#define NDIS_STATUS_INVALID_DATA 0xC0010015 -#define NDIS_STATUS_BUFFER_TOO_SHORT 0xC0010016 -#define NDIS_STATUS_INVALID_OID 0xC0010017 -#define NDIS_STATUS_ADAPTER_REMOVED 0xC0010018 -#define NDIS_STATUS_UNSUPPORTED_MEDIA 0xC0010019 -#define NDIS_STATUS_GROUP_ADDRESS_IN_USE 0xC001001A -#define NDIS_STATUS_FILE_NOT_FOUND 0xC001001B -#define NDIS_STATUS_ERROR_READING_FILE 0xC001001C -#define NDIS_STATUS_ALREADY_MAPPED 0xC001001D -#define NDIS_STATUS_RESOURCE_CONFLICT 0xC001001E -#define NDIS_STATUS_NO_CABLE 0xC001001F -#define NDIS_STATUS_INVALID_SAP 0xC0010020 -#define NDIS_STATUS_SAP_IN_USE 0xC0010021 -#define NDIS_STATUS_INVALID_ADDRESS 0xC0010022 -#define NDIS_STATUS_VC_NOT_ACTIVATED 0xC0010023 -#define NDIS_STATUS_DEST_OUT_OF_ORDER 0xC0010024 -#define NDIS_STATUS_VC_NOT_AVAILABLE 0xC0010025 -#define NDIS_STATUS_CELLRATE_NOT_AVAILABLE 0xC0010026 -#define NDIS_STATUS_INCOMPATABLE_QOS 0xC0010027 -#define NDIS_STATUS_AAL_PARAMS_UNSUPPORTED 0xC0010028 -#define NDIS_STATUS_NO_ROUTE_TO_DESTINATION 0xC0010029 -#define NDIS_STATUS_TOKEN_RING_OPEN_ERROR 0xC0011000 -#define NDIS_STATUS_INVALID_DEVICE_REQUEST 0xC0000010 -#define NDIS_STATUS_NETWORK_UNREACHABLE 0xC000023C - -/* - * NDIS event codes. They are usually reported to NdisWriteErrorLogEntry(). - */ - -#define EVENT_NDIS_RESOURCE_CONFLICT 0xC0001388 -#define EVENT_NDIS_OUT_OF_RESOURCE 0xC0001389 -#define EVENT_NDIS_HARDWARE_FAILURE 0xC000138A -#define EVENT_NDIS_ADAPTER_NOT_FOUND 0xC000138B -#define EVENT_NDIS_INTERRUPT_CONNECT 0xC000138C -#define EVENT_NDIS_DRIVER_FAILURE 0xC000138D -#define EVENT_NDIS_BAD_VERSION 0xC000138E -#define EVENT_NDIS_TIMEOUT 0x8000138F -#define EVENT_NDIS_NETWORK_ADDRESS 0xC0001390 -#define EVENT_NDIS_UNSUPPORTED_CONFIGURATION 0xC0001391 -#define EVENT_NDIS_INVALID_VALUE_FROM_ADAPTER 0xC0001392 -#define EVENT_NDIS_MISSING_CONFIGURATION_PARAMETER 0xC0001393 -#define EVENT_NDIS_BAD_IO_BASE_ADDRESS 0xC0001394 -#define EVENT_NDIS_RECEIVE_SPACE_SMALL 0x40001395 -#define EVENT_NDIS_ADAPTER_DISABLED 0x80001396 -#define EVENT_NDIS_IO_PORT_CONFLICT 0x80001397 -#define EVENT_NDIS_PORT_OR_DMA_CONFLICT 0x80001398 -#define EVENT_NDIS_MEMORY_CONFLICT 0x80001399 -#define EVENT_NDIS_INTERRUPT_CONFLICT 0x8000139A -#define EVENT_NDIS_DMA_CONFLICT 0x8000139B -#define EVENT_NDIS_INVALID_DOWNLOAD_FILE_ERROR 0xC000139C -#define EVENT_NDIS_MAXRECEIVES_ERROR 0x8000139D -#define EVENT_NDIS_MAXTRANSMITS_ERROR 0x8000139E -#define EVENT_NDIS_MAXFRAMESIZE_ERROR 0x8000139F -#define EVENT_NDIS_MAXINTERNALBUFS_ERROR 0x800013A0 -#define EVENT_NDIS_MAXMULTICAST_ERROR 0x800013A1 -#define EVENT_NDIS_PRODUCTID_ERROR 0x800013A2 -#define EVENT_NDIS_LOBE_FAILUE_ERROR 0x800013A3 -#define EVENT_NDIS_SIGNAL_LOSS_ERROR 0x800013A4 -#define EVENT_NDIS_REMOVE_RECEIVED_ERROR 0x800013A5 -#define EVENT_NDIS_TOKEN_RING_CORRECTION 0x400013A6 -#define EVENT_NDIS_ADAPTER_CHECK_ERROR 0xC00013A7 -#define EVENT_NDIS_RESET_FAILURE_ERROR 0x800013A8 -#define EVENT_NDIS_CABLE_DISCONNECTED_ERROR 0x800013A9 -#define EVENT_NDIS_RESET_FAILURE_CORRECTION 0x800013AA - -/* - * NDIS OIDs used by the queryinfo/setinfo routines. - * Some are required by all NDIS drivers, some are specific to - * a particular type of device, and some are purely optional. - * Unfortunately, one of the purely optional OIDs is the one - * that lets us set the MAC address of the device. - */ - -/* Required OIDs */ -#define OID_GEN_SUPPORTED_LIST 0x00010101 -#define OID_GEN_HARDWARE_STATUS 0x00010102 -#define OID_GEN_MEDIA_SUPPORTED 0x00010103 -#define OID_GEN_MEDIA_IN_USE 0x00010104 -#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 -#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 -#define OID_GEN_LINK_SPEED 0x00010107 -#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 -#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 -#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A -#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B -#define OID_GEN_VENDOR_ID 0x0001010C -#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D -#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E -#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F -#define OID_GEN_DRIVER_VERSION 0x00010110 -#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 -#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 -#define OID_GEN_MAC_OPTIONS 0x00010113 -#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 -#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 -#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 -#define OID_GEN_SUPPORTED_GUIDS 0x00010117 -#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 /* Set only */ -#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 /* Set only */ -#define OID_GEN_MACHINE_NAME 0x0001021A -#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B /* Set only */ -#define OID_GEN_VLAN_ID 0x0001021C - -/* Optional OIDs. */ -#define OID_GEN_MEDIA_CAPABILITIES 0x00010201 -#define OID_GEN_PHYSICAL_MEDIUM 0x00010202 - -/* Required statistics OIDs. */ -#define OID_GEN_XMIT_OK 0x00020101 -#define OID_GEN_RCV_OK 0x00020102 -#define OID_GEN_XMIT_ERROR 0x00020103 -#define OID_GEN_RCV_ERROR 0x00020104 -#define OID_GEN_RCV_NO_BUFFER 0x00020105 - -/* Optional OID statistics */ -#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 -#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 -#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 -#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 -#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 -#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 -#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 -#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 -#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 -#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A -#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B -#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C -#define OID_GEN_RCV_CRC_ERROR 0x0002020D -#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E -#define OID_GEN_GET_TIME_CAPS 0x0002020F -#define OID_GEN_GET_NETCARD_TIME 0x00020210 -#define OID_GEN_NETCARD_LOAD 0x00020211 -#define OID_GEN_DEVICE_PROFILE 0x00020212 - -/* 802.3 (ethernet) OIDs */ -#define OID_802_3_PERMANENT_ADDRESS 0x01010101 -#define OID_802_3_CURRENT_ADDRESS 0x01010102 -#define OID_802_3_MULTICAST_LIST 0x01010103 -#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 -#define OID_802_3_MAC_OPTIONS 0x01010105 -#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001 -#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 -#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 -#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 -#define OID_802_3_XMIT_DEFERRED 0x01020201 -#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 -#define OID_802_3_RCV_OVERRUN 0x01020203 -#define OID_802_3_XMIT_UNDERRUN 0x01020204 -#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 -#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 -#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 - -/* PnP and power management OIDs */ -#define OID_PNP_CAPABILITIES 0xFD010100 -#define OID_PNP_SET_POWER 0xFD010101 -#define OID_PNP_QUERY_POWER 0xFD010102 -#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103 -#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104 -#define OID_PNP_WAKE_UP_PATTERN_LIST 0xFD010105 -#define OID_PNP_ENABLE_WAKE_UP 0xFD010106 - -/* - * These are the possible power states for - * OID_PNP_SET_POWER and OID_PNP_QUERY_POWER. - */ -#define NDIS_POWERSTATE_UNSPEC 0 -#define NDIS_POWERSTATE_D0 1 -#define NDIS_POWERSTATE_D1 2 -#define NDIS_POWERSTATE_D2 3 -#define NDIS_POWERSTATE_D3 4 - -/* - * These are used with the MiniportPnpEventNotify() method. - */ - -#define NDIS_POWERPROFILE_BATTERY 0 -#define NDIS_POWERPROFILE_ACONLINE 1 - -#define NDIS_PNP_EVENT_QUERY_REMOVED 0 -#define NDIS_PNP_EVENT_REMOVED 1 -#define NDIS_PNP_EVENT_SURPRISE_REMOVED 2 -#define NDIS_PNP_EVENT_QUERY_STOPPED 3 -#define NDIS_PNP_EVENT_STOPPED 4 -#define NDIS_PNP_EVENT_PROFILECHANGED 5 - -/* PnP/PM Statistics (Optional). */ -#define OID_PNP_WAKE_UP_OK 0xFD020200 -#define OID_PNP_WAKE_UP_ERROR 0xFD020201 - -/* The following bits are defined for OID_PNP_ENABLE_WAKE_UP */ -#define NDIS_PNP_WAKE_UP_MAGIC_PACKET 0x00000001 -#define NDIS_PNP_WAKE_UP_PATTERN_MATCH 0x00000002 -#define NDIS_PNP_WAKE_UP_LINK_CHANGE 0x00000004 - -/* 802.11 OIDs */ -#define OID_802_11_BSSID 0x0D010101 -#define OID_802_11_SSID 0x0D010102 -#define OID_802_11_NETWORK_TYPES_SUPPORTED 0x0D010203 -#define OID_802_11_NETWORK_TYPE_IN_USE 0x0D010204 -#define OID_802_11_TX_POWER_LEVEL 0x0D010205 -#define OID_802_11_RSSI 0x0D010206 -#define OID_802_11_RSSI_TRIGGER 0x0D010207 -#define OID_802_11_INFRASTRUCTURE_MODE 0x0D010108 -#define OID_802_11_FRAGMENTATION_THRESHOLD 0x0D010209 -#define OID_802_11_RTS_THRESHOLD 0x0D01020A -#define OID_802_11_NUMBER_OF_ANTENNAS 0x0D01020B -#define OID_802_11_RX_ANTENNA_SELECTED 0x0D01020C -#define OID_802_11_TX_ANTENNA_SELECTED 0x0D01020D -#define OID_802_11_SUPPORTED_RATES 0x0D01020E -#define OID_802_11_DESIRED_RATES 0x0D010210 -#define OID_802_11_CONFIGURATION 0x0D010211 -#define OID_802_11_STATISTICS 0x0D020212 -#define OID_802_11_ADD_WEP 0x0D010113 -#define OID_802_11_REMOVE_WEP 0x0D010114 -#define OID_802_11_DISASSOCIATE 0x0D010115 -#define OID_802_11_POWER_MODE 0x0D010216 -#define OID_802_11_BSSID_LIST 0x0D010217 -#define OID_802_11_AUTHENTICATION_MODE 0x0D010118 -#define OID_802_11_PRIVACY_FILTER 0x0D010119 -#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A -#define OID_802_11_WEP_STATUS 0x0D01011B -#define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS -#define OID_802_11_RELOAD_DEFAULTS 0x0D01011C -#define OID_802_11_ADD_KEY 0x0D01011D -#define OID_802_11_REMOVE_KEY 0x0D01011E -#define OID_802_11_ASSOCIATION_INFORMATION 0x0D01011F -#define OID_802_11_TEST 0x0D010120 -#define OID_802_11_CAPABILITY 0x0D010122 -#define OID_802_11_PMKID 0x0D010123 - -/* structures/definitions for 802.11 */ -#define NDIS_80211_NETTYPE_11FH 0x00000000 -#define NDIS_80211_NETTYPE_11DS 0x00000001 -#define NDIS_80211_NETTYPE_11OFDM5 0x00000002 -#define NDIS_80211_NETTYPE_11OFDM24 0x00000003 -#define NDIS_80211_NETTYPE_AUTO 0x00000004 - -struct ndis_80211_nettype_list { - uint32_t ntl_items; - uint32_t ntl_type[1]; -}; - -#define NDIS_80211_POWERMODE_CAM 0x00000000 -#define NDIS_80211_POWERMODE_MAX_PSP 0x00000001 -#define NDIS_80211_POWERMODE_FAST_PSP 0x00000002 - -typedef uint32_t ndis_80211_power; /* Power in milliwatts */ -typedef uint32_t ndis_80211_rssi; /* Signal strength in dBm */ - -struct ndis_80211_config_fh { - uint32_t ncf_length; - uint32_t ncf_hoppatterh; - uint32_t ncf_hopset; - uint32_t ncf_dwelltime; -}; - -typedef struct ndis_80211_config_fh ndis_80211_config_fh; - -struct ndis_80211_config { - uint32_t nc_length; - uint32_t nc_beaconperiod; - uint32_t nc_atimwin; - uint32_t nc_dsconfig; - ndis_80211_config_fh nc_fhconfig; -}; - -typedef struct ndis_80211_config ndis_80211_config; - -struct ndis_80211_stats { - uint32_t ns_length; - uint64_t ns_txfragcnt; - uint64_t ns_txmcastcnt; - uint64_t ns_failedcnt; - uint64_t ns_retrycnt; - uint64_t ns_multiretrycnt; - uint64_t ns_rtssuccesscnt; - uint64_t ns_rtsfailcnt; - uint64_t ns_ackfailcnt; - uint64_t ns_dupeframecnt; - uint64_t ns_rxfragcnt; - uint64_t ns_rxmcastcnt; - uint64_t ns_fcserrcnt; -}; - -typedef struct ndis_80211_stats ndis_80211_stats; - -typedef uint32_t ndis_80211_key_idx; - -struct ndis_80211_wep { - uint32_t nw_length; - uint32_t nw_keyidx; - uint32_t nw_keylen; - uint8_t nw_keydata[256]; -}; - -typedef struct ndis_80211_wep ndis_80211_wep; - -#define NDIS_80211_WEPKEY_TX 0x80000000 -#define NDIS_80211_WEPKEY_PERCLIENT 0x40000000 - -#define NDIS_80211_NET_INFRA_IBSS 0x00000000 -#define NDIS_80211_NET_INFRA_BSS 0x00000001 -#define NDIS_80211_NET_INFRA_AUTO 0x00000002 - -#define NDIS_80211_AUTHMODE_OPEN 0x00000000 -#define NDIS_80211_AUTHMODE_SHARED 0x00000001 -#define NDIS_80211_AUTHMODE_AUTO 0x00000002 -#define NDIS_80211_AUTHMODE_WPA 0x00000003 -#define NDIS_80211_AUTHMODE_WPAPSK 0x00000004 -#define NDIS_80211_AUTHMODE_WPANONE 0x00000005 -#define NDIS_80211_AUTHMODE_WPA2 0x00000006 -#define NDIS_80211_AUTHMODE_WPA2PSK 0x00000007 - -typedef uint8_t ndis_80211_rates[8]; -typedef uint8_t ndis_80211_rates_ex[16]; -typedef uint8_t ndis_80211_macaddr[6]; - -struct ndis_80211_ssid { - uint32_t ns_ssidlen; - uint8_t ns_ssid[32]; -}; - -typedef struct ndis_80211_ssid ndis_80211_ssid; - -struct ndis_wlan_bssid { - uint32_t nwb_length; - ndis_80211_macaddr nwb_macaddr; - uint8_t nwb_rsvd[2]; - ndis_80211_ssid nwb_ssid; - uint32_t nwb_privacy; - ndis_80211_rssi nwb_rssi; - uint32_t nwb_nettype; - ndis_80211_config nwb_config; - uint32_t nwb_netinfra; - ndis_80211_rates nwb_supportedrates; -}; - -typedef struct ndis_wlan_bssid ndis_wlan_bssid; - -struct ndis_80211_bssid_list { - uint32_t nbl_items; - ndis_wlan_bssid nbl_bssid[1]; -}; - -typedef struct ndis_80211_bssid_list ndis_80211_bssid_list; - -struct ndis_wlan_bssid_ex { - uint32_t nwbx_len; - ndis_80211_macaddr nwbx_macaddr; - uint8_t nwbx_rsvd[2]; - ndis_80211_ssid nwbx_ssid; - uint32_t nwbx_privacy; - ndis_80211_rssi nwbx_rssi; - uint32_t nwbx_nettype; - ndis_80211_config nwbx_config; - uint32_t nwbx_netinfra; - ndis_80211_rates_ex nwbx_supportedrates; - uint32_t nwbx_ielen; - uint8_t nwbx_ies[1]; -}; - -typedef struct ndis_wlan_bssid_ex ndis_wlan_bssid_ex; - -struct ndis_80211_bssid_list_ex { - uint32_t nblx_items; - ndis_wlan_bssid_ex nblx_bssid[1]; -}; - -typedef struct ndis_80211_bssid_list_ex ndis_80211_bssid_list_ex; - -struct ndis_80211_fixed_ies { - uint8_t nfi_tstamp[8]; - uint16_t nfi_beaconint; - uint16_t nfi_caps; -}; - -struct ndis_80211_variable_ies { - uint8_t nvi_elemid; - uint8_t nvi_len; - uint8_t nvi_data[1]; -}; - -typedef uint32_t ndis_80211_fragthresh; -typedef uint32_t ndis_80211_rtsthresh; -typedef uint32_t ndis_80211_antenna; - -#define NDIS_80211_PRIVFILT_ACCEPTALL 0x00000000 -#define NDIS_80211_PRIVFILT_8021XWEP 0x00000001 - -#define NDIS_80211_WEPSTAT_ENABLED 0x00000000 -#define NDIS_80211_WEPSTAT_ENC1ENABLED NDIS_80211_WEPSTAT_ENABLED -#define NDIS_80211_WEPSTAT_DISABLED 0x00000001 -#define NDIS_80211_WEPSTAT_ENCDISABLED NDIS_80211_WEPSTAT_DISABLED -#define NDIS_80211_WEPSTAT_KEYABSENT 0x00000002 -#define NDIS_80211_WEPSTAT_ENC1KEYABSENT NDIS_80211_WEPSTAT_KEYABSENT -#define NDIS_80211_WEPSTAT_NOTSUPPORTED 0x00000003 -#define NDIS_80211_WEPSTAT_ENCNOTSUPPORTED NDIS_80211_WEPSTAT_NOTSUPPORTED -#define NDIS_80211_WEPSTAT_ENC2ENABLED 0x00000004 -#define NDIS_80211_WEPSTAT_ENC2KEYABSENT 0x00000005 -#define NDIS_80211_WEPSTAT_ENC3ENABLED 0x00000006 -#define NDIS_80211_WEPSTAT_ENC3KEYABSENT 0x00000007 - -#define NDIS_80211_RELOADDEFAULT_WEP 0x00000000 - -#define NDIS_80211_STATUSTYPE_AUTH 0x00000000 -#define NDIS_80211_STATUSTYPE_PMKIDLIST 0x00000001 - -struct ndis_80211_status_indication { - uint32_t nsi_type; -}; - -typedef struct ndis_80211_status_indication ndis_80211_status_indication; - -#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01 -#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02 -#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06 -#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E - -struct ndis_80211_auth_request { - uint32_t nar_len; - ndis_80211_macaddr nar_bssid; - uint32_t nar_flags; -}; - -typedef struct ndis_80211_auth_request ndis_80211_auth_request; - -struct ndis_80211_key { - uint32_t nk_len; - uint32_t nk_keyidx; - uint32_t nk_keylen; - ndis_80211_macaddr nk_bssid; - uint8_t nk_pad[6]; - uint64_t nk_keyrsc; - uint8_t nk_keydata[32]; -}; - -typedef struct ndis_80211_key ndis_80211_key; - -struct ndis_80211_remove_key { - uint32_t nk_len; - uint32_t nk_keyidx; - ndis_80211_macaddr nk_bssid; -}; - -typedef struct ndis_80211_remove_key ndis_80211_remove_key; - -#define NDIS_80211_AI_REQFI_CAPABILITIES 0x00000001 -#define NDIS_80211_AI_REQFI_LISTENINTERVAL 0x00000002 -#define NDIS_80211_AI_REQFI_CURRENTAPADDRESS 0x00000004 - -#define NDIS_80211_AI_RESFI_CAPABILITIES 0x00000001 -#define NDIS_80211_AI_RESFI_STATUSCODE 0x00000002 -#define NDIS_80211_AI_RESFI_ASSOCIATIONID 0x00000004 - -struct ndis_80211_ai_reqfi { - uint16_t naq_caps; - uint16_t naq_listentint; - ndis_80211_macaddr naq_currentapaddr; -}; - -typedef struct ndis_80211_ai_reqfi ndis_80211_ai_reqfi; - -struct ndis_80211_ai_resfi { - uint16_t nas_caps; - uint16_t nas_statuscode; - uint16_t nas_associd; -}; - -typedef struct ndis_80211_ai_resfi ndis_80211_ai_resfi; - -struct ndis_80211_assoc_info { - uint32_t nai_len; - uint16_t nai_avail_req_fixed_ies; - ndis_80211_ai_reqfi nai_req_fixed_ies; - uint32_t nai_req_ielen; - uint32_t nai_offset_req_ies; - uint16_t nai_avail_resp_fixed_ies; - ndis_80211_ai_resfi nai_resp_fixed_iex; - uint32_t nai_resp_ielen; - uint32_t nai_offset_resp_ies; -}; - -typedef struct ndis_80211_assoc_info ndis_80211_assoc_info; - -struct ndis_80211_auth_event { - ndis_80211_status_indication nae_status; - ndis_80211_auth_request nae_request[1]; -}; - -typedef struct ndis_80211_auth_event ndis_80211_auth_event; - -struct ndis_80211_test { - uint32_t nt_len; - uint32_t nt_type; - union { - ndis_80211_auth_event nt_authevent; - uint32_t nt_rssitrigger; - } u; -}; - -typedef struct ndis_80211_test ndis_80211_test; - -struct ndis_80211_auth_encrypt { - uint32_t ne_authmode; - uint32_t ne_cryptstat; -}; - -typedef struct ndis_80211_auth_encrypt ndis_80211_auth_encrypt; - -struct ndis_80211_caps { - uint32_t nc_len; - uint32_t nc_ver; - uint32_t nc_numpmkids; - ndis_80211_auth_encrypt nc_authencs[1]; -}; - -typedef struct ndis_80211_caps ndis_80211_caps; - -struct ndis_80211_bssidinfo { - ndis_80211_macaddr nb_bssid; - uint8_t nb_pmkid[16]; -}; - -typedef struct ndis_80211_bssidinfo ndis_80211_bssidinfo; - -struct ndis_80211_pmkid { - uint32_t np_len; - uint32_t np_bssidcnt; - ndis_80211_bssidinfo np_bssidinfo[1]; -}; - -typedef struct ndis_80211_pmkid ndis_80211_pmkid; - -struct ndis_80211_pmkid_cand { - ndis_80211_macaddr npc_bssid; - uint32_t npc_flags; -}; - -typedef struct ndis_80211_pmkid_cand ndis_80211_pmkid_cand; - -#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED (0x01) - -struct ndis_80211_pmkid_candidate_list { - uint32_t npcl_version; - uint32_t npcl_numcandidates; - ndis_80211_pmkid_cand npcl_candidatelist[1]; -}; - -typedef struct ndis_80211_pmkid_candidate_list ndis_80211_pmkid_candidate_list; - -struct ndis_80211_enc_indication { - uint32_t nei_statustype; - ndis_80211_pmkid_candidate_list nei_pmkidlist; -}; - -typedef struct ndis_80211_enc_indication ndis_80211_enc_indication; - -/* TCP OIDs. */ - -#define OID_TCP_TASK_OFFLOAD 0xFC010201 -#define OID_TCP_TASK_IPSEC_ADD_SA 0xFC010202 -#define OID_TCP_TASK_IPSEC_DELETE_SA 0xFC010203 -#define OID_TCP_SAN_SUPPORT 0xFC010204 - -#define NDIS_TASK_OFFLOAD_VERSION 1 - -#define NDIS_TASK_TCPIP_CSUM 0x00000000 -#define NDIS_TASK_IPSEC 0x00000001 -#define NDIS_TASK_TCP_LARGESEND 0x00000002 - -#define NDIS_ENCAP_UNSPEC 0x00000000 -#define NDIS_ENCAP_NULL 0x00000001 -#define NDIS_ENCAP_IEEE802_3 0x00000002 -#define NDIS_ENCAP_IEEE802_5 0x00000003 -#define NDIS_ENCAP_SNAP_ROUTED 0x00000004 -#define NDIS_ENCAP_SNAP_BRIDGED 0x00000005 - -#define NDIS_ENCAPFLAG_FIXEDHDRLEN 0x00000001 - -struct ndis_encap_fmt { - uint32_t nef_encap; - uint32_t nef_flags; - uint32_t nef_encaphdrlen; -}; - -typedef struct ndis_encap_fmt ndis_encap_fmt; - -struct ndis_task_offload_hdr { - uint32_t ntoh_vers; - uint32_t ntoh_len; - uint32_t ntoh_rsvd; - uint32_t ntoh_offset_firsttask; - ndis_encap_fmt ntoh_encapfmt; -}; - -typedef struct ndis_task_offload_hdr ndis_task_offload_hdr; - -struct ndis_task_offload { - uint32_t nto_vers; - uint32_t nto_len; - uint32_t nto_task; - uint32_t nto_offset_nexttask; - uint32_t nto_taskbuflen; - uint8_t nto_taskbuf[1]; -}; - -typedef struct ndis_task_offload ndis_task_offload; - -#define NDIS_TCPSUM_FLAGS_IP_OPTS 0x00000001 -#define NDIS_TCPSUM_FLAGS_TCP_OPTS 0x00000002 -#define NDIS_TCPSUM_FLAGS_TCP_CSUM 0x00000004 -#define NDIS_TCPSUM_FLAGS_UDP_CSUM 0x00000008 -#define NDIS_TCPSUM_FLAGS_IP_CSUM 0x00000010 - -struct ndis_task_tcpip_csum { - uint32_t nttc_v4tx; - uint32_t nttc_v4rx; - uint32_t nttc_v6tx; - uint32_t nttc_v6rx; -}; - -typedef struct ndis_task_tcpip_csum ndis_task_tcpip_csum; - -struct ndis_task_tcp_largesend { - uint32_t nttl_vers; - uint32_t nttl_maxofflen; - uint32_t nttl_minsegcnt; - uint8_t nttl_tcpopt; - uint8_t nttl_ipopt; -}; - -typedef struct ndis_task_tcp_largesend ndis_task_tcp_largesend; - -#define NDIS_IPSEC_AH_MD5 0x00000001 -#define NDIS_IPSEC_AH_SHA1 0x00000002 -#define NDIS_IPSEC_AH_TRANSPORT 0x00000004 -#define NDIS_IPSEC_AH_TUNNEL 0x00000008 -#define NDIS_IPSEC_AH_SEND 0x00000010 -#define NDIS_IPSEC_AH_RECEIVE 0x00000020 - -#define NDIS_IPSEC_ESP_DES 0x00000001 -#define NDIS_IPSEC_ESP_RSVD 0x00000002 -#define NDIS_IPSEC_ESP_3DES 0x00000004 -#define NDIS_IPSEC_ESP_NULL 0x00000008 -#define NDIS_IPSEC_ESP_TRANSPORT 0x00000010 -#define NDIS_IPSEC_ESP_TUNNEL 0x00000020 -#define NDIS_IPSEC_ESP_SEND 0x00000040 -#define NDIS_IPSEC_ESP_RECEIVE 0x00000080 - -struct ndis_task_ipsec { - uint32_t nti_ah_esp_combined; - uint32_t nti_ah_transport_tunnel_combined; - uint32_t nti_v4_options; - uint32_t nti_rsvd; - uint32_t nti_v4ah; - uint32_t nti_v4esp; -}; - -typedef struct ndis_task_ipsec ndis_task_ipsec; - -/* - * Attribures of NDIS drivers. Not all drivers support - * all attributes. - */ - -#define NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT 0x00000001 -#define NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT 0x00000002 -#define NDIS_ATTRIBUTE_IGNORE_TOKEN_RING_ERRORS 0x00000004 -#define NDIS_ATTRIBUTE_BUS_MASTER 0x00000008 -#define NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER 0x00000010 -#define NDIS_ATTRIBUTE_DESERIALIZE 0x00000020 -#define NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND 0x00000040 -#define NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK 0x00000080 -#define NDIS_ATTRIBUTE_NOT_CO_NDIS 0x00000100 -#define NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS 0x00000200 - -#define NDIS_SERIALIZED(block) \ - (((block)->nmb_flags & NDIS_ATTRIBUTE_DESERIALIZE) == 0) - -enum ndis_media_state { - nmc_connected, - nmc_disconnected -}; - -typedef enum ndis_media_state ndis_media_state; - -/* Ndis Packet Filter Bits (OID_GEN_CURRENT_PACKET_FILTER). */ - -#define NDIS_PACKET_TYPE_DIRECTED 0x00000001 -#define NDIS_PACKET_TYPE_MULTICAST 0x00000002 -#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 -#define NDIS_PACKET_TYPE_BROADCAST 0x00000008 -#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 -#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 -#define NDIS_PACKET_TYPE_SMT 0x00000040 -#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 -#define NDIS_PACKET_TYPE_GROUP 0x00001000 -#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00002000 -#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00004000 -#define NDIS_PACKET_TYPE_MAC_FRAME 0x00008000 - -/* Ndis MAC option bits (OID_GEN_MAC_OPTIONS). */ - -#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001 -#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002 -#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004 -#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008 -#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010 -#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020 -#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040 -#define NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00000080 -#define NDIS_MAC_OPTION_RECEIVE_AT_DPC 0x00000100 -#define NDIS_MAC_OPTION_8021Q_VLAN 0x00000200 -#define NDIS_MAC_OPTION_RESERVED 0x80000000 - -#define NDIS_DMA_24BITS 0x00 -#define NDIS_DMA_32BITS 0x01 -#define NDIS_DMA_64BITS 0x02 - -/* -struct ndis_physaddr { -#ifdef __i386__ - uint64_t np_quad; -#endif -#ifdef __amd64__ - uint32_t np_low; - uint32_t np_high; -#define np_quad np_low -#endif -#ifdef notdef - uint32_t np_low; - uint32_t np_high; -#endif -}; -*/ - -typedef struct physaddr ndis_physaddr; - -struct ndis_ansi_string { - uint16_t nas_len; - uint16_t nas_maxlen; - char *nas_buf; -}; - -typedef struct ndis_ansi_string ndis_ansi_string; - -#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 - * pointer anyway, so for now, just make it a uint16_t *. - */ -struct ndis_unicode_string { - uint16_t nus_len; - uint16_t nus_maxlen; - uint16_t *nus_buf; -}; -typedef struct ndis_unicode_string ndis_unicode_string; -#endif - -typedef unicode_string ndis_unicode_string; - -enum ndis_parm_type { - ndis_parm_int, - ndis_parm_hexint, - ndis_parm_string, - ndis_parm_multistring, - ndis_parm_binary -}; - -typedef enum ndis_parm_type ndis_parm_type; - -struct ndis_binary_data { - uint16_t nbd_len; - void *nbd_buf; -}; - -typedef struct ndis_binary_data ndis_binary_data; - -struct ndis_config_parm { - ndis_parm_type ncp_type; - union { - uint32_t ncp_intdata; - ndis_unicode_string ncp_stringdata; - ndis_binary_data ncp_binarydata; - } ncp_parmdata; -}; - -/* - * Not part of Windows NDIS spec; we uses this to keep a - * list of ndis_config_parm structures that we've allocated. - */ - -typedef struct ndis_config_parm ndis_config_parm; - -struct ndis_parmlist_entry { - list_entry np_list; - ndis_config_parm np_parm; -}; - -typedef struct ndis_parmlist_entry ndis_parmlist_entry; - -#ifdef notdef -struct ndis_list_entry { - struct ndis_list_entry *nle_flink; - struct ndis_list_entry *nle_blink; -}; - -typedef struct ndis_list_entry ndis_list_entry; -#endif - -struct ndis_bind_paths { - uint32_t nbp_number; - ndis_unicode_string nbp_paths[1]; -}; - -typedef struct ndis_bind_paths ndis_bind_paths; - -#ifdef notdef -struct dispatch_header { - uint8_t dh_type; - uint8_t dh_abs; - uint8_t dh_size; - uint8_t dh_inserted; - uint32_t dh_sigstate; - list_entry dh_waitlisthead; -}; -#endif - -#define dispatch_header nt_dispatch_header - -struct ndis_ktimer { - struct dispatch_header nk_header; - uint64_t nk_duetime; - list_entry nk_timerlistentry; - void *nk_dpc; - uint32_t nk_period; -}; - -struct ndis_kevent { - struct dispatch_header nk_header; -}; - -struct ndis_event { - struct nt_kevent ne_event; -}; - -typedef struct ndis_event ndis_event; - -/* Kernel defered procedure call (i.e. timer callback) */ - -struct ndis_kdpc; -typedef void (*ndis_kdpc_func)(struct ndis_kdpc *, void *, void *, void *); - -struct ndis_kdpc { - uint16_t nk_type; - uint8_t nk_num; - uint8_t nk_importance; - list_entry nk_dpclistentry; - ndis_kdpc_func nk_deferedfunc; - void *nk_deferredctx; - void *nk_sysarg1; - void *nk_sysarg2; - uint32_t *nk_lock; -}; - -struct ndis_timer { - struct ktimer nt_ktimer; - struct kdpc nt_kdpc; -}; - -typedef struct ndis_timer ndis_timer; - -typedef void (*ndis_timer_function)(void *, void *, void *, void *); - -struct ndis_miniport_timer { - struct ktimer nmt_ktimer; - struct kdpc nmt_kdpc; - ndis_timer_function nmt_timerfunc; - void *nmt_timerctx; - ndis_miniport_block *nmt_block; - struct ndis_miniport_timer *nmt_nexttimer; -}; - -typedef struct ndis_miniport_timer ndis_miniport_timer; - -struct ndis_spin_lock { - ndis_kspin_lock nsl_spinlock; - ndis_kirql nsl_kirql; -}; - -typedef struct ndis_spin_lock ndis_spin_lock; - -struct ndis_rw_lock { - union { - kspin_lock nrl_spinlock; - void *nrl_ctx; - } u; - uint8_t nrl_rsvd[16]; -}; - -#define nrl_spinlock u.nrl_spinlock -#define nrl_ctx u.nrl_ctx; - -typedef struct ndis_rw_lock ndis_rw_lock; - -struct ndis_lock_state { - uint16_t nls_lockstate; - ndis_kirql nls_oldirql; -}; - -typedef struct ndis_lock_state ndis_lock_state; - -struct ndis_request { - uint8_t nr_macreserved[4*sizeof(void *)]; - uint32_t nr_requesttype; - union _ndis_data { - struct _ndis_query_information { - ndis_oid nr_oid; - void *nr_infobuf; - uint32_t nr_infobuflen; - uint32_t nr_byteswritten; - uint32_t nr_bytesneeded; - } ndis_query_information; - struct _ndis_set_information { - ndis_oid nr_oid; - void *nr_infobuf; - uint32_t nr_infobuflen; - uint32_t nr_byteswritten; - uint32_t nr_bytesneeded; - } ndis_set_information; - } ndis_data; - /* NDIS 5.0 extensions */ - uint8_t nr_ndis_rsvd[9 * sizeof(void *)]; - union { - uint8_t nr_callmgr_rsvd[2 * sizeof(void *)]; - uint8_t nr_protocol_rsvd[2 * sizeof(void *)]; - } u; - uint8_t nr_miniport_rsvd[2 * sizeof(void *)]; -}; - -typedef struct ndis_request ndis_request; - -/* - * Filler, not used. - */ -struct ndis_miniport_interrupt { - kinterrupt *ni_introbj; - ndis_kspin_lock ni_dpccountlock; - void *ni_rsvd; - void *ni_isrfunc; - void *ni_dpcfunc; - kdpc ni_dpc; - ndis_miniport_block *ni_block; - uint8_t ni_dpccnt; - uint8_t ni_filler1; - struct nt_kevent ni_dpcevt; - uint8_t ni_shared; - uint8_t ni_isrreq; -}; - -typedef struct ndis_miniport_interrupt ndis_miniport_interrupt; - -enum ndis_interrupt_mode { - nim_level, - nim_latched -}; - -typedef enum ndis_interrupt_mode ndis_interrupt_mode; - -#define NUMBER_OF_SINGLE_WORK_ITEMS 6 - -struct ndis_work_item; - -typedef void (*ndis_proc)(struct ndis_work_item *, void *); - -struct ndis_work_item { - void *nwi_ctx; - ndis_proc nwi_func; - uint8_t nwi_wraprsvd[sizeof(void *) * 8]; -}; - -typedef struct ndis_work_item ndis_work_item; - -#define NdisInitializeWorkItem(w, f, c) \ - do { \ - (w)->nwi_ctx = c; \ - (w)->nwi_func = f; \ - } while (0) - -#ifdef notdef -struct ndis_buffer { - struct ndis_buffer *nb_next; - uint16_t nb_size; - uint16_t nb_flags; - void *nb_process; - void *nb_mappedsystemva; - void *nb_startva; - uint32_t nb_bytecount; - uint32_t nb_byteoffset; -}; - -typedef struct ndis_buffer ndis_buffer; -#endif - -struct ndis_sc_element { - ndis_physaddr nse_addr; - uint32_t nse_len; - uint32_t *nse_rsvd; -}; - -typedef struct ndis_sc_element ndis_sc_element; - -#define NDIS_MAXSEG 32 -#define NDIS_BUS_SPACE_SHARED_MAXADDR 0x3E7FFFFF - -struct ndis_sc_list { - uint32_t nsl_frags; - uint32_t *nsl_rsvd; - ndis_sc_element nsl_elements[NDIS_MAXSEG]; -}; - -typedef struct ndis_sc_list ndis_sc_list; - -struct ndis_tcpip_csum { - union { - uint32_t ntc_txflags; - uint32_t ntc_rxflags; - uint32_t ntc_val; - } u; -}; - -typedef struct ndis_tcpip_csum ndis_tcpip_csum; - -#define NDIS_TXCSUM_DO_IPV4 0x00000001 -#define NDIS_TXCSUM_DO_IPV6 0x00000002 -#define NDIS_TXCSUM_DO_TCP 0x00000004 -#define NDIS_TXCSUM_DO_UDP 0x00000008 -#define NDIS_TXCSUM_DO_IP 0x00000010 - -#define NDIS_RXCSUM_TCP_FAILED 0x00000001 -#define NDIS_RXCSUM_UDP_FAILED 0x00000002 -#define NDIS_RXCSUM_IP_FAILED 0x00000004 -#define NDIS_RXCSUM_TCP_PASSED 0x00000008 -#define NDIS_RXCSUM_UDP_PASSED 0x00000010 -#define NDIS_RXCSUM_IP_PASSED 0x00000020 -#define NDIS_RXCSUM_LOOPBACK 0x00000040 - -struct ndis_vlan { - union { - struct { - uint32_t nvt_userprio:3; - uint32_t nvt_canformatid:1; - uint32_t nvt_vlanid:12; - uint32_t nvt_rsvd:16; - } nv_taghdr; - } u; -}; - -typedef struct ndis_vlan ndis_vlan; - -enum ndis_perpkt_info { - ndis_tcpipcsum_info, - ndis_ipsec_info, - ndis_largesend_info, - ndis_classhandle_info, - ndis_rsvd, - ndis_sclist_info, - ndis_ieee8021q_info, - ndis_originalpkt_info, - ndis_packetcancelid, - ndis_maxpkt_info -}; - -typedef enum ndis_perpkt_info ndis_perpkt_info; - -struct ndis_packet_extension { - void *npe_info[ndis_maxpkt_info]; -}; - -typedef struct ndis_packet_extension ndis_packet_extension; - -struct ndis_packet_private { - uint32_t npp_physcnt; - uint32_t npp_totlen; - ndis_buffer *npp_head; - ndis_buffer *npp_tail; - - void *npp_pool; - uint32_t npp_count; - uint32_t npp_flags; - uint8_t npp_validcounts; - uint8_t npp_ndispktflags; - uint16_t npp_packetooboffset; -}; - -#define NDIS_FLAGS_PROTOCOL_ID_MASK 0x0000000F -#define NDIS_FLAGS_MULTICAST_PACKET 0x00000010 -#define NDIS_FLAGS_RESERVED2 0x00000020 -#define NDIS_FLAGS_RESERVED3 0x00000040 -#define NDIS_FLAGS_DONT_LOOPBACK 0x00000080 -#define NDIS_FLAGS_IS_LOOPBACK_PACKET 0x00000100 -#define NDIS_FLAGS_LOOPBACK_ONLY 0x00000200 -#define NDIS_FLAGS_RESERVED4 0x00000400 -#define NDIS_FLAGS_DOUBLE_BUFFERED 0x00000800 -#define NDIS_FLAGS_SENT_AT_DPC 0x00001000 -#define NDIS_FLAGS_USES_SG_BUFFER_LIST 0x00002000 - -#define NDIS_PACKET_WRAPPER_RESERVED 0x3F -#define NDIS_PACKET_CONTAINS_MEDIA_SPECIFIC_INFO 0x40 -#define NDIS_PACKET_ALLOCATED_BY_NDIS 0x80 - -#define NDIS_PROTOCOL_ID_DEFAULT 0x00 -#define NDIS_PROTOCOL_ID_TCP_IP 0x02 -#define NDIS_PROTOCOL_ID_IPX 0x06 -#define NDIS_PROTOCOL_ID_NBF 0x07 -#define NDIS_PROTOCOL_ID_MAX 0x0F -#define NDIS_PROTOCOL_ID_MASK 0x0F - -typedef struct ndis_packet_private ndis_packet_private; - -enum ndis_classid { - ndis_class_802_3prio, - ndis_class_wirelesswan_mbx, - ndis_class_irda_packetinfo, - ndis_class_atm_aainfo -}; - -typedef enum ndis_classid ndis_classid; - -struct ndis_mediaspecific_info { - uint32_t nmi_nextentoffset; - ndis_classid nmi_classid; - uint32_t nmi_size; - uint8_t nmi_classinfo[1]; -}; - -typedef struct ndis_mediaspecific_info ndis_mediaspecific_info; - -struct ndis_packet_oob { - union { - uint64_t npo_timetotx; - uint64_t npo_timetxed; - } u; - uint64_t npo_timerxed; - uint32_t npo_hdrlen; - uint32_t npo_mediaspecific_len; - void *npo_mediaspecific; - ndis_status npo_status; -}; - -typedef struct ndis_packet_oob ndis_packet_oob; - -/* - * Our protocol private region for handling ethernet. - * We need this to stash some of the things returned - * by NdisMEthIndicateReceive(). - */ - -struct ndis_ethpriv { - void *nep_ctx; /* packet context */ - long nep_offset; /* residual data to transfer */ - void *nep_pad[2]; -}; - -typedef struct ndis_ethpriv ndis_ethpriv; - -#define PROTOCOL_RESERVED_SIZE_IN_PACKET (4 * sizeof(void *)) - -struct ndis_packet { - ndis_packet_private np_private; - union { - /* For connectionless miniports. */ - struct { - uint8_t np_miniport_rsvd[2 * sizeof(void *)]; - uint8_t np_wrapper_rsvd[2 * sizeof(void *)]; - } np_clrsvd; - /* For de-serialized miniports */ - struct { - uint8_t np_miniport_rsvdex[3 * sizeof(void *)]; - uint8_t np_wrapper_rsvdex[sizeof(void *)]; - } np_dsrsvd; - struct { - uint8_t np_mac_rsvd[4 * sizeof(void *)]; - } np_macrsvd; - } u; - uint32_t *np_rsvd[2]; - uint8_t np_protocolreserved[PROTOCOL_RESERVED_SIZE_IN_PACKET]; - - /* - * This next part is probably wrong, but we need some place - * to put the out of band data structure... - */ - ndis_packet_oob np_oob; - ndis_packet_extension np_ext; - ndis_sc_list np_sclist; - - /* BSD-specific stuff which should be invisible to drivers. */ - - uint32_t np_refcnt; - void *np_softc; - void *np_m0; - int np_txidx; - list_entry np_list; -}; - -typedef struct ndis_packet ndis_packet; - -struct ndis_packet_pool { - slist_header np_head; - int np_dead; - nt_kevent np_event; - kspin_lock np_lock; - int np_cnt; - int np_len; - int np_protrsvd; - void *np_pktmem; -}; - -typedef struct ndis_packet_pool ndis_packet_pool; - -/* mbuf ext type for NDIS */ -#define EXT_NDIS EXT_NET_DRV - -/* mtx type for NDIS */ -#define MTX_NDIS_LOCK "NDIS lock" - -struct ndis_filterdbs { - union { - void *nf_ethdb; - void *nf_nulldb; - } u; - void *nf_trdb; - void *nf_fddidb; - void *nf_arcdb; -}; - -typedef struct ndis_filterdbs ndis_filterdbs; - -#define nf_ethdb u.nf_ethdb - -enum ndis_medium { - NdisMedium802_3, - NdisMedium802_5, - NdisMediumFddi, - NdisMediumWan, - NdisMediumLocalTalk, - NdisMediumDix, /* defined for convenience, not a real medium */ - NdisMediumArcnetRaw, - NdisMediumArcnet878_2, - NdisMediumAtm, - NdisMediumWirelessWan, - NdisMediumIrda, - NdisMediumBpc, - NdisMediumCoWan, - NdisMedium1394, - NdisMediumMax -}; - -typedef enum ndis_medium ndis_medium; -/* -enum interface_type { - InterfaceTypeUndefined = -1, - Internal, - Isa, - Eisa, - MicroChannel, - TurboChannel, - PCIBus, - VMEBus, - NuBus, - PCMCIABus, - CBus, - MPIBus, - MPSABus, - ProcessorInternal, - InternalPowerBus, - PNPISABus, - PNPBus, - MaximumInterfaceType -}; -*/ -enum ndis_interface_type { - NdisInterfaceInternal = Internal, - NdisInterfaceIsa = Isa, - NdisInterfaceEisa = Eisa, - NdisInterfaceMca = MicroChannel, - NdisInterfaceTurboChannel = TurboChannel, - NdisInterfacePci = PCIBus, - NdisInterfacePcMcia = PCMCIABus -}; - -typedef enum ndis_interface_type ndis_interface_type; - -struct ndis_paddr_unit { - ndis_physaddr npu_physaddr; - uint32_t npu_len; -}; - -typedef struct ndis_paddr_unit ndis_paddr_unit; - -struct ndis_map_arg { - ndis_paddr_unit *nma_fraglist; - int nma_cnt; - int nma_max; -}; - -/* - * Miniport characteristics were originally defined in the NDIS 3.0 - * spec and then extended twice, in NDIS 4.0 and 5.0. - */ - -struct ndis_miniport_characteristics { - /* NDIS 3.0 */ - - uint8_t nmc_version_major; - uint8_t nmc_version_minor; - uint16_t nmc_pad; - uint32_t nmc_rsvd; - void * nmc_checkhang_func; - void * nmc_disable_interrupts_func; - void * nmc_enable_interrupts_func; - void * nmc_halt_func; - void * nmc_interrupt_func; - void * nmc_init_func; - void * nmc_isr_func; - void * nmc_queryinfo_func; - void * nmc_reconfig_func; - void * nmc_reset_func; - void * nmc_sendsingle_func; - void * nmc_setinfo_func; - void * nmc_transferdata_func; - - /* NDIS 4.0 extensions */ - - void * nmc_return_packet_func; - void * nmc_sendmulti_func; - void * nmc_allocate_complete_func; - - /* NDIS 5.0 extensions */ - - void * nmc_cocreatevc_func; - void * nmc_codeletevc_func; - void * nmc_coactivatevc_func; - void * nmc_codeactivatevc_func; - void * nmc_comultisend_func; - void * nmc_corequest_func; - - /* NDIS 5.1 extensions */ - - void * nmc_canceltxpkts_handler; - void * nmc_pnpevent_handler; - void * nmc_shutdown_handler; - void * nmc_rsvd0; - void * nmc_rsvd1; - void * nmc_rsvd2; - void * nmc_rsvd3; -}; - -typedef struct ndis_miniport_characteristics ndis_miniport_characteristics; - -struct ndis_driver_object { - char *ndo_ifname; - void *ndo_softc; - ndis_miniport_characteristics ndo_chars; -}; - -typedef struct ndis_driver_object ndis_driver_object; - -struct ndis_reference { - ndis_kspin_lock nr_spinlock; - uint16_t nr_refcnt; - uint8_t nr_closing; -}; - -typedef struct ndis_reference ndis_reference; - -struct ndis_timer_entry { - struct callout nte_ch; - ndis_miniport_timer *nte_timer; - TAILQ_ENTRY(ndis_timer_entry) link; -}; - -TAILQ_HEAD(nte_head, ndis_timer_entry); - -#define NDIS_FH_TYPE_VFS 0 -#define NDIS_FH_TYPE_MODULE 1 - -struct ndis_fh { - int nf_type; - char *nf_name; - void *nf_vp; - void *nf_map; - uint32_t nf_maplen; -}; - -typedef struct ndis_fh ndis_fh; - -/* - * The miniport block is basically the internal NDIS handle. We need - * to define this because, unfortunately, it is not entirely opaque - * to NDIS drivers. For one thing, it contains the function pointer - * to the NDIS packet receive handler, which is invoked out of the - * NDIS block via a macro rather than a function pointer. (The - * NdisMIndicateReceivePacket() routine is a macro rather than - * a function.) For another, the driver maintains a pointer to the - * miniport block and passes it as a handle to various NDIS functions. - * (The driver never really knows this because it's hidden behind - * an ndis_handle though.) - * - * The miniport block has two parts: the first part contains fields - * that must never change, since they are referenced by driver - * binaries through macros. The second part is ignored by the driver, - * but contains various things used internaly by NDIS.SYS. In our - * case, we define the first 'immutable' part exactly as it appears - * in Windows, but don't bother duplicating the Windows definitions - * for the second part. Instead, we replace them with a few BSD-specific - * things. - */ - -struct ndis_miniport_block { - /* - * Windows-specific portion -- DO NOT MODIFY OR NDIS - * DRIVERS WILL NOT WORK. - */ - void *nmb_signature; /* magic number */ - ndis_miniport_block *nmb_nextminiport; - ndis_mdriver_block *nmb_driverhandle; - ndis_handle nmb_miniportadapterctx; - ndis_unicode_string nmb_name; - ndis_bind_paths *nmb_bindpaths; - ndis_handle nmb_openqueue; - ndis_reference nmb_ref; - ndis_handle nmb_devicectx; - uint8_t nmb_padding; - uint8_t nmb_lockacquired; - uint8_t nmb_pmodeopens; - uint8_t nmb_assignedcpu; - ndis_kspin_lock nmb_lock; - ndis_request *nmb_mediarequest; - ndis_miniport_interrupt *nmb_interrupt; - uint32_t nmb_flags; - uint32_t nmb_pnpflags; - list_entry nmb_packetlist; - ndis_packet *nmb_firstpendingtxpacket; - ndis_packet *nmb_returnpacketqueue; - uint32_t nmb_requestbuffer; - void *nmb_setmcastbuf; - ndis_miniport_block *nmb_primaryminiport; - void *nmb_wrapperctx; - void *nmb_busdatactx; - uint32_t nmb_pnpcaps; - cm_resource_list *nmb_resources; - ndis_timer nmb_wkupdpctimer; - ndis_unicode_string nmb_basename; - ndis_unicode_string nmb_symlinkname; - uint32_t nmb_checkforhangsecs; - uint16_t nmb_cfhticks; - uint16_t nmb_cfhcurrticks; - ndis_status nmb_resetstatus; - ndis_handle nmb_resetopen; - ndis_filterdbs nmb_filterdbs; - void *nmb_pktind_func; - void *nmb_senddone_func; - void *nmb_sendrsrc_func; - void *nmb_resetdone_func; - ndis_medium nmb_medium; - uint32_t nmb_busnum; - uint32_t nmb_bustype; - uint32_t nmb_adaptertype; - 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; - void *nmb_setinfobuf; - uint16_t nmb_setinfobuflen; - uint16_t nmb_maxsendpkts; - ndis_status nmb_fakestatus; - void *nmb_lockhandler; - ndis_unicode_string *nmb_adapterinstancename; - void *nmb_timerqueue; - uint32_t nmb_mactoptions; - ndis_request *nmb_pendingreq; - uint32_t nmb_maxlongaddrs; - uint32_t nmb_maxshortaddrs; - uint32_t nmb_currlookahead; - uint32_t nmb_maxlookahead; - void *nmb_interrupt_func; - void *nmb_disableintr_func; - void *nmb_enableintr_func; - void *nmb_sendpkts_func; - void *nmb_deferredsend_func; - void *nmb_ethrxindicate_func; - void *nmb_txrxindicate_func; - void *nmb_fddirxindicate_func; - void *nmb_ethrxdone_func; - void *nmb_txrxdone_func; - void *nmb_fddirxcond_func; - void *nmb_status_func; - void *nmb_statusdone_func; - void *nmb_tdcond_func; - void *nmb_querydone_func; - void *nmb_setdone_func; - void *nmb_wantxdone_func; - void *nmb_wanrx_func; - void *nmb_wanrxdone_func; - /* - * End of windows-specific portion of miniport block. Everything - * below is BSD-specific. - */ - list_entry nmb_parmlist; - ndis_resource_list *nmb_rlist; - ndis_status nmb_getstat; - nt_kevent nmb_getevent; - ndis_status nmb_setstat; - nt_kevent nmb_setevent; - nt_kevent nmb_resetevent; - io_workitem *nmb_returnitem; - ndis_miniport_timer *nmb_timerlist; - ndis_handle nmb_rxpool; - list_entry nmb_returnlist; - kspin_lock nmb_returnlock; - TAILQ_ENTRY(ndis_miniport_block) link; -}; - -TAILQ_HEAD(nd_head, ndis_miniport_block); - -typedef ndis_status (*ndis_init_handler)(ndis_status *, uint32_t *, - ndis_medium *, uint32_t, ndis_handle, ndis_handle); -typedef ndis_status (*ndis_queryinfo_handler)(ndis_handle, ndis_oid, - void *, uint32_t, uint32_t *, uint32_t *); -typedef ndis_status (*ndis_setinfo_handler)(ndis_handle, ndis_oid, - void *, uint32_t, uint32_t *, uint32_t *); -typedef ndis_status (*ndis_sendsingle_handler)(ndis_handle, - ndis_packet *, uint32_t); -typedef ndis_status (*ndis_sendmulti_handler)(ndis_handle, - ndis_packet **, uint32_t); -typedef void (*ndis_isr_handler)(uint8_t *, uint8_t *, ndis_handle); -typedef void (*ndis_interrupt_handler)(ndis_handle); -typedef int (*ndis_reset_handler)(uint8_t *, ndis_handle); -typedef void (*ndis_halt_handler)(ndis_handle); -typedef void (*ndis_return_handler)(ndis_handle, ndis_packet *); -typedef void (*ndis_enable_interrupts_handler)(ndis_handle); -typedef void (*ndis_disable_interrupts_handler)(ndis_handle); -typedef void (*ndis_shutdown_handler)(void *); -typedef void (*ndis_pnpevent_handler)(void *, int, void *, uint32_t); -typedef void (*ndis_allocdone_handler)(ndis_handle, void *, - ndis_physaddr *, uint32_t, void *); -typedef uint8_t (*ndis_checkforhang_handler)(ndis_handle); - -typedef ndis_status (*driver_entry)(void *, unicode_string *); - -extern image_patch_table ndis_functbl[]; - -#define NDIS_TASKQUEUE 1 -#define NDIS_SWI 2 - -#define NDIS_PSTATE_RUNNING 1 -#define NDIS_PSTATE_SLEEPING 2 - -#define NdisQueryPacket(p, pbufcnt, bufcnt, firstbuf, plen) \ - do { \ - if ((firstbuf) != NULL) { \ - ndis_buffer **_first; \ - _first = firstbuf; \ - *(_first) = (p)->np_private.npp_head; \ - } \ - if ((plen) || (bufcnt) || (pbufcnt)) { \ - if ((p)->np_private.npp_validcounts == FALSE) { \ - ndis_buffer *tmp; \ - unsigned int tlen = 0, pcnt = 0; \ - unsigned int add = 0; \ - unsigned int pktlen, off; \ - \ - tmp = (p)->np_private.npp_head; \ - while (tmp != NULL) { \ - off = MmGetMdlByteOffset(tmp); \ - pktlen = MmGetMdlByteCount(tmp);\ - tlen += pktlen; \ - pcnt += \ - NDIS_BUFFER_TO_SPAN_PAGES(tmp); \ - add++; \ - tmp = tmp->mdl_next; \ - } \ - (p)->np_private.npp_count = add; \ - (p)->np_private.npp_totlen = tlen; \ - (p)->np_private.npp_physcnt = pcnt; \ - (p)->np_private.npp_validcounts = TRUE; \ - } \ - if (pbufcnt) { \ - unsigned int *_pbufcnt; \ - _pbufcnt = (pbufcnt); \ - *(_pbufcnt) = (p)->np_private.npp_physcnt; \ - } \ - if (bufcnt) { \ - unsigned int *_bufcnt; \ - _bufcnt = (bufcnt); \ - *(_bufcnt) = (p)->np_private.npp_count; \ - } \ - if (plen) { \ - unsigned int *_plen; \ - _plen = (plen); \ - *(_plen) = (p)->np_private.npp_totlen; \ - } \ - } \ - } while (0) - -__BEGIN_DECLS -extern int ndis_libinit(void); -extern int ndis_libfini(void); -extern int ndis_load_driver(vm_offset_t, void *); -extern int ndis_unload_driver(void *); -extern int ndis_mtop(struct mbuf *, ndis_packet **); -extern int ndis_ptom(struct mbuf **, ndis_packet *); -extern int ndis_get_info(void *, ndis_oid, void *, int *); -extern int ndis_set_info(void *, ndis_oid, void *, int *); -extern void *ndis_get_routine_address(struct image_patch_table *, char *); -extern int ndis_get_supported_oids(void *, ndis_oid **, int *); -extern int ndis_send_packets(void *, ndis_packet **, int); -extern int ndis_send_packet(void *, ndis_packet *); -extern int ndis_convert_res(void *); -extern void ndis_free_packet(ndis_packet *); -extern void ndis_free_bufs(ndis_buffer *); -extern int ndis_reset_nic(void *); -extern int ndis_halt_nic(void *); -extern int ndis_shutdown_nic(void *); -extern int ndis_pnpevent_nic(void *, int); -extern int ndis_init_nic(void *); -extern void ndis_return_packet(ndis_packet *); -extern int ndis_init_dma(void *); -extern int ndis_destroy_dma(void *); -extern int ndis_create_sysctls(void *); -extern int ndis_add_sysctl(void *, char *, char *, char *, int); -extern int ndis_flush_sysctls(void *); - -extern uint32_t NdisAddDevice(driver_object *, device_object *); -extern void NdisAllocatePacketPool(ndis_status *, - ndis_handle *, uint32_t, uint32_t); -extern void NdisAllocatePacketPoolEx(ndis_status *, - ndis_handle *, uint32_t, uint32_t, uint32_t); -extern uint32_t NdisPacketPoolUsage(ndis_handle); -extern void NdisFreePacketPool(ndis_handle); -extern void NdisAllocatePacket(ndis_status *, - ndis_packet **, ndis_handle); -extern void NdisFreePacket(ndis_packet *); -extern ndis_status NdisScheduleWorkItem(ndis_work_item *); -extern void NdisMSleep(uint32_t); -__END_DECLS - -#endif /* _NDIS_VAR_H_ */ diff --git a/sys/compat/ndis/ntoskrnl_var.h b/sys/compat/ndis/ntoskrnl_var.h deleted file mode 100644 index 3f9f604da947..000000000000 --- a/sys/compat/ndis/ntoskrnl_var.h +++ /dev/null @@ -1,1517 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul . All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _NTOSKRNL_VAR_H_ -#define _NTOSKRNL_VAR_H_ - -#define MTX_NTOSKRNL_SPIN_LOCK "NDIS thread lock" - -/* - * us_buf is really a wchar_t *, but it's inconvenient to include - * all the necessary header goop needed to define it, and it's a - * pointer anyway, so for now, just make it a uint16_t *. - */ -struct unicode_string { - uint16_t us_len; - uint16_t us_maxlen; - uint16_t *us_buf; -}; - -typedef struct unicode_string unicode_string; - -struct ansi_string { - uint16_t as_len; - uint16_t as_maxlen; - char *as_buf; -}; - -typedef struct ansi_string ansi_string; - -/* - * Windows memory descriptor list. In Windows, it's possible for - * buffers to be passed between user and kernel contexts without - * copying. Buffers may also be allocated in either paged or - * non-paged memory regions. An MDL describes the pages of memory - * used to contain a particular buffer. Note that a single MDL - * may describe a buffer that spans multiple pages. An array of - * page addresses appears immediately after the MDL structure itself. - * MDLs are therefore implicitly variably sized, even though they - * don't look it. - * - * Note that in FreeBSD, we can take many shortcuts in the way - * we handle MDLs because: - * - * - We are only concerned with pages in kernel context. This means - * we will only ever use the kernel's memory map, and remapping - * of buffers is never needed. - * - * - Kernel pages can never be paged out, so we don't have to worry - * about whether or not a page is actually mapped before going to - * touch it. - */ - -struct mdl { - struct mdl *mdl_next; - uint16_t mdl_size; - uint16_t mdl_flags; - void *mdl_process; - void *mdl_mappedsystemva; - void *mdl_startva; - uint32_t mdl_bytecount; - uint32_t mdl_byteoffset; -}; - -typedef struct mdl mdl, ndis_buffer; - -/* MDL flags */ - -#define MDL_MAPPED_TO_SYSTEM_VA 0x0001 -#define MDL_PAGES_LOCKED 0x0002 -#define MDL_SOURCE_IS_NONPAGED_POOL 0x0004 -#define MDL_ALLOCATED_FIXED_SIZE 0x0008 -#define MDL_PARTIAL 0x0010 -#define MDL_PARTIAL_HAS_BEEN_MAPPED 0x0020 -#define MDL_IO_PAGE_READ 0x0040 -#define MDL_WRITE_OPERATION 0x0080 -#define MDL_PARENT_MAPPED_SYSTEM_VA 0x0100 -#define MDL_FREE_EXTRA_PTES 0x0200 -#define MDL_IO_SPACE 0x0800 -#define MDL_NETWORK_HEADER 0x1000 -#define MDL_MAPPING_CAN_FAIL 0x2000 -#define MDL_ALLOCATED_MUST_SUCCEED 0x4000 -#define MDL_ZONE_ALLOCED 0x8000 /* BSD private */ - -#define MDL_ZONE_PAGES 16 -#define MDL_ZONE_SIZE (sizeof(mdl) + (sizeof(vm_offset_t) * MDL_ZONE_PAGES)) - -/* Note: assumes x86 page size of 4K. */ - -#ifndef PAGE_SHIFT -#if PAGE_SIZE == 4096 -#define PAGE_SHIFT 12 -#elif PAGE_SIZE == 8192 -#define PAGE_SHIFT 13 -#else -#error PAGE_SHIFT undefined! -#endif -#endif - -#define SPAN_PAGES(ptr, len) \ - ((uint32_t)((((uintptr_t)(ptr) & (PAGE_SIZE - 1)) + \ - (len) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)) - -#define PAGE_ALIGN(ptr) \ - ((void *)((uintptr_t)(ptr) & ~(PAGE_SIZE - 1))) - -#define BYTE_OFFSET(ptr) \ - ((uint32_t)((uintptr_t)(ptr) & (PAGE_SIZE - 1))) - -#define MDL_PAGES(m) (vm_offset_t *)(m + 1) - -#define MmInitializeMdl(b, baseva, len) \ - (b)->mdl_next = NULL; \ - (b)->mdl_size = (uint16_t)(sizeof(mdl) + \ - (sizeof(vm_offset_t) * SPAN_PAGES((baseva), (len)))); \ - (b)->mdl_flags = 0; \ - (b)->mdl_startva = (void *)PAGE_ALIGN((baseva)); \ - (b)->mdl_byteoffset = BYTE_OFFSET((baseva)); \ - (b)->mdl_bytecount = (uint32_t)(len); - -#define MmGetMdlByteOffset(mdl) ((mdl)->mdl_byteoffset) -#define MmGetMdlByteCount(mdl) ((mdl)->mdl_bytecount) -#define MmGetMdlVirtualAddress(mdl) \ - ((void *)((char *)((mdl)->mdl_startva) + (mdl)->mdl_byteoffset)) -#define MmGetMdlStartVa(mdl) ((mdl)->mdl_startva) -#define MmGetMdlPfnArray(mdl) MDL_PAGES(mdl) - -#define WDM_MAJOR 1 -#define WDM_MINOR_WIN98 0x00 -#define WDM_MINOR_WINME 0x05 -#define WDM_MINOR_WIN2000 0x10 -#define WDM_MINOR_WINXP 0x20 -#define WDM_MINOR_WIN2003 0x30 - -enum nt_caching_type { - MmNonCached = 0, - MmCached = 1, - MmWriteCombined = 2, - MmHardwareCoherentCached = 3, - MmNonCachedUnordered = 4, - MmUSWCCached = 5, - MmMaximumCacheType = 6 -}; - -/*- - * The ndis_kspin_lock type is called KSPIN_LOCK in MS-Windows. - * According to the Windows DDK header files, KSPIN_LOCK is defined like this: - * typedef ULONG_PTR KSPIN_LOCK; - * - * From basetsd.h (SDK, Feb. 2003): - * typedef [public] unsigned __int3264 ULONG_PTR, *PULONG_PTR; - * typedef unsigned __int64 ULONG_PTR, *PULONG_PTR; - * typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR; - * - * The keyword __int3264 specifies an integral type that has the following - * properties: - * + It is 32-bit on 32-bit platforms - * + It is 64-bit on 64-bit platforms - * + It is 32-bit on the wire for backward compatibility. - * It gets truncated on the sending side and extended appropriately - * (signed or unsigned) on the receiving side. - * - * Thus register_t seems the proper mapping onto FreeBSD for spin locks. - */ - -typedef register_t kspin_lock; - -struct slist_entry { - struct slist_entry *sl_next; -}; - -typedef struct slist_entry slist_entry; - -union slist_header { - uint64_t slh_align; - struct { - struct slist_entry *slh_next; - uint16_t slh_depth; - uint16_t slh_seq; - } slh_list; -}; - -typedef union slist_header slist_header; - -struct list_entry { - struct list_entry *nle_flink; - struct list_entry *nle_blink; -}; - -typedef struct list_entry list_entry; - -#define InitializeListHead(l) \ - (l)->nle_flink = (l)->nle_blink = (l) - -#define IsListEmpty(h) \ - ((h)->nle_flink == (h)) - -#define RemoveEntryList(e) \ - do { \ - list_entry *b; \ - list_entry *f; \ - \ - f = (e)->nle_flink; \ - b = (e)->nle_blink; \ - b->nle_flink = f; \ - f->nle_blink = b; \ - } while (0) - -/* These two have to be inlined since they return things. */ - -static __inline__ list_entry * -RemoveHeadList(list_entry *l) -{ - list_entry *f; - list_entry *e; - - e = l->nle_flink; - f = e->nle_flink; - l->nle_flink = f; - f->nle_blink = l; - - return (e); -} - -static __inline__ list_entry * -RemoveTailList(list_entry *l) -{ - list_entry *b; - list_entry *e; - - e = l->nle_blink; - b = e->nle_blink; - l->nle_blink = b; - b->nle_flink = l; - - return (e); -} - -#define InsertTailList(l, e) \ - do { \ - list_entry *b; \ - \ - b = l->nle_blink; \ - e->nle_flink = l; \ - e->nle_blink = b; \ - b->nle_flink = (e); \ - l->nle_blink = (e); \ - } while (0) - -#define InsertHeadList(l, e) \ - do { \ - list_entry *f; \ - \ - f = l->nle_flink; \ - e->nle_flink = f; \ - e->nle_blink = l; \ - f->nle_blink = e; \ - l->nle_flink = e; \ - } while (0) - -#define CONTAINING_RECORD(addr, type, field) \ - ((type *)((vm_offset_t)(addr) - (vm_offset_t)(&((type *)0)->field))) - -struct nt_dispatch_header { - uint8_t dh_type; - uint8_t dh_abs; - uint8_t dh_size; - uint8_t dh_inserted; - int32_t dh_sigstate; - list_entry dh_waitlisthead; -}; - -typedef struct nt_dispatch_header nt_dispatch_header; - -/* Dispatcher object types */ - -#define DISP_TYPE_NOTIFICATION_EVENT 0 /* KEVENT */ -#define DISP_TYPE_SYNCHRONIZATION_EVENT 1 /* KEVENT */ -#define DISP_TYPE_MUTANT 2 /* KMUTANT/KMUTEX */ -#define DISP_TYPE_PROCESS 3 /* KPROCESS */ -#define DISP_TYPE_QUEUE 4 /* KQUEUE */ -#define DISP_TYPE_SEMAPHORE 5 /* KSEMAPHORE */ -#define DISP_TYPE_THREAD 6 /* KTHREAD */ -#define DISP_TYPE_NOTIFICATION_TIMER 8 /* KTIMER */ -#define DISP_TYPE_SYNCHRONIZATION_TIMER 9 /* KTIMER */ - -#define OTYPE_EVENT 0 -#define OTYPE_MUTEX 1 -#define OTYPE_THREAD 2 -#define OTYPE_TIMER 3 - -/* Windows dispatcher levels. */ - -#define PASSIVE_LEVEL 0 -#define LOW_LEVEL 0 -#define APC_LEVEL 1 -#define DISPATCH_LEVEL 2 -#define DEVICE_LEVEL (DISPATCH_LEVEL + 1) -#define PROFILE_LEVEL 27 -#define CLOCK1_LEVEL 28 -#define CLOCK2_LEVEL 28 -#define IPI_LEVEL 29 -#define POWER_LEVEL 30 -#define HIGH_LEVEL 31 - -#define SYNC_LEVEL_UP DISPATCH_LEVEL -#define SYNC_LEVEL_MP (IPI_LEVEL - 1) - -#define AT_PASSIVE_LEVEL(td) \ - ((td)->td_proc->p_flag & P_KPROC == FALSE) - -#define AT_DISPATCH_LEVEL(td) \ - ((td)->td_base_pri == PI_REALTIME) - -#define AT_DIRQL_LEVEL(td) \ - ((td)->td_priority <= PI_NET) - -#define AT_HIGH_LEVEL(td) \ - ((td)->td_critnest != 0) - -struct nt_objref { - nt_dispatch_header no_dh; - void *no_obj; - TAILQ_ENTRY(nt_objref) link; -}; - -TAILQ_HEAD(nt_objref_head, nt_objref); - -typedef struct nt_objref nt_objref; - -#define EVENT_TYPE_NOTIFY 0 -#define EVENT_TYPE_SYNC 1 - -struct ktimer { - nt_dispatch_header k_header; - uint64_t k_duetime; - union { - list_entry k_timerlistentry; - struct callout *k_callout; - } u; - void *k_dpc; - uint32_t k_period; -}; - -#define k_timerlistentry u.k_timerlistentry -#define k_callout u.k_callout - -typedef struct ktimer ktimer; - -struct nt_kevent { - nt_dispatch_header k_header; -}; - -typedef struct nt_kevent nt_kevent; - -/* Kernel defered procedure call (i.e. timer callback) */ - -struct kdpc; -typedef void (*kdpc_func)(struct kdpc *, void *, void *, void *); - -struct kdpc { - uint16_t k_type; - uint8_t k_num; /* CPU number */ - uint8_t k_importance; /* priority */ - list_entry k_dpclistentry; - void *k_deferedfunc; - void *k_deferredctx; - void *k_sysarg1; - void *k_sysarg2; - void *k_lock; -}; - -#define KDPC_IMPORTANCE_LOW 0 -#define KDPC_IMPORTANCE_MEDIUM 1 -#define KDPC_IMPORTANCE_HIGH 2 - -#define KDPC_CPU_DEFAULT 255 - -typedef struct kdpc kdpc; - -/* - * Note: the acquisition count is BSD-specific. The Microsoft - * documentation says that mutexes can be acquired recursively - * by a given thread, but that you must release the mutex as - * many times as you acquired it before it will be set to the - * signalled state (i.e. before any other threads waiting on - * the object will be woken up). However the Windows KMUTANT - * structure has no field for keeping track of the number of - * acquisitions, so we need to add one ourselves. As long as - * driver code treats the mutex as opaque, we should be ok. - */ -struct kmutant { - nt_dispatch_header km_header; - list_entry km_listentry; - void *km_ownerthread; - uint8_t km_abandoned; - uint8_t km_apcdisable; -}; - -typedef struct kmutant kmutant; - -#define LOOKASIDE_DEPTH 256 - -struct general_lookaside { - slist_header gl_listhead; - uint16_t gl_depth; - uint16_t gl_maxdepth; - uint32_t gl_totallocs; - union { - uint32_t gl_allocmisses; - uint32_t gl_allochits; - } u_a; - uint32_t gl_totalfrees; - union { - uint32_t gl_freemisses; - uint32_t gl_freehits; - } u_m; - uint32_t gl_type; - uint32_t gl_tag; - uint32_t gl_size; - void *gl_allocfunc; - void *gl_freefunc; - list_entry gl_listent; - uint32_t gl_lasttotallocs; - union { - uint32_t gl_lastallocmisses; - uint32_t gl_lastallochits; - } u_l; - uint32_t gl_rsvd[2]; -}; - -typedef struct general_lookaside general_lookaside; - -struct npaged_lookaside_list { - general_lookaside nll_l; -#ifdef __i386__ - kspin_lock nll_obsoletelock; -#endif -}; - -typedef struct npaged_lookaside_list npaged_lookaside_list; -typedef struct npaged_lookaside_list paged_lookaside_list; - -typedef void * (*lookaside_alloc_func)(uint32_t, size_t, uint32_t); -typedef void (*lookaside_free_func)(void *); - -struct irp; - -struct kdevice_qentry { - list_entry kqe_devlistent; - uint32_t kqe_sortkey; - uint8_t kqe_inserted; -}; - -typedef struct kdevice_qentry kdevice_qentry; - -struct kdevice_queue { - uint16_t kq_type; - uint16_t kq_size; - list_entry kq_devlisthead; - kspin_lock kq_lock; - uint8_t kq_busy; -}; - -typedef struct kdevice_queue kdevice_queue; - -struct wait_ctx_block { - kdevice_qentry wcb_waitqueue; - void *wcb_devfunc; - void *wcb_devctx; - uint32_t wcb_mapregcnt; - void *wcb_devobj; - void *wcb_curirp; - void *wcb_bufchaindpc; -}; - -typedef struct wait_ctx_block wait_ctx_block; - -struct wait_block { - list_entry wb_waitlist; - void *wb_kthread; - nt_dispatch_header *wb_object; - struct wait_block *wb_next; -#ifdef notdef - uint16_t wb_waitkey; - uint16_t wb_waittype; -#endif - uint8_t wb_waitkey; - uint8_t wb_waittype; - uint8_t wb_awakened; - uint8_t wb_oldpri; -}; - -typedef struct wait_block wait_block; - -#define wb_ext wb_kthread - -#define THREAD_WAIT_OBJECTS 3 -#define MAX_WAIT_OBJECTS 64 - -#define WAITTYPE_ALL 0 -#define WAITTYPE_ANY 1 - -#define WAITKEY_VALID 0x8000 - -/* kthread priority */ -#define LOW_PRIORITY 0 -#define LOW_REALTIME_PRIORITY 16 -#define HIGH_PRIORITY 31 - -struct thread_context { - void *tc_thrctx; - void *tc_thrfunc; -}; - -typedef struct thread_context thread_context; - -/* Forward declaration */ -struct driver_object; -struct devobj_extension; - -struct driver_extension { - struct driver_object *dre_driverobj; - 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; - -/* - * The KINTERRUPT structure in Windows is opaque to drivers. - * We define our own custom version with things we need. - */ - -struct kinterrupt { - list_entry ki_list; - device_t ki_dev; - int ki_rid; - void *ki_cookie; - struct resource *ki_irq; - kspin_lock ki_lock_priv; - kspin_lock *ki_lock; - void *ki_svcfunc; - void *ki_svcctx; -}; - -typedef struct kinterrupt kinterrupt; - -struct ksystem_time { - uint32_t low_part; - int32_t high1_time; - int32_t high2_time; -}; - -enum nt_product_type { - NT_PRODUCT_WIN_NT = 1, - NT_PRODUCT_LAN_MAN_NT, - NT_PRODUCT_SERVER -}; - -enum alt_arch_type { - STANDARD_DESIGN, - NEC98x86, - END_ALTERNATIVES -}; - -struct kuser_shared_data { - uint32_t tick_count; - uint32_t tick_count_multiplier; - volatile struct ksystem_time interrupt_time; - volatile struct ksystem_time system_time; - volatile struct ksystem_time time_zone_bias; - uint16_t image_number_low; - uint16_t image_number_high; - int16_t nt_system_root[260]; - uint32_t max_stack_trace_depth; - uint32_t crypto_exponent; - uint32_t time_zone_id; - uint32_t large_page_min; - uint32_t reserved2[7]; - enum nt_product_type nt_product_type; - uint8_t product_type_is_valid; - uint32_t nt_major_version; - uint32_t nt_minor_version; - uint8_t processor_features[64]; - uint32_t reserved1; - uint32_t reserved3; - volatile uint32_t time_slip; - enum alt_arch_type alt_arch_type; - int64_t system_expiration_date; - uint32_t suite_mask; - uint8_t kdbg_enabled; - volatile uint32_t active_console; - volatile uint32_t dismount_count; - uint32_t com_plus_package; - uint32_t last_system_rit_event_tick_count; - uint32_t num_phys_pages; - uint8_t safe_boot_mode; - uint32_t trace_log; - uint64_t fill0; - uint64_t sys_call[4]; - union { - volatile struct ksystem_time tick_count; - volatile uint64_t tick_count_quad; - } tick; -}; - -/* - * In Windows, there are Physical Device Objects (PDOs) and - * Functional Device Objects (FDOs). Physical Device Objects are - * created and maintained by bus drivers. For example, the PCI - * bus driver might detect two PCI ethernet cards on a given - * bus. The PCI bus driver will then allocate two device_objects - * for its own internal bookeeping purposes. This is analogous - * to the device_t that the FreeBSD PCI code allocates and passes - * into each PCI driver's probe and attach routines. - * - * When an ethernet driver claims one of the ethernet cards - * on the bus, it will create its own device_object. This is - * the Functional Device Object. This object is analogous to the - * device-specific softc structure. - */ - -struct device_object { - uint16_t do_type; - uint16_t do_size; - uint32_t do_refcnt; - struct driver_object *do_drvobj; - struct device_object *do_nextdev; - struct device_object *do_attacheddev; - struct irp *do_currirp; - void *do_iotimer; - uint32_t do_flags; - uint32_t do_characteristics; - void *do_vpb; - void *do_devext; - uint32_t do_devtype; - uint8_t do_stacksize; - union { - list_entry do_listent; - wait_ctx_block do_wcb; - } queue; - uint32_t do_alignreq; - kdevice_queue do_devqueue; - struct kdpc do_dpc; - uint32_t do_activethreads; - void *do_securitydesc; - struct nt_kevent do_devlock; - uint16_t do_sectorsz; - uint16_t do_spare1; - struct devobj_extension *do_devobj_ext; - void *do_rsvd; -}; - -typedef struct device_object device_object; - -struct devobj_extension { - uint16_t dve_type; - uint16_t dve_size; - device_object *dve_devobj; -}; - -typedef struct devobj_extension devobj_extension; - -/* Device object flags */ - -#define DO_VERIFY_VOLUME 0x00000002 -#define DO_BUFFERED_IO 0x00000004 -#define DO_EXCLUSIVE 0x00000008 -#define DO_DIRECT_IO 0x00000010 -#define DO_MAP_IO_BUFFER 0x00000020 -#define DO_DEVICE_HAS_NAME 0x00000040 -#define DO_DEVICE_INITIALIZING 0x00000080 -#define DO_SYSTEM_BOOT_PARTITION 0x00000100 -#define DO_LONG_TERM_REQUESTS 0x00000200 -#define DO_NEVER_LAST_DEVICE 0x00000400 -#define DO_SHUTDOWN_REGISTERED 0x00000800 -#define DO_BUS_ENUMERATED_DEVICE 0x00001000 -#define DO_POWER_PAGABLE 0x00002000 -#define DO_POWER_INRUSH 0x00004000 -#define DO_LOW_PRIORITY_FILESYSTEM 0x00010000 - -/* Priority boosts */ - -#define IO_NO_INCREMENT 0 -#define IO_CD_ROM_INCREMENT 1 -#define IO_DISK_INCREMENT 1 -#define IO_KEYBOARD_INCREMENT 6 -#define IO_MAILSLOT_INCREMENT 2 -#define IO_MOUSE_INCREMENT 6 -#define IO_NAMED_PIPE_INCREMENT 2 -#define IO_NETWORK_INCREMENT 2 -#define IO_PARALLEL_INCREMENT 1 -#define IO_SERIAL_INCREMENT 2 -#define IO_SOUND_INCREMENT 8 -#define IO_VIDEO_INCREMENT 1 - -/* IRP major codes */ - -#define IRP_MJ_CREATE 0x00 -#define IRP_MJ_CREATE_NAMED_PIPE 0x01 -#define IRP_MJ_CLOSE 0x02 -#define IRP_MJ_READ 0x03 -#define IRP_MJ_WRITE 0x04 -#define IRP_MJ_QUERY_INFORMATION 0x05 -#define IRP_MJ_SET_INFORMATION 0x06 -#define IRP_MJ_QUERY_EA 0x07 -#define IRP_MJ_SET_EA 0x08 -#define IRP_MJ_FLUSH_BUFFERS 0x09 -#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a -#define IRP_MJ_SET_VOLUME_INFORMATION 0x0b -#define IRP_MJ_DIRECTORY_CONTROL 0x0c -#define IRP_MJ_FILE_SYSTEM_CONTROL 0x0d -#define IRP_MJ_DEVICE_CONTROL 0x0e -#define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f -#define IRP_MJ_SHUTDOWN 0x10 -#define IRP_MJ_LOCK_CONTROL 0x11 -#define IRP_MJ_CLEANUP 0x12 -#define IRP_MJ_CREATE_MAILSLOT 0x13 -#define IRP_MJ_QUERY_SECURITY 0x14 -#define IRP_MJ_SET_SECURITY 0x15 -#define IRP_MJ_POWER 0x16 -#define IRP_MJ_SYSTEM_CONTROL 0x17 -#define IRP_MJ_DEVICE_CHANGE 0x18 -#define IRP_MJ_QUERY_QUOTA 0x19 -#define IRP_MJ_SET_QUOTA 0x1a -#define IRP_MJ_PNP 0x1b -#define IRP_MJ_PNP_POWER IRP_MJ_PNP // Obsolete.... -#define IRP_MJ_MAXIMUM_FUNCTION 0x1b -#define IRP_MJ_SCSI IRP_MJ_INTERNAL_DEVICE_CONTROL - -/* IRP minor codes */ - -#define IRP_MN_QUERY_DIRECTORY 0x01 -#define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x02 -#define IRP_MN_USER_FS_REQUEST 0x00 - -#define IRP_MN_MOUNT_VOLUME 0x01 -#define IRP_MN_VERIFY_VOLUME 0x02 -#define IRP_MN_LOAD_FILE_SYSTEM 0x03 -#define IRP_MN_TRACK_LINK 0x04 -#define IRP_MN_KERNEL_CALL 0x04 - -#define IRP_MN_LOCK 0x01 -#define IRP_MN_UNLOCK_SINGLE 0x02 -#define IRP_MN_UNLOCK_ALL 0x03 -#define IRP_MN_UNLOCK_ALL_BY_KEY 0x04 - -#define IRP_MN_NORMAL 0x00 -#define IRP_MN_DPC 0x01 -#define IRP_MN_MDL 0x02 -#define IRP_MN_COMPLETE 0x04 -#define IRP_MN_COMPRESSED 0x08 - -#define IRP_MN_MDL_DPC (IRP_MN_MDL | IRP_MN_DPC) -#define IRP_MN_COMPLETE_MDL (IRP_MN_COMPLETE | IRP_MN_MDL) -#define IRP_MN_COMPLETE_MDL_DPC (IRP_MN_COMPLETE_MDL | IRP_MN_DPC) - -#define IRP_MN_SCSI_CLASS 0x01 - -#define IRP_MN_START_DEVICE 0x00 -#define IRP_MN_QUERY_REMOVE_DEVICE 0x01 -#define IRP_MN_REMOVE_DEVICE 0x02 -#define IRP_MN_CANCEL_REMOVE_DEVICE 0x03 -#define IRP_MN_STOP_DEVICE 0x04 -#define IRP_MN_QUERY_STOP_DEVICE 0x05 -#define IRP_MN_CANCEL_STOP_DEVICE 0x06 - -#define IRP_MN_QUERY_DEVICE_RELATIONS 0x07 -#define IRP_MN_QUERY_INTERFACE 0x08 -#define IRP_MN_QUERY_CAPABILITIES 0x09 -#define IRP_MN_QUERY_RESOURCES 0x0A -#define IRP_MN_QUERY_RESOURCE_REQUIREMENTS 0x0B -#define IRP_MN_QUERY_DEVICE_TEXT 0x0C -#define IRP_MN_FILTER_RESOURCE_REQUIREMENTS 0x0D - -#define IRP_MN_READ_CONFIG 0x0F -#define IRP_MN_WRITE_CONFIG 0x10 -#define IRP_MN_EJECT 0x11 -#define IRP_MN_SET_LOCK 0x12 -#define IRP_MN_QUERY_ID 0x13 -#define IRP_MN_QUERY_PNP_DEVICE_STATE 0x14 -#define IRP_MN_QUERY_BUS_INFORMATION 0x15 -#define IRP_MN_DEVICE_USAGE_NOTIFICATION 0x16 -#define IRP_MN_SURPRISE_REMOVAL 0x17 -#define IRP_MN_QUERY_LEGACY_BUS_INFORMATION 0x18 - -#define IRP_MN_WAIT_WAKE 0x00 -#define IRP_MN_POWER_SEQUENCE 0x01 -#define IRP_MN_SET_POWER 0x02 -#define IRP_MN_QUERY_POWER 0x03 - -#define IRP_MN_QUERY_ALL_DATA 0x00 -#define IRP_MN_QUERY_SINGLE_INSTANCE 0x01 -#define IRP_MN_CHANGE_SINGLE_INSTANCE 0x02 -#define IRP_MN_CHANGE_SINGLE_ITEM 0x03 -#define IRP_MN_ENABLE_EVENTS 0x04 -#define IRP_MN_DISABLE_EVENTS 0x05 -#define IRP_MN_ENABLE_COLLECTION 0x06 -#define IRP_MN_DISABLE_COLLECTION 0x07 -#define IRP_MN_REGINFO 0x08 -#define IRP_MN_EXECUTE_METHOD 0x09 -#define IRP_MN_REGINFO_EX 0x0b - -/* IRP flags */ - -#define IRP_NOCACHE 0x00000001 -#define IRP_PAGING_IO 0x00000002 -#define IRP_MOUNT_COMPLETION 0x00000002 -#define IRP_SYNCHRONOUS_API 0x00000004 -#define IRP_ASSOCIATED_IRP 0x00000008 -#define IRP_BUFFERED_IO 0x00000010 -#define IRP_DEALLOCATE_BUFFER 0x00000020 -#define IRP_INPUT_OPERATION 0x00000040 -#define IRP_SYNCHRONOUS_PAGING_IO 0x00000040 -#define IRP_CREATE_OPERATION 0x00000080 -#define IRP_READ_OPERATION 0x00000100 -#define IRP_WRITE_OPERATION 0x00000200 -#define IRP_CLOSE_OPERATION 0x00000400 -#define IRP_DEFER_IO_COMPLETION 0x00000800 -#define IRP_OB_QUERY_NAME 0x00001000 -#define IRP_HOLD_DEVICE_QUEUE 0x00002000 -#define IRP_RETRY_IO_COMPLETION 0x00004000 -#define IRP_CLASS_CACHE_OPERATION 0x00008000 -#define IRP_SET_USER_EVENT IRP_CLOSE_OPERATION - -/* IRP I/O control flags */ - -#define IRP_QUOTA_CHARGED 0x01 -#define IRP_ALLOCATED_MUST_SUCCEED 0x02 -#define IRP_ALLOCATED_FIXED_SIZE 0x04 -#define IRP_LOOKASIDE_ALLOCATION 0x08 - -/* I/O method types */ - -#define METHOD_BUFFERED 0 -#define METHOD_IN_DIRECT 1 -#define METHOD_OUT_DIRECT 2 -#define METHOD_NEITHER 3 - -/* File access types */ - -#define FILE_ANY_ACCESS 0x0000 -#define FILE_SPECIAL_ACCESS FILE_ANY_ACCESS -#define FILE_READ_ACCESS 0x0001 -#define FILE_WRITE_ACCESS 0x0002 - -/* Recover I/O access method from IOCTL code. */ - -#define IO_METHOD(x) ((x) & 0xFFFFFFFC) - -/* Recover function code from IOCTL code */ - -#define IO_FUNC(x) (((x) & 0x7FFC) >> 2) - -/* Macro to construct an IOCTL code. */ - -#define IOCTL_CODE(dev, func, iomethod, acc) \ - ((dev) << 16) | (acc << 14) | (func << 2) | (iomethod)) - -struct io_status_block { - union { - uint32_t isb_status; - void *isb_ptr; - } 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; - -struct kapc { - uint16_t apc_type; - uint16_t apc_size; - uint32_t apc_spare0; - void *apc_thread; - list_entry apc_list; - void *apc_kernfunc; - void *apc_rundownfunc; - void *apc_normalfunc; - void *apc_normctx; - void *apc_sysarg1; - void *apc_sysarg2; - uint8_t apc_stateidx; - uint8_t apc_cpumode; - uint8_t apc_inserted; -}; - -typedef struct kapc kapc; - -typedef uint32_t (*completion_func)(device_object *, - struct irp *, void *); -typedef uint32_t (*cancel_func)(device_object *, - struct irp *); - -struct io_stack_location { - uint8_t isl_major; - uint8_t isl_minor; - uint8_t isl_flags; - uint8_t isl_ctl; - - /* - * There's a big-ass union here in the actual Windows - * definition of the structure, but it contains stuff - * that doesn't really apply to BSD, and defining it - * all properly would require duplicating over a dozen - * other structures that we'll never use. Since the - * io_stack_location structure is opaque to drivers - * anyway, I'm not going to bother with the extra crap. - */ - - union { - struct { - uint32_t isl_len; - uint32_t *isl_key; - uint64_t isl_byteoff; - } isl_read; - struct { - uint32_t isl_len; - uint32_t *isl_key; - uint64_t isl_byteoff; - } isl_write; - struct { - uint32_t isl_obuflen; - uint32_t isl_ibuflen; - uint32_t isl_iocode; - void *isl_type3ibuf; - } isl_ioctl; - struct { - void *isl_arg1; - void *isl_arg2; - void *isl_arg3; - void *isl_arg4; - } isl_others; - } isl_parameters __attribute__((packed)); - - void *isl_devobj; - void *isl_fileobj; - completion_func isl_completionfunc; - void *isl_completionctx; -}; - -typedef struct io_stack_location io_stack_location; - -/* Stack location control flags */ - -#define SL_PENDING_RETURNED 0x01 -#define SL_INVOKE_ON_CANCEL 0x20 -#define SL_INVOKE_ON_SUCCESS 0x40 -#define SL_INVOKE_ON_ERROR 0x80 - -struct irp { - uint16_t irp_type; - uint16_t irp_size; - mdl *irp_mdl; - uint32_t irp_flags; - union { - struct irp *irp_master; - uint32_t irp_irpcnt; - void *irp_sysbuf; - } irp_assoc; - list_entry irp_thlist; - io_status_block irp_iostat; - uint8_t irp_reqmode; - uint8_t irp_pendingreturned; - uint8_t irp_stackcnt; - uint8_t irp_currentstackloc; - uint8_t irp_cancel; - uint8_t irp_cancelirql; - uint8_t irp_apcenv; - uint8_t irp_allocflags; - io_status_block *irp_usriostat; - nt_kevent *irp_usrevent; - union { - struct { - void *irp_apcfunc; - void *irp_apcctx; - } irp_asyncparms; - uint64_t irp_allocsz; - } irp_overlay; - cancel_func irp_cancelfunc; - void *irp_userbuf; - - /* Windows kernel info */ - - union { - struct { - union { - kdevice_qentry irp_dqe; - struct { - void *irp_drvctx[4]; - } s1; - } u1; - void *irp_thread; - char *irp_auxbuf; - struct { - list_entry irp_list; - union { - io_stack_location *irp_csl; - uint32_t irp_pkttype; - } u2; - } s2; - void *irp_fileobj; - } irp_overlay; - union { - kapc irp_apc; - struct { - void *irp_ep; - void *irp_dev; - } irp_usb; - } irp_misc; - void *irp_compkey; - } irp_tail; -}; - -#define irp_csl s2.u2.irp_csl -#define irp_pkttype s2.u2.irp_pkttype - -#define IRP_NDIS_DEV(irp) (irp)->irp_tail.irp_misc.irp_usb.irp_dev -#define IRP_NDISUSB_EP(irp) (irp)->irp_tail.irp_misc.irp_usb.irp_ep - -typedef struct irp irp; - -#define InterlockedExchangePointer(dst, val) \ - (void *)InterlockedExchange((uint32_t *)(dst), (uintptr_t)(val)) - -#define IoSizeOfIrp(ssize) \ - ((uint16_t) (sizeof(irp) + ((ssize) * (sizeof(io_stack_location))))) - -#define IoSetCancelRoutine(irp, func) \ - (cancel_func)InterlockedExchangePointer( \ - (void *)&(ip)->irp_cancelfunc, (void *)(func)) - -#define IoSetCancelValue(irp, val) \ - (u_long)InterlockedExchangePointer( \ - (void *)&(ip)->irp_cancel, (void *)(val)) - -#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; \ - s = IoGetNextIrpStackLocation((irp)); \ - s->isl_completionfunc = (func); \ - s->isl_completionctx = (ctx); \ - s->isl_ctl = 0; \ - 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 IoUnmarkIrpPending(irp) \ - IoGetCurrentIrpStackLocation(irp)->isl_ctl &= ~SL_PENDING_RETURNED - -#define IoCopyCurrentIrpStackLocationToNext(irp) \ - do { \ - io_stack_location *src, *dst; \ - src = IoGetCurrentIrpStackLocation(irp); \ - dst = IoGetNextIrpStackLocation(irp); \ - bcopy((char *)src, (char *)dst, \ - offsetof(io_stack_location, isl_completionfunc)); \ - } while(0) - -#define IoSkipCurrentIrpStackLocation(irp) \ - do { \ - (irp)->irp_currentstackloc++; \ - (irp)->irp_tail.irp_overlay.irp_csl++; \ - } while(0) - -#define IoInitializeDpcRequest(dobj, dpcfunc) \ - KeInitializeDpc(&(dobj)->do_dpc, dpcfunc, dobj) - -#define IoRequestDpc(dobj, irp, ctx) \ - KeInsertQueueDpc(&(dobj)->do_dpc, irp, ctx) - -typedef uint32_t (*driver_dispatch)(device_object *, irp *); - -/* - * The driver_object is allocated once for each driver that's loaded - * into the system. A new one is allocated for each driver and - * populated a bit via the driver's DriverEntry function. - * In general, a Windows DriverEntry() function will provide a pointer - * to its AddDevice() method and set up the dispatch table. - * For NDIS drivers, this is all done behind the scenes in the - * NdisInitializeWrapper() and/or NdisMRegisterMiniport() routines. - */ - -struct driver_object { - uint16_t dro_type; - uint16_t dro_size; - device_object *dro_devobj; - uint32_t dro_flags; - void *dro_driverstart; - uint32_t dro_driversize; - void *dro_driversection; - driver_extension *dro_driverext; - unicode_string dro_drivername; - unicode_string *dro_hwdb; - void *dro_pfastiodispatch; - void *dro_driverinitfunc; - void *dro_driverstartiofunc; - void *dro_driverunloadfunc; - driver_dispatch dro_dispatch[IRP_MJ_MAXIMUM_FUNCTION + 1]; -}; - -typedef struct driver_object driver_object; - -#define DEVPROP_DEVICE_DESCRIPTION 0x00000000 -#define DEVPROP_HARDWARE_ID 0x00000001 -#define DEVPROP_COMPATIBLE_IDS 0x00000002 -#define DEVPROP_BOOTCONF 0x00000003 -#define DEVPROP_BOOTCONF_TRANSLATED 0x00000004 -#define DEVPROP_CLASS_NAME 0x00000005 -#define DEVPROP_CLASS_GUID 0x00000006 -#define DEVPROP_DRIVER_KEYNAME 0x00000007 -#define DEVPROP_MANUFACTURER 0x00000008 -#define DEVPROP_FRIENDLYNAME 0x00000009 -#define DEVPROP_LOCATION_INFO 0x0000000A -#define DEVPROP_PHYSDEV_NAME 0x0000000B -#define DEVPROP_BUSTYPE_GUID 0x0000000C -#define DEVPROP_LEGACY_BUSTYPE 0x0000000D -#define DEVPROP_BUS_NUMBER 0x0000000E -#define DEVPROP_ENUMERATOR_NAME 0x0000000F -#define DEVPROP_ADDRESS 0x00000010 -#define DEVPROP_UINUMBER 0x00000011 -#define DEVPROP_INSTALL_STATE 0x00000012 -#define DEVPROP_REMOVAL_POLICY 0x00000013 - -/* 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 -#define STATUS_ALERTED 0x00000101 -#define STATUS_TIMEOUT 0x00000102 -#define STATUS_PENDING 0x00000103 -#define STATUS_FAILURE 0xC0000001 -#define STATUS_NOT_IMPLEMENTED 0xC0000002 -#define STATUS_ACCESS_VIOLATION 0xC0000005 -#define STATUS_INVALID_PARAMETER 0xC000000D -#define STATUS_INVALID_DEVICE_REQUEST 0xC0000010 -#define STATUS_MORE_PROCESSING_REQUIRED 0xC0000016 -#define STATUS_NO_MEMORY 0xC0000017 -#define STATUS_BUFFER_TOO_SMALL 0xC0000023 -#define STATUS_MUTANT_NOT_OWNED 0xC0000046 -#define STATUS_NOT_SUPPORTED 0xC00000BB -#define STATUS_INVALID_PARAMETER_2 0xC00000F0 -#define STATUS_INSUFFICIENT_RESOURCES 0xC000009A -#define STATUS_DEVICE_NOT_CONNECTED 0xC000009D -#define STATUS_CANCELLED 0xC0000120 -#define STATUS_NOT_FOUND 0xC0000225 -#define STATUS_DEVICE_REMOVED 0xC00002B6 - -#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 - -/* - * IO_WORKITEM is an opaque structures that must be allocated - * via IoAllocateWorkItem() and released via IoFreeWorkItem(). - * Consequently, we can define it any way we want. - */ -typedef void (*io_workitem_func)(device_object *, void *); - -struct io_workitem { - io_workitem_func iw_func; - void *iw_ctx; - list_entry iw_listentry; - device_object *iw_dobj; - int iw_idx; -}; - -typedef struct io_workitem io_workitem; - -#define WORKQUEUE_CRITICAL 0 -#define WORKQUEUE_DELAYED 1 -#define WORKQUEUE_HYPERCRITICAL 2 - -#define WORKITEM_THREADS 4 -#define WORKITEM_LEGACY_THREAD 3 -#define WORKIDX_INC(x) (x) = (x + 1) % WORKITEM_LEGACY_THREAD - -/* - * Older, deprecated work item API, needed to support NdisQueueWorkItem(). - */ - -struct work_queue_item; - -typedef void (*work_item_func)(struct work_queue_item *, void *); - -struct work_queue_item { - list_entry wqi_entry; - work_item_func wqi_func; - void *wqi_ctx; -}; - -typedef struct work_queue_item work_queue_item; - -#define ExInitializeWorkItem(w, func, ctx) \ - do { \ - (w)->wqi_func = (func); \ - (w)->wqi_ctx = (ctx); \ - InitializeListHead(&((w)->wqi_entry)); \ - } while (0) - -/* - * FreeBSD's kernel stack is 2 pages in size by default. The - * Windows stack is larger, so we need to give our threads more - * stack pages. 4 should be enough, we use 8 just to extra safe. - */ -#define NDIS_KSTACK_PAGES 8 - -/* - * Different kinds of function wrapping we can do. - */ - -#define WINDRV_WRAP_STDCALL 1 -#define WINDRV_WRAP_FASTCALL 2 -#define WINDRV_WRAP_REGPARM 3 -#define WINDRV_WRAP_CDECL 4 -#define WINDRV_WRAP_AMD64 5 - -struct drvdb_ent { - driver_object *windrv_object; - void *windrv_devlist; - ndis_cfg *windrv_regvals; - interface_type windrv_bustype; - STAILQ_ENTRY(drvdb_ent) link; -}; - -extern image_patch_table ntoskrnl_functbl[]; -#ifdef __amd64__ -extern struct kuser_shared_data kuser_shared_data; -#endif -typedef void (*funcptr)(void); -typedef int (*matchfuncptr)(interface_type, void *, void *); - -__BEGIN_DECLS -extern int windrv_libinit(void); -extern int windrv_libfini(void); -extern driver_object *windrv_lookup(vm_offset_t, char *); -extern struct drvdb_ent *windrv_match(matchfuncptr, void *); -extern int windrv_load(module_t, vm_offset_t, int, interface_type, - void *, ndis_cfg *); -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 windrv_wrap(funcptr, funcptr *, int, int); -extern int windrv_unwrap(funcptr); -extern void ctxsw_utow(void); -extern void ctxsw_wtou(void); - -extern int ntoskrnl_libinit(void); -extern int ntoskrnl_libfini(void); - -extern void ntoskrnl_intr(void *); -extern void ntoskrnl_time(uint64_t *); - -extern uint16_t ExQueryDepthSList(slist_header *); -extern slist_entry - *InterlockedPushEntrySList(slist_header *, slist_entry *); -extern slist_entry *InterlockedPopEntrySList(slist_header *); -extern uint32_t RtlUnicodeStringToAnsiString(ansi_string *, - unicode_string *, uint8_t); -extern uint32_t RtlAnsiStringToUnicodeString(unicode_string *, - ansi_string *, uint8_t); -extern void RtlInitAnsiString(ansi_string *, char *); -extern void RtlInitUnicodeString(unicode_string *, - uint16_t *); -extern void RtlFreeUnicodeString(unicode_string *); -extern void RtlFreeAnsiString(ansi_string *); -extern void KeInitializeDpc(kdpc *, void *, void *); -extern uint8_t KeInsertQueueDpc(kdpc *, void *, void *); -extern uint8_t KeRemoveQueueDpc(kdpc *); -extern void KeSetImportanceDpc(kdpc *, uint32_t); -extern void KeSetTargetProcessorDpc(kdpc *, uint8_t); -extern void KeFlushQueuedDpcs(void); -extern uint32_t KeGetCurrentProcessorNumber(void); -extern void KeInitializeTimer(ktimer *); -extern void KeInitializeTimerEx(ktimer *, uint32_t); -extern uint8_t KeSetTimer(ktimer *, int64_t, kdpc *); -extern uint8_t KeSetTimerEx(ktimer *, int64_t, uint32_t, kdpc *); -extern uint8_t KeCancelTimer(ktimer *); -extern uint8_t KeReadStateTimer(ktimer *); -extern uint32_t KeWaitForSingleObject(void *, uint32_t, - uint32_t, uint8_t, int64_t *); -extern void KeInitializeEvent(nt_kevent *, uint32_t, uint8_t); -extern void KeClearEvent(nt_kevent *); -extern uint32_t KeReadStateEvent(nt_kevent *); -extern uint32_t KeSetEvent(nt_kevent *, uint32_t, uint8_t); -extern uint32_t KeResetEvent(nt_kevent *); -#ifdef __i386__ -extern void KefAcquireSpinLockAtDpcLevel(kspin_lock *); -extern void KefReleaseSpinLockFromDpcLevel(kspin_lock *); -extern uint8_t KeAcquireSpinLockRaiseToDpc(kspin_lock *); -#else -extern void KeAcquireSpinLockAtDpcLevel(kspin_lock *); -extern void KeReleaseSpinLockFromDpcLevel(kspin_lock *); -#endif -extern void KeInitializeSpinLock(kspin_lock *); -extern uint8_t KeAcquireInterruptSpinLock(kinterrupt *); -extern void KeReleaseInterruptSpinLock(kinterrupt *, uint8_t); -extern uint8_t KeSynchronizeExecution(kinterrupt *, void *, void *); -extern uintptr_t InterlockedExchange(volatile uint32_t *, - uintptr_t); -extern void *ExAllocatePoolWithTag(uint32_t, size_t, uint32_t); -extern void ExFreePool(void *); -extern uint32_t IoConnectInterrupt(kinterrupt **, void *, void *, - kspin_lock *, uint32_t, uint8_t, uint8_t, uint8_t, uint8_t, - uint32_t, uint8_t); -extern uint8_t MmIsAddressValid(void *); -extern void *MmGetSystemRoutineAddress(unicode_string *); -extern void *MmMapIoSpace(uint64_t, uint32_t, uint32_t); -extern void MmUnmapIoSpace(void *, size_t); -extern void MmBuildMdlForNonPagedPool(mdl *); -extern void IoDisconnectInterrupt(kinterrupt *); -extern uint32_t IoAllocateDriverObjectExtension(driver_object *, - void *, uint32_t, void **); -extern void *IoGetDriverObjectExtension(driver_object *, void *); -extern uint32_t IoCreateDevice(driver_object *, uint32_t, - unicode_string *, uint32_t, uint32_t, uint8_t, device_object **); -extern void IoDeleteDevice(device_object *); -extern device_object *IoGetAttachedDevice(device_object *); -extern uint32_t IofCallDriver(device_object *, irp *); -extern void IofCompleteRequest(irp *, uint8_t); -extern void IoAcquireCancelSpinLock(uint8_t *); -extern void IoReleaseCancelSpinLock(uint8_t); -extern uint8_t IoCancelIrp(irp *); -extern void IoDetachDevice(device_object *); -extern device_object *IoAttachDeviceToDeviceStack(device_object *, - device_object *); -extern mdl *IoAllocateMdl(void *, uint32_t, uint8_t, uint8_t, irp *); -extern void IoFreeMdl(mdl *); -extern io_workitem *IoAllocateWorkItem(device_object *); -extern void ExQueueWorkItem(work_queue_item *, u_int32_t); -extern void IoFreeWorkItem(io_workitem *); -extern void IoQueueWorkItem(io_workitem *, io_workitem_func, - uint32_t, void *); - -#define IoCallDriver(a, b) IofCallDriver(a, b) -#define IoCompleteRequest(a, b) IofCompleteRequest(a, b) - -/* - * On the Windows x86 arch, KeAcquireSpinLock() and KeReleaseSpinLock() - * routines live in the HAL. We try to imitate this behavior. - */ -#ifdef __i386__ -#define KI_USER_SHARED_DATA 0xffdf0000 -#define KeAcquireSpinLock(a, b) *(b) = KfAcquireSpinLock(a) -#define KeReleaseSpinLock(a, b) KfReleaseSpinLock(a, b) -#define KeRaiseIrql(a, b) *(b) = KfRaiseIrql(a) -#define KeLowerIrql(a) KfLowerIrql(a) -#define KeAcquireSpinLockAtDpcLevel(a) KefAcquireSpinLockAtDpcLevel(a) -#define KeReleaseSpinLockFromDpcLevel(a) KefReleaseSpinLockFromDpcLevel(a) -#endif /* __i386__ */ - -#ifdef __amd64__ -#define KI_USER_SHARED_DATA 0xfffff78000000000UL -#define KeAcquireSpinLock(a, b) *(b) = KfAcquireSpinLock(a) -#define KeReleaseSpinLock(a, b) KfReleaseSpinLock(a, b) - -/* - * These may need to be redefined later; - * not sure where they live on amd64 yet. - */ -#define KeRaiseIrql(a, b) *(b) = KfRaiseIrql(a) -#define KeLowerIrql(a) KfLowerIrql(a) -#endif /* __amd64__ */ - -__END_DECLS - -#endif /* _NTOSKRNL_VAR_H_ */ diff --git a/sys/compat/ndis/pe_var.h b/sys/compat/ndis/pe_var.h deleted file mode 100644 index a7fdcacb2844..000000000000 --- a/sys/compat/ndis/pe_var.h +++ /dev/null @@ -1,555 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul . All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _PE_VAR_H_ -#define _PE_VAR_H_ - -/* - * Image Format - */ - -#define IMAGE_DOS_SIGNATURE 0x5A4D /* MZ */ -#define IMAGE_OS2_SIGNATURE 0x454E /* NE */ -#define IMAGE_OS2_SIGNATURE_LE 0x454C /* LE */ -#define IMAGE_VXD_SIGNATURE 0x454C /* LE */ -#define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */ - -/* - * All PE files have one of these, just so if you attempt to - * run them, they'll print out a message telling you they can - * only be run in Windows. - */ - -struct image_dos_header { - uint16_t idh_magic; /* Magic number */ - uint16_t idh_cblp; /* Bytes on last page of file */ - uint16_t idh_cp; /* Pages in file */ - uint16_t idh_crlc; /* Relocations */ - uint16_t idh_cparhdr; /* Size of header in paragraphs */ - uint16_t idh_minalloc; /* Minimum extra paragraphs needed */ - uint16_t idh_maxalloc; /* Maximum extra paragraphs needed */ - uint16_t idh_ss; /* Initial (relative) SS value */ - uint16_t idh_sp; /* Initial SP value */ - uint16_t idh_csum; /* Checksum */ - uint16_t idh_ip; /* Initial IP value */ - uint16_t idh_cs; /* Initial (relative) CS value */ - uint16_t idh_lfarlc; /* File address of relocation table */ - uint16_t idh_ovno; /* Overlay number */ - uint16_t idh_rsvd1[4]; /* Reserved words */ - uint16_t idh_oemid; /* OEM identifier (for idh_oeminfo) */ - uint16_t idh_oeminfo; /* OEM information; oemid specific */ - uint16_t idh_rsvd2[10]; /* Reserved words */ - uint32_t idh_lfanew; /* File address of new exe header */ -}; - -typedef struct image_dos_header image_dos_header; - -/* - * File header format. - */ - -struct image_file_header { - uint16_t ifh_machine; /* Machine type */ - uint16_t ifh_numsections; /* # of sections */ - uint32_t ifh_timestamp; /* Date/time stamp */ - uint32_t ifh_symtblptr; /* Offset to symbol table */ - uint32_t ifh_numsyms; /* # of symbols */ - uint16_t ifh_optionalhdrlen; /* Size of optional header */ - uint16_t ifh_characteristics; /* Characteristics */ -}; - -typedef struct image_file_header image_file_header; - -/* Machine types */ - -#define IMAGE_FILE_MACHINE_UNKNOWN 0 -#define IMAGE_FILE_MACHINE_I860 0x014d -#define IMAGE_FILE_MACHINE_I386 0x014c -#define IMAGE_FILE_MACHINE_R3000 0x0162 -#define IMAGE_FILE_MACHINE_R4000 0x0166 -#define IMAGE_FILE_MACHINE_R10000 0x0168 -#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 -#define IMAGE_FILE_MACHINE_ALPHA 0x0184 -#define IMAGE_FILE_MACHINE_SH3 0x01a2 -#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 -#define IMAGE_FILE_MACHINE_SH3E 0x01a4 -#define IMAGE_FILE_MACHINE_SH4 0x01a6 -#define IMAGE_FILE_MACHINE_SH5 0x01a8 -#define IMAGE_FILE_MACHINE_ARM 0x01c0 -#define IMAGE_FILE_MACHINE_THUMB 0x01c2 -#define IMAGE_FILE_MACHINE_AM33 0x01d3 -#define IMAGE_FILE_MACHINE_POWERPC 0x01f0 -#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 -#define IMAGE_FILE_MACHINE_MIPS16 0x0266 -#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 -#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 -#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 -#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64 -#define IMAGE_FILE_MACHINE_TRICORE 0x0520 -#define IMAGE_FILE_MACHINE_CEF 0x0cef -#define IMAGE_FILE_MACHINE_EBC 0x0ebc -#define IMAGE_FILE_MACHINE_AMD64 0x8664 -#define IMAGE_FILE_MACHINE_M32R 0x9041 -#define IMAGE_FILE_MACHINE_CEE 0xc0ee - -/* Characteristics */ - -#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 /* No relocation info */ -#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 -#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 -#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 -#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 -#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 -#define IMAGE_FILE_16BIT_MACHINE 0x0040 -#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 -#define IMAGE_FILE_32BIT_MACHINE 0x0100 -#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 -#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 -#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 -#define IMAGE_FILE_SYSTEM 0x1000 -#define IMAGE_FILE_DLL 0x2000 -#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 -#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 - -#define IMAGE_SIZEOF_FILE_HEADER 20 - -/* - * Directory format. - */ - -struct image_data_directory { - uint32_t idd_vaddr; /* virtual address */ - uint32_t idd_size; /* size */ -}; - -typedef struct image_data_directory image_data_directory; - -#define IMAGE_DIRECTORY_ENTRIES_MAX 16 - -/* - * Optional header format. - */ - -struct image_optional_header { - /* Standard fields */ - - uint16_t ioh_magic; - uint8_t ioh_linkerver_major; - uint8_t ioh_linkerver_minor; - uint32_t ioh_codesize; - uint32_t ioh_datasize; - uint32_t ioh_bsssize; - uint32_t ioh_entryaddr; - uint32_t ioh_codebaseaddr; -#ifndef __amd64__ - uint32_t ioh_databaseaddr; -#endif - - /* NT-specific fields */ - - uintptr_t ioh_imagebase; - uint32_t ioh_sectalign; - uint32_t ioh_filealign; - uint16_t ioh_osver_major; - uint16_t ioh_osver_minor; - uint16_t ioh_imagever_major; - uint16_t ioh_imagever_minor; - uint16_t ioh_subsys_major; - uint16_t ioh_subsys_minor; - uint32_t ioh_win32ver; - uint32_t ioh_imagesize; - uint32_t ioh_headersize; - uint32_t ioh_csum; - uint16_t ioh_subsys; - uint16_t ioh_dll_characteristics; - uintptr_t ioh_stackreservesize; - uintptr_t ioh_stackcommitsize; - uintptr_t ioh_heapreservesize; - uintptr_t ioh_heapcommitsize; - uint16_t ioh_loaderflags; - uint32_t ioh_rva_size_cnt; - image_data_directory ioh_datadir[IMAGE_DIRECTORY_ENTRIES_MAX]; -}; - -typedef struct image_optional_header image_optional_header; - -struct image_nt_header { - uint32_t inh_signature; - image_file_header inh_filehdr; - image_optional_header inh_optionalhdr; -}; - -typedef struct image_nt_header image_nt_header; - -#define IMAGE_SIZEOF_NT_HEADER(nthdr) \ - (offsetof(image_nt_header, inh_optionalhdr) + \ - ((image_nt_header *)(nthdr))->inh_filehdr.ifh_optionalhdrlen) - -/* Directory Entries */ - -#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 /* Export Directory */ -#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 /* Import Directory */ -#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 /* Resource Directory */ -#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 /* Exception Directory */ -#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 /* Security Directory */ -#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 /* Base Relocation Table */ -#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 /* Debug Directory */ -#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 /* Description String */ -#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 /* Machine Value (MIPS GP) */ -#define IMAGE_DIRECTORY_ENTRY_TLS 9 /* TLS Directory */ -#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 /* Load Configuration Directory */ -#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 /* Bound Import Directory in headers */ -#define IMAGE_DIRECTORY_ENTRY_IAT 12 /* Import Address Table */ -#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 -#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 - -/* Resource types */ - -#define RT_CURSOR 1 -#define RT_BITMAP 2 -#define RT_ICON 3 -#define RT_MENU 4 -#define RT_DIALOG 5 -#define RT_STRING 6 -#define RT_FONTDIR 7 -#define RT_FONT 8 -#define RT_ACCELERATOR 9 -#define RT_RCDATA 10 -#define RT_MESSAGETABLE 11 -#define RT_GROUP_CURSOR 12 -#define RT_GROUP_ICON 14 -#define RT_VERSION 16 -#define RT_DLGINCLUDE 17 -#define RT_PLUGPLAY 19 -#define RT_VXD 20 -#define RT_ANICURSOR 21 -#define RT_ANIICON 22 -#define RT_HTML 23 - -/* - * Section header format. - */ - -#define IMAGE_SHORT_NAME_LEN 8 - -struct image_section_header { - uint8_t ish_name[IMAGE_SHORT_NAME_LEN]; - union { - uint32_t ish_paddr; - uint32_t ish_vsize; - } ish_misc; - uint32_t ish_vaddr; - uint32_t ish_rawdatasize; - uint32_t ish_rawdataaddr; - uint32_t ish_relocaddr; - uint32_t ish_linenumaddr; - uint16_t ish_numrelocs; - uint16_t ish_numlinenums; - uint32_t ish_characteristics; -}; - -typedef struct image_section_header image_section_header; - -#define IMAGE_SIZEOF_SECTION_HEADER 40 - -#define IMAGE_FIRST_SECTION(nthdr) \ - ((image_section_header *)((vm_offset_t)(nthdr) + \ - offsetof(image_nt_header, inh_optionalhdr) + \ - ((image_nt_header *)(nthdr))->inh_filehdr.ifh_optionalhdrlen)) - -/* - * Import format - */ - -struct image_import_by_name { - uint16_t iibn_hint; - uint8_t iibn_name[1]; -}; - -#define IMAGE_ORDINAL_FLAG 0x80000000 -#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) - -struct image_import_descriptor { - uint32_t iid_import_name_table_addr; - uint32_t iid_timestamp; - uint32_t iid_forwardchain; - uint32_t iid_nameaddr; - uint32_t iid_import_address_table_addr; -}; - -typedef struct image_import_descriptor image_import_descriptor; - -struct image_base_reloc { - uint32_t ibr_vaddr; - uint32_t ibr_blocksize; - uint16_t ibr_rel[1]; -}; - -typedef struct image_base_reloc image_base_reloc; - -#define IMR_RELTYPE(x) ((x >> 12) & 0xF) -#define IMR_RELOFFSET(x) (x & 0xFFF) - -/* generic relocation types */ -#define IMAGE_REL_BASED_ABSOLUTE 0 -#define IMAGE_REL_BASED_HIGH 1 -#define IMAGE_REL_BASED_LOW 2 -#define IMAGE_REL_BASED_HIGHLOW 3 -#define IMAGE_REL_BASED_HIGHADJ 4 -#define IMAGE_REL_BASED_MIPS_JMPADDR 5 -#define IMAGE_REL_BASED_SECTION 6 -#define IMAGE_REL_BASED_REL 7 -#define IMAGE_REL_BASED_MIPS_JMPADDR16 9 -#define IMAGE_REL_BASED_DIR64 10 -#define IMAGE_REL_BASED_HIGH3ADJ 11 - -struct image_resource_directory_entry { - uint32_t irde_name; - uint32_t irde_dataoff; -}; - -typedef struct image_resource_directory_entry image_resource_directory_entry; - -#define RESOURCE_NAME_STR 0x80000000 -#define RESOURCE_DIR_FLAG 0x80000000 - -struct image_resource_directory { - uint32_t ird_characteristics; - uint32_t ird_timestamp; - uint16_t ird_majorver; - uint16_t ird_minorver; - uint16_t ird_named_entries; - uint16_t ird_id_entries; -#ifdef notdef - image_resource_directory_entry ird_entries[1]; -#endif -}; - -typedef struct image_resource_directory image_resource_directory; - -struct image_resource_directory_string { - uint16_t irds_len; - char irds_name[1]; -}; - -typedef struct image_resource_directory_string image_resource_directory_string; - -struct image_resource_directory_string_u { - uint16_t irds_len; - char irds_name[1]; -}; - -typedef struct image_resource_directory_string_u - image_resource_directory_string_u; - -struct image_resource_data_entry { - uint32_t irde_offset; - uint32_t irde_size; - uint32_t irde_codepage; - uint32_t irde_rsvd; -}; - -typedef struct image_resource_data_entry image_resource_data_entry; - -struct message_resource_data { - uint32_t mrd_numblocks; -#ifdef notdef - message_resource_block mrd_blocks[1]; -#endif -}; - -typedef struct message_resource_data message_resource_data; - -struct message_resource_block { - uint32_t mrb_lowid; - uint32_t mrb_highid; - uint32_t mrb_entryoff; -}; - -typedef struct message_resource_block message_resource_block; - -struct message_resource_entry { - uint16_t mre_len; - uint16_t mre_flags; - char mre_text[]; -}; - -typedef struct message_resource_entry message_resource_entry; - -#define MESSAGE_RESOURCE_UNICODE 0x0001 - -struct image_patch_table { - char *ipt_name; - void (*ipt_func)(void); - void (*ipt_wrap)(void); - int ipt_argcnt; - int ipt_ftype; -}; - -typedef struct image_patch_table image_patch_table; - -/* - * AMD64 support. Microsoft uses a different calling convention - * than everyone else on the amd64 platform. Sadly, gcc has no - * built-in support for it (yet). - * - * The three major differences we're concerned with are: - * - * - The first 4 register-sized arguments are passed in the - * %rcx, %rdx, %r8 and %r9 registers, and the rest are pushed - * onto the stack. (The ELF ABI uses 6 registers, not 4). - * - * - The caller must reserve space on the stack for the 4 - * register arguments in case the callee has to spill them. - * - * - The stack myst be 16-byte aligned by the time the callee - * executes. A call instruction implicitly pushes an 8 byte - * return address onto the stack. We have to make sure that - * the amount of space we consume, plus the return address, - * is a multiple of 16 bytes in size. This means that in - * some cases, we may need to chew up an extra 8 bytes on - * the stack that will be unused. - * - * On the bright side, Microsoft seems to be using just the one - * calling convention for all functions on amd64, unlike x86 where - * they use a mix of _stdcall, _fastcall and _cdecl. - */ - -#ifdef __amd64__ - -extern uint64_t x86_64_call1(void *, uint64_t); -extern uint64_t x86_64_call2(void *, uint64_t, uint64_t); -extern uint64_t x86_64_call3(void *, uint64_t, uint64_t, uint64_t); -extern uint64_t x86_64_call4(void *, uint64_t, uint64_t, uint64_t, uint64_t); -extern uint64_t x86_64_call5(void *, uint64_t, uint64_t, uint64_t, uint64_t, - uint64_t); -extern uint64_t x86_64_call6(void *, uint64_t, uint64_t, uint64_t, uint64_t, - uint64_t, uint64_t); - -uint64_t _x86_64_call1(void *, uint64_t); -uint64_t _x86_64_call2(void *, uint64_t, uint64_t); -uint64_t _x86_64_call3(void *, uint64_t, uint64_t, uint64_t); -uint64_t _x86_64_call4(void *, uint64_t, uint64_t, uint64_t, uint64_t); -uint64_t _x86_64_call5(void *, uint64_t, uint64_t, uint64_t, uint64_t, - uint64_t); -uint64_t _x86_64_call6(void *, uint64_t, uint64_t, uint64_t, uint64_t, - uint64_t, uint64_t); - -#define MSCALL1(fn, a) \ - _x86_64_call1((fn), (uint64_t)(a)) -#define MSCALL2(fn, a, b) \ - _x86_64_call2((fn), (uint64_t)(a), (uint64_t)(b)) -#define MSCALL3(fn, a, b, c) \ - _x86_64_call3((fn), (uint64_t)(a), (uint64_t)(b), \ - (uint64_t)(c)) -#define MSCALL4(fn, a, b, c, d) \ - _x86_64_call4((fn), (uint64_t)(a), (uint64_t)(b), \ - (uint64_t)(c), (uint64_t)(d)) -#define MSCALL5(fn, a, b, c, d, e) \ - _x86_64_call5((fn), (uint64_t)(a), (uint64_t)(b), \ - (uint64_t)(c), (uint64_t)(d), (uint64_t)(e)) -#define MSCALL6(fn, a, b, c, d, e, f) \ - _x86_64_call6((fn), (uint64_t)(a), (uint64_t)(b), \ - (uint64_t)(c), (uint64_t)(d), (uint64_t)(e), (uint64_t)(f)) - -#endif /* __amd64__ */ - -#ifdef __i386__ - -extern uint32_t x86_stdcall_call(void *, int, ...); - -#define MSCALL1(fn, a) x86_stdcall_call(fn, 1, (a)) -#define MSCALL2(fn, a, b) x86_stdcall_call(fn, 2, (a), (b)) -#define MSCALL3(fn, a, b, c) x86_stdcall_call(fn, 3, (a), (b), (c)) -#define MSCALL4(fn, a, b, c, d) x86_stdcall_call(fn, 4, (a), (b), (c), (d)) -#define MSCALL5(fn, a, b, c, d, e) \ - x86_stdcall_call(fn, 5, (a), (b), (c), (d), (e)) -#define MSCALL6(fn, a, b, c, d, e, f) \ - x86_stdcall_call(fn, 6, (a), (b), (c), (d), (e), (f)) - -#endif /* __i386__ */ - -#define FUNC void(*)(void) - -#ifdef __i386__ -#define IMPORT_SFUNC(x, y) { #x, (FUNC)x, NULL, y, WINDRV_WRAP_STDCALL } -#define IMPORT_SFUNC_MAP(x, y, z) \ - { #x, (FUNC)y, NULL, z, WINDRV_WRAP_STDCALL } -#define IMPORT_FFUNC(x, y) { #x, (FUNC)x, NULL, y, WINDRV_WRAP_FASTCALL } -#define IMPORT_FFUNC_MAP(x, y, z) \ - { #x, (FUNC)y, NULL, z, WINDRV_WRAP_FASTCALL } -#define IMPORT_RFUNC(x, y) { #x, (FUNC)x, NULL, y, WINDRV_WRAP_REGPARM } -#define IMPORT_RFUNC_MAP(x, y, z) \ - { #x, (FUNC)y, NULL, z, WINDRV_WRAP_REGPARM } -#define IMPORT_CFUNC(x, y) { #x, (FUNC)x, NULL, y, WINDRV_WRAP_CDECL } -#define IMPORT_CFUNC_MAP(x, y, z) \ - { #x, (FUNC)y, NULL, z, WINDRV_WRAP_CDECL } -#endif /* __i386__ */ - -#ifdef __amd64__ -#define IMPORT_SFUNC(x, y) { #x, (FUNC)x, NULL, y, WINDRV_WRAP_AMD64 } -#define IMPORT_SFUNC_MAP(x, y, z) \ - { #x, (FUNC)y, NULL, z, WINDRV_WRAP_AMD64 } -#define IMPORT_FFUNC(x, y) { #x, (FUNC)x, NULL, y, WINDRV_WRAP_AMD64 } -#define IMPORT_FFUNC_MAP(x, y, z) \ - { #x, (FUNC)y, NULL, z, WINDRV_WRAP_AMD64 } -#define IMPORT_RFUNC(x, y) { #x, (FUNC)x, NULL, y, WINDRV_WRAP_AMD64 } -#define IMPORT_RFUNC_MAP(x, y, z) \ - { #x, (FUNC)y, NULL, z, WINDRV_WRAP_AMD64 } -#define IMPORT_CFUNC(x, y) { #x, (FUNC)x, NULL, y, WINDRV_WRAP_AMD64 } -#define IMPORT_CFUNC_MAP(x, y, z) \ - { #x, (FUNC)y, NULL, z, WINDRV_WRAP_AMD64 } -#endif /* __amd64__ */ - -__BEGIN_DECLS -extern int pe_get_dos_header(vm_offset_t, image_dos_header *); -extern int pe_is_nt_image(vm_offset_t); -extern int pe_get_optional_header(vm_offset_t, image_optional_header *); -extern int pe_get_file_header(vm_offset_t, image_file_header *); -extern int pe_get_section_header(vm_offset_t, image_section_header *); -extern int pe_numsections(vm_offset_t); -extern vm_offset_t pe_imagebase(vm_offset_t); -extern vm_offset_t pe_directory_offset(vm_offset_t, uint32_t); -extern vm_offset_t pe_translate_addr (vm_offset_t, vm_offset_t); -extern int pe_get_section(vm_offset_t, image_section_header *, const char *); -extern int pe_relocate(vm_offset_t); -extern int pe_get_import_descriptor(vm_offset_t, image_import_descriptor *, char *); -extern int pe_patch_imports(vm_offset_t, char *, image_patch_table *); -extern int pe_get_messagetable(vm_offset_t, message_resource_data **); -extern int pe_get_message(vm_offset_t, uint32_t, char **, int *, uint16_t *); -__END_DECLS - -#endif /* _PE_VAR_H_ */ diff --git a/sys/compat/ndis/resource_var.h b/sys/compat/ndis/resource_var.h deleted file mode 100644 index b06a2e09f910..000000000000 --- a/sys/compat/ndis/resource_var.h +++ /dev/null @@ -1,201 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2005 - * Bill Paul . All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _RESOURCE_VAR_H_ -#define _RESOURCE_VAR_H_ - -typedef int cm_resource_type; - -struct physaddr { - uint64_t np_quad; -#ifdef notdef - uint32_t np_low; - uint32_t np_high; -#endif -}; - -typedef struct physaddr physaddr; - -enum interface_type { - InterfaceTypeUndefined = -1, - Internal, - Isa, - Eisa, - MicroChannel, - TurboChannel, - PCIBus, - VMEBus, - NuBus, - PCMCIABus, - CBus, - MPIBus, - MPSABus, - ProcessorInternal, - InternalPowerBus, - PNPISABus, - PNPBus, - MaximumInterfaceType -}; - -typedef enum interface_type interface_type; - -#define CmResourceTypeNull 0 /* ResType_All or ResType_None (0x0000) */ -#define CmResourceTypePort 1 /* ResType_IO (0x0002) */ -#define CmResourceTypeInterrupt 2 /* ResType_IRQ (0x0004) */ -#define CmResourceTypeMemory 3 /* ResType_Mem (0x0001) */ -#define CmResourceTypeDma 4 /* ResType_DMA (0x0003) */ -#define CmResourceTypeDeviceSpecific 5 /* ResType_ClassSpecific (0xFFFF) */ -#define CmResourceTypeBusNumber 6 /* ResType_BusNumber (0x0006) */ -#define CmResourceTypeMaximum 7 -#define CmResourceTypeNonArbitrated 128 /* Not arbitrated if 0x80 bit set */ -#define CmResourceTypeConfigData 128 /* ResType_Reserved (0x8000) */ -#define CmResourceTypeDevicePrivate 129 /* ResType_DevicePrivate (0x8001) */ -#define CmResourceTypePcCardConfig 130 /* ResType_PcCardConfig (0x8002) */ - -enum cm_share_disposition { - CmResourceShareUndetermined = 0, /* Reserved */ - CmResourceShareDeviceExclusive, - CmResourceShareDriverExclusive, - CmResourceShareShared -}; - -typedef enum cm_share_disposition cm_share_disposition; - -/* Define the bit masks for Flags when type is CmResourceTypeInterrupt */ - -#define CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE 0 -#define CM_RESOURCE_INTERRUPT_LATCHED 1 - -/* Define the bit masks for Flags when type is CmResourceTypeMemory */ - -#define CM_RESOURCE_MEMORY_READ_WRITE 0x0000 -#define CM_RESOURCE_MEMORY_READ_ONLY 0x0001 -#define CM_RESOURCE_MEMORY_WRITE_ONLY 0x0002 -#define CM_RESOURCE_MEMORY_PREFETCHABLE 0x0004 - -#define CM_RESOURCE_MEMORY_COMBINEDWRITE 0x0008 -#define CM_RESOURCE_MEMORY_24 0x0010 -#define CM_RESOURCE_MEMORY_CACHEABLE 0x0020 - -/* Define the bit masks for Flags when type is CmResourceTypePort */ - -#define CM_RESOURCE_PORT_MEMORY 0x0000 -#define CM_RESOURCE_PORT_IO 0x0001 -#define CM_RESOURCE_PORT_10_BIT_DECODE 0x0004 -#define CM_RESOURCE_PORT_12_BIT_DECODE 0x0008 -#define CM_RESOURCE_PORT_16_BIT_DECODE 0x0010 -#define CM_RESOURCE_PORT_POSITIVE_DECODE 0x0020 -#define CM_RESOURCE_PORT_PASSIVE_DECODE 0x0040 -#define CM_RESOURCE_PORT_WINDOW_DECODE 0x0080 - -/* Define the bit masks for Flags when type is CmResourceTypeDma */ - -#define CM_RESOURCE_DMA_8 0x0000 -#define CM_RESOURCE_DMA_16 0x0001 -#define CM_RESOURCE_DMA_32 0x0002 -#define CM_RESOURCE_DMA_8_AND_16 0x0004 -#define CM_RESOURCE_DMA_BUS_MASTER 0x0008 -#define CM_RESOURCE_DMA_TYPE_A 0x0010 -#define CM_RESOURCE_DMA_TYPE_B 0x0020 -#define CM_RESOURCE_DMA_TYPE_F 0x0040 - -struct cm_partial_resource_desc { - uint8_t cprd_type; - uint8_t cprd_sharedisp; - uint16_t cprd_flags; - union { - struct { - physaddr cprd_start; - uint32_t cprd_len; - } cprd_generic; - struct { - physaddr cprd_start; - uint32_t cprd_len; - } cprd_port; - struct { - uint32_t cprd_level; - uint32_t cprd_vector; - uint32_t cprd_affinity; - } cprd_intr; - struct { - physaddr cprd_start; - uint32_t cprd_len; - } cprd_mem; - struct { - uint32_t cprd_chan; - uint32_t cprd_port; - uint32_t cprd_rsvd; - } cprd_dmachan; - struct { - uint32_t cprd_data[3]; - } cprd_devpriv; - struct { - uint32_t cprd_datasize; - uint32_t cprd_rsvd1; - uint32_t cprd_rsvd2; - } cprd_devspec; - } u __attribute__((packed)); -}; - -typedef struct cm_partial_resource_desc cm_partial_resource_desc; - -struct cm_partial_resource_list { - uint16_t cprl_version; - uint16_t cprl_revision; - uint32_t cprl_count; - cm_partial_resource_desc cprl_partial_descs[1]; -}; - -typedef struct cm_partial_resource_list cm_partial_resource_list; - -struct cm_full_resource_list { - interface_type cfrl_type; - uint32_t cfrl_busnum; - cm_partial_resource_desc cfrl_partiallist; -}; - -typedef struct cm_full_resource_list cm_full_resource_list; - -struct cm_resource_list { - uint32_t crl_count; - cm_full_resource_list crl_rlist; -}; - -typedef struct cm_resource_list cm_resource_list; - -typedef cm_partial_resource_list ndis_resource_list; - -#endif /* _RESOURCE_VAR_H_ */ diff --git a/sys/compat/ndis/subr_hal.c b/sys/compat/ndis/subr_hal.c deleted file mode 100644 index c609db52ed2d..000000000000 --- a/sys/compat/ndis/subr_hal.c +++ /dev/null @@ -1,482 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul . 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -static void KeStallExecutionProcessor(uint32_t); -static void WRITE_PORT_BUFFER_ULONG(uint32_t *, - uint32_t *, uint32_t); -static void WRITE_PORT_BUFFER_USHORT(uint16_t *, - uint16_t *, uint32_t); -static void WRITE_PORT_BUFFER_UCHAR(uint8_t *, - uint8_t *, uint32_t); -static void WRITE_PORT_ULONG(uint32_t *, uint32_t); -static void WRITE_PORT_USHORT(uint16_t *, uint16_t); -static void WRITE_PORT_UCHAR(uint8_t *, uint8_t); -static uint32_t READ_PORT_ULONG(uint32_t *); -static uint16_t READ_PORT_USHORT(uint16_t *); -static uint8_t READ_PORT_UCHAR(uint8_t *); -static void READ_PORT_BUFFER_ULONG(uint32_t *, - uint32_t *, uint32_t); -static void READ_PORT_BUFFER_USHORT(uint16_t *, - uint16_t *, uint32_t); -static void READ_PORT_BUFFER_UCHAR(uint8_t *, - uint8_t *, uint32_t); -static uint64_t KeQueryPerformanceCounter(uint64_t *); -static void _KeLowerIrql(uint8_t); -static uint8_t KeRaiseIrqlToDpcLevel(void); -static void dummy (void); - -#define NDIS_MAXCPUS 64 -static struct mtx disp_lock[NDIS_MAXCPUS]; - -int -hal_libinit() -{ - image_patch_table *patch; - int i; - - for (i = 0; i < NDIS_MAXCPUS; i++) - mtx_init(&disp_lock[i], "HAL preemption lock", - "HAL lock", MTX_RECURSE|MTX_DEF); - - patch = hal_functbl; - while (patch->ipt_func != NULL) { - windrv_wrap((funcptr)patch->ipt_func, - (funcptr *)&patch->ipt_wrap, - patch->ipt_argcnt, patch->ipt_ftype); - patch++; - } - - return (0); -} - -int -hal_libfini() -{ - image_patch_table *patch; - int i; - - for (i = 0; i < NDIS_MAXCPUS; i++) - mtx_destroy(&disp_lock[i]); - - patch = hal_functbl; - while (patch->ipt_func != NULL) { - windrv_unwrap(patch->ipt_wrap); - patch++; - } - - return (0); -} - -static void -KeStallExecutionProcessor(usecs) - uint32_t usecs; -{ - DELAY(usecs); -} - -static void -WRITE_PORT_ULONG(port, val) - uint32_t *port; - uint32_t val; -{ - bus_space_write_4(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port, val); -} - -static void -WRITE_PORT_USHORT(uint16_t *port, uint16_t val) -{ - bus_space_write_2(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port, val); -} - -static void -WRITE_PORT_UCHAR(uint8_t *port, uint8_t val) -{ - bus_space_write_1(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port, val); -} - -static void -WRITE_PORT_BUFFER_ULONG(port, val, cnt) - uint32_t *port; - uint32_t *val; - uint32_t cnt; -{ - bus_space_write_multi_4(NDIS_BUS_SPACE_IO, 0x0, - (bus_size_t)port, val, cnt); -} - -static void -WRITE_PORT_BUFFER_USHORT(port, val, cnt) - uint16_t *port; - uint16_t *val; - uint32_t cnt; -{ - bus_space_write_multi_2(NDIS_BUS_SPACE_IO, 0x0, - (bus_size_t)port, val, cnt); -} - -static void -WRITE_PORT_BUFFER_UCHAR(port, val, cnt) - uint8_t *port; - uint8_t *val; - uint32_t cnt; -{ - bus_space_write_multi_1(NDIS_BUS_SPACE_IO, 0x0, - (bus_size_t)port, val, cnt); -} - -static uint16_t -READ_PORT_USHORT(port) - uint16_t *port; -{ - return (bus_space_read_2(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port)); -} - -static uint32_t -READ_PORT_ULONG(port) - uint32_t *port; -{ - return (bus_space_read_4(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port)); -} - -static uint8_t -READ_PORT_UCHAR(port) - uint8_t *port; -{ - return (bus_space_read_1(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port)); -} - -static void -READ_PORT_BUFFER_ULONG(port, val, cnt) - uint32_t *port; - uint32_t *val; - uint32_t cnt; -{ - bus_space_read_multi_4(NDIS_BUS_SPACE_IO, 0x0, - (bus_size_t)port, val, cnt); -} - -static void -READ_PORT_BUFFER_USHORT(port, val, cnt) - uint16_t *port; - uint16_t *val; - uint32_t cnt; -{ - bus_space_read_multi_2(NDIS_BUS_SPACE_IO, 0x0, - (bus_size_t)port, val, cnt); -} - -static void -READ_PORT_BUFFER_UCHAR(port, val, cnt) - uint8_t *port; - uint8_t *val; - uint32_t cnt; -{ - bus_space_read_multi_1(NDIS_BUS_SPACE_IO, 0x0, - (bus_size_t)port, val, cnt); -} - -/* - * The spinlock implementation in Windows differs from that of FreeBSD. - * The basic operation of spinlocks involves two steps: 1) spin in a - * tight loop while trying to acquire a lock, 2) after obtaining the - * lock, disable preemption. (Note that on uniprocessor systems, you're - * allowed to skip the first step and just lock out pre-emption, since - * it's not possible for you to be in contention with another running - * thread.) Later, you release the lock then re-enable preemption. - * The difference between Windows and FreeBSD lies in how preemption - * is disabled. In FreeBSD, it's done using critical_enter(), which on - * the x86 arch translates to a cli instruction. This masks off all - * interrupts, and effectively stops the scheduler from ever running - * so _nothing_ can execute except the current thread. In Windows, - * preemption is disabled by raising the processor IRQL to DISPATCH_LEVEL. - * This stops other threads from running, but does _not_ block device - * interrupts. This means ISRs can still run, and they can make other - * threads runable, but those other threads won't be able to execute - * until the current thread lowers the IRQL to something less than - * DISPATCH_LEVEL. - * - * 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. - * - * 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 - * functions are KfAcquireSpinLock() and KfReleaseSpinLock(), and - * they live in HAL.dll. Meanwhile, KeInitializeSpinLock(), - * KefAcquireSpinLockAtDpcLevel() and KefReleaseSpinLockFromDpcLevel() - * live in ntoskrnl.exe. Most Windows source code will call - * KeAcquireSpinLock() and KeReleaseSpinLock(), but these are just - * macros that call KfAcquireSpinLock() and KfReleaseSpinLock(). - * KefAcquireSpinLockAtDpcLevel() and KefReleaseSpinLockFromDpcLevel() - * perform the lock acquisition/release functions without doing the - * IRQL manipulation, and are used when one is already running at - * DISPATCH_LEVEL. Make sense? Good. - * - * According to the Microsoft documentation, any thread that calls - * KeAcquireSpinLock() must be running at IRQL <= DISPATCH_LEVEL. If - * we detect someone trying to acquire a spinlock from DEVICE_LEVEL - * or HIGH_LEVEL, we panic. - * - * Alternate sleep-lock-based spinlock implementation - * -------------------------------------------------- - * - * The earlier spinlock implementation was arguably a bit of a hack - * and presented several problems. It was basically designed to provide - * the functionality of spinlocks without incurring the wrath of - * WITNESS. We could get away with using both our spinlock implementation - * and FreeBSD sleep locks at the same time, but if WITNESS knew what - * we were really up to, it would have spanked us rather severely. - * - * There's another method we can use based entirely on sleep locks. - * First, it's important to realize that everything we're locking - * resides inside Project Evil itself: any critical data being locked - * by drivers belongs to the drivers, and should not be referenced - * by any other OS code outside of the NDISulator. The priority-based - * locking scheme has system-wide effects, just like real spinlocks - * (blocking preemption affects the whole CPU), but since we keep all - * our critical data private, we can use a simpler mechanism that - * affects only code/threads directly related to Project Evil. - * - * The idea is to create a sleep lock mutex for each CPU in the system. - * When a CPU running in the NDISulator wants to acquire a spinlock, it - * does the following: - * - Pin ourselves to the current CPU - * - Acquire the mutex for the current CPU - * - Spin on the spinlock variable using atomic test and set, just like - * a real spinlock. - * - Once we have the lock, we execute our critical code - * - * To give up the lock, we do: - * - Clear the spinlock variable with an atomic op - * - Release the per-CPU mutex - * - Unpin ourselves from the current CPU. - * - * On a uniprocessor system, this means all threads that access protected - * data are serialized through the per-CPU mutex. After one thread - * acquires the 'spinlock,' any other thread that uses a spinlock on the - * current CPU will block on the per-CPU mutex, which has the same general - * effect of blocking pre-emption, but _only_ for those threads that are - * running NDISulator code. - * - * On a multiprocessor system, threads on different CPUs all block on - * their respective per-CPU mutex, and the atomic test/set operation - * on the spinlock variable provides inter-CPU synchronization, though - * only for threads running NDISulator code. - * - * This method solves an important problem. In Windows, you're allowed - * to do an ExAllocatePoolWithTag() with a spinlock held, provided you - * allocate from NonPagedPool. This implies an atomic heap allocation - * that will not cause the current thread to sleep. (You can't sleep - * while holding real spinlock: clowns will eat you.) But in FreeBSD, - * malloc(9) _always_ triggers the acquisition of a sleep lock, even - * when you use M_NOWAIT. This is not a problem for FreeBSD native - * code: you're allowed to sleep in things like interrupt threads. But - * it is a problem with the old priority-based spinlock implementation: - * even though we get away with it most of the time, we really can't - * do a malloc(9) after doing a KeAcquireSpinLock() or KeRaiseIrql(). - * With the new implementation, it's not a problem: you're allowed to - * acquire more than one sleep lock (as long as you avoid lock order - * reversals). - * - * The one drawback to this approach is that now we have a lot of - * contention on one per-CPU mutex within the NDISulator code. Whether - * or not this is preferable to the expected Windows spinlock behavior - * of blocking pre-emption is debatable. - */ - -uint8_t -KfAcquireSpinLock(lock) - kspin_lock *lock; -{ - uint8_t oldirql; - - KeRaiseIrql(DISPATCH_LEVEL, &oldirql); - KeAcquireSpinLockAtDpcLevel(lock); - - return (oldirql); -} - -void -KfReleaseSpinLock(kspin_lock *lock, uint8_t newirql) -{ - KeReleaseSpinLockFromDpcLevel(lock); - KeLowerIrql(newirql); -} - -uint8_t -KeGetCurrentIrql() -{ - if (mtx_owned(&disp_lock[curthread->td_oncpu])) - return (DISPATCH_LEVEL); - return (PASSIVE_LEVEL); -} - -static uint64_t -KeQueryPerformanceCounter(freq) - uint64_t *freq; -{ - if (freq != NULL) - *freq = hz; - - return ((uint64_t)ticks); -} - -uint8_t -KfRaiseIrql(uint8_t irql) -{ - uint8_t oldirql; - - sched_pin(); - oldirql = KeGetCurrentIrql(); - - /* I am so going to hell for this. */ - if (oldirql > irql) - panic("IRQL_NOT_LESS_THAN_OR_EQUAL"); - - if (oldirql != DISPATCH_LEVEL) - mtx_lock(&disp_lock[curthread->td_oncpu]); - else - sched_unpin(); - -/*printf("RAISE IRQL: %d %d\n", irql, oldirql);*/ - - return (oldirql); -} - -void -KfLowerIrql(uint8_t oldirql) -{ - if (oldirql == DISPATCH_LEVEL) - return; - - if (KeGetCurrentIrql() != DISPATCH_LEVEL) - panic("IRQL_NOT_GREATER_THAN"); - - mtx_unlock(&disp_lock[curthread->td_oncpu]); - sched_unpin(); -} - -static uint8_t -KeRaiseIrqlToDpcLevel(void) -{ - uint8_t irql; - - KeRaiseIrql(DISPATCH_LEVEL, &irql); - return (irql); -} - -static void -_KeLowerIrql(uint8_t oldirql) -{ - KeLowerIrql(oldirql); -} - -static void dummy() -{ - printf("hal dummy called...\n"); -} - -image_patch_table hal_functbl[] = { - IMPORT_SFUNC(KeStallExecutionProcessor, 1), - IMPORT_SFUNC(WRITE_PORT_ULONG, 2), - IMPORT_SFUNC(WRITE_PORT_USHORT, 2), - IMPORT_SFUNC(WRITE_PORT_UCHAR, 2), - IMPORT_SFUNC(WRITE_PORT_BUFFER_ULONG, 3), - IMPORT_SFUNC(WRITE_PORT_BUFFER_USHORT, 3), - IMPORT_SFUNC(WRITE_PORT_BUFFER_UCHAR, 3), - IMPORT_SFUNC(READ_PORT_ULONG, 1), - IMPORT_SFUNC(READ_PORT_USHORT, 1), - IMPORT_SFUNC(READ_PORT_UCHAR, 1), - IMPORT_SFUNC(READ_PORT_BUFFER_ULONG, 3), - IMPORT_SFUNC(READ_PORT_BUFFER_USHORT, 3), - IMPORT_SFUNC(READ_PORT_BUFFER_UCHAR, 3), - IMPORT_FFUNC(KfAcquireSpinLock, 1), - IMPORT_FFUNC(KfReleaseSpinLock, 1), - IMPORT_SFUNC(KeGetCurrentIrql, 0), - IMPORT_SFUNC(KeQueryPerformanceCounter, 1), - IMPORT_FFUNC(KfLowerIrql, 1), - IMPORT_FFUNC(KfRaiseIrql, 1), - IMPORT_SFUNC(KeRaiseIrqlToDpcLevel, 0), -#undef KeLowerIrql - IMPORT_SFUNC_MAP(KeLowerIrql, _KeLowerIrql, 1), - - /* - * This last entry is a catch-all for any function we haven't - * implemented yet. The PE import list patching routine will - * use it for any function that doesn't have an explicit match - * in this table. - */ - - { NULL, (FUNC)dummy, NULL, 0, WINDRV_WRAP_STDCALL }, - - /* End of list. */ - { NULL, NULL, NULL } -}; diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c deleted file mode 100644 index fb037d52b1d4..000000000000 --- a/sys/compat/ndis/subr_ndis.c +++ /dev/null @@ -1,3372 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul . 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 -__FBSDID("$FreeBSD$"); - -/* - * This file implements a translation layer between the BSD networking - * infrasturcture and Windows(R) NDIS network driver modules. A Windows - * NDIS driver calls into several functions in the NDIS.SYS Windows - * kernel module and exports a table of functions designed to be called - * by the NDIS subsystem. Using the PE loader, we can patch our own - * versions of the NDIS routines into a given Windows driver module and - * convince the driver that it is in fact running on Windows. - * - * We provide a table of all our implemented NDIS routines which is patched - * into the driver object code. All our exported routines must use the - * _stdcall calling convention, since that's what the Windows object code - * expects. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -static char ndis_filepath[MAXPATHLEN]; - -SYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath, - MAXPATHLEN, "Path used by NdisOpenFile() to search for files"); - -static void NdisInitializeWrapper(ndis_handle *, - driver_object *, void *, void *); -static ndis_status NdisMRegisterMiniport(ndis_handle, - ndis_miniport_characteristics *, int); -static ndis_status NdisAllocateMemoryWithTag(void **, - uint32_t, uint32_t); -static ndis_status NdisAllocateMemory(void **, - uint32_t, uint32_t, ndis_physaddr); -static void NdisFreeMemory(void *, uint32_t, uint32_t); -static ndis_status NdisMSetAttributesEx(ndis_handle, ndis_handle, - uint32_t, uint32_t, ndis_interface_type); -static void NdisOpenConfiguration(ndis_status *, - ndis_handle *, ndis_handle); -static void NdisOpenConfigurationKeyByIndex(ndis_status *, - ndis_handle, uint32_t, unicode_string *, ndis_handle *); -static void NdisOpenConfigurationKeyByName(ndis_status *, - ndis_handle, unicode_string *, ndis_handle *); -static ndis_status ndis_encode_parm(ndis_miniport_block *, - struct sysctl_oid *, ndis_parm_type, ndis_config_parm **); -static ndis_status ndis_decode_parm(ndis_miniport_block *, - ndis_config_parm *, char *); -static void NdisReadConfiguration(ndis_status *, ndis_config_parm **, - ndis_handle, unicode_string *, ndis_parm_type); -static void NdisWriteConfiguration(ndis_status *, ndis_handle, - unicode_string *, ndis_config_parm *); -static void NdisCloseConfiguration(ndis_handle); -static void NdisAllocateSpinLock(ndis_spin_lock *); -static void NdisFreeSpinLock(ndis_spin_lock *); -static void NdisAcquireSpinLock(ndis_spin_lock *); -static void NdisReleaseSpinLock(ndis_spin_lock *); -static void NdisDprAcquireSpinLock(ndis_spin_lock *); -static void NdisDprReleaseSpinLock(ndis_spin_lock *); -static void NdisInitializeReadWriteLock(ndis_rw_lock *); -static void NdisAcquireReadWriteLock(ndis_rw_lock *, - uint8_t, ndis_lock_state *); -static void NdisReleaseReadWriteLock(ndis_rw_lock *, ndis_lock_state *); -static uint32_t NdisReadPciSlotInformation(ndis_handle, uint32_t, - uint32_t, void *, uint32_t); -static uint32_t NdisWritePciSlotInformation(ndis_handle, uint32_t, - uint32_t, void *, uint32_t); -static void NdisWriteErrorLogEntry(ndis_handle, ndis_error_code, uint32_t, ...); -static void ndis_map_cb(void *, bus_dma_segment_t *, int, int); -static void NdisMStartBufferPhysicalMapping(ndis_handle, - ndis_buffer *, uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *); -static void NdisMCompleteBufferPhysicalMapping(ndis_handle, - ndis_buffer *, uint32_t); -static void NdisMInitializeTimer(ndis_miniport_timer *, ndis_handle, - ndis_timer_function, void *); -static void NdisInitializeTimer(ndis_timer *, - ndis_timer_function, void *); -static void NdisSetTimer(ndis_timer *, uint32_t); -static void NdisMSetPeriodicTimer(ndis_miniport_timer *, uint32_t); -static void NdisMCancelTimer(ndis_timer *, uint8_t *); -static void ndis_timercall(kdpc *, ndis_miniport_timer *, - void *, void *); -static void NdisMQueryAdapterResources(ndis_status *, ndis_handle, - ndis_resource_list *, uint32_t *); -static ndis_status NdisMRegisterIoPortRange(void **, - ndis_handle, uint32_t, uint32_t); -static void NdisMDeregisterIoPortRange(ndis_handle, - uint32_t, uint32_t, void *); -static void NdisReadNetworkAddress(ndis_status *, void **, - uint32_t *, ndis_handle); -static ndis_status NdisQueryMapRegisterCount(uint32_t, uint32_t *); -static ndis_status NdisMAllocateMapRegisters(ndis_handle, - uint32_t, uint8_t, uint32_t, uint32_t); -static void NdisMFreeMapRegisters(ndis_handle); -static void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int); -static void NdisMAllocateSharedMemory(ndis_handle, uint32_t, - uint8_t, void **, ndis_physaddr *); -static void ndis_asyncmem_complete(device_object *, void *); -static ndis_status NdisMAllocateSharedMemoryAsync(ndis_handle, - uint32_t, uint8_t, void *); -static void NdisMFreeSharedMemory(ndis_handle, uint32_t, - uint8_t, void *, ndis_physaddr); -static ndis_status NdisMMapIoSpace(void **, ndis_handle, - ndis_physaddr, uint32_t); -static void NdisMUnmapIoSpace(ndis_handle, void *, uint32_t); -static uint32_t NdisGetCacheFillSize(void); -static void *NdisGetRoutineAddress(unicode_string *); -static uint32_t NdisMGetDmaAlignment(ndis_handle); -static ndis_status NdisMInitializeScatterGatherDma(ndis_handle, - uint8_t, uint32_t); -static void NdisUnchainBufferAtFront(ndis_packet *, ndis_buffer **); -static void NdisUnchainBufferAtBack(ndis_packet *, ndis_buffer **); -static void NdisAllocateBufferPool(ndis_status *, - ndis_handle *, uint32_t); -static void NdisFreeBufferPool(ndis_handle); -static void NdisAllocateBuffer(ndis_status *, ndis_buffer **, - ndis_handle, void *, uint32_t); -static void NdisFreeBuffer(ndis_buffer *); -static uint32_t NdisBufferLength(ndis_buffer *); -static void NdisQueryBuffer(ndis_buffer *, void **, uint32_t *); -static void NdisQueryBufferSafe(ndis_buffer *, void **, - uint32_t *, uint32_t); -static void *NdisBufferVirtualAddress(ndis_buffer *); -static void *NdisBufferVirtualAddressSafe(ndis_buffer *, uint32_t); -static void NdisAdjustBufferLength(ndis_buffer *, int); -static uint32_t NdisInterlockedIncrement(uint32_t *); -static uint32_t NdisInterlockedDecrement(uint32_t *); -static void NdisInitializeEvent(ndis_event *); -static void NdisSetEvent(ndis_event *); -static void NdisResetEvent(ndis_event *); -static uint8_t NdisWaitEvent(ndis_event *, uint32_t); -static ndis_status NdisUnicodeStringToAnsiString(ansi_string *, - unicode_string *); -static ndis_status - NdisAnsiStringToUnicodeString(unicode_string *, ansi_string *); -static ndis_status NdisMPciAssignResources(ndis_handle, - uint32_t, ndis_resource_list **); -static ndis_status NdisMRegisterInterrupt(ndis_miniport_interrupt *, - ndis_handle, uint32_t, uint32_t, uint8_t, - uint8_t, ndis_interrupt_mode); -static void NdisMDeregisterInterrupt(ndis_miniport_interrupt *); -static void NdisMRegisterAdapterShutdownHandler(ndis_handle, void *, - ndis_shutdown_handler); -static void NdisMDeregisterAdapterShutdownHandler(ndis_handle); -static uint32_t NDIS_BUFFER_TO_SPAN_PAGES(ndis_buffer *); -static void NdisGetBufferPhysicalArraySize(ndis_buffer *, - uint32_t *); -static void NdisQueryBufferOffset(ndis_buffer *, - uint32_t *, uint32_t *); -static uint32_t NdisReadPcmciaAttributeMemory(ndis_handle, - uint32_t, void *, uint32_t); -static uint32_t NdisWritePcmciaAttributeMemory(ndis_handle, - uint32_t, void *, uint32_t); -static list_entry *NdisInterlockedInsertHeadList(list_entry *, - list_entry *, ndis_spin_lock *); -static list_entry *NdisInterlockedRemoveHeadList(list_entry *, - ndis_spin_lock *); -static list_entry *NdisInterlockedInsertTailList(list_entry *, - list_entry *, ndis_spin_lock *); -static uint8_t - NdisMSynchronizeWithInterrupt(ndis_miniport_interrupt *, - void *, void *); -static void NdisGetCurrentSystemTime(uint64_t *); -static void NdisGetSystemUpTime(uint32_t *); -static uint32_t NdisGetVersion(void); -static void NdisInitializeString(unicode_string *, char *); -static void NdisInitAnsiString(ansi_string *, char *); -static void NdisInitUnicodeString(unicode_string *, uint16_t *); -static void NdisFreeString(unicode_string *); -static ndis_status NdisMRemoveMiniport(ndis_handle *); -static void NdisTerminateWrapper(ndis_handle, void *); -static void NdisMGetDeviceProperty(ndis_handle, device_object **, - device_object **, device_object **, cm_resource_list *, - cm_resource_list *); -static void NdisGetFirstBufferFromPacket(ndis_packet *, - ndis_buffer **, void **, uint32_t *, uint32_t *); -static void NdisGetFirstBufferFromPacketSafe(ndis_packet *, - ndis_buffer **, void **, uint32_t *, uint32_t *, uint32_t); -static int ndis_find_sym(linker_file_t, char *, char *, caddr_t *); -static void NdisOpenFile(ndis_status *, ndis_handle *, uint32_t *, - unicode_string *, ndis_physaddr); -static void NdisMapFile(ndis_status *, void **, ndis_handle); -static void NdisUnmapFile(ndis_handle); -static void NdisCloseFile(ndis_handle); -static uint8_t NdisSystemProcessorCount(void); -static void NdisGetCurrentProcessorCounts(uint32_t *, uint32_t *, uint32_t *); -static void NdisMIndicateStatusComplete(ndis_handle); -static void NdisMIndicateStatus(ndis_handle, ndis_status, - void *, uint32_t); -static uint8_t ndis_intr(kinterrupt *, void *); -static void ndis_intrhand(kdpc *, ndis_miniport_interrupt *, void *, void *); -static funcptr ndis_findwrap(funcptr); -static void NdisCopyFromPacketToPacket(ndis_packet *, - uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *); -static void NdisCopyFromPacketToPacketSafe(ndis_packet *, - uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *, uint32_t); -static void NdisIMCopySendPerPacketInfo(ndis_packet *, ndis_packet *); -static ndis_status NdisMRegisterDevice(ndis_handle, - unicode_string *, unicode_string *, driver_dispatch **, - void **, ndis_handle *); -static ndis_status NdisMDeregisterDevice(ndis_handle); -static ndis_status - NdisMQueryAdapterInstanceName(unicode_string *, ndis_handle); -static void NdisMRegisterUnloadHandler(ndis_handle, void *); -static void dummy(void); - -/* - * Some really old drivers do not properly check the return value - * from NdisAllocatePacket() and NdisAllocateBuffer() and will - * sometimes allocate few more buffers/packets that they originally - * requested when they created the pool. To prevent this from being - * a problem, we allocate a few extra buffers/packets beyond what - * the driver asks for. This #define controls how many. - */ -#define NDIS_POOL_EXTRA 16 - -int -ndis_libinit() -{ - image_patch_table *patch; - - strcpy(ndis_filepath, "/compat/ndis"); - - patch = ndis_functbl; - while (patch->ipt_func != NULL) { - windrv_wrap((funcptr)patch->ipt_func, - (funcptr *)&patch->ipt_wrap, - patch->ipt_argcnt, patch->ipt_ftype); - patch++; - } - - return (0); -} - -int -ndis_libfini() -{ - image_patch_table *patch; - - patch = ndis_functbl; - while (patch->ipt_func != NULL) { - windrv_unwrap(patch->ipt_wrap); - patch++; - } - - return (0); -} - -static funcptr -ndis_findwrap(func) - funcptr func; -{ - image_patch_table *patch; - - patch = ndis_functbl; - while (patch->ipt_func != NULL) { - if ((funcptr)patch->ipt_func == func) - return ((funcptr)patch->ipt_wrap); - patch++; - } - - return (NULL); -} - -/* - * This routine does the messy Windows Driver Model device attachment - * stuff on behalf of NDIS drivers. We register our own AddDevice - * routine here - */ -static void -NdisInitializeWrapper(wrapper, drv, path, unused) - ndis_handle *wrapper; - driver_object *drv; - void *path; - void *unused; -{ - /* - * 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. - */ - - *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; -} - -static void -NdisTerminateWrapper(handle, syspec) - ndis_handle handle; - void *syspec; -{ - /* Nothing to see here, move along. */ -} - -static ndis_status -NdisMRegisterMiniport(handle, characteristics, len) - ndis_handle handle; - ndis_miniport_characteristics *characteristics; - int len; -{ - ndis_miniport_characteristics *ch = NULL; - driver_object *drv; - - 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); -} - -static ndis_status -NdisAllocateMemoryWithTag(vaddr, len, tag) - void **vaddr; - uint32_t len; - uint32_t tag; -{ - void *mem; - - mem = ExAllocatePoolWithTag(NonPagedPool, len, tag); - if (mem == NULL) { - return (NDIS_STATUS_RESOURCES); - } - *vaddr = mem; - - return (NDIS_STATUS_SUCCESS); -} - -static ndis_status -NdisAllocateMemory(vaddr, len, flags, highaddr) - void **vaddr; - uint32_t len; - uint32_t flags; - ndis_physaddr highaddr; -{ - void *mem; - - mem = ExAllocatePoolWithTag(NonPagedPool, len, 0); - if (mem == NULL) - return (NDIS_STATUS_RESOURCES); - *vaddr = mem; - - return (NDIS_STATUS_SUCCESS); -} - -static void -NdisFreeMemory(vaddr, len, flags) - void *vaddr; - uint32_t len; - uint32_t flags; -{ - if (len == 0) - return; - - ExFreePool(vaddr); -} - -static ndis_status -NdisMSetAttributesEx(adapter_handle, adapter_ctx, hangsecs, - flags, iftype) - ndis_handle adapter_handle; - ndis_handle adapter_ctx; - uint32_t hangsecs; - uint32_t flags; - ndis_interface_type iftype; -{ - ndis_miniport_block *block; - - /* - * Save the adapter context, we need it for calling - * the driver's internal functions. - */ - block = (ndis_miniport_block *)adapter_handle; - block->nmb_miniportadapterctx = adapter_ctx; - block->nmb_checkforhangsecs = hangsecs; - block->nmb_flags = flags; - - return (NDIS_STATUS_SUCCESS); -} - -static void -NdisOpenConfiguration(status, cfg, wrapctx) - ndis_status *status; - ndis_handle *cfg; - ndis_handle wrapctx; -{ - *cfg = wrapctx; - *status = NDIS_STATUS_SUCCESS; -} - -static void -NdisOpenConfigurationKeyByName(status, cfg, subkey, subhandle) - ndis_status *status; - ndis_handle cfg; - unicode_string *subkey; - ndis_handle *subhandle; -{ - *subhandle = cfg; - *status = NDIS_STATUS_SUCCESS; -} - -static void -NdisOpenConfigurationKeyByIndex(status, cfg, idx, subkey, subhandle) - ndis_status *status; - ndis_handle cfg; - uint32_t idx; - unicode_string *subkey; - ndis_handle *subhandle; -{ - *status = NDIS_STATUS_FAILURE; -} - -static ndis_status -ndis_encode_parm(block, oid, type, parm) - ndis_miniport_block *block; - struct sysctl_oid *oid; - ndis_parm_type type; - ndis_config_parm **parm; -{ - ndis_config_parm *p; - ndis_parmlist_entry *np; - unicode_string *us; - ansi_string as; - int base = 0; - uint32_t val; - char tmp[32]; - - np = ExAllocatePoolWithTag(NonPagedPool, - sizeof(ndis_parmlist_entry), 0); - if (np == NULL) - return (NDIS_STATUS_RESOURCES); - InsertHeadList((&block->nmb_parmlist), (&np->np_list)); - *parm = p = &np->np_parm; - - switch(type) { - case ndis_parm_string: - /* See if this might be a number. */ - val = strtoul((char *)oid->oid_arg1, NULL, 10); - us = &p->ncp_parmdata.ncp_stringdata; - p->ncp_type = ndis_parm_string; - if (val) { - snprintf(tmp, 32, "%x", val); - RtlInitAnsiString(&as, tmp); - } else { - RtlInitAnsiString(&as, (char *)oid->oid_arg1); - } - - if (RtlAnsiStringToUnicodeString(us, &as, TRUE)) { - ExFreePool(np); - return (NDIS_STATUS_RESOURCES); - } - break; - case ndis_parm_int: - if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) - base = 16; - else - base = 10; - p->ncp_type = ndis_parm_int; - p->ncp_parmdata.ncp_intdata = - strtol((char *)oid->oid_arg1, NULL, base); - break; - case ndis_parm_hexint: -#ifdef notdef - if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) - base = 16; - else - base = 10; -#endif - base = 16; - p->ncp_type = ndis_parm_hexint; - p->ncp_parmdata.ncp_intdata = - strtoul((char *)oid->oid_arg1, NULL, base); - break; - default: - return (NDIS_STATUS_FAILURE); - break; - } - - return (NDIS_STATUS_SUCCESS); -} - -static void -NdisReadConfiguration(status, parm, cfg, key, type) - ndis_status *status; - ndis_config_parm **parm; - ndis_handle cfg; - unicode_string *key; - ndis_parm_type type; -{ - char *keystr = NULL; - ndis_miniport_block *block; - struct ndis_softc *sc; - struct sysctl_oid *oidp; - struct sysctl_ctx_entry *e; - ansi_string as; - - block = (ndis_miniport_block *)cfg; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - /* - device_printf(sc->ndis_dev, "NdisReadConfiguration sc=%p\n", sc); - */ - - if (key->us_len == 0 || key->us_buf == NULL) { - *status = NDIS_STATUS_FAILURE; - return; - } - - if (RtlUnicodeStringToAnsiString(&as, key, TRUE)) { - *status = NDIS_STATUS_RESOURCES; - return; - } - - keystr = as.as_buf; - - /* - * See if registry key is already in a list of known keys - * included with the driver. - */ - TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) { - oidp = e->entry; - if (strcasecmp(oidp->oid_name, keystr) == 0) { - if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) { - RtlFreeAnsiString(&as); - *status = NDIS_STATUS_FAILURE; - return; - } - - *status = ndis_encode_parm(block, oidp, type, parm); - RtlFreeAnsiString(&as); - return; - } - } - - /* - * If the key didn't match, add it to the list of dynamically - * created ones. Sometimes, drivers refer to registry keys - * that aren't documented in their .INF files. These keys - * are supposed to be created by some sort of utility or - * control panel snap-in that comes with the driver software. - * Sometimes it's useful to be able to manipulate these. - * If the driver requests the key in the form of a string, - * make its default value an empty string, otherwise default - * it to "0". - */ - - if (type == ndis_parm_int || type == ndis_parm_hexint) - ndis_add_sysctl(sc, keystr, "(dynamic integer key)", - "UNSET", CTLFLAG_RW); - else - ndis_add_sysctl(sc, keystr, "(dynamic string key)", - "UNSET", CTLFLAG_RW); - - RtlFreeAnsiString(&as); - *status = NDIS_STATUS_FAILURE; -} - -static ndis_status -ndis_decode_parm(block, parm, val) - ndis_miniport_block *block; - ndis_config_parm *parm; - char *val; -{ - unicode_string *ustr; - ansi_string as; - - switch(parm->ncp_type) { - case ndis_parm_string: - ustr = &parm->ncp_parmdata.ncp_stringdata; - if (RtlUnicodeStringToAnsiString(&as, ustr, TRUE)) - return (NDIS_STATUS_RESOURCES); - bcopy(as.as_buf, val, as.as_len); - RtlFreeAnsiString(&as); - break; - case ndis_parm_int: - sprintf(val, "%d", parm->ncp_parmdata.ncp_intdata); - break; - case ndis_parm_hexint: - sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata); - break; - default: - return (NDIS_STATUS_FAILURE); - break; - } - return (NDIS_STATUS_SUCCESS); -} - -static void -NdisWriteConfiguration(status, cfg, key, parm) - ndis_status *status; - ndis_handle cfg; - unicode_string *key; - ndis_config_parm *parm; -{ - ansi_string as; - char *keystr = NULL; - ndis_miniport_block *block; - struct ndis_softc *sc; - struct sysctl_oid *oidp; - struct sysctl_ctx_entry *e; - char val[256]; - - block = (ndis_miniport_block *)cfg; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - - if (RtlUnicodeStringToAnsiString(&as, key, TRUE)) { - *status = NDIS_STATUS_RESOURCES; - return; - } - - keystr = as.as_buf; - - /* Decode the parameter into a string. */ - bzero(val, sizeof(val)); - *status = ndis_decode_parm(block, parm, val); - if (*status != NDIS_STATUS_SUCCESS) { - RtlFreeAnsiString(&as); - return; - } - - /* See if the key already exists. */ - - TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) { - oidp = e->entry; - if (strcasecmp(oidp->oid_name, keystr) == 0) { - /* Found it, set the value. */ - strcpy((char *)oidp->oid_arg1, val); - RtlFreeAnsiString(&as); - return; - } - } - - /* Not found, add a new key with the specified value. */ - ndis_add_sysctl(sc, keystr, "(dynamically set key)", - val, CTLFLAG_RW); - - RtlFreeAnsiString(&as); - *status = NDIS_STATUS_SUCCESS; -} - -static void -NdisCloseConfiguration(cfg) - ndis_handle cfg; -{ - list_entry *e; - ndis_parmlist_entry *pe; - ndis_miniport_block *block; - ndis_config_parm *p; - - block = (ndis_miniport_block *)cfg; - - while (!IsListEmpty(&block->nmb_parmlist)) { - e = RemoveHeadList(&block->nmb_parmlist); - pe = CONTAINING_RECORD(e, ndis_parmlist_entry, np_list); - p = &pe->np_parm; - if (p->ncp_type == ndis_parm_string) - RtlFreeUnicodeString(&p->ncp_parmdata.ncp_stringdata); - ExFreePool(e); - } -} - -/* - * Initialize a Windows spinlock. - */ -static void -NdisAllocateSpinLock(lock) - ndis_spin_lock *lock; -{ - KeInitializeSpinLock(&lock->nsl_spinlock); - lock->nsl_kirql = 0; -} - -/* - * Destroy a Windows spinlock. This is a no-op for now. There are two reasons - * for this. One is that it's sort of superfluous: we don't have to do anything - * special to deallocate the spinlock. The other is that there are some buggy - * drivers which call NdisFreeSpinLock() _after_ calling NdisFreeMemory() on - * the block of memory in which the spinlock resides. (Yes, ADMtek, I'm - * talking to you.) - */ -static void -NdisFreeSpinLock(lock) - ndis_spin_lock *lock; -{ -#ifdef notdef - KeInitializeSpinLock(&lock->nsl_spinlock); - lock->nsl_kirql = 0; -#endif -} - -/* - * Acquire a spinlock from IRQL <= DISPATCH_LEVEL. - */ - -static void -NdisAcquireSpinLock(lock) - ndis_spin_lock *lock; -{ - KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql); -} - -/* - * Release a spinlock from IRQL == DISPATCH_LEVEL. - */ - -static void -NdisReleaseSpinLock(lock) - ndis_spin_lock *lock; -{ - KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql); -} - -/* - * Acquire a spinlock when already running at IRQL == DISPATCH_LEVEL. - */ -static void -NdisDprAcquireSpinLock(lock) - ndis_spin_lock *lock; -{ - KeAcquireSpinLockAtDpcLevel(&lock->nsl_spinlock); -} - -/* - * Release a spinlock without leaving IRQL == DISPATCH_LEVEL. - */ -static void -NdisDprReleaseSpinLock(lock) - ndis_spin_lock *lock; -{ - KeReleaseSpinLockFromDpcLevel(&lock->nsl_spinlock); -} - -static void -NdisInitializeReadWriteLock(lock) - ndis_rw_lock *lock; -{ - KeInitializeSpinLock(&lock->nrl_spinlock); - bzero((char *)&lock->nrl_rsvd, sizeof(lock->nrl_rsvd)); -} - -static void -NdisAcquireReadWriteLock(ndis_rw_lock *lock, uint8_t writeacc, - ndis_lock_state *state) -{ - if (writeacc == TRUE) { - KeAcquireSpinLock(&lock->nrl_spinlock, &state->nls_oldirql); - lock->nrl_rsvd[0]++; - } else - lock->nrl_rsvd[1]++; -} - -static void -NdisReleaseReadWriteLock(lock, state) - ndis_rw_lock *lock; - ndis_lock_state *state; -{ - if (lock->nrl_rsvd[0]) { - lock->nrl_rsvd[0]--; - KeReleaseSpinLock(&lock->nrl_spinlock, state->nls_oldirql); - } else - lock->nrl_rsvd[1]--; -} - -static uint32_t -NdisReadPciSlotInformation(adapter, slot, offset, buf, len) - ndis_handle adapter; - uint32_t slot; - uint32_t offset; - void *buf; - uint32_t len; -{ - ndis_miniport_block *block; - uint32_t i; - char *dest; - device_t dev; - - block = (ndis_miniport_block *)adapter; - dest = buf; - if (block == NULL) - return (0); - - dev = block->nmb_physdeviceobj->do_devext; - - /* - * I have a test system consisting of a Sun w2100z - * dual 2.4Ghz Opteron machine and an Atheros 802.11a/b/g - * "Aries" miniPCI NIC. (The NIC is installed in the - * machine using a miniPCI to PCI bus adapter card.) - * When running in SMP mode, I found that - * performing a large number of consecutive calls to - * NdisReadPciSlotInformation() would result in a - * sudden system reset (or in some cases a freeze). - * My suspicion is that the multiple reads are somehow - * triggering a fatal PCI bus error that leads to a - * machine check. The 1us delay in the loop below - * seems to prevent this problem. - */ - - for (i = 0; i < len; i++) { - DELAY(1); - dest[i] = pci_read_config(dev, i + offset, 1); - } - - return (len); -} - -static uint32_t -NdisWritePciSlotInformation(adapter, slot, offset, buf, len) - ndis_handle adapter; - uint32_t slot; - uint32_t offset; - void *buf; - uint32_t len; -{ - ndis_miniport_block *block; - uint32_t i; - char *dest; - device_t dev; - - block = (ndis_miniport_block *)adapter; - dest = buf; - - if (block == NULL) - return (0); - - dev = block->nmb_physdeviceobj->do_devext; - for (i = 0; i < len; i++) { - DELAY(1); - pci_write_config(dev, i + offset, dest[i], 1); - } - - return (len); -} - -/* - * The errorlog routine uses a variable argument list, so we - * have to declare it this way. - */ - -#define ERRMSGLEN 512 -static void -NdisWriteErrorLogEntry(ndis_handle adapter, ndis_error_code code, - uint32_t numerrors, ...) -{ - ndis_miniport_block *block; - va_list ap; - int i, error; - char *str = NULL; - uint16_t flags; - device_t dev; - driver_object *drv; - struct ndis_softc *sc; - struct ifnet *ifp; - unicode_string us; - ansi_string as = { 0, 0, NULL }; - - block = (ndis_miniport_block *)adapter; - dev = block->nmb_physdeviceobj->do_devext; - drv = block->nmb_deviceobj->do_drvobj; - sc = device_get_softc(dev); - ifp = NDISUSB_GET_IFNET(sc); - - if (ifp != NULL && ifp->if_flags & IFF_DEBUG) { - error = pe_get_message((vm_offset_t)drv->dro_driverstart, - code, &str, &i, &flags); - if (error == 0) { - if (flags & MESSAGE_RESOURCE_UNICODE) { - RtlInitUnicodeString(&us, (uint16_t *)str); - if (RtlUnicodeStringToAnsiString(&as, - &us, TRUE) == STATUS_SUCCESS) - str = as.as_buf; - else - str = NULL; - } - } - } - - device_printf(dev, "NDIS ERROR: %x (%s)\n", code, - str == NULL ? "unknown error" : str); - - if (ifp != NULL && ifp->if_flags & IFF_DEBUG) { - device_printf(dev, "NDIS NUMERRORS: %x\n", numerrors); - va_start(ap, numerrors); - for (i = 0; i < numerrors; i++) - device_printf(dev, "argptr: %p\n", - va_arg(ap, void *)); - va_end(ap); - } - - if (as.as_len) - RtlFreeAnsiString(&as); -} - -static void -ndis_map_cb(arg, segs, nseg, error) - void *arg; - bus_dma_segment_t *segs; - int nseg; - int error; -{ - struct ndis_map_arg *ctx; - int i; - - if (error) - return; - - ctx = arg; - - for (i = 0; i < nseg; i++) { - ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr; - ctx->nma_fraglist[i].npu_len = segs[i].ds_len; - } - - ctx->nma_cnt = nseg; -} - -static void -NdisMStartBufferPhysicalMapping(ndis_handle adapter, ndis_buffer *buf, - uint32_t mapreg, uint8_t writedev, ndis_paddr_unit *addrarray, - uint32_t *arraysize) -{ - ndis_miniport_block *block; - struct ndis_softc *sc; - struct ndis_map_arg nma; - bus_dmamap_t map; - int error; - - if (adapter == NULL) - return; - - block = (ndis_miniport_block *)adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - - if (mapreg > sc->ndis_mmapcnt) - return; - - map = sc->ndis_mmaps[mapreg]; - nma.nma_fraglist = addrarray; - - error = bus_dmamap_load(sc->ndis_mtag, map, - MmGetMdlVirtualAddress(buf), MmGetMdlByteCount(buf), ndis_map_cb, - (void *)&nma, BUS_DMA_NOWAIT); - - if (error) - return; - - bus_dmamap_sync(sc->ndis_mtag, map, - writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD); - - *arraysize = nma.nma_cnt; -} - -static void -NdisMCompleteBufferPhysicalMapping(adapter, buf, mapreg) - ndis_handle adapter; - ndis_buffer *buf; - uint32_t mapreg; -{ - ndis_miniport_block *block; - struct ndis_softc *sc; - bus_dmamap_t map; - - if (adapter == NULL) - return; - - block = (ndis_miniport_block *)adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - - if (mapreg > sc->ndis_mmapcnt) - return; - - map = sc->ndis_mmaps[mapreg]; - - bus_dmamap_sync(sc->ndis_mtag, map, - BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); - - bus_dmamap_unload(sc->ndis_mtag, map); -} - -/* - * This is an older (?) timer init routine which doesn't - * accept a miniport context handle. Serialized miniports should - * never call this function. - */ - -static void -NdisInitializeTimer(timer, func, ctx) - ndis_timer *timer; - ndis_timer_function func; - void *ctx; -{ - KeInitializeTimer(&timer->nt_ktimer); - KeInitializeDpc(&timer->nt_kdpc, func, ctx); - KeSetImportanceDpc(&timer->nt_kdpc, KDPC_IMPORTANCE_LOW); -} - -static void -ndis_timercall(dpc, timer, sysarg1, sysarg2) - kdpc *dpc; - ndis_miniport_timer *timer; - void *sysarg1; - void *sysarg2; -{ - /* - * Since we're called as a DPC, we should be running - * at DISPATCH_LEVEL here. This means to acquire the - * spinlock, we can use KeAcquireSpinLockAtDpcLevel() - * rather than KeAcquireSpinLock(). - */ - if (NDIS_SERIALIZED(timer->nmt_block)) - KeAcquireSpinLockAtDpcLevel(&timer->nmt_block->nmb_lock); - - MSCALL4(timer->nmt_timerfunc, dpc, timer->nmt_timerctx, - sysarg1, sysarg2); - - if (NDIS_SERIALIZED(timer->nmt_block)) - KeReleaseSpinLockFromDpcLevel(&timer->nmt_block->nmb_lock); -} - -/* - * For a long time I wondered why there were two NDIS timer initialization - * routines, and why this one needed an NDIS_MINIPORT_TIMER and the - * MiniportAdapterHandle. The NDIS_MINIPORT_TIMER has its own callout - * function and context pointers separate from those in the DPC, which - * allows for another level of indirection: when the timer fires, we - * can have our own timer function invoked, and from there we can call - * the driver's function. But why go to all that trouble? Then it hit - * me: for serialized miniports, the timer callouts are not re-entrant. - * By trapping the callouts and having access to the MiniportAdapterHandle, - * we can protect the driver callouts by acquiring the NDIS serialization - * lock. This is essential for allowing serialized miniports to work - * correctly on SMP systems. On UP hosts, setting IRQL to DISPATCH_LEVEL - * is enough to prevent other threads from pre-empting you, but with - * SMP, you must acquire a lock as well, otherwise the other CPU is - * free to clobber you. - */ -static void -NdisMInitializeTimer(timer, handle, func, ctx) - ndis_miniport_timer *timer; - ndis_handle handle; - ndis_timer_function func; - void *ctx; -{ - ndis_miniport_block *block; - struct ndis_softc *sc; - - block = (ndis_miniport_block *)handle; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - - /* Save the driver's funcptr and context */ - - timer->nmt_timerfunc = func; - timer->nmt_timerctx = ctx; - timer->nmt_block = handle; - - /* - * Set up the timer so it will call our intermediate DPC. - * Be sure to use the wrapped entry point, since - * ntoskrnl_run_dpc() expects to invoke a function with - * Microsoft calling conventions. - */ - KeInitializeTimer(&timer->nmt_ktimer); - KeInitializeDpc(&timer->nmt_kdpc, - ndis_findwrap((funcptr)ndis_timercall), timer); - timer->nmt_ktimer.k_dpc = &timer->nmt_kdpc; -} - -/* - * In Windows, there's both an NdisMSetTimer() and an NdisSetTimer(), - * but the former is just a macro wrapper around the latter. - */ -static void -NdisSetTimer(timer, msecs) - ndis_timer *timer; - uint32_t msecs; -{ - /* - * KeSetTimer() wants the period in - * hundred nanosecond intervals. - */ - KeSetTimer(&timer->nt_ktimer, - ((int64_t)msecs * -10000), &timer->nt_kdpc); -} - -static void -NdisMSetPeriodicTimer(timer, msecs) - ndis_miniport_timer *timer; - uint32_t msecs; -{ - KeSetTimerEx(&timer->nmt_ktimer, - ((int64_t)msecs * -10000), msecs, &timer->nmt_kdpc); -} - -/* - * Technically, this is really NdisCancelTimer(), but we also - * (ab)use it for NdisMCancelTimer(), since in our implementation - * we don't need the extra info in the ndis_miniport_timer - * structure just to cancel a timer. - */ - -static void -NdisMCancelTimer(timer, cancelled) - ndis_timer *timer; - uint8_t *cancelled; -{ - - *cancelled = KeCancelTimer(&timer->nt_ktimer); -} - -static void -NdisMQueryAdapterResources(status, adapter, list, buflen) - ndis_status *status; - ndis_handle adapter; - ndis_resource_list *list; - uint32_t *buflen; -{ - ndis_miniport_block *block; - struct ndis_softc *sc; - int rsclen; - - block = (ndis_miniport_block *)adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - - rsclen = sizeof(ndis_resource_list) + - (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)); - if (*buflen < rsclen) { - *buflen = rsclen; - *status = NDIS_STATUS_INVALID_LENGTH; - return; - } - - bcopy((char *)block->nmb_rlist, (char *)list, rsclen); - *status = NDIS_STATUS_SUCCESS; -} - -static ndis_status -NdisMRegisterIoPortRange(offset, adapter, port, numports) - void **offset; - ndis_handle adapter; - uint32_t port; - uint32_t numports; -{ - struct ndis_miniport_block *block; - struct ndis_softc *sc; - - if (adapter == NULL) - return (NDIS_STATUS_FAILURE); - - block = (ndis_miniport_block *)adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - - if (sc->ndis_res_io == NULL) - return (NDIS_STATUS_FAILURE); - - /* Don't let the device map more ports than we have. */ - if (rman_get_size(sc->ndis_res_io) < numports) - return (NDIS_STATUS_INVALID_LENGTH); - - *offset = (void *)(uintptr_t)rman_get_start(sc->ndis_res_io); - - return (NDIS_STATUS_SUCCESS); -} - -static void -NdisMDeregisterIoPortRange(adapter, port, numports, offset) - ndis_handle adapter; - uint32_t port; - uint32_t numports; - void *offset; -{ -} - -static void -NdisReadNetworkAddress(status, addr, addrlen, adapter) - ndis_status *status; - void **addr; - uint32_t *addrlen; - ndis_handle adapter; -{ - struct ndis_softc *sc; - struct ifnet *ifp; - ndis_miniport_block *block; - uint8_t empty[] = { 0, 0, 0, 0, 0, 0 }; - - block = (ndis_miniport_block *)adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - ifp = NDISUSB_GET_IFNET(sc); - if (ifp == NULL) { - *status = NDIS_STATUS_FAILURE; - return; - } - - if (ifp->if_addr == NULL || - bcmp(IF_LLADDR(sc->ifp), empty, ETHER_ADDR_LEN) == 0) - *status = NDIS_STATUS_FAILURE; - else { - *addr = IF_LLADDR(sc->ifp); - *addrlen = ETHER_ADDR_LEN; - *status = NDIS_STATUS_SUCCESS; - } -} - -static ndis_status -NdisQueryMapRegisterCount(bustype, cnt) - uint32_t bustype; - uint32_t *cnt; -{ - *cnt = 8192; - return (NDIS_STATUS_SUCCESS); -} - -static ndis_status -NdisMAllocateMapRegisters(ndis_handle adapter, uint32_t dmachannel, - uint8_t dmasize, uint32_t physmapneeded, uint32_t maxmap) -{ - struct ndis_softc *sc; - ndis_miniport_block *block; - int error, i, nseg = NDIS_MAXSEG; - - block = (ndis_miniport_block *)adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - - sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded, - M_DEVBUF, M_NOWAIT|M_ZERO); - - if (sc->ndis_mmaps == NULL) - return (NDIS_STATUS_RESOURCES); - - error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, - NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW, - NULL, NULL, &sc->ndis_mtag); - - if (error) { - free(sc->ndis_mmaps, M_DEVBUF); - return (NDIS_STATUS_RESOURCES); - } - - for (i = 0; i < physmapneeded; i++) - bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]); - - sc->ndis_mmapcnt = physmapneeded; - - return (NDIS_STATUS_SUCCESS); -} - -static void -NdisMFreeMapRegisters(adapter) - ndis_handle adapter; -{ - struct ndis_softc *sc; - ndis_miniport_block *block; - int i; - - block = (ndis_miniport_block *)adapter; - 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]); - - free(sc->ndis_mmaps, M_DEVBUF); - - bus_dma_tag_destroy(sc->ndis_mtag); -} - -static void -ndis_mapshared_cb(arg, segs, nseg, error) - void *arg; - bus_dma_segment_t *segs; - int nseg; - int error; -{ - ndis_physaddr *p; - - if (error || nseg > 1) - return; - - p = arg; - - p->np_quad = segs[0].ds_addr; -} - -/* - * This maps to bus_dmamem_alloc(). - */ - -static void -NdisMAllocateSharedMemory(ndis_handle adapter, uint32_t len, uint8_t cached, - void **vaddr, ndis_physaddr *paddr) -{ - ndis_miniport_block *block; - struct ndis_softc *sc; - struct ndis_shmem *sh; - int error; - - if (adapter == NULL) - return; - - block = (ndis_miniport_block *)adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - - sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO); - if (sh == NULL) - return; - - InitializeListHead(&sh->ndis_list); - - /* - * When performing shared memory allocations, create a tag - * with a lowaddr limit that restricts physical memory mappings - * so that they all fall within the first 1GB of memory. - * At least one device/driver combination (Linksys Instant - * Wireless PCI Card V2.7, Broadcom 802.11b) seems to have - * problems with performing DMA operations with physical - * addresses that lie above the 1GB mark. I don't know if this - * is a hardware limitation or if the addresses are being - * truncated within the driver, but this seems to be the only - * way to make these cards work reliably in systems with more - * than 1GB of physical memory. - */ - - error = bus_dma_tag_create(sc->ndis_parent_tag, 64, - 0, NDIS_BUS_SPACE_SHARED_MAXADDR, BUS_SPACE_MAXADDR, NULL, - NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL, - &sh->ndis_stag); - - if (error) { - free(sh, M_DEVBUF); - return; - } - - error = bus_dmamem_alloc(sh->ndis_stag, vaddr, - BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap); - - if (error) { - bus_dma_tag_destroy(sh->ndis_stag); - free(sh, M_DEVBUF); - return; - } - - error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr, - len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT); - - if (error) { - bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap); - bus_dma_tag_destroy(sh->ndis_stag); - free(sh, M_DEVBUF); - return; - } - - /* - * Save the physical address along with the source address. - * The AirGo MIMO driver will call NdisMFreeSharedMemory() - * with a bogus virtual address sometimes, but with a valid - * physical address. To keep this from causing trouble, we - * use the physical address to as a sanity check in case - * searching based on the virtual address fails. - */ - - NDIS_LOCK(sc); - sh->ndis_paddr.np_quad = paddr->np_quad; - sh->ndis_saddr = *vaddr; - InsertHeadList((&sc->ndis_shlist), (&sh->ndis_list)); - NDIS_UNLOCK(sc); -} - -struct ndis_allocwork { - uint32_t na_len; - uint8_t na_cached; - void *na_ctx; - io_workitem *na_iw; -}; - -static void -ndis_asyncmem_complete(dobj, arg) - device_object *dobj; - void *arg; -{ - ndis_miniport_block *block; - struct ndis_softc *sc; - struct ndis_allocwork *w; - void *vaddr; - ndis_physaddr paddr; - ndis_allocdone_handler donefunc; - - w = arg; - block = (ndis_miniport_block *)dobj->do_devext; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - - vaddr = NULL; - paddr.np_quad = 0; - - donefunc = sc->ndis_chars->nmc_allocate_complete_func; - NdisMAllocateSharedMemory(block, w->na_len, - w->na_cached, &vaddr, &paddr); - MSCALL5(donefunc, block, vaddr, &paddr, w->na_len, w->na_ctx); - - IoFreeWorkItem(w->na_iw); - free(w, M_DEVBUF); -} - -static ndis_status -NdisMAllocateSharedMemoryAsync(ndis_handle adapter, uint32_t len, - uint8_t cached, void *ctx) -{ - ndis_miniport_block *block; - struct ndis_allocwork *w; - io_workitem *iw; - io_workitem_func ifw; - - if (adapter == NULL) - return (NDIS_STATUS_FAILURE); - - block = adapter; - - iw = IoAllocateWorkItem(block->nmb_deviceobj); - if (iw == NULL) - return (NDIS_STATUS_FAILURE); - - w = malloc(sizeof(struct ndis_allocwork), M_TEMP, M_NOWAIT); - - if (w == NULL) - return (NDIS_STATUS_FAILURE); - - w->na_cached = cached; - w->na_len = len; - w->na_ctx = ctx; - w->na_iw = iw; - - ifw = (io_workitem_func)ndis_findwrap((funcptr)ndis_asyncmem_complete); - IoQueueWorkItem(iw, ifw, WORKQUEUE_DELAYED, w); - - return (NDIS_STATUS_PENDING); -} - -static void -NdisMFreeSharedMemory(ndis_handle adapter, uint32_t len, uint8_t cached, - void *vaddr, ndis_physaddr paddr) -{ - ndis_miniport_block *block; - struct ndis_softc *sc; - struct ndis_shmem *sh = NULL; - list_entry *l; - - if (vaddr == NULL || adapter == NULL) - return; - - block = (ndis_miniport_block *)adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - - /* Sanity check: is list empty? */ - - if (IsListEmpty(&sc->ndis_shlist)) - return; - - NDIS_LOCK(sc); - l = sc->ndis_shlist.nle_flink; - while (l != &sc->ndis_shlist) { - sh = CONTAINING_RECORD(l, struct ndis_shmem, ndis_list); - if (sh->ndis_saddr == vaddr) - break; - /* - * Check the physaddr too, just in case the driver lied - * about the virtual address. - */ - if (sh->ndis_paddr.np_quad == paddr.np_quad) - break; - l = l->nle_flink; - } - - if (sh == NULL) { - NDIS_UNLOCK(sc); - printf("NDIS: buggy driver tried to free " - "invalid shared memory: vaddr: %p paddr: 0x%jx\n", - vaddr, (uintmax_t)paddr.np_quad); - return; - } - - RemoveEntryList(&sh->ndis_list); - - NDIS_UNLOCK(sc); - - bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap); - bus_dmamem_free(sh->ndis_stag, sh->ndis_saddr, sh->ndis_smap); - bus_dma_tag_destroy(sh->ndis_stag); - - free(sh, M_DEVBUF); -} - -static ndis_status -NdisMMapIoSpace(vaddr, adapter, paddr, len) - void **vaddr; - ndis_handle adapter; - ndis_physaddr paddr; - uint32_t len; -{ - if (adapter == NULL) - return (NDIS_STATUS_FAILURE); - - *vaddr = MmMapIoSpace(paddr.np_quad, len, 0); - - if (*vaddr == NULL) - return (NDIS_STATUS_FAILURE); - - return (NDIS_STATUS_SUCCESS); -} - -static void -NdisMUnmapIoSpace(adapter, vaddr, len) - ndis_handle adapter; - void *vaddr; - uint32_t len; -{ - MmUnmapIoSpace(vaddr, len); -} - -static uint32_t -NdisGetCacheFillSize(void) -{ - return (128); -} - -static void * -NdisGetRoutineAddress(ustr) - unicode_string *ustr; -{ - ansi_string astr; - - if (RtlUnicodeStringToAnsiString(&astr, ustr, TRUE)) - return (NULL); - return (ndis_get_routine_address(ndis_functbl, astr.as_buf)); -} - -static uint32_t -NdisMGetDmaAlignment(handle) - ndis_handle handle; -{ - return (16); -} - -/* - * NDIS has two methods for dealing with NICs that support DMA. - * One is to just pass packets to the driver and let it call - * NdisMStartBufferPhysicalMapping() to map each buffer in the packet - * all by itself, and the other is to let the NDIS library handle the - * buffer mapping internally, and hand the driver an already populated - * scatter/gather fragment list. If the driver calls - * NdisMInitializeScatterGatherDma(), it wants to use the latter - * method. - */ - -static ndis_status -NdisMInitializeScatterGatherDma(ndis_handle adapter, uint8_t is64, - uint32_t maxphysmap) -{ - struct ndis_softc *sc; - ndis_miniport_block *block; - int error; - - if (adapter == NULL) - return (NDIS_STATUS_FAILURE); - block = (ndis_miniport_block *)adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - - /* Don't do this twice. */ - if (sc->ndis_sc == 1) - return (NDIS_STATUS_SUCCESS); - - error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW, - NULL, NULL, &sc->ndis_ttag); - - sc->ndis_sc = 1; - - return (NDIS_STATUS_SUCCESS); -} - -void -NdisAllocatePacketPool(status, pool, descnum, protrsvdlen) - ndis_status *status; - ndis_handle *pool; - uint32_t descnum; - uint32_t protrsvdlen; -{ - ndis_packet_pool *p; - ndis_packet *packets; - int i; - - p = ExAllocatePoolWithTag(NonPagedPool, sizeof(ndis_packet_pool), 0); - if (p == NULL) { - *status = NDIS_STATUS_RESOURCES; - return; - } - - p->np_cnt = descnum + NDIS_POOL_EXTRA; - p->np_protrsvd = protrsvdlen; - p->np_len = sizeof(ndis_packet) + protrsvdlen; - - packets = ExAllocatePoolWithTag(NonPagedPool, p->np_cnt * - p->np_len, 0); - - if (packets == NULL) { - ExFreePool(p); - *status = NDIS_STATUS_RESOURCES; - return; - } - - p->np_pktmem = packets; - - for (i = 0; i < p->np_cnt; i++) - InterlockedPushEntrySList(&p->np_head, - (struct slist_entry *)&packets[i]); - -#ifdef NDIS_DEBUG_PACKETS - p->np_dead = 0; - KeInitializeSpinLock(&p->np_lock); - KeInitializeEvent(&p->np_event, EVENT_TYPE_NOTIFY, TRUE); -#endif - - *pool = p; - *status = NDIS_STATUS_SUCCESS; -} - -void -NdisAllocatePacketPoolEx(status, pool, descnum, oflowdescnum, protrsvdlen) - ndis_status *status; - ndis_handle *pool; - uint32_t descnum; - uint32_t oflowdescnum; - uint32_t protrsvdlen; -{ - return (NdisAllocatePacketPool(status, pool, - descnum + oflowdescnum, protrsvdlen)); -} - -uint32_t -NdisPacketPoolUsage(pool) - ndis_handle pool; -{ - ndis_packet_pool *p; - - p = (ndis_packet_pool *)pool; - return (p->np_cnt - ExQueryDepthSList(&p->np_head)); -} - -void -NdisFreePacketPool(pool) - ndis_handle pool; -{ - ndis_packet_pool *p; - int usage; -#ifdef NDIS_DEBUG_PACKETS - uint8_t irql; -#endif - - p = (ndis_packet_pool *)pool; - -#ifdef NDIS_DEBUG_PACKETS - KeAcquireSpinLock(&p->np_lock, &irql); -#endif - - usage = NdisPacketPoolUsage(pool); - -#ifdef NDIS_DEBUG_PACKETS - if (usage) { - p->np_dead = 1; - KeResetEvent(&p->np_event); - KeReleaseSpinLock(&p->np_lock, irql); - KeWaitForSingleObject(&p->np_event, 0, 0, FALSE, NULL); - } else - KeReleaseSpinLock(&p->np_lock, irql); -#endif - - ExFreePool(p->np_pktmem); - ExFreePool(p); -} - -void -NdisAllocatePacket(status, packet, pool) - ndis_status *status; - ndis_packet **packet; - ndis_handle pool; -{ - ndis_packet_pool *p; - ndis_packet *pkt; -#ifdef NDIS_DEBUG_PACKETS - uint8_t irql; -#endif - - p = (ndis_packet_pool *)pool; - -#ifdef NDIS_DEBUG_PACKETS - KeAcquireSpinLock(&p->np_lock, &irql); - if (p->np_dead) { - KeReleaseSpinLock(&p->np_lock, irql); - printf("NDIS: tried to allocate packet from dead pool %p\n", - pool); - *status = NDIS_STATUS_RESOURCES; - return; - } -#endif - - pkt = (ndis_packet *)InterlockedPopEntrySList(&p->np_head); - -#ifdef NDIS_DEBUG_PACKETS - KeReleaseSpinLock(&p->np_lock, irql); -#endif - - if (pkt == NULL) { - *status = NDIS_STATUS_RESOURCES; - return; - } - - bzero((char *)pkt, sizeof(ndis_packet)); - - /* Save pointer to the pool. */ - pkt->np_private.npp_pool = pool; - - /* Set the oob offset pointer. Lots of things expect this. */ - pkt->np_private.npp_packetooboffset = offsetof(ndis_packet, np_oob); - - /* - * We must initialize the packet flags correctly in order - * for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and - * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() macros to work - * correctly. - */ - pkt->np_private.npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS; - pkt->np_private.npp_validcounts = FALSE; - - *packet = pkt; - - *status = NDIS_STATUS_SUCCESS; -} - -void -NdisFreePacket(packet) - ndis_packet *packet; -{ - ndis_packet_pool *p; -#ifdef NDIS_DEBUG_PACKETS - uint8_t irql; -#endif - - p = (ndis_packet_pool *)packet->np_private.npp_pool; - -#ifdef NDIS_DEBUG_PACKETS - KeAcquireSpinLock(&p->np_lock, &irql); -#endif - - InterlockedPushEntrySList(&p->np_head, (slist_entry *)packet); - -#ifdef NDIS_DEBUG_PACKETS - if (p->np_dead) { - if (ExQueryDepthSList(&p->np_head) == p->np_cnt) - KeSetEvent(&p->np_event, IO_NO_INCREMENT, FALSE); - } - KeReleaseSpinLock(&p->np_lock, irql); -#endif -} - -static void -NdisUnchainBufferAtFront(packet, buf) - ndis_packet *packet; - ndis_buffer **buf; -{ - ndis_packet_private *priv; - - if (packet == NULL || buf == NULL) - return; - - priv = &packet->np_private; - - priv->npp_validcounts = FALSE; - - if (priv->npp_head == priv->npp_tail) { - *buf = priv->npp_head; - priv->npp_head = priv->npp_tail = NULL; - } else { - *buf = priv->npp_head; - priv->npp_head = (*buf)->mdl_next; - } -} - -static void -NdisUnchainBufferAtBack(packet, buf) - ndis_packet *packet; - ndis_buffer **buf; -{ - ndis_packet_private *priv; - ndis_buffer *tmp; - - if (packet == NULL || buf == NULL) - return; - - priv = &packet->np_private; - - priv->npp_validcounts = FALSE; - - if (priv->npp_head == priv->npp_tail) { - *buf = priv->npp_head; - priv->npp_head = priv->npp_tail = NULL; - } else { - *buf = priv->npp_tail; - tmp = priv->npp_head; - while (tmp->mdl_next != priv->npp_tail) - tmp = tmp->mdl_next; - priv->npp_tail = tmp; - tmp->mdl_next = NULL; - } -} - -/* - * The NDIS "buffer" is really an MDL (memory descriptor list) - * which is used to describe a buffer in a way that allows it - * to mapped into different contexts. We have to be careful how - * we handle them: in some versions of Windows, the NdisFreeBuffer() - * routine is an actual function in the NDIS API, but in others - * it's just a macro wrapper around IoFreeMdl(). There's really - * no way to use the 'descnum' parameter to count how many - * "buffers" are allocated since in order to use IoFreeMdl() to - * dispose of a buffer, we have to use IoAllocateMdl() to allocate - * them, and IoAllocateMdl() just grabs them out of the heap. - */ - -static void -NdisAllocateBufferPool(status, pool, descnum) - ndis_status *status; - ndis_handle *pool; - uint32_t descnum; -{ - - /* - * The only thing we can really do here is verify that descnum - * is a reasonable value, but I really don't know what to check - * it against. - */ - - *pool = NonPagedPool; - *status = NDIS_STATUS_SUCCESS; -} - -static void -NdisFreeBufferPool(pool) - ndis_handle pool; -{ -} - -static void -NdisAllocateBuffer(status, buffer, pool, vaddr, len) - ndis_status *status; - ndis_buffer **buffer; - ndis_handle pool; - void *vaddr; - uint32_t len; -{ - ndis_buffer *buf; - - buf = IoAllocateMdl(vaddr, len, FALSE, FALSE, NULL); - if (buf == NULL) { - *status = NDIS_STATUS_RESOURCES; - return; - } - - MmBuildMdlForNonPagedPool(buf); - - *buffer = buf; - *status = NDIS_STATUS_SUCCESS; -} - -static void -NdisFreeBuffer(buf) - ndis_buffer *buf; -{ - IoFreeMdl(buf); -} - -/* Aw c'mon. */ - -static uint32_t -NdisBufferLength(buf) - ndis_buffer *buf; -{ - return (MmGetMdlByteCount(buf)); -} - -/* - * Get the virtual address and length of a buffer. - * Note: the vaddr argument is optional. - */ - -static void -NdisQueryBuffer(buf, vaddr, len) - ndis_buffer *buf; - void **vaddr; - uint32_t *len; -{ - if (vaddr != NULL) - *vaddr = MmGetMdlVirtualAddress(buf); - *len = MmGetMdlByteCount(buf); -} - -/* Same as above -- we don't care about the priority. */ - -static void -NdisQueryBufferSafe(buf, vaddr, len, prio) - ndis_buffer *buf; - void **vaddr; - uint32_t *len; - uint32_t prio; -{ - if (vaddr != NULL) - *vaddr = MmGetMdlVirtualAddress(buf); - *len = MmGetMdlByteCount(buf); -} - -/* Damnit Microsoft!! How many ways can you do the same thing?! */ - -static void * -NdisBufferVirtualAddress(buf) - ndis_buffer *buf; -{ - return (MmGetMdlVirtualAddress(buf)); -} - -static void * -NdisBufferVirtualAddressSafe(buf, prio) - ndis_buffer *buf; - uint32_t prio; -{ - return (MmGetMdlVirtualAddress(buf)); -} - -static void -NdisAdjustBufferLength(buf, len) - ndis_buffer *buf; - int len; -{ - MmGetMdlByteCount(buf) = len; -} - -static uint32_t -NdisInterlockedIncrement(addend) - uint32_t *addend; -{ - atomic_add_long((u_long *)addend, 1); - return (*addend); -} - -static uint32_t -NdisInterlockedDecrement(addend) - uint32_t *addend; -{ - atomic_subtract_long((u_long *)addend, 1); - return (*addend); -} - -static uint32_t -NdisGetVersion(void) -{ - return (0x00050001); -} - -static void -NdisInitializeEvent(event) - ndis_event *event; -{ - /* - * NDIS events are always notification - * events, and should be initialized to the - * not signaled state. - */ - KeInitializeEvent(&event->ne_event, EVENT_TYPE_NOTIFY, FALSE); -} - -static void -NdisSetEvent(event) - ndis_event *event; -{ - KeSetEvent(&event->ne_event, IO_NO_INCREMENT, FALSE); -} - -static void -NdisResetEvent(event) - ndis_event *event; -{ - KeResetEvent(&event->ne_event); -} - -static uint8_t -NdisWaitEvent(event, msecs) - ndis_event *event; - uint32_t msecs; -{ - int64_t duetime; - uint32_t rval; - - duetime = ((int64_t)msecs * -10000); - rval = KeWaitForSingleObject(event, - 0, 0, TRUE, msecs ? & duetime : NULL); - - if (rval == STATUS_TIMEOUT) - return (FALSE); - - return (TRUE); -} - -static ndis_status -NdisUnicodeStringToAnsiString(dstr, sstr) - ansi_string *dstr; - unicode_string *sstr; -{ - uint32_t rval; - - rval = RtlUnicodeStringToAnsiString(dstr, sstr, FALSE); - - if (rval == STATUS_INSUFFICIENT_RESOURCES) - return (NDIS_STATUS_RESOURCES); - if (rval) - return (NDIS_STATUS_FAILURE); - - return (NDIS_STATUS_SUCCESS); -} - -static ndis_status -NdisAnsiStringToUnicodeString(dstr, sstr) - unicode_string *dstr; - ansi_string *sstr; -{ - uint32_t rval; - - rval = RtlAnsiStringToUnicodeString(dstr, sstr, FALSE); - - if (rval == STATUS_INSUFFICIENT_RESOURCES) - return (NDIS_STATUS_RESOURCES); - if (rval) - return (NDIS_STATUS_FAILURE); - - return (NDIS_STATUS_SUCCESS); -} - -static ndis_status -NdisMPciAssignResources(adapter, slot, list) - ndis_handle adapter; - uint32_t slot; - ndis_resource_list **list; -{ - ndis_miniport_block *block; - - if (adapter == NULL || list == NULL) - return (NDIS_STATUS_FAILURE); - - block = (ndis_miniport_block *)adapter; - *list = block->nmb_rlist; - - return (NDIS_STATUS_SUCCESS); -} - -static uint8_t -ndis_intr(iobj, arg) - kinterrupt *iobj; - void *arg; -{ - struct ndis_softc *sc; - uint8_t is_our_intr = FALSE; - int call_isr = 0; - ndis_miniport_interrupt *intr; - - sc = arg; - intr = sc->ndis_block->nmb_interrupt; - - if (intr == NULL || sc->ndis_block->nmb_miniportadapterctx == NULL) - return (FALSE); - - if (sc->ndis_block->nmb_interrupt->ni_isrreq == TRUE) - MSCALL3(intr->ni_isrfunc, &is_our_intr, &call_isr, - sc->ndis_block->nmb_miniportadapterctx); - else { - MSCALL1(sc->ndis_chars->nmc_disable_interrupts_func, - sc->ndis_block->nmb_miniportadapterctx); - call_isr = 1; - } - - if (call_isr) - IoRequestDpc(sc->ndis_block->nmb_deviceobj, NULL, sc); - - return (is_our_intr); -} - -static void -ndis_intrhand(dpc, intr, sysarg1, sysarg2) - kdpc *dpc; - ndis_miniport_interrupt *intr; - void *sysarg1; - void *sysarg2; -{ - struct ndis_softc *sc; - ndis_miniport_block *block; - ndis_handle adapter; - - block = intr->ni_block; - adapter = block->nmb_miniportadapterctx; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - - if (NDIS_SERIALIZED(sc->ndis_block)) - KeAcquireSpinLockAtDpcLevel(&block->nmb_lock); - - MSCALL1(intr->ni_dpcfunc, adapter); - - /* If there's a MiniportEnableInterrupt() routine, call it. */ - - if (sc->ndis_chars->nmc_enable_interrupts_func != NULL) - MSCALL1(sc->ndis_chars->nmc_enable_interrupts_func, adapter); - - if (NDIS_SERIALIZED(sc->ndis_block)) - KeReleaseSpinLockFromDpcLevel(&block->nmb_lock); - - /* - * Set the completion event if we've drained all - * pending interrupts. - */ - - KeAcquireSpinLockAtDpcLevel(&intr->ni_dpccountlock); - intr->ni_dpccnt--; - if (intr->ni_dpccnt == 0) - KeSetEvent(&intr->ni_dpcevt, IO_NO_INCREMENT, FALSE); - KeReleaseSpinLockFromDpcLevel(&intr->ni_dpccountlock); -} - -static ndis_status -NdisMRegisterInterrupt(ndis_miniport_interrupt *intr, ndis_handle adapter, - uint32_t ivec, uint32_t ilevel, uint8_t reqisr, uint8_t shared, - ndis_interrupt_mode imode) -{ - ndis_miniport_block *block; - ndis_miniport_characteristics *ch; - struct ndis_softc *sc; - int error; - - block = adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - ch = IoGetDriverObjectExtension(block->nmb_deviceobj->do_drvobj, - (void *)1); - - intr->ni_rsvd = ExAllocatePoolWithTag(NonPagedPool, - sizeof(struct mtx), 0); - if (intr->ni_rsvd == NULL) - return (NDIS_STATUS_RESOURCES); - - intr->ni_block = adapter; - intr->ni_isrreq = reqisr; - intr->ni_shared = shared; - intr->ni_dpccnt = 0; - intr->ni_isrfunc = ch->nmc_isr_func; - intr->ni_dpcfunc = ch->nmc_interrupt_func; - - KeInitializeEvent(&intr->ni_dpcevt, EVENT_TYPE_NOTIFY, TRUE); - KeInitializeDpc(&intr->ni_dpc, - ndis_findwrap((funcptr)ndis_intrhand), intr); - KeSetImportanceDpc(&intr->ni_dpc, KDPC_IMPORTANCE_LOW); - - error = IoConnectInterrupt(&intr->ni_introbj, - ndis_findwrap((funcptr)ndis_intr), sc, NULL, - ivec, ilevel, 0, imode, shared, 0, FALSE); - - if (error != STATUS_SUCCESS) - return (NDIS_STATUS_FAILURE); - - block->nmb_interrupt = intr; - - return (NDIS_STATUS_SUCCESS); -} - -static void -NdisMDeregisterInterrupt(intr) - ndis_miniport_interrupt *intr; -{ - ndis_miniport_block *block; - uint8_t irql; - - block = intr->ni_block; - - /* Should really be KeSynchronizeExecution() */ - - KeAcquireSpinLock(intr->ni_introbj->ki_lock, &irql); - block->nmb_interrupt = NULL; - KeReleaseSpinLock(intr->ni_introbj->ki_lock, irql); -/* - KeFlushQueuedDpcs(); -*/ - /* Disconnect our ISR */ - - IoDisconnectInterrupt(intr->ni_introbj); - - KeWaitForSingleObject(&intr->ni_dpcevt, 0, 0, FALSE, NULL); - KeResetEvent(&intr->ni_dpcevt); -} - -static void -NdisMRegisterAdapterShutdownHandler(adapter, shutdownctx, shutdownfunc) - ndis_handle adapter; - void *shutdownctx; - ndis_shutdown_handler shutdownfunc; -{ - ndis_miniport_block *block; - ndis_miniport_characteristics *chars; - struct ndis_softc *sc; - - if (adapter == NULL) - return; - - block = (ndis_miniport_block *)adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - chars = sc->ndis_chars; - - chars->nmc_shutdown_handler = shutdownfunc; - chars->nmc_rsvd0 = shutdownctx; -} - -static void -NdisMDeregisterAdapterShutdownHandler(adapter) - ndis_handle adapter; -{ - ndis_miniport_block *block; - ndis_miniport_characteristics *chars; - struct ndis_softc *sc; - - if (adapter == NULL) - return; - - block = (ndis_miniport_block *)adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - chars = sc->ndis_chars; - - chars->nmc_shutdown_handler = NULL; - chars->nmc_rsvd0 = NULL; -} - -static uint32_t -NDIS_BUFFER_TO_SPAN_PAGES(buf) - ndis_buffer *buf; -{ - if (buf == NULL) - return (0); - if (MmGetMdlByteCount(buf) == 0) - return (1); - return (SPAN_PAGES(MmGetMdlVirtualAddress(buf), - MmGetMdlByteCount(buf))); -} - -static void -NdisGetBufferPhysicalArraySize(buf, pages) - ndis_buffer *buf; - uint32_t *pages; -{ - if (buf == NULL) - return; - - *pages = NDIS_BUFFER_TO_SPAN_PAGES(buf); -} - -static void -NdisQueryBufferOffset(buf, off, len) - ndis_buffer *buf; - uint32_t *off; - uint32_t *len; -{ - if (buf == NULL) - return; - - *off = MmGetMdlByteOffset(buf); - *len = MmGetMdlByteCount(buf); -} - -void -NdisMSleep(usecs) - uint32_t usecs; -{ - ktimer timer; - - /* - * During system bootstrap, (i.e. cold == 1), we aren't - * allowed to sleep, so we have to do a hard DELAY() - * instead. - */ - - if (cold) - DELAY(usecs); - else { - KeInitializeTimer(&timer); - KeSetTimer(&timer, ((int64_t)usecs * -10), NULL); - KeWaitForSingleObject(&timer, 0, 0, FALSE, NULL); - } -} - -static uint32_t -NdisReadPcmciaAttributeMemory(handle, offset, buf, len) - ndis_handle handle; - uint32_t offset; - void *buf; - uint32_t len; -{ - struct ndis_softc *sc; - ndis_miniport_block *block; - bus_space_handle_t bh; - bus_space_tag_t bt; - char *dest; - uint32_t i; - - if (handle == NULL) - return (0); - - block = (ndis_miniport_block *)handle; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - dest = buf; - - bh = rman_get_bushandle(sc->ndis_res_am); - bt = rman_get_bustag(sc->ndis_res_am); - - for (i = 0; i < len; i++) - dest[i] = bus_space_read_1(bt, bh, (offset + i) * 2); - - return (i); -} - -static uint32_t -NdisWritePcmciaAttributeMemory(handle, offset, buf, len) - ndis_handle handle; - uint32_t offset; - void *buf; - uint32_t len; -{ - struct ndis_softc *sc; - ndis_miniport_block *block; - bus_space_handle_t bh; - bus_space_tag_t bt; - char *src; - uint32_t i; - - if (handle == NULL) - return (0); - - block = (ndis_miniport_block *)handle; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - src = buf; - - bh = rman_get_bushandle(sc->ndis_res_am); - bt = rman_get_bustag(sc->ndis_res_am); - - for (i = 0; i < len; i++) - bus_space_write_1(bt, bh, (offset + i) * 2, src[i]); - - return (i); -} - -static list_entry * -NdisInterlockedInsertHeadList(head, entry, lock) - list_entry *head; - list_entry *entry; - ndis_spin_lock *lock; -{ - list_entry *flink; - - KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql); - flink = head->nle_flink; - entry->nle_flink = flink; - entry->nle_blink = head; - flink->nle_blink = entry; - head->nle_flink = entry; - KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql); - - return (flink); -} - -static list_entry * -NdisInterlockedRemoveHeadList(head, lock) - list_entry *head; - ndis_spin_lock *lock; -{ - list_entry *flink; - list_entry *entry; - - KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql); - entry = head->nle_flink; - flink = entry->nle_flink; - head->nle_flink = flink; - flink->nle_blink = head; - KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql); - - return (entry); -} - -static list_entry * -NdisInterlockedInsertTailList(head, entry, lock) - list_entry *head; - list_entry *entry; - ndis_spin_lock *lock; -{ - list_entry *blink; - - KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql); - blink = head->nle_blink; - entry->nle_flink = head; - entry->nle_blink = blink; - blink->nle_flink = entry; - head->nle_blink = entry; - KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql); - - return (blink); -} - -static uint8_t -NdisMSynchronizeWithInterrupt(intr, syncfunc, syncctx) - ndis_miniport_interrupt *intr; - void *syncfunc; - void *syncctx; -{ - return (KeSynchronizeExecution(intr->ni_introbj, syncfunc, syncctx)); -} - -static void -NdisGetCurrentSystemTime(tval) - uint64_t *tval; -{ - ntoskrnl_time(tval); -} - -/* - * Return the number of milliseconds since the system booted. - */ -static void -NdisGetSystemUpTime(tval) - uint32_t *tval; -{ - struct timespec ts; - - nanouptime(&ts); - *tval = ts.tv_nsec / 1000000 + ts.tv_sec * 1000; -} - -static void -NdisInitializeString(dst, src) - unicode_string *dst; - char *src; -{ - ansi_string as; - RtlInitAnsiString(&as, src); - RtlAnsiStringToUnicodeString(dst, &as, TRUE); -} - -static void -NdisFreeString(str) - unicode_string *str; -{ - RtlFreeUnicodeString(str); -} - -static ndis_status -NdisMRemoveMiniport(adapter) - ndis_handle *adapter; -{ - return (NDIS_STATUS_SUCCESS); -} - -static void -NdisInitAnsiString(dst, src) - ansi_string *dst; - char *src; -{ - RtlInitAnsiString(dst, src); -} - -static void -NdisInitUnicodeString(dst, src) - unicode_string *dst; - uint16_t *src; -{ - RtlInitUnicodeString(dst, src); -} - -static void NdisMGetDeviceProperty(adapter, phydevobj, - funcdevobj, nextdevobj, resources, transresources) - ndis_handle adapter; - device_object **phydevobj; - device_object **funcdevobj; - device_object **nextdevobj; - cm_resource_list *resources; - cm_resource_list *transresources; -{ - ndis_miniport_block *block; - - block = (ndis_miniport_block *)adapter; - - if (phydevobj != NULL) - *phydevobj = block->nmb_physdeviceobj; - if (funcdevobj != NULL) - *funcdevobj = block->nmb_deviceobj; - if (nextdevobj != NULL) - *nextdevobj = block->nmb_nextdeviceobj; -} - -static void -NdisGetFirstBufferFromPacket(packet, buf, firstva, firstlen, totlen) - ndis_packet *packet; - ndis_buffer **buf; - void **firstva; - uint32_t *firstlen; - uint32_t *totlen; -{ - ndis_buffer *tmp; - - tmp = packet->np_private.npp_head; - *buf = tmp; - if (tmp == NULL) { - *firstva = NULL; - *firstlen = *totlen = 0; - } else { - *firstva = MmGetMdlVirtualAddress(tmp); - *firstlen = *totlen = MmGetMdlByteCount(tmp); - for (tmp = tmp->mdl_next; tmp != NULL; tmp = tmp->mdl_next) - *totlen += MmGetMdlByteCount(tmp); - } -} - -static void -NdisGetFirstBufferFromPacketSafe(packet, buf, firstva, firstlen, totlen, prio) - ndis_packet *packet; - ndis_buffer **buf; - void **firstva; - uint32_t *firstlen; - uint32_t *totlen; - uint32_t prio; -{ - NdisGetFirstBufferFromPacket(packet, buf, firstva, firstlen, totlen); -} - -static int -ndis_find_sym(lf, filename, suffix, sym) - linker_file_t lf; - char *filename; - char *suffix; - caddr_t *sym; -{ - char *fullsym; - char *suf; - u_int i; - - fullsym = ExAllocatePoolWithTag(NonPagedPool, MAXPATHLEN, 0); - if (fullsym == NULL) - return (ENOMEM); - - bzero(fullsym, MAXPATHLEN); - strncpy(fullsym, filename, MAXPATHLEN); - if (strlen(filename) < 4) { - ExFreePool(fullsym); - return (EINVAL); - } - - /* If the filename has a .ko suffix, strip if off. */ - suf = fullsym + (strlen(filename) - 3); - if (strcmp(suf, ".ko") == 0) - *suf = '\0'; - - for (i = 0; i < strlen(fullsym); i++) { - if (fullsym[i] == '.') - fullsym[i] = '_'; - else - fullsym[i] = tolower(fullsym[i]); - } - strcat(fullsym, suffix); - *sym = linker_file_lookup_symbol(lf, fullsym, 0); - ExFreePool(fullsym); - if (*sym == 0) - return (ENOENT); - - return (0); -} - -struct ndis_checkmodule { - char *afilename; - ndis_fh *fh; -}; - -/* - * See if a single module contains the symbols for a specified file. - */ -static int -NdisCheckModule(linker_file_t lf, void *context) -{ - struct ndis_checkmodule *nc; - caddr_t kldstart, kldend; - - nc = (struct ndis_checkmodule *)context; - if (ndis_find_sym(lf, nc->afilename, "_start", &kldstart)) - return (0); - if (ndis_find_sym(lf, nc->afilename, "_end", &kldend)) - return (0); - nc->fh->nf_vp = lf; - nc->fh->nf_map = NULL; - nc->fh->nf_type = NDIS_FH_TYPE_MODULE; - nc->fh->nf_maplen = (kldend - kldstart) & 0xFFFFFFFF; - return (1); -} - -/* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */ -static void -NdisOpenFile(status, filehandle, filelength, filename, highestaddr) - ndis_status *status; - ndis_handle *filehandle; - uint32_t *filelength; - unicode_string *filename; - ndis_physaddr highestaddr; -{ - ansi_string as; - char *afilename = NULL; - struct thread *td = curthread; - struct nameidata nd; - int flags, error; - struct vattr vat; - struct vattr *vap = &vat; - ndis_fh *fh; - char *path; - struct ndis_checkmodule nc; - - if (RtlUnicodeStringToAnsiString(&as, filename, TRUE)) { - *status = NDIS_STATUS_RESOURCES; - return; - } - - afilename = strdup(as.as_buf, M_DEVBUF); - RtlFreeAnsiString(&as); - - fh = ExAllocatePoolWithTag(NonPagedPool, sizeof(ndis_fh), 0); - if (fh == NULL) { - free(afilename, M_DEVBUF); - *status = NDIS_STATUS_RESOURCES; - return; - } - - fh->nf_name = afilename; - - /* - * During system bootstrap, it's impossible to load files - * from the rootfs since it's not mounted yet. We therefore - * offer the possibility of opening files that have been - * preloaded as modules instead. Both choices will work - * when kldloading a module from multiuser, but only the - * module option will work during bootstrap. The module - * loading option works by using the ndiscvt(8) utility - * to convert the arbitrary file into a .ko using objcopy(1). - * This file will contain two special symbols: filename_start - * and filename_end. All we have to do is traverse the KLD - * list in search of those symbols and we've found the file - * data. As an added bonus, ndiscvt(8) will also generate - * a normal .o file which can be linked statically with - * the kernel. This means that the symbols will actual reside - * in the kernel's symbol table, but that doesn't matter to - * us since the kernel appears to us as just another module. - */ - - nc.afilename = afilename; - nc.fh = fh; - if (linker_file_foreach(NdisCheckModule, &nc)) { - *filelength = fh->nf_maplen; - *filehandle = fh; - *status = NDIS_STATUS_SUCCESS; - return; - } - - if (TAILQ_EMPTY(&mountlist)) { - ExFreePool(fh); - *status = NDIS_STATUS_FILE_NOT_FOUND; - printf("NDIS: could not find file %s in linker list\n", - afilename); - printf("NDIS: and no filesystems mounted yet, " - "aborting NdisOpenFile()\n"); - free(afilename, M_DEVBUF); - return; - } - - path = ExAllocatePoolWithTag(NonPagedPool, MAXPATHLEN, 0); - if (path == NULL) { - ExFreePool(fh); - free(afilename, M_DEVBUF); - *status = NDIS_STATUS_RESOURCES; - return; - } - - snprintf(path, MAXPATHLEN, "%s/%s", ndis_filepath, afilename); - - /* Some threads don't have a current working directory. */ - - pwd_ensure_dirs(); - - NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td); - - flags = FREAD; - error = vn_open(&nd, &flags, 0, NULL); - if (error) { - *status = NDIS_STATUS_FILE_NOT_FOUND; - ExFreePool(fh); - printf("NDIS: open file %s failed: %d\n", path, error); - ExFreePool(path); - free(afilename, M_DEVBUF); - return; - } - - ExFreePool(path); - - NDFREE(&nd, NDF_ONLY_PNBUF); - - /* Get the file size. */ - VOP_GETATTR(nd.ni_vp, vap, td->td_ucred); - VOP_UNLOCK(nd.ni_vp); - - fh->nf_vp = nd.ni_vp; - fh->nf_map = NULL; - fh->nf_type = NDIS_FH_TYPE_VFS; - *filehandle = fh; - *filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF; - *status = NDIS_STATUS_SUCCESS; -} - -static void -NdisMapFile(status, mappedbuffer, filehandle) - ndis_status *status; - void **mappedbuffer; - ndis_handle filehandle; -{ - ndis_fh *fh; - struct thread *td = curthread; - linker_file_t lf; - caddr_t kldstart; - int error; - ssize_t resid; - struct vnode *vp; - - if (filehandle == NULL) { - *status = NDIS_STATUS_FAILURE; - return; - } - - fh = (ndis_fh *)filehandle; - - if (fh->nf_vp == NULL) { - *status = NDIS_STATUS_FAILURE; - return; - } - - if (fh->nf_map != NULL) { - *status = NDIS_STATUS_ALREADY_MAPPED; - return; - } - - if (fh->nf_type == NDIS_FH_TYPE_MODULE) { - lf = fh->nf_vp; - if (ndis_find_sym(lf, fh->nf_name, "_start", &kldstart)) { - *status = NDIS_STATUS_FAILURE; - return; - } - fh->nf_map = kldstart; - *status = NDIS_STATUS_SUCCESS; - *mappedbuffer = fh->nf_map; - return; - } - - fh->nf_map = ExAllocatePoolWithTag(NonPagedPool, fh->nf_maplen, 0); - - if (fh->nf_map == NULL) { - *status = NDIS_STATUS_RESOURCES; - return; - } - - vp = fh->nf_vp; - error = vn_rdwr(UIO_READ, vp, fh->nf_map, fh->nf_maplen, 0, - UIO_SYSSPACE, 0, td->td_ucred, NOCRED, &resid, td); - - if (error) - *status = NDIS_STATUS_FAILURE; - else { - *status = NDIS_STATUS_SUCCESS; - *mappedbuffer = fh->nf_map; - } -} - -static void -NdisUnmapFile(filehandle) - ndis_handle filehandle; -{ - ndis_fh *fh; - fh = (ndis_fh *)filehandle; - - if (fh->nf_map == NULL) - return; - - if (fh->nf_type == NDIS_FH_TYPE_VFS) - ExFreePool(fh->nf_map); - fh->nf_map = NULL; -} - -static void -NdisCloseFile(filehandle) - ndis_handle filehandle; -{ - struct thread *td = curthread; - ndis_fh *fh; - struct vnode *vp; - - if (filehandle == NULL) - return; - - fh = (ndis_fh *)filehandle; - if (fh->nf_map != NULL) { - if (fh->nf_type == NDIS_FH_TYPE_VFS) - ExFreePool(fh->nf_map); - fh->nf_map = NULL; - } - - if (fh->nf_vp == NULL) - return; - - if (fh->nf_type == NDIS_FH_TYPE_VFS) { - vp = fh->nf_vp; - vn_close(vp, FREAD, td->td_ucred, td); - } - - fh->nf_vp = NULL; - free(fh->nf_name, M_DEVBUF); - ExFreePool(fh); -} - -static uint8_t -NdisSystemProcessorCount() -{ - return (mp_ncpus); -} - -static void -NdisGetCurrentProcessorCounts(idle_count, kernel_and_user, index) - uint32_t *idle_count; - uint32_t *kernel_and_user; - uint32_t *index; -{ - struct pcpu *pcpu; - - pcpu = pcpu_find(curthread->td_oncpu); - *index = pcpu->pc_cpuid; - *idle_count = pcpu->pc_cp_time[CP_IDLE]; - *kernel_and_user = pcpu->pc_cp_time[CP_INTR]; -} - -typedef void (*ndis_statusdone_handler)(ndis_handle); -typedef void (*ndis_status_handler)(ndis_handle, ndis_status, - void *, uint32_t); - -static void -NdisMIndicateStatusComplete(adapter) - ndis_handle adapter; -{ - ndis_miniport_block *block; - ndis_statusdone_handler statusdonefunc; - - block = (ndis_miniport_block *)adapter; - statusdonefunc = block->nmb_statusdone_func; - - MSCALL1(statusdonefunc, adapter); -} - -static void -NdisMIndicateStatus(adapter, status, sbuf, slen) - ndis_handle adapter; - ndis_status status; - void *sbuf; - uint32_t slen; -{ - ndis_miniport_block *block; - ndis_status_handler statusfunc; - - block = (ndis_miniport_block *)adapter; - statusfunc = block->nmb_status_func; - - MSCALL4(statusfunc, adapter, status, sbuf, slen); -} - -/* - * The DDK documentation says that you should use IoQueueWorkItem() - * instead of ExQueueWorkItem(). The problem is, IoQueueWorkItem() - * is fundamentally incompatible with NdisScheduleWorkItem(), which - * depends on the API semantics of ExQueueWorkItem(). In our world, - * ExQueueWorkItem() is implemented on top of IoAllocateQueueItem() - * anyway. - * - * There are actually three distinct APIs here. NdisScheduleWorkItem() - * takes a pointer to an NDIS_WORK_ITEM. ExQueueWorkItem() takes a pointer - * to a WORK_QUEUE_ITEM. And finally, IoQueueWorkItem() takes a pointer - * to an opaque work item thingie which you get from IoAllocateWorkItem(). - * An NDIS_WORK_ITEM is not the same as a WORK_QUEUE_ITEM. However, - * the NDIS_WORK_ITEM has some opaque storage at the end of it, and we - * (ab)use this storage as a WORK_QUEUE_ITEM, which is what we submit - * to ExQueueWorkItem(). - * - * Got all that? (Sheesh.) - */ - -ndis_status -NdisScheduleWorkItem(work) - ndis_work_item *work; -{ - work_queue_item *wqi; - - wqi = (work_queue_item *)work->nwi_wraprsvd; - ExInitializeWorkItem(wqi, - (work_item_func)work->nwi_func, work->nwi_ctx); - ExQueueWorkItem(wqi, WORKQUEUE_DELAYED); - - return (NDIS_STATUS_SUCCESS); -} - -static void -NdisCopyFromPacketToPacket(dpkt, doff, reqlen, spkt, soff, cpylen) - ndis_packet *dpkt; - uint32_t doff; - uint32_t reqlen; - ndis_packet *spkt; - uint32_t soff; - uint32_t *cpylen; -{ - ndis_buffer *src, *dst; - char *sptr, *dptr; - int resid, copied, len, scnt, dcnt; - - *cpylen = 0; - - src = spkt->np_private.npp_head; - dst = dpkt->np_private.npp_head; - - sptr = MmGetMdlVirtualAddress(src); - dptr = MmGetMdlVirtualAddress(dst); - scnt = MmGetMdlByteCount(src); - dcnt = MmGetMdlByteCount(dst); - - while (soff) { - if (MmGetMdlByteCount(src) > soff) { - sptr += soff; - scnt = MmGetMdlByteCount(src)- soff; - break; - } - soff -= MmGetMdlByteCount(src); - src = src->mdl_next; - if (src == NULL) - return; - sptr = MmGetMdlVirtualAddress(src); - } - - while (doff) { - if (MmGetMdlByteCount(dst) > doff) { - dptr += doff; - dcnt = MmGetMdlByteCount(dst) - doff; - break; - } - doff -= MmGetMdlByteCount(dst); - dst = dst->mdl_next; - if (dst == NULL) - return; - dptr = MmGetMdlVirtualAddress(dst); - } - - resid = reqlen; - copied = 0; - - while(1) { - if (resid < scnt) - len = resid; - else - len = scnt; - if (dcnt < len) - len = dcnt; - - bcopy(sptr, dptr, len); - - copied += len; - resid -= len; - if (resid == 0) - break; - - dcnt -= len; - if (dcnt == 0) { - dst = dst->mdl_next; - if (dst == NULL) - break; - dptr = MmGetMdlVirtualAddress(dst); - dcnt = MmGetMdlByteCount(dst); - } - - scnt -= len; - if (scnt == 0) { - src = src->mdl_next; - if (src == NULL) - break; - sptr = MmGetMdlVirtualAddress(src); - scnt = MmGetMdlByteCount(src); - } - } - - *cpylen = copied; -} - -static void -NdisCopyFromPacketToPacketSafe(dpkt, doff, reqlen, spkt, soff, cpylen, prio) - ndis_packet *dpkt; - uint32_t doff; - uint32_t reqlen; - ndis_packet *spkt; - uint32_t soff; - uint32_t *cpylen; - uint32_t prio; -{ - NdisCopyFromPacketToPacket(dpkt, doff, reqlen, spkt, soff, cpylen); -} - -static void -NdisIMCopySendPerPacketInfo(dpkt, spkt) - ndis_packet *dpkt; - ndis_packet *spkt; -{ - memcpy(&dpkt->np_ext, &spkt->np_ext, sizeof(ndis_packet_extension)); -} - -static ndis_status -NdisMRegisterDevice(handle, devname, symname, majorfuncs, devobj, devhandle) - ndis_handle handle; - unicode_string *devname; - unicode_string *symname; - driver_dispatch *majorfuncs[]; - void **devobj; - ndis_handle *devhandle; -{ - uint32_t status; - device_object *dobj; - - status = IoCreateDevice(handle, 0, devname, - FILE_DEVICE_UNKNOWN, 0, FALSE, &dobj); - - if (status == STATUS_SUCCESS) { - *devobj = dobj; - *devhandle = dobj; - } - - return (status); -} - -static ndis_status -NdisMDeregisterDevice(handle) - ndis_handle handle; -{ - IoDeleteDevice(handle); - return (NDIS_STATUS_SUCCESS); -} - -static ndis_status -NdisMQueryAdapterInstanceName(name, handle) - unicode_string *name; - ndis_handle handle; -{ - ndis_miniport_block *block; - device_t dev; - ansi_string as; - - block = (ndis_miniport_block *)handle; - dev = block->nmb_physdeviceobj->do_devext; - - RtlInitAnsiString(&as, __DECONST(char *, device_get_nameunit(dev))); - if (RtlAnsiStringToUnicodeString(name, &as, TRUE)) - return (NDIS_STATUS_RESOURCES); - - return (NDIS_STATUS_SUCCESS); -} - -static void -NdisMRegisterUnloadHandler(handle, func) - ndis_handle handle; - void *func; -{ -} - -static void -dummy() -{ - printf("NDIS dummy called...\n"); -} - -/* - * Note: a couple of entries in this table specify the - * number of arguments as "foo + 1". These are routines - * that accept a 64-bit argument, passed by value. On - * x86, these arguments consume two longwords on the stack, - * so we lie and say there's one additional argument so - * that the wrapping routines will do the right thing. - */ - -image_patch_table ndis_functbl[] = { - IMPORT_SFUNC(NdisCopyFromPacketToPacket, 6), - IMPORT_SFUNC(NdisCopyFromPacketToPacketSafe, 7), - IMPORT_SFUNC(NdisIMCopySendPerPacketInfo, 2), - IMPORT_SFUNC(NdisScheduleWorkItem, 1), - IMPORT_SFUNC(NdisMIndicateStatusComplete, 1), - IMPORT_SFUNC(NdisMIndicateStatus, 4), - IMPORT_SFUNC(NdisSystemProcessorCount, 0), - IMPORT_SFUNC(NdisGetCurrentProcessorCounts, 3), - IMPORT_SFUNC(NdisUnchainBufferAtBack, 2), - IMPORT_SFUNC(NdisGetFirstBufferFromPacket, 5), - IMPORT_SFUNC(NdisGetFirstBufferFromPacketSafe, 6), - IMPORT_SFUNC(NdisGetBufferPhysicalArraySize, 2), - IMPORT_SFUNC(NdisMGetDeviceProperty, 6), - IMPORT_SFUNC(NdisInitAnsiString, 2), - IMPORT_SFUNC(NdisInitUnicodeString, 2), - IMPORT_SFUNC(NdisWriteConfiguration, 4), - IMPORT_SFUNC(NdisAnsiStringToUnicodeString, 2), - IMPORT_SFUNC(NdisTerminateWrapper, 2), - IMPORT_SFUNC(NdisOpenConfigurationKeyByName, 4), - IMPORT_SFUNC(NdisOpenConfigurationKeyByIndex, 5), - IMPORT_SFUNC(NdisMRemoveMiniport, 1), - IMPORT_SFUNC(NdisInitializeString, 2), - IMPORT_SFUNC(NdisFreeString, 1), - IMPORT_SFUNC(NdisGetCurrentSystemTime, 1), - IMPORT_SFUNC(NdisGetRoutineAddress, 1), - IMPORT_SFUNC(NdisGetSystemUpTime, 1), - IMPORT_SFUNC(NdisGetVersion, 0), - IMPORT_SFUNC(NdisMSynchronizeWithInterrupt, 3), - IMPORT_SFUNC(NdisMAllocateSharedMemoryAsync, 4), - IMPORT_SFUNC(NdisInterlockedInsertHeadList, 3), - IMPORT_SFUNC(NdisInterlockedInsertTailList, 3), - IMPORT_SFUNC(NdisInterlockedRemoveHeadList, 2), - IMPORT_SFUNC(NdisInitializeWrapper, 4), - IMPORT_SFUNC(NdisMRegisterMiniport, 3), - IMPORT_SFUNC(NdisAllocateMemoryWithTag, 3), - IMPORT_SFUNC(NdisAllocateMemory, 4 + 1), - IMPORT_SFUNC(NdisMSetAttributesEx, 5), - IMPORT_SFUNC(NdisCloseConfiguration, 1), - IMPORT_SFUNC(NdisReadConfiguration, 5), - IMPORT_SFUNC(NdisOpenConfiguration, 3), - IMPORT_SFUNC(NdisAcquireSpinLock, 1), - IMPORT_SFUNC(NdisReleaseSpinLock, 1), - IMPORT_SFUNC(NdisDprAcquireSpinLock, 1), - IMPORT_SFUNC(NdisDprReleaseSpinLock, 1), - IMPORT_SFUNC(NdisAllocateSpinLock, 1), - IMPORT_SFUNC(NdisInitializeReadWriteLock, 1), - IMPORT_SFUNC(NdisAcquireReadWriteLock, 3), - IMPORT_SFUNC(NdisReleaseReadWriteLock, 2), - IMPORT_SFUNC(NdisFreeSpinLock, 1), - IMPORT_SFUNC(NdisFreeMemory, 3), - IMPORT_SFUNC(NdisReadPciSlotInformation, 5), - IMPORT_SFUNC(NdisWritePciSlotInformation, 5), - IMPORT_SFUNC_MAP(NdisImmediateReadPciSlotInformation, - NdisReadPciSlotInformation, 5), - IMPORT_SFUNC_MAP(NdisImmediateWritePciSlotInformation, - NdisWritePciSlotInformation, 5), - IMPORT_CFUNC(NdisWriteErrorLogEntry, 0), - IMPORT_SFUNC(NdisMStartBufferPhysicalMapping, 6), - IMPORT_SFUNC(NdisMCompleteBufferPhysicalMapping, 3), - IMPORT_SFUNC(NdisMInitializeTimer, 4), - IMPORT_SFUNC(NdisInitializeTimer, 3), - IMPORT_SFUNC(NdisSetTimer, 2), - IMPORT_SFUNC(NdisMCancelTimer, 2), - IMPORT_SFUNC_MAP(NdisCancelTimer, NdisMCancelTimer, 2), - IMPORT_SFUNC(NdisMSetPeriodicTimer, 2), - IMPORT_SFUNC(NdisMQueryAdapterResources, 4), - IMPORT_SFUNC(NdisMRegisterIoPortRange, 4), - IMPORT_SFUNC(NdisMDeregisterIoPortRange, 4), - IMPORT_SFUNC(NdisReadNetworkAddress, 4), - IMPORT_SFUNC(NdisQueryMapRegisterCount, 2), - IMPORT_SFUNC(NdisMAllocateMapRegisters, 5), - IMPORT_SFUNC(NdisMFreeMapRegisters, 1), - IMPORT_SFUNC(NdisMAllocateSharedMemory, 5), - IMPORT_SFUNC(NdisMMapIoSpace, 4 + 1), - IMPORT_SFUNC(NdisMUnmapIoSpace, 3), - IMPORT_SFUNC(NdisGetCacheFillSize, 0), - IMPORT_SFUNC(NdisMGetDmaAlignment, 1), - IMPORT_SFUNC(NdisMInitializeScatterGatherDma, 3), - IMPORT_SFUNC(NdisAllocatePacketPool, 4), - IMPORT_SFUNC(NdisAllocatePacketPoolEx, 5), - IMPORT_SFUNC(NdisAllocatePacket, 3), - IMPORT_SFUNC(NdisFreePacket, 1), - IMPORT_SFUNC(NdisFreePacketPool, 1), - IMPORT_SFUNC_MAP(NdisDprAllocatePacket, NdisAllocatePacket, 3), - IMPORT_SFUNC_MAP(NdisDprFreePacket, NdisFreePacket, 1), - IMPORT_SFUNC(NdisAllocateBufferPool, 3), - IMPORT_SFUNC(NdisAllocateBuffer, 5), - IMPORT_SFUNC(NdisQueryBuffer, 3), - IMPORT_SFUNC(NdisQueryBufferSafe, 4), - IMPORT_SFUNC(NdisBufferVirtualAddress, 1), - IMPORT_SFUNC(NdisBufferVirtualAddressSafe, 2), - IMPORT_SFUNC(NdisBufferLength, 1), - IMPORT_SFUNC(NdisFreeBuffer, 1), - IMPORT_SFUNC(NdisFreeBufferPool, 1), - IMPORT_SFUNC(NdisInterlockedIncrement, 1), - IMPORT_SFUNC(NdisInterlockedDecrement, 1), - IMPORT_SFUNC(NdisInitializeEvent, 1), - IMPORT_SFUNC(NdisSetEvent, 1), - IMPORT_SFUNC(NdisResetEvent, 1), - IMPORT_SFUNC(NdisWaitEvent, 2), - IMPORT_SFUNC(NdisUnicodeStringToAnsiString, 2), - IMPORT_SFUNC(NdisMPciAssignResources, 3), - IMPORT_SFUNC(NdisMFreeSharedMemory, 5 + 1), - IMPORT_SFUNC(NdisMRegisterInterrupt, 7), - IMPORT_SFUNC(NdisMDeregisterInterrupt, 1), - IMPORT_SFUNC(NdisMRegisterAdapterShutdownHandler, 3), - IMPORT_SFUNC(NdisMDeregisterAdapterShutdownHandler, 1), - IMPORT_SFUNC(NDIS_BUFFER_TO_SPAN_PAGES, 1), - IMPORT_SFUNC(NdisQueryBufferOffset, 3), - IMPORT_SFUNC(NdisAdjustBufferLength, 2), - IMPORT_SFUNC(NdisPacketPoolUsage, 1), - IMPORT_SFUNC(NdisMSleep, 1), - IMPORT_SFUNC(NdisUnchainBufferAtFront, 2), - IMPORT_SFUNC(NdisReadPcmciaAttributeMemory, 4), - IMPORT_SFUNC(NdisWritePcmciaAttributeMemory, 4), - IMPORT_SFUNC(NdisOpenFile, 5 + 1), - IMPORT_SFUNC(NdisMapFile, 3), - IMPORT_SFUNC(NdisUnmapFile, 1), - IMPORT_SFUNC(NdisCloseFile, 1), - IMPORT_SFUNC(NdisMRegisterDevice, 6), - IMPORT_SFUNC(NdisMDeregisterDevice, 1), - IMPORT_SFUNC(NdisMQueryAdapterInstanceName, 2), - IMPORT_SFUNC(NdisMRegisterUnloadHandler, 2), - IMPORT_SFUNC(ndis_timercall, 4), - IMPORT_SFUNC(ndis_asyncmem_complete, 2), - IMPORT_SFUNC(ndis_intr, 2), - IMPORT_SFUNC(ndis_intrhand, 4), - - /* - * This last entry is a catch-all for any function we haven't - * implemented yet. The PE import list patching routine will - * use it for any function that doesn't have an explicit match - * in this table. - */ - - { NULL, (FUNC)dummy, NULL, 0, WINDRV_WRAP_STDCALL }, - - /* End of list. */ - { NULL, NULL, NULL } -}; diff --git a/sys/compat/ndis/subr_ntoskrnl.c b/sys/compat/ndis/subr_ntoskrnl.c deleted file mode 100644 index f8b3d3a41732..000000000000 --- a/sys/compat/ndis/subr_ntoskrnl.c +++ /dev/null @@ -1,4446 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul . 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifdef NTOSKRNL_DEBUG_TIMERS -static int sysctl_show_timers(SYSCTL_HANDLER_ARGS); - -SYSCTL_PROC(_debug, OID_AUTO, ntoskrnl_timers, - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, NULL, 0, - sysctl_show_timers, "I", - "Show ntoskrnl timer stats"); -#endif - -struct kdpc_queue { - list_entry kq_disp; - struct thread *kq_td; - int kq_cpu; - int kq_exit; - int kq_running; - kspin_lock kq_lock; - nt_kevent kq_proc; - nt_kevent kq_done; -}; - -typedef struct kdpc_queue kdpc_queue; - -struct wb_ext { - struct cv we_cv; - struct thread *we_td; -}; - -typedef struct wb_ext wb_ext; - -#define NTOSKRNL_TIMEOUTS 256 -#ifdef NTOSKRNL_DEBUG_TIMERS -static uint64_t ntoskrnl_timer_fires; -static uint64_t ntoskrnl_timer_sets; -static uint64_t ntoskrnl_timer_reloads; -static uint64_t ntoskrnl_timer_cancels; -#endif - -struct callout_entry { - struct callout ce_callout; - list_entry ce_list; -}; - -typedef struct callout_entry callout_entry; - -static struct list_entry ntoskrnl_calllist; -static struct mtx ntoskrnl_calllock; -struct kuser_shared_data kuser_shared_data; - -static struct list_entry ntoskrnl_intlist; -static kspin_lock ntoskrnl_intlock; - -static uint8_t RtlEqualUnicodeString(unicode_string *, - unicode_string *, uint8_t); -static void RtlCopyString(ansi_string *, const ansi_string *); -static void RtlCopyUnicodeString(unicode_string *, - unicode_string *); -static irp *IoBuildSynchronousFsdRequest(uint32_t, device_object *, - void *, uint32_t, uint64_t *, nt_kevent *, io_status_block *); -static irp *IoBuildAsynchronousFsdRequest(uint32_t, - device_object *, void *, uint32_t, uint64_t *, io_status_block *); -static irp *IoBuildDeviceIoControlRequest(uint32_t, - device_object *, void *, uint32_t, void *, uint32_t, - uint8_t, nt_kevent *, io_status_block *); -static irp *IoAllocateIrp(uint8_t, uint8_t); -static void IoReuseIrp(irp *, uint32_t); -static void IoFreeIrp(irp *); -static void IoInitializeIrp(irp *, uint16_t, uint8_t); -static irp *IoMakeAssociatedIrp(irp *, uint8_t); -static uint32_t KeWaitForMultipleObjects(uint32_t, - nt_dispatch_header **, uint32_t, uint32_t, uint32_t, uint8_t, - int64_t *, wait_block *); -static void ntoskrnl_waittest(nt_dispatch_header *, uint32_t); -static void ntoskrnl_satisfy_wait(nt_dispatch_header *, struct thread *); -static void ntoskrnl_satisfy_multiple_waits(wait_block *); -static int ntoskrnl_is_signalled(nt_dispatch_header *, struct thread *); -static void ntoskrnl_insert_timer(ktimer *, int); -static void ntoskrnl_remove_timer(ktimer *); -#ifdef NTOSKRNL_DEBUG_TIMERS -static void ntoskrnl_show_timers(void); -#endif -static void ntoskrnl_timercall(void *); -static void ntoskrnl_dpc_thread(void *); -static void ntoskrnl_destroy_dpc_threads(void); -static void ntoskrnl_destroy_workitem_threads(void); -static void ntoskrnl_workitem_thread(void *); -static void ntoskrnl_workitem(device_object *, void *); -static void ntoskrnl_unicode_to_ascii(uint16_t *, char *, int); -static void ntoskrnl_ascii_to_unicode(char *, uint16_t *, int); -static uint8_t ntoskrnl_insert_dpc(list_entry *, kdpc *); -static void WRITE_REGISTER_USHORT(uint16_t *, uint16_t); -static uint16_t READ_REGISTER_USHORT(uint16_t *); -static void WRITE_REGISTER_ULONG(uint32_t *, uint32_t); -static uint32_t READ_REGISTER_ULONG(uint32_t *); -static void WRITE_REGISTER_UCHAR(uint8_t *, uint8_t); -static uint8_t READ_REGISTER_UCHAR(uint8_t *); -static int64_t _allmul(int64_t, int64_t); -static int64_t _alldiv(int64_t, int64_t); -static int64_t _allrem(int64_t, int64_t); -static int64_t _allshr(int64_t, uint8_t); -static int64_t _allshl(int64_t, uint8_t); -static uint64_t _aullmul(uint64_t, uint64_t); -static uint64_t _aulldiv(uint64_t, uint64_t); -static uint64_t _aullrem(uint64_t, uint64_t); -static uint64_t _aullshr(uint64_t, uint8_t); -static uint64_t _aullshl(uint64_t, uint8_t); -static slist_entry *ntoskrnl_pushsl(slist_header *, slist_entry *); -static void InitializeSListHead(slist_header *); -static slist_entry *ntoskrnl_popsl(slist_header *); -static void ExFreePoolWithTag(void *, uint32_t); -static void ExInitializePagedLookasideList(paged_lookaside_list *, - lookaside_alloc_func *, lookaside_free_func *, - uint32_t, size_t, uint32_t, uint16_t); -static void ExDeletePagedLookasideList(paged_lookaside_list *); -static void ExInitializeNPagedLookasideList(npaged_lookaside_list *, - lookaside_alloc_func *, lookaside_free_func *, - uint32_t, size_t, uint32_t, uint16_t); -static void ExDeleteNPagedLookasideList(npaged_lookaside_list *); -static slist_entry - *ExInterlockedPushEntrySList(slist_header *, - slist_entry *, kspin_lock *); -static slist_entry - *ExInterlockedPopEntrySList(slist_header *, kspin_lock *); -static uint32_t InterlockedIncrement(volatile uint32_t *); -static uint32_t InterlockedDecrement(volatile uint32_t *); -static void ExInterlockedAddLargeStatistic(uint64_t *, uint32_t); -static void *MmAllocateContiguousMemory(uint32_t, uint64_t); -static void *MmAllocateContiguousMemorySpecifyCache(uint32_t, - uint64_t, uint64_t, uint64_t, enum nt_caching_type); -static void MmFreeContiguousMemory(void *); -static void MmFreeContiguousMemorySpecifyCache(void *, uint32_t, - enum nt_caching_type); -static uint32_t MmSizeOfMdl(void *, size_t); -static void *MmMapLockedPages(mdl *, uint8_t); -static void *MmMapLockedPagesSpecifyCache(mdl *, - uint8_t, uint32_t, void *, uint32_t, uint32_t); -static void MmUnmapLockedPages(void *, mdl *); -static device_t ntoskrnl_finddev(device_t, uint64_t, struct resource **); -static void RtlZeroMemory(void *, size_t); -static void RtlSecureZeroMemory(void *, size_t); -static void RtlFillMemory(void *, size_t, uint8_t); -static void RtlMoveMemory(void *, const void *, size_t); -static ndis_status RtlCharToInteger(const char *, uint32_t, uint32_t *); -static void RtlCopyMemory(void *, const void *, size_t); -static size_t RtlCompareMemory(const void *, const void *, size_t); -static ndis_status RtlUnicodeStringToInteger(unicode_string *, - uint32_t, uint32_t *); -static int atoi (const char *); -static long atol (const char *); -static int rand(void); -static void srand(unsigned int); -static void KeQuerySystemTime(uint64_t *); -static uint32_t KeTickCount(void); -static uint8_t IoIsWdmVersionAvailable(uint8_t, uint8_t); -static int32_t IoOpenDeviceRegistryKey(struct device_object *, uint32_t, - uint32_t, void **); -static void ntoskrnl_thrfunc(void *); -static ndis_status PsCreateSystemThread(ndis_handle *, - uint32_t, void *, ndis_handle, void *, void *, void *); -static ndis_status PsTerminateSystemThread(ndis_status); -static ndis_status IoGetDeviceObjectPointer(unicode_string *, - uint32_t, void *, device_object *); -static ndis_status IoGetDeviceProperty(device_object *, uint32_t, - uint32_t, void *, uint32_t *); -static void KeInitializeMutex(kmutant *, uint32_t); -static uint32_t KeReleaseMutex(kmutant *, uint8_t); -static uint32_t KeReadStateMutex(kmutant *); -static ndis_status ObReferenceObjectByHandle(ndis_handle, - uint32_t, void *, uint8_t, void **, void **); -static void ObfDereferenceObject(void *); -static uint32_t ZwClose(ndis_handle); -static uint32_t WmiQueryTraceInformation(uint32_t, void *, uint32_t, - uint32_t, void *); -static uint32_t WmiTraceMessage(uint64_t, uint32_t, void *, uint16_t, ...); -static uint32_t IoWMIRegistrationControl(device_object *, uint32_t); -static void *ntoskrnl_memset(void *, int, size_t); -static void *ntoskrnl_memmove(void *, void *, size_t); -static void *ntoskrnl_memchr(void *, unsigned char, size_t); -static char *ntoskrnl_strstr(char *, char *); -static char *ntoskrnl_strncat(char *, char *, size_t); -static int ntoskrnl_toupper(int); -static int ntoskrnl_tolower(int); -static funcptr ntoskrnl_findwrap(funcptr); -static uint32_t DbgPrint(char *, ...); -static void DbgBreakPoint(void); -static void KeBugCheckEx(uint32_t, u_long, u_long, u_long, u_long); -static int32_t KeDelayExecutionThread(uint8_t, uint8_t, int64_t *); -static int32_t KeSetPriorityThread(struct thread *, int32_t); -static void dummy(void); - -static struct mtx ntoskrnl_dispatchlock; -static struct mtx ntoskrnl_interlock; -static kspin_lock ntoskrnl_cancellock; -static int ntoskrnl_kth = 0; -static struct nt_objref_head ntoskrnl_reflist; -static uma_zone_t mdl_zone; -static uma_zone_t iw_zone; -static struct kdpc_queue *kq_queues; -static struct kdpc_queue *wq_queues; -static int wq_idx = 0; - -int -ntoskrnl_libinit() -{ - image_patch_table *patch; - int error; - struct proc *p; - kdpc_queue *kq; - callout_entry *e; - int i; - - mtx_init(&ntoskrnl_dispatchlock, - "ntoskrnl dispatch lock", MTX_NDIS_LOCK, MTX_DEF|MTX_RECURSE); - mtx_init(&ntoskrnl_interlock, MTX_NTOSKRNL_SPIN_LOCK, NULL, MTX_SPIN); - KeInitializeSpinLock(&ntoskrnl_cancellock); - KeInitializeSpinLock(&ntoskrnl_intlock); - TAILQ_INIT(&ntoskrnl_reflist); - - InitializeListHead(&ntoskrnl_calllist); - InitializeListHead(&ntoskrnl_intlist); - mtx_init(&ntoskrnl_calllock, MTX_NTOSKRNL_SPIN_LOCK, NULL, MTX_SPIN); - - kq_queues = ExAllocatePoolWithTag(NonPagedPool, -#ifdef NTOSKRNL_MULTIPLE_DPCS - sizeof(kdpc_queue) * mp_ncpus, 0); -#else - sizeof(kdpc_queue), 0); -#endif - - if (kq_queues == NULL) - return (ENOMEM); - - wq_queues = ExAllocatePoolWithTag(NonPagedPool, - sizeof(kdpc_queue) * WORKITEM_THREADS, 0); - - if (wq_queues == NULL) - return (ENOMEM); - -#ifdef NTOSKRNL_MULTIPLE_DPCS - bzero((char *)kq_queues, sizeof(kdpc_queue) * mp_ncpus); -#else - bzero((char *)kq_queues, sizeof(kdpc_queue)); -#endif - bzero((char *)wq_queues, sizeof(kdpc_queue) * WORKITEM_THREADS); - - /* - * Launch the DPC threads. - */ - -#ifdef NTOSKRNL_MULTIPLE_DPCS - for (i = 0; i < mp_ncpus; i++) { -#else - for (i = 0; i < 1; i++) { -#endif - kq = kq_queues + i; - kq->kq_cpu = i; - error = kproc_create(ntoskrnl_dpc_thread, kq, &p, - RFHIGHPID, NDIS_KSTACK_PAGES, "Windows DPC %d", i); - if (error) - panic("failed to launch DPC thread"); - } - - /* - * Launch the workitem threads. - */ - - for (i = 0; i < WORKITEM_THREADS; i++) { - kq = wq_queues + i; - error = kproc_create(ntoskrnl_workitem_thread, kq, &p, - RFHIGHPID, NDIS_KSTACK_PAGES, "Windows Workitem %d", i); - if (error) - panic("failed to launch workitem thread"); - } - - patch = ntoskrnl_functbl; - while (patch->ipt_func != NULL) { - windrv_wrap((funcptr)patch->ipt_func, - (funcptr *)&patch->ipt_wrap, - patch->ipt_argcnt, patch->ipt_ftype); - patch++; - } - - for (i = 0; i < NTOSKRNL_TIMEOUTS; i++) { - e = ExAllocatePoolWithTag(NonPagedPool, - sizeof(callout_entry), 0); - if (e == NULL) - panic("failed to allocate timeouts"); - mtx_lock_spin(&ntoskrnl_calllock); - InsertHeadList((&ntoskrnl_calllist), (&e->ce_list)); - mtx_unlock_spin(&ntoskrnl_calllock); - } - - /* - * MDLs are supposed to be variable size (they describe - * buffers containing some number of pages, but we don't - * know ahead of time how many pages that will be). But - * always allocating them off the heap is very slow. As - * a compromise, we create an MDL UMA zone big enough to - * handle any buffer requiring up to 16 pages, and we - * use those for any MDLs for buffers of 16 pages or less - * in size. For buffers larger than that (which we assume - * will be few and far between, we allocate the MDLs off - * the heap. - */ - - mdl_zone = uma_zcreate("Windows MDL", MDL_ZONE_SIZE, - NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); - - iw_zone = uma_zcreate("Windows WorkItem", sizeof(io_workitem), - NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); - - return (0); -} - -int -ntoskrnl_libfini() -{ - image_patch_table *patch; - callout_entry *e; - list_entry *l; - - patch = ntoskrnl_functbl; - while (patch->ipt_func != NULL) { - windrv_unwrap(patch->ipt_wrap); - patch++; - } - - /* Stop the workitem queues. */ - ntoskrnl_destroy_workitem_threads(); - /* Stop the DPC queues. */ - ntoskrnl_destroy_dpc_threads(); - - ExFreePool(kq_queues); - ExFreePool(wq_queues); - - uma_zdestroy(mdl_zone); - uma_zdestroy(iw_zone); - - mtx_lock_spin(&ntoskrnl_calllock); - while(!IsListEmpty(&ntoskrnl_calllist)) { - l = RemoveHeadList(&ntoskrnl_calllist); - e = CONTAINING_RECORD(l, callout_entry, ce_list); - mtx_unlock_spin(&ntoskrnl_calllock); - ExFreePool(e); - mtx_lock_spin(&ntoskrnl_calllock); - } - mtx_unlock_spin(&ntoskrnl_calllock); - - mtx_destroy(&ntoskrnl_dispatchlock); - mtx_destroy(&ntoskrnl_interlock); - mtx_destroy(&ntoskrnl_calllock); - - return (0); -} - -/* - * We need to be able to reference this externally from the wrapper; - * GCC only generates a local implementation of memset. - */ -static void * -ntoskrnl_memset(buf, ch, size) - void *buf; - int ch; - size_t size; -{ - return (memset(buf, ch, size)); -} - -static void * -ntoskrnl_memmove(dst, src, size) - void *src; - void *dst; - size_t size; -{ - bcopy(src, dst, size); - return (dst); -} - -static void * -ntoskrnl_memchr(void *buf, unsigned char ch, size_t len) -{ - if (len != 0) { - unsigned char *p = buf; - - do { - if (*p++ == ch) - return (p - 1); - } while (--len != 0); - } - return (NULL); -} - -static char * -ntoskrnl_strstr(s, find) - char *s, *find; -{ - char c, sc; - size_t len; - - if ((c = *find++) != 0) { - len = strlen(find); - do { - do { - if ((sc = *s++) == 0) - return (NULL); - } while (sc != c); - } while (strncmp(s, find, len) != 0); - s--; - } - return ((char *)s); -} - -/* Taken from libc */ -static char * -ntoskrnl_strncat(dst, src, n) - char *dst; - char *src; - size_t n; -{ - if (n != 0) { - char *d = dst; - const char *s = src; - - while (*d != 0) - d++; - do { - if ((*d = *s++) == 0) - break; - d++; - } while (--n != 0); - *d = 0; - } - return (dst); -} - -static int -ntoskrnl_toupper(c) - int c; -{ - return (toupper(c)); -} - -static int -ntoskrnl_tolower(c) - int c; -{ - return (tolower(c)); -} - -static uint8_t -RtlEqualUnicodeString(unicode_string *str1, unicode_string *str2, - uint8_t caseinsensitive) -{ - int i; - - if (str1->us_len != str2->us_len) - return (FALSE); - - for (i = 0; i < str1->us_len; i++) { - if (caseinsensitive == TRUE) { - if (toupper((char)(str1->us_buf[i] & 0xFF)) != - toupper((char)(str2->us_buf[i] & 0xFF))) - return (FALSE); - } else { - if (str1->us_buf[i] != str2->us_buf[i]) - return (FALSE); - } - } - - return (TRUE); -} - -static void -RtlCopyString(dst, src) - ansi_string *dst; - const ansi_string *src; -{ - if (src != NULL && src->as_buf != NULL && dst->as_buf != NULL) { - dst->as_len = min(src->as_len, dst->as_maxlen); - memcpy(dst->as_buf, src->as_buf, dst->as_len); - if (dst->as_len < dst->as_maxlen) - dst->as_buf[dst->as_len] = 0; - } else - dst->as_len = 0; -} - -static void -RtlCopyUnicodeString(dest, src) - unicode_string *dest; - unicode_string *src; -{ - - if (dest->us_maxlen >= src->us_len) - dest->us_len = src->us_len; - else - dest->us_len = dest->us_maxlen; - memcpy(dest->us_buf, src->us_buf, dest->us_len); -} - -static void -ntoskrnl_ascii_to_unicode(ascii, unicode, len) - char *ascii; - uint16_t *unicode; - int len; -{ - int i; - uint16_t *ustr; - - ustr = unicode; - for (i = 0; i < len; i++) { - *ustr = (uint16_t)ascii[i]; - ustr++; - } -} - -static void -ntoskrnl_unicode_to_ascii(unicode, ascii, len) - uint16_t *unicode; - char *ascii; - int len; -{ - int i; - uint8_t *astr; - - astr = ascii; - for (i = 0; i < len / 2; i++) { - *astr = (uint8_t)unicode[i]; - astr++; - } -} - -uint32_t -RtlUnicodeStringToAnsiString(ansi_string *dest, unicode_string *src, uint8_t allocate) -{ - if (dest == NULL || src == NULL) - return (STATUS_INVALID_PARAMETER); - - dest->as_len = src->us_len / 2; - if (dest->as_maxlen < dest->as_len) - dest->as_len = dest->as_maxlen; - - if (allocate == TRUE) { - dest->as_buf = ExAllocatePoolWithTag(NonPagedPool, - (src->us_len / 2) + 1, 0); - if (dest->as_buf == NULL) - return (STATUS_INSUFFICIENT_RESOURCES); - dest->as_len = dest->as_maxlen = src->us_len / 2; - } else { - dest->as_len = src->us_len / 2; /* XXX */ - if (dest->as_maxlen < dest->as_len) - dest->as_len = dest->as_maxlen; - } - - ntoskrnl_unicode_to_ascii(src->us_buf, dest->as_buf, - dest->as_len * 2); - - return (STATUS_SUCCESS); -} - -uint32_t -RtlAnsiStringToUnicodeString(unicode_string *dest, ansi_string *src, - uint8_t allocate) -{ - if (dest == NULL || src == NULL) - return (STATUS_INVALID_PARAMETER); - - if (allocate == TRUE) { - dest->us_buf = ExAllocatePoolWithTag(NonPagedPool, - src->as_len * 2, 0); - if (dest->us_buf == NULL) - return (STATUS_INSUFFICIENT_RESOURCES); - dest->us_len = dest->us_maxlen = strlen(src->as_buf) * 2; - } else { - dest->us_len = src->as_len * 2; /* XXX */ - if (dest->us_maxlen < dest->us_len) - dest->us_len = dest->us_maxlen; - } - - ntoskrnl_ascii_to_unicode(src->as_buf, dest->us_buf, - dest->us_len / 2); - - return (STATUS_SUCCESS); -} - -void * -ExAllocatePoolWithTag(pooltype, len, tag) - uint32_t pooltype; - size_t len; - uint32_t tag; -{ - void *buf; - - buf = malloc(len, M_DEVBUF, M_NOWAIT|M_ZERO); - if (buf == NULL) - return (NULL); - - return (buf); -} - -static void -ExFreePoolWithTag(buf, tag) - void *buf; - uint32_t tag; -{ - ExFreePool(buf); -} - -void -ExFreePool(buf) - void *buf; -{ - free(buf, M_DEVBUF); -} - -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; - InsertTailList((&drv->dro_driverext->dre_usrext), (&ce->ce_list)); - - *ext = (void *)(ce + 1); - - return (STATUS_SUCCESS); -} - -void * -IoGetDriverObjectExtension(drv, clid) - driver_object *drv; - void *clid; -{ - list_entry *e; - custom_extension *ce; - - /* - * Sanity check. Our dummy bus drivers don't have - * any driver extensions. - */ - - if (drv->dro_driverext == NULL) - return (NULL); - - 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); -} - -uint32_t -IoCreateDevice(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); - } - - bzero(dev->do_devext, devextlen); - } 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); -} - -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); -} - -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); -} - -static irp * -IoBuildSynchronousFsdRequest(func, dobj, buf, len, off, event, status) - uint32_t func; - device_object *dobj; - void *buf; - uint32_t len; - uint64_t *off; - nt_kevent *event; - io_status_block *status; -{ - irp *ip; - - ip = IoBuildAsynchronousFsdRequest(func, dobj, buf, len, off, status); - if (ip == NULL) - return (NULL); - ip->irp_usrevent = event; - - return (ip); -} - -static irp * -IoBuildAsynchronousFsdRequest(func, dobj, buf, len, off, status) - uint32_t func; - device_object *dobj; - void *buf; - uint32_t len; - uint64_t *off; - io_status_block *status; -{ - irp *ip; - io_stack_location *sl; - - ip = IoAllocateIrp(dobj->do_stacksize, TRUE); - if (ip == NULL) - return (NULL); - - ip->irp_usriostat = status; - ip->irp_tail.irp_overlay.irp_thread = NULL; - - sl = IoGetNextIrpStackLocation(ip); - sl->isl_major = func; - sl->isl_minor = 0; - sl->isl_flags = 0; - sl->isl_ctl = 0; - sl->isl_devobj = dobj; - sl->isl_fileobj = NULL; - sl->isl_completionfunc = NULL; - - ip->irp_userbuf = buf; - - if (dobj->do_flags & DO_BUFFERED_IO) { - ip->irp_assoc.irp_sysbuf = - ExAllocatePoolWithTag(NonPagedPool, len, 0); - if (ip->irp_assoc.irp_sysbuf == NULL) { - IoFreeIrp(ip); - return (NULL); - } - bcopy(buf, ip->irp_assoc.irp_sysbuf, len); - } - - if (dobj->do_flags & DO_DIRECT_IO) { - ip->irp_mdl = IoAllocateMdl(buf, len, FALSE, FALSE, ip); - if (ip->irp_mdl == NULL) { - if (ip->irp_assoc.irp_sysbuf != NULL) - ExFreePool(ip->irp_assoc.irp_sysbuf); - IoFreeIrp(ip); - return (NULL); - } - ip->irp_userbuf = NULL; - ip->irp_assoc.irp_sysbuf = NULL; - } - - if (func == IRP_MJ_READ) { - sl->isl_parameters.isl_read.isl_len = len; - if (off != NULL) - sl->isl_parameters.isl_read.isl_byteoff = *off; - else - sl->isl_parameters.isl_read.isl_byteoff = 0; - } - - if (func == IRP_MJ_WRITE) { - sl->isl_parameters.isl_write.isl_len = len; - if (off != NULL) - sl->isl_parameters.isl_write.isl_byteoff = *off; - else - sl->isl_parameters.isl_write.isl_byteoff = 0; - } - - return (ip); -} - -static irp * -IoBuildDeviceIoControlRequest(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) -{ - irp *ip; - io_stack_location *sl; - uint32_t buflen; - - ip = IoAllocateIrp(dobj->do_stacksize, TRUE); - if (ip == NULL) - return (NULL); - ip->irp_usrevent = event; - ip->irp_usriostat = status; - ip->irp_tail.irp_overlay.irp_thread = NULL; - - sl = IoGetNextIrpStackLocation(ip); - sl->isl_major = isinternal == TRUE ? - IRP_MJ_INTERNAL_DEVICE_CONTROL : IRP_MJ_DEVICE_CONTROL; - sl->isl_minor = 0; - sl->isl_flags = 0; - sl->isl_ctl = 0; - sl->isl_devobj = dobj; - sl->isl_fileobj = NULL; - sl->isl_completionfunc = NULL; - sl->isl_parameters.isl_ioctl.isl_iocode = iocode; - sl->isl_parameters.isl_ioctl.isl_ibuflen = ilen; - sl->isl_parameters.isl_ioctl.isl_obuflen = olen; - - switch(IO_METHOD(iocode)) { - case METHOD_BUFFERED: - if (ilen > olen) - buflen = ilen; - else - buflen = olen; - if (buflen) { - ip->irp_assoc.irp_sysbuf = - ExAllocatePoolWithTag(NonPagedPool, buflen, 0); - if (ip->irp_assoc.irp_sysbuf == NULL) { - IoFreeIrp(ip); - return (NULL); - } - } - if (ilen && ibuf != NULL) { - bcopy(ibuf, ip->irp_assoc.irp_sysbuf, ilen); - bzero((char *)ip->irp_assoc.irp_sysbuf + ilen, - buflen - ilen); - } else - bzero(ip->irp_assoc.irp_sysbuf, ilen); - ip->irp_userbuf = obuf; - break; - case METHOD_IN_DIRECT: - case METHOD_OUT_DIRECT: - if (ilen && ibuf != NULL) { - ip->irp_assoc.irp_sysbuf = - ExAllocatePoolWithTag(NonPagedPool, ilen, 0); - if (ip->irp_assoc.irp_sysbuf == NULL) { - IoFreeIrp(ip); - return (NULL); - } - bcopy(ibuf, ip->irp_assoc.irp_sysbuf, ilen); - } - if (olen && obuf != NULL) { - ip->irp_mdl = IoAllocateMdl(obuf, olen, - FALSE, FALSE, ip); - /* - * Normally we would MmProbeAndLockPages() - * here, but we don't have to in our - * imlementation. - */ - } - break; - case METHOD_NEITHER: - ip->irp_userbuf = obuf; - sl->isl_parameters.isl_ioctl.isl_type3ibuf = ibuf; - break; - default: - break; - } - - /* - * Ideally, we should associate this IRP with the calling - * thread here. - */ - - return (ip); -} - -static irp * -IoAllocateIrp(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 (i); -} - -static irp * -IoMakeAssociatedIrp(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); -} - -static void -IoFreeIrp(ip) - irp *ip; -{ - ExFreePool(ip); -} - -static void -IoInitializeIrp(irp *io, uint16_t psize, uint8_t ssize) -{ - bzero((char *)io, IoSizeOfIrp(ssize)); - io->irp_size = psize; - io->irp_stackcnt = ssize; - io->irp_currentstackloc = ssize; - InitializeListHead(&io->irp_thlist); - io->irp_tail.irp_overlay.irp_csl = - (io_stack_location *)(io + 1) + ssize; -} - -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; -} - -void -IoAcquireCancelSpinLock(uint8_t *irql) -{ - KeAcquireSpinLock(&ntoskrnl_cancellock, irql); -} - -void -IoReleaseCancelSpinLock(uint8_t irql) -{ - KeReleaseSpinLock(&ntoskrnl_cancellock, irql); -} - -uint8_t -IoCancelIrp(irp *ip) -{ - cancel_func cfunc; - uint8_t cancelirql; - - IoAcquireCancelSpinLock(&cancelirql); - cfunc = IoSetCancelRoutine(ip, NULL); - ip->irp_cancel = TRUE; - if (cfunc == NULL) { - IoReleaseCancelSpinLock(cancelirql); - return (FALSE); - } - ip->irp_cancelirql = cancelirql; - MSCALL2(cfunc, IoGetCurrentIrpStackLocation(ip)->isl_devobj, ip); - return (uint8_t)IoSetCancelValue(ip, TRUE); -} - -uint32_t -IofCallDriver(dobj, ip) - device_object *dobj; - irp *ip; -{ - 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 = MSCALL2(disp, dobj, ip); - - return (status); -} - -void -IofCompleteRequest(irp *ip, uint8_t prioboost) -{ - uint32_t status; - device_object *dobj; - io_stack_location *sl; - completion_func cf; - - KASSERT(ip->irp_iostat.isb_status != STATUS_PENDING, - ("incorrect IRP(%p) status (STATUS_PENDING)", ip)); - - sl = IoGetCurrentIrpStackLocation(ip); - IoSkipCurrentIrpStackLocation(ip); - - do { - if (sl->isl_ctl & SL_PENDING_RETURNED) - ip->irp_pendingreturned = TRUE; - - if (ip->irp_currentstackloc != (ip->irp_stackcnt + 1)) - dobj = IoGetCurrentIrpStackLocation(ip)->isl_devobj; - else - dobj = NULL; - - if (sl->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 = MSCALL3(cf, dobj, ip, sl->isl_completionctx); - if (status == STATUS_MORE_PROCESSING_REQUIRED) - return; - } else { - if ((ip->irp_currentstackloc <= ip->irp_stackcnt) && - (ip->irp_pendingreturned == TRUE)) - IoMarkIrpPending(ip); - } - - /* move to the next. */ - IoSkipCurrentIrpStackLocation(ip); - sl++; - } while (ip->irp_currentstackloc <= (ip->irp_stackcnt + 1)); - - if (ip->irp_usriostat != NULL) - *ip->irp_usriostat = ip->irp_iostat; - if (ip->irp_usrevent != NULL) - KeSetEvent(ip->irp_usrevent, prioboost, FALSE); - - /* 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 = - 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) { - if (ip->irp_mdl != NULL) - IoFreeMdl(ip->irp_mdl); - IoFreeIrp(ip); - } -} - -void -ntoskrnl_intr(arg) - void *arg; -{ - kinterrupt *iobj; - uint8_t irql; - uint8_t claimed; - list_entry *l; - - KeAcquireSpinLock(&ntoskrnl_intlock, &irql); - l = ntoskrnl_intlist.nle_flink; - while (l != &ntoskrnl_intlist) { - iobj = CONTAINING_RECORD(l, kinterrupt, ki_list); - claimed = MSCALL2(iobj->ki_svcfunc, iobj, iobj->ki_svcctx); - if (claimed == TRUE) - break; - l = l->nle_flink; - } - KeReleaseSpinLock(&ntoskrnl_intlock, irql); -} - -uint8_t -KeAcquireInterruptSpinLock(iobj) - kinterrupt *iobj; -{ - uint8_t irql; - KeAcquireSpinLock(&ntoskrnl_intlock, &irql); - return (irql); -} - -void -KeReleaseInterruptSpinLock(kinterrupt *iobj, uint8_t irql) -{ - KeReleaseSpinLock(&ntoskrnl_intlock, irql); -} - -uint8_t -KeSynchronizeExecution(iobj, syncfunc, syncctx) - kinterrupt *iobj; - void *syncfunc; - void *syncctx; -{ - uint8_t irql; - - KeAcquireSpinLock(&ntoskrnl_intlock, &irql); - MSCALL1(syncfunc, syncctx); - KeReleaseSpinLock(&ntoskrnl_intlock, irql); - - return (TRUE); -} - -/* - * IoConnectInterrupt() is passed only the interrupt vector and - * irql that a device wants to use, but no device-specific tag - * of any kind. This conflicts rather badly with FreeBSD's - * bus_setup_intr(), which needs the device_t for the device - * requesting interrupt delivery. In order to bypass this - * inconsistency, we implement a second level of interrupt - * dispatching on top of bus_setup_intr(). All devices use - * ntoskrnl_intr() as their ISR, and any device requesting - * interrupts will be registered with ntoskrnl_intr()'s interrupt - * dispatch list. When an interrupt arrives, we walk the list - * and invoke all the registered ISRs. This effectively makes all - * interrupts shared, but it's the only way to duplicate the - * semantics of IoConnectInterrupt() and IoDisconnectInterrupt() properly. - */ - -uint32_t -IoConnectInterrupt(kinterrupt **iobj, void *svcfunc, void *svcctx, - kspin_lock *lock, uint32_t vector, uint8_t irql, uint8_t syncirql, - uint8_t imode, uint8_t shared, uint32_t affinity, uint8_t savefloat) -{ - uint8_t curirql; - - *iobj = ExAllocatePoolWithTag(NonPagedPool, sizeof(kinterrupt), 0); - if (*iobj == NULL) - return (STATUS_INSUFFICIENT_RESOURCES); - - (*iobj)->ki_svcfunc = svcfunc; - (*iobj)->ki_svcctx = svcctx; - - if (lock == NULL) { - KeInitializeSpinLock(&(*iobj)->ki_lock_priv); - (*iobj)->ki_lock = &(*iobj)->ki_lock_priv; - } else - (*iobj)->ki_lock = lock; - - KeAcquireSpinLock(&ntoskrnl_intlock, &curirql); - InsertHeadList((&ntoskrnl_intlist), (&(*iobj)->ki_list)); - KeReleaseSpinLock(&ntoskrnl_intlock, curirql); - - return (STATUS_SUCCESS); -} - -void -IoDisconnectInterrupt(iobj) - kinterrupt *iobj; -{ - uint8_t irql; - - if (iobj == NULL) - return; - - KeAcquireSpinLock(&ntoskrnl_intlock, &irql); - RemoveEntryList((&iobj->ki_list)); - KeReleaseSpinLock(&ntoskrnl_intlock, irql); - - ExFreePool(iobj); -} - -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); -} - -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 takm_il objects. */ - - tail = topdev->do_attacheddev; - while (tail != NULL) { - tail->do_stacksize--; - tail = tail->do_attacheddev; - } - - mtx_unlock(&ntoskrnl_dispatchlock); -} - -/* - * For the most part, an object is considered signalled if - * dh_sigstate == TRUE. The exception is for mutant objects - * (mutexes), where the logic works like this: - * - * - If the thread already owns the object and sigstate is - * less than or equal to 0, then the object is considered - * signalled (recursive acquisition). - * - If dh_sigstate == 1, the object is also considered - * signalled. - */ - -static int -ntoskrnl_is_signalled(obj, td) - nt_dispatch_header *obj; - struct thread *td; -{ - kmutant *km; - - if (obj->dh_type == DISP_TYPE_MUTANT) { - km = (kmutant *)obj; - if ((obj->dh_sigstate <= 0 && km->km_ownerthread == td) || - obj->dh_sigstate == 1) - return (TRUE); - return (FALSE); - } - - if (obj->dh_sigstate > 0) - return (TRUE); - return (FALSE); -} - -static void -ntoskrnl_satisfy_wait(obj, td) - nt_dispatch_header *obj; - struct thread *td; -{ - kmutant *km; - - switch (obj->dh_type) { - case DISP_TYPE_MUTANT: - km = (struct kmutant *)obj; - obj->dh_sigstate--; - /* - * If sigstate reaches 0, the mutex is now - * non-signalled (the new thread owns it). - */ - if (obj->dh_sigstate == 0) { - km->km_ownerthread = td; - if (km->km_abandoned == TRUE) - km->km_abandoned = FALSE; - } - break; - /* Synchronization objects get reset to unsignalled. */ - case DISP_TYPE_SYNCHRONIZATION_EVENT: - case DISP_TYPE_SYNCHRONIZATION_TIMER: - obj->dh_sigstate = 0; - break; - case DISP_TYPE_SEMAPHORE: - obj->dh_sigstate--; - break; - default: - break; - } -} - -static void -ntoskrnl_satisfy_multiple_waits(wb) - wait_block *wb; -{ - wait_block *cur; - struct thread *td; - - cur = wb; - td = wb->wb_kthread; - - do { - ntoskrnl_satisfy_wait(wb->wb_object, td); - cur->wb_awakened = TRUE; - cur = cur->wb_next; - } while (cur != wb); -} - -/* Always called with dispatcher lock held. */ -static void -ntoskrnl_waittest(obj, increment) - nt_dispatch_header *obj; - uint32_t increment; -{ - wait_block *w, *next; - list_entry *e; - struct thread *td; - wb_ext *we; - int satisfied; - - /* - * Once an object has been signalled, we walk its list of - * wait blocks. If a wait block can be awakened, then satisfy - * waits as necessary and wake the thread. - * - * The rules work like this: - * - * If a wait block is marked as WAITTYPE_ANY, then - * we can satisfy the wait conditions on the current - * object and wake the thread right away. Satisfying - * the wait also has the effect of breaking us out - * of the search loop. - * - * If the object is marked as WAITTYLE_ALL, then the - * wait block will be part of a circularly linked - * list of wait blocks belonging to a waiting thread - * that's sleeping in KeWaitForMultipleObjects(). In - * order to wake the thread, all the objects in the - * wait list must be in the signalled state. If they - * are, we then satisfy all of them and wake the - * thread. - * - */ - - e = obj->dh_waitlisthead.nle_flink; - - while (e != &obj->dh_waitlisthead && obj->dh_sigstate > 0) { - w = CONTAINING_RECORD(e, wait_block, wb_waitlist); - we = w->wb_ext; - td = we->we_td; - satisfied = FALSE; - if (w->wb_waittype == WAITTYPE_ANY) { - /* - * Thread can be awakened if - * any wait is satisfied. - */ - ntoskrnl_satisfy_wait(obj, td); - satisfied = TRUE; - w->wb_awakened = TRUE; - } else { - /* - * Thread can only be woken up - * if all waits are satisfied. - * If the thread is waiting on multiple - * objects, they should all be linked - * through the wb_next pointers in the - * wait blocks. - */ - satisfied = TRUE; - next = w->wb_next; - while (next != w) { - if (ntoskrnl_is_signalled(obj, td) == FALSE) { - satisfied = FALSE; - break; - } - next = next->wb_next; - } - ntoskrnl_satisfy_multiple_waits(w); - } - - if (satisfied == TRUE) - cv_broadcastpri(&we->we_cv, - (w->wb_oldpri - (increment * 4)) > PRI_MIN_KERN ? - w->wb_oldpri - (increment * 4) : PRI_MIN_KERN); - - e = e->nle_flink; - } -} - -/* - * Return the number of 100 nanosecond intervals since - * January 1, 1601. (?!?!) - */ -void -ntoskrnl_time(tval) - uint64_t *tval; -{ - struct timespec ts; - - nanotime(&ts); - *tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 + - 11644473600 * 10000000; /* 100ns ticks from 1601 to 1970 */ -} - -static void -KeQuerySystemTime(current_time) - uint64_t *current_time; -{ - ntoskrnl_time(current_time); -} - -static uint32_t -KeTickCount(void) -{ - struct timeval tv; - getmicrouptime(&tv); - return tvtohz(&tv); -} - -/* - * KeWaitForSingleObject() is a tricky beast, because it can be used - * with several different object types: semaphores, timers, events, - * mutexes and threads. Semaphores don't appear very often, but the - * other object types are quite common. KeWaitForSingleObject() is - * what's normally used to acquire a mutex, and it can be used to - * wait for a thread termination. - * - * The Windows NDIS API is implemented in terms of Windows kernel - * primitives, and some of the object manipulation is duplicated in - * NDIS. For example, NDIS has timers and events, which are actually - * Windows kevents and ktimers. Now, you're supposed to only use the - * NDIS variants of these objects within the confines of the NDIS API, - * but there are some naughty developers out there who will use - * KeWaitForSingleObject() on NDIS timer and event objects, so we - * have to support that as well. Conseqently, our NDIS timer and event - * code has to be closely tied into our ntoskrnl timer and event code, - * just as it is in Windows. - * - * KeWaitForSingleObject() may do different things for different kinds - * of objects: - * - * - For events, we check if the event has been signalled. If the - * event is already in the signalled state, we just return immediately, - * otherwise we wait for it to be set to the signalled state by someone - * else calling KeSetEvent(). Events can be either synchronization or - * notification events. - * - * - For timers, if the timer has already fired and the timer is in - * the signalled state, we just return, otherwise we wait on the - * timer. Unlike an event, timers get signalled automatically when - * they expire rather than someone having to trip them manually. - * Timers initialized with KeInitializeTimer() are always notification - * events: KeInitializeTimerEx() lets you initialize a timer as - * either a notification or synchronization event. - * - * - For mutexes, we try to acquire the mutex and if we can't, we wait - * on the mutex until it's available and then grab it. When a mutex is - * released, it enters the signalled state, which wakes up one of the - * threads waiting to acquire it. Mutexes are always synchronization - * events. - * - * - For threads, the only thing we do is wait until the thread object - * enters a signalled state, which occurs when the thread terminates. - * Threads are always notification events. - * - * A notification event wakes up all threads waiting on an object. A - * synchronization event wakes up just one. Also, a synchronization event - * is auto-clearing, which means we automatically set the event back to - * the non-signalled state once the wakeup is done. - */ - -uint32_t -KeWaitForSingleObject(void *arg, uint32_t reason, uint32_t mode, - uint8_t alertable, int64_t *duetime) -{ - wait_block w; - struct thread *td = curthread; - struct timeval tv; - int error = 0; - uint64_t curtime; - wb_ext we; - nt_dispatch_header *obj; - - obj = arg; - - if (obj == NULL) - return (STATUS_INVALID_PARAMETER); - - mtx_lock(&ntoskrnl_dispatchlock); - - cv_init(&we.we_cv, "KeWFS"); - we.we_td = td; - - /* - * Check to see if this object is already signalled, - * and just return without waiting if it is. - */ - if (ntoskrnl_is_signalled(obj, td) == TRUE) { - /* Sanity check the signal state value. */ - if (obj->dh_sigstate != INT32_MIN) { - ntoskrnl_satisfy_wait(obj, curthread); - mtx_unlock(&ntoskrnl_dispatchlock); - return (STATUS_SUCCESS); - } else { - /* - * There's a limit to how many times we can - * recursively acquire a mutant. If we hit - * the limit, something is very wrong. - */ - if (obj->dh_type == DISP_TYPE_MUTANT) { - mtx_unlock(&ntoskrnl_dispatchlock); - panic("mutant limit exceeded"); - } - } - } - - bzero((char *)&w, sizeof(wait_block)); - w.wb_object = obj; - w.wb_ext = &we; - w.wb_waittype = WAITTYPE_ANY; - w.wb_next = &w; - w.wb_waitkey = 0; - w.wb_awakened = FALSE; - w.wb_oldpri = td->td_priority; - - InsertTailList((&obj->dh_waitlisthead), (&w.wb_waitlist)); - - /* - * The timeout value is specified in 100 nanosecond units - * and can be a positive or negative number. If it's positive, - * then the duetime is absolute, and we need to convert it - * to an absolute offset relative to now in order to use it. - * If it's negative, then the duetime is relative and we - * just have to convert the units. - */ - - if (duetime != NULL) { - if (*duetime < 0) { - tv.tv_sec = - (*duetime) / 10000000; - tv.tv_usec = (- (*duetime) / 10) - - (tv.tv_sec * 1000000); - } else { - ntoskrnl_time(&curtime); - if (*duetime < curtime) - tv.tv_sec = tv.tv_usec = 0; - else { - tv.tv_sec = ((*duetime) - curtime) / 10000000; - tv.tv_usec = ((*duetime) - curtime) / 10 - - (tv.tv_sec * 1000000); - } - } - } - - if (duetime == NULL) - cv_wait(&we.we_cv, &ntoskrnl_dispatchlock); - else - error = cv_timedwait(&we.we_cv, - &ntoskrnl_dispatchlock, tvtohz(&tv)); - - RemoveEntryList(&w.wb_waitlist); - - cv_destroy(&we.we_cv); - - /* We timed out. Leave the object alone and return status. */ - - if (error == EWOULDBLOCK) { - mtx_unlock(&ntoskrnl_dispatchlock); - return (STATUS_TIMEOUT); - } - - mtx_unlock(&ntoskrnl_dispatchlock); - - return (STATUS_SUCCESS); -/* - return (KeWaitForMultipleObjects(1, &obj, WAITTYPE_ALL, reason, - mode, alertable, duetime, &w)); -*/ -} - -static uint32_t -KeWaitForMultipleObjects(uint32_t cnt, nt_dispatch_header *obj[], uint32_t wtype, - uint32_t reason, uint32_t mode, uint8_t alertable, int64_t *duetime, - wait_block *wb_array) -{ - struct thread *td = curthread; - wait_block *whead, *w; - wait_block _wb_array[MAX_WAIT_OBJECTS]; - nt_dispatch_header *cur; - struct timeval tv; - int i, wcnt = 0, error = 0; - uint64_t curtime; - struct timespec t1, t2; - uint32_t status = STATUS_SUCCESS; - wb_ext we; - - if (cnt > MAX_WAIT_OBJECTS) - return (STATUS_INVALID_PARAMETER); - if (cnt > THREAD_WAIT_OBJECTS && wb_array == NULL) - return (STATUS_INVALID_PARAMETER); - - mtx_lock(&ntoskrnl_dispatchlock); - - cv_init(&we.we_cv, "KeWFM"); - we.we_td = td; - - if (wb_array == NULL) - whead = _wb_array; - else - whead = wb_array; - - bzero((char *)whead, sizeof(wait_block) * cnt); - - /* First pass: see if we can satisfy any waits immediately. */ - - wcnt = 0; - w = whead; - - for (i = 0; i < cnt; i++) { - InsertTailList((&obj[i]->dh_waitlisthead), - (&w->wb_waitlist)); - w->wb_ext = &we; - w->wb_object = obj[i]; - w->wb_waittype = wtype; - w->wb_waitkey = i; - w->wb_awakened = FALSE; - w->wb_oldpri = td->td_priority; - w->wb_next = w + 1; - w++; - wcnt++; - if (ntoskrnl_is_signalled(obj[i], td)) { - /* - * There's a limit to how many times - * we can recursively acquire a mutant. - * If we hit the limit, something - * is very wrong. - */ - if (obj[i]->dh_sigstate == INT32_MIN && - obj[i]->dh_type == DISP_TYPE_MUTANT) { - mtx_unlock(&ntoskrnl_dispatchlock); - panic("mutant limit exceeded"); - } - - /* - * If this is a WAITTYPE_ANY wait, then - * satisfy the waited object and exit - * right now. - */ - - if (wtype == WAITTYPE_ANY) { - ntoskrnl_satisfy_wait(obj[i], td); - status = STATUS_WAIT_0 + i; - goto wait_done; - } else { - w--; - wcnt--; - w->wb_object = NULL; - RemoveEntryList(&w->wb_waitlist); - } - } - } - - /* - * If this is a WAITTYPE_ALL wait and all objects are - * already signalled, satisfy the waits and exit now. - */ - - if (wtype == WAITTYPE_ALL && wcnt == 0) { - for (i = 0; i < cnt; i++) - ntoskrnl_satisfy_wait(obj[i], td); - status = STATUS_SUCCESS; - goto wait_done; - } - - /* - * Create a circular waitblock list. The waitcount - * must always be non-zero when we get here. - */ - - (w - 1)->wb_next = whead; - - /* Wait on any objects that aren't yet signalled. */ - - /* Calculate timeout, if any. */ - - if (duetime != NULL) { - if (*duetime < 0) { - tv.tv_sec = - (*duetime) / 10000000; - tv.tv_usec = (- (*duetime) / 10) - - (tv.tv_sec * 1000000); - } else { - ntoskrnl_time(&curtime); - if (*duetime < curtime) - tv.tv_sec = tv.tv_usec = 0; - else { - tv.tv_sec = ((*duetime) - curtime) / 10000000; - tv.tv_usec = ((*duetime) - curtime) / 10 - - (tv.tv_sec * 1000000); - } - } - } - - while (wcnt) { - nanotime(&t1); - - if (duetime == NULL) - cv_wait(&we.we_cv, &ntoskrnl_dispatchlock); - else - error = cv_timedwait(&we.we_cv, - &ntoskrnl_dispatchlock, tvtohz(&tv)); - - /* Wait with timeout expired. */ - - if (error) { - status = STATUS_TIMEOUT; - goto wait_done; - } - - nanotime(&t2); - - /* See what's been signalled. */ - - w = whead; - do { - cur = w->wb_object; - if (ntoskrnl_is_signalled(cur, td) == TRUE || - w->wb_awakened == TRUE) { - /* Sanity check the signal state value. */ - if (cur->dh_sigstate == INT32_MIN && - cur->dh_type == DISP_TYPE_MUTANT) { - mtx_unlock(&ntoskrnl_dispatchlock); - panic("mutant limit exceeded"); - } - wcnt--; - if (wtype == WAITTYPE_ANY) { - status = w->wb_waitkey & - STATUS_WAIT_0; - goto wait_done; - } - } - w = w->wb_next; - } while (w != whead); - - /* - * If all objects have been signalled, or if this - * is a WAITTYPE_ANY wait and we were woke up by - * someone, we can bail. - */ - - if (wcnt == 0) { - status = STATUS_SUCCESS; - goto wait_done; - } - - /* - * If this is WAITTYPE_ALL wait, and there's still - * objects that haven't been signalled, deduct the - * time that's elapsed so far from the timeout and - * wait again (or continue waiting indefinitely if - * there's no timeout). - */ - - if (duetime != NULL) { - tv.tv_sec -= (t2.tv_sec - t1.tv_sec); - tv.tv_usec -= (t2.tv_nsec - t1.tv_nsec) / 1000; - } - } - -wait_done: - - cv_destroy(&we.we_cv); - - for (i = 0; i < cnt; i++) { - if (whead[i].wb_object != NULL) - RemoveEntryList(&whead[i].wb_waitlist); - } - mtx_unlock(&ntoskrnl_dispatchlock); - - return (status); -} - -static void -WRITE_REGISTER_USHORT(uint16_t *reg, uint16_t val) -{ - bus_space_write_2(NDIS_BUS_SPACE_MEM, 0x0, (bus_size_t)reg, val); -} - -static uint16_t -READ_REGISTER_USHORT(reg) - uint16_t *reg; -{ - return (bus_space_read_2(NDIS_BUS_SPACE_MEM, 0x0, (bus_size_t)reg)); -} - -static void -WRITE_REGISTER_ULONG(reg, val) - uint32_t *reg; - uint32_t val; -{ - bus_space_write_4(NDIS_BUS_SPACE_MEM, 0x0, (bus_size_t)reg, val); -} - -static uint32_t -READ_REGISTER_ULONG(reg) - uint32_t *reg; -{ - return (bus_space_read_4(NDIS_BUS_SPACE_MEM, 0x0, (bus_size_t)reg)); -} - -static uint8_t -READ_REGISTER_UCHAR(uint8_t *reg) -{ - return (bus_space_read_1(NDIS_BUS_SPACE_MEM, 0x0, (bus_size_t)reg)); -} - -static void -WRITE_REGISTER_UCHAR(uint8_t *reg, uint8_t val) -{ - bus_space_write_1(NDIS_BUS_SPACE_MEM, 0x0, (bus_size_t)reg, val); -} - -static int64_t -_allmul(a, b) - int64_t a; - int64_t b; -{ - return (a * b); -} - -static int64_t -_alldiv(a, b) - int64_t a; - int64_t b; -{ - return (a / b); -} - -static int64_t -_allrem(a, b) - int64_t a; - int64_t b; -{ - return (a % b); -} - -static uint64_t -_aullmul(a, b) - uint64_t a; - uint64_t b; -{ - return (a * b); -} - -static uint64_t -_aulldiv(a, b) - uint64_t a; - uint64_t b; -{ - return (a / b); -} - -static uint64_t -_aullrem(a, b) - uint64_t a; - uint64_t b; -{ - return (a % b); -} - -static int64_t -_allshl(int64_t a, uint8_t b) -{ - return (a << b); -} - -static uint64_t -_aullshl(uint64_t a, uint8_t b) -{ - return (a << b); -} - -static int64_t -_allshr(int64_t a, uint8_t b) -{ - return (a >> b); -} - -static uint64_t -_aullshr(uint64_t a, uint8_t b) -{ - return (a >> b); -} - -static slist_entry * -ntoskrnl_pushsl(head, entry) - slist_header *head; - slist_entry *entry; -{ - slist_entry *oldhead; - - oldhead = head->slh_list.slh_next; - entry->sl_next = head->slh_list.slh_next; - head->slh_list.slh_next = entry; - head->slh_list.slh_depth++; - head->slh_list.slh_seq++; - - return (oldhead); -} - -static void -InitializeSListHead(head) - slist_header *head; -{ - memset(head, 0, sizeof(*head)); -} - -static slist_entry * -ntoskrnl_popsl(head) - slist_header *head; -{ - slist_entry *first; - - first = head->slh_list.slh_next; - if (first != NULL) { - head->slh_list.slh_next = first->sl_next; - head->slh_list.slh_depth--; - head->slh_list.slh_seq++; - } - - return (first); -} - -/* - * We need this to make lookaside lists work for amd64. - * We pass a pointer to ExAllocatePoolWithTag() the lookaside - * list structure. For amd64 to work right, this has to be a - * pointer to the wrapped version of the routine, not the - * original. Letting the Windows driver invoke the original - * function directly will result in a convention calling - * mismatch and a pretty crash. On x86, this effectively - * becomes a no-op since ipt_func and ipt_wrap are the same. - */ - -static funcptr -ntoskrnl_findwrap(func) - funcptr func; -{ - image_patch_table *patch; - - patch = ntoskrnl_functbl; - while (patch->ipt_func != NULL) { - if ((funcptr)patch->ipt_func == func) - return ((funcptr)patch->ipt_wrap); - patch++; - } - - return (NULL); -} - -static void -ExInitializePagedLookasideList(paged_lookaside_list *lookaside, - lookaside_alloc_func *allocfunc, lookaside_free_func *freefunc, - uint32_t flags, size_t size, uint32_t tag, uint16_t depth) -{ - bzero((char *)lookaside, sizeof(paged_lookaside_list)); - - if (size < sizeof(slist_entry)) - lookaside->nll_l.gl_size = sizeof(slist_entry); - else - lookaside->nll_l.gl_size = size; - lookaside->nll_l.gl_tag = tag; - if (allocfunc == NULL) - lookaside->nll_l.gl_allocfunc = - ntoskrnl_findwrap((funcptr)ExAllocatePoolWithTag); - else - lookaside->nll_l.gl_allocfunc = allocfunc; - - if (freefunc == NULL) - lookaside->nll_l.gl_freefunc = - ntoskrnl_findwrap((funcptr)ExFreePool); - else - lookaside->nll_l.gl_freefunc = freefunc; - -#ifdef __i386__ - KeInitializeSpinLock(&lookaside->nll_obsoletelock); -#endif - - lookaside->nll_l.gl_type = NonPagedPool; - lookaside->nll_l.gl_depth = depth; - lookaside->nll_l.gl_maxdepth = LOOKASIDE_DEPTH; -} - -static void -ExDeletePagedLookasideList(lookaside) - paged_lookaside_list *lookaside; -{ - void *buf; - void (*freefunc)(void *); - - freefunc = lookaside->nll_l.gl_freefunc; - while((buf = ntoskrnl_popsl(&lookaside->nll_l.gl_listhead)) != NULL) - MSCALL1(freefunc, buf); -} - -static void -ExInitializeNPagedLookasideList(npaged_lookaside_list *lookaside, - lookaside_alloc_func *allocfunc, lookaside_free_func *freefunc, - uint32_t flags, size_t size, uint32_t tag, uint16_t depth) -{ - bzero((char *)lookaside, sizeof(npaged_lookaside_list)); - - if (size < sizeof(slist_entry)) - lookaside->nll_l.gl_size = sizeof(slist_entry); - else - lookaside->nll_l.gl_size = size; - lookaside->nll_l.gl_tag = tag; - if (allocfunc == NULL) - lookaside->nll_l.gl_allocfunc = - ntoskrnl_findwrap((funcptr)ExAllocatePoolWithTag); - else - lookaside->nll_l.gl_allocfunc = allocfunc; - - if (freefunc == NULL) - lookaside->nll_l.gl_freefunc = - ntoskrnl_findwrap((funcptr)ExFreePool); - else - lookaside->nll_l.gl_freefunc = freefunc; - -#ifdef __i386__ - KeInitializeSpinLock(&lookaside->nll_obsoletelock); -#endif - - lookaside->nll_l.gl_type = NonPagedPool; - lookaside->nll_l.gl_depth = depth; - lookaside->nll_l.gl_maxdepth = LOOKASIDE_DEPTH; -} - -static void -ExDeleteNPagedLookasideList(lookaside) - npaged_lookaside_list *lookaside; -{ - void *buf; - void (*freefunc)(void *); - - freefunc = lookaside->nll_l.gl_freefunc; - while((buf = ntoskrnl_popsl(&lookaside->nll_l.gl_listhead)) != NULL) - MSCALL1(freefunc, buf); -} - -slist_entry * -InterlockedPushEntrySList(head, entry) - slist_header *head; - slist_entry *entry; -{ - slist_entry *oldhead; - - mtx_lock_spin(&ntoskrnl_interlock); - oldhead = ntoskrnl_pushsl(head, entry); - mtx_unlock_spin(&ntoskrnl_interlock); - - return (oldhead); -} - -slist_entry * -InterlockedPopEntrySList(head) - slist_header *head; -{ - slist_entry *first; - - mtx_lock_spin(&ntoskrnl_interlock); - first = ntoskrnl_popsl(head); - mtx_unlock_spin(&ntoskrnl_interlock); - - return (first); -} - -static slist_entry * -ExInterlockedPushEntrySList(head, entry, lock) - slist_header *head; - slist_entry *entry; - kspin_lock *lock; -{ - return (InterlockedPushEntrySList(head, entry)); -} - -static slist_entry * -ExInterlockedPopEntrySList(head, lock) - slist_header *head; - kspin_lock *lock; -{ - return (InterlockedPopEntrySList(head)); -} - -uint16_t -ExQueryDepthSList(head) - slist_header *head; -{ - uint16_t depth; - - mtx_lock_spin(&ntoskrnl_interlock); - depth = head->slh_list.slh_depth; - mtx_unlock_spin(&ntoskrnl_interlock); - - return (depth); -} - -void -KeInitializeSpinLock(lock) - kspin_lock *lock; -{ - *lock = 0; -} - -#ifdef __i386__ -void -KefAcquireSpinLockAtDpcLevel(lock) - kspin_lock *lock; -{ -#ifdef NTOSKRNL_DEBUG_SPINLOCKS - int i = 0; -#endif - - while (atomic_cmpset_acq_int((volatile u_int *)lock, 0, 1) == 0) { - /* sit and spin */; -#ifdef NTOSKRNL_DEBUG_SPINLOCKS - i++; - if (i > 200000000) - panic("DEADLOCK!"); -#endif - } -} - -void -KefReleaseSpinLockFromDpcLevel(lock) - kspin_lock *lock; -{ - atomic_store_rel_int((volatile u_int *)lock, 0); -} - -uint8_t -KeAcquireSpinLockRaiseToDpc(kspin_lock *lock) -{ - uint8_t oldirql; - - if (KeGetCurrentIrql() > DISPATCH_LEVEL) - panic("IRQL_NOT_LESS_THAN_OR_EQUAL"); - - KeRaiseIrql(DISPATCH_LEVEL, &oldirql); - KeAcquireSpinLockAtDpcLevel(lock); - - return (oldirql); -} -#else -void -KeAcquireSpinLockAtDpcLevel(kspin_lock *lock) -{ - while (atomic_cmpset_acq_int((volatile u_int *)lock, 0, 1) == 0) - /* sit and spin */; -} - -void -KeReleaseSpinLockFromDpcLevel(kspin_lock *lock) -{ - atomic_store_rel_int((volatile u_int *)lock, 0); -} -#endif /* __i386__ */ - -uintptr_t -InterlockedExchange(dst, val) - volatile uint32_t *dst; - uintptr_t val; -{ - uintptr_t r; - - mtx_lock_spin(&ntoskrnl_interlock); - r = *dst; - *dst = val; - mtx_unlock_spin(&ntoskrnl_interlock); - - return (r); -} - -static uint32_t -InterlockedIncrement(addend) - volatile uint32_t *addend; -{ - atomic_add_long((volatile u_long *)addend, 1); - return (*addend); -} - -static uint32_t -InterlockedDecrement(addend) - volatile uint32_t *addend; -{ - atomic_subtract_long((volatile u_long *)addend, 1); - return (*addend); -} - -static void -ExInterlockedAddLargeStatistic(addend, inc) - uint64_t *addend; - uint32_t inc; -{ - mtx_lock_spin(&ntoskrnl_interlock); - *addend += inc; - mtx_unlock_spin(&ntoskrnl_interlock); -}; - -mdl * -IoAllocateMdl(void *vaddr, uint32_t len, uint8_t secondarybuf, - uint8_t chargequota, irp *iopkt) -{ - mdl *m; - int zone = 0; - - if (MmSizeOfMdl(vaddr, len) > MDL_ZONE_SIZE) - m = ExAllocatePoolWithTag(NonPagedPool, - MmSizeOfMdl(vaddr, len), 0); - else { - m = uma_zalloc(mdl_zone, M_NOWAIT | M_ZERO); - zone++; - } - - if (m == NULL) - return (NULL); - - MmInitializeMdl(m, vaddr, len); - - /* - * MmInitializMdl() clears the flags field, so we - * have to set this here. If the MDL came from the - * MDL UMA zone, tag it so we can release it to - * the right place later. - */ - if (zone) - m->mdl_flags = MDL_ZONE_ALLOCED; - - if (iopkt != NULL) { - if (secondarybuf == TRUE) { - mdl *last; - last = iopkt->irp_mdl; - while (last->mdl_next != NULL) - last = last->mdl_next; - last->mdl_next = m; - } else { - if (iopkt->irp_mdl != NULL) - panic("leaking an MDL in IoAllocateMdl()"); - iopkt->irp_mdl = m; - } - } - - return (m); -} - -void -IoFreeMdl(m) - mdl *m; -{ - if (m == NULL) - return; - - if (m->mdl_flags & MDL_ZONE_ALLOCED) - uma_zfree(mdl_zone, m); - else - ExFreePool(m); -} - -static void * -MmAllocateContiguousMemory(size, highest) - uint32_t size; - uint64_t highest; -{ - void *addr; - size_t pagelength = roundup(size, PAGE_SIZE); - - addr = ExAllocatePoolWithTag(NonPagedPool, pagelength, 0); - - return (addr); -} - -static void * -MmAllocateContiguousMemorySpecifyCache(size, lowest, highest, - boundary, cachetype) - uint32_t size; - uint64_t lowest; - uint64_t highest; - uint64_t boundary; - enum nt_caching_type cachetype; -{ - vm_memattr_t memattr; - void *ret; - - switch (cachetype) { - case MmNonCached: - memattr = VM_MEMATTR_UNCACHEABLE; - break; - case MmWriteCombined: - memattr = VM_MEMATTR_WRITE_COMBINING; - break; - case MmNonCachedUnordered: - memattr = VM_MEMATTR_UNCACHEABLE; - break; - case MmCached: - case MmHardwareCoherentCached: - case MmUSWCCached: - default: - memattr = VM_MEMATTR_DEFAULT; - break; - } - - ret = (void *)kmem_alloc_contig(size, M_ZERO | M_NOWAIT, lowest, - highest, PAGE_SIZE, boundary, memattr); - if (ret != NULL) - malloc_type_allocated(M_DEVBUF, round_page(size)); - return (ret); -} - -static void -MmFreeContiguousMemory(base) - void *base; -{ - ExFreePool(base); -} - -static void -MmFreeContiguousMemorySpecifyCache(base, size, cachetype) - void *base; - uint32_t size; - enum nt_caching_type cachetype; -{ - contigfree(base, size, M_DEVBUF); -} - -static uint32_t -MmSizeOfMdl(vaddr, len) - void *vaddr; - size_t len; -{ - uint32_t l; - - l = sizeof(struct mdl) + - (sizeof(vm_offset_t *) * SPAN_PAGES(vaddr, len)); - - return (l); -} - -/* - * The Microsoft documentation says this routine fills in the - * page array of an MDL with the _physical_ page addresses that - * comprise the buffer, but we don't really want to do that here. - * Instead, we just fill in the page array with the kernel virtual - * addresses of the buffers. - */ -void -MmBuildMdlForNonPagedPool(m) - mdl *m; -{ - vm_offset_t *mdl_pages; - int pagecnt, i; - - pagecnt = SPAN_PAGES(m->mdl_byteoffset, m->mdl_bytecount); - - if (pagecnt > (m->mdl_size - sizeof(mdl)) / sizeof(vm_offset_t *)) - panic("not enough pages in MDL to describe buffer"); - - mdl_pages = MmGetMdlPfnArray(m); - - for (i = 0; i < pagecnt; i++) - *mdl_pages = (vm_offset_t)m->mdl_startva + (i * PAGE_SIZE); - - m->mdl_flags |= MDL_SOURCE_IS_NONPAGED_POOL; - m->mdl_mappedsystemva = MmGetMdlVirtualAddress(m); -} - -static void * -MmMapLockedPages(mdl *buf, uint8_t accessmode) -{ - buf->mdl_flags |= MDL_MAPPED_TO_SYSTEM_VA; - return (MmGetMdlVirtualAddress(buf)); -} - -static void * -MmMapLockedPagesSpecifyCache(mdl *buf, uint8_t accessmode, uint32_t cachetype, - void *vaddr, uint32_t bugcheck, uint32_t prio) -{ - return (MmMapLockedPages(buf, accessmode)); -} - -static void -MmUnmapLockedPages(vaddr, buf) - void *vaddr; - mdl *buf; -{ - buf->mdl_flags &= ~MDL_MAPPED_TO_SYSTEM_VA; -} - -/* - * This function has a problem in that it will break if you - * compile this module without PAE and try to use it on a PAE - * kernel. Unfortunately, there's no way around this at the - * moment. It's slightly less broken that using pmap_kextract(). - * You'd think the virtual memory subsystem would help us out - * here, but it doesn't. - */ - -static uint64_t -MmGetPhysicalAddress(void *base) -{ - return (pmap_extract(kernel_map->pmap, (vm_offset_t)base)); -} - -void * -MmGetSystemRoutineAddress(ustr) - unicode_string *ustr; -{ - ansi_string astr; - - if (RtlUnicodeStringToAnsiString(&astr, ustr, TRUE)) - return (NULL); - return (ndis_get_routine_address(ntoskrnl_functbl, astr.as_buf)); -} - -uint8_t -MmIsAddressValid(vaddr) - void *vaddr; -{ - if (pmap_extract(kernel_map->pmap, (vm_offset_t)vaddr)) - return (TRUE); - - return (FALSE); -} - -void * -MmMapIoSpace(paddr, len, cachetype) - uint64_t paddr; - uint32_t len; - uint32_t cachetype; -{ - devclass_t nexus_class; - device_t *nexus_devs, devp; - int nexus_count = 0; - device_t matching_dev = NULL; - struct resource *res; - int i; - vm_offset_t v; - - /* There will always be at least one nexus. */ - - nexus_class = devclass_find("nexus"); - devclass_get_devices(nexus_class, &nexus_devs, &nexus_count); - - for (i = 0; i < nexus_count; i++) { - devp = nexus_devs[i]; - matching_dev = ntoskrnl_finddev(devp, paddr, &res); - if (matching_dev) - break; - } - - free(nexus_devs, M_TEMP); - - if (matching_dev == NULL) - return (NULL); - - v = (vm_offset_t)rman_get_virtual(res); - if (paddr > rman_get_start(res)) - v += paddr - rman_get_start(res); - - return ((void *)v); -} - -void -MmUnmapIoSpace(vaddr, len) - void *vaddr; - size_t len; -{ -} - -static device_t -ntoskrnl_finddev(dev, paddr, res) - device_t dev; - uint64_t paddr; - struct resource **res; -{ - device_t *children = NULL; - device_t matching_dev; - int childcnt; - struct resource *r; - struct resource_list *rl; - struct resource_list_entry *rle; - uint32_t flags; - int i; - - /* We only want devices that have been successfully probed. */ - - if (device_is_alive(dev) == FALSE) - return (NULL); - - rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); - if (rl != NULL) { - STAILQ_FOREACH(rle, rl, link) { - r = rle->res; - - if (r == NULL) - continue; - - flags = rman_get_flags(r); - - if (rle->type == SYS_RES_MEMORY && - paddr >= rman_get_start(r) && - paddr <= rman_get_end(r)) { - if (!(flags & RF_ACTIVE)) - bus_activate_resource(dev, - SYS_RES_MEMORY, 0, r); - *res = r; - return (dev); - } - } - } - - /* - * If this device has children, do another - * level of recursion to inspect them. - */ - - device_get_children(dev, &children, &childcnt); - - for (i = 0; i < childcnt; i++) { - matching_dev = ntoskrnl_finddev(children[i], paddr, res); - if (matching_dev != NULL) { - free(children, M_TEMP); - return (matching_dev); - } - } - - /* Won't somebody please think of the children! */ - - if (children != NULL) - free(children, M_TEMP); - - return (NULL); -} - -/* - * Workitems are unlike DPCs, in that they run in a user-mode thread - * context rather than at DISPATCH_LEVEL in kernel context. In our - * case we run them in kernel context anyway. - */ -static void -ntoskrnl_workitem_thread(arg) - void *arg; -{ - kdpc_queue *kq; - list_entry *l; - io_workitem *iw; - uint8_t irql; - - kq = arg; - - InitializeListHead(&kq->kq_disp); - kq->kq_td = curthread; - kq->kq_exit = 0; - KeInitializeSpinLock(&kq->kq_lock); - KeInitializeEvent(&kq->kq_proc, EVENT_TYPE_SYNC, FALSE); - - while (1) { - KeWaitForSingleObject(&kq->kq_proc, 0, 0, TRUE, NULL); - - KeAcquireSpinLock(&kq->kq_lock, &irql); - - if (kq->kq_exit) { - kq->kq_exit = 0; - KeReleaseSpinLock(&kq->kq_lock, irql); - break; - } - - while (!IsListEmpty(&kq->kq_disp)) { - l = RemoveHeadList(&kq->kq_disp); - iw = CONTAINING_RECORD(l, - io_workitem, iw_listentry); - InitializeListHead((&iw->iw_listentry)); - if (iw->iw_func == NULL) - continue; - KeReleaseSpinLock(&kq->kq_lock, irql); - MSCALL2(iw->iw_func, iw->iw_dobj, iw->iw_ctx); - KeAcquireSpinLock(&kq->kq_lock, &irql); - } - - KeReleaseSpinLock(&kq->kq_lock, irql); - } - - kproc_exit(0); - return; /* notreached */ -} - -static ndis_status -RtlCharToInteger(src, base, val) - const char *src; - uint32_t base; - uint32_t *val; -{ - int negative = 0; - uint32_t res; - - if (!src || !val) - return (STATUS_ACCESS_VIOLATION); - while (*src != '\0' && *src <= ' ') - src++; - if (*src == '+') - src++; - else if (*src == '-') { - src++; - negative = 1; - } - if (base == 0) { - base = 10; - if (*src == '0') { - src++; - if (*src == 'b') { - base = 2; - src++; - } else if (*src == 'o') { - base = 8; - src++; - } else if (*src == 'x') { - base = 16; - src++; - } - } - } else if (!(base == 2 || base == 8 || base == 10 || base == 16)) - return (STATUS_INVALID_PARAMETER); - - for (res = 0; *src; src++) { - int v; - if (isdigit(*src)) - v = *src - '0'; - else if (isxdigit(*src)) - v = tolower(*src) - 'a' + 10; - else - v = base; - if (v >= base) - return (STATUS_INVALID_PARAMETER); - res = res * base + v; - } - *val = negative ? -res : res; - return (STATUS_SUCCESS); -} - -static void -ntoskrnl_destroy_workitem_threads(void) -{ - kdpc_queue *kq; - int i; - - for (i = 0; i < WORKITEM_THREADS; i++) { - kq = wq_queues + i; - kq->kq_exit = 1; - KeSetEvent(&kq->kq_proc, IO_NO_INCREMENT, FALSE); - while (kq->kq_exit) - tsleep(kq->kq_td->td_proc, PWAIT, "waitiw", hz/10); - } -} - -io_workitem * -IoAllocateWorkItem(dobj) - device_object *dobj; -{ - io_workitem *iw; - - iw = uma_zalloc(iw_zone, M_NOWAIT); - if (iw == NULL) - return (NULL); - - InitializeListHead(&iw->iw_listentry); - iw->iw_dobj = dobj; - - mtx_lock(&ntoskrnl_dispatchlock); - iw->iw_idx = wq_idx; - WORKIDX_INC(wq_idx); - mtx_unlock(&ntoskrnl_dispatchlock); - - return (iw); -} - -void -IoFreeWorkItem(iw) - io_workitem *iw; -{ - uma_zfree(iw_zone, iw); -} - -void -IoQueueWorkItem(iw, iw_func, qtype, ctx) - io_workitem *iw; - io_workitem_func iw_func; - uint32_t qtype; - void *ctx; -{ - kdpc_queue *kq; - list_entry *l; - io_workitem *cur; - uint8_t irql; - - kq = wq_queues + iw->iw_idx; - - KeAcquireSpinLock(&kq->kq_lock, &irql); - - /* - * Traverse the list and make sure this workitem hasn't - * already been inserted. Queuing the same workitem - * twice will hose the list but good. - */ - - l = kq->kq_disp.nle_flink; - while (l != &kq->kq_disp) { - cur = CONTAINING_RECORD(l, io_workitem, iw_listentry); - if (cur == iw) { - /* Already queued -- do nothing. */ - KeReleaseSpinLock(&kq->kq_lock, irql); - return; - } - l = l->nle_flink; - } - - iw->iw_func = iw_func; - iw->iw_ctx = ctx; - - InsertTailList((&kq->kq_disp), (&iw->iw_listentry)); - KeReleaseSpinLock(&kq->kq_lock, irql); - - KeSetEvent(&kq->kq_proc, IO_NO_INCREMENT, FALSE); -} - -static void -ntoskrnl_workitem(dobj, arg) - device_object *dobj; - void *arg; -{ - io_workitem *iw; - work_queue_item *w; - work_item_func f; - - iw = arg; - w = (work_queue_item *)dobj; - f = (work_item_func)w->wqi_func; - uma_zfree(iw_zone, iw); - MSCALL2(f, w, w->wqi_ctx); -} - -/* - * The ExQueueWorkItem() API is deprecated in Windows XP. Microsoft - * warns that it's unsafe and to use IoQueueWorkItem() instead. The - * problem with ExQueueWorkItem() is that it can't guard against - * the condition where a driver submits a job to the work queue and - * is then unloaded before the job is able to run. IoQueueWorkItem() - * acquires a reference to the device's device_object via the - * object manager and retains it until after the job has completed, - * which prevents the driver from being unloaded before the job - * runs. (We don't currently support this behavior, though hopefully - * that will change once the object manager API is fleshed out a bit.) - * - * Having said all that, the ExQueueWorkItem() API remains, because - * there are still other parts of Windows that use it, including - * NDIS itself: NdisScheduleWorkItem() calls ExQueueWorkItem(). - * We fake up the ExQueueWorkItem() API on top of our implementation - * of IoQueueWorkItem(). Workitem thread #3 is reserved exclusively - * for ExQueueWorkItem() jobs, and we pass a pointer to the work - * queue item (provided by the caller) in to IoAllocateWorkItem() - * instead of the device_object. We need to save this pointer so - * we can apply a sanity check: as with the DPC queue and other - * workitem queues, we can't allow the same work queue item to - * be queued twice. If it's already pending, we silently return - */ - -void -ExQueueWorkItem(w, qtype) - work_queue_item *w; - uint32_t qtype; -{ - io_workitem *iw; - io_workitem_func iwf; - kdpc_queue *kq; - list_entry *l; - io_workitem *cur; - uint8_t irql; - - /* - * We need to do a special sanity test to make sure - * the ExQueueWorkItem() API isn't used to queue - * the same workitem twice. Rather than checking the - * io_workitem pointer itself, we test the attached - * device object, which is really a pointer to the - * legacy work queue item structure. - */ - - kq = wq_queues + WORKITEM_LEGACY_THREAD; - KeAcquireSpinLock(&kq->kq_lock, &irql); - l = kq->kq_disp.nle_flink; - while (l != &kq->kq_disp) { - cur = CONTAINING_RECORD(l, io_workitem, iw_listentry); - if (cur->iw_dobj == (device_object *)w) { - /* Already queued -- do nothing. */ - KeReleaseSpinLock(&kq->kq_lock, irql); - return; - } - l = l->nle_flink; - } - KeReleaseSpinLock(&kq->kq_lock, irql); - - iw = IoAllocateWorkItem((device_object *)w); - if (iw == NULL) - return; - - iw->iw_idx = WORKITEM_LEGACY_THREAD; - iwf = (io_workitem_func)ntoskrnl_findwrap((funcptr)ntoskrnl_workitem); - IoQueueWorkItem(iw, iwf, qtype, iw); -} - -static void -RtlZeroMemory(dst, len) - void *dst; - size_t len; -{ - bzero(dst, len); -} - -static void -RtlSecureZeroMemory(dst, len) - void *dst; - size_t len; -{ - memset(dst, 0, len); -} - -static void -RtlFillMemory(void *dst, size_t len, uint8_t c) -{ - memset(dst, c, len); -} - -static void -RtlMoveMemory(dst, src, len) - void *dst; - const void *src; - size_t len; -{ - memmove(dst, src, len); -} - -static void -RtlCopyMemory(dst, src, len) - void *dst; - const void *src; - size_t len; -{ - bcopy(src, dst, len); -} - -static size_t -RtlCompareMemory(s1, s2, len) - const void *s1; - const void *s2; - size_t len; -{ - size_t i; - uint8_t *m1, *m2; - - m1 = __DECONST(char *, s1); - m2 = __DECONST(char *, s2); - - for (i = 0; i < len && m1[i] == m2[i]; i++); - return (i); -} - -void -RtlInitAnsiString(dst, src) - ansi_string *dst; - char *src; -{ - ansi_string *a; - - a = dst; - if (a == NULL) - return; - if (src == NULL) { - a->as_len = a->as_maxlen = 0; - a->as_buf = NULL; - } else { - a->as_buf = src; - a->as_len = a->as_maxlen = strlen(src); - } -} - -void -RtlInitUnicodeString(dst, src) - unicode_string *dst; - uint16_t *src; -{ - unicode_string *u; - int i; - - u = dst; - if (u == NULL) - return; - if (src == NULL) { - u->us_len = u->us_maxlen = 0; - u->us_buf = NULL; - } else { - i = 0; - while(src[i] != 0) - i++; - u->us_buf = src; - u->us_len = u->us_maxlen = i * 2; - } -} - -ndis_status -RtlUnicodeStringToInteger(ustr, base, val) - unicode_string *ustr; - uint32_t base; - uint32_t *val; -{ - uint16_t *uchr; - int len, neg = 0; - char abuf[64]; - char *astr; - - uchr = ustr->us_buf; - len = ustr->us_len; - bzero(abuf, sizeof(abuf)); - - if ((char)((*uchr) & 0xFF) == '-') { - neg = 1; - uchr++; - len -= 2; - } else if ((char)((*uchr) & 0xFF) == '+') { - neg = 0; - uchr++; - len -= 2; - } - - if (base == 0) { - if ((char)((*uchr) & 0xFF) == 'b') { - base = 2; - uchr++; - len -= 2; - } else if ((char)((*uchr) & 0xFF) == 'o') { - base = 8; - uchr++; - len -= 2; - } else if ((char)((*uchr) & 0xFF) == 'x') { - base = 16; - uchr++; - len -= 2; - } else - base = 10; - } - - astr = abuf; - if (neg) { - strcpy(astr, "-"); - astr++; - } - - ntoskrnl_unicode_to_ascii(uchr, astr, len); - *val = strtoul(abuf, NULL, base); - - return (STATUS_SUCCESS); -} - -void -RtlFreeUnicodeString(ustr) - unicode_string *ustr; -{ - if (ustr->us_buf == NULL) - return; - ExFreePool(ustr->us_buf); - ustr->us_buf = NULL; -} - -void -RtlFreeAnsiString(astr) - ansi_string *astr; -{ - if (astr->as_buf == NULL) - return; - ExFreePool(astr->as_buf); - astr->as_buf = NULL; -} - -static int -atoi(str) - const char *str; -{ - return (int)strtol(str, (char **)NULL, 10); -} - -static long -atol(str) - const char *str; -{ - return strtol(str, (char **)NULL, 10); -} - -static int -rand(void) -{ - - return (random()); -} - -static void -srand(unsigned int seed __unused) -{ -} - -static uint8_t -IoIsWdmVersionAvailable(uint8_t major, uint8_t minor) -{ - if (major == WDM_MAJOR && minor == WDM_MINOR_WINXP) - return (TRUE); - return (FALSE); -} - -static int32_t -IoOpenDeviceRegistryKey(struct device_object *devobj, uint32_t type, - uint32_t mask, void **key) -{ - return (NDIS_STATUS_INVALID_DEVICE_REQUEST); -} - -static ndis_status -IoGetDeviceObjectPointer(name, reqaccess, fileobj, devobj) - unicode_string *name; - uint32_t reqaccess; - void *fileobj; - device_object *devobj; -{ - return (STATUS_SUCCESS); -} - -static ndis_status -IoGetDeviceProperty(devobj, regprop, buflen, prop, reslen) - device_object *devobj; - uint32_t regprop; - uint32_t buflen; - void *prop; - uint32_t *reslen; -{ - driver_object *drv; - uint16_t **name; - - drv = devobj->do_drvobj; - - switch (regprop) { - case DEVPROP_DRIVER_KEYNAME: - name = prop; - *name = drv->dro_drivername.us_buf; - *reslen = drv->dro_drivername.us_len; - break; - default: - return (STATUS_INVALID_PARAMETER_2); - break; - } - - return (STATUS_SUCCESS); -} - -static void -KeInitializeMutex(kmutex, level) - kmutant *kmutex; - uint32_t level; -{ - InitializeListHead((&kmutex->km_header.dh_waitlisthead)); - kmutex->km_abandoned = FALSE; - kmutex->km_apcdisable = 1; - kmutex->km_header.dh_sigstate = 1; - kmutex->km_header.dh_type = DISP_TYPE_MUTANT; - kmutex->km_header.dh_size = sizeof(kmutant) / sizeof(uint32_t); - kmutex->km_ownerthread = NULL; -} - -static uint32_t -KeReleaseMutex(kmutant *kmutex, uint8_t kwait) -{ - uint32_t prevstate; - - mtx_lock(&ntoskrnl_dispatchlock); - prevstate = kmutex->km_header.dh_sigstate; - if (kmutex->km_ownerthread != curthread) { - mtx_unlock(&ntoskrnl_dispatchlock); - return (STATUS_MUTANT_NOT_OWNED); - } - - kmutex->km_header.dh_sigstate++; - kmutex->km_abandoned = FALSE; - - if (kmutex->km_header.dh_sigstate == 1) { - kmutex->km_ownerthread = NULL; - ntoskrnl_waittest(&kmutex->km_header, IO_NO_INCREMENT); - } - - mtx_unlock(&ntoskrnl_dispatchlock); - - return (prevstate); -} - -static uint32_t -KeReadStateMutex(kmutex) - kmutant *kmutex; -{ - return (kmutex->km_header.dh_sigstate); -} - -void -KeInitializeEvent(nt_kevent *kevent, uint32_t type, uint8_t state) -{ - InitializeListHead((&kevent->k_header.dh_waitlisthead)); - kevent->k_header.dh_sigstate = state; - if (type == EVENT_TYPE_NOTIFY) - kevent->k_header.dh_type = DISP_TYPE_NOTIFICATION_EVENT; - else - kevent->k_header.dh_type = DISP_TYPE_SYNCHRONIZATION_EVENT; - kevent->k_header.dh_size = sizeof(nt_kevent) / sizeof(uint32_t); -} - -uint32_t -KeResetEvent(kevent) - nt_kevent *kevent; -{ - uint32_t prevstate; - - mtx_lock(&ntoskrnl_dispatchlock); - prevstate = kevent->k_header.dh_sigstate; - kevent->k_header.dh_sigstate = FALSE; - mtx_unlock(&ntoskrnl_dispatchlock); - - return (prevstate); -} - -uint32_t -KeSetEvent(nt_kevent *kevent, uint32_t increment, uint8_t kwait) -{ - uint32_t prevstate; - wait_block *w; - nt_dispatch_header *dh; - struct thread *td; - wb_ext *we; - - mtx_lock(&ntoskrnl_dispatchlock); - prevstate = kevent->k_header.dh_sigstate; - dh = &kevent->k_header; - - if (IsListEmpty(&dh->dh_waitlisthead)) - /* - * If there's nobody in the waitlist, just set - * the state to signalled. - */ - dh->dh_sigstate = 1; - else { - /* - * Get the first waiter. If this is a synchronization - * event, just wake up that one thread (don't bother - * setting the state to signalled since we're supposed - * to automatically clear synchronization events anyway). - * - * If it's a notification event, or the first - * waiter is doing a WAITTYPE_ALL wait, go through - * the full wait satisfaction process. - */ - w = CONTAINING_RECORD(dh->dh_waitlisthead.nle_flink, - wait_block, wb_waitlist); - we = w->wb_ext; - td = we->we_td; - if (kevent->k_header.dh_type == DISP_TYPE_NOTIFICATION_EVENT || - w->wb_waittype == WAITTYPE_ALL) { - if (prevstate == 0) { - dh->dh_sigstate = 1; - ntoskrnl_waittest(dh, increment); - } - } else { - w->wb_awakened |= TRUE; - cv_broadcastpri(&we->we_cv, - (w->wb_oldpri - (increment * 4)) > PRI_MIN_KERN ? - w->wb_oldpri - (increment * 4) : PRI_MIN_KERN); - } - } - - mtx_unlock(&ntoskrnl_dispatchlock); - - return (prevstate); -} - -void -KeClearEvent(kevent) - nt_kevent *kevent; -{ - kevent->k_header.dh_sigstate = FALSE; -} - -uint32_t -KeReadStateEvent(kevent) - nt_kevent *kevent; -{ - return (kevent->k_header.dh_sigstate); -} - -/* - * The object manager in Windows is responsible for managing - * references and access to various types of objects, including - * device_objects, events, threads, timers and so on. However, - * there's a difference in the way objects are handled in user - * mode versus kernel mode. - * - * In user mode (i.e. Win32 applications), all objects are - * managed by the object manager. For example, when you create - * a timer or event object, you actually end up with an - * object_header (for the object manager's bookkeeping - * purposes) and an object body (which contains the actual object - * structure, e.g. ktimer, kevent, etc...). This allows Windows - * to manage resource quotas and to enforce access restrictions - * on basically every kind of system object handled by the kernel. - * - * However, in kernel mode, you only end up using the object - * manager some of the time. For example, in a driver, you create - * a timer object by simply allocating the memory for a ktimer - * structure and initializing it with KeInitializeTimer(). Hence, - * the timer has no object_header and no reference counting or - * security/resource checks are done on it. The assumption in - * this case is that if you're running in kernel mode, you know - * what you're doing, and you're already at an elevated privilege - * anyway. - * - * There are some exceptions to this. The two most important ones - * for our purposes are device_objects and threads. We need to use - * the object manager to do reference counting on device_objects, - * and for threads, you can only get a pointer to a thread's - * dispatch header by using ObReferenceObjectByHandle() on the - * handle returned by PsCreateSystemThread(). - */ - -static ndis_status -ObReferenceObjectByHandle(ndis_handle handle, uint32_t reqaccess, void *otype, - uint8_t accessmode, void **object, void **handleinfo) -{ - nt_objref *nr; - - nr = malloc(sizeof(nt_objref), M_DEVBUF, M_NOWAIT|M_ZERO); - if (nr == NULL) - return (STATUS_INSUFFICIENT_RESOURCES); - - InitializeListHead((&nr->no_dh.dh_waitlisthead)); - nr->no_obj = handle; - nr->no_dh.dh_type = DISP_TYPE_THREAD; - nr->no_dh.dh_sigstate = 0; - nr->no_dh.dh_size = (uint8_t)(sizeof(struct thread) / - sizeof(uint32_t)); - TAILQ_INSERT_TAIL(&ntoskrnl_reflist, nr, link); - *object = nr; - - return (STATUS_SUCCESS); -} - -static void -ObfDereferenceObject(object) - void *object; -{ - nt_objref *nr; - - nr = object; - TAILQ_REMOVE(&ntoskrnl_reflist, nr, link); - free(nr, M_DEVBUF); -} - -static uint32_t -ZwClose(handle) - ndis_handle handle; -{ - return (STATUS_SUCCESS); -} - -static uint32_t -WmiQueryTraceInformation(traceclass, traceinfo, infolen, reqlen, buf) - uint32_t traceclass; - void *traceinfo; - uint32_t infolen; - uint32_t reqlen; - void *buf; -{ - return (STATUS_NOT_FOUND); -} - -static uint32_t -WmiTraceMessage(uint64_t loghandle, uint32_t messageflags, - void *guid, uint16_t messagenum, ...) -{ - return (STATUS_SUCCESS); -} - -static uint32_t -IoWMIRegistrationControl(dobj, action) - device_object *dobj; - uint32_t action; -{ - return (STATUS_SUCCESS); -} - -/* - * This is here just in case the thread returns without calling - * PsTerminateSystemThread(). - */ -static void -ntoskrnl_thrfunc(arg) - void *arg; -{ - thread_context *thrctx; - uint32_t (*tfunc)(void *); - void *tctx; - uint32_t rval; - - thrctx = arg; - tfunc = thrctx->tc_thrfunc; - tctx = thrctx->tc_thrctx; - free(thrctx, M_TEMP); - - rval = MSCALL1(tfunc, tctx); - - PsTerminateSystemThread(rval); - return; /* notreached */ -} - -static ndis_status -PsCreateSystemThread(handle, reqaccess, objattrs, phandle, - clientid, thrfunc, thrctx) - ndis_handle *handle; - uint32_t reqaccess; - void *objattrs; - ndis_handle phandle; - void *clientid; - void *thrfunc; - void *thrctx; -{ - int error; - thread_context *tc; - struct proc *p; - - tc = malloc(sizeof(thread_context), M_TEMP, M_NOWAIT); - if (tc == NULL) - return (STATUS_INSUFFICIENT_RESOURCES); - - tc->tc_thrctx = thrctx; - tc->tc_thrfunc = thrfunc; - - error = kproc_create(ntoskrnl_thrfunc, tc, &p, - RFHIGHPID, NDIS_KSTACK_PAGES, "Windows Kthread %d", ntoskrnl_kth); - - if (error) { - free(tc, M_TEMP); - return (STATUS_INSUFFICIENT_RESOURCES); - } - - *handle = p; - ntoskrnl_kth++; - - return (STATUS_SUCCESS); -} - -/* - * In Windows, the exit of a thread is an event that you're allowed - * to wait on, assuming you've obtained a reference to the thread using - * ObReferenceObjectByHandle(). Unfortunately, the only way we can - * simulate this behavior is to register each thread we create in a - * reference list, and if someone holds a reference to us, we poke - * them. - */ -static ndis_status -PsTerminateSystemThread(status) - ndis_status status; -{ - struct nt_objref *nr; - - mtx_lock(&ntoskrnl_dispatchlock); - TAILQ_FOREACH(nr, &ntoskrnl_reflist, link) { - if (nr->no_obj != curthread->td_proc) - continue; - nr->no_dh.dh_sigstate = 1; - ntoskrnl_waittest(&nr->no_dh, IO_NO_INCREMENT); - break; - } - mtx_unlock(&ntoskrnl_dispatchlock); - - ntoskrnl_kth--; - - kproc_exit(0); - return (0); /* notreached */ -} - -static uint32_t -DbgPrint(char *fmt, ...) -{ - va_list ap; - - if (bootverbose) { - va_start(ap, fmt); - vprintf(fmt, ap); - va_end(ap); - } - - return (STATUS_SUCCESS); -} - -static void -DbgBreakPoint(void) -{ - - kdb_enter(KDB_WHY_NDIS, "DbgBreakPoint(): breakpoint"); -} - -static void -KeBugCheckEx(code, param1, param2, param3, param4) - uint32_t code; - u_long param1; - u_long param2; - u_long param3; - u_long param4; -{ - panic("KeBugCheckEx: STOP 0x%X", code); -} - -static void -ntoskrnl_timercall(arg) - void *arg; -{ - ktimer *timer; - struct timeval tv; - kdpc *dpc; - - mtx_lock(&ntoskrnl_dispatchlock); - - timer = arg; - -#ifdef NTOSKRNL_DEBUG_TIMERS - ntoskrnl_timer_fires++; -#endif - ntoskrnl_remove_timer(timer); - - /* - * This should never happen, but complain - * if it does. - */ - - if (timer->k_header.dh_inserted == FALSE) { - mtx_unlock(&ntoskrnl_dispatchlock); - printf("NTOS: timer %p fired even though " - "it was canceled\n", timer); - return; - } - - /* Mark the timer as no longer being on the timer queue. */ - - timer->k_header.dh_inserted = FALSE; - - /* Now signal the object and satisfy any waits on it. */ - - timer->k_header.dh_sigstate = 1; - ntoskrnl_waittest(&timer->k_header, IO_NO_INCREMENT); - - /* - * If this is a periodic timer, re-arm it - * so it will fire again. We do this before - * calling any deferred procedure calls because - * it's possible the DPC might cancel the timer, - * in which case it would be wrong for us to - * re-arm it again afterwards. - */ - - if (timer->k_period) { - tv.tv_sec = 0; - tv.tv_usec = timer->k_period * 1000; - timer->k_header.dh_inserted = TRUE; - ntoskrnl_insert_timer(timer, tvtohz(&tv)); -#ifdef NTOSKRNL_DEBUG_TIMERS - ntoskrnl_timer_reloads++; -#endif - } - - dpc = timer->k_dpc; - - mtx_unlock(&ntoskrnl_dispatchlock); - - /* If there's a DPC associated with the timer, queue it up. */ - - if (dpc != NULL) - KeInsertQueueDpc(dpc, NULL, NULL); -} - -#ifdef NTOSKRNL_DEBUG_TIMERS -static int -sysctl_show_timers(SYSCTL_HANDLER_ARGS) -{ - int ret; - - ret = 0; - ntoskrnl_show_timers(); - return (sysctl_handle_int(oidp, &ret, 0, req)); -} - -static void -ntoskrnl_show_timers() -{ - int i = 0; - list_entry *l; - - mtx_lock_spin(&ntoskrnl_calllock); - l = ntoskrnl_calllist.nle_flink; - while(l != &ntoskrnl_calllist) { - i++; - l = l->nle_flink; - } - mtx_unlock_spin(&ntoskrnl_calllock); - - printf("\n"); - printf("%d timers available (out of %d)\n", i, NTOSKRNL_TIMEOUTS); - printf("timer sets: %qu\n", ntoskrnl_timer_sets); - printf("timer reloads: %qu\n", ntoskrnl_timer_reloads); - printf("timer cancels: %qu\n", ntoskrnl_timer_cancels); - printf("timer fires: %qu\n", ntoskrnl_timer_fires); - printf("\n"); -} -#endif - -/* - * Must be called with dispatcher lock held. - */ - -static void -ntoskrnl_insert_timer(timer, ticks) - ktimer *timer; - int ticks; -{ - callout_entry *e; - list_entry *l; - struct callout *c; - - /* - * Try and allocate a timer. - */ - mtx_lock_spin(&ntoskrnl_calllock); - if (IsListEmpty(&ntoskrnl_calllist)) { - mtx_unlock_spin(&ntoskrnl_calllock); -#ifdef NTOSKRNL_DEBUG_TIMERS - ntoskrnl_show_timers(); -#endif - panic("out of timers!"); - } - l = RemoveHeadList(&ntoskrnl_calllist); - mtx_unlock_spin(&ntoskrnl_calllock); - - e = CONTAINING_RECORD(l, callout_entry, ce_list); - c = &e->ce_callout; - - timer->k_callout = c; - - callout_init(c, 1); - callout_reset(c, ticks, ntoskrnl_timercall, timer); -} - -static void -ntoskrnl_remove_timer(timer) - ktimer *timer; -{ - callout_entry *e; - - e = (callout_entry *)timer->k_callout; - callout_stop(timer->k_callout); - - mtx_lock_spin(&ntoskrnl_calllock); - InsertHeadList((&ntoskrnl_calllist), (&e->ce_list)); - mtx_unlock_spin(&ntoskrnl_calllock); -} - -void -KeInitializeTimer(timer) - ktimer *timer; -{ - if (timer == NULL) - return; - - KeInitializeTimerEx(timer, EVENT_TYPE_NOTIFY); -} - -void -KeInitializeTimerEx(timer, type) - ktimer *timer; - uint32_t type; -{ - if (timer == NULL) - return; - - bzero((char *)timer, sizeof(ktimer)); - InitializeListHead((&timer->k_header.dh_waitlisthead)); - timer->k_header.dh_sigstate = FALSE; - timer->k_header.dh_inserted = FALSE; - if (type == EVENT_TYPE_NOTIFY) - timer->k_header.dh_type = DISP_TYPE_NOTIFICATION_TIMER; - else - timer->k_header.dh_type = DISP_TYPE_SYNCHRONIZATION_TIMER; - timer->k_header.dh_size = sizeof(ktimer) / sizeof(uint32_t); -} - -/* - * DPC subsystem. A Windows Defered Procedure Call has the following - * properties: - * - It runs at DISPATCH_LEVEL. - * - It can have one of 3 importance values that control when it - * runs relative to other DPCs in the queue. - * - On SMP systems, it can be set to run on a specific processor. - * In order to satisfy the last property, we create a DPC thread for - * each CPU in the system and bind it to that CPU. Each thread - * maintains three queues with different importance levels, which - * will be processed in order from lowest to highest. - * - * In Windows, interrupt handlers run as DPCs. (Not to be confused - * with ISRs, which run in interrupt context and can preempt DPCs.) - * ISRs are given the highest importance so that they'll take - * precedence over timers and other things. - */ - -static void -ntoskrnl_dpc_thread(arg) - void *arg; -{ - kdpc_queue *kq; - kdpc *d; - list_entry *l; - uint8_t irql; - - kq = arg; - - InitializeListHead(&kq->kq_disp); - kq->kq_td = curthread; - kq->kq_exit = 0; - kq->kq_running = FALSE; - KeInitializeSpinLock(&kq->kq_lock); - KeInitializeEvent(&kq->kq_proc, EVENT_TYPE_SYNC, FALSE); - KeInitializeEvent(&kq->kq_done, EVENT_TYPE_SYNC, FALSE); - - /* - * Elevate our priority. DPCs are used to run interrupt - * handlers, and they should trigger as soon as possible - * once scheduled by an ISR. - */ - - thread_lock(curthread); -#ifdef NTOSKRNL_MULTIPLE_DPCS - sched_bind(curthread, kq->kq_cpu); -#endif - sched_prio(curthread, PRI_MIN_KERN); - thread_unlock(curthread); - - while (1) { - KeWaitForSingleObject(&kq->kq_proc, 0, 0, TRUE, NULL); - - KeAcquireSpinLock(&kq->kq_lock, &irql); - - if (kq->kq_exit) { - kq->kq_exit = 0; - KeReleaseSpinLock(&kq->kq_lock, irql); - break; - } - - kq->kq_running = TRUE; - - while (!IsListEmpty(&kq->kq_disp)) { - l = RemoveHeadList((&kq->kq_disp)); - d = CONTAINING_RECORD(l, kdpc, k_dpclistentry); - InitializeListHead((&d->k_dpclistentry)); - KeReleaseSpinLockFromDpcLevel(&kq->kq_lock); - MSCALL4(d->k_deferedfunc, d, d->k_deferredctx, - d->k_sysarg1, d->k_sysarg2); - KeAcquireSpinLockAtDpcLevel(&kq->kq_lock); - } - - kq->kq_running = FALSE; - - KeReleaseSpinLock(&kq->kq_lock, irql); - - KeSetEvent(&kq->kq_done, IO_NO_INCREMENT, FALSE); - } - - kproc_exit(0); - return; /* notreached */ -} - -static void -ntoskrnl_destroy_dpc_threads(void) -{ - kdpc_queue *kq; - kdpc dpc; - int i; - - kq = kq_queues; -#ifdef NTOSKRNL_MULTIPLE_DPCS - for (i = 0; i < mp_ncpus; i++) { -#else - for (i = 0; i < 1; i++) { -#endif - kq += i; - - kq->kq_exit = 1; - KeInitializeDpc(&dpc, NULL, NULL); - KeSetTargetProcessorDpc(&dpc, i); - KeInsertQueueDpc(&dpc, NULL, NULL); - while (kq->kq_exit) - tsleep(kq->kq_td->td_proc, PWAIT, "dpcw", hz/10); - } -} - -static uint8_t -ntoskrnl_insert_dpc(head, dpc) - list_entry *head; - kdpc *dpc; -{ - list_entry *l; - kdpc *d; - - l = head->nle_flink; - while (l != head) { - d = CONTAINING_RECORD(l, kdpc, k_dpclistentry); - if (d == dpc) - return (FALSE); - l = l->nle_flink; - } - - if (dpc->k_importance == KDPC_IMPORTANCE_LOW) - InsertTailList((head), (&dpc->k_dpclistentry)); - else - InsertHeadList((head), (&dpc->k_dpclistentry)); - - return (TRUE); -} - -void -KeInitializeDpc(dpc, dpcfunc, dpcctx) - kdpc *dpc; - void *dpcfunc; - void *dpcctx; -{ - - if (dpc == NULL) - return; - - dpc->k_deferedfunc = dpcfunc; - dpc->k_deferredctx = dpcctx; - dpc->k_num = KDPC_CPU_DEFAULT; - dpc->k_importance = KDPC_IMPORTANCE_MEDIUM; - InitializeListHead((&dpc->k_dpclistentry)); -} - -uint8_t -KeInsertQueueDpc(dpc, sysarg1, sysarg2) - kdpc *dpc; - void *sysarg1; - void *sysarg2; -{ - kdpc_queue *kq; - uint8_t r; - uint8_t irql; - - if (dpc == NULL) - return (FALSE); - - kq = kq_queues; - -#ifdef NTOSKRNL_MULTIPLE_DPCS - KeRaiseIrql(DISPATCH_LEVEL, &irql); - - /* - * By default, the DPC is queued to run on the same CPU - * that scheduled it. - */ - - if (dpc->k_num == KDPC_CPU_DEFAULT) - kq += curthread->td_oncpu; - else - kq += dpc->k_num; - KeAcquireSpinLockAtDpcLevel(&kq->kq_lock); -#else - KeAcquireSpinLock(&kq->kq_lock, &irql); -#endif - - r = ntoskrnl_insert_dpc(&kq->kq_disp, dpc); - if (r == TRUE) { - dpc->k_sysarg1 = sysarg1; - dpc->k_sysarg2 = sysarg2; - } - KeReleaseSpinLock(&kq->kq_lock, irql); - - if (r == FALSE) - return (r); - - KeSetEvent(&kq->kq_proc, IO_NO_INCREMENT, FALSE); - - return (r); -} - -uint8_t -KeRemoveQueueDpc(dpc) - kdpc *dpc; -{ - kdpc_queue *kq; - uint8_t irql; - - if (dpc == NULL) - return (FALSE); - -#ifdef NTOSKRNL_MULTIPLE_DPCS - KeRaiseIrql(DISPATCH_LEVEL, &irql); - - kq = kq_queues + dpc->k_num; - - KeAcquireSpinLockAtDpcLevel(&kq->kq_lock); -#else - kq = kq_queues; - KeAcquireSpinLock(&kq->kq_lock, &irql); -#endif - - if (dpc->k_dpclistentry.nle_flink == &dpc->k_dpclistentry) { - KeReleaseSpinLockFromDpcLevel(&kq->kq_lock); - KeLowerIrql(irql); - return (FALSE); - } - - RemoveEntryList((&dpc->k_dpclistentry)); - InitializeListHead((&dpc->k_dpclistentry)); - - KeReleaseSpinLock(&kq->kq_lock, irql); - - return (TRUE); -} - -void -KeSetImportanceDpc(dpc, imp) - kdpc *dpc; - uint32_t imp; -{ - if (imp != KDPC_IMPORTANCE_LOW && - imp != KDPC_IMPORTANCE_MEDIUM && - imp != KDPC_IMPORTANCE_HIGH) - return; - - dpc->k_importance = (uint8_t)imp; -} - -void -KeSetTargetProcessorDpc(kdpc *dpc, uint8_t cpu) -{ - if (cpu > mp_ncpus) - return; - - dpc->k_num = cpu; -} - -void -KeFlushQueuedDpcs(void) -{ - kdpc_queue *kq; - int i; - - /* - * Poke each DPC queue and wait - * for them to drain. - */ - -#ifdef NTOSKRNL_MULTIPLE_DPCS - for (i = 0; i < mp_ncpus; i++) { -#else - for (i = 0; i < 1; i++) { -#endif - kq = kq_queues + i; - KeSetEvent(&kq->kq_proc, IO_NO_INCREMENT, FALSE); - KeWaitForSingleObject(&kq->kq_done, 0, 0, TRUE, NULL); - } -} - -uint32_t -KeGetCurrentProcessorNumber(void) -{ - return ((uint32_t)curthread->td_oncpu); -} - -uint8_t -KeSetTimerEx(timer, duetime, period, dpc) - ktimer *timer; - int64_t duetime; - uint32_t period; - kdpc *dpc; -{ - struct timeval tv; - uint64_t curtime; - uint8_t pending; - - if (timer == NULL) - return (FALSE); - - mtx_lock(&ntoskrnl_dispatchlock); - - if (timer->k_header.dh_inserted == TRUE) { - ntoskrnl_remove_timer(timer); -#ifdef NTOSKRNL_DEBUG_TIMERS - ntoskrnl_timer_cancels++; -#endif - timer->k_header.dh_inserted = FALSE; - pending = TRUE; - } else - pending = FALSE; - - timer->k_duetime = duetime; - timer->k_period = period; - timer->k_header.dh_sigstate = FALSE; - timer->k_dpc = dpc; - - if (duetime < 0) { - tv.tv_sec = - (duetime) / 10000000; - tv.tv_usec = (- (duetime) / 10) - - (tv.tv_sec * 1000000); - } else { - ntoskrnl_time(&curtime); - if (duetime < curtime) - tv.tv_sec = tv.tv_usec = 0; - else { - tv.tv_sec = ((duetime) - curtime) / 10000000; - tv.tv_usec = ((duetime) - curtime) / 10 - - (tv.tv_sec * 1000000); - } - } - - timer->k_header.dh_inserted = TRUE; - ntoskrnl_insert_timer(timer, tvtohz(&tv)); -#ifdef NTOSKRNL_DEBUG_TIMERS - ntoskrnl_timer_sets++; -#endif - - mtx_unlock(&ntoskrnl_dispatchlock); - - return (pending); -} - -uint8_t -KeSetTimer(timer, duetime, dpc) - ktimer *timer; - int64_t duetime; - kdpc *dpc; -{ - return (KeSetTimerEx(timer, duetime, 0, dpc)); -} - -/* - * The Windows DDK documentation seems to say that cancelling - * a timer that has a DPC will result in the DPC also being - * cancelled, but this isn't really the case. - */ - -uint8_t -KeCancelTimer(timer) - ktimer *timer; -{ - uint8_t pending; - - if (timer == NULL) - return (FALSE); - - mtx_lock(&ntoskrnl_dispatchlock); - - pending = timer->k_header.dh_inserted; - - if (timer->k_header.dh_inserted == TRUE) { - timer->k_header.dh_inserted = FALSE; - ntoskrnl_remove_timer(timer); -#ifdef NTOSKRNL_DEBUG_TIMERS - ntoskrnl_timer_cancels++; -#endif - } - - mtx_unlock(&ntoskrnl_dispatchlock); - - return (pending); -} - -uint8_t -KeReadStateTimer(timer) - ktimer *timer; -{ - return (timer->k_header.dh_sigstate); -} - -static int32_t -KeDelayExecutionThread(uint8_t wait_mode, uint8_t alertable, int64_t *interval) -{ - ktimer timer; - - if (wait_mode != 0) - panic("invalid wait_mode %d", wait_mode); - - KeInitializeTimer(&timer); - KeSetTimer(&timer, *interval, NULL); - KeWaitForSingleObject(&timer, 0, 0, alertable, NULL); - - return STATUS_SUCCESS; -} - -static uint64_t -KeQueryInterruptTime(void) -{ - int ticks; - struct timeval tv; - - getmicrouptime(&tv); - - ticks = tvtohz(&tv); - - return ticks * howmany(10000000, hz); -} - -static struct thread * -KeGetCurrentThread(void) -{ - - return curthread; -} - -static int32_t -KeSetPriorityThread(td, pri) - struct thread *td; - int32_t pri; -{ - int32_t old; - - if (td == NULL) - return LOW_REALTIME_PRIORITY; - - if (td->td_priority <= PRI_MIN_KERN) - old = HIGH_PRIORITY; - else if (td->td_priority >= PRI_MAX_KERN) - old = LOW_PRIORITY; - else - old = LOW_REALTIME_PRIORITY; - - thread_lock(td); - if (pri == HIGH_PRIORITY) - sched_prio(td, PRI_MIN_KERN); - if (pri == LOW_REALTIME_PRIORITY) - sched_prio(td, PRI_MIN_KERN + (PRI_MAX_KERN - PRI_MIN_KERN) / 2); - if (pri == LOW_PRIORITY) - sched_prio(td, PRI_MAX_KERN); - thread_unlock(td); - - return old; -} - -static void -dummy() -{ - printf("ntoskrnl dummy called...\n"); -} - -image_patch_table ntoskrnl_functbl[] = { - IMPORT_SFUNC(RtlZeroMemory, 2), - IMPORT_SFUNC(RtlSecureZeroMemory, 2), - IMPORT_SFUNC(RtlFillMemory, 3), - IMPORT_SFUNC(RtlMoveMemory, 3), - IMPORT_SFUNC(RtlCharToInteger, 3), - IMPORT_SFUNC(RtlCopyMemory, 3), - IMPORT_SFUNC(RtlCopyString, 2), - IMPORT_SFUNC(RtlCompareMemory, 3), - IMPORT_SFUNC(RtlEqualUnicodeString, 3), - IMPORT_SFUNC(RtlCopyUnicodeString, 2), - IMPORT_SFUNC(RtlUnicodeStringToAnsiString, 3), - IMPORT_SFUNC(RtlAnsiStringToUnicodeString, 3), - IMPORT_SFUNC(RtlInitAnsiString, 2), - IMPORT_SFUNC_MAP(RtlInitString, RtlInitAnsiString, 2), - IMPORT_SFUNC(RtlInitUnicodeString, 2), - IMPORT_SFUNC(RtlFreeAnsiString, 1), - IMPORT_SFUNC(RtlFreeUnicodeString, 1), - IMPORT_SFUNC(RtlUnicodeStringToInteger, 3), - IMPORT_CFUNC(sprintf, 0), - IMPORT_CFUNC(vsprintf, 0), - IMPORT_CFUNC_MAP(_snprintf, snprintf, 0), - IMPORT_CFUNC_MAP(_vsnprintf, vsnprintf, 0), - IMPORT_CFUNC(DbgPrint, 0), - IMPORT_SFUNC(DbgBreakPoint, 0), - IMPORT_SFUNC(KeBugCheckEx, 5), - IMPORT_CFUNC(strncmp, 0), - IMPORT_CFUNC(strcmp, 0), - IMPORT_CFUNC_MAP(stricmp, strcasecmp, 0), - IMPORT_CFUNC(strncpy, 0), - IMPORT_CFUNC(strcpy, 0), - IMPORT_CFUNC(strlen, 0), - IMPORT_CFUNC_MAP(toupper, ntoskrnl_toupper, 0), - IMPORT_CFUNC_MAP(tolower, ntoskrnl_tolower, 0), - IMPORT_CFUNC_MAP(strstr, ntoskrnl_strstr, 0), - IMPORT_CFUNC_MAP(strncat, ntoskrnl_strncat, 0), - IMPORT_CFUNC_MAP(strchr, index, 0), - IMPORT_CFUNC_MAP(strrchr, rindex, 0), - IMPORT_CFUNC(memcpy, 0), - IMPORT_CFUNC_MAP(memmove, ntoskrnl_memmove, 0), - IMPORT_CFUNC_MAP(memset, ntoskrnl_memset, 0), - IMPORT_CFUNC_MAP(memchr, ntoskrnl_memchr, 0), - IMPORT_SFUNC(IoAllocateDriverObjectExtension, 4), - IMPORT_SFUNC(IoGetDriverObjectExtension, 2), - IMPORT_FFUNC(IofCallDriver, 2), - IMPORT_FFUNC(IofCompleteRequest, 2), - IMPORT_SFUNC(IoAcquireCancelSpinLock, 1), - IMPORT_SFUNC(IoReleaseCancelSpinLock, 1), - IMPORT_SFUNC(IoCancelIrp, 1), - IMPORT_SFUNC(IoConnectInterrupt, 11), - IMPORT_SFUNC(IoDisconnectInterrupt, 1), - IMPORT_SFUNC(IoCreateDevice, 7), - IMPORT_SFUNC(IoDeleteDevice, 1), - IMPORT_SFUNC(IoGetAttachedDevice, 1), - IMPORT_SFUNC(IoAttachDeviceToDeviceStack, 2), - IMPORT_SFUNC(IoDetachDevice, 1), - IMPORT_SFUNC(IoBuildSynchronousFsdRequest, 7), - IMPORT_SFUNC(IoBuildAsynchronousFsdRequest, 6), - IMPORT_SFUNC(IoBuildDeviceIoControlRequest, 9), - IMPORT_SFUNC(IoAllocateIrp, 2), - IMPORT_SFUNC(IoReuseIrp, 2), - IMPORT_SFUNC(IoMakeAssociatedIrp, 2), - IMPORT_SFUNC(IoFreeIrp, 1), - IMPORT_SFUNC(IoInitializeIrp, 3), - IMPORT_SFUNC(KeAcquireInterruptSpinLock, 1), - IMPORT_SFUNC(KeReleaseInterruptSpinLock, 2), - IMPORT_SFUNC(KeSynchronizeExecution, 3), - IMPORT_SFUNC(KeWaitForSingleObject, 5), - IMPORT_SFUNC(KeWaitForMultipleObjects, 8), - IMPORT_SFUNC(_allmul, 4), - IMPORT_SFUNC(_alldiv, 4), - IMPORT_SFUNC(_allrem, 4), - IMPORT_RFUNC(_allshr, 0), - IMPORT_RFUNC(_allshl, 0), - IMPORT_SFUNC(_aullmul, 4), - IMPORT_SFUNC(_aulldiv, 4), - IMPORT_SFUNC(_aullrem, 4), - IMPORT_RFUNC(_aullshr, 0), - IMPORT_RFUNC(_aullshl, 0), - IMPORT_CFUNC(atoi, 0), - IMPORT_CFUNC(atol, 0), - IMPORT_CFUNC(rand, 0), - IMPORT_CFUNC(srand, 0), - IMPORT_SFUNC(WRITE_REGISTER_USHORT, 2), - IMPORT_SFUNC(READ_REGISTER_USHORT, 1), - IMPORT_SFUNC(WRITE_REGISTER_ULONG, 2), - IMPORT_SFUNC(READ_REGISTER_ULONG, 1), - IMPORT_SFUNC(READ_REGISTER_UCHAR, 1), - IMPORT_SFUNC(WRITE_REGISTER_UCHAR, 2), - IMPORT_SFUNC(ExInitializePagedLookasideList, 7), - IMPORT_SFUNC(ExDeletePagedLookasideList, 1), - IMPORT_SFUNC(ExInitializeNPagedLookasideList, 7), - IMPORT_SFUNC(ExDeleteNPagedLookasideList, 1), - IMPORT_FFUNC(InterlockedPopEntrySList, 1), - IMPORT_FFUNC(InitializeSListHead, 1), - IMPORT_FFUNC(InterlockedPushEntrySList, 2), - IMPORT_SFUNC(ExQueryDepthSList, 1), - IMPORT_FFUNC_MAP(ExpInterlockedPopEntrySList, - InterlockedPopEntrySList, 1), - IMPORT_FFUNC_MAP(ExpInterlockedPushEntrySList, - InterlockedPushEntrySList, 2), - IMPORT_FFUNC(ExInterlockedPopEntrySList, 2), - IMPORT_FFUNC(ExInterlockedPushEntrySList, 3), - IMPORT_SFUNC(ExAllocatePoolWithTag, 3), - IMPORT_SFUNC(ExFreePoolWithTag, 2), - IMPORT_SFUNC(ExFreePool, 1), -#ifdef __i386__ - IMPORT_FFUNC(KefAcquireSpinLockAtDpcLevel, 1), - IMPORT_FFUNC(KefReleaseSpinLockFromDpcLevel,1), - IMPORT_FFUNC(KeAcquireSpinLockRaiseToDpc, 1), -#else - /* - * For AMD64, we can get away with just mapping - * KeAcquireSpinLockRaiseToDpc() directly to KfAcquireSpinLock() - * because the calling conventions end up being the same. - * On i386, we have to be careful because KfAcquireSpinLock() - * is _fastcall but KeAcquireSpinLockRaiseToDpc() isn't. - */ - IMPORT_SFUNC(KeAcquireSpinLockAtDpcLevel, 1), - IMPORT_SFUNC(KeReleaseSpinLockFromDpcLevel, 1), - IMPORT_SFUNC_MAP(KeAcquireSpinLockRaiseToDpc, KfAcquireSpinLock, 1), -#endif - IMPORT_SFUNC_MAP(KeReleaseSpinLock, KfReleaseSpinLock, 1), - IMPORT_FFUNC(InterlockedIncrement, 1), - IMPORT_FFUNC(InterlockedDecrement, 1), - IMPORT_FFUNC(InterlockedExchange, 2), - IMPORT_FFUNC(ExInterlockedAddLargeStatistic, 2), - IMPORT_SFUNC(IoAllocateMdl, 5), - IMPORT_SFUNC(IoFreeMdl, 1), - IMPORT_SFUNC(MmAllocateContiguousMemory, 2 + 1), - IMPORT_SFUNC(MmAllocateContiguousMemorySpecifyCache, 5 + 3), - IMPORT_SFUNC(MmFreeContiguousMemory, 1), - IMPORT_SFUNC(MmFreeContiguousMemorySpecifyCache, 3), - IMPORT_SFUNC(MmSizeOfMdl, 1), - IMPORT_SFUNC(MmMapLockedPages, 2), - IMPORT_SFUNC(MmMapLockedPagesSpecifyCache, 6), - IMPORT_SFUNC(MmUnmapLockedPages, 2), - IMPORT_SFUNC(MmBuildMdlForNonPagedPool, 1), - IMPORT_SFUNC(MmGetPhysicalAddress, 1), - IMPORT_SFUNC(MmGetSystemRoutineAddress, 1), - IMPORT_SFUNC(MmIsAddressValid, 1), - IMPORT_SFUNC(MmMapIoSpace, 3 + 1), - IMPORT_SFUNC(MmUnmapIoSpace, 2), - IMPORT_SFUNC(KeInitializeSpinLock, 1), - IMPORT_SFUNC(IoIsWdmVersionAvailable, 2), - IMPORT_SFUNC(IoOpenDeviceRegistryKey, 4), - IMPORT_SFUNC(IoGetDeviceObjectPointer, 4), - IMPORT_SFUNC(IoGetDeviceProperty, 5), - IMPORT_SFUNC(IoAllocateWorkItem, 1), - IMPORT_SFUNC(IoFreeWorkItem, 1), - IMPORT_SFUNC(IoQueueWorkItem, 4), - IMPORT_SFUNC(ExQueueWorkItem, 2), - IMPORT_SFUNC(ntoskrnl_workitem, 2), - IMPORT_SFUNC(KeInitializeMutex, 2), - IMPORT_SFUNC(KeReleaseMutex, 2), - IMPORT_SFUNC(KeReadStateMutex, 1), - IMPORT_SFUNC(KeInitializeEvent, 3), - IMPORT_SFUNC(KeSetEvent, 3), - IMPORT_SFUNC(KeResetEvent, 1), - IMPORT_SFUNC(KeClearEvent, 1), - IMPORT_SFUNC(KeReadStateEvent, 1), - IMPORT_SFUNC(KeInitializeTimer, 1), - IMPORT_SFUNC(KeInitializeTimerEx, 2), - IMPORT_SFUNC(KeSetTimer, 3), - IMPORT_SFUNC(KeSetTimerEx, 4), - IMPORT_SFUNC(KeCancelTimer, 1), - IMPORT_SFUNC(KeReadStateTimer, 1), - IMPORT_SFUNC(KeInitializeDpc, 3), - IMPORT_SFUNC(KeInsertQueueDpc, 3), - IMPORT_SFUNC(KeRemoveQueueDpc, 1), - IMPORT_SFUNC(KeSetImportanceDpc, 2), - IMPORT_SFUNC(KeSetTargetProcessorDpc, 2), - IMPORT_SFUNC(KeFlushQueuedDpcs, 0), - IMPORT_SFUNC(KeGetCurrentProcessorNumber, 1), - IMPORT_SFUNC(ObReferenceObjectByHandle, 6), - IMPORT_FFUNC(ObfDereferenceObject, 1), - IMPORT_SFUNC(ZwClose, 1), - IMPORT_SFUNC(PsCreateSystemThread, 7), - IMPORT_SFUNC(PsTerminateSystemThread, 1), - IMPORT_SFUNC(IoWMIRegistrationControl, 2), - IMPORT_SFUNC(WmiQueryTraceInformation, 5), - IMPORT_CFUNC(WmiTraceMessage, 0), - IMPORT_SFUNC(KeQuerySystemTime, 1), - IMPORT_CFUNC(KeTickCount, 0), - IMPORT_SFUNC(KeDelayExecutionThread, 3), - IMPORT_SFUNC(KeQueryInterruptTime, 0), - IMPORT_SFUNC(KeGetCurrentThread, 0), - IMPORT_SFUNC(KeSetPriorityThread, 2), - - /* - * This last entry is a catch-all for any function we haven't - * implemented yet. The PE import list patching routine will - * use it for any function that doesn't have an explicit match - * in this table. - */ - - { NULL, (FUNC)dummy, NULL, 0, WINDRV_WRAP_STDCALL }, - - /* End of list. */ - { NULL, NULL, NULL } -}; diff --git a/sys/compat/ndis/subr_pe.c b/sys/compat/ndis/subr_pe.c deleted file mode 100644 index 1cd698fdd51c..000000000000 --- a/sys/compat/ndis/subr_pe.c +++ /dev/null @@ -1,644 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul . 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 -__FBSDID("$FreeBSD$"); - -/* - * This file contains routines for relocating and dynamically linking - * executable object code files in the Windows(r) PE (Portable Executable) - * format. In Windows, anything with a .EXE, .DLL or .SYS extension is - * considered an executable, and all such files have some structures in - * common. The PE format was apparently based largely on COFF but has - * mutated significantly over time. We are mainly concerned with .SYS files, - * so this module implements only enough routines to be able to parse the - * headers and sections of a .SYS object file and perform the necessary - * relocations and jump table patching to allow us to call into it - * (and to have it call back to us). Note that while this module - * can handle fixups for imported symbols, it knows nothing about - * exporting them. - */ - -#include -#include -#include -#ifdef _KERNEL -#include -#else -#include -#include -#include -#include -#include -#endif - -#include - -static vm_offset_t pe_functbl_match(image_patch_table *, char *); - -/* - * Check for an MS-DOS executable header. All Windows binaries - * have a small MS-DOS executable prepended to them to print out - * the "This program requires Windows" message. Even .SYS files - * have this header, in spite of the fact that you're can't actually - * run them directly. - */ - -int -pe_get_dos_header(imgbase, hdr) - vm_offset_t imgbase; - image_dos_header *hdr; -{ - uint16_t signature; - - if (imgbase == 0 || hdr == NULL) - return (EINVAL); - - signature = *(uint16_t *)imgbase; - if (signature != IMAGE_DOS_SIGNATURE) - return (ENOEXEC); - - bcopy ((char *)imgbase, (char *)hdr, sizeof(image_dos_header)); - - return (0); -} - -/* - * Verify that this image has a Windows NT PE signature. - */ - -int -pe_is_nt_image(imgbase) - vm_offset_t imgbase; -{ - uint32_t signature; - image_dos_header *dos_hdr; - - if (imgbase == 0) - return (EINVAL); - - signature = *(uint16_t *)imgbase; - if (signature == IMAGE_DOS_SIGNATURE) { - dos_hdr = (image_dos_header *)imgbase; - signature = *(uint32_t *)(imgbase + dos_hdr->idh_lfanew); - if (signature == IMAGE_NT_SIGNATURE) - return (0); - } - - return (ENOEXEC); -} - -/* - * Return a copy of the optional header. This contains the - * executable entry point and the directory listing which we - * need to find the relocations and imports later. - */ - -int -pe_get_optional_header(imgbase, hdr) - vm_offset_t imgbase; - image_optional_header *hdr; -{ - image_dos_header *dos_hdr; - image_nt_header *nt_hdr; - - if (imgbase == 0 || hdr == NULL) - return (EINVAL); - - if (pe_is_nt_image(imgbase)) - return (EINVAL); - - dos_hdr = (image_dos_header *)(imgbase); - nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew); - - bcopy ((char *)&nt_hdr->inh_optionalhdr, (char *)hdr, - nt_hdr->inh_filehdr.ifh_optionalhdrlen); - - return (0); -} - -/* - * Return a copy of the file header. Contains the number of - * sections in this image. - */ - -int -pe_get_file_header(imgbase, hdr) - vm_offset_t imgbase; - image_file_header *hdr; -{ - image_dos_header *dos_hdr; - image_nt_header *nt_hdr; - - if (imgbase == 0 || hdr == NULL) - return (EINVAL); - - if (pe_is_nt_image(imgbase)) - return (EINVAL); - - dos_hdr = (image_dos_header *)imgbase; - nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew); - - /* - * Note: the size of the nt_header is variable since it - * can contain optional fields, as indicated by ifh_optionalhdrlen. - * However it happens we're only interested in fields in the - * non-variant portion of the nt_header structure, so we don't - * bother copying the optional parts here. - */ - - bcopy ((char *)&nt_hdr->inh_filehdr, (char *)hdr, - sizeof(image_file_header)); - - return (0); -} - -/* - * Return the header of the first section in this image (usually - * .text). - */ - -int -pe_get_section_header(imgbase, hdr) - vm_offset_t imgbase; - image_section_header *hdr; -{ - image_dos_header *dos_hdr; - image_nt_header *nt_hdr; - image_section_header *sect_hdr; - - if (imgbase == 0 || hdr == NULL) - return (EINVAL); - - if (pe_is_nt_image(imgbase)) - return (EINVAL); - - dos_hdr = (image_dos_header *)imgbase; - nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew); - sect_hdr = IMAGE_FIRST_SECTION(nt_hdr); - - bcopy ((char *)sect_hdr, (char *)hdr, sizeof(image_section_header)); - - return (0); -} - -/* - * Return the number of sections in this executable, or 0 on error. - */ - -int -pe_numsections(imgbase) - vm_offset_t imgbase; -{ - image_file_header file_hdr; - - if (pe_get_file_header(imgbase, &file_hdr)) - return (0); - - return (file_hdr.ifh_numsections); -} - -/* - * Return the base address that this image was linked for. - * This helps us calculate relocation addresses later. - */ - -vm_offset_t -pe_imagebase(imgbase) - vm_offset_t imgbase; -{ - image_optional_header optional_hdr; - - if (pe_get_optional_header(imgbase, &optional_hdr)) - return (0); - - return (optional_hdr.ioh_imagebase); -} - -/* - * Return the offset of a given directory structure within the - * image. Directories reside within sections. - */ - -vm_offset_t -pe_directory_offset(imgbase, diridx) - vm_offset_t imgbase; - uint32_t diridx; -{ - image_optional_header opt_hdr; - vm_offset_t dir; - - if (pe_get_optional_header(imgbase, &opt_hdr)) - return (0); - - if (diridx >= opt_hdr.ioh_rva_size_cnt) - return (0); - - dir = opt_hdr.ioh_datadir[diridx].idd_vaddr; - - return (pe_translate_addr(imgbase, dir)); -} - -vm_offset_t -pe_translate_addr(imgbase, rva) - vm_offset_t imgbase; - vm_offset_t rva; -{ - image_optional_header opt_hdr; - image_section_header *sect_hdr; - image_dos_header *dos_hdr; - image_nt_header *nt_hdr; - int i = 0, sections, fixedlen; - - if (pe_get_optional_header(imgbase, &opt_hdr)) - return (0); - - sections = pe_numsections(imgbase); - - dos_hdr = (image_dos_header *)imgbase; - nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew); - sect_hdr = IMAGE_FIRST_SECTION(nt_hdr); - - /* - * The test here is to see if the RVA falls somewhere - * inside the section, based on the section's start RVA - * and its length. However it seems sometimes the - * virtual length isn't enough to cover the entire - * area of the section. We fudge by taking into account - * the section alignment and rounding the section length - * up to a page boundary. - */ - while (i++ < sections) { - fixedlen = sect_hdr->ish_misc.ish_vsize; - fixedlen += ((opt_hdr.ioh_sectalign - 1) - - sect_hdr->ish_misc.ish_vsize) & - (opt_hdr.ioh_sectalign - 1); - if (sect_hdr->ish_vaddr <= (uint32_t)rva && - (sect_hdr->ish_vaddr + fixedlen) > - (uint32_t)rva) - break; - sect_hdr++; - } - - if (i > sections) - return (0); - - return ((vm_offset_t)(imgbase + rva - sect_hdr->ish_vaddr + - sect_hdr->ish_rawdataaddr)); -} - -/* - * Get the section header for a particular section. Note that - * section names can be anything, but there are some standard - * ones (.text, .data, .rdata, .reloc). - */ - -int -pe_get_section(imgbase, hdr, name) - vm_offset_t imgbase; - image_section_header *hdr; - const char *name; -{ - image_dos_header *dos_hdr; - image_nt_header *nt_hdr; - image_section_header *sect_hdr; - - int i, sections; - - if (imgbase == 0 || hdr == NULL) - return (EINVAL); - - if (pe_is_nt_image(imgbase)) - return (EINVAL); - - sections = pe_numsections(imgbase); - - dos_hdr = (image_dos_header *)imgbase; - nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew); - sect_hdr = IMAGE_FIRST_SECTION(nt_hdr); - - for (i = 0; i < sections; i++) { - if (!strcmp ((char *)§_hdr->ish_name, name)) { - bcopy((char *)sect_hdr, (char *)hdr, - sizeof(image_section_header)); - return (0); - } else - sect_hdr++; - } - - return (ENOEXEC); -} - -/* - * Apply the base relocations to this image. The relocation table - * resides within the .reloc section. Relocations are specified in - * blocks which refer to a particular page. We apply the relocations - * one page block at a time. - */ - -int -pe_relocate(imgbase) - vm_offset_t imgbase; -{ - image_section_header sect; - image_base_reloc *relhdr; - uint16_t rel, *sloc; - vm_offset_t base; - vm_size_t delta; - uint32_t *lloc; - uint64_t *qloc; - int i, count; - vm_offset_t txt; - - base = pe_imagebase(imgbase); - pe_get_section(imgbase, §, ".text"); - txt = pe_translate_addr(imgbase, sect.ish_vaddr); - delta = (uint32_t)(txt) - base - sect.ish_vaddr; - - pe_get_section(imgbase, §, ".reloc"); - - relhdr = (image_base_reloc *)(imgbase + sect.ish_rawdataaddr); - - do { - count = (relhdr->ibr_blocksize - - (sizeof(uint32_t) * 2)) / sizeof(uint16_t); - for (i = 0; i < count; i++) { - rel = relhdr->ibr_rel[i]; - switch (IMR_RELTYPE(rel)) { - case IMAGE_REL_BASED_ABSOLUTE: - break; - case IMAGE_REL_BASED_HIGHLOW: - lloc = (uint32_t *)pe_translate_addr(imgbase, - relhdr->ibr_vaddr + IMR_RELOFFSET(rel)); - *lloc = pe_translate_addr(imgbase, - (*lloc - base)); - break; - case IMAGE_REL_BASED_HIGH: - sloc = (uint16_t *)pe_translate_addr(imgbase, - relhdr->ibr_vaddr + IMR_RELOFFSET(rel)); - *sloc += (delta & 0xFFFF0000) >> 16; - break; - case IMAGE_REL_BASED_LOW: - sloc = (uint16_t *)pe_translate_addr(imgbase, - relhdr->ibr_vaddr + IMR_RELOFFSET(rel)); - *sloc += (delta & 0xFFFF); - break; - case IMAGE_REL_BASED_DIR64: - qloc = (uint64_t *)pe_translate_addr(imgbase, - relhdr->ibr_vaddr + IMR_RELOFFSET(rel)); - *qloc = pe_translate_addr(imgbase, - (*qloc - base)); - break; - - default: - printf("[%d]reloc type: %d\n",i, - IMR_RELTYPE(rel)); - break; - } - } - relhdr = (image_base_reloc *)((vm_offset_t)relhdr + - relhdr->ibr_blocksize); - } while (relhdr->ibr_blocksize); - - return (0); -} - -/* - * Return the import descriptor for a particular module. An image - * may be linked against several modules, typically HAL.dll, ntoskrnl.exe - * and NDIS.SYS. For each module, there is a list of imported function - * names and their addresses. - * - * Note: module names are case insensitive! - */ - -int -pe_get_import_descriptor(imgbase, desc, module) - vm_offset_t imgbase; - image_import_descriptor *desc; - char *module; -{ - vm_offset_t offset; - image_import_descriptor *imp_desc; - char *modname; - - if (imgbase == 0 || module == NULL || desc == NULL) - return (EINVAL); - - offset = pe_directory_offset(imgbase, IMAGE_DIRECTORY_ENTRY_IMPORT); - if (offset == 0) - return (ENOENT); - - imp_desc = (void *)offset; - - while (imp_desc->iid_nameaddr) { - modname = (char *)pe_translate_addr(imgbase, - imp_desc->iid_nameaddr); - if (!strncasecmp(module, modname, strlen(module))) { - bcopy((char *)imp_desc, (char *)desc, - sizeof(image_import_descriptor)); - return (0); - } - imp_desc++; - } - - return (ENOENT); -} - -int -pe_get_messagetable(imgbase, md) - vm_offset_t imgbase; - message_resource_data **md; -{ - image_resource_directory *rdir, *rtype; - image_resource_directory_entry *dent, *dent2; - image_resource_data_entry *rent; - vm_offset_t offset; - int i; - - if (imgbase == 0) - return (EINVAL); - - offset = pe_directory_offset(imgbase, IMAGE_DIRECTORY_ENTRY_RESOURCE); - if (offset == 0) - return (ENOENT); - - rdir = (image_resource_directory *)offset; - - dent = (image_resource_directory_entry *)(offset + - sizeof(image_resource_directory)); - - for (i = 0; i < rdir->ird_id_entries; i++){ - if (dent->irde_name != RT_MESSAGETABLE) { - dent++; - continue; - } - dent2 = dent; - while (dent2->irde_dataoff & RESOURCE_DIR_FLAG) { - rtype = (image_resource_directory *)(offset + - (dent2->irde_dataoff & ~RESOURCE_DIR_FLAG)); - dent2 = (image_resource_directory_entry *) - ((uintptr_t)rtype + - sizeof(image_resource_directory)); - } - rent = (image_resource_data_entry *)(offset + - dent2->irde_dataoff); - *md = (message_resource_data *)pe_translate_addr(imgbase, - rent->irde_offset); - return (0); - } - - return (ENOENT); -} - -int -pe_get_message(imgbase, id, str, len, flags) - vm_offset_t imgbase; - uint32_t id; - char **str; - int *len; - uint16_t *flags; -{ - message_resource_data *md = NULL; - message_resource_block *mb; - message_resource_entry *me; - uint32_t i; - - pe_get_messagetable(imgbase, &md); - - if (md == NULL) - return (ENOENT); - - mb = (message_resource_block *)((uintptr_t)md + - sizeof(message_resource_data)); - - for (i = 0; i < md->mrd_numblocks; i++) { - if (id >= mb->mrb_lowid && id <= mb->mrb_highid) { - me = (message_resource_entry *)((uintptr_t)md + - mb->mrb_entryoff); - for (i = id - mb->mrb_lowid; i > 0; i--) - me = (message_resource_entry *)((uintptr_t)me + - me->mre_len); - *str = me->mre_text; - *len = me->mre_len; - *flags = me->mre_flags; - return (0); - } - mb++; - } - - return (ENOENT); -} - -/* - * Find the function that matches a particular name. This doesn't - * need to be particularly speedy since it's only run when loading - * a module for the first time. - */ - -static vm_offset_t -pe_functbl_match(functbl, name) - image_patch_table *functbl; - char *name; -{ - image_patch_table *p; - - if (functbl == NULL || name == NULL) - return (0); - - p = functbl; - - while (p->ipt_name != NULL) { - if (!strcmp(p->ipt_name, name)) - return ((vm_offset_t)p->ipt_wrap); - p++; - } - printf("no match for %s\n", name); - - /* - * Return the wrapper pointer for this routine. - * For x86, this is the same as the funcptr. - * For amd64, this points to a wrapper routine - * that does calling convention translation and - * then invokes the underlying routine. - */ - return ((vm_offset_t)p->ipt_wrap); -} - -/* - * Patch the imported function addresses for a given module. - * The caller must specify the module name and provide a table - * of function pointers that will be patched into the jump table. - * Note that there are actually two copies of the jump table: one - * copy is left alone. In a .SYS file, the jump tables are usually - * merged into the INIT segment. - */ - -int -pe_patch_imports(imgbase, module, functbl) - vm_offset_t imgbase; - char *module; - image_patch_table *functbl; -{ - image_import_descriptor imp_desc; - char *fname; - vm_offset_t *nptr, *fptr; - vm_offset_t func; - - if (imgbase == 0 || module == NULL || functbl == NULL) - return (EINVAL); - - if (pe_get_import_descriptor(imgbase, &imp_desc, module)) - return (ENOEXEC); - - nptr = (vm_offset_t *)pe_translate_addr(imgbase, - imp_desc.iid_import_name_table_addr); - fptr = (vm_offset_t *)pe_translate_addr(imgbase, - imp_desc.iid_import_address_table_addr); - - while (nptr != NULL && pe_translate_addr(imgbase, *nptr)) { - fname = (char *)pe_translate_addr(imgbase, (*nptr) + 2); - func = pe_functbl_match(functbl, fname); - if (func) - *fptr = func; -#ifdef notdef - if (*fptr == 0) - return (ENOENT); -#endif - nptr++; - fptr++; - } - - return (0); -} diff --git a/sys/compat/ndis/subr_usbd.c b/sys/compat/ndis/subr_usbd.c deleted file mode 100644 index 114a2640ea7e..000000000000 --- a/sys/compat/ndis/subr_usbd.c +++ /dev/null @@ -1,1461 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2005 - * Bill Paul . 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -static driver_object usbd_driver; -static usb_callback_t usbd_non_isoc_callback; -static usb_callback_t usbd_ctrl_callback; - -#define USBD_CTRL_READ_PIPE 0 -#define USBD_CTRL_WRITE_PIPE 1 -#define USBD_CTRL_MAX_PIPE 2 -#define USBD_CTRL_READ_BUFFER_SP 256 -#define USBD_CTRL_WRITE_BUFFER_SP 256 -#define USBD_CTRL_READ_BUFFER_SIZE \ - (sizeof(struct usb_device_request) + USBD_CTRL_READ_BUFFER_SP) -#define USBD_CTRL_WRITE_BUFFER_SIZE \ - (sizeof(struct usb_device_request) + USBD_CTRL_WRITE_BUFFER_SP) -static struct usb_config usbd_default_epconfig[USBD_CTRL_MAX_PIPE] = { - [USBD_CTRL_READ_PIPE] = { - .type = UE_CONTROL, - .endpoint = 0x00, /* control pipe */ - .direction = UE_DIR_ANY, - .if_index = 0, - .bufsize = USBD_CTRL_READ_BUFFER_SIZE, - .flags = { .short_xfer_ok = 1, }, - .callback = &usbd_ctrl_callback, - .timeout = 5000, /* 5 seconds */ - }, - [USBD_CTRL_WRITE_PIPE] = { - .type = UE_CONTROL, - .endpoint = 0x00, /* control pipe */ - .direction = UE_DIR_ANY, - .if_index = 0, - .bufsize = USBD_CTRL_WRITE_BUFFER_SIZE, - .flags = { .proxy_buffer = 1, }, - .callback = &usbd_ctrl_callback, - .timeout = 5000, /* 5 seconds */ - } -}; - -static int32_t usbd_func_bulkintr(irp *); -static int32_t usbd_func_vendorclass(irp *); -static int32_t usbd_func_selconf(irp *); -static int32_t usbd_func_abort_pipe(irp *); -static usb_error_t usbd_setup_endpoint(irp *, uint8_t, - struct usb_endpoint_descriptor *); -static usb_error_t usbd_setup_endpoint_default(irp *, uint8_t); -static usb_error_t usbd_setup_endpoint_one(irp *, uint8_t, - struct ndisusb_ep *, struct usb_config *); -static int32_t usbd_func_getdesc(irp *); -static union usbd_urb *usbd_geturb(irp *); -static struct ndisusb_ep*usbd_get_ndisep(irp *, usb_endpoint_descriptor_t *); -static int32_t usbd_iodispatch(device_object *, irp *); -static int32_t usbd_ioinvalid(device_object *, irp *); -static int32_t usbd_pnp(device_object *, irp *); -static int32_t usbd_power(device_object *, irp *); -static void usbd_irpcancel(device_object *, irp *); -static int32_t usbd_submit_urb(irp *); -static int32_t usbd_urb2nt(int32_t); -static void usbd_task(device_object *, void *); -static int32_t usbd_taskadd(irp *, unsigned); -static void usbd_xfertask(device_object *, void *); -static void dummy(void); - -static union usbd_urb *USBD_CreateConfigurationRequestEx( - usb_config_descriptor_t *, - struct usbd_interface_list_entry *); -static union usbd_urb *USBD_CreateConfigurationRequest( - usb_config_descriptor_t *, - uint16_t *); -static void USBD_GetUSBDIVersion(usbd_version_info *); -static usb_interface_descriptor_t *USBD_ParseConfigurationDescriptorEx( - usb_config_descriptor_t *, void *, int32_t, int32_t, - int32_t, int32_t, int32_t); -static usb_interface_descriptor_t *USBD_ParseConfigurationDescriptor( - usb_config_descriptor_t *, uint8_t, uint8_t); - -/* - * We need to wrap these functions because these need `context switch' from - * Windows to UNIX before it's called. - */ -static funcptr usbd_iodispatch_wrap; -static funcptr usbd_ioinvalid_wrap; -static funcptr usbd_pnp_wrap; -static funcptr usbd_power_wrap; -static funcptr usbd_irpcancel_wrap; -static funcptr usbd_task_wrap; -static funcptr usbd_xfertask_wrap; - -int -usbd_libinit(void) -{ - image_patch_table *patch; - int i; - - patch = usbd_functbl; - while (patch->ipt_func != NULL) { - windrv_wrap((funcptr)patch->ipt_func, - (funcptr *)&patch->ipt_wrap, - patch->ipt_argcnt, patch->ipt_ftype); - patch++; - } - - windrv_wrap((funcptr)usbd_ioinvalid, - (funcptr *)&usbd_ioinvalid_wrap, 2, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)usbd_iodispatch, - (funcptr *)&usbd_iodispatch_wrap, 2, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)usbd_pnp, - (funcptr *)&usbd_pnp_wrap, 2, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)usbd_power, - (funcptr *)&usbd_power_wrap, 2, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)usbd_irpcancel, - (funcptr *)&usbd_irpcancel_wrap, 2, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)usbd_task, - (funcptr *)&usbd_task_wrap, 2, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)usbd_xfertask, - (funcptr *)&usbd_xfertask_wrap, 2, WINDRV_WRAP_STDCALL); - - /* Create a fake USB driver instance. */ - - windrv_bus_attach(&usbd_driver, "USB Bus"); - - /* Set up our dipatch routine. */ - for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) - usbd_driver.dro_dispatch[i] = - (driver_dispatch)usbd_ioinvalid_wrap; - - usbd_driver.dro_dispatch[IRP_MJ_INTERNAL_DEVICE_CONTROL] = - (driver_dispatch)usbd_iodispatch_wrap; - usbd_driver.dro_dispatch[IRP_MJ_DEVICE_CONTROL] = - (driver_dispatch)usbd_iodispatch_wrap; - usbd_driver.dro_dispatch[IRP_MJ_POWER] = - (driver_dispatch)usbd_power_wrap; - usbd_driver.dro_dispatch[IRP_MJ_PNP] = - (driver_dispatch)usbd_pnp_wrap; - - return (0); -} - -int -usbd_libfini(void) -{ - image_patch_table *patch; - - patch = usbd_functbl; - while (patch->ipt_func != NULL) { - windrv_unwrap(patch->ipt_wrap); - patch++; - } - - windrv_unwrap(usbd_ioinvalid_wrap); - windrv_unwrap(usbd_iodispatch_wrap); - windrv_unwrap(usbd_pnp_wrap); - windrv_unwrap(usbd_power_wrap); - windrv_unwrap(usbd_irpcancel_wrap); - windrv_unwrap(usbd_task_wrap); - windrv_unwrap(usbd_xfertask_wrap); - - free(usbd_driver.dro_drivername.us_buf, M_DEVBUF); - - return (0); -} - -static int32_t -usbd_iodispatch(device_object *dobj, irp *ip) -{ - device_t dev = dobj->do_devext; - int32_t status; - struct io_stack_location *irp_sl; - - irp_sl = IoGetCurrentIrpStackLocation(ip); - switch (irp_sl->isl_parameters.isl_ioctl.isl_iocode) { - case IOCTL_INTERNAL_USB_SUBMIT_URB: - IRP_NDIS_DEV(ip) = dev; - - status = usbd_submit_urb(ip); - break; - default: - device_printf(dev, "ioctl 0x%x isn't supported\n", - irp_sl->isl_parameters.isl_ioctl.isl_iocode); - status = USBD_STATUS_NOT_SUPPORTED; - break; - } - - if (status == USBD_STATUS_PENDING) - return (STATUS_PENDING); - - ip->irp_iostat.isb_status = usbd_urb2nt(status); - if (status != USBD_STATUS_SUCCESS) - ip->irp_iostat.isb_info = 0; - return (ip->irp_iostat.isb_status); -} - -static int32_t -usbd_ioinvalid(device_object *dobj, irp *ip) -{ - device_t dev = dobj->do_devext; - struct io_stack_location *irp_sl; - - irp_sl = IoGetCurrentIrpStackLocation(ip); - device_printf(dev, "invalid I/O dispatch %d:%d\n", irp_sl->isl_major, - irp_sl->isl_minor); - - ip->irp_iostat.isb_status = STATUS_FAILURE; - ip->irp_iostat.isb_info = 0; - - IoCompleteRequest(ip, IO_NO_INCREMENT); - - return (STATUS_FAILURE); -} - -static int32_t -usbd_pnp(device_object *dobj, irp *ip) -{ - device_t dev = dobj->do_devext; - struct io_stack_location *irp_sl; - - irp_sl = IoGetCurrentIrpStackLocation(ip); - device_printf(dev, "%s: unsupported I/O dispatch %d:%d\n", - __func__, irp_sl->isl_major, irp_sl->isl_minor); - - ip->irp_iostat.isb_status = STATUS_FAILURE; - ip->irp_iostat.isb_info = 0; - - IoCompleteRequest(ip, IO_NO_INCREMENT); - - return (STATUS_FAILURE); -} - -static int32_t -usbd_power(device_object *dobj, irp *ip) -{ - device_t dev = dobj->do_devext; - struct io_stack_location *irp_sl; - - irp_sl = IoGetCurrentIrpStackLocation(ip); - device_printf(dev, "%s: unsupported I/O dispatch %d:%d\n", - __func__, irp_sl->isl_major, irp_sl->isl_minor); - - ip->irp_iostat.isb_status = STATUS_FAILURE; - ip->irp_iostat.isb_info = 0; - - IoCompleteRequest(ip, IO_NO_INCREMENT); - - return (STATUS_FAILURE); -} - -/* Convert USBD_STATUS to NTSTATUS */ -static int32_t -usbd_urb2nt(int32_t status) -{ - - switch (status) { - case USBD_STATUS_SUCCESS: - return (STATUS_SUCCESS); - case USBD_STATUS_DEVICE_GONE: - return (STATUS_DEVICE_NOT_CONNECTED); - case USBD_STATUS_PENDING: - return (STATUS_PENDING); - case USBD_STATUS_NOT_SUPPORTED: - return (STATUS_NOT_IMPLEMENTED); - case USBD_STATUS_NO_MEMORY: - return (STATUS_NO_MEMORY); - case USBD_STATUS_REQUEST_FAILED: - return (STATUS_NOT_SUPPORTED); - case USBD_STATUS_CANCELED: - return (STATUS_CANCELLED); - default: - break; - } - - return (STATUS_FAILURE); -} - -/* Convert FreeBSD's usb_error_t to USBD_STATUS */ -static int32_t -usbd_usb2urb(int status) -{ - - switch (status) { - case USB_ERR_NORMAL_COMPLETION: - return (USBD_STATUS_SUCCESS); - case USB_ERR_PENDING_REQUESTS: - return (USBD_STATUS_PENDING); - case USB_ERR_TIMEOUT: - return (USBD_STATUS_TIMEOUT); - case USB_ERR_SHORT_XFER: - return (USBD_STATUS_ERROR_SHORT_TRANSFER); - case USB_ERR_IOERROR: - return (USBD_STATUS_XACT_ERROR); - case USB_ERR_NOMEM: - return (USBD_STATUS_NO_MEMORY); - case USB_ERR_INVAL: - return (USBD_STATUS_REQUEST_FAILED); - case USB_ERR_NOT_STARTED: - case USB_ERR_TOO_DEEP: - case USB_ERR_NO_POWER: - return (USBD_STATUS_DEVICE_GONE); - case USB_ERR_CANCELLED: - return (USBD_STATUS_CANCELED); - default: - break; - } - - return (USBD_STATUS_NOT_SUPPORTED); -} - -static union usbd_urb * -usbd_geturb(irp *ip) -{ - struct io_stack_location *irp_sl; - - irp_sl = IoGetCurrentIrpStackLocation(ip); - - return (irp_sl->isl_parameters.isl_others.isl_arg1); -} - -static int32_t -usbd_submit_urb(irp *ip) -{ - device_t dev = IRP_NDIS_DEV(ip); - int32_t status; - union usbd_urb *urb; - - urb = usbd_geturb(ip); - /* - * In a case of URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER, - * USBD_URB_STATUS(urb) would be set at callback functions like - * usbd_intr() or usbd_xfereof(). - */ - switch (urb->uu_hdr.uuh_func) { - case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: - status = usbd_func_bulkintr(ip); - if (status != USBD_STATUS_SUCCESS && - status != USBD_STATUS_PENDING) - USBD_URB_STATUS(urb) = status; - break; - case URB_FUNCTION_VENDOR_DEVICE: - case URB_FUNCTION_VENDOR_INTERFACE: - case URB_FUNCTION_VENDOR_ENDPOINT: - case URB_FUNCTION_VENDOR_OTHER: - case URB_FUNCTION_CLASS_DEVICE: - case URB_FUNCTION_CLASS_INTERFACE: - case URB_FUNCTION_CLASS_ENDPOINT: - case URB_FUNCTION_CLASS_OTHER: - status = usbd_func_vendorclass(ip); - USBD_URB_STATUS(urb) = status; - break; - case URB_FUNCTION_SELECT_CONFIGURATION: - status = usbd_func_selconf(ip); - USBD_URB_STATUS(urb) = status; - break; - case URB_FUNCTION_ABORT_PIPE: - status = usbd_func_abort_pipe(ip); - USBD_URB_STATUS(urb) = status; - break; - case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: - status = usbd_func_getdesc(ip); - USBD_URB_STATUS(urb) = status; - break; - default: - device_printf(dev, "func 0x%x isn't supported\n", - urb->uu_hdr.uuh_func); - USBD_URB_STATUS(urb) = status = USBD_STATUS_NOT_SUPPORTED; - break; - } - - return (status); -} - -static int32_t -usbd_func_getdesc(irp *ip) -{ -#define NDISUSB_GETDESC_MAXRETRIES 3 - device_t dev = IRP_NDIS_DEV(ip); - struct ndis_softc *sc = device_get_softc(dev); - struct usbd_urb_control_descriptor_request *ctldesc; - uint16_t actlen; - uint32_t len; - union usbd_urb *urb; - usb_config_descriptor_t *cdp; - usb_error_t status; - - urb = usbd_geturb(ip); - ctldesc = &urb->uu_ctldesc; - if (ctldesc->ucd_desctype == UDESC_CONFIG) { - /* - * The NDIS driver is not allowed to change the - * config! There is only one choice! - */ - cdp = usbd_get_config_descriptor(sc->ndisusb_dev); - if (cdp == NULL) { - status = USB_ERR_INVAL; - goto exit; - } - if (cdp->bDescriptorType != UDESC_CONFIG) { - device_printf(dev, "bad desc %d\n", - cdp->bDescriptorType); - status = USB_ERR_INVAL; - goto exit; - } - /* get minimum length */ - len = MIN(UGETW(cdp->wTotalLength), ctldesc->ucd_trans_buflen); - /* copy out config descriptor */ - memcpy(ctldesc->ucd_trans_buf, cdp, len); - /* set actual length */ - actlen = len; - status = USB_ERR_NORMAL_COMPLETION; - } else { - NDISUSB_LOCK(sc); - status = usbd_req_get_desc(sc->ndisusb_dev, &sc->ndisusb_mtx, - &actlen, ctldesc->ucd_trans_buf, 2, - ctldesc->ucd_trans_buflen, ctldesc->ucd_langid, - ctldesc->ucd_desctype, ctldesc->ucd_idx, - NDISUSB_GETDESC_MAXRETRIES); - NDISUSB_UNLOCK(sc); - } -exit: - if (status != USB_ERR_NORMAL_COMPLETION) { - ctldesc->ucd_trans_buflen = 0; - return usbd_usb2urb(status); - } - - ctldesc->ucd_trans_buflen = actlen; - ip->irp_iostat.isb_info = actlen; - - return (USBD_STATUS_SUCCESS); -#undef NDISUSB_GETDESC_MAXRETRIES -} - -static int32_t -usbd_func_selconf(irp *ip) -{ - device_t dev = IRP_NDIS_DEV(ip); - int i, j; - struct ndis_softc *sc = device_get_softc(dev); - struct usb_device *udev = sc->ndisusb_dev; - struct usb_endpoint *ep = NULL; - struct usbd_interface_information *intf; - struct usbd_pipe_information *pipe; - struct usbd_urb_select_configuration *selconf; - union usbd_urb *urb; - usb_config_descriptor_t *conf; - usb_endpoint_descriptor_t *edesc; - usb_error_t ret; - - urb = usbd_geturb(ip); - - selconf = &urb->uu_selconf; - conf = selconf->usc_conf; - if (conf == NULL) { - device_printf(dev, "select configuration is NULL\n"); - return usbd_usb2urb(USB_ERR_NORMAL_COMPLETION); - } - - intf = &selconf->usc_intf; - for (i = 0; i < conf->bNumInterface && intf->uii_len > 0; i++) { - ret = usbd_set_alt_interface_index(udev, - intf->uii_intfnum, intf->uii_altset); - if (ret != USB_ERR_NORMAL_COMPLETION && ret != USB_ERR_IN_USE) { - device_printf(dev, - "setting alternate interface failed: %s\n", - usbd_errstr(ret)); - return usbd_usb2urb(ret); - } - - for (j = 0; (ep = usb_endpoint_foreach(udev, ep)); j++) { - if (j >= intf->uii_numeps) { - device_printf(dev, - "endpoint %d and above are ignored", - intf->uii_numeps); - break; - } - edesc = ep->edesc; - pipe = &intf->uii_pipes[j]; - pipe->upi_handle = edesc; - pipe->upi_epaddr = edesc->bEndpointAddress; - pipe->upi_maxpktsize = UGETW(edesc->wMaxPacketSize); - pipe->upi_type = UE_GET_XFERTYPE(edesc->bmAttributes); - - ret = usbd_setup_endpoint(ip, intf->uii_intfnum, edesc); - if (ret != USB_ERR_NORMAL_COMPLETION) - return usbd_usb2urb(ret); - - if (pipe->upi_type != UE_INTERRUPT) - continue; - - /* XXX we're following linux USB's interval policy. */ - if (udev->speed == USB_SPEED_LOW) - pipe->upi_interval = edesc->bInterval + 5; - else if (udev->speed == USB_SPEED_FULL) - pipe->upi_interval = edesc->bInterval; - else { - int k0 = 0, k1 = 1; - do { - k1 = k1 * 2; - k0 = k0 + 1; - } while (k1 < edesc->bInterval); - pipe->upi_interval = k0; - } - } - - intf = (struct usbd_interface_information *)(((char *)intf) + - intf->uii_len); - } - - return (USBD_STATUS_SUCCESS); -} - -static usb_error_t -usbd_setup_endpoint_one(irp *ip, uint8_t ifidx, struct ndisusb_ep *ne, - struct usb_config *epconf) -{ - device_t dev = IRP_NDIS_DEV(ip); - struct ndis_softc *sc = device_get_softc(dev); - struct usb_xfer *xfer; - usb_error_t status; - - InitializeListHead(&ne->ne_active); - InitializeListHead(&ne->ne_pending); - KeInitializeSpinLock(&ne->ne_lock); - - status = usbd_transfer_setup(sc->ndisusb_dev, &ifidx, ne->ne_xfer, - epconf, 1, sc, &sc->ndisusb_mtx); - if (status != USB_ERR_NORMAL_COMPLETION) { - device_printf(dev, "couldn't setup xfer: %s\n", - usbd_errstr(status)); - return (status); - } - xfer = ne->ne_xfer[0]; - usbd_xfer_set_priv(xfer, ne); - - return (status); -} - -static usb_error_t -usbd_setup_endpoint_default(irp *ip, uint8_t ifidx) -{ - device_t dev = IRP_NDIS_DEV(ip); - struct ndis_softc *sc = device_get_softc(dev); - usb_error_t status; - - if (ifidx > 0) - device_printf(dev, "warning: ifidx > 0 isn't supported.\n"); - - status = usbd_setup_endpoint_one(ip, ifidx, &sc->ndisusb_dread_ep, - &usbd_default_epconfig[USBD_CTRL_READ_PIPE]); - if (status != USB_ERR_NORMAL_COMPLETION) - return (status); - - status = usbd_setup_endpoint_one(ip, ifidx, &sc->ndisusb_dwrite_ep, - &usbd_default_epconfig[USBD_CTRL_WRITE_PIPE]); - return (status); -} - -static usb_error_t -usbd_setup_endpoint(irp *ip, uint8_t ifidx, - struct usb_endpoint_descriptor *ep) -{ - device_t dev = IRP_NDIS_DEV(ip); - struct ndis_softc *sc = device_get_softc(dev); - struct ndisusb_ep *ne; - struct usb_config cfg; - struct usb_xfer *xfer; - usb_error_t status; - - /* check for non-supported transfer types */ - if (UE_GET_XFERTYPE(ep->bmAttributes) == UE_CONTROL || - UE_GET_XFERTYPE(ep->bmAttributes) == UE_ISOCHRONOUS) { - device_printf(dev, "%s: unsuppotted transfer types %#x\n", - __func__, UE_GET_XFERTYPE(ep->bmAttributes)); - return (USB_ERR_INVAL); - } - - ne = &sc->ndisusb_ep[NDISUSB_GET_ENDPT(ep->bEndpointAddress)]; - InitializeListHead(&ne->ne_active); - InitializeListHead(&ne->ne_pending); - KeInitializeSpinLock(&ne->ne_lock); - ne->ne_dirin = UE_GET_DIR(ep->bEndpointAddress) >> 7; - - memset(&cfg, 0, sizeof(struct usb_config)); - cfg.type = UE_GET_XFERTYPE(ep->bmAttributes); - cfg.endpoint = UE_GET_ADDR(ep->bEndpointAddress); - cfg.direction = UE_GET_DIR(ep->bEndpointAddress); - cfg.callback = &usbd_non_isoc_callback; - cfg.bufsize = UGETW(ep->wMaxPacketSize); - cfg.flags.proxy_buffer = 1; - if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN) - cfg.flags.short_xfer_ok = 1; - - status = usbd_transfer_setup(sc->ndisusb_dev, &ifidx, ne->ne_xfer, - &cfg, 1, sc, &sc->ndisusb_mtx); - if (status != USB_ERR_NORMAL_COMPLETION) { - device_printf(dev, "couldn't setup xfer: %s\n", - usbd_errstr(status)); - return (status); - } - xfer = ne->ne_xfer[0]; - usbd_xfer_set_priv(xfer, ne); - if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN) - usbd_xfer_set_timeout(xfer, NDISUSB_NO_TIMEOUT); - else { - if (UE_GET_XFERTYPE(ep->bmAttributes) == UE_BULK) - usbd_xfer_set_timeout(xfer, NDISUSB_TX_TIMEOUT); - else - usbd_xfer_set_timeout(xfer, NDISUSB_INTR_TIMEOUT); - } - - return (status); -} - -static int32_t -usbd_func_abort_pipe(irp *ip) -{ - device_t dev = IRP_NDIS_DEV(ip); - struct ndis_softc *sc = device_get_softc(dev); - struct ndisusb_ep *ne; - union usbd_urb *urb; - - urb = usbd_geturb(ip); - ne = usbd_get_ndisep(ip, urb->uu_pipe.upr_handle); - if (ne == NULL) { - device_printf(IRP_NDIS_DEV(ip), "get NULL endpoint info.\n"); - return (USBD_STATUS_INVALID_PIPE_HANDLE); - } - - NDISUSB_LOCK(sc); - usbd_transfer_stop(ne->ne_xfer[0]); - usbd_transfer_start(ne->ne_xfer[0]); - NDISUSB_UNLOCK(sc); - - return (USBD_STATUS_SUCCESS); -} - -static int32_t -usbd_func_vendorclass(irp *ip) -{ - device_t dev = IRP_NDIS_DEV(ip); - int32_t error; - struct ndis_softc *sc = device_get_softc(dev); - struct ndisusb_ep *ne; - struct ndisusb_xfer *nx; - struct usbd_urb_vendor_or_class_request *vcreq; - union usbd_urb *urb; - - if (!(sc->ndisusb_status & NDISUSB_STATUS_SETUP_EP)) { - /* - * XXX In some cases the interface number isn't 0. However - * some driver (eg. RTL8187L NDIS driver) calls this function - * before calling URB_FUNCTION_SELECT_CONFIGURATION. - */ - error = usbd_setup_endpoint_default(ip, 0); - if (error != USB_ERR_NORMAL_COMPLETION) - return usbd_usb2urb(error); - sc->ndisusb_status |= NDISUSB_STATUS_SETUP_EP; - } - - urb = usbd_geturb(ip); - vcreq = &urb->uu_vcreq; - ne = (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) ? - &sc->ndisusb_dread_ep : &sc->ndisusb_dwrite_ep; - IRP_NDISUSB_EP(ip) = ne; - ip->irp_cancelfunc = (cancel_func)usbd_irpcancel_wrap; - - nx = malloc(sizeof(struct ndisusb_xfer), M_USBDEV, M_NOWAIT | M_ZERO); - if (nx == NULL) { - device_printf(IRP_NDIS_DEV(ip), "out of memory\n"); - return (USBD_STATUS_NO_MEMORY); - } - nx->nx_ep = ne; - nx->nx_priv = ip; - KeAcquireSpinLockAtDpcLevel(&ne->ne_lock); - InsertTailList((&ne->ne_pending), (&nx->nx_next)); - KeReleaseSpinLockFromDpcLevel(&ne->ne_lock); - - /* we've done to setup xfer. Let's transfer it. */ - ip->irp_iostat.isb_status = STATUS_PENDING; - ip->irp_iostat.isb_info = 0; - USBD_URB_STATUS(urb) = USBD_STATUS_PENDING; - IoMarkIrpPending(ip); - - error = usbd_taskadd(ip, NDISUSB_TASK_VENDOR); - if (error != USBD_STATUS_SUCCESS) - return (error); - - return (USBD_STATUS_PENDING); -} - -static void -usbd_irpcancel(device_object *dobj, irp *ip) -{ - device_t dev = IRP_NDIS_DEV(ip); - struct ndis_softc *sc = device_get_softc(dev); - struct ndisusb_ep *ne = IRP_NDISUSB_EP(ip); - - if (ne == NULL) { - ip->irp_cancel = TRUE; - IoReleaseCancelSpinLock(ip->irp_cancelirql); - return; - } - - /* - * Make sure that the current USB transfer proxy is - * cancelled and then restarted. - */ - NDISUSB_LOCK(sc); - usbd_transfer_stop(ne->ne_xfer[0]); - usbd_transfer_start(ne->ne_xfer[0]); - NDISUSB_UNLOCK(sc); - - ip->irp_cancel = TRUE; - IoReleaseCancelSpinLock(ip->irp_cancelirql); -} - -static void -usbd_xfer_complete(struct ndis_softc *sc, struct ndisusb_ep *ne, - struct ndisusb_xfer *nx, usb_error_t status) -{ - struct ndisusb_xferdone *nd; - uint8_t irql; - - nd = malloc(sizeof(struct ndisusb_xferdone), M_USBDEV, - M_NOWAIT | M_ZERO); - if (nd == NULL) { - device_printf(sc->ndis_dev, "out of memory"); - return; - } - nd->nd_xfer = nx; - nd->nd_status = status; - - KeAcquireSpinLock(&sc->ndisusb_xferdonelock, &irql); - InsertTailList((&sc->ndisusb_xferdonelist), (&nd->nd_donelist)); - KeReleaseSpinLock(&sc->ndisusb_xferdonelock, irql); - - IoQueueWorkItem(sc->ndisusb_xferdoneitem, - (io_workitem_func)usbd_xfertask_wrap, WORKQUEUE_CRITICAL, sc); -} - -static struct ndisusb_xfer * -usbd_aq_getfirst(struct ndis_softc *sc, struct ndisusb_ep *ne) -{ - struct ndisusb_xfer *nx; - - KeAcquireSpinLockAtDpcLevel(&ne->ne_lock); - if (IsListEmpty(&ne->ne_active)) { - device_printf(sc->ndis_dev, - "%s: the active queue can't be empty.\n", __func__); - KeReleaseSpinLockFromDpcLevel(&ne->ne_lock); - return (NULL); - } - nx = CONTAINING_RECORD(ne->ne_active.nle_flink, struct ndisusb_xfer, - nx_next); - RemoveEntryList(&nx->nx_next); - KeReleaseSpinLockFromDpcLevel(&ne->ne_lock); - - return (nx); -} - -static void -usbd_non_isoc_callback(struct usb_xfer *xfer, usb_error_t error) -{ - irp *ip; - struct ndis_softc *sc = usbd_xfer_softc(xfer); - struct ndisusb_ep *ne = usbd_xfer_get_priv(xfer); - struct ndisusb_xfer *nx; - struct usbd_urb_bulk_or_intr_transfer *ubi; - struct usb_page_cache *pc; - uint8_t irql; - uint32_t len; - union usbd_urb *urb; - usb_endpoint_descriptor_t *ep; - int actlen, sumlen; - - usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - nx = usbd_aq_getfirst(sc, ne); - pc = usbd_xfer_get_frame(xfer, 0); - if (nx == NULL) - return; - - /* copy in data with regard to the URB */ - if (ne->ne_dirin != 0) - usbd_copy_out(pc, 0, nx->nx_urbbuf, actlen); - nx->nx_urbbuf += actlen; - nx->nx_urbactlen += actlen; - nx->nx_urblen -= actlen; - - /* check for short transfer */ - if (actlen < sumlen) - nx->nx_urblen = 0; - else { - /* check remainder */ - if (nx->nx_urblen > 0) { - KeAcquireSpinLock(&ne->ne_lock, &irql); - InsertHeadList((&ne->ne_active), (&nx->nx_next)); - KeReleaseSpinLock(&ne->ne_lock, irql); - - ip = nx->nx_priv; - urb = usbd_geturb(ip); - ubi = &urb->uu_bulkintr; - ep = ubi->ubi_epdesc; - goto extra; - } - } - usbd_xfer_complete(sc, ne, nx, - ((actlen < sumlen) && (nx->nx_shortxfer == 0)) ? - USB_ERR_SHORT_XFER : USB_ERR_NORMAL_COMPLETION); - - /* fall through */ - case USB_ST_SETUP: -next: - /* get next transfer */ - KeAcquireSpinLock(&ne->ne_lock, &irql); - if (IsListEmpty(&ne->ne_pending)) { - KeReleaseSpinLock(&ne->ne_lock, irql); - return; - } - nx = CONTAINING_RECORD(ne->ne_pending.nle_flink, - struct ndisusb_xfer, nx_next); - RemoveEntryList(&nx->nx_next); - /* add a entry to the active queue's tail. */ - InsertTailList((&ne->ne_active), (&nx->nx_next)); - KeReleaseSpinLock(&ne->ne_lock, irql); - - ip = nx->nx_priv; - urb = usbd_geturb(ip); - ubi = &urb->uu_bulkintr; - ep = ubi->ubi_epdesc; - - nx->nx_urbbuf = ubi->ubi_trans_buf; - nx->nx_urbactlen = 0; - nx->nx_urblen = ubi->ubi_trans_buflen; - nx->nx_shortxfer = (ubi->ubi_trans_flags & - USBD_SHORT_TRANSFER_OK) ? 1 : 0; -extra: - len = MIN(usbd_xfer_max_len(xfer), nx->nx_urblen); - pc = usbd_xfer_get_frame(xfer, 0); - if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_OUT) - usbd_copy_in(pc, 0, nx->nx_urbbuf, len); - usbd_xfer_set_frame_len(xfer, 0, len); - usbd_xfer_set_frames(xfer, 1); - usbd_transfer_submit(xfer); - break; - default: - nx = usbd_aq_getfirst(sc, ne); - if (nx == NULL) - return; - if (error != USB_ERR_CANCELLED) { - usbd_xfer_set_stall(xfer); - device_printf(sc->ndis_dev, "usb xfer warning (%s)\n", - usbd_errstr(error)); - } - usbd_xfer_complete(sc, ne, nx, error); - if (error != USB_ERR_CANCELLED) - goto next; - break; - } -} - -static void -usbd_ctrl_callback(struct usb_xfer *xfer, usb_error_t error) -{ - irp *ip; - struct ndis_softc *sc = usbd_xfer_softc(xfer); - struct ndisusb_ep *ne = usbd_xfer_get_priv(xfer); - struct ndisusb_xfer *nx; - uint8_t irql; - union usbd_urb *urb; - struct usbd_urb_vendor_or_class_request *vcreq; - struct usb_page_cache *pc; - uint8_t type = 0; - struct usb_device_request req; - int len; - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - nx = usbd_aq_getfirst(sc, ne); - if (nx == NULL) - return; - - ip = nx->nx_priv; - urb = usbd_geturb(ip); - vcreq = &urb->uu_vcreq; - - if (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) { - pc = usbd_xfer_get_frame(xfer, 1); - len = usbd_xfer_frame_len(xfer, 1); - usbd_copy_out(pc, 0, vcreq->uvc_trans_buf, len); - nx->nx_urbactlen += len; - } - - usbd_xfer_complete(sc, ne, nx, USB_ERR_NORMAL_COMPLETION); - /* fall through */ - case USB_ST_SETUP: -next: - /* get next transfer */ - KeAcquireSpinLock(&ne->ne_lock, &irql); - if (IsListEmpty(&ne->ne_pending)) { - KeReleaseSpinLock(&ne->ne_lock, irql); - return; - } - nx = CONTAINING_RECORD(ne->ne_pending.nle_flink, - struct ndisusb_xfer, nx_next); - RemoveEntryList(&nx->nx_next); - /* add a entry to the active queue's tail. */ - InsertTailList((&ne->ne_active), (&nx->nx_next)); - KeReleaseSpinLock(&ne->ne_lock, irql); - - ip = nx->nx_priv; - urb = usbd_geturb(ip); - vcreq = &urb->uu_vcreq; - - switch (urb->uu_hdr.uuh_func) { - case URB_FUNCTION_CLASS_DEVICE: - type = UT_CLASS | UT_DEVICE; - break; - case URB_FUNCTION_CLASS_INTERFACE: - type = UT_CLASS | UT_INTERFACE; - break; - case URB_FUNCTION_CLASS_OTHER: - type = UT_CLASS | UT_OTHER; - break; - case URB_FUNCTION_CLASS_ENDPOINT: - type = UT_CLASS | UT_ENDPOINT; - break; - case URB_FUNCTION_VENDOR_DEVICE: - type = UT_VENDOR | UT_DEVICE; - break; - case URB_FUNCTION_VENDOR_INTERFACE: - type = UT_VENDOR | UT_INTERFACE; - break; - case URB_FUNCTION_VENDOR_OTHER: - type = UT_VENDOR | UT_OTHER; - break; - case URB_FUNCTION_VENDOR_ENDPOINT: - type = UT_VENDOR | UT_ENDPOINT; - break; - default: - /* never reached. */ - break; - } - - type |= (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) ? - UT_READ : UT_WRITE; - type |= vcreq->uvc_reserved1; - - req.bmRequestType = type; - req.bRequest = vcreq->uvc_req; - USETW(req.wIndex, vcreq->uvc_idx); - USETW(req.wValue, vcreq->uvc_value); - USETW(req.wLength, vcreq->uvc_trans_buflen); - - nx->nx_urbbuf = vcreq->uvc_trans_buf; - nx->nx_urblen = vcreq->uvc_trans_buflen; - nx->nx_urbactlen = 0; - - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_in(pc, 0, &req, sizeof(req)); - usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); - usbd_xfer_set_frames(xfer, 1); - if (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) { - if (vcreq->uvc_trans_buflen >= USBD_CTRL_READ_BUFFER_SP) - device_printf(sc->ndis_dev, - "warning: not enough buffer space (%d).\n", - vcreq->uvc_trans_buflen); - usbd_xfer_set_frame_len(xfer, 1, - MIN(usbd_xfer_max_len(xfer), - vcreq->uvc_trans_buflen)); - usbd_xfer_set_frames(xfer, 2); - } else { - if (nx->nx_urblen > USBD_CTRL_WRITE_BUFFER_SP) - device_printf(sc->ndis_dev, - "warning: not enough write buffer space" - " (%d).\n", nx->nx_urblen); - /* - * XXX with my local tests there was no cases to require - * a extra buffer until now but it'd need to update in - * the future if it needs to be. - */ - if (nx->nx_urblen > 0) { - pc = usbd_xfer_get_frame(xfer, 1); - usbd_copy_in(pc, 0, nx->nx_urbbuf, - nx->nx_urblen); - usbd_xfer_set_frame_len(xfer, 1, nx->nx_urblen); - usbd_xfer_set_frames(xfer, 2); - } - } - usbd_transfer_submit(xfer); - break; - default: - nx = usbd_aq_getfirst(sc, ne); - if (nx == NULL) - return; - if (error != USB_ERR_CANCELLED) { - usbd_xfer_set_stall(xfer); - device_printf(sc->ndis_dev, "usb xfer warning (%s)\n", - usbd_errstr(error)); - } - usbd_xfer_complete(sc, ne, nx, error); - if (error != USB_ERR_CANCELLED) - goto next; - break; - } -} - -static struct ndisusb_ep * -usbd_get_ndisep(irp *ip, usb_endpoint_descriptor_t *ep) -{ - device_t dev = IRP_NDIS_DEV(ip); - struct ndis_softc *sc = device_get_softc(dev); - struct ndisusb_ep *ne; - - ne = &sc->ndisusb_ep[NDISUSB_GET_ENDPT(ep->bEndpointAddress)]; - - IRP_NDISUSB_EP(ip) = ne; - ip->irp_cancelfunc = (cancel_func)usbd_irpcancel_wrap; - - return (ne); -} - -static void -usbd_xfertask(device_object *dobj, void *arg) -{ - int error; - irp *ip; - device_t dev; - list_entry *l; - struct ndis_softc *sc = arg; - struct ndisusb_xferdone *nd; - struct ndisusb_xfer *nq; - struct usbd_urb_bulk_or_intr_transfer *ubi; - struct usbd_urb_vendor_or_class_request *vcreq; - union usbd_urb *urb; - usb_error_t status; - void *priv; - - dev = sc->ndis_dev; - - if (IsListEmpty(&sc->ndisusb_xferdonelist)) - return; - - KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_xferdonelock); - l = sc->ndisusb_xferdonelist.nle_flink; - while (l != &sc->ndisusb_xferdonelist) { - nd = CONTAINING_RECORD(l, struct ndisusb_xferdone, nd_donelist); - nq = nd->nd_xfer; - priv = nq->nx_priv; - status = nd->nd_status; - error = 0; - ip = priv; - urb = usbd_geturb(ip); - - ip->irp_cancelfunc = NULL; - IRP_NDISUSB_EP(ip) = NULL; - - switch (status) { - case USB_ERR_NORMAL_COMPLETION: - if (urb->uu_hdr.uuh_func == - URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) { - ubi = &urb->uu_bulkintr; - ubi->ubi_trans_buflen = nq->nx_urbactlen; - } else { - vcreq = &urb->uu_vcreq; - vcreq->uvc_trans_buflen = nq->nx_urbactlen; - } - ip->irp_iostat.isb_info = nq->nx_urbactlen; - ip->irp_iostat.isb_status = STATUS_SUCCESS; - USBD_URB_STATUS(urb) = USBD_STATUS_SUCCESS; - break; - case USB_ERR_CANCELLED: - ip->irp_iostat.isb_info = 0; - ip->irp_iostat.isb_status = STATUS_CANCELLED; - USBD_URB_STATUS(urb) = USBD_STATUS_CANCELED; - break; - default: - ip->irp_iostat.isb_info = 0; - USBD_URB_STATUS(urb) = usbd_usb2urb(status); - ip->irp_iostat.isb_status = - usbd_urb2nt(USBD_URB_STATUS(urb)); - break; - } - - l = l->nle_flink; - RemoveEntryList(&nd->nd_donelist); - free(nq, M_USBDEV); - free(nd, M_USBDEV); - if (error) - continue; - KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_xferdonelock); - /* NB: call after cleaning */ - IoCompleteRequest(ip, IO_NO_INCREMENT); - KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_xferdonelock); - } - KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_xferdonelock); -} - -/* - * this function is for mainly deferring a task to the another thread because - * we don't want to be in the scope of HAL lock. - */ -static int32_t -usbd_taskadd(irp *ip, unsigned type) -{ - device_t dev = IRP_NDIS_DEV(ip); - struct ndis_softc *sc = device_get_softc(dev); - struct ndisusb_task *nt; - - nt = malloc(sizeof(struct ndisusb_task), M_USBDEV, M_NOWAIT | M_ZERO); - if (nt == NULL) - return (USBD_STATUS_NO_MEMORY); - nt->nt_type = type; - nt->nt_ctx = ip; - - KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_tasklock); - InsertTailList((&sc->ndisusb_tasklist), (&nt->nt_tasklist)); - KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_tasklock); - - IoQueueWorkItem(sc->ndisusb_taskitem, - (io_workitem_func)usbd_task_wrap, WORKQUEUE_CRITICAL, sc); - - return (USBD_STATUS_SUCCESS); -} - -static void -usbd_task(device_object *dobj, void *arg) -{ - irp *ip; - list_entry *l; - struct ndis_softc *sc = arg; - struct ndisusb_ep *ne; - struct ndisusb_task *nt; - union usbd_urb *urb; - - if (IsListEmpty(&sc->ndisusb_tasklist)) - return; - - KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_tasklock); - l = sc->ndisusb_tasklist.nle_flink; - while (l != &sc->ndisusb_tasklist) { - nt = CONTAINING_RECORD(l, struct ndisusb_task, nt_tasklist); - - ip = nt->nt_ctx; - urb = usbd_geturb(ip); - - KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_tasklock); - NDISUSB_LOCK(sc); - switch (nt->nt_type) { - case NDISUSB_TASK_TSTART: - ne = usbd_get_ndisep(ip, urb->uu_bulkintr.ubi_epdesc); - if (ne == NULL) - goto exit; - usbd_transfer_start(ne->ne_xfer[0]); - break; - case NDISUSB_TASK_IRPCANCEL: - ne = usbd_get_ndisep(ip, - (nt->nt_type == NDISUSB_TASK_IRPCANCEL) ? - urb->uu_bulkintr.ubi_epdesc : - urb->uu_pipe.upr_handle); - if (ne == NULL) - goto exit; - - usbd_transfer_stop(ne->ne_xfer[0]); - usbd_transfer_start(ne->ne_xfer[0]); - break; - case NDISUSB_TASK_VENDOR: - ne = (urb->uu_vcreq.uvc_trans_flags & - USBD_TRANSFER_DIRECTION_IN) ? - &sc->ndisusb_dread_ep : &sc->ndisusb_dwrite_ep; - usbd_transfer_start(ne->ne_xfer[0]); - break; - default: - break; - } -exit: - NDISUSB_UNLOCK(sc); - KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_tasklock); - - l = l->nle_flink; - RemoveEntryList(&nt->nt_tasklist); - free(nt, M_USBDEV); - } - KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_tasklock); -} - -static int32_t -usbd_func_bulkintr(irp *ip) -{ - int32_t error; - struct ndisusb_ep *ne; - struct ndisusb_xfer *nx; - struct usbd_urb_bulk_or_intr_transfer *ubi; - union usbd_urb *urb; - usb_endpoint_descriptor_t *ep; - - urb = usbd_geturb(ip); - ubi = &urb->uu_bulkintr; - ep = ubi->ubi_epdesc; - if (ep == NULL) - return (USBD_STATUS_INVALID_PIPE_HANDLE); - - ne = usbd_get_ndisep(ip, ep); - if (ne == NULL) { - device_printf(IRP_NDIS_DEV(ip), "get NULL endpoint info.\n"); - return (USBD_STATUS_INVALID_PIPE_HANDLE); - } - - nx = malloc(sizeof(struct ndisusb_xfer), M_USBDEV, M_NOWAIT | M_ZERO); - if (nx == NULL) { - device_printf(IRP_NDIS_DEV(ip), "out of memory\n"); - return (USBD_STATUS_NO_MEMORY); - } - nx->nx_ep = ne; - nx->nx_priv = ip; - KeAcquireSpinLockAtDpcLevel(&ne->ne_lock); - InsertTailList((&ne->ne_pending), (&nx->nx_next)); - KeReleaseSpinLockFromDpcLevel(&ne->ne_lock); - - /* we've done to setup xfer. Let's transfer it. */ - ip->irp_iostat.isb_status = STATUS_PENDING; - ip->irp_iostat.isb_info = 0; - USBD_URB_STATUS(urb) = USBD_STATUS_PENDING; - IoMarkIrpPending(ip); - - error = usbd_taskadd(ip, NDISUSB_TASK_TSTART); - if (error != USBD_STATUS_SUCCESS) - return (error); - - return (USBD_STATUS_PENDING); -} - -static union usbd_urb * -USBD_CreateConfigurationRequest(usb_config_descriptor_t *conf, uint16_t *len) -{ - struct usbd_interface_list_entry list[2]; - union usbd_urb *urb; - - bzero(list, sizeof(struct usbd_interface_list_entry) * 2); - list[0].uil_intfdesc = USBD_ParseConfigurationDescriptorEx(conf, conf, - -1, -1, -1, -1, -1); - urb = USBD_CreateConfigurationRequestEx(conf, list); - if (urb == NULL) - return (NULL); - - *len = urb->uu_selconf.usc_hdr.uuh_len; - return (urb); -} - -static union usbd_urb * -USBD_CreateConfigurationRequestEx(usb_config_descriptor_t *conf, - struct usbd_interface_list_entry *list) -{ - int i, j, size; - struct usbd_interface_information *intf; - struct usbd_pipe_information *pipe; - struct usbd_urb_select_configuration *selconf; - usb_interface_descriptor_t *desc; - - for (i = 0, size = 0; i < conf->bNumInterface; i++) { - j = list[i].uil_intfdesc->bNumEndpoints; - size = size + sizeof(struct usbd_interface_information) + - sizeof(struct usbd_pipe_information) * (j - 1); - } - size += sizeof(struct usbd_urb_select_configuration) - - sizeof(struct usbd_interface_information); - - selconf = ExAllocatePoolWithTag(NonPagedPool, size, 0); - if (selconf == NULL) - return (NULL); - selconf->usc_hdr.uuh_func = URB_FUNCTION_SELECT_CONFIGURATION; - selconf->usc_hdr.uuh_len = size; - selconf->usc_handle = conf; - selconf->usc_conf = conf; - - intf = &selconf->usc_intf; - for (i = 0; i < conf->bNumInterface; i++) { - if (list[i].uil_intfdesc == NULL) - break; - - list[i].uil_intf = intf; - desc = list[i].uil_intfdesc; - - intf->uii_len = sizeof(struct usbd_interface_information) + - (desc->bNumEndpoints - 1) * - sizeof(struct usbd_pipe_information); - intf->uii_intfnum = desc->bInterfaceNumber; - intf->uii_altset = desc->bAlternateSetting; - intf->uii_intfclass = desc->bInterfaceClass; - intf->uii_intfsubclass = desc->bInterfaceSubClass; - intf->uii_intfproto = desc->bInterfaceProtocol; - intf->uii_handle = desc; - intf->uii_numeps = desc->bNumEndpoints; - - pipe = &intf->uii_pipes[0]; - for (j = 0; j < intf->uii_numeps; j++) - pipe[j].upi_maxtxsize = - USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE; - - intf = (struct usbd_interface_information *)((char *)intf + - intf->uii_len); - } - - return ((union usbd_urb *)selconf); -} - -static void -USBD_GetUSBDIVersion(usbd_version_info *ui) -{ - - /* Pretend to be Windows XP. */ - - ui->uvi_usbdi_vers = USBDI_VERSION; - ui->uvi_supported_vers = USB_VER_2_0; -} - -static usb_interface_descriptor_t * -USBD_ParseConfigurationDescriptor(usb_config_descriptor_t *conf, - uint8_t intfnum, uint8_t altset) -{ - - return USBD_ParseConfigurationDescriptorEx(conf, conf, intfnum, altset, - -1, -1, -1); -} - -static usb_interface_descriptor_t * -USBD_ParseConfigurationDescriptorEx(usb_config_descriptor_t *conf, - void *start, int32_t intfnum, int32_t altset, int32_t intfclass, - int32_t intfsubclass, int32_t intfproto) -{ - struct usb_descriptor *next = NULL; - usb_interface_descriptor_t *desc; - - while ((next = usb_desc_foreach(conf, next)) != NULL) { - desc = (usb_interface_descriptor_t *)next; - if (desc->bDescriptorType != UDESC_INTERFACE) - continue; - if (!(intfnum == -1 || desc->bInterfaceNumber == intfnum)) - continue; - if (!(altset == -1 || desc->bAlternateSetting == altset)) - continue; - if (!(intfclass == -1 || desc->bInterfaceClass == intfclass)) - continue; - if (!(intfsubclass == -1 || - desc->bInterfaceSubClass == intfsubclass)) - continue; - if (!(intfproto == -1 || desc->bInterfaceProtocol == intfproto)) - continue; - return (desc); - } - - return (NULL); -} - -static void -dummy(void) -{ - printf("USBD dummy called\n"); -} - -image_patch_table usbd_functbl[] = { - IMPORT_SFUNC(USBD_CreateConfigurationRequest, 2), - IMPORT_SFUNC(USBD_CreateConfigurationRequestEx, 2), - IMPORT_SFUNC_MAP(_USBD_CreateConfigurationRequestEx@8, - USBD_CreateConfigurationRequestEx, 2), - IMPORT_SFUNC(USBD_GetUSBDIVersion, 1), - IMPORT_SFUNC(USBD_ParseConfigurationDescriptor, 3), - IMPORT_SFUNC(USBD_ParseConfigurationDescriptorEx, 7), - IMPORT_SFUNC_MAP(_USBD_ParseConfigurationDescriptorEx@28, - USBD_ParseConfigurationDescriptorEx, 7), - - /* - * This last entry is a catch-all for any function we haven't - * implemented yet. The PE import list patching routine will - * use it for any function that doesn't have an explicit match - * in this table. - */ - - { NULL, (FUNC)dummy, NULL, 0, WINDRV_WRAP_STDCALL }, - - /* End of list. */ - { NULL, NULL, NULL } -}; - -MODULE_DEPEND(ndis, usb, 1, 1, 1); diff --git a/sys/compat/ndis/usbd_var.h b/sys/compat/ndis/usbd_var.h deleted file mode 100644 index 6566a29d52d6..000000000000 --- a/sys/compat/ndis/usbd_var.h +++ /dev/null @@ -1,224 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul . All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _USBD_VAR_H_ -#define _USBD_VAR_H_ - -#define IOCTL_INTERNAL_USB_SUBMIT_URB 0x00220003 - -#define URB_FUNCTION_SELECT_CONFIGURATION 0x0000 -#define URB_FUNCTION_ABORT_PIPE 0x0002 -#define URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER 0x0009 -#define URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE 0x000B -#define URB_FUNCTION_VENDOR_DEVICE 0x0017 -#define URB_FUNCTION_VENDOR_INTERFACE 0x0018 -#define URB_FUNCTION_VENDOR_ENDPOINT 0x0019 -#define URB_FUNCTION_CLASS_DEVICE 0x001A -#define URB_FUNCTION_CLASS_INTERFACE 0x001B -#define URB_FUNCTION_CLASS_ENDPOINT 0x001C -#define URB_FUNCTION_CLASS_OTHER 0x001F -#define URB_FUNCTION_VENDOR_OTHER 0x0020 - -#define USBD_STATUS_SUCCESS 0x00000000 -#define USBD_STATUS_CANCELED 0x00010000 -#define USBD_STATUS_PENDING 0x40000000 -#define USBD_STATUS_NO_MEMORY 0x80000100 -#define USBD_STATUS_REQUEST_FAILED 0x80000500 -#define USBD_STATUS_INVALID_PIPE_HANDLE 0x80000600 -#define USBD_STATUS_ERROR_SHORT_TRANSFER 0x80000900 -#define USBD_STATUS_CRC 0xC0000001 -#define USBD_STATUS_BTSTUFF 0xC0000002 -#define USBD_STATUS_DATA_TOGGLE_MISMATCH 0xC0000003 -#define USBD_STATUS_STALL_PID 0xC0000004 -#define USBD_STATUS_DEV_NOT_RESPONDING 0xC0000005 -#define USBD_STATUS_PID_CHECK_FAILURE 0xC0000006 -#define USBD_STATUS_UNEXPECTED_PID 0xC0000007 -#define USBD_STATUS_DATA_OVERRUN 0xC0000008 -#define USBD_STATUS_DATA_UNDERRUN 0xC0000009 -#define USBD_STATUS_RESERVED1 0xC000000A -#define USBD_STATUS_RESERVED2 0xC000000B -#define USBD_STATUS_BUFFER_OVERRUN 0xC000000C -#define USBD_STATUS_BUFFER_UNDERRUN 0xC000000D -#define USBD_STATUS_NOT_ACCESSED 0xC000000F -#define USBD_STATUS_FIFO 0xC0000010 -#define USBD_STATUS_XACT_ERROR 0xC0000011 -#define USBD_STATUS_BABBLE_DETECTED 0xC0000012 -#define USBD_STATUS_DATA_BUFFER_ERROR 0xC0000013 -#define USBD_STATUS_NOT_SUPPORTED 0xC0000E00 -#define USBD_STATUS_TIMEOUT 0xC0006000 -#define USBD_STATUS_DEVICE_GONE 0xC0007000 - -struct usbd_urb_header { - uint16_t uuh_len; - uint16_t uuh_func; - int32_t uuh_status; - void *uuh_handle; - uint32_t uuh_flags; -}; - -enum usbd_pipe_type { - UsbdPipeTypeControl = UE_CONTROL, - UsbdPipeTypeIsochronous = UE_ISOCHRONOUS, - UsbdPipeTypeBulk = UE_BULK, - UsbdPipeTypeInterrupt = UE_INTERRUPT -}; - -struct usbd_pipe_information { - uint16_t upi_maxpktsize; - uint8_t upi_epaddr; - uint8_t upi_interval; - enum usbd_pipe_type upi_type; - usb_endpoint_descriptor_t *upi_handle; - uint32_t upi_maxtxsize; -#define USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE PAGE_SIZE - uint32_t upi_flags; -}; - -struct usbd_interface_information { - uint16_t uii_len; - uint8_t uii_intfnum; - uint8_t uii_altset; - uint8_t uii_intfclass; - uint8_t uii_intfsubclass; - uint8_t uii_intfproto; - uint8_t uii_reserved; - void *uii_handle; - uint32_t uii_numeps; - struct usbd_pipe_information uii_pipes[1]; -}; - -struct usbd_urb_select_interface { - struct usbd_urb_header usi_hdr; - void *usi_handle; - struct usbd_interface_information uusi_intf; -}; - -struct usbd_urb_select_configuration { - struct usbd_urb_header usc_hdr; - usb_config_descriptor_t *usc_conf; - void *usc_handle; - struct usbd_interface_information usc_intf; -}; - -struct usbd_urb_pipe_request { - struct usbd_urb_header upr_hdr; - usb_endpoint_descriptor_t *upr_handle; -}; - -struct usbd_hcd_area { - void *reserved8[8]; -}; - -struct usbd_urb_bulk_or_intr_transfer { - struct usbd_urb_header ubi_hdr; - usb_endpoint_descriptor_t *ubi_epdesc; - uint32_t ubi_trans_flags; -#define USBD_SHORT_TRANSFER_OK 0x00000002 - uint32_t ubi_trans_buflen; - void *ubi_trans_buf; - struct mdl *ubi_mdl; - union usbd_urb *ubi_urblink; - struct usbd_hcd_area ubi_hca; -}; - -struct usbd_urb_control_descriptor_request { - struct usbd_urb_header ucd_hdr; - void *ucd_reserved0; - uint32_t ucd_reserved1; - uint32_t ucd_trans_buflen; - void *ucd_trans_buf; - struct mdl *ucd_mdl; - union nt_urb *ucd_urblink; - struct usbd_hcd_area ucd_hca; - uint16_t ucd_reserved2; - uint8_t ucd_idx; - uint8_t ucd_desctype; - uint16_t ucd_langid; - uint16_t ucd_reserved3; -}; - -struct usbd_urb_vendor_or_class_request { - struct usbd_urb_header uvc_hdr; - void *uvc_reserved0; - uint32_t uvc_trans_flags; -#define USBD_TRANSFER_DIRECTION_IN 1 - uint32_t uvc_trans_buflen; - void *uvc_trans_buf; - struct mdl *uvc_mdl; - union nt_urb *uvc_urblink; - struct usbd_hcd_area uvc_hca; - uint8_t uvc_reserved1; - uint8_t uvc_req; - uint16_t uvc_value; - uint16_t uvc_idx; - uint16_t uvc_reserved2; -}; - -struct usbd_interface_list_entry { - usb_interface_descriptor_t *uil_intfdesc; - struct usbd_interface_information *uil_intf; -}; - -union usbd_urb { - struct usbd_urb_header uu_hdr; - struct usbd_urb_select_configuration uu_selconf; - struct usbd_urb_bulk_or_intr_transfer uu_bulkintr; - struct usbd_urb_control_descriptor_request uu_ctldesc; - struct usbd_urb_vendor_or_class_request uu_vcreq; - struct usbd_urb_pipe_request uu_pipe; -}; - -#define USBD_URB_STATUS(urb) ((urb)->uu_hdr.uuh_status) - -#define USBDI_VERSION 0x00000500 -#define USB_VER_1_1 0x00000110 -#define USB_VER_2_0 0x00000200 - -struct usbd_version_info { - uint32_t uvi_usbdi_vers; - uint32_t uvi_supported_vers; -}; - -typedef struct usbd_version_info usbd_version_info; - -extern image_patch_table usbd_functbl[]; - -__BEGIN_DECLS -extern int usbd_libinit(void); -extern int usbd_libfini(void); -__END_DECLS - -#endif /* _USBD_VAR_H_ */ diff --git a/sys/compat/ndis/winx32_wrap.S b/sys/compat/ndis/winx32_wrap.S deleted file mode 100644 index c051504afb29..000000000000 --- a/sys/compat/ndis/winx32_wrap.S +++ /dev/null @@ -1,385 +0,0 @@ -/*- - * Copyright (c) 2005 - * Bill Paul . All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -/* The 'ret' macro doesn't work in this file if GPROF is enabled. */ -#ifdef GPROF -#undef GPROF -#endif - -#include - -/* - * This file contains assembly language wrappers for the different - * calling conventions supported by Windows on the i386 architecture. - * In FreeBSD, the whole OS typically use same C calling convention - * everywhere, namely _cdecl. Windows, on the other hand, uses several - * different C calling conventions depending on the circumstances: - * - * _stdcall: Used for most ordinary Windows APIs. With _stdcall, - * arguments are passed on the stack, and the callee unwinds the stack - * before returning control to the caller. Not suitable for variadic - * functions. - * - * _fastcall: Used for some APIs that may be invoked frequently and - * where speed is a critical factor (e.g. KeAcquireSpinLock() and - * KeReleaseSpinLock()) Similar to _stdcall, except the first 2 32-bit - * or smaller arguments are passed in the %ecx and %edx registers - * instead of on the stack. Not suitable for variadic functions. - * - * _cdecl: Used for standard C library routines and for variadic - * functions. - * - * _regparm(3): Used for certain assembly routines. All arguments - * passed in %eax, %ecx and %edx. - * - * Furthermore, there is an additional wrinkle that's not obvious - * with all code: Microsoft supports the use of exceptions in C - * (__try/__except) both in user _and_ kernel mode. Sadly, Windows - * structured exception handling uses machine-specific features - * that conflict rather badly with FreeBSD. (See utility routines - * at the end of this module for more details.) - * - * We want to support these calling conventions in as portable a manner - * as possible. The trick is doing it not only with different versions - * of GNU C, but with compilers other than GNU C (e.g. the Solaris - * SunOne C compiler). The only sure fire method is with assembly - * language trampoline code which both fixes up the argument passing, - * stack unwinding and exception/thread context all at once. - * - * You'll notice that we call the thunk/unthunk routines in the - * *_wrap() functions in an awkward way. Rather than branching - * directly to the address, we load the address into a register - * first as a literal value, then we branch to it. This is done - * to insure that the assembler doesn't translate the branch into - * a relative branch. We use the *_wrap() routines here as templates - * and create the actual trampolines at run time, at which point - * we only know the absolute addresses of the thunk and unthunk - * routines. So we need to make sure the templates have enough - * room in them for the full address. - * - * Also note that when we call the a thunk/unthunk routine after - * invoking a wrapped function, we have to make sure to preserve - * the value returned from that function. Most functions return - * a 32-bit value in %eax, however some routines return 64-bit - * values, which span both %eax and %edx. Consequently, we have - * to preserve both registers. - */ - -/* - * Handle _stdcall going from Windows to UNIX. - * This is frustrating, because to do it right you have to - * know how many arguments the called function takes, and there's - * no way to figure this out on the fly: you just have to be told - * ahead of time. We assume there will be 16 arguments. I don't - * think there are any Windows APIs that require this many. - */ - - .globl x86_stdcall_wrap_call - .globl x86_stdcall_wrap_arg - .globl x86_stdcall_wrap_end - -ENTRY(x86_stdcall_wrap) - push %esi - push %edi - sub $64,%esp - mov %esp,%esi - add $64+8+4,%esi - mov %esp,%edi - mov $16,%ecx # handle up to 16 args - rep - movsl - - movl $ctxsw_wtou, %eax - call *%eax # unthunk - -x86_stdcall_wrap_call: - movl $0,%eax - call *%eax # jump to routine - push %eax # preserve return val - push %edx - - movl $ctxsw_utow, %eax - call *%eax # thunk - - pop %edx - pop %eax # restore return val - - add $64,%esp # clean the stack - pop %edi - pop %esi -x86_stdcall_wrap_arg: - ret $0xFF -x86_stdcall_wrap_end: - - -/* - * Handle _stdcall going from UNIX to Windows. This routine - * expects to be passed the function to be called, number of - * args and the arguments for the Windows function on the stack. - */ - -ENTRY(x86_stdcall_call) - push %esi # must preserve %esi - push %edi # and %edi - - mov 16(%esp),%eax # get arg cnt - mov %eax,%ecx # save as copy count - mov %esp,%esi # Set source address register to point to - add $20,%esi # first agument to be forwarded. - shl $2,%eax # turn arg cnt into offset - sub %eax,%esp # shift stack to new location - mov %esp,%edi # store dest copy addr - rep # do the copy - movsl - - call ctxsw_utow # thunk - - call *12(%edi) # branch to stdcall routine - push %eax # preserve return val - push %edx - - call ctxsw_wtou # unthunk - - pop %edx - pop %eax # restore return val - mov %edi,%esp # restore stack - pop %edi # restore %edi - pop %esi # and %esi - ret - -/* - * Fastcall support. Similar to _stdcall, except the first - * two arguments are passed in %ecx and %edx. It happens we - * only support a small number of _fastcall APIs, none of them - * take more than three arguments. So to keep the code size - * and complexity down, we only handle 3 arguments here. - */ - -/* Call _fastcall function going from Windows to UNIX. */ - - .globl x86_fastcall_wrap_call - .globl x86_fastcall_wrap_arg - .globl x86_fastcall_wrap_end - -ENTRY(x86_fastcall_wrap) - mov 4(%esp),%eax - push %eax - push %edx - push %ecx - - movl $ctxsw_wtou, %eax - call *%eax # unthunk - -x86_fastcall_wrap_call: - mov $0,%eax - call *%eax # branch to fastcall routine - push %eax # preserve return val - push %edx - - movl $ctxsw_utow, %eax - call *%eax # thunk - - pop %edx - pop %eax # restore return val - add $12,%esp # clean the stack -x86_fastcall_wrap_arg: - ret $0xFF -x86_fastcall_wrap_end: - -/* - * Call _fastcall function going from UNIX to Windows. - * This routine isn't normally used since NDIS miniport drivers - * only have _stdcall entry points, but it's provided anyway - * to round out the API, and for testing purposes. - */ - -ENTRY(x86_fastcall_call) - mov 4(%esp),%eax - push 16(%esp) - - call ctxsw_utow # thunk - - mov 12(%esp),%ecx - mov 16(%esp),%edx - call *8(%esp) # branch to fastcall routine - push %eax # preserve return val - push %edx - - call ctxsw_wtou # unthunk - - pop %edx - pop %eax # restore return val - add $4,%esp # clean the stack - ret - -/* - * Call regparm(3) function going from Windows to UNIX. Arguments - * are passed in %eax, %edx and %ecx. Note that while additional - * arguments are passed on the stack, we never bother when them, - * since the only regparm(3) routines we need to wrap never take - * more than 3 arguments. - */ - - .globl x86_regparm_wrap_call - .globl x86_regparm_wrap_end - -ENTRY(x86_regparm_wrap) - push %ecx - push %edx - push %eax - - movl $ctxsw_wtou, %eax - call *%eax # unthunk - -x86_regparm_wrap_call: - movl $0,%eax - call *%eax # jump to routine - push %eax # preserve return val - push %edx # preserve return val - - movl $ctxsw_utow, %eax - call *%eax # thunk - - pop %edx # restore return val - pop %eax # restore return val - add $12,%esp # restore stack - ret -x86_regparm_wrap_end: - -/* - * Call regparm(3) function going from UNIX to Windows. - * This routine isn't normally used since NDIS miniport drivers - * only have _stdcall entry points, but it's provided anyway - * to round out the API, and for testing purposes. - */ - -ENTRY(x86_regparm_call) - call ctxsw_utow # thunk - - mov 8(%esp),%eax - mov 12(%esp),%edx - mov 16(%esp),%ecx - call *4(%esp) # branch to fastcall routine - push %eax # preserve return val - push %edx # preserve return val - - call ctxsw_wtou # unthunk - - pop %edx # restore return val - pop %eax # restore return val - ret - -/* - * Ugly hack alert: - * - * On Win32/i386, using __try/__except results in code that tries to - * manipulate what's supposed to be the Windows Threada Environment - * Block (TEB), which one accesses via the %fs register. In particular, - * %fs:0 (the first DWORD in the TEB) points to the exception - * registration list. Unfortunately, FreeBSD uses %fs for the - * per-cpu data structure (pcpu), and we can't allow Windows code - * to muck with that. I don't even know what Solaris uses %fs for - * (or if it even uses it at all). - * - * Even worse, in 32-bit protected mode, %fs is a selector that - * refers to an entry in either the GDT or the LDT. Ideally, we would - * like to be able to temporarily point it at another descriptor - * while Windows code executes, but to do that we need a separate - * descriptor entry of our own to play with. - * - * Therefore, we go to some trouble to learn the existing layout of - * the GDT and update it to include an extra entry that we can use. - * We need the following utility routines to help us do that. On - * FreeBSD, index #7 in the GDT happens to be unused, so we turn - * this into our own data segment descriptor. It would be better - * if we could use a private LDT entry, but there's no easy way to - * do that in SMP mode because of the way FreeBSD handles user LDTs. - * - * Once we have a custom descriptor, we have to thunk/unthunk whenever - * we cross between FreeBSD code and Windows code. The thunking is - * based on the premise that when executing instructions in the - * Windows binary itself, we won't go to sleep. This is because in - * order to yield the CPU, the code has to call back out to a FreeBSD - * routine first, and when that happens we can unthunk in order to - * restore FreeBSD context. What we're desperately trying to avoid is - * being involuntarily pre-empted with the %fs register still pointing - * to our fake TIB: if FreeBSD code runs with %fs pointing at our - * Windows TIB instead of pcpu, we'll panic the kernel. Fortunately, - * the only way involuntary preemption can occur is if an interrupt - * fires, and the trap handler saves/restores %fs for us. - * - * The thunking routines themselves, ctxsw_utow() (Context SWitch UNIX - * to Windows) and ctxsw_wtou() (Context SWitch Windows to UNIX), are - * external to this module. This is done simply because it's easier - * to manipulate data structures in C rather than assembly. - */ - -ENTRY(x86_getldt) - movl 4(%esp),%eax - sgdtl (%eax) - movl 8(%esp),%eax - sldt (%eax) - xor %eax,%eax - ret - -ENTRY(x86_setldt) - movl 4(%esp),%eax - lgdt (%eax) - jmp 1f - nop -1: - movl 8(%esp),%eax - lldt %ax - xor %eax,%eax - ret - -ENTRY(x86_getfs) - mov %fs,%ax - ret - -ENTRY(x86_setfs) - mov 4(%esp),%fs - ret - -ENTRY(x86_gettid) - mov %fs:12,%eax - ret - -ENTRY(x86_critical_enter) - cli - ret - -ENTRY(x86_critical_exit) - sti - ret diff --git a/sys/compat/ndis/winx64_wrap.S b/sys/compat/ndis/winx64_wrap.S deleted file mode 100644 index 3e5d994ab70b..000000000000 --- a/sys/compat/ndis/winx64_wrap.S +++ /dev/null @@ -1,179 +0,0 @@ -/*- - * Copyright (c) 2005 - * Bill Paul . 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. - * - * The x86_64 callback routines were written and graciously submitted - * by Ville-Pertti Keinonen . - * - * $FreeBSD$ - */ - -#include - -/* - * Wrapper for handling up to 16 arguments. We can't really - * know how many arguments the caller will pass us. I'm taking an - * educated guess that we'll never get over 16. Handling too - * few arguments is bad. Handling too many is inefficient, but - * not fatal. If someone can think of a way to handle an arbitrary - * number of arguments with more elegant code, freel free to let - * me know. - * - * Standard amd64 calling conventions specify the following registers - * to be used for passing the first 6 arguments: - * - * %rdi, %rsi, %rdx, %rcx, %r8, %r9 - * - * Further arguments are passed on the stack (the 7th argument is - * located immediately after the return address). - * - * Windows x86_64 calling conventions only pass the first 4 - * arguments in registers: - * - * %rcx, %rdx, %r8, %r9 - * - * Even when arguments are passed in registers, the stack must have - * space reserved for those arguments. Thus the 5th argument (the - * first non-register argument) is placed 32 bytes after the return - * address. Additionally, %rdi and %rsi must be preserved. (These - * two registers are not scratch registers in the standard convention.) - * - * Note that in this template, we load a contrived 64 bit address into - * %r11 to represent our jump address. This is to guarantee that the - * assembler leaves enough room to patch in an absolute 64-bit address - * later. The idea behind this code is that we want to avoid having to - * manually create all the wrapper functions at compile time with - * a bunch of macros. This is doable, but a) messy and b) requires - * us to maintain two separate tables (one for the UNIX function - * pointers and another with the wrappers). This means I'd have to - * update two different tables each time I added a function. - * - * To avoid this, we create the wrappers at runtime instead. The - * image patch tables now contain two pointers: one two the normal - * routine, and a blank one for the wrapper. To construct a wrapper, - * we allocate some memory and copy the template function into it, - * then patch the function pointer for the routine we want to wrap - * into the newly created wrapper. The subr_pe module can then - * simply patch the wrapper routine into the jump table into the - * windows image. As a bonus, the wrapper pointer not only serves - * as the wrapper entry point address, it's also a data pointer - * that we can pass to free() later when we unload the module. - */ - - .globl x86_64_wrap_call - .globl x86_64_wrap_end - -ENTRY(x86_64_wrap) - push %rbp # insure that the stack - mov %rsp,%rbp # is 16-byte aligned - and $-16,%rsp # - subq $96,%rsp # allocate space on stack - mov %rsi,96-8(%rsp) # save %rsi - mov %rdi,96-16(%rsp)# save %rdi - mov %rcx,%r10 # temporarily save %rcx in scratch - lea 56+8(%rbp),%rsi # source == old stack top (stack+56) - mov %rsp,%rdi # destination == new stack top - mov $10,%rcx # count == 10 quadwords - rep - movsq # copy old stack contents to new location - mov %r10,%rdi # set up arg0 (%rcx -> %rdi) - mov %rdx,%rsi # set up arg1 (%rdx -> %rsi) - mov %r8,%rdx # set up arg2 (%r8 -> %rdx) - mov %r9,%rcx # set up arg3 (%r9 -> %rcx) - mov 40+8(%rbp),%r8 # set up arg4 (stack+40 -> %r8) - mov 48+8(%rbp),%r9 # set up arg5 (stack+48 -> %r9) - xor %rax,%rax # clear return value -x86_64_wrap_call: - mov $0xFF00FF00FF00FF00,%r11 - callq *%r11 # call routine - mov 96-16(%rsp),%rdi# restore %rdi - mov 96-8(%rsp),%rsi # restore %rsi - leave # delete space on stack - ret -x86_64_wrap_end: - -/* - * Functions for invoking x86_64 callbacks. In each case, the first - * argument is a pointer to the function. - */ - -ENTRY(x86_64_call1) - subq $40,%rsp - mov %rsi,%rcx - call *%rdi - addq $40,%rsp - ret - -ENTRY(x86_64_call2) - subq $40,%rsp - mov %rsi,%rcx - /* %rdx is already correct */ - call *%rdi - addq $40,%rsp - ret - -ENTRY(x86_64_call3) - subq $40,%rsp - mov %rcx,%r8 - mov %rsi,%rcx - call *%rdi - addq $40,%rsp - ret - -ENTRY(x86_64_call4) - subq $40,%rsp - mov %r8,%r9 - mov %rcx,%r8 - mov %rsi,%rcx - call *%rdi - addq $40,%rsp - ret - -ENTRY(x86_64_call5) - subq $48,%rsp - mov %r9,32(%rsp) - mov %r8,%r9 - mov %rcx,%r8 - mov %rsi,%rcx - call *%rdi - addq $48,%rsp - ret - -ENTRY(x86_64_call6) - subq $56,%rsp - mov 56+8(%rsp),%rax - mov %r9,32(%rsp) - mov %rax,40(%rsp) - mov %r8,%r9 - mov %rcx,%r8 - mov %rsi,%rcx - call *%rdi - addq $56,%rsp - ret diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index ddd4e07b365c..395f501198f8 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -438,7 +438,6 @@ compat/linux/linux.c optional compat_linux32 x86/linux/linux_dummy_x86.c optional compat_linux32 dev/amr/amr_linux.c optional compat_linux32 amr dev/mfi/mfi_linux.c optional compat_linux32 mfi -compat/ndis/winx64_wrap.S optional ndisapi pci # # x86 real mode BIOS emulator, required by dpms/pci/vesa # diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index b5192e47a738..6560ab217d96 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -75,7 +75,6 @@ compat/linux/linux_uid16.c optional compat_linux compat/linux/linux_util.c optional compat_linux compat/linux/linux_vdso.c optional compat_linux compat/linux/linux.c optional compat_linux -compat/ndis/winx32_wrap.S optional ndisapi pci crypto/aesni/aeskeys_i386.S optional aesni crypto/des/arch/i386/des_enc.S optional netsmb crypto/openssl/i386/sha1-586.S optional ossl diff --git a/sys/conf/files.x86 b/sys/conf/files.x86 index f51392d0614c..cb7fabf44cfb 100644 --- a/sys/conf/files.x86 +++ b/sys/conf/files.x86 @@ -20,13 +20,6 @@ atkbdmap.h optional atkbd_dflt_keymap \ cddl/dev/fbt/x86/fbt_isa.c optional dtrace_fbt | dtraceall compile-with "${FBT_C}" cddl/dev/dtrace/x86/dis_tables.c optional dtrace_fbt | dtraceall compile-with "${DTRACE_C}" cddl/dev/dtrace/x86/instr_size.c optional dtrace_fbt | dtraceall compile-with "${DTRACE_C}" -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 -compat/ndis/subr_pe.c optional ndisapi pci -compat/ndis/subr_usbd.c optional ndisapi pci crypto/aesni/aesni.c optional aesni aesni_ghash.o optional aesni \ dependency "$S/crypto/aesni/aesni_ghash.c" \ @@ -157,9 +150,6 @@ dev/hyperv/vmbus/vmbus_if.m optional hyperv dev/hyperv/vmbus/vmbus_res.c optional hyperv dev/hyperv/vmbus/vmbus_xact.c optional hyperv dev/ichwd/ichwd.c optional ichwd -dev/if_ndis/if_ndis.c optional ndis -dev/if_ndis/if_ndis_pci.c optional ndis cardbus | ndis pci -dev/if_ndis/if_ndis_usb.c optional ndis usb dev/imcsmb/imcsmb.c optional imcsmb dev/imcsmb/imcsmb_pci.c optional imcsmb pci dev/intel/spi.c optional intelspi diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c deleted file mode 100644 index 1a5e8eeed4be..000000000000 --- a/sys/dev/if_ndis/if_ndis.c +++ /dev/null @@ -1,3423 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul . All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * WPA support originally contributed by Arvind Srinivasan - * then hacked upon mercilessly by my. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#define NDIS_DEBUG -#ifdef NDIS_DEBUG -#define DPRINTF(x) do { if (ndis_debug > 0) printf x; } while (0) -int ndis_debug = 0; -SYSCTL_INT(_debug, OID_AUTO, ndis, CTLFLAG_RW, &ndis_debug, 0, - "if_ndis debug level"); -#else -#define DPRINTF(x) -#endif - -SYSCTL_DECL(_hw_ndisusb); -int ndisusb_halt = 1; -SYSCTL_INT(_hw_ndisusb, OID_AUTO, halt, CTLFLAG_RW, &ndisusb_halt, 0, - "Halt NDIS USB driver when it's attached"); - -/* 0 - 30 dBm to mW conversion table */ -static const uint16_t dBm2mW[] = { - 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, - 3, 4, 4, 4, 5, 6, 6, 7, 8, 9, - 10, 11, 13, 14, 16, 18, 20, 22, 25, 28, - 32, 35, 40, 45, 50, 56, 63, 71, 79, 89, - 100, 112, 126, 141, 158, 178, 200, 224, 251, 282, - 316, 355, 398, 447, 501, 562, 631, 708, 794, 891, - 1000 -}; - -MODULE_DEPEND(ndis, ether, 1, 1, 1); -MODULE_DEPEND(ndis, wlan, 1, 1, 1); -MODULE_DEPEND(ndis, ndisapi, 1, 1, 1); - -MODULE_VERSION(ndis, 1); - -int ndis_attach (device_t); -int ndis_detach (device_t); -int ndis_suspend (device_t); -int ndis_resume (device_t); -void ndis_shutdown (device_t); - -int ndisdrv_modevent (module_t, int, void *); - -static void ndis_txeof (ndis_handle, ndis_packet *, ndis_status); -static void ndis_rxeof (ndis_handle, ndis_packet **, uint32_t); -static void ndis_rxeof_eth (ndis_handle, ndis_handle, char *, void *, - uint32_t, void *, uint32_t, uint32_t); -static void ndis_rxeof_done (ndis_handle); -static void ndis_rxeof_xfr (kdpc *, ndis_handle, void *, void *); -static void ndis_rxeof_xfr_done (ndis_handle, ndis_packet *, - uint32_t, uint32_t); -static void ndis_linksts (ndis_handle, ndis_status, void *, uint32_t); -static void ndis_linksts_done (ndis_handle); - -/* We need to wrap these functions for amd64. */ -static funcptr ndis_txeof_wrap; -static funcptr ndis_rxeof_wrap; -static funcptr ndis_rxeof_eth_wrap; -static funcptr ndis_rxeof_done_wrap; -static funcptr ndis_rxeof_xfr_wrap; -static funcptr ndis_rxeof_xfr_done_wrap; -static funcptr ndis_linksts_wrap; -static funcptr ndis_linksts_done_wrap; -static funcptr ndis_ticktask_wrap; -static funcptr ndis_ifstarttask_wrap; -static funcptr ndis_resettask_wrap; -static funcptr ndis_inputtask_wrap; - -static struct ieee80211vap *ndis_vap_create(struct ieee80211com *, - const char [IFNAMSIZ], int, enum ieee80211_opmode, int, - const uint8_t [IEEE80211_ADDR_LEN], - const uint8_t [IEEE80211_ADDR_LEN]); -static void ndis_vap_delete (struct ieee80211vap *); -static void ndis_tick (void *); -static void ndis_ticktask (device_object *, void *); -static int ndis_raw_xmit (struct ieee80211_node *, struct mbuf *, - const struct ieee80211_bpf_params *); -static void ndis_update_mcast (struct ieee80211com *); -static void ndis_update_promisc (struct ieee80211com *); -static void ndis_ifstart (struct ifnet *); -static void ndis_ifstarttask (device_object *, void *); -static void ndis_resettask (device_object *, void *); -static void ndis_inputtask (device_object *, void *); -static int ndis_ifioctl (struct ifnet *, u_long, caddr_t); -static int ndis_newstate (struct ieee80211vap *, enum ieee80211_state, - int); -static int ndis_nettype_chan (uint32_t); -static int ndis_nettype_mode (uint32_t); -static void ndis_scan (void *); -static void ndis_scan_results (struct ndis_softc *); -static void ndis_scan_start (struct ieee80211com *); -static void ndis_scan_end (struct ieee80211com *); -static void ndis_set_channel (struct ieee80211com *); -static void ndis_scan_curchan (struct ieee80211_scan_state *, unsigned long); -static void ndis_scan_mindwell (struct ieee80211_scan_state *); -static void ndis_init (void *); -static void ndis_stop (struct ndis_softc *); -static int ndis_ifmedia_upd (struct ifnet *); -static void ndis_ifmedia_sts (struct ifnet *, struct ifmediareq *); -static int ndis_get_bssid_list (struct ndis_softc *, - ndis_80211_bssid_list_ex **); -static int ndis_get_assoc (struct ndis_softc *, ndis_wlan_bssid_ex **); -static int ndis_probe_offload (struct ndis_softc *); -static int ndis_set_offload (struct ndis_softc *); -static void ndis_getstate_80211 (struct ndis_softc *); -static void ndis_setstate_80211 (struct ndis_softc *); -static void ndis_auth_and_assoc (struct ndis_softc *, struct ieee80211vap *); -static void ndis_media_status (struct ifnet *, struct ifmediareq *); -static int ndis_set_cipher (struct ndis_softc *, int); -static int ndis_set_wpa (struct ndis_softc *, void *, int); -static int ndis_add_key (struct ieee80211vap *, - const struct ieee80211_key *); -static int ndis_del_key (struct ieee80211vap *, - const struct ieee80211_key *); -static void ndis_setmulti (struct ndis_softc *); -static void ndis_map_sclist (void *, bus_dma_segment_t *, - int, bus_size_t, int); -static int ndis_ifattach(struct ndis_softc *); - -static int ndis_80211attach(struct ndis_softc *); -static int ndis_80211ioctl(struct ieee80211com *, u_long , void *); -static int ndis_80211transmit(struct ieee80211com *, struct mbuf *); -static void ndis_80211parent(struct ieee80211com *); - -static int ndisdrv_loaded = 0; - -/* - * This routine should call windrv_load() once for each driver - * image. This will do the relocation and dynalinking for the - * image, and create a Windows driver object which will be - * saved in our driver database. - */ -int -ndisdrv_modevent(mod, cmd, arg) - module_t mod; - int cmd; - void *arg; -{ - int error = 0; - - switch (cmd) { - case MOD_LOAD: - ndisdrv_loaded++; - if (ndisdrv_loaded > 1) - break; - windrv_wrap((funcptr)ndis_rxeof, &ndis_rxeof_wrap, - 3, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_rxeof_eth, &ndis_rxeof_eth_wrap, - 8, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_rxeof_done, &ndis_rxeof_done_wrap, - 1, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_rxeof_xfr, &ndis_rxeof_xfr_wrap, - 4, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_rxeof_xfr_done, - &ndis_rxeof_xfr_done_wrap, 4, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_txeof, &ndis_txeof_wrap, - 3, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_linksts, &ndis_linksts_wrap, - 4, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_linksts_done, - &ndis_linksts_done_wrap, 1, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_ticktask, &ndis_ticktask_wrap, - 2, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_ifstarttask, &ndis_ifstarttask_wrap, - 2, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_resettask, &ndis_resettask_wrap, - 2, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)ndis_inputtask, &ndis_inputtask_wrap, - 2, WINDRV_WRAP_STDCALL); - break; - case MOD_UNLOAD: - ndisdrv_loaded--; - if (ndisdrv_loaded > 0) - break; - /* fallthrough */ - case MOD_SHUTDOWN: - windrv_unwrap(ndis_rxeof_wrap); - windrv_unwrap(ndis_rxeof_eth_wrap); - windrv_unwrap(ndis_rxeof_done_wrap); - windrv_unwrap(ndis_rxeof_xfr_wrap); - windrv_unwrap(ndis_rxeof_xfr_done_wrap); - windrv_unwrap(ndis_txeof_wrap); - windrv_unwrap(ndis_linksts_wrap); - windrv_unwrap(ndis_linksts_done_wrap); - windrv_unwrap(ndis_ticktask_wrap); - windrv_unwrap(ndis_ifstarttask_wrap); - windrv_unwrap(ndis_resettask_wrap); - windrv_unwrap(ndis_inputtask_wrap); - break; - default: - error = EINVAL; - break; - } - - return (error); -} - -struct mclist_ctx { - uint8_t *mclist; - int mclistsz; -}; - -static u_int -ndis_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) -{ - struct mclist_ctx *ctx = arg; - - if (cnt < ctx->mclistsz) - bcopy(LLADDR(sdl), ctx->mclist + (ETHER_ADDR_LEN * cnt), - ETHER_ADDR_LEN); - return (1); -} - -/* - * Program the 64-bit multicast hash filter. - */ -static void -ndis_setmulti(sc) - struct ndis_softc *sc; -{ - struct ifnet *ifp; - struct mclist_ctx ctx; - int len, error; - - - if (!NDIS_INITIALIZED(sc)) - return; - - if (sc->ndis_80211) - return; - - ifp = sc->ifp; - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { - sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; - len = sizeof(sc->ndis_filter); - error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER, - &sc->ndis_filter, &len); - if (error) - device_printf(sc->ndis_dev, - "set allmulti failed: %d\n", error); - return; - } - - if (if_llmaddr_count(ifp) == 0) - return; - - len = sizeof(ctx.mclistsz); - ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &ctx.mclistsz, &len); - - ctx.mclist = malloc(ETHER_ADDR_LEN * ctx.mclistsz, M_TEMP, - M_NOWAIT | M_ZERO); - - if (ctx.mclist == NULL) { - sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; - goto out; - } - - sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST; - - len = if_foreach_llmaddr(ifp, ndis_copy_maddr, &ctx); - if (len > ctx.mclistsz) { - sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; - sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST; - goto out; - } - - len = len * ETHER_ADDR_LEN; - error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, ctx.mclist, &len); - if (error) { - device_printf(sc->ndis_dev, "set mclist failed: %d\n", error); - sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; - sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST; - } - -out: - free(ctx.mclist, M_TEMP); - - len = sizeof(sc->ndis_filter); - error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER, - &sc->ndis_filter, &len); - if (error) - device_printf(sc->ndis_dev, "set multi failed: %d\n", error); -} - -static int -ndis_set_offload(sc) - struct ndis_softc *sc; -{ - ndis_task_offload *nto; - ndis_task_offload_hdr *ntoh; - ndis_task_tcpip_csum *nttc; - struct ifnet *ifp; - int len, error; - - if (!NDIS_INITIALIZED(sc)) - return (EINVAL); - - if (sc->ndis_80211) - return (EINVAL); - /* See if there's anything to set. */ - - ifp = sc->ifp; - error = ndis_probe_offload(sc); - if (error) - return (error); - - if (sc->ndis_hwassist == 0 && ifp->if_capabilities == 0) - return (0); - - len = sizeof(ndis_task_offload_hdr) + sizeof(ndis_task_offload) + - sizeof(ndis_task_tcpip_csum); - - ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO); - - if (ntoh == NULL) - return (ENOMEM); - - ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION; - ntoh->ntoh_len = sizeof(ndis_task_offload_hdr); - ntoh->ntoh_offset_firsttask = sizeof(ndis_task_offload_hdr); - ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header); - ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3; - ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN; - - nto = (ndis_task_offload *)((char *)ntoh + - ntoh->ntoh_offset_firsttask); - - nto->nto_vers = NDIS_TASK_OFFLOAD_VERSION; - nto->nto_len = sizeof(ndis_task_offload); - nto->nto_task = NDIS_TASK_TCPIP_CSUM; - nto->nto_offset_nexttask = 0; - nto->nto_taskbuflen = sizeof(ndis_task_tcpip_csum); - - nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf; - - if (ifp->if_capenable & IFCAP_TXCSUM) - nttc->nttc_v4tx = sc->ndis_v4tx; - - if (ifp->if_capenable & IFCAP_RXCSUM) - nttc->nttc_v4rx = sc->ndis_v4rx; - - error = ndis_set_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len); - free(ntoh, M_TEMP); - - return (error); -} - -static int -ndis_probe_offload(sc) - struct ndis_softc *sc; -{ - ndis_task_offload *nto; - ndis_task_offload_hdr *ntoh; - ndis_task_tcpip_csum *nttc = NULL; - struct ifnet *ifp; - int len, error, dummy; - - ifp = sc->ifp; - - len = sizeof(dummy); - error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, &dummy, &len); - - if (error != ENOSPC) - return (error); - - ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO); - - if (ntoh == NULL) - return (ENOMEM); - - ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION; - ntoh->ntoh_len = sizeof(ndis_task_offload_hdr); - ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header); - ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3; - ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN; - - error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len); - - if (error) { - free(ntoh, M_TEMP); - return (error); - } - - if (ntoh->ntoh_vers != NDIS_TASK_OFFLOAD_VERSION) { - free(ntoh, M_TEMP); - return (EINVAL); - } - - nto = (ndis_task_offload *)((char *)ntoh + - ntoh->ntoh_offset_firsttask); - - while (1) { - switch (nto->nto_task) { - case NDIS_TASK_TCPIP_CSUM: - nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf; - break; - /* Don't handle these yet. */ - case NDIS_TASK_IPSEC: - case NDIS_TASK_TCP_LARGESEND: - default: - break; - } - if (nto->nto_offset_nexttask == 0) - break; - nto = (ndis_task_offload *)((char *)nto + - nto->nto_offset_nexttask); - } - - if (nttc == NULL) { - free(ntoh, M_TEMP); - return (ENOENT); - } - - sc->ndis_v4tx = nttc->nttc_v4tx; - sc->ndis_v4rx = nttc->nttc_v4rx; - - if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_IP_CSUM) - sc->ndis_hwassist |= CSUM_IP; - if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_TCP_CSUM) - sc->ndis_hwassist |= CSUM_TCP; - if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_UDP_CSUM) - sc->ndis_hwassist |= CSUM_UDP; - - if (sc->ndis_hwassist) - ifp->if_capabilities |= IFCAP_TXCSUM; - - if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_IP_CSUM) - ifp->if_capabilities |= IFCAP_RXCSUM; - if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_TCP_CSUM) - ifp->if_capabilities |= IFCAP_RXCSUM; - if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_UDP_CSUM) - ifp->if_capabilities |= IFCAP_RXCSUM; - - free(ntoh, M_TEMP); - return (0); -} - -static int -ndis_nettype_chan(uint32_t type) -{ - switch (type) { - case NDIS_80211_NETTYPE_11FH: return (IEEE80211_CHAN_FHSS); - case NDIS_80211_NETTYPE_11DS: return (IEEE80211_CHAN_B); - case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_CHAN_A); - case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_CHAN_G); - } - DPRINTF(("unknown channel nettype %d\n", type)); - return (IEEE80211_CHAN_B); /* Default to 11B chan */ -} - -static int -ndis_nettype_mode(uint32_t type) -{ - switch (type) { - case NDIS_80211_NETTYPE_11FH: return (IEEE80211_MODE_FH); - case NDIS_80211_NETTYPE_11DS: return (IEEE80211_MODE_11B); - case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_MODE_11A); - case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_MODE_11G); - } - DPRINTF(("unknown mode nettype %d\n", type)); - return (IEEE80211_MODE_AUTO); -} - -/* - * Attach the interface. Allocate softc structures, do ifmedia - * setup and ethernet/BPF attach. - */ -int -ndis_attach(device_t dev) -{ - struct ndis_softc *sc; - driver_object *pdrv; - device_object *pdo; - int error = 0, len; - int i; - - sc = device_get_softc(dev); - - mtx_init(&sc->ndis_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, - MTX_DEF); - KeInitializeSpinLock(&sc->ndis_rxlock); - KeInitializeSpinLock(&sc->ndisusb_tasklock); - KeInitializeSpinLock(&sc->ndisusb_xferdonelock); - InitializeListHead(&sc->ndis_shlist); - InitializeListHead(&sc->ndisusb_tasklist); - InitializeListHead(&sc->ndisusb_xferdonelist); - callout_init(&sc->ndis_stat_callout, 1); - mbufq_init(&sc->ndis_rxqueue, INT_MAX); /* XXXGL: sane maximum */ - - /* Create sysctl registry nodes */ - ndis_create_sysctls(sc); - - /* Find the PDO for this device instance. */ - - if (sc->ndis_iftype == PCIBus) - pdrv = windrv_lookup(0, "PCI Bus"); - else if (sc->ndis_iftype == PCMCIABus) - pdrv = windrv_lookup(0, "PCCARD Bus"); - else - pdrv = windrv_lookup(0, "USB Bus"); - pdo = windrv_find_pdo(pdrv, dev); - - /* - * Create a new functional device object for this - * device. This is what creates the miniport block - * for this device instance. - */ - - if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) { - device_printf(dev, "failed to create FDO!\n"); - error = ENXIO; - goto fail; - } - - /* Tell the user what version of the API the driver is using. */ - device_printf(dev, "NDIS API version: %d.%d\n", - sc->ndis_chars->nmc_version_major, - sc->ndis_chars->nmc_version_minor); - - /* Do resource conversion. */ - if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus) - ndis_convert_res(sc); - else - sc->ndis_block->nmb_rlist = NULL; - - /* Install our RX and TX interrupt handlers. */ - sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap; - sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap; - sc->ndis_block->nmb_ethrxindicate_func = ndis_rxeof_eth_wrap; - sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap; - sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap; - - /* Override the status handler so we can detect link changes. */ - sc->ndis_block->nmb_status_func = ndis_linksts_wrap; - sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap; - - /* Set up work item handlers. */ - sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); - sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); - sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); - sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); - sc->ndisusb_xferdoneitem = - IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); - sc->ndisusb_taskitem = - IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); - KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block); - - /* Call driver's init routine. */ - if (ndis_init_nic(sc)) { - device_printf(dev, "init handler failed\n"); - error = ENXIO; - goto fail; - } - - /* - * Figure out how big to make the TX buffer pool. - */ - len = sizeof(sc->ndis_maxpkts); - if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS, - &sc->ndis_maxpkts, &len)) { - device_printf(dev, "failed to get max TX packets\n"); - error = ENXIO; - goto fail; - } - - /* - * If this is a deserialized miniport, we don't have - * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result. - */ - if (!NDIS_SERIALIZED(sc->ndis_block)) - sc->ndis_maxpkts = NDIS_TXPKTS; - - /* Enforce some sanity, just in case. */ - - if (sc->ndis_maxpkts == 0) - sc->ndis_maxpkts = 10; - - sc->ndis_txarray = malloc(sizeof(ndis_packet *) * - sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO); - - /* Allocate a pool of ndis_packets for TX encapsulation. */ - - NdisAllocatePacketPool(&i, &sc->ndis_txpool, - sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET); - - if (i != NDIS_STATUS_SUCCESS) { - sc->ndis_txpool = NULL; - device_printf(dev, "failed to allocate TX packet pool"); - error = ENOMEM; - goto fail; - } - - sc->ndis_txpending = sc->ndis_maxpkts; - - sc->ndis_oidcnt = 0; - /* Get supported oid list. */ - ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt); - - /* If the NDIS module requested scatter/gather, init maps. */ - if (sc->ndis_sc) - ndis_init_dma(sc); - - /* - * See if the OID_802_11_CONFIGURATION OID is - * supported by this driver. If it is, then this an 802.11 - * wireless driver, and we should set up media for wireless. - */ - for (i = 0; i < sc->ndis_oidcnt; i++) - if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) { - sc->ndis_80211 = 1; - break; - } - - if (sc->ndis_80211) - error = ndis_80211attach(sc); - else - error = ndis_ifattach(sc); - -fail: - if (error) { - ndis_detach(dev); - return (error); - } - - if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0) - return (error); - - DPRINTF(("attach done.\n")); - /* We're done talking to the NIC for now; halt it. */ - ndis_halt_nic(sc); - DPRINTF(("halting done.\n")); - - return (error); -} - -static int -ndis_80211attach(struct ndis_softc *sc) -{ - struct ieee80211com *ic = &sc->ndis_ic; - ndis_80211_rates_ex rates; - struct ndis_80211_nettype_list *ntl; - uint32_t arg; - int mode, i, r, len, nonettypes = 1; - uint8_t bands[IEEE80211_MODE_BYTES] = { 0 }; - - callout_init(&sc->ndis_scan_callout, 1); - - ic->ic_softc = sc; - ic->ic_ioctl = ndis_80211ioctl; - ic->ic_name = device_get_nameunit(sc->ndis_dev); - ic->ic_opmode = IEEE80211_M_STA; - ic->ic_phytype = IEEE80211_T_DS; - ic->ic_caps = IEEE80211_C_8023ENCAP | - IEEE80211_C_STA | IEEE80211_C_IBSS; - setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO); - len = 0; - r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, NULL, &len); - if (r != ENOSPC) - goto nonettypes; - ntl = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); - r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, ntl, &len); - if (r != 0) { - free(ntl, M_DEVBUF); - goto nonettypes; - } - - for (i = 0; i < ntl->ntl_items; i++) { - mode = ndis_nettype_mode(ntl->ntl_type[i]); - if (mode) { - nonettypes = 0; - setbit(ic->ic_modecaps, mode); - setbit(bands, mode); - } else - device_printf(sc->ndis_dev, "Unknown nettype %d\n", - ntl->ntl_type[i]); - } - free(ntl, M_DEVBUF); -nonettypes: - /* Default to 11b channels if the card did not supply any */ - if (nonettypes) { - setbit(ic->ic_modecaps, IEEE80211_MODE_11B); - setbit(bands, IEEE80211_MODE_11B); - } - len = sizeof(rates); - bzero((char *)&rates, len); - r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len); - if (r != 0) - device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r); - /* - * Since the supported rates only up to 8 can be supported, - * if this is not 802.11b we're just going to be faking it - * all up to heck. - */ - -#define TESTSETRATE(x, y) \ - do { \ - int i; \ - for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \ - if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \ - break; \ - } \ - if (i == ic->ic_sup_rates[x].rs_nrates) { \ - ic->ic_sup_rates[x].rs_rates[i] = (y); \ - ic->ic_sup_rates[x].rs_nrates++; \ - } \ - } while (0) - -#define SETRATE(x, y) \ - ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y) -#define INCRATE(x) \ - ic->ic_sup_rates[x].rs_nrates++ - - ic->ic_curmode = IEEE80211_MODE_AUTO; - if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) - ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0; - if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) - ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0; - if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) - ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0; - for (i = 0; i < len; i++) { - switch (rates[i] & IEEE80211_RATE_VAL) { - case 2: - case 4: - case 11: - case 10: - case 22: - if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) { - /* Lazy-init 802.11b. */ - setbit(ic->ic_modecaps, IEEE80211_MODE_11B); - ic->ic_sup_rates[IEEE80211_MODE_11B]. - rs_nrates = 0; - } - SETRATE(IEEE80211_MODE_11B, rates[i]); - INCRATE(IEEE80211_MODE_11B); - break; - default: - if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) { - SETRATE(IEEE80211_MODE_11A, rates[i]); - INCRATE(IEEE80211_MODE_11A); - } - if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) { - SETRATE(IEEE80211_MODE_11G, rates[i]); - INCRATE(IEEE80211_MODE_11G); - } - break; - } - } - - /* - * If the hardware supports 802.11g, it most - * likely supports 802.11b and all of the - * 802.11b and 802.11g speeds, so maybe we can - * just cheat here. Just how in the heck do - * we detect turbo modes, though? - */ - if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) { - TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|2); - TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|4); - TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|11); - TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|22); - } - if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) { - TESTSETRATE(IEEE80211_MODE_11G, 48); - TESTSETRATE(IEEE80211_MODE_11G, 72); - TESTSETRATE(IEEE80211_MODE_11G, 96); - TESTSETRATE(IEEE80211_MODE_11G, 108); - } - if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) { - TESTSETRATE(IEEE80211_MODE_11A, 48); - TESTSETRATE(IEEE80211_MODE_11A, 72); - TESTSETRATE(IEEE80211_MODE_11A, 96); - TESTSETRATE(IEEE80211_MODE_11A, 108); - } - -#undef SETRATE -#undef INCRATE -#undef TESTSETRATE - - ieee80211_init_channels(ic, NULL, bands); - - /* - * To test for WPA support, we need to see if we can - * set AUTHENTICATION_MODE to WPA and read it back - * successfully. - */ - i = sizeof(arg); - arg = NDIS_80211_AUTHMODE_WPA; - r = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i); - if (r == 0) { - r = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i); - if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA) - ic->ic_caps |= IEEE80211_C_WPA; - } - - /* - * To test for supported ciphers, we set each - * available encryption type in descending order. - * If ENC3 works, then we have WEP, TKIP and AES. - * If only ENC2 works, then we have WEP and TKIP. - * If only ENC1 works, then we have just WEP. - */ - i = sizeof(arg); - arg = NDIS_80211_WEPSTAT_ENC3ENABLED; - r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i); - if (r == 0) { - ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP - | IEEE80211_CRYPTO_TKIP - | IEEE80211_CRYPTO_AES_CCM; - goto got_crypto; - } - arg = NDIS_80211_WEPSTAT_ENC2ENABLED; - r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i); - if (r == 0) { - ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP - | IEEE80211_CRYPTO_TKIP; - goto got_crypto; - } - arg = NDIS_80211_WEPSTAT_ENC1ENABLED; - r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i); - if (r == 0) - ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP; -got_crypto: - i = sizeof(arg); - r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i); - if (r == 0) - ic->ic_caps |= IEEE80211_C_PMGT; - - r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i); - if (r == 0) - ic->ic_caps |= IEEE80211_C_TXPMGT; - - /* - * Get station address from the driver. - */ - len = sizeof(ic->ic_macaddr); - ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &ic->ic_macaddr, &len); - - ieee80211_ifattach(ic); - ic->ic_raw_xmit = ndis_raw_xmit; - ic->ic_scan_start = ndis_scan_start; - ic->ic_scan_end = ndis_scan_end; - ic->ic_set_channel = ndis_set_channel; - ic->ic_scan_curchan = ndis_scan_curchan; - ic->ic_scan_mindwell = ndis_scan_mindwell; - ic->ic_bsschan = IEEE80211_CHAN_ANYC; - ic->ic_vap_create = ndis_vap_create; - ic->ic_vap_delete = ndis_vap_delete; - ic->ic_update_mcast = ndis_update_mcast; - ic->ic_update_promisc = ndis_update_promisc; - ic->ic_transmit = ndis_80211transmit; - ic->ic_parent = ndis_80211parent; - - if (bootverbose) - ieee80211_announce(ic); - - return (0); -} - -static int -ndis_ifattach(struct ndis_softc *sc) -{ - struct ifnet *ifp; - u_char eaddr[ETHER_ADDR_LEN]; - int len; - - ifp = if_alloc(IFT_ETHER); - if (ifp == NULL) - return (ENOSPC); - sc->ifp = ifp; - ifp->if_softc = sc; - - /* Check for task offload support. */ - ndis_probe_offload(sc); - - /* - * Get station address from the driver. - */ - len = sizeof(eaddr); - ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, eaddr, &len); - - if_initname(ifp, device_get_name(sc->ndis_dev), - device_get_unit(sc->ndis_dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = ndis_ifioctl; - ifp->if_start = ndis_ifstart; - ifp->if_init = ndis_init; - ifp->if_baudrate = 10000000; - IFQ_SET_MAXLEN(&ifp->if_snd, 50); - ifp->if_snd.ifq_drv_maxlen = 25; - IFQ_SET_READY(&ifp->if_snd); - ifp->if_capenable = ifp->if_capabilities; - ifp->if_hwassist = sc->ndis_hwassist; - - ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd, - ndis_ifmedia_sts); - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL); - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL); - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); - ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO); - ether_ifattach(ifp, eaddr); - - return (0); -} - -static struct ieee80211vap * -ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, - enum ieee80211_opmode opmode, int flags, - const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct ndis_vap *nvp; - struct ieee80211vap *vap; - - if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ - return NULL; - nvp = malloc(sizeof(struct ndis_vap), M_80211_VAP, M_WAITOK | M_ZERO); - vap = &nvp->vap; - ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); - /* override with driver methods */ - nvp->newstate = vap->iv_newstate; - vap->iv_newstate = ndis_newstate; - - /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status, - mac); - ic->ic_opmode = opmode; - /* install key handing routines */ - vap->iv_key_set = ndis_add_key; - vap->iv_key_delete = ndis_del_key; - return vap; -} - -static void -ndis_vap_delete(struct ieee80211vap *vap) -{ - struct ndis_vap *nvp = NDIS_VAP(vap); - struct ieee80211com *ic = vap->iv_ic; - struct ndis_softc *sc = ic->ic_softc; - - ndis_stop(sc); - callout_drain(&sc->ndis_scan_callout); - ieee80211_vap_detach(vap); - free(nvp, M_80211_VAP); -} - -/* - * Shutdown hardware and free up resources. This can be called any - * time after the mutex has been initialized. It is called in both - * the error case in attach and the normal detach case so it needs - * to be careful about only freeing resources that have actually been - * allocated. - */ -int -ndis_detach(device_t dev) -{ - struct ifnet *ifp; - struct ndis_softc *sc; - driver_object *drv; - - sc = device_get_softc(dev); - NDIS_LOCK(sc); - if (!sc->ndis_80211) - ifp = sc->ifp; - else - ifp = NULL; - if (ifp != NULL) - ifp->if_flags &= ~IFF_UP; - if (device_is_attached(dev)) { - NDIS_UNLOCK(sc); - ndis_stop(sc); - if (sc->ndis_80211) - ieee80211_ifdetach(&sc->ndis_ic); - else if (ifp != NULL) - ether_ifdetach(ifp); - } else - NDIS_UNLOCK(sc); - - if (sc->ndis_tickitem != NULL) - IoFreeWorkItem(sc->ndis_tickitem); - if (sc->ndis_startitem != NULL) - IoFreeWorkItem(sc->ndis_startitem); - if (sc->ndis_resetitem != NULL) - IoFreeWorkItem(sc->ndis_resetitem); - if (sc->ndis_inputitem != NULL) - IoFreeWorkItem(sc->ndis_inputitem); - if (sc->ndisusb_xferdoneitem != NULL) - IoFreeWorkItem(sc->ndisusb_xferdoneitem); - if (sc->ndisusb_taskitem != NULL) - IoFreeWorkItem(sc->ndisusb_taskitem); - - bus_generic_detach(dev); - ndis_unload_driver(sc); - - if (sc->ndis_irq) - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq); - if (sc->ndis_res_io) - bus_release_resource(dev, SYS_RES_IOPORT, - sc->ndis_io_rid, sc->ndis_res_io); - if (sc->ndis_res_mem) - bus_release_resource(dev, SYS_RES_MEMORY, - sc->ndis_mem_rid, sc->ndis_res_mem); - if (sc->ndis_res_altmem) - bus_release_resource(dev, SYS_RES_MEMORY, - sc->ndis_altmem_rid, sc->ndis_res_altmem); - - if (ifp != NULL) - if_free(ifp); - - if (sc->ndis_sc) - ndis_destroy_dma(sc); - - if (sc->ndis_txarray) - free(sc->ndis_txarray, M_DEVBUF); - - if (!sc->ndis_80211) - ifmedia_removeall(&sc->ifmedia); - - if (sc->ndis_txpool != NULL) - NdisFreePacketPool(sc->ndis_txpool); - - /* Destroy the PDO for this device. */ - - if (sc->ndis_iftype == PCIBus) - drv = windrv_lookup(0, "PCI Bus"); - else if (sc->ndis_iftype == PCMCIABus) - drv = windrv_lookup(0, "PCCARD Bus"); - else - drv = windrv_lookup(0, "USB Bus"); - if (drv == NULL) - panic("couldn't find driver object"); - windrv_destroy_pdo(drv, dev); - - if (sc->ndis_iftype == PCIBus) - bus_dma_tag_destroy(sc->ndis_parent_tag); - - return (0); -} - -int -ndis_suspend(dev) - device_t dev; -{ - struct ndis_softc *sc; - struct ifnet *ifp; - - sc = device_get_softc(dev); - ifp = sc->ifp; - -#ifdef notdef - if (NDIS_INITIALIZED(sc)) - ndis_stop(sc); -#endif - - return (0); -} - -int -ndis_resume(dev) - device_t dev; -{ - struct ndis_softc *sc; - struct ifnet *ifp; - - sc = device_get_softc(dev); - ifp = sc->ifp; - - if (NDIS_INITIALIZED(sc)) - ndis_init(sc); - - return (0); -} - -/* - * The following bunch of routines are here to support drivers that - * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism. - * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for - * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized - * miniports. - */ -static void -ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen) - ndis_handle adapter; - ndis_handle ctx; - char *addr; - void *hdr; - uint32_t hdrlen; - void *lookahead; - uint32_t lookaheadlen; - uint32_t pktlen; -{ - ndis_miniport_block *block; - uint8_t irql = 0; - uint32_t status; - ndis_buffer *b; - ndis_packet *p; - struct mbuf *m; - ndis_ethpriv *priv; - - block = adapter; - - m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); - if (m == NULL) - return; - - /* Save the data provided to us so far. */ - - m->m_len = lookaheadlen + hdrlen; - m->m_pkthdr.len = pktlen + hdrlen; - m->m_next = NULL; - m_copyback(m, 0, hdrlen, hdr); - m_copyback(m, hdrlen, lookaheadlen, lookahead); - - /* Now create a fake NDIS_PACKET to hold the data */ - - NdisAllocatePacket(&status, &p, block->nmb_rxpool); - - if (status != NDIS_STATUS_SUCCESS) { - m_freem(m); - return; - } - - p->np_m0 = m; - - b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL); - - if (b == NULL) { - NdisFreePacket(p); - m_freem(m); - return; - } - - p->np_private.npp_head = p->np_private.npp_tail = b; - p->np_private.npp_totlen = m->m_pkthdr.len; - - /* Save the packet RX context somewhere. */ - priv = (ndis_ethpriv *)&p->np_protocolreserved; - priv->nep_ctx = ctx; - - if (!NDIS_SERIALIZED(block)) - KeAcquireSpinLock(&block->nmb_lock, &irql); - - InsertTailList((&block->nmb_packetlist), (&p->np_list)); - - if (!NDIS_SERIALIZED(block)) - KeReleaseSpinLock(&block->nmb_lock, irql); -} - -/* - * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL - * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized - * miniports. - */ -static void -ndis_rxeof_done(adapter) - ndis_handle adapter; -{ - struct ndis_softc *sc; - ndis_miniport_block *block; - - block = adapter; - - /* Schedule transfer/RX of queued packets. */ - - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - - KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL); -} - -/* - * MiniportTransferData() handler, runs at DISPATCH_LEVEL. - */ -static void -ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2) - kdpc *dpc; - ndis_handle adapter; - void *sysarg1; - void *sysarg2; -{ - ndis_miniport_block *block; - struct ndis_softc *sc; - ndis_packet *p; - list_entry *l; - uint32_t status; - ndis_ethpriv *priv; - struct ifnet *ifp; - struct mbuf *m; - - block = adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - ifp = sc->ifp; - - KeAcquireSpinLockAtDpcLevel(&block->nmb_lock); - - l = block->nmb_packetlist.nle_flink; - while(!IsListEmpty(&block->nmb_packetlist)) { - l = RemoveHeadList((&block->nmb_packetlist)); - p = CONTAINING_RECORD(l, ndis_packet, np_list); - InitializeListHead((&p->np_list)); - - priv = (ndis_ethpriv *)&p->np_protocolreserved; - m = p->np_m0; - p->np_softc = sc; - p->np_m0 = NULL; - - KeReleaseSpinLockFromDpcLevel(&block->nmb_lock); - - status = MSCALL6(sc->ndis_chars->nmc_transferdata_func, - p, &p->np_private.npp_totlen, block, priv->nep_ctx, - m->m_len, m->m_pkthdr.len - m->m_len); - - KeAcquireSpinLockAtDpcLevel(&block->nmb_lock); - - /* - * If status is NDIS_STATUS_PENDING, do nothing and - * wait for a callback to the ndis_rxeof_xfr_done() - * handler. - */ - - m->m_len = m->m_pkthdr.len; - m->m_pkthdr.rcvif = ifp; - - if (status == NDIS_STATUS_SUCCESS) { - IoFreeMdl(p->np_private.npp_head); - NdisFreePacket(p); - KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock); - mbufq_enqueue(&sc->ndis_rxqueue, m); - KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock); - IoQueueWorkItem(sc->ndis_inputitem, - (io_workitem_func)ndis_inputtask_wrap, - WORKQUEUE_CRITICAL, sc); - } - - if (status == NDIS_STATUS_FAILURE) - m_freem(m); - - /* Advance to next packet */ - l = block->nmb_packetlist.nle_flink; - } - - KeReleaseSpinLockFromDpcLevel(&block->nmb_lock); -} - -/* - * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL. - */ -static void -ndis_rxeof_xfr_done(adapter, packet, status, len) - ndis_handle adapter; - ndis_packet *packet; - uint32_t status; - uint32_t len; -{ - ndis_miniport_block *block; - struct ndis_softc *sc; - struct ifnet *ifp; - struct mbuf *m; - - block = adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - ifp = sc->ifp; - - m = packet->np_m0; - IoFreeMdl(packet->np_private.npp_head); - NdisFreePacket(packet); - - if (status != NDIS_STATUS_SUCCESS) { - m_freem(m); - return; - } - - m->m_len = m->m_pkthdr.len; - m->m_pkthdr.rcvif = ifp; - KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock); - mbufq_enqueue(&sc->ndis_rxqueue, m); - KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock); - IoQueueWorkItem(sc->ndis_inputitem, - (io_workitem_func)ndis_inputtask_wrap, - WORKQUEUE_CRITICAL, sc); -} -/* - * A frame has been uploaded: pass the resulting mbuf chain up to - * the higher level protocols. - * - * When handling received NDIS packets, the 'status' field in the - * out-of-band portion of the ndis_packet has special meaning. In the - * most common case, the underlying NDIS driver will set this field - * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to - * take possession of it. We then change the status field to - * NDIS_STATUS_PENDING to tell the driver that we now own the packet, - * and that we will return it at some point in the future via the - * return packet handler. - * - * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES, - * this means the driver is running out of packet/buffer resources and - * wants to maintain ownership of the packet. In this case, we have to - * copy the packet data into local storage and let the driver keep the - * packet. - */ -static void -ndis_rxeof(adapter, packets, pktcnt) - ndis_handle adapter; - ndis_packet **packets; - uint32_t pktcnt; -{ - struct ndis_softc *sc; - ndis_miniport_block *block; - ndis_packet *p; - uint32_t s; - ndis_tcpip_csum *csum; - struct ifnet *ifp; - struct mbuf *m0, *m; - int i; - - block = (ndis_miniport_block *)adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - ifp = sc->ifp; - - /* - * There's a slim chance the driver may indicate some packets - * before we're completely ready to handle them. If we detect this, - * we need to return them to the miniport and ignore them. - */ - if (!sc->ndis_running) { - for (i = 0; i < pktcnt; i++) { - p = packets[i]; - if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) { - p->np_refcnt++; - ndis_return_packet(p); - } - } - return; - } - - for (i = 0; i < pktcnt; i++) { - p = packets[i]; - /* Stash the softc here so ptom can use it. */ - p->np_softc = sc; - if (ndis_ptom(&m0, p)) { - device_printf(sc->ndis_dev, "ptom failed\n"); - if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) - ndis_return_packet(p); - } else { -#ifdef notdef - if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) { - m = m_dup(m0, M_NOWAIT); - /* - * NOTE: we want to destroy the mbuf here, but - * we don't actually want to return it to the - * driver via the return packet handler. By - * bumping np_refcnt, we can prevent the - * ndis_return_packet() routine from actually - * doing anything. - */ - p->np_refcnt++; - m_freem(m0); - if (m == NULL) - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - else - m0 = m; - } else - p->np_oob.npo_status = NDIS_STATUS_PENDING; -#endif - m = m_dup(m0, M_NOWAIT); - if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) - p->np_refcnt++; - else - p->np_oob.npo_status = NDIS_STATUS_PENDING; - m_freem(m0); - if (m == NULL) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - continue; - } - m0 = m; - m0->m_pkthdr.rcvif = ifp; - - /* Deal with checksum offload. */ - - if (ifp->if_capenable & IFCAP_RXCSUM && - p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) { - s = (uintptr_t) - p->np_ext.npe_info[ndis_tcpipcsum_info]; - csum = (ndis_tcpip_csum *)&s; - if (csum->u.ntc_rxflags & - NDIS_RXCSUM_IP_PASSED) - m0->m_pkthdr.csum_flags |= - CSUM_IP_CHECKED|CSUM_IP_VALID; - if (csum->u.ntc_rxflags & - (NDIS_RXCSUM_TCP_PASSED | - NDIS_RXCSUM_UDP_PASSED)) { - m0->m_pkthdr.csum_flags |= - CSUM_DATA_VALID|CSUM_PSEUDO_HDR; - m0->m_pkthdr.csum_data = 0xFFFF; - } - } - - KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock); - mbufq_enqueue(&sc->ndis_rxqueue, m0); - KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock); - IoQueueWorkItem(sc->ndis_inputitem, - (io_workitem_func)ndis_inputtask_wrap, - WORKQUEUE_CRITICAL, sc); - } - } -} - -/* - * This routine is run at PASSIVE_LEVEL. We use this routine to pass - * packets into the stack in order to avoid calling (*ifp->if_input)() - * with any locks held (at DISPATCH_LEVEL, we'll be holding the - * 'dispatch level' per-cpu sleep lock). - */ -static void -ndis_inputtask(device_object *dobj, void *arg) -{ - ndis_miniport_block *block; - struct ndis_softc *sc = arg; - struct mbuf *m; - uint8_t irql; - - block = dobj->do_devext; - - KeAcquireSpinLock(&sc->ndis_rxlock, &irql); - while ((m = mbufq_dequeue(&sc->ndis_rxqueue)) != NULL) { - KeReleaseSpinLock(&sc->ndis_rxlock, irql); - if ((sc->ndis_80211 != 0)) { - struct ieee80211com *ic = &sc->ndis_ic; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - - if (vap != NULL) - vap->iv_deliver_data(vap, vap->iv_bss, m); - } else { - struct ifnet *ifp = sc->ifp; - - (*ifp->if_input)(ifp, m); - } - KeAcquireSpinLock(&sc->ndis_rxlock, &irql); - } - KeReleaseSpinLock(&sc->ndis_rxlock, irql); -} - -/* - * A frame was downloaded to the chip. It's safe for us to clean up - * the list buffers. - */ -static void -ndis_txeof(adapter, packet, status) - ndis_handle adapter; - ndis_packet *packet; - ndis_status status; - -{ - struct ndis_softc *sc; - ndis_miniport_block *block; - struct ifnet *ifp; - int idx; - struct mbuf *m; - - block = (ndis_miniport_block *)adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - ifp = sc->ifp; - - m = packet->np_m0; - idx = packet->np_txidx; - if (sc->ndis_sc) - bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]); - - ndis_free_packet(packet); - m_freem(m); - - NDIS_LOCK(sc); - sc->ndis_txarray[idx] = NULL; - sc->ndis_txpending++; - - if (!sc->ndis_80211) { - struct ifnet *ifp = sc->ifp; - if (status == NDIS_STATUS_SUCCESS) - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); - else - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - } - sc->ndis_tx_timer = 0; - - NDIS_UNLOCK(sc); - - if (!sc->ndis_80211) - IoQueueWorkItem(sc->ndis_startitem, - (io_workitem_func)ndis_ifstarttask_wrap, - WORKQUEUE_CRITICAL, sc); - DPRINTF(("%s: ndis_ifstarttask_wrap sc=%p\n", __func__, sc)); -} - -static void -ndis_linksts(adapter, status, sbuf, slen) - ndis_handle adapter; - ndis_status status; - void *sbuf; - uint32_t slen; -{ - ndis_miniport_block *block; - struct ndis_softc *sc; - - block = adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - sc->ndis_sts = status; - - /* Event list is all full up, drop this one. */ - - NDIS_LOCK(sc); - if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) { - NDIS_UNLOCK(sc); - return; - } - - /* Cache the event. */ - - if (slen) { - sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen, - M_TEMP, M_NOWAIT); - if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) { - NDIS_UNLOCK(sc); - return; - } - bcopy((char *)sbuf, - sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen); - } - sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status; - sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen; - NDIS_EVTINC(sc->ndis_evtpidx); - NDIS_UNLOCK(sc); -} - -static void -ndis_linksts_done(adapter) - ndis_handle adapter; -{ - ndis_miniport_block *block; - struct ndis_softc *sc; - struct ifnet *ifp; - - block = adapter; - sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - ifp = sc->ifp; - - if (!NDIS_INITIALIZED(sc)) - return; - - switch (sc->ndis_sts) { - case NDIS_STATUS_MEDIA_CONNECT: - IoQueueWorkItem(sc->ndis_tickitem, - (io_workitem_func)ndis_ticktask_wrap, - WORKQUEUE_CRITICAL, sc); - if (!sc->ndis_80211) - IoQueueWorkItem(sc->ndis_startitem, - (io_workitem_func)ndis_ifstarttask_wrap, - WORKQUEUE_CRITICAL, sc); - break; - case NDIS_STATUS_MEDIA_DISCONNECT: - if (sc->ndis_link) - IoQueueWorkItem(sc->ndis_tickitem, - (io_workitem_func)ndis_ticktask_wrap, - WORKQUEUE_CRITICAL, sc); - break; - default: - break; - } -} - -static void -ndis_tick(xsc) - void *xsc; -{ - struct ndis_softc *sc; - - sc = xsc; - - if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) { - IoQueueWorkItem(sc->ndis_tickitem, - (io_workitem_func)ndis_ticktask_wrap, - WORKQUEUE_CRITICAL, sc); - sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs; - } - - if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) { - if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1); - device_printf(sc->ndis_dev, "watchdog timeout\n"); - - IoQueueWorkItem(sc->ndis_resetitem, - (io_workitem_func)ndis_resettask_wrap, - WORKQUEUE_CRITICAL, sc); - if (!sc->ndis_80211) - IoQueueWorkItem(sc->ndis_startitem, - (io_workitem_func)ndis_ifstarttask_wrap, - WORKQUEUE_CRITICAL, sc); - } - - callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc); -} - -static void -ndis_ticktask(device_object *d, void *xsc) -{ - struct ndis_softc *sc = xsc; - ndis_checkforhang_handler hangfunc; - uint8_t rval; - - NDIS_LOCK(sc); - if (!NDIS_INITIALIZED(sc)) { - NDIS_UNLOCK(sc); - return; - } - NDIS_UNLOCK(sc); - - hangfunc = sc->ndis_chars->nmc_checkhang_func; - - if (hangfunc != NULL) { - rval = MSCALL1(hangfunc, - sc->ndis_block->nmb_miniportadapterctx); - if (rval == TRUE) { - ndis_reset_nic(sc); - return; - } - } - - NDIS_LOCK(sc); - if (sc->ndis_link == 0 && - sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) { - sc->ndis_link = 1; - if (sc->ndis_80211 != 0) { - struct ieee80211com *ic = &sc->ndis_ic; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - - if (vap != NULL) { - NDIS_UNLOCK(sc); - ndis_getstate_80211(sc); - ieee80211_new_state(vap, IEEE80211_S_RUN, -1); - NDIS_LOCK(sc); - if_link_state_change(vap->iv_ifp, - LINK_STATE_UP); - } - } else - if_link_state_change(sc->ifp, LINK_STATE_UP); - } - - if (sc->ndis_link == 1 && - sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) { - sc->ndis_link = 0; - if (sc->ndis_80211 != 0) { - struct ieee80211com *ic = &sc->ndis_ic; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - - if (vap != NULL) { - NDIS_UNLOCK(sc); - ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); - NDIS_LOCK(sc); - if_link_state_change(vap->iv_ifp, - LINK_STATE_DOWN); - } - } else - if_link_state_change(sc->ifp, LINK_STATE_DOWN); - } - - NDIS_UNLOCK(sc); -} - -static void -ndis_map_sclist(arg, segs, nseg, mapsize, error) - void *arg; - bus_dma_segment_t *segs; - int nseg; - bus_size_t mapsize; - int error; - -{ - struct ndis_sc_list *sclist; - int i; - - if (error || arg == NULL) - return; - - sclist = arg; - - sclist->nsl_frags = nseg; - - for (i = 0; i < nseg; i++) { - sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr; - sclist->nsl_elements[i].nse_len = segs[i].ds_len; - } -} - -static int -ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, - const struct ieee80211_bpf_params *params) -{ - /* no support; just discard */ - m_freem(m); - ieee80211_free_node(ni); - return (0); -} - -static void -ndis_update_mcast(struct ieee80211com *ic) -{ - struct ndis_softc *sc = ic->ic_softc; - - ndis_setmulti(sc); -} - -static void -ndis_update_promisc(struct ieee80211com *ic) -{ - /* not supported */ -} - -static void -ndis_ifstarttask(device_object *d, void *arg) -{ - struct ndis_softc *sc = arg; - DPRINTF(("%s: sc=%p, ifp=%p\n", __func__, sc, sc->ifp)); - if (sc->ndis_80211) - return; - - struct ifnet *ifp = sc->ifp; - if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - ndis_ifstart(ifp); -} - -/* - * Main transmit routine. To make NDIS drivers happy, we need to - * transform mbuf chains into NDIS packets and feed them to the - * send packet routines. Most drivers allow you to send several - * packets at once (up to the maxpkts limit). Unfortunately, rather - * that accepting them in the form of a linked list, they expect - * a contiguous array of pointers to packets. - * - * For those drivers which use the NDIS scatter/gather DMA mechanism, - * we need to perform busdma work here. Those that use map registers - * will do the mapping themselves on a buffer by buffer basis. - */ -static void -ndis_ifstart(struct ifnet *ifp) -{ - struct ndis_softc *sc; - struct mbuf *m = NULL; - ndis_packet **p0 = NULL, *p = NULL; - ndis_tcpip_csum *csum; - int pcnt = 0, status; - - sc = ifp->if_softc; - - NDIS_LOCK(sc); - if (!sc->ndis_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) { - NDIS_UNLOCK(sc); - return; - } - - p0 = &sc->ndis_txarray[sc->ndis_txidx]; - - while(sc->ndis_txpending) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - - NdisAllocatePacket(&status, - &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool); - - if (status != NDIS_STATUS_SUCCESS) - break; - - if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) { - IFQ_DRV_PREPEND(&ifp->if_snd, m); - NDIS_UNLOCK(sc); - return; - } - - /* - * Save pointer to original mbuf - * so we can free it later. - */ - - p = sc->ndis_txarray[sc->ndis_txidx]; - p->np_txidx = sc->ndis_txidx; - p->np_m0 = m; - p->np_oob.npo_status = NDIS_STATUS_PENDING; - - /* - * Do scatter/gather processing, if driver requested it. - */ - if (sc->ndis_sc) { - bus_dmamap_load_mbuf(sc->ndis_ttag, - sc->ndis_tmaps[sc->ndis_txidx], m, - ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT); - bus_dmamap_sync(sc->ndis_ttag, - sc->ndis_tmaps[sc->ndis_txidx], - BUS_DMASYNC_PREREAD); - p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist; - } - - /* Handle checksum offload. */ - - if (ifp->if_capenable & IFCAP_TXCSUM && - m->m_pkthdr.csum_flags) { - csum = (ndis_tcpip_csum *) - &p->np_ext.npe_info[ndis_tcpipcsum_info]; - csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4; - if (m->m_pkthdr.csum_flags & CSUM_IP) - csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP; - if (m->m_pkthdr.csum_flags & CSUM_TCP) - csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP; - if (m->m_pkthdr.csum_flags & CSUM_UDP) - csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP; - p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP; - } - - NDIS_INC(sc); - sc->ndis_txpending--; - - pcnt++; - - /* - * If there's a BPF listener, bounce a copy of this frame - * to him. - */ - if (!sc->ndis_80211) /* XXX handle 80211 */ - BPF_MTAP(ifp, m); - - /* - * The array that p0 points to must appear contiguous, - * so we must not wrap past the end of sc->ndis_txarray[]. - * If it looks like we're about to wrap, break out here - * so the this batch of packets can be transmitted, then - * wait for txeof to ask us to send the rest. - */ - if (sc->ndis_txidx == 0) - break; - } - - if (pcnt == 0) { - NDIS_UNLOCK(sc); - return; - } - - if (sc->ndis_txpending == 0) - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - - /* - * Set a timeout in case the chip goes out to lunch. - */ - sc->ndis_tx_timer = 5; - - NDIS_UNLOCK(sc); - - /* - * According to NDIS documentation, if a driver exports - * a MiniportSendPackets() routine, we prefer that over - * a MiniportSend() routine (which sends just a single - * packet). - */ - if (sc->ndis_chars->nmc_sendmulti_func != NULL) - ndis_send_packets(sc, p0, pcnt); - else - ndis_send_packet(sc, p); - - return; -} - -static int -ndis_80211transmit(struct ieee80211com *ic, struct mbuf *m) -{ - struct ndis_softc *sc = ic->ic_softc; - ndis_packet **p0 = NULL, *p = NULL; - int status; - - NDIS_LOCK(sc); - if (!sc->ndis_link || !sc->ndis_running) { - NDIS_UNLOCK(sc); - return (ENXIO); - } - - if (sc->ndis_txpending == 0) { - NDIS_UNLOCK(sc); - return (ENOBUFS); - } - - p0 = &sc->ndis_txarray[sc->ndis_txidx]; - - NdisAllocatePacket(&status, - &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool); - - if (status != NDIS_STATUS_SUCCESS) { - NDIS_UNLOCK(sc); - return (ENOBUFS); - } - - if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) { - NDIS_UNLOCK(sc); - return (ENOBUFS); - } - - /* - * Save pointer to original mbuf - * so we can free it later. - */ - - p = sc->ndis_txarray[sc->ndis_txidx]; - p->np_txidx = sc->ndis_txidx; - p->np_m0 = m; - p->np_oob.npo_status = NDIS_STATUS_PENDING; - - /* - * Do scatter/gather processing, if driver requested it. - */ - if (sc->ndis_sc) { - bus_dmamap_load_mbuf(sc->ndis_ttag, - sc->ndis_tmaps[sc->ndis_txidx], m, - ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT); - bus_dmamap_sync(sc->ndis_ttag, - sc->ndis_tmaps[sc->ndis_txidx], - BUS_DMASYNC_PREREAD); - p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist; - } - - NDIS_INC(sc); - sc->ndis_txpending--; - - /* - * Set a timeout in case the chip goes out to lunch. - */ - sc->ndis_tx_timer = 5; - NDIS_UNLOCK(sc); - - /* - * According to NDIS documentation, if a driver exports - * a MiniportSendPackets() routine, we prefer that over - * a MiniportSend() routine (which sends just a single - * packet). - */ - if (sc->ndis_chars->nmc_sendmulti_func != NULL) - ndis_send_packets(sc, p0, 1); - else - ndis_send_packet(sc, p); - - return (0); -} - -static void -ndis_80211parent(struct ieee80211com *ic) -{ - struct ndis_softc *sc = ic->ic_softc; - - /*NDIS_LOCK(sc);*/ - if (ic->ic_nrunning > 0) { - if (!sc->ndis_running) - ndis_init(sc); - } else if (sc->ndis_running) - ndis_stop(sc); - /*NDIS_UNLOCK(sc);*/ -} - -static void -ndis_init(void *xsc) -{ - struct ndis_softc *sc = xsc; - int i, len, error; - - /* - * Avoid reintializing the link unnecessarily. - * This should be dealt with in a better way by - * fixing the upper layer modules so they don't - * call ifp->if_init() quite as often. - */ - if (sc->ndis_link) - return; - - /* - * Cancel pending I/O and free all RX/TX buffers. - */ - ndis_stop(sc); - - if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) { - error = ndis_init_nic(sc); - if (error != 0) { - device_printf(sc->ndis_dev, - "failed to initialize the device: %d\n", error); - return; - } - } - - /* Program the packet filter */ - sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED | - NDIS_PACKET_TYPE_BROADCAST; - - if (sc->ndis_80211) { - struct ieee80211com *ic = &sc->ndis_ic; - - if (ic->ic_promisc > 0) - sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; - } else { - struct ifnet *ifp = sc->ifp; - - if (ifp->if_flags & IFF_PROMISC) - sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; - } - - len = sizeof(sc->ndis_filter); - - error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER, - &sc->ndis_filter, &len); - - if (error) - device_printf(sc->ndis_dev, "set filter failed: %d\n", error); - - /* - * Set lookahead. - */ - if (sc->ndis_80211) - i = ETHERMTU; - else - i = sc->ifp->if_mtu; - len = sizeof(i); - ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len); - - /* - * Program the multicast filter, if necessary. - */ - ndis_setmulti(sc); - - /* Setup task offload. */ - ndis_set_offload(sc); - - NDIS_LOCK(sc); - - sc->ndis_txidx = 0; - sc->ndis_txpending = sc->ndis_maxpkts; - sc->ndis_link = 0; - - if (!sc->ndis_80211) { - if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN); - sc->ifp->if_drv_flags |= IFF_DRV_RUNNING; - sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - } - - sc->ndis_tx_timer = 0; - - /* - * Some drivers don't set this value. The NDIS spec says - * the default checkforhang timeout is "approximately 2 - * seconds." We use 3 seconds, because it seems for some - * drivers, exactly 2 seconds is too fast. - */ - if (sc->ndis_block->nmb_checkforhangsecs == 0) - sc->ndis_block->nmb_checkforhangsecs = 3; - - sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs; - callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc); - sc->ndis_running = 1; - NDIS_UNLOCK(sc); - - /* XXX force handling */ - if (sc->ndis_80211) - ieee80211_start_all(&sc->ndis_ic); /* start all vap's */ -} - -/* - * Set media options. - */ -static int -ndis_ifmedia_upd(ifp) - struct ifnet *ifp; -{ - struct ndis_softc *sc; - - sc = ifp->if_softc; - - if (NDIS_INITIALIZED(sc)) - ndis_init(sc); - - return (0); -} - -/* - * Report current media status. - */ -static void -ndis_ifmedia_sts(ifp, ifmr) - struct ifnet *ifp; - struct ifmediareq *ifmr; -{ - struct ndis_softc *sc; - uint32_t media_info; - ndis_media_state linkstate; - int len; - - ifmr->ifm_status = IFM_AVALID; - ifmr->ifm_active = IFM_ETHER; - sc = ifp->if_softc; - - if (!NDIS_INITIALIZED(sc)) - return; - - len = sizeof(linkstate); - ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS, - (void *)&linkstate, &len); - - len = sizeof(media_info); - ndis_get_info(sc, OID_GEN_LINK_SPEED, - (void *)&media_info, &len); - - if (linkstate == nmc_connected) - ifmr->ifm_status |= IFM_ACTIVE; - - switch (media_info) { - case 100000: - ifmr->ifm_active |= IFM_10_T; - break; - case 1000000: - ifmr->ifm_active |= IFM_100_TX; - break; - case 10000000: - ifmr->ifm_active |= IFM_1000_T; - break; - default: - device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info); - break; - } -} - -static int -ndis_set_cipher(struct ndis_softc *sc, int cipher) -{ - struct ieee80211com *ic = &sc->ndis_ic; - int rval = 0, len; - uint32_t arg, save; - - len = sizeof(arg); - - if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) { - if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP)) - return (ENOTSUP); - arg = NDIS_80211_WEPSTAT_ENC1ENABLED; - } - - if (cipher == WPA_CSE_TKIP) { - if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP)) - return (ENOTSUP); - arg = NDIS_80211_WEPSTAT_ENC2ENABLED; - } - - if (cipher == WPA_CSE_CCMP) { - if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM)) - return (ENOTSUP); - arg = NDIS_80211_WEPSTAT_ENC3ENABLED; - } - - DPRINTF(("Setting cipher to %d\n", arg)); - save = arg; - rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len); - - if (rval) - return (rval); - - /* Check that the cipher was set correctly. */ - - len = sizeof(save); - rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len); - - if (rval != 0 || arg != save) - return (ENODEV); - - return (0); -} - -/* - * WPA is hairy to set up. Do the work in a separate routine - * so we don't clutter the setstate function too much. - * Important yet undocumented fact: first we have to set the - * authentication mode, _then_ we enable the ciphers. If one - * of the WPA authentication modes isn't enabled, the driver - * might not permit the TKIP or AES ciphers to be selected. - */ -static int -ndis_set_wpa(sc, ie, ielen) - struct ndis_softc *sc; - void *ie; - int ielen; -{ - struct ieee80211_ie_wpa *w; - struct ndis_ie *n; - char *pos; - uint32_t arg; - int i; - - /* - * Apparently, the only way for us to know what ciphers - * and key management/authentication mode to use is for - * us to inspect the optional information element (IE) - * stored in the 802.11 state machine. This IE should be - * supplied by the WPA supplicant. - */ - - w = (struct ieee80211_ie_wpa *)ie; - - /* Check for the right kind of IE. */ - if (w->wpa_id != IEEE80211_ELEMID_VENDOR) { - DPRINTF(("Incorrect IE type %d\n", w->wpa_id)); - return (EINVAL); - } - - /* Skip over the ucast cipher OIDs. */ - pos = (char *)&w->wpa_uciphers[0]; - pos += w->wpa_uciphercnt * sizeof(struct ndis_ie); - - /* Skip over the authmode count. */ - pos += sizeof(u_int16_t); - - /* - * Check for the authentication modes. I'm - * pretty sure there's only supposed to be one. - */ - - n = (struct ndis_ie *)pos; - if (n->ni_val == WPA_ASE_NONE) - arg = NDIS_80211_AUTHMODE_WPANONE; - - if (n->ni_val == WPA_ASE_8021X_UNSPEC) - arg = NDIS_80211_AUTHMODE_WPA; - - if (n->ni_val == WPA_ASE_8021X_PSK) - arg = NDIS_80211_AUTHMODE_WPAPSK; - - DPRINTF(("Setting WPA auth mode to %d\n", arg)); - i = sizeof(arg); - if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i)) - return (ENOTSUP); - i = sizeof(arg); - ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i); - - /* Now configure the desired ciphers. */ - - /* First, set up the multicast group cipher. */ - n = (struct ndis_ie *)&w->wpa_mcipher[0]; - - if (ndis_set_cipher(sc, n->ni_val)) - return (ENOTSUP); - - /* Now start looking around for the unicast ciphers. */ - pos = (char *)&w->wpa_uciphers[0]; - n = (struct ndis_ie *)pos; - - for (i = 0; i < w->wpa_uciphercnt; i++) { - if (ndis_set_cipher(sc, n->ni_val)) - return (ENOTSUP); - n++; - } - - return (0); -} - -static void -ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr) -{ - struct ieee80211vap *vap = ifp->if_softc; - struct ndis_softc *sc = vap->iv_ic->ic_softc; - uint32_t txrate; - int len; - - if (!NDIS_INITIALIZED(sc)) - return; - - len = sizeof(txrate); - if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0) - vap->iv_bss->ni_txrate = txrate / 5000; - ieee80211_media_status(ifp, imr); -} - -static void -ndis_setstate_80211(struct ndis_softc *sc) -{ - struct ieee80211com *ic = &sc->ndis_ic; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - ndis_80211_macaddr bssid; - ndis_80211_config config; - int rval = 0, len; - uint32_t arg; - - if (!NDIS_INITIALIZED(sc)) { - DPRINTF(("%s: NDIS not initialized\n", __func__)); - return; - } - - /* Disassociate and turn off radio. */ - len = sizeof(arg); - arg = 1; - ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len); - - /* Set network infrastructure mode. */ - - len = sizeof(arg); - if (ic->ic_opmode == IEEE80211_M_IBSS) - arg = NDIS_80211_NET_INFRA_IBSS; - else - arg = NDIS_80211_NET_INFRA_BSS; - - rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len); - - if (rval) - device_printf (sc->ndis_dev, "set infra failed: %d\n", rval); - - /* Set power management */ - len = sizeof(arg); - if (vap->iv_flags & IEEE80211_F_PMGTON) - arg = NDIS_80211_POWERMODE_FAST_PSP; - else - arg = NDIS_80211_POWERMODE_CAM; - ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len); - - /* Set TX power */ - if ((ic->ic_caps & IEEE80211_C_TXPMGT) && - ic->ic_txpowlimit < nitems(dBm2mW)) { - arg = dBm2mW[ic->ic_txpowlimit]; - len = sizeof(arg); - ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len); - } - - /* - * Default encryption mode to off, authentication - * to open and privacy to 'accept everything.' - */ - len = sizeof(arg); - arg = NDIS_80211_WEPSTAT_DISABLED; - ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len); - - len = sizeof(arg); - arg = NDIS_80211_AUTHMODE_OPEN; - ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len); - - /* - * Note that OID_802_11_PRIVACY_FILTER is optional: - * not all drivers implement it. - */ - len = sizeof(arg); - arg = NDIS_80211_PRIVFILT_8021XWEP; - ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len); - - len = sizeof(config); - bzero((char *)&config, len); - config.nc_length = len; - config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh); - rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len); - - /* - * Some drivers expect us to initialize these values, so - * provide some defaults. - */ - - if (config.nc_beaconperiod == 0) - config.nc_beaconperiod = 100; - if (config.nc_atimwin == 0) - config.nc_atimwin = 100; - if (config.nc_fhconfig.ncf_dwelltime == 0) - config.nc_fhconfig.ncf_dwelltime = 200; - if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) { - int chan, chanflag; - - chan = ieee80211_chan2ieee(ic, ic->ic_bsschan); - chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ : - IEEE80211_CHAN_5GHZ; - if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) { - config.nc_dsconfig = - ic->ic_bsschan->ic_freq * 1000; - len = sizeof(config); - config.nc_length = len; - config.nc_fhconfig.ncf_length = - sizeof(ndis_80211_config_fh); - DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig)); - rval = ndis_set_info(sc, OID_802_11_CONFIGURATION, - &config, &len); - if (rval) - device_printf(sc->ndis_dev, "couldn't change " - "DS config to %ukHz: %d\n", - config.nc_dsconfig, rval); - } - } else if (rval) - device_printf(sc->ndis_dev, "couldn't retrieve " - "channel info: %d\n", rval); - - /* Set the BSSID to our value so the driver doesn't associate */ - len = IEEE80211_ADDR_LEN; - bcopy(vap->iv_myaddr, bssid, len); - DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":")); - rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len); - if (rval) - device_printf(sc->ndis_dev, - "setting BSSID failed: %d\n", rval); -} - -static void -ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap) -{ - struct ieee80211_node *ni = vap->iv_bss; - ndis_80211_ssid ssid; - ndis_80211_macaddr bssid; - ndis_80211_wep wep; - int i, rval = 0, len, error; - uint32_t arg; - - if (!NDIS_INITIALIZED(sc)) { - DPRINTF(("%s: NDIS not initialized\n", __func__)); - return; - } - - /* Initial setup */ - ndis_setstate_80211(sc); - - /* Set network infrastructure mode. */ - - len = sizeof(arg); - if (vap->iv_opmode == IEEE80211_M_IBSS) - arg = NDIS_80211_NET_INFRA_IBSS; - else - arg = NDIS_80211_NET_INFRA_BSS; - - rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len); - - if (rval) - device_printf (sc->ndis_dev, "set infra failed: %d\n", rval); - - /* Set RTS threshold */ - - len = sizeof(arg); - arg = vap->iv_rtsthreshold; - ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len); - - /* Set fragmentation threshold */ - - len = sizeof(arg); - arg = vap->iv_fragthreshold; - ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len); - - /* Set WEP */ - - if (vap->iv_flags & IEEE80211_F_PRIVACY && - !(vap->iv_flags & IEEE80211_F_WPA)) { - int keys_set = 0; - - if (ni->ni_authmode == IEEE80211_AUTH_SHARED) { - len = sizeof(arg); - arg = NDIS_80211_AUTHMODE_SHARED; - DPRINTF(("Setting shared auth\n")); - ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, - &arg, &len); - } - for (i = 0; i < IEEE80211_WEP_NKID; i++) { - if (vap->iv_nw_keys[i].wk_keylen) { - if (vap->iv_nw_keys[i].wk_cipher->ic_cipher != - IEEE80211_CIPHER_WEP) - continue; - bzero((char *)&wep, sizeof(wep)); - wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen; - - /* - * 5, 13 and 16 are the only valid - * key lengths. Anything in between - * will be zero padded out to the - * next highest boundary. - */ - if (vap->iv_nw_keys[i].wk_keylen < 5) - wep.nw_keylen = 5; - else if (vap->iv_nw_keys[i].wk_keylen > 5 && - vap->iv_nw_keys[i].wk_keylen < 13) - wep.nw_keylen = 13; - else if (vap->iv_nw_keys[i].wk_keylen > 13 && - vap->iv_nw_keys[i].wk_keylen < 16) - wep.nw_keylen = 16; - - wep.nw_keyidx = i; - wep.nw_length = (sizeof(uint32_t) * 3) - + wep.nw_keylen; - if (i == vap->iv_def_txkey) - wep.nw_keyidx |= NDIS_80211_WEPKEY_TX; - bcopy(vap->iv_nw_keys[i].wk_key, - wep.nw_keydata, wep.nw_length); - len = sizeof(wep); - DPRINTF(("Setting WEP key %d\n", i)); - rval = ndis_set_info(sc, - OID_802_11_ADD_WEP, &wep, &len); - if (rval) - device_printf(sc->ndis_dev, - "set wepkey failed: %d\n", rval); - keys_set++; - } - } - if (keys_set) { - DPRINTF(("Setting WEP on\n")); - arg = NDIS_80211_WEPSTAT_ENABLED; - len = sizeof(arg); - rval = ndis_set_info(sc, - OID_802_11_WEP_STATUS, &arg, &len); - if (rval) - device_printf(sc->ndis_dev, - "enable WEP failed: %d\n", rval); - if (vap->iv_flags & IEEE80211_F_DROPUNENC) - arg = NDIS_80211_PRIVFILT_8021XWEP; - else - arg = NDIS_80211_PRIVFILT_ACCEPTALL; - - len = sizeof(arg); - ndis_set_info(sc, - OID_802_11_PRIVACY_FILTER, &arg, &len); - } - } - - /* Set up WPA. */ - if ((vap->iv_flags & IEEE80211_F_WPA) && - vap->iv_appie_assocreq != NULL) { - struct ieee80211_appie *ie = vap->iv_appie_assocreq; - error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len); - if (error != 0) - device_printf(sc->ndis_dev, "WPA setup failed\n"); - } - -#ifdef notyet - /* Set network type. */ - - arg = 0; - - switch (vap->iv_curmode) { - case IEEE80211_MODE_11A: - arg = NDIS_80211_NETTYPE_11OFDM5; - break; - case IEEE80211_MODE_11B: - arg = NDIS_80211_NETTYPE_11DS; - break; - case IEEE80211_MODE_11G: - arg = NDIS_80211_NETTYPE_11OFDM24; - break; - default: - device_printf(sc->ndis_dev, "unknown mode: %d\n", - vap->iv_curmode); - } - - if (arg) { - DPRINTF(("Setting network type to %d\n", arg)); - len = sizeof(arg); - rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE, - &arg, &len); - if (rval) - device_printf(sc->ndis_dev, - "set nettype failed: %d\n", rval); - } -#endif - - /* - * If the user selected a specific BSSID, try - * to use that one. This is useful in the case where - * there are several APs in range with the same network - * name. To delete the BSSID, we use the broadcast - * address as the BSSID. - * Note that some drivers seem to allow setting a BSSID - * in ad-hoc mode, which has the effect of forcing the - * NIC to create an ad-hoc cell with a specific BSSID, - * instead of a randomly chosen one. However, the net80211 - * code makes the assumtion that the BSSID setting is invalid - * when you're in ad-hoc mode, so we don't allow that here. - */ - - len = IEEE80211_ADDR_LEN; - if (vap->iv_flags & IEEE80211_F_DESBSSID && - vap->iv_opmode != IEEE80211_M_IBSS) - bcopy(ni->ni_bssid, bssid, len); - else - bcopy(ieee80211broadcastaddr, bssid, len); - - DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":")); - rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len); - if (rval) - device_printf(sc->ndis_dev, - "setting BSSID failed: %d\n", rval); - - /* Set SSID -- always do this last. */ - -#ifdef NDIS_DEBUG - if (ndis_debug > 0) { - printf("Setting ESSID to "); - ieee80211_print_essid(ni->ni_essid, ni->ni_esslen); - printf("\n"); - } -#endif - - len = sizeof(ssid); - bzero((char *)&ssid, len); - ssid.ns_ssidlen = ni->ni_esslen; - if (ssid.ns_ssidlen == 0) { - ssid.ns_ssidlen = 1; - } else - bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen); - - rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len); - - if (rval) - device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval); - - return; -} - -static int -ndis_get_bssid_list(sc, bl) - struct ndis_softc *sc; - ndis_80211_bssid_list_ex **bl; -{ - int len, error; - - len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16); - *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO); - if (*bl == NULL) - return (ENOMEM); - - error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len); - if (error == ENOSPC) { - free(*bl, M_DEVBUF); - *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO); - if (*bl == NULL) - return (ENOMEM); - - error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len); - } - if (error) { - DPRINTF(("%s: failed to read\n", __func__)); - free(*bl, M_DEVBUF); - return (error); - } - - return (0); -} - -static int -ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc) -{ - struct ieee80211com *ic = &sc->ndis_ic; - struct ieee80211vap *vap; - struct ieee80211_node *ni; - ndis_80211_bssid_list_ex *bl; - ndis_wlan_bssid_ex *bs; - ndis_80211_macaddr bssid; - int i, len, error; - - if (!sc->ndis_link) - return (ENOENT); - - len = sizeof(bssid); - error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len); - if (error) { - device_printf(sc->ndis_dev, "failed to get bssid\n"); - return (ENOENT); - } - - vap = TAILQ_FIRST(&ic->ic_vaps); - ni = vap->iv_bss; - - error = ndis_get_bssid_list(sc, &bl); - if (error) - return (error); - - bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0]; - for (i = 0; i < bl->nblx_items; i++) { - if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) { - *assoc = malloc(bs->nwbx_len, M_TEMP, M_NOWAIT); - if (*assoc == NULL) { - free(bl, M_TEMP); - return (ENOMEM); - } - bcopy((char *)bs, (char *)*assoc, bs->nwbx_len); - free(bl, M_TEMP); - if (ic->ic_opmode == IEEE80211_M_STA) - ni->ni_associd = 1 | 0xc000; /* fake associd */ - return (0); - } - bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len); - } - - free(bl, M_TEMP); - return (ENOENT); -} - -static void -ndis_getstate_80211(struct ndis_softc *sc) -{ - struct ieee80211com *ic = &sc->ndis_ic; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct ieee80211_node *ni = vap->iv_bss; - ndis_wlan_bssid_ex *bs; - int rval, len, i = 0; - int chanflag; - uint32_t arg; - - if (!NDIS_INITIALIZED(sc)) - return; - - if ((rval = ndis_get_assoc(sc, &bs)) != 0) - return; - - /* We're associated, retrieve info on the current bssid. */ - ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype); - chanflag = ndis_nettype_chan(bs->nwbx_nettype); - IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr); - - /* Get SSID from current association info. */ - bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid, - bs->nwbx_ssid.ns_ssidlen); - ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen; - - if (ic->ic_caps & IEEE80211_C_PMGT) { - len = sizeof(arg); - rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len); - - if (rval) - device_printf(sc->ndis_dev, - "get power mode failed: %d\n", rval); - if (arg == NDIS_80211_POWERMODE_CAM) - vap->iv_flags &= ~IEEE80211_F_PMGTON; - else - vap->iv_flags |= IEEE80211_F_PMGTON; - } - - /* Get TX power */ - if (ic->ic_caps & IEEE80211_C_TXPMGT) { - len = sizeof(arg); - ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len); - for (i = 0; i < nitems(dBm2mW); i++) - if (dBm2mW[i] >= arg) - break; - ic->ic_txpowlimit = i; - } - - /* - * Use the current association information to reflect - * what channel we're on. - */ - ic->ic_curchan = ieee80211_find_channel(ic, - bs->nwbx_config.nc_dsconfig / 1000, chanflag); - if (ic->ic_curchan == NULL) - ic->ic_curchan = &ic->ic_channels[0]; - ni->ni_chan = ic->ic_curchan; - ic->ic_bsschan = ic->ic_curchan; - - free(bs, M_TEMP); - - /* - * Determine current authentication mode. - */ - len = sizeof(arg); - rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len); - if (rval) - device_printf(sc->ndis_dev, - "get authmode status failed: %d\n", rval); - else { - vap->iv_flags &= ~IEEE80211_F_WPA; - switch (arg) { - case NDIS_80211_AUTHMODE_OPEN: - ni->ni_authmode = IEEE80211_AUTH_OPEN; - break; - case NDIS_80211_AUTHMODE_SHARED: - ni->ni_authmode = IEEE80211_AUTH_SHARED; - break; - case NDIS_80211_AUTHMODE_AUTO: - ni->ni_authmode = IEEE80211_AUTH_AUTO; - break; - case NDIS_80211_AUTHMODE_WPA: - case NDIS_80211_AUTHMODE_WPAPSK: - case NDIS_80211_AUTHMODE_WPANONE: - ni->ni_authmode = IEEE80211_AUTH_WPA; - vap->iv_flags |= IEEE80211_F_WPA1; - break; - case NDIS_80211_AUTHMODE_WPA2: - case NDIS_80211_AUTHMODE_WPA2PSK: - ni->ni_authmode = IEEE80211_AUTH_WPA; - vap->iv_flags |= IEEE80211_F_WPA2; - break; - default: - ni->ni_authmode = IEEE80211_AUTH_NONE; - break; - } - } - - len = sizeof(arg); - rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len); - - if (rval) - device_printf(sc->ndis_dev, - "get wep status failed: %d\n", rval); - - if (arg == NDIS_80211_WEPSTAT_ENABLED) - vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC; - else - vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC); -} - -static int -ndis_ifioctl(ifp, command, data) - struct ifnet *ifp; - u_long command; - caddr_t data; -{ - struct ndis_softc *sc = ifp->if_softc; - struct ifreq *ifr = (struct ifreq *) data; - int i, error = 0; - - /*NDIS_LOCK(sc);*/ - - switch (command) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (sc->ndis_running && - ifp->if_flags & IFF_PROMISC && - !(sc->ndis_if_flags & IFF_PROMISC)) { - sc->ndis_filter |= - NDIS_PACKET_TYPE_PROMISCUOUS; - i = sizeof(sc->ndis_filter); - error = ndis_set_info(sc, - OID_GEN_CURRENT_PACKET_FILTER, - &sc->ndis_filter, &i); - } else if (sc->ndis_running && - !(ifp->if_flags & IFF_PROMISC) && - sc->ndis_if_flags & IFF_PROMISC) { - sc->ndis_filter &= - ~NDIS_PACKET_TYPE_PROMISCUOUS; - i = sizeof(sc->ndis_filter); - error = ndis_set_info(sc, - OID_GEN_CURRENT_PACKET_FILTER, - &sc->ndis_filter, &i); - } else - ndis_init(sc); - } else { - if (sc->ndis_running) - ndis_stop(sc); - } - sc->ndis_if_flags = ifp->if_flags; - error = 0; - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - ndis_setmulti(sc); - error = 0; - break; - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command); - break; - case SIOCSIFCAP: - ifp->if_capenable = ifr->ifr_reqcap; - if (ifp->if_capenable & IFCAP_TXCSUM) - ifp->if_hwassist = sc->ndis_hwassist; - else - ifp->if_hwassist = 0; - ndis_set_offload(sc); - break; - default: - error = ether_ioctl(ifp, command, data); - break; - } - - /*NDIS_UNLOCK(sc);*/ - - return(error); -} - -static int -ndis_80211ioctl(struct ieee80211com *ic, u_long cmd, void *data) -{ - struct ndis_softc *sc = ic->ic_softc; - struct ifreq *ifr = data; - struct ndis_oid_data oid; - struct ndis_evt evt; - void *oidbuf = NULL; - int error = 0; - - if ((error = priv_check(curthread, PRIV_DRIVER)) != 0) - return (error); - - switch (cmd) { - case SIOCGDRVSPEC: - case SIOCSDRVSPEC: - error = copyin(ifr_data_get_ptr(ifr), &oid, sizeof(oid)); - if (error) - break; - oidbuf = malloc(oid.len, M_TEMP, M_WAITOK | M_ZERO); - error = copyin((caddr_t)ifr_data_get_ptr(ifr) + sizeof(oid), - oidbuf, oid.len); - } - - if (error) { - free(oidbuf, M_TEMP); - return (error); - } - - switch (cmd) { - case SIOCGDRVSPEC: - error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len); - break; - case SIOCSDRVSPEC: - error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len); - break; - case SIOCGPRIVATE_0: - NDIS_LOCK(sc); - if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) { - error = ENOENT; - NDIS_UNLOCK(sc); - break; - } - error = copyin(ifr_data_get_ptr(ifr), &evt, sizeof(evt)); - if (error) { - NDIS_UNLOCK(sc); - break; - } - if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) { - error = ENOSPC; - NDIS_UNLOCK(sc); - break; - } - error = copyout(&sc->ndis_evt[sc->ndis_evtcidx], - ifr_data_get_ptr(ifr), sizeof(uint32_t) * 2); - if (error) { - NDIS_UNLOCK(sc); - break; - } - if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) { - error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, - (caddr_t)ifr_data_get_ptr(ifr) + - (sizeof(uint32_t) * 2), - sc->ndis_evt[sc->ndis_evtcidx].ne_len); - if (error) { - NDIS_UNLOCK(sc); - break; - } - free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP); - sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL; - } - sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0; - sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0; - NDIS_EVTINC(sc->ndis_evtcidx); - NDIS_UNLOCK(sc); - break; - default: - error = ENOTTY; - break; - } - - switch (cmd) { - case SIOCGDRVSPEC: - case SIOCSDRVSPEC: - error = copyout(&oid, ifr_data_get_ptr(ifr), sizeof(oid)); - if (error) - break; - error = copyout(oidbuf, - (caddr_t)ifr_data_get_ptr(ifr) + sizeof(oid), oid.len); - } - - free(oidbuf, M_TEMP); - - return (error); -} - -int -ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key) -{ - struct ndis_softc *sc = vap->iv_ic->ic_softc; - ndis_80211_key rkey; - int len, error = 0; - - bzero((char *)&rkey, sizeof(rkey)); - len = sizeof(rkey); - - rkey.nk_len = len; - rkey.nk_keyidx = key->wk_keyix; - - bcopy(vap->iv_ifp->if_broadcastaddr, - rkey.nk_bssid, IEEE80211_ADDR_LEN); - - error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len); - - if (error) - return (0); - - return (1); -} - -/* - * In theory this could be called for any key, but we'll - * only use it for WPA TKIP or AES keys. These need to be - * set after initial authentication with the AP. - */ -static int -ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key) -{ - struct ndis_softc *sc = vap->iv_ic->ic_softc; - ndis_80211_key rkey; - int len, error = 0; - - switch (key->wk_cipher->ic_cipher) { - case IEEE80211_CIPHER_TKIP: - - len = sizeof(ndis_80211_key); - bzero((char *)&rkey, sizeof(rkey)); - - rkey.nk_len = len; - rkey.nk_keylen = key->wk_keylen; - - if (key->wk_flags & IEEE80211_KEY_SWMIC) - rkey.nk_keylen += 16; - - /* key index - gets weird in NDIS */ - - if (key->wk_keyix != IEEE80211_KEYIX_NONE) - rkey.nk_keyidx = key->wk_keyix; - else - rkey.nk_keyidx = 0; - - if (key->wk_flags & IEEE80211_KEY_XMIT) - rkey.nk_keyidx |= 1 << 31; - - if (key->wk_flags & IEEE80211_KEY_GROUP) { - bcopy(ieee80211broadcastaddr, - rkey.nk_bssid, IEEE80211_ADDR_LEN); - } else { - bcopy(vap->iv_bss->ni_bssid, - rkey.nk_bssid, IEEE80211_ADDR_LEN); - /* pairwise key */ - rkey.nk_keyidx |= 1 << 30; - } - - /* need to set bit 29 based on keyrsc */ - rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */ - - if (rkey.nk_keyrsc) - rkey.nk_keyidx |= 1 << 29; - - if (key->wk_flags & IEEE80211_KEY_SWMIC) { - bcopy(key->wk_key, rkey.nk_keydata, 16); - bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8); - bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8); - } else - bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen); - - error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len); - break; - case IEEE80211_CIPHER_WEP: - error = 0; - break; - /* - * I don't know how to set up keys for the AES - * cipher yet. Is it the same as TKIP? - */ - case IEEE80211_CIPHER_AES_CCM: - default: - error = ENOTTY; - break; - } - - /* We need to return 1 for success, 0 for failure. */ - - if (error) - return (0); - - return (1); -} - -static void -ndis_resettask(d, arg) - device_object *d; - void *arg; -{ - struct ndis_softc *sc; - - sc = arg; - ndis_reset_nic(sc); -} - -/* - * Stop the adapter and free any mbufs allocated to the - * RX and TX lists. - */ -static void -ndis_stop(struct ndis_softc *sc) -{ - int i; - - callout_drain(&sc->ndis_stat_callout); - - NDIS_LOCK(sc); - sc->ndis_tx_timer = 0; - sc->ndis_link = 0; - if (!sc->ndis_80211) - sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - sc->ndis_running = 0; - NDIS_UNLOCK(sc); - - if (sc->ndis_iftype != PNPBus || - (sc->ndis_iftype == PNPBus && - !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) && - ndisusb_halt != 0)) - ndis_halt_nic(sc); - - NDIS_LOCK(sc); - for (i = 0; i < NDIS_EVENTS; i++) { - if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) { - free(sc->ndis_evt[i].ne_buf, M_TEMP); - sc->ndis_evt[i].ne_buf = NULL; - } - sc->ndis_evt[i].ne_sts = 0; - sc->ndis_evt[i].ne_len = 0; - } - sc->ndis_evtcidx = 0; - sc->ndis_evtpidx = 0; - NDIS_UNLOCK(sc); -} - -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ -void -ndis_shutdown(dev) - device_t dev; -{ - struct ndis_softc *sc; - - sc = device_get_softc(dev); - ndis_stop(sc); -} - -static int -ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) -{ - struct ndis_vap *nvp = NDIS_VAP(vap); - struct ieee80211com *ic = vap->iv_ic; - struct ndis_softc *sc = ic->ic_softc; - enum ieee80211_state ostate; - - DPRINTF(("%s: %s -> %s\n", __func__, - ieee80211_state_name[vap->iv_state], - ieee80211_state_name[nstate])); - - ostate = vap->iv_state; - vap->iv_state = nstate; - - switch (nstate) { - /* pass on to net80211 */ - case IEEE80211_S_INIT: - case IEEE80211_S_SCAN: - return nvp->newstate(vap, nstate, arg); - case IEEE80211_S_ASSOC: - if (ostate != IEEE80211_S_AUTH) { - IEEE80211_UNLOCK(ic); - ndis_auth_and_assoc(sc, vap); - IEEE80211_LOCK(ic); - } - break; - case IEEE80211_S_AUTH: - IEEE80211_UNLOCK(ic); - ndis_auth_and_assoc(sc, vap); - if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */ - ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0); - IEEE80211_LOCK(ic); - break; - default: - break; - } - return (0); -} - -static void -ndis_scan(void *arg) -{ - struct ieee80211vap *vap = arg; - - ieee80211_scan_done(vap); -} - -static void -ndis_scan_results(struct ndis_softc *sc) -{ - struct ieee80211com *ic = &sc->ndis_ic; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - ndis_80211_bssid_list_ex *bl; - ndis_wlan_bssid_ex *wb; - struct ieee80211_scanparams sp; - struct ieee80211_frame wh; - struct ieee80211_channel *saved_chan; - int i, j; - int rssi, noise, freq, chanflag; - uint8_t ssid[2+IEEE80211_NWID_LEN]; - uint8_t rates[2+IEEE80211_RATE_MAXSIZE]; - uint8_t *frm, *efrm; - - saved_chan = ic->ic_curchan; - noise = -96; - - if (ndis_get_bssid_list(sc, &bl)) - return; - - DPRINTF(("%s: %d results\n", __func__, bl->nblx_items)); - wb = &bl->nblx_bssid[0]; - for (i = 0; i < bl->nblx_items; i++) { - memset(&sp, 0, sizeof(sp)); - - memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2)); - memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3)); - rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise); - rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */ - if (wb->nwbx_privacy) - sp.capinfo |= IEEE80211_CAPINFO_PRIVACY; - sp.bintval = wb->nwbx_config.nc_beaconperiod; - switch (wb->nwbx_netinfra) { - case NDIS_80211_NET_INFRA_IBSS: - sp.capinfo |= IEEE80211_CAPINFO_IBSS; - break; - case NDIS_80211_NET_INFRA_BSS: - sp.capinfo |= IEEE80211_CAPINFO_ESS; - break; - } - sp.rates = &rates[0]; - for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) { - /* XXX - check units */ - if (wb->nwbx_supportedrates[j] == 0) - break; - rates[2 + j] = - wb->nwbx_supportedrates[j] & 0x7f; - } - rates[1] = j; - sp.ssid = (uint8_t *)&ssid[0]; - memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid, - wb->nwbx_ssid.ns_ssidlen); - sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen; - - chanflag = ndis_nettype_chan(wb->nwbx_nettype); - freq = wb->nwbx_config.nc_dsconfig / 1000; - sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag); - /* Hack ic->ic_curchan to be in sync with the scan result */ - ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag); - if (ic->ic_curchan == NULL) - ic->ic_curchan = &ic->ic_channels[0]; - - /* Process extended info from AP */ - if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) { - frm = (uint8_t *)&wb->nwbx_ies; - efrm = frm + wb->nwbx_ielen; - if (efrm - frm < 12) - goto done; - sp.tstamp = frm; frm += 8; - sp.bintval = le16toh(*(uint16_t *)frm); frm += 2; - sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2; - sp.ies = frm; - sp.ies_len = efrm - frm; - } -done: - DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n", - ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag, - rssi)); - ieee80211_add_scan(vap, ic->ic_curchan, &sp, &wh, 0, rssi, noise); - wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len); - } - free(bl, M_DEVBUF); - /* Restore the channel after messing with it */ - ic->ic_curchan = saved_chan; -} - -static void -ndis_scan_start(struct ieee80211com *ic) -{ - struct ndis_softc *sc = ic->ic_softc; - struct ieee80211vap *vap; - struct ieee80211_scan_state *ss; - ndis_80211_ssid ssid; - int error, len; - - ss = ic->ic_scan; - vap = TAILQ_FIRST(&ic->ic_vaps); - - if (!NDIS_INITIALIZED(sc)) { - DPRINTF(("%s: scan aborted\n", __func__)); - ieee80211_cancel_scan(vap); - return; - } - - len = sizeof(ssid); - bzero((char *)&ssid, len); - if (ss->ss_nssid == 0) - ssid.ns_ssidlen = 1; - else { - /* Perform a directed scan */ - ssid.ns_ssidlen = ss->ss_ssid[0].len; - bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen); - } - - error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len); - if (error) - DPRINTF(("%s: set ESSID failed\n", __func__)); - - len = 0; - error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len); - if (error) { - DPRINTF(("%s: scan command failed\n", __func__)); - ieee80211_cancel_scan(vap); - return; - } - /* Set a timer to collect the results */ - callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap); -} - -static void -ndis_set_channel(struct ieee80211com *ic) -{ - /* ignore */ -} - -static void -ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell) -{ - /* ignore */ -} - -static void -ndis_scan_mindwell(struct ieee80211_scan_state *ss) -{ - /* NB: don't try to abort scan; wait for firmware to finish */ -} - -static void -ndis_scan_end(struct ieee80211com *ic) -{ - struct ndis_softc *sc = ic->ic_softc; - - ndis_scan_results(sc); -} diff --git a/sys/dev/if_ndis/if_ndis_pci.c b/sys/dev/if_ndis/if_ndis_pci.c deleted file mode 100644 index cf1685a920ea..000000000000 --- a/sys/dev/if_ndis/if_ndis_pci.c +++ /dev/null @@ -1,357 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul . 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -MODULE_DEPEND(ndis, pci, 1, 1, 1); - -static int ndis_probe_pci (device_t); -static int ndis_attach_pci (device_t); -static struct resource_list *ndis_get_resource_list - (device_t, device_t); -static int ndis_devcompare (interface_type, - struct ndis_pci_type *, device_t); -extern int ndisdrv_modevent (module_t, int, void *); -extern int ndis_attach (device_t); -extern int ndis_shutdown (device_t); -extern int ndis_detach (device_t); -extern int ndis_suspend (device_t); -extern int ndis_resume (device_t); - -static device_method_t ndis_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ndis_probe_pci), - DEVMETHOD(device_attach, ndis_attach_pci), - DEVMETHOD(device_detach, ndis_detach), - DEVMETHOD(device_shutdown, ndis_shutdown), - DEVMETHOD(device_suspend, ndis_suspend), - DEVMETHOD(device_resume, ndis_resume), - - /* Bus interface */ - DEVMETHOD(bus_get_resource_list, ndis_get_resource_list), - - { 0, 0 } -}; - -static driver_t ndis_driver = { - "ndis", - ndis_methods, - sizeof(struct ndis_softc) -}; - -static devclass_t ndis_devclass; - -DRIVER_MODULE(ndis, pci, ndis_driver, ndis_devclass, ndisdrv_modevent, 0); - -static int -ndis_devcompare(bustype, t, dev) - interface_type bustype; - struct ndis_pci_type *t; - device_t dev; -{ - uint16_t vid, did; - uint32_t subsys; - - if (bustype != PCIBus) - return(FALSE); - - vid = pci_get_vendor(dev); - did = pci_get_device(dev); - subsys = pci_get_subdevice(dev); - subsys = (subsys << 16) | pci_get_subvendor(dev); - - while(t->ndis_name != NULL) { - if ((t->ndis_vid == vid) && (t->ndis_did == did) && - (t->ndis_subsys == subsys || t->ndis_subsys == 0)) { - device_set_desc(dev, t->ndis_name); - return(TRUE); - } - t++; - } - - return(FALSE); -} - -/* - * Probe for an NDIS device. Check the PCI vendor and device - * IDs against our list and return a device name if we find a match. - */ -static int -ndis_probe_pci(dev) - device_t dev; -{ - driver_object *drv; - struct drvdb_ent *db; - - drv = windrv_lookup(0, "PCI Bus"); - - if (drv == NULL) - return(ENXIO); - - db = windrv_match((matchfuncptr)ndis_devcompare, dev); - - if (db != NULL) { - /* Create PDO for this device instance */ - windrv_create_pdo(drv, dev); - return(0); - } - - return(ENXIO); -} - -/* - * Attach the interface. Allocate softc structures, do ifmedia - * setup and ethernet/BPF attach. - */ -static int -ndis_attach_pci(dev) - device_t dev; -{ - struct ndis_softc *sc; - int unit, error = 0, rid; - struct ndis_pci_type *t; - int devidx = 0, defidx = 0; - struct resource_list *rl; - struct resource_list_entry *rle; - struct drvdb_ent *db; - uint16_t vid, did; - uint32_t subsys; - - sc = device_get_softc(dev); - unit = device_get_unit(dev); - sc->ndis_dev = dev; - - db = windrv_match((matchfuncptr)ndis_devcompare, dev); - if (db == NULL) - return (ENXIO); - sc->ndis_dobj = db->windrv_object; - sc->ndis_regvals = db->windrv_regvals; - - /* - * Map control/status registers. - */ - - pci_enable_busmaster(dev); - - rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); - if (rl != NULL) { - STAILQ_FOREACH(rle, rl, link) { - switch (rle->type) { - case SYS_RES_IOPORT: - sc->ndis_io_rid = rle->rid; - sc->ndis_res_io = bus_alloc_resource_any(dev, - SYS_RES_IOPORT, &sc->ndis_io_rid, - RF_ACTIVE); - if (sc->ndis_res_io == NULL) { - device_printf(dev, - "couldn't map iospace\n"); - error = ENXIO; - goto fail; - } - break; - case SYS_RES_MEMORY: - if (sc->ndis_res_altmem != NULL && - sc->ndis_res_mem != NULL) { - device_printf(dev, - "too many memory resources\n"); - error = ENXIO; - goto fail; - } - if (sc->ndis_res_mem) { - sc->ndis_altmem_rid = rle->rid; - sc->ndis_res_altmem = - bus_alloc_resource_any(dev, - SYS_RES_MEMORY, - &sc->ndis_altmem_rid, - RF_ACTIVE); - if (sc->ndis_res_altmem == NULL) { - device_printf(dev, - "couldn't map alt " - "memory\n"); - error = ENXIO; - goto fail; - } - } else { - sc->ndis_mem_rid = rle->rid; - sc->ndis_res_mem = - bus_alloc_resource_any(dev, - SYS_RES_MEMORY, - &sc->ndis_mem_rid, - RF_ACTIVE); - if (sc->ndis_res_mem == NULL) { - device_printf(dev, - "couldn't map memory\n"); - error = ENXIO; - goto fail; - } - } - break; - case SYS_RES_IRQ: - rid = rle->rid; - sc->ndis_irq = bus_alloc_resource_any(dev, - SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE); - if (sc->ndis_irq == NULL) { - device_printf(dev, - "couldn't map interrupt\n"); - error = ENXIO; - goto fail; - } - break; - default: - break; - } - sc->ndis_rescnt++; - } - } - - /* - * If the BIOS did not set up an interrupt for this device, - * the resource traversal code above will fail to set up - * an IRQ resource. This is usually a bad thing, so try to - * force the allocation of an interrupt here. If one was - * not assigned to us by the BIOS, bus_alloc_resource() - * should route one for us. - */ - if (sc->ndis_irq == NULL) { - rid = 0; - sc->ndis_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &rid, RF_SHAREABLE | RF_ACTIVE); - if (sc->ndis_irq == NULL) { - device_printf(dev, "couldn't route interrupt\n"); - error = ENXIO; - goto fail; - } - sc->ndis_rescnt++; - } - - /* - * Allocate the parent bus DMA tag appropriate for PCI. - */ -#define NDIS_NSEG_NEW 32 - error = bus_dma_tag_create(bus_get_dma_tag(dev),/* PCI parent */ - 1, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - DFLTPHYS, NDIS_NSEG_NEW,/* maxsize, nsegments */ - BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */ - BUS_DMA_ALLOCNOW, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->ndis_parent_tag); - - if (error) - goto fail; - - sc->ndis_iftype = PCIBus; - - /* Figure out exactly which device we matched. */ - - vid = pci_get_vendor(dev); - did = pci_get_device(dev); - subsys = pci_get_subdevice(dev); - subsys = (subsys << 16) | pci_get_subvendor(dev); - - t = db->windrv_devlist; - - while(t->ndis_name != NULL) { - if (t->ndis_vid == vid && t->ndis_did == did) { - if (t->ndis_subsys == 0) - defidx = devidx; - else if (t->ndis_subsys == subsys) - break; - } - t++; - devidx++; - } - - if (t->ndis_name == NULL) - sc->ndis_devidx = defidx; - else - sc->ndis_devidx = devidx; - - error = ndis_attach(dev); - if (error == 0) - gone_in_dev(dev, 14, "ndis removed"); - - -fail: - return(error); -} - -static struct resource_list * -ndis_get_resource_list(dev, child) - device_t dev; - device_t child; -{ - struct ndis_softc *sc; - - sc = device_get_softc(dev); - return (BUS_GET_RESOURCE_LIST(device_get_parent(sc->ndis_dev), dev)); -} diff --git a/sys/dev/if_ndis/if_ndis_usb.c b/sys/dev/if_ndis/if_ndis_usb.c deleted file mode 100644 index 3364d3181532..000000000000 --- a/sys/dev/if_ndis/if_ndis_usb.c +++ /dev/null @@ -1,240 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2005 - * Bill Paul . 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -SYSCTL_NODE(_hw, OID_AUTO, ndisusb, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, - "NDIS USB driver parameters"); - -MODULE_DEPEND(ndis, usb, 1, 1, 1); - -static device_probe_t ndisusb_match; -static device_attach_t ndisusb_attach; -static device_detach_t ndisusb_detach; -static bus_get_resource_list_t ndis_get_resource_list; - -extern int ndisdrv_modevent (module_t, int, void *); -extern int ndis_attach (device_t); -extern int ndis_shutdown (device_t); -extern int ndis_detach (device_t); -extern int ndis_suspend (device_t); -extern int ndis_resume (device_t); - -extern unsigned char drv_data[]; - -static device_method_t ndis_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ndisusb_match), - DEVMETHOD(device_attach, ndisusb_attach), - DEVMETHOD(device_detach, ndisusb_detach), - DEVMETHOD(device_shutdown, ndis_shutdown), - - /* bus interface */ - DEVMETHOD(bus_get_resource_list, ndis_get_resource_list), - - DEVMETHOD_END -}; - -static driver_t ndis_driver = { - "ndis", - ndis_methods, - sizeof(struct ndis_softc) -}; - -static devclass_t ndis_devclass; - -DRIVER_MODULE(ndis, uhub, ndis_driver, ndis_devclass, ndisdrv_modevent, 0); - -static int -ndisusb_devcompare(interface_type bustype, struct ndis_usb_type *t, device_t dev) -{ - struct usb_attach_arg *uaa; - - if (bustype != PNPBus) - return (FALSE); - - uaa = device_get_ivars(dev); - - while (t->ndis_name != NULL) { - if ((uaa->info.idVendor == t->ndis_vid) && - (uaa->info.idProduct == t->ndis_did)) { - device_set_desc(dev, t->ndis_name); - return (TRUE); - } - t++; - } - - return (FALSE); -} - -static int -ndisusb_match(device_t self) -{ - struct drvdb_ent *db; - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->usb_mode != USB_MODE_HOST) - return (ENXIO); - if (uaa->info.bConfigIndex != NDISUSB_CONFIG_NO) - return (ENXIO); - if (uaa->info.bIfaceIndex != NDISUSB_IFACE_INDEX) - return (ENXIO); - - if (windrv_lookup(0, "USB Bus") == NULL) - return (ENXIO); - - db = windrv_match((matchfuncptr)ndisusb_devcompare, self); - if (db == NULL) - return (ENXIO); - uaa->driver_ivar = db; - - return (0); -} - -static int -ndisusb_attach(device_t self) -{ - const struct drvdb_ent *db; - struct ndisusb_softc *dummy = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - struct ndis_softc *sc; - struct ndis_usb_type *t; - driver_object *drv; - int devidx = 0; - - device_set_usb_desc(self); - db = uaa->driver_ivar; - sc = (struct ndis_softc *)dummy; - sc->ndis_dev = self; - mtx_init(&sc->ndisusb_mtx, "NDIS USB", MTX_NETWORK_LOCK, MTX_DEF); - sc->ndis_dobj = db->windrv_object; - sc->ndis_regvals = db->windrv_regvals; - sc->ndis_iftype = PNPBus; - sc->ndisusb_dev = uaa->device; - - /* Create PDO for this device instance */ - - drv = windrv_lookup(0, "USB Bus"); - windrv_create_pdo(drv, self); - - /* Figure out exactly which device we matched. */ - - t = db->windrv_devlist; - - while (t->ndis_name != NULL) { - if ((uaa->info.idVendor == t->ndis_vid) && - (uaa->info.idProduct == t->ndis_did)) { - sc->ndis_devidx = devidx; - break; - } - t++; - devidx++; - } - - if (ndis_attach(self) != 0) - return (ENXIO); - - gone_in_dev(self, 14, "ndis removed"); - - return (0); -} - -static int -ndisusb_detach(device_t self) -{ - int i; - struct ndis_softc *sc = device_get_softc(self); - struct ndisusb_ep *ne; - - sc->ndisusb_status |= NDISUSB_STATUS_DETACH; - - ndis_pnpevent_nic(self, NDIS_PNP_EVENT_SURPRISE_REMOVED); - - if (sc->ndisusb_status & NDISUSB_STATUS_SETUP_EP) { - usbd_transfer_unsetup(sc->ndisusb_dread_ep.ne_xfer, 1); - usbd_transfer_unsetup(sc->ndisusb_dwrite_ep.ne_xfer, 1); - } - for (i = 0; i < NDISUSB_ENDPT_MAX; i++) { - ne = &sc->ndisusb_ep[i]; - usbd_transfer_unsetup(ne->ne_xfer, 1); - } - - (void)ndis_detach(self); - - mtx_destroy(&sc->ndisusb_mtx); - return (0); -} - -static struct resource_list * -ndis_get_resource_list(device_t dev, device_t child) -{ - struct ndis_softc *sc; - - sc = device_get_softc(dev); - return (BUS_GET_RESOURCE_LIST(device_get_parent(sc->ndis_dev), dev)); -} diff --git a/sys/dev/if_ndis/if_ndisvar.h b/sys/dev/if_ndis/if_ndisvar.h deleted file mode 100644 index 0182e15f6e2a..000000000000 --- a/sys/dev/if_ndis/if_ndisvar.h +++ /dev/null @@ -1,263 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul . All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#define NDIS_DEFAULT_NODENAME "FreeBSD NDIS node" -#define NDIS_NODENAME_LEN 32 - -/* For setting/getting OIDs from userspace. */ - -struct ndis_oid_data { - uint32_t oid; - uint32_t len; -#ifdef notdef - uint8_t data[1]; -#endif -}; - -struct ndis_pci_type { - uint16_t ndis_vid; - uint16_t ndis_did; - uint32_t ndis_subsys; - char *ndis_name; -}; - -struct ndis_pccard_type { - const char *ndis_vid; - const char *ndis_did; - char *ndis_name; -}; - -struct ndis_usb_type { - uint16_t ndis_vid; - uint16_t ndis_did; - char *ndis_name; -}; - -struct ndis_shmem { - list_entry ndis_list; - bus_dma_tag_t ndis_stag; - bus_dmamap_t ndis_smap; - void *ndis_saddr; - ndis_physaddr ndis_paddr; -}; - -struct ndis_cfglist { - ndis_cfg ndis_cfg; - struct sysctl_oid *ndis_oid; - TAILQ_ENTRY(ndis_cfglist) link; -}; - -/* - * Helper struct to make parsing information - * elements easier. - */ -struct ndis_ie { - uint8_t ni_oui[3]; - uint8_t ni_val; -}; - -TAILQ_HEAD(nch, ndis_cfglist); - -#define NDIS_INITIALIZED(sc) (sc->ndis_block->nmb_devicectx != NULL) - -#define NDIS_TXPKTS 64 -#define NDIS_INC(x) \ - (x)->ndis_txidx = ((x)->ndis_txidx + 1) % (x)->ndis_maxpkts - - -#define NDIS_EVENTS 4 -#define NDIS_EVTINC(x) (x) = ((x) + 1) % NDIS_EVENTS - -struct ndis_evt { - uint32_t ne_sts; - uint32_t ne_len; - char *ne_buf; -}; - -struct ndis_vap { - struct ieee80211vap vap; - - int (*newstate)(struct ieee80211vap *, - enum ieee80211_state, int); -}; -#define NDIS_VAP(vap) ((struct ndis_vap *)(vap)) - -#define NDISUSB_CONFIG_NO 0 -#define NDISUSB_IFACE_INDEX 0 -/* XXX at USB2 there's no USBD_NO_TIMEOUT macro anymore */ -#define NDISUSB_NO_TIMEOUT 0 -#define NDISUSB_INTR_TIMEOUT 1000 -#define NDISUSB_TX_TIMEOUT 10000 -struct ndisusb_xfer; -struct ndisusb_ep { - struct usb_xfer *ne_xfer[1]; - list_entry ne_active; - list_entry ne_pending; - kspin_lock ne_lock; - uint8_t ne_dirin; -}; -struct ndisusb_xfer { - struct ndisusb_ep *nx_ep; - void *nx_priv; - uint8_t *nx_urbbuf; - uint32_t nx_urbactlen; - uint32_t nx_urblen; - uint8_t nx_shortxfer; - list_entry nx_next; -}; -struct ndisusb_xferdone { - struct ndisusb_xfer *nd_xfer; - usb_error_t nd_status; - list_entry nd_donelist; -}; - -struct ndisusb_task { - unsigned nt_type; -#define NDISUSB_TASK_TSTART 0 -#define NDISUSB_TASK_IRPCANCEL 1 -#define NDISUSB_TASK_VENDOR 2 - void *nt_ctx; - list_entry nt_tasklist; -}; - -struct ndis_softc { -#define NDISUSB_GET_IFNET(ndis_softc) ( (ndis_softc)->ndis_80211 ? NULL : (ndis_softc)->ifp ) - u_int ndis_80211:1, - ndis_link:1, - ndis_running:1; - union { - struct { /* Ethernet */ - struct ifnet *ifp; - struct ifmedia ifmedia; - int ndis_if_flags; - }; - struct { /* Wireless */ - struct ieee80211com ndis_ic; - struct callout ndis_scan_callout; - int (*ndis_newstate)(struct ieee80211com *, - enum ieee80211_state, int); - }; - }; - u_long ndis_hwassist; - uint32_t ndis_v4tx; - uint32_t ndis_v4rx; - bus_space_handle_t ndis_bhandle; - bus_space_tag_t ndis_btag; - void *ndis_intrhand; - struct resource *ndis_irq; - struct resource *ndis_res; - struct resource *ndis_res_io; - int ndis_io_rid; - struct resource *ndis_res_mem; - int ndis_mem_rid; - struct resource *ndis_res_altmem; - int ndis_altmem_rid; - struct resource *ndis_res_am; /* attribute mem (pccard) */ - int ndis_am_rid; - struct resource *ndis_res_cm; /* common mem (pccard) */ - struct resource_list ndis_rl; - int ndis_rescnt; - struct mtx ndis_mtx; - uint8_t ndis_irql; - device_t ndis_dev; - int ndis_unit; - ndis_miniport_block *ndis_block; - ndis_miniport_characteristics *ndis_chars; - interface_type ndis_type; - struct callout ndis_stat_callout; - int ndis_maxpkts; - ndis_oid *ndis_oids; - int ndis_oidcnt; - int ndis_txidx; - int ndis_txpending; - ndis_packet **ndis_txarray; - ndis_handle ndis_txpool; - int ndis_sc; - ndis_cfg *ndis_regvals; - struct nch ndis_cfglist_head; - uint32_t ndis_sts; - uint32_t ndis_filter; - int ndis_skip; - int ndis_devidx; - interface_type ndis_iftype; - driver_object *ndis_dobj; - io_workitem *ndis_tickitem; - io_workitem *ndis_startitem; - io_workitem *ndis_resetitem; - io_workitem *ndis_inputitem; - kdpc ndis_rxdpc; - bus_dma_tag_t ndis_parent_tag; - list_entry ndis_shlist; - bus_dma_tag_t ndis_mtag; - bus_dma_tag_t ndis_ttag; - bus_dmamap_t *ndis_mmaps; - bus_dmamap_t *ndis_tmaps; - int ndis_mmapcnt; - struct ndis_evt ndis_evt[NDIS_EVENTS]; - int ndis_evtpidx; - int ndis_evtcidx; - struct mbufq ndis_rxqueue; - kspin_lock ndis_rxlock; - - int ndis_tx_timer; - int ndis_hang_timer; - - struct usb_device *ndisusb_dev; - struct mtx ndisusb_mtx; - struct ndisusb_ep ndisusb_dread_ep; - struct ndisusb_ep ndisusb_dwrite_ep; -#define NDISUSB_GET_ENDPT(addr) \ - ((UE_GET_DIR(addr) >> 7) | (UE_GET_ADDR(addr) << 1)) -#define NDISUSB_ENDPT_MAX ((UE_ADDR + 1) * 2) - struct ndisusb_ep ndisusb_ep[NDISUSB_ENDPT_MAX]; - io_workitem *ndisusb_xferdoneitem; - list_entry ndisusb_xferdonelist; - kspin_lock ndisusb_xferdonelock; - io_workitem *ndisusb_taskitem; - list_entry ndisusb_tasklist; - kspin_lock ndisusb_tasklock; - int ndisusb_status; -#define NDISUSB_STATUS_DETACH 0x1 -#define NDISUSB_STATUS_SETUP_EP 0x2 -}; - -#define NDIS_LOCK(_sc) mtx_lock(&(_sc)->ndis_mtx) -#define NDIS_UNLOCK(_sc) mtx_unlock(&(_sc)->ndis_mtx) -#define NDIS_LOCK_ASSERT(_sc, t) mtx_assert(&(_sc)->ndis_mtx, t) -#define NDISUSB_LOCK(_sc) mtx_lock(&(_sc)->ndisusb_mtx) -#define NDISUSB_UNLOCK(_sc) mtx_unlock(&(_sc)->ndisusb_mtx) -#define NDISUSB_LOCK_ASSERT(_sc, t) mtx_assert(&(_sc)->ndisusb_mtx, t) - diff --git a/sys/modules/Makefile b/sys/modules/Makefile index f5dd13527f08..781495110cb9 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -159,7 +159,6 @@ SUBDIR= \ ${_if_me} \ if_infiniband \ if_lagg \ - ${_if_ndis} \ ${_if_stf} \ if_tuntap \ if_vlan \ @@ -261,7 +260,6 @@ SUBDIR= \ mxge \ my \ ${_nctgpio} \ - ${_ndis} \ ${_netgraph} \ ${_nfe} \ nfscl \ @@ -634,7 +632,6 @@ _em= em _et= et _ftwd= ftwd _exca= exca -_if_ndis= if_ndis _io= io _itwd= itwd _ix= ix @@ -643,7 +640,6 @@ _ixv= ixv _lio= lio .endif _nctgpio= nctgpio -_ndis= ndis _ntb= ntb _ocs_fc= ocs_fc _pccard= pccard diff --git a/sys/modules/if_ndis/Makefile b/sys/modules/if_ndis/Makefile deleted file mode 100644 index efdde6e0977e..000000000000 --- a/sys/modules/if_ndis/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# $FreeBSD$ - -.PATH: ${SRCTOP}/sys/dev/if_ndis - -KMOD= if_ndis -SRCS= if_ndis.c if_ndis_pci.c if_ndis_usb.c -SRCS+= device_if.h bus_if.h pci_if.h -SRCS+= opt_bus.h opt_usb.h usb_if.h usbdevs.h - -.include diff --git a/targets/pseudo/userland/Makefile.depend b/targets/pseudo/userland/Makefile.depend index 78b5c1e3a046..cde4eadd6eee 100644 --- a/targets/pseudo/userland/Makefile.depend +++ b/targets/pseudo/userland/Makefile.depend @@ -737,7 +737,6 @@ DIRDEPS+= \ usr.sbin/wlandebug \ usr.sbin/wpa/hostapd \ usr.sbin/wpa/hostapd_cli \ - usr.sbin/wpa/ndis_events \ usr.sbin/wpa/wpa_cli \ usr.sbin/wpa/wpa_passphrase \ usr.sbin/wpa/wpa_supplicant \ @@ -788,7 +787,6 @@ DIRDEPS.amd64= \ usr.sbin/kgmon \ usr.sbin/lptcontrol \ usr.sbin/mptable \ - usr.sbin/ndiscvt \ usr.sbin/spkrtest \ usr.sbin/sade \ usr.sbin/zzz @@ -814,7 +812,6 @@ DIRDEPS.i386= \ usr.sbin/kgmon \ usr.sbin/lptcontrol \ usr.sbin/mptable \ - usr.sbin/ndiscvt \ usr.sbin/pnpinfo \ usr.sbin/sade \ usr.sbin/spkrtest \ diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index b517cff65338..4a075a78cf70 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -5938,14 +5938,6 @@ OLD_FILES+=usr/share/man/whatis OLD_FILES+=usr/share/openssl/man/whatis .endif -.if ${MK_NDIS} == no -OLD_FILES+=usr/sbin/ndiscvt -OLD_FILES+=usr/sbin/ndisgen -OLD_FILES+=usr/share/man/man8/ndiscvt.8.gz -OLD_FILES+=usr/share/man/man8/ndisgen.8.gz -OLD_FILES+=usr/share/misc/windrv_stub.c -.endif - .if ${MK_NETCAT} == no OLD_FILES+=rescue/nc OLD_FILES+=usr/bin/nc diff --git a/tools/kerneldoc/subsys/Doxyfile-dev_if_ndis b/tools/kerneldoc/subsys/Doxyfile-dev_if_ndis deleted file mode 100644 index d758d8de8971..000000000000 --- a/tools/kerneldoc/subsys/Doxyfile-dev_if_ndis +++ /dev/null @@ -1,21 +0,0 @@ -# Doxyfile 1.5.2 - -# $FreeBSD$ - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -PROJECT_NAME = "FreeBSD kernel IF_NDIS device code" -OUTPUT_DIRECTORY = $(DOXYGEN_DEST_PATH)/dev_if_ndis/ -EXTRACT_ALL = YES # for undocumented src, no warnings enabled -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = $(DOXYGEN_SRC_PATH)/dev/if_ndis/ \ - $(NOTREVIEWED) - -GENERATE_TAGFILE = dev_if_ndis/dev_if_ndis.tag - -@INCLUDE_PATH = $(DOXYGEN_INCLUDE_PATH) -@INCLUDE = common-Doxyfile - diff --git a/usr.sbin/Makefile.amd64 b/usr.sbin/Makefile.amd64 index fca60eae07e1..64e5d8678c41 100644 --- a/usr.sbin/Makefile.amd64 +++ b/usr.sbin/Makefile.amd64 @@ -24,8 +24,5 @@ SUBDIR+= hyperv SUBDIR+= kgmon SUBDIR+= lptcontrol SUBDIR+= mptable -.if ${MK_NDIS} != "no" -SUBDIR+= ndiscvt -.endif SUBDIR+= spkrtest SUBDIR+= zzz diff --git a/usr.sbin/Makefile.i386 b/usr.sbin/Makefile.i386 index 6724115b8217..90a74e05e061 100644 --- a/usr.sbin/Makefile.i386 +++ b/usr.sbin/Makefile.i386 @@ -18,9 +18,6 @@ SUBDIR+= hyperv SUBDIR+= kgmon SUBDIR+= lptcontrol SUBDIR+= mptable -.if ${MK_NDIS} != "no" -SUBDIR+= ndiscvt -.endif SUBDIR+= pnpinfo SUBDIR+= spkrtest SUBDIR+= zzz diff --git a/usr.sbin/ndiscvt/Makefile b/usr.sbin/ndiscvt/Makefile deleted file mode 100644 index a8be84fe7255..000000000000 --- a/usr.sbin/ndiscvt/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -# $FreeBSD$ - -.PATH: ${SRCTOP}/sys/compat/ndis - -PROG= ndiscvt -SRCS= ndiscvt.c -SRCS+= subr_pe.c -SRCS+= inf.c inf-token.l inf-parse.y y.tab.h - -MAN= ndiscvt.8 -MAN+= ndisgen.8 - -WARNS?= 4 -NO_WCAST_ALIGN= - -YFLAGS+=-v - -CFLAGS+=-I. -I${.CURDIR} -I${SRCTOP}/sys - -CLEANFILES= y.output - -FILES= windrv_stub.c -FILESDIR= ${SHAREDIR}/misc - -SCRIPTS= ndisgen.sh - -.include diff --git a/usr.sbin/ndiscvt/Makefile.depend b/usr.sbin/ndiscvt/Makefile.depend deleted file mode 100644 index af1fb7abc88e..000000000000 --- a/usr.sbin/ndiscvt/Makefile.depend +++ /dev/null @@ -1,19 +0,0 @@ -# $FreeBSD$ -# Autogenerated - do NOT edit! - -DIRDEPS = \ - gnu/lib/csu \ - include \ - include/xlocale \ - lib/${CSU_DIR} \ - lib/libc \ - lib/libcompiler_rt \ - usr.bin/lex/lib \ - usr.bin/yacc.host \ - - -.include - -.if ${DEP_RELDIR} == ${_DEP_RELDIR} -# local dependencies - needed for -jN in clean tree -.endif diff --git a/usr.sbin/ndiscvt/inf-parse.y b/usr.sbin/ndiscvt/inf-parse.y deleted file mode 100644 index 740aba5e87d1..000000000000 --- a/usr.sbin/ndiscvt/inf-parse.y +++ /dev/null @@ -1,112 +0,0 @@ -%{ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul . 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include - -#include "inf.h" - -extern int yylex (void); -extern void yyerror(const char *); -%} - -%token EQUALS COMMA EOL -%token SECTION -%token STRING -%token WORD - -%union { - char *str; -} - -%% - -inf_file - : inf_list - | - ; - -inf_list - : inf - | inf_list inf - ; - -inf - : SECTION EOL - { section_add($1); } - | WORD EQUALS assign EOL - { assign_add($1); } - | WORD COMMA regkey EOL - { regkey_add($1); } - | WORD EOL - { define_add($1); } - | EOL - ; - -assign - : WORD - { push_word($1); } - | STRING - { push_word($1); } - | WORD COMMA assign - { push_word($1); } - | STRING COMMA assign - { push_word($1); } - | COMMA assign - { push_word(NULL); } - | COMMA - { push_word(NULL); } - | - ; - -regkey - : WORD - { push_word($1); } - | STRING - { push_word($1); } - | WORD COMMA regkey - { push_word($1); } - | STRING COMMA regkey - { push_word($1); } - | COMMA regkey - { push_word(NULL); } - | COMMA - { push_word(NULL); } - ; -%% diff --git a/usr.sbin/ndiscvt/inf-token.l b/usr.sbin/ndiscvt/inf-token.l deleted file mode 100644 index 2aac5b477067..000000000000 --- a/usr.sbin/ndiscvt/inf-token.l +++ /dev/null @@ -1,134 +0,0 @@ -%{ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul . 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include "y.tab.h" - -int lineno = 1; - -int yylex(void); -void yyerror(const char *); - -static void -update_lineno(const char *cp) -{ - while (*cp) - if (*cp++ == '\n') - lineno++; -} - -%} - -%option noyywrap -%option nounput -%option noinput - -%% - -[ \t]+ ; -\n { lineno++; return EOL; } -\r ; -;.*$ ; -\/\/.*$ ; -= { return EQUALS; } -, { return COMMA; } -\"(\\\"|[^"]|\"\")*\" { - int len = strlen(yytext) - 2; - int blen = len + 1; - char *walker; - int i; - update_lineno(yytext); - yylval.str = (char *)malloc(blen); - if (yylval.str == NULL) - goto out; - walker = yylval.str; - for (i = 1; i <= len; i++) { - if (yytext[i] == '\"') { - switch (yytext[i + 1]) { - case '\"': - i++; - break; - default: - break; - } - } - if (yytext[i] == '\\') { - switch (yytext[i + 1]) { - case '\n': - i += 2; - while(isspace(yytext[i])) - i++; - break; - case '\"': - i++; - break; - case '(': - i++; - break; - default: - break; - } - } - *walker++ = yytext[i]; - } - *walker++ = '\0'; - out:; - return STRING; - } -\[[a-zA-Z0-9%&\{\}\-\.\/_\\\*\ ]+\] { - int len = strlen(yytext); - yytext[len-1] = '\0'; - yylval.str = strdup(yytext+1); - return SECTION; - } -[a-zA-Z0-9%&\{\}\-\.\/_\\\*]+ { - yylval.str = strdup(yytext); - return WORD; - } -%% - -void -yyerror(const char *s) -{ - errx(1, "line %d: %s%s %s.", lineno, yytext, yytext?":":"", s); -} diff --git a/usr.sbin/ndiscvt/inf.c b/usr.sbin/ndiscvt/inf.c deleted file mode 100644 index 442e7f61b1fd..000000000000 --- a/usr.sbin/ndiscvt/inf.c +++ /dev/null @@ -1,920 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul . 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include - -#include - -#include "inf.h" - -extern FILE *yyin; -int yyparse (void); - -const char *words[W_MAX]; /* More than we'll need. */ -int idx; - -static struct section_head sh; -static struct reg_head rh; -static struct assign_head ah; - -static char *sstrdup (const char *); -static struct assign - *find_assign (const char *, const char *); -static struct assign - *find_next_assign - (struct assign *); -static struct section - *find_section (const char *); -static int dump_deviceids_pci (void); -static int dump_deviceids_pcmcia (void); -static int dump_deviceids_usb (void); -static void dump_pci_id (const char *); -static void dump_pcmcia_id (const char *); -static void dump_usb_id (const char *); -static void dump_regvals (void); -static void dump_paramreg (const struct section *, - const struct reg *, int); - -static FILE *ofp; - -int -inf_parse (FILE *fp, FILE *outfp) -{ - TAILQ_INIT(&sh); - TAILQ_INIT(&rh); - TAILQ_INIT(&ah); - - ofp = outfp; - yyin = fp; - yyparse(); - - if (dump_deviceids_pci() == 0 && - dump_deviceids_pcmcia() == 0 && - dump_deviceids_usb() == 0) - return (-1); - - fprintf(outfp, "#ifdef NDIS_REGVALS\n"); - dump_regvals(); - fprintf(outfp, "#endif /* NDIS_REGVALS */\n"); - - return (0); -} - -void -section_add (const char *s) -{ - struct section *sec; - - sec = malloc(sizeof(struct section)); - bzero(sec, sizeof(struct section)); - sec->name = s; - TAILQ_INSERT_TAIL(&sh, sec, link); - - return; -} - -static struct assign * -find_assign (const char *s, const char *k) -{ - struct assign *assign; - char newkey[256]; - - /* Deal with string section lookups. */ - - if (k != NULL && k[0] == '%') { - bzero(newkey, sizeof(newkey)); - strncpy(newkey, k + 1, strlen(k) - 2); - k = newkey; - } - - TAILQ_FOREACH(assign, &ah, link) { - if (strcasecmp(assign->section->name, s) == 0) { - if (k == NULL) - return(assign); - else - if (strcasecmp(assign->key, k) == 0) - return(assign); - } - } - return(NULL); -} - -static struct assign * -find_next_assign (struct assign *a) -{ - struct assign *assign; - - TAILQ_FOREACH(assign, &ah, link) { - if (assign == a) - break; - } - - assign = assign->link.tqe_next; - - if (assign == NULL || assign->section != a->section) - return(NULL); - - return (assign); -} - -static const char * -stringcvt(const char *s) -{ - struct assign *manf; - - manf = find_assign("strings", s); - if (manf == NULL) - return(s); - return(manf->vals[0]); -} - -struct section * -find_section (const char *s) -{ - struct section *section; - - TAILQ_FOREACH(section, &sh, link) { - if (strcasecmp(section->name, s) == 0) - return(section); - } - return(NULL); -} - -static void -dump_pcmcia_id(const char *s) -{ - char *manstr, *devstr; - char *p0, *p; - - p0 = __DECONST(char *, s); - - p = strchr(p0, '\\'); - if (p == NULL) - return; - p0 = p + 1; - - p = strchr(p0, '-'); - if (p == NULL) - return; - *p = '\0'; - - manstr = p0; - - /* Convert any underscores to spaces. */ - - while (*p0 != '\0') { - if (*p0 == '_') - *p0 = ' '; - p0++; - } - - p0 = p + 1; - p = strchr(p0, '-'); - if (p == NULL) - return; - *p = '\0'; - - devstr = p0; - - /* Convert any underscores to spaces. */ - - while (*p0 != '\0') { - if (*p0 == '_') - *p0 = ' '; - p0++; - } - - fprintf(ofp, "\t\\\n\t{ \"%s\", \"%s\", ", manstr, devstr); - return; -} - -static void -dump_pci_id(const char *s) -{ - char *p; - char vidstr[7], didstr[7], subsysstr[14]; - - p = strcasestr(s, "VEN_"); - if (p == NULL) - return; - p += 4; - strcpy(vidstr, "0x"); - strncat(vidstr, p, 4); - p = strcasestr(s, "DEV_"); - if (p == NULL) - return; - p += 4; - strcpy(didstr, "0x"); - strncat(didstr, p, 4); - if (p == NULL) - return; - p = strcasestr(s, "SUBSYS_"); - if (p == NULL) - strcpy(subsysstr, "0x00000000"); - else { - p += 7; - strcpy(subsysstr, "0x"); - strncat(subsysstr, p, 8); - } - - fprintf(ofp, "\t\\\n\t{ %s, %s, %s, ", vidstr, didstr, subsysstr); - return; -} - -static void -dump_usb_id(const char *s) -{ - char *p; - char vidstr[7], pidstr[7]; - - p = strcasestr(s, "VID_"); - if (p == NULL) - return; - p += 4; - strcpy(vidstr, "0x"); - strncat(vidstr, p, 4); - p = strcasestr(s, "PID_"); - if (p == NULL) - return; - p += 4; - strcpy(pidstr, "0x"); - strncat(pidstr, p, 4); - if (p == NULL) - return; - - fprintf(ofp, "\t\\\n\t{ %s, %s, ", vidstr, pidstr); -} - -static int -dump_deviceids_pci() -{ - struct assign *manf, *dev; - struct section *sec; - struct assign *assign; - char xpsec[256]; - int first = 1, found = 0; - - /* Find manufacturer name */ - manf = find_assign("Manufacturer", NULL); - -nextmanf: - - /* Find manufacturer section */ - if (manf->vals[1] != NULL && - (strcasecmp(manf->vals[1], "NT.5.1") == 0 || - strcasecmp(manf->vals[1], "NTx86") == 0 || - strcasecmp(manf->vals[1], "NTx86.5.1") == 0 || - strcasecmp(manf->vals[1], "NTamd64") == 0)) { - /* Handle Windows XP INF files. */ - snprintf(xpsec, sizeof(xpsec), "%s.%s", - manf->vals[0], manf->vals[1]); - sec = find_section(xpsec); - } else - sec = find_section(manf->vals[0]); - - /* See if there are any PCI device definitions. */ - - TAILQ_FOREACH(assign, &ah, link) { - if (assign->section == sec) { - dev = find_assign("strings", assign->key); - if (strcasestr(assign->vals[1], "PCI") != NULL) { - found++; - break; - } - } - } - - if (found == 0) - goto done; - - found = 0; - - if (first == 1) { - /* Emit start of PCI device table */ - fprintf (ofp, "#define NDIS_PCI_DEV_TABLE"); - first = 0; - } - -retry: - - /* - * Now run through all the device names listed - * in the manufacturer section and dump out the - * device descriptions and vendor/device IDs. - */ - - TAILQ_FOREACH(assign, &ah, link) { - if (assign->section == sec) { - dev = find_assign("strings", assign->key); - /* Emit device IDs. */ - if (strcasestr(assign->vals[1], "PCI") != NULL) - dump_pci_id(assign->vals[1]); - else - continue; - /* Emit device description */ - fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]); - found++; - } - } - - /* Someone tried to fool us. Shame on them. */ - if (!found) { - found++; - sec = find_section(manf->vals[0]); - goto retry; - } - - /* Handle Manufacturer sections with multiple entries. */ - manf = find_next_assign(manf); - - if (manf != NULL) - goto nextmanf; - -done: - /* Emit end of table */ - - fprintf(ofp, "\n\n"); - - return (found); -} - -static int -dump_deviceids_pcmcia() -{ - struct assign *manf, *dev; - struct section *sec; - struct assign *assign; - char xpsec[256]; - int first = 1, found = 0; - - /* Find manufacturer name */ - manf = find_assign("Manufacturer", NULL); - -nextmanf: - - /* Find manufacturer section */ - if (manf->vals[1] != NULL && - (strcasecmp(manf->vals[1], "NT.5.1") == 0 || - strcasecmp(manf->vals[1], "NTx86") == 0 || - strcasecmp(manf->vals[1], "NTx86.5.1") == 0 || - strcasecmp(manf->vals[1], "NTamd64") == 0)) { - /* Handle Windows XP INF files. */ - snprintf(xpsec, sizeof(xpsec), "%s.%s", - manf->vals[0], manf->vals[1]); - sec = find_section(xpsec); - } else - sec = find_section(manf->vals[0]); - - /* See if there are any PCMCIA device definitions. */ - - TAILQ_FOREACH(assign, &ah, link) { - if (assign->section == sec) { - dev = find_assign("strings", assign->key); - if (strcasestr(assign->vals[1], "PCMCIA") != NULL) { - found++; - break; - } - } - } - - if (found == 0) - goto done; - - found = 0; - - if (first == 1) { - /* Emit start of PCMCIA device table */ - fprintf (ofp, "#define NDIS_PCMCIA_DEV_TABLE"); - first = 0; - } - -retry: - - /* - * Now run through all the device names listed - * in the manufacturer section and dump out the - * device descriptions and vendor/device IDs. - */ - - TAILQ_FOREACH(assign, &ah, link) { - if (assign->section == sec) { - dev = find_assign("strings", assign->key); - /* Emit device IDs. */ - if (strcasestr(assign->vals[1], "PCMCIA") != NULL) - dump_pcmcia_id(assign->vals[1]); - else - continue; - /* Emit device description */ - fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]); - found++; - } - } - - /* Someone tried to fool us. Shame on them. */ - if (!found) { - found++; - sec = find_section(manf->vals[0]); - goto retry; - } - - /* Handle Manufacturer sections with multiple entries. */ - manf = find_next_assign(manf); - - if (manf != NULL) - goto nextmanf; - -done: - /* Emit end of table */ - - fprintf(ofp, "\n\n"); - - return (found); -} - -static int -dump_deviceids_usb() -{ - struct assign *manf, *dev; - struct section *sec; - struct assign *assign; - char xpsec[256]; - int first = 1, found = 0; - - /* Find manufacturer name */ - manf = find_assign("Manufacturer", NULL); - -nextmanf: - - /* Find manufacturer section */ - if (manf->vals[1] != NULL && - (strcasecmp(manf->vals[1], "NT.5.1") == 0 || - strcasecmp(manf->vals[1], "NTx86") == 0 || - strcasecmp(manf->vals[1], "NTx86.5.1") == 0 || - strcasecmp(manf->vals[1], "NTamd64") == 0)) { - /* Handle Windows XP INF files. */ - snprintf(xpsec, sizeof(xpsec), "%s.%s", - manf->vals[0], manf->vals[1]); - sec = find_section(xpsec); - } else - sec = find_section(manf->vals[0]); - - /* See if there are any USB device definitions. */ - - TAILQ_FOREACH(assign, &ah, link) { - if (assign->section == sec) { - dev = find_assign("strings", assign->key); - if (strcasestr(assign->vals[1], "USB") != NULL) { - found++; - break; - } - } - } - - if (found == 0) - goto done; - - found = 0; - - if (first == 1) { - /* Emit start of USB device table */ - fprintf (ofp, "#define NDIS_USB_DEV_TABLE"); - first = 0; - } - -retry: - - /* - * Now run through all the device names listed - * in the manufacturer section and dump out the - * device descriptions and vendor/device IDs. - */ - - TAILQ_FOREACH(assign, &ah, link) { - if (assign->section == sec) { - dev = find_assign("strings", assign->key); - /* Emit device IDs. */ - if (strcasestr(assign->vals[1], "USB") != NULL) - dump_usb_id(assign->vals[1]); - else - continue; - /* Emit device description */ - fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]); - found++; - } - } - - /* Someone tried to fool us. Shame on them. */ - if (!found) { - found++; - sec = find_section(manf->vals[0]); - goto retry; - } - - /* Handle Manufacturer sections with multiple entries. */ - manf = find_next_assign(manf); - - if (manf != NULL) - goto nextmanf; - -done: - /* Emit end of table */ - - fprintf(ofp, "\n\n"); - - return (found); -} - -static void -dump_addreg(const char *s, int devidx) -{ - struct section *sec; - struct reg *reg; - - /* Find the addreg section */ - sec = find_section(s); - - /* Dump all the keys defined in it. */ - TAILQ_FOREACH(reg, &rh, link) { - /* - * Keys with an empty subkey are very easy to parse, - * so just deal with them here. If a parameter key - * of the same name also exists, prefer that one and - * skip this one. - */ - if (reg->section == sec) { - if (reg->subkey == NULL) { - fprintf(ofp, "\n\t{ \"%s\",", reg->key); - fprintf(ofp,"\n\t\"%s \",", reg->key); - fprintf(ofp, "\n\t{ \"%s\" }, %d },", - reg->value == NULL ? "" : - stringcvt(reg->value), devidx); - } else if (strncasecmp(reg->subkey, - "Ndi\\params", strlen("Ndi\\params")-1) == 0 && - (reg->key != NULL && strcasecmp(reg->key, - "ParamDesc") == 0)) - dump_paramreg(sec, reg, devidx); - } - } - - return; -} - -static void -dump_enumreg(const struct section *s, const struct reg *r) -{ - struct reg *reg; - char enumkey[256]; - - sprintf(enumkey, "%s\\enum", r->subkey); - TAILQ_FOREACH(reg, &rh, link) { - if (reg->section != s) - continue; - if (reg->subkey == NULL || strcasecmp(reg->subkey, enumkey)) - continue; - fprintf(ofp, " [%s=%s]", reg->key, - stringcvt(reg->value)); - } - return; -} - -static void -dump_editreg(const struct section *s, const struct reg *r) -{ - struct reg *reg; - - TAILQ_FOREACH(reg, &rh, link) { - if (reg->section != s) - continue; - if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey)) - continue; - if (reg->key == NULL) - continue; - if (strcasecmp(reg->key, "LimitText") == 0) - fprintf(ofp, " [maxchars=%s]", reg->value); - if (strcasecmp(reg->key, "Optional") == 0 && - strcmp(reg->value, "1") == 0) - fprintf(ofp, " [optional]"); - } - return; -} - -/* Use this for int too */ -static void -dump_dwordreg(const struct section *s, const struct reg *r) -{ - struct reg *reg; - - TAILQ_FOREACH(reg, &rh, link) { - if (reg->section != s) - continue; - if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey)) - continue; - if (reg->key == NULL) - continue; - if (strcasecmp(reg->key, "min") == 0) - fprintf(ofp, " [min=%s]", reg->value); - if (strcasecmp(reg->key, "max") == 0) - fprintf(ofp, " [max=%s]", reg->value); - } - return; -} - -static void -dump_defaultinfo(const struct section *s, const struct reg *r, int devidx) -{ - struct reg *reg; - TAILQ_FOREACH(reg, &rh, link) { - if (reg->section != s) - continue; - if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey)) - continue; - if (reg->key == NULL || strcasecmp(reg->key, "Default")) - continue; - fprintf(ofp, "\n\t{ \"%s\" }, %d },", reg->value == NULL ? "" : - stringcvt(reg->value), devidx); - return; - } - /* Default registry entry missing */ - fprintf(ofp, "\n\t{ \"\" }, %d },", devidx); - return; -} - -static void -dump_paramdesc(const struct section *s, const struct reg *r) -{ - struct reg *reg; - TAILQ_FOREACH(reg, &rh, link) { - if (reg->section != s) - continue; - if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey)) - continue; - if (reg->key == NULL || strcasecmp(reg->key, "ParamDesc")) - continue; - fprintf(ofp, "\n\t\"%s", stringcvt(r->value)); - break; - } - return; -} - -static void -dump_typeinfo(const struct section *s, const struct reg *r) -{ - struct reg *reg; - TAILQ_FOREACH(reg, &rh, link) { - if (reg->section != s) - continue; - if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey)) - continue; - if (reg->key == NULL) - continue; - if (strcasecmp(reg->key, "type")) - continue; - if (strcasecmp(reg->value, "dword") == 0 || - strcasecmp(reg->value, "int") == 0) - dump_dwordreg(s, r); - if (strcasecmp(reg->value, "enum") == 0) - dump_enumreg(s, r); - if (strcasecmp(reg->value, "edit") == 0) - dump_editreg(s, r); - } - return; -} - -static void -dump_paramreg(const struct section *s, const struct reg *r, int devidx) -{ - const char *keyname; - - keyname = r->subkey + strlen("Ndi\\params\\"); - fprintf(ofp, "\n\t{ \"%s\",", keyname); - dump_paramdesc(s, r); - dump_typeinfo(s, r); - fprintf(ofp, "\","); - dump_defaultinfo(s, r, devidx); - - return; -} - -static void -dump_regvals(void) -{ - struct assign *manf, *dev; - struct section *sec; - struct assign *assign; - char sname[256]; - int found = 0, i, is_winxp = 0, is_winnt = 0, devidx = 0; - - /* Find signature to check for special case of WinNT. */ - assign = find_assign("version", "signature"); - if (strcasecmp(assign->vals[0], "$windows nt$") == 0) - is_winnt++; - - /* Emit start of block */ - fprintf (ofp, "ndis_cfg ndis_regvals[] = {"); - - /* Find manufacturer name */ - manf = find_assign("Manufacturer", NULL); - -nextmanf: - - /* Find manufacturer section */ - if (manf->vals[1] != NULL && - (strcasecmp(manf->vals[1], "NT.5.1") == 0 || - strcasecmp(manf->vals[1], "NTx86") == 0 || - strcasecmp(manf->vals[1], "NTx86.5.1") == 0 || - strcasecmp(manf->vals[1], "NTamd64") == 0)) { - is_winxp++; - /* Handle Windows XP INF files. */ - snprintf(sname, sizeof(sname), "%s.%s", - manf->vals[0], manf->vals[1]); - sec = find_section(sname); - } else - sec = find_section(manf->vals[0]); - -retry: - - TAILQ_FOREACH(assign, &ah, link) { - if (assign->section == sec) { - found++; - /* - * Find all the AddReg sections. - * Look for section names with .NT, unless - * this is a WinXP .INF file. - */ - - if (is_winxp) { - sprintf(sname, "%s.NTx86", assign->vals[0]); - dev = find_assign(sname, "AddReg"); - if (dev == NULL) { - sprintf(sname, "%s.NT", - assign->vals[0]); - dev = find_assign(sname, "AddReg"); - } - if (dev == NULL) - dev = find_assign(assign->vals[0], - "AddReg"); - } else { - sprintf(sname, "%s.NT", assign->vals[0]); - dev = find_assign(sname, "AddReg"); - if (dev == NULL && is_winnt) - dev = find_assign(assign->vals[0], - "AddReg"); - } - /* Section not found. */ - if (dev == NULL) - continue; - for (i = 0; i < W_MAX; i++) { - if (dev->vals[i] != NULL) - dump_addreg(dev->vals[i], devidx); - } - devidx++; - } - } - - if (!found) { - sec = find_section(manf->vals[0]); - is_winxp = 0; - found++; - goto retry; - } - - manf = find_next_assign(manf); - - if (manf != NULL) - goto nextmanf; - - fprintf(ofp, "\n\t{ NULL, NULL, { 0 }, 0 }\n};\n\n"); - - return; -} - -void -assign_add (const char *a) -{ - struct assign *assign; - int i; - - assign = malloc(sizeof(struct assign)); - bzero(assign, sizeof(struct assign)); - assign->section = TAILQ_LAST(&sh, section_head); - assign->key = sstrdup(a); - for (i = 0; i < idx; i++) - assign->vals[(idx - 1) - i] = sstrdup(words[i]); - TAILQ_INSERT_TAIL(&ah, assign, link); - - clear_words(); - return; -} - -void -define_add (const char *d __unused) -{ -#ifdef notdef - fprintf(stderr, "define \"%s\"\n", d); -#endif - return; -} - -static char * -sstrdup(const char *str) -{ - if (str != NULL && strlen(str)) - return (strdup(str)); - return (NULL); -} - -static int -satoi (const char *nptr) -{ - if (nptr != NULL && strlen(nptr)) - return (atoi(nptr)); - return (0); -} - -void -regkey_add (const char *r) -{ - struct reg *reg; - - reg = malloc(sizeof(struct reg)); - bzero(reg, sizeof(struct reg)); - reg->section = TAILQ_LAST(&sh, section_head); - reg->root = sstrdup(r); - reg->subkey = sstrdup(words[3]); - reg->key = sstrdup(words[2]); - reg->flags = satoi(words[1]); - reg->value = sstrdup(words[0]); - TAILQ_INSERT_TAIL(&rh, reg, link); - - free(__DECONST(char *, r)); - clear_words(); - return; -} - -void -push_word (const char *w) -{ - - if (idx == W_MAX) { - fprintf(stderr, "too many words; try bumping W_MAX in inf.h\n"); - exit(1); - } - - if (w && strlen(w)) - words[idx++] = w; - else - words[idx++] = NULL; - return; -} - -void -clear_words (void) -{ - int i; - - for (i = 0; i < idx; i++) { - if (words[i]) { - free(__DECONST(char *, words[i])); - } - } - idx = 0; - bzero(words, sizeof(words)); - return; -} diff --git a/usr.sbin/ndiscvt/inf.h b/usr.sbin/ndiscvt/inf.h deleted file mode 100644 index ba08d674eeac..000000000000 --- a/usr.sbin/ndiscvt/inf.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * $Id: inf.h,v 1.3 2003/11/30 21:58:16 winter Exp $ - * - * $FreeBSD$ - */ - -#define W_MAX 32 - -struct section { - const char * name; - - TAILQ_ENTRY(section) link; -}; -TAILQ_HEAD(section_head, section); - -struct assign { - struct section *section; - - const char * key; - const char * vals[W_MAX]; - - TAILQ_ENTRY(assign) link; -}; -TAILQ_HEAD(assign_head, assign); - -struct reg { - struct section *section; - - const char * root; - const char * subkey; - const char * key; - u_int flags; - const char * value; - - TAILQ_ENTRY(reg) link; -}; -TAILQ_HEAD(reg_head, reg); - -#define FLG_ADDREG_TYPE_SZ 0x00000000 -#define FLG_ADDREG_BINVALUETYPE 0x00000001 -#define FLG_ADDREG_NOCLOBBER 0x00000002 -#define FLG_ADDREG_DELVAL 0x00000004 -#define FLG_ADDREG_APPEND 0x00000008 -#define FLG_ADDREG_KEYONLY 0x00000010 -#define FLG_ADDREG_OVERWRITEONLY 0x00000020 -#define FLG_ADDREG_64BITKEY 0x00001000 -#define FLG_ADDREG_KEYONLY_COMMON 0x00002000 -#define FLG_ADDREG_32BITKEY 0x00004000 -#define FLG_ADDREG_TYPE_MULTI_SZ 0x00010000 -#define FLG_ADDREG_TYPE_EXPAND_SZ 0x00020000 -#define FLG_ADDREG_TYPE_DWORD 0x00010001 -#define FLG_ADDREG_TYPE_NONE 0x00020001 - -extern void section_add (const char *); -extern void assign_add (const char *); -extern void define_add (const char *); -extern void regkey_add (const char *); - -extern void push_word (const char *); -extern void clear_words (void); -extern int inf_parse (FILE *, FILE *); diff --git a/usr.sbin/ndiscvt/ndiscvt.8 b/usr.sbin/ndiscvt/ndiscvt.8 deleted file mode 100644 index f4974958e005..000000000000 --- a/usr.sbin/ndiscvt/ndiscvt.8 +++ /dev/null @@ -1,283 +0,0 @@ -.\" Copyright (c) 2003 -.\" Bill Paul All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by Bill Paul. -.\" 4. Neither the name of the author nor the names of any co-contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD -.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -.\" THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd December 10, 2003 -.Dt NDISCVT 8 -.Os -.Sh NAME -.Nm ndiscvt -.Nd convert -.Tn Windows\[rg] -NDIS drivers for use with FreeBSD -.Sh SYNOPSIS -.Nm -.Op Fl O -.Op Fl i Ar inffile -.Fl s Ar sysfile -.Op Fl n Ar devname -.Op Fl o Ar outfile -.Nm -.Op Fl f Ar firmfile -.Sh DESCRIPTION -The -.Nm -utility transforms a -.Tn Windows\[rg] -NDIS driver into a data file which -is used to build an -.Xr ndis 4 -compatibility driver module. -.Tn Windows\[rg] -drivers consist of two main parts: a -.Pa .SYS -file, which contains the actual driver executable code, -and an -.Pa .INF -file, which provides the -.Tn Windows\[rg] -installer with device -identifier information and a list of driver-specific registry keys. -The -.Nm -utility can convert these files into a header file that is compiled -into -.Pa if_ndis.c -to create an object code module that can be linked into -the -.Fx -kernel. -.Pp -The -.Pa .INF -file is typically required since only it contains device -identification data such as PCI vendor and device IDs or PCMCIA -identifier strings. -The -.Pa .INF -file may be optionally omitted however, -in which case the -.Nm -utility will only perform the conversion of the -.Pa .SYS -file. -This is useful for debugging purposes only. -.Sh OPTIONS -The options are as follows: -.Bl -tag -width indent -.It Fl i Ar inffile -Open and parse the specified -.Pa .INF -file when performing conversion. -The -.Nm -utility will parse this file and emit a device identification -structure and registry key configuration structures which will be -used by the -.Xr ndis 4 -driver and -.Xr ndisapi 9 -kernel subsystem. -If this is omitted, -.Nm -will emit a dummy configuration structure only. -.It Fl s Ar sysfile -Open and parse the specified -.Pa .SYS -file. -This file must contain a -.Tn Windows\[rg] -driver image. -The -.Nm -utility will perform some manipulation of the sections within the -executable file to make runtime linking within the kernel a little -easier and then convert the image into a data array. -.It Fl n Ar devname -Specify an alternate name for the network device/interface which will -be created when the driver is instantiated. -If you need to load more -than one NDIS driver into your system (i.e., if you have two different -network cards in your system which require NDIS driver support), each -module you create must have a unique name. -Device can not be larger than -.Dv IFNAMSIZ . -If no name is specified, the driver will use the -default a default name -.Pq Dq Li ndis . -.It Fl o Ar outfile -Specify the output file in which to place the resulting data. -This can be any file pathname. -If -.Ar outfile -is a single dash -.Pq Sq Fl , -the data will be written to the standard output. -The -.Pa if_ndis.c -module expects to find the driver data in a file called -.Pa ndis_driver_data.h , -so it is recommended that this name be used. -.It Fl O -Generate both an -.Pa ndis_driver_data.h -file and -an -.Pa ndis_driver.data.o -file. -The latter file will contain a copy of the -.Tn Windows\[rg] -.Pa .SYS -driver image encoded as a -.Fx -ELF object file -(created with -.Xr objcopy 1 ) . -Turning the -.Tn Windows\[rg] -driver image directly into an object code file saves disk space -and compilation time. -.It Fl f Ar firmfile -A few NDIS drivers come with additional files that the core -driver module will load during initialization time. -Typically, -these files contain firmware which the driver will transfer to -the device in order to make it fully operational. -In -.Tn Windows\[rg] , -these files are usually just copied into one of the system -directories along with the driver itself. -.Pp -In -.Fx -there are two mechanism for loading these files. -If the driver -is built as a loadable kernel module which is loaded after the -kernel has finished booting -(and after the root file system has -been mounted), -the extra files can simply be copied to the -.Pa /compat/ndis -directory, and they will be loaded into the kernel on demand when the -driver needs them. -.Pp -If however the driver is required to bootstrap the system -(i.e., if -the NDIS-based network interface is to be used for diskless/PXE -booting), -the files need to be pre-loaded by the bootstrap -loader in order to be accessible, since the driver will need them -before the root file system has been mounted. -However, the bootstrap -loader is only able to load files that are shared -.Fx -binary objects. -.Pp -The -.Fl f -flag can be used to convert an arbitrary file -.Ar firmfile -into shared object format -(the actual conversion is done using -the -.Xr objcopy 1 -and -.Xr ld 1 -commands). -The resulting files can then be copied to the -.Pa /boot/kernel -directory, and can be pre-loaded directly from the boot loader -prompt, or automatically by editing the -.Xr loader.conf 5 -file. -If desired, the files can also be loaded into memory -at runtime using the -.Xr kldload 8 -command. -.Pp -When an NDIS driver tries to open an external file, the -.Xr ndisapi 9 -code will first search for a loaded kernel module that matches the -name specified in the open request, and if that fails, it will then -try to open the file from the -.Pa /compat/ndis -directory as well. -Note that during kernel bootstrap, the ability -to open files from -.Pa /compat/ndis -is disabled: only the module search will be performed. -.Pp -When using the -.Fl f -flag, -.Nm -will generate both a relocatable object file -(with a -.Pa .o -extension) -and a shared object file -(with a -.Pa .ko -extension). -The shared object is the one that should be placed in -the -.Pa /boot/kernel -directory. -The relocatable object file is useful if the user wishes -to create a completely static kernel image: the object file can be -linked into the kernel directly along with the driver itself. -Some -editing of the kernel configuration files will be necessary in order -to have the extra object included in the build. -.El -.Sh SEE ALSO -.Xr ld 1 , -.Xr objcopy 1 , -.Xr ndis 4 , -.Xr kldload 8 -.Sh HISTORY -The -.Nm -utility first appeared in -.Fx 5.3 . -.Sh AUTHORS -.An -nosplit -The -.Nm -utility was written by -.An Bill Paul Aq Mt wpaul@windriver.com . -The -.Xr lex 1 -and -.Xr yacc 1 -.Pa INF -file parser was written by -.An Matthew Dodd Aq Mt mdodd@FreeBSD.org . diff --git a/usr.sbin/ndiscvt/ndiscvt.c b/usr.sbin/ndiscvt/ndiscvt.c deleted file mode 100644 index 1b7660700786..000000000000 --- a/usr.sbin/ndiscvt/ndiscvt.c +++ /dev/null @@ -1,436 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2003 - * Bill Paul . 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "inf.h" - -static int insert_padding(void **, int *); -extern const char *__progname; - -/* - * Sections within Windows PE files are defined using virtual - * and physical address offsets and virtual and physical sizes. - * The physical values define how the section data is stored in - * the executable file while the virtual values describe how the - * sections will look once loaded into memory. It happens that - * the linker in the Microsoft(r) DDK will tend to generate - * binaries where the virtual and physical values are identical, - * which means in most cases we can just transfer the file - * directly to memory without any fixups. This is not always - * the case though, so we have to be prepared to handle files - * where the in-memory section layout differs from the disk file - * section layout. - * - * There are two kinds of variations that can occur: the relative - * virtual address of the section might be different from the - * physical file offset, and the virtual section size might be - * different from the physical size (for example, the physical - * size of the .data section might be 1024 bytes, but the virtual - * size might be 1384 bytes, indicating that the data section should - * actually use up 1384 bytes in RAM and be padded with zeros). What we - * do is read the original file into memory and then make an in-memory - * copy with all of the sections relocated, re-sized and zero padded - * according to the virtual values specified in the section headers. - * We then emit the fixed up image file for use by the if_ndis driver. - * This way, we don't have to do the fixups inside the kernel. - */ - -#define ROUND_DOWN(n, align) (((uintptr_t)n) & ~((align) - 1l)) -#define ROUND_UP(n, align) ROUND_DOWN(((uintptr_t)n) + (align) - 1l, \ - (align)) - -#define SET_HDRS(x) \ - dos_hdr = (image_dos_header *)x; \ - nt_hdr = (image_nt_header *)(x + dos_hdr->idh_lfanew); \ - sect_hdr = IMAGE_FIRST_SECTION(nt_hdr); - -static int -insert_padding(void **imgbase, int *imglen) -{ - image_section_header *sect_hdr; - image_dos_header *dos_hdr; - image_nt_header *nt_hdr; - image_optional_header opt_hdr; - int i = 0, sections, curlen = 0; - int offaccum = 0, oldraddr, oldrlen; - uint8_t *newimg, *tmp; - - newimg = malloc(*imglen); - - if (newimg == NULL) - return(ENOMEM); - - bcopy(*imgbase, newimg, *imglen); - curlen = *imglen; - - if (pe_get_optional_header((vm_offset_t)newimg, &opt_hdr)) - return(0); - - sections = pe_numsections((vm_offset_t)newimg); - - SET_HDRS(newimg); - - for (i = 0; i < sections; i++) { - oldraddr = sect_hdr->ish_rawdataaddr; - oldrlen = sect_hdr->ish_rawdatasize; - sect_hdr->ish_rawdataaddr = sect_hdr->ish_vaddr; - offaccum += ROUND_UP(sect_hdr->ish_vaddr - oldraddr, - opt_hdr.ioh_filealign); - offaccum += - ROUND_UP(sect_hdr->ish_misc.ish_vsize, - opt_hdr.ioh_filealign) - - ROUND_UP(sect_hdr->ish_rawdatasize, - opt_hdr.ioh_filealign); - tmp = realloc(newimg, *imglen + offaccum); - if (tmp == NULL) { - free(newimg); - return(ENOMEM); - } - newimg = tmp; - SET_HDRS(newimg); - sect_hdr += i; - bzero(newimg + sect_hdr->ish_rawdataaddr, - ROUND_UP(sect_hdr->ish_misc.ish_vsize, - opt_hdr.ioh_filealign)); - bcopy((uint8_t *)(*imgbase) + oldraddr, - newimg + sect_hdr->ish_rawdataaddr, oldrlen); - sect_hdr++; - } - - free(*imgbase); - - *imgbase = newimg; - *imglen += offaccum; - - return(0); -} - -static void -usage(void) -{ - fprintf(stderr, "Usage: %s [-O] [-i ] -s " - "[-n devname] [-o outfile]\n", __progname); - fprintf(stderr, " %s -f \n", __progname); - - exit(1); -} - -static void -bincvt(char *sysfile, char *outfile, void *img, int fsize) -{ - char *ptr; - char tname[] = "/tmp/ndiscvt.XXXXXX"; - char sysbuf[1024]; - FILE *binfp; - - mkstemp(tname); - - binfp = fopen(tname, "a+"); - if (binfp == NULL) - err(1, "opening %s failed", tname); - - if (fwrite(img, fsize, 1, binfp) != 1) - err(1, "failed to output binary image"); - - fclose(binfp); - - outfile = strdup(basename(outfile)); - if (strchr(outfile, '.')) - *strchr(outfile, '.') = '\0'; - - snprintf(sysbuf, sizeof(sysbuf), -#ifdef __i386__ - "objcopy -I binary -O elf32-i386-freebsd -B i386 %s %s.o\n", -#endif -#ifdef __amd64__ - "objcopy -I binary -O elf64-x86-64-freebsd -B i386 %s %s.o\n", -#endif - tname, outfile); - printf("%s", sysbuf); - system(sysbuf); - unlink(tname); - - ptr = tname; - while (*ptr) { - if (*ptr == '/' || *ptr == '.') - *ptr = '_'; - ptr++; - } - - snprintf(sysbuf, sizeof(sysbuf), - "objcopy --redefine-sym _binary_%s_start=ndis_%s_drv_data_start " - "--strip-symbol _binary_%s_size " - "--redefine-sym _binary_%s_end=ndis_%s_drv_data_end %s.o %s.o\n", - tname, sysfile, tname, tname, sysfile, outfile, outfile); - printf("%s", sysbuf); - system(sysbuf); - free(outfile); - - return; -} - -static void -firmcvt(char *firmfile) -{ - char *basefile, *outfile, *ptr; - char sysbuf[1024]; - - outfile = strdup(basename(firmfile)); - basefile = strdup(outfile); - - snprintf(sysbuf, sizeof(sysbuf), -#ifdef __i386__ - "objcopy -I binary -O elf32-i386-freebsd -B i386 %s %s.o\n", -#endif -#ifdef __amd64__ - "objcopy -I binary -O elf64-x86-64-freebsd -B i386 %s %s.o\n", -#endif - firmfile, outfile); - printf("%s", sysbuf); - system(sysbuf); - - ptr = firmfile; - while (*ptr) { - if (*ptr == '/' || *ptr == '.') - *ptr = '_'; - ptr++; - } - ptr = basefile; - while (*ptr) { - if (*ptr == '/' || *ptr == '.') - *ptr = '_'; - else - *ptr = tolower(*ptr); - ptr++; - } - - snprintf(sysbuf, sizeof(sysbuf), - "objcopy --redefine-sym _binary_%s_start=%s_start " - "--strip-symbol _binary_%s_size " - "--redefine-sym _binary_%s_end=%s_end %s.o %s.o\n", - firmfile, basefile, firmfile, firmfile, - basefile, outfile, outfile); - ptr = sysbuf; - printf("%s", sysbuf); - system(sysbuf); - - snprintf(sysbuf, sizeof(sysbuf), - "ld -Bshareable -d -warn-common -o %s.ko %s.o\n", - outfile, outfile); - printf("%s", sysbuf); - system(sysbuf); - - free(basefile); - - exit(0); -} - -int -main(int argc, char *argv[]) -{ - FILE *fp, *outfp; - int i, bin = 0; - void *img; - int n, fsize, cnt; - unsigned char *ptr; - char *inffile = NULL, *sysfile = NULL; - char *outfile = NULL, *firmfile = NULL; - char *dname = NULL; - int ch; - - while((ch = getopt(argc, argv, "i:s:o:n:f:O")) != -1) { - switch(ch) { - case 'f': - firmfile = optarg; - break; - case 'i': - inffile = optarg; - break; - case 's': - sysfile = optarg; - break; - case 'o': - outfile = optarg; - break; - case 'n': - dname = optarg; - break; - case 'O': - bin = 1; - break; - default: - usage(); - break; - } - } - - if (firmfile != NULL) - firmcvt(firmfile); - - if (sysfile == NULL) - usage(); - - /* Open the .SYS file and load it into memory */ - fp = fopen(sysfile, "r"); - if (fp == NULL) - err(1, "opening .SYS file '%s' failed", sysfile); - fseek (fp, 0L, SEEK_END); - fsize = ftell (fp); - rewind (fp); - img = calloc(fsize, 1); - n = fread (img, fsize, 1, fp); - if (n == 0) - err(1, "reading .SYS file '%s' failed", sysfile); - - fclose(fp); - - if (insert_padding(&img, &fsize)) { - fprintf(stderr, "section relocation failed\n"); - exit(1); - } - - if (outfile == NULL || strcmp(outfile, "-") == 0) - outfp = stdout; - else { - outfp = fopen(outfile, "w"); - if (outfp == NULL) - err(1, "opening output file '%s' failed", outfile); - } - - fprintf(outfp, "\n/*\n"); - fprintf(outfp, " * Generated from %s and %s (%d bytes)\n", - inffile == NULL ? "" : inffile, sysfile, fsize); - fprintf(outfp, " */\n\n"); - - if (dname != NULL) { - if (strlen(dname) > IFNAMSIZ) - err(1, "selected device name '%s' is " - "too long (max chars: %d)", dname, IFNAMSIZ); - fprintf (outfp, "#define NDIS_DEVNAME \"%s\"\n", dname); - fprintf (outfp, "#define NDIS_MODNAME %s\n\n", dname); - } - - if (inffile == NULL) { - fprintf (outfp, "#ifdef NDIS_REGVALS\n"); - fprintf (outfp, "ndis_cfg ndis_regvals[] = {\n"); - fprintf (outfp, "\t{ NULL, NULL, { 0 }, 0 }\n"); - fprintf (outfp, "#endif /* NDIS_REGVALS */\n"); - - fprintf (outfp, "};\n\n"); - } else { - fp = fopen(inffile, "r"); - if (fp == NULL) - err(1, "opening .INF file '%s' failed", inffile); - - - if (inf_parse(fp, outfp) != 0) - errx(1, "creating .INF file - no entries created, are you using the correct files?"); - fclose(fp); - } - - fprintf(outfp, "\n#ifdef NDIS_IMAGE\n"); - - if (bin) { - sysfile = strdup(basename(sysfile)); - ptr = (unsigned char *)sysfile; - while (*ptr) { - if (*ptr == '.') - *ptr = '_'; - ptr++; - } - fprintf(outfp, - "\nextern unsigned char ndis_%s_drv_data_start[];\n", - sysfile); - fprintf(outfp, "static unsigned char *drv_data = " - "ndis_%s_drv_data_start;\n\n", sysfile); - bincvt(sysfile, outfile, img, fsize); - goto done; - } - - - fprintf(outfp, "\nextern unsigned char drv_data[];\n\n"); - - fprintf(outfp, "__asm__(\".data\");\n"); - fprintf(outfp, "__asm__(\".globl drv_data\");\n"); - fprintf(outfp, "__asm__(\".type drv_data, @object\");\n"); - fprintf(outfp, "__asm__(\".size drv_data, %d\");\n", fsize); - fprintf(outfp, "__asm__(\"drv_data:\");\n"); - - ptr = img; - cnt = 0; - while(cnt < fsize) { - fprintf (outfp, "__asm__(\".byte "); - for (i = 0; i < 10; i++) { - cnt++; - if (cnt == fsize) { - fprintf(outfp, "0x%.2X\");\n", ptr[i]); - goto done; - } else { - if (i == 9) - fprintf(outfp, "0x%.2X\");\n", ptr[i]); - else - fprintf(outfp, "0x%.2X, ", ptr[i]); - } - } - ptr += 10; - } - -done: - - fprintf(outfp, "#endif /* NDIS_IMAGE */\n"); - - if (fp != NULL) - fclose(fp); - fclose(outfp); - free(img); - exit(0); -} diff --git a/usr.sbin/ndiscvt/ndisgen.8 b/usr.sbin/ndiscvt/ndisgen.8 deleted file mode 100644 index 2fb4f401596e..000000000000 --- a/usr.sbin/ndiscvt/ndisgen.8 +++ /dev/null @@ -1,86 +0,0 @@ -.\" Copyright (c) 2005 -.\" Bill Paul All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by Bill Paul. -.\" 4. Neither the name of the author nor the names of any co-contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD -.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -.\" THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd April 24, 2005 -.Dt NDISGEN 8 -.Os -.Sh NAME -.Nm ndisgen -.Nd generate a FreeBSD driver module from a -.Tn Windows\[rg] -NDIS driver distribution -.Sh SYNOPSIS -.Nm -.Op Ar /path/to/INF /path/to/SYS -.Sh DESCRIPTION -The -.Nm -script uses the -.Xr ndiscvt 8 -utility and other tools to generate a -.Fx -loadable driver module -and a static ELF object module from a -.Tn Windows\[rg] -NDIS driver, for use with the -.Xr ndis 4 -compatibility module. -.Pp -The -.Nm -script is interactive and contains its own help section. -Unless the paths to both files are supplied on the command line, -the script will prompt the user for the -.Pa .INF -and -.Pa .SYS -files needed to generate the -.Fx -driver module. -The script will also prompt for -any firmware or other external files needed. -.Sh SEE ALSO -.Xr ld 1 , -.Xr objcopy 1 , -.Xr ndis 4 , -.Xr kldload 8 , -.Xr ndiscvt 8 -.Sh HISTORY -The -.Nm -utility first appeared in -.Fx 6.0 . -.Sh AUTHORS -The -.Nm -utility was written by -.An Bill Paul Aq Mt wpaul@windriver.com . diff --git a/usr.sbin/ndiscvt/ndisgen.sh b/usr.sbin/ndiscvt/ndisgen.sh deleted file mode 100644 index c5a0dbd4fc46..000000000000 --- a/usr.sbin/ndiscvt/ndisgen.sh +++ /dev/null @@ -1,556 +0,0 @@ -#!/bin/sh -# -# SPDX-License-Identifier: BSD-4-Clause -# -# Copyright (c) 2005 -# Bill Paul . All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. All advertising materials mentioning features or use of this software -# must display the following acknowledgement: -# This product includes software developed by Bill Paul. -# 4. Neither the name of the author nor the names of any co-contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -# THE POSSIBILITY OF SUCH DAMAGE. -# -# $FreeBSD$ -# - -header () { -clear -echo " ==================================================================" -echo " ------------------ Windows(r) driver converter -------------------" -echo " ==================================================================" -echo "" -} - -mainmenu() { -header -echo " This script is designed to guide you through the process" -echo " of converting a Windows(r) binary driver module and .INF" -echo " specification file into a FreeBSD ELF kernel module for use" -echo " with the NDIS compatibility system." -echo "" -echo " The following options are available:" -echo "" -echo " 1] Learn about the NDIS compatibility system" -echo " 2] Convert individual firmware files" -echo " 3] Convert driver" -echo " 4] Exit" -echo "" -echo -n " Enter your selection here and press return: " -read KEYPRESS -return -} - - -help1 () { -header -echo " General information" -echo "" -echo " The NDIS compatibility system is designed to let you use Windows(r)" -echo " binary drivers for networking devices with FreeBSD, in cases where" -echo " a native FreeBSD driver is not available due to hardware manufacturer" -echo " oversight or stupidity. NDIS stands for Network Driver Interface" -echo " Standard, and refers to the programming model used to write Windows(r)" -echo " network drivers. (These are often called \"NDIS miniport\" drivers.)" -echo "" -echo " In order to use your network device in NDIS compatibility mode," -echo " you need the Windows(r) driver that goes with it. Also, the driver" -echo " must be compiled for the same architecture as the release of FreeBSD" -echo " you have installed. At this time, the i386 and amd64 architectures" -echo " are both supported. Note that you cannot use a Windows/i386 driver" -echo " with FreeBSD/amd64: you must obtain a Windows/amd64 driver." -echo "" -echo -n " Press return to continue... " -read KEYPRESS -return -} - -help2() { -header -echo " Where to get drivers" -echo "" -echo " If you purchased your network card separately from your computer," -echo " there should have been a driver distribution CD included with the" -echo " card which contains Windows(r) drivers. The NDIS compatibility" -echo " system is designed to emulate the NDIS API of a couple of different" -echo " Windows(r) releases, however it works best with drivers designed" -echo " for NDIS 5.0 or later. Drivers distributed for Windows 2000 should" -echo " work; however, for best results you should use a driver designed" -echo " for Windows XP or Windows Server 2003." -echo "" -echo " If your card was supplied with your computer, or is a built-in device," -echo " drivers may have been included on a special driver bundle CD shipped" -echo " with the computer." -echo "" -echo " If you don't have a driver CD, you should be able to find a driver" -echo " kit on the card or computer vendor's web site." -echo "" -echo -n " Press return to continue... " -read KEYPRESS -return -} - -help3 () { -header -echo " What files do I need?" -echo "" -echo " In most cases, you will need only two files: a .INF file and a .SYS" -echo " file. The .INF file is a text file used by the Windows(r) installer to" -echo " perform the driver installation. It contains information that tells" -echo " the installer what devices the driver supports and what registry keys" -echo " should be created to control driver configuration. The .SYS file" -echo " is the actual driver executable code in Windows(r) Portable Executable" -echo " (PE) format. Note that sometimes the .INF file is supplied in Unicode" -echo " format. Unicode .INF files must be converted to ASCII form with the" -echo " iconv(1) utility before this installer script can use them." -echo " Occasionally, a driver may require firmware or register setup" -echo " files that are external to the main .SYS file. These are provided" -echo " on the same CD with the driver itself, and sometimes have a .BIN" -echo " extension, though they can be named almost anything. You will need" -echo " these additional files to make your device work with the NDIS" -echo " compatibility system as well." -echo "" -echo -n " Press return to continue... " -read KEYPRESS -return -} - -help4 () { -header -echo " How does it all work?" -echo "" -echo " The installer script uses the ndiscvt(1) utility to convert the .INF," -echo " .SYS and optional firmware files into a FreeBSD kernel loadable module" -echo " (.ko) file. This module can be loaded via the kldload(8) utility or" -echo " loaded automatically via the /boot/loader.conf file. The ndiscvt(1)" -echo " utility extracts the device ID information and registry key data" -echo " from the .INF file and converts it into a C header file. It also uses" -echo " the objcopy(1) utility to convert the .SYS file and optional firmware" -echo " files into ELF objects. The header file is compiled into a small C" -echo " stub file which contains a small amount of code to interface with" -echo " the FreeBSD module system. This stub is linked together with the" -echo " converted ELF objects to form a FreeBSD kernel module. A static ELF" -echo " object (.o) file is also created. This file can be linked into a" -echo " static kernel image for those who want/need a fully linked kernel" -echo " image (possibly for embedded bootstrap purposes, or just plain old" -echo " experimentation)." -echo "" -echo -n " Press return to continue... " -read KEYPRESS -return -} - -help5 () { -header -echo " Prerequisites" -echo "" -echo " Converting a driver requires the following utilities:" -echo "" -echo " - The FreeBSD C compiler, cc(1) (part of the base install)." -echo " - The FreeBSD linker, ld(1) (part of the base install)." -echo " - The objcopy(1) utility (part of the base install)." -echo " - The ndiscvt(1) utility (part of the base install)." -echo "" -echo " If you happen to end up with a .INF file that's in Unicode format," -echo " then you'll also need:" -echo "" -echo " - The iconv(1) utility." -echo "" -echo " If you have installed the X Window system or some sort of desktop" -echo " environment, then iconv(1) should already be present. If not, you" -echo " will need to install the libiconv package or port." -echo "" -echo -n " Press return to continue... " -read KEYPRESS -return -} - -infconv () { -header -echo " INF file validation" - -if [ -z "$INFPATH" ]; then - echo "" - echo "" - echo " A .INF file is most often provided as an ASCII file, however" - echo " files with multilanguage support are provided in Unicode format." - echo " Please type in the path to your .INF file now." - echo "" - echo -n " > " - read INFPATH -fi - -if [ ${INFPATH} ] && [ -e ${INFPATH} ]; then - INFTYPE=`${EGREP} -i -c "Signature|.S.i.g.n.a.t.u.r.e" ${INFPATH}` - if [ ${INFTYPE} -le 0 ]; then - echo "" - echo " I don't recognize this file format. It may not be a valid .INF file." - echo "" - echo -n " Press enter to try again, or ^C to quit. " - read KEYPRESS - INFPATH="" - return - fi - - INFTYPE=`${EGREP} -i -c "Class.*=.*Net" ${INFPATH}` - if [ ${INFTYPE} -gt 0 ]; then - echo "" - echo " This .INF file appears to be ASCII." - echo "" - echo -n " Press return to continue... " - read KEYPRESS - return - fi - - INFTYPE=`${EGREP} -i -c ".C.l.a.s.s.*=.*N.e.t" ${INFPATH}` - if [ ${INFTYPE} -gt 0 ]; then - echo "" - echo " This .INF file appears to be Unicode." - if [ -e ${ICONVPATH} ]; then - echo " Trying to convert to ASCII..." - ${ICONVPATH} -f utf-16 -t utf-8 ${INFPATH} > ${INFFILE} - INFPATH=${INFFILE} - echo " Done." - echo "" - echo -n " Press return to continue... " - read KEYPRESS - else - echo " The iconv(1) utility does not appear to be installed." - echo " Please install this utility or convert the .INF file" - echo " to ASCII and run this utility again." - echo "" - exit - fi - return - fi - - echo "" - echo " I don't recognize this file format. It may not be a valid .INF file." - echo "" - echo -n " Press enter to try again, or ^C to quit. " - read KEYPRESS - INFPATH="" -else - echo "" - echo " The file '${INFPATH}' was not found." - echo "" - echo -n " Press enter to try again, or ^C to quit. " - read KEYPRESS - INFPATH="" -fi -return -} - -sysconv() { -header -echo " Driver file validation" - -if [ ! -r "$SYSPATH" ]; then - echo "" - echo "" - echo " Now you need to specify the name of the Windows(r) driver .SYS" - echo " file for your device. Note that if you are running FreeBSD/amd64," - echo " then you must provide a driver that has been compiled for the" - echo " 64-bit Windows(r) platform. If a 64-bit driver is not available" - echo " for your device, you must install FreeBSD/i386 and use the" - echo " 32-bit driver instead." - echo "" - echo " Please type in the path to the Windows(r) driver .SYS file now." - echo "" - echo -n " > " - read SYSPATH -fi - -if [ ${SYSPATH} ] && [ -e ${SYSPATH} ]; then - SYSTYPE=`${FILE} ${SYSPATH}` - - case ${SYSTYPE} in - *Windows*) - echo "" - echo " This .SYS file appears to be in Windows(r) PE format." - echo "" - echo -n " Press return to continue... " - read KEYPRESS - SYSBASE=`${BASENAME} ${SYSPATH} | ${TR} '.' '_'` - ;; - *) - echo "" - echo " I don't recognize this file format. It may not be a valid .SYS file." - echo "" - - echo -n " Press enter to try again, or ^C to quit. " - read KEYPRESS - SYSPATH="" - ;; - esac -else - echo "" - echo " The file '${SYSPATH}' was not found." - echo "" - echo -n " Press enter to try again, or ^C to quit. " - read KEYPRESS - SYSPATH="" -fi -return -} - -ndiscvt() { -header -echo " Driver file conversion" -echo "" -echo " The script will now try to convert the .INF and .SYS files" -echo " using the ndiscvt(1) utility. This utility can handle most" -echo " .INF files; however, occasionally it can fail to parse some files" -echo " due to subtle syntax issues: the .INF syntax is very complex," -echo " and the Windows(r) parser will sometimes allow files with small" -echo " syntax errors to be processed correctly which ndiscvt(1) will" -echo " not. If the conversion fails, you may have to edit the .INF" -echo " file by hand to remove the offending lines." -echo "" -echo -n " Press enter to try converting the files now: " -read KEYPRESS -if ! ${NDISCVT} -i ${INFPATH} -s ${SYSPATH} -O -o ${DNAME}.h > /dev/null; then - echo "CONVERSION FAILED" - exit -else - echo "" - echo " Conversion was successful." - echo "" - echo -n " Press enter to continue... " - read KEYPRESS -fi -return -} - -firmcvt() { - while : ; do -header -echo " Firmware file conversion" -echo "" -echo " If your driver uses additional firmware files, please list them" -echo " below. When you're finished, just press enter to continue. (If your" -echo " driver doesn't need any extra firmware files, just press enter" -echo " to move to the next step.)" -echo "" - echo -n " > " - read FIRMPATH - - if [ ${FIRMPATH} ]; then - if [ ! -e ${FIRMPATH} ]; then - echo "" - echo " The file '${FIRMPATH}' was not found" - echo "" - echo -n " Press enter to try again, or ^C to quit. " - read KEYPRESS - continue - fi - if ! ${NDISCVT} -f ${FIRMPATH} > /dev/null; then - echo "" - echo "CONVERSION FAILED" - else - echo "" - echo " Conversion was successful." - echo "" - FRMBASE=`${BASENAME} ${FIRMPATH}` - FRMBASE="${FRMBASE}.o" - FRMLIST="${FRMLIST} ${FRMBASE}" - fi - echo -n " Press enter to continue... " - read KEYPRESS - else - break - fi - done - -header -echo "" -echo " List of files converted firmware files:" -echo "" -for i in ${FRMLIST} -do - echo " "$i -done -echo "" -echo -n " Press enter to continue... " -read KEYPRESS -return -} - -drvgen () { -header -echo " Kernel module generation" -echo "" -echo "" -echo " The script will now try to generate the kernel driver module." -echo " This is the last step. Once this module is generated, you should" -echo " be able to load it just like any other FreeBSD driver module." -echo "" -echo " Press enter to compile the stub module and generate the driver" -echo -n " module now: " -read KEYPRESS -echo "" -echo -n " Generating Makefile... " -echo ".PATH: ${PWD} ${STUBPATH}" > ${MAKEFILE} -echo "KMOD= ${SYSBASE}" >> ${MAKEFILE} -echo "SRCS+= ${STUBFILE} ${DNAME}.h bus_if.h device_if.h" >> ${MAKEFILE} -echo "OBJS+=${FRMLIST} ${DNAME}.o" >> ${MAKEFILE} -echo "CFLAGS+= \\" >> ${MAKEFILE} -echo " -DDRV_DATA_START=ndis_${SYSBASE}_drv_data_start \\" >> ${MAKEFILE} -echo " -DDRV_NAME=ndis_${SYSBASE} \\" >> ${MAKEFILE} -echo " -DDRV_DATA_END=ndis_${SYSBASE}_drv_data_end" >> ${MAKEFILE} -echo "CLEANFILES+= \\" >> ${MAKEFILE} -echo " ${INFFILE} \\" >> ${MAKEFILE} -echo " ${DNAME}.h \\" >> ${MAKEFILE} -echo " ${DNAME}.o" >> ${MAKEFILE} -echo ".include " >> ${MAKEFILE} -if [ -f ${MAKEFILE} ]; then - echo "done." -else - echo "generating Makefile failed. Exiting." - echo "" - exit -fi -echo -n " Building kernel module... " -echo "" > bus_if.h -echo "" > device_if.h -if ! ${MAKE} -f ${MAKEFILE} all > /dev/null; then - echo "build failed. Exiting." - echo "" - exit -else - if [ -f ${SYSBASE}.ko ]; then - ${MV} ${SYSBASE}.ko ${SYSBASE}.kmod - echo "done." - else - echo "build failed. Exiting." - echo "" - exit - fi -fi -echo -n " Cleaning up... " -if ! ${MAKE} -f ${MAKEFILE} clean cleandepend > /dev/null; then - echo "cleanup failed. Exiting." - echo "" - exit -else - echo "done." -fi -${RM} ${MAKEFILE} -${MV} ${SYSBASE}.kmod ${SYSBASE}.ko -echo "" -echo " The file ${SYSBASE}.ko has been successfully generated." -echo " You can kldload this module to get started." -echo "" -echo -n " Press return to exit. " -read KEYPRESS -echo "" -echo "" -return -} - -convert_driver () { - while : ; do - infconv - if [ ${INFPATH} ]; then - break - fi - done - - while : ; do - sysconv - if [ ${SYSPATH} ]; then - break - fi - done - - ndiscvt - firmcvt - drvgen - return -} - -ICONVPATH=/usr/bin/iconv -NDISCVT=/usr/sbin/ndiscvt -STUBPATH=/usr/share/misc -STUBFILE=windrv_stub.c -DNAME=windrv -CP=/bin/cp -MV=/bin/mv -RM=/bin/rm -TR=/usr/bin/tr -FILE=/usr/bin/file -EGREP=/usr/bin/egrep -MAKE=/usr/bin/make -BASENAME=/usr/bin/basename -TOUCH=/usr/bin/touch -MKTEMP=/usr/bin/mktemp - -MAKEFILE=`${MKTEMP} /tmp/Makefile.XXXXXX` -INFFILE=`${MKTEMP} /tmp/ascii_inf.XXXXXX` - -INFPATH="" -FRMLIST="" -SYSPATH="" -SYSBASE="" -FRMBASE="" - -if [ -r "$1" -a -r "$2" ]; then - # Looks like the user supplied .INF and .SYS files on the command line - INFPATH=$1 - SYSPATH=$2 - convert_driver && exit 0 -fi - -while : ; do - mainmenu - case ${KEYPRESS} in - 1) - help1 - help2 - help3 - help4 - help5 - ;; - 2) - firmcvt - ;; - 3) - convert_driver - ;; - 4) - header - echo "" - echo " Be seeing you!" - echo "" - exit - ;; - *) - header - echo "" - echo -n " Sorry, I didn't understand that. Press enter to try again: " - read KEYPRESS - ;; - esac -done -exit diff --git a/usr.sbin/ndiscvt/windrv_stub.c b/usr.sbin/ndiscvt/windrv_stub.c deleted file mode 100644 index 8aaa23835cba..000000000000 --- a/usr.sbin/ndiscvt/windrv_stub.c +++ /dev/null @@ -1,268 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2005 - * Bill Paul . 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include - -#include -#include -#include - -#define NDIS_REGVALS - -struct ndis_cfg { - char *nc_cfgkey; - char *nc_cfgdesc; - char nc_val[256]; - int nc_idx; -}; - -typedef struct ndis_cfg ndis_cfg; - -#include "windrv.h" - -struct ndis_pci_type { - uint16_t ndis_vid; - uint16_t ndis_did; - uint32_t ndis_subsys; - char *ndis_name; -}; - -struct ndis_pccard_type { - const char *ndis_vid; - const char *ndis_did; - char *ndis_name; -}; - -struct ndis_usb_type { - uint16_t ndis_vid; - uint16_t ndis_did; - char *ndis_name; -}; - -#ifdef NDIS_PCI_DEV_TABLE -static struct ndis_pci_type ndis_devs_pci[] = { - NDIS_PCI_DEV_TABLE - { 0, 0, 0, NULL } -}; -#endif - -#ifdef NDIS_PCMCIA_DEV_TABLE -static struct ndis_pccard_type ndis_devs_pccard[] = { - NDIS_PCMCIA_DEV_TABLE - { NULL, NULL, NULL } -}; -#endif - -#ifdef NDIS_USB_DEV_TABLE -static struct ndis_usb_type ndis_devs_usb[] = { - NDIS_USB_DEV_TABLE - { 0, 0, NULL } -}; -#endif - -enum interface_type { - InterfaceTypeUndefined = -1, - Internal, - Isa, - Eisa, - MicroChannel, - TurboChannel, - PCIBus, - VMEBus, - NuBus, - PCMCIABus, - CBus, - MPIBus, - MPSABus, - ProcessorInternal, - InternalPowerBus, - PNPISABus, - PNPBus, - MaximumInterfaceType -}; - -typedef enum interface_type interface_type; - -/* - * XXX - * Ordinarily, device_probe_desc is defined in device_if.h, which - * is created from device_if.m. The problem is, the latter file - * is only available if you have the kernel source code installed, - * and not all users choose to install it. I'd like to let people - * load Windows driver modules with the minimal amount of hassle - * and dependencies. wants both device_if.h and bus_if.h - * to be defined, but it turns out the only thing we really need - * to get this module compiled is device_probe_desc, so we define - * that here, and let the build script create empty copies of - * device_if.h and bus_if.h to make the compiler happy. - */ - -extern struct kobjop_desc device_probe_desc; -typedef int device_probe_t(device_t dev); - -extern int windrv_load(module_t, vm_offset_t, size_t, - interface_type, void *, void *); -extern int windrv_unload(module_t, vm_offset_t, size_t); - -#ifndef DRV_DATA_START -#define DRV_DATA_START UNDEF_START -#endif - -#ifndef DRV_DATA_END -#define DRV_DATA_END UNDEF_END -#endif - -#ifndef DRV_NAME -#define DRV_NAME UNDEF_NAME -#endif - -extern uint8_t DRV_DATA_START; -extern uint8_t DRV_DATA_END; - -/* - * The following is stub code that makes it look as though we want - * to be a child device of all the buses that our supported devices - * might want to attach to. Our probe routine always fails. The - * reason we need this code is so that loading an ELF-ified Windows - * driver module will trigger a bus reprobe. - */ - -#define MODULE_DECL(x) \ - MODULE_DEPEND(x, ndisapi, 1, 1, 1); \ - MODULE_DEPEND(x, ndis, 1, 1, 1) - -MODULE_DECL(DRV_NAME); - -static int windrv_probe(device_t); -static int windrv_modevent(module_t, int, void *); -static int windrv_loaded = 0; - -static device_method_t windrv_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, windrv_probe), - - { 0, 0 } -}; - -static driver_t windrv_driver = { - "windrv_stub", - windrv_methods, - 0 -}; - -static devclass_t windrv_devclass; - -#define DRIVER_DECL(x) \ - DRIVER_MODULE(x, pci, windrv_driver, \ - windrv_devclass, windrv_modevent, NULL); \ - DRIVER_MODULE(x, cardbus, windrv_driver, \ - windrv_devclass, windrv_modevent, NULL); \ - DRIVER_MODULE(x, pccard, windrv_driver, \ - windrv_devclass, windrv_modevent, NULL); \ - DRIVER_MODULE(x, uhub, windrv_driver, \ - windrv_devclass, windrv_modevent, NULL); \ - MODULE_VERSION(x, 1) - -DRIVER_DECL(DRV_NAME); - -static int -windrv_probe(dev) - device_t dev; -{ - return (ENXIO); -} - -static int -windrv_modevent(mod, cmd, arg) - module_t mod; - int cmd; - void *arg; -{ - int drv_data_len; - int error = 0; - vm_offset_t drv_data_start; - vm_offset_t drv_data_end; - - drv_data_start = (vm_offset_t)&DRV_DATA_START; - drv_data_end = (vm_offset_t)&DRV_DATA_END; - - drv_data_len = drv_data_end - drv_data_start; - switch (cmd) { - case MOD_LOAD: - windrv_loaded++; - if (windrv_loaded > 1) - break; -#ifdef NDIS_PCI_DEV_TABLE - windrv_load(mod, drv_data_start, drv_data_len, PCIBus, - ndis_devs_pci, &ndis_regvals); -#endif -#ifdef NDIS_PCMCIA_DEV_TABLE - windrv_load(mod, drv_data_start, drv_data_len, PCMCIABus, - ndis_devs_pccard, &ndis_regvals); -#endif -#ifdef NDIS_USB_DEV_TABLE - windrv_load(mod, drv_data_start, drv_data_len, PNPBus, - ndis_devs_usb, &ndis_regvals); -#endif - break; - case MOD_UNLOAD: - windrv_loaded--; - if (windrv_loaded > 0) - break; -#ifdef NDIS_PCI_DEV_TABLE - windrv_unload(mod, drv_data_start, drv_data_len); -#endif -#ifdef NDIS_PCMCIA_DEV_TABLE - windrv_unload(mod, drv_data_start, drv_data_len); -#endif -#ifdef NDIS_USB_DEV_TABLE - windrv_unload(mod, drv_data_start, drv_data_len); -#endif - break; - case MOD_SHUTDOWN: - break; - default: - error = EINVAL; - break; - } - - return (error); -} diff --git a/usr.sbin/wpa/Makefile b/usr.sbin/wpa/Makefile index ae07ec04f001..451c4c3b17a6 100644 --- a/usr.sbin/wpa/Makefile +++ b/usr.sbin/wpa/Makefile @@ -2,7 +2,6 @@ SUBDIR= wpa_supplicant wpa_cli wpa_passphrase SUBDIR+= hostapd hostapd_cli -SUBDIR+= ndis_events SUBDIR_PARALLEL= .include diff --git a/usr.sbin/wpa/ndis_events/Makefile b/usr.sbin/wpa/ndis_events/Makefile deleted file mode 100644 index 07caf5a48465..000000000000 --- a/usr.sbin/wpa/ndis_events/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD$ - -PROG= ndis_events -SRCS+= ndis_events.c - -MAN= ndis_events.8 - -.include diff --git a/usr.sbin/wpa/ndis_events/Makefile.depend b/usr.sbin/wpa/ndis_events/Makefile.depend deleted file mode 100644 index d5ed563ecfc8..000000000000 --- a/usr.sbin/wpa/ndis_events/Makefile.depend +++ /dev/null @@ -1,18 +0,0 @@ -# $FreeBSD$ -# Autogenerated - do NOT edit! - -DIRDEPS = \ - gnu/lib/csu \ - include \ - include/arpa \ - include/xlocale \ - lib/${CSU_DIR} \ - lib/libc \ - lib/libcompiler_rt \ - - -.include - -.if ${DEP_RELDIR} == ${_DEP_RELDIR} -# local dependencies - needed for -jN in clean tree -.endif diff --git a/usr.sbin/wpa/ndis_events/ndis_events.8 b/usr.sbin/wpa/ndis_events/ndis_events.8 deleted file mode 100644 index bf11c1943fec..000000000000 --- a/usr.sbin/wpa/ndis_events/ndis_events.8 +++ /dev/null @@ -1,135 +0,0 @@ -.\" Copyright (c) 2005 -.\" Bill Paul All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by Bill Paul. -.\" 4. Neither the name of the author nor the names of any co-contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD -.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -.\" THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd August 30, 2007 -.Dt NDIS_EVENTS 8 -.Os -.Sh NAME -.Nm ndis_events -.Nd relay events from -.Xr ndis 4 -drivers to -.Xr wpa_supplicant 8 -.Sh SYNOPSIS -.Nm -.Op Fl a -.Op Fl d -.Op Fl v -.Sh DESCRIPTION -The -.Nm -utility listens for events generated by an -.Xr ndis 4 -wireless network driver and relays them to -.Xr wpa_supplicant 8 -for possible processing. -The three event types that can occur -are media connect and disconnect events, such as when a wireless -interface joins or leaves a network, and media-specific events. -In particular, -.Xr ndis 4 -drivers that support WPA2 will generate media-specific events -containing PMKID candidate information which -.Xr wpa_supplicant 8 -needs in order to properly associate with WPA2-capable access points. -.Pp -The -.Nm -daemon works by listening for interface information events via -a routing socket. -When it detects an event that was generated by an -.Xr ndis 4 -interface, it transmits it via UDP packet on the loopback interface, -where -.Xr wpa_supplicant 8 -is presumably listening. -The standard -.Xr wpa_supplicant 8 -distribution includes its own version of this utility for use with -.Tn Windows\[rg] . -The -.Fx -version performs the same functions as the -.Tn Windows\[rg] -one, except that it uses an -.Xr ioctl 2 -and routing socket interface instead of WMI. -.Pp -Note that a single instance of -.Nm -is sufficient to scan for events for any number of -.Xr ndis 4 -interfaces in a system. -.Sh OPTIONS -The -.Nm -daemon supports the following options: -.Bl -tag -width indent -.It Fl a -Process all events. -By default, -.Nm -will only process and forward media-specific events, which contain -PMKID candidate information, and not bother forwarding connect and -disconnect events, since -.Xr wpa_supplicant 8 -normally can determine the current link state on its own. -In some -cases, the additional connect and disconnect events only confuse it -and make the association and authentication process take longer. -.It Fl d -Run in debug mode. -This causes -.Nm -to run in the foreground and generate any output to the standard -error instead of using the -.Xr syslog 3 -facility. -.It Fl v -Run in verbose mode. -This causes -.Nm -to emit notifications when it receives events. -.El -.Sh SEE ALSO -.Xr ndis 4 , -.Xr wpa_supplicant 8 -.Sh HISTORY -The -.Nm -utility first appeared in -.Fx 6.0 . -.Sh AUTHORS -The -.Nm -utility was written by -.An Bill Paul Aq Mt wpaul@windriver.com . diff --git a/usr.sbin/wpa/ndis_events/ndis_events.c b/usr.sbin/wpa/ndis_events/ndis_events.c deleted file mode 100644 index cfd971af8ea1..000000000000 --- a/usr.sbin/wpa/ndis_events/ndis_events.c +++ /dev/null @@ -1,353 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2005 - * Bill Paul . 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 -__FBSDID("$FreeBSD$"); - -/* - * This program simulates the behavior of the ndis_events utility - * supplied with wpa_supplicant for Windows. The original utility - * is designed to translate Windows WMI events. We don't have WMI, - * but we need to supply certain event info to wpa_supplicant in - * order to make WPA2 work correctly, so we fake up the interface. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -static int verbose = 0; -static int debug = 0; -static int all_events = 0; - -#define PROGNAME "ndis_events" - -#define WPA_SUPPLICANT_PORT 9876 -#define NDIS_INDICATION_LEN 2048 - -#define EVENT_CONNECT 0 -#define EVENT_DISCONNECT 1 -#define EVENT_MEDIA_SPECIFIC 2 - -#define NDIS_STATUS_MEDIA_CONNECT 0x4001000B -#define NDIS_STATUS_MEDIA_DISCONNECT 0x4001000C -#define NDIS_STATUS_MEDIA_SPECIFIC_INDICATION 0x40010012 - -struct ndis_evt { - uint32_t ne_sts; - uint32_t ne_len; -#ifdef notdef - char ne_buf[1]; -#endif -}; - -static int find_ifname(int, char *); -static int announce_event(char *, int, struct sockaddr_in *); -static void usage(void); - -static void -dbgmsg(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - if (debug) - vwarnx(fmt, ap); - else - vsyslog(LOG_ERR, fmt, ap); - va_end(ap); - - return; -} - -static int -find_ifname(idx, name) - int idx; - char *name; -{ - int mib[6]; - size_t needed; - struct if_msghdr *ifm; - struct sockaddr_dl *sdl; - char *buf, *lim, *next; - - needed = 0; - mib[0] = CTL_NET; - mib[1] = PF_ROUTE; - mib[2] = 0; /* protocol */ - mib[3] = 0; /* wildcard address family */ - mib[4] = NET_RT_IFLIST; - mib[5] = 0; /* no flags */ - - if (sysctl (mib, 6, NULL, &needed, NULL, 0) < 0) - return(EIO); - - buf = malloc (needed); - if (buf == NULL) - return(ENOMEM); - - if (sysctl (mib, 6, buf, &needed, NULL, 0) < 0) { - free(buf); - return(EIO); - } - - lim = buf + needed; - - next = buf; - while (next < lim) { - ifm = (struct if_msghdr *)next; - if (ifm->ifm_type == RTM_IFINFO) { - sdl = (struct sockaddr_dl *)(ifm + 1); - if (ifm->ifm_index == idx) { - strncpy(name, sdl->sdl_data, sdl->sdl_nlen); - name[sdl->sdl_nlen] = '\0'; - free (buf); - return (0); - } - } - next += ifm->ifm_msglen; - } - - free (buf); - - return(ENOENT); -} - -static int -announce_event(ifname, sock, dst) - char *ifname; - int sock; - struct sockaddr_in *dst; -{ - int s; - char indication[NDIS_INDICATION_LEN]; - struct ifreq ifr; - struct ndis_evt *e; - char buf[512], *pos, *end; - int len, type, _type; - - s = socket(PF_INET, SOCK_DGRAM, 0); - - if (s < 0) { - dbgmsg("socket creation failed"); - return(EINVAL); - } - - bzero((char *)&ifr, sizeof(ifr)); - e = (struct ndis_evt *)indication; - e->ne_len = NDIS_INDICATION_LEN - sizeof(struct ndis_evt); - - strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - ifr.ifr_data = indication; - - if (ioctl(s, SIOCGPRIVATE_0, &ifr) < 0) { - close(s); - if (verbose) { - if (errno == ENOENT) - dbgmsg("drained all events from %s", - ifname, errno); - else - dbgmsg("failed to read event info from %s: %d", - ifname, errno); - } - return(ENOENT); - } - - if (e->ne_sts == NDIS_STATUS_MEDIA_CONNECT) { - type = EVENT_CONNECT; - if (verbose) - dbgmsg("Received a connect event for %s", ifname); - if (!all_events) { - close(s); - return(0); - } - } - if (e->ne_sts == NDIS_STATUS_MEDIA_DISCONNECT) { - type = EVENT_DISCONNECT; - if (verbose) - dbgmsg("Received a disconnect event for %s", ifname); - if (!all_events) { - close(s); - return(0); - } - } - if (e->ne_sts == NDIS_STATUS_MEDIA_SPECIFIC_INDICATION) { - type = EVENT_MEDIA_SPECIFIC; - if (verbose) - dbgmsg("Received a media-specific event for %s", - ifname); - } - - end = buf + sizeof(buf); - _type = (int) type; - memcpy(buf, &_type, sizeof(_type)); - pos = buf + sizeof(_type); - - len = snprintf(pos + 1, end - pos - 1, "%s", ifname); - if (len < 0) { - close(s); - return(ENOSPC); - } - if (len > 255) - len = 255; - *pos = (unsigned char) len; - pos += 1 + len; - if (e->ne_len) { - if (e->ne_len > 255 || 1 + e->ne_len > end - pos) { - dbgmsg("Not enough room for send_event data (%d)\n", - e->ne_len); - close(s); - return(ENOSPC); - } - *pos++ = (unsigned char) e->ne_len; - memcpy(pos, (indication) + sizeof(struct ndis_evt), e->ne_len); - pos += e->ne_len; - } - - len = sendto(sock, buf, pos - buf, 0, (struct sockaddr *) dst, - sizeof(struct sockaddr_in)); - - close(s); - return(0); -} - -static void -usage() -{ - fprintf(stderr, "Usage: ndis_events [-a] [-d] [-v]\n"); - exit(1); -} - -int -main(argc, argv) - int argc; - char *argv[]; -{ - int s, r, n; - struct sockaddr_in sin; - char msg[NDIS_INDICATION_LEN]; - struct rt_msghdr *rtm; - struct if_msghdr *ifm; - char ifname[IFNAMSIZ]; - int ch; - - while ((ch = getopt(argc, argv, "dva")) != -1) { - switch(ch) { - case 'd': - debug++; - break; - case 'v': - verbose++; - break; - case 'a': - all_events++; - break; - default: - usage(); - break; - } - } - - if (!debug && daemon(0, 0)) - err(1, "failed to daemonize ourselves"); - - if (!debug) - openlog(PROGNAME, LOG_PID | LOG_CONS, LOG_DAEMON); - - bzero((char *)&sin, sizeof(sin)); - - /* Create a datagram socket. */ - - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s < 0) { - dbgmsg("socket creation failed"); - exit(1); - } - - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = inet_addr("127.0.0.1"); - sin.sin_port = htons(WPA_SUPPLICANT_PORT); - - /* Create a routing socket. */ - - r = socket (PF_ROUTE, SOCK_RAW, 0); - if (r < 0) { - dbgmsg("routing socket creation failed"); - exit(1); - } - - /* Now sit and spin, waiting for events. */ - - if (verbose) - dbgmsg("Listening for events"); - - while (1) { - n = read(r, msg, NDIS_INDICATION_LEN); - rtm = (struct rt_msghdr *)msg; - if (rtm->rtm_type != RTM_IFINFO) - continue; - ifm = (struct if_msghdr *)msg; - if (find_ifname(ifm->ifm_index, ifname)) - continue; - if (strstr(ifname, "ndis")) { - while(announce_event(ifname, s, &sin) == 0) - ; - } else { - if (verbose) - dbgmsg("Skipping ifinfo message from %s", - ifname); - } - } - - /* NOTREACHED */ - exit(0); -} diff --git a/usr.sbin/wpa/wpa_supplicant/Makefile b/usr.sbin/wpa/wpa_supplicant/Makefile index dc8178ccf9b8..352e13e6bde6 100644 --- a/usr.sbin/wpa/wpa_supplicant/Makefile +++ b/usr.sbin/wpa/wpa_supplicant/Makefile @@ -15,7 +15,7 @@ SRCS= base64.c bitfield.c blacklist.c bss.c cli.c common.c \ config.c config_file.c \ ctrl_iface.c ctrl_iface_common.c ctrl_iface_unix.c \ driver_bsd.c driver_common.c \ - driver_ndis.c driver_wired.c driver_wired_common.c drivers.c \ + driver_wired.c driver_wired_common.c drivers.c \ eap_register.c eloop.c \ events.c gas.c gas_query.c \ http_client.c http_server.c \ @@ -24,8 +24,7 @@ SRCS= base64.c bitfield.c blacklist.c bss.c cli.c common.c \ notify.c offchannel.c op_classes.c os_unix.c pmksa_cache.c preauth.c \ rrm.c scan.c upnp_xml.c \ wmm_ac.c wpa.c wpa_common.c wpa_ctrl.c \ - wpa_debug.c wpa_ft.c wpa_ie.c wpa_supplicant.c wpabuf.c wpas_glue.c \ - Packet32.c + wpa_debug.c wpa_ft.c wpa_ie.c wpa_supplicant.c wpabuf.c wpas_glue.c MAN= wpa_supplicant.8 wpa_supplicant.conf.5 @@ -38,7 +37,6 @@ FILES= wpa_supplicant.conf CFLAGS+=-DCONFIG_BACKEND_FILE \ -DCONFIG_DEBUG_SYSLOG \ -DCONFIG_DRIVER_BSD \ - -DCONFIG_DRIVER_NDIS \ -DCONFIG_DRIVER_WIRED \ -DCONFIG_GAS \ -DCONFIG_IEEE80211R \ diff --git a/usr.sbin/wpa/wpa_supplicant/Packet32.c b/usr.sbin/wpa/wpa_supplicant/Packet32.c deleted file mode 100644 index 3f852b722080..000000000000 --- a/usr.sbin/wpa/wpa_supplicant/Packet32.c +++ /dev/null @@ -1,415 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2005 - * Bill Paul . 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 -__FBSDID("$FreeBSD$"); - -/* - * This file implements a small portion of the Winpcap API for the - * Windows NDIS interface in wpa_supplicant. It provides just enough - * routines to fool wpa_supplicant into thinking it's really running - * in a Windows environment. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include "Packet32.h" - -#define OID_802_11_ADD_KEY 0x0d01011D - -typedef ULONGLONG NDIS_802_11_KEY_RSC; -typedef UCHAR NDIS_802_11_MAC_ADDRESS[6]; - -typedef struct NDIS_802_11_KEY { - ULONG Length; - ULONG KeyIndex; - ULONG KeyLength; - NDIS_802_11_MAC_ADDRESS BSSID; - NDIS_802_11_KEY_RSC KeyRSC; - UCHAR KeyMaterial[1]; -} NDIS_802_11_KEY; - -typedef struct NDIS_802_11_KEY_COMPAT { - ULONG Length; - ULONG KeyIndex; - ULONG KeyLength; - NDIS_802_11_MAC_ADDRESS BSSID; - UCHAR Pad[6]; /* Make struct layout match Windows. */ - NDIS_802_11_KEY_RSC KeyRSC; -#ifdef notdef - UCHAR KeyMaterial[1]; -#endif -} NDIS_802_11_KEY_COMPAT; - -#define TRUE 1 -#define FALSE 0 - -struct adapter { - int socket; - char name[IFNAMSIZ]; - int prev_roaming; -}; - -PCHAR -PacketGetVersion(void) -{ - return("FreeBSD WinPcap compatibility shim v1.0"); -} - -void * -PacketOpenAdapter(CHAR *iface) -{ - struct adapter *a; - int s; - int ifflags; - struct ifreq ifr; - struct ieee80211req ireq; - - s = socket(PF_INET, SOCK_DGRAM, 0); - - if (s == -1) - return(NULL); - - a = malloc(sizeof(struct adapter)); - if (a == NULL) - return(NULL); - - a->socket = s; - if (strncmp(iface, "\\Device\\NPF_", 12) == 0) - iface += 12; - else if (strncmp(iface, "\\DEVICE\\", 8) == 0) - iface += 8; - snprintf(a->name, IFNAMSIZ, "%s", iface); - - /* Turn off net80211 roaming */ - bzero((char *)&ireq, sizeof(ireq)); - strncpy(ireq.i_name, iface, sizeof (ifr.ifr_name)); - ireq.i_type = IEEE80211_IOC_ROAMING; - if (ioctl(a->socket, SIOCG80211, &ireq) == 0) { - a->prev_roaming = ireq.i_val; - ireq.i_val = IEEE80211_ROAMING_MANUAL; - if (ioctl(a->socket, SIOCS80211, &ireq) < 0) - fprintf(stderr, - "Could not set IEEE80211_ROAMING_MANUAL\n"); - } - - bzero((char *)&ifr, sizeof(ifr)); - strncpy(ifr.ifr_name, iface, sizeof (ifr.ifr_name)); - if (ioctl(a->socket, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { - free(a); - close(s); - return(NULL); - } - ifr.ifr_flags |= IFF_UP; - if (ioctl(a->socket, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) { - free(a); - close(s); - return(NULL); - } - - return(a); -} - -int -PacketRequest(void *iface, BOOLEAN set, PACKET_OID_DATA *oid) -{ - struct adapter *a; - uint32_t retval; - struct ifreq ifr; - NDIS_802_11_KEY *old; - NDIS_802_11_KEY_COMPAT *new; - PACKET_OID_DATA *o = NULL; - - if (iface == NULL) - return(-1); - - a = iface; - bzero((char *)&ifr, sizeof(ifr)); - - /* - * This hack is necessary to work around a difference - * betwee the GNU C and Microsoft C compilers. The NDIS_802_11_KEY - * structure has a uint64_t in it, right after an array of - * chars. The Microsoft compiler inserts padding right before - * the 64-bit value to align it on a 64-bit boundary, but - * GCC only aligns it on a 32-bit boundary. Trying to pass - * the GCC-formatted structure to an NDIS binary driver - * fails because some of the fields appear to be at the - * wrong offsets. - * - * To get around this, if we detect someone is trying to do - * a set operation on OID_802_11_ADD_KEY, we shuffle the data - * into a properly padded structure and pass that into the - * driver instead. This allows the driver_ndis.c code supplied - * with wpa_supplicant to work unmodified. - */ - - if (set == TRUE && oid->Oid == OID_802_11_ADD_KEY) { - old = (NDIS_802_11_KEY *)&oid->Data; - o = malloc(sizeof(PACKET_OID_DATA) + - sizeof(NDIS_802_11_KEY_COMPAT) + old->KeyLength); - if (o == NULL) - return(0); - bzero((char *)o, sizeof(PACKET_OID_DATA) + - sizeof(NDIS_802_11_KEY_COMPAT) + old->KeyLength); - o->Oid = oid->Oid; - o->Length = sizeof(NDIS_802_11_KEY_COMPAT) + old->KeyLength; - new = (NDIS_802_11_KEY_COMPAT *)&o->Data; - new->KeyRSC = old->KeyRSC; - new->Length = o->Length; - new->KeyIndex = old->KeyIndex; - new->KeyLength = old->KeyLength; - bcopy(old->BSSID, new->BSSID, sizeof(NDIS_802_11_MAC_ADDRESS)); - bcopy(old->KeyMaterial, (char *)new + - sizeof(NDIS_802_11_KEY_COMPAT), new->KeyLength); - ifr.ifr_data = (caddr_t)o; - } else - ifr.ifr_data = (caddr_t)oid; - - strlcpy(ifr.ifr_name, a->name, sizeof(ifr.ifr_name)); - - if (set == TRUE) - retval = ioctl(a->socket, SIOCSDRVSPEC, &ifr); - else - retval = ioctl(a->socket, SIOCGDRVSPEC, &ifr); - - if (o != NULL) - free(o); - - if (retval) - return(0); - - return(1); -} - -int -PacketGetAdapterNames(CHAR *namelist, ULONG *len) -{ - int mib[6]; - size_t needed; - struct if_msghdr *ifm; - struct sockaddr_dl *sdl; - char *buf, *lim, *next; - char *plist; - int spc; - int i, ifcnt = 0; - - plist = namelist; - spc = 0; - - bzero(plist, *len); - - needed = 0; - mib[0] = CTL_NET; - mib[1] = PF_ROUTE; - mib[2] = 0; /* protocol */ - mib[3] = 0; /* wildcard address family */ - mib[4] = NET_RT_IFLIST; - mib[5] = 0; /* no flags */ - - if (sysctl (mib, 6, NULL, &needed, NULL, 0) < 0) - return(FALSE); - - buf = malloc (needed); - if (buf == NULL) - return(FALSE); - - if (sysctl (mib, 6, buf, &needed, NULL, 0) < 0) { - free(buf); - return(FALSE); - } - - lim = buf + needed; - - /* Generate interface name list. */ - - next = buf; - while (next < lim) { - ifm = (struct if_msghdr *)next; - if (ifm->ifm_type == RTM_IFINFO) { - sdl = (struct sockaddr_dl *)(ifm + 1); - if (strnstr(sdl->sdl_data, "wlan", sdl->sdl_nlen)) { - if ((spc + sdl->sdl_nlen) > *len) { - free(buf); - return(FALSE); - } - strncpy(plist, sdl->sdl_data, sdl->sdl_nlen); - plist += (sdl->sdl_nlen + 1); - spc += (sdl->sdl_nlen + 1); - ifcnt++; - } - } - next += ifm->ifm_msglen; - } - - - /* Insert an extra "" as a spacer */ - - plist++; - spc++; - - /* - * Now generate the interface description list. There - * must be a unique description for each interface, and - * they have to match what the ndis_events program will - * feed in later. To keep this simple, we just repeat - * the interface list over again. - */ - - next = buf; - while (next < lim) { - ifm = (struct if_msghdr *)next; - if (ifm->ifm_type == RTM_IFINFO) { - sdl = (struct sockaddr_dl *)(ifm + 1); - if (strnstr(sdl->sdl_data, "wlan", sdl->sdl_nlen)) { - if ((spc + sdl->sdl_nlen) > *len) { - free(buf); - return(FALSE); - } - strncpy(plist, sdl->sdl_data, sdl->sdl_nlen); - plist += (sdl->sdl_nlen + 1); - spc += (sdl->sdl_nlen + 1); - ifcnt++; - } - } - next += ifm->ifm_msglen; - } - - free (buf); - - *len = spc + 1; - - return(TRUE); -} - -void -PacketCloseAdapter(void *iface) -{ - struct adapter *a; - struct ifreq ifr; - struct ieee80211req ireq; - - if (iface == NULL) - return; - - a = iface; - - /* Reset net80211 roaming */ - bzero((char *)&ireq, sizeof(ireq)); - strncpy(ireq.i_name, a->name, sizeof (ifr.ifr_name)); - ireq.i_type = IEEE80211_IOC_ROAMING; - ireq.i_val = a->prev_roaming; - ioctl(a->socket, SIOCS80211, &ireq); - - bzero((char *)&ifr, sizeof(ifr)); - strncpy(ifr.ifr_name, a->name, sizeof (ifr.ifr_name)); - ioctl(a->socket, SIOCGIFFLAGS, (caddr_t)&ifr); - ifr.ifr_flags &= ~IFF_UP; - ioctl(a->socket, SIOCSIFFLAGS, (caddr_t)&ifr); - close(a->socket); - free(a); - - return; -} - -#if __FreeBSD_version < 600000 - -/* - * The version of libpcap in FreeBSD 5.2.1 doesn't have these routines. - * Call me insane if you will, but I still run 5.2.1 on my laptop, and - * I'd like to use WPA there. - */ - -int -pcap_get_selectable_fd(pcap_t *p) -{ - return(pcap_fileno(p)); -} - -/* - * The old version of libpcap opens its BPF descriptor in read-only - * mode. We need to temporarily create a new one we can write to. - */ - -int -pcap_inject(pcap_t *p, const void *buf, size_t len) -{ - int fd; - int res, n = 0; - char device[sizeof "/dev/bpf0000000000"]; - struct ifreq ifr; - - /* - * Go through all the minors and find one that isn't in use. - */ - do { - (void)snprintf(device, sizeof(device), "/dev/bpf%d", n++); - fd = open(device, O_RDWR); - } while (fd < 0 && errno == EBUSY); - - if (fd == -1) - return(-1); - - bzero((char *)&ifr, sizeof(ifr)); - ioctl(pcap_fileno(p), BIOCGETIF, (caddr_t)&ifr); - ioctl(fd, BIOCSETIF, (caddr_t)&ifr); - - res = write(fd, buf, len); - - close(fd); - - return(res); -} -#endif diff --git a/usr.sbin/wpa/wpa_supplicant/Packet32.h b/usr.sbin/wpa/wpa_supplicant/Packet32.h deleted file mode 100644 index c96553afc8a1..000000000000 --- a/usr.sbin/wpa/wpa_supplicant/Packet32.h +++ /dev/null @@ -1,69 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2005 - * Bill Paul . All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _PACKET32_H_ -#define _PACKET32_H_ - -#include -#include - -struct PACKET_OID_DATA { - uint32_t Oid; - uint32_t Length; - uint8_t Data[1]; -}; - - -typedef struct PACKET_OID_DATA PACKET_OID_DATA; - -extern PCHAR PacketGetVersion(void); -extern void *PacketOpenAdapter(CHAR *); -extern int PacketRequest(void *, BOOLEAN, PACKET_OID_DATA *); -extern int PacketGetAdapterNames(CHAR *, ULONG *); -extern void PacketCloseAdapter(void *); - -/* - * This is for backwards compatibility on FreeBSD 5. - */ - -#ifndef SIOCGDRVSPEC -#define SIOCSDRVSPEC _IOW('i', 123, struct ifreq) /* set driver-specific - parameters */ -#define SIOCGDRVSPEC _IOWR('i', 123, struct ifreq) /* get driver-specific - parameters */ -#endif - -#endif /* _PACKET32_H_ */ diff --git a/usr.sbin/wpa/wpa_supplicant/ntddndis.h b/usr.sbin/wpa/wpa_supplicant/ntddndis.h deleted file mode 100644 index 42e403d7bb12..000000000000 --- a/usr.sbin/wpa/wpa_supplicant/ntddndis.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef _NTDDNDIS_H_ -#define _NTDDNDIS_H_ - -/* - * $FreeBSD$ - */ - -/* - * Fake up some of the Windows type definitions so that the NDIS - * interface module in wpa_supplicant will build. - */ - -#define ULONG uint32_t -#define USHORT uint16_t -#define UCHAR uint8_t -#define LONG int32_t -#define SHORT int16_t -#define CHAR int8_t -#define ULONGLONG uint64_t -#define LONGLONG int64_t -#define BOOLEAN uint8_t -typedef void * LPADAPTER; -typedef char * PTSTR; -typedef char * PCHAR; - -#define TRUE 1 -#define FALSE 0 - -#define OID_802_3_CURRENT_ADDRESS 0x01010102 - -#endif /* _NTDDNDIS_H_ */