add_subdirectory(usbohci)
#add_subdirectory(usbohci_new)
add_subdirectory(usbport)
+#add_subdirectory(usbport_new)
add_subdirectory(usbstor)
add_subdirectory(usbuhci)
--- /dev/null
+
+add_definitions(-DDEBUG_MODE)
+include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
+
+list(APPEND SOURCE
+ descriptor.c
+ disk.c
+ fdo.c
+ misc.c
+ pdo.c
+ queue.c
+ error.c
+ scsi.c
+ usbstor.c
+ usbstor.h)
+
+add_library(usbstor SHARED
+ ${SOURCE}
+ guid.c
+ usbstor.rc)
+
+set_module_type(usbstor kernelmodedriver)
+add_importlibs(usbstor ntoskrnl hal usbd)
+add_pch(usbstor usbstor.h SOURCE)
+add_cd_file(TARGET usbstor DESTINATION reactos/system32/drivers NO_CAB FOR all)
--- /dev/null
+/*
+ * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: drivers/usb/usbstor/descriptor.c
+ * PURPOSE: USB block storage device driver.
+ * PROGRAMMERS:
+ * James Tabor
+ * Michael Martin (michael.martin@reactos.org)
+ * Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+#include "usbstor.h"
+
+#define NDEBUG
+#include <debug.h>
+
+NTSTATUS
+NTAPI
+USBSTOR_GetDescriptor(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN UCHAR DescriptorType,
+ IN ULONG DescriptorLength,
+ IN UCHAR DescriptorIndex,
+ IN LANGID LanguageId,
+ OUT PVOID *OutDescriptor)
+{
+ PURB Urb;
+ NTSTATUS Status;
+ PVOID Descriptor;
+
+ //
+ // sanity checks
+ //
+ ASSERT(DeviceObject);
+ ASSERT(OutDescriptor);
+ ASSERT(DescriptorLength);
+
+ //
+ // first allocate descriptor buffer
+ //
+ Descriptor = AllocateItem(NonPagedPool, DescriptorLength);
+ if (!Descriptor)
+ {
+ //
+ // no memory
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // allocate urb
+ //
+ Urb = (PURB) AllocateItem(NonPagedPool, sizeof(URB));
+ if (!Urb)
+ {
+ //
+ // no memory
+ //
+ FreeItem(Descriptor);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // initialize urb
+ //
+ UsbBuildGetDescriptorRequest(Urb,
+ sizeof(Urb->UrbControlDescriptorRequest),
+ DescriptorType,
+ DescriptorIndex,
+ LanguageId,
+ Descriptor,
+ NULL,
+ DescriptorLength,
+ NULL);
+
+ //
+ // submit urb
+ //
+ Status = USBSTOR_SyncUrbRequest(DeviceObject, Urb);
+
+ //
+ // free urb
+ //
+ FreeItem(Urb);
+
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // store result
+ //
+ *OutDescriptor = Descriptor;
+ }
+
+ //
+ // done
+ //
+ return Status;
+}
+
+
+NTSTATUS
+USBSTOR_GetDescriptors(
+ IN PDEVICE_OBJECT DeviceObject)
+{
+ NTSTATUS Status;
+ PFDO_DEVICE_EXTENSION DeviceExtension;
+ USHORT DescriptorLength;
+
+ //
+ // get device extension
+ //
+ DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // first get device descriptor
+ //
+ Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_DEVICE_DESCRIPTOR_TYPE, sizeof(USB_DEVICE_DESCRIPTOR), 0, 0, (PVOID*)&DeviceExtension->DeviceDescriptor);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to get device descriptor
+ //
+ DeviceExtension->DeviceDescriptor = NULL;
+ return Status;
+ }
+
+ //
+ // now get basic configuration descriptor
+ //
+ Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_CONFIGURATION_DESCRIPTOR_TYPE, sizeof(USB_CONFIGURATION_DESCRIPTOR), 0, 0, (PVOID*)&DeviceExtension->ConfigurationDescriptor);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to get configuration descriptor
+ //
+ FreeItem(DeviceExtension->DeviceDescriptor);
+ DeviceExtension->DeviceDescriptor = NULL;
+ return Status;
+ }
+
+ //
+ // backup length
+ //
+ DescriptorLength = DeviceExtension->ConfigurationDescriptor->wTotalLength;
+
+ //
+ // release basic descriptor
+ //
+ FreeItem(DeviceExtension->ConfigurationDescriptor);
+ DeviceExtension->ConfigurationDescriptor = NULL;
+
+ //
+ // allocate full descriptor
+ //
+ Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_CONFIGURATION_DESCRIPTOR_TYPE, DescriptorLength, 0, 0, (PVOID*)&DeviceExtension->ConfigurationDescriptor);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to get configuration descriptor
+ //
+ FreeItem(DeviceExtension->DeviceDescriptor);
+ DeviceExtension->DeviceDescriptor = NULL;
+ return Status;
+ }
+
+ //
+ // check if there is a serial number provided
+ //
+ if (DeviceExtension->DeviceDescriptor->iSerialNumber)
+ {
+ //
+ // get serial number
+ //
+ Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_STRING_DESCRIPTOR_TYPE, 100 * sizeof(WCHAR), DeviceExtension->DeviceDescriptor->iSerialNumber, 0x0409, (PVOID*)&DeviceExtension->SerialNumber);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to get serial number descriptor, free device descriptor
+ //
+ FreeItem(DeviceExtension->DeviceDescriptor);
+ DeviceExtension->DeviceDescriptor = NULL;
+
+ //
+ // free configuration descriptor
+ //
+ FreeItem(DeviceExtension->ConfigurationDescriptor);
+ DeviceExtension->ConfigurationDescriptor = NULL;
+
+ //
+ // set serial number to zero
+ //
+ DeviceExtension->SerialNumber = NULL;
+ return Status;
+ }
+ }
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+USBSTOR_ScanConfigurationDescriptor(
+ IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
+ OUT PUSB_INTERFACE_DESCRIPTOR * OutInterfaceDescriptor,
+ OUT PUSB_ENDPOINT_DESCRIPTOR * InEndpointDescriptor,
+ OUT PUSB_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
+{
+ PUSB_CONFIGURATION_DESCRIPTOR CurrentDescriptor;
+ PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+
+ //
+ // sanity checks
+ //
+ ASSERT(ConfigurationDescriptor);
+ ASSERT(OutInterfaceDescriptor);
+ ASSERT(InEndpointDescriptor);
+ ASSERT(OutEndpointDescriptor);
+
+ //
+ // nullify pointers
+ //
+ *OutInterfaceDescriptor = NULL;
+ *InEndpointDescriptor = NULL;
+ *OutEndpointDescriptor = NULL;
+
+ //
+ // start scanning
+ //
+ CurrentDescriptor = ConfigurationDescriptor;
+
+ do
+ {
+ //
+ // check current descriptor type
+ //
+ if (CurrentDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
+ {
+ //
+ // found interface descriptor
+ //
+ if (*OutInterfaceDescriptor)
+ {
+ //
+ // we only process the first interface descriptor as ms does -> see documentation
+ //
+ break;
+ }
+
+ //
+ // store interface descriptor
+ //
+ *OutInterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)CurrentDescriptor;
+ }
+ else if (CurrentDescriptor->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE)
+ {
+ //
+ // convert to endpoint descriptor
+ //
+ EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)CurrentDescriptor;
+
+ //
+ // sanity check
+ //
+ ASSERT(*OutInterfaceDescriptor);
+
+ //
+ // get endpoint type
+ //
+ if ((EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK)
+ {
+ //
+ // bulk endpoint type
+ //
+ if (USB_ENDPOINT_DIRECTION_IN(EndpointDescriptor->bEndpointAddress))
+ {
+ //
+ // bulk in
+ //
+ *InEndpointDescriptor = EndpointDescriptor;
+ }
+ else
+ {
+ //
+ // bulk out
+ //
+ *OutEndpointDescriptor = EndpointDescriptor;
+ }
+ }
+ else if ((EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT)
+ {
+ //
+ // interrupt endpoint type
+ //
+ UNIMPLEMENTED;
+ }
+ }
+
+ //
+ // move to next descriptor
+ //
+ CurrentDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)((ULONG_PTR)CurrentDescriptor + CurrentDescriptor->bLength);
+
+ //
+ // was it the last descriptor
+ //
+ if ((ULONG_PTR)CurrentDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
+ {
+ //
+ // reached last descriptor
+ //
+ break;
+ }
+
+ }while(TRUE);
+
+ //
+ // check if everything has been found
+ //
+ if (*OutInterfaceDescriptor == NULL || *InEndpointDescriptor == NULL || *OutEndpointDescriptor == NULL)
+ {
+ //
+ // failed to find interface / endpoint descriptor
+ //
+ DPRINT1("USBSTOR_ScanConfigurationDescriptor: Failed to find InterfaceDescriptor %p InEndpointDescriptor %p OutEndpointDescriptor %p\n", *OutInterfaceDescriptor, *InEndpointDescriptor, *OutEndpointDescriptor);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // completed successfully
+ //
+ return STATUS_SUCCESS;
+}
+
+VOID
+DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
+{
+ DPRINT1("Dumping ConfigurationDescriptor %p\n", ConfigurationDescriptor);
+ DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength);
+ DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
+ DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
+ DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
+ DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
+ DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
+ DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
+ DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
+}
+
+NTSTATUS
+USBSTOR_SelectConfigurationAndInterface(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PFDO_DEVICE_EXTENSION DeviceExtension)
+{
+ PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+ PUSB_ENDPOINT_DESCRIPTOR InEndpointDescriptor, OutEndpointDescriptor;
+ NTSTATUS Status;
+ PURB Urb;
+ PUSBD_INTERFACE_LIST_ENTRY InterfaceList;
+
+ //
+ // now scan configuration descriptors
+ //
+ Status = USBSTOR_ScanConfigurationDescriptor(DeviceExtension->ConfigurationDescriptor, &InterfaceDescriptor, &InEndpointDescriptor, &OutEndpointDescriptor);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to scan
+ //
+ return Status;
+ }
+
+ //
+ // now allocate one interface entry and terminating null entry
+ //
+ InterfaceList = (PUSBD_INTERFACE_LIST_ENTRY)AllocateItem(PagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * 2);
+ if (!InterfaceList)
+ {
+ //
+ // no memory
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // initialize interface list entry
+ //
+ InterfaceList[0].InterfaceDescriptor = InterfaceDescriptor;
+
+ //
+ // now allocate the urb
+ //
+ Urb = USBD_CreateConfigurationRequestEx(DeviceExtension->ConfigurationDescriptor, InterfaceList);
+ if (!Urb)
+ {
+ //
+ // no memory
+ //
+ FreeItem(InterfaceList);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // sanity check
+ //
+ ASSERT(InterfaceList[0].Interface);
+
+ //
+ // submit urb
+ //
+ Status = USBSTOR_SyncUrbRequest(DeviceExtension->LowerDeviceObject, Urb);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to set configuration
+ //
+ DPRINT1("USBSTOR_SelectConfiguration failed to set interface %x\n", Status);
+ FreeItem(InterfaceList);
+ ExFreePoolWithTag(Urb, 0);
+ return Status;
+ }
+
+ //
+ // backup interface information
+ //
+ DeviceExtension->InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)AllocateItem(NonPagedPool, Urb->UrbSelectConfiguration.Interface.Length);
+ if (!DeviceExtension->InterfaceInformation)
+ {
+ //
+ // failed to allocate interface information structure
+ //
+ FreeItem(InterfaceList);
+ ExFreePoolWithTag(Urb, 0);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // copy interface information
+ //
+ RtlCopyMemory(DeviceExtension->InterfaceInformation, &Urb->UrbSelectConfiguration.Interface, Urb->UrbSelectConfiguration.Interface.Length);
+
+ //
+ // store pipe handle
+ //
+ DeviceExtension->ConfigurationHandle = Urb->UrbSelectConfiguration.ConfigurationHandle;
+
+ //
+ // now prepare interface urb
+ //
+ UsbBuildSelectInterfaceRequest(Urb, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceDescriptor->bNumEndpoints), DeviceExtension->ConfigurationHandle, InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting);
+
+ //
+ // copy interface information structure back - as offset for SelectConfiguration / SelectInterface request do differ
+ //
+ RtlCopyMemory(&Urb->UrbSelectInterface.Interface, DeviceExtension->InterfaceInformation, DeviceExtension->InterfaceInformation->Length);
+
+ //
+ // now select the interface
+ //
+ Status = USBSTOR_SyncUrbRequest(DeviceExtension->LowerDeviceObject, Urb);
+
+ //
+ // did it succeed
+ //
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // update configuration info
+ //
+ ASSERT(Urb->UrbSelectInterface.Interface.Length == DeviceExtension->InterfaceInformation->Length);
+ RtlCopyMemory(DeviceExtension->InterfaceInformation, &Urb->UrbSelectInterface.Interface, Urb->UrbSelectInterface.Interface.Length);
+ }
+
+ //
+ // free interface list & urb
+ //
+ FreeItem(InterfaceList);
+ ExFreePoolWithTag(Urb, 0);
+
+ //
+ // done
+ //
+ return Status;
+}
+
+NTSTATUS
+USBSTOR_GetPipeHandles(
+ IN PFDO_DEVICE_EXTENSION DeviceExtension)
+{
+ ULONG Index;
+ BOOLEAN BulkInFound = FALSE, BulkOutFound = FALSE;
+
+ //
+ // no enumerate all pipes and extract bulk-in / bulk-out pipe handle
+ //
+ for(Index = 0; Index < DeviceExtension->InterfaceInformation->NumberOfPipes; Index++)
+ {
+ //
+ // check pipe type
+ //
+ if (DeviceExtension->InterfaceInformation->Pipes[Index].PipeType == UsbdPipeTypeBulk)
+ {
+ //
+ // check direction
+ //
+ if (USB_ENDPOINT_DIRECTION_IN(DeviceExtension->InterfaceInformation->Pipes[Index].EndpointAddress))
+ {
+ //
+ // bulk in pipe
+ //
+ DeviceExtension->BulkInPipeIndex = Index;
+
+ //
+ // there should not be another bulk in pipe
+ //
+ ASSERT(BulkInFound == FALSE);
+ BulkInFound = TRUE;
+ }
+ else
+ {
+ //
+ // bulk out pipe
+ //
+ DeviceExtension->BulkOutPipeIndex = Index;
+
+ //
+ // there should not be another bulk out pipe
+ //
+ ASSERT(BulkOutFound == FALSE);
+ BulkOutFound = TRUE;
+ }
+ }
+ }
+
+ //
+ // check if both bulk pipes have been found
+ //
+ if (!BulkInFound || !BulkOutFound)
+ {
+ //
+ // WTF? usb port driver does not give us bulk pipe access
+ //
+ DPRINT1("USBSTOR_GetPipeHandles> BulkInFound %c BulkOutFound %c missing!!!\n", BulkInFound, BulkOutFound);
+ return STATUS_DEVICE_CONFIGURATION_ERROR;
+ }
+
+ //
+ // device is configured
+ //
+ return STATUS_SUCCESS;
+}
--- /dev/null
+/*
+ * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: drivers/usb/usbstor/disk.c
+ * PURPOSE: USB block storage device driver.
+ * PROGRAMMERS:
+ * James Tabor
+ * Michael Martin (michael.martin@reactos.org)
+ * Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+#include "usbstor.h"
+
+#define NDEBUG
+#include <debug.h>
+
+NTSTATUS
+USBSTOR_HandleInternalDeviceControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ PSCSI_REQUEST_BLOCK Request;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ NTSTATUS Status;
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // get request block
+ //
+ Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
+
+ //
+ // sanity check
+ //
+ ASSERT(Request);
+
+ //
+ // get device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+
+ switch(Request->Function)
+ {
+ case SRB_FUNCTION_EXECUTE_SCSI:
+ {
+ DPRINT("SRB_FUNCTION_EXECUTE_SCSI\n");
+
+ //
+ // check if request is valid
+ //
+ if (Request->SrbFlags & (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT))
+ {
+ //
+ // data is transferred with this irp
+ //
+ if ((Request->SrbFlags & (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT)) == (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT) ||
+ Request->DataTransferLength == 0 ||
+ Irp->MdlAddress == NULL)
+ {
+ //
+ // invalid parameter
+ //
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ }
+ else
+ {
+ //
+ // sense buffer request
+ //
+ if (Request->DataTransferLength ||
+ Request->DataBuffer ||
+ Irp->MdlAddress)
+ {
+ //
+ // invalid parameter
+ //
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ }
+
+ //
+ // add the request
+ //
+ if (!USBSTOR_QueueAddIrp(PDODeviceExtension->LowerDeviceObject, Irp))
+ {
+ //
+ // irp was not added to the queue
+ //
+ IoStartPacket(PDODeviceExtension->LowerDeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo);
+ }
+
+ //
+ // irp pending
+ //
+ return STATUS_PENDING;
+ }
+ case SRB_FUNCTION_RELEASE_DEVICE:
+ {
+ DPRINT1("SRB_FUNCTION_RELEASE_DEVICE\n");
+ //
+ // sanity check
+ //
+ ASSERT(PDODeviceExtension->Claimed == TRUE);
+
+ //
+ // release claim
+ //
+ PDODeviceExtension->Claimed = FALSE;
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ case SRB_FUNCTION_CLAIM_DEVICE:
+ {
+ DPRINT1("SRB_FUNCTION_CLAIM_DEVICE\n");
+ //
+ // check if the device has been claimed
+ //
+ if (PDODeviceExtension->Claimed)
+ {
+ //
+ // device has already been claimed
+ //
+ Status = STATUS_DEVICE_BUSY;
+ Request->SrbStatus = SRB_STATUS_BUSY;
+ break;
+ }
+
+ //
+ // claim device
+ //
+ PDODeviceExtension->Claimed = TRUE;
+
+ //
+ // output device object
+ //
+ Request->DataBuffer = DeviceObject;
+
+ //
+ // completed successfully
+ //
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ case SRB_FUNCTION_RELEASE_QUEUE:
+ {
+ DPRINT1("SRB_FUNCTION_RELEASE_QUEUE\n");
+
+ //
+ // release queue
+ //
+ USBSTOR_QueueRelease(PDODeviceExtension->LowerDeviceObject);
+
+ //
+ // set status success
+ //
+ Request->SrbStatus = SRB_STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
+ break;
+ }
+
+ case SRB_FUNCTION_SHUTDOWN:
+ case SRB_FUNCTION_FLUSH:
+ case SRB_FUNCTION_FLUSH_QUEUE:
+ {
+ DPRINT1("SRB_FUNCTION_FLUSH / SRB_FUNCTION_FLUSH_QUEUE / SRB_FUNCTION_SHUTDOWN\n");
+
+ // HACK: don't flush pending requests
+#if 0 // we really need a proper storage stack
+ //
+ // wait for pending requests to finish
+ //
+ USBSTOR_QueueWaitForPendingRequests(PDODeviceExtension->LowerDeviceObject);
+#endif
+ //
+ // set status success
+ //
+ Request->SrbStatus = SRB_STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ default:
+ {
+ //
+ // not supported
+ //
+ Status = STATUS_NOT_SUPPORTED;
+ Request->SrbStatus = SRB_STATUS_ERROR;
+ }
+ }
+
+ //
+ // complete request
+ //
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+}
+
+ULONG
+USBSTOR_GetFieldLength(
+ IN PUCHAR Name,
+ IN ULONG MaxLength)
+{
+ ULONG Index;
+ ULONG LastCharacterPosition = 0;
+
+ //
+ // scan the field and return last position which contains a valid character
+ //
+ for(Index = 0; Index < MaxLength; Index++)
+ {
+ if (Name[Index] != ' ')
+ {
+ //
+ // trim white spaces from field
+ //
+ LastCharacterPosition = Index;
+ }
+ }
+
+ //
+ // convert from zero based index to length
+ //
+ return LastCharacterPosition + 1;
+}
+
+NTSTATUS
+USBSTOR_HandleQueryProperty(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ PSTORAGE_PROPERTY_QUERY PropertyQuery;
+ PSTORAGE_DESCRIPTOR_HEADER DescriptorHeader;
+ PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor;
+ ULONG FieldLengthVendor, FieldLengthProduct, FieldLengthRevision, TotalLength, FieldLengthSerialNumber;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PUFI_INQUIRY_RESPONSE InquiryData;
+ PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor;
+ PUCHAR Buffer;
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
+ UNICODE_STRING SerialNumber;
+ ANSI_STRING AnsiString;
+ NTSTATUS Status;
+
+ DPRINT("USBSTOR_HandleQueryProperty\n");
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // sanity check
+ //
+ ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(STORAGE_PROPERTY_QUERY));
+ ASSERT(Irp->AssociatedIrp.SystemBuffer);
+
+ //
+ // get property query
+ //
+ PropertyQuery = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
+
+ //
+ // check property type
+ //
+ if (PropertyQuery->PropertyId != StorageDeviceProperty &&
+ PropertyQuery->PropertyId != StorageAdapterProperty)
+ {
+ //
+ // only device property / adapter property are supported
+ //
+ return STATUS_INVALID_PARAMETER_1;
+ }
+
+ //
+ // check query type
+ //
+ if (PropertyQuery->QueryType == PropertyExistsQuery)
+ {
+ //
+ // device property / adapter property is supported
+ //
+ return STATUS_SUCCESS;
+ }
+
+ if (PropertyQuery->QueryType != PropertyStandardQuery)
+ {
+ //
+ // only standard query and exists query are supported
+ //
+ return STATUS_INVALID_PARAMETER_2;
+ }
+
+ //
+ // check if it is a device property
+ //
+ if (PropertyQuery->PropertyId == StorageDeviceProperty)
+ {
+ DPRINT("USBSTOR_HandleQueryProperty StorageDeviceProperty OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength);
+
+ //
+ // get device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ ASSERT(PDODeviceExtension);
+ ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+
+ //
+ // get device extension
+ //
+ FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
+ ASSERT(FDODeviceExtension);
+ ASSERT(FDODeviceExtension->Common.IsFDO);
+
+ //
+ // get inquiry data
+ //
+ InquiryData = (PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData;
+ ASSERT(InquiryData);
+
+ //
+ // compute extra parameters length
+ //
+ FieldLengthVendor = USBSTOR_GetFieldLength(InquiryData->Vendor, 8);
+ FieldLengthProduct = USBSTOR_GetFieldLength(InquiryData->Product, 16);
+ FieldLengthRevision = USBSTOR_GetFieldLength(InquiryData->Revision, 4);
+
+ //
+ // is there a serial number
+ //
+ if (FDODeviceExtension->SerialNumber)
+ {
+ //
+ // get length
+ //
+ FieldLengthSerialNumber = wcslen(FDODeviceExtension->SerialNumber->bString);
+ }
+ else
+ {
+ //
+ // no serial number
+ //
+ FieldLengthSerialNumber = 0;
+ }
+
+ //
+ // total length required is sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLength + 4 extra null bytes - 1
+ // -1 due STORAGE_DEVICE_DESCRIPTOR contains one byte length of parameter data
+ //
+ TotalLength = sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + FieldLengthSerialNumber + 3;
+
+ //
+ // check if output buffer is long enough
+ //
+ if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < TotalLength)
+ {
+ //
+ // buffer too small
+ //
+ DescriptorHeader = (PSTORAGE_DESCRIPTOR_HEADER)Irp->AssociatedIrp.SystemBuffer;
+ ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(STORAGE_DESCRIPTOR_HEADER));
+
+ //
+ // return required size
+ //
+ DescriptorHeader->Version = TotalLength;
+ DescriptorHeader->Size = TotalLength;
+
+ Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER);
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // get device descriptor
+ //
+ DeviceDescriptor = (PSTORAGE_DEVICE_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
+
+ //
+ // initialize device descriptor
+ //
+ DeviceDescriptor->Version = TotalLength;
+ DeviceDescriptor->Size = TotalLength;
+ DeviceDescriptor->DeviceType = InquiryData->DeviceType;
+ DeviceDescriptor->DeviceTypeModifier = (InquiryData->RMB & 0x7F);
+ DeviceDescriptor->RemovableMedia = (InquiryData->RMB & 0x80) ? TRUE : FALSE;
+ DeviceDescriptor->CommandQueueing = FALSE;
+ DeviceDescriptor->BusType = BusTypeUsb;
+ DeviceDescriptor->VendorIdOffset = sizeof(STORAGE_DEVICE_DESCRIPTOR) - sizeof(UCHAR);
+ DeviceDescriptor->ProductIdOffset = DeviceDescriptor->VendorIdOffset + FieldLengthVendor + 1;
+ DeviceDescriptor->ProductRevisionOffset = DeviceDescriptor->ProductIdOffset + FieldLengthProduct + 1;
+ DeviceDescriptor->SerialNumberOffset = (FieldLengthSerialNumber > 0 ? DeviceDescriptor->ProductRevisionOffset + FieldLengthRevision + 1 : 0);
+ DeviceDescriptor->RawPropertiesLength = FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + FieldLengthSerialNumber + 3 + (FieldLengthSerialNumber > 0 ? + 1 : 0);
+
+ //
+ // copy descriptors
+ //
+ Buffer = (PUCHAR)((ULONG_PTR)DeviceDescriptor + sizeof(STORAGE_DEVICE_DESCRIPTOR) - sizeof(UCHAR));
+
+ //
+ // copy vendor
+ //
+ RtlCopyMemory(Buffer, InquiryData->Vendor, FieldLengthVendor);
+ Buffer[FieldLengthVendor] = '\0';
+ Buffer += FieldLengthVendor + 1;
+
+ //
+ // copy product
+ //
+ RtlCopyMemory(Buffer, InquiryData->Product, FieldLengthProduct);
+ Buffer[FieldLengthProduct] = '\0';
+ Buffer += FieldLengthProduct + 1;
+
+ //
+ // copy revision
+ //
+ RtlCopyMemory(Buffer, InquiryData->Revision, FieldLengthRevision);
+ Buffer[FieldLengthRevision] = '\0';
+ Buffer += FieldLengthRevision + 1;
+
+ //
+ // copy serial number
+ //
+ if (FieldLengthSerialNumber)
+ {
+ //
+ // init unicode string
+ //
+ RtlInitUnicodeString(&SerialNumber, FDODeviceExtension->SerialNumber->bString);
+
+ //
+ // init ansi string
+ //
+ AnsiString.Buffer = (PCHAR)Buffer;
+ AnsiString.Length = 0;
+ AnsiString.MaximumLength = FieldLengthSerialNumber * sizeof(WCHAR);
+
+ //
+ // convert to ansi code
+ //
+ Status = RtlUnicodeStringToAnsiString(&AnsiString, &SerialNumber, FALSE);
+ ASSERT(Status == STATUS_SUCCESS);
+ }
+
+
+ DPRINT("Vendor %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->VendorIdOffset));
+ DPRINT("Product %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->ProductIdOffset));
+ DPRINT("Revision %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->ProductRevisionOffset));
+ DPRINT("Serial %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->SerialNumberOffset));
+
+ //
+ // done
+ //
+ Irp->IoStatus.Information = TotalLength;
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ //
+ // adapter property query request
+ //
+ DPRINT("USBSTOR_HandleQueryProperty StorageAdapterProperty OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength);
+
+ if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_ADAPTER_DESCRIPTOR))
+ {
+ //
+ // buffer too small
+ //
+ DescriptorHeader = (PSTORAGE_DESCRIPTOR_HEADER)Irp->AssociatedIrp.SystemBuffer;
+ ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(STORAGE_DESCRIPTOR_HEADER));
+
+ //
+ // return required size
+ //
+ DescriptorHeader->Version = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
+ DescriptorHeader->Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
+
+ Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER);
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // get adapter descriptor, information is returned in the same buffer
+ //
+ AdapterDescriptor = (PSTORAGE_ADAPTER_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
+
+ //
+ // fill out descriptor
+ //
+ AdapterDescriptor->Version = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
+ AdapterDescriptor->Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
+ AdapterDescriptor->MaximumTransferLength = MAXULONG; //FIXME compute some sane value
+ AdapterDescriptor->MaximumPhysicalPages = 25; //FIXME compute some sane value
+ AdapterDescriptor->AlignmentMask = 0;
+ AdapterDescriptor->AdapterUsesPio = FALSE;
+ AdapterDescriptor->AdapterScansDown = FALSE;
+ AdapterDescriptor->CommandQueueing = FALSE;
+ AdapterDescriptor->AcceleratedTransfer = FALSE;
+ AdapterDescriptor->BusType = BusTypeUsb;
+ AdapterDescriptor->BusMajorVersion = 0x2; //FIXME verify
+ AdapterDescriptor->BusMinorVersion = 0x00; //FIXME
+
+ //
+ // store returned length
+ //
+ Irp->IoStatus.Information = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
+ }
+}
+
+NTSTATUS
+USBSTOR_HandleDeviceControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ NTSTATUS Status;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PSCSI_ADAPTER_BUS_INFO BusInfo;
+ PSCSI_INQUIRY_DATA InquiryData;
+ PINQUIRYDATA ScsiInquiryData;
+ PUFI_INQUIRY_RESPONSE UFIInquiryResponse;
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_STORAGE_QUERY_PROPERTY)
+ {
+ //
+ // query property
+ //
+ Status = USBSTOR_HandleQueryProperty(DeviceObject, Irp);
+ }
+ else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH)
+ {
+ //
+ // query scsi pass through
+ //
+ DPRINT1("USBSTOR_HandleDeviceControl IOCTL_SCSI_PASS_THROUGH NOT implemented\n");
+ Status = STATUS_NOT_SUPPORTED;
+ }
+ else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT)
+ {
+ //
+ // query scsi pass through direct
+ //
+ DPRINT1("USBSTOR_HandleDeviceControl IOCTL_SCSI_PASS_THROUGH_DIRECT NOT implemented\n");
+ Status = STATUS_NOT_SUPPORTED;
+ }
+ else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER)
+ {
+ //
+ // query serial number
+ //
+ DPRINT1("USBSTOR_HandleDeviceControl IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER NOT implemented\n");
+ Status = STATUS_NOT_SUPPORTED;
+ }
+ else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_GET_CAPABILITIES)
+ {
+ PIO_SCSI_CAPABILITIES Capabilities;
+
+ /* Legacy port capability query */
+ if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(PVOID))
+ {
+ Capabilities = *((PVOID *)Irp->AssociatedIrp.SystemBuffer) = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(IO_SCSI_CAPABILITIES),
+ USB_STOR_TAG);
+ Irp->IoStatus.Information = sizeof(PVOID);
+ }
+ else
+ {
+ Capabilities = Irp->AssociatedIrp.SystemBuffer;
+ Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
+ }
+
+ if (Capabilities)
+ {
+ Capabilities->MaximumTransferLength = MAXULONG;
+ Capabilities->MaximumPhysicalPages = 25;
+ Capabilities->SupportedAsynchronousEvents = 0;
+ Capabilities->AlignmentMask = 0;
+ Capabilities->TaggedQueuing = FALSE;
+ Capabilities->AdapterScansDown = FALSE;
+ Capabilities->AdapterUsesPio = FALSE;
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_GET_INQUIRY_DATA)
+ {
+ //
+ // get device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ ASSERT(PDODeviceExtension);
+ ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+
+ //
+ // get parameters
+ //
+ BusInfo = Irp->AssociatedIrp.SystemBuffer;
+ InquiryData = (PSCSI_INQUIRY_DATA)(BusInfo + 1);
+ ScsiInquiryData = (PINQUIRYDATA)InquiryData->InquiryData;
+
+
+ //
+ // get inquiry data
+ //
+ UFIInquiryResponse = (PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData;
+ ASSERT(UFIInquiryResponse);
+
+
+ BusInfo->NumberOfBuses = 1;
+ BusInfo->BusData[0].NumberOfLogicalUnits = 1; //FIXME
+ BusInfo->BusData[0].InitiatorBusId = 0;
+ BusInfo->BusData[0].InquiryDataOffset = sizeof(SCSI_ADAPTER_BUS_INFO);
+
+ InquiryData->PathId = 0;
+ InquiryData->TargetId = 0;
+ InquiryData->Lun = PDODeviceExtension->LUN & MAX_LUN;
+ InquiryData->DeviceClaimed = PDODeviceExtension->Claimed;
+ InquiryData->InquiryDataLength = sizeof(INQUIRYDATA);
+ InquiryData->NextInquiryDataOffset = 0;
+
+ RtlZeroMemory(ScsiInquiryData, sizeof(INQUIRYDATA));
+ ScsiInquiryData->DeviceType = UFIInquiryResponse->DeviceType;
+ ScsiInquiryData->DeviceTypeQualifier = (UFIInquiryResponse->RMB & 0x7F);
+
+ /* Hack for IoReadPartitionTable call in disk.sys */
+ ScsiInquiryData->RemovableMedia = ((ScsiInquiryData->DeviceType != DIRECT_ACCESS_DEVICE) ? ((UFIInquiryResponse->RMB & 0x80) ? 1 : 0) : 0);
+
+ ScsiInquiryData->Versions = 0x04;
+ ScsiInquiryData->ResponseDataFormat = 0x02;
+ ScsiInquiryData->AdditionalLength = 31;
+ ScsiInquiryData->SoftReset = 0;
+ ScsiInquiryData->CommandQueue = 0;
+ ScsiInquiryData->LinkedCommands = 0;
+ ScsiInquiryData->RelativeAddressing = 0;
+
+ RtlCopyMemory(&ScsiInquiryData->VendorId, UFIInquiryResponse->Vendor, USBSTOR_GetFieldLength(UFIInquiryResponse->Vendor, 8));
+ RtlCopyMemory(&ScsiInquiryData->ProductId, UFIInquiryResponse->Product, USBSTOR_GetFieldLength(UFIInquiryResponse->Product, 16));
+
+ Irp->IoStatus.Information = sizeof(SCSI_ADAPTER_BUS_INFO) + sizeof(SCSI_INQUIRY_DATA) + sizeof(INQUIRYDATA) - 1;
+ Status = STATUS_SUCCESS;
+ }
+ else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_GET_ADDRESS)
+ {
+ PSCSI_ADDRESS Address = Irp->AssociatedIrp.SystemBuffer;
+
+ Address->Length = sizeof(SCSI_ADDRESS);
+ Address->PortNumber = 0;
+ Address->PathId = 0;
+ Address->TargetId = 0;
+ Address->Lun = (((PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LUN & MAX_LUN);
+ Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
+
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ //
+ // unsupported
+ //
+ DPRINT("USBSTOR_HandleDeviceControl IoControl %x not supported\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
+ Status = STATUS_NOT_SUPPORTED;
+ }
+
+ return Status;
+}
--- /dev/null
+/*
+ * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: drivers/usb/usbstor/error.c
+ * PURPOSE: USB block storage device driver.
+ * PROGRAMMERS:
+ * James Tabor
+ * Michael Martin (michael.martin@reactos.org)
+ * Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+#include "usbstor.h"
+
+#define NDEBUG
+#include <debug.h>
+
+NTSTATUS
+USBSTOR_GetEndpointStatus(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN UCHAR bEndpointAddress,
+ OUT PUSHORT Value)
+{
+ PURB Urb;
+ NTSTATUS Status;
+
+ //
+ // allocate urb
+ //
+ DPRINT("Allocating URB\n");
+ Urb = (PURB)AllocateItem(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
+ if (!Urb)
+ {
+ //
+ // out of memory
+ //
+ DPRINT1("OutofMemory!\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // build status
+ //
+ UsbBuildGetStatusRequest(Urb, URB_FUNCTION_GET_STATUS_FROM_ENDPOINT, bEndpointAddress & 0x0F, Value, NULL, NULL);
+
+ //
+ // send the request
+ //
+ DPRINT1("Sending Request DeviceObject %p, Urb %p\n", DeviceObject, Urb);
+ Status = USBSTOR_SyncUrbRequest(DeviceObject, Urb);
+
+ //
+ // free urb
+ //
+ FreeItem(Urb);
+
+ //
+ // done
+ //
+ return Status;
+}
+
+
+
+NTSTATUS
+USBSTOR_ResetPipeWithHandle(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN USBD_PIPE_HANDLE PipeHandle)
+{
+ PURB Urb;
+ NTSTATUS Status;
+
+ //
+ // allocate urb
+ //
+ DPRINT("Allocating URB\n");
+ Urb = (PURB)AllocateItem(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST));
+ if (!Urb)
+ {
+ //
+ // out of memory
+ //
+ DPRINT1("OutofMemory!\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // initialize the urb
+ //
+ Urb->UrbPipeRequest.Hdr.Length = sizeof(struct _URB_PIPE_REQUEST);
+ Urb->UrbPipeRequest.Hdr.Function = URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL;
+ Urb->UrbPipeRequest.PipeHandle = PipeHandle;
+
+ //
+ // send the request
+ //
+ DPRINT1("Sending Request DeviceObject %p, Urb %p\n", DeviceObject, Urb);
+ Status = USBSTOR_SyncUrbRequest(DeviceObject, Urb);
+
+ //
+ // free urb
+ //
+ FreeItem(Urb);
+
+ //
+ // done
+ //
+ return Status;
+}
+
+
+NTSTATUS
+USBSTOR_HandleTransferError(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP_CONTEXT Context)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PIO_STACK_LOCATION Stack;
+ PSCSI_REQUEST_BLOCK Request;
+ PCDB pCDB;
+
+ //
+ // sanity checks
+ //
+ ASSERT(Context);
+ ASSERT(Context->PDODeviceExtension);
+ ASSERT(Context->PDODeviceExtension->Self);
+ ASSERT(Context->Irp);
+
+ //
+ // first perform a mass storage reset step 1 in 5.3.4 USB Mass Storage Bulk Only Specification
+ //
+ Status = USBSTOR_ResetDevice(Context->FDODeviceExtension->LowerDeviceObject, Context->FDODeviceExtension);
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // step 2 reset bulk in pipe section 5.3.4
+ //
+ Status = USBSTOR_ResetPipeWithHandle(Context->FDODeviceExtension->LowerDeviceObject, Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle);
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // finally reset bulk out pipe
+ //
+ Status = USBSTOR_ResetPipeWithHandle(Context->FDODeviceExtension->LowerDeviceObject, Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkOutPipeIndex].PipeHandle);
+ }
+ }
+
+ //
+ // get next stack location
+ //
+ Stack = IoGetCurrentIrpStackLocation(Context->Irp);
+
+ //
+ // get request block
+ //
+ Request = (PSCSI_REQUEST_BLOCK)Stack->Parameters.Others.Argument1;
+ ASSERT(Request);
+
+ //
+ // obtain request type
+ //
+ pCDB = (PCDB)Request->Cdb;
+ ASSERT(pCDB);
+
+ if (Status != STATUS_SUCCESS || Context->RetryCount >= 1)
+ {
+ //
+ // Complete the master IRP
+ //
+ Context->Irp->IoStatus.Status = Status;
+ Context->Irp->IoStatus.Information = 0;
+ 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
+ {
+ DPRINT1("Retrying Count %lu %p\n", Context->RetryCount, Context->PDODeviceExtension->Self);
+
+ //
+ // 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;
+ }
+
+ //
+ // cleanup irp context
+ //
+ FreeItem(Context->cbw);
+ FreeItem(Context);
+
+
+ DPRINT1("USBSTOR_HandleTransferError returning with Status %x\n", Status);
+ return Status;
+}
+
+VOID
+NTAPI
+USBSTOR_ResetHandlerWorkItemRoutine(
+ PVOID Context)
+{
+ NTSTATUS Status;
+ PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context;
+
+ //
+ // clear stall on BulkIn pipe
+ //
+ Status = USBSTOR_ResetPipeWithHandle(WorkItemData->Context->FDODeviceExtension->LowerDeviceObject, WorkItemData->Context->FDODeviceExtension->InterfaceInformation->Pipes[WorkItemData->Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle);
+ DPRINT1("USBSTOR_ResetPipeWithHandle Status %x\n", Status);
+
+ //
+ // now resend the csw as the stall got cleared
+ //
+ USBSTOR_SendCSW(WorkItemData->Context, WorkItemData->Irp);
+}
+
+VOID
+NTAPI
+ErrorHandlerWorkItemRoutine(
+ PVOID Context)
+{
+ PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context;
+
+ if (WorkItemData->Context->ErrorIndex == 2)
+ {
+ //
+ // reset device
+ //
+ USBSTOR_HandleTransferError(WorkItemData->DeviceObject, WorkItemData->Context);
+ }
+ else
+ {
+ //
+ // clear stall
+ //
+ USBSTOR_ResetHandlerWorkItemRoutine(WorkItemData);
+ }
+
+ //
+ // Free Work Item Data
+ //
+ ExFreePoolWithTag(WorkItemData, USB_STOR_TAG);
+}
+
+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
+ //
+ ExFreePoolWithTag(WorkItemData, USB_STOR_TAG);
+}
+
+
+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 = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(ERRORHANDLER_WORKITEM_DATA),
+ USB_STOR_TAG);
+ 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);
+ }
+ }
+}
--- /dev/null
+/*
+ * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: drivers/usb/usbstor/fdo.c
+ * PURPOSE: USB block storage device driver.
+ * PROGRAMMERS:
+ * James Tabor
+ * Michael Martin (michael.martin@reactos.org)
+ * Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+#include "usbstor.h"
+
+#define NDEBUG
+#include <debug.h>
+
+VOID
+USBSTOR_DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
+{
+ DPRINT1("Dumping Device Descriptor %p\n", DeviceDescriptor);
+ DPRINT1("bLength %x\n", DeviceDescriptor->bLength);
+ DPRINT1("bDescriptorType %x\n", DeviceDescriptor->bDescriptorType);
+ DPRINT1("bcdUSB %x\n", DeviceDescriptor->bcdUSB);
+ DPRINT1("bDeviceClass %x\n", DeviceDescriptor->bDeviceClass);
+ DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor->bDeviceSubClass);
+ DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor->bDeviceProtocol);
+ DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor->bMaxPacketSize0);
+ DPRINT1("idVendor %x\n", DeviceDescriptor->idVendor);
+ DPRINT1("idProduct %x\n", DeviceDescriptor->idProduct);
+ DPRINT1("bcdDevice %x\n", DeviceDescriptor->bcdDevice);
+ DPRINT1("iManufacturer %x\n", DeviceDescriptor->iManufacturer);
+ DPRINT1("iProduct %x\n", DeviceDescriptor->iProduct);
+ DPRINT1("iSerialNumber %x\n", DeviceDescriptor->iSerialNumber);
+ DPRINT1("bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations);
+}
+
+NTSTATUS
+USBSTOR_FdoHandleDeviceRelations(
+ IN PFDO_DEVICE_EXTENSION DeviceExtension,
+ IN OUT PIRP Irp)
+{
+ ULONG DeviceCount = 0;
+ LONG Index;
+ PDEVICE_RELATIONS DeviceRelations;
+ PIO_STACK_LOCATION IoStack;
+
+ //
+ // get current irp stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // check if relation type is BusRelations
+ //
+ if (IoStack->Parameters.QueryDeviceRelations.Type != BusRelations)
+ {
+ //
+ // FDO always only handles bus relations
+ //
+ return USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
+ }
+
+ //
+ // go through array and count device objects
+ //
+ for (Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++)
+ {
+ if (DeviceExtension->ChildPDO[Index])
+ {
+ //
+ // child pdo
+ //
+ DeviceCount++;
+ }
+ }
+
+ //
+ // allocate device relations
+ //
+ DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS) + (DeviceCount > 1 ? (DeviceCount-1) * sizeof(PDEVICE_OBJECT) : 0));
+ if (!DeviceRelations)
+ {
+ //
+ // no memory
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // add device objects
+ //
+ for(Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++)
+ {
+ if (DeviceExtension->ChildPDO[Index])
+ {
+ //
+ // store child pdo
+ //
+ DeviceRelations->Objects[DeviceRelations->Count] = DeviceExtension->ChildPDO[Index];
+
+ //
+ // add reference
+ //
+ ObReferenceObject(DeviceExtension->ChildPDO[Index]);
+
+ //
+ // increment count
+ //
+ DeviceRelations->Count++;
+ }
+ }
+
+ //
+ // store result
+ //
+ Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
+
+ //
+ // request completed successfully
+ //
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USBSTOR_FdoHandleRemoveDevice(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PFDO_DEVICE_EXTENSION DeviceExtension,
+ IN OUT PIRP Irp)
+{
+ NTSTATUS Status;
+ ULONG Index;
+
+ DPRINT("Handling FDO removal %p\n", DeviceObject);
+
+ /* FIXME: wait for devices finished processing */
+ for(Index = 0; Index < 16; Index++)
+ {
+ if (DeviceExtension->ChildPDO[Index] != NULL)
+ {
+ DPRINT("Deleting PDO %p RefCount %x AttachedDevice %p \n", DeviceExtension->ChildPDO[Index], DeviceExtension->ChildPDO[Index]->ReferenceCount, DeviceExtension->ChildPDO[Index]->AttachedDevice);
+ IoDeleteDevice(DeviceExtension->ChildPDO[Index]);
+ }
+ }
+
+ /* Send the IRP down the stack */
+ IoSkipCurrentIrpStackLocation(Irp);
+ Status = IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
+
+ /* Detach from the device stack */
+ IoDetachDevice(DeviceExtension->LowerDeviceObject);
+
+ /* Delete the device object */
+ IoDeleteDevice(DeviceObject);
+
+ return Status;
+}
+
+NTSTATUS
+USBSTOR_FdoHandleStartDevice(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PFDO_DEVICE_EXTENSION DeviceExtension,
+ IN OUT PIRP Irp)
+{
+ PUSB_INTERFACE_DESCRIPTOR InterfaceDesc;
+ NTSTATUS Status;
+ UCHAR Index = 0;
+
+ //
+ // forward irp to lower device
+ //
+ Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to start
+ //
+ DPRINT1("USBSTOR_FdoHandleStartDevice Lower device failed to start %x\n", Status);
+ return Status;
+ }
+
+ //
+ // initialize irp queue
+ //
+ USBSTOR_QueueInitialize(DeviceExtension);
+
+ //
+ // first get device & configuration & string descriptor
+ //
+ Status = USBSTOR_GetDescriptors(DeviceObject);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to get device descriptor
+ //
+ DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device descriptor with %x\n", Status);
+ return Status;
+ }
+
+ //
+ // dump device descriptor
+ //
+ USBSTOR_DumpDeviceDescriptor(DeviceExtension->DeviceDescriptor);
+
+ //
+ // Check that this device uses bulk transfers and is SCSI
+ //
+ InterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)DeviceExtension->ConfigurationDescriptor + sizeof(USB_CONFIGURATION_DESCRIPTOR));
+
+ //
+ // sanity check
+ //
+ ASSERT(InterfaceDesc->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
+ ASSERT(InterfaceDesc->bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
+
+ DPRINT("bInterfaceSubClass %x\n", InterfaceDesc->bInterfaceSubClass);
+ if (InterfaceDesc->bInterfaceProtocol != 0x50)
+ {
+ DPRINT1("USB Device is not a bulk only device and is not currently supported\n");
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ if (InterfaceDesc->bInterfaceSubClass != 0x06)
+ {
+ //
+ // FIXME: need to pad CDBs to 12 byte
+ // mode select commands must be translated from 1AH / 15h to 5AH / 55h
+ //
+ DPRINT1("[USBSTOR] Error: need to pad CDBs\n");
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ //
+ // now select an interface
+ //
+ Status = USBSTOR_SelectConfigurationAndInterface(DeviceObject, DeviceExtension);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to get device descriptor
+ //
+ DPRINT1("USBSTOR_FdoHandleStartDevice failed to select configuration / interface with %x\n", Status);
+ return Status;
+ }
+
+ //
+ // check if we got a bulk in + bulk out endpoint
+ //
+ Status = USBSTOR_GetPipeHandles(DeviceExtension);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to get pipe handles descriptor
+ //
+ DPRINT1("USBSTOR_FdoHandleStartDevice no pipe handles %x\n", Status);
+ return Status;
+ }
+
+ //
+ // get num of lun which are supported
+ //
+ Status = USBSTOR_GetMaxLUN(DeviceExtension->LowerDeviceObject, DeviceExtension);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to get max LUN
+ //
+ DPRINT1("USBSTOR_FdoHandleStartDevice failed to get max lun %x\n", Status);
+ return Status;
+ }
+
+ //
+ // now create for each LUN a device object, 1 minimum
+ //
+ do
+ {
+ //
+ // create pdo
+ //
+ Status = USBSTOR_CreatePDO(DeviceObject, Index);
+
+ //
+ // check for failure
+ //
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to create child pdo
+ //
+ DPRINT1("USBSTOR_FdoHandleStartDevice USBSTOR_CreatePDO failed for Index %lu with Status %x\n", Index, Status);
+ return Status;
+ }
+
+ //
+ // increment pdo index
+ //
+ Index++;
+ DeviceExtension->InstanceCount++;
+
+ }while(Index < DeviceExtension->MaxLUN);
+
+#if 0
+ //
+ // finally get usb device interface
+ //
+ Status = USBSTOR_GetBusInterface(DeviceExtension->LowerDeviceObject, &DeviceExtension->BusInterface);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to device interface
+ //
+ DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device interface %x\n", Status);
+ return Status;
+ }
+#endif
+
+
+ //
+ // start the timer
+ //
+ //IoStartTimer(DeviceObject);
+
+
+ //
+ // fdo is now initialized
+ //
+ DPRINT("USBSTOR_FdoHandleStartDevice FDO is initialized\n");
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USBSTOR_FdoHandlePnp(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ PFDO_DEVICE_EXTENSION DeviceExtension;
+ NTSTATUS Status;
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // get device extension
+ //
+ DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(DeviceExtension->Common.IsFDO);
+
+ switch(IoStack->MinorFunction)
+ {
+ case IRP_MN_SURPRISE_REMOVAL:
+ {
+ DPRINT("IRP_MN_SURPRISE_REMOVAL %p\n", DeviceObject);
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+
+ //
+ // forward irp to next device object
+ //
+ IoSkipCurrentIrpStackLocation(Irp);
+ return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
+ }
+ case IRP_MN_QUERY_DEVICE_RELATIONS:
+ {
+ DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS %p\n", DeviceObject);
+ Status = USBSTOR_FdoHandleDeviceRelations(DeviceExtension, Irp);
+ break;
+ }
+ case IRP_MN_STOP_DEVICE:
+ {
+ DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n");
+ 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:
+ {
+ DPRINT("IRP_MN_REMOVE_DEVICE\n");
+
+ return USBSTOR_FdoHandleRemoveDevice(DeviceObject, DeviceExtension, Irp);
+ }
+ case IRP_MN_QUERY_CAPABILITIES:
+ {
+ //
+ // FIXME: set custom capabilities
+ //
+ IoSkipCurrentIrpStackLocation(Irp);
+ return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
+ }
+ case IRP_MN_QUERY_STOP_DEVICE:
+ case IRP_MN_QUERY_REMOVE_DEVICE:
+ {
+#if 0
+ //
+ // we can if nothing is pending
+ //
+ if (DeviceExtension->IrpPendingCount != 0 ||
+ DeviceExtension->ActiveSrb != NULL)
+#else
+ if (TRUE)
+#endif
+ {
+ /* We have pending requests */
+ DPRINT1("Failing removal/stop request due to pending requests present\n");
+ Status = STATUS_UNSUCCESSFUL;
+ }
+ else
+ {
+ /* We're all clear */
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+
+ IoSkipCurrentIrpStackLocation(Irp);
+ return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
+ }
+ break;
+ }
+ case IRP_MN_START_DEVICE:
+ {
+ Status = USBSTOR_FdoHandleStartDevice(DeviceObject, DeviceExtension, Irp);
+ break;
+ }
+ default:
+ {
+ //
+ // forward irp to next device object
+ //
+ IoSkipCurrentIrpStackLocation(Irp);
+ return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
+ }
+ }
+
+ //
+ // complete request
+ //
+ if (Status != STATUS_PENDING)
+ {
+ //
+ // store result
+ //
+ Irp->IoStatus.Status = Status;
+
+ //
+ // complete request
+ //
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+
+ //
+ // done processing
+ //
+ return Status;
+}
--- /dev/null
+/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */
+
+#include <ntdef.h>
+#include <miniport.h>
+#include <usb.h>
+#include <initguid.h>
+#include <usbbusif.h>
+
+/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */
--- /dev/null
+/*
+ * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: drivers/usb/usbstor/misc.c
+ * PURPOSE: USB block storage device driver.
+ * PROGRAMMERS:
+ * James Tabor
+ * Michael Martin (michael.martin@reactos.org)
+ * Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+#include "usbstor.h"
+
+#define NDEBUG
+#include <debug.h>
+
+//
+// driver verifier
+//
+IO_COMPLETION_ROUTINE SyncForwardIrpCompletionRoutine;
+
+NTSTATUS
+NTAPI
+USBSTOR_SyncForwardIrpCompletionRoutine(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PVOID Context)
+{
+ if (Irp->PendingReturned)
+ {
+ KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
+ }
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS
+NTAPI
+USBSTOR_SyncForwardIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+ KEVENT Event;
+ NTSTATUS Status;
+
+ //
+ // initialize event
+ //
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+ //
+ // copy irp stack location
+ //
+ IoCopyCurrentIrpStackLocationToNext(Irp);
+
+ //
+ // set completion routine
+ //
+ IoSetCompletionRoutine(Irp, USBSTOR_SyncForwardIrpCompletionRoutine, &Event, TRUE, TRUE, TRUE);
+
+
+ //
+ // call driver
+ //
+ Status = IoCallDriver(DeviceObject, Irp);
+
+ //
+ // check if pending
+ //
+ if (Status == STATUS_PENDING)
+ {
+ //
+ // wait for the request to finish
+ //
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+
+ //
+ // copy status code
+ //
+ Status = Irp->IoStatus.Status;
+ }
+
+ //
+ // done
+ //
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+USBSTOR_GetBusInterface(
+ IN PDEVICE_OBJECT DeviceObject,
+ OUT PUSB_BUS_INTERFACE_USBDI_V2 BusInterface)
+{
+ KEVENT Event;
+ NTSTATUS Status;
+ PIRP Irp;
+ IO_STATUS_BLOCK IoStatus;
+ PIO_STACK_LOCATION Stack;
+
+ //
+ // sanity checks
+ //
+ ASSERT(DeviceObject);
+ ASSERT(BusInterface);
+
+
+ //
+ // initialize event
+ //
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+
+ //
+ // create irp
+ //
+ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
+ DeviceObject,
+ NULL,
+ 0,
+ NULL,
+ &Event,
+ &IoStatus);
+
+ //
+ // was irp built
+ //
+ if (Irp == NULL)
+ {
+ //
+ // no memory
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // initialize request
+ //
+ Stack=IoGetNextIrpStackLocation(Irp);
+ Stack->MajorFunction = IRP_MJ_PNP;
+ Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
+ Stack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
+ Stack->Parameters.QueryInterface.InterfaceType = (LPGUID)&USB_BUS_INTERFACE_USBDI_GUID;
+ Stack->Parameters.QueryInterface.Version = 2;
+ Stack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterface;
+ Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
+ Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+
+ //
+ // call driver
+ //
+ Status= IoCallDriver(DeviceObject, Irp);
+
+ //
+ // did operation complete
+ //
+ if (Status == STATUS_PENDING)
+ {
+ //
+ // wait for completion
+ //
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+
+ //
+ // collect status
+ //
+ Status=IoStatus.Status;
+ }
+
+ return Status;
+}
+
+NTSTATUS
+USBSTOR_SyncUrbRequest(
+ IN PDEVICE_OBJECT DeviceObject,
+ OUT PURB UrbRequest)
+{
+ PIRP Irp;
+ PIO_STACK_LOCATION IoStack;
+ KEVENT Event;
+ NTSTATUS Status;
+
+ //
+ // allocate irp
+ //
+ Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
+ if (!Irp)
+ {
+ //
+ // no memory
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // initialize event
+ //
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+
+ //
+ // 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)UrbRequest;
+ IoStack->Parameters.DeviceIoControl.InputBufferLength = UrbRequest->UrbHeader.Length;
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+
+ //
+ // setup completion routine
+ //
+ IoSetCompletionRoutine(Irp, USBSTOR_SyncForwardIrpCompletionRoutine, &Event, TRUE, TRUE, TRUE);
+
+ //
+ // call driver
+ //
+ Status = IoCallDriver(DeviceObject, Irp);
+
+ //
+ // check if request is pending
+ //
+ if (Status == STATUS_PENDING)
+ {
+ //
+ // wait for completion
+ //
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+
+ //
+ // update status
+ //
+ Status = Irp->IoStatus.Status;
+ }
+
+ //
+ // free irp
+ //
+ IoFreeIrp(Irp);
+
+ //
+ // done
+ //
+ return Status;
+}
+
+PVOID
+AllocateItem(
+ IN POOL_TYPE PoolType,
+ IN ULONG ItemSize)
+{
+ //
+ // allocate item
+ //
+ PVOID Item = ExAllocatePoolWithTag(PoolType, ItemSize, USB_STOR_TAG);
+
+ if (Item)
+ {
+ //
+ // zero item
+ //
+ RtlZeroMemory(Item, ItemSize);
+ }
+
+ //
+ // return element
+ //
+ return Item;
+}
+
+VOID
+FreeItem(
+ IN PVOID Item)
+{
+ //
+ // free item
+ //
+ ExFreePoolWithTag(Item, USB_STOR_TAG);
+}
+
+NTSTATUS
+USBSTOR_ClassRequest(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PFDO_DEVICE_EXTENSION DeviceExtension,
+ IN UCHAR RequestType,
+ IN USHORT Index,
+ IN ULONG TransferFlags,
+ IN ULONG TransferBufferLength,
+ IN PVOID TransferBuffer)
+
+{
+ PURB Urb;
+ NTSTATUS Status;
+
+ //
+ // first allocate urb
+ //
+ Urb = (PURB)AllocateItem(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
+ if (!Urb)
+ {
+ //
+ // no memory
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // initialize vendor request
+ //
+ Urb->UrbControlVendorClassRequest.Hdr.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
+ Urb->UrbControlVendorClassRequest.Hdr.Function = URB_FUNCTION_CLASS_INTERFACE;
+ Urb->UrbControlVendorClassRequest.TransferFlags = TransferFlags;
+ Urb->UrbControlVendorClassRequest.TransferBufferLength = TransferBufferLength;
+ Urb->UrbControlVendorClassRequest.TransferBuffer = TransferBuffer;
+ Urb->UrbControlVendorClassRequest.Request = RequestType;
+ Urb->UrbControlVendorClassRequest.Index = Index;
+
+ //
+ // submit request
+ //
+ Status = USBSTOR_SyncUrbRequest(DeviceObject, Urb);
+
+ //
+ // free urb
+ //
+ FreeItem(Urb);
+
+ //
+ // done
+ //
+ return Status;
+}
+
+
+NTSTATUS
+USBSTOR_GetMaxLUN(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PFDO_DEVICE_EXTENSION DeviceExtension)
+{
+ PUCHAR Buffer;
+ NTSTATUS Status;
+
+ //
+ // allocate 1-byte buffer
+ //
+ Buffer = (PUCHAR)AllocateItem(NonPagedPool, sizeof(UCHAR));
+ if (!Buffer)
+ {
+ //
+ // no memory
+ //
+ FreeItem(Buffer);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // execute request
+ //
+ Status = USBSTOR_ClassRequest(DeviceObject, DeviceExtension, USB_BULK_GET_MAX_LUN, DeviceExtension->InterfaceInformation->InterfaceNumber, USBD_TRANSFER_DIRECTION_IN, sizeof(UCHAR), Buffer);
+
+ DPRINT("MaxLUN: %x\n", *Buffer);
+
+ if (NT_SUCCESS(Status))
+ {
+ if (*Buffer > 0xF)
+ {
+ //
+ // invalid response documented in usb mass storage specification
+ //
+ Status = STATUS_DEVICE_DATA_ERROR;
+ }
+ else
+ {
+ //
+ // store maxlun
+ //
+ DeviceExtension->MaxLUN = *Buffer;
+ }
+ }
+ else
+ {
+ //
+ // "USB Mass Storage Class. Bulk-Only Transport. Revision 1.0"
+ // 3.2 Get Max LUN (class-specific request) :
+ // Devices that do not support multiple LUNs may STALL this command.
+ //
+ USBSTOR_ResetDevice(DeviceExtension->LowerDeviceObject, DeviceExtension);
+
+ DeviceExtension->MaxLUN = 0;
+ Status = STATUS_SUCCESS;
+ }
+
+ //
+ // free buffer
+ //
+ FreeItem(Buffer);
+
+ //
+ // done
+ //
+ return Status;
+
+}
+
+NTSTATUS
+USBSTOR_ResetDevice(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PFDO_DEVICE_EXTENSION DeviceExtension)
+{
+ NTSTATUS Status;
+
+ //
+ // execute request
+ //
+ Status = USBSTOR_ClassRequest(DeviceObject, DeviceExtension, USB_BULK_RESET_DEVICE, DeviceExtension->InterfaceInformation->InterfaceNumber, USBD_TRANSFER_DIRECTION_OUT, 0, NULL);
+
+ //
+ // done
+ //
+ 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;
+}
--- /dev/null
+/*
+ * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: drivers/usb/usbstor/pdo.c
+ * PURPOSE: USB block storage device driver.
+ * PROGRAMMERS:
+ * James Tabor
+ * Michael Martin (michael.martin@reactos.org)
+ * Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+#include "usbstor.h"
+
+#define NDEBUG
+#include <debug.h>
+
+LPCSTR
+USBSTOR_GetDeviceType(
+ 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
+ //
+ return "Disk";
+ }
+
+ //
+ // FIXME: use constant - derived from http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type
+ //
+ switch (InquiryData->DeviceType)
+ {
+ case 1:
+ {
+ //
+ // sequential device, i.e magnetic tape
+ //
+ return "Sequential";
+ }
+ case 4:
+ {
+ //
+ // write once device
+ //
+ return "Worm";
+ }
+ case 5:
+ {
+ //
+ // CDROM device
+ //
+ return "CdRom";
+ }
+ case 7:
+ {
+ //
+ // optical memory device
+ //
+ return "Optical";
+ }
+ case 8:
+ {
+ //
+ // medium change device
+ //
+ return "Changer";
+ }
+ default:
+ {
+ //
+ // other device
+ //
+ return "Other";
+ }
+ }
+}
+
+LPCSTR
+USBSTOR_GetGenericType(
+ 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
+ //
+ return "GenDisk";
+ }
+
+ //
+ // FIXME: use constant - derived from http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type
+ //
+ switch (InquiryData->DeviceType)
+ {
+ case 1:
+ {
+ //
+ // sequential device, i.e magnetic tape
+ //
+ return "GenSequential";
+ }
+ case 4:
+ {
+ //
+ // write once device
+ //
+ return "GenWorm";
+ }
+ case 5:
+ {
+ //
+ // CDROM device
+ //
+ return "GenCdRom";
+ }
+ case 7:
+ {
+ //
+ // optical memory device
+ //
+ return "GenOptical";
+ }
+ case 8:
+ {
+ //
+ // medium change device
+ //
+ return "GenChanger";
+ }
+ default:
+ {
+ //
+ // other device
+ //
+ return "UsbstorOther";
+ }
+ }
+}
+
+
+ULONG
+CopyField(
+ IN PUCHAR Name,
+ IN PCHAR Buffer,
+ IN ULONG MaxLength)
+{
+ ULONG Index;
+
+ for(Index = 0; Index < MaxLength; Index++)
+ {
+ if (Name[Index] <= ' ' || Name[Index] >= 0x7F /* last printable ascii character */ || Name[Index] == ',')
+ {
+ //
+ // convert to underscore
+ //
+ Buffer[Index] = '_';
+ }
+ else
+ {
+ //
+ // just copy character
+ //
+ Buffer[Index] = Name[Index];
+ }
+ }
+
+ return MaxLength;
+}
+
+NTSTATUS
+USBSTOR_PdoHandleQueryDeviceText(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ //PPDO_DEVICE_EXTENSION DeviceExtension;
+ PIO_STACK_LOCATION IoStack;
+ LPWSTR Buffer;
+ static WCHAR DeviceText[] = L"USB Mass Storage Device";
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ if (IoStack->Parameters.QueryDeviceText.DeviceTextType == DeviceTextDescription)
+ {
+ DPRINT("USBSTOR_PdoHandleQueryDeviceText DeviceTextDescription\n");
+
+ //
+ // allocate item
+ //
+ Buffer = (LPWSTR)AllocateItem(PagedPool, sizeof(DeviceText));
+ if (!Buffer)
+ {
+ //
+ // no memory
+ //
+ Irp->IoStatus.Information = 0;
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // copy buffer
+ //
+ wcscpy(Buffer, DeviceText);
+
+ //
+ // save result
+ //
+ Irp->IoStatus.Information = (ULONG_PTR)Buffer;
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ DPRINT("USBSTOR_PdoHandleQueryDeviceText DeviceTextLocationInformation\n");
+
+ //
+ // allocate item
+ //
+ Buffer = (LPWSTR)AllocateItem(PagedPool, sizeof(DeviceText));
+ if (!Buffer)
+ {
+ //
+ // no memory
+ //
+ Irp->IoStatus.Information = 0;
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // copy buffer
+ //
+ wcscpy(Buffer, DeviceText);
+
+ //
+ // save result
+ //
+ Irp->IoStatus.Information = (ULONG_PTR)Buffer;
+ return STATUS_SUCCESS;
+ }
+
+}
+
+
+NTSTATUS
+USBSTOR_PdoHandleQueryDeviceId(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PPDO_DEVICE_EXTENSION DeviceExtension;
+ NTSTATUS Status;
+ CHAR Buffer[100];
+ LPCSTR DeviceType;
+ ULONG Offset = 0;
+ PUFI_INQUIRY_RESPONSE InquiryData;
+ ANSI_STRING AnsiString;
+ UNICODE_STRING DeviceId;
+
+ //
+ // get device extension
+ //
+ DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(DeviceExtension->InquiryData);
+
+ //
+ // get inquiry data
+ //
+ InquiryData = (PUFI_INQUIRY_RESPONSE)DeviceExtension->InquiryData;
+
+ //
+ // get device type
+ //
+ DeviceType = USBSTOR_GetDeviceType(InquiryData, DeviceExtension->IsFloppy);
+
+ //
+ // zero buffer
+ //
+ RtlZeroMemory(Buffer, sizeof(Buffer));
+
+ //
+ // lets create device string
+ //
+ Offset = sprintf(&Buffer[Offset], "USBSTOR\\");
+ Offset += sprintf(&Buffer[Offset], DeviceType);
+ Offset += sprintf(&Buffer[Offset], "&Ven_");
+ Offset += CopyField(InquiryData->Vendor, &Buffer[Offset], 8);
+ Offset += sprintf(&Buffer[Offset], "&Prod_");
+ Offset += CopyField(InquiryData->Product, &Buffer[Offset], 16);
+ Offset += sprintf(&Buffer[Offset], "&Rev_");
+ Offset += CopyField(InquiryData->Revision, &Buffer[Offset], 4);
+
+ //
+ // now initialize ansi string
+ //
+ RtlInitAnsiString(&AnsiString, (PCSZ)Buffer);
+
+ //
+ // allocate DeviceId string
+ //
+ DeviceId.Length = 0;
+ DeviceId.MaximumLength = (strlen((PCHAR)Buffer) + 1) * sizeof(WCHAR);
+ DeviceId.Buffer = (LPWSTR)AllocateItem(PagedPool, DeviceId.MaximumLength);
+ if (!DeviceId.Buffer)
+ {
+ //
+ // no memory
+ //
+ Irp->IoStatus.Information = 0;
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+
+ //
+ // convert to unicode
+ //
+ Status = RtlAnsiStringToUnicodeString(&DeviceId, &AnsiString, FALSE);
+
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // store result
+ //
+ Irp->IoStatus.Information = (ULONG_PTR)DeviceId.Buffer;
+ }
+
+ DPRINT("DeviceId %wZ Status %x\n", &DeviceId, Status);
+
+ //
+ // done
+ //
+ return Status;
+}
+
+VOID
+USBSTOR_ConvertToUnicodeString(
+ IN CHAR * Buffer,
+ IN ULONG ResultBufferLength,
+ IN ULONG ResultBufferOffset,
+ OUT LPWSTR ResultBuffer,
+ OUT PULONG NewResultBufferOffset)
+{
+ UNICODE_STRING DeviceString;
+ ANSI_STRING AnsiString;
+ NTSTATUS Status;
+
+ ASSERT(ResultBufferLength);
+ ASSERT(ResultBufferLength > ResultBufferOffset);
+
+ DPRINT("ResultBufferOffset %lu ResultBufferLength %lu Buffer %s Length %lu\n", ResultBufferOffset, ResultBufferLength, Buffer, strlen(Buffer));
+
+ //
+ // construct destination string
+ //
+ DeviceString.Buffer = &ResultBuffer[ResultBufferOffset];
+ DeviceString.Length = 0;
+ DeviceString.MaximumLength = (ResultBufferLength - ResultBufferOffset) * sizeof(WCHAR);
+
+ //
+ // initialize source string
+ //
+ RtlInitAnsiString(&AnsiString, Buffer);
+
+ //
+ // convert to unicode
+ //
+ Status = RtlAnsiStringToUnicodeString(&DeviceString, &AnsiString, FALSE);
+ ASSERT(Status == STATUS_SUCCESS);
+
+ //
+ // subtract consumed bytes
+ //
+ ResultBufferLength -= (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR);
+ ResultBufferOffset += (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR);
+
+ //
+ // store new offset
+ //
+ *NewResultBufferOffset = ResultBufferOffset;
+}
+
+
+
+NTSTATUS
+USBSTOR_PdoHandleQueryHardwareId(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp)
+{
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
+ LPCSTR GenericType, DeviceType;
+ LPWSTR Buffer;
+ CHAR Id1[50], Id2[50], Id3[50], Id4[50], Id5[50], Id6[50];
+ ULONG Id1Length, Id2Length, Id3Length, Id4Length, Id5Length,Id6Length;
+ ULONG Offset, TotalLength, Length;
+ PUFI_INQUIRY_RESPONSE InquiryData;
+
+ //
+ // get PDO device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // get FDO device extension
+ //
+ FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(FDODeviceExtension->DeviceDescriptor);
+
+ //
+ // get inquiry data
+ //
+ InquiryData = (PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData;
+
+
+ //
+ // get device type and generic type
+ //
+ DeviceType = USBSTOR_GetDeviceType(InquiryData, PDODeviceExtension->IsFloppy);
+ GenericType = USBSTOR_GetGenericType(InquiryData, PDODeviceExtension->IsFloppy);
+
+ ASSERT(GenericType);
+
+ //
+ // generate id 1
+ // USBSTOR\SCSIType_Vendor(8)_Product(16)_Revision(4)
+ //
+ RtlZeroMemory(Id1, sizeof(Id1));
+ Offset = 0;
+ Offset = sprintf(&Id1[Offset], "USBSTOR\\");
+ Offset += sprintf(&Id1[Offset], DeviceType);
+ Offset += CopyField(InquiryData->Vendor, &Id1[Offset], 8);
+ Offset += CopyField(InquiryData->Product, &Id1[Offset], 16);
+ Offset += CopyField(InquiryData->Revision, &Id1[Offset], 4);
+ Id1Length = strlen(Id1) + 1;
+ DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId1 %s\n", Id1);
+
+ //
+ // generate id 2
+ // USBSTOR\SCSIType_VENDOR(8)_Product(16)
+ //
+ RtlZeroMemory(Id2, sizeof(Id2));
+ Offset = 0;
+ Offset = sprintf(&Id2[Offset], "USBSTOR\\");
+ Offset += sprintf(&Id2[Offset], DeviceType);
+ Offset += CopyField(InquiryData->Vendor, &Id2[Offset], 8);
+ Offset += CopyField(InquiryData->Product, &Id2[Offset], 16);
+ Id2Length = strlen(Id2) + 1;
+ DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId2 %s\n", Id2);
+
+ //
+ // generate id 3
+ // USBSTOR\SCSIType_VENDOR(8)
+ //
+ RtlZeroMemory(Id3, sizeof(Id3));
+ Offset = 0;
+ Offset = sprintf(&Id3[Offset], "USBSTOR\\");
+ Offset += sprintf(&Id3[Offset], DeviceType);
+ Offset += CopyField(InquiryData->Vendor, &Id3[Offset], 8);
+ Id3Length = strlen(Id3) + 1;
+ DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId3 %s\n", Id3);
+
+ //
+ // generate id 4
+ // USBSTOR\SCSIType_VENDOR(8)_Product(16)_Revision(1)
+ //
+ RtlZeroMemory(Id4, sizeof(Id4));
+ Offset = 0;
+ Offset = sprintf(&Id4[Offset], "USBSTOR\\");
+ Offset += sprintf(&Id4[Offset], DeviceType);
+ Offset += CopyField(InquiryData->Vendor, &Id4[Offset], 8);
+ Offset += CopyField(InquiryData->Product, &Id4[Offset], 16);
+ Offset += CopyField(InquiryData->Revision, &Id4[Offset], 1);
+ Id4Length = strlen(Id4) + 1;
+ DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId4 %s\n", Id4);
+
+ //
+ // generate id 5
+ // USBSTOR\SCSIType
+ //
+ RtlZeroMemory(Id5, sizeof(Id5));
+ Offset = 0;
+ Offset = sprintf(&Id5[Offset], "USBSTOR\\");
+ Offset += sprintf(&Id5[Offset], GenericType);
+ Id5Length = strlen(Id5) + 1;
+ DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId5 %s\n", Id5);
+
+ //
+ // generate id 6
+ // SCSIType
+ //
+ RtlZeroMemory(Id6, sizeof(Id6));
+ Offset = 0;
+ Offset = sprintf(&Id6[Offset], GenericType);
+ Id6Length = strlen(Id6) + 1;
+ DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId6 %s\n", Id6);
+
+ //
+ // compute total length
+ //
+ TotalLength = Id1Length + Id2Length + Id3Length + Id4Length + Id5Length + Id6Length + 1;
+
+ //
+ // allocate buffer
+ //
+ Buffer = (LPWSTR)AllocateItem(PagedPool, TotalLength * sizeof(WCHAR));
+ if (!Buffer)
+ {
+ //
+ // no memory
+ //
+ Irp->IoStatus.Information = 0;
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // reset offset
+ //
+ Offset = 0;
+ Length = TotalLength;
+
+ USBSTOR_ConvertToUnicodeString(Id1, Length, Offset, Buffer, &Offset);
+ USBSTOR_ConvertToUnicodeString(Id2, Length, Offset, Buffer, &Offset);
+ USBSTOR_ConvertToUnicodeString(Id3, Length, Offset, Buffer, &Offset);
+ USBSTOR_ConvertToUnicodeString(Id4, Length, Offset, Buffer, &Offset);
+ USBSTOR_ConvertToUnicodeString(Id5, Length, Offset, Buffer, &Offset);
+ USBSTOR_ConvertToUnicodeString(Id6, Length, Offset, Buffer, &Offset);
+
+ //
+ // sanity check
+ //
+ ASSERT(Offset + 1 == Length);
+
+ //
+ // store result
+ //
+ Irp->IoStatus.Information = (ULONG_PTR)Buffer;
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USBSTOR_PdoHandleQueryCompatibleId(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp)
+{
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
+ CHAR Buffer[100];
+ ULONG Length, Offset;
+ LPWSTR InstanceId;
+ LPCSTR DeviceType;
+
+ //
+ // get PDO device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // get FDO device extension
+ //
+ FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(FDODeviceExtension->DeviceDescriptor);
+
+ //
+ // get target device type
+ //
+ DeviceType = USBSTOR_GetDeviceType((PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData, PDODeviceExtension->IsFloppy);
+
+ //
+ // zero memory
+ //
+ RtlZeroMemory(Buffer, sizeof(Buffer));
+
+ //
+ // format instance id
+ //
+ Length = sprintf(Buffer, "USBSTOR\\%s", DeviceType) + 1;
+ Length += sprintf(&Buffer[Length], "USBSTOR\\%s", "RAW") + 2;
+
+ //
+ // allocate instance id
+ //
+ InstanceId = (LPWSTR)AllocateItem(PagedPool, Length * sizeof(WCHAR));
+ if (!InstanceId)
+ {
+ //
+ // no memory
+ //
+ Irp->IoStatus.Information = 0;
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ USBSTOR_ConvertToUnicodeString(Buffer, Length, 0, InstanceId, &Offset);
+ USBSTOR_ConvertToUnicodeString(&Buffer[Offset], Length, Offset, InstanceId, &Offset);
+
+ DPRINT("USBSTOR_PdoHandleQueryCompatibleId %S\n", InstanceId);
+
+ //
+ // store result
+ //
+ Irp->IoStatus.Information = (ULONG_PTR)InstanceId;
+
+ //
+ // completed successfully
+ //
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USBSTOR_PdoHandleQueryInstanceId(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp)
+{
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
+ WCHAR Buffer[100];
+ ULONG Length;
+ LPWSTR InstanceId;
+
+ //
+ // get PDO device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // get FDO device extension
+ //
+ FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
+
+ //
+ // format instance id
+ //
+ if (FDODeviceExtension->SerialNumber)
+ {
+ //
+ // using serial number from device
+ //
+ swprintf(Buffer, L"%s&%c", FDODeviceExtension->SerialNumber->bString, PDODeviceExtension->LUN);
+ }
+ else
+ {
+ //
+ // use instance count and LUN
+ //
+ swprintf(Buffer, L"%04lu&%c", FDODeviceExtension->InstanceCount, PDODeviceExtension->LUN);
+ }
+
+ //
+ // calculate length
+ //
+ Length = wcslen(Buffer) + 1;
+
+ //
+ // allocate instance id
+ //
+ InstanceId = (LPWSTR)AllocateItem(PagedPool, Length * sizeof(WCHAR));
+ if (!InstanceId)
+ {
+ //
+ // no memory
+ //
+ Irp->IoStatus.Information = 0;
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // copy instance id
+ //
+ wcscpy(InstanceId, Buffer);
+
+ DPRINT("USBSTOR_PdoHandleQueryInstanceId %S\n", InstanceId);
+
+ //
+ // store result
+ //
+ Irp->IoStatus.Information = (ULONG_PTR)InstanceId;
+
+ //
+ // completed successfully
+ //
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USBSTOR_PdoHandleDeviceRelations(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp)
+{
+ PDEVICE_RELATIONS DeviceRelations;
+ PIO_STACK_LOCATION IoStack;
+
+ DPRINT("USBSTOR_PdoHandleDeviceRelations\n");
+
+ //
+ // get current irp stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // check if relation type is BusRelations
+ //
+ if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
+ {
+ //
+ // PDO handles only target device relation
+ //
+ return Irp->IoStatus.Status;
+ }
+
+ //
+ // allocate device relations
+ //
+ DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS));
+ if (!DeviceRelations)
+ {
+ //
+ // no memory
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // initialize device relations
+ //
+ DeviceRelations->Count = 1;
+ DeviceRelations->Objects[0] = DeviceObject;
+ ObReferenceObject(DeviceObject);
+
+ //
+ // store result
+ //
+ Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
+
+ //
+ // completed successfully
+ //
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+USBSTOR_PdoHandlePnp(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ PPDO_DEVICE_EXTENSION DeviceExtension;
+ NTSTATUS Status;
+ PDEVICE_CAPABILITIES Caps;
+ ULONG bDelete;
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // get device extension
+ //
+ DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(DeviceExtension->Common.IsFDO == FALSE);
+
+ switch(IoStack->MinorFunction)
+ {
+ case IRP_MN_QUERY_DEVICE_RELATIONS:
+ {
+ Status = USBSTOR_PdoHandleDeviceRelations(DeviceObject, Irp);
+ break;
+ }
+ case IRP_MN_QUERY_DEVICE_TEXT:
+ {
+ Status = USBSTOR_PdoHandleQueryDeviceText(DeviceObject, Irp);
+ break;
+ }
+ case IRP_MN_QUERY_ID:
+ {
+ if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID)
+ {
+ //
+ // handle query device id
+ //
+ Status = USBSTOR_PdoHandleQueryDeviceId(DeviceObject, Irp);
+ break;
+ }
+ else if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
+ {
+ //
+ // handle instance id
+ //
+ Status = USBSTOR_PdoHandleQueryHardwareId(DeviceObject, Irp);
+ break;
+ }
+ else if (IoStack->Parameters.QueryId.IdType == BusQueryInstanceID)
+ {
+ //
+ // handle instance id
+ //
+ Status = USBSTOR_PdoHandleQueryInstanceId(DeviceObject, Irp);
+ break;
+ }
+ else if (IoStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs)
+ {
+ //
+ // handle instance id
+ //
+ Status = USBSTOR_PdoHandleQueryCompatibleId(DeviceObject, Irp);
+ break;
+ }
+
+ DPRINT1("USBSTOR_PdoHandlePnp: IRP_MN_QUERY_ID IdType %x unimplemented\n", IoStack->Parameters.QueryId.IdType);
+ Status = STATUS_NOT_SUPPORTED;
+ Irp->IoStatus.Information = 0;
+ break;
+ }
+ case IRP_MN_REMOVE_DEVICE:
+ {
+ DPRINT("IRP_MN_REMOVE_DEVICE\n");
+
+ if(*DeviceExtension->PDODeviceObject != NULL)
+ {
+ //
+ // clear entry in FDO pdo list
+ //
+ *DeviceExtension->PDODeviceObject = NULL;
+ bDelete = TRUE;
+ }
+ else
+ {
+ //
+ // device object already marked for deletion
+ //
+ bDelete = FALSE;
+ }
+
+ /* Complete the IRP */
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ if (bDelete)
+ {
+ /* Delete the device object */
+ IoDeleteDevice(DeviceObject);
+ }
+ return STATUS_SUCCESS;
+ }
+ case IRP_MN_QUERY_CAPABILITIES:
+ {
+ //
+ // just forward irp to lower device
+ //
+ Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
+ ASSERT(Status == STATUS_SUCCESS);
+
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // check if no unique id
+ //
+ Caps = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities;
+ Caps->UniqueID = FALSE; // no unique id is supported
+ Caps->Removable = TRUE; //FIXME
+ }
+ break;
+ }
+ case IRP_MN_QUERY_REMOVE_DEVICE:
+ case IRP_MN_QUERY_STOP_DEVICE:
+ {
+#if 0
+ //
+ // if we're not claimed it's ok
+ //
+ if (DeviceExtension->Claimed)
+#else
+ if (TRUE)
+#endif
+ {
+ Status = STATUS_UNSUCCESSFUL;
+ DPRINT1("[USBSTOR] Request %x fails because device is still claimed\n", IoStack->MinorFunction);
+ }
+ else
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ case IRP_MN_START_DEVICE:
+ {
+ //
+ // no-op for PDO
+ //
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ case IRP_MN_SURPRISE_REMOVAL:
+ {
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ default:
+ {
+ //
+ // do nothing
+ //
+ Status = Irp->IoStatus.Status;
+ }
+ }
+
+ //
+ // complete request
+ //
+ if (Status != STATUS_PENDING)
+ {
+ //
+ // store result
+ //
+ Irp->IoStatus.Status = Status;
+
+ //
+ // complete request
+ //
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+
+ //
+ // done processing
+ //
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+USBSTOR_CompletionRoutine(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Ctx)
+{
+ PKEVENT Event = (PKEVENT)Ctx;
+
+ //
+ // signal event
+ //
+ KeSetEvent(Event, 0, FALSE);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS
+USBSTOR_AllocateIrp(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN ULONG DataTransferLength,
+ IN UCHAR OpCode,
+ IN PKEVENT Event,
+ OUT PSCSI_REQUEST_BLOCK *OutRequest,
+ OUT PIRP *OutIrp)
+{
+ PIRP Irp;
+ PIO_STACK_LOCATION IoStack;
+ PSCSI_REQUEST_BLOCK Request;
+ PCDB pCDB;
+
+ //
+ // allocate irp
+ //
+ Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
+ if (!Irp)
+ {
+ //
+ // no memory
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // get next stack location
+ //
+ IoStack = IoGetNextIrpStackLocation(Irp);
+
+ //
+ // create scsi block
+ //
+ Request = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(SCSI_REQUEST_BLOCK),
+ USB_STOR_TAG);
+ if (!Request)
+ {
+ //
+ // no memory
+ //
+ IoFreeIrp(Irp);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // init request
+ //
+ RtlZeroMemory(Request, sizeof(SCSI_REQUEST_BLOCK));
+
+ //
+ // allocate data transfer block
+ //
+ Request->DataBuffer = ExAllocatePoolWithTag(NonPagedPool,
+ DataTransferLength,
+ USB_STOR_TAG);
+ if (!Request->DataBuffer)
+ {
+ //
+ // no memory
+ //
+ IoFreeIrp(Irp);
+ ExFreePoolWithTag(Request, USB_STOR_TAG);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // allocate MDL
+ //
+ Irp->MdlAddress = IoAllocateMdl(Request->DataBuffer, DataTransferLength, FALSE, FALSE, NULL);
+ if (!Irp->MdlAddress)
+ {
+ //
+ // no memory
+ //
+ IoFreeIrp(Irp);
+ ExFreePoolWithTag(Request->DataBuffer, USB_STOR_TAG);
+ ExFreePoolWithTag(Request, USB_STOR_TAG);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // non paged pool
+ //
+ MmBuildMdlForNonPagedPool(Irp->MdlAddress);
+
+ //
+ // init scsi block
+ //
+ Request->DataTransferLength = DataTransferLength;
+ Request->Function = SRB_FUNCTION_EXECUTE_SCSI;
+ Request->SrbFlags = SRB_FLAGS_DATA_IN;
+
+ RtlZeroMemory(Request->DataBuffer, DataTransferLength);
+
+
+ //
+ // get SCSI command data block
+ //
+ pCDB = (PCDB)Request->Cdb;
+
+ //
+ // set op code
+ //
+ pCDB->AsByte[0] = OpCode;
+
+ //
+ // store result
+ //
+ IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+ IoStack->Parameters.Others.Argument1 = Request;
+ IoStack->DeviceObject = DeviceObject;
+
+ //
+ // init event
+ //
+ KeInitializeEvent(Event, NotificationEvent, FALSE);
+
+ //
+ // lets setup a completion routine
+ //
+ IoSetCompletionRoutine(Irp, USBSTOR_CompletionRoutine, (PVOID)Event, TRUE, TRUE, TRUE);
+
+ //
+ // output result
+ //
+ *OutIrp = Irp;
+ *OutRequest = Request;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USBSTOR_SendIrp(
+ IN PDEVICE_OBJECT PDODeviceObject,
+ IN ULONG DataTransferLength,
+ IN UCHAR OpCode,
+ OUT PVOID *OutData)
+{
+ NTSTATUS Status;
+ PIRP Irp;
+ KEVENT Event;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PSCSI_REQUEST_BLOCK Request;
+
+ //
+ // let's allocate an irp
+ //
+ Status = USBSTOR_AllocateIrp(PDODeviceObject, DataTransferLength, OpCode, &Event, &Request, &Irp);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed
+ //
+ DPRINT1("[USBSTOR] Failed to build irp\n");
+ return Status;
+ }
+
+ //
+ // get device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
+
+ //
+ // send irp
+ //
+ ASSERT(Irp);
+ ASSERT(PDODeviceExtension->LowerDeviceObject);
+ Status = IoCallDriver(PDODeviceExtension->Self, Irp);
+
+ if (Status == STATUS_PENDING)
+ {
+ //
+ // wait for completion
+ //
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ Status = Irp->IoStatus.Status;
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // store result
+ //
+ *OutData = Request->DataBuffer;
+ }
+ else
+ {
+ //
+ // free the data
+ //
+ ExFreePoolWithTag(Request->DataBuffer, USB_STOR_TAG);
+ *OutData = NULL;
+ }
+
+ //
+ // free resources
+ //
+ ExFreePoolWithTag(Request, USB_STOR_TAG);
+ IoFreeMdl(Irp->MdlAddress);
+ IoFreeIrp(Irp);
+ return Status;
+}
+
+NTSTATUS
+USBSTOR_SendInquiryIrp(
+ IN PDEVICE_OBJECT PDODeviceObject)
+{
+ NTSTATUS Status;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PUFI_INQUIRY_RESPONSE Response;
+
+ //
+ // get device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
+
+ //
+ // send request
+ //
+ Status = USBSTOR_SendIrp(PDODeviceObject, sizeof(UFI_INQUIRY_RESPONSE), SCSIOP_INQUIRY, (PVOID*)&Response);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // command failed
+ //
+ DPRINT1("USBSTOR_SendInquiryIrp Failed with %x\n", Status);
+ return Status;
+ }
+
+ DPRINT1("Response %p\n", Response);
+ DPRINT1("DeviceType %x\n", Response->DeviceType);
+ DPRINT1("RMB %x\n", Response->RMB);
+ DPRINT1("Version %x\n", Response->Version);
+ DPRINT1("Format %x\n", Response->Format);
+ DPRINT1("Length %x\n", Response->Length);
+ DPRINT1("Reserved %p\n", Response->Reserved);
+ DPRINT1("Vendor %c%c%c%c%c%c%c%c\n", Response->Vendor[0], Response->Vendor[1], Response->Vendor[2], Response->Vendor[3], Response->Vendor[4], Response->Vendor[5], Response->Vendor[6], Response->Vendor[7]);
+ DPRINT1("Product %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", Response->Product[0], Response->Product[1], Response->Product[2], Response->Product[3],
+ Response->Product[4], Response->Product[5], Response->Product[6], Response->Product[7],
+ Response->Product[8], Response->Product[9], Response->Product[10], Response->Product[11],
+ Response->Product[12], Response->Product[13], Response->Product[14], Response->Product[15]);
+
+ DPRINT1("Revision %c%c%c%c\n", Response->Revision[0], Response->Revision[1], Response->Revision[2], Response->Revision[3]);
+
+ //
+ // store result
+ //
+ PDODeviceExtension->InquiryData = (PVOID)Response;
+ return Status;
+}
+
+NTSTATUS
+USBSTOR_SendFormatCapacityIrp(
+ IN PDEVICE_OBJECT PDODeviceObject)
+{
+ NTSTATUS Status;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PUCHAR Response;
+
+ //
+ // get device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
+
+ //
+ // send request
+ //
+ Status = USBSTOR_SendIrp(PDODeviceObject, 0xFC, SCSIOP_READ_FORMATTED_CAPACITY, (PVOID*)&Response);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // command failed
+ //
+ return Status;
+ }
+
+ //
+ // check if its a floppy
+ //
+ PDODeviceExtension->IsFloppy = USBSTOR_IsFloppy(Response, 0xFC /*FIXME*/, &PDODeviceExtension->MediumTypeCode);
+
+ //
+ // free response
+ //
+ ExFreePoolWithTag(Response, USB_STOR_TAG);
+ return Status;
+}
+
+
+
+NTSTATUS
+USBSTOR_CreatePDO(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN UCHAR LUN)
+{
+ PDEVICE_OBJECT PDO;
+ NTSTATUS Status;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PUFI_INQUIRY_RESPONSE Response;
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
+
+ //
+ // get device extension
+ //
+ FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+
+ //
+ // create child device object
+ //
+ Status = IoCreateDevice(DeviceObject->DriverObject, sizeof(PDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_MASS_STORAGE, FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN, FALSE, &PDO);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to create device
+ //
+ return Status;
+ }
+
+ //
+ // patch the stack size
+ //
+ PDO->StackSize = DeviceObject->StackSize;
+
+ //
+ // get device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDO->DeviceExtension;
+
+ //
+ // initialize device extension
+ //
+ RtlZeroMemory(PDODeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
+ PDODeviceExtension->Common.IsFDO = FALSE;
+ PDODeviceExtension->LowerDeviceObject = DeviceObject;
+ PDODeviceExtension->PDODeviceObject = &FDODeviceExtension->ChildPDO[LUN];
+ PDODeviceExtension->Self = PDO;
+ PDODeviceExtension->LUN = LUN;
+
+ //
+ // set device flags
+ //
+ PDO->Flags |= DO_DIRECT_IO | DO_MAP_IO_BUFFER;
+
+ //
+ // device is initialized
+ //
+ PDO->Flags &= ~DO_DEVICE_INITIALIZING;
+
+ //
+ // output device object
+ //
+ FDODeviceExtension->ChildPDO[LUN] = PDO;
+
+ //
+ // send inquiry command by irp
+ //
+ Status = USBSTOR_SendInquiryIrp(PDO);
+ ASSERT(Status == STATUS_SUCCESS);
+
+ //
+ // check response data
+ //
+ Response = (PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData;
+ ASSERT(Response);
+
+ if (Response->DeviceType == 0)
+ {
+ //
+ // check if it is a floppy
+ //
+ Status = USBSTOR_SendFormatCapacityIrp(PDO);
+
+ //
+ // display result
+ //
+ DPRINT1("[USBSTOR] Status %x IsFloppy %x MediumTypeCode %x\n", Status, PDODeviceExtension->IsFloppy, PDODeviceExtension->MediumTypeCode);
+
+ //
+ // failing command is non critical
+ //
+ Status = STATUS_SUCCESS;
+ }
+
+ //
+ // done
+ //
+ return Status;
+}
--- /dev/null
+/*
+ * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: drivers/usb/usbstor/queue.c
+ * PURPOSE: USB block storage device driver.
+ * PROGRAMMERS:
+ * James Tabor
+ * Michael Martin (michael.martin@reactos.org)
+ * Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+#include "usbstor.h"
+
+#define NDEBUG
+#include <debug.h>
+
+VOID
+USBSTOR_QueueInitialize(
+ PFDO_DEVICE_EXTENSION FDODeviceExtension)
+{
+ //
+ // sanity check
+ //
+ ASSERT(FDODeviceExtension->Common.IsFDO);
+
+ //
+ // initialize queue lock
+ //
+ KeInitializeSpinLock(&FDODeviceExtension->IrpListLock);
+
+ //
+ // initialize irp list head
+ //
+ InitializeListHead(&FDODeviceExtension->IrpListHead);
+
+ //
+ // initialize event
+ //
+ KeInitializeEvent(&FDODeviceExtension->NoPendingRequests, NotificationEvent, TRUE);
+}
+
+VOID
+NTAPI
+USBSTOR_CancelIo(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
+
+ //
+ // get FDO device extension
+ //
+ FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+ ASSERT(FDODeviceExtension->Common.IsFDO);
+
+ //
+ // this IRP isn't in our list here
+ //
+
+ //
+ // now release the cancel lock
+ //
+ IoReleaseCancelSpinLock(Irp->CancelIrql);
+
+ //
+ // set cancel status
+ //
+ Irp->IoStatus.Status = STATUS_CANCELLED;
+
+ //
+ // now cancel the irp
+ //
+ USBSTOR_QueueTerminateRequest(DeviceObject, Irp);
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ //
+ // start the next one
+ //
+ USBSTOR_QueueNextRequest(DeviceObject);
+}
+
+VOID
+NTAPI
+USBSTOR_Cancel(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
+
+ //
+ // get FDO device extension
+ //
+ FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+ ASSERT(FDODeviceExtension->Common.IsFDO);
+
+ //
+ // acquire irp list lock
+ //
+ KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension->IrpListLock);
+
+ //
+ // remove the irp from the list
+ //
+ RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+
+ //
+ // release irp list lock
+ //
+ KeReleaseSpinLockFromDpcLevel(&FDODeviceExtension->IrpListLock);
+
+ //
+ // now release the cancel lock
+ //
+ IoReleaseCancelSpinLock(Irp->CancelIrql);
+
+ //
+ // set cancel status
+ //
+ Irp->IoStatus.Status = STATUS_CANCELLED;
+
+ //
+ // now cancel the irp
+ //
+ USBSTOR_QueueTerminateRequest(DeviceObject, Irp);
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ //
+ // start the next one
+ //
+ USBSTOR_QueueNextRequest(DeviceObject);
+}
+
+BOOLEAN
+USBSTOR_QueueAddIrp(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PDRIVER_CANCEL OldDriverCancel;
+ KIRQL OldLevel;
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
+ BOOLEAN IrpListFreeze;
+ BOOLEAN SrbProcessing;
+ PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
+ PSCSI_REQUEST_BLOCK Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
+
+ //
+ // get FDO device extension
+ //
+ FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(FDODeviceExtension->Common.IsFDO);
+
+ //
+ // mark irp pending
+ //
+ IoMarkIrpPending(Irp);
+
+ //
+ // acquire lock
+ //
+ KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
+
+ //
+ // check if there are irp pending
+ //
+ SrbProcessing = FDODeviceExtension->IrpPendingCount != 0;
+
+ if (SrbProcessing)
+ {
+ //
+ // add irp to queue
+ //
+ InsertTailList(&FDODeviceExtension->IrpListHead, &Irp->Tail.Overlay.ListEntry);
+ }
+
+ //
+ // increment pending count
+ //
+ FDODeviceExtension->IrpPendingCount++;
+
+
+ //
+ // clear the no requests pending event
+ //
+ KeClearEvent(&FDODeviceExtension->NoPendingRequests);
+
+ //
+ // check if queue is freezed
+ //
+ IrpListFreeze = FDODeviceExtension->IrpListFreeze;
+
+ //
+ // release list lock
+ //
+ KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
+
+ //
+ // synchronize with cancellations by holding the cancel lock
+ //
+ IoAcquireCancelSpinLock(&Irp->CancelIrql);
+
+ //
+ // now set the driver cancel routine
+ //
+ if (SrbProcessing)
+ {
+ ASSERT(FDODeviceExtension->ActiveSrb != NULL);
+
+ OldDriverCancel = IoSetCancelRoutine(Irp, USBSTOR_Cancel);
+ }
+ else
+ {
+ ASSERT(FDODeviceExtension->ActiveSrb == NULL);
+
+ FDODeviceExtension->ActiveSrb = Request;
+ OldDriverCancel = IoSetCancelRoutine(Irp, USBSTOR_CancelIo);
+ }
+
+ //
+ // check if the irp has already been cancelled
+ //
+ if (Irp->Cancel && OldDriverCancel == NULL)
+ {
+ //
+ // cancel irp
+ //
+ Irp->CancelRoutine(DeviceObject, Irp);
+
+ //
+ // irp was cancelled
+ //
+ return FALSE;
+ }
+
+ //
+ // release the cancel lock
+ //
+ IoReleaseCancelSpinLock(Irp->CancelIrql);
+
+ //
+ // if list is freezed, dont start this packet
+ //
+ DPRINT("IrpListFreeze: %lu IrpPendingCount %lu\n", IrpListFreeze, FDODeviceExtension->IrpPendingCount);
+
+ return (IrpListFreeze || SrbProcessing);
+}
+
+PIRP
+USBSTOR_RemoveIrp(
+ IN PDEVICE_OBJECT DeviceObject)
+{
+ KIRQL OldLevel;
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
+ PLIST_ENTRY Entry;
+ PIRP Irp = NULL;
+
+ //
+ // get FDO device extension
+ //
+ FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(FDODeviceExtension->Common.IsFDO);
+
+ //
+ // acquire lock
+ //
+ KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
+
+ //
+ // check if list is empty
+ //
+ if (!IsListEmpty(&FDODeviceExtension->IrpListHead))
+ {
+ //
+ // remove entry
+ //
+ Entry = RemoveHeadList(&FDODeviceExtension->IrpListHead);
+
+ //
+ // get offset to start of irp
+ //
+ Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
+ }
+
+ //
+ // release list lock
+ //
+ KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
+
+ //
+ // return result
+ //
+ return Irp;
+}
+
+VOID
+USBSTOR_QueueWaitForPendingRequests(
+ IN PDEVICE_OBJECT DeviceObject)
+{
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
+
+ //
+ // get FDO device extension
+ //
+ FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // perform the wait
+ //
+ KeWaitForSingleObject(&FDODeviceExtension->NoPendingRequests,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+}
+
+VOID
+USBSTOR_QueueTerminateRequest(
+ IN PDEVICE_OBJECT FDODeviceObject,
+ IN PIRP Irp)
+{
+ KIRQL OldLevel;
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
+ PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
+ PSCSI_REQUEST_BLOCK Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
+
+ //
+ // get FDO device extension
+ //
+ FDODeviceExtension = (PFDO_DEVICE_EXTENSION)FDODeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(FDODeviceExtension->Common.IsFDO);
+
+ //
+ // acquire lock
+ //
+ KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
+
+ //
+ // decrement pending irp count
+ //
+ FDODeviceExtension->IrpPendingCount--;
+
+ //
+ // check if this was our current active SRB
+ //
+ if (FDODeviceExtension->ActiveSrb == Request)
+ {
+ //
+ // indicate processing is completed
+ //
+ FDODeviceExtension->ActiveSrb = NULL;
+ }
+
+ //
+ // Set the event if nothing else is pending
+ //
+ if (FDODeviceExtension->IrpPendingCount == 0 &&
+ FDODeviceExtension->ActiveSrb == NULL)
+ {
+ KeSetEvent(&FDODeviceExtension->NoPendingRequests, IO_NO_INCREMENT, FALSE);
+ }
+
+ //
+ // release lock
+ //
+ KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
+
+}
+
+VOID
+USBSTOR_QueueNextRequest(
+ IN PDEVICE_OBJECT DeviceObject)
+{
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
+ PIRP Irp;
+ PIO_STACK_LOCATION IoStack;
+ PSCSI_REQUEST_BLOCK Request;
+
+ //
+ // get pdo device extension
+ //
+ FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(FDODeviceExtension->Common.IsFDO);
+
+ //
+ // check first if there's already a request pending or the queue is frozen
+ //
+ if (FDODeviceExtension->ActiveSrb != NULL ||
+ FDODeviceExtension->IrpListFreeze)
+ {
+ //
+ // no work to do yet
+ //
+ return;
+ }
+
+ //
+ // remove first irp from list
+ //
+ Irp = USBSTOR_RemoveIrp(DeviceObject);
+
+ //
+ // is there an irp pending
+ //
+ if (!Irp)
+ {
+ //
+ // no work to do
+ //
+ IoStartNextPacket(DeviceObject, TRUE);
+ return;
+ }
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // get srb
+ //
+ Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
+
+ //
+ // sanity check
+ //
+ ASSERT(Request);
+
+ //
+ // set the active SRB
+ //
+ FDODeviceExtension->ActiveSrb = Request;
+
+ //
+ // start next packet
+ //
+ IoStartPacket(DeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo);
+
+ //
+ // start next request
+ //
+ IoStartNextPacket(DeviceObject, TRUE);
+}
+
+VOID
+USBSTOR_QueueRelease(
+ IN PDEVICE_OBJECT DeviceObject)
+{
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
+ PIRP Irp;
+ KIRQL OldLevel;
+ PIO_STACK_LOCATION IoStack;
+ PSCSI_REQUEST_BLOCK Request;
+
+ //
+ // get FDO device extension
+ //
+ FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(FDODeviceExtension->Common.IsFDO);
+
+ //
+ // acquire lock
+ //
+ KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
+
+ //
+ // clear freezed status
+ //
+ FDODeviceExtension->IrpListFreeze = FALSE;
+
+ //
+ // release irp list lock
+ //
+ KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
+
+ //
+ // grab newest irp
+ //
+ Irp = USBSTOR_RemoveIrp(DeviceObject);
+
+ //
+ // is there an irp
+ //
+ if (!Irp)
+ {
+ //
+ // no irp
+ //
+ return;
+ }
+
+ //
+ // get current irp stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // get srb
+ //
+ Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
+
+ //
+ // start new packet
+ //
+ IoStartPacket(DeviceObject,
+ Irp,
+ &Request->QueueSortKey,
+ USBSTOR_CancelIo);
+}
+
+
+VOID
+NTAPI
+USBSTOR_StartIo(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ KIRQL OldLevel;
+ BOOLEAN ResetInProgress;
+
+ DPRINT("USBSTOR_StartIo\n");
+
+ //
+ // get FDO device extension
+ //
+ FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(FDODeviceExtension->Common.IsFDO);
+
+ //
+ // acquire cancel spinlock
+ //
+ IoAcquireCancelSpinLock(&OldLevel);
+
+ //
+ // set cancel routine to zero
+ //
+ IoSetCancelRoutine(Irp, NULL);
+
+ //
+ // check if the irp has been cancelled
+ //
+ if (Irp->Cancel)
+ {
+ //
+ // irp has been cancelled, release cancel spinlock
+ //
+ IoReleaseCancelSpinLock(OldLevel);
+
+ //
+ // irp is cancelled
+ //
+ Irp->IoStatus.Status = STATUS_CANCELLED;
+ Irp->IoStatus.Information = 0;
+
+ //
+ // terminate request
+ //
+ USBSTOR_QueueTerminateRequest(DeviceObject, Irp);
+
+ //
+ // complete request
+ //
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ //
+ // queue next request
+ //
+ USBSTOR_QueueNextRequest(DeviceObject);
+
+ //
+ // done
+ //
+ return;
+ }
+
+ //
+ // release cancel spinlock
+ //
+ IoReleaseCancelSpinLock(OldLevel);
+
+ //
+ // acquire lock
+ //
+ KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
+
+ //
+ // check reset is in progress
+ //
+ ResetInProgress = FDODeviceExtension->ResetInProgress;
+ ASSERT(ResetInProgress == FALSE);
+
+ //
+ // release lock
+ //
+ KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
+
+ //
+ // get current irp stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // get pdo device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+
+ //
+ // is a reset in progress
+ //
+ if (ResetInProgress)
+ {
+ //
+ // hard reset is in progress
+ //
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
+ USBSTOR_QueueTerminateRequest(DeviceObject, Irp);
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return;
+ }
+
+ //
+ // execute scsi
+ //
+ USBSTOR_HandleExecuteSCSI(IoStack->DeviceObject, Irp, 0);
+
+ //
+ // FIXME: handle error
+ //
+}
--- /dev/null
+/*
+ * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: drivers/usb/usbstor/pdo.c
+ * PURPOSE: USB block storage device driver.
+ * PROGRAMMERS:
+ * James Tabor
+ * Michael Martin (michael.martin@reactos.org)
+ * Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+#include "usbstor.h"
+
+#define NDEBUG
+#include <debug.h>
+
+NTSTATUS
+USBSTOR_BuildCBW(
+ IN ULONG Tag,
+ IN ULONG DataTransferLength,
+ IN UCHAR LUN,
+ IN UCHAR CommandBlockLength,
+ IN PUCHAR CommandBlock,
+ IN OUT PCBW Control)
+{
+ //
+ // sanity check
+ //
+ ASSERT(CommandBlockLength <= 16);
+
+ //
+ // now initialize CBW
+ //
+ Control->Signature = CBW_SIGNATURE;
+ Control->Tag = Tag;
+ Control->DataTransferLength = DataTransferLength;
+ Control->Flags = (CommandBlock[0] != SCSIOP_WRITE) ? 0x80 : 0x00;
+ Control->LUN = (LUN & MAX_LUN);
+ Control->CommandBlockLength = CommandBlockLength;
+
+ //
+ // copy command block
+ //
+ RtlCopyMemory(Control->CommandBlock, CommandBlock, CommandBlockLength);
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
+}
+
+PIRP_CONTEXT
+USBSTOR_AllocateIrpContext()
+{
+ PIRP_CONTEXT Context;
+
+ //
+ // allocate irp context
+ //
+ Context = (PIRP_CONTEXT)AllocateItem(NonPagedPool, sizeof(IRP_CONTEXT));
+ if (!Context)
+ {
+ //
+ // no memory
+ //
+ return NULL;
+ }
+
+ //
+ // allocate cbw block
+ //
+ Context->cbw = (PCBW)AllocateItem(NonPagedPool, 512);
+ if (!Context->cbw)
+ {
+ //
+ // no memory
+ //
+ FreeItem(Context);
+ return NULL;
+ }
+
+ //
+ // done
+ //
+ return Context;
+
+}
+
+BOOLEAN
+USBSTOR_IsCSWValid(
+ PIRP_CONTEXT Context)
+{
+ //
+ // sanity checks
+ //
+ if (Context->csw->Signature != CSW_SIGNATURE)
+ {
+ DPRINT1("[USBSTOR] Expected Signature %x but got %x\n", CSW_SIGNATURE, Context->csw->Signature);
+ return FALSE;
+ }
+
+ if (Context->csw->Tag != (ULONG)Context->csw)
+ {
+ DPRINT1("[USBSTOR] Expected Tag %x but got %x\n", (ULONG)Context->csw, Context->csw->Tag);
+ return FALSE;
+ }
+
+ if (Context->csw->Status != 0x00)
+ {
+ DPRINT1("[USBSTOR] Expected Status 0x00 but got %x\n", Context->csw->Status);
+ return FALSE;
+ }
+
+ //
+ // CSW is valid
+ //
+ return TRUE;
+
+}
+
+NTSTATUS
+USBSTOR_QueueWorkItem(
+ PIRP_CONTEXT Context,
+ PIRP Irp)
+{
+ PERRORHANDLER_WORKITEM_DATA ErrorHandlerWorkItemData;
+
+ //
+ // Allocate Work Item Data
+ //
+ ErrorHandlerWorkItemData = ExAllocatePoolWithTag(NonPagedPool, sizeof(ERRORHANDLER_WORKITEM_DATA), USB_STOR_TAG);
+ if (!ErrorHandlerWorkItemData)
+ {
+ //
+ // no memory
+ //
+ 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
+ //
+ ExInitializeWorkItem(&ErrorHandlerWorkItemData->WorkQueueItem,
+ ErrorHandlerWorkItemRoutine,
+ ErrorHandlerWorkItemData);
+
+ ErrorHandlerWorkItemData->DeviceObject = Context->FDODeviceExtension->FunctionalDeviceObject;
+ ErrorHandlerWorkItemData->Context = Context;
+ ErrorHandlerWorkItemData->Irp = Irp;
+ ErrorHandlerWorkItemData->DeviceObject = Context->FDODeviceExtension->FunctionalDeviceObject;
+
+ DPRINT1("Queuing WorkItemROutine\n");
+ ExQueueWorkItem(&ErrorHandlerWorkItemData->WorkQueueItem, DelayedWorkQueue);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+
+//
+// driver verifier
+//
+IO_COMPLETION_ROUTINE USBSTOR_CSWCompletionRoutine;
+
+NTSTATUS
+NTAPI
+USBSTOR_CSWCompletionRoutine(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PVOID Ctx)
+{
+ PIRP_CONTEXT Context;
+ PIO_STACK_LOCATION IoStack;
+ PSCSI_REQUEST_BLOCK Request;
+ PCDB pCDB;
+ PREAD_CAPACITY_DATA_EX CapacityDataEx;
+ PREAD_CAPACITY_DATA CapacityData;
+ PUFI_CAPACITY_RESPONSE Response;
+ NTSTATUS Status;
+
+ //
+ // access context
+ //
+ Context = (PIRP_CONTEXT)Ctx;
+
+ //
+ // is there a mdl
+ //
+ if (Context->TransferBufferMDL)
+ {
+ //
+ // is there an irp associated
+ //
+ if (Context->Irp)
+ {
+ //
+ // did we allocate the mdl
+ //
+ if (Context->TransferBufferMDL != Context->Irp->MdlAddress)
+ {
+ //
+ // free mdl
+ //
+ IoFreeMdl(Context->TransferBufferMDL);
+ }
+ }
+ else
+ {
+ //
+ // free mdl
+ //
+ IoFreeMdl(Context->TransferBufferMDL);
+ }
+ }
+
+ DPRINT("USBSTOR_CSWCompletionRoutine Status %x\n", Irp->IoStatus.Status);
+
+ if (!NT_SUCCESS(Irp->IoStatus.Information))
+ {
+ if (Context->ErrorIndex == 0)
+ {
+ //
+ // increment error index
+ //
+ Context->ErrorIndex = 1;
+
+ //
+ // clear stall and resend cbw
+ //
+ Status = USBSTOR_QueueWorkItem(Context, Irp);
+ ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+ }
+
+ //
+ // perform reset recovery
+ //
+ Context->ErrorIndex = 2;
+ IoFreeIrp(Irp);
+ Status = USBSTOR_QueueWorkItem(Context, NULL);
+ ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+ }
+
+ if (!USBSTOR_IsCSWValid(Context))
+ {
+ //
+ // perform reset recovery
+ //
+ Context->ErrorIndex = 2;
+ IoFreeIrp(Irp);
+ Status = USBSTOR_QueueWorkItem(Context, NULL);
+ ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+ }
+
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Context->Irp);
+
+ //
+ // get request block
+ //
+ Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
+ ASSERT(Request);
+
+ Status = Irp->IoStatus.Status;
+
+ //
+ // get SCSI command data block
+ //
+ pCDB = (PCDB)Request->Cdb;
+ Request->SrbStatus = SRB_STATUS_SUCCESS;
+
+ //
+ // read capacity needs special work
+ //
+ if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
+ {
+ //
+ // get output buffer
+ //
+ Response = (PUFI_CAPACITY_RESPONSE)Context->TransferData;
+
+ //
+ // store in pdo
+ //
+ Context->PDODeviceExtension->BlockLength = NTOHL(Response->BlockLength);
+ Context->PDODeviceExtension->LastLogicBlockAddress = NTOHL(Response->LastLogicalBlockAddress);
+
+ if (Request->DataTransferLength == sizeof(READ_CAPACITY_DATA_EX))
+ {
+ //
+ // get input buffer
+ //
+ CapacityDataEx = (PREAD_CAPACITY_DATA_EX)Request->DataBuffer;
+
+ //
+ // set result
+ //
+ CapacityDataEx->BytesPerBlock = Response->BlockLength;
+ CapacityDataEx->LogicalBlockAddress.QuadPart = Response->LastLogicalBlockAddress;
+ Irp->IoStatus.Information = sizeof(READ_CAPACITY_DATA_EX);
+ }
+ else
+ {
+ //
+ // get input buffer
+ //
+ CapacityData = (PREAD_CAPACITY_DATA)Request->DataBuffer;
+
+ //
+ // set result
+ //
+ CapacityData->BytesPerBlock = Response->BlockLength;
+ CapacityData->LogicalBlockAddress = Response->LastLogicalBlockAddress;
+ Irp->IoStatus.Information = sizeof(READ_CAPACITY_DATA);
+ }
+
+ //
+ // free response
+ //
+ FreeItem(Context->TransferData);
+ }
+
+ //
+ // free cbw
+ //
+ FreeItem(Context->cbw);
+
+ //
+ // FIXME: check status
+ //
+ Context->Irp->IoStatus.Status = Irp->IoStatus.Status;
+ Context->Irp->IoStatus.Information = Context->TransferDataLength;
+
+ //
+ // terminate current request
+ //
+ USBSTOR_QueueTerminateRequest(Context->PDODeviceExtension->LowerDeviceObject, Context->Irp);
+
+ //
+ // complete request
+ //
+ IoCompleteRequest(Context->Irp, IO_NO_INCREMENT);
+
+ //
+ // start next request
+ //
+ USBSTOR_QueueNextRequest(Context->PDODeviceExtension->LowerDeviceObject);
+
+ //
+ // free our allocated irp
+ //
+ IoFreeIrp(Irp);
+
+ //
+ // free context
+ //
+ FreeItem(Context);
+
+ //
+ // done
+ //
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+VOID
+USBSTOR_SendCSW(
+ PIRP_CONTEXT Context,
+ PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+
+ //
+ // get next irp stack location
+ //
+ IoStack = IoGetNextIrpStackLocation(Irp);
+
+ //
+ // now initialize the urb for sending the csw
+ //
+ UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
+ sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
+ Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle,
+ 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)&Context->Urb;
+ IoStack->Parameters.DeviceIoControl.InputBufferLength = Context->Urb.UrbHeader.Length;
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+
+
+ //
+ // setup completion routine
+ //
+ IoSetCompletionRoutine(Irp, USBSTOR_CSWCompletionRoutine, Context, TRUE, TRUE, TRUE);
+
+ //
+ // 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 (!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;
+ }
+
+ //
+ // send csw
+ //
+ USBSTOR_SendCSW(Context, Irp);
+
+ //
+ // cancel completion
+ //
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+//
+// driver verifier
+//
+IO_COMPLETION_ROUTINE USBSTOR_CBWCompletionRoutine;
+
+NTSTATUS
+NTAPI
+USBSTOR_CBWCompletionRoutine(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PVOID Ctx)
+{
+ PIRP_CONTEXT Context;
+ PIO_STACK_LOCATION IoStack;
+ UCHAR Code;
+ USBD_PIPE_HANDLE PipeHandle;
+
+ DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
+
+ //
+ // access context
+ //
+ Context = (PIRP_CONTEXT)Ctx;
+
+ //
+ // get next stack location
+ //
+ IoStack = IoGetNextIrpStackLocation(Irp);
+
+ //
+ // is there data to be submitted
+ //
+ if (Context->TransferDataLength)
+ {
+ //
+ // get command code
+ //
+ Code = Context->cbw->CommandBlock[0];
+
+ if (Code == SCSIOP_WRITE)
+ {
+ //
+ // write request use bulk out pipe
+ //
+ PipeHandle = Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkOutPipeIndex].PipeHandle;
+ }
+ else
+ {
+ //
+ // default bulk in pipe
+ //
+ PipeHandle = Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle;
+ }
+
+ //
+ // now initialize the urb for sending data
+ //
+ UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
+ sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
+ PipeHandle,
+ NULL,
+ Context->TransferBufferMDL,
+ Context->TransferDataLength,
+ ((Code == SCSIOP_WRITE) ? USBD_TRANSFER_DIRECTION_OUT : (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK)),
+ NULL);
+
+ //
+ // setup completion routine
+ //
+ IoSetCompletionRoutine(Irp, USBSTOR_DataCompletionRoutine, Context, TRUE, TRUE, TRUE);
+ }
+ else
+ {
+ //
+ // now initialize the urb for sending the csw
+ //
+
+ UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
+ sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
+ Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle,
+ Context->csw,
+ NULL,
+ 512, //FIXME
+ USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
+ NULL);
+
+ //
+ // setup completion routine
+ //
+ IoSetCompletionRoutine(Irp, USBSTOR_CSWCompletionRoutine, Context, TRUE, TRUE, TRUE);
+ }
+
+ //
+ // 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;
+
+ //
+ // call driver
+ //
+ IoCallDriver(Context->FDODeviceExtension->LowerDeviceObject, Irp);
+
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+VOID
+DumpCBW(
+ PUCHAR Block)
+{
+ DPRINT("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ Block[0] & 0xFF, Block[1] & 0xFF, Block[2] & 0xFF, Block[3] & 0xFF, Block[4] & 0xFF, Block[5] & 0xFF, Block[6] & 0xFF, Block[7] & 0xFF, Block[8] & 0xFF, Block[9] & 0xFF,
+ Block[10] & 0xFF, Block[11] & 0xFF, Block[12] & 0xFF, Block[13] & 0xFF, Block[14] & 0xFF, Block[15] & 0xFF, Block[16] & 0xFF, Block[17] & 0xFF, Block[18] & 0xFF, Block[19] & 0xFF,
+ Block[20] & 0xFF, Block[21] & 0xFF, Block[22] & 0xFF, Block[23] & 0xFF, Block[24] & 0xFF, Block[25] & 0xFF, Block[26] & 0xFF, Block[27] & 0xFF, Block[28] & 0xFF, Block[29] & 0xFF,
+ Block[30] & 0xFF);
+
+}
+
+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(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP OriginalRequest,
+ IN UCHAR CommandLength,
+ IN PUCHAR Command,
+ IN ULONG TransferDataLength,
+ IN PUCHAR TransferData,
+ IN ULONG RetryCount)
+{
+ PIRP_CONTEXT Context;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
+ PIRP Irp;
+ PUCHAR MdlVirtualAddress;
+
+ //
+ // first allocate irp context
+ //
+ Context = USBSTOR_AllocateIrpContext();
+ if (!Context)
+ {
+ //
+ // no memory
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // get PDO device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // get FDO device extension
+ //
+ FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
+
+ //
+ // now build the cbw
+ //
+ USBSTOR_BuildCBW((ULONG)Context->cbw,
+ TransferDataLength,
+ PDODeviceExtension->LUN,
+ CommandLength,
+ Command,
+ Context->cbw);
+
+ DPRINT("CBW %p\n", Context->cbw);
+ DumpCBW((PUCHAR)Context->cbw);
+
+ //
+ // now initialize the urb
+ //
+ UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
+ sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
+ FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle,
+ Context->cbw,
+ NULL,
+ sizeof(CBW),
+ USBD_TRANSFER_DIRECTION_OUT,
+ NULL);
+
+ //
+ // initialize rest of context
+ //
+ Context->Irp = OriginalRequest;
+ Context->TransferData = TransferData;
+ Context->TransferDataLength = TransferDataLength;
+ Context->FDODeviceExtension = FDODeviceExtension;
+ Context->PDODeviceExtension = PDODeviceExtension;
+ Context->RetryCount = RetryCount;
+
+ //
+ // is there transfer data
+ //
+ if (Context->TransferDataLength)
+ {
+ //
+ // check if the original request already does have an mdl associated
+ //
+ if (OriginalRequest)
+ {
+ if ((OriginalRequest->MdlAddress != NULL) &&
+ (Context->TransferData == NULL || Command[0] == SCSIOP_READ || Command[0] == SCSIOP_WRITE))
+ {
+ //
+ // Sanity check that the Mdl does describe the TransferData for read/write
+ //
+ if (CommandLength == UFI_READ_WRITE_CMD_LEN)
+ {
+ MdlVirtualAddress = MmGetMdlVirtualAddress(OriginalRequest->MdlAddress);
+
+ //
+ // is there an offset
+ //
+ if (MdlVirtualAddress != Context->TransferData)
+ {
+ //
+ // lets build an mdl
+ //
+ Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, MmGetMdlByteCount(OriginalRequest->MdlAddress), FALSE, FALSE, NULL);
+ if (!Context->TransferBufferMDL)
+ {
+ //
+ // failed to allocate MDL
+ //
+ FreeItem(Context->cbw);
+ FreeItem(Context);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // now build the partial mdl
+ //
+ IoBuildPartialMdl(OriginalRequest->MdlAddress, Context->TransferBufferMDL, Context->TransferData, Context->TransferDataLength);
+ }
+ }
+
+ if (!Context->TransferBufferMDL)
+ {
+ //
+ // I/O paging request
+ //
+ Context->TransferBufferMDL = OriginalRequest->MdlAddress;
+ }
+ }
+ else
+ {
+ //
+ // allocate mdl for buffer, buffer must be allocated from NonPagedPool
+ //
+ Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, Context->TransferDataLength, FALSE, FALSE, NULL);
+ if (!Context->TransferBufferMDL)
+ {
+ //
+ // failed to allocate MDL
+ //
+ FreeItem(Context->cbw);
+ FreeItem(Context);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // build mdl for nonpaged pool
+ //
+ MmBuildMdlForNonPagedPool(Context->TransferBufferMDL);
+ }
+ }
+ else
+ {
+ //
+ // allocate mdl for buffer, buffer must be allocated from NonPagedPool
+ //
+ Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, Context->TransferDataLength, FALSE, FALSE, NULL);
+ if (!Context->TransferBufferMDL)
+ {
+ //
+ // failed to allocate MDL
+ //
+ FreeItem(Context->cbw);
+ FreeItem(Context);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // build mdl for nonpaged pool
+ //
+ MmBuildMdlForNonPagedPool(Context->TransferBufferMDL);
+ }
+ }
+
+ //
+ // now allocate the request
+ //
+ Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
+ if (!Irp)
+ {
+ FreeItem(Context->cbw);
+ FreeItem(Context);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ if (OriginalRequest)
+ {
+ //
+ // mark orignal irp as pending
+ //
+ IoMarkIrpPending(OriginalRequest);
+ }
+
+ //
+ // send request
+ //
+ USBSTOR_SendCBW(Context, Irp);
+
+ //
+ // done
+ //
+ return STATUS_PENDING;
+}
+
+NTSTATUS
+USBSTOR_SendFormatCapacity(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN ULONG RetryCount)
+{
+ UFI_READ_FORMAT_CAPACITY Cmd;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PIO_STACK_LOCATION IoStack;
+ PSCSI_REQUEST_BLOCK Request;
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // get PDO device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // get request block
+ //
+ Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
+
+ //
+ // initialize inquiry cmd
+ //
+ RtlZeroMemory(&Cmd, sizeof(UFI_READ_FORMAT_CAPACITY));
+ Cmd.Code = SCSIOP_READ_FORMATTED_CAPACITY;
+ Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
+ Cmd.AllocationLengthMsb = HTONS(Request->DataTransferLength & 0xFFFF) >> 8;
+ Cmd.AllocationLengthLsb = HTONS(Request->DataTransferLength & 0xFFFF) & 0xFF;
+
+ //
+ // now send the request
+ //
+ return USBSTOR_SendRequest(DeviceObject, Irp, UFI_READ_FORMAT_CAPACITY_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, (PUCHAR)Request->DataBuffer, RetryCount);
+}
+
+NTSTATUS
+USBSTOR_SendInquiry(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN ULONG RetryCount)
+{
+ UFI_INQUIRY_CMD Cmd;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PIO_STACK_LOCATION IoStack;
+ PSCSI_REQUEST_BLOCK Request;
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // get request block
+ //
+ Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
+
+ //
+ // get PDO device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // initialize inquiry cmd
+ //
+ RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD));
+ Cmd.Code = SCSIOP_INQUIRY;
+ Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
+ Cmd.AllocationLength = sizeof(UFI_INQUIRY_RESPONSE);
+
+ //
+ // sanity check
+ //
+ ASSERT(Request->DataTransferLength >= sizeof(UFI_INQUIRY_RESPONSE));
+
+ //
+ // now send the request
+ //
+ return USBSTOR_SendRequest(DeviceObject, Irp, UFI_INQUIRY_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, (PUCHAR)Request->DataBuffer, RetryCount);
+}
+
+NTSTATUS
+USBSTOR_SendCapacity(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN ULONG RetryCount)
+{
+ UFI_CAPACITY_CMD Cmd;
+ PUFI_CAPACITY_RESPONSE Response;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+
+ //
+ // get PDO device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // allocate capacity response
+ //
+ Response = (PUFI_CAPACITY_RESPONSE)AllocateItem(NonPagedPool, PAGE_SIZE);
+ if (!Response)
+ {
+ //
+ // no memory
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // initialize capacity cmd
+ //
+ RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD));
+ Cmd.Code = SCSIOP_READ_CAPACITY;
+ Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
+
+ //
+ // send request, response will be freed in completion routine
+ //
+ return USBSTOR_SendRequest(DeviceObject, Irp, UFI_READ_CAPACITY_CMD_LEN, (PUCHAR)&Cmd, sizeof(UFI_CAPACITY_RESPONSE), (PUCHAR)Response, RetryCount);
+}
+
+NTSTATUS
+USBSTOR_SendModeSense(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN ULONG RetryCount)
+{
+#if 0
+ UFI_SENSE_CMD Cmd;
+ NTSTATUS Status;
+ PVOID Response;
+ PCBW OutControl;
+ PCDB pCDB;
+ PUFI_MODE_PARAMETER_HEADER Header;
+#endif
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PIO_STACK_LOCATION IoStack;
+ PSCSI_REQUEST_BLOCK Request;
+
+ //
+ // get PDO device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // get request block
+ //
+ Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
+
+ RtlZeroMemory(Request->DataBuffer, Request->DataTransferLength);
+ Request->SrbStatus = SRB_STATUS_SUCCESS;
+ Irp->IoStatus.Information = Request->DataTransferLength;
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ //
+ // start next request
+ //
+ USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject);
+
+ return STATUS_SUCCESS;
+
+#if 0
+ //
+ // get SCSI command data block
+ //
+ pCDB = (PCDB)Request->Cdb;
+
+ //
+ // get PDO device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // allocate sense response from non paged pool
+ //
+ Response = (PUFI_CAPACITY_RESPONSE)AllocateItem(NonPagedPool, Request->DataTransferLength);
+ if (!Response)
+ {
+ //
+ // no memory
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // sanity check
+ //
+
+
+ // Supported pages
+ // MODE_PAGE_ERROR_RECOVERY
+ // MODE_PAGE_FLEXIBILE
+ // MODE_PAGE_LUN_MAPPING
+ // MODE_PAGE_FAULT_REPORTING
+ // MODE_SENSE_RETURN_ALL
+
+ //
+ // initialize mode sense cmd
+ //
+ RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD));
+ Cmd.Code = SCSIOP_MODE_SENSE;
+ Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
+ Cmd.PageCode = pCDB->MODE_SENSE.PageCode;
+ Cmd.PC = pCDB->MODE_SENSE.Pc;
+ Cmd.AllocationLength = HTONS(pCDB->MODE_SENSE.AllocationLength);
+
+ DPRINT1("PageCode %x\n", pCDB->MODE_SENSE.PageCode);
+ DPRINT1("PC %x\n", pCDB->MODE_SENSE.Pc);
+
+ //
+ // now send mode sense cmd
+ //
+ Status = USBSTOR_SendCBW(DeviceObject, UFI_SENSE_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, &OutControl);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to send CBW
+ //
+ DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendCBW failed with %x\n", Status);
+ FreeItem(Response);
+ ASSERT(FALSE);
+ return Status;
+ }
+
+ //
+ // now send data block response
+ //
+ Status = USBSTOR_SendData(DeviceObject, Request->DataTransferLength, Response);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to send CBW
+ //
+ DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendData failed with %x\n", Status);
+ FreeItem(Response);
+ ASSERT(FALSE);
+ return Status;
+ }
+
+ Header = (PUFI_MODE_PARAMETER_HEADER)Response;
+
+ //
+ // TODO: build layout
+ //
+ // first struct is the header
+ // MODE_PARAMETER_HEADER / _MODE_PARAMETER_HEADER10
+ //
+ // followed by
+ // MODE_PARAMETER_BLOCK
+ //
+ //
+ UNIMPLEMENTED;
+
+ //
+ // send csw
+ //
+ Status = USBSTOR_SendCSW(DeviceObject, OutControl, 512, &CSW);
+
+ DPRINT1("------------------------\n");
+ DPRINT1("CSW %p\n", &CSW);
+ DPRINT1("Signature %x\n", CSW.Signature);
+ DPRINT1("Tag %x\n", CSW.Tag);
+ DPRINT1("DataResidue %x\n", CSW.DataResidue);
+ DPRINT1("Status %x\n", CSW.Status);
+
+ //
+ // FIXME: handle error
+ //
+ ASSERT(CSW.Status == 0);
+ ASSERT(CSW.DataResidue == 0);
+
+ //
+ // calculate transfer length
+ //
+ *TransferBufferLength = Request->DataTransferLength - CSW.DataResidue;
+
+ //
+ // copy buffer
+ //
+ RtlCopyMemory(Request->DataBuffer, Response, *TransferBufferLength);
+
+ //
+ // free item
+ //
+ FreeItem(OutControl);
+
+ //
+ // free response
+ //
+ FreeItem(Response);
+
+ //
+ // done
+ //
+ return Status;
+#endif
+}
+
+NTSTATUS
+USBSTOR_SendReadWrite(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN ULONG RetryCount)
+{
+ UFI_READ_WRITE_CMD Cmd;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PCDB pCDB;
+ ULONG BlockCount, Temp;
+ PIO_STACK_LOCATION IoStack;
+ PSCSI_REQUEST_BLOCK Request;
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // get request block
+ //
+ Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
+
+ //
+ // get SCSI command data block
+ //
+ pCDB = (PCDB)Request->Cdb;
+
+ //
+ // get PDO device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // informal debug print
+ //
+ DPRINT("USBSTOR_SendReadWrite DataTransferLength %lu, BlockLength %lu\n", Request->DataTransferLength, PDODeviceExtension->BlockLength);
+
+ //
+ // sanity check
+ //
+ ASSERT(PDODeviceExtension->BlockLength);
+
+ //
+ // block count
+ //
+ BlockCount = Request->DataTransferLength / PDODeviceExtension->BlockLength;
+
+ //
+ // initialize read cmd
+ //
+ RtlZeroMemory(&Cmd, sizeof(UFI_READ_WRITE_CMD));
+ Cmd.Code = pCDB->AsByte[0];
+ Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
+ Cmd.ContiguousLogicBlocksByte0 = pCDB->CDB10.TransferBlocksMsb;
+ Cmd.ContiguousLogicBlocksByte1 = pCDB->CDB10.TransferBlocksLsb;
+ Cmd.LogicalBlockByte0 = pCDB->CDB10.LogicalBlockByte0;
+ Cmd.LogicalBlockByte1 = pCDB->CDB10.LogicalBlockByte1;
+ Cmd.LogicalBlockByte2 = pCDB->CDB10.LogicalBlockByte2;
+ Cmd.LogicalBlockByte3 = pCDB->CDB10.LogicalBlockByte3;
+
+ //
+ // sanity check
+ //
+ Temp = (Cmd.ContiguousLogicBlocksByte0 << 8 | Cmd.ContiguousLogicBlocksByte1);
+ ASSERT(Temp == BlockCount);
+
+ DPRINT("USBSTOR_SendReadWrite 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, UFI_READ_WRITE_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, (PUCHAR)Request->DataBuffer, RetryCount);
+}
+
+NTSTATUS
+USBSTOR_SendTestUnit(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp,
+ IN ULONG RetryCount)
+{
+ UFI_TEST_UNIT_CMD Cmd;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PIO_STACK_LOCATION IoStack;
+ PSCSI_REQUEST_BLOCK Request;
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // get request block
+ //
+ Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
+
+ //
+ // no transfer length
+ //
+ ASSERT(Request->DataTransferLength == 0);
+
+ //
+ // get PDO device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // initialize test unit cmd
+ //
+ RtlZeroMemory(&Cmd, sizeof(UFI_TEST_UNIT_CMD));
+ Cmd.Code = SCSIOP_TEST_UNIT_READY;
+ Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
+
+ //
+ // send the request
+ //
+ return USBSTOR_SendRequest(DeviceObject, Irp, UFI_TEST_UNIT_CMD_LEN, (PUCHAR)&Cmd, 0, NULL, RetryCount);
+}
+
+NTSTATUS
+USBSTOR_SendUnknownRequest(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp,
+ IN ULONG RetryCount)
+{
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PIO_STACK_LOCATION IoStack;
+ PSCSI_REQUEST_BLOCK Request;
+ UFI_UNKNOWN_CMD Cmd;
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // get request block
+ //
+ Request = IoStack->Parameters.Others.Argument1;
+
+ //
+ // get PDO device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // check that we're sending to the right LUN
+ //
+ ASSERT(Request->Cdb[1] == (PDODeviceExtension->LUN & MAX_LUN));
+
+ //
+ // sanity check
+ //
+ ASSERT(Request->CdbLength <= sizeof(UFI_UNKNOWN_CMD));
+
+ //
+ // initialize test unit cmd
+ //
+ RtlCopyMemory(&Cmd, Request->Cdb, Request->CdbLength);
+
+ //
+ // send the request
+ //
+ return USBSTOR_SendRequest(DeviceObject, Irp, Request->CdbLength, (PUCHAR)&Cmd, Request->DataTransferLength, Request->DataBuffer, RetryCount);
+}
+
+NTSTATUS
+USBSTOR_HandleExecuteSCSI(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN ULONG RetryCount)
+{
+ PCDB pCDB;
+ NTSTATUS Status;
+ PIO_STACK_LOCATION IoStack;
+ PSCSI_REQUEST_BLOCK Request;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+
+ //
+ // get PDO device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // get request block
+ //
+ Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
+
+ //
+ // get SCSI command data block
+ //
+ pCDB = (PCDB)Request->Cdb;
+
+ DPRINT("USBSTOR_HandleExecuteSCSI Operation Code %x\n", pCDB->AsByte[0]);
+
+ if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
+ {
+ //
+ // sanity checks
+ //
+ ASSERT(Request->DataBuffer);
+
+ DPRINT("SCSIOP_READ_CAPACITY Length %lu\n", Request->DataTransferLength);
+ Status = USBSTOR_SendCapacity(DeviceObject, Irp, RetryCount);
+ }
+ else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE)
+ {
+ DPRINT("SCSIOP_MODE_SENSE DataTransferLength %lu\n", Request->DataTransferLength);
+ ASSERT(pCDB->MODE_SENSE.AllocationLength == Request->DataTransferLength);
+ ASSERT(Request->DataBuffer);
+
+ //
+ // send mode sense command
+ //
+ Status = USBSTOR_SendModeSense(DeviceObject, Irp, RetryCount);
+ }
+ else if (pCDB->AsByte[0] == SCSIOP_READ_FORMATTED_CAPACITY)
+ {
+ DPRINT("SCSIOP_READ_FORMATTED_CAPACITY DataTransferLength %lu\n", Request->DataTransferLength);
+
+ //
+ // send read format capacity
+ //
+ Status = USBSTOR_SendFormatCapacity(DeviceObject, Irp, RetryCount);
+ }
+ else if (pCDB->AsByte[0] == SCSIOP_INQUIRY)
+ {
+ DPRINT("SCSIOP_INQUIRY DataTransferLength %lu\n", Request->DataTransferLength);
+
+ //
+ // send read format capacity
+ //
+ Status = USBSTOR_SendInquiry(DeviceObject, Irp, RetryCount);
+ }
+ else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_READ || pCDB->MODE_SENSE.OperationCode == SCSIOP_WRITE)
+ {
+ DPRINT("SCSIOP_READ / SCSIOP_WRITE DataTransferLength %lu\n", Request->DataTransferLength);
+
+ //
+ // send read / write command
+ //
+ Status = USBSTOR_SendReadWrite(DeviceObject, Irp, RetryCount);
+ }
+ else if (pCDB->AsByte[0] == SCSIOP_MEDIUM_REMOVAL)
+ {
+ DPRINT("SCSIOP_MEDIUM_REMOVAL\n");
+
+ //
+ // just complete the request
+ //
+ Request->SrbStatus = SRB_STATUS_SUCCESS;
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = Request->DataTransferLength;
+ USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ //
+ // start next request
+ //
+ USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject);
+
+ return STATUS_SUCCESS;
+ }
+ else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_TEST_UNIT_READY)
+ {
+ DPRINT("SCSIOP_TEST_UNIT_READY\n");
+
+ //
+ // send test unit command
+ //
+ Status = USBSTOR_SendTestUnit(DeviceObject, Irp, RetryCount);
+ }
+ else
+ {
+ // Unknown request. Simply forward
+ DPRINT1("Forwarding unknown Operation Code %x\n", pCDB->AsByte[0]);
+ Status = USBSTOR_SendUnknownRequest(DeviceObject, Irp, RetryCount);
+ }
+
+ return Status;
+}
--- /dev/null
+/*
+ * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: drivers/usb/usbstor/usbstor.c
+ * PURPOSE: USB block storage device driver.
+ * PROGRAMMERS:
+ * James Tabor
+ Johannes Anderwald
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include "usbstor.h"
+
+#define NDEBUG
+#include <debug.h>
+
+/* PUBLIC AND PRIVATE FUNCTIONS **********************************************/
+
+NTSTATUS
+NTAPI
+USBSTOR_AddDevice(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT PhysicalDeviceObject)
+{
+ NTSTATUS Status;
+ PDEVICE_OBJECT DeviceObject;
+ PFDO_DEVICE_EXTENSION DeviceExtension;
+
+ //
+ // lets create the device
+ //
+ Status = IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_EXTENSION), 0, FILE_DEVICE_BUS_EXTENDER, FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN, FALSE, &DeviceObject);
+
+ //
+ // check for success
+ //
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("USBSTOR_AddDevice: Failed to create FDO Status %x\n", Status);
+ return Status;
+ }
+
+ //
+ // get device extension
+ //
+ DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ ASSERT(DeviceExtension);
+
+ //
+ // zero device extension
+ //
+ RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
+
+ //
+ // initialize device extension
+ //
+ DeviceExtension->Common.IsFDO = TRUE;
+ DeviceExtension->FunctionalDeviceObject = DeviceObject;
+ DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
+ DeviceExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
+
+ //
+ // init timer
+ //
+ IoInitializeTimer(DeviceObject, USBSTOR_TimerRoutine, (PVOID)DeviceExtension);
+
+ //
+ // did attaching fail
+ //
+ if (!DeviceExtension->LowerDeviceObject)
+ {
+ //
+ // device removed
+ //
+ IoDeleteDevice(DeviceObject);
+
+ return STATUS_DEVICE_REMOVED;
+ }
+
+ //
+ // set device flags
+ //
+ DeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
+
+ //
+ // device is initialized
+ //
+ DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+USBSTOR_Unload(
+ PDRIVER_OBJECT DriverObject)
+{
+ //
+ // no-op
+ //
+}
+
+NTSTATUS
+NTAPI
+USBSTOR_DispatchClose(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ //
+ // function always succeeds ;)
+ //
+ DPRINT("USBSTOR_DispatchClose\n");
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+NTAPI
+USBSTOR_DispatchDeviceControl(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ NTSTATUS Status;
+
+ //
+ // handle requests
+ //
+ Status = USBSTOR_HandleDeviceControl(DeviceObject, Irp);
+
+ //
+ // complete request
+ //
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ //
+ // done
+ //
+ return Status;
+}
+
+
+NTSTATUS
+NTAPI
+USBSTOR_DispatchScsi(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ //
+ // handle requests
+ //
+ return USBSTOR_HandleInternalDeviceControl(DeviceObject, Irp);
+}
+
+NTSTATUS
+NTAPI
+USBSTOR_DispatchReadWrite(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ //
+ // read write ioctl is not supported
+ //
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INVALID_PARAMETER;
+}
+
+NTSTATUS
+NTAPI
+USBSTOR_DispatchPnp(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ PUSBSTOR_COMMON_DEVICE_EXTENSION DeviceExtension;
+
+ //
+ // get common device extension
+ //
+ DeviceExtension = (PUSBSTOR_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // is it for the FDO
+ //
+ if (DeviceExtension->IsFDO)
+ {
+ //
+ // dispatch pnp request to fdo pnp handler
+ //
+ return USBSTOR_FdoHandlePnp(DeviceObject, Irp);
+ }
+ else
+ {
+ //
+ // dispatch request to pdo pnp handler
+ //
+ return USBSTOR_PdoHandlePnp(DeviceObject, Irp);
+ }
+}
+
+NTSTATUS
+NTAPI
+USBSTOR_DispatchPower(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ PFDO_DEVICE_EXTENSION DeviceExtension;
+
+ // get common device extension
+ DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ if (DeviceExtension->Common.IsFDO)
+ {
+ PoStartNextPowerIrp(Irp);
+ IoSkipCurrentIrpStackLocation(Irp);
+ return PoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
+ }
+ else
+ {
+ PoStartNextPowerIrp(Irp);
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_SUCCESS;
+ }
+}
+
+
+
+NTSTATUS
+NTAPI
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegPath)
+{
+
+ DPRINT("********* USB Storage *********\n");
+
+ //
+ // driver unload routine
+ //
+ DriverObject->DriverUnload = USBSTOR_Unload;
+
+ //
+ // add device function
+ //
+ DriverObject->DriverExtension->AddDevice = USBSTOR_AddDevice;
+
+ //
+ // driver start i/o routine
+ //
+ DriverObject->DriverStartIo = USBSTOR_StartIo;
+
+ //
+ // create / close
+ //
+ DriverObject->MajorFunction[IRP_MJ_CREATE] = USBSTOR_DispatchClose;
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBSTOR_DispatchClose;
+
+ //
+ // scsi pass through requests
+ //
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBSTOR_DispatchDeviceControl;
+
+ //
+ // irp dispatch read / write
+ //
+ DriverObject->MajorFunction[IRP_MJ_READ] = USBSTOR_DispatchReadWrite;
+ DriverObject->MajorFunction[IRP_MJ_WRITE] = USBSTOR_DispatchReadWrite;
+
+ //
+ // scsi queue ioctl
+ //
+ DriverObject->MajorFunction[IRP_MJ_SCSI] = USBSTOR_DispatchScsi;
+
+ //
+ // pnp processing
+ //
+ DriverObject->MajorFunction[IRP_MJ_PNP] = USBSTOR_DispatchPnp;
+
+ //
+ // power processing
+ //
+ DriverObject->MajorFunction[IRP_MJ_POWER] = USBSTOR_DispatchPower;
+
+ return STATUS_SUCCESS;
+}
--- /dev/null
+#ifndef _USBSTOR_H_
+#define _USBSTOR_H_
+
+#include <wdm.h>
+#include <usbdi.h>
+#include <usbbusif.h>
+#include <usbdlib.h>
+#include <classpnp.h>
+
+#define USB_STOR_TAG 'sbsu'
+#define USB_MAXCHILDREN (16)
+
+#define HTONS(n) (((((unsigned short)(n) & 0xFF)) << 8) | (((unsigned short)(n) & 0xFF00) >> 8))
+#define NTOHS(n) (((((unsigned short)(n) & 0xFF)) << 8) | (((unsigned short)(n) & 0xFF00) >> 8))
+
+#define HTONL(n) (((((unsigned long)(n) & 0xFF)) << 24) | \
+ ((((unsigned long)(n) & 0xFF00)) << 8) | \
+ ((((unsigned long)(n) & 0xFF0000)) >> 8) | \
+ ((((unsigned long)(n) & 0xFF000000)) >> 24))
+
+
+#define NTOHL(n) (((((unsigned long)(n) & 0xFF)) << 24) | \
+ ((((unsigned long)(n) & 0xFF00)) << 8) | \
+ ((((unsigned long)(n) & 0xFF0000)) >> 8) | \
+ ((((unsigned long)(n) & 0xFF000000)) >> 24))
+
+#define USB_RECOVERABLE_ERRORS (USBD_STATUS_STALL_PID | USBD_STATUS_DEV_NOT_RESPONDING \
+ | USBD_STATUS_ENDPOINT_HALTED | USBD_STATUS_NO_BANDWIDTH)
+
+typedef struct __COMMON_DEVICE_EXTENSION__
+{
+ BOOLEAN IsFDO;
+
+}USBSTOR_COMMON_DEVICE_EXTENSION, *PUSBSTOR_COMMON_DEVICE_EXTENSION;
+
+typedef struct
+{
+ USBSTOR_COMMON_DEVICE_EXTENSION Common; // common device extension
+
+ PDEVICE_OBJECT FunctionalDeviceObject; // functional device object
+ PDEVICE_OBJECT PhysicalDeviceObject; // physical device object
+ PDEVICE_OBJECT LowerDeviceObject; // lower device object
+ USB_BUS_INTERFACE_USBDI_V2 BusInterface; // bus interface of device
+ PUSB_DEVICE_DESCRIPTOR DeviceDescriptor; // usb device descriptor
+ PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; // usb configuration descriptor
+ PUSB_STRING_DESCRIPTOR SerialNumber; // usb serial number
+ PUSBD_INTERFACE_INFORMATION InterfaceInformation; // usb interface information
+ USBD_CONFIGURATION_HANDLE ConfigurationHandle; // usb configuration handle
+ UCHAR BulkInPipeIndex; // bulk in pipe index
+ UCHAR BulkOutPipeIndex; // bulk out pipe index
+ UCHAR MaxLUN; // max lun for device
+ PDEVICE_OBJECT ChildPDO[16]; // max 16 child pdo devices
+ KSPIN_LOCK IrpListLock; // irp list lock
+ LIST_ENTRY IrpListHead; // irp list head
+ BOOLEAN IrpListFreeze; // if true the irp list is freezed
+ BOOLEAN ResetInProgress; // if hard reset is in progress
+ 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
+ ULONG InstanceCount; // pdo instance count
+}FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
+
+typedef struct
+{
+ USBSTOR_COMMON_DEVICE_EXTENSION Common;
+ 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;
+
+//
+// max lun command identifier
+//
+#define USB_BULK_GET_MAX_LUN 0xFE
+#define USB_BULK_RESET_DEVICE 0xFF
+
+#include <pshpack1.h>
+typedef struct
+{
+ ULONG Signature; // CBW signature
+ ULONG Tag; // CBW Tag of operation
+ ULONG DataTransferLength; // data transfer length
+ UCHAR Flags; // CBW Flags endpoint direction
+ UCHAR LUN; // lun unit
+ UCHAR CommandBlockLength; // Command block length
+ UCHAR CommandBlock[16];
+}CBW, *PCBW;
+
+C_ASSERT(sizeof(CBW) == 31);
+
+
+#define CBW_SIGNATURE 0x43425355
+#define CSW_SIGNATURE 0x53425355
+
+#define MAX_LUN 0xF
+
+typedef struct
+{
+ ULONG Signature; // CSW signature
+ ULONG Tag; // CSW tag
+ ULONG DataResidue; // CSW data transfer diff
+ UCHAR Status; // CSW status
+}CSW, *PCSW;
+
+//--------------------------------------------------------------------------------------------------------------------------------------------
+//
+// UFI INQUIRY command
+//
+typedef struct
+{
+ UCHAR Code; // operation code 0x12
+ UCHAR LUN; // lun address
+ UCHAR PageCode; // product data information, always 0x00
+ UCHAR Reserved; // reserved 0x00
+ UCHAR AllocationLength; // length of inquiry data to be returned, default 36 bytes
+ UCHAR Reserved1[7]; //reserved bytes 0x00
+}UFI_INQUIRY_CMD, *PUFI_INQUIRY_CMD;
+
+C_ASSERT(sizeof(UFI_INQUIRY_CMD) == 12);
+
+#define UFI_INQUIRY_CMD_LEN 0x6
+
+//
+// UFI INQUIRY command response
+//
+typedef struct
+{
+ UCHAR DeviceType; // device type
+ UCHAR RMB; // removable media bit
+ UCHAR Version; // contains version 0x00
+ UCHAR Format; // response format
+ UCHAR Length; // additional length
+ UCHAR Reserved[3]; // reserved
+ UCHAR Vendor[8]; // vendor identification string
+ UCHAR Product[16]; // product identification string
+ UCHAR Revision[4]; // product revision code
+}UFI_INQUIRY_RESPONSE, *PUFI_INQUIRY_RESPONSE;
+
+C_ASSERT(sizeof(UFI_INQUIRY_RESPONSE) == 36);
+
+//--------------------------------------------------------------------------------------------------------------------------------------------
+//
+// UFI read cmd
+//
+typedef struct
+{
+ UCHAR Code; // operation code
+ UCHAR LUN; // lun
+ UCHAR LogicalBlockByte0; // lba byte 0
+ UCHAR LogicalBlockByte1; // lba byte 1
+ UCHAR LogicalBlockByte2; // lba byte 2
+ UCHAR LogicalBlockByte3; // lba byte 3
+ UCHAR Reserved; // reserved 0x00
+ UCHAR ContiguousLogicBlocksByte0; // msb contiguous logic blocks byte
+ UCHAR ContiguousLogicBlocksByte1; // msb contiguous logic blocks
+ UCHAR Reserved1[3]; // reserved 0x00
+}UFI_READ_WRITE_CMD;
+
+C_ASSERT(sizeof(UFI_READ_WRITE_CMD) == 12);
+
+#define UFI_READ_WRITE_CMD_LEN (0xA)
+
+//--------------------------------------------------------------------------------------------------------------------------------------------
+//
+// UFI read capacity cmd
+//
+typedef struct
+{
+ UCHAR Code; // operation code 0x25
+ UCHAR LUN; // lun address
+ UCHAR LBA[4]; // logical block address, should be zero
+ UCHAR Reserved1[2]; // reserved 0x00
+ UCHAR PMI; // PMI = 0x00
+ UCHAR Reserved2[3]; // reserved 0x00
+}UFI_CAPACITY_CMD, *PUFI_CAPACITY_CMD;
+
+C_ASSERT(sizeof(UFI_CAPACITY_CMD) == 12);
+
+#define UFI_CAPACITY_CMD_LEN 0xA //FIXME support length 16 too if requested
+
+//
+// UFI Read Capacity command response
+//
+typedef struct
+{
+ ULONG LastLogicalBlockAddress; // last logical block address
+ ULONG BlockLength; // block length in bytes
+}UFI_CAPACITY_RESPONSE, *PUFI_CAPACITY_RESPONSE;
+
+#define UFI_READ_CAPACITY_CMD_LEN 0xA
+C_ASSERT(sizeof(UFI_CAPACITY_RESPONSE) == 8);
+
+//--------------------------------------------------------------------------------------------------------------------------------------------
+//
+// UFI sense mode cmd
+//
+typedef struct
+{
+ UCHAR Code; // operation code
+ UCHAR LUN; // lun address
+ UCHAR PageCode:6; // page code selector
+ UCHAR PC:2; // type of parameters to be returned
+ UCHAR Reserved[4]; // reserved 0x00
+ USHORT AllocationLength; // parameters length
+ UCHAR Reserved1[3];
+}UFI_SENSE_CMD, *PUFI_SENSE_CMD;
+
+C_ASSERT(sizeof(UFI_SENSE_CMD) == 12);
+
+#define UFI_SENSE_CMD_LEN (6)
+
+typedef struct
+{
+ USHORT ModeDataLength; // length of parameters for sense cmd
+ UCHAR MediumTypeCode; // 00 for mass storage, 0x94 for floppy
+ UCHAR WP:1; // write protect bit
+ UCHAR Reserved1:2; // reserved 00
+ UCHAR DPOFUA:1; // should be zero
+ UCHAR Reserved2:4; // reserved
+ UCHAR Reserved[4]; // reserved
+}UFI_MODE_PARAMETER_HEADER, *PUFI_MODE_PARAMETER_HEADER;
+
+
+C_ASSERT(sizeof(UFI_MODE_PARAMETER_HEADER) == 8);
+
+typedef struct
+{
+ UCHAR PC;
+ UCHAR PageLength;
+ UCHAR Reserved1;
+ UCHAR ITM;
+ UCHAR Flags;
+ 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 UNFORMATTED_MEDIA_CODE_DESCRIPTORY_TYPE (1)
+#define FORMAT_MEDIA_CODE_DESCRIPTOR_TYPE (2)
+#define CARTRIDGE_MEDIA_CODE_DESCRIPTOR_TYPE (3)
+
+
+
+
+//--------------------------------------------------------------------------------------------------------------------------------------------
+//
+// UFI test unit command
+//
+
+typedef struct
+{
+ UCHAR Code; // operation code 0x00
+ UCHAR LUN; // lun
+ UCHAR Reserved[10]; // reserved 0x00
+}UFI_TEST_UNIT_CMD, *PUFI_TEST_UNIT_CMD;
+
+C_ASSERT(sizeof(UFI_TEST_UNIT_CMD) == 12);
+
+#define UFI_TEST_UNIT_CMD_LEN (6)
+
+//-------------------------------------------------------------------------------------------------------------------------------------------
+typedef struct
+{
+ UCHAR Bytes[16];
+}UFI_UNKNOWN_CMD, *PUFI_UNKNOWN_CMD;
+
+typedef struct
+{
+ union
+ {
+ PCBW cbw;
+ PCSW csw;
+ };
+ URB Urb;
+ PIRP Irp;
+ ULONG TransferDataLength;
+ PUCHAR TransferData;
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PMDL TransferBufferMDL;
+ ULONG ErrorIndex;
+ ULONG RetryCount;
+}IRP_CONTEXT, *PIRP_CONTEXT;
+
+typedef struct _ERRORHANDLER_WORKITEM_DATA
+{
+ PDEVICE_OBJECT DeviceObject;
+ PIRP_CONTEXT Context;
+ WORK_QUEUE_ITEM WorkQueueItem;
+ PIRP Irp;
+} ERRORHANDLER_WORKITEM_DATA, *PERRORHANDLER_WORKITEM_DATA;
+
+
+//---------------------------------------------------------------------
+//
+// fdo.c routines
+//
+NTSTATUS
+USBSTOR_FdoHandlePnp(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp);
+
+//---------------------------------------------------------------------
+//
+// pdo.c routines
+//
+NTSTATUS
+USBSTOR_PdoHandlePnp(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp);
+
+NTSTATUS
+USBSTOR_CreatePDO(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN UCHAR LUN);
+
+//---------------------------------------------------------------------
+//
+// misc.c routines
+//
+NTSTATUS
+NTAPI
+USBSTOR_SyncForwardIrp(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp);
+
+NTSTATUS
+NTAPI
+USBSTOR_GetBusInterface(
+ IN PDEVICE_OBJECT DeviceObject,
+ OUT PUSB_BUS_INTERFACE_USBDI_V2 BusInterface);
+
+PVOID
+AllocateItem(
+ IN POOL_TYPE PoolType,
+ IN ULONG ItemSize);
+
+VOID
+FreeItem(
+ IN PVOID Item);
+
+NTSTATUS
+USBSTOR_SyncUrbRequest(
+ IN PDEVICE_OBJECT DeviceObject,
+ OUT PURB UrbRequest);
+
+NTSTATUS
+USBSTOR_GetMaxLUN(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PFDO_DEVICE_EXTENSION DeviceExtension);
+
+NTSTATUS
+NTAPI
+USBSTOR_SyncForwardIrpCompletionRoutine(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PVOID Context);
+
+NTSTATUS
+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
+//
+
+NTSTATUS
+USBSTOR_GetDescriptors(
+ IN PDEVICE_OBJECT DeviceObject);
+
+NTSTATUS
+USBSTOR_SelectConfigurationAndInterface(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PFDO_DEVICE_EXTENSION DeviceExtension);
+
+NTSTATUS
+USBSTOR_GetPipeHandles(
+ IN PFDO_DEVICE_EXTENSION DeviceExtension);
+
+//---------------------------------------------------------------------
+//
+// scsi.c routines
+//
+NTSTATUS
+USBSTOR_HandleExecuteSCSI(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN ULONG RetryCount);
+
+NTSTATUS
+NTAPI
+USBSTOR_CSWCompletionRoutine(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PVOID Ctx);
+
+NTSTATUS
+USBSTOR_SendCBW(
+ PIRP_CONTEXT Context,
+ PIRP Irp);
+
+VOID
+USBSTOR_SendCSW(
+ PIRP_CONTEXT Context,
+ PIRP Irp);
+
+
+//---------------------------------------------------------------------
+//
+// disk.c routines
+//
+NTSTATUS
+USBSTOR_HandleInternalDeviceControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+NTSTATUS
+USBSTOR_HandleDeviceControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+//---------------------------------------------------------------------
+//
+// queue.c routines
+//
+VOID
+NTAPI
+USBSTOR_StartIo(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp);
+
+VOID
+USBSTOR_QueueWaitForPendingRequests(
+ IN PDEVICE_OBJECT DeviceObject);
+
+VOID
+USBSTOR_QueueRelease(
+ IN PDEVICE_OBJECT DeviceObject);
+
+BOOLEAN
+USBSTOR_QueueAddIrp(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+VOID
+NTAPI
+USBSTOR_CancelIo(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+VOID
+USBSTOR_QueueInitialize(
+ PFDO_DEVICE_EXTENSION FDODeviceExtension);
+
+VOID
+NTAPI
+ErrorHandlerWorkItemRoutine(
+ PVOID Context);
+
+VOID
+NTAPI
+ResetHandlerWorkItemRoutine(
+ PVOID Context);
+
+
+
+VOID
+USBSTOR_QueueNextRequest(
+ IN PDEVICE_OBJECT DeviceObject);
+
+VOID
+USBSTOR_QueueTerminateRequest(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+/* error.c */
+NTSTATUS
+USBSTOR_GetEndpointStatus(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN UCHAR bEndpointAddress,
+ OUT PUSHORT Value);
+
+NTSTATUS
+USBSTOR_ResetPipeWithHandle(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN USBD_PIPE_HANDLE PipeHandle);
+
+VOID
+NTAPI
+USBSTOR_TimerRoutine(
+ PDEVICE_OBJECT DeviceObject,
+ PVOID Context);
+
+#endif /* _USBSTOR_H_ */
--- /dev/null
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION "USB Storage Device Driver"
+#define REACTOS_STR_INTERNAL_NAME "usbstor"
+#define REACTOS_STR_ORIGINAL_FILENAME "usbstor.sys"
+#include <reactos/version.rc>