PREAD_CAPACITY_DATA_EX CapacityDataEx;
PREAD_CAPACITY_DATA CapacityData;
PUFI_CAPACITY_RESPONSE Response;
+ PERRORHANDLER_WORKITEM_DATA ErrorHandlerWorkItemData;
+ NTSTATUS Status;
+ PURB Urb;
- DPRINT1("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p\n", Irp, Ctx);
+ DPRINT("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p\n", Irp, Ctx);
//
// access context
Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
ASSERT(Request);
- //
- // FIXME: check status
- //
- Request->SrbStatus = SRB_STATUS_SUCCESS;
+ Status = Irp->IoStatus.Status;
+
+ Urb = &Context->Urb;
//
// get SCSI command data block
//
pCDB = (PCDB)Request->Cdb;
+ //
+ // check status
+ //
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Status %x\n", Status);
+ DPRINT1("UrbStatus %x\n", Urb->UrbHeader.Status);
+
+ //
+ // Check for errors that can be handled
+ // FIXME: Verify all usb errors that can be recovered via pipe reset/port reset/controller reset
+ //
+ if ((Urb->UrbHeader.Status & USB_RECOVERABLE_ERRORS) == Urb->UrbHeader.Status)
+ {
+ DPRINT1("Attempting Error Recovery\n");
+ //
+ // free the allocated irp
+ //
+ IoFreeIrp(Irp);
+
+ //
+ // Allocate Work Item Data
+ //
+ ErrorHandlerWorkItemData = ExAllocatePoolWithTag(NonPagedPool, sizeof(ERRORHANDLER_WORKITEM_DATA), USB_STOR_TAG);
+ if (!ErrorHandlerWorkItemData)
+ {
+ DPRINT1("Failed to allocate memory\n");
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ //
+ // Initialize and queue the work item to handle the error
+ //
+ ExInitializeWorkItem(&ErrorHandlerWorkItemData->WorkQueueItem,
+ ErrorHandlerWorkItemRoutine,
+ ErrorHandlerWorkItemData);
+
+ ErrorHandlerWorkItemData->DeviceObject = Context->FDODeviceExtension->FunctionalDeviceObject;
+ ErrorHandlerWorkItemData->Context = Context;
+ DPRINT1("Queuing WorkItemROutine\n");
+ ExQueueWorkItem(&ErrorHandlerWorkItemData->WorkQueueItem, DelayedWorkQueue);
+
+ return STATUS_MORE_PROCESSING_REQUIRED;
+ }
+ }
+ }
+
+ Request->SrbStatus = SRB_STATUS_SUCCESS;
+
//
// read capacity needs special work
//
Context->Irp->IoStatus.Status = Irp->IoStatus.Status;
Context->Irp->IoStatus.Information = Context->TransferDataLength;
+ //
+ // terminate current request
+ //
+ USBSTOR_QueueTerminateRequest(Context->PDODeviceExtension->LowerDeviceObject, Context->Irp);
+
//
// complete request
//
IoCompleteRequest(Context->Irp, IO_NO_INCREMENT);
+
+ //
+ // start next request
+ //
+ USBSTOR_QueueNextRequest(Context->PDODeviceExtension->LowerDeviceObject);
}
if (Context->Event)
KeSetEvent(Context->Event, 0, FALSE);
}
+ //
+ // free our allocated irp
+ //
+ IoFreeIrp(Irp);
//
// free context
PIRP_CONTEXT Context;
PIO_STACK_LOCATION IoStack;
- DPRINT1("USBSTOR_DataCompletionRoutine Irp %p Ctx %p\n", Irp, Ctx);
+ DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p\n", Irp, Ctx);
//
// access context
UCHAR Code;
USBD_PIPE_HANDLE PipeHandle;
- DPRINT1("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p\n", Irp, Ctx);
+ DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p\n", Irp, Ctx);
//
// access context
NULL,
Context->TransferBufferMDL,
Context->TransferDataLength,
- USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
+ ((Code == SCSIOP_WRITE) ? USBD_TRANSFER_DIRECTION_OUT : USBD_TRANSFER_DIRECTION_IN) | USBD_SHORT_TRANSFER_OK,
NULL);
//
IN PDEVICE_OBJECT DeviceObject,
IN PIRP OriginalRequest,
IN OPTIONAL PKEVENT Event,
- IN ULONG CommandLength,
+ IN UCHAR CommandLength,
IN PUCHAR Command,
IN ULONG TransferDataLength,
IN PUCHAR TransferData)
PFDO_DEVICE_EXTENSION FDODeviceExtension;
PIRP Irp;
PIO_STACK_LOCATION IoStack;
+ PUCHAR MdlVirtualAddress;
//
// first allocate irp context
if (Context->TransferDataLength)
{
//
- // check if the original request already does not have an mdl associated
+ // check if the original request already does have an mdl associated
//
if (OriginalRequest)
{
- if (OriginalRequest->MdlAddress != NULL && Context->TransferData == NULL)
+ if ((OriginalRequest->MdlAddress != NULL) &&
+ (Context->TransferData == NULL || Command[0] == SCSIOP_READ || Command[0] == SCSIOP_WRITE))
{
//
- // I/O paging request
+ // Sanity check that the Mdl does describe the TransferData for read/write
//
- Context->TransferBufferMDL = OriginalRequest->MdlAddress;
+ if (CommandLength == UFI_READ_WRITE_CMD_LEN)
+ {
+ MdlVirtualAddress = MmGetMdlVirtualAddress(OriginalRequest->MdlAddress);
+
+ //
+ // is there an offset
+ //
+ if (MdlVirtualAddress != Context->TransferData)
+ {
+ //
+ // lets build an mdl
+ //
+ Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, MmGetMdlByteCount(OriginalRequest->MdlAddress), FALSE, FALSE, NULL);
+ if (!Context->TransferBufferMDL)
+ {
+ //
+ // failed to allocate MDL
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // now build the partial mdl
+ //
+ IoBuildPartialMdl(OriginalRequest->MdlAddress, Context->TransferBufferMDL, Context->TransferData, Context->TransferDataLength);
+ }
+ }
+
+ if (!Context->TransferBufferMDL)
+ {
+ //
+ // I/O paging request
+ //
+ Context->TransferBufferMDL = OriginalRequest->MdlAddress;
+ }
}
else
{
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
+#if 0
UFI_SENSE_CMD Cmd;
NTSTATUS Status;
PVOID Response;
- PPDO_DEVICE_EXTENSION PDODeviceExtension;
PCBW OutControl;
PCDB pCDB;
PUFI_MODE_PARAMETER_HEADER Header;
-
+#endif
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
PIO_STACK_LOCATION IoStack;
PSCSI_REQUEST_BLOCK Request;
+ //
+ // get PDO device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+
//
// get current stack location
//
Request->SrbStatus = SRB_STATUS_SUCCESS;
Irp->IoStatus.Information = Request->DataTransferLength;
Irp->IoStatus.Status = STATUS_SUCCESS;
+ USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ //
+ // start next request
+ //
+ USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject);
+
return STATUS_SUCCESS;
#if 0
IN PIRP Irp)
{
UFI_READ_WRITE_CMD Cmd;
- NTSTATUS Status;
PPDO_DEVICE_EXTENSION PDODeviceExtension;
PCDB pCDB;
ULONG BlockCount;
PIO_STACK_LOCATION IoStack;
PSCSI_REQUEST_BLOCK Request;
- PVOID Buffer;
//
// get current stack location
//
// informal debug print
//
- DPRINT1("USBSTOR_SendReadWriteCmd DataTransferLength %x, BlockLength %x\n", Request->DataTransferLength, PDODeviceExtension->BlockLength);
+ DPRINT("USBSTOR_SendReadWriteCmd DataTransferLength %lu, BlockLength %lu\n", Request->DataTransferLength, PDODeviceExtension->BlockLength);
//
// sanity check
RtlZeroMemory(&Cmd, sizeof(UFI_READ_WRITE_CMD));
Cmd.Code = pCDB->AsByte[0];
Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
- Cmd.ContiguousLogicBlocks = _byteswap_ushort(BlockCount);
+ Cmd.ContiguousLogicBlocksByte0 = pCDB->CDB10.TransferBlocksMsb;
+ Cmd.ContiguousLogicBlocksByte1 = pCDB->CDB10.TransferBlocksLsb;
Cmd.LogicalBlockByte0 = pCDB->CDB10.LogicalBlockByte0;
Cmd.LogicalBlockByte1 = pCDB->CDB10.LogicalBlockByte1;
Cmd.LogicalBlockByte2 = pCDB->CDB10.LogicalBlockByte2;
Cmd.LogicalBlockByte3 = pCDB->CDB10.LogicalBlockByte3;
- DPRINT1("BlockAddress %x%x%x%x BlockCount %lu BlockLength %lu\n", Cmd.LogicalBlockByte0, Cmd.LogicalBlockByte1, Cmd.LogicalBlockByte2, Cmd.LogicalBlockByte3, BlockCount, PDODeviceExtension->BlockLength);
+ DPRINT("USBSTOR_SendReadWriteCmd BlockAddress %x%x%x%x BlockCount %lu BlockLength %lu\n", Cmd.LogicalBlockByte0, Cmd.LogicalBlockByte1, Cmd.LogicalBlockByte2, Cmd.LogicalBlockByte3, BlockCount, PDODeviceExtension->BlockLength);
//
// send request
//
- return USBSTOR_SendRequest(DeviceObject, Irp, NULL, UFI_READ_WRITE_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, (PUCHAR)Request->DataBuffer);
+ return USBSTOR_SendRequest(DeviceObject, Irp, NULL, UFI_READ_WRITE_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, (PUCHAR)Request->DataBuffer);
}
NTSTATUS
//
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;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+
+ //
+ // get PDO device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // sanity check
+ //
+ ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // get request block
+ //
+ Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
+
+ //
+ // get SCSI command data block
+ //
+ pCDB = (PCDB)Request->Cdb;
+
+ DPRINT("USBSTOR_HandleExecuteSCSI Operation Code %x\n", pCDB->AsByte[0]);
+
+ if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
+ {
+ //
+ // sanity checks
+ //
+ ASSERT(Request->DataBuffer);
+
+ DPRINT("SCSIOP_READ_CAPACITY Length %\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)
+ {
+ DPRINT("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)
+ {
+ DPRINT("SCSIOP_MEDIUM_REMOVAL\n");
+
+ //
+ // just complete the request
+ //
+ Request->SrbStatus = SRB_STATUS_SUCCESS;
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = Request->DataTransferLength;
+ USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ //
+ // start next request
+ //
+ USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject);
+
+ return STATUS_SUCCESS;
+ }
+ else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_TEST_UNIT_READY)
+ {
+ DPRINT("SCSIOP_TEST_UNIT_READY\n");
+
+ //
+ // send test unit command
+ //
+ Status = USBSTOR_SendTestUnitCmd(DeviceObject, Irp);
+ }
+ else
+ {
+ DPRINT1("UNIMPLEMENTED Operation Code %x\n", pCDB->AsByte[0]);
+ Request->SrbStatus = SRB_STATUS_ERROR;
+ Status = STATUS_NOT_SUPPORTED;
+ DbgBreakPoint();
+ }
+
+ return Status;
+}