Author: janderwald Date: Fri Feb 17 03:02:14 2012 New Revision: 55659
URL: http://svn.reactos.org/svn/reactos?rev=55659&view=rev Log: [USBSTOR] - Implement timer routine which checks for hung srbs, not yet activated - Stop timer when the device is stopped - Implement function to check if the attached device is a floppy device - Implement function to send read format capacity request - Implement missing hardware id / device id support for floppy - Add retry count parameter for debugging purposes - Tested in VBox + VmWare + RH
Modified: trunk/reactos/drivers/usb/usbstor/error.c trunk/reactos/drivers/usb/usbstor/fdo.c trunk/reactos/drivers/usb/usbstor/misc.c trunk/reactos/drivers/usb/usbstor/pdo.c trunk/reactos/drivers/usb/usbstor/queue.c trunk/reactos/drivers/usb/usbstor/scsi.c trunk/reactos/drivers/usb/usbstor/usbstor.c trunk/reactos/drivers/usb/usbstor/usbstor.h
Modified: trunk/reactos/drivers/usb/usbstor/error.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbstor/error.c... ============================================================================== --- trunk/reactos/drivers/usb/usbstor/error.c [iso-8859-1] (original) +++ trunk/reactos/drivers/usb/usbstor/error.c [iso-8859-1] Fri Feb 17 03:02:14 2012 @@ -112,10 +112,8 @@ { NTSTATUS Status = STATUS_SUCCESS; PIO_STACK_LOCATION Stack; - //USBD_PIPE_HANDLE PipeHandle; PSCSI_REQUEST_BLOCK Request; PCDB pCDB; -
// // first perform a mass storage reset step 1 in 5.3.4 USB Mass Storage Bulk Only Specification @@ -172,10 +170,20 @@ USBSTOR_QueueTerminateRequest(Context->PDODeviceExtension->LowerDeviceObject, Context->Irp); IoCompleteRequest(Context->Irp, IO_NO_INCREMENT);
- // + // // Start the next request // USBSTOR_QueueNextRequest(Context->PDODeviceExtension->LowerDeviceObject); + + // + // srb handling finished + // + Context->FDODeviceExtension->SrbErrorHandlingActive = FALSE; + + // + // clear timer srb + // + Context->FDODeviceExtension->LastTimerActiveSrb = NULL; } } else @@ -187,13 +195,42 @@ // ASSERT(Context->Event); KeSetEvent(Context->Event, 0, FALSE); + + // + // srb handling finished + // + Context->FDODeviceExtension->SrbErrorHandlingActive = FALSE; + + // + // clear timer srb + // + Context->FDODeviceExtension->LastTimerActiveSrb = NULL; } }
if (NT_SUCCESS(Status)) { - DPRINT1("Retrying\n"); - USBSTOR_HandleExecuteSCSI(*Context->PDODeviceExtension->PDODeviceObject, Context->Irp); + DPRINT1("Retrying Count %x\n", Context->RetryCount); + + // + // re-schedule request + // + USBSTOR_HandleExecuteSCSI(Context->PDODeviceExtension->Self, Context->Irp, Context->RetryCount + 1); + + // + // srb error handling finished + // + Context->FDODeviceExtension->SrbErrorHandlingActive = FALSE; + + // + // srb error handling finished + // + Context->FDODeviceExtension->TimerWorkQueueEnabled = TRUE; + + // + // clear timer srb + // + Context->FDODeviceExtension->LastTimerActiveSrb = NULL; }
// @@ -213,8 +250,6 @@ PVOID Context) { NTSTATUS Status; - PIO_STACK_LOCATION IoStack; - PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context;
// @@ -224,42 +259,9 @@ DPRINT1("USBSTOR_ResetPipeWithHandle Status %x\n", Status);
// - // get next stack location - // - - IoStack = IoGetNextIrpStackLocation(WorkItemData->Irp); - - // - // now initialize the urb for sending the csw - // - UsbBuildInterruptOrBulkTransferRequest(&WorkItemData->Context->Urb, - sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), - WorkItemData->Context->FDODeviceExtension->InterfaceInformation->Pipes[WorkItemData->Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle, - WorkItemData->Context->csw, - NULL, - 512, //FIXME - USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK, - NULL); - - // - // initialize stack location - // - IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; - IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; - IoStack->Parameters.Others.Argument1 = (PVOID)&WorkItemData->Context->Urb; - IoStack->Parameters.DeviceIoControl.InputBufferLength = WorkItemData->Context->Urb.UrbHeader.Length; - WorkItemData->Irp->IoStatus.Status = STATUS_SUCCESS; - - - // - // setup completion routine - // - IoSetCompletionRoutine(WorkItemData->Irp, USBSTOR_CSWCompletionRoutine, Context, TRUE, TRUE, TRUE); - - // - // call driver - // - IoCallDriver(WorkItemData->Context->FDODeviceExtension->LowerDeviceObject, WorkItemData->Irp); + // now resend the csw as the stall got cleared + // + USBSTOR_SendCSW(WorkItemData->Context, WorkItemData->Irp); }
VOID @@ -268,8 +270,14 @@ PVOID Context) { NTSTATUS Status; + PFDO_DEVICE_EXTENSION FDODeviceExtension; PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context;
+ // + // get fdo + // + FDODeviceExtension = WorkItemData->Context->FDODeviceExtension; + if (WorkItemData->Context->ErrorIndex == 2) { // @@ -290,3 +298,139 @@ // ExFreePool(WorkItemData); } + +VOID +NTAPI +USBSTOR_TimerWorkerRoutine( + IN PVOID Context) +{ + PFDO_DEVICE_EXTENSION FDODeviceExtension; + NTSTATUS Status; + PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context; + + // + // get device extension + // + FDODeviceExtension = (PFDO_DEVICE_EXTENSION)WorkItemData->DeviceObject->DeviceExtension; + ASSERT(FDODeviceExtension->Common.IsFDO); + + // + // first perform a mass storage reset step 1 in 5.3.4 USB Mass Storage Bulk Only Specification + // + Status = USBSTOR_ResetDevice(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension); + if (NT_SUCCESS(Status)) + { + // + // step 2 reset bulk in pipe section 5.3.4 + // + Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkInPipeIndex].PipeHandle); + if (NT_SUCCESS(Status)) + { + // + // finally reset bulk out pipe + // + Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle); + } + } + DPRINT1("Status %x\n", Status); + + // + // clear timer srb + // + FDODeviceExtension->LastTimerActiveSrb = NULL; + + // + // re-schedule request + // + //USBSTOR_HandleExecuteSCSI(WorkItemData->Context->PDODeviceExtension->Self, WorkItemData->Context->Irp, Context->RetryCount + 1); + + + + // + // do not retry for the same packet again + // + FDODeviceExtension->TimerWorkQueueEnabled = FALSE; + + // + // Free Work Item Data + // + ExFreePool(WorkItemData); +} + + +VOID +NTAPI +USBSTOR_TimerRoutine( + PDEVICE_OBJECT DeviceObject, + PVOID Context) +{ + PFDO_DEVICE_EXTENSION FDODeviceExtension; + BOOLEAN ResetDevice = FALSE; + PERRORHANDLER_WORKITEM_DATA WorkItemData; + + // + // get device extension + // + FDODeviceExtension = (PFDO_DEVICE_EXTENSION)Context; + DPRINT1("[USBSTOR] TimerRoutine entered\n"); + DPRINT1("[USBSTOR] ActiveSrb %p ResetInProgress %x LastTimerActiveSrb %p\n", FDODeviceExtension->ActiveSrb, FDODeviceExtension->ResetInProgress, FDODeviceExtension->LastTimerActiveSrb); + + // + // acquire spinlock + // + KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension->IrpListLock); + + // + // is there an active srb and no global reset is in progress + // + if (FDODeviceExtension->ActiveSrb && FDODeviceExtension->ResetInProgress == FALSE && FDODeviceExtension->TimerWorkQueueEnabled) + { + if (FDODeviceExtension->LastTimerActiveSrb != NULL && FDODeviceExtension->LastTimerActiveSrb == FDODeviceExtension->ActiveSrb) + { + // + // check if empty + // + DPRINT1("[USBSTOR] ActiveSrb %p hang detected\n", FDODeviceExtension->ActiveSrb); + ResetDevice = TRUE; + } + else + { + // + // update pointer + // + FDODeviceExtension->LastTimerActiveSrb = FDODeviceExtension->ActiveSrb; + } + } + else + { + // + // reset srb + // + FDODeviceExtension->LastTimerActiveSrb = NULL; + } + + // + // release lock + // + KeReleaseSpinLockFromDpcLevel(&FDODeviceExtension->IrpListLock); + + + if (ResetDevice && FDODeviceExtension->TimerWorkQueueEnabled && FDODeviceExtension->SrbErrorHandlingActive == FALSE) + { + WorkItemData = (PERRORHANDLER_WORKITEM_DATA)ExAllocatePool(NonPagedPool, sizeof(ERRORHANDLER_WORKITEM_DATA)); + if (WorkItemData) + { + // + // Initialize and queue the work item to handle the error + // + ExInitializeWorkItem(&WorkItemData->WorkQueueItem, + USBSTOR_TimerWorkerRoutine, + WorkItemData); + + WorkItemData->DeviceObject = FDODeviceExtension->FunctionalDeviceObject; + + DPRINT1("[USBSTOR] Queing Timer WorkItem\n"); + ExQueueWorkItem(&WorkItemData->WorkQueueItem, DelayedWorkQueue); + } + } +}
Modified: trunk/reactos/drivers/usb/usbstor/fdo.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbstor/fdo.c?r... ============================================================================== --- trunk/reactos/drivers/usb/usbstor/fdo.c [iso-8859-1] (original) +++ trunk/reactos/drivers/usb/usbstor/fdo.c [iso-8859-1] Fri Feb 17 03:02:14 2012 @@ -300,6 +300,13 @@ } #endif
+ + // + // start the timer + // + //IoStartTimer(DeviceObject); + + // // fdo is now initialized // @@ -341,8 +348,14 @@ case IRP_MN_STOP_DEVICE: { DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n"); - Status = STATUS_NOT_SUPPORTED; - break; + IoStopTimer(DeviceObject); + Irp->IoStatus.Status = STATUS_SUCCESS; + + // + // forward irp to next device object + // + IoSkipCurrentIrpStackLocation(Irp); + return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); } case IRP_MN_REMOVE_DEVICE: {
Modified: trunk/reactos/drivers/usb/usbstor/misc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbstor/misc.c?... ============================================================================== --- trunk/reactos/drivers/usb/usbstor/misc.c [iso-8859-1] (original) +++ trunk/reactos/drivers/usb/usbstor/misc.c [iso-8859-1] Fri Feb 17 03:02:14 2012 @@ -418,3 +418,100 @@ return Status;
} + +BOOLEAN +USBSTOR_IsFloppy( + IN PUCHAR Buffer, + IN ULONG BufferLength, + OUT PUCHAR MediumTypeCode) +{ + PUFI_CAPACITY_FORMAT_HEADER FormatHeader; + PUFI_CAPACITY_DESCRIPTOR Descriptor; + ULONG Length, Index, BlockCount, BlockLength; + + // + // get format header + // + FormatHeader = (PUFI_CAPACITY_FORMAT_HEADER)Buffer; + + // + // sanity checks + // + ASSERT(FormatHeader->Reserved1 == 0x00); + ASSERT(FormatHeader->Reserved2 == 0x00); + ASSERT(FormatHeader->Reserved3 == 0x00); + + // + // is there capacity data + // + if (!FormatHeader->CapacityLength) + { + // + // no data provided + // + DPRINT1("[USBSTOR] No capacity length\n"); + return FALSE; + } + + // + // the format header are always 8 bytes in length + // + ASSERT((FormatHeader->CapacityLength & 0x7) == 0); + DPRINT1("CapacityLength %x\n", FormatHeader->CapacityLength); + + // + // grab length and locate first descriptor + // + Length = FormatHeader->CapacityLength; + Descriptor = (PUFI_CAPACITY_DESCRIPTOR)(FormatHeader + 1); + for(Index = 0; Index < Length / sizeof(UFI_CAPACITY_DESCRIPTOR); Index++) + { + // + // blocks are little endian format + // + BlockCount = NTOHL(Descriptor->BlockCount); + + // + // get block length + // + BlockLength = NTOHL((Descriptor->BlockLengthByte0 << 24 | Descriptor->BlockLengthByte1 << 16 | Descriptor->BlockLengthByte2 << 8)); + + DPRINT1("BlockCount %x BlockLength %x Code %x\n", BlockCount, BlockLength, Descriptor->Code); + + if (BlockLength == 512 && BlockCount == 1440) + { + // + // 720 KB DD + // + *MediumTypeCode = 0x1E; + return TRUE; + } + else if (BlockLength == 1024 && BlockCount == 1232) + { + // + // 1,25 MB + // + *MediumTypeCode = 0x93; + return TRUE; + } + else if (BlockLength == 512 && BlockCount == 2880) + { + // + // 1,44MB KB DD + // + *MediumTypeCode = 0x94; + return TRUE; + } + + // + // move to next descriptor + // + Descriptor = (Descriptor + 1); + } + + // + // no floppy detected + // + return FALSE; +} +
Modified: trunk/reactos/drivers/usb/usbstor/pdo.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbstor/pdo.c?r... ============================================================================== --- trunk/reactos/drivers/usb/usbstor/pdo.c [iso-8859-1] (original) +++ trunk/reactos/drivers/usb/usbstor/pdo.c [iso-8859-1] Fri Feb 17 03:02:14 2012 @@ -13,19 +13,24 @@
LPCSTR USBSTOR_GetDeviceType( - IN PUFI_INQUIRY_RESPONSE InquiryData) + IN PUFI_INQUIRY_RESPONSE InquiryData, + IN UCHAR IsFloppy) { // // check if device type is zero // if (InquiryData->DeviceType == 0) { + if (IsFloppy) + { + // + // floppy device + // + return "SFloppy"; + } + // // direct access device - // - - // - // FIXME: check if floppy // return "Disk"; } @@ -82,19 +87,24 @@
LPCSTR USBSTOR_GetGenericType( - IN PUFI_INQUIRY_RESPONSE InquiryData) + IN PUFI_INQUIRY_RESPONSE InquiryData, + IN UCHAR IsFloppy) { // // check if device type is zero // if (InquiryData->DeviceType == 0) { + if (IsFloppy) + { + // + // floppy device + // + return "GenSFloppy"; + } + // // direct access device - // - - // - // FIXME: check if floppy // return "GenDisk"; } @@ -286,7 +296,7 @@ // // get device type // - DeviceType = USBSTOR_GetDeviceType(InquiryData); + DeviceType = USBSTOR_GetDeviceType(InquiryData, DeviceExtension->IsFloppy);
// // zero buffer @@ -434,8 +444,8 @@ // // get device type and generic type // - DeviceType = USBSTOR_GetDeviceType(InquiryData); - GenericType = USBSTOR_GetGenericType(InquiryData); + DeviceType = USBSTOR_GetDeviceType(InquiryData, PDODeviceExtension->IsFloppy); + GenericType = USBSTOR_GetGenericType(InquiryData, PDODeviceExtension->IsFloppy);
ASSERT(GenericType);
@@ -590,7 +600,7 @@ // // get target device type // - DeviceType = USBSTOR_GetDeviceType((PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData); + DeviceType = USBSTOR_GetDeviceType((PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData, PDODeviceExtension->IsFloppy);
// // zero memory @@ -984,6 +994,7 @@ PDODeviceExtension->Common.IsFDO = FALSE; PDODeviceExtension->LowerDeviceObject = DeviceObject; PDODeviceExtension->PDODeviceObject = ChildDeviceObject; + PDODeviceExtension->Self = PDO;
// // set device flags @@ -1000,7 +1011,24 @@ // *ChildDeviceObject = PDO;
- USBSTOR_SendInquiryCmd(PDO); + // + // send inquiry command + // + USBSTOR_SendInquiryCmd(PDO, 0); + + // + // retrieve format capacity + // + if (NT_SUCCESS(USBSTOR_SendFormatCapacity(PDO, 0))) + { + // + // check if its a floppy + // + PDODeviceExtension->IsFloppy = USBSTOR_IsFloppy(PDODeviceExtension->FormatData, PAGE_SIZE /*FIXME*/, &PDODeviceExtension->MediumTypeCode); + DPRINT1("[USBSTOR] IsFloppy %x MediumTypeCode %x\n", PDODeviceExtension->IsFloppy, PDODeviceExtension->MediumTypeCode); + } + +
// // done
Modified: trunk/reactos/drivers/usb/usbstor/queue.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbstor/queue.c... ============================================================================== --- trunk/reactos/drivers/usb/usbstor/queue.c [iso-8859-1] (original) +++ trunk/reactos/drivers/usb/usbstor/queue.c [iso-8859-1] Fri Feb 17 03:02:14 2012 @@ -660,7 +660,7 @@ // // execute scsi // - Status = USBSTOR_HandleExecuteSCSI(IoStack->DeviceObject, Irp); + Status = USBSTOR_HandleExecuteSCSI(IoStack->DeviceObject, Irp, 0);
// // FIXME: handle error
Modified: trunk/reactos/drivers/usb/usbstor/scsi.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbstor/scsi.c?... ============================================================================== --- trunk/reactos/drivers/usb/usbstor/scsi.c [iso-8859-1] (original) +++ trunk/reactos/drivers/usb/usbstor/scsi.c [iso-8859-1] Fri Feb 17 03:02:14 2012 @@ -135,6 +135,16 @@ }
// + // error handling started + // + Context->FDODeviceExtension->SrbErrorHandlingActive = TRUE; + + // + // srb error handling finished + // + Context->FDODeviceExtension->TimerWorkQueueEnabled = FALSE; + + // // Initialize and queue the work item to handle the error // ExInitializeWorkItem(&ErrorHandlerWorkItemData->WorkQueueItem, @@ -175,8 +185,6 @@ NTSTATUS Status; PURB Urb;
- DPRINT("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p\n", Irp, Ctx); - // // access context // @@ -212,7 +220,7 @@ } }
- DPRINT1("USBSTOR_CSWCompletionRoutine Status %x\n", Irp->IoStatus.Status); + DPRINT("USBSTOR_CSWCompletionRoutine Status %x\n", Irp->IoStatus.Status);
if (!NT_SUCCESS(Irp->IoStatus.Information)) { @@ -382,32 +390,16 @@ return STATUS_MORE_PROCESSING_REQUIRED; }
-// -// driver verifier -// -IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine; - -NTSTATUS -NTAPI -USBSTOR_DataCompletionRoutine( - PDEVICE_OBJECT DeviceObject, - PIRP Irp, - PVOID Ctx) -{ - PIRP_CONTEXT Context; +VOID +USBSTOR_SendCSW( + PIRP_CONTEXT Context, + PIRP Irp) +{ PIO_STACK_LOCATION IoStack;
- DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p\n", Irp, Ctx); - - // - // access context - // - Context = (PIRP_CONTEXT)Ctx; - - // - // get next stack location - // - + // + // get next irp stack location + // IoStack = IoGetNextIrpStackLocation(Irp);
// @@ -441,7 +433,52 @@ // call driver // IoCallDriver(Context->FDODeviceExtension->LowerDeviceObject, Irp); - +} + + +// +// driver verifier +// +IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine; + +NTSTATUS +NTAPI +USBSTOR_DataCompletionRoutine( + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Ctx) +{ + PIRP_CONTEXT Context; + NTSTATUS Status; + + DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status); + + // + // access context + // + Context = (PIRP_CONTEXT)Ctx; + +#if 0 + if (!NT_SUCCESS(Irp->IoStatus.Status)) + { + // + // clear stall and resend cbw + // + Context->ErrorIndex = 1; + Status = USBSTOR_QueueWorkItem(Context, Irp); + ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED); + return STATUS_MORE_PROCESSING_REQUIRED; + } +#endif + + // + // send csw + // + USBSTOR_SendCSW(Context, Irp); + + // + // cancel completion + // return STATUS_MORE_PROCESSING_REQUIRED; }
@@ -462,7 +499,7 @@ UCHAR Code; USBD_PIPE_HANDLE PipeHandle;
- DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p\n", Irp, Ctx); + DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
// // access context @@ -566,6 +603,37 @@
}
+NTSTATUS +USBSTOR_SendCBW( + PIRP_CONTEXT Context, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + + // + // get next stack location + // + IoStack = IoGetNextIrpStackLocation(Irp); + + // + // initialize stack location + // + IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; + IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; + IoStack->Parameters.Others.Argument1 = (PVOID)&Context->Urb; + IoStack->Parameters.DeviceIoControl.InputBufferLength = Context->Urb.UrbHeader.Length; + Irp->IoStatus.Status = STATUS_SUCCESS; + + // + // setup completion routine + // + IoSetCompletionRoutine(Irp, USBSTOR_CBWCompletionRoutine, Context, TRUE, TRUE, TRUE); + + // + // call driver + // + return IoCallDriver(Context->FDODeviceExtension->LowerDeviceObject, Irp); +}
NTSTATUS USBSTOR_SendRequest( @@ -575,13 +643,13 @@ IN UCHAR CommandLength, IN PUCHAR Command, IN ULONG TransferDataLength, - IN PUCHAR TransferData) + IN PUCHAR TransferData, + IN ULONG RetryCount) { PIRP_CONTEXT Context; PPDO_DEVICE_EXTENSION PDODeviceExtension; PFDO_DEVICE_EXTENSION FDODeviceExtension; PIRP Irp; - PIO_STACK_LOCATION IoStack; PUCHAR MdlVirtualAddress;
// @@ -640,6 +708,7 @@ Context->FDODeviceExtension = FDODeviceExtension; Context->PDODeviceExtension = PDODeviceExtension; Context->Event = Event; + Context->RetryCount = RetryCount;
// // is there transfer data @@ -745,25 +814,6 @@ return STATUS_INSUFFICIENT_RESOURCES; }
- // - // get next stack location - // - IoStack = IoGetNextIrpStackLocation(Irp); - - // - // initialize stack location - // - IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; - IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; - IoStack->Parameters.Others.Argument1 = (PVOID)&Context->Urb; - IoStack->Parameters.DeviceIoControl.InputBufferLength = Context->Urb.UrbHeader.Length; - Irp->IoStatus.Status = STATUS_SUCCESS; - - // - // setup completion routine - // - IoSetCompletionRoutine(Irp, USBSTOR_CBWCompletionRoutine, Context, TRUE, TRUE, TRUE); - if (OriginalRequest) { // @@ -773,19 +823,84 @@ }
// - // call driver - // - IoCallDriver(FDODeviceExtension->LowerDeviceObject, Irp); + // send request + // + USBSTOR_SendCBW(Context, Irp);
// // done // return STATUS_PENDING; +} + +NTSTATUS +USBSTOR_SendFormatCapacity( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG RetryCount) +{ + UFI_READ_FORMAT_CAPACITY Cmd; + NTSTATUS Status; + KEVENT Event; + PPDO_DEVICE_EXTENSION PDODeviceExtension; + PUCHAR Response; + + + // + // allocate inquiry response + // + Response = AllocateItem(NonPagedPool, PAGE_SIZE); + if (!Response) + { + // + // no memory + // + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // get PDO device extension + // + PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + // + // initialize inquiry cmd + // + RtlZeroMemory(&Cmd, sizeof(UFI_READ_FORMAT_CAPACITY)); + Cmd.Code = SCSIOP_READ_FORMATTED_CAPACITY; + Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN) << 5; + Cmd.AllocationLengthLsb = 0xFC; // FIXME: compute some same value + + // + // initialize event + // + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + // + // now send the request + // + Status = USBSTOR_SendRequest(DeviceObject, NULL, &Event, UFI_READ_FORMAT_CAPACITY_CMD_LEN, (PUCHAR)&Cmd, sizeof(UFI_INQUIRY_RESPONSE), (PUCHAR)Response, RetryCount); + + // + // wait for the action to complete + // + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + + // + // store inquiry data + // + PDODeviceExtension->FormatData = Response; + + // + // done + // + return Status; + }
NTSTATUS USBSTOR_SendInquiryCmd( - IN PDEVICE_OBJECT DeviceObject) + IN PDEVICE_OBJECT DeviceObject, + IN ULONG RetryCount) { UFI_INQUIRY_CMD Cmd; NTSTATUS Status; @@ -827,7 +942,7 @@ // // now send the request // - Status = USBSTOR_SendRequest(DeviceObject, NULL, &Event, UFI_INQUIRY_CMD_LEN, (PUCHAR)&Cmd, sizeof(UFI_INQUIRY_RESPONSE), (PUCHAR)Response); + Status = USBSTOR_SendRequest(DeviceObject, NULL, &Event, UFI_INQUIRY_CMD_LEN, (PUCHAR)&Cmd, sizeof(UFI_INQUIRY_RESPONSE), (PUCHAR)Response, RetryCount);
// // wait for the action to complete @@ -863,7 +978,8 @@ NTSTATUS USBSTOR_SendCapacityCmd( IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) + IN PIRP Irp, + IN ULONG RetryCount) { UFI_CAPACITY_CMD Cmd; PUFI_CAPACITY_RESPONSE Response; @@ -904,13 +1020,14 @@ // // send request, response will be freed in completion routine // - return USBSTOR_SendRequest(DeviceObject, Irp, NULL, UFI_READ_CAPACITY_CMD_LEN, (PUCHAR)&Cmd, sizeof(UFI_CAPACITY_RESPONSE), (PUCHAR)Response); + return USBSTOR_SendRequest(DeviceObject, Irp, NULL, UFI_READ_CAPACITY_CMD_LEN, (PUCHAR)&Cmd, sizeof(UFI_CAPACITY_RESPONSE), (PUCHAR)Response, RetryCount); }
NTSTATUS USBSTOR_SendModeSenseCmd( IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) + IN PIRP Irp, + IN ULONG RetryCount) { #if 0 UFI_SENSE_CMD Cmd; @@ -1098,12 +1215,13 @@ NTSTATUS USBSTOR_SendReadWriteCmd( IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) + IN PIRP Irp, + IN ULONG RetryCount) { UFI_READ_WRITE_CMD Cmd; PPDO_DEVICE_EXTENSION PDODeviceExtension; PCDB pCDB; - ULONG BlockCount; + ULONG BlockCount, Temp; PIO_STACK_LOCATION IoStack; PSCSI_REQUEST_BLOCK Request;
@@ -1155,18 +1273,25 @@ Cmd.LogicalBlockByte2 = pCDB->CDB10.LogicalBlockByte2; Cmd.LogicalBlockByte3 = pCDB->CDB10.LogicalBlockByte3;
+ // + // sanity check + // + Temp = (Cmd.ContiguousLogicBlocksByte0 << 8 | Cmd.ContiguousLogicBlocksByte1); + ASSERT(NTOHL(Temp == BlockCount)); + DPRINT("USBSTOR_SendReadWriteCmd BlockAddress %x%x%x%x BlockCount %lu BlockLength %lu\n", Cmd.LogicalBlockByte0, Cmd.LogicalBlockByte1, Cmd.LogicalBlockByte2, Cmd.LogicalBlockByte3, BlockCount, PDODeviceExtension->BlockLength);
// // send request // - return USBSTOR_SendRequest(DeviceObject, Irp, NULL, UFI_READ_WRITE_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, (PUCHAR)Request->DataBuffer); + return USBSTOR_SendRequest(DeviceObject, Irp, NULL, UFI_READ_WRITE_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, (PUCHAR)Request->DataBuffer, RetryCount); }
NTSTATUS USBSTOR_SendTestUnitCmd( IN PDEVICE_OBJECT DeviceObject, - IN OUT PIRP Irp) + IN OUT PIRP Irp, + IN ULONG RetryCount) { UFI_TEST_UNIT_CMD Cmd; PPDO_DEVICE_EXTENSION PDODeviceExtension; @@ -1203,14 +1328,15 @@ // // send the request // - return USBSTOR_SendRequest(DeviceObject, Irp, NULL, UFI_TEST_UNIT_CMD_LEN, (PUCHAR)&Cmd, 0, NULL); + return USBSTOR_SendRequest(DeviceObject, Irp, NULL, UFI_TEST_UNIT_CMD_LEN, (PUCHAR)&Cmd, 0, NULL, RetryCount); }
NTSTATUS USBSTOR_HandleExecuteSCSI( IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) + IN PIRP Irp, + IN ULONG RetryCount) { PCDB pCDB; NTSTATUS Status; @@ -1253,7 +1379,7 @@ ASSERT(Request->DataBuffer);
DPRINT("SCSIOP_READ_CAPACITY Length %lu\n", Request->DataTransferLength); - Status = USBSTOR_SendCapacityCmd(DeviceObject, Irp); + Status = USBSTOR_SendCapacityCmd(DeviceObject, Irp, RetryCount); } else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE) { @@ -1264,7 +1390,7 @@ // // send mode sense command // - Status = USBSTOR_SendModeSenseCmd(DeviceObject, Irp); + Status = USBSTOR_SendModeSenseCmd(DeviceObject, Irp, RetryCount); } else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_READ || pCDB->MODE_SENSE.OperationCode == SCSIOP_WRITE) { @@ -1273,7 +1399,7 @@ // // send read / write command // - Status = USBSTOR_SendReadWriteCmd(DeviceObject, Irp); + Status = USBSTOR_SendReadWriteCmd(DeviceObject, Irp, RetryCount); } else if (pCDB->AsByte[0] == SCSIOP_MEDIUM_REMOVAL) { @@ -1302,7 +1428,7 @@ // // send test unit command // - Status = USBSTOR_SendTestUnitCmd(DeviceObject, Irp); + Status = USBSTOR_SendTestUnitCmd(DeviceObject, Irp, RetryCount); } else {
Modified: trunk/reactos/drivers/usb/usbstor/usbstor.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbstor/usbstor... ============================================================================== --- trunk/reactos/drivers/usb/usbstor/usbstor.c [iso-8859-1] (original) +++ trunk/reactos/drivers/usb/usbstor/usbstor.c [iso-8859-1] Fri Feb 17 03:02:14 2012 @@ -60,6 +60,11 @@ DeviceExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
// + // init timer + // + IoInitializeTimer(DeviceObject, USBSTOR_TimerRoutine, (PVOID)DeviceExtension); + + // // did attaching fail // if (!DeviceExtension->LowerDeviceObject)
Modified: trunk/reactos/drivers/usb/usbstor/usbstor.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbstor/usbstor... ============================================================================== --- trunk/reactos/drivers/usb/usbstor/usbstor.h [iso-8859-1] (original) +++ trunk/reactos/drivers/usb/usbstor/usbstor.h [iso-8859-1] Fri Feb 17 03:02:14 2012 @@ -68,6 +68,9 @@ ULONG IrpPendingCount; // count of irp pending PSCSI_REQUEST_BLOCK ActiveSrb; // stores the current active SRB KEVENT NoPendingRequests; // set if no pending or in progress requests + PSCSI_REQUEST_BLOCK LastTimerActiveSrb; // last timer tick active srb + ULONG SrbErrorHandlingActive; // error handling of srb is activated + ULONG TimerWorkQueueEnabled; // timer work queue enabled }FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
typedef struct @@ -76,10 +79,14 @@ PDEVICE_OBJECT LowerDeviceObject; // points to FDO UCHAR LUN; // lun id PVOID InquiryData; // USB SCSI inquiry data + PUCHAR FormatData; // USB SCSI Read Format Capacity Data UCHAR Claimed; // indicating if it has been claimed by upper driver ULONG BlockLength; // length of block ULONG LastLogicBlockAddress; // last block address PDEVICE_OBJECT *PDODeviceObject; // entry in pdo list + PDEVICE_OBJECT Self; // self + UCHAR MediumTypeCode; // floppy medium type code + UCHAR IsFloppy; // is device floppy }PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
// @@ -247,6 +254,51 @@ UCHAR Reserved[3]; }UFI_TIMER_PROTECT_PAGE, *PUFI_TIMER_PROTECT_PAGE; C_ASSERT(sizeof(UFI_TIMER_PROTECT_PAGE) == 8); + +//-------------------------------------------------------------------------------------------------------------------------------------------- +// +// UFI read capacity cmd +// + +typedef struct +{ + UCHAR Code; + UCHAR LUN; + UCHAR Reserved[5]; + UCHAR AllocationLengthMsb; + UCHAR AllocationLengthLsb; + UCHAR Reserved1[3]; +}UFI_READ_FORMAT_CAPACITY, *PUFI_READ_FORMAT_CAPACITY; + +C_ASSERT(sizeof(UFI_READ_FORMAT_CAPACITY) == 12); + +#define UFI_READ_FORMAT_CAPACITY_CMD_LEN (10) + +typedef struct +{ + UCHAR Reserved1; + UCHAR Reserved2; + UCHAR Reserved3; + UCHAR CapacityLength; +}UFI_CAPACITY_FORMAT_HEADER, *PUFI_CAPACITY_FORMAT_HEADER; + +C_ASSERT(sizeof(UFI_CAPACITY_FORMAT_HEADER) == 4); + +typedef struct +{ + ULONG BlockCount; + UCHAR Code; + UCHAR BlockLengthByte0; + UCHAR BlockLengthByte1; + UCHAR BlockLengthByte2; +}UFI_CAPACITY_DESCRIPTOR, *PUFI_CAPACITY_DESCRIPTOR; + +#define UNFORMATED_MEDIA_CODE_DESCRIPTORY_TYPE (1) +#define FORMAT_MEDIA_CODE_DESCRIPTOR_TYPE (2) +#define CARTRIDGE_MEDIA_CODE_DESCRIPTOR_TYPE (3) + + +
//-------------------------------------------------------------------------------------------------------------------------------------------- // @@ -280,6 +332,7 @@ PMDL TransferBufferMDL; PKEVENT Event; ULONG ErrorIndex; + ULONG RetryCount; }IRP_CONTEXT, *PIRP_CONTEXT;
typedef struct _ERRORHANDLER_WORKITEM_DATA @@ -361,6 +414,12 @@ IN PDEVICE_OBJECT DeviceObject, IN PFDO_DEVICE_EXTENSION DeviceExtension);
+BOOLEAN +USBSTOR_IsFloppy( + IN PUCHAR Buffer, + IN ULONG BufferLength, + OUT PUCHAR MediumTypeCode); + //--------------------------------------------------------------------- // // descriptor.c routines @@ -386,11 +445,20 @@ NTSTATUS USBSTOR_HandleExecuteSCSI( IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); + IN PIRP Irp, + IN ULONG RetryCount);
NTSTATUS USBSTOR_SendInquiryCmd( - IN PDEVICE_OBJECT DeviceObject); + IN PDEVICE_OBJECT DeviceObject, + IN ULONG RetryCount); + +NTSTATUS +USBSTOR_SendFormatCapacity( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG RetryCount); + +
NTSTATUS NTAPI @@ -399,6 +467,17 @@ PIRP Irp, PVOID Ctx);
+NTSTATUS +USBSTOR_SendCBW( + PIRP_CONTEXT Context, + PIRP Irp); + +VOID +USBSTOR_SendCSW( + PIRP_CONTEXT Context, + PIRP Irp); + + //--------------------------------------------------------------------- // // disk.c routines @@ -479,3 +558,9 @@ IN PDEVICE_OBJECT DeviceObject, IN USBD_PIPE_HANDLE PipeHandle);
+VOID +NTAPI +USBSTOR_TimerRoutine( + PDEVICE_OBJECT DeviceObject, + PVOID Context); +