mirror of
https://github.com/reactos/reactos.git
synced 2025-05-19 17:14:32 +00:00
[USBSTOR]
- Start implementing queued srb handling - Implement SRB_FUNCTION_RELEASE_QUEUE, SRB_FUNCTION_FLUSH, SRB_FUNCTION_FLUSH_QUEUE - WIP, not yet working perfectly svn path=/branches/usb-bringup/; revision=51739
This commit is contained in:
parent
3f8c058a07
commit
be12088a55
7 changed files with 777 additions and 128 deletions
|
@ -3,7 +3,7 @@ add_definitions(-DDEBUG_MODE)
|
||||||
|
|
||||||
include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
|
include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
|
||||||
|
|
||||||
add_library(usbstor SHARED descriptor.c disk.c fdo.c misc.c pdo.c scsi.c usbstor.c usbstor.rc)
|
add_library(usbstor SHARED descriptor.c disk.c fdo.c misc.c pdo.c queue.c scsi.c usbstor.c usbstor.rc)
|
||||||
|
|
||||||
set_module_type(usbstor kernelmodedriver)
|
set_module_type(usbstor kernelmodedriver)
|
||||||
add_importlibs(usbstor ntoskrnl hal usbd)
|
add_importlibs(usbstor ntoskrnl hal usbd)
|
||||||
|
|
|
@ -11,87 +11,6 @@
|
||||||
|
|
||||||
#include "usbstor.h"
|
#include "usbstor.h"
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
USBSTOR_HandleExecuteSCSI(
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN PIRP Irp,
|
|
||||||
IN OUT PSCSI_REQUEST_BLOCK Request,
|
|
||||||
IN PPDO_DEVICE_EXTENSION PDODeviceExtension)
|
|
||||||
{
|
|
||||||
PCDB pCDB;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
//
|
|
||||||
// get SCSI command data block
|
|
||||||
//
|
|
||||||
pCDB = (PCDB)Request->Cdb;
|
|
||||||
|
|
||||||
DPRINT1("USBSTOR_HandleExecuteSCSI Operation Code %x\n", pCDB->AsByte[0]);
|
|
||||||
|
|
||||||
|
|
||||||
if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// sanity checks
|
|
||||||
//
|
|
||||||
ASSERT(Request->DataBuffer);
|
|
||||||
|
|
||||||
DPRINT1("SCSIOP_READ_CAPACITY Length %\n", Request->DataTransferLength);
|
|
||||||
Status = USBSTOR_SendCapacityCmd(DeviceObject, Irp);
|
|
||||||
}
|
|
||||||
else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE)
|
|
||||||
{
|
|
||||||
DPRINT1("SCSIOP_MODE_SENSE DataTransferLength %lu\n", Request->DataTransferLength);
|
|
||||||
ASSERT(pCDB->MODE_SENSE.AllocationLength == Request->DataTransferLength);
|
|
||||||
ASSERT(Request->DataBuffer);
|
|
||||||
|
|
||||||
//
|
|
||||||
// send mode sense command
|
|
||||||
//
|
|
||||||
Status = USBSTOR_SendModeSenseCmd(DeviceObject, Irp);
|
|
||||||
}
|
|
||||||
else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_READ /*|| pCDB->MODE_SENSE.OperationCode == SCSIOP_WRITE*/)
|
|
||||||
{
|
|
||||||
DPRINT1("SCSIOP_READ / SCSIOP_WRITE DataTransferLength %lu\n", Request->DataTransferLength);
|
|
||||||
|
|
||||||
//
|
|
||||||
// send read / write command
|
|
||||||
//
|
|
||||||
Status = USBSTOR_SendReadWriteCmd(DeviceObject, Irp);
|
|
||||||
}
|
|
||||||
else if (pCDB->AsByte[0] == SCSIOP_MEDIUM_REMOVAL)
|
|
||||||
{
|
|
||||||
DPRINT1("SCSIOP_MEDIUM_REMOVAL\n");
|
|
||||||
|
|
||||||
//
|
|
||||||
// just complete the request
|
|
||||||
//
|
|
||||||
Request->SrbStatus = SRB_STATUS_SUCCESS;
|
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
||||||
Irp->IoStatus.Information = Request->DataTransferLength;
|
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_TEST_UNIT_READY)
|
|
||||||
{
|
|
||||||
DPRINT1("SCSIOP_TEST_UNIT_READY\n");
|
|
||||||
|
|
||||||
//
|
|
||||||
// send test unit command
|
|
||||||
//
|
|
||||||
Status = USBSTOR_SendTestUnitCmd(DeviceObject, Irp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
Request->SrbStatus = SRB_STATUS_ERROR;
|
|
||||||
Status = STATUS_NOT_SUPPORTED;
|
|
||||||
DbgBreakPoint();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
USBSTOR_HandleInternalDeviceControl(
|
USBSTOR_HandleInternalDeviceControl(
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
@ -128,7 +47,58 @@ USBSTOR_HandleInternalDeviceControl(
|
||||||
case SRB_FUNCTION_EXECUTE_SCSI:
|
case SRB_FUNCTION_EXECUTE_SCSI:
|
||||||
{
|
{
|
||||||
DPRINT1("SRB_FUNCTION_EXECUTE_SCSI\n");
|
DPRINT1("SRB_FUNCTION_EXECUTE_SCSI\n");
|
||||||
return USBSTOR_HandleExecuteSCSI(DeviceObject, Irp, Request, PDODeviceExtension);
|
|
||||||
|
//
|
||||||
|
// 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(DeviceObject, 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:
|
case SRB_FUNCTION_RELEASE_DEVICE:
|
||||||
{
|
{
|
||||||
|
@ -179,20 +149,37 @@ USBSTOR_HandleInternalDeviceControl(
|
||||||
}
|
}
|
||||||
case SRB_FUNCTION_RELEASE_QUEUE:
|
case SRB_FUNCTION_RELEASE_QUEUE:
|
||||||
{
|
{
|
||||||
DPRINT1("SRB_FUNCTION_RELEASE_QUEUE UNIMPLEMENTED\n");
|
DPRINT1("SRB_FUNCTION_RELEASE_QUEUE\n");
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
|
||||||
|
//
|
||||||
|
// release queue
|
||||||
|
//
|
||||||
|
USBSTOR_QueueRelease(DeviceObject);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// set status success
|
||||||
|
//
|
||||||
|
Request->SrbStatus = SRB_STATUS_SUCCESS;
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SRB_FUNCTION_FLUSH:
|
case SRB_FUNCTION_FLUSH:
|
||||||
|
case SRB_FUNCTION_FLUSH_QUEUE:
|
||||||
{
|
{
|
||||||
DPRINT1("SRB_FUNCTION_FLUSH UNIMPLEMENTED\n");
|
DPRINT1("SRB_FUNCTION_FLUSH / SRB_FUNCTION_FLUSH_QUEUE\n");
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
|
||||||
break;
|
//
|
||||||
}
|
// flush all requests
|
||||||
case SRB_FUNCTION_SET_LINK_TIMEOUT:
|
//
|
||||||
{
|
USBSTOR_QueueFlushIrps(DeviceObject);
|
||||||
DPRINT1("SRB_FUNCTION_FLUSH UNIMPLEMENTED\n");
|
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
//
|
||||||
|
// set status success
|
||||||
|
//
|
||||||
|
Request->SrbStatus = SRB_STATUS_SUCCESS;
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -141,6 +141,11 @@ USBSTOR_FdoHandleStartDevice(
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// intialize irp queue
|
||||||
|
//
|
||||||
|
USBSTOR_QueueInitialize(DeviceExtension);
|
||||||
|
|
||||||
//
|
//
|
||||||
// first get device & configuration & string descriptor
|
// first get device & configuration & string descriptor
|
||||||
//
|
//
|
||||||
|
|
561
drivers/usb/usbstor/queue.c
Normal file
561
drivers/usb/usbstor/queue.c
Normal file
|
@ -0,0 +1,561 @@
|
||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
VOID
|
||||||
|
USBSTOR_QueueInitialize(
|
||||||
|
PFDO_DEVICE_EXTENSION FDODeviceExtension)
|
||||||
|
{
|
||||||
|
|
||||||
|
//
|
||||||
|
// initialize queue lock
|
||||||
|
//
|
||||||
|
KeInitializeSpinLock(&FDODeviceExtension->IrpListLock);
|
||||||
|
|
||||||
|
//
|
||||||
|
// initialize irp list head
|
||||||
|
//
|
||||||
|
InitializeListHead(&FDODeviceExtension->IrpListHead);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
//
|
||||||
|
// acquire irp list lock
|
||||||
|
//
|
||||||
|
KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension->IrpListLock);
|
||||||
|
|
||||||
|
//
|
||||||
|
// now release the cancel lock
|
||||||
|
//
|
||||||
|
IoReleaseCancelSpinLock(Irp->CancelIrql);
|
||||||
|
|
||||||
|
//
|
||||||
|
// remove the irp from the list
|
||||||
|
//
|
||||||
|
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
|
||||||
|
|
||||||
|
//
|
||||||
|
// release irp list lock
|
||||||
|
//
|
||||||
|
KeReleaseSpinLockFromDpcLevel(&FDODeviceExtension->IrpListLock);
|
||||||
|
|
||||||
|
//
|
||||||
|
// set cancel status
|
||||||
|
//
|
||||||
|
Irp->IoStatus.Status = STATUS_CANCELLED;
|
||||||
|
|
||||||
|
//
|
||||||
|
// now cancel the irp
|
||||||
|
//
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
USBSTOR_QueueAddIrp(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PDRIVER_CANCEL OldDriverCancel;
|
||||||
|
KIRQL OldLevel;
|
||||||
|
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||||
|
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||||
|
BOOLEAN IrpListFreeze;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get pdo device extension
|
||||||
|
//
|
||||||
|
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get FDO device extension
|
||||||
|
//
|
||||||
|
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// mark irp pending
|
||||||
|
//
|
||||||
|
IoMarkIrpPending(Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// acquire lock
|
||||||
|
//
|
||||||
|
KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
|
||||||
|
|
||||||
|
//
|
||||||
|
// add irp to queue
|
||||||
|
//
|
||||||
|
InsertTailList(&FDODeviceExtension->IrpListHead, &Irp->Tail.Overlay.ListEntry);
|
||||||
|
|
||||||
|
//
|
||||||
|
// now set the driver cancel routine
|
||||||
|
//
|
||||||
|
OldDriverCancel = IoSetCancelRoutine(Irp, USBSTOR_CancelIo);
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if the irp has already been cancelled
|
||||||
|
//
|
||||||
|
if (Irp->Cancel && OldDriverCancel == NULL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// the irp has already been cancelled
|
||||||
|
//
|
||||||
|
KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
|
||||||
|
|
||||||
|
//
|
||||||
|
// cancel routine requires that cancel spinlock is held
|
||||||
|
//
|
||||||
|
IoAcquireCancelSpinLock(&Irp->CancelIrql);
|
||||||
|
|
||||||
|
//
|
||||||
|
// cancel irp
|
||||||
|
//
|
||||||
|
USBSTOR_CancelIo(DeviceObject, Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// irp was cancelled
|
||||||
|
//
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if queue is freezed
|
||||||
|
//
|
||||||
|
IrpListFreeze = FDODeviceExtension->IrpListFreeze;
|
||||||
|
|
||||||
|
//
|
||||||
|
// release list lock
|
||||||
|
//
|
||||||
|
KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
|
||||||
|
|
||||||
|
//
|
||||||
|
// if list is freezed, dont start this packet
|
||||||
|
//
|
||||||
|
return IrpListFreeze;
|
||||||
|
}
|
||||||
|
|
||||||
|
PIRP
|
||||||
|
USBSTOR_RemoveIrp(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
KIRQL OldLevel;
|
||||||
|
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||||
|
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||||
|
PLIST_ENTRY Entry;
|
||||||
|
PIRP Irp = NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get pdo device extension
|
||||||
|
//
|
||||||
|
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get FDO device extension
|
||||||
|
//
|
||||||
|
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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_QueueFlushIrps(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
KIRQL OldLevel;
|
||||||
|
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||||
|
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||||
|
PLIST_ENTRY Entry;
|
||||||
|
PIRP Irp;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PSCSI_REQUEST_BLOCK Request;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get pdo device extension
|
||||||
|
//
|
||||||
|
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get FDO device extension
|
||||||
|
//
|
||||||
|
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// acquire lock
|
||||||
|
//
|
||||||
|
KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
|
||||||
|
|
||||||
|
//
|
||||||
|
// complete all irps with status cancelled
|
||||||
|
//
|
||||||
|
while(!IsListEmpty(&FDODeviceExtension->IrpListHead))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// remove irp
|
||||||
|
//
|
||||||
|
Entry = RemoveHeadList(&FDODeviceExtension->IrpListHead);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get start of irp structure
|
||||||
|
//
|
||||||
|
Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get current stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get request block
|
||||||
|
//
|
||||||
|
Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(Request);
|
||||||
|
|
||||||
|
//
|
||||||
|
// set srb status to flushed
|
||||||
|
//
|
||||||
|
Request->SrbStatus = SRB_STATUS_REQUEST_FLUSHED;
|
||||||
|
|
||||||
|
//
|
||||||
|
// set unsuccessful status
|
||||||
|
//
|
||||||
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// complete request
|
||||||
|
//
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// release lock
|
||||||
|
//
|
||||||
|
KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
USBSTOR_QueueNextRequest(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||||
|
PIRP Irp;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PSCSI_REQUEST_BLOCK Request;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get pdo device extension
|
||||||
|
//
|
||||||
|
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// remove first irp from list
|
||||||
|
//
|
||||||
|
Irp = USBSTOR_RemoveIrp(DeviceObject);
|
||||||
|
|
||||||
|
//
|
||||||
|
// is there an irp pending
|
||||||
|
//
|
||||||
|
if (!Irp)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no work to do
|
||||||
|
//
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// get current stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get srb
|
||||||
|
//
|
||||||
|
Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// start next packet
|
||||||
|
//
|
||||||
|
IoStartPacket(PDODeviceExtension->LowerDeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
USBSTOR_QueueRelease(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||||
|
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||||
|
PIRP Irp;
|
||||||
|
KIRQL OldLevel;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PSCSI_REQUEST_BLOCK Request;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get pdo device extension
|
||||||
|
//
|
||||||
|
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get FDO device extension
|
||||||
|
//
|
||||||
|
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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(PDODeviceExtension->LowerDeviceObject, // FDO
|
||||||
|
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;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
DPRINT1("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;
|
||||||
|
|
||||||
|
//
|
||||||
|
// complete request
|
||||||
|
//
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if the queue has been frozen
|
||||||
|
//
|
||||||
|
if (FDODeviceExtension->IrpListFreeze == FALSE)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// queue next request
|
||||||
|
//
|
||||||
|
USBSTOR_QueueNextRequest(DeviceObject);
|
||||||
|
|
||||||
|
//
|
||||||
|
// start next request
|
||||||
|
//
|
||||||
|
IoStartNextPacket(DeviceObject, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// release cancel spinlock
|
||||||
|
//
|
||||||
|
IoReleaseCancelSpinLock(OldLevel);
|
||||||
|
|
||||||
|
//
|
||||||
|
// acquire lock
|
||||||
|
//
|
||||||
|
KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
|
||||||
|
|
||||||
|
//
|
||||||
|
// remove irp from list
|
||||||
|
//
|
||||||
|
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
//
|
||||||
|
// execute scsi
|
||||||
|
//
|
||||||
|
Status = USBSTOR_HandleExecuteSCSI(IoStack->DeviceObject, Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: synchronize action with error handling
|
||||||
|
//
|
||||||
|
USBSTOR_QueueNextRequest(IoStack->DeviceObject);
|
||||||
|
|
||||||
|
//
|
||||||
|
// start next request
|
||||||
|
//
|
||||||
|
IoStartNextPacket(DeviceObject, TRUE);
|
||||||
|
|
||||||
|
}
|
|
@ -1002,3 +1002,94 @@ USBSTOR_SendTestUnitCmd(
|
||||||
//
|
//
|
||||||
return USBSTOR_SendRequest(DeviceObject, Irp, NULL, UFI_TEST_UNIT_CMD_LEN, (PUCHAR)&Cmd, 0, NULL);
|
return USBSTOR_SendRequest(DeviceObject, Irp, NULL, UFI_TEST_UNIT_CMD_LEN, (PUCHAR)&Cmd, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
USBSTOR_HandleExecuteSCSI(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PCDB pCDB;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PSCSI_REQUEST_BLOCK Request;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get current stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get request block
|
||||||
|
//
|
||||||
|
Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get SCSI command data block
|
||||||
|
//
|
||||||
|
pCDB = (PCDB)Request->Cdb;
|
||||||
|
|
||||||
|
DPRINT1("USBSTOR_HandleExecuteSCSI Operation Code %x\n", pCDB->AsByte[0]);
|
||||||
|
|
||||||
|
if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// sanity checks
|
||||||
|
//
|
||||||
|
ASSERT(Request->DataBuffer);
|
||||||
|
|
||||||
|
DPRINT1("SCSIOP_READ_CAPACITY Length %\n", Request->DataTransferLength);
|
||||||
|
Status = USBSTOR_SendCapacityCmd(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE)
|
||||||
|
{
|
||||||
|
DPRINT1("SCSIOP_MODE_SENSE DataTransferLength %lu\n", Request->DataTransferLength);
|
||||||
|
ASSERT(pCDB->MODE_SENSE.AllocationLength == Request->DataTransferLength);
|
||||||
|
ASSERT(Request->DataBuffer);
|
||||||
|
|
||||||
|
//
|
||||||
|
// send mode sense command
|
||||||
|
//
|
||||||
|
Status = USBSTOR_SendModeSenseCmd(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_READ /*|| pCDB->MODE_SENSE.OperationCode == SCSIOP_WRITE*/)
|
||||||
|
{
|
||||||
|
DPRINT1("SCSIOP_READ / SCSIOP_WRITE DataTransferLength %lu\n", Request->DataTransferLength);
|
||||||
|
|
||||||
|
//
|
||||||
|
// send read / write command
|
||||||
|
//
|
||||||
|
Status = USBSTOR_SendReadWriteCmd(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
else if (pCDB->AsByte[0] == SCSIOP_MEDIUM_REMOVAL)
|
||||||
|
{
|
||||||
|
DPRINT1("SCSIOP_MEDIUM_REMOVAL\n");
|
||||||
|
|
||||||
|
//
|
||||||
|
// just complete the request
|
||||||
|
//
|
||||||
|
Request->SrbStatus = SRB_STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = Request->DataTransferLength;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_TEST_UNIT_READY)
|
||||||
|
{
|
||||||
|
DPRINT1("SCSIOP_TEST_UNIT_READY\n");
|
||||||
|
|
||||||
|
//
|
||||||
|
// send test unit command
|
||||||
|
//
|
||||||
|
Status = USBSTOR_SendTestUnitCmd(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
Request->SrbStatus = SRB_STATUS_ERROR;
|
||||||
|
Status = STATUS_NOT_SUPPORTED;
|
||||||
|
DbgBreakPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
|
@ -99,18 +99,6 @@ USBSTOR_Unload(
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
USBSTOR_StartIo(
|
|
||||||
PDEVICE_OBJECT DeviceObject,
|
|
||||||
PIRP Irp)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// implement me
|
|
||||||
//
|
|
||||||
UNIMPLEMENTED
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
USBSTOR_DispatchClose(
|
USBSTOR_DispatchClose(
|
||||||
|
@ -251,10 +239,9 @@ DriverEntry(
|
||||||
DriverObject->DriverExtension->AddDevice = USBSTOR_AddDevice;
|
DriverObject->DriverExtension->AddDevice = USBSTOR_AddDevice;
|
||||||
|
|
||||||
//
|
//
|
||||||
// FIXME: driver start i/o routine
|
// driver start i/o routine
|
||||||
//
|
//
|
||||||
//DriverObject->DriverStartIo = USBSTOR_StartIo;
|
DriverObject->DriverStartIo = USBSTOR_StartIo;
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// create / close
|
// create / close
|
||||||
|
|
|
@ -63,6 +63,9 @@ typedef struct
|
||||||
UCHAR BulkOutPipeIndex; // bulk out pipe index
|
UCHAR BulkOutPipeIndex; // bulk out pipe index
|
||||||
UCHAR MaxLUN; // max lun for device
|
UCHAR MaxLUN; // max lun for device
|
||||||
PDEVICE_OBJECT ChildPDO[16]; // max 16 child pdo devices
|
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
|
||||||
}FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
|
}FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -76,6 +79,9 @@ typedef struct
|
||||||
ULONG LastLogicBlockAddress; // last block address
|
ULONG LastLogicBlockAddress; // last block address
|
||||||
}PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
|
}PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// max lun command identifier
|
// max lun command identifier
|
||||||
//
|
//
|
||||||
|
@ -361,26 +367,7 @@ USBSTOR_GetPipeHandles(
|
||||||
// scsi.c routines
|
// scsi.c routines
|
||||||
//
|
//
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
USBSTOR_SendInquiryCmd(
|
USBSTOR_HandleExecuteSCSI(
|
||||||
IN PDEVICE_OBJECT DeviceObject);
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
USBSTOR_SendCapacityCmd(
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN PIRP Irp);
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
USBSTOR_SendModeSenseCmd(
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN PIRP Irp);
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
USBSTOR_SendReadWriteCmd(
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN PIRP Irp);
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
USBSTOR_SendTestUnitCmd(
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PIRP Irp);
|
IN PIRP Irp);
|
||||||
|
|
||||||
|
@ -398,4 +385,35 @@ USBSTOR_HandleDeviceControl(
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PIRP Irp);
|
IN PIRP Irp);
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// queue.c routines
|
||||||
|
//
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
USBSTOR_StartIo(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
USBSTOR_QueueFlushIrps(
|
||||||
|
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);
|
||||||
|
|
Loading…
Reference in a new issue