diff --git a/reactos/drivers/usb/usbstor/error.c b/reactos/drivers/usb/usbstor/error.c index 532a5a85336..1e97946249a 100644 --- a/reactos/drivers/usb/usbstor/error.c +++ b/reactos/drivers/usb/usbstor/error.c @@ -112,11 +112,9 @@ USBSTOR_HandleTransferError( { 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_HandleTransferError( 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 @@ USBSTOR_HandleTransferError( // 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 @@ USBSTOR_ResetHandlerWorkItemRoutine( PVOID Context) { NTSTATUS Status; - PIO_STACK_LOCATION IoStack; - PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context; // @@ -224,42 +259,9 @@ USBSTOR_ResetHandlerWorkItemRoutine( DPRINT1("USBSTOR_ResetPipeWithHandle Status %x\n", Status); // - // get next stack location + // now resend the csw as the stall got cleared // - - 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); + USBSTOR_SendCSW(WorkItemData->Context, WorkItemData->Irp); } VOID @@ -268,8 +270,14 @@ ErrorHandlerWorkItemRoutine( 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 @@ ErrorHandlerWorkItemRoutine( // 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); + } + } +} diff --git a/reactos/drivers/usb/usbstor/fdo.c b/reactos/drivers/usb/usbstor/fdo.c index 56ad612ad41..8785a59388b 100644 --- a/reactos/drivers/usb/usbstor/fdo.c +++ b/reactos/drivers/usb/usbstor/fdo.c @@ -300,6 +300,13 @@ USBSTOR_FdoHandleStartDevice( } #endif + + // + // start the timer + // + //IoStartTimer(DeviceObject); + + // // fdo is now initialized // @@ -341,8 +348,14 @@ USBSTOR_FdoHandlePnp( 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: { diff --git a/reactos/drivers/usb/usbstor/misc.c b/reactos/drivers/usb/usbstor/misc.c index 4daf7488a4c..7fa3ff54fa6 100644 --- a/reactos/drivers/usb/usbstor/misc.c +++ b/reactos/drivers/usb/usbstor/misc.c @@ -418,3 +418,100 @@ USBSTOR_ResetDevice( 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; +} + diff --git a/reactos/drivers/usb/usbstor/pdo.c b/reactos/drivers/usb/usbstor/pdo.c index 2c42744f208..104406bde65 100644 --- a/reactos/drivers/usb/usbstor/pdo.c +++ b/reactos/drivers/usb/usbstor/pdo.c @@ -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) { - // - // direct access device - // + if (IsFloppy) + { + // + // floppy device + // + return "SFloppy"; + } // - // FIXME: check if floppy + // direct access device // return "Disk"; } @@ -82,19 +87,24 @@ USBSTOR_GetDeviceType( 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) { - // - // direct access device - // + if (IsFloppy) + { + // + // floppy device + // + return "GenSFloppy"; + } // - // FIXME: check if floppy + // direct access device // return "GenDisk"; } @@ -286,7 +296,7 @@ USBSTOR_PdoHandleQueryDeviceId( // // get device type // - DeviceType = USBSTOR_GetDeviceType(InquiryData); + DeviceType = USBSTOR_GetDeviceType(InquiryData, DeviceExtension->IsFloppy); // // zero buffer @@ -434,8 +444,8 @@ USBSTOR_PdoHandleQueryHardwareId( // // 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 @@ USBSTOR_PdoHandleQueryCompatibleId( // // 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 @@ USBSTOR_CreatePDO( PDODeviceExtension->Common.IsFDO = FALSE; PDODeviceExtension->LowerDeviceObject = DeviceObject; PDODeviceExtension->PDODeviceObject = ChildDeviceObject; + PDODeviceExtension->Self = PDO; // // set device flags @@ -1000,7 +1011,24 @@ USBSTOR_CreatePDO( // *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 diff --git a/reactos/drivers/usb/usbstor/queue.c b/reactos/drivers/usb/usbstor/queue.c index cda2d28d2e3..7dd0c42a042 100644 --- a/reactos/drivers/usb/usbstor/queue.c +++ b/reactos/drivers/usb/usbstor/queue.c @@ -660,7 +660,7 @@ USBSTOR_StartIo( // // execute scsi // - Status = USBSTOR_HandleExecuteSCSI(IoStack->DeviceObject, Irp); + Status = USBSTOR_HandleExecuteSCSI(IoStack->DeviceObject, Irp, 0); // // FIXME: handle error diff --git a/reactos/drivers/usb/usbstor/scsi.c b/reactos/drivers/usb/usbstor/scsi.c index b248d199034..ab0bff14350 100644 --- a/reactos/drivers/usb/usbstor/scsi.c +++ b/reactos/drivers/usb/usbstor/scsi.c @@ -134,6 +134,16 @@ USBSTOR_QueueWorkItem( return STATUS_INSUFFICIENT_RESOURCES; } + // + // 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 // @@ -175,8 +185,6 @@ USBSTOR_CSWCompletionRoutine( NTSTATUS Status; PURB Urb; - DPRINT("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p\n", Irp, Ctx); - // // access context // @@ -212,7 +220,7 @@ USBSTOR_CSWCompletionRoutine( } } - 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 @@ USBSTOR_CSWCompletionRoutine( return STATUS_MORE_PROCESSING_REQUIRED; } -// -// driver verifier -// -IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine; - -NTSTATUS -NTAPI -USBSTOR_DataCompletionRoutine( - PDEVICE_OBJECT DeviceObject, - PIRP Irp, - PVOID Ctx) +VOID +USBSTOR_SendCSW( + PIRP_CONTEXT Context, + PIRP Irp) { - PIRP_CONTEXT Context; PIO_STACK_LOCATION IoStack; - DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p\n", Irp, Ctx); - // - // access context + // get next irp stack location // - Context = (PIRP_CONTEXT)Ctx; - - // - // get next stack location - // - IoStack = IoGetNextIrpStackLocation(Irp); // @@ -441,7 +433,52 @@ USBSTOR_DataCompletionRoutine( // 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 @@ USBSTOR_CBWCompletionRoutine( 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 @@ DumpCBW( } +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 @@ USBSTOR_SendRequest( 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 @@ USBSTOR_SendRequest( Context->FDODeviceExtension = FDODeviceExtension; Context->PDODeviceExtension = PDODeviceExtension; Context->Event = Event; + Context->RetryCount = RetryCount; // // is there transfer data @@ -745,25 +814,6 @@ USBSTOR_SendRequest( 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,9 +823,9 @@ USBSTOR_SendRequest( } // - // call driver + // send request // - IoCallDriver(FDODeviceExtension->LowerDeviceObject, Irp); + USBSTOR_SendCBW(Context, Irp); // // done @@ -783,9 +833,74 @@ USBSTOR_SendRequest( 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 @@ USBSTOR_SendInquiryCmd( // // 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 @@ USBSTOR_SendInquiryCmd( 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 @@ USBSTOR_SendCapacityCmd( // // 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 @@ USBSTOR_SendModeSenseCmd( 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 @@ USBSTOR_SendReadWriteCmd( 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 @@ USBSTOR_SendTestUnitCmd( // // 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 @@ USBSTOR_HandleExecuteSCSI( 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 @@ USBSTOR_HandleExecuteSCSI( // // 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 @@ USBSTOR_HandleExecuteSCSI( // // 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 @@ USBSTOR_HandleExecuteSCSI( // // send test unit command // - Status = USBSTOR_SendTestUnitCmd(DeviceObject, Irp); + Status = USBSTOR_SendTestUnitCmd(DeviceObject, Irp, RetryCount); } else { diff --git a/reactos/drivers/usb/usbstor/usbstor.c b/reactos/drivers/usb/usbstor/usbstor.c index 50fb0bf2670..fb7f70f3884 100644 --- a/reactos/drivers/usb/usbstor/usbstor.c +++ b/reactos/drivers/usb/usbstor/usbstor.c @@ -59,6 +59,11 @@ USBSTOR_AddDevice( DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; DeviceExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject); + // + // init timer + // + IoInitializeTimer(DeviceObject, USBSTOR_TimerRoutine, (PVOID)DeviceExtension); + // // did attaching fail // diff --git a/reactos/drivers/usb/usbstor/usbstor.h b/reactos/drivers/usb/usbstor/usbstor.h index 700443e75f2..f3e881f3688 100644 --- a/reactos/drivers/usb/usbstor/usbstor.h +++ b/reactos/drivers/usb/usbstor/usbstor.h @@ -68,6 +68,9 @@ typedef struct 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 @@ typedef struct 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; // @@ -248,6 +255,51 @@ typedef struct }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) + + + + //-------------------------------------------------------------------------------------------------------------------------------------------- // // UFI test unit command @@ -280,6 +332,7 @@ typedef struct PMDL TransferBufferMDL; PKEVENT Event; ULONG ErrorIndex; + ULONG RetryCount; }IRP_CONTEXT, *PIRP_CONTEXT; typedef struct _ERRORHANDLER_WORKITEM_DATA @@ -361,6 +414,12 @@ USBSTOR_ResetDevice( 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 @@ USBSTOR_GetPipeHandles( 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 @@ USBSTOR_CSWCompletionRoutine( 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 @@ USBSTOR_ResetPipeWithHandle( IN PDEVICE_OBJECT DeviceObject, IN USBD_PIPE_HANDLE PipeHandle); +VOID +NTAPI +USBSTOR_TimerRoutine( + PDEVICE_OBJECT DeviceObject, + PVOID Context); +