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>