mirror of
https://github.com/reactos/reactos.git
synced 2024-06-28 17:01:28 +00:00
[USBSTOR_NEW] Create usbstor_new based on usbstor in order to contain Vadim Galyant's work.
This commit is contained in:
parent
d7c47feb25
commit
94e0942644
|
@ -6,5 +6,6 @@ add_subdirectory(usbhub)
|
|||
add_subdirectory(usbohci)
|
||||
#add_subdirectory(usbohci_new)
|
||||
add_subdirectory(usbport)
|
||||
#add_subdirectory(usbport_new)
|
||||
add_subdirectory(usbstor)
|
||||
add_subdirectory(usbuhci)
|
||||
|
|
25
drivers/usb/usbstor_new/CMakeLists.txt
Normal file
25
drivers/usb/usbstor_new/CMakeLists.txt
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
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)
|
549
drivers/usb/usbstor_new/descriptor.c
Normal file
549
drivers/usb/usbstor_new/descriptor.c
Normal file
|
@ -0,0 +1,549 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
691
drivers/usb/usbstor_new/disk.c
Normal file
691
drivers/usb/usbstor_new/disk.c
Normal file
|
@ -0,0 +1,691 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
410
drivers/usb/usbstor_new/error.c
Normal file
410
drivers/usb/usbstor_new/error.c
Normal file
|
@ -0,0 +1,410 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
461
drivers/usb/usbstor_new/fdo.c
Normal file
461
drivers/usb/usbstor_new/fdo.c
Normal file
|
@ -0,0 +1,461 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
9
drivers/usb/usbstor_new/guid.c
Normal file
9
drivers/usb/usbstor_new/guid.c
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* 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 */
|
520
drivers/usb/usbstor_new/misc.c
Normal file
520
drivers/usb/usbstor_new/misc.c
Normal file
|
@ -0,0 +1,520 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
1376
drivers/usb/usbstor_new/pdo.c
Normal file
1376
drivers/usb/usbstor_new/pdo.c
Normal file
File diff suppressed because it is too large
Load diff
670
drivers/usb/usbstor_new/queue.c
Normal file
670
drivers/usb/usbstor_new/queue.c
Normal file
|
@ -0,0 +1,670 @@
|
|||
/*
|
||||
* 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
|
||||
//
|
||||
}
|
1429
drivers/usb/usbstor_new/scsi.c
Normal file
1429
drivers/usb/usbstor_new/scsi.c
Normal file
File diff suppressed because it is too large
Load diff
295
drivers/usb/usbstor_new/usbstor.c
Normal file
295
drivers/usb/usbstor_new/usbstor.c
Normal file
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
550
drivers/usb/usbstor_new/usbstor.h
Normal file
550
drivers/usb/usbstor_new/usbstor.h
Normal file
|
@ -0,0 +1,550 @@
|
|||
#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_ */
|
5
drivers/usb/usbstor_new/usbstor.rc
Normal file
5
drivers/usb/usbstor_new/usbstor.rc
Normal file
|
@ -0,0 +1,5 @@
|
|||
#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>
|
Loading…
Reference in a new issue