/*
* ReactOS kernel
- * Copyright (C) 2001, 2002 ReactOS Team
+ * Copyright (C) 2001, 2002, 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: class2.c,v 1.27 2002/11/18 22:40:32 ekohl Exp $
+/* $Id: class2.c,v 1.41 2003/10/15 22:16:44 vizzini Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
-static NTSTATUS STDCALL
-ScsiClassScsiDispatch(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp);
-
static NTSTATUS STDCALL
ScsiClassDeviceDispatch(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
static VOID
ScsiClassRetryRequest(PDEVICE_OBJECT DeviceObject,
- PIRP Irp,
- PSCSI_REQUEST_BLOCK Srb,
- BOOLEAN Associated);
+ PIRP Irp, PSCSI_REQUEST_BLOCK Srb, BOOLEAN Associated);
/* FUNCTIONS ****************************************************************/
}
+/*
+ * @unimplemented
+ */
NTSTATUS STDCALL
ScsiClassAsynchronousCompletion(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
}
+/*
+ * @implemented
+ */
VOID STDCALL
-ScsiClassBuildRequest(PDEVICE_OBJECT DeviceObject,
- PIRP Irp)
+ScsiClassBuildRequest(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
{
PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION CurrentIrpStack;
DPRINT("Logical block address: %lu\n", LogicalBlockAddress);
/* Allocate and initialize an SRB */
- /* FIXME: use lookaside list instead */
- Srb = ExAllocatePool(NonPagedPool,
- sizeof(SCSI_REQUEST_BLOCK));
+ Srb = ExAllocateFromNPagedLookasideList(&DeviceExtension->SrbLookasideListHead);
Srb->SrbFlags = 0;
Srb->Length = sizeof(SCSI_REQUEST_BLOCK); //SCSI_REQUEST_BLOCK_SIZE;
Srb->TargetId = DeviceExtension->TargetId;
Srb->Lun = DeviceExtension->Lun;
Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
+ //FIXME: NT4 DDK sample uses MmGetMdlVirtualAddress! Why shouldn't we?
Srb->DataBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
Srb->DataTransferLength = CurrentIrpStack->Parameters.Read.Length;
Srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
/* Initialize next stack location */
NextIrpStack->MajorFunction = IRP_MJ_SCSI;
NextIrpStack->Parameters.Scsi.Srb = Srb;
- NextIrpStack->DeviceObject = DeviceObject;
/* Set retry count */
- NextIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
+ CurrentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
DPRINT("IoSetCompletionRoutine (Irp %p Srb %p)\n", Irp, Srb);
IoSetCompletionRoutine(Irp,
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
ScsiClassClaimDevice(PDEVICE_OBJECT PortDeviceObject,
PSCSI_INQUIRY_DATA LunInfo,
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
ScsiClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
IN PCCHAR ObjectNameBuffer,
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
-ScsiClassDeviceControl(PDEVICE_OBJECT DeviceObject,
- PIRP Irp)
+ScsiClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
{
PDEVICE_EXTENSION DeviceExtension;
+ PIO_STACK_LOCATION NextStack;
PIO_STACK_LOCATION Stack;
ULONG IoControlCode;
+ ULONG InputBufferLength;
ULONG OutputBufferLength;
+ ULONG ModifiedControlCode;
+ PSCSI_REQUEST_BLOCK Srb;
+ PCDB Cdb;
DPRINT("ScsiClassDeviceControl() called\n");
Stack = IoGetCurrentIrpStackLocation(Irp);
IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode;
+ InputBufferLength = Stack->Parameters.DeviceIoControl.InputBufferLength;
OutputBufferLength = Stack->Parameters.DeviceIoControl.OutputBufferLength;
+ if (IoControlCode == IOCTL_SCSI_GET_DUMP_POINTERS)
+ {
+ PDUMP_POINTERS DumpPointers;
+
+ if (OutputBufferLength < sizeof(DUMP_POINTERS))
+ {
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return(STATUS_BUFFER_TOO_SMALL);
+ }
+ DumpPointers = (PDUMP_POINTERS)Irp->AssociatedIrp.SystemBuffer;
+
+ /* Initialize next stack location for call to the port driver */
+ NextStack = IoGetNextIrpStackLocation(Irp);
+
+ NextStack->Parameters = Stack->Parameters;
+ NextStack->MajorFunction = Stack->MajorFunction;
+ NextStack->MinorFunction = Stack->MinorFunction;
+
+ /* Call port driver */
+ return(IoCallDriver(DeviceExtension->PortDeviceObject,
+ Irp));
+ }
if (IoControlCode == IOCTL_SCSI_GET_ADDRESS)
{
PSCSI_ADDRESS ScsiAddress;
if (IoControlCode == IOCTL_SCSI_PASS_THROUGH ||
IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT)
{
- DPRINT1("Fixme: IOCTL_SCSI_PASS_THROUGH/IOCTL_SCSI_PASS_THROUGH_DIRECT\n");
+ PSCSI_PASS_THROUGH ScsiPassThrough;
+ DPRINT("IOCTL_SCSI_PASS_THROUGH/IOCTL_SCSI_PASS_THROUGH_DIRECT\n");
- Irp->IoStatus.Information = 0;
- Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ /* Check input size */
+ if (InputBufferLength < sizeof(SCSI_PASS_THROUGH))
+ {
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return(STATUS_INVALID_PARAMETER);
+ }
+
+ /* Initialize next stack location for call to the port driver */
+ NextStack = IoGetNextIrpStackLocation(Irp);
+
+ ScsiPassThrough = Irp->AssociatedIrp.SystemBuffer;
+ ScsiPassThrough->PathId = DeviceExtension->PathId;
+ ScsiPassThrough->TargetId = DeviceExtension->TargetId;
+ ScsiPassThrough->Lun = DeviceExtension->Lun;
+ ScsiPassThrough->Cdb[1] |= DeviceExtension->Lun << 5;
+
+ NextStack->Parameters = Stack->Parameters;
+ NextStack->MajorFunction = Stack->MajorFunction;
+ NextStack->MinorFunction = Stack->MinorFunction;
- return(STATUS_UNSUCCESSFUL);
+ /* Call port driver */
+ return(IoCallDriver(DeviceExtension->PortDeviceObject,
+ Irp));
+ }
+
+ /* Allocate an SRB */
+ Srb = ExAllocatePool (NonPagedPool,
+ sizeof(SCSI_REQUEST_BLOCK));
+ if (Srb == NULL)
+ {
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp,
+ IO_NO_INCREMENT);
+ return(STATUS_INSUFFICIENT_RESOURCES);
}
- DPRINT1("Fixme: unknown device io control code\n");
+ /* Initialize the SRB */
+ RtlZeroMemory(Srb,
+ sizeof(SCSI_REQUEST_BLOCK));
+ Cdb = (PCDB)Srb->Cdb;
+
+ ModifiedControlCode = (IoControlCode & 0x0000FFFF) | (IOCTL_DISK_BASE << 16);
+ switch (ModifiedControlCode)
+ {
+ case IOCTL_DISK_CHECK_VERIFY:
+ DPRINT("IOCTL_DISK_CHECK_VERIFY\n");
+
+ /* Initialize SRB operation */
+ Srb->CdbLength = 6;
+ Srb->TimeOutValue = DeviceExtension->TimeOutValue;
+ Cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
+
+ return(ScsiClassSendSrbAsynchronous(DeviceObject,
+ Srb,
+ Irp,
+ NULL,
+ 0,
+ FALSE));
+
+ default:
+ DPRINT1("Unknown device io control code %lx\n",
+ ModifiedControlCode);
+ ExFreePool(Srb);
+
+ /* Pass the IOCTL down to the port driver */
+ NextStack = IoGetNextIrpStackLocation(Irp);
+ NextStack->Parameters = Stack->Parameters;
+ NextStack->MajorFunction = Stack->MajorFunction;
+ NextStack->MinorFunction = Stack->MinorFunction;
+
+ /* Call port driver */
+ return(IoCallDriver(DeviceExtension->PortDeviceObject,
+ Irp));
+ }
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
}
+/*
+ * @implemented
+ */
PVOID STDCALL
-ScsiClassFindModePage(PCHAR ModeSenseBuffer,
- ULONG Length,
- UCHAR PageMode,
- BOOLEAN Use6Byte)
+ScsiClassFindModePage(IN PCHAR ModeSenseBuffer,
+ IN ULONG Length,
+ IN UCHAR PageMode,
+ IN BOOLEAN Use6Byte)
{
- UNIMPLEMENTED;
+ ULONG DescriptorLength;
+ ULONG HeaderLength;
+ PCHAR End;
+ PCHAR Ptr;
+
+ DPRINT("ScsiClassFindModePage() called\n");
+
+ /* Get header length */
+ HeaderLength = (Use6Byte) ? sizeof(MODE_PARAMETER_HEADER) : sizeof(MODE_PARAMETER_HEADER10);
+
+ /* Check header length */
+ if (Length < HeaderLength)
+ return NULL;
+
+ /* Get descriptor length */
+ if (Use6Byte == TRUE)
+ {
+ DescriptorLength = ((PMODE_PARAMETER_HEADER)ModeSenseBuffer)->BlockDescriptorLength;
+ }
+ else
+ {
+ DescriptorLength = ((PMODE_PARAMETER_HEADER10)ModeSenseBuffer)->BlockDescriptorLength[1];
+ }
+
+ /* Set page pointers */
+ Ptr = ModeSenseBuffer + HeaderLength + DescriptorLength;
+ End = ModeSenseBuffer + Length;
+
+ /* Search for page */
+ while (Ptr < End)
+ {
+ /* Check page code */
+ if (((PMODE_DISCONNECT_PAGE)Ptr)->PageCode == PageMode)
+ return Ptr;
+
+ /* Skip to next page */
+ Ptr += ((PMODE_DISCONNECT_PAGE)Ptr)->PageLength;
+ }
+
+ return NULL;
}
+/*
+ * @implemented
+ */
ULONG STDCALL
-ScsiClassFindUnclaimedDevices(PCLASS_INIT_DATA InitializationData,
- PSCSI_ADAPTER_BUS_INFO AdapterInformation)
+ScsiClassFindUnclaimedDevices(IN PCLASS_INIT_DATA InitializationData,
+ IN PSCSI_ADAPTER_BUS_INFO AdapterInformation)
{
PSCSI_INQUIRY_DATA UnitInfo;
PINQUIRYDATA InquiryData;
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
-ScsiClassGetCapabilities(PDEVICE_OBJECT PortDeviceObject,
- PIO_SCSI_CAPABILITIES *PortCapabilities)
+ScsiClassGetCapabilities(IN PDEVICE_OBJECT PortDeviceObject,
+ OUT PIO_SCSI_CAPABILITIES *PortCapabilities)
{
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
-ScsiClassGetInquiryData(PDEVICE_OBJECT PortDeviceObject,
- PSCSI_ADAPTER_BUS_INFO *ConfigInfo)
+ScsiClassGetInquiryData(IN PDEVICE_OBJECT PortDeviceObject,
+ IN PSCSI_ADAPTER_BUS_INFO *ConfigInfo)
{
PSCSI_ADAPTER_BUS_INFO Buffer;
IO_STATUS_BLOCK IoStatusBlock;
}
+/*
+ * @implemented
+ */
ULONG STDCALL
-ScsiClassInitialize(PVOID Argument1,
- PVOID Argument2,
- PCLASS_INIT_DATA InitializationData)
+ScsiClassInitialize(IN PVOID Argument1,
+ IN PVOID Argument2,
+ IN PCLASS_INIT_DATA InitializationData)
{
PCONFIGURATION_INFORMATION ConfigInfo;
PDRIVER_OBJECT DriverObject = Argument1;
DPRINT("ScsiClassInitialize() called!\n");
- DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiClassCreateClose;
- DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiClassCreateClose;
- DriverObject->MajorFunction[IRP_MJ_READ] = ScsiClassReadWrite;
- DriverObject->MajorFunction[IRP_MJ_WRITE] = ScsiClassReadWrite;
- DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiClassScsiDispatch;
- DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiClassDeviceDispatch;
- DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = ScsiClassShutdownFlush;
- DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = ScsiClassShutdownFlush;
+ DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)ScsiClassCreateClose;
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)ScsiClassCreateClose;
+ DriverObject->MajorFunction[IRP_MJ_READ] = (PDRIVER_DISPATCH)ScsiClassReadWrite;
+ DriverObject->MajorFunction[IRP_MJ_WRITE] = (PDRIVER_DISPATCH)ScsiClassReadWrite;
+ DriverObject->MajorFunction[IRP_MJ_SCSI] = (PDRIVER_DISPATCH)ScsiClassInternalIoControl;
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)ScsiClassDeviceDispatch;
+ DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = (PDRIVER_DISPATCH)ScsiClassShutdownFlush;
+ DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = (PDRIVER_DISPATCH)ScsiClassShutdownFlush;
if (InitializationData->ClassStartIo)
{
DriverObject->DriverStartIo = InitializationData->ClassStartIo;
*
* RETURN VALUE
* None.
+ *
+ * @implemented
*/
-
VOID STDCALL
-ScsiClassInitializeSrbLookasideList(PDEVICE_EXTENSION DeviceExtension,
- ULONG NumberElements)
+ScsiClassInitializeSrbLookasideList(IN PDEVICE_EXTENSION DeviceExtension,
+ IN ULONG NumberElements)
{
ExInitializeNPagedLookasideList(&DeviceExtension->SrbLookasideListHead,
NULL,
}
+/*
+ * @unimplemented
+ */
NTSTATUS STDCALL
-ScsiClassInternalIoControl(PDEVICE_OBJECT DeviceObject,
- PIRP Irp)
+ScsiClassInternalIoControl(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
{
- UNIMPLEMENTED;
+ DPRINT1("ScsiClassInternalIoContol() called\n");
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return(STATUS_SUCCESS);
}
+/*
+ * @implemented
+ */
BOOLEAN STDCALL
-ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
- PSCSI_REQUEST_BLOCK Srb,
- UCHAR MajorFunctionCode,
- ULONG IoDeviceCode,
- ULONG RetryCount,
- NTSTATUS *Status)
+ScsiClassInterpretSenseInfo(IN PDEVICE_OBJECT DeviceObject,
+ IN PSCSI_REQUEST_BLOCK Srb,
+ IN UCHAR MajorFunctionCode,
+ IN ULONG IoDeviceCode,
+ IN ULONG RetryCount,
+ OUT NTSTATUS *Status)
{
PDEVICE_EXTENSION DeviceExtension;
+#if 0
+ PIO_ERROR_LOG_PACKET LogPacket;
+#endif
PSENSE_DATA SenseData;
+ NTSTATUS LogStatus;
+ BOOLEAN LogError;
BOOLEAN Retry;
DPRINT("ScsiClassInterpretSenseInfo() called\n");
DeviceExtension = DeviceObject->DeviceExtension;
SenseData = Srb->SenseInfoBuffer;
+ LogError = FALSE;
Retry = TRUE;
if ((Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
switch (SenseData->SenseKey & 0xf)
{
- /* FIXME: add more sense key codes */
+ case SCSI_SENSE_NO_SENSE:
+ DPRINT("SCSI_SENSE_NO_SENSE\n");
+ if (SenseData->IncorrectLength)
+ {
+ DPRINT("Incorrect block length\n");
+ *Status = STATUS_INVALID_BLOCK_LENGTH;
+ Retry = FALSE;
+ }
+ else
+ {
+ DPRINT("Unspecified error\n");
+ *Status = STATUS_IO_DEVICE_ERROR;
+ Retry = FALSE;
+ }
+ break;
+
+ case SCSI_SENSE_RECOVERED_ERROR:
+ DPRINT("SCSI_SENSE_RECOVERED_ERROR\n");
+ *Status = STATUS_SUCCESS;
+ Retry = FALSE;
+ break;
case SCSI_SENSE_NOT_READY:
DPRINT("SCSI_SENSE_NOT_READY\n");
*Status = STATUS_DEVICE_NOT_READY;
+ switch (SenseData->AdditionalSenseCode)
+ {
+ case SCSI_ADSENSE_LUN_NOT_READY:
+ DPRINT("SCSI_ADSENSE_LUN_NOT_READY\n");
+ break;
+
+ case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE:
+ DPRINT("SCSI_ADSENSE_NO_MEDIA_IN_DEVICE\n");
+ *Status = STATUS_NO_MEDIA_IN_DEVICE;
+ Retry = FALSE;
+ break;
+ }
+ break;
+
+ case SCSI_SENSE_MEDIUM_ERROR:
+ DPRINT("SCSI_SENSE_MEDIUM_ERROR\n");
+ *Status = STATUS_DEVICE_DATA_ERROR;
+ Retry = FALSE;
+ break;
+
+ case SCSI_SENSE_HARDWARE_ERROR:
+ DPRINT("SCSI_SENSE_HARDWARE_ERROR\n");
+ *Status = STATUS_IO_DEVICE_ERROR;
+ break;
+
+ case SCSI_SENSE_ILLEGAL_REQUEST:
+ DPRINT("SCSI_SENSE_ILLEGAL_REQUEST\n");
+ *Status = STATUS_INVALID_DEVICE_REQUEST;
+ switch (SenseData->AdditionalSenseCode)
+ {
+ case SCSI_ADSENSE_ILLEGAL_COMMAND:
+ DPRINT("SCSI_ADSENSE_ILLEGAL_COMMAND\n");
+ Retry = FALSE;
+ break;
+
+ case SCSI_ADSENSE_ILLEGAL_BLOCK:
+ DPRINT("SCSI_ADSENSE_ILLEGAL_BLOCK\n");
+ *Status = STATUS_NONEXISTENT_SECTOR;
+ Retry = FALSE;
+ break;
+
+ case SCSI_ADSENSE_INVALID_LUN:
+ DPRINT("SCSI_ADSENSE_INVALID_LUN\n");
+ *Status = STATUS_NO_SUCH_DEVICE;
+ Retry = FALSE;
+ break;
+
+ case SCSI_ADSENSE_MUSIC_AREA:
+ DPRINT("SCSI_ADSENSE_MUSIC_AREA\n");
+ Retry = FALSE;
+ break;
+
+ case SCSI_ADSENSE_DATA_AREA:
+ DPRINT("SCSI_ADSENSE_DATA_AREA\n");
+ Retry = FALSE;
+ break;
+
+ case SCSI_ADSENSE_VOLUME_OVERFLOW:
+ DPRINT("SCSI_ADSENSE_VOLUME_OVERFLOW\n");
+ Retry = FALSE;
+ break;
+
+ case SCSI_ADSENSE_INVALID_CDB:
+ DPRINT("SCSI_ADSENSE_INVALID_CDB\n");
+ Retry = FALSE;
+ break;
+ }
break;
case SCSI_SENSE_UNIT_ATTENTION:
}
break;
- case SCSI_SENSE_ILLEGAL_REQUEST:
- DPRINT("SCSI_SENSE_ILLEGAL_REQUEST\n");
- *Status = STATUS_INVALID_DEVICE_REQUEST;
+ case SCSI_SENSE_DATA_PROTECT:
+ DPRINT("SCSI_SENSE_DATA_PROTECT\n");
+ *Status = STATUS_MEDIA_WRITE_PROTECTED;
Retry = FALSE;
break;
+ case SCSI_SENSE_ABORTED_COMMAND:
+ DPRINT("SCSI_SENSE_ABORTED_COMMAND\n");
+ *Status = STATUS_IO_DEVICE_ERROR;
+ break;
default:
DPRINT1("SCSI error (sense key: %x)\n",
default:
DPRINT1("SCSI error (SRB status: %x)\n",
SRB_STATUS(Srb->SrbStatus));
+ LogError = TRUE;
*Status = STATUS_IO_DEVICE_ERROR;
break;
}
&Retry);
}
- /* FIXME: log severe errors */
+ if (LogError == TRUE)
+ {
+#if 0
+ /* Allocate error packet */
+ LogPacket = IoAllocateErrorLogEntry (DeviceObject,
+ sizeof(IO_ERROR_LOG_PACKET) +
+ 5 * sizeof(ULONG));
+ if (LogPacket == NULL)
+ {
+ DPRINT1 ("Failed to allocate a log packet!\n");
+ return Retry;
+ }
+
+ /* Initialize error packet */
+ LogPacket->MajorFunctionCode = MajorFunctionCode;
+ LogPacket->RetryCount = (UCHAR)RetryCount;
+ LogPacket->DumpDataSize = 6 * sizeof(ULONG);
+ LogPacket->ErrorCode = 0; /* FIXME */
+ LogPacket->FinalStatus = *Status;
+ LogPacket->IoControlCode = IoDeviceCode;
+ LogPacket->DeviceOffset.QuadPart = 0; /* FIXME */
+ LogPacket->DumpData[0] = Srb->PathId;
+ LogPacket->DumpData[1] = Srb->TargetId;
+ LogPacket->DumpData[2] = Srb->Lun;
+ LogPacket->DumpData[3] = 0;
+ LogPacket->DumpData[4] = (Srb->SrbStatus << 8) | Srb->ScsiStatus;
+ if (SenseData != NULL)
+ {
+ LogPacket->DumpData[5] = (SenseData->SenseKey << 16) |
+ (SenseData->AdditionalSenseCode << 8) |
+ SenseData->AdditionalSenseCodeQualifier;
+ }
+
+ /* Write error packet */
+ IoWriteErrorLogEntry (LogPacket);
+#endif
+ }
DPRINT("ScsiClassInterpretSenseInfo() done\n");
- return(Retry);
+ return Retry;
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
-ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject,
- PIRP Irp,
- PVOID Context)
+ScsiClassIoComplete(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context)
{
PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION IrpStack;
DeviceObject, Irp, Context);
DeviceExtension = DeviceObject->DeviceExtension;
- Srb = (PSCSI_REQUEST_BLOCK)Context;
- DPRINT("Srb %p\n", Srb);
IrpStack = IoGetCurrentIrpStackLocation(Irp);
+ /*
+ * BUGBUG -> Srb = IrpStack->Parameters.Scsi.Srb;
+ * Must pass Srb as Context arg!! See comment about Completion routines in
+ * IofCallDriver for more info.
+ */
+
+ Srb = (PSCSI_REQUEST_BLOCK)Context;
+
+ DPRINT("Srb %p\n", Srb);
+
if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS)
{
Status = STATUS_SUCCESS;
0,
MAXIMUM_RETRIES - ((ULONG)IrpStack->Parameters.Others.Argument4),
&Status);
- if ((Retry == TRUE) &&
+ if ((Retry) &&
((ULONG)IrpStack->Parameters.Others.Argument4 > 0))
{
((ULONG)IrpStack->Parameters.Others.Argument4)--;
Irp,
Srb,
FALSE);
+
return(STATUS_MORE_PROCESSING_REQUIRED);
}
}
- /* FIXME: use lookaside list instead */
- DPRINT("Freed SRB %p\n", IrpStack->Parameters.Scsi.Srb);
- ExFreePool(IrpStack->Parameters.Scsi.Srb);
+ /* Free the SRB */
+ ExFreeToNPagedLookasideList(&DeviceExtension->SrbLookasideListHead,
+ Srb);
Irp->IoStatus.Status = Status;
if (!NT_SUCCESS(Status))
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
-ScsiClassIoCompleteAssociated(PDEVICE_OBJECT DeviceObject,
- PIRP Irp,
- PVOID Context)
+ScsiClassIoCompleteAssociated(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context)
{
PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION IrpStack;
MasterIrp = Irp->AssociatedIrp.MasterIrp;
DeviceExtension = DeviceObject->DeviceExtension;
- Srb = (PSCSI_REQUEST_BLOCK)Context;
- DPRINT("Srb %p\n", Srb);
IrpStack = IoGetCurrentIrpStackLocation(Irp);
+ /*
+ * BUGBUG -> Srb = Srb = IrpStack->Parameters.Scsi.Srb;
+ * Must pass Srb as Context arg!! See comment about Completion routines in
+ * IofCallDriver for more info.
+ */
+
+ Srb = (PSCSI_REQUEST_BLOCK)Context;
+
+ DPRINT("Srb %p\n", Srb);
+
if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS)
{
Status = STATUS_SUCCESS;
MAXIMUM_RETRIES - ((ULONG)IrpStack->Parameters.Others.Argument4),
&Status);
- DPRINT1("Retry count: %lu\n", (ULONG)IrpStack->Parameters.Others.Argument4);
-
- if ((Retry == TRUE) &&
+ if ((Retry) &&
((ULONG)IrpStack->Parameters.Others.Argument4 > 0))
{
((ULONG)IrpStack->Parameters.Others.Argument4)--;
Irp,
Srb,
TRUE);
+
return(STATUS_MORE_PROCESSING_REQUIRED);
}
}
- /* FIXME: use lookaside list instead */
- DPRINT("Freed SRB %p\n", IrpStack->Parameters.Scsi.Srb);
- ExFreePool(IrpStack->Parameters.Scsi.Srb);
+ /* Free the SRB */
+ ExFreeToNPagedLookasideList(&DeviceExtension->SrbLookasideListHead,
+ Srb);
Irp->IoStatus.Status = Status;
}
+/*
+ * @implemented
+ */
ULONG STDCALL
-ScsiClassModeSense(PDEVICE_OBJECT DeviceObject,
- CHAR ModeSenseBuffer,
- ULONG Length,
- UCHAR PageMode)
+ScsiClassModeSense(IN PDEVICE_OBJECT DeviceObject,
+ IN PCHAR ModeSenseBuffer,
+ IN ULONG Length,
+ IN UCHAR PageMode)
{
- UNIMPLEMENTED;
+ PDEVICE_EXTENSION DeviceExtension;
+ SCSI_REQUEST_BLOCK Srb;
+ ULONG RetryCount;
+ PCDB Cdb;
+ NTSTATUS Status;
+
+ DPRINT("ScsiClassModeSense() called\n");
+
+ DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ RetryCount = 1;
+
+ /* Initialize the SRB */
+ RtlZeroMemory (&Srb,
+ sizeof(SCSI_REQUEST_BLOCK));
+ Srb.CdbLength = 6;
+ Srb.TimeOutValue = DeviceExtension->TimeOutValue;
+
+ /* Initialize the CDB */
+ Cdb = (PCDB)&Srb.Cdb;
+ Cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
+ Cdb->MODE_SENSE.PageCode = PageMode;
+ Cdb->MODE_SENSE.AllocationLength = (UCHAR)Length;
+
+TryAgain:
+ Status = ScsiClassSendSrbSynchronous (DeviceObject,
+ &Srb,
+ ModeSenseBuffer,
+ Length,
+ FALSE);
+ if (Status == STATUS_VERIFY_REQUIRED)
+ {
+ if (RetryCount != 0)
+ {
+ RetryCount--;
+ goto TryAgain;
+ }
+ }
+ else if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN)
+ {
+ Status = STATUS_SUCCESS;
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ return 0;
+ }
+
+ return Srb.DataTransferLength;
}
+/*
+ * @implemented
+ */
ULONG STDCALL
ScsiClassQueryTimeOutRegistryValue(IN PUNICODE_STRING RegistryPath)
{
- UNIMPLEMENTED;
+ PRTL_QUERY_REGISTRY_TABLE Table;
+ ULONG TimeOutValue;
+ ULONG ZeroTimeOut;
+ ULONG Size;
+ PWSTR Path;
+ NTSTATUS Status;
+
+ if (RegistryPath == NULL)
+ {
+ return 0;
+ }
+
+ TimeOutValue = 0;
+ ZeroTimeOut = 0;
+
+ /* Allocate zero-terminated path string */
+ Size = RegistryPath->Length + sizeof(WCHAR);
+ Path = (PWSTR)ExAllocatePool (NonPagedPool,
+ Size);
+ if (Path == NULL)
+ {
+ return 0;
+ }
+ RtlZeroMemory (Path,
+ Size);
+ RtlCopyMemory (Path,
+ RegistryPath->Buffer,
+ Size - sizeof(WCHAR));
+
+ /* Allocate query table */
+ Size = sizeof(RTL_QUERY_REGISTRY_TABLE) * 2;
+ Table = (PRTL_QUERY_REGISTRY_TABLE)ExAllocatePool (NonPagedPool,
+ Size);
+ if (Table == NULL)
+ {
+ ExFreePool (Path);
+ return 0;
+ }
+ RtlZeroMemory (Table,
+ Size);
+
+ Table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ Table[0].Name = L"TimeOutValue";
+ Table[0].EntryContext = &TimeOutValue;
+ Table[0].DefaultType = REG_DWORD;
+ Table[0].DefaultData = &ZeroTimeOut;
+ Table[0].DefaultLength = sizeof(ULONG);
+
+ Status = RtlQueryRegistryValues (RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
+ Path,
+ Table,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("RtlQueryRegistryValue() failed (Status %lx)\n", Status);
+ TimeOutValue = 0;
+ }
+
+ ExFreePool (Table);
+ ExFreePool (Path);
+
+ DPRINT("TimeOut: %lu\n", TimeOutValue);
+
+ return TimeOutValue;
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject)
{
}
+/*
+ * @unimplemented
+ */
VOID STDCALL
ScsiClassReleaseQueue(IN PDEVICE_OBJECT DeviceObject)
{
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
ScsiClassSendSrbAsynchronous(PDEVICE_OBJECT DeviceObject,
PSCSI_REQUEST_BLOCK Srb,
ULONG BufferLength,
BOOLEAN WriteToDevice)
{
- UNIMPLEMENTED;
+ PDEVICE_EXTENSION DeviceExtension;
+ PIO_STACK_LOCATION Stack;
+
+ DPRINT("ScsiClassSendSrbAsynchronous() called\n");
+
+ DeviceExtension = DeviceObject->DeviceExtension;
+
+ /* Initialize the SRB */
+ Srb->Length = SCSI_REQUEST_BLOCK_SIZE;
+ Srb->PathId = DeviceExtension->PathId;
+ Srb->TargetId = DeviceExtension->TargetId;
+ Srb->Lun = DeviceExtension->Lun;
+ Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
+ Srb->Cdb[1] |= DeviceExtension->Lun << 5;
+
+ Srb->SenseInfoBuffer = DeviceExtension->SenseData;
+ Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
+
+ Srb->DataBuffer = BufferAddress;
+ Srb->DataTransferLength = BufferLength;
+
+ Srb->ScsiStatus = 0;
+ Srb->SrbStatus = 0;
+ Srb->NextSrb = NULL;
+
+ if (BufferAddress != NULL)
+ {
+ if (Irp->MdlAddress == NULL)
+ {
+ /* Allocate an MDL */
+ if (!IoAllocateMdl(BufferAddress,
+ BufferLength,
+ FALSE,
+ FALSE,
+ Irp))
+ {
+ DPRINT1("Mdl-Allocation failed\n");
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ MmBuildMdlForNonPagedPool(Irp->MdlAddress);
+ }
+
+ /* Set data direction */
+ Srb->SrbFlags = (WriteToDevice) ? SRB_FLAGS_DATA_OUT : SRB_FLAGS_DATA_IN;
+ }
+ else
+ {
+ /* Set data direction */
+ Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;
+ }
+
+ /* Set the retry counter */
+ Stack = IoGetCurrentIrpStackLocation(Irp);
+ Stack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
+
+ /* Set the completion routine */
+ IoSetCompletionRoutine(Irp,
+ ScsiClassIoComplete,
+ Srb,
+ TRUE,
+ TRUE,
+ TRUE);
+
+ /* Attach Srb to the Irp */
+ Stack = IoGetNextIrpStackLocation(Irp);
+ Stack->MajorFunction = IRP_MJ_SCSI;
+ Stack->Parameters.Scsi.Srb = Srb;
+ Srb->OriginalRequest = Irp;
+
+ /* Call the port driver */
+ return(IoCallDriver(DeviceExtension->PortDeviceObject,
+ Irp));
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject,
PSCSI_REQUEST_BLOCK Srb,
{
if (WriteToDevice == TRUE)
{
- RequestType = IOCTL_SCSI_EXECUTE_OUT;
- Srb->SrbFlags = SRB_FLAGS_DATA_OUT;
+ RequestType = IOCTL_SCSI_EXECUTE_IN; // needs _in_ to the device
+ Srb->SrbFlags = SRB_FLAGS_DATA_OUT; // needs _out_ from the caller
}
else
{
- RequestType = IOCTL_SCSI_EXECUTE_IN;
+ RequestType = IOCTL_SCSI_EXECUTE_OUT;
Srb->SrbFlags = SRB_FLAGS_DATA_IN;
}
}
}
+/*
+ * @implemented
+ */
VOID STDCALL
-ScsiClassSplitRequest(PDEVICE_OBJECT DeviceObject,
- PIRP Irp,
- ULONG MaximumBytes)
+ScsiClassSplitRequest(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN ULONG MaximumBytes)
{
PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION CurrentStack;
DeviceExtension = DeviceObject->DeviceExtension;
CurrentStack = IoGetCurrentIrpStackLocation(Irp);
NextStack = IoGetNextIrpStackLocation(Irp);
- DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
+ DataBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
/* Initialize transfer data for first request */
Offset = CurrentStack->Parameters.Read.ByteOffset;
}
/* Adjust partition-relative starting offset to absolute offset */
- IrpStack->Parameters.Read.ByteOffset.QuadPart += DeviceExtension->StartingOffset.QuadPart;
+ IrpStack->Parameters.Read.ByteOffset.QuadPart +=
+ (DeviceExtension->StartingOffset.QuadPart + DeviceExtension->DMByteSkew);
/* Calculate number of pages in this transfer */
CurrentTransferPages =
}
-static NTSTATUS STDCALL
-ScsiClassScsiDispatch(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
-{
- DPRINT1("ScsiClassScsiDispatch() called\n");
-
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- return(STATUS_SUCCESS);
-}
-
-
static NTSTATUS STDCALL
ScsiClassDeviceDispatch(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION CurrentIrpStack;
PIO_STACK_LOCATION NextIrpStack;
+
ULONG TransferLength;
DPRINT("ScsiPortRetryRequest() called\n");
CurrentIrpStack = IoGetCurrentIrpStackLocation(Irp);
NextIrpStack = IoGetNextIrpStackLocation(Irp);
- if (CurrentIrpStack->MajorFunction == IRP_MJ_READ ||
- CurrentIrpStack->MajorFunction == IRP_MJ_WRITE)
- {
- TransferLength = CurrentIrpStack->Parameters.Read.Length;
- }
- else if (Irp->MdlAddress != NULL)
+ if (CurrentIrpStack->MajorFunction != IRP_MJ_READ &&
+ CurrentIrpStack->MajorFunction != IRP_MJ_WRITE)
{
- TransferLength = Irp->MdlAddress->ByteCount;
- }
- else
- {
- TransferLength = 0;
+ /* We shouldn't setup the buffer pointer and transfer length on read/write requests. */
+ if (Irp->MdlAddress != NULL)
+ {
+ TransferLength = Irp->MdlAddress->ByteCount;
+ }
+ else
+ {
+ TransferLength = 0;
+ }
+
+ Srb->DataBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
+ Srb->DataTransferLength = TransferLength;
}
- Srb->DataTransferLength = TransferLength;
Srb->SrbStatus = 0;
Srb->ScsiStatus = 0;
TRUE,
TRUE,
TRUE);
- }
+ }
else
{
IoSetCompletionRoutine(Irp,