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);
}
+/*
+ * @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;
}
+/*
+ * @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;
- return(STATUS_UNSUCCESSFUL);
+ NextStack->Parameters = Stack->Parameters;
+ NextStack->MajorFunction = Stack->MajorFunction;
+ NextStack->MinorFunction = Stack->MinorFunction;
+
+ /* 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;
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_SCSI] = ScsiClassInternalIoControl;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiClassDeviceDispatch;
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = ScsiClassShutdownFlush;
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = ScsiClassShutdownFlush;
*
* 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");
DPRINT("Srb->SrbStatus %lx\n", Srb->SrbStatus);
-
+
if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_PENDING)
{
*Status = STATUS_SUCCESS;
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;
DeviceExtension = DeviceObject->DeviceExtension;
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.
-
+
+ /*
+ * 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);
{
((ULONG)IrpStack->Parameters.Others.Argument4)--;
- ScsiClassRetryRequest(
- DeviceObject,
- Irp,
- Srb,
- FALSE);
+ ScsiClassRetryRequest(DeviceObject,
+ Irp,
+ Srb,
+ FALSE);
return(STATUS_MORE_PROCESSING_REQUIRED);
}
}
+/*
+ * @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;
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.
+ /*
+ * 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;
{
((ULONG)IrpStack->Parameters.Others.Argument4)--;
- ScsiClassRetryRequest(
- DeviceObject,
- Irp,
- Srb,
- TRUE);
+ ScsiClassRetryRequest(DeviceObject,
+ Irp,
+ Srb,
+ TRUE);
return(STATUS_MORE_PROCESSING_REQUIRED);
}
}
+/*
+ * @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,
}
+/*
+ * @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;
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)
{
static VOID
-ScsiClassRetryRequest(
- PDEVICE_OBJECT DeviceObject,
- PIRP Irp,
- PSCSI_REQUEST_BLOCK Srb,
- BOOLEAN Associated
- )
+ScsiClassRetryRequest(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PSCSI_REQUEST_BLOCK Srb,
+ BOOLEAN Associated)
{
PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION CurrentIrpStack;
NextIrpStack->Parameters.Scsi.Srb = Srb;
if (Associated == FALSE)
- {
- IoSetCompletionRoutine(Irp,
- ScsiClassIoComplete,
- Srb,
- TRUE,
- TRUE,
- TRUE);
- }
- else
- {
- IoSetCompletionRoutine(Irp,
- ScsiClassIoCompleteAssociated,
- Srb,
- TRUE,
- TRUE,
- TRUE);
- }
-
+ {
+ IoSetCompletionRoutine(Irp,
+ ScsiClassIoComplete,
+ Srb,
+ TRUE,
+ TRUE,
+ TRUE);
+ }
+ else
+ {
+ IoSetCompletionRoutine(Irp,
+ ScsiClassIoCompleteAssociated,
+ Srb,
+ TRUE,
+ TRUE,
+ TRUE);
+ }
IoCallDriver(DeviceExtension->PortDeviceObject,
Irp);