mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
621 lines
17 KiB
621 lines
17 KiB
|
|
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 2000
|
|
|
|
Module Name:
|
|
|
|
pdo.c
|
|
|
|
Abstract:
|
|
|
|
This file contains PDO routines
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "port.h"
|
|
|
|
|
|
NTSTATUS
|
|
iScsiPortPdoDeviceControl(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
PISCSI_PDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
|
|
PCOMMON_EXTENSION commonExtension = Pdo->DeviceExtension;
|
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
ULONG ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
|
|
NTSTATUS status;
|
|
ULONG isRemoved;
|
|
|
|
isRemoved = iSpAcquireRemoveLock(Pdo, Irp);
|
|
if(isRemoved) {
|
|
|
|
iSpReleaseRemoveLock(Pdo, Irp);
|
|
Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_DEVICE_DOES_NOT_EXIST;
|
|
}
|
|
|
|
DebugPrint((3, "PDO DeviceControl - IO Control Code : 0x%08x\n",
|
|
ioControlCode));
|
|
|
|
switch (ioControlCode) {
|
|
case IOCTL_STORAGE_QUERY_PROPERTY: {
|
|
|
|
//
|
|
// Validate the query
|
|
//
|
|
|
|
PSTORAGE_PROPERTY_QUERY query = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
if(irpStack->Parameters.DeviceIoControl.InputBufferLength <
|
|
sizeof(STORAGE_PROPERTY_QUERY)) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
status = iScsiPortQueryProperty(Pdo, Irp);
|
|
|
|
return status;
|
|
|
|
break;
|
|
}
|
|
|
|
case IOCTL_SCSI_GET_IP_ADDRESS: {
|
|
PISCSI_IP_ADDRESS iScsiAddress = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
if(irpStack->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(ISCSI_IP_ADDRESS)) {
|
|
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
break;
|
|
}
|
|
|
|
iScsiAddress->IPAddress = pdoExtension->TargetIPAddress;
|
|
iScsiAddress->PortNumber = pdoExtension->TargetPortNumber;
|
|
|
|
Irp->IoStatus.Information = sizeof(ISCSI_IP_ADDRESS);
|
|
status = STATUS_SUCCESS;
|
|
|
|
break;
|
|
}
|
|
|
|
case IOCTL_SCSI_GET_ADDRESS: {
|
|
|
|
PSCSI_ADDRESS scsiAddress = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
if(irpStack->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(SCSI_ADDRESS)) {
|
|
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
break;
|
|
}
|
|
|
|
scsiAddress->Length = sizeof(PSCSI_ADDRESS);
|
|
scsiAddress->PortNumber = (UCHAR) pdoExtension->PortNumber;
|
|
scsiAddress->PathId = pdoExtension->PathId;
|
|
scsiAddress->TargetId = pdoExtension->TargetId;
|
|
scsiAddress->Lun = pdoExtension->Lun;
|
|
|
|
Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
default: {
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
iSpReleaseRemoveLock(Pdo, Irp);
|
|
return IoCallDriver(commonExtension->LowerDeviceObject, Irp);
|
|
}
|
|
} // switch (ioControlCode)
|
|
|
|
iSpReleaseRemoveLock(Pdo, Irp);
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
iScsiPortPdoPnp(
|
|
IN PDEVICE_OBJECT LogicalUnit,
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
PISCSI_PDO_EXTENSION pdoExtension = LogicalUnit->DeviceExtension;
|
|
PCOMMON_EXTENSION commonExtension = LogicalUnit->DeviceExtension;
|
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
ULONG isRemoved;
|
|
|
|
isRemoved = iSpAcquireRemoveLock(LogicalUnit, Irp);
|
|
if(isRemoved) {
|
|
|
|
iSpReleaseRemoveLock(LogicalUnit, Irp);
|
|
Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_DEVICE_DOES_NOT_EXIST;
|
|
}
|
|
|
|
DebugPrint((1, "PDO PnP - Minorfunction Code : 0x%x\n",
|
|
irpStack->MinorFunction));
|
|
|
|
switch (irpStack->MinorFunction) {
|
|
|
|
case IRP_MN_START_DEVICE: {
|
|
commonExtension->CurrentPnpState = IRP_MN_START_DEVICE;
|
|
commonExtension->PreviousPnpState = 0xff;
|
|
|
|
commonExtension->IsInitialized = TRUE;
|
|
|
|
//
|
|
// Make up numbers here
|
|
//
|
|
pdoExtension->PortNumber = 5;
|
|
pdoExtension->PathId = 0;
|
|
|
|
//
|
|
// N.B. TargetId is set in iSpInitializeLocalNodes
|
|
// routine when the PDO is created.
|
|
//
|
|
pdoExtension->Lun = 0;
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
case IRP_MN_QUERY_DEVICE_RELATIONS: {
|
|
|
|
PDEVICE_RELATIONS deviceRelations;
|
|
|
|
if(irpStack->Parameters.QueryDeviceRelations.Type !=
|
|
TargetDeviceRelation) {
|
|
|
|
DebugPrint((1, "Not TargetDevicesRelations for PDO\n"));
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// DEVICE_RELATIONS definition contains one object pointer.
|
|
//
|
|
|
|
deviceRelations = iSpAllocatePool(PagedPool,
|
|
sizeof(DEVICE_RELATIONS),
|
|
ISCSI_TAG_DEVICE_RELATIONS);
|
|
|
|
if(deviceRelations == NULL) {
|
|
|
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
RtlZeroMemory(deviceRelations, sizeof(DEVICE_RELATIONS));
|
|
|
|
deviceRelations->Count = 1;
|
|
deviceRelations->Objects[0] = LogicalUnit;
|
|
|
|
ObReferenceObject(deviceRelations->Objects[0]);
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
|
|
|
|
DebugPrint((1, "Completing QDR for PDO successfully\n"));
|
|
break;
|
|
}
|
|
|
|
case IRP_MN_QUERY_PNP_DEVICE_STATE: {
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
case IRP_MN_QUERY_DEVICE_TEXT: {
|
|
|
|
Irp->IoStatus.Status =
|
|
iSpQueryDeviceText(
|
|
LogicalUnit,
|
|
irpStack->Parameters.QueryDeviceText.DeviceTextType,
|
|
irpStack->Parameters.QueryDeviceText.LocaleId,
|
|
(PWSTR *) &Irp->IoStatus.Information
|
|
);
|
|
|
|
break;
|
|
}
|
|
|
|
case IRP_MN_QUERY_ID: {
|
|
|
|
UCHAR rawIdString[64] = "UNKNOWN ID TYPE";
|
|
ANSI_STRING ansiIdString;
|
|
UNICODE_STRING unicodeIdString;
|
|
BOOLEAN multiStrings;
|
|
|
|
PINQUIRYDATA inquiryData = &(pdoExtension->InquiryData);
|
|
|
|
if ((pdoExtension->InquiryDataInitialized) == FALSE) {
|
|
DebugPrint((3, "PdoPnp : Will obtain inquiry data\n"));
|
|
|
|
status = IssueInquiry(LogicalUnit);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,
|
|
"Failed to get inquiry data. Status : %x\n",
|
|
status));
|
|
|
|
Irp->IoStatus.Status = status;
|
|
iSpReleaseRemoveLock(LogicalUnit, Irp);
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return status;
|
|
} else {
|
|
DebugPrint((3, "PdoPnp : Obtained Inquiry data.\n"));
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// We've been asked for the id of one of the physical device objects
|
|
//
|
|
|
|
DebugPrint((3, "PDO PnP: Got IRP_MN_QUERY_ID\n"));
|
|
|
|
RtlInitUnicodeString(&unicodeIdString, NULL);
|
|
RtlInitAnsiString(&ansiIdString, NULL);
|
|
|
|
switch(irpStack->Parameters.QueryId.IdType) {
|
|
|
|
case BusQueryDeviceID: {
|
|
|
|
DebugPrint((3, "BusQueryDeviceID\n"));
|
|
status = iScsiPortGetDeviceId(LogicalUnit,
|
|
&unicodeIdString);
|
|
multiStrings = FALSE;
|
|
|
|
break;
|
|
}
|
|
|
|
case BusQueryInstanceID: {
|
|
|
|
DebugPrint((3, "BusQueryInstanceID\n"));
|
|
status = iScsiPortGetInstanceId(LogicalUnit,
|
|
&unicodeIdString);
|
|
multiStrings = FALSE;
|
|
|
|
break;
|
|
}
|
|
|
|
case BusQueryHardwareIDs: {
|
|
|
|
DebugPrint((3, "BusQueryHardwareIDs\n"));
|
|
status = iScsiPortGetHardwareIds(
|
|
LogicalUnit->DriverObject,
|
|
&(pdoExtension->InquiryData),
|
|
&unicodeIdString);
|
|
multiStrings = TRUE;
|
|
break;
|
|
}
|
|
|
|
case BusQueryCompatibleIDs: {
|
|
|
|
DebugPrint((3, "BusQueryCompatibleIDs\n"));
|
|
status = iScsiPortGetCompatibleIds(
|
|
LogicalUnit->DriverObject,
|
|
&(pdoExtension->InquiryData),
|
|
&unicodeIdString);
|
|
multiStrings = TRUE;
|
|
|
|
break;
|
|
}
|
|
|
|
default: {
|
|
|
|
status = Irp->IoStatus.Status;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
Irp->IoStatus.Status = status;
|
|
|
|
if(NT_SUCCESS(status)) {
|
|
|
|
PWCHAR idString;
|
|
|
|
DebugPrint((3, "Query ID successful\n"));
|
|
|
|
//
|
|
// fix up all invalid characters
|
|
//
|
|
idString = unicodeIdString.Buffer;
|
|
while (*idString) {
|
|
|
|
if ((*idString <= L' ') ||
|
|
(*idString > (WCHAR)0x7F) ||
|
|
(*idString == L',')) {
|
|
*idString = L'_';
|
|
}
|
|
idString++;
|
|
|
|
if ((*idString == L'\0') && multiStrings) {
|
|
idString++;
|
|
}
|
|
}
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR) unicodeIdString.Buffer;
|
|
} else {
|
|
DebugPrint((1, "Query ID failed\n"));
|
|
Irp->IoStatus.Information = (ULONG_PTR) NULL;
|
|
}
|
|
|
|
iSpReleaseRemoveLock(LogicalUnit, Irp);
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return status;
|
|
break;
|
|
}
|
|
|
|
case IRP_MN_QUERY_RESOURCES:
|
|
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: {
|
|
|
|
status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = (ULONG_PTR) NULL;
|
|
break;
|
|
}
|
|
|
|
case IRP_MN_REMOVE_DEVICE: {
|
|
PISCSI_FDO_EXTENSION fdoExtension;
|
|
ULONG inx;
|
|
BOOLEAN foundPDO = FALSE;
|
|
|
|
iSpReleaseRemoveLock(LogicalUnit, Irp);
|
|
|
|
//
|
|
// Remove this PDO from FDO's PDO List
|
|
//
|
|
|
|
fdoExtension = pdoExtension->ParentFDOExtension;
|
|
inx = 0;
|
|
while (inx < (fdoExtension->NumberOfTargets)) {
|
|
|
|
if (fdoExtension->PDOList[inx] == LogicalUnit) {
|
|
foundPDO = TRUE;
|
|
break;
|
|
}
|
|
|
|
inx++;
|
|
}
|
|
|
|
if (foundPDO == TRUE) {
|
|
DebugPrint((1, "Found the PDO : 0x%x\n",
|
|
LogicalUnit));
|
|
|
|
pdoExtension->IsClaimed = FALSE;
|
|
|
|
commonExtension->IsRemoved = REMOVE_PENDING;
|
|
|
|
if ((pdoExtension->IsMissing == TRUE) &&
|
|
(pdoExtension->IsEnumerated == FALSE)) {
|
|
|
|
(fdoExtension->NumberOfTargets)--;
|
|
|
|
DebugPrint((0, "Will remove the PDO\n"));
|
|
|
|
commonExtension->IsRemoved = REMOVE_COMPLETE;
|
|
|
|
pdoExtension->PathId = 0xff;
|
|
pdoExtension->TargetId = 0xff;
|
|
pdoExtension->Lun = 0xff;
|
|
|
|
DebugPrint((0, "Query remove received for the PDO\n"));
|
|
|
|
iSpStopNetwork(LogicalUnit);
|
|
|
|
IoDeleteDevice(LogicalUnit);
|
|
|
|
} else {
|
|
DebugPrint((0, "Will not delete the PDO\n"));
|
|
commonExtension->IsRemoved = NO_REMOVE;
|
|
}
|
|
|
|
status = STATUS_SUCCESS;
|
|
} else {
|
|
DebugPrint((0, "Did not find the PDO\n"));
|
|
status = STATUS_NO_SUCH_DEVICE;
|
|
}
|
|
|
|
Irp->IoStatus.Status = status;
|
|
Irp->IoStatus.Information = (ULONG_PTR) NULL;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return status;
|
|
}
|
|
|
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
|
case IRP_MN_QUERY_STOP_DEVICE: {
|
|
|
|
DebugPrint((0, "Query remove or query stop received\n"));
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
break;
|
|
}
|
|
|
|
default: {
|
|
DebugPrint((1,
|
|
"Not handling PDO MN Code - 0x%x. Status - 0x%08x\n",
|
|
(irpStack->MinorFunction),
|
|
(Irp->IoStatus.Status)));
|
|
}
|
|
}
|
|
|
|
iSpReleaseRemoveLock(LogicalUnit, Irp);
|
|
|
|
status = Irp->IoStatus.Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
iScsiPortPdoDispatch(
|
|
IN PDEVICE_OBJECT LogicalUnit,
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
PISCSI_PDO_EXTENSION pdoExtension = LogicalUnit->DeviceExtension;
|
|
PCOMMON_EXTENSION commonExtension = LogicalUnit->DeviceExtension;
|
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
PSCSI_REQUEST_BLOCK srb = irpStack->Parameters.Scsi.Srb;
|
|
NTSTATUS status;
|
|
ULONG isRemoved;
|
|
BOOLEAN sendCommandToServer = FALSE;
|
|
|
|
DebugPrint((3, "PdoDispatch - SRB Function : 0x%x\n",
|
|
srb->Function));
|
|
|
|
isRemoved = iSpAcquireRemoveLock(LogicalUnit, Irp);
|
|
if (isRemoved &&
|
|
!IS_CLEANUP_REQUEST(irpStack) &&
|
|
(srb->Function != SRB_FUNCTION_CLAIM_DEVICE)) {
|
|
|
|
iSpReleaseRemoveLock(LogicalUnit, Irp);
|
|
Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_DEVICE_DOES_NOT_EXIST;
|
|
}
|
|
|
|
switch(srb->Function) {
|
|
|
|
case SRB_FUNCTION_ABORT_COMMAND: {
|
|
DebugPrint((1, "Not handling abort command\n"));
|
|
status = STATUS_NOT_SUPPORTED;
|
|
break;
|
|
|
|
}
|
|
|
|
case SRB_FUNCTION_CLAIM_DEVICE:
|
|
case SRB_FUNCTION_REMOVE_DEVICE: {
|
|
|
|
status = iSpClaimLogicalUnit(
|
|
pdoExtension->CommonExtension.LowerDeviceObject->DeviceExtension,
|
|
pdoExtension,
|
|
Irp);
|
|
|
|
break;
|
|
}
|
|
|
|
case SRB_FUNCTION_RELEASE_QUEUE:
|
|
case SRB_FUNCTION_FLUSH_QUEUE:
|
|
case SRB_FUNCTION_SHUTDOWN:
|
|
case SRB_FUNCTION_FLUSH:
|
|
case SRB_FUNCTION_LOCK_QUEUE:
|
|
case SRB_FUNCTION_UNLOCK_QUEUE:
|
|
case SRB_FUNCTION_IO_CONTROL:
|
|
case SRB_FUNCTION_RESET_BUS:
|
|
case SRB_FUNCTION_WMI: {
|
|
|
|
//
|
|
// We won't handle these functions on the client
|
|
// side for the timebeing.
|
|
//
|
|
status = STATUS_SUCCESS;
|
|
srb->SrbStatus = SRB_STATUS_SUCCESS;
|
|
|
|
break;
|
|
}
|
|
|
|
case SRB_FUNCTION_EXECUTE_SCSI: {
|
|
|
|
//
|
|
// Mark Irp status pending.
|
|
//
|
|
|
|
IoMarkIrpPending(Irp);
|
|
|
|
sendCommandToServer = TRUE;
|
|
|
|
status = STATUS_PENDING;
|
|
|
|
break;
|
|
}
|
|
|
|
default: {
|
|
//
|
|
// Unsupported SRB function.
|
|
//
|
|
DebugPrint((0,
|
|
"PdoDispatch: Unsupported function, SRB %p\n",
|
|
srb));
|
|
|
|
srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (sendCommandToServer == FALSE) {
|
|
DebugPrint((1, "Not sending the command to the server\n"));
|
|
iSpReleaseRemoveLock(LogicalUnit, Irp);
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return status;
|
|
}
|
|
|
|
DebugPrint((3, "Will send the command to the server\n"));
|
|
|
|
status = iSpSendScsiCommand(LogicalUnit, Irp);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
DebugPrint((3, "Command successfully sent to the server.\n"));
|
|
status = STATUS_PENDING;
|
|
} else {
|
|
//
|
|
// In case of error, the lock will be released and the irp will
|
|
// be completed in iSpSendScsiCommand routine.
|
|
//
|
|
DebugPrint((1, "Failed to send the command. Status : %x\n",
|
|
status));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
iScsiPortPdoCreateClose(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
ULONG isRemoved;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
isRemoved = iSpAcquireRemoveLock(DeviceObject, Irp);
|
|
|
|
if(IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_CREATE) {
|
|
|
|
if(isRemoved) {
|
|
status = STATUS_DEVICE_DOES_NOT_EXIST;
|
|
}
|
|
}
|
|
|
|
Irp->IoStatus.Status = status;
|
|
|
|
iSpReleaseRemoveLock(DeviceObject, Irp);
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return status;
|
|
}
|
|
|