mirror of
https://github.com/reactos/reactos.git
synced 2025-05-29 14:08:22 +00:00
[USBSTOR] Do not create a new Irp for USB requests - use the original one
from higher-level driver instead. Refactored CSWCompletionRoutine for correct handling different CSW statuses, more work to be done here.
This commit is contained in:
parent
b4c03399ba
commit
ed6724cd7e
2 changed files with 75 additions and 108 deletions
|
@ -57,6 +57,7 @@ USBSTOR_AllocateIrpContext()
|
||||||
return Context;
|
return Context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
USBSTOR_IsCSWValid(
|
USBSTOR_IsCSWValid(
|
||||||
PIRP_CONTEXT Context)
|
PIRP_CONTEXT Context)
|
||||||
|
@ -73,12 +74,6 @@ USBSTOR_IsCSWValid(
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Context->csw->Status != 0x00)
|
|
||||||
{
|
|
||||||
DPRINT1("[USBSTOR] Expected Status 0x00 but got %x\n", Context->csw->Status);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,99 +123,99 @@ USBSTOR_CSWCompletionRoutine(
|
||||||
PIRP_CONTEXT Context;
|
PIRP_CONTEXT Context;
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
PSCSI_REQUEST_BLOCK Request;
|
PSCSI_REQUEST_BLOCK Request;
|
||||||
PCDB pCDB;
|
|
||||||
PUFI_CAPACITY_RESPONSE Response;
|
PUFI_CAPACITY_RESPONSE Response;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
Context = (PIRP_CONTEXT)Ctx;
|
Context = (PIRP_CONTEXT)Ctx;
|
||||||
|
|
||||||
if (Context->TransferBufferMDL)
|
if (Context->TransferBufferMDL && Context->TransferBufferMDL != Context->Irp->MdlAddress)
|
||||||
{
|
{
|
||||||
// is there an irp associated
|
IoFreeMdl(Context->TransferBufferMDL);
|
||||||
if (Context->Irp)
|
}
|
||||||
|
|
||||||
|
DPRINT("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
|
||||||
|
|
||||||
|
// first check for Irp errors
|
||||||
|
if (!NT_SUCCESS(Irp->IoStatus.Status))
|
||||||
|
{
|
||||||
|
if (USBD_STATUS(Context->Urb.UrbHeader.Status) == USBD_STATUS(USBD_STATUS_STALL_PID))
|
||||||
{
|
{
|
||||||
// did we allocate the mdl
|
if (Context->ErrorIndex == 0)
|
||||||
if (Context->TransferBufferMDL != Context->Irp->MdlAddress)
|
|
||||||
{
|
{
|
||||||
IoFreeMdl(Context->TransferBufferMDL);
|
Context->ErrorIndex = 1;
|
||||||
|
|
||||||
|
// clear stall and resend cbw
|
||||||
|
Status = USBSTOR_QueueWorkItem(Context, Irp);
|
||||||
|
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
|
||||||
|
|
||||||
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
IoFreeMdl(Context->TransferBufferMDL);
|
DPRINT1("USBSTOR_CSWCompletionRoutine: Urb.Hdr.Status - %x\n", Context->Urb.UrbHeader.Status);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("USBSTOR_CSWCompletionRoutine Status %x\n", Irp->IoStatus.Status);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Irp->IoStatus.Information))
|
|
||||||
{
|
|
||||||
if (Context->ErrorIndex == 0)
|
|
||||||
{
|
|
||||||
Context->ErrorIndex = 1;
|
|
||||||
|
|
||||||
// clear stall and resend cbw
|
|
||||||
Status = USBSTOR_QueueWorkItem(Context, Irp);
|
|
||||||
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
|
|
||||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// perform reset recovery
|
// perform reset recovery
|
||||||
Context->ErrorIndex = 2;
|
Context->ErrorIndex = 2;
|
||||||
IoFreeIrp(Irp);
|
|
||||||
Status = USBSTOR_QueueWorkItem(Context, NULL);
|
Status = USBSTOR_QueueWorkItem(Context, NULL);
|
||||||
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
|
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
|
||||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!USBSTOR_IsCSWValid(Context))
|
// now check the CSW packet validity
|
||||||
|
if (!USBSTOR_IsCSWValid(Context) || Context->csw->Status == CSW_STATUS_PHASE_ERROR)
|
||||||
{
|
{
|
||||||
// perform reset recovery
|
// perform reset recovery
|
||||||
Context->ErrorIndex = 2;
|
Context->ErrorIndex = 2;
|
||||||
IoFreeIrp(Irp);
|
|
||||||
Status = USBSTOR_QueueWorkItem(Context, NULL);
|
Status = USBSTOR_QueueWorkItem(Context, NULL);
|
||||||
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
|
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
|
||||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Context->Irp);
|
Request = IoStack->Parameters.Scsi.Srb;
|
||||||
|
|
||||||
Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
|
|
||||||
ASSERT(Request);
|
ASSERT(Request);
|
||||||
|
|
||||||
Status = Irp->IoStatus.Status;
|
Status = Irp->IoStatus.Status;
|
||||||
|
|
||||||
pCDB = (PCDB)Request->Cdb;
|
// finally check for CSW errors
|
||||||
Request->SrbStatus = SRB_STATUS_SUCCESS;
|
if (Context->csw->Status == CSW_STATUS_COMMAND_PASSED)
|
||||||
|
|
||||||
// read capacity needs special work
|
|
||||||
if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
|
|
||||||
{
|
{
|
||||||
// get output buffer
|
// read capacity needs special work
|
||||||
Response = (PUFI_CAPACITY_RESPONSE)Context->TransferData;
|
if (Request->Cdb[0] == SCSIOP_READ_CAPACITY)
|
||||||
|
{
|
||||||
|
// get output buffer
|
||||||
|
Response = (PUFI_CAPACITY_RESPONSE)Context->TransferData;
|
||||||
|
|
||||||
// store in pdo
|
// store in pdo
|
||||||
Context->PDODeviceExtension->BlockLength = NTOHL(Response->BlockLength);
|
Context->PDODeviceExtension->BlockLength = NTOHL(Response->BlockLength);
|
||||||
Context->PDODeviceExtension->LastLogicBlockAddress = NTOHL(Response->LastLogicalBlockAddress);
|
Context->PDODeviceExtension->LastLogicBlockAddress = NTOHL(Response->LastLogicalBlockAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
Request->SrbStatus = SRB_STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = Request->DataTransferLength;
|
||||||
|
}
|
||||||
|
else if (Context->csw->Status == CSW_STATUS_COMMAND_FAILED)
|
||||||
|
{
|
||||||
|
DPRINT("USBSTOR_CSWCompletionRoutine: CSW_STATUS_COMMAND_FAILED\n");
|
||||||
|
// perform reset recovery
|
||||||
|
Context->ErrorIndex = 2;
|
||||||
|
Status = USBSTOR_QueueWorkItem(Context, NULL);
|
||||||
|
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
|
||||||
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeItem(Context->cbw);
|
FreeItem(Context->cbw);
|
||||||
|
|
||||||
// FIXME: check status
|
|
||||||
Context->Irp->IoStatus.Status = Irp->IoStatus.Status;
|
|
||||||
Context->Irp->IoStatus.Information = Context->TransferDataLength;
|
|
||||||
|
|
||||||
// terminate current request
|
// terminate current request
|
||||||
USBSTOR_QueueTerminateRequest(Context->PDODeviceExtension->LowerDeviceObject, Context->Irp);
|
USBSTOR_QueueTerminateRequest(Context->PDODeviceExtension->LowerDeviceObject, Irp);
|
||||||
|
|
||||||
IoCompleteRequest(Context->Irp, IO_NO_INCREMENT);
|
|
||||||
|
|
||||||
USBSTOR_QueueNextRequest(Context->PDODeviceExtension->LowerDeviceObject);
|
USBSTOR_QueueNextRequest(Context->PDODeviceExtension->LowerDeviceObject);
|
||||||
|
|
||||||
IoFreeIrp(Irp);
|
|
||||||
FreeItem(Context);
|
FreeItem(Context);
|
||||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -406,7 +401,6 @@ USBSTOR_SendRequest(
|
||||||
PIRP_CONTEXT Context;
|
PIRP_CONTEXT Context;
|
||||||
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||||
PIRP Irp;
|
|
||||||
PUCHAR MdlVirtualAddress;
|
PUCHAR MdlVirtualAddress;
|
||||||
|
|
||||||
Context = USBSTOR_AllocateIrpContext();
|
Context = USBSTOR_AllocateIrpContext();
|
||||||
|
@ -450,50 +444,34 @@ USBSTOR_SendRequest(
|
||||||
if (Context->TransferDataLength)
|
if (Context->TransferDataLength)
|
||||||
{
|
{
|
||||||
// check if the original request already does have an mdl associated
|
// check if the original request already does have an mdl associated
|
||||||
if (OriginalRequest)
|
if ((OriginalRequest->MdlAddress != NULL) &&
|
||||||
|
(Context->TransferData == NULL || Command[0] == SCSIOP_READ || Command[0] == SCSIOP_WRITE))
|
||||||
{
|
{
|
||||||
if ((OriginalRequest->MdlAddress != NULL) &&
|
// Sanity check that the Mdl does describe the TransferData for read/write
|
||||||
(Context->TransferData == NULL || Command[0] == SCSIOP_READ || Command[0] == SCSIOP_WRITE))
|
if (CommandLength == UFI_READ_WRITE_CMD_LEN)
|
||||||
{
|
{
|
||||||
// Sanity check that the Mdl does describe the TransferData for read/write
|
MdlVirtualAddress = MmGetMdlVirtualAddress(OriginalRequest->MdlAddress);
|
||||||
if (CommandLength == UFI_READ_WRITE_CMD_LEN)
|
|
||||||
{
|
|
||||||
MdlVirtualAddress = MmGetMdlVirtualAddress(OriginalRequest->MdlAddress);
|
|
||||||
|
|
||||||
// is there an offset
|
// is there an offset
|
||||||
if (MdlVirtualAddress != Context->TransferData)
|
if (MdlVirtualAddress != Context->TransferData)
|
||||||
|
{
|
||||||
|
// lets build an mdl
|
||||||
|
Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, MmGetMdlByteCount(OriginalRequest->MdlAddress), FALSE, FALSE, NULL);
|
||||||
|
if (!Context->TransferBufferMDL)
|
||||||
{
|
{
|
||||||
// lets build an mdl
|
FreeItem(Context->cbw);
|
||||||
Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, MmGetMdlByteCount(OriginalRequest->MdlAddress), FALSE, FALSE, NULL);
|
FreeItem(Context);
|
||||||
if (!Context->TransferBufferMDL)
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
{
|
|
||||||
FreeItem(Context->cbw);
|
|
||||||
FreeItem(Context);
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
IoBuildPartialMdl(OriginalRequest->MdlAddress, Context->TransferBufferMDL, Context->TransferData, Context->TransferDataLength);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!Context->TransferBufferMDL)
|
IoBuildPartialMdl(OriginalRequest->MdlAddress, Context->TransferBufferMDL, Context->TransferData, Context->TransferDataLength);
|
||||||
{
|
|
||||||
// I/O paging request
|
|
||||||
Context->TransferBufferMDL = OriginalRequest->MdlAddress;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// allocate mdl for buffer, buffer must be allocated from NonPagedPool
|
|
||||||
Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, Context->TransferDataLength, FALSE, FALSE, NULL);
|
|
||||||
if (!Context->TransferBufferMDL)
|
|
||||||
{
|
|
||||||
FreeItem(Context->cbw);
|
|
||||||
FreeItem(Context);
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
MmBuildMdlForNonPagedPool(Context->TransferBufferMDL);
|
if (!Context->TransferBufferMDL)
|
||||||
|
{
|
||||||
|
// I/O paging request
|
||||||
|
Context->TransferBufferMDL = OriginalRequest->MdlAddress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -511,22 +489,7 @@ USBSTOR_SendRequest(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
return USBSTOR_SendCBW(Context, OriginalRequest);
|
||||||
if (!Irp)
|
|
||||||
{
|
|
||||||
FreeItem(Context->cbw);
|
|
||||||
FreeItem(Context);
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (OriginalRequest)
|
|
||||||
{
|
|
||||||
IoMarkIrpPending(OriginalRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
USBSTOR_SendCBW(Context, Irp);
|
|
||||||
|
|
||||||
return STATUS_PENDING;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -105,6 +105,10 @@ C_ASSERT(sizeof(CBW) == 31);
|
||||||
|
|
||||||
#define MAX_LUN 0xF
|
#define MAX_LUN 0xF
|
||||||
|
|
||||||
|
#define CSW_STATUS_COMMAND_PASSED 0x00
|
||||||
|
#define CSW_STATUS_COMMAND_FAILED 0x01
|
||||||
|
#define CSW_STATUS_PHASE_ERROR 0x02
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
ULONG Signature; // CSW signature
|
ULONG Signature; // CSW signature
|
||||||
|
|
Loading…
Reference in a new issue