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.
753 lines
21 KiB
753 lines
21 KiB
|
|
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 2000
|
|
|
|
Module Name:
|
|
|
|
enum.c
|
|
|
|
Abstract:
|
|
|
|
This file contains device enumeration routines
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "port.h"
|
|
|
|
|
|
VOID
|
|
iSpEnumerateDevicesAsynchronous(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PVOID Context
|
|
)
|
|
{
|
|
PISCSI_FDO_EXTENSION fdoExtension;
|
|
PCOMMON_EXTENSION commonExtension;
|
|
PISCSI_CONNECTION iScsiConnection;
|
|
PIRP Irp;
|
|
LARGE_INTEGER Timeout;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
UCHAR oldIrql;
|
|
|
|
fdoExtension = (PISCSI_FDO_EXTENSION) Context;
|
|
commonExtension = DeviceObject->DeviceExtension;
|
|
|
|
IoFreeWorkItem(fdoExtension->EnumerationWorkItem);
|
|
fdoExtension->EnumerationWorkItem = NULL;
|
|
|
|
//
|
|
// Local network nodes should be setup at this point.
|
|
// If not, fail the enumeration irp
|
|
//
|
|
if ((fdoExtension->LocalNodesInitialized) == TRUE) {
|
|
PDEVICE_OBJECT pdo;
|
|
PISCSI_PDO_EXTENSION pdoExtension;
|
|
ULONG inx;
|
|
|
|
DebugPrint((3, "Number of targets : %d\n",
|
|
(fdoExtension->NumberOfTargets)));
|
|
|
|
fdoExtension->TargetsYetToRespond = fdoExtension->NumberOfTargets;
|
|
|
|
for (inx = 0; inx < (fdoExtension->NumberOfTargets); inx++) {
|
|
|
|
pdo = fdoExtension->PDOList[inx];
|
|
pdoExtension = (PISCSI_PDO_EXTENSION)(pdo->DeviceExtension);
|
|
iScsiConnection = pdoExtension->ClientNodeInfo;
|
|
|
|
DebugPrint((3, "Will connect to the server\n"));
|
|
|
|
pdoExtension->LogonTickCount = 0;
|
|
|
|
//
|
|
// Connection timeout is 60 seconds. Is this enough???
|
|
//
|
|
Timeout.QuadPart = -600000000;
|
|
status = iSpTdiConnect(iScsiConnection->ConnectionDeviceObject,
|
|
iScsiConnection->ConnectionFileObject,
|
|
pdoExtension->TargetIPAddress,
|
|
htons(pdoExtension->TargetPortNumber),
|
|
Timeout);
|
|
if (NT_SUCCESS(status)) {
|
|
DebugPrint((3, "Connected to the server\n"));
|
|
|
|
iScsiConnection->ConnectionState = ConnectionStateConnected;
|
|
|
|
pdoExtension->CurrentProtocolState = PSLogonInProgress;
|
|
|
|
DebugPrint((3, "Will send logon packet\n"));
|
|
|
|
status = iSpSendLoginCommand(pdoExtension);
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
pdoExtension->LogonTickCount = 0;
|
|
|
|
DebugPrint((3, "Login command sent successfully\n"));
|
|
} else {
|
|
|
|
LARGE_INTEGER disconnectTimeout;
|
|
|
|
DebugPrint((1,
|
|
"Send failed for logon. Status : %x\n",
|
|
status));
|
|
|
|
InterlockedDecrement(&(fdoExtension->TargetsYetToRespond));
|
|
pdoExtension->CurrentProtocolState = PSLogonFailed;
|
|
|
|
disconnectTimeout.QuadPart = -100000000L;
|
|
|
|
iScsiConnection->ConnectionState = ConnectionStateStopping;
|
|
|
|
status = iSpTdiDisconnect(iScsiConnection->ConnectionDeviceObject,
|
|
iScsiConnection->ConnectionFileObject,
|
|
TDI_DISCONNECT_RELEASE,
|
|
iSpTdiCompletionRoutine,
|
|
iScsiConnection,
|
|
disconnectTimeout);
|
|
|
|
DebugPrint((3, "iSpTdiDisconnect returned : %x\n",
|
|
status));
|
|
|
|
}
|
|
} else {
|
|
|
|
DebugPrint((1, "Could not connect to server. Status : %x\n",
|
|
status));
|
|
pdoExtension->CurrentProtocolState = PSConnectToServerFailed;
|
|
InterlockedDecrement(&(fdoExtension->TargetsYetToRespond));
|
|
}
|
|
}
|
|
|
|
KeAcquireSpinLock(&(fdoExtension->EnumerationSpinLock),
|
|
&oldIrql);
|
|
|
|
//
|
|
// Launch the enum completion thread if all targets have
|
|
// responded or none could be contacted.
|
|
//
|
|
if (((fdoExtension->TargetsYetToRespond) == 0) &&
|
|
((fdoExtension->EnumerationThreadLaunched) == FALSE)) {
|
|
|
|
DebugPrint((0,
|
|
"All or no targets responded. Will complete QDR\n"));
|
|
|
|
iSpLaunchEnumerationCompletion(fdoExtension);
|
|
|
|
}
|
|
|
|
KeReleaseSpinLock(&(fdoExtension->EnumerationSpinLock),
|
|
oldIrql);
|
|
|
|
} else {
|
|
DebugPrint((1, "iSpEnumerateDevices : Client node not setup yet\n"));
|
|
|
|
status = STATUS_UNSUCCESSFUL;
|
|
|
|
Irp = fdoExtension->EnumerationIrp;
|
|
fdoExtension->EnumerationIrp = NULL;
|
|
|
|
Irp->IoStatus.Status = status;
|
|
Irp->IoStatus.Information = 0L;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
|
|
NTSTATUS
|
|
iSpPerformDeviceEnumeration(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp
|
|
)
|
|
{
|
|
PISCSI_FDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
|
|
PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
|
|
PISCSI_CONNECTION iScsiConnection = fdoExtension->ClientNodeInfo;
|
|
PISCSI_LOGIN_COMMAND iscsiLoginCommand;
|
|
LARGE_INTEGER disconnectTimeout;
|
|
NTSTATUS status;
|
|
USHORT connectionID;
|
|
|
|
ASSERT((iScsiConnection != NULL));
|
|
ASSERT((iScsiConnection->Type) == ISCSI_CONNECTION_TYPE);
|
|
ASSERT((iScsiConnection->ConnectionState) == ConnectionStateConnected);
|
|
|
|
if ((fdoExtension->CurrentProtocolState) != PSConnectedToServer) {
|
|
DebugPrint((1, "Probably already logged on. CurrentState : %d\n",
|
|
(fdoExtension->CurrentProtocolState)));
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// First send logon packet
|
|
//
|
|
fdoExtension->CurrentIrp = Irp;
|
|
fdoExtension->CurrentProtocolState = PSLogonInProgress;
|
|
|
|
status = iSpSendLoginCommand(fdoExtension);
|
|
if (NT_SUCCESS(status)) {
|
|
DebugPrint((3, "Login command sent successfully\n"));
|
|
} else {
|
|
DebugPrint((1, "Send failed for logon. Status : %x\n", status));
|
|
|
|
fdoExtension->CurrentIrp = NULL;
|
|
fdoExtension->CurrentProtocolState = PSLogonFailed;
|
|
|
|
disconnectTimeout.QuadPart = -100000000L;
|
|
|
|
iScsiConnection->ConnectionState = ConnectionStateStopping;
|
|
|
|
status = iSpTdiDisconnect(iScsiConnection->ConnectionDeviceObject,
|
|
iScsiConnection->ConnectionFileObject,
|
|
TDI_DISCONNECT_RELEASE,
|
|
iSpTdiCompletionRoutine,
|
|
iScsiConnection,
|
|
disconnectTimeout);
|
|
|
|
DebugPrint((3, "iSpTdiDisconnect returned : %x\n",
|
|
status));
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// QDR Irp will be completed upon receipt of login response
|
|
//
|
|
// ISSUE : nramas : 12/24/2000
|
|
// Should have a timer here to take care of the case where
|
|
// the server fails to send logon response.
|
|
//
|
|
return STATUS_SUCCESS;
|
|
}
|
|
*/
|
|
|
|
|
|
NTSTATUS
|
|
iSpQueryDeviceRelationsCompletion(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PVOID Context
|
|
)
|
|
{
|
|
PISCSI_FDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
|
|
PISCSI_PDO_EXTENSION pdoExtension;
|
|
|
|
PCOMMON_EXTENSION commonExtension;
|
|
PISCSI_CONNECTION iScsiConnection;
|
|
PISCSI_LOGIN_RESPONSE loginResponse;
|
|
PIRP Irp;
|
|
PDEVICE_OBJECT pdo;
|
|
PDEVICE_RELATIONS deviceRelations;
|
|
|
|
PACTIVE_REQUESTS activeClientRequests = NULL;
|
|
|
|
ULONG relationSize;
|
|
ULONG maxCmdRN = 0;
|
|
ULONG inx;
|
|
ULONG targetIndex;
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
IoFreeWorkItem((PIO_WORKITEM) Context);
|
|
|
|
Irp = fdoExtension->EnumerationIrp;
|
|
fdoExtension->EnumerationIrp = NULL;
|
|
|
|
relationSize = sizeof(DEVICE_RELATIONS) +
|
|
((fdoExtension->NumberOfTargets) * sizeof(PDEVICE_OBJECT));
|
|
|
|
deviceRelations = iSpAllocatePool(PagedPool,
|
|
relationSize,
|
|
ISCSI_TAG_DEVICE_RELATIONS);
|
|
if (deviceRelations == NULL) {
|
|
DebugPrint((1, "Failed to allocate memory for device relations\n"));
|
|
|
|
for (inx = 0; inx < (fdoExtension->NumberOfTargets); inx++) {
|
|
pdo = fdoExtension->PDOList[inx];
|
|
|
|
iSpStopNetwork(pdo);
|
|
|
|
IoDeleteDevice(pdo);
|
|
|
|
fdoExtension->PDOList[inx] = NULL;
|
|
}
|
|
|
|
fdoExtension->NumberOfTargets = 0;
|
|
|
|
fdoExtension->LocalNodesInitialized = FALSE;
|
|
|
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
Irp->IoStatus.Information = 0L;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
deviceRelations->Count = 0;
|
|
|
|
targetIndex = 0;
|
|
for (inx = 0; inx < (fdoExtension->NumberOfTargets); inx++) {
|
|
|
|
pdo = fdoExtension->PDOList[inx];
|
|
|
|
pdoExtension = (PISCSI_PDO_EXTENSION)(pdo->DeviceExtension);
|
|
|
|
iScsiConnection = pdoExtension->ClientNodeInfo;
|
|
|
|
if ((pdoExtension->CurrentProtocolState) == PSLogonSucceeded) {
|
|
|
|
loginResponse = (PISCSI_LOGIN_RESPONSE) (iScsiConnection->IScsiPacket);
|
|
|
|
//
|
|
// Allocate memory to keep active requests. Size of this
|
|
// array is the value returned in MaxCmdRN field
|
|
//
|
|
GetUlongFromArray((loginResponse->InitStatRN),
|
|
(iScsiConnection->CurrentStatusRefNum));
|
|
|
|
GetUlongFromArray((loginResponse->ExpCmdRN),
|
|
(iScsiConnection->CommandRefNum));
|
|
|
|
GetUlongFromArray((loginResponse->MaxCmdRN), maxCmdRN);
|
|
|
|
iScsiConnection->MaxCommandRefNum = maxCmdRN;
|
|
|
|
DebugPrint((1, "InitStatRN : %d, ExpCmdRN : %d, MaxCmdRN : %d\n",
|
|
(iScsiConnection->CurrentStatusRefNum),
|
|
(iScsiConnection->CommandRefNum),
|
|
maxCmdRN));
|
|
|
|
ASSERT((maxCmdRN != 0));
|
|
|
|
ASSERT(((iScsiConnection->CommandRefNum) <= maxCmdRN));
|
|
|
|
iScsiConnection->NumberOfReqsInProgress = 0;
|
|
|
|
iScsiConnection->ReceiveState = ReceiveHeader;
|
|
|
|
iScsiConnection->MaxPendingRequests = maxCmdRN;
|
|
|
|
activeClientRequests = iSpAllocatePool(
|
|
NonPagedPool,
|
|
(sizeof(ACTIVE_REQUESTS) * (maxCmdRN + 1)),
|
|
ISCSI_TAG_ACTIVE_REQ);
|
|
|
|
if (activeClientRequests == NULL) {
|
|
|
|
DebugPrint((1, "Failed to allocate ActiveClientRequests array\n"));
|
|
|
|
iSpStopNetwork(pdo);
|
|
|
|
IoDeleteDevice(pdo);
|
|
|
|
fdoExtension->PDOList[inx] = NULL;
|
|
} else {
|
|
RtlZeroMemory(activeClientRequests,
|
|
(sizeof(ACTIVE_REQUESTS) * (maxCmdRN + 1)));
|
|
|
|
commonExtension = pdo->DeviceExtension;
|
|
pdoExtension = pdo->DeviceExtension;
|
|
pdo->StackSize = 1;
|
|
pdo->Flags |= (DO_BUS_ENUMERATED_DEVICE | DO_DIRECT_IO);
|
|
pdo->AlignmentRequirement = DeviceObject->AlignmentRequirement;
|
|
|
|
commonExtension->DeviceObject = pdo;
|
|
commonExtension->LowerDeviceObject = DeviceObject;
|
|
commonExtension->IsPdo = TRUE;
|
|
commonExtension->MajorFunction = PdoMajorFunctionTable;
|
|
commonExtension->RemoveLock = 0;
|
|
commonExtension->CurrentPnpState = 0xff;
|
|
commonExtension->PreviousPnpState = 0xff;
|
|
|
|
iScsiConnection->ActiveClientRequests = activeClientRequests;
|
|
|
|
//
|
|
// Inquiry data will be filled when we get the
|
|
// first query id irp
|
|
//
|
|
pdoExtension->InquiryDataInitialized = FALSE;
|
|
|
|
pdoExtension->CurrentProtocolState = PSFullFeaturePhase;
|
|
|
|
pdoExtension->IsEnumerated = TRUE;
|
|
|
|
//
|
|
// Initialize the remove lock event.
|
|
//
|
|
|
|
KeInitializeEvent(
|
|
&(commonExtension->RemoveEvent),
|
|
SynchronizationEvent,
|
|
FALSE);
|
|
|
|
//
|
|
// Initialize the request list for this PDO
|
|
//
|
|
InitializeListHead(&(iScsiConnection->RequestList));
|
|
|
|
pdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
|
|
fdoExtension->PDOList[targetIndex] = pdo;
|
|
targetIndex++;
|
|
|
|
ObReferenceObject(pdo);
|
|
|
|
DebugPrint((1, "PDO %d : 0x%x\n",
|
|
(deviceRelations->Count), pdo));
|
|
|
|
deviceRelations->Objects[deviceRelations->Count] = pdo;
|
|
|
|
(deviceRelations->Count)++;
|
|
|
|
}
|
|
} else {
|
|
iSpStopNetwork(pdo);
|
|
|
|
IoDeleteDevice(pdo);
|
|
|
|
fdoExtension->PDOList[inx] = NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Group all the targets to the beginning of the PDOList
|
|
//
|
|
for (inx = targetIndex; inx < MAX_TARGETS_SUPPORTED; inx++) {
|
|
fdoExtension->PDOList[inx] = NULL;
|
|
}
|
|
|
|
DebugPrint((1, "Number of PDOs reported : %d\n",
|
|
(deviceRelations->Count)));
|
|
|
|
if ((deviceRelations->Count) > 0) {
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
|
|
|
|
fdoExtension->EnumerationComplete = TRUE;
|
|
fdoExtension->NumberOfTargets = deviceRelations->Count;
|
|
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
|
|
return IoCallDriver((fdoExtension->CommonExtension.LowerDeviceObject),
|
|
Irp);
|
|
} else {
|
|
DebugPrint((1, "No PDOs to report in QDR\n"));
|
|
ExFreePool(deviceRelations);
|
|
|
|
fdoExtension->NumberOfTargets = 0;
|
|
|
|
fdoExtension->LocalNodesInitialized = FALSE;
|
|
|
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
|
Irp->IoStatus.Information = 0L;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
IssueInquiry(
|
|
IN PDEVICE_OBJECT LogicalUnit
|
|
)
|
|
{
|
|
PISCSI_PDO_EXTENSION pdoExtension = LogicalUnit->DeviceExtension;
|
|
PIRP irp;
|
|
SCSI_REQUEST_BLOCK srb;
|
|
PCDB cdb;
|
|
PVOID dataBuffer;
|
|
PSENSE_DATA senseInfoBuffer;
|
|
|
|
UCHAR allocationLength;
|
|
ULONG bytesReturned;
|
|
|
|
NTSTATUS status;
|
|
|
|
PAGED_CODE();
|
|
|
|
dataBuffer = &(pdoExtension->InquiryData);
|
|
senseInfoBuffer = &(pdoExtension->InquirySenseBuffer);
|
|
|
|
irp = IoAllocateIrp((LogicalUnit->StackSize) + 1, FALSE);
|
|
if (irp == NULL) {
|
|
DebugPrint((1, "IssueInquiry : Failed to allocate IRP.\n"));
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
IoInitializeIrp(irp,
|
|
IoSizeOfIrp((LogicalUnit->StackSize) + 1),
|
|
((LogicalUnit->StackSize) + 1));
|
|
|
|
//
|
|
// Fill in SRB fields.
|
|
//
|
|
|
|
RtlZeroMemory(dataBuffer, sizeof(INQUIRYDATA));
|
|
RtlZeroMemory(senseInfoBuffer, SENSE_BUFFER_SIZE);
|
|
RtlZeroMemory(&srb, SCSI_REQUEST_BLOCK_SIZE);
|
|
|
|
srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
|
|
srb.Length = SCSI_REQUEST_BLOCK_SIZE;
|
|
|
|
//
|
|
// Set flags to disable synchronous negociation.
|
|
//
|
|
|
|
srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
|
|
|
|
//
|
|
// Set timeout to 4 seconds.
|
|
//
|
|
|
|
srb.TimeOutValue = 4;
|
|
|
|
srb.CdbLength = 6;
|
|
|
|
cdb = (PCDB)(srb.Cdb);
|
|
|
|
//
|
|
// Set CDB operation code.
|
|
//
|
|
|
|
cdb->CDB6INQUIRY3.OperationCode = SCSIOP_INQUIRY;
|
|
|
|
//
|
|
// Set allocation length to inquiry data buffer size.
|
|
//
|
|
|
|
allocationLength = sizeof(INQUIRYDATA);
|
|
|
|
cdb->CDB6INQUIRY3.AllocationLength = allocationLength;
|
|
|
|
cdb->CDB6INQUIRY3.EnableVitalProductData = FALSE;
|
|
|
|
|
|
cdb->CDB6INQUIRY3.PageCode = 0;
|
|
|
|
status = iSpSendSrbSynchronous(LogicalUnit,
|
|
&srb,
|
|
irp,
|
|
dataBuffer,
|
|
allocationLength,
|
|
senseInfoBuffer,
|
|
SENSE_BUFFER_SIZE,
|
|
&bytesReturned
|
|
);
|
|
|
|
ASSERT(bytesReturned <= allocationLength);
|
|
|
|
//
|
|
// Return the inquiry data for the device if the call was successful.
|
|
// Otherwise cleanup.
|
|
//
|
|
|
|
if(NT_SUCCESS(status)) {
|
|
|
|
pdoExtension->InquiryDataInitialized = TRUE;
|
|
|
|
DebugPrint((3, "Inquiry data obtained successfully\n"));
|
|
} else {
|
|
DebugPrint((1, "Failed to obtain inquiry data. Status : %x\n",
|
|
status));
|
|
}
|
|
|
|
IoFreeIrp(irp);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
iSpSendSrbSynchronous(
|
|
IN PDEVICE_OBJECT LogicalUnit,
|
|
IN PSCSI_REQUEST_BLOCK Srb,
|
|
IN PIRP Irp,
|
|
IN PVOID DataBuffer,
|
|
IN ULONG TransferLength,
|
|
IN OPTIONAL PVOID SenseInfoBuffer,
|
|
IN OPTIONAL UCHAR SenseInfoBufferLength,
|
|
OUT PULONG BytesReturned
|
|
)
|
|
{
|
|
KEVENT event;
|
|
|
|
PIO_STACK_LOCATION irpStack;
|
|
PMDL Mdl = NULL;
|
|
|
|
PSENSE_DATA senseInfo = SenseInfoBuffer;
|
|
|
|
NTSTATUS status;
|
|
|
|
PAGED_CODE();
|
|
|
|
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
|
|
|
if(ARGUMENT_PRESENT(DataBuffer)) {
|
|
ASSERT(TransferLength != 0);
|
|
|
|
Mdl = IoAllocateMdl(DataBuffer,
|
|
TransferLength,
|
|
FALSE,
|
|
FALSE,
|
|
NULL);
|
|
|
|
if(Mdl == NULL) {
|
|
IoFreeIrp(Irp);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
MmBuildMdlForNonPagedPool(Mdl);
|
|
Irp->MdlAddress = Mdl;
|
|
} else {
|
|
ASSERT(TransferLength == 0);
|
|
}
|
|
|
|
irpStack = IoGetNextIrpStackLocation(Irp);
|
|
|
|
//
|
|
// Mark the minor function to indicate that this is an internal scsiport
|
|
// request and that the start state of the device can be ignored.
|
|
//
|
|
|
|
irpStack->MajorFunction = IRP_MJ_SCSI;
|
|
irpStack->MinorFunction = 1;
|
|
|
|
irpStack->Parameters.Scsi.Srb = Srb;
|
|
|
|
Srb->SrbStatus = Srb->ScsiStatus = 0;
|
|
|
|
Srb->OriginalRequest = Irp;
|
|
|
|
//
|
|
// Enable auto request sense.
|
|
//
|
|
|
|
if(ARGUMENT_PRESENT(SenseInfoBuffer)) {
|
|
Srb->SenseInfoBuffer = SenseInfoBuffer;
|
|
Srb->SenseInfoBufferLength = SenseInfoBufferLength;
|
|
} else {
|
|
Srb->SenseInfoBuffer = NULL;
|
|
Srb->SenseInfoBufferLength = 0;
|
|
SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DISABLE_AUTOSENSE);
|
|
}
|
|
|
|
if(ARGUMENT_PRESENT(Mdl)) {
|
|
Srb->DataBuffer = MmGetMdlVirtualAddress(Mdl);
|
|
Srb->DataTransferLength = TransferLength;
|
|
} else {
|
|
Srb->DataBuffer = NULL;
|
|
Srb->DataTransferLength = 0;
|
|
}
|
|
|
|
IoSetCompletionRoutine(Irp,
|
|
iSpSetEvent,
|
|
&event,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
|
|
KeEnterCriticalRegion();
|
|
|
|
status = IoCallDriver(LogicalUnit, Irp);
|
|
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
|
|
|
|
status = Irp->IoStatus.Status;
|
|
|
|
*BytesReturned = (ULONG) Irp->IoStatus.Information;
|
|
|
|
IoFreeMdl(Mdl);
|
|
|
|
KeLeaveCriticalRegion();
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
VOID
|
|
iSpTickHandler(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PVOID Context
|
|
)
|
|
{
|
|
PISCSI_FDO_EXTENSION fdoExtension;
|
|
PISCSI_PDO_EXTENSION pdoExtension;
|
|
PDEVICE_OBJECT pdo;
|
|
ULONG inx;
|
|
UCHAR oldIrql;
|
|
|
|
fdoExtension = (PISCSI_FDO_EXTENSION) DeviceObject->DeviceExtension;
|
|
|
|
KeAcquireSpinLock(&(fdoExtension->EnumerationSpinLock),
|
|
&oldIrql);
|
|
|
|
if ((fdoExtension->TargetsYetToRespond) > 0) {
|
|
|
|
for (inx = 0; inx < (fdoExtension->NumberOfTargets); inx++) {
|
|
|
|
pdo = fdoExtension->PDOList[inx];
|
|
if (pdo != NULL) {
|
|
|
|
pdoExtension = (PISCSI_PDO_EXTENSION) (pdo->DeviceExtension);
|
|
|
|
if ((pdoExtension->CurrentProtocolState) == PSLogonInProgress) {
|
|
(pdoExtension->LogonTickCount)++;
|
|
}
|
|
|
|
if ((pdoExtension->LogonTickCount) == MAX_LOGON_WAIT_TIME) {
|
|
|
|
DebugPrint((0, "Timeout waiting for logon response\n"));
|
|
|
|
pdoExtension->CurrentProtocolState = PSLogonTimedOut;
|
|
|
|
(fdoExtension->TargetsYetToRespond)--;
|
|
|
|
if ((fdoExtension->TargetsYetToRespond) == 0) {
|
|
|
|
DebugPrint((0,
|
|
"TickHandler : All targets responded.\n"));
|
|
|
|
iSpLaunchEnumerationCompletion(fdoExtension);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
KeReleaseSpinLock(&(fdoExtension->EnumerationSpinLock),
|
|
oldIrql);
|
|
}
|
|
|
|
|
|
VOID
|
|
iSpLaunchEnumerationCompletion(
|
|
IN PISCSI_FDO_EXTENSION FdoExtension
|
|
)
|
|
{
|
|
PIO_WORKITEM workItem;
|
|
|
|
if ((FdoExtension->EnumerationThreadLaunched) == FALSE) {
|
|
|
|
workItem = IoAllocateWorkItem(FdoExtension->DeviceObject);
|
|
if (workItem != NULL) {
|
|
|
|
IoQueueWorkItem(workItem,
|
|
iSpQueryDeviceRelationsCompletion,
|
|
DelayedWorkQueue,
|
|
workItem);
|
|
|
|
FdoExtension->EnumerationThreadLaunched = TRUE;
|
|
}
|
|
|
|
}
|
|
}
|