Integrate the NDIS USB support code to CURRENT.

Now the NDISulator supports NDIS USB drivers that it've tested with
devices as follows:

  - Anygate XM-142 (Conexant)
  - Netgear WG111v2 (Realtek)
  - U-Khan UW-2054u (Marvell)
  - Shuttle XPC Accessory PN20 (Realtek)
  - ipTIME G054U2 (Ralink)
  - UNiCORN WL-54G (ZyDAS)
  - ZyXEL G-200v2 (ZyDAS)

All of them succeeded to attach and worked though there are still some
problems that it's expected to be solved.

To use NDIS USB support, you should rebuild and install ndiscvt(8) and
if you encounter a problem to attach please set `hw.ndisusb.halt' to
0 then retry.

I expect no changes of the NDIS code for PCI, PCMCIA devices.

Obtained from:  //depot/projects/ndisusb/...
This commit is contained in:
weongyo 2008-12-27 08:03:32 +00:00
parent a83406ae2e
commit 0f8825b3f7
17 changed files with 1820 additions and 60 deletions

View File

@ -105,7 +105,7 @@ file.
The
.Nm
driver is designed to support mainly Ethernet and wireless
network devices with PCI and PCMCIA bus attachments.
network devices with PCI, PCMCIA and USB bus attachments.
(Cardbus
devices are also supported as a subset of PCI.)
It can

View File

@ -65,6 +65,9 @@ __FBSDID("$FreeBSD$");
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_ioctl.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <compat/ndis/pe_var.h>
#include <compat/ndis/cfg_var.h>
#include <compat/ndis/resource_var.h>
@ -144,7 +147,6 @@ ndis_modevent(module_t mod, int cmd, void *arg)
}
TAILQ_INIT(&ndis_devhead);
break;
case MOD_SHUTDOWN:
if (TAILQ_FIRST(&ndis_devhead) == NULL) {
@ -1198,6 +1200,31 @@ ndis_shutdown_nic(arg)
return(0);
}
int
ndis_pnpevent_nic(arg, type)
void *arg;
int type;
{
struct ndis_softc *sc;
ndis_handle adapter;
ndis_pnpevent_handler pnpeventfunc;
sc = 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;

View File

@ -56,6 +56,9 @@ __FBSDID("$FreeBSD$");
#include <machine/segments.h>
#endif
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <compat/ndis/pe_var.h>
#include <compat/ndis/cfg_var.h>
#include <compat/ndis/resource_var.h>
@ -349,9 +352,11 @@ windrv_load(mod, img, len, bustype, devlist, regvals)
if (pe_patch_imports(img, "NDIS", ndis_functbl))
return(ENOEXEC);
/* Dynamically link the HAL.dll routines -- also required. */
if (pe_patch_imports(img, "HAL", hal_functbl))
return(ENOEXEC);
/* Dynamically link 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) {

View File

@ -1658,6 +1658,7 @@ 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);
@ -1739,6 +1740,7 @@ 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(void *, void *);
extern int ndis_init_dma(void *);
@ -1759,6 +1761,7 @@ extern void NdisAllocatePacket(ndis_status *,
extern void NdisFreePacket(ndis_packet *);
extern ndis_status NdisScheduleWorkItem(ndis_work_item *);
extern void NdisMSleep(uint32_t);
extern void ndis_cancel_timerlist(void);
__END_DECLS
#endif /* _NDIS_VAR_H_ */

View File

@ -536,6 +536,11 @@ typedef struct wait_block wait_block;
#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;
@ -989,7 +994,13 @@ struct irp {
} s2;
void *irp_fileobj;
} irp_overlay;
kapc irp_apc;
union {
kapc irp_apc;
struct {
void *irp_xfer;
void *irp_dev;
} irp_usb;
} irp_misc;
void *irp_compkey;
} irp_tail;
};
@ -997,6 +1008,9 @@ struct irp {
#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_XFER(irp) (irp)->irp_tail.irp_misc.irp_usb.irp_xfer
typedef struct irp irp;
#define InterlockedExchangePointer(dst, val) \
@ -1009,6 +1023,10 @@ typedef struct irp irp;
(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
@ -1035,6 +1053,8 @@ typedef struct irp irp;
#define IoMarkIrpPending(irp) \
IoGetCurrentIrpStackLocation(irp)->isl_ctl |= SL_PENDING_RETURNED
#define IoUnmarkIrpPending(irp) \
IoGetCurrentIrpStackLocation(irp)->isl_ctl &= ~SL_PENDING_RETURNED
#define IoCopyCurrentIrpStackLocationToNext(irp) \
do { \
@ -1191,14 +1211,21 @@ typedef struct driver_object driver_object;
#define STATUS_ALERTED 0x00000101
#define STATUS_TIMEOUT 0x00000102
#define STATUS_PENDING 0x00000103
#define STATUS_FAILURE 0xC0000001
#define STATUS_NOT_IMPLEMENTED 0xC0000002
#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
@ -1365,6 +1392,7 @@ 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 *MmMapIoSpace(uint64_t, uint32_t, uint32_t);
extern void MmUnmapIoSpace(void *, size_t);
extern void MmBuildMdlForNonPagedPool(mdl *);

View File

@ -95,6 +95,8 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <compat/ndis/pe_var.h>
#include <compat/ndis/cfg_var.h>
@ -302,6 +304,15 @@ static void dummy(void);
*/
#define NDIS_POOL_EXTRA 16
struct ktimer_list {
ktimer *kl_timer;
list_entry kl_next;
};
static struct list_entry ndis_timerlist;
static kspin_lock ndis_timerlock;
static int ndis_isusbdev;
int
ndis_libinit()
{
@ -317,6 +328,9 @@ ndis_libinit()
patch++;
}
KeInitializeSpinLock(&ndis_timerlock);
InitializeListHead(&ndis_timerlist);
return(0);
}
@ -1215,6 +1229,16 @@ NdisMInitializeTimer(timer, handle, func, ctx)
ndis_timer_function func;
void *ctx;
{
ndis_miniport_block *block;
struct ktimer_list *kl;
struct ndis_softc *sc;
uint8_t irql;
block = (ndis_miniport_block *)handle;
sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
if (sc->ndis_iftype == PNPBus && ndis_isusbdev == 0)
ndis_isusbdev = 1;
/* Save the driver's funcptr and context */
timer->nmt_timerfunc = func;
@ -1232,7 +1256,38 @@ NdisMInitializeTimer(timer, handle, func, ctx)
ndis_findwrap((funcptr)ndis_timercall), timer);
timer->nmt_ktimer.k_dpc = &timer->nmt_kdpc;
return;
if (ndis_isusbdev == 1) {
kl = (struct ktimer_list *)malloc(sizeof(*kl), M_DEVBUF,
M_NOWAIT | M_ZERO);
if (kl == NULL)
panic("out of memory"); /* no way to report errors */
kl->kl_timer = &timer->nmt_ktimer;
KeAcquireSpinLock(&ndis_timerlock, &irql);
InsertHeadList((&ndis_timerlist), (&kl->kl_next));
KeReleaseSpinLock(&ndis_timerlock, irql);
}
}
void
ndis_cancel_timerlist(void)
{
list_entry *l;
struct ktimer_list *kl;
uint8_t cancelled, irql;
KeAcquireSpinLock(&ndis_timerlock, &irql);
while(!IsListEmpty(&ndis_timerlist)) {
l = RemoveHeadList(&ndis_timerlist);
kl = CONTAINING_RECORD(l, struct ktimer_list, kl_next);
KeReleaseSpinLock(&ndis_timerlock, irql);
cancelled = KeCancelTimer(kl->kl_timer);
free(kl, M_DEVBUF);
KeAcquireSpinLock(&ndis_timerlock, &irql);
}
KeReleaseSpinLock(&ndis_timerlock, irql);
}
/*
@ -1277,6 +1332,26 @@ NdisMCancelTimer(timer, cancelled)
ndis_timer *timer;
uint8_t *cancelled;
{
list_entry *l;
struct ktimer_list *kl;
uint8_t irql;
if (ndis_isusbdev == 1) {
KeAcquireSpinLock(&ndis_timerlock, &irql);
l = ndis_timerlist.nle_flink;
while(l != &ndis_timerlist) {
kl = CONTAINING_RECORD(l, struct ktimer_list, kl_next);
if (kl->kl_timer == &timer->nt_ktimer) {
RemoveEntryList((&kl->kl_next));
l = l->nle_flink;
free(kl, M_DEVBUF);
continue;
}
l = l->nle_flink;
}
KeReleaseSpinLock(&ndis_timerlock, irql);
}
*cancelled = KeCancelTimer(&timer->nt_ktimer);
return;
}

View File

@ -207,7 +207,6 @@ 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 uint8_t MmIsAddressValid(void *);
static device_t ntoskrnl_finddev(device_t, uint64_t, struct resource **);
static void RtlZeroMemory(void *, size_t);
static void RtlCopyMemory(void *, const void *, size_t);
@ -251,6 +250,8 @@ 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;
@ -1143,16 +1144,18 @@ uint8_t
IoCancelIrp(irp *ip)
{
cancel_func cfunc;
uint8_t cancelirql;
IoAcquireCancelSpinLock(&ip->irp_cancelirql);
IoAcquireCancelSpinLock(&cancelirql);
cfunc = IoSetCancelRoutine(ip, NULL);
ip->irp_cancel = TRUE;
if (ip->irp_cancelfunc == NULL) {
IoReleaseCancelSpinLock(ip->irp_cancelirql);
if (cfunc == NULL) {
IoReleaseCancelSpinLock(cancelirql);
return(FALSE);
}
ip->irp_cancelirql = cancelirql;
MSCALL2(cfunc, IoGetCurrentIrpStackLocation(ip)->isl_devobj, ip);
return(TRUE);
return (uint8_t)IoSetCancelValue(ip, TRUE);
}
uint32_t
@ -1186,24 +1189,27 @@ IofCompleteRequest(ip, prioboost)
irp *ip;
uint8_t prioboost;
{
uint32_t i;
uint32_t status;
device_object *dobj;
io_stack_location *sl;
completion_func cf;
ip->irp_pendingreturned =
IoGetCurrentIrpStackLocation(ip)->isl_ctl & SL_PENDING_RETURNED;
sl = (io_stack_location *)(ip + 1);
KASSERT(ip->irp_iostat.isb_status != STATUS_PENDING,
("incorrect IRP(%p) status (STATUS_PENDING)", ip));
for (i = ip->irp_currentstackloc; i < (uint32_t)ip->irp_stackcnt; i++) {
if (ip->irp_currentstackloc < ip->irp_stackcnt - 1) {
IoSkipCurrentIrpStackLocation(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
else
dobj = NULL;
if (sl[i].isl_completionfunc != 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 &&
@ -1214,12 +1220,16 @@ IofCompleteRequest(ip, prioboost)
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);
}
if (IoGetCurrentIrpStackLocation(ip)->isl_ctl &
SL_PENDING_RETURNED)
ip->irp_pendingreturned = TRUE;
}
/* move to the next. */
IoSkipCurrentIrpStackLocation(ip);
sl++;
} while (ip->irp_currentstackloc <= (ip->irp_stackcnt + 1));
/* Handle any associated IRPs. */
@ -2672,7 +2682,7 @@ MmUnmapLockedPages(vaddr, buf)
* here, but it doesn't.
*/
static uint8_t
uint8_t
MmIsAddressValid(vaddr)
void *vaddr;
{
@ -4258,6 +4268,73 @@ KeReadStateTimer(timer)
return(timer->k_header.dh_sigstate);
}
static int32_t
KeDelayExecutionThread(wait_mode, alertable, interval)
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 * ((10000000 + hz - 1) / 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()
{
@ -4441,6 +4518,10 @@ image_patch_table ntoskrnl_functbl[] = {
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

File diff suppressed because it is too large Load Diff

View File

@ -35,9 +35,168 @@
#ifndef _USBD_VAR_H_
#define _USBD_VAR_H_
#define USBDI_VERSION 0x00000500
#define USB_VER_1_1 0x00000110
#define USB_VER_2_0 0x00000200
#define IOCTL_INTERNAL_USB_SUBMIT_URB 0x00220003
#define URB_FUNCTION_SELECT_CONFIGURATION 0x0000
#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_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;
};
#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;
@ -46,6 +205,13 @@ struct usbd_version_info {
typedef struct usbd_version_info usbd_version_info;
/* used for IRP cancel. */
struct ndisusb_cancel {
device_t dev;
usbd_xfer_handle xfer;
struct usb_task task;
};
extern image_patch_table usbd_functbl[];
__BEGIN_DECLS

View File

@ -74,6 +74,8 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <compat/ndis/pe_var.h>
#include <compat/ndis/cfg_var.h>
@ -81,6 +83,7 @@ __FBSDID("$FreeBSD$");
#include <compat/ndis/ntoskrnl_var.h>
#include <compat/ndis/hal_var.h>
#include <compat/ndis/ndis_var.h>
#include <compat/ndis/usbd_var.h>
#include <dev/if_ndis/if_ndisvar.h>
#define NDIS_DEBUG
@ -93,6 +96,11 @@ SYSCTL_INT(_debug, OID_AUTO, ndis, CTLFLAG_RW, &ndis_debug, 0,
#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");
MODULE_DEPEND(ndis, ether, 1, 1, 1);
MODULE_DEPEND(ndis, wlan, 1, 1, 1);
MODULE_DEPEND(ndis, ndisapi, 1, 1, 1);
@ -538,7 +546,9 @@ ndis_attach(dev)
mtx_init(&sc->ndis_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF);
KeInitializeSpinLock(&sc->ndis_rxlock);
KeInitializeSpinLock(&sc->ndisusb_xferlock);
InitializeListHead(&sc->ndis_shlist);
InitializeListHead(&sc->ndisusb_xferlist);
callout_init(&sc->ndis_stat_callout, CALLOUT_MPSAFE);
if (sc->ndis_iftype == PCMCIABus) {
@ -602,6 +612,7 @@ ndis_attach(dev)
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_xferitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block);
/* Call driver's init routine. */
@ -696,6 +707,8 @@ ndis_attach(dev)
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_mtu = ETHERMTU;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
if (sc->ndis_iftype == PNPBus)
ifp->if_flags |= IFF_NEEDSGIANT;
ifp->if_ioctl = ndis_ioctl;
ifp->if_start = ndis_start;
ifp->if_init = ndis_init;
@ -934,11 +947,16 @@ ndis_attach(dev)
}
fail:
if (error)
if (error) {
ndis_detach(dev);
else
/* We're done talking to the NIC for now; halt it. */
ndis_halt_nic(sc);
return (error);
}
if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
return (error);
/* We're done talking to the NIC for now; halt it. */
ndis_halt_nic(sc);
return(error);
}
@ -1029,6 +1047,8 @@ ndis_detach(dev)
IoFreeWorkItem(sc->ndis_resetitem);
if (sc->ndis_inputitem != NULL)
IoFreeWorkItem(sc->ndis_inputitem);
if (sc->ndisusb_xferitem != NULL)
IoFreeWorkItem(sc->ndisusb_xferitem);
bus_generic_detach(dev);
ndis_unload_driver(sc);
@ -1538,7 +1558,7 @@ ndis_txeof(adapter, packet, status)
ndis_free_packet(packet);
m_freem(m);
NDIS_LOCK(sc);
NDISMTX_LOCK(sc);
sc->ndis_txarray[idx] = NULL;
sc->ndis_txpending++;
@ -1550,7 +1570,7 @@ ndis_txeof(adapter, packet, status)
sc->ndis_tx_timer = 0;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
NDIS_UNLOCK(sc);
NDISMTX_UNLOCK(sc);
IoQueueWorkItem(sc->ndis_startitem,
(io_workitem_func)ndis_starttask_wrap,
@ -1575,9 +1595,9 @@ ndis_linksts(adapter, status, sbuf, slen)
/* Event list is all full up, drop this one. */
NDIS_LOCK(sc);
NDISMTX_LOCK(sc);
if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
NDIS_UNLOCK(sc);
NDISMTX_UNLOCK(sc);
return;
}
@ -1587,7 +1607,7 @@ ndis_linksts(adapter, status, sbuf, 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);
NDISMTX_UNLOCK(sc);
return;
}
bcopy((char *)sbuf,
@ -1596,7 +1616,7 @@ ndis_linksts(adapter, status, sbuf, 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);
NDISMTX_UNLOCK(sc);
return;
}
@ -1966,8 +1986,14 @@ ndis_init(xsc)
*/
ndis_stop(sc);
if (ndis_init_nic(sc))
return;
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;
}
}
/* Init our MAC address */
@ -2688,6 +2714,8 @@ ndis_getstate_80211(sc)
ifp = sc->ifp;
ic = ifp->if_l2com;
vap = TAILQ_FIRST(&ic->ic_vaps);
if (vap == NULL)
return;
ni = vap->iv_bss;
if (!NDIS_INITIALIZED(sc))
@ -3173,7 +3201,9 @@ ndis_stop(sc)
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
NDIS_UNLOCK(sc);
ndis_halt_nic(sc);
if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0) ||
sc->ndisusb_status & NDISUSB_STATUS_DETACH)
ndis_halt_nic(sc);
NDIS_LOCK(sc);
for (i = 0; i < NDIS_EVENTS; i++) {

View File

@ -53,6 +53,9 @@ __FBSDID("$FreeBSD$");
#include <net80211/ieee80211_var.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <compat/ndis/pe_var.h>
#include <compat/ndis/cfg_var.h>
#include <compat/ndis/resource_var.h>

View File

@ -54,6 +54,8 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <compat/ndis/pe_var.h>
#include <compat/ndis/cfg_var.h>

View File

@ -65,12 +65,16 @@ __FBSDID("$FreeBSD$");
#include <compat/ndis/resource_var.h>
#include <compat/ndis/ntoskrnl_var.h>
#include <compat/ndis/ndis_var.h>
#include <compat/ndis/usbd_var.h>
#include <dev/if_ndis/if_ndisvar.h>
SYSCTL_NODE(_hw, OID_AUTO, ndisusb, CTLFLAG_RD, 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 *);
@ -86,7 +90,7 @@ static device_method_t ndis_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ndisusb_match),
DEVMETHOD(device_attach, ndisusb_attach),
DEVMETHOD(device_detach, ndis_detach),
DEVMETHOD(device_detach, ndisusb_detach),
DEVMETHOD(device_shutdown, ndis_shutdown),
/* bus interface */
@ -107,9 +111,32 @@ 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->vendor == t->ndis_vid) &&
(uaa->product == 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 (windrv_lookup(0, "USB Bus") == NULL)
@ -118,35 +145,103 @@ ndisusb_match(device_t self)
if (uaa->iface != NULL)
return (UMATCH_NONE);
return (UMATCH_NONE);
db = windrv_match((matchfuncptr)ndisusb_devcompare, self);
if (db == NULL)
return (UMATCH_NONE);
return (UMATCH_VENDOR_PRODUCT);
}
static int
ndisusb_attach(device_t self)
{
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;
usbd_status status;
sc = (struct ndis_softc *)dummy;
if (uaa->device == NULL)
return ENXIO;
db = windrv_match((matchfuncptr)ndisusb_devcompare, self);
if (db == NULL)
return (ENXIO);
sc->ndis_dev = self;
sc->ndis_dobj = db->windrv_object;
sc->ndis_regvals = db->windrv_regvals;
sc->ndis_iftype = PNPBus;
/* Create PDO for this device instance */
drv = windrv_lookup(0, "USB Bus");
windrv_create_pdo(drv, self);
status = usbd_set_config_no(uaa->device, NDISUSB_CONFIG_NO, 0);
if (status != USBD_NORMAL_COMPLETION) {
device_printf(self, "setting config no failed\n");
return (ENXIO);
}
/* Figure out exactly which device we matched. */
t = db->windrv_devlist;
while (t->ndis_name != NULL) {
if ((uaa->vendor == t->ndis_vid) &&
(uaa->product == t->ndis_did)) {
sc->ndis_devidx = devidx;
break;
}
t++;
devidx++;
}
if (ndis_attach(self) != 0)
return ENXIO;
usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, uaa->device, self);
return 0;
}
static int
ndisusb_detach(device_t self)
{
int i;
struct ndis_softc *sc = device_get_softc(self);
struct usb_attach_arg *uaa = device_get_ivars(self);
sc->ndisusb_status |= NDISUSB_STATUS_DETACH;
for (i = 0; i < NDISUSB_ENDPT_MAX; i++) {
if (sc->ndisusb_ep[i] == NULL)
continue;
usbd_abort_pipe(sc->ndisusb_ep[i]);
usbd_close_pipe(sc->ndisusb_ep[i]);
sc->ndisusb_ep[i] = NULL;
}
if (sc->ndisusb_iin_buf != NULL) {
free(sc->ndisusb_iin_buf, M_USBDEV);
sc->ndisusb_iin_buf = NULL;
}
ndis_pnpevent_nic(self, NDIS_PNP_EVENT_SURPRISE_REMOVED);
ndis_cancel_timerlist();
usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, uaa->device, self);
return ndis_detach(self);
}
static struct resource_list *
ndis_get_resource_list(device_t dev, device_t child)
{

View File

@ -58,6 +58,12 @@ struct ndis_pccard_type {
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;
@ -107,6 +113,17 @@ struct ndis_vap {
};
#define NDIS_VAP(vap) ((struct ndis_vap *)(vap))
#define NDISUSB_CONFIG_NO 1
#define NDISUSB_IFACE_INDEX 0
#define NDISUSB_INTR_TIMEOUT 1000
#define NDISUSB_TX_TIMEOUT 10000
struct ndisusb_xfer {
usbd_xfer_handle nx_xfer;
usbd_private_handle nx_priv;
usbd_status nx_status;
list_entry nx_xferlist;
};
struct ndis_softc {
struct ifnet *ifp;
struct ifmedia ifmedia; /* media info */
@ -183,7 +200,32 @@ struct ndis_softc {
enum ieee80211_state, int);
int ndis_tx_timer;
int ndis_hang_timer;
io_workitem *ndisusb_xferitem;
list_entry ndisusb_xferlist;
kspin_lock ndisusb_xferlock;
#define NDISUSB_ENDPT_BOUT 0
#define NDISUSB_ENDPT_BIN 1
#define NDISUSB_ENDPT_IIN 2
#define NDISUSB_ENDPT_IOUT 3
#define NDISUSB_ENDPT_MAX 4
usbd_pipe_handle ndisusb_ep[NDISUSB_ENDPT_MAX];
char *ndisusb_iin_buf;
int ndisusb_status;
#define NDISUSB_STATUS_DETACH 0x1
};
#define NDIS_LOCK(_sc) mtx_lock(&(_sc)->ndis_mtx)
#define NDIS_UNLOCK(_sc) mtx_unlock(&(_sc)->ndis_mtx)
#define NDISMTX_LOCK(_sc) mtx_lock(&(_sc)->ndis_mtx)
#define NDISMTX_UNLOCK(_sc) mtx_unlock(&(_sc)->ndis_mtx)
#define NDISUSB_LOCK(_sc) mtx_lock(&Giant)
#define NDISUSB_UNLOCK(_sc) mtx_unlock(&Giant)
#define NDIS_LOCK(_sc) do { \
if ((_sc)->ndis_iftype == PNPBus) \
NDISUSB_LOCK(_sc); \
NDISMTX_LOCK(_sc); \
} while (0)
#define NDIS_UNLOCK(_sc) do { \
if ((_sc)->ndis_iftype == PNPBus) \
NDISUSB_UNLOCK(_sc); \
NDISMTX_UNLOCK(_sc); \
} while (0)

View File

@ -6,6 +6,7 @@ KMOD= ndis
SRCS= subr_pe.c subr_ndis.c subr_hal.c subr_ntoskrnl.c kern_ndis.c
SRCS+= kern_windrv.c subr_usbd.c
SRCS+= device_if.h bus_if.h pci_if.h vnode_if.h
SRCS+= opt_usb.h usbdevs.h
.if ${MACHINE_ARCH} == "amd64"
SRCS+= winx64_wrap.S

View File

@ -62,8 +62,10 @@ static struct section
*find_section (const char *);
static void dump_deviceids_pci (void);
static void dump_deviceids_pcmcia (void);
static void 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);
@ -83,6 +85,7 @@ inf_parse (FILE *fp, FILE *outfp)
dump_deviceids_pci();
dump_deviceids_pcmcia();
dump_deviceids_usb();
fprintf(outfp, "#ifdef NDIS_REGVALS\n");
dump_regvals();
fprintf(outfp, "#endif /* NDIS_REGVALS */\n");
@ -251,6 +254,30 @@ dump_pci_id(const char *s)
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 void
dump_deviceids_pci()
{
@ -437,6 +464,99 @@ dump_deviceids_pcmcia()
return;
}
static void
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;
}
static void
dump_addreg(const char *s, int devidx)
{

View File

@ -69,6 +69,11 @@ struct ndis_pccard_type {
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[] = {
@ -84,6 +89,13 @@ static struct ndis_pccard_type ndis_devs_pccard[] = {
};
#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,
@ -223,6 +235,10 @@ windrv_modevent(mod, cmd, arg)
#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:
@ -234,6 +250,9 @@ windrv_modevent(mod, cmd, arg)
#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: