From 9eed4afb3d229d0a7f393f7cbf4949fee52ba33d Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Fri, 3 Feb 2012 16:03:42 +0000 Subject: [PATCH] [USBCCGP] - Remove hack of forwarding pdo requests to lower device object of fdo - Implement handling of reset port and cycle port - IOCTL_INTERNAL_USB_RESET_PORT / IOCTL_INTERNAL_USB_CYCLE_PORT now need to be implemented in usbhub svn path=/branches/usb-bringup-trunk/; revision=55396 --- drivers/usb/usbccgp/fdo.c | 178 +++++++++++++++++++++++++++++++++- drivers/usb/usbccgp/pdo.c | 18 ++++ drivers/usb/usbccgp/usbccgp.c | 4 + drivers/usb/usbccgp/usbccgp.h | 5 + 4 files changed, 204 insertions(+), 1 deletion(-) diff --git a/drivers/usb/usbccgp/fdo.c b/drivers/usb/usbccgp/fdo.c index d4bfacf30ac..04d38e927bd 100644 --- a/drivers/usb/usbccgp/fdo.c +++ b/drivers/usb/usbccgp/fdo.c @@ -277,7 +277,7 @@ FDO_CreateChildPdo( // PDODeviceExtension->Common.IsFDO = FALSE; PDODeviceExtension->FunctionDescriptor = &FDODeviceExtension->FunctionDescriptor[Index]; - PDODeviceExtension->NextDeviceObject = FDODeviceExtension->NextDeviceObject; //DeviceObject; HACK + PDODeviceExtension->NextDeviceObject = DeviceObject; PDODeviceExtension->FunctionIndex = Index; PDODeviceExtension->FDODeviceExtension = FDODeviceExtension; PDODeviceExtension->InterfaceList = FDODeviceExtension->InterfaceList; @@ -498,8 +498,182 @@ FDO_HandlePnp( Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; +} + +NTSTATUS +FDO_HandleResetCyclePort( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + NTSTATUS Status; + PFDO_DEVICE_EXTENSION FDODeviceExtension; + PLIST_ENTRY ListHead, Entry; + LIST_ENTRY TempList; + PUCHAR ResetActive; + PIRP ListIrp; + KIRQL OldLevel; + + // + // get device extension + // + FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + ASSERT(FDODeviceExtension->Common.IsFDO); + + // get stack location + IoStack = IoGetCurrentIrpStackLocation(Irp); + DPRINT1("FDO_HandleResetCyclePort IOCTL %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode); + + if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_RESET_PORT) + { + // + // use reset port list + // + ListHead = &FDODeviceExtension->ResetPortListHead; + ResetActive = &FDODeviceExtension->ResetPortActive; + } + else + { + // + // use cycle port list + // + ListHead = &FDODeviceExtension->CyclePortListHead; + ResetActive = &FDODeviceExtension->CyclePortActive; + } + + // + // acquire lock + // + KeAcquireSpinLock(&FDODeviceExtension->Lock, &OldLevel); + + if (*ResetActive) + { + // + // insert into pending list + // + InsertTailList(ListHead, &Irp->Tail.Overlay.ListEntry); + + // + // mark irp pending + // + IoMarkIrpPending(Irp); + Status = STATUS_PENDING; + + // + // release lock + // + KeReleaseSpinLock(&FDODeviceExtension->Lock, OldLevel); + } + else + { + // + // mark reset active + // + *ResetActive = TRUE; + + // + // release lock + // + KeReleaseSpinLock(&FDODeviceExtension->Lock, OldLevel); + + // + // forward request synchronized + // + USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp); + + // + // reacquire lock + // + KeAcquireSpinLock(&FDODeviceExtension->Lock, &OldLevel); + + // + // mark reset as completed + // + *ResetActive = FALSE; + + // + // move all requests into temporary list + // + InitializeListHead(&TempList); + while(!IsListEmpty(ListHead)) + { + Entry = RemoveHeadList(ListHead); + InsertTailList(&TempList, Entry); + } + + // + // release lock + // + KeReleaseSpinLock(&FDODeviceExtension->Lock, OldLevel); + + // + // complete pending irps + // + while(!IsListEmpty(&TempList)) + { + Entry = RemoveHeadList(&TempList); + ListIrp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry); + + // + // complete request with status success + // + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + // + // status success + // + Status = STATUS_SUCCESS; + } + + return Status; +} + +NTSTATUS +FDO_HandleInternalDeviceControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + NTSTATUS Status; + PFDO_DEVICE_EXTENSION FDODeviceExtension; + + // + // get device extension + // + FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + ASSERT(FDODeviceExtension->Common.IsFDO); + + // get stack location + IoStack = IoGetCurrentIrpStackLocation(Irp); + + if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_RESET_PORT || + IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_CYCLE_PORT) + { + // + // handle reset / cycle ports + // + Status = FDO_HandleResetCyclePort(DeviceObject, Irp); + DPRINT1("FDO_HandleResetCyclePort Status %x\n", Status); + if (Status != STATUS_PENDING) + { + // + // complete request + // + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + return Status; + } + + // + // forward and forget request + // + IoSkipCurrentIrpStackLocation(Irp); + return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp); } NTSTATUS @@ -517,6 +691,8 @@ FDO_Dispatch( { case IRP_MJ_PNP: return FDO_HandlePnp(DeviceObject, Irp); + case IRP_MJ_INTERNAL_DEVICE_CONTROL: + return FDO_HandleInternalDeviceControl(DeviceObject, Irp); default: DPRINT1("FDO_Dispatch Function %x not implemented\n", IoStack->MajorFunction); ASSERT(FALSE); diff --git a/drivers/usb/usbccgp/pdo.c b/drivers/usb/usbccgp/pdo.c index 9d7180dc666..1a2c0be7b1a 100644 --- a/drivers/usb/usbccgp/pdo.c +++ b/drivers/usb/usbccgp/pdo.c @@ -925,6 +925,24 @@ PDO_HandleInternalDeviceControl( return Status; } } + else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_GET_PORT_STATUS) + { + IoSkipCurrentIrpStackLocation(Irp); + Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp); + return Status; + } + else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_RESET_PORT) + { + IoSkipCurrentIrpStackLocation(Irp); + Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp); + return Status; + } + else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_CYCLE_PORT) + { + IoSkipCurrentIrpStackLocation(Irp); + Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp); + return Status; + } diff --git a/drivers/usb/usbccgp/usbccgp.c b/drivers/usb/usbccgp/usbccgp.c index 174612d94bc..f5cb58444bb 100644 --- a/drivers/usb/usbccgp/usbccgp.c +++ b/drivers/usb/usbccgp/usbccgp.c @@ -43,6 +43,10 @@ USBCCGP_AddDevice( FDODeviceExtension->Common.IsFDO = TRUE; FDODeviceExtension->DriverObject = DriverObject; FDODeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; + InitializeListHead(&FDODeviceExtension->ResetPortListHead); + InitializeListHead(&FDODeviceExtension->CyclePortListHead); + KeInitializeSpinLock(&FDODeviceExtension->Lock); + FDODeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject); if (!FDODeviceExtension->NextDeviceObject) { diff --git a/drivers/usb/usbccgp/usbccgp.h b/drivers/usb/usbccgp/usbccgp.h index 55e08064612..2208dfe8b49 100644 --- a/drivers/usb/usbccgp/usbccgp.h +++ b/drivers/usb/usbccgp/usbccgp.h @@ -39,6 +39,11 @@ typedef struct PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptor; // usb function descriptor ULONG FunctionDescriptorCount; // number of function descriptor PDEVICE_OBJECT * ChildPDO; // child pdos + LIST_ENTRY ResetPortListHead; // reset port list head + LIST_ENTRY CyclePortListHead; // cycle port list head + UCHAR ResetPortActive; // reset port active + UCHAR CyclePortActive; // cycle port active + KSPIN_LOCK Lock; // reset / cycle port list lock }FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION; #define USBCCPG_TAG 'cbsu'