* COPYRIGHT: 2005-2006 James Tabor
* 2011-2012 Michael Martin (michael.martin@reactos.org)
* 2011-2013 Johannes Anderwald (johannes.anderwald@reactos.org)
+ * 2017 Vadim Galyant
+ * 2019 Victor Perevertkin (victor.perevertkin@reactos.org)
*/
#include "usbstor.h"
#include <debug.h>
+static
NTSTATUS
-USBSTOR_BuildCBW(
- IN ULONG Tag,
- IN ULONG DataTransferLength,
- IN UCHAR LUN,
- IN UCHAR CommandBlockLength,
- IN PUCHAR CommandBlock,
- IN OUT PCBW Control)
+USBSTOR_SrbStatusToNtStatus(
+ IN PSCSI_REQUEST_BLOCK Srb)
{
- ASSERT(CommandBlockLength <= 16);
+ UCHAR SrbStatus;
- Control->Signature = CBW_SIGNATURE;
- Control->Tag = Tag;
- Control->DataTransferLength = DataTransferLength;
- Control->Flags = (CommandBlock[0] != SCSIOP_WRITE) ? 0x80 : 0x00;
- Control->LUN = (LUN & MAX_LUN);
- Control->CommandBlockLength = CommandBlockLength;
+ SrbStatus = SRB_STATUS(Srb->SrbStatus);
- RtlCopyMemory(Control->CommandBlock, CommandBlock, CommandBlockLength);
+ switch (SrbStatus)
+ {
+ case SRB_STATUS_SUCCESS:
+ return STATUS_SUCCESS;
+
+ case SRB_STATUS_DATA_OVERRUN:
+ return STATUS_BUFFER_OVERFLOW;
+
+ case SRB_STATUS_BAD_FUNCTION:
+ case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:
+ return STATUS_INVALID_DEVICE_REQUEST;
+
+ case SRB_STATUS_INVALID_LUN:
+ case SRB_STATUS_INVALID_TARGET_ID:
+ case SRB_STATUS_NO_HBA:
+ case SRB_STATUS_NO_DEVICE:
+ return STATUS_DEVICE_DOES_NOT_EXIST;
+
+ case SRB_STATUS_TIMEOUT:
+ return STATUS_IO_TIMEOUT;
+
+ case SRB_STATUS_BUS_RESET:
+ case SRB_STATUS_COMMAND_TIMEOUT:
+ case SRB_STATUS_SELECTION_TIMEOUT:
+ return STATUS_DEVICE_NOT_CONNECTED;
- return STATUS_SUCCESS;
+ default:
+ return STATUS_IO_DEVICE_ERROR;
+ }
}
-PIRP_CONTEXT
-USBSTOR_AllocateIrpContext()
+static
+NTSTATUS
+USBSTOR_IssueBulkOrInterruptRequest(
+ IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
+ IN PIRP Irp,
+ IN USBD_PIPE_HANDLE PipeHandle,
+ IN ULONG TransferFlags,
+ IN ULONG TransferBufferLength,
+ IN PVOID TransferBuffer,
+ IN PMDL TransferBufferMDL,
+ IN PIO_COMPLETION_ROUTINE CompletionRoutine,
+ IN PIRP_CONTEXT Context)
{
- PIRP_CONTEXT Context;
+ PIO_STACK_LOCATION NextStack;
- Context = (PIRP_CONTEXT)AllocateItem(NonPagedPool, sizeof(IRP_CONTEXT));
- if (!Context)
- {
- return NULL;
- }
+ RtlZeroMemory(&Context->Urb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
- Context->cbw = (PCBW)AllocateItem(NonPagedPool, 512);
- if (!Context->cbw)
- {
- FreeItem(Context);
- return NULL;
- }
+ Context->Urb.UrbHeader.Length = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
+ Context->Urb.UrbHeader.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
+
+ Context->Urb.UrbBulkOrInterruptTransfer.PipeHandle = PipeHandle;
+ Context->Urb.UrbBulkOrInterruptTransfer.TransferFlags = TransferFlags;
+ Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength = TransferBufferLength;
+ Context->Urb.UrbBulkOrInterruptTransfer.TransferBuffer = TransferBuffer;
+ Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferMDL = TransferBufferMDL;
+
+ NextStack = IoGetNextIrpStackLocation(Irp);
+ NextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+ NextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
+ NextStack->Parameters.Others.Argument1 = &Context->Urb;
+
+ IoSetCompletionRoutine(Irp,
+ CompletionRoutine,
+ Context,
+ TRUE,
+ TRUE,
+ TRUE);
- return Context;
+ return IoCallDriver(FDODeviceExtension->LowerDeviceObject, Irp);
}
+static
BOOLEAN
USBSTOR_IsCSWValid(
PIRP_CONTEXT Context)
{
- if (Context->csw->Signature != CSW_SIGNATURE)
+ if (Context->csw.Signature != CSW_SIGNATURE)
{
- DPRINT1("[USBSTOR] Expected Signature %x but got %x\n", CSW_SIGNATURE, Context->csw->Signature);
+ DPRINT1("[USBSTOR] Expected Signature %x but got %x\n", CSW_SIGNATURE, Context->csw.Signature);
return FALSE;
}
- if (Context->csw->Tag != (ULONG_PTR)Context->csw)
+ if (Context->csw.Tag != PtrToUlong(&Context->csw))
{
- DPRINT1("[USBSTOR] Expected Tag %Ix but got %x\n", (ULONG_PTR)Context->csw, Context->csw->Tag);
- return FALSE;
- }
-
- if (Context->csw->Status != 0x00)
- {
- DPRINT1("[USBSTOR] Expected Status 0x00 but got %x\n", Context->csw->Status);
+ DPRINT1("[USBSTOR] Expected Tag %Ix but got %x\n", PtrToUlong(&Context->csw), Context->csw.Tag);
return FALSE;
}
return STATUS_MORE_PROCESSING_REQUIRED;
}
+static
+NTSTATUS
+USBSTOR_IssueRequestSense(
+ IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
+ IN PIRP Irp,
+ IN PIRP_CONTEXT Context);
+
IO_COMPLETION_ROUTINE USBSTOR_CSWCompletionRoutine;
NTSTATUS
{
PIRP_CONTEXT Context;
PIO_STACK_LOCATION IoStack;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
PSCSI_REQUEST_BLOCK Request;
- PCDB pCDB;
PUFI_CAPACITY_RESPONSE Response;
NTSTATUS Status;
Context = (PIRP_CONTEXT)Ctx;
- if (Context->TransferBufferMDL)
+ 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))
{
- // is there an irp associated
- if (Context->Irp)
+ if (USBD_STATUS(Context->Urb.UrbHeader.Status) == USBD_STATUS(USBD_STATUS_STALL_PID))
{
- // did we allocate the mdl
- if (Context->TransferBufferMDL != Context->Irp->MdlAddress)
+ if (Context->StallRetryCount < 2)
{
- IoFreeMdl(Context->TransferBufferMDL);
+ ++Context->StallRetryCount;
+
+ // clear stall and resend cbw
+ Context->ErrorIndex = 1;
+ Status = USBSTOR_QueueWorkItem(Context, Irp);
+ ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
+
+ return STATUS_MORE_PROCESSING_REQUIRED;
}
}
else
{
- IoFreeMdl(Context->TransferBufferMDL);
- }
- }
-
- 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;
+ DPRINT1("USBSTOR_CSWCompletionRoutine: Urb.Hdr.Status - %x\n", Context->Urb.UrbHeader.Status);
}
// perform reset recovery
Context->ErrorIndex = 2;
- IoFreeIrp(Irp);
Status = USBSTOR_QueueWorkItem(Context, NULL);
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
return STATUS_MORE_PROCESSING_REQUIRED;
}
- if (!USBSTOR_IsCSWValid(Context))
+ // now check the CSW packet validity
+ if (!USBSTOR_IsCSWValid(Context) || Context->csw.Status == CSW_STATUS_PHASE_ERROR)
{
// perform reset recovery
Context->ErrorIndex = 2;
- IoFreeIrp(Irp);
Status = USBSTOR_QueueWorkItem(Context, NULL);
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
return STATUS_MORE_PROCESSING_REQUIRED;
}
-
- IoStack = IoGetCurrentIrpStackLocation(Context->Irp);
-
- Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
+ FDODeviceExtension = Context->FDODeviceExtension;
+ Request = IoStack->Parameters.Scsi.Srb;
ASSERT(Request);
- Status = Irp->IoStatus.Status;
+ // finally check for CSW errors
+ if (Context->csw.Status == CSW_STATUS_COMMAND_PASSED)
+ {
+ // should happen only when a sense request was sent
+ if (Request != FDODeviceExtension->ActiveSrb)
+ {
+ ASSERT(IoStack->Parameters.Scsi.Srb == &Context->SenseSrb);
+ FDODeviceExtension->ActiveSrb->SenseInfoBufferLength = Request->DataTransferLength;
+ Request = FDODeviceExtension->ActiveSrb;
+ IoStack->Parameters.Scsi.Srb = Request;
+ Request->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
+ }
+
+ // read capacity needs special work
+ if (Request->Cdb[0] == SCSIOP_READ_CAPACITY)
+ {
+ // get output buffer
+ Response = (PUFI_CAPACITY_RESPONSE)Request->DataBuffer;
- pCDB = (PCDB)Request->Cdb;
- Request->SrbStatus = SRB_STATUS_SUCCESS;
+ // store in pdo
+ PDODeviceExtension->BlockLength = NTOHL(Response->BlockLength);
+ PDODeviceExtension->LastLogicBlockAddress = NTOHL(Response->LastLogicalBlockAddress);
+ }
- // read capacity needs special work
- if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
+ Status = USBSTOR_SrbStatusToNtStatus(Request);
+ }
+ else if (Context->csw.Status == CSW_STATUS_COMMAND_FAILED)
{
- // get output buffer
- Response = (PUFI_CAPACITY_RESPONSE)Context->TransferData;
+ // the command is correct but with failed status - issue request sense
+ DPRINT("USBSTOR_CSWCompletionRoutine: CSW_STATUS_COMMAND_FAILED\n");
+
+ ASSERT(FDODeviceExtension->ActiveSrb == Request);
+
+ // setting a generic error status, additional information
+ // should be read by higher-level driver from SenseInfoBuffer
+ Request->SrbStatus = SRB_STATUS_ERROR;
+ Request->ScsiStatus = 2;
+ Request->DataTransferLength = 0;
+
+ DPRINT("Flags: %x SBL: %x, buf: %p\n", Request->SrbFlags, Request->SenseInfoBufferLength, Request->SenseInfoBuffer);
+
+ if (!(Request->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) &&
+ Request->SenseInfoBufferLength &&
+ Request->SenseInfoBuffer)
+ {
+ USBSTOR_IssueRequestSense(FDODeviceExtension, Irp, Context);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+ }
- // store in pdo
- Context->PDODeviceExtension->BlockLength = NTOHL(Response->BlockLength);
- Context->PDODeviceExtension->LastLogicBlockAddress = NTOHL(Response->LastLogicalBlockAddress);
+ Status = STATUS_IO_DEVICE_ERROR;
}
- FreeItem(Context->cbw);
-
- // FIXME: check status
- Context->Irp->IoStatus.Status = Irp->IoStatus.Status;
- Context->Irp->IoStatus.Information = Context->TransferDataLength;
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = Request->DataTransferLength;
// terminate current request
- USBSTOR_QueueTerminateRequest(Context->PDODeviceExtension->LowerDeviceObject, Context->Irp);
-
- IoCompleteRequest(Context->Irp, IO_NO_INCREMENT);
-
- USBSTOR_QueueNextRequest(Context->PDODeviceExtension->LowerDeviceObject);
+ USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
+ USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject);
- IoFreeIrp(Irp);
- FreeItem(Context);
- return STATUS_MORE_PROCESSING_REQUIRED;
+ ExFreePoolWithTag(Context, USB_STOR_TAG);
+ return Status;
}
-VOID
-USBSTOR_SendCSW(
+NTSTATUS
+USBSTOR_SendCSWRequest(
PIRP_CONTEXT Context,
PIRP Irp)
{
- PIO_STACK_LOCATION IoStack;
-
- IoStack = IoGetNextIrpStackLocation(Irp);
-
- // now initialize the urb for sending the csw
- UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
- sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
- Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle,
- Context->csw,
- NULL,
- 512, //FIXME
- USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
- NULL);
-
- // initialize stack location
- IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
- IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
- IoStack->Parameters.Others.Argument1 = (PVOID)&Context->Urb;
- IoStack->Parameters.DeviceIoControl.InputBufferLength = Context->Urb.UrbHeader.Length;
- Irp->IoStatus.Status = STATUS_SUCCESS;
-
- IoSetCompletionRoutine(Irp, USBSTOR_CSWCompletionRoutine, Context, TRUE, TRUE, TRUE);
-
- IoCallDriver(Context->FDODeviceExtension->LowerDeviceObject, Irp);
+ return USBSTOR_IssueBulkOrInterruptRequest(Context->FDODeviceExtension,
+ Irp,
+ Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle,
+ USBD_TRANSFER_DIRECTION_IN,
+ sizeof(CSW),
+ &Context->csw,
+ NULL,
+ USBSTOR_CSWCompletionRoutine,
+ Context);
}
IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine;
{
PIRP_CONTEXT Context;
NTSTATUS Status;
-
+ PIO_STACK_LOCATION IoStack;
+ PSCSI_REQUEST_BLOCK Request;
DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
Context = (PIRP_CONTEXT)Ctx;
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+ Request = IoStack->Parameters.Scsi.Srb;
- if (!NT_SUCCESS(Irp->IoStatus.Status))
+ // for Sense Request a partial MDL was already freed (if existed)
+ if (Request == Context->FDODeviceExtension->ActiveSrb &&
+ Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferMDL != Irp->MdlAddress)
+ {
+ IoFreeMdl(Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferMDL);
+ }
+
+ if (NT_SUCCESS(Irp->IoStatus.Status))
{
+ if (Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength < Request->DataTransferLength)
+ {
+ Request->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+ }
+ else
+ {
+ Request->SrbStatus = SRB_STATUS_SUCCESS;
+ }
+
+ Request->DataTransferLength = Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength;
+ USBSTOR_SendCSWRequest(Context, Irp);
+ }
+ else if (USBD_STATUS(Context->Urb.UrbHeader.Status) == USBD_STATUS(USBD_STATUS_STALL_PID))
+ {
+ ++Context->StallRetryCount;
+
+ Request->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+ Request->DataTransferLength = Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength;
+
// clear stall and resend cbw
Context->ErrorIndex = 1;
Status = USBSTOR_QueueWorkItem(Context, Irp);
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
- return STATUS_MORE_PROCESSING_REQUIRED;
}
-
- USBSTOR_SendCSW(Context, Irp);
+ else
+ {
+ // perform reset recovery
+ Context->ErrorIndex = 2;
+ Status = USBSTOR_QueueWorkItem(Context, NULL);
+ ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
+ }
return STATUS_MORE_PROCESSING_REQUIRED;
}
{
PIRP_CONTEXT Context;
PIO_STACK_LOCATION IoStack;
- UCHAR Code;
+ PSCSI_REQUEST_BLOCK Request;
USBD_PIPE_HANDLE PipeHandle;
+ ULONG TransferFlags;
+ PMDL Mdl = NULL;
+ PVOID TransferBuffer = NULL;
+ NTSTATUS Status;
DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
Context = (PIRP_CONTEXT)Ctx;
- IoStack = IoGetNextIrpStackLocation(Irp);
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+ Request = IoStack->Parameters.Scsi.Srb;
- // is there data to be submitted
- if (Context->TransferDataLength)
+ if (!NT_SUCCESS(Irp->IoStatus.Status))
+ {
+ goto ResetRecovery;
+ }
+
+ // a request without the buffer AND not a sense request
+ // for a sense request we provide just a TransferBuffer, an Mdl will be allocated by usbport (see below)
+ if (!Irp->MdlAddress && Request == Context->FDODeviceExtension->ActiveSrb)
+ {
+ Request->SrbStatus = SRB_STATUS_SUCCESS;
+ USBSTOR_SendCSWRequest(Context, Irp);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+ }
+
+ // a request with the data buffer
+
+ if ((Request->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) == SRB_FLAGS_DATA_IN)
+ {
+ PipeHandle = Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle;
+ TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK;
+ }
+ else if ((Request->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) == SRB_FLAGS_DATA_OUT)
+ {
+ PipeHandle = Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkOutPipeIndex].PipeHandle;
+ TransferFlags = USBD_TRANSFER_DIRECTION_OUT;
+ }
+ else
{
- // get command code
- Code = Context->cbw->CommandBlock[0];
+ // we check the validity of a request in disk.c so we should never be here
+ DPRINT1("Warning: shouldn't be here\n");
+ goto ResetRecovery;
+ }
- if (Code == SCSIOP_WRITE)
+ // if it is not a Sense Request
+ if (Request == Context->FDODeviceExtension->ActiveSrb)
+ {
+ if (MmGetMdlVirtualAddress(Irp->MdlAddress) == Request->DataBuffer)
{
- // write request - use bulk out pipe
- PipeHandle = Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkOutPipeIndex].PipeHandle;
+ Mdl = Irp->MdlAddress;
}
else
{
- // default bulk in pipe
- PipeHandle = Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle;
+ Mdl = IoAllocateMdl(Request->DataBuffer,
+ Request->DataTransferLength,
+ FALSE,
+ FALSE,
+ NULL);
+
+ if (Mdl)
+ {
+ IoBuildPartialMdl(Irp->MdlAddress,
+ Mdl,
+ Request->DataBuffer,
+ Request->DataTransferLength);
+ }
}
- // now initialize the urb for sending data
- UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
- sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
- PipeHandle,
- NULL,
- Context->TransferBufferMDL,
- Context->TransferDataLength,
- ((Code == SCSIOP_WRITE) ? USBD_TRANSFER_DIRECTION_OUT : (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK)),
- NULL);
-
- IoSetCompletionRoutine(Irp, USBSTOR_DataCompletionRoutine, Context, TRUE, TRUE, TRUE);
+ if (!Mdl)
+ {
+ DPRINT1("USBSTOR_CBWCompletionRoutine: Mdl - %p\n", Mdl);
+ goto ResetRecovery;
+ }
}
else
{
- // now initialize the urb for sending the csw
- UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
- sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
- Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle,
- Context->csw,
- NULL,
- 512, //FIXME
- USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
- NULL);
+ TransferBuffer = Request->DataBuffer;
- IoSetCompletionRoutine(Irp, USBSTOR_CSWCompletionRoutine, Context, TRUE, TRUE, TRUE);
+ if (!Request->DataBuffer)
+ {
+ DPRINT("USBSTOR_CBWCompletionRoutine: Request->DataBuffer == NULL!\n");
+ return STATUS_INVALID_PARAMETER;
+ }
}
- // initialize stack location
- IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
- IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
- IoStack->Parameters.Others.Argument1 = (PVOID)&Context->Urb;
- IoStack->Parameters.DeviceIoControl.InputBufferLength = Context->Urb.UrbHeader.Length;
- Irp->IoStatus.Status = STATUS_SUCCESS;
+ USBSTOR_IssueBulkOrInterruptRequest(Context->FDODeviceExtension,
+ Irp,
+ PipeHandle,
+ TransferFlags,
+ Request->DataTransferLength,
+ TransferBuffer,
+ Mdl,
+ USBSTOR_DataCompletionRoutine,
+ Context);
- IoCallDriver(Context->FDODeviceExtension->LowerDeviceObject, Irp);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+ResetRecovery:
+ Context->ErrorIndex = 2;
+ Status = USBSTOR_QueueWorkItem(Context, NULL);
+ ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
return STATUS_MORE_PROCESSING_REQUIRED;
}
Block[10] & 0xFF, Block[11] & 0xFF, Block[12] & 0xFF, Block[13] & 0xFF, Block[14] & 0xFF, Block[15] & 0xFF, Block[16] & 0xFF, Block[17] & 0xFF, Block[18] & 0xFF, Block[19] & 0xFF,
Block[20] & 0xFF, Block[21] & 0xFF, Block[22] & 0xFF, Block[23] & 0xFF, Block[24] & 0xFF, Block[25] & 0xFF, Block[26] & 0xFF, Block[27] & 0xFF, Block[28] & 0xFF, Block[29] & 0xFF,
Block[30] & 0xFF);
-
}
+static
NTSTATUS
-USBSTOR_SendCBW(
- PIRP_CONTEXT Context,
- PIRP Irp)
+USBSTOR_SendCBWRequest(
+ IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
+ IN PIRP Irp,
+ IN PIRP_CONTEXT Context)
{
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
PIO_STACK_LOCATION IoStack;
+ PSCSI_REQUEST_BLOCK Request;
+
+ RtlZeroMemory(&Context->cbw, sizeof(CBW));
+ RtlZeroMemory(&Context->Urb, sizeof(URB));
+
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+ PDODeviceExtension = IoStack->DeviceObject->DeviceExtension;
+ Request = IoStack->Parameters.Scsi.Srb;
- IoStack = IoGetNextIrpStackLocation(Irp);
+ Context->cbw.Signature = CBW_SIGNATURE;
+ Context->cbw.Tag = PtrToUlong(&Context->cbw);
+ Context->cbw.DataTransferLength = Request->DataTransferLength;
+ Context->cbw.Flags = ((UCHAR)Request->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) << 1;
+ Context->cbw.LUN = PDODeviceExtension->LUN;
+ Context->cbw.CommandBlockLength = Request->CdbLength;
- // initialize stack location
- IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
- IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
- IoStack->Parameters.Others.Argument1 = (PVOID)&Context->Urb;
- IoStack->Parameters.DeviceIoControl.InputBufferLength = Context->Urb.UrbHeader.Length;
- Irp->IoStatus.Status = STATUS_SUCCESS;
+ RtlCopyMemory(&Context->cbw.CommandBlock, Request->Cdb, Request->CdbLength);
- IoSetCompletionRoutine(Irp, USBSTOR_CBWCompletionRoutine, Context, TRUE, TRUE, TRUE);
+ DPRINT("CBW for IRP %p\n", Irp);
+ DumpCBW((PUCHAR)&Context->cbw);
- return IoCallDriver(Context->FDODeviceExtension->LowerDeviceObject, Irp);
+ // initialize rest of context
+ Context->Irp = Irp;
+ Context->FDODeviceExtension = FDODeviceExtension;
+ Context->StallRetryCount = 0;
+
+ return USBSTOR_IssueBulkOrInterruptRequest(
+ FDODeviceExtension,
+ Irp,
+ FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle,
+ USBD_TRANSFER_DIRECTION_OUT,
+ sizeof(CBW),
+ &Context->cbw,
+ NULL,
+ USBSTOR_CBWCompletionRoutine,
+ Context);
}
+static
NTSTATUS
-USBSTOR_SendRequest(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP OriginalRequest,
- IN UCHAR CommandLength,
- IN PUCHAR Command,
- IN ULONG TransferDataLength,
- IN PUCHAR TransferData,
- IN ULONG RetryCount)
+USBSTOR_IssueRequestSense(
+ IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
+ IN PIRP Irp,
+ IN PIRP_CONTEXT Context)
{
- PIRP_CONTEXT Context;
- PPDO_DEVICE_EXTENSION PDODeviceExtension;
- PFDO_DEVICE_EXTENSION FDODeviceExtension;
- PIRP Irp;
- PUCHAR MdlVirtualAddress;
-
- Context = USBSTOR_AllocateIrpContext();
- if (!Context)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
+ PIO_STACK_LOCATION IoStack;
+ PSCSI_REQUEST_BLOCK CurrentSrb;
+ PSCSI_REQUEST_BLOCK SenseSrb;
+ PCDB pCDB;
- PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
- FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
-
- USBSTOR_BuildCBW(PtrToUlong(Context->cbw),
- TransferDataLength,
- PDODeviceExtension->LUN,
- CommandLength,
- Command,
- Context->cbw);
-
- DPRINT("CBW %p\n", Context->cbw);
- DumpCBW((PUCHAR)Context->cbw);
-
- // now initialize the urb
- UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
- sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
- FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle,
- Context->cbw,
- NULL,
- sizeof(CBW),
- USBD_TRANSFER_DIRECTION_OUT,
- NULL);
+ DPRINT("USBSTOR_IssueRequestSense: \n");
- // initialize rest of context
- Context->Irp = OriginalRequest;
- Context->TransferData = TransferData;
- Context->TransferDataLength = TransferDataLength;
- Context->FDODeviceExtension = FDODeviceExtension;
- Context->PDODeviceExtension = PDODeviceExtension;
- Context->RetryCount = RetryCount;
+ CurrentSrb = FDODeviceExtension->ActiveSrb;
+ SenseSrb = &Context->SenseSrb;
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+ IoStack->Parameters.Scsi.Srb = SenseSrb;
- // is there transfer data
- if (Context->TransferDataLength)
- {
- // check if the original request already does have an mdl associated
- if (OriginalRequest)
- {
- if ((OriginalRequest->MdlAddress != NULL) &&
- (Context->TransferData == NULL || Command[0] == SCSIOP_READ || Command[0] == SCSIOP_WRITE))
- {
- // Sanity check that the Mdl does describe the TransferData for read/write
- if (CommandLength == UFI_READ_WRITE_CMD_LEN)
- {
- MdlVirtualAddress = MmGetMdlVirtualAddress(OriginalRequest->MdlAddress);
-
- // is there an offset
- if (MdlVirtualAddress != Context->TransferData)
- {
- // lets build an mdl
- Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, MmGetMdlByteCount(OriginalRequest->MdlAddress), FALSE, FALSE, NULL);
- if (!Context->TransferBufferMDL)
- {
- FreeItem(Context->cbw);
- FreeItem(Context);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- IoBuildPartialMdl(OriginalRequest->MdlAddress, Context->TransferBufferMDL, Context->TransferData, Context->TransferDataLength);
- }
- }
-
- if (!Context->TransferBufferMDL)
- {
- // I/O paging request
- Context->TransferBufferMDL = OriginalRequest->MdlAddress;
- }
- }
- else
- {
- // allocate mdl for buffer, buffer must be allocated from NonPagedPool
- Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, Context->TransferDataLength, FALSE, FALSE, NULL);
- if (!Context->TransferBufferMDL)
- {
- FreeItem(Context->cbw);
- FreeItem(Context);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- MmBuildMdlForNonPagedPool(Context->TransferBufferMDL);
- }
- }
- else
- {
- // allocate mdl for buffer, buffer must be allocated from NonPagedPool
- Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, Context->TransferDataLength, FALSE, FALSE, NULL);
- if (!Context->TransferBufferMDL)
- {
- FreeItem(Context->cbw);
- FreeItem(Context);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
+ RtlZeroMemory(SenseSrb, sizeof(*SenseSrb));
- MmBuildMdlForNonPagedPool(Context->TransferBufferMDL);
- }
- }
+ SenseSrb->Function = SRB_FUNCTION_EXECUTE_SCSI;
+ SenseSrb->Length = sizeof(*SenseSrb);
+ SenseSrb->CdbLength = CDB6GENERIC_LENGTH;
+ SenseSrb->SrbFlags = SRB_FLAGS_DATA_IN |
+ SRB_FLAGS_NO_QUEUE_FREEZE |
+ SRB_FLAGS_DISABLE_AUTOSENSE;
- Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
- if (!Irp)
- {
- FreeItem(Context->cbw);
- FreeItem(Context);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
+ ASSERT(CurrentSrb->SenseInfoBufferLength);
+ ASSERT(CurrentSrb->SenseInfoBuffer);
+ DPRINT("SenseInfoBuffer %x, SenseInfoBufferLength %x\n", CurrentSrb->SenseInfoBuffer, CurrentSrb->SenseInfoBufferLength);
- if (OriginalRequest)
- {
- IoMarkIrpPending(OriginalRequest);
- }
+ SenseSrb->DataTransferLength = CurrentSrb->SenseInfoBufferLength;
+ SenseSrb->DataBuffer = CurrentSrb->SenseInfoBuffer;
- USBSTOR_SendCBW(Context, Irp);
+ pCDB = (PCDB)SenseSrb->Cdb;
+ pCDB->CDB6GENERIC.OperationCode = SCSIOP_REQUEST_SENSE;
+ pCDB->AsByte[4] = CurrentSrb->SenseInfoBufferLength;
- return STATUS_PENDING;
+ return USBSTOR_SendCBWRequest(FDODeviceExtension, Irp, Context);
}
NTSTATUS
USBSTOR_HandleExecuteSCSI(
IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp,
- IN ULONG RetryCount)
+ IN PIRP Irp)
{
PCDB pCDB;
NTSTATUS Status;
PIO_STACK_LOCATION IoStack;
PSCSI_REQUEST_BLOCK Request;
PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PIRP_CONTEXT Context;
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
// check that we're sending to the right LUN
ASSERT(pCDB->CDB10.LogicalUnitNumber == (PDODeviceExtension->LUN & MAX_LUN));
- Status = USBSTOR_SendRequest(DeviceObject, Irp, Request->CdbLength, (PUCHAR)pCDB, Request->DataTransferLength, Request->DataBuffer, RetryCount);
+ Context = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRP_CONTEXT), USB_STOR_TAG);
+
+ if (!Context)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ Status = USBSTOR_SendCBWRequest(PDODeviceExtension->LowerDeviceObject->DeviceExtension, Irp, Context);
+ }
return Status;
}