9b307fe2be
- Remove the old task threads from kern_ndis.c and reimplement them in subr_ntoskrnl.c, in order to more properly emulate the Windows DPC API. Each CPU gets its own DPC queue/thread, and each queue can have low, medium and high importance DPCs. New APIs implemented: KeSetTargetProcessorDpc(), KeSetImportanceDpc() and KeFlushQueuedDpcs(). (This is the biggest change.) - Fix a bug in NdisMInitializeTimer(): the k_dpc pointer in the nmt_timer embedded in the ndis_miniport_timer struct must be set to point to the DPC, also embedded in the struct. Failing to do this breaks dequeueing of DPCs submitted via timers, and in turn breaks cancelling timers. - Fix a bug in KeCancelTimer(): if the timer is interted in the timer queue (i.e. the timeout callback is still pending), we have to both untimeout() the timer _and_ call KeRemoveQueueDpc() to nuke the DPC that might be pending. Failing to do this breaks cancellation of periodic timers, which always appear to be inserted in the timer queue. - Make use of the nmt_nexttimer field in ndis_miniport_timer: keep a queue of pending timers and cancel them all in ndis_halt_nic(), prior to calling MiniportHalt(). Also call KeFlushQueuedDpcs() to make sure any DPCs queued by the timers have expired. - Modify NdisMAllocateSharedMemory() and NdisMFreeSharedMemory() to keep track of both the virtual and physical addresses of the shared memory buffers that get handed out. The AirGo MIMO driver appears to have a bug in it: for one of the segments is allocates, it returns the wrong virtual address. This would confuse NdisMFreeSharedMemory() and cause a crash. Why it doesn't crash Windows too I have no idea (from reading the documentation for NdisMFreeSharedMemory(), it appears to be a violation of the API). - Implement strstr(), strchr() and MmIsAddressValid(). - Implement IoAllocateWorkItem(), IoFreeWorkItem(), IoQueueWorkItem() and ExQueueWorkItem(). (This is the second biggest change.) - Make NdisScheduleWorkItem() call ExQueueWorkItem(). (Note that the ExQueueWorkItem() API is deprecated by Microsoft, but NDIS still uses it, since NdisScheduleWorkItem() is incompatible with the IoXXXWorkItem() API.) - Change if_ndis.c to use the NdisScheduleWorkItem() interface for scheduling tasks. With all these changes and fixes, the AirGo MIMO driver for the Belkin F5D8010 Pre-N card now works. Special thanks to Paul Robinson (paul dawt robinson at pwermedia dawt net) for the loan of a card for testing.
159 lines
4.2 KiB
C
159 lines
4.2 KiB
C
/*-
|
|
* Copyright (c) 2005
|
|
* Bill Paul <wpaul@windriver.com>. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by Bill Paul.
|
|
* 4. Neither the name of the author nor the names of any co-contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/unistd.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/kernel.h>
|
|
#include <sys/malloc.h>
|
|
#include <sys/lock.h>
|
|
#include <sys/mutex.h>
|
|
#include <sys/module.h>
|
|
#include <sys/conf.h>
|
|
#include <sys/mbuf.h>
|
|
#include <sys/bus.h>
|
|
|
|
#include <sys/queue.h>
|
|
|
|
#include <compat/ndis/pe_var.h>
|
|
#include <compat/ndis/cfg_var.h>
|
|
#include <compat/ndis/resource_var.h>
|
|
#include <compat/ndis/ntoskrnl_var.h>
|
|
#include <compat/ndis/ndis_var.h>
|
|
#include <compat/ndis/hal_var.h>
|
|
#include <compat/ndis/usbd_var.h>
|
|
|
|
static driver_object usbd_driver;
|
|
|
|
static uint32_t usbd_iodispatch(device_object *, irp *);
|
|
|
|
static void USBD_GetUSBDIVersion(usbd_version_info *);
|
|
static void dummy(void);
|
|
|
|
int
|
|
usbd_libinit(void)
|
|
{
|
|
image_patch_table *patch;
|
|
|
|
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++;
|
|
}
|
|
|
|
/* Create a fake USB driver instance. */
|
|
|
|
windrv_bus_attach(&usbd_driver, "USB Bus");
|
|
|
|
/* Set up our dipatch routine. */
|
|
|
|
usbd_driver.dro_dispatch[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
|
|
(driver_dispatch)usbd_iodispatch;
|
|
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
usbd_libfini(void)
|
|
{
|
|
image_patch_table *patch;
|
|
|
|
patch = usbd_functbl;
|
|
while (patch->ipt_func != NULL) {
|
|
windrv_unwrap(patch->ipt_wrap);
|
|
patch++;
|
|
}
|
|
|
|
free(usbd_driver.dro_drivername.us_buf, M_DEVBUF);
|
|
|
|
return(0);
|
|
}
|
|
|
|
static uint32_t
|
|
usbd_iodispatch(dobj, ip)
|
|
device_object *dobj;
|
|
irp *ip;
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
static void
|
|
USBD_GetUSBDIVersion(ui)
|
|
usbd_version_info *ui;
|
|
{
|
|
/* Pretend to be Windows XP. */
|
|
|
|
ui->uvi_usbdi_vers = USBDI_VERSION;
|
|
ui->uvi_supported_vers = USB_VER_2_0;
|
|
|
|
return;
|
|
}
|
|
|
|
static void
|
|
dummy(void)
|
|
{
|
|
printf("USBD dummy called\n");
|
|
return;
|
|
}
|
|
|
|
image_patch_table usbd_functbl[] = {
|
|
IMPORT_SFUNC(USBD_GetUSBDIVersion, 0),
|
|
IMPORT_SFUNC(usbd_iodispatch, 2),
|
|
#ifdef notyet
|
|
IMPORT_FUNC_MAP(_USBD_ParseConfigurationDescriptorEx@28,
|
|
USBD_ParseConfigurationDescriptorEx),
|
|
IMPORT_FUNC_MAP(_USBD_CreateConfigurationRequestEx@8,
|
|
USBD_CreateConfigurationRequestEx),
|
|
#endif
|
|
|
|
/*
|
|
* 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 }
|
|
};
|
|
|