Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 30 May 2008 09:20:28 +0200
From:      Hans Petter Selasky <hselasky@c2i.net>
To:        Weongyo Jeong <weongyo@freebsd.org>
Cc:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   Re: PERFORCE change 142519 for review
Message-ID:  <200805300920.28816.hselasky@c2i.net>
In-Reply-To: <200805290517.m4T5HbDm043288@repoman.freebsd.org>
References:  <200805290517.m4T5HbDm043288@repoman.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
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@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) <<<





Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200805300920.28816.hselasky>