PERFORCE change 142519 for review
Hans Petter Selasky
hselasky at c2i.net
Fri May 30 08:19:02 UTC 2008
Hi,
I will get your USB files ported over to the USB P4 project at FreeBSD when
you are finished, because there is a different USB API there. Maybe you can
drop me a note when the USB support is complete ?
--HPS
On Thursday 29 May 2008, Weongyo Jeong wrote:
> http://perforce.freebsd.org/chv.cgi?CH=142519
>
> Change 142519 by weongyo at weongyo_ws on 2008/05/29 05:16:48
>
> Commit the basic implementation of NDIS USB support. With this
> changeset, we can support few NDIS USB drivers (e.g. currently U-Khan
> UW-2054u).
>
> Affected files ...
>
> .. //depot/projects/ndisusb/sys/compat/ndis/cfg_var.h#2 edit
> .. //depot/projects/ndisusb/sys/compat/ndis/hal_var.h#2 edit
> .. //depot/projects/ndisusb/sys/compat/ndis/kern_ndis.c#2 edit
> .. //depot/projects/ndisusb/sys/compat/ndis/kern_windrv.c#2 edit
> .. //depot/projects/ndisusb/sys/compat/ndis/ndis_var.h#2 edit
> .. //depot/projects/ndisusb/sys/compat/ndis/ntoskrnl_var.h#2 edit
> .. //depot/projects/ndisusb/sys/compat/ndis/pe_var.h#2 edit
> .. //depot/projects/ndisusb/sys/compat/ndis/resource_var.h#2 edit
> .. //depot/projects/ndisusb/sys/compat/ndis/subr_hal.c#2 edit
> .. //depot/projects/ndisusb/sys/compat/ndis/subr_ndis.c#2 edit
> .. //depot/projects/ndisusb/sys/compat/ndis/subr_ntoskrnl.c#2 edit
> .. //depot/projects/ndisusb/sys/compat/ndis/subr_pe.c#2 edit
> .. //depot/projects/ndisusb/sys/compat/ndis/subr_usbd.c#2 edit
> .. //depot/projects/ndisusb/sys/compat/ndis/usbd_var.h#2 edit
> .. //depot/projects/ndisusb/sys/dev/if_ndis/if_ndis.c#2 edit
> .. //depot/projects/ndisusb/sys/dev/if_ndis/if_ndis_pccard.c#2 edit
> .. //depot/projects/ndisusb/sys/dev/if_ndis/if_ndis_pci.c#2 edit
> .. //depot/projects/ndisusb/sys/dev/if_ndis/if_ndis_usb.c#2 edit
> .. //depot/projects/ndisusb/sys/dev/if_ndis/if_ndisvar.h#2 edit
> .. //depot/projects/ndisusb/usr.sbin/ndiscvt/inf.c#2 edit
> .. //depot/projects/ndisusb/usr.sbin/ndiscvt/windrv_stub.c#2 edit
>
> Differences ...
>
> ==== //depot/projects/ndisusb/sys/compat/ndis/cfg_var.h#2 (text+ko) ====
>
> @@ -29,7 +29,7 @@
> * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> * THE POSSIBILITY OF SUCH DAMAGE.
> *
> - * $FreeBSD: src/sys/compat/ndis/cfg_var.h,v 1.3 2005/01/05 22:34:36 imp
> Exp $ + * $FreeBSD$
> */
>
> #ifndef _CFG_VAR_H_
>
> ==== //depot/projects/ndisusb/sys/compat/ndis/hal_var.h#2 (text+ko) ====
>
> @@ -29,7 +29,7 @@
> * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> * THE POSSIBILITY OF SUCH DAMAGE.
> *
> - * $FreeBSD: src/sys/compat/ndis/hal_var.h,v 1.8 2005/04/11 02:02:34 wpaul
> Exp $ + * $FreeBSD$
> */
>
> #ifndef _HAL_VAR_H_
>
> ==== //depot/projects/ndisusb/sys/compat/ndis/kern_ndis.c#2 (text+ko) ====
>
> @@ -31,7 +31,7 @@
> */
>
> #include <sys/cdefs.h>
> -__FBSDID("$FreeBSD: src/sys/compat/ndis/kern_ndis.c,v 1.97 2008/02/01
> 19:36:22 phk Exp $"); +__FBSDID("$FreeBSD$");
>
> #include <sys/param.h>
> #include <sys/systm.h>
> @@ -65,6 +65,9 @@
> #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>
>
> ==== //depot/projects/ndisusb/sys/compat/ndis/kern_windrv.c#2 (text+ko)
> ====
>
> @@ -31,7 +31,7 @@
> */
>
> #include <sys/cdefs.h>
> -__FBSDID("$FreeBSD: src/sys/compat/ndis/kern_windrv.c,v 1.14 2007/05/20
> 22:03:57 jeff Exp $"); +__FBSDID("$FreeBSD$");
>
> #include <sys/param.h>
> #include <sys/systm.h>
> @@ -56,6 +56,9 @@
> #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>
>
> ==== //depot/projects/ndisusb/sys/compat/ndis/ndis_var.h#2 (text+ko) ====
>
> @@ -29,7 +29,7 @@
> * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> * THE POSSIBILITY OF SUCH DAMAGE.
> *
> - * $FreeBSD: src/sys/compat/ndis/ndis_var.h,v 1.48 2007/12/02 04:04:42
> thompsa Exp $ + * $FreeBSD$
> */
>
> #ifndef _NDIS_VAR_H_
>
> ==== //depot/projects/ndisusb/sys/compat/ndis/ntoskrnl_var.h#2 (text+ko)
> ====
>
> @@ -29,7 +29,7 @@
> * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> * THE POSSIBILITY OF SUCH DAMAGE.
> *
> - * $FreeBSD: src/sys/compat/ndis/ntoskrnl_var.h,v 1.44 2007/12/02 08:54:50
> thompsa Exp $ + * $FreeBSD$
> */
>
> #ifndef _NTOSKRNL_VAR_H_
> @@ -987,7 +987,13 @@
> } 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;
> };
> @@ -995,6 +1001,9 @@
> #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) \
> @@ -1007,6 +1016,10 @@
> (cancel_func)InterlockedExchangePointer( \
> (void *)&(ip)->irp_cancelfunc, (void *)(func))
>
> +#define IoSetCancelValue(irp, val) \
> + (uint32_t)InterlockedExchangePointer( \
> + (void *)&(ip)->irp_cancel, (void *)(val))
> +
> #define IoGetCurrentIrpStackLocation(irp) \
> (irp)->irp_tail.irp_overlay.irp_csl
>
> @@ -1033,6 +1046,8 @@
>
> #define IoMarkIrpPending(irp) \
> IoGetCurrentIrpStackLocation(irp)->isl_ctl |= SL_PENDING_RETURNED
> +#define IoUnmarkIrpPending(irp) \
> + IoGetCurrentIrpStackLocation(irp)->isl_ctl &= ~SL_PENDING_RETURNED
>
> #define IoCopyCurrentIrpStackLocationToNext(irp) \
> do { \
> @@ -1189,14 +1204,20 @@
> #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_CANCELLED 0xC0000120
> #define STATUS_NOT_FOUND 0xC0000225
> +#define STATUS_DEVICE_REMOVED 0xC00002B6
>
> #define STATUS_WAIT_0 0x00000000
>
> @@ -1363,6 +1384,7 @@
> 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 *);
>
> ==== //depot/projects/ndisusb/sys/compat/ndis/pe_var.h#2 (text+ko) ====
>
> @@ -29,7 +29,7 @@
> * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> * THE POSSIBILITY OF SUCH DAMAGE.
> *
> - * $FreeBSD: src/sys/compat/ndis/pe_var.h,v 1.14 2005/10/26 18:46:27 wpaul
> Exp $ + * $FreeBSD$
> */
>
> #ifndef _PE_VAR_H_
>
> ==== //depot/projects/ndisusb/sys/compat/ndis/resource_var.h#2 (text+ko)
> ====
>
> @@ -29,7 +29,7 @@
> * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> * THE POSSIBILITY OF SUCH DAMAGE.
> *
> - * $FreeBSD: src/sys/compat/ndis/resource_var.h,v 1.3 2005/02/16 05:41:17
> wpaul Exp $ + * $FreeBSD$
> */
>
> #ifndef _RESOURCE_VAR_H_
>
> ==== //depot/projects/ndisusb/sys/compat/ndis/subr_hal.c#2 (text+ko) ====
>
> @@ -31,7 +31,7 @@
> */
>
> #include <sys/cdefs.h>
> -__FBSDID("$FreeBSD: src/sys/compat/ndis/subr_hal.c,v 1.28 2006/05/16
> 14:37:57 phk Exp $"); +__FBSDID("$FreeBSD$");
>
> #include <sys/param.h>
> #include <sys/types.h>
>
> ==== //depot/projects/ndisusb/sys/compat/ndis/subr_ndis.c#2 (text+ko) ====
>
> @@ -31,7 +31,7 @@
> */
>
> #include <sys/cdefs.h>
> -__FBSDID("$FreeBSD: src/sys/compat/ndis/subr_ndis.c,v 1.112 2008/05/15
> 04:29:28 weongyo Exp $"); +__FBSDID("$FreeBSD$");
>
> /*
> * This file implements a translation layer between the BSD networking
> @@ -95,6 +95,8 @@
>
> #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>
>
> ==== //depot/projects/ndisusb/sys/compat/ndis/subr_ntoskrnl.c#2 (text+ko)
> ====
>
> @@ -31,7 +31,7 @@
> */
>
> #include <sys/cdefs.h>
> -__FBSDID("$FreeBSD: src/sys/compat/ndis/subr_ntoskrnl.c,v 1.94 2007/12/25
> 17:51:56 rwatson Exp $"); +__FBSDID("$FreeBSD$");
>
> #include <sys/ctype.h>
> #include <sys/unistd.h>
> @@ -207,7 +207,6 @@
> 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);
> @@ -249,6 +248,7 @@
> 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 void dummy(void);
>
> static struct mtx ntoskrnl_dispatchlock;
> @@ -1141,16 +1141,18 @@
> 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
> @@ -1184,24 +1186,27 @@
> 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));
> +
> + sl = IoGetCurrentIrpStackLocation(ip);
> + IoSkipCurrentIrpStackLocation(ip);
> +
> + do {
> + if (sl->isl_ctl & SL_PENDING_RETURNED)
> + ip->irp_pendingreturned = TRUE;
>
> - for (i = ip->irp_currentstackloc; i < (uint32_t)ip->irp_stackcnt; i++) {
> - if (ip->irp_currentstackloc < ip->irp_stackcnt - 1) {
> - IoSkipCurrentIrpStackLocation(ip);
> + 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 &&
> @@ -1212,12 +1217,16 @@
> 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. */
>
> @@ -2669,7 +2678,7 @@
> * here, but it doesn't.
> */
>
> -static uint8_t
> +uint8_t
> MmIsAddressValid(vaddr)
> void *vaddr;
> {
> @@ -4244,6 +4253,37 @@
> 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 void
> dummy()
> {
> @@ -4426,6 +4466,8 @@
> IMPORT_CFUNC(WmiTraceMessage, 0),
> IMPORT_SFUNC(KeQuerySystemTime, 1),
> IMPORT_CFUNC(KeTickCount, 0),
> + IMPORT_SFUNC(KeDelayExecutionThread, 3),
> + IMPORT_SFUNC(KeQueryInterruptTime, 0),
>
> /*
> * This last entry is a catch-all for any function we haven't
>
> ==== //depot/projects/ndisusb/sys/compat/ndis/subr_pe.c#2 (text+ko) ====
>
> @@ -31,7 +31,7 @@
> */
>
> #include <sys/cdefs.h>
> -__FBSDID("$FreeBSD: src/sys/compat/ndis/subr_pe.c,v 1.13 2007/04/06
> 11:18:57 pjd Exp $"); +__FBSDID("$FreeBSD$");
>
> /*
> * This file contains routines for relocating and dynamically linking
>
> ==== //depot/projects/ndisusb/sys/compat/ndis/subr_usbd.c#2 (text+ko) ====
>
> @@ -31,7 +31,7 @@
> */
>
> #include <sys/cdefs.h>
> -__FBSDID("$FreeBSD: src/sys/compat/ndis/subr_usbd.c,v 1.3 2005/05/05
> 03:56:09 wpaul Exp $"); +__FBSDID("$FreeBSD$");
>
> #include <sys/param.h>
> #include <sys/systm.h>
> @@ -45,10 +45,24 @@
> #include <sys/module.h>
> #include <sys/conf.h>
> #include <sys/mbuf.h>
> +#include <sys/socket.h>
> +#include <machine/bus.h>
> #include <sys/bus.h>
>
> #include <sys/queue.h>
>
> +#include <net/if.h>
> +#include <net/if_media.h>
> +#include <net80211/ieee80211_var.h>
> +#include <net80211/ieee80211_ioctl.h>
> +
> +#include <dev/usb/usb.h>
> +#include <dev/usb/usbdi.h>
> +#include <dev/usb/usbdi_util.h>
> +#include <dev/usb/usbdivar.h>
> +#include <dev/usb/usb_quirks.h>
> +#include "usbdevs.h"
> +
> #include <compat/ndis/pe_var.h>
> #include <compat/ndis/cfg_var.h>
> #include <compat/ndis/resource_var.h>
> @@ -56,18 +70,56 @@
> #include <compat/ndis/ndis_var.h>
> #include <compat/ndis/hal_var.h>
> #include <compat/ndis/usbd_var.h>
> +#include <dev/if_ndis/if_ndisvar.h>
>
> static driver_object usbd_driver;
>
> -static uint32_t usbd_iodispatch(device_object *, irp *);
> +static int32_t usbd_func_bulkintr(irp *);
> +static int32_t usbd_func_bulkintr_iin(irp *);
> +static int32_t usbd_func_vendorclass(irp *);
> +static int32_t usbd_func_selconf(irp *);
> +static int32_t usbd_func_getdesc(irp *);
> +static union usbd_urb *usbd_geturb(irp *);
> +static usbd_status usbd_init_ndispipe(irp *, usb_endpoint_descriptor_t *);
> +static usbd_xfer_handle usbd_init_ndisxfer(irp *,
> usb_endpoint_descriptor_t *, + void *, uint32_t);
> +static void usbd_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
> +static int32_t usbd_iodispatch(device_object *, irp *);
> +static int32_t usbd_ioinvalid(device_object *, irp *);
> +static int32_t usbd_irpcancel(device_object *, irp *);
> +static void usbd_irpcancel_cb(void *);
> +static int32_t usbd_irpcancel_iin(device_object *, irp *);
> +static void usbd_irpcancel_iin_cb(void *);
> +static int32_t usbd_submit_urb(irp *);
> +static int32_t usbd_urb2nt(int32_t);
> +static void usbd_xfereof(usbd_xfer_handle, usbd_private_handle,
> usbd_status); +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 void dummy(void);
> +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_irpcancel_wrap;
> +static funcptr usbd_irpcancel_iin_wrap;
>
> int
> usbd_libinit(void)
> {
> image_patch_table *patch;
> + int i;
>
> patch = usbd_functbl;
> while (patch->ipt_func != NULL) {
> @@ -77,14 +129,26 @@
> 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_irpcancel,
> + (funcptr *)&usbd_irpcancel_wrap, 2, WINDRV_WRAP_STDCALL);
> + windrv_wrap((funcptr)usbd_irpcancel_iin,
> + (funcptr *)&usbd_irpcancel_iin_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;
> + (driver_dispatch)usbd_iodispatch_wrap;
>
> return(0);
> }
> @@ -100,17 +164,925 @@
> patch++;
> }
>
> + windrv_unwrap(usbd_ioinvalid_wrap);
> + windrv_unwrap(usbd_iodispatch_wrap);
> + windrv_unwrap(usbd_irpcancel_wrap);
> + windrv_unwrap(usbd_irpcancel_iin_wrap);
> +
> free(usbd_driver.dro_drivername.us_buf, M_DEVBUF);
>
> return(0);
> }
>
> -static uint32_t
> +static int32_t
> usbd_iodispatch(dobj, ip)
> device_object *dobj;
> irp *ip;
> {
> - return(0);
> + 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(dobj, ip)
> + 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);
> +}
> +
> +/* Convert USBD_STATUS to NTSTATUS */
> +static int32_t
> +usbd_urb2nt(status)
> + int32_t status;
> +{
> +
> + switch (status) {
> + case USBD_STATUS_SUCCESS:
> + return (STATUS_SUCCESS);
> + case USBD_STATUS_DEVICE_GONE:
> + return (STATUS_DEVICE_REMOVED);
> + 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);
> + default:
> + break;
> + }
> +
> + return (STATUS_FAILURE);
> +}
> +
> +/* Convert FreeBSD's usbd_status to USBD_STATUS */
> +static int32_t
> +usbd_usb2urb(int urb_status)
> +{
> +
> + switch (urb_status) {
> + case USBD_NORMAL_COMPLETION:
> + return (USBD_STATUS_SUCCESS);
> + case USBD_IN_PROGRESS:
> + return (USBD_STATUS_PENDING);
> + case USBD_TIMEOUT:
> + return (USBD_STATUS_TIMEOUT);
> + case USBD_SHORT_XFER:
> + return (USBD_STATUS_ERROR_SHORT_TRANSFER);
> + case USBD_IOERROR:
> + return (USBD_STATUS_INVALID_PIPE_HANDLE);
> + case USBD_NOMEM:
> + return (USBD_STATUS_NO_MEMORY);
> + case USBD_INVAL:
> + return (USBD_STATUS_REQUEST_FAILED);
> + case USBD_NOT_STARTED:
> + case USBD_TOO_DEEP:
> + case USBD_NO_POWER:
> + return (USBD_STATUS_DEVICE_GONE);
> + default:
> + break;
> + }
> +
> + return (USBD_STATUS_NOT_SUPPORTED);
> +}
> +
> +static union usbd_urb *
> +usbd_geturb(ip)
> + 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(ip)
> + irp *ip;
> +{
> + device_t dev = IRP_NDIS_DEV(ip);
> + int32_t status;
> + union usbd_urb *urb;
> +
> + urb = usbd_geturb(ip);
> + switch (urb->uu_hdr.uuh_func) {
> + case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
> + status = usbd_func_bulkintr(ip);
> + 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);
> + break;
> + case URB_FUNCTION_SELECT_CONFIGURATION:
> + status = usbd_func_selconf(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(ip)
> + irp *ip;
> +{
> + device_t dev = IRP_NDIS_DEV(ip);
> + int i;
> + struct usb_attach_arg *uaa = device_get_ivars(dev);
> + struct usbd_urb_control_descriptor_request *ctldesc;
> + uint32_t len;
> + union usbd_urb *urb;
> + usb_config_descriptor_t cd, *cdp;
> + usbd_status status;
> +
> + urb = usbd_geturb(ip);
> + ctldesc = &urb->uu_ctldesc;
> + if (ctldesc->ucd_desctype == UDESC_CONFIG) {
> + /* Get the short config descriptor. */
> + status = usbd_get_config_desc(uaa->device, ctldesc->ucd_idx,
> + &cd);
> + if (status != USBD_NORMAL_COMPLETION) {
> + ctldesc->ucd_trans_buflen = 0;
> + return usbd_usb2urb(status);
> + }
> + len = UGETW(cd.wTotalLength);
> + /* Get the full descriptor. Try a few times for slow devices. */
> + for (i = 0; i < 3; i++) {
> + status = usbd_get_desc(uaa->device,
> + ctldesc->ucd_desctype, ctldesc->ucd_idx,
> + len, ctldesc->ucd_trans_buf);
> + if (status == USBD_NORMAL_COMPLETION)
> + break;
> + usbd_delay_ms(uaa->device, 200);
> + }
> + if (status != USBD_NORMAL_COMPLETION) {
> + ctldesc->ucd_trans_buflen = 0;
> + return usbd_usb2urb(status);
> + }
> +
> + cdp = (usb_config_descriptor_t *)ctldesc->ucd_trans_buf;
> + if (cdp->bDescriptorType != UDESC_CONFIG) {
> + device_printf(dev, "bad desc %d\n",
> + cdp->bDescriptorType);
> + status = USBD_INVAL;
> + }
> + } else if (ctldesc->ucd_desctype == UDESC_STRING) {
> + /* Try a few times for slow devices. */
> + for (i = 0; i < 3; i++) {
> + status = usbd_get_string(uaa->device,
> + (UDESC_STRING << 8) + ctldesc->ucd_idx,
> + ctldesc->ucd_trans_buf, ctldesc->ucd_trans_buflen);
> + if (status != USBD_NORMAL_COMPLETION)
> + break;
> + usbd_delay_ms(uaa->device, 200);
> + }
> + } else
> + status = usbd_get_desc(uaa->device, ctldesc->ucd_desctype,
> + ctldesc->ucd_idx, ctldesc->ucd_trans_buflen,
> + ctldesc->ucd_trans_buf);
> +
> + if (status != USBD_NORMAL_COMPLETION) {
> + ctldesc->ucd_trans_buflen = 0;
> + return usbd_usb2urb(status);
> + }
> +
> + ctldesc->ucd_trans_buflen = status;
> + ip->irp_iostat.isb_info = status;
> + return (USBD_STATUS_SUCCESS);
> +}
> +
> +static int32_t
> +usbd_func_selconf(ip)
> + irp *ip;
> +{
> + device_t dev = IRP_NDIS_DEV(ip);
> + int i, j;
> + struct usb_attach_arg *uaa = device_get_ivars(dev);
> + 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;
> + usbd_device_handle udev = uaa->device;
> + usbd_interface_handle iface;
> + usbd_status 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(USBD_NORMAL_COMPLETION);
> + }
> +
> + if (conf->bConfigurationValue > NDISUSB_CONFIG_NO)
> + device_printf(dev, "warning: config_no is larger than default");
> +
> + intf = &selconf->usc_intf;
> + for (i = 0; i < conf->bNumInterface && intf->uii_len > 0; i++) {
> + ret = usbd_device2interface_handle(uaa->device,
> + intf->uii_intfnum, &iface);
> + if (ret != USBD_NORMAL_COMPLETION) {
> + device_printf(dev,
> + "getting interface handle failed: %s\n",
> + usbd_errstr(ret));
> + return usbd_usb2urb(ret);
> + }
> +
> + ret = usbd_set_interface(iface, intf->uii_altset);
> + if (ret != USBD_NORMAL_COMPLETION) {
> + device_printf(dev,
> + "setting alternate interface failed: %s\n",
> + usbd_errstr(ret));
> + return usbd_usb2urb(ret);
> + }
> +
> + for (j = 0; j < iface->idesc->bNumEndpoints; j++) {
> + if (j >= intf->uii_numeps) {
> + device_printf(dev,
> + "endpoint %d and above are ignored",
> + intf->uii_numeps);
> + break;
> + }
> + edesc = iface->endpoints[j].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);
> + 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 = 1, 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 int32_t
> +usbd_func_vendorclass(ip)
> + irp *ip;
> +{
> + device_t dev = IRP_NDIS_DEV(ip);
> + struct usb_attach_arg *uaa = device_get_ivars(dev);
> + struct usbd_urb_vendor_or_class_request *vcreq;
> + uint8_t type = 0;
> + union usbd_urb *urb;
> + usb_device_request_t req;
> + usbd_status status;
> +
> + urb = usbd_geturb(ip);
> + 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 reach. */
> + break;
> + }
> +
> + vcreq = &urb->uu_vcreq;
> + if (!(vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN))
> + type |= UT_WRITE;
> + else
> + type |= UT_READ;
> + 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);
> +
> + status = usbd_do_request(uaa->device, &req, vcreq->uvc_trans_buf);
> +
> + return usbd_usb2urb(status);
> +}
> +
> +static void
> +usbd_irpcancel_iin_cb(priv)
> + void *priv;
> +{
> + struct ndisusb_cancel *nc = priv;
> + irp *ip = nc->ip;
> + device_t dev = IRP_NDIS_DEV(ip);
> + struct ndis_softc *sc = device_get_softc(dev);
> + struct usb_attach_arg *uaa = device_get_ivars(dev);
> + usbd_status status;
> + usbd_xfer_handle xfer;
> +
> + usb_rem_task(uaa->device, &nc->task);
> + free(priv, M_USBDEV);
> +
> + xfer = IRP_NDISUSB_XFER(ip);
> + IRP_NDISUSB_XFER(ip) = NULL;
> +
> + status = usbd_abort_pipe(sc->ndisusb_ep[NDISUSB_ENDPT_IIN]);
> + if (status != USBD_NORMAL_COMPLETION)
> + device_printf(dev, "IIN can't be canceld");
> +}
> +
> +static int32_t
> +usbd_irpcancel_iin(dobj, ip)
> + device_object *dobj;
> + irp *ip;
> +{
> + device_t dev = IRP_NDIS_DEV(ip);
> + struct ndisusb_cancel *nc;
> + struct usb_attach_arg *uaa = device_get_ivars(dev);
> +
> + /* XXX see the description of usbd_irpcancel() */
> + nc = malloc(sizeof(struct ndisusb_cancel), M_USBDEV, M_NOWAIT | M_ZERO);
> + if (nc == NULL) {
> + ip->irp_cancel = FALSE;
> + IoReleaseCancelSpinLock(ip->irp_cancelirql);
> + return (-1);
> + }
> +
> + nc->ip = ip;
> + usb_init_task(&nc->task, usbd_irpcancel_iin_cb, nc);
> + usb_add_task(uaa->device, &nc->task, USB_TASKQ_DRIVER);
> +
> + IoReleaseCancelSpinLock(ip->irp_cancelirql);
> +
> + return (0);
> +}
> +
> +static int32_t
> +usbd_func_bulkintr_iin(ip)
> + irp *ip;
>
> >>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list