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?rev=55659&r1=55658&r2=55659&view=diff
==============================================================================
--- 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?rev=55659&r1=55658&r2=55659&view=diff
==============================================================================
--- 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?rev=55659&r1=55658&r2=55659&view=diff
==============================================================================
--- 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?rev=55659&r1=55658&r2=55659&view=diff
==============================================================================
--- 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?rev=55659&r1=55658&r2=55659&view=diff
==============================================================================
--- 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?rev=55659&r1=55658&r2=55659&view=diff
==============================================================================
--- 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.c?rev=55659&r1=55658&r2=55659&view=diff
==============================================================================
--- 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.h?rev=55659&r1=55658&r2=55659&view=diff
==============================================================================
--- 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);
+


Reply via email to