mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[SCSIPORT] Make the driver PnP-aware
Basic functions are implemented in order to work in PnP stack, only legacy (non-pnp) miniport drivers are supported. Tested mostly with uniata CORE-17132
This commit is contained in:
parent
582ca68696
commit
a97c6e0aa9
11 changed files with 2087 additions and 1050 deletions
|
@ -5,17 +5,22 @@ list(APPEND SOURCE
|
||||||
fdo.c
|
fdo.c
|
||||||
ioctl.c
|
ioctl.c
|
||||||
pdo.c
|
pdo.c
|
||||||
|
power.c
|
||||||
registry.c
|
registry.c
|
||||||
scsi.c
|
scsi.c
|
||||||
scsiport.c
|
scsiport.c
|
||||||
stubs.c)
|
stubs.c)
|
||||||
|
|
||||||
|
list(APPEND PCH_SKIP_SOURCE
|
||||||
|
guid.c)
|
||||||
|
|
||||||
add_library(scsiport MODULE
|
add_library(scsiport MODULE
|
||||||
${SOURCE}
|
${SOURCE}
|
||||||
|
${PCH_SKIP_SOURCE}
|
||||||
scsiport.rc
|
scsiport.rc
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/scsiport.def)
|
${CMAKE_CURRENT_BINARY_DIR}/scsiport.def)
|
||||||
|
|
||||||
add_pch(scsiport scsiport.h "")
|
add_pch(scsiport scsiport.h "${PCH_SKIP_SOURCE}")
|
||||||
set_module_type(scsiport kernelmodedriver)
|
set_module_type(scsiport kernelmodedriver)
|
||||||
add_importlibs(scsiport ntoskrnl hal)
|
add_importlibs(scsiport ntoskrnl hal)
|
||||||
add_cd_file(TARGET scsiport DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
add_cd_file(TARGET scsiport DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* PURPOSE: Adapter device object (FDO) support routines
|
* PURPOSE: Adapter device object (FDO) support routines
|
||||||
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
||||||
* Aleksey Bragin (aleksey@reactos.org)
|
* Aleksey Bragin (aleksey@reactos.org)
|
||||||
|
* 2020 Victor Perevertkin (victor.perevertkin@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "scsiport.h"
|
#include "scsiport.h"
|
||||||
|
@ -14,9 +15,8 @@
|
||||||
|
|
||||||
static
|
static
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
SpiSendInquiry(
|
FdoSendInquiry(
|
||||||
_In_ PDEVICE_OBJECT DeviceObject,
|
_In_ PDEVICE_OBJECT DeviceObject)
|
||||||
_Inout_ PSCSI_LUN_INFO LunInfo)
|
|
||||||
{
|
{
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
PIO_STACK_LOCATION IrpStack;
|
PIO_STACK_LOCATION IrpStack;
|
||||||
|
@ -30,12 +30,12 @@ SpiSendInquiry(
|
||||||
ULONG RetryCount = 0;
|
ULONG RetryCount = 0;
|
||||||
SCSI_REQUEST_BLOCK Srb;
|
SCSI_REQUEST_BLOCK Srb;
|
||||||
PCDB Cdb;
|
PCDB Cdb;
|
||||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
|
||||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
|
||||||
|
|
||||||
DPRINT("SpiSendInquiry() called\n");
|
DPRINT("FdoSendInquiry() called\n");
|
||||||
|
|
||||||
DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
PSCSI_PORT_LUN_EXTENSION LunExtension = DeviceObject->DeviceExtension;
|
||||||
|
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension =
|
||||||
|
LunExtension->Common.LowerDevice->DeviceExtension;
|
||||||
|
|
||||||
InquiryBuffer = ExAllocatePoolWithTag(NonPagedPool, INQUIRYDATABUFFERSIZE, TAG_SCSIPORT);
|
InquiryBuffer = ExAllocatePoolWithTag(NonPagedPool, INQUIRYDATABUFFERSIZE, TAG_SCSIPORT);
|
||||||
if (InquiryBuffer == NULL)
|
if (InquiryBuffer == NULL)
|
||||||
|
@ -80,9 +80,9 @@ SpiSendInquiry(
|
||||||
|
|
||||||
Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
|
Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
|
||||||
Srb.OriginalRequest = Irp;
|
Srb.OriginalRequest = Irp;
|
||||||
Srb.PathId = LunInfo->PathId;
|
Srb.PathId = LunExtension->PathId;
|
||||||
Srb.TargetId = LunInfo->TargetId;
|
Srb.TargetId = LunExtension->TargetId;
|
||||||
Srb.Lun = LunInfo->Lun;
|
Srb.Lun = LunExtension->Lun;
|
||||||
Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
|
Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
|
||||||
Srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
|
Srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
|
||||||
Srb.TimeOutValue = 4;
|
Srb.TimeOutValue = 4;
|
||||||
|
@ -101,7 +101,7 @@ SpiSendInquiry(
|
||||||
/* Fill in CDB */
|
/* Fill in CDB */
|
||||||
Cdb = (PCDB)Srb.Cdb;
|
Cdb = (PCDB)Srb.Cdb;
|
||||||
Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
|
Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
|
||||||
Cdb->CDB6INQUIRY.LogicalUnitNumber = LunInfo->Lun;
|
Cdb->CDB6INQUIRY.LogicalUnitNumber = LunExtension->Lun;
|
||||||
Cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
|
Cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
|
||||||
|
|
||||||
/* Call the driver */
|
/* Call the driver */
|
||||||
|
@ -110,7 +110,7 @@ SpiSendInquiry(
|
||||||
/* Wait for it to complete */
|
/* Wait for it to complete */
|
||||||
if (Status == STATUS_PENDING)
|
if (Status == STATUS_PENDING)
|
||||||
{
|
{
|
||||||
DPRINT("SpiSendInquiry(): Waiting for the driver to process request...\n");
|
DPRINT("FdoSendInquiry(): Waiting for the driver to process request...\n");
|
||||||
KeWaitForSingleObject(&Event,
|
KeWaitForSingleObject(&Event,
|
||||||
Executive,
|
Executive,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
|
@ -119,12 +119,12 @@ SpiSendInquiry(
|
||||||
Status = IoStatusBlock.Status;
|
Status = IoStatusBlock.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT("SpiSendInquiry(): Request processed by driver, status = 0x%08X\n", Status);
|
DPRINT("FdoSendInquiry(): Request processed by driver, status = 0x%08X\n", Status);
|
||||||
|
|
||||||
if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_SUCCESS)
|
if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
/* All fine, copy data over */
|
/* All fine, copy data over */
|
||||||
RtlCopyMemory(LunInfo->InquiryData,
|
RtlCopyMemory(&LunExtension->InquiryData,
|
||||||
InquiryBuffer,
|
InquiryBuffer,
|
||||||
INQUIRYDATABUFFERSIZE);
|
INQUIRYDATABUFFERSIZE);
|
||||||
|
|
||||||
|
@ -142,12 +142,7 @@ SpiSendInquiry(
|
||||||
/* Something weird happened, deal with it (unfreeze the queue) */
|
/* Something weird happened, deal with it (unfreeze the queue) */
|
||||||
KeepTrying = FALSE;
|
KeepTrying = FALSE;
|
||||||
|
|
||||||
DPRINT("SpiSendInquiry(): the queue is frozen at TargetId %d\n", Srb.TargetId);
|
DPRINT("FdoSendInquiry(): the queue is frozen at TargetId %d\n", Srb.TargetId);
|
||||||
|
|
||||||
LunExtension = SpiGetLunExtension(DeviceExtension,
|
|
||||||
LunInfo->PathId,
|
|
||||||
LunInfo->TargetId,
|
|
||||||
LunInfo->Lun);
|
|
||||||
|
|
||||||
/* Clear frozen flag */
|
/* Clear frozen flag */
|
||||||
LunExtension->Flags &= ~LUNEX_FROZEN_QUEUE;
|
LunExtension->Flags &= ~LUNEX_FROZEN_QUEUE;
|
||||||
|
@ -156,7 +151,7 @@ SpiSendInquiry(
|
||||||
KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
|
KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
|
||||||
|
|
||||||
/* Process the request */
|
/* Process the request */
|
||||||
SpiGetNextRequestFromLun(DeviceObject->DeviceExtension, LunExtension);
|
SpiGetNextRequestFromLun(DeviceExtension, LunExtension);
|
||||||
|
|
||||||
/* SpiGetNextRequestFromLun() releases the spinlock,
|
/* SpiGetNextRequestFromLun() releases the spinlock,
|
||||||
so we just lower irql back to what it was before */
|
so we just lower irql back to what it was before */
|
||||||
|
@ -166,10 +161,10 @@ SpiSendInquiry(
|
||||||
/* Check if data overrun happened */
|
/* Check if data overrun happened */
|
||||||
if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN)
|
if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN)
|
||||||
{
|
{
|
||||||
DPRINT("Data overrun at TargetId %d\n", LunInfo->TargetId);
|
DPRINT("Data overrun at TargetId %d\n", LunExtension->TargetId);
|
||||||
|
|
||||||
/* Nothing dramatic, just copy data, but limiting the size */
|
/* Nothing dramatic, just copy data, but limiting the size */
|
||||||
RtlCopyMemory(LunInfo->InquiryData,
|
RtlCopyMemory(&LunExtension->InquiryData,
|
||||||
InquiryBuffer,
|
InquiryBuffer,
|
||||||
(Srb.DataTransferLength > INQUIRYDATABUFFERSIZE) ?
|
(Srb.DataTransferLength > INQUIRYDATABUFFERSIZE) ?
|
||||||
INQUIRYDATABUFFERSIZE : Srb.DataTransferLength);
|
INQUIRYDATABUFFERSIZE : Srb.DataTransferLength);
|
||||||
|
@ -221,229 +216,141 @@ SpiSendInquiry(
|
||||||
ExFreePoolWithTag(InquiryBuffer, TAG_SCSIPORT);
|
ExFreePoolWithTag(InquiryBuffer, TAG_SCSIPORT);
|
||||||
ExFreePoolWithTag(SenseBuffer, TAG_SCSIPORT);
|
ExFreePoolWithTag(SenseBuffer, TAG_SCSIPORT);
|
||||||
|
|
||||||
DPRINT("SpiSendInquiry() done with Status 0x%08X\n", Status);
|
DPRINT("FdoSendInquiry() done with Status 0x%08X\n", Status);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scans all SCSI buses */
|
/* Scans all SCSI buses */
|
||||||
VOID
|
VOID
|
||||||
SpiScanAdapter(
|
FdoScanAdapter(
|
||||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
_In_ PSCSI_PORT_DEVICE_EXTENSION PortExtension)
|
||||||
{
|
{
|
||||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
NTSTATUS status;
|
||||||
ULONG Bus;
|
UINT32 totalLUNs = PortExtension->TotalLUCount;
|
||||||
ULONG Target;
|
|
||||||
ULONG Lun;
|
|
||||||
PSCSI_BUS_SCAN_INFO BusScanInfo;
|
|
||||||
PSCSI_LUN_INFO LastLunInfo, LunInfo, LunInfoExists;
|
|
||||||
BOOLEAN DeviceExists;
|
|
||||||
ULONG Hint;
|
|
||||||
NTSTATUS Status;
|
|
||||||
ULONG DevicesFound;
|
|
||||||
|
|
||||||
DPRINT("SpiScanAdapter() called\n");
|
DPRINT("FdoScanAdapter() called\n");
|
||||||
|
|
||||||
/* Scan all buses */
|
/* Scan all buses */
|
||||||
for (Bus = 0; Bus < DeviceExtension->BusNum; Bus++)
|
for (UINT8 pathId = 0; pathId < PortExtension->NumberOfBuses; pathId++)
|
||||||
{
|
{
|
||||||
DPRINT(" Scanning bus %d\n", Bus);
|
DPRINT(" Scanning bus/pathID %u\n", pathId);
|
||||||
DevicesFound = 0;
|
|
||||||
|
|
||||||
/* Get pointer to the scan information */
|
/* Get pointer to the scan information */
|
||||||
BusScanInfo = DeviceExtension->BusesConfig->BusScanInfo[Bus];
|
PSCSI_BUS_INFO currentBus = &PortExtension->Buses[pathId];
|
||||||
|
|
||||||
if (BusScanInfo)
|
|
||||||
{
|
|
||||||
/* Find the last LUN info in the list */
|
|
||||||
LunInfo = DeviceExtension->BusesConfig->BusScanInfo[Bus]->LunInfo;
|
|
||||||
LastLunInfo = LunInfo;
|
|
||||||
|
|
||||||
while (LunInfo != NULL)
|
|
||||||
{
|
|
||||||
LastLunInfo = LunInfo;
|
|
||||||
LunInfo = LunInfo->Next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* We need to allocate this buffer */
|
|
||||||
BusScanInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCSI_BUS_SCAN_INFO), TAG_SCSIPORT);
|
|
||||||
if (!BusScanInfo)
|
|
||||||
{
|
|
||||||
DPRINT1("Out of resources!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Store the pointer in the BusScanInfo array */
|
|
||||||
DeviceExtension->BusesConfig->BusScanInfo[Bus] = BusScanInfo;
|
|
||||||
|
|
||||||
/* Fill this struct (length and bus ids for now) */
|
|
||||||
BusScanInfo->Length = sizeof(SCSI_BUS_SCAN_INFO);
|
|
||||||
BusScanInfo->LogicalUnitsCount = 0;
|
|
||||||
BusScanInfo->BusIdentifier = DeviceExtension->PortConfig->InitiatorBusId[Bus];
|
|
||||||
BusScanInfo->LunInfo = NULL;
|
|
||||||
|
|
||||||
/* Set pointer to the last LUN info to NULL */
|
|
||||||
LastLunInfo = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create LUN information structure */
|
|
||||||
LunInfo = ExAllocatePoolWithTag(PagedPool, sizeof(SCSI_LUN_INFO), TAG_SCSIPORT);
|
|
||||||
if (!LunInfo)
|
|
||||||
{
|
|
||||||
DPRINT1("Out of resources!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RtlZeroMemory(LunInfo, sizeof(SCSI_LUN_INFO));
|
|
||||||
|
|
||||||
/* Create LunExtension */
|
|
||||||
LunExtension = SpiAllocateLunExtension(DeviceExtension);
|
|
||||||
|
|
||||||
/* And send INQUIRY to every target */
|
/* And send INQUIRY to every target */
|
||||||
for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
|
for (UINT8 targetId = 0;
|
||||||
|
targetId < PortExtension->PortConfig->MaximumNumberOfTargets;
|
||||||
|
targetId++)
|
||||||
{
|
{
|
||||||
|
BOOLEAN targetFound = FALSE;
|
||||||
|
|
||||||
/* TODO: Support scan bottom-up */
|
/* TODO: Support scan bottom-up */
|
||||||
|
|
||||||
/* Skip if it's the same address */
|
/* Skip if it's the same address */
|
||||||
if (Target == BusScanInfo->BusIdentifier)
|
if (targetId == currentBus->BusIdentifier)
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Try to find an existing device here */
|
|
||||||
DeviceExists = FALSE;
|
|
||||||
LunInfoExists = BusScanInfo->LunInfo;
|
|
||||||
|
|
||||||
/* Find matching address on this bus */
|
|
||||||
while (LunInfoExists)
|
|
||||||
{
|
|
||||||
if (LunInfoExists->TargetId == Target)
|
|
||||||
{
|
|
||||||
DeviceExists = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Advance to the next one */
|
|
||||||
LunInfoExists = LunInfoExists->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No need to bother rescanning, since we already did that before */
|
|
||||||
if (DeviceExists)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Scan all logical units */
|
/* Scan all logical units */
|
||||||
for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
|
for (UINT8 lun = 0; lun < PortExtension->MaxLunCount; lun++)
|
||||||
{
|
{
|
||||||
if ((!LunExtension) || (!LunInfo))
|
// try to find an existing device
|
||||||
break;
|
PSCSI_PORT_LUN_EXTENSION lunExt = GetLunByPath(PortExtension,
|
||||||
|
pathId,
|
||||||
|
targetId,
|
||||||
|
lun);
|
||||||
|
|
||||||
/* Add extension to the list */
|
if (lunExt)
|
||||||
Hint = (Target + Lun) % LUS_NUMBER;
|
|
||||||
LunExtension->Next = DeviceExtension->LunExtensionList[Hint];
|
|
||||||
DeviceExtension->LunExtensionList[Hint] = LunExtension;
|
|
||||||
|
|
||||||
/* Fill Path, Target, Lun fields */
|
|
||||||
LunExtension->PathId = LunInfo->PathId = (UCHAR)Bus;
|
|
||||||
LunExtension->TargetId = LunInfo->TargetId = (UCHAR)Target;
|
|
||||||
LunExtension->Lun = LunInfo->Lun = (UCHAR)Lun;
|
|
||||||
|
|
||||||
/* Set flag to prevent race conditions */
|
|
||||||
LunExtension->Flags |= SCSI_PORT_SCAN_IN_PROGRESS;
|
|
||||||
|
|
||||||
/* Zero LU extension contents */
|
|
||||||
if (DeviceExtension->LunExtensionSize)
|
|
||||||
{
|
{
|
||||||
RtlZeroMemory(LunExtension + 1,
|
// check if the device still exists
|
||||||
DeviceExtension->LunExtensionSize);
|
status = FdoSendInquiry(lunExt->Common.DeviceObject);
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
// remove the device
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
__debugbreak();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally send the inquiry command */
|
if (lunExt->InquiryData.DeviceTypeQualifier == DEVICE_QUALIFIER_NOT_SUPPORTED)
|
||||||
Status = SpiSendInquiry(DeviceExtension->DeviceObject, LunInfo);
|
{
|
||||||
|
// remove the device
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
__debugbreak();
|
||||||
|
}
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
/* Decide whether we are continuing or not */
|
||||||
|
if (status == STATUS_INVALID_DEVICE_REQUEST)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a new LUN device
|
||||||
|
PDEVICE_OBJECT lunPDO = PdoCreateLunDevice(PortExtension);
|
||||||
|
if (!lunPDO)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
lunExt = lunPDO->DeviceExtension;
|
||||||
|
|
||||||
|
lunExt->PathId = pathId;
|
||||||
|
lunExt->TargetId = targetId;
|
||||||
|
lunExt->Lun = lun;
|
||||||
|
|
||||||
|
DPRINT("Add PDO to list: PDO: %p, FDOExt: %p, PDOExt: %p\n", lunPDO, PortExtension, lunExt);
|
||||||
|
|
||||||
|
/* Set flag to prevent race conditions */
|
||||||
|
lunExt->Flags |= SCSI_PORT_SCAN_IN_PROGRESS;
|
||||||
|
|
||||||
|
/* Finally send the inquiry command */
|
||||||
|
status = FdoSendInquiry(lunPDO);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(status))
|
||||||
{
|
{
|
||||||
/* Let's see if we really found a device */
|
/* Let's see if we really found a device */
|
||||||
PINQUIRYDATA InquiryData = (PINQUIRYDATA)LunInfo->InquiryData;
|
PINQUIRYDATA InquiryData = &lunExt->InquiryData;
|
||||||
|
|
||||||
/* Check if this device is unsupported */
|
/* Check if this device is unsupported */
|
||||||
if (InquiryData->DeviceTypeQualifier == DEVICE_QUALIFIER_NOT_SUPPORTED)
|
if (InquiryData->DeviceTypeQualifier == DEVICE_QUALIFIER_NOT_SUPPORTED)
|
||||||
{
|
{
|
||||||
DeviceExtension->LunExtensionList[Hint] =
|
IoDeleteDevice(lunPDO);
|
||||||
DeviceExtension->LunExtensionList[Hint]->Next;
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear the "in scan" flag */
|
/* Clear the "in scan" flag */
|
||||||
LunExtension->Flags &= ~SCSI_PORT_SCAN_IN_PROGRESS;
|
lunExt->Flags &= ~SCSI_PORT_SCAN_IN_PROGRESS;
|
||||||
|
|
||||||
DPRINT("SpiScanAdapter(): Found device of type %d at bus %d tid %d lun %d\n",
|
DPRINT("FdoScanAdapter(): Found device of type %d at bus %d tid %d lun %d\n",
|
||||||
InquiryData->DeviceType, Bus, Target, Lun);
|
InquiryData->DeviceType, pathId, targetId, lun);
|
||||||
|
|
||||||
/*
|
InsertTailList(¤tBus->LunsListHead, &lunExt->LunEntry);
|
||||||
* Cache the inquiry data into the LUN extension (or alternatively
|
|
||||||
* we could save a pointer to LunInfo within the LunExtension?)
|
|
||||||
*/
|
|
||||||
RtlCopyMemory(&LunExtension->InquiryData,
|
|
||||||
InquiryData,
|
|
||||||
INQUIRYDATABUFFERSIZE);
|
|
||||||
|
|
||||||
/* Add this info to the linked list */
|
DPRINT1("SCSIPORT: created lun device: %p Status: %x\n", lunPDO, status);
|
||||||
LunInfo->Next = NULL;
|
|
||||||
if (LastLunInfo)
|
|
||||||
LastLunInfo->Next = LunInfo;
|
|
||||||
else
|
|
||||||
BusScanInfo->LunInfo = LunInfo;
|
|
||||||
|
|
||||||
/* Store the last LUN info */
|
totalLUNs++;
|
||||||
LastLunInfo = LunInfo;
|
currentBus->LogicalUnitsCount++;
|
||||||
|
targetFound = TRUE;
|
||||||
/* Store DeviceObject */
|
|
||||||
LunInfo->DeviceObject = DeviceExtension->DeviceObject;
|
|
||||||
|
|
||||||
/* Allocate another buffer */
|
|
||||||
LunInfo = ExAllocatePoolWithTag(PagedPool, sizeof(SCSI_LUN_INFO), TAG_SCSIPORT);
|
|
||||||
if (!LunInfo)
|
|
||||||
{
|
|
||||||
DPRINT1("Out of resources!\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
RtlZeroMemory(LunInfo, sizeof(SCSI_LUN_INFO));
|
|
||||||
|
|
||||||
/* Create a new LU extension */
|
|
||||||
LunExtension = SpiAllocateLunExtension(DeviceExtension);
|
|
||||||
|
|
||||||
DevicesFound++;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Remove this LUN from the list */
|
|
||||||
DeviceExtension->LunExtensionList[Hint] =
|
|
||||||
DeviceExtension->LunExtensionList[Hint]->Next;
|
|
||||||
|
|
||||||
/* Decide whether we are continuing or not */
|
/* Decide whether we are continuing or not */
|
||||||
if (Status == STATUS_INVALID_DEVICE_REQUEST)
|
if (status == STATUS_INVALID_DEVICE_REQUEST)
|
||||||
continue;
|
continue;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (targetFound)
|
||||||
|
{
|
||||||
|
currentBus->TargetsCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free allocated buffers */
|
PortExtension->TotalLUCount = totalLUNs;
|
||||||
if (LunExtension)
|
|
||||||
ExFreePoolWithTag(LunExtension, TAG_SCSIPORT);
|
|
||||||
|
|
||||||
if (LunInfo)
|
|
||||||
ExFreePoolWithTag(LunInfo, TAG_SCSIPORT);
|
|
||||||
|
|
||||||
/* Sum what we found */
|
|
||||||
BusScanInfo->LogicalUnitsCount += (UCHAR)DevicesFound;
|
|
||||||
DPRINT(" Found %d devices on bus %d\n", DevicesFound, Bus);
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("SpiScanAdapter() done\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -456,11 +363,11 @@ SpiScanAdapter(
|
||||||
* @return NTSTATUS of the operation
|
* @return NTSTATUS of the operation
|
||||||
*/
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CallHWInitialize(
|
FdoCallHWInitialize(
|
||||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
||||||
{
|
{
|
||||||
PPORT_CONFIGURATION_INFORMATION PortConfig = DeviceExtension->PortConfig;
|
PPORT_CONFIGURATION_INFORMATION PortConfig = DeviceExtension->PortConfig;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
|
|
||||||
/* Deal with interrupts */
|
/* Deal with interrupts */
|
||||||
|
@ -508,9 +415,13 @@ CallHWInitialize(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DeviceExtension->InterruptCount == 1 || Dirql[0] > Dirql[1])
|
if (DeviceExtension->InterruptCount == 1 || Dirql[0] > Dirql[1])
|
||||||
|
{
|
||||||
MaxDirql = Dirql[0];
|
MaxDirql = Dirql[0];
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
MaxDirql = Dirql[1];
|
MaxDirql = Dirql[1];
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < DeviceExtension->InterruptCount; i++)
|
for (i = 0; i < DeviceExtension->InterruptCount; i++)
|
||||||
{
|
{
|
||||||
|
@ -525,10 +436,16 @@ CallHWInitialize(
|
||||||
InterruptShareable = FALSE;
|
InterruptShareable = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = IoConnectInterrupt(
|
Status = IoConnectInterrupt(&DeviceExtension->Interrupt[i],
|
||||||
&DeviceExtension->Interrupt[i], (PKSERVICE_ROUTINE)ScsiPortIsr, DeviceExtension,
|
ScsiPortIsr,
|
||||||
&DeviceExtension->IrqLock, MappedIrq[i], Dirql[i], MaxDirql, InterruptMode[i],
|
DeviceExtension,
|
||||||
InterruptShareable, Affinity[i], FALSE);
|
&DeviceExtension->IrqLock,
|
||||||
|
MappedIrq[i], Dirql[i],
|
||||||
|
MaxDirql,
|
||||||
|
InterruptMode[i],
|
||||||
|
InterruptShareable,
|
||||||
|
Affinity[i],
|
||||||
|
FALSE);
|
||||||
|
|
||||||
if (!(NT_SUCCESS(Status)))
|
if (!(NT_SUCCESS(Status)))
|
||||||
{
|
{
|
||||||
|
@ -537,9 +454,6 @@ CallHWInitialize(
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
return Status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save IoAddress (from access ranges) */
|
/* Save IoAddress (from access ranges) */
|
||||||
|
@ -583,84 +497,82 @@ CallHWInitialize(
|
||||||
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
|
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
|
||||||
{
|
{
|
||||||
/* Call DPC right away, because we're already at DISPATCH_LEVEL */
|
/* Call DPC right away, because we're already at DISPATCH_LEVEL */
|
||||||
ScsiPortDpcForIsr(NULL, DeviceExtension->DeviceObject, NULL, NULL);
|
ScsiPortDpcForIsr(NULL, DeviceExtension->Common.DeviceObject, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lower irql back to what it was */
|
/* Lower irql back to what it was */
|
||||||
KeLowerIrql(OldIrql);
|
KeLowerIrql(OldIrql);
|
||||||
|
|
||||||
return Status;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
NTSTATUS
|
||||||
SpiCleanupAfterInit(
|
FdoRemoveAdapter(
|
||||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
||||||
{
|
{
|
||||||
PSCSI_LUN_INFO LunInfo;
|
IoStopTimer(DeviceExtension->Common.DeviceObject);
|
||||||
PVOID Ptr;
|
|
||||||
ULONG Bus, Lun;
|
|
||||||
|
|
||||||
/* Check if we have something to clean up */
|
// release device interface
|
||||||
if (DeviceExtension == NULL)
|
if (DeviceExtension->InterfaceName.Buffer)
|
||||||
return;
|
{
|
||||||
|
IoSetDeviceInterfaceState(&DeviceExtension->InterfaceName, FALSE);
|
||||||
|
|
||||||
/* Stop the timer */
|
RtlFreeUnicodeString(&DeviceExtension->InterfaceName);
|
||||||
IoStopTimer(DeviceExtension->DeviceObject);
|
RtlInitUnicodeString(&DeviceExtension->InterfaceName, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Disconnect the interrupts */
|
// remove the dos device link
|
||||||
|
WCHAR dosNameBuffer[12];
|
||||||
|
UNICODE_STRING dosDeviceName;
|
||||||
|
|
||||||
|
swprintf(dosNameBuffer, L"\\??\\Scsi%lu:", DeviceExtension->PortNumber);
|
||||||
|
RtlInitUnicodeString(&dosDeviceName, dosNameBuffer);
|
||||||
|
|
||||||
|
IoDeleteSymbolicLink(&dosDeviceName); // don't check the result
|
||||||
|
|
||||||
|
// decrease the port count
|
||||||
|
if (DeviceExtension->DeviceStarted)
|
||||||
|
{
|
||||||
|
PCONFIGURATION_INFORMATION sysConfig = IoGetConfigurationInformation();
|
||||||
|
sysConfig->ScsiPortCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// disconnect the interrupts
|
||||||
while (DeviceExtension->InterruptCount)
|
while (DeviceExtension->InterruptCount)
|
||||||
{
|
{
|
||||||
if (DeviceExtension->Interrupt[--DeviceExtension->InterruptCount])
|
if (DeviceExtension->Interrupt[--DeviceExtension->InterruptCount])
|
||||||
IoDisconnectInterrupt(DeviceExtension->Interrupt[DeviceExtension->InterruptCount]);
|
IoDisconnectInterrupt(DeviceExtension->Interrupt[DeviceExtension->InterruptCount]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delete ConfigInfo */
|
// FIXME: delete LUNs
|
||||||
if (DeviceExtension->BusesConfig)
|
if (DeviceExtension->Buses)
|
||||||
{
|
{
|
||||||
for (Bus = 0; Bus < DeviceExtension->BusNum; Bus++)
|
for (UINT8 pathId = 0; pathId < DeviceExtension->NumberOfBuses; pathId++)
|
||||||
{
|
{
|
||||||
if (!DeviceExtension->BusesConfig->BusScanInfo[Bus])
|
PSCSI_BUS_INFO bus = &DeviceExtension->Buses[pathId];
|
||||||
continue;
|
if (bus->RegistryMapKey)
|
||||||
|
|
||||||
LunInfo = DeviceExtension->BusesConfig->BusScanInfo[Bus]->LunInfo;
|
|
||||||
|
|
||||||
while (LunInfo)
|
|
||||||
{
|
{
|
||||||
/* Free current, but save pointer to the next one */
|
ZwDeleteKey(bus->RegistryMapKey);
|
||||||
Ptr = LunInfo->Next;
|
ZwClose(bus->RegistryMapKey);
|
||||||
ExFreePool(LunInfo);
|
bus->RegistryMapKey = NULL;
|
||||||
LunInfo = Ptr;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExFreePool(DeviceExtension->BusesConfig->BusScanInfo[Bus]);
|
ExFreePoolWithTag(DeviceExtension->Buses, TAG_SCSIPORT);
|
||||||
}
|
|
||||||
|
|
||||||
ExFreePool(DeviceExtension->BusesConfig);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free PortConfig */
|
/* Free PortConfig */
|
||||||
if (DeviceExtension->PortConfig)
|
if (DeviceExtension->PortConfig)
|
||||||
ExFreePool(DeviceExtension->PortConfig);
|
|
||||||
|
|
||||||
/* Free LUNs*/
|
|
||||||
for(Lun = 0; Lun < LUS_NUMBER; Lun++)
|
|
||||||
{
|
{
|
||||||
while (DeviceExtension->LunExtensionList[Lun])
|
ExFreePoolWithTag(DeviceExtension->PortConfig, TAG_SCSIPORT);
|
||||||
{
|
|
||||||
Ptr = DeviceExtension->LunExtensionList[Lun];
|
|
||||||
DeviceExtension->LunExtensionList[Lun] = DeviceExtension->LunExtensionList[Lun]->Next;
|
|
||||||
|
|
||||||
ExFreePool(Ptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free common buffer (if it exists) */
|
/* Free common buffer (if it exists) */
|
||||||
if (DeviceExtension->SrbExtensionBuffer != NULL &&
|
if (DeviceExtension->SrbExtensionBuffer != NULL && DeviceExtension->CommonBufferLength != 0)
|
||||||
DeviceExtension->CommonBufferLength != 0)
|
|
||||||
{
|
{
|
||||||
if (!DeviceExtension->AdapterObject)
|
if (!DeviceExtension->AdapterObject)
|
||||||
{
|
{
|
||||||
ExFreePool(DeviceExtension->SrbExtensionBuffer);
|
ExFreePoolWithTag(DeviceExtension->SrbExtensionBuffer, TAG_SCSIPORT);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -674,7 +586,7 @@ SpiCleanupAfterInit(
|
||||||
|
|
||||||
/* Free SRB info */
|
/* Free SRB info */
|
||||||
if (DeviceExtension->SrbInfo != NULL)
|
if (DeviceExtension->SrbInfo != NULL)
|
||||||
ExFreePool(DeviceExtension->SrbInfo);
|
ExFreePoolWithTag(DeviceExtension->SrbInfo, TAG_SCSIPORT);
|
||||||
|
|
||||||
/* Unmap mapped addresses */
|
/* Unmap mapped addresses */
|
||||||
while (DeviceExtension->MappedAddressList != NULL)
|
while (DeviceExtension->MappedAddressList != NULL)
|
||||||
|
@ -682,13 +594,161 @@ SpiCleanupAfterInit(
|
||||||
MmUnmapIoSpace(DeviceExtension->MappedAddressList->MappedAddress,
|
MmUnmapIoSpace(DeviceExtension->MappedAddressList->MappedAddress,
|
||||||
DeviceExtension->MappedAddressList->NumberOfBytes);
|
DeviceExtension->MappedAddressList->NumberOfBytes);
|
||||||
|
|
||||||
Ptr = DeviceExtension->MappedAddressList;
|
PVOID ptr = DeviceExtension->MappedAddressList;
|
||||||
DeviceExtension->MappedAddressList = DeviceExtension->MappedAddressList->NextMappedAddress;
|
DeviceExtension->MappedAddressList = DeviceExtension->MappedAddressList->NextMappedAddress;
|
||||||
|
|
||||||
ExFreePool(Ptr);
|
ExFreePoolWithTag(ptr, TAG_SCSIPORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally delete the device object */
|
IoDeleteDevice(DeviceExtension->Common.DeviceObject);
|
||||||
DPRINT("Deleting device %p\n", DeviceExtension->DeviceObject);
|
|
||||||
IoDeleteDevice(DeviceExtension->DeviceObject);
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
FdoStartAdapter(
|
||||||
|
_In_ PSCSI_PORT_DEVICE_EXTENSION PortExtension)
|
||||||
|
{
|
||||||
|
WCHAR dosNameBuffer[12];
|
||||||
|
UNICODE_STRING dosDeviceName;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
// Start our timer
|
||||||
|
IoStartTimer(PortExtension->Common.DeviceObject);
|
||||||
|
|
||||||
|
// Create the dos device link
|
||||||
|
swprintf(dosNameBuffer, L"\\??\\Scsi%u:", PortExtension->PortNumber);
|
||||||
|
RtlInitUnicodeString(&dosDeviceName, dosNameBuffer);
|
||||||
|
status = IoCreateSymbolicLink(&dosDeviceName, &PortExtension->DeviceName);
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start building a device map
|
||||||
|
RegistryInitAdapterKey(PortExtension);
|
||||||
|
|
||||||
|
// increase the port count
|
||||||
|
PCONFIGURATION_INFORMATION sysConfig = IoGetConfigurationInformation();
|
||||||
|
sysConfig->ScsiPortCount++;
|
||||||
|
|
||||||
|
// Register and enable the device interface
|
||||||
|
status = IoRegisterDeviceInterface(PortExtension->Common.DeviceObject,
|
||||||
|
&StoragePortClassGuid,
|
||||||
|
NULL,
|
||||||
|
&PortExtension->InterfaceName);
|
||||||
|
DPRINT("IoRegisterDeviceInterface status: %x, InterfaceName: %wZ\n",
|
||||||
|
status, &PortExtension->InterfaceName);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
IoSetDeviceInterfaceState(&PortExtension->InterfaceName, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
PortExtension->DeviceStarted = TRUE;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
FdoHandleDeviceRelations(
|
||||||
|
_In_ PSCSI_PORT_DEVICE_EXTENSION PortExtension,
|
||||||
|
_Inout_ PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
// FDO always only handles bus relations
|
||||||
|
if (ioStack->Parameters.QueryDeviceRelations.Type == BusRelations)
|
||||||
|
{
|
||||||
|
FdoScanAdapter(PortExtension);
|
||||||
|
DPRINT("Found %u PD objects, FDOExt: %p\n", PortExtension->TotalLUCount, PortExtension);
|
||||||
|
|
||||||
|
// check that no filter driver has messed up this
|
||||||
|
ASSERT(Irp->IoStatus.Information == 0);
|
||||||
|
|
||||||
|
PDEVICE_RELATIONS deviceRelations =
|
||||||
|
ExAllocatePoolWithTag(PagedPool,
|
||||||
|
(sizeof(DEVICE_RELATIONS) +
|
||||||
|
sizeof(PDEVICE_OBJECT) * (PortExtension->TotalLUCount - 1)),
|
||||||
|
TAG_SCSIPORT);
|
||||||
|
|
||||||
|
if (!deviceRelations)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceRelations->Count = 0;
|
||||||
|
|
||||||
|
for (UINT8 pathId = 0; pathId < PortExtension->NumberOfBuses; pathId++)
|
||||||
|
{
|
||||||
|
PSCSI_BUS_INFO bus = &PortExtension->Buses[pathId];
|
||||||
|
|
||||||
|
for (PLIST_ENTRY lunEntry = bus->LunsListHead.Flink;
|
||||||
|
lunEntry != &bus->LunsListHead;
|
||||||
|
lunEntry = lunEntry->Flink)
|
||||||
|
{
|
||||||
|
PSCSI_PORT_LUN_EXTENSION lunExt =
|
||||||
|
CONTAINING_RECORD(lunEntry, SCSI_PORT_LUN_EXTENSION, LunEntry);
|
||||||
|
|
||||||
|
deviceRelations->Objects[deviceRelations->Count++] = lunExt->Common.DeviceObject;
|
||||||
|
ObReferenceObject(lunExt->Common.DeviceObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(deviceRelations->Count == PortExtension->TotalLUCount);
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = (ULONG_PTR)deviceRelations;
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
IoSkipCurrentIrpStackLocation(Irp);
|
||||||
|
return IoCallDriver(PortExtension->Common.LowerDevice, Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
FdoDispatchPnp(
|
||||||
|
_In_ PDEVICE_OBJECT DeviceObject,
|
||||||
|
_Inout_ PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
PSCSI_PORT_DEVICE_EXTENSION portExt = DeviceObject->DeviceExtension;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
ASSERT(portExt->Common.IsFDO);
|
||||||
|
|
||||||
|
DPRINT("FDO PnP request %s\n", GetIRPMinorFunctionString(ioStack->MinorFunction));
|
||||||
|
|
||||||
|
switch (ioStack->MinorFunction)
|
||||||
|
{
|
||||||
|
case IRP_MN_START_DEVICE:
|
||||||
|
{
|
||||||
|
// as we don't support PnP yet, this is a no-op for us
|
||||||
|
// (FdoStartAdapter is being called during initialization for legacy miniports)
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
// status = FdoStartAdapter(DeviceExtension);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
||||||
|
{
|
||||||
|
return FdoHandleDeviceRelations(portExt, Irp);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// forward irp to next device object
|
||||||
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
||||||
|
return IoCallDriver(portExt->Common.LowerDevice, Irp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != STATUS_PENDING)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Status = status;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
11
drivers/storage/port/scsiport/guid.c
Normal file
11
drivers/storage/port/scsiport/guid.c
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */
|
||||||
|
|
||||||
|
#include <ntdef.h>
|
||||||
|
#include <initguid.h>
|
||||||
|
#include <ioevent.h>
|
||||||
|
#include <wdmguid.h>
|
||||||
|
|
||||||
|
#define DEVICE_TYPE ULONG
|
||||||
|
#include <ntddstor.h>
|
||||||
|
|
||||||
|
/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */
|
|
@ -4,6 +4,7 @@
|
||||||
* PURPOSE: IOCTL handlers
|
* PURPOSE: IOCTL handlers
|
||||||
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
||||||
* Aleksey Bragin (aleksey@reactos.org)
|
* Aleksey Bragin (aleksey@reactos.org)
|
||||||
|
* 2020 Victor Perevertkin (victor.perevertkin@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "scsiport.h"
|
#include "scsiport.h"
|
||||||
|
@ -19,13 +20,10 @@ SpiGetInquiryData(
|
||||||
_In_ PIRP Irp)
|
_In_ PIRP Irp)
|
||||||
{
|
{
|
||||||
ULONG InquiryDataSize;
|
ULONG InquiryDataSize;
|
||||||
PSCSI_LUN_INFO LunInfo;
|
ULONG BusCount, Length;
|
||||||
ULONG BusCount, LunCount, Length;
|
|
||||||
PIO_STACK_LOCATION IrpStack;
|
PIO_STACK_LOCATION IrpStack;
|
||||||
PSCSI_ADAPTER_BUS_INFO AdapterBusInfo;
|
PSCSI_ADAPTER_BUS_INFO AdapterBusInfo;
|
||||||
PSCSI_INQUIRY_DATA InquiryData;
|
PSCSI_INQUIRY_DATA InquiryData;
|
||||||
PSCSI_BUS_DATA BusData;
|
|
||||||
ULONG Bus;
|
|
||||||
PUCHAR Buffer;
|
PUCHAR Buffer;
|
||||||
|
|
||||||
DPRINT("SpiGetInquiryData() called\n");
|
DPRINT("SpiGetInquiryData() called\n");
|
||||||
|
@ -35,22 +33,15 @@ SpiGetInquiryData(
|
||||||
Buffer = Irp->AssociatedIrp.SystemBuffer;
|
Buffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
|
||||||
/* Initialize bus and LUN counters */
|
/* Initialize bus and LUN counters */
|
||||||
BusCount = DeviceExtension->BusesConfig->NumberOfBuses;
|
BusCount = DeviceExtension->NumberOfBuses;
|
||||||
LunCount = 0;
|
|
||||||
|
|
||||||
/* Calculate total number of LUNs */
|
|
||||||
for (Bus = 0; Bus < BusCount; Bus++)
|
|
||||||
LunCount += DeviceExtension->BusesConfig->BusScanInfo[Bus]->LogicalUnitsCount;
|
|
||||||
|
|
||||||
/* Calculate size of inquiry data, rounding up to sizeof(ULONG) */
|
/* Calculate size of inquiry data, rounding up to sizeof(ULONG) */
|
||||||
InquiryDataSize =
|
InquiryDataSize = ALIGN_UP(sizeof(SCSI_INQUIRY_DATA) - 1 + INQUIRYDATABUFFERSIZE, ULONG);
|
||||||
((sizeof(SCSI_INQUIRY_DATA) - 1 + INQUIRYDATABUFFERSIZE +
|
|
||||||
sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1));
|
|
||||||
|
|
||||||
/* Calculate data size */
|
/* Calculate data size */
|
||||||
Length = sizeof(SCSI_ADAPTER_BUS_INFO) + (BusCount - 1) * sizeof(SCSI_BUS_DATA);
|
Length = sizeof(SCSI_ADAPTER_BUS_INFO) + (BusCount - 1) * sizeof(SCSI_BUS_DATA);
|
||||||
|
|
||||||
Length += InquiryDataSize * LunCount;
|
Length += InquiryDataSize * DeviceExtension->TotalLUCount;
|
||||||
|
|
||||||
/* Check, if all data is going to fit into provided buffer */
|
/* Check, if all data is going to fit into provided buffer */
|
||||||
if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < Length)
|
if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < Length)
|
||||||
|
@ -73,47 +64,47 @@ SpiGetInquiryData(
|
||||||
(BusCount - 1) * sizeof(SCSI_BUS_DATA));
|
(BusCount - 1) * sizeof(SCSI_BUS_DATA));
|
||||||
|
|
||||||
/* Loop each bus */
|
/* Loop each bus */
|
||||||
for (Bus = 0; Bus < BusCount; Bus++)
|
for (UINT8 pathId = 0; pathId < DeviceExtension->NumberOfBuses; pathId++)
|
||||||
{
|
{
|
||||||
BusData = &AdapterBusInfo->BusData[Bus];
|
PSCSI_BUS_DATA BusData = &AdapterBusInfo->BusData[pathId];
|
||||||
|
|
||||||
/* Calculate and save an offset of the inquiry data */
|
/* Calculate and save an offset of the inquiry data */
|
||||||
BusData->InquiryDataOffset = (ULONG)((PUCHAR)InquiryData - Buffer);
|
BusData->InquiryDataOffset = (ULONG)((PUCHAR)InquiryData - Buffer);
|
||||||
|
|
||||||
/* Get a pointer to the LUN information structure */
|
|
||||||
LunInfo = DeviceExtension->BusesConfig->BusScanInfo[Bus]->LunInfo;
|
|
||||||
|
|
||||||
/* Store Initiator Bus Id */
|
/* Store Initiator Bus Id */
|
||||||
BusData->InitiatorBusId =
|
BusData->InitiatorBusId = DeviceExtension->Buses[pathId].BusIdentifier;
|
||||||
DeviceExtension->BusesConfig->BusScanInfo[Bus]->BusIdentifier;
|
|
||||||
|
|
||||||
/* Store LUN count */
|
/* Store LUN count */
|
||||||
BusData->NumberOfLogicalUnits =
|
BusData->NumberOfLogicalUnits = DeviceExtension->Buses[pathId].LogicalUnitsCount;
|
||||||
DeviceExtension->BusesConfig->BusScanInfo[Bus]->LogicalUnitsCount;
|
|
||||||
|
|
||||||
/* Loop all LUNs */
|
/* Loop all LUNs */
|
||||||
while (LunInfo != NULL)
|
PSCSI_BUS_INFO bus = &DeviceExtension->Buses[pathId];
|
||||||
|
|
||||||
|
for (PLIST_ENTRY lunEntry = bus->LunsListHead.Flink;
|
||||||
|
lunEntry != &bus->LunsListHead;
|
||||||
|
lunEntry = lunEntry->Flink)
|
||||||
{
|
{
|
||||||
DPRINT("(Bus %lu Target %lu Lun %lu)\n",
|
PSCSI_PORT_LUN_EXTENSION lunExt =
|
||||||
Bus, LunInfo->TargetId, LunInfo->Lun);
|
CONTAINING_RECORD(lunEntry, SCSI_PORT_LUN_EXTENSION, LunEntry);
|
||||||
|
|
||||||
|
DPRINT("(Bus %lu Target %lu Lun %lu)\n", pathId, lunExt->TargetId, lunExt->Lun);
|
||||||
|
|
||||||
/* Fill InquiryData with values */
|
/* Fill InquiryData with values */
|
||||||
InquiryData->PathId = LunInfo->PathId;
|
InquiryData->PathId = lunExt->PathId;
|
||||||
InquiryData->TargetId = LunInfo->TargetId;
|
InquiryData->TargetId = lunExt->TargetId;
|
||||||
InquiryData->Lun = LunInfo->Lun;
|
InquiryData->Lun = lunExt->Lun;
|
||||||
InquiryData->InquiryDataLength = INQUIRYDATABUFFERSIZE;
|
InquiryData->InquiryDataLength = INQUIRYDATABUFFERSIZE;
|
||||||
InquiryData->DeviceClaimed = LunInfo->DeviceClaimed;
|
InquiryData->DeviceClaimed = lunExt->DeviceClaimed;
|
||||||
InquiryData->NextInquiryDataOffset =
|
InquiryData->NextInquiryDataOffset =
|
||||||
(ULONG)((PUCHAR)InquiryData + InquiryDataSize - Buffer);
|
(ULONG)((PUCHAR)InquiryData + InquiryDataSize - Buffer);
|
||||||
|
|
||||||
/* Copy data in it */
|
/* Copy data in it */
|
||||||
RtlCopyMemory(InquiryData->InquiryData,
|
RtlCopyMemory(InquiryData->InquiryData,
|
||||||
LunInfo->InquiryData,
|
&lunExt->InquiryData,
|
||||||
INQUIRYDATABUFFERSIZE);
|
INQUIRYDATABUFFERSIZE);
|
||||||
|
|
||||||
/* Move to the next LUN */
|
/* Move to the next LUN */
|
||||||
LunInfo = LunInfo->Next;
|
InquiryData = (PSCSI_INQUIRY_DATA) ((ULONG_PTR)InquiryData + InquiryDataSize);
|
||||||
InquiryData = (PSCSI_INQUIRY_DATA) ((PCHAR)InquiryData + InquiryDataSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Either mark the end, or set offset to 0 */
|
/* Either mark the end, or set offset to 0 */
|
||||||
|
@ -128,6 +119,269 @@ SpiGetInquiryData(
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
UINT32
|
||||||
|
GetFieldLength(
|
||||||
|
_In_ PUCHAR Name,
|
||||||
|
_In_ UINT32 MaxLength)
|
||||||
|
{
|
||||||
|
UINT32 Index;
|
||||||
|
UINT32 LastCharacterPosition = 0;
|
||||||
|
|
||||||
|
// scan the field and return last position which contains a valid character
|
||||||
|
for (Index = 0; Index < MaxLength; Index++)
|
||||||
|
{
|
||||||
|
if (Name[Index] != ' ')
|
||||||
|
{
|
||||||
|
// trim white spaces from field
|
||||||
|
LastCharacterPosition = Index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert from zero based index to length
|
||||||
|
return LastCharacterPosition + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
PdoHandleQueryProperty(
|
||||||
|
_In_ PDEVICE_OBJECT DeviceObject,
|
||||||
|
_Inout_ PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
PSCSI_PORT_LUN_EXTENSION lunExt = DeviceObject->DeviceExtension;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
ASSERT(ioStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(STORAGE_PROPERTY_QUERY));
|
||||||
|
ASSERT(Irp->AssociatedIrp.SystemBuffer);
|
||||||
|
ASSERT(!lunExt->Common.IsFDO);
|
||||||
|
|
||||||
|
PSTORAGE_PROPERTY_QUERY PropertyQuery = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
|
||||||
|
// check property type
|
||||||
|
if (PropertyQuery->PropertyId != StorageDeviceProperty &&
|
||||||
|
PropertyQuery->PropertyId != StorageAdapterProperty)
|
||||||
|
{
|
||||||
|
// only device property / adapter property are supported
|
||||||
|
status = STATUS_INVALID_PARAMETER_1;
|
||||||
|
goto completeIrp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check query type
|
||||||
|
if (PropertyQuery->QueryType == PropertyExistsQuery)
|
||||||
|
{
|
||||||
|
// device property / adapter property is supported
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
goto completeIrp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PropertyQuery->QueryType != PropertyStandardQuery)
|
||||||
|
{
|
||||||
|
// only standard query and exists query are supported
|
||||||
|
status = STATUS_INVALID_PARAMETER_2;
|
||||||
|
goto completeIrp;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (PropertyQuery->PropertyId)
|
||||||
|
{
|
||||||
|
case StorageDeviceProperty:
|
||||||
|
{
|
||||||
|
PINQUIRYDATA inquiryData = &lunExt->InquiryData;
|
||||||
|
|
||||||
|
// compute extra parameters length
|
||||||
|
UINT32 FieldLengthVendor = GetFieldLength(inquiryData->VendorId, 8),
|
||||||
|
FieldLengthProduct = GetFieldLength(inquiryData->ProductId, 16),
|
||||||
|
FieldLengthRevision = GetFieldLength(inquiryData->ProductRevisionLevel, 4);
|
||||||
|
|
||||||
|
// total length required is sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLength + 4 extra null bytes - 1
|
||||||
|
// -1 due STORAGE_DEVICE_DESCRIPTOR contains one byte length of parameter data
|
||||||
|
UINT32 TotalLength = sizeof(STORAGE_DEVICE_DESCRIPTOR)
|
||||||
|
+ FieldLengthVendor
|
||||||
|
+ FieldLengthProduct
|
||||||
|
+ FieldLengthRevision
|
||||||
|
+ 3;
|
||||||
|
|
||||||
|
// check if output buffer is long enough
|
||||||
|
if (ioStack->Parameters.DeviceIoControl.OutputBufferLength < TotalLength)
|
||||||
|
{
|
||||||
|
// buffer too small
|
||||||
|
PSTORAGE_DESCRIPTOR_HEADER DescriptorHeader = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
ASSERT(ioStack->Parameters.DeviceIoControl.OutputBufferLength >=
|
||||||
|
sizeof(STORAGE_DESCRIPTOR_HEADER));
|
||||||
|
|
||||||
|
// return required size
|
||||||
|
DescriptorHeader->Version = TotalLength;
|
||||||
|
DescriptorHeader->Size = TotalLength;
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER);
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
goto completeIrp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize the device descriptor
|
||||||
|
PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
|
||||||
|
deviceDescriptor->Version = sizeof(STORAGE_DEVICE_DESCRIPTOR);
|
||||||
|
deviceDescriptor->Size = TotalLength;
|
||||||
|
deviceDescriptor->DeviceType = inquiryData->DeviceType;
|
||||||
|
deviceDescriptor->DeviceTypeModifier = inquiryData->DeviceTypeModifier;
|
||||||
|
deviceDescriptor->RemovableMedia = inquiryData->RemovableMedia;
|
||||||
|
deviceDescriptor->CommandQueueing = inquiryData->CommandQueue;
|
||||||
|
deviceDescriptor->BusType = BusTypeScsi;
|
||||||
|
deviceDescriptor->VendorIdOffset =
|
||||||
|
FIELD_OFFSET(STORAGE_DEVICE_DESCRIPTOR, RawDeviceProperties);
|
||||||
|
deviceDescriptor->ProductIdOffset =
|
||||||
|
deviceDescriptor->VendorIdOffset + FieldLengthVendor + 1;
|
||||||
|
deviceDescriptor->ProductRevisionOffset =
|
||||||
|
deviceDescriptor->ProductIdOffset + FieldLengthProduct + 1;
|
||||||
|
deviceDescriptor->SerialNumberOffset = 0;
|
||||||
|
deviceDescriptor->RawPropertiesLength =
|
||||||
|
FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + 3;
|
||||||
|
|
||||||
|
// copy descriptors
|
||||||
|
PUCHAR Buffer = deviceDescriptor->RawDeviceProperties;
|
||||||
|
|
||||||
|
RtlCopyMemory(Buffer, inquiryData->VendorId, FieldLengthVendor);
|
||||||
|
Buffer[FieldLengthVendor] = '\0';
|
||||||
|
Buffer += FieldLengthVendor + 1;
|
||||||
|
|
||||||
|
RtlCopyMemory(Buffer, inquiryData->ProductId, FieldLengthProduct);
|
||||||
|
Buffer[FieldLengthProduct] = '\0';
|
||||||
|
Buffer += FieldLengthProduct + 1;
|
||||||
|
|
||||||
|
RtlCopyMemory(Buffer, inquiryData->ProductRevisionLevel, FieldLengthRevision);
|
||||||
|
Buffer[FieldLengthRevision] = '\0';
|
||||||
|
Buffer += FieldLengthRevision + 1;
|
||||||
|
|
||||||
|
DPRINT("Vendor %s\n",
|
||||||
|
(LPCSTR)((ULONG_PTR)deviceDescriptor + deviceDescriptor->VendorIdOffset));
|
||||||
|
DPRINT("Product %s\n",
|
||||||
|
(LPCSTR)((ULONG_PTR)deviceDescriptor + deviceDescriptor->ProductIdOffset));
|
||||||
|
DPRINT("Revision %s\n",
|
||||||
|
(LPCSTR)((ULONG_PTR)deviceDescriptor + deviceDescriptor->ProductRevisionOffset));
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = TotalLength;
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
goto completeIrp;
|
||||||
|
}
|
||||||
|
case StorageAdapterProperty:
|
||||||
|
{
|
||||||
|
// forward to the lower device
|
||||||
|
IoSkipCurrentIrpStackLocation(Irp);
|
||||||
|
return IoCallDriver(lunExt->Common.LowerDevice, Irp);
|
||||||
|
}
|
||||||
|
case StorageDeviceIdProperty:
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
UNREACHABLE;
|
||||||
|
status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
goto completeIrp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
completeIrp:
|
||||||
|
Irp->IoStatus.Status = status;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
FdoHandleQueryProperty(
|
||||||
|
_In_ PDEVICE_OBJECT DeviceObject,
|
||||||
|
_Inout_ PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
PSCSI_PORT_DEVICE_EXTENSION portExt = DeviceObject->DeviceExtension;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
ASSERT(ioStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(STORAGE_PROPERTY_QUERY));
|
||||||
|
ASSERT(Irp->AssociatedIrp.SystemBuffer);
|
||||||
|
ASSERT(portExt->Common.IsFDO);
|
||||||
|
|
||||||
|
PSTORAGE_PROPERTY_QUERY PropertyQuery = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
|
||||||
|
// check property type (handle only StorageAdapterProperty)
|
||||||
|
if (PropertyQuery->PropertyId != StorageAdapterProperty)
|
||||||
|
{
|
||||||
|
if (PropertyQuery->PropertyId == StorageDeviceProperty ||
|
||||||
|
PropertyQuery->PropertyId == StorageDeviceIdProperty)
|
||||||
|
{
|
||||||
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = STATUS_INVALID_PARAMETER_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto completeIrp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check query type
|
||||||
|
if (PropertyQuery->QueryType == PropertyExistsQuery)
|
||||||
|
{
|
||||||
|
// device property / adapter property is supported
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
goto completeIrp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PropertyQuery->QueryType != PropertyStandardQuery)
|
||||||
|
{
|
||||||
|
// only standard query and exists query are supported
|
||||||
|
status = STATUS_INVALID_PARAMETER_2;
|
||||||
|
goto completeIrp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_ADAPTER_DESCRIPTOR))
|
||||||
|
{
|
||||||
|
// buffer too small
|
||||||
|
PSTORAGE_DESCRIPTOR_HEADER DescriptorHeader = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
ASSERT(ioStack->Parameters.DeviceIoControl.OutputBufferLength
|
||||||
|
>= sizeof(STORAGE_DESCRIPTOR_HEADER));
|
||||||
|
|
||||||
|
// return required size
|
||||||
|
DescriptorHeader->Version = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
|
||||||
|
DescriptorHeader->Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER);
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
goto completeIrp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get adapter descriptor, information is returned in the same buffer
|
||||||
|
PSTORAGE_ADAPTER_DESCRIPTOR adapterDescriptor = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
|
||||||
|
// fill out descriptor
|
||||||
|
// NOTE: STORAGE_ADAPTER_DESCRIPTOR may vary in size, so it's important to zero out
|
||||||
|
// all unused fields
|
||||||
|
*adapterDescriptor = (STORAGE_ADAPTER_DESCRIPTOR) {
|
||||||
|
.Version = sizeof(STORAGE_ADAPTER_DESCRIPTOR),
|
||||||
|
.Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR),
|
||||||
|
.MaximumTransferLength = portExt->PortCapabilities.MaximumTransferLength,
|
||||||
|
.MaximumPhysicalPages = portExt->PortCapabilities.MaximumPhysicalPages,
|
||||||
|
.AlignmentMask = portExt->PortCapabilities.AlignmentMask,
|
||||||
|
.AdapterUsesPio = portExt->PortCapabilities.AdapterUsesPio,
|
||||||
|
.AdapterScansDown = portExt->PortCapabilities.AdapterScansDown,
|
||||||
|
.CommandQueueing = portExt->PortCapabilities.TaggedQueuing,
|
||||||
|
.AcceleratedTransfer = TRUE,
|
||||||
|
.BusType = BusTypeScsi, // FIXME
|
||||||
|
.BusMajorVersion = 2,
|
||||||
|
.BusMinorVersion = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// store returned length
|
||||||
|
Irp->IoStatus.Information = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
completeIrp:
|
||||||
|
Irp->IoStatus.Status = status;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* NAME INTERNAL
|
* NAME INTERNAL
|
||||||
* ScsiPortDeviceControl
|
* ScsiPortDeviceControl
|
||||||
|
@ -152,104 +406,147 @@ ScsiPortDeviceControl(
|
||||||
_In_ PIRP Irp)
|
_In_ PIRP Irp)
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION Stack;
|
PIO_STACK_LOCATION Stack;
|
||||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
PSCSI_PORT_COMMON_EXTENSION comExt = DeviceObject->DeviceExtension;
|
||||||
PDUMP_POINTERS DumpPointers;
|
PSCSI_PORT_DEVICE_EXTENSION portExt;
|
||||||
NTSTATUS Status;
|
PSCSI_PORT_LUN_EXTENSION lunExt;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
DPRINT("ScsiPortDeviceControl()\n");
|
DPRINT("ScsiPortDeviceControl()\n");
|
||||||
|
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
DeviceExtension = DeviceObject->DeviceExtension;
|
|
||||||
|
|
||||||
switch (Stack->Parameters.DeviceIoControl.IoControlCode)
|
switch (Stack->Parameters.DeviceIoControl.IoControlCode)
|
||||||
{
|
{
|
||||||
|
case IOCTL_STORAGE_QUERY_PROPERTY:
|
||||||
|
{
|
||||||
|
DPRINT(" IOCTL_STORAGE_QUERY_PROPERTY\n");
|
||||||
|
|
||||||
|
if (!VerifyIrpInBufferSize(Irp, sizeof(STORAGE_PROPERTY_QUERY)))
|
||||||
|
{
|
||||||
|
status = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comExt->IsFDO)
|
||||||
|
return FdoHandleQueryProperty(DeviceObject, Irp);
|
||||||
|
else
|
||||||
|
return PdoHandleQueryProperty(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
case IOCTL_SCSI_GET_ADDRESS:
|
||||||
|
{
|
||||||
|
DPRINT(" IOCTL_SCSI_GET_ADDRESS\n");
|
||||||
|
|
||||||
|
if (comExt->IsFDO)
|
||||||
|
{
|
||||||
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PSCSI_ADDRESS address = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
if (!VerifyIrpOutBufferSize(Irp, sizeof(*address)))
|
||||||
|
{
|
||||||
|
status = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lunExt = DeviceObject->DeviceExtension;
|
||||||
|
portExt = comExt->LowerDevice->DeviceExtension;
|
||||||
|
|
||||||
|
address->Length = sizeof(SCSI_ADDRESS);
|
||||||
|
address->PortNumber = portExt->PortNumber;
|
||||||
|
address->PathId = lunExt->PathId;
|
||||||
|
address->TargetId = lunExt->TargetId;
|
||||||
|
address->Lun = lunExt->Lun;
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case IOCTL_SCSI_GET_DUMP_POINTERS:
|
case IOCTL_SCSI_GET_DUMP_POINTERS:
|
||||||
|
{
|
||||||
DPRINT(" IOCTL_SCSI_GET_DUMP_POINTERS\n");
|
DPRINT(" IOCTL_SCSI_GET_DUMP_POINTERS\n");
|
||||||
|
|
||||||
if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DUMP_POINTERS))
|
if (!comExt->IsFDO)
|
||||||
{
|
{
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
IoSkipCurrentIrpStackLocation(Irp);
|
||||||
Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
|
return IoCallDriver(comExt->LowerDevice, Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDUMP_POINTERS dumpPointers = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
if (!VerifyIrpOutBufferSize(Irp, sizeof(*dumpPointers)))
|
||||||
|
{
|
||||||
|
status = STATUS_BUFFER_TOO_SMALL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
DumpPointers = Irp->AssociatedIrp.SystemBuffer;
|
dumpPointers->DeviceObject = DeviceObject;
|
||||||
DumpPointers->DeviceObject = DeviceObject;
|
|
||||||
/* More data.. ? */
|
/* More data.. ? */
|
||||||
|
|
||||||
Status = STATUS_SUCCESS;
|
status = STATUS_SUCCESS;
|
||||||
Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
|
Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case IOCTL_SCSI_GET_CAPABILITIES:
|
case IOCTL_SCSI_GET_CAPABILITIES:
|
||||||
|
{
|
||||||
DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
|
DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
|
||||||
if (Stack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(PVOID))
|
|
||||||
{
|
|
||||||
*((PVOID *)Irp->AssociatedIrp.SystemBuffer) = &DeviceExtension->PortCapabilities;
|
|
||||||
|
|
||||||
Irp->IoStatus.Information = sizeof(PVOID);
|
if (!comExt->IsFDO)
|
||||||
Status = STATUS_SUCCESS;
|
{
|
||||||
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(IO_SCSI_CAPABILITIES))
|
if (!VerifyIrpOutBufferSize(Irp, sizeof(IO_SCSI_CAPABILITIES)))
|
||||||
{
|
{
|
||||||
Status = STATUS_BUFFER_TOO_SMALL;
|
status = STATUS_BUFFER_TOO_SMALL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
portExt = DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
|
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
|
||||||
&DeviceExtension->PortCapabilities,
|
&portExt->PortCapabilities,
|
||||||
sizeof(IO_SCSI_CAPABILITIES));
|
sizeof(IO_SCSI_CAPABILITIES));
|
||||||
|
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
|
Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case IOCTL_SCSI_GET_INQUIRY_DATA:
|
case IOCTL_SCSI_GET_INQUIRY_DATA:
|
||||||
|
{
|
||||||
DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
|
DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
|
||||||
|
|
||||||
/* Copy inquiry data to the port device extension */
|
if (!comExt->IsFDO)
|
||||||
Status = SpiGetInquiryData(DeviceExtension, Irp);
|
{
|
||||||
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy inquiry data to the port device extension */
|
||||||
|
status = SpiGetInquiryData(DeviceObject->DeviceExtension, Irp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case IOCTL_SCSI_MINIPORT:
|
case IOCTL_SCSI_MINIPORT:
|
||||||
DPRINT1("IOCTL_SCSI_MINIPORT unimplemented!\n");
|
DPRINT1("IOCTL_SCSI_MINIPORT unimplemented!\n");
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
status = STATUS_NOT_IMPLEMENTED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_SCSI_PASS_THROUGH:
|
case IOCTL_SCSI_PASS_THROUGH:
|
||||||
DPRINT1("IOCTL_SCSI_PASS_THROUGH unimplemented!\n");
|
DPRINT1("IOCTL_SCSI_PASS_THROUGH unimplemented!\n");
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
status = STATUS_NOT_IMPLEMENTED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (DEVICE_TYPE_FROM_CTL_CODE(Stack->Parameters.DeviceIoControl.IoControlCode) == MOUNTDEVCONTROLTYPE)
|
DPRINT1("unknown ioctl code: 0x%lX\n", Stack->Parameters.DeviceIoControl.IoControlCode);
|
||||||
{
|
status = STATUS_NOT_SUPPORTED;
|
||||||
switch (Stack->Parameters.DeviceIoControl.IoControlCode)
|
|
||||||
{
|
|
||||||
case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
|
|
||||||
DPRINT1("Got unexpected IOCTL_MOUNTDEV_QUERY_DEVICE_NAME\n");
|
|
||||||
break;
|
|
||||||
case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:
|
|
||||||
DPRINT1("Got unexpected IOCTL_MOUNTDEV_QUERY_UNIQUE_ID\n");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DPRINT(" got ioctl intended for the mount manager: 0x%lX\n", Stack->Parameters.DeviceIoControl.IoControlCode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DPRINT1(" unknown ioctl code: 0x%lX\n", Stack->Parameters.DeviceIoControl.IoControlCode);
|
|
||||||
}
|
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Complete the request with the given status */
|
/* Complete the request with the given status */
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = status;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
return Status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,40 +4,48 @@
|
||||||
* PURPOSE: Logical Unit (PDO) functions
|
* PURPOSE: Logical Unit (PDO) functions
|
||||||
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
||||||
* Aleksey Bragin (aleksey@reactos.org)
|
* Aleksey Bragin (aleksey@reactos.org)
|
||||||
|
* 2020 Victor Perevertkin (victor.perevertkin@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "scsiport.h"
|
#include "scsiport.h"
|
||||||
|
#include "scsitypes.h"
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
|
||||||
PSCSI_PORT_LUN_EXTENSION
|
PDEVICE_OBJECT
|
||||||
SpiAllocateLunExtension(
|
PdoCreateLunDevice(
|
||||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
||||||
{
|
{
|
||||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
||||||
ULONG LunExtensionSize;
|
PDEVICE_OBJECT LunPDO;
|
||||||
|
|
||||||
DPRINT("SpiAllocateLunExtension(%p)\n", DeviceExtension);
|
ULONG LunExtensionSize = DeviceExtension->LunExtensionSize + sizeof(SCSI_PORT_LUN_EXTENSION);
|
||||||
|
|
||||||
/* Round LunExtensionSize first to the sizeof LONGLONG */
|
NTSTATUS Status = IoCreateDevice(DeviceExtension->Common.DeviceObject->DriverObject,
|
||||||
LunExtensionSize = (DeviceExtension->LunExtensionSize +
|
LunExtensionSize,
|
||||||
sizeof(LONGLONG) - 1) & ~(sizeof(LONGLONG) - 1);
|
NULL,
|
||||||
|
FILE_DEVICE_DISK,
|
||||||
|
FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN,
|
||||||
|
FALSE,
|
||||||
|
&LunPDO);
|
||||||
|
|
||||||
LunExtensionSize += sizeof(SCSI_PORT_LUN_EXTENSION);
|
if (!NT_SUCCESS(Status))
|
||||||
DPRINT("LunExtensionSize %lu\n", LunExtensionSize);
|
|
||||||
|
|
||||||
LunExtension = ExAllocatePoolWithTag(NonPagedPool, LunExtensionSize, TAG_SCSIPORT);
|
|
||||||
if (LunExtension == NULL)
|
|
||||||
{
|
{
|
||||||
DPRINT1("Out of resources!\n");
|
DPRINT1("Failed to create a Lun PDO, status: %x\n", Status);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LunExtension = LunPDO->DeviceExtension;
|
||||||
|
|
||||||
/* Zero everything */
|
/* Zero everything */
|
||||||
RtlZeroMemory(LunExtension, LunExtensionSize);
|
RtlZeroMemory(LunExtension, LunExtensionSize);
|
||||||
|
|
||||||
|
LunExtension->Common.IsFDO = FALSE;
|
||||||
|
LunExtension->Common.DeviceObject = LunPDO;
|
||||||
|
LunExtension->Common.LowerDevice = DeviceExtension->Common.DeviceObject;
|
||||||
|
|
||||||
/* Initialize a list of requests */
|
/* Initialize a list of requests */
|
||||||
InitializeListHead(&LunExtension->SrbInfo.Requests);
|
InitializeListHead(&LunExtension->SrbInfo.Requests);
|
||||||
|
|
||||||
|
@ -50,66 +58,54 @@ SpiAllocateLunExtension(
|
||||||
/* Initialize request queue */
|
/* Initialize request queue */
|
||||||
KeInitializeDeviceQueue(&LunExtension->DeviceQueue);
|
KeInitializeDeviceQueue(&LunExtension->DeviceQueue);
|
||||||
|
|
||||||
return LunExtension;
|
LunPDO->Flags |= DO_DIRECT_IO;
|
||||||
|
LunPDO->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||||
|
|
||||||
|
return LunPDO;
|
||||||
}
|
}
|
||||||
|
|
||||||
PSCSI_PORT_LUN_EXTENSION
|
PSCSI_PORT_LUN_EXTENSION
|
||||||
SpiGetLunExtension(
|
GetLunByPath(
|
||||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
_In_ UCHAR PathId,
|
_In_ UCHAR PathId,
|
||||||
_In_ UCHAR TargetId,
|
_In_ UCHAR TargetId,
|
||||||
_In_ UCHAR Lun)
|
_In_ UCHAR Lun)
|
||||||
{
|
{
|
||||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
if (PathId >= DeviceExtension->NumberOfBuses)
|
||||||
|
|
||||||
DPRINT("SpiGetLunExtension(%p %u %u %u) called\n",
|
|
||||||
DeviceExtension, PathId, TargetId, Lun);
|
|
||||||
|
|
||||||
/* Get appropriate list */
|
|
||||||
LunExtension = DeviceExtension->LunExtensionList[(TargetId + Lun) % LUS_NUMBER];
|
|
||||||
|
|
||||||
/* Iterate it until we find what we need */
|
|
||||||
while (LunExtension)
|
|
||||||
{
|
{
|
||||||
if (LunExtension->TargetId == TargetId &&
|
DPRINT1("Invalid PathId: %u\n", PathId);
|
||||||
LunExtension->Lun == Lun &&
|
return NULL;
|
||||||
LunExtension->PathId == PathId)
|
|
||||||
{
|
|
||||||
/* All matches, return */
|
|
||||||
return LunExtension;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Advance to the next item */
|
PSCSI_BUS_INFO bus = &DeviceExtension->Buses[PathId];
|
||||||
LunExtension = LunExtension->Next;
|
|
||||||
|
for (PLIST_ENTRY lunEntry = bus->LunsListHead.Flink;
|
||||||
|
lunEntry != &bus->LunsListHead;
|
||||||
|
lunEntry = lunEntry->Flink)
|
||||||
|
{
|
||||||
|
PSCSI_PORT_LUN_EXTENSION lunExt =
|
||||||
|
CONTAINING_RECORD(lunEntry, SCSI_PORT_LUN_EXTENSION, LunEntry);
|
||||||
|
|
||||||
|
if (lunExt->PathId == PathId &&
|
||||||
|
lunExt->TargetId == TargetId &&
|
||||||
|
lunExt->Lun == Lun)
|
||||||
|
{
|
||||||
|
return lunExt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We did not find anything */
|
DPRINT("SCSI LUN (%u, %u, %u) was not found\n", PathId, TargetId, Lun);
|
||||||
DPRINT("Nothing found\n");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
PSCSI_REQUEST_BLOCK_INFO
|
PSCSI_REQUEST_BLOCK_INFO
|
||||||
SpiGetSrbData(
|
SpiGetSrbData(
|
||||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
_In_ UCHAR PathId,
|
_In_ PSCSI_PORT_LUN_EXTENSION LunExtension,
|
||||||
_In_ UCHAR TargetId,
|
|
||||||
_In_ UCHAR Lun,
|
|
||||||
_In_ UCHAR QueueTag)
|
_In_ UCHAR QueueTag)
|
||||||
{
|
{
|
||||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
|
||||||
|
|
||||||
if (QueueTag == SP_UNTAGGED)
|
if (QueueTag == SP_UNTAGGED)
|
||||||
{
|
{
|
||||||
/* Untagged request, get LU and return pointer to SrbInfo */
|
|
||||||
LunExtension = SpiGetLunExtension(DeviceExtension,
|
|
||||||
PathId,
|
|
||||||
TargetId,
|
|
||||||
Lun);
|
|
||||||
|
|
||||||
/* Return NULL in case of error */
|
|
||||||
if (!LunExtension)
|
|
||||||
return(NULL);
|
|
||||||
|
|
||||||
/* Return the pointer to SrbInfo */
|
/* Return the pointer to SrbInfo */
|
||||||
return &LunExtension->SrbInfo;
|
return &LunExtension->SrbInfo;
|
||||||
}
|
}
|
||||||
|
@ -122,3 +118,506 @@ SpiGetSrbData(
|
||||||
return &DeviceExtension->SrbInfo[QueueTag -1];
|
return &DeviceExtension->SrbInfo[QueueTag -1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
ULONG
|
||||||
|
CopyField(
|
||||||
|
IN PUCHAR Name,
|
||||||
|
IN PCHAR Buffer,
|
||||||
|
IN ULONG MaxLength)
|
||||||
|
{
|
||||||
|
ULONG Index;
|
||||||
|
|
||||||
|
for (Index = 0; Index < MaxLength; Index++)
|
||||||
|
{
|
||||||
|
if (Name[Index] <= ' ' || Name[Index] >= 0x7F /* last printable ascii character */ || Name[Index] == ',')
|
||||||
|
{
|
||||||
|
// convert to underscore
|
||||||
|
Buffer[Index] = '_';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// just copy character
|
||||||
|
Buffer[Index] = Name[Index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MaxLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
ULONG
|
||||||
|
CopyFieldTruncate(
|
||||||
|
IN PUCHAR Name,
|
||||||
|
IN PCHAR Buffer,
|
||||||
|
IN ULONG MaxLength)
|
||||||
|
{
|
||||||
|
ULONG Index;
|
||||||
|
|
||||||
|
for (Index = 0; Index < MaxLength; Index++)
|
||||||
|
{
|
||||||
|
if (Name[Index] == '\0')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (Name[Index] <= ' ' || Name[Index] >= 0x7F /* last printable ascii character */ || Name[Index] == ',')
|
||||||
|
{
|
||||||
|
// convert to space
|
||||||
|
Buffer[Index] = ' ';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// just copy character
|
||||||
|
Buffer[Index] = Name[Index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
PdoHandleQueryDeviceText(
|
||||||
|
_In_ PDEVICE_OBJECT DeviceObject,
|
||||||
|
_Inout_ PIRP Irp)
|
||||||
|
{
|
||||||
|
PSCSI_PORT_LUN_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
UINT32 Offset = 0;
|
||||||
|
PINQUIRYDATA InquiryData;
|
||||||
|
CHAR LocalBuffer[sizeof(InquiryData->VendorId) + sizeof(InquiryData->ProductId) + 2];
|
||||||
|
ANSI_STRING AnsiString;
|
||||||
|
UNICODE_STRING DeviceDescription;
|
||||||
|
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
InquiryData = &DeviceExtension->InquiryData;
|
||||||
|
|
||||||
|
switch (IoStack->Parameters.QueryDeviceText.DeviceTextType)
|
||||||
|
{
|
||||||
|
case DeviceTextDescription:
|
||||||
|
case DeviceTextLocationInformation:
|
||||||
|
{
|
||||||
|
DPRINT("PdoHandleQueryDeviceText\n");
|
||||||
|
|
||||||
|
Offset += CopyFieldTruncate(InquiryData->VendorId,
|
||||||
|
&LocalBuffer[Offset],
|
||||||
|
sizeof(InquiryData->VendorId));
|
||||||
|
LocalBuffer[Offset++] = ' ';
|
||||||
|
Offset += CopyFieldTruncate(InquiryData->ProductId,
|
||||||
|
&LocalBuffer[Offset],
|
||||||
|
sizeof(InquiryData->ProductId));
|
||||||
|
LocalBuffer[Offset++] = '\0';
|
||||||
|
|
||||||
|
RtlInitAnsiString(&AnsiString, (PCSZ)&LocalBuffer);
|
||||||
|
|
||||||
|
DeviceDescription.Length = 0;
|
||||||
|
DeviceDescription.MaximumLength = (USHORT)(Offset * sizeof(WCHAR));
|
||||||
|
DeviceDescription.Buffer = ExAllocatePoolWithTag(PagedPool,
|
||||||
|
DeviceDescription.MaximumLength,
|
||||||
|
TAG_SCSIPORT);
|
||||||
|
if (!DeviceDescription.Buffer)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlAnsiStringToUnicodeString(&DeviceDescription, &AnsiString, FALSE);
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = (ULONG_PTR)DeviceDescription.Buffer;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
return Irp->IoStatus.Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
PdoHandleQueryDeviceId(
|
||||||
|
_In_ PDEVICE_OBJECT DeviceObject,
|
||||||
|
_Inout_ PIRP Irp)
|
||||||
|
{
|
||||||
|
PSCSI_PORT_LUN_EXTENSION DeviceExtension;
|
||||||
|
NTSTATUS Status;
|
||||||
|
CHAR Buffer[100] = {0};
|
||||||
|
LPCSTR DeviceType;
|
||||||
|
ULONG Offset = 0;
|
||||||
|
PINQUIRYDATA InquiryData;
|
||||||
|
ANSI_STRING AnsiString;
|
||||||
|
UNICODE_STRING DeviceId;
|
||||||
|
|
||||||
|
DeviceExtension = DeviceObject->DeviceExtension;
|
||||||
|
InquiryData = &DeviceExtension->InquiryData;
|
||||||
|
|
||||||
|
DeviceType = GetDeviceType(InquiryData);
|
||||||
|
|
||||||
|
// lets create device string
|
||||||
|
Offset = sprintf(&Buffer[Offset], "SCSI\\");
|
||||||
|
Offset += sprintf(&Buffer[Offset], DeviceType);
|
||||||
|
Offset += sprintf(&Buffer[Offset], "&Ven_");
|
||||||
|
Offset += CopyField(InquiryData->VendorId, &Buffer[Offset], 8);
|
||||||
|
Offset += sprintf(&Buffer[Offset], "&Prod_");
|
||||||
|
Offset += CopyField(InquiryData->ProductId, &Buffer[Offset], 16);
|
||||||
|
Offset += sprintf(&Buffer[Offset], "&Rev_");
|
||||||
|
Offset += CopyField(InquiryData->ProductRevisionLevel, &Buffer[Offset], 4);
|
||||||
|
|
||||||
|
RtlInitAnsiString(&AnsiString, (PCSZ)Buffer);
|
||||||
|
|
||||||
|
// allocate DeviceId string
|
||||||
|
Status = RtlAnsiStringToUnicodeString(&DeviceId, &AnsiString, TRUE);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = (ULONG_PTR)DeviceId.Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("DeviceId %wZ Status %x\n", &DeviceId, Status);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
ConvertToUnicodeString(
|
||||||
|
IN CHAR * Buffer,
|
||||||
|
IN ULONG ResultBufferLength,
|
||||||
|
IN ULONG ResultBufferOffset,
|
||||||
|
OUT LPWSTR ResultBuffer,
|
||||||
|
OUT PULONG NewResultBufferOffset)
|
||||||
|
{
|
||||||
|
UNICODE_STRING DeviceString;
|
||||||
|
ANSI_STRING AnsiString;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
ASSERT(ResultBufferLength);
|
||||||
|
ASSERT(ResultBufferLength > ResultBufferOffset);
|
||||||
|
|
||||||
|
DPRINT("ResultBufferOffset %lu ResultBufferLength %lu Buffer %s Length %lu\n",
|
||||||
|
ResultBufferOffset, ResultBufferLength, Buffer, strlen(Buffer));
|
||||||
|
|
||||||
|
// construct destination string
|
||||||
|
DeviceString.Buffer = &ResultBuffer[ResultBufferOffset];
|
||||||
|
DeviceString.Length = 0;
|
||||||
|
DeviceString.MaximumLength = (ResultBufferLength - ResultBufferOffset) * sizeof(WCHAR);
|
||||||
|
|
||||||
|
// initialize source string
|
||||||
|
RtlInitAnsiString(&AnsiString, Buffer);
|
||||||
|
|
||||||
|
Status = RtlAnsiStringToUnicodeString(&DeviceString, &AnsiString, FALSE);
|
||||||
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
|
||||||
|
// subtract consumed bytes
|
||||||
|
ResultBufferLength -= (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR);
|
||||||
|
ResultBufferOffset += (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR);
|
||||||
|
|
||||||
|
*NewResultBufferOffset = ResultBufferOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
PdoHandleQueryHardwareId(
|
||||||
|
_In_ PDEVICE_OBJECT DeviceObject,
|
||||||
|
_Inout_ PIRP Irp)
|
||||||
|
{
|
||||||
|
PSCSI_PORT_LUN_EXTENSION PDODeviceExtension = DeviceObject->DeviceExtension;
|
||||||
|
LPCSTR GenericType, DeviceType;
|
||||||
|
LPWSTR Buffer;
|
||||||
|
CHAR Id1[50], Id2[50], Id3[50], Id4[50], Id5[50], Id6[50], Id7[50];
|
||||||
|
ULONG Id1Length, Id2Length, Id3Length, Id4Length, Id5Length, Id6Length, Id7Length;
|
||||||
|
ULONG Offset, TotalLength, Length;
|
||||||
|
PINQUIRYDATA InquiryData;
|
||||||
|
|
||||||
|
InquiryData = &PDODeviceExtension->InquiryData;
|
||||||
|
|
||||||
|
DeviceType = GetDeviceType(InquiryData);
|
||||||
|
GenericType = GetGenericType(InquiryData);
|
||||||
|
|
||||||
|
ASSERT(GenericType);
|
||||||
|
|
||||||
|
// generate id 1
|
||||||
|
// SCSI\SCSIType_VendorId(8)_ProductId(16)_Revision(4)
|
||||||
|
RtlZeroMemory(Id1, sizeof(Id1));
|
||||||
|
Offset = 0;
|
||||||
|
Offset = sprintf(&Id1[Offset], "SCSI\\");
|
||||||
|
Offset += sprintf(&Id1[Offset], DeviceType);
|
||||||
|
Offset += CopyField(InquiryData->VendorId, &Id1[Offset], 8);
|
||||||
|
Offset += CopyField(InquiryData->ProductId, &Id1[Offset], 16);
|
||||||
|
Offset += CopyField(InquiryData->ProductRevisionLevel, &Id1[Offset], 4);
|
||||||
|
Id1Length = strlen(Id1) + 1;
|
||||||
|
DPRINT("PdoHandleQueryHardwareId HardwareId1 %s\n", Id1);
|
||||||
|
|
||||||
|
// generate id 2
|
||||||
|
// SCSI\SCSIType_VendorId(8)_ProductId(16)
|
||||||
|
RtlZeroMemory(Id2, sizeof(Id2));
|
||||||
|
Offset = 0;
|
||||||
|
Offset = sprintf(&Id2[Offset], "SCSI\\");
|
||||||
|
Offset += sprintf(&Id2[Offset], DeviceType);
|
||||||
|
Offset += CopyField(InquiryData->VendorId, &Id2[Offset], 8);
|
||||||
|
Offset += CopyField(InquiryData->ProductId, &Id2[Offset], 16);
|
||||||
|
Id2Length = strlen(Id2) + 1;
|
||||||
|
DPRINT("PdoHandleQueryHardwareId HardwareId2 %s\n", Id2);
|
||||||
|
|
||||||
|
// generate id 3
|
||||||
|
// SCSI\SCSIType_VendorId(8)
|
||||||
|
RtlZeroMemory(Id3, sizeof(Id3));
|
||||||
|
Offset = 0;
|
||||||
|
Offset = sprintf(&Id3[Offset], "SCSI\\");
|
||||||
|
Offset += sprintf(&Id3[Offset], DeviceType);
|
||||||
|
Offset += CopyField(InquiryData->VendorId, &Id3[Offset], 8);
|
||||||
|
Id3Length = strlen(Id3) + 1;
|
||||||
|
DPRINT("PdoHandleQueryHardwareId HardwareId3 %s\n", Id3);
|
||||||
|
|
||||||
|
// generate id 4
|
||||||
|
// SCSI\SCSIType_VendorId(8)_ProductId(16)_Revision(1)
|
||||||
|
RtlZeroMemory(Id4, sizeof(Id4));
|
||||||
|
Offset = 0;
|
||||||
|
Offset = sprintf(&Id4[Offset], "SCSI\\");
|
||||||
|
Offset += sprintf(&Id4[Offset], DeviceType);
|
||||||
|
Offset += CopyField(InquiryData->VendorId, &Id4[Offset], 8);
|
||||||
|
Offset += CopyField(InquiryData->ProductId, &Id4[Offset], 16);
|
||||||
|
Offset += CopyField(InquiryData->ProductRevisionLevel, &Id4[Offset], 1);
|
||||||
|
Id4Length = strlen(Id4) + 1;
|
||||||
|
DPRINT("PdoHandleQueryHardwareId HardwareId4 %s\n", Id4);
|
||||||
|
|
||||||
|
// generate id 5
|
||||||
|
// SCSIType_VendorId(8)_ProductId(16)_Revision(1)
|
||||||
|
RtlZeroMemory(Id5, sizeof(Id5));
|
||||||
|
Offset = 0;
|
||||||
|
Offset = sprintf(&Id5[Offset], DeviceType);
|
||||||
|
Offset += CopyField(InquiryData->VendorId, &Id5[Offset], 8);
|
||||||
|
Offset += CopyField(InquiryData->ProductId, &Id5[Offset], 16);
|
||||||
|
Offset += CopyField(InquiryData->ProductRevisionLevel, &Id5[Offset], 1);
|
||||||
|
Id5Length = strlen(Id5) + 1;
|
||||||
|
DPRINT("PdoHandleQueryHardwareId HardwareId5 %s\n", Id5);
|
||||||
|
|
||||||
|
// generate id 6
|
||||||
|
// SCSI\SCSIType
|
||||||
|
RtlZeroMemory(Id6, sizeof(Id6));
|
||||||
|
Offset = 0;
|
||||||
|
Offset = sprintf(&Id6[Offset], "SCSI\\");
|
||||||
|
Offset += sprintf(&Id6[Offset], GenericType);
|
||||||
|
Id6Length = strlen(Id6) + 1;
|
||||||
|
DPRINT("PdoHandleQueryHardwareId HardwareId6 %s\n", Id6);
|
||||||
|
|
||||||
|
// generate id 7
|
||||||
|
// SCSIType
|
||||||
|
RtlZeroMemory(Id7, sizeof(Id7));
|
||||||
|
Offset = 0;
|
||||||
|
Offset = sprintf(&Id7[Offset], GenericType);
|
||||||
|
Id7Length = strlen(Id7) + 1;
|
||||||
|
DPRINT("PdoHandleQueryHardwareId HardwareId7 %s\n", Id7);
|
||||||
|
|
||||||
|
TotalLength = Id1Length + Id2Length + Id3Length + Id4Length + Id5Length + Id6Length + Id7Length + 1;
|
||||||
|
|
||||||
|
Buffer = ExAllocatePoolWithTag(PagedPool, TotalLength * sizeof(WCHAR), TAG_SCSIPORT);
|
||||||
|
if (!Buffer)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset offset
|
||||||
|
Offset = 0;
|
||||||
|
Length = TotalLength;
|
||||||
|
|
||||||
|
ConvertToUnicodeString(Id1, Length, Offset, Buffer, &Offset);
|
||||||
|
ConvertToUnicodeString(Id2, Length, Offset, Buffer, &Offset);
|
||||||
|
ConvertToUnicodeString(Id3, Length, Offset, Buffer, &Offset);
|
||||||
|
ConvertToUnicodeString(Id4, Length, Offset, Buffer, &Offset);
|
||||||
|
ConvertToUnicodeString(Id5, Length, Offset, Buffer, &Offset);
|
||||||
|
ConvertToUnicodeString(Id6, Length, Offset, Buffer, &Offset);
|
||||||
|
ConvertToUnicodeString(Id7, Length, Offset, Buffer, &Offset);
|
||||||
|
|
||||||
|
Buffer[Offset] = UNICODE_NULL;
|
||||||
|
|
||||||
|
ASSERT(Offset + 1 == Length);
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = (ULONG_PTR)Buffer;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
PdoHandleQueryCompatibleId(
|
||||||
|
_In_ PDEVICE_OBJECT DeviceObject,
|
||||||
|
_Inout_ PIRP Irp)
|
||||||
|
{
|
||||||
|
PSCSI_PORT_LUN_EXTENSION PDODeviceExtension = DeviceObject->DeviceExtension;
|
||||||
|
CHAR Buffer[100] = {0};
|
||||||
|
ULONG Length, Offset;
|
||||||
|
LPWSTR InstanceId;
|
||||||
|
LPCSTR DeviceType;
|
||||||
|
|
||||||
|
DeviceType = GetDeviceType(&PDODeviceExtension->InquiryData);
|
||||||
|
|
||||||
|
// format instance id
|
||||||
|
Length = sprintf(Buffer, "%s", DeviceType) + 1;
|
||||||
|
Length += sprintf(&Buffer[Length], "%s", "RAW") + 2;
|
||||||
|
|
||||||
|
InstanceId = ExAllocatePoolWithTag(PagedPool, Length * sizeof(WCHAR), TAG_SCSIPORT);
|
||||||
|
if (!InstanceId)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConvertToUnicodeString(Buffer, Length, 0, InstanceId, &Offset);
|
||||||
|
ConvertToUnicodeString(&Buffer[Offset], Length, Offset, InstanceId, &Offset);
|
||||||
|
|
||||||
|
InstanceId[Offset] = UNICODE_NULL;
|
||||||
|
|
||||||
|
DPRINT("PdoHandleQueryCompatibleId %S\n", InstanceId);
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = (ULONG_PTR)InstanceId;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
PdoHandleQueryInstanceId(
|
||||||
|
_In_ PDEVICE_OBJECT DeviceObject,
|
||||||
|
_Inout_ PIRP Irp)
|
||||||
|
{
|
||||||
|
PSCSI_PORT_LUN_EXTENSION lunExt = DeviceObject->DeviceExtension;
|
||||||
|
WCHAR Buffer[26];
|
||||||
|
ULONG Length;
|
||||||
|
LPWSTR InstanceId;
|
||||||
|
|
||||||
|
// use instance count and LUN
|
||||||
|
swprintf(Buffer, L"%x%x%x", lunExt->PathId, lunExt->TargetId, lunExt->Lun);
|
||||||
|
|
||||||
|
Length = wcslen(Buffer) + 1;
|
||||||
|
|
||||||
|
InstanceId = ExAllocatePoolWithTag(PagedPool, Length * sizeof(WCHAR), TAG_SCSIPORT);
|
||||||
|
if (!InstanceId)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
wcscpy(InstanceId, Buffer);
|
||||||
|
|
||||||
|
DPRINT("PdoHandleQueryInstanceId %S\n", InstanceId);
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = (ULONG_PTR)InstanceId;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
PdoHandleDeviceRelations(
|
||||||
|
_In_ PDEVICE_OBJECT DeviceObject,
|
||||||
|
_Inout_ PIRP Irp)
|
||||||
|
{
|
||||||
|
PDEVICE_RELATIONS deviceRelations;
|
||||||
|
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
// check if relation type is BusRelations
|
||||||
|
if (ioStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
|
||||||
|
{
|
||||||
|
// PDO handles only target device relation
|
||||||
|
return Irp->IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceRelations = ExAllocatePoolWithTag(PagedPool, sizeof(DEVICE_RELATIONS), TAG_SCSIPORT);
|
||||||
|
if (!deviceRelations)
|
||||||
|
{
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize device relations
|
||||||
|
deviceRelations->Count = 1;
|
||||||
|
deviceRelations->Objects[0] = DeviceObject;
|
||||||
|
ObReferenceObject(DeviceObject);
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = (ULONG_PTR)deviceRelations;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
PdoDispatchPnp(
|
||||||
|
_In_ PDEVICE_OBJECT DeviceObject,
|
||||||
|
_Inout_ PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
PSCSI_PORT_LUN_EXTENSION lunExt = DeviceObject->DeviceExtension;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
DPRINT("PDO PnP request %s\n", GetIRPMinorFunctionString(ioStack->MinorFunction));
|
||||||
|
|
||||||
|
ASSERT(!lunExt->Common.IsFDO);
|
||||||
|
|
||||||
|
switch (ioStack->MinorFunction)
|
||||||
|
{
|
||||||
|
case IRP_MN_START_DEVICE:
|
||||||
|
{
|
||||||
|
RegistryInitLunKey(lunExt);
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IRP_MN_REMOVE_DEVICE:
|
||||||
|
case IRP_MN_QUERY_CAPABILITIES:
|
||||||
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||||
|
case IRP_MN_QUERY_STOP_DEVICE:
|
||||||
|
case IRP_MN_SURPRISE_REMOVAL:
|
||||||
|
{
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
||||||
|
{
|
||||||
|
status = PdoHandleDeviceRelations(DeviceObject, Irp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IRP_MN_QUERY_DEVICE_TEXT:
|
||||||
|
{
|
||||||
|
status = PdoHandleQueryDeviceText(DeviceObject, Irp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IRP_MN_QUERY_ID:
|
||||||
|
{
|
||||||
|
DPRINT("IRP_MN_QUERY_ID IdType %s\n",
|
||||||
|
DbgGetDeviceIDString(ioStack->Parameters.QueryId.IdType));
|
||||||
|
|
||||||
|
if (ioStack->Parameters.QueryId.IdType == BusQueryDeviceID)
|
||||||
|
{
|
||||||
|
status = PdoHandleQueryDeviceId(DeviceObject, Irp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (ioStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
|
||||||
|
{
|
||||||
|
status = PdoHandleQueryHardwareId(DeviceObject, Irp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (ioStack->Parameters.QueryId.IdType == BusQueryInstanceID)
|
||||||
|
{
|
||||||
|
status = PdoHandleQueryInstanceId(DeviceObject, Irp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (ioStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs)
|
||||||
|
{
|
||||||
|
status = PdoHandleQueryCompatibleId(DeviceObject, Irp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallthrough
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
status = Irp->IoStatus.Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != STATUS_PENDING)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Status = status;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
41
drivers/storage/port/scsiport/power.c
Normal file
41
drivers/storage/port/scsiport/power.c
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS Storage Stack / SCSIPORT storage port library
|
||||||
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
|
* PURPOSE: PnP power handlers
|
||||||
|
* COPYRIGHT: Copyright 2016 Thomas Faber <thomas.faber@reactos.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "scsiport.h"
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
ScsiPortDispatchPower(
|
||||||
|
_In_ PDEVICE_OBJECT DeviceObject,
|
||||||
|
_Inout_ PIRP Irp)
|
||||||
|
{
|
||||||
|
PSCSI_PORT_COMMON_EXTENSION comExt = DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
if (comExt->IsFDO)
|
||||||
|
{
|
||||||
|
PoStartNextPowerIrp(Irp);
|
||||||
|
IoSkipCurrentIrpStackLocation(Irp);
|
||||||
|
return PoCallDriver(comExt->LowerDevice, Irp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
switch (ioStack->MinorFunction)
|
||||||
|
{
|
||||||
|
case IRP_MN_SET_POWER:
|
||||||
|
case IRP_MN_QUERY_POWER:
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS status = Irp->IoStatus.Status;
|
||||||
|
PoStartNextPowerIrp(Irp);
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,9 +4,11 @@
|
||||||
* PURPOSE: Registry operations
|
* PURPOSE: Registry operations
|
||||||
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
||||||
* Aleksey Bragin (aleksey@reactos.org)
|
* Aleksey Bragin (aleksey@reactos.org)
|
||||||
|
* 2020 Victor Perevertkin (victor.perevertkin@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "scsiport.h"
|
#include "scsiport.h"
|
||||||
|
#include "scsitypes.h"
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
@ -15,26 +17,28 @@
|
||||||
VOID
|
VOID
|
||||||
SpiInitOpenKeys(
|
SpiInitOpenKeys(
|
||||||
_Inout_ PCONFIGURATION_INFO ConfigInfo,
|
_Inout_ PCONFIGURATION_INFO ConfigInfo,
|
||||||
_In_ PUNICODE_STRING RegistryPath)
|
_In_ PSCSI_PORT_DRIVER_EXTENSION DriverExtension)
|
||||||
{
|
{
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
UNICODE_STRING KeyName;
|
UNICODE_STRING KeyName;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
HANDLE parametersKey;
|
||||||
|
|
||||||
|
DriverExtension->IsLegacyDriver = TRUE;
|
||||||
|
|
||||||
/* Open the service key */
|
/* Open the service key */
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
RegistryPath,
|
&DriverExtension->RegistryPath,
|
||||||
OBJ_CASE_INSENSITIVE,
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
Status = ZwOpenKey(&ConfigInfo->ServiceKey,
|
Status = ZwOpenKey(&ConfigInfo->ServiceKey, KEY_READ, &ObjectAttributes);
|
||||||
KEY_READ,
|
|
||||||
&ObjectAttributes);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("Unable to open driver's registry key %wZ, status 0x%08x\n", RegistryPath, Status);
|
DPRINT("Unable to open driver's registry key %wZ, status 0x%08x\n",
|
||||||
|
DriverExtension->RegistryPath, Status);
|
||||||
ConfigInfo->ServiceKey = NULL;
|
ConfigInfo->ServiceKey = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,14 +48,12 @@ SpiInitOpenKeys(
|
||||||
RtlInitUnicodeString(&KeyName, L"Parameters");
|
RtlInitUnicodeString(&KeyName, L"Parameters");
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
&KeyName,
|
&KeyName,
|
||||||
OBJ_CASE_INSENSITIVE,
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||||
ConfigInfo->ServiceKey,
|
ConfigInfo->ServiceKey,
|
||||||
(PSECURITY_DESCRIPTOR) NULL);
|
NULL);
|
||||||
|
|
||||||
/* Try to open it */
|
/* Try to open it */
|
||||||
Status = ZwOpenKey(&ConfigInfo->DeviceKey,
|
Status = ZwOpenKey(&ConfigInfo->DeviceKey, KEY_READ, &ObjectAttributes);
|
||||||
KEY_READ,
|
|
||||||
&ObjectAttributes);
|
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -69,14 +71,32 @@ SpiInitOpenKeys(
|
||||||
RtlInitUnicodeString(&KeyName, L"Device");
|
RtlInitUnicodeString(&KeyName, L"Device");
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
&KeyName,
|
&KeyName,
|
||||||
OBJ_CASE_INSENSITIVE,
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||||
ConfigInfo->ServiceKey,
|
ConfigInfo->ServiceKey,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
/* We don't check for failure here - not needed */
|
/* We don't check for failure here - not needed */
|
||||||
ZwOpenKey(&ConfigInfo->DeviceKey,
|
ZwOpenKey(&ConfigInfo->DeviceKey, KEY_READ, &ObjectAttributes);
|
||||||
KEY_READ,
|
|
||||||
&ObjectAttributes);
|
// Detect the driver PnP capabilities via its Parameters\PnpInterface key
|
||||||
|
// for example: HKLM\SYSTEM\CurrentControlSet\Services\UNIATA\Parameters\PnpInterface
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&KeyName, L"PnpInterface");
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&KeyName,
|
||||||
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||||
|
ConfigInfo->ServiceKey,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
Status = ZwOpenKey(¶metersKey, KEY_READ, &ObjectAttributes);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
// if the key exists, it's enough for us for now
|
||||||
|
// (the proper check should iterate over INTERFACE_TYPE values)
|
||||||
|
DriverExtension->IsLegacyDriver = FALSE;
|
||||||
|
ZwClose(parametersKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,34 +124,24 @@ SpiInitOpenKeys(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
SpiBuildDeviceMap(
|
RegistryInitAdapterKey(
|
||||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
_Inout_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
||||||
_In_ PUNICODE_STRING RegistryPath)
|
|
||||||
{
|
{
|
||||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
UNICODE_STRING KeyName;
|
UNICODE_STRING KeyName;
|
||||||
UNICODE_STRING ValueName;
|
UNICODE_STRING ValueName;
|
||||||
WCHAR NameBuffer[64];
|
WCHAR NameBuffer[64];
|
||||||
ULONG Disposition;
|
|
||||||
HANDLE ScsiKey;
|
HANDLE ScsiKey;
|
||||||
HANDLE ScsiPortKey = NULL;
|
HANDLE ScsiPortKey = NULL;
|
||||||
HANDLE ScsiBusKey = NULL;
|
HANDLE ScsiBusKey = NULL;
|
||||||
HANDLE ScsiInitiatorKey = NULL;
|
HANDLE ScsiInitiatorKey = NULL;
|
||||||
HANDLE ScsiTargetKey = NULL;
|
|
||||||
HANDLE ScsiLunKey = NULL;
|
|
||||||
ULONG BusNumber;
|
ULONG BusNumber;
|
||||||
ULONG Target;
|
|
||||||
ULONG CurrentTarget;
|
|
||||||
ULONG Lun;
|
|
||||||
PWCHAR DriverName;
|
|
||||||
ULONG UlongData;
|
ULONG UlongData;
|
||||||
PWCHAR TypeName;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT("SpiBuildDeviceMap() called\n");
|
DPRINT("SpiBuildDeviceMap() called\n");
|
||||||
|
|
||||||
if (DeviceExtension == NULL || RegistryPath == NULL)
|
if (DeviceExtension == NULL)
|
||||||
{
|
{
|
||||||
DPRINT1("Invalid parameter\n");
|
DPRINT1("Invalid parameter\n");
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
@ -151,7 +161,7 @@ SpiBuildDeviceMap(
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
REG_OPTION_VOLATILE,
|
REG_OPTION_VOLATILE,
|
||||||
&Disposition);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
|
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
|
||||||
|
@ -165,18 +175,14 @@ SpiBuildDeviceMap(
|
||||||
L"Scsi Port %lu",
|
L"Scsi Port %lu",
|
||||||
DeviceExtension->PortNumber);
|
DeviceExtension->PortNumber);
|
||||||
RtlInitUnicodeString(&KeyName, NameBuffer);
|
RtlInitUnicodeString(&KeyName, NameBuffer);
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_KERNEL_HANDLE, ScsiKey, NULL);
|
||||||
&KeyName,
|
|
||||||
OBJ_KERNEL_HANDLE,
|
|
||||||
ScsiKey,
|
|
||||||
NULL);
|
|
||||||
Status = ZwCreateKey(&ScsiPortKey,
|
Status = ZwCreateKey(&ScsiPortKey,
|
||||||
KEY_ALL_ACCESS,
|
KEY_ALL_ACCESS,
|
||||||
&ObjectAttributes,
|
&ObjectAttributes,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
REG_OPTION_VOLATILE,
|
REG_OPTION_VOLATILE,
|
||||||
&Disposition);
|
NULL);
|
||||||
ZwClose(ScsiKey);
|
ZwClose(ScsiKey);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -206,14 +212,29 @@ SpiBuildDeviceMap(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set 'Driver' (REG_SZ) value */
|
/* Set 'Driver' (REG_SZ) value */
|
||||||
DriverName = wcsrchr(RegistryPath->Buffer, L'\\') + 1;
|
PUNICODE_STRING driverNameU = &DeviceExtension->Common.DeviceObject->DriverObject->DriverName;
|
||||||
|
PWCHAR driverName = ExAllocatePoolWithTag(PagedPool,
|
||||||
|
driverNameU->Length + sizeof(UNICODE_NULL),
|
||||||
|
TAG_SCSIPORT);
|
||||||
|
if (!driverName)
|
||||||
|
{
|
||||||
|
DPRINT("Failed to allocate driverName!\n");
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlCopyMemory(driverName, driverNameU->Buffer, driverNameU->Length);
|
||||||
|
driverName[driverNameU->Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||||
|
|
||||||
RtlInitUnicodeString(&ValueName, L"Driver");
|
RtlInitUnicodeString(&ValueName, L"Driver");
|
||||||
Status = ZwSetValueKey(ScsiPortKey,
|
Status = ZwSetValueKey(ScsiPortKey,
|
||||||
&ValueName,
|
&ValueName,
|
||||||
0,
|
0,
|
||||||
REG_SZ,
|
REG_SZ,
|
||||||
DriverName,
|
driverName,
|
||||||
(ULONG)((wcslen(DriverName) + 1) * sizeof(WCHAR)));
|
driverNameU->Length + sizeof(UNICODE_NULL));
|
||||||
|
|
||||||
|
ExFreePoolWithTag(driverName, TAG_SCSIPORT);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("ZwSetValueKey('Driver') failed (Status %lx)\n", Status);
|
DPRINT("ZwSetValueKey('Driver') failed (Status %lx)\n", Status);
|
||||||
|
@ -256,7 +277,7 @@ SpiBuildDeviceMap(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enumerate buses */
|
/* Enumerate buses */
|
||||||
for (BusNumber = 0; BusNumber < DeviceExtension->PortConfig->NumberOfBuses; BusNumber++)
|
for (BusNumber = 0; BusNumber < DeviceExtension->NumberOfBuses; BusNumber++)
|
||||||
{
|
{
|
||||||
/* Create 'Scsi Bus X' key */
|
/* Create 'Scsi Bus X' key */
|
||||||
DPRINT(" Scsi Bus %lu\n", BusNumber);
|
DPRINT(" Scsi Bus %lu\n", BusNumber);
|
||||||
|
@ -266,7 +287,7 @@ SpiBuildDeviceMap(
|
||||||
RtlInitUnicodeString(&KeyName, NameBuffer);
|
RtlInitUnicodeString(&KeyName, NameBuffer);
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
&KeyName,
|
&KeyName,
|
||||||
0,
|
OBJ_KERNEL_HANDLE,
|
||||||
ScsiPortKey,
|
ScsiPortKey,
|
||||||
NULL);
|
NULL);
|
||||||
Status = ZwCreateKey(&ScsiBusKey,
|
Status = ZwCreateKey(&ScsiBusKey,
|
||||||
|
@ -275,7 +296,7 @@ SpiBuildDeviceMap(
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
REG_OPTION_VOLATILE,
|
REG_OPTION_VOLATILE,
|
||||||
&Disposition);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
|
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
|
||||||
|
@ -291,7 +312,7 @@ SpiBuildDeviceMap(
|
||||||
RtlInitUnicodeString(&KeyName, NameBuffer);
|
RtlInitUnicodeString(&KeyName, NameBuffer);
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
&KeyName,
|
&KeyName,
|
||||||
0,
|
OBJ_KERNEL_HANDLE,
|
||||||
ScsiBusKey,
|
ScsiBusKey,
|
||||||
NULL);
|
NULL);
|
||||||
Status = ZwCreateKey(&ScsiInitiatorKey,
|
Status = ZwCreateKey(&ScsiInitiatorKey,
|
||||||
|
@ -300,7 +321,7 @@ SpiBuildDeviceMap(
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
REG_OPTION_VOLATILE,
|
REG_OPTION_VOLATILE,
|
||||||
&Disposition);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
|
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
|
||||||
|
@ -312,202 +333,14 @@ SpiBuildDeviceMap(
|
||||||
ZwClose(ScsiInitiatorKey);
|
ZwClose(ScsiInitiatorKey);
|
||||||
ScsiInitiatorKey = NULL;
|
ScsiInitiatorKey = NULL;
|
||||||
|
|
||||||
|
DeviceExtension->Buses[BusNumber].RegistryMapKey = ScsiBusKey;
|
||||||
/* Enumerate targets */
|
|
||||||
CurrentTarget = (ULONG)-1;
|
|
||||||
ScsiTargetKey = NULL;
|
|
||||||
for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
|
|
||||||
{
|
|
||||||
for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
|
|
||||||
{
|
|
||||||
LunExtension = SpiGetLunExtension(DeviceExtension,
|
|
||||||
(UCHAR)BusNumber,
|
|
||||||
(UCHAR)Target,
|
|
||||||
(UCHAR)Lun);
|
|
||||||
if (LunExtension == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (Target != CurrentTarget)
|
|
||||||
{
|
|
||||||
/* Close old target key */
|
|
||||||
if (ScsiTargetKey != NULL)
|
|
||||||
{
|
|
||||||
ZwClose(ScsiTargetKey);
|
|
||||||
ScsiTargetKey = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create 'Target Id X' key */
|
|
||||||
DPRINT(" Target Id %lu\n", Target);
|
|
||||||
swprintf(NameBuffer,
|
|
||||||
L"Target Id %lu",
|
|
||||||
Target);
|
|
||||||
RtlInitUnicodeString(&KeyName, NameBuffer);
|
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
|
||||||
&KeyName,
|
|
||||||
0,
|
|
||||||
ScsiBusKey,
|
|
||||||
NULL);
|
|
||||||
Status = ZwCreateKey(&ScsiTargetKey,
|
|
||||||
KEY_ALL_ACCESS,
|
|
||||||
&ObjectAttributes,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
REG_OPTION_VOLATILE,
|
|
||||||
&Disposition);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
|
|
||||||
goto ByeBye;
|
|
||||||
}
|
|
||||||
|
|
||||||
CurrentTarget = Target;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create 'Logical Unit Id X' key */
|
|
||||||
DPRINT(" Logical Unit Id %lu\n", Lun);
|
|
||||||
swprintf(NameBuffer,
|
|
||||||
L"Logical Unit Id %lu",
|
|
||||||
Lun);
|
|
||||||
RtlInitUnicodeString(&KeyName, NameBuffer);
|
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
|
||||||
&KeyName,
|
|
||||||
0,
|
|
||||||
ScsiTargetKey,
|
|
||||||
NULL);
|
|
||||||
Status = ZwCreateKey(&ScsiLunKey,
|
|
||||||
KEY_ALL_ACCESS,
|
|
||||||
&ObjectAttributes,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
REG_OPTION_VOLATILE,
|
|
||||||
&Disposition);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
|
|
||||||
goto ByeBye;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set 'Identifier' (REG_SZ) value */
|
|
||||||
swprintf(NameBuffer,
|
|
||||||
L"%.8S%.16S%.4S",
|
|
||||||
LunExtension->InquiryData.VendorId,
|
|
||||||
LunExtension->InquiryData.ProductId,
|
|
||||||
LunExtension->InquiryData.ProductRevisionLevel);
|
|
||||||
DPRINT(" Identifier = '%S'\n", NameBuffer);
|
|
||||||
RtlInitUnicodeString(&ValueName, L"Identifier");
|
|
||||||
Status = ZwSetValueKey(ScsiLunKey,
|
|
||||||
&ValueName,
|
|
||||||
0,
|
|
||||||
REG_SZ,
|
|
||||||
NameBuffer,
|
|
||||||
(ULONG)((wcslen(NameBuffer) + 1) * sizeof(WCHAR)));
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("ZwSetValueKey('Identifier') failed (Status %lx)\n", Status);
|
|
||||||
goto ByeBye;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set 'Type' (REG_SZ) value */
|
|
||||||
/*
|
|
||||||
* See https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-ide-devices
|
|
||||||
* and https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-scsi-devices
|
|
||||||
* for a list of types with their human-readable forms.
|
|
||||||
*/
|
|
||||||
switch (LunExtension->InquiryData.DeviceType)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
TypeName = L"DiskPeripheral";
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
TypeName = L"TapePeripheral";
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
TypeName = L"PrinterPeripheral";
|
|
||||||
break;
|
|
||||||
// case 3: "ProcessorPeripheral", classified as 'other': fall back to default case.
|
|
||||||
case 4:
|
|
||||||
TypeName = L"WormPeripheral";
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
TypeName = L"CdRomPeripheral";
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
TypeName = L"ScannerPeripheral";
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
TypeName = L"OpticalDiskPeripheral";
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
TypeName = L"MediumChangerPeripheral";
|
|
||||||
break;
|
|
||||||
case 9:
|
|
||||||
TypeName = L"CommunicationsPeripheral";
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* New peripheral types (SCSI only) */
|
|
||||||
case 10: case 11:
|
|
||||||
TypeName = L"ASCPrePressGraphicsPeripheral";
|
|
||||||
break;
|
|
||||||
case 12:
|
|
||||||
TypeName = L"ArrayPeripheral";
|
|
||||||
break;
|
|
||||||
case 13:
|
|
||||||
TypeName = L"EnclosurePeripheral";
|
|
||||||
break;
|
|
||||||
case 14:
|
|
||||||
TypeName = L"RBCPeripheral";
|
|
||||||
break;
|
|
||||||
case 15:
|
|
||||||
TypeName = L"CardReaderPeripheral";
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
TypeName = L"BridgePeripheral";
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
TypeName = L"OtherPeripheral";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
DPRINT(" Type = '%S'\n", TypeName);
|
|
||||||
RtlInitUnicodeString(&ValueName, L"Type");
|
|
||||||
Status = ZwSetValueKey(ScsiLunKey,
|
|
||||||
&ValueName,
|
|
||||||
0,
|
|
||||||
REG_SZ,
|
|
||||||
TypeName,
|
|
||||||
(ULONG)((wcslen(TypeName) + 1) * sizeof(WCHAR)));
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("ZwSetValueKey('Type') failed (Status %lx)\n", Status);
|
|
||||||
goto ByeBye;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZwClose(ScsiLunKey);
|
|
||||||
ScsiLunKey = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Close old target key */
|
|
||||||
if (ScsiTargetKey != NULL)
|
|
||||||
{
|
|
||||||
ZwClose(ScsiTargetKey);
|
|
||||||
ScsiTargetKey = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ZwClose(ScsiBusKey);
|
|
||||||
ScsiBusKey = NULL;
|
ScsiBusKey = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByeBye:
|
ByeBye:
|
||||||
if (ScsiLunKey != NULL)
|
|
||||||
ZwClose(ScsiLunKey);
|
|
||||||
|
|
||||||
if (ScsiInitiatorKey != NULL)
|
if (ScsiInitiatorKey != NULL)
|
||||||
ZwClose(ScsiInitiatorKey);
|
ZwClose(ScsiInitiatorKey);
|
||||||
|
|
||||||
if (ScsiTargetKey != NULL)
|
|
||||||
ZwClose(ScsiTargetKey);
|
|
||||||
|
|
||||||
if (ScsiBusKey != NULL)
|
if (ScsiBusKey != NULL)
|
||||||
ZwClose(ScsiBusKey);
|
ZwClose(ScsiBusKey);
|
||||||
|
|
||||||
|
@ -518,3 +351,109 @@ ByeBye:
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
RegistryInitLunKey(
|
||||||
|
_Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension)
|
||||||
|
{
|
||||||
|
WCHAR nameBuffer[64];
|
||||||
|
UNICODE_STRING keyName;
|
||||||
|
UNICODE_STRING valueName;
|
||||||
|
OBJECT_ATTRIBUTES objectAttributes;
|
||||||
|
HANDLE targetKey;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
// get the LUN's bus key
|
||||||
|
PSCSI_PORT_DEVICE_EXTENSION portExt = LunExtension->Common.LowerDevice->DeviceExtension;
|
||||||
|
HANDLE busKey = portExt->Buses[LunExtension->PathId].RegistryMapKey;
|
||||||
|
|
||||||
|
// create/open 'Target Id X' key
|
||||||
|
swprintf(nameBuffer, L"Target Id %lu", LunExtension->TargetId);
|
||||||
|
RtlInitUnicodeString(&keyName, nameBuffer);
|
||||||
|
InitializeObjectAttributes(&objectAttributes, &keyName, OBJ_KERNEL_HANDLE, busKey, NULL);
|
||||||
|
status = ZwCreateKey(&targetKey,
|
||||||
|
KEY_ALL_ACCESS,
|
||||||
|
&objectAttributes,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
REG_OPTION_VOLATILE,
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
DPRINT("ZwCreateKey() failed (Status %lx)\n", status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create 'Logical Unit Id X' key
|
||||||
|
swprintf(nameBuffer, L"Logical Unit Id %lu", LunExtension->Lun);
|
||||||
|
RtlInitUnicodeString(&keyName, nameBuffer);
|
||||||
|
InitializeObjectAttributes(&objectAttributes, &keyName, OBJ_KERNEL_HANDLE, targetKey, NULL);
|
||||||
|
status = ZwCreateKey(&LunExtension->RegistryMapKey,
|
||||||
|
KEY_ALL_ACCESS,
|
||||||
|
&objectAttributes,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
REG_OPTION_VOLATILE,
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
DPRINT("ZwCreateKey() failed (Status %lx)\n", status);
|
||||||
|
goto ByeBye;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set 'Identifier' (REG_SZ) value
|
||||||
|
swprintf(nameBuffer,
|
||||||
|
L"%.8S%.16S%.4S",
|
||||||
|
LunExtension->InquiryData.VendorId,
|
||||||
|
LunExtension->InquiryData.ProductId,
|
||||||
|
LunExtension->InquiryData.ProductRevisionLevel);
|
||||||
|
RtlInitUnicodeString(&valueName, L"Identifier");
|
||||||
|
status = ZwSetValueKey(LunExtension->RegistryMapKey,
|
||||||
|
&valueName,
|
||||||
|
0,
|
||||||
|
REG_SZ,
|
||||||
|
nameBuffer,
|
||||||
|
(wcslen(nameBuffer) + 1) * sizeof(WCHAR));
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
DPRINT("ZwSetValueKey('Identifier') failed (Status %lx)\n", status);
|
||||||
|
goto ByeBye;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set 'Type' (REG_SZ) value
|
||||||
|
PWCHAR typeName = (PWCHAR)GetPeripheralTypeW(&LunExtension->InquiryData);
|
||||||
|
DPRINT(" Type = '%S'\n", typeName);
|
||||||
|
RtlInitUnicodeString(&valueName, L"Type");
|
||||||
|
status = ZwSetValueKey(LunExtension->RegistryMapKey,
|
||||||
|
&valueName,
|
||||||
|
0,
|
||||||
|
REG_SZ,
|
||||||
|
typeName,
|
||||||
|
(wcslen(typeName) + 1) * sizeof(WCHAR));
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
DPRINT("ZwSetValueKey('Type') failed (Status %lx)\n", status);
|
||||||
|
goto ByeBye;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set 'InquiryData' (REG_BINARY) value
|
||||||
|
RtlInitUnicodeString(&valueName, L"InquiryData");
|
||||||
|
status = ZwSetValueKey(LunExtension->RegistryMapKey,
|
||||||
|
&valueName,
|
||||||
|
0,
|
||||||
|
REG_BINARY,
|
||||||
|
&LunExtension->InquiryData,
|
||||||
|
INQUIRYDATABUFFERSIZE);
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
DPRINT("ZwSetValueKey('InquiryData') failed (Status %lx)\n", status);
|
||||||
|
goto ByeBye;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByeBye:
|
||||||
|
ZwClose(targetKey);
|
||||||
|
// TODO: maybe we will need it in future
|
||||||
|
ZwClose(LunExtension->RegistryMapKey);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
|
@ -50,47 +50,17 @@ SpiStatusSrbToNt(
|
||||||
static
|
static
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
SpiHandleAttachRelease(
|
SpiHandleAttachRelease(
|
||||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
_In_ PSCSI_PORT_LUN_EXTENSION LunExtension,
|
||||||
_Inout_ PIRP Irp)
|
_Inout_ PIRP Irp)
|
||||||
{
|
{
|
||||||
PSCSI_LUN_INFO LunInfo;
|
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension =
|
||||||
PIO_STACK_LOCATION IrpStack;
|
LunExtension->Common.LowerDevice->DeviceExtension;
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
PSCSI_REQUEST_BLOCK Srb;
|
|
||||||
KIRQL Irql;
|
KIRQL Irql;
|
||||||
|
|
||||||
/* Get pointer to the SRB */
|
/* Get pointer to the SRB */
|
||||||
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
Srb = (PSCSI_REQUEST_BLOCK)IrpStack->Parameters.Others.Argument1;
|
PSCSI_REQUEST_BLOCK Srb = IrpStack->Parameters.Scsi.Srb;
|
||||||
|
|
||||||
/* Check if PathId matches number of buses */
|
|
||||||
if (DeviceExtension->BusesConfig == NULL ||
|
|
||||||
DeviceExtension->BusesConfig->NumberOfBuses <= Srb->PathId)
|
|
||||||
{
|
|
||||||
Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
|
|
||||||
return STATUS_DEVICE_DOES_NOT_EXIST;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get pointer to LunInfo */
|
|
||||||
LunInfo = DeviceExtension->BusesConfig->BusScanInfo[Srb->PathId]->LunInfo;
|
|
||||||
|
|
||||||
/* Find matching LunInfo */
|
|
||||||
while (LunInfo)
|
|
||||||
{
|
|
||||||
if (LunInfo->PathId == Srb->PathId &&
|
|
||||||
LunInfo->TargetId == Srb->TargetId &&
|
|
||||||
LunInfo->Lun == Srb->Lun)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
LunInfo = LunInfo->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we couldn't find it - exit */
|
|
||||||
if (LunInfo == NULL)
|
|
||||||
return STATUS_DEVICE_DOES_NOT_EXIST;
|
|
||||||
|
|
||||||
|
|
||||||
/* Get spinlock */
|
/* Get spinlock */
|
||||||
KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
|
KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
|
||||||
|
@ -98,7 +68,7 @@ SpiHandleAttachRelease(
|
||||||
/* Release, if asked */
|
/* Release, if asked */
|
||||||
if (Srb->Function == SRB_FUNCTION_RELEASE_DEVICE)
|
if (Srb->Function == SRB_FUNCTION_RELEASE_DEVICE)
|
||||||
{
|
{
|
||||||
LunInfo->DeviceClaimed = FALSE;
|
LunExtension->DeviceClaimed = FALSE;
|
||||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
|
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
|
||||||
Srb->SrbStatus = SRB_STATUS_SUCCESS;
|
Srb->SrbStatus = SRB_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
@ -106,7 +76,7 @@ SpiHandleAttachRelease(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attach, if not already claimed */
|
/* Attach, if not already claimed */
|
||||||
if (LunInfo->DeviceClaimed)
|
if (LunExtension->DeviceClaimed)
|
||||||
{
|
{
|
||||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
|
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
|
||||||
Srb->SrbStatus = SRB_STATUS_BUSY;
|
Srb->SrbStatus = SRB_STATUS_BUSY;
|
||||||
|
@ -115,13 +85,13 @@ SpiHandleAttachRelease(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the device object */
|
/* Save the device object */
|
||||||
DeviceObject = LunInfo->DeviceObject;
|
DeviceObject = LunExtension->Common.DeviceObject;
|
||||||
|
|
||||||
if (Srb->Function == SRB_FUNCTION_CLAIM_DEVICE)
|
if (Srb->Function == SRB_FUNCTION_CLAIM_DEVICE)
|
||||||
LunInfo->DeviceClaimed = TRUE;
|
LunExtension->DeviceClaimed = TRUE;
|
||||||
|
|
||||||
if (Srb->Function == SRB_FUNCTION_ATTACH_DEVICE)
|
if (Srb->Function == SRB_FUNCTION_ATTACH_DEVICE)
|
||||||
LunInfo->DeviceObject = Srb->DataBuffer;
|
LunExtension->Common.DeviceObject = Srb->DataBuffer;
|
||||||
|
|
||||||
Srb->DataBuffer = DeviceObject;
|
Srb->DataBuffer = DeviceObject;
|
||||||
|
|
||||||
|
@ -154,8 +124,8 @@ ScsiPortDispatchScsi(
|
||||||
_In_ PDEVICE_OBJECT DeviceObject,
|
_In_ PDEVICE_OBJECT DeviceObject,
|
||||||
_Inout_ PIRP Irp)
|
_Inout_ PIRP Irp)
|
||||||
{
|
{
|
||||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
PSCSI_PORT_DEVICE_EXTENSION portExt;
|
||||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
PSCSI_PORT_LUN_EXTENSION lunExt;
|
||||||
PIO_STACK_LOCATION Stack;
|
PIO_STACK_LOCATION Stack;
|
||||||
PSCSI_REQUEST_BLOCK Srb;
|
PSCSI_REQUEST_BLOCK Srb;
|
||||||
KIRQL Irql;
|
KIRQL Irql;
|
||||||
|
@ -165,10 +135,12 @@ ScsiPortDispatchScsi(
|
||||||
|
|
||||||
DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
|
DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
|
||||||
|
|
||||||
DeviceExtension = DeviceObject->DeviceExtension;
|
|
||||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
Srb = Stack->Parameters.Scsi.Srb;
|
Srb = Stack->Parameters.Scsi.Srb;
|
||||||
|
lunExt = DeviceObject->DeviceExtension;
|
||||||
|
ASSERT(!lunExt->Common.IsFDO);
|
||||||
|
portExt = lunExt->Common.LowerDevice->DeviceExtension;
|
||||||
|
|
||||||
if (Srb == NULL)
|
if (Srb == NULL)
|
||||||
{
|
{
|
||||||
DPRINT1("ScsiPortDispatchScsi() called with Srb = NULL!\n");
|
DPRINT1("ScsiPortDispatchScsi() called with Srb = NULL!\n");
|
||||||
|
@ -179,15 +151,16 @@ ScsiPortDispatchScsi(
|
||||||
|
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
return (Status);
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT("Srb: %p\n", Srb);
|
DPRINT("Srb: %p, Srb->Function: %lu\n", Srb, Srb->Function);
|
||||||
DPRINT("Srb->Function: %lu\n", Srb->Function);
|
|
||||||
DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
|
|
||||||
|
|
||||||
LunExtension = SpiGetLunExtension(DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
|
Srb->PathId = lunExt->PathId;
|
||||||
if (LunExtension == NULL)
|
Srb->TargetId = lunExt->TargetId;
|
||||||
|
Srb->Lun = lunExt->Lun;
|
||||||
|
|
||||||
|
if (lunExt == NULL)
|
||||||
{
|
{
|
||||||
DPRINT("ScsiPortDispatchScsi() called with an invalid LUN\n");
|
DPRINT("ScsiPortDispatchScsi() called with an invalid LUN\n");
|
||||||
Status = STATUS_NO_SUCH_DEVICE;
|
Status = STATUS_NO_SUCH_DEVICE;
|
||||||
|
@ -198,7 +171,7 @@ ScsiPortDispatchScsi(
|
||||||
|
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
return (Status);
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Srb->Function)
|
switch (Srb->Function)
|
||||||
|
@ -206,7 +179,7 @@ ScsiPortDispatchScsi(
|
||||||
case SRB_FUNCTION_SHUTDOWN:
|
case SRB_FUNCTION_SHUTDOWN:
|
||||||
case SRB_FUNCTION_FLUSH:
|
case SRB_FUNCTION_FLUSH:
|
||||||
DPRINT(" SRB_FUNCTION_SHUTDOWN or FLUSH\n");
|
DPRINT(" SRB_FUNCTION_SHUTDOWN or FLUSH\n");
|
||||||
if (DeviceExtension->CachesData == FALSE)
|
if (portExt->CachesData == FALSE)
|
||||||
{
|
{
|
||||||
/* All success here */
|
/* All success here */
|
||||||
Srb->SrbStatus = SRB_STATUS_SUCCESS;
|
Srb->SrbStatus = SRB_STATUS_SUCCESS;
|
||||||
|
@ -225,7 +198,7 @@ ScsiPortDispatchScsi(
|
||||||
if (Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)
|
if (Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)
|
||||||
{
|
{
|
||||||
/* Start IO directly */
|
/* Start IO directly */
|
||||||
IoStartPacket(DeviceObject, Irp, NULL, NULL);
|
IoStartPacket(portExt->Common.DeviceObject, Irp, NULL, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -235,13 +208,12 @@ ScsiPortDispatchScsi(
|
||||||
KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
|
KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
|
||||||
|
|
||||||
/* Insert IRP into the queue */
|
/* Insert IRP into the queue */
|
||||||
if (!KeInsertByKeyDeviceQueue(
|
if (!KeInsertByKeyDeviceQueue(&lunExt->DeviceQueue,
|
||||||
&LunExtension->DeviceQueue,
|
|
||||||
&Irp->Tail.Overlay.DeviceQueueEntry,
|
&Irp->Tail.Overlay.DeviceQueueEntry,
|
||||||
Srb->QueueSortKey))
|
Srb->QueueSortKey))
|
||||||
{
|
{
|
||||||
/* It means the queue is empty, and we just start this request */
|
/* It means the queue is empty, and we just start this request */
|
||||||
IoStartPacket(DeviceObject, Irp, NULL, NULL);
|
IoStartPacket(portExt->Common.DeviceObject, Irp, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Back to the old IRQL */
|
/* Back to the old IRQL */
|
||||||
|
@ -254,39 +226,40 @@ ScsiPortDispatchScsi(
|
||||||
DPRINT(" SRB_FUNCTION_CLAIM_DEVICE or ATTACH\n");
|
DPRINT(" SRB_FUNCTION_CLAIM_DEVICE or ATTACH\n");
|
||||||
|
|
||||||
/* Reference device object and keep the device object */
|
/* Reference device object and keep the device object */
|
||||||
Status = SpiHandleAttachRelease(DeviceExtension, Irp);
|
Status = SpiHandleAttachRelease(lunExt, Irp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SRB_FUNCTION_RELEASE_DEVICE:
|
case SRB_FUNCTION_RELEASE_DEVICE:
|
||||||
DPRINT(" SRB_FUNCTION_RELEASE_DEVICE\n");
|
DPRINT(" SRB_FUNCTION_RELEASE_DEVICE\n");
|
||||||
|
|
||||||
/* Dereference device object and clear the device object */
|
/* Dereference device object and clear the device object */
|
||||||
Status = SpiHandleAttachRelease(DeviceExtension, Irp);
|
Status = SpiHandleAttachRelease(lunExt, Irp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SRB_FUNCTION_RELEASE_QUEUE:
|
case SRB_FUNCTION_RELEASE_QUEUE:
|
||||||
DPRINT(" SRB_FUNCTION_RELEASE_QUEUE\n");
|
DPRINT(" SRB_FUNCTION_RELEASE_QUEUE\n");
|
||||||
|
|
||||||
/* Guard with the spinlock */
|
/* Guard with the spinlock */
|
||||||
KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
|
KeAcquireSpinLock(&portExt->SpinLock, &Irql);
|
||||||
|
|
||||||
if (!(LunExtension->Flags & LUNEX_FROZEN_QUEUE))
|
if (!(lunExt->Flags & LUNEX_FROZEN_QUEUE))
|
||||||
{
|
{
|
||||||
DPRINT("Queue is not frozen really\n");
|
DPRINT("Queue is not frozen really\n");
|
||||||
|
|
||||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
|
KeReleaseSpinLock(&portExt->SpinLock, Irql);
|
||||||
Srb->SrbStatus = SRB_STATUS_SUCCESS;
|
Srb->SrbStatus = SRB_STATUS_SUCCESS;
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unfreeze the queue */
|
/* Unfreeze the queue */
|
||||||
LunExtension->Flags &= ~LUNEX_FROZEN_QUEUE;
|
lunExt->Flags &= ~LUNEX_FROZEN_QUEUE;
|
||||||
|
|
||||||
if (LunExtension->SrbInfo.Srb == NULL)
|
if (lunExt->SrbInfo.Srb == NULL)
|
||||||
{
|
{
|
||||||
/* Get next logical unit request */
|
/* Get next logical unit request */
|
||||||
SpiGetNextRequestFromLun(DeviceExtension, LunExtension);
|
SpiGetNextRequestFromLun(portExt, lunExt);
|
||||||
|
|
||||||
/* SpiGetNextRequestFromLun() releases the spinlock */
|
/* SpiGetNextRequestFromLun() releases the spinlock */
|
||||||
KeLowerIrql(Irql);
|
KeLowerIrql(Irql);
|
||||||
|
@ -294,7 +267,7 @@ ScsiPortDispatchScsi(
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DPRINT("The queue has active request\n");
|
DPRINT("The queue has active request\n");
|
||||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
|
KeReleaseSpinLock(&portExt->SpinLock, Irql);
|
||||||
}
|
}
|
||||||
|
|
||||||
Srb->SrbStatus = SRB_STATUS_SUCCESS;
|
Srb->SrbStatus = SRB_STATUS_SUCCESS;
|
||||||
|
@ -305,23 +278,23 @@ ScsiPortDispatchScsi(
|
||||||
DPRINT(" SRB_FUNCTION_FLUSH_QUEUE\n");
|
DPRINT(" SRB_FUNCTION_FLUSH_QUEUE\n");
|
||||||
|
|
||||||
/* Guard with the spinlock */
|
/* Guard with the spinlock */
|
||||||
KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
|
KeAcquireSpinLock(&portExt->SpinLock, &Irql);
|
||||||
|
|
||||||
if (!(LunExtension->Flags & LUNEX_FROZEN_QUEUE))
|
if (!(lunExt->Flags & LUNEX_FROZEN_QUEUE))
|
||||||
{
|
{
|
||||||
DPRINT("Queue is not frozen really\n");
|
DPRINT("Queue is not frozen really\n");
|
||||||
|
|
||||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
|
KeReleaseSpinLock(&portExt->SpinLock, Irql);
|
||||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure there is no active request */
|
/* Make sure there is no active request */
|
||||||
ASSERT(LunExtension->SrbInfo.Srb == NULL);
|
ASSERT(lunExt->SrbInfo.Srb == NULL);
|
||||||
|
|
||||||
/* Compile a list from the device queue */
|
/* Compile a list from the device queue */
|
||||||
IrpList = NULL;
|
IrpList = NULL;
|
||||||
while ((Entry = KeRemoveDeviceQueue(&LunExtension->DeviceQueue)) != NULL)
|
while ((Entry = KeRemoveDeviceQueue(&lunExt->DeviceQueue)) != NULL)
|
||||||
{
|
{
|
||||||
NextIrp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DeviceQueueEntry);
|
NextIrp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DeviceQueueEntry);
|
||||||
|
|
||||||
|
@ -339,10 +312,10 @@ ScsiPortDispatchScsi(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unfreeze the queue */
|
/* Unfreeze the queue */
|
||||||
LunExtension->Flags &= ~LUNEX_FROZEN_QUEUE;
|
lunExt->Flags &= ~LUNEX_FROZEN_QUEUE;
|
||||||
|
|
||||||
/* Release the spinlock */
|
/* Release the spinlock */
|
||||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
|
KeReleaseSpinLock(&portExt->SpinLock, Irql);
|
||||||
|
|
||||||
/* Complete those requests */
|
/* Complete those requests */
|
||||||
while (IrpList)
|
while (IrpList)
|
||||||
|
@ -415,7 +388,7 @@ SpiGetNextRequestFromLun(
|
||||||
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
|
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
|
||||||
|
|
||||||
/* Start the next pending request */
|
/* Start the next pending request */
|
||||||
IoStartPacket(DeviceExtension->DeviceObject, NextIrp, (PULONG)NULL, NULL);
|
IoStartPacket(DeviceExtension->Common.DeviceObject, NextIrp, (PULONG)NULL, NULL);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -454,7 +427,7 @@ SpiGetNextRequestFromLun(
|
||||||
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
|
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
|
||||||
|
|
||||||
/* Start the next pending request */
|
/* Start the next pending request */
|
||||||
IoStartPacket(DeviceExtension->DeviceObject, NextIrp, (PULONG)NULL, NULL);
|
IoStartPacket(DeviceExtension->Common.DeviceObject, NextIrp, (PULONG)NULL, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -525,7 +498,7 @@ SpiSenseCompletionRoutine(
|
||||||
static
|
static
|
||||||
VOID
|
VOID
|
||||||
SpiSendRequestSense(
|
SpiSendRequestSense(
|
||||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
_In_ PSCSI_PORT_LUN_EXTENSION LunExtension,
|
||||||
_In_ PSCSI_REQUEST_BLOCK InitialSrb)
|
_In_ PSCSI_REQUEST_BLOCK InitialSrb)
|
||||||
{
|
{
|
||||||
PSCSI_REQUEST_BLOCK Srb;
|
PSCSI_REQUEST_BLOCK Srb;
|
||||||
|
@ -544,7 +517,7 @@ SpiSendRequestSense(
|
||||||
/* Allocate IRP */
|
/* Allocate IRP */
|
||||||
LargeInt.QuadPart = (LONGLONG) 1;
|
LargeInt.QuadPart = (LONGLONG) 1;
|
||||||
Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_READ,
|
Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_READ,
|
||||||
DeviceExtension->DeviceObject,
|
LunExtension->Common.DeviceObject,
|
||||||
InitialSrb->SenseInfoBuffer,
|
InitialSrb->SenseInfoBuffer,
|
||||||
InitialSrb->SenseInfoBufferLength,
|
InitialSrb->SenseInfoBufferLength,
|
||||||
&LargeInt,
|
&LargeInt,
|
||||||
|
@ -621,7 +594,7 @@ SpiSendRequestSense(
|
||||||
Srb->NextSrb = 0;
|
Srb->NextSrb = 0;
|
||||||
|
|
||||||
/* Call the driver */
|
/* Call the driver */
|
||||||
(VOID)IoCallDriver(DeviceExtension->DeviceObject, Irp);
|
(VOID)IoCallDriver(LunExtension->Common.DeviceObject, Irp);
|
||||||
|
|
||||||
DPRINT("SpiSendRequestSense() done\n");
|
DPRINT("SpiSendRequestSense() done\n");
|
||||||
}
|
}
|
||||||
|
@ -642,12 +615,11 @@ SpiProcessCompletedRequest(
|
||||||
|
|
||||||
Srb = SrbInfo->Srb;
|
Srb = SrbInfo->Srb;
|
||||||
Irp = Srb->OriginalRequest;
|
Irp = Srb->OriginalRequest;
|
||||||
|
PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
/* Get Lun extension */
|
/* Get Lun extension */
|
||||||
LunExtension = SpiGetLunExtension(DeviceExtension,
|
LunExtension = IoStack->DeviceObject->DeviceExtension;
|
||||||
Srb->PathId,
|
ASSERT(LunExtension && !LunExtension->Common.IsFDO);
|
||||||
Srb->TargetId,
|
|
||||||
Srb->Lun);
|
|
||||||
|
|
||||||
if (Srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION &&
|
if (Srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION &&
|
||||||
DeviceExtension->MapBuffers &&
|
DeviceExtension->MapBuffers &&
|
||||||
|
@ -697,7 +669,7 @@ SpiProcessCompletedRequest(
|
||||||
!(*NeedToCallStartIo))
|
!(*NeedToCallStartIo))
|
||||||
{
|
{
|
||||||
/* We're not busy, but we have a request pending */
|
/* We're not busy, but we have a request pending */
|
||||||
IoStartNextPacket(DeviceExtension->DeviceObject, FALSE);
|
IoStartNextPacket(DeviceExtension->Common.DeviceObject, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -931,7 +903,7 @@ Error:
|
||||||
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
|
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
|
||||||
|
|
||||||
/* Send RequestSense */
|
/* Send RequestSense */
|
||||||
SpiSendRequestSense(DeviceExtension, Srb);
|
SpiSendRequestSense(LunExtension, Srb);
|
||||||
|
|
||||||
/* Exit */
|
/* Exit */
|
||||||
return;
|
return;
|
||||||
|
@ -950,10 +922,11 @@ NTAPI
|
||||||
ScsiPortStartPacket(
|
ScsiPortStartPacket(
|
||||||
_In_ PVOID Context)
|
_In_ PVOID Context)
|
||||||
{
|
{
|
||||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
|
||||||
PIO_STACK_LOCATION IrpStack;
|
PIO_STACK_LOCATION IrpStack;
|
||||||
PSCSI_REQUEST_BLOCK Srb;
|
PSCSI_REQUEST_BLOCK Srb;
|
||||||
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context;
|
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context;
|
||||||
|
PSCSI_PORT_COMMON_EXTENSION CommonExtension = DeviceObject->DeviceExtension;
|
||||||
|
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
||||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
||||||
PSCSI_REQUEST_BLOCK_INFO SrbInfo;
|
PSCSI_REQUEST_BLOCK_INFO SrbInfo;
|
||||||
BOOLEAN Result;
|
BOOLEAN Result;
|
||||||
|
@ -961,16 +934,20 @@ ScsiPortStartPacket(
|
||||||
|
|
||||||
DPRINT("ScsiPortStartPacket() called\n");
|
DPRINT("ScsiPortStartPacket() called\n");
|
||||||
|
|
||||||
DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
||||||
|
|
||||||
IrpStack = IoGetCurrentIrpStackLocation(DeviceObject->CurrentIrp);
|
IrpStack = IoGetCurrentIrpStackLocation(DeviceObject->CurrentIrp);
|
||||||
Srb = IrpStack->Parameters.Scsi.Srb;
|
Srb = IrpStack->Parameters.Scsi.Srb;
|
||||||
|
|
||||||
/* Get LUN extension */
|
if (CommonExtension->IsFDO) // IsFDO
|
||||||
LunExtension = SpiGetLunExtension(DeviceExtension,
|
{
|
||||||
Srb->PathId,
|
DeviceExtension = DeviceObject->DeviceExtension;
|
||||||
Srb->TargetId,
|
LunExtension = IrpStack->DeviceObject->DeviceExtension;
|
||||||
Srb->Lun);
|
ASSERT(LunExtension && !LunExtension->Common.IsFDO);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LunExtension = DeviceObject->DeviceExtension;
|
||||||
|
DeviceExtension = LunExtension->Common.LowerDevice->DeviceExtension;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if we are in a reset state */
|
/* Check if we are in a reset state */
|
||||||
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_RESET)
|
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_RESET)
|
||||||
|
@ -1006,11 +983,7 @@ ScsiPortStartPacket(
|
||||||
if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND)
|
if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND)
|
||||||
{
|
{
|
||||||
/* Get pointer to SRB info structure */
|
/* Get pointer to SRB info structure */
|
||||||
SrbInfo = SpiGetSrbData(DeviceExtension,
|
SrbInfo = SpiGetSrbData(DeviceExtension, LunExtension, Srb->QueueTag);
|
||||||
Srb->PathId,
|
|
||||||
Srb->TargetId,
|
|
||||||
Srb->Lun,
|
|
||||||
Srb->QueueTag);
|
|
||||||
|
|
||||||
/* Check if the request is still "active" */
|
/* Check if the request is still "active" */
|
||||||
if (SrbInfo == NULL ||
|
if (SrbInfo == NULL ||
|
||||||
|
@ -1036,7 +1009,7 @@ ScsiPortStartPacket(
|
||||||
DeviceExtension->MiniPortDeviceExtension);
|
DeviceExtension->MiniPortDeviceExtension);
|
||||||
|
|
||||||
/* They might ask for some work, so queue the DPC for them */
|
/* They might ask for some work, so queue the DPC for them */
|
||||||
IoRequestDpc(DeviceExtension->DeviceObject, NULL, NULL);
|
IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL);
|
||||||
|
|
||||||
/* We're done in this branch */
|
/* We're done in this branch */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -1096,7 +1069,7 @@ ScsiPortStartPacket(
|
||||||
|
|
||||||
/* If notification is needed, then request a DPC */
|
/* If notification is needed, then request a DPC */
|
||||||
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
|
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
|
||||||
IoRequestDpc(DeviceExtension->DeviceObject, NULL, NULL);
|
IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
@ -1140,10 +1113,9 @@ SpiSaveInterruptData(IN PVOID Context)
|
||||||
/* Get SRB and LunExtension */
|
/* Get SRB and LunExtension */
|
||||||
Srb = SrbInfo->Srb;
|
Srb = SrbInfo->Srb;
|
||||||
|
|
||||||
LunExtension = SpiGetLunExtension(DeviceExtension,
|
PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Srb->OriginalRequest);
|
||||||
Srb->PathId,
|
LunExtension = IoStack->DeviceObject->DeviceExtension;
|
||||||
Srb->TargetId,
|
ASSERT(LunExtension && !LunExtension->Common.IsFDO);
|
||||||
Srb->Lun);
|
|
||||||
|
|
||||||
/* We have to check special cases if request is unsuccessful*/
|
/* We have to check special cases if request is unsuccessful*/
|
||||||
if (Srb->SrbStatus != SRB_STATUS_SUCCESS)
|
if (Srb->SrbStatus != SRB_STATUS_SUCCESS)
|
||||||
|
@ -1359,7 +1331,7 @@ TryAgain:
|
||||||
|
|
||||||
/* If we ready for next packet, start it */
|
/* If we ready for next packet, start it */
|
||||||
if (InterruptData.Flags & SCSI_PORT_NEXT_REQUEST_READY)
|
if (InterruptData.Flags & SCSI_PORT_NEXT_REQUEST_READY)
|
||||||
IoStartNextPacket(DeviceExtension->DeviceObject, FALSE);
|
IoStartNextPacket(DeviceExtension->Common.DeviceObject, FALSE);
|
||||||
|
|
||||||
NeedToStartIo = FALSE;
|
NeedToStartIo = FALSE;
|
||||||
|
|
||||||
|
@ -1456,11 +1428,7 @@ SpiAllocateSrbStructures(
|
||||||
/* Treat the abort request in a special way */
|
/* Treat the abort request in a special way */
|
||||||
if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND)
|
if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND)
|
||||||
{
|
{
|
||||||
SrbInfo = SpiGetSrbData(DeviceExtension,
|
SrbInfo = SpiGetSrbData(DeviceExtension, LunExtension, Srb->QueueTag);
|
||||||
Srb->PathId,
|
|
||||||
Srb->TargetId,
|
|
||||||
Srb->Lun,
|
|
||||||
Srb->QueueTag);
|
|
||||||
}
|
}
|
||||||
else if (Srb->SrbFlags &
|
else if (Srb->SrbFlags &
|
||||||
(SRB_FLAGS_QUEUE_ACTION_ENABLE | SRB_FLAGS_NO_QUEUE_FREEZE) &&
|
(SRB_FLAGS_QUEUE_ACTION_ENABLE | SRB_FLAGS_NO_QUEUE_FREEZE) &&
|
||||||
|
@ -1606,20 +1574,18 @@ ScsiPortStartIo(
|
||||||
|
|
||||||
DeviceExtension = DeviceObject->DeviceExtension;
|
DeviceExtension = DeviceObject->DeviceExtension;
|
||||||
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
LunExtension = IrpStack->DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
DPRINT("DeviceExtension %p\n", DeviceExtension);
|
ASSERT(DeviceExtension->Common.IsFDO);
|
||||||
|
ASSERT(!LunExtension->Common.IsFDO);
|
||||||
|
|
||||||
|
DPRINT("LunExtension %p DeviceExtension %p\n", LunExtension, DeviceExtension);
|
||||||
|
|
||||||
Srb = IrpStack->Parameters.Scsi.Srb;
|
Srb = IrpStack->Parameters.Scsi.Srb;
|
||||||
|
|
||||||
/* Apply "default" flags */
|
/* Apply "default" flags */
|
||||||
Srb->SrbFlags |= DeviceExtension->SrbFlags;
|
Srb->SrbFlags |= DeviceExtension->SrbFlags;
|
||||||
|
|
||||||
/* Get LUN extension */
|
|
||||||
LunExtension = SpiGetLunExtension(DeviceExtension,
|
|
||||||
Srb->PathId,
|
|
||||||
Srb->TargetId,
|
|
||||||
Srb->Lun);
|
|
||||||
|
|
||||||
if (DeviceExtension->NeedSrbDataAlloc ||
|
if (DeviceExtension->NeedSrbDataAlloc ||
|
||||||
DeviceExtension->NeedSrbExtensionAlloc)
|
DeviceExtension->NeedSrbExtensionAlloc)
|
||||||
{
|
{
|
||||||
|
@ -1699,7 +1665,7 @@ ScsiPortStartIo(
|
||||||
|
|
||||||
/* Allocate adapter channel */
|
/* Allocate adapter channel */
|
||||||
Status = IoAllocateAdapterChannel(DeviceExtension->AdapterObject,
|
Status = IoAllocateAdapterChannel(DeviceExtension->AdapterObject,
|
||||||
DeviceExtension->DeviceObject,
|
DeviceExtension->Common.DeviceObject,
|
||||||
SrbInfo->NumberOfMapRegisters,
|
SrbInfo->NumberOfMapRegisters,
|
||||||
SpiAdapterControl,
|
SpiAdapterControl,
|
||||||
SrbInfo);
|
SrbInfo);
|
||||||
|
@ -1717,7 +1683,7 @@ ScsiPortStartIo(
|
||||||
DeviceExtension + 1);
|
DeviceExtension + 1);
|
||||||
|
|
||||||
/* Request DPC for that work */
|
/* Request DPC for that work */
|
||||||
IoRequestDpc(DeviceExtension->DeviceObject, NULL, NULL);
|
IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Control goes to SpiAdapterControl */
|
/* Control goes to SpiAdapterControl */
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* PURPOSE: Main and exported functions
|
* PURPOSE: Main and exported functions
|
||||||
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
||||||
* Aleksey Bragin (aleksey@reactos.org)
|
* Aleksey Bragin (aleksey@reactos.org)
|
||||||
|
* 2020 Victor Perevertkin (victor.perevertkin@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
@ -112,8 +113,43 @@ NTSTATUS NTAPI
|
||||||
DriverEntry(IN PDRIVER_OBJECT DriverObject,
|
DriverEntry(IN PDRIVER_OBJECT DriverObject,
|
||||||
IN PUNICODE_STRING RegistryPath)
|
IN PUNICODE_STRING RegistryPath)
|
||||||
{
|
{
|
||||||
DPRINT("ScsiPort Driver %s\n", VERSION);
|
return STATUS_SUCCESS;
|
||||||
return(STATUS_SUCCESS);
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
ScsiPortUnload(
|
||||||
|
_In_ PDRIVER_OBJECT DriverObject)
|
||||||
|
{
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
ScsiPortDispatchPnp(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
if (((PSCSI_PORT_COMMON_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
|
||||||
|
{
|
||||||
|
return FdoDispatchPnp(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return PdoDispatchPnp(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
ScsiPortAddDevice(
|
||||||
|
_In_ PDRIVER_OBJECT DriverObject,
|
||||||
|
_In_ PDEVICE_OBJECT PhysicalDeviceObject)
|
||||||
|
{
|
||||||
|
|
||||||
|
DPRINT("AddDevice no-op DriverObj: %p, PDO: %p\n", DriverObject, PhysicalDeviceObject);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -202,8 +238,6 @@ ScsiPortCompleteRequest(IN PVOID HwDeviceExtension,
|
||||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
||||||
PSCSI_REQUEST_BLOCK_INFO SrbInfo;
|
PSCSI_REQUEST_BLOCK_INFO SrbInfo;
|
||||||
PLIST_ENTRY ListEntry;
|
PLIST_ENTRY ListEntry;
|
||||||
ULONG BusNumber;
|
|
||||||
ULONG Target;
|
|
||||||
|
|
||||||
DPRINT("ScsiPortCompleteRequest() called\n");
|
DPRINT("ScsiPortCompleteRequest() called\n");
|
||||||
|
|
||||||
|
@ -212,17 +246,17 @@ ScsiPortCompleteRequest(IN PVOID HwDeviceExtension,
|
||||||
MiniPortDeviceExtension);
|
MiniPortDeviceExtension);
|
||||||
|
|
||||||
/* Go through all buses */
|
/* Go through all buses */
|
||||||
for (BusNumber = 0; BusNumber < 8; BusNumber++)
|
for (UINT8 pathId = 0; pathId < DeviceExtension->NumberOfBuses; pathId++)
|
||||||
{
|
{
|
||||||
/* Go through all targets */
|
PSCSI_BUS_INFO bus = &DeviceExtension->Buses[pathId];
|
||||||
for (Target = 0; Target < DeviceExtension->MaxTargedIds; Target++)
|
|
||||||
{
|
|
||||||
/* Get logical unit list head */
|
|
||||||
LunExtension = DeviceExtension->LunExtensionList[Target % 8];
|
|
||||||
|
|
||||||
/* Go through all logical units */
|
/* Go through all logical units */
|
||||||
while (LunExtension)
|
for (PLIST_ENTRY lunEntry = bus->LunsListHead.Flink;
|
||||||
|
lunEntry != &bus->LunsListHead;
|
||||||
|
lunEntry = lunEntry->Flink)
|
||||||
{
|
{
|
||||||
|
LunExtension = CONTAINING_RECORD(lunEntry, SCSI_PORT_LUN_EXTENSION, LunEntry);
|
||||||
|
|
||||||
/* Now match what caller asked with what we are at now */
|
/* Now match what caller asked with what we are at now */
|
||||||
if ((PathId == SP_UNTAGGED || PathId == LunExtension->PathId) &&
|
if ((PathId == SP_UNTAGGED || PathId == LunExtension->PathId) &&
|
||||||
(TargetId == SP_UNTAGGED || TargetId == LunExtension->TargetId) &&
|
(TargetId == SP_UNTAGGED || TargetId == LunExtension->TargetId) &&
|
||||||
|
@ -263,10 +297,6 @@ ScsiPortCompleteRequest(IN PVOID HwDeviceExtension,
|
||||||
ListEntry = SrbInfo->Requests.Flink;
|
ListEntry = SrbInfo->Requests.Flink;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Advance to the next one */
|
|
||||||
LunExtension = LunExtension->Next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -468,10 +498,8 @@ ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
LunExtension = SpiGetLunExtension(DeviceExtension,
|
LunExtension = GetLunByPath(DeviceExtension, PathId, TargetId, Lun);
|
||||||
PathId,
|
|
||||||
TargetId,
|
|
||||||
Lun);
|
|
||||||
/* Check that the logical unit exists */
|
/* Check that the logical unit exists */
|
||||||
if (!LunExtension)
|
if (!LunExtension)
|
||||||
{
|
{
|
||||||
|
@ -517,12 +545,12 @@ ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
|
||||||
}
|
}
|
||||||
else if (DeviceExtension->MapRegisters)
|
else if (DeviceExtension->MapRegisters)
|
||||||
{
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Srb->OriginalRequest);
|
||||||
|
PSCSI_PORT_LUN_EXTENSION LunExtension = IoStack->DeviceObject->DeviceExtension;
|
||||||
|
ASSERT(LunExtension && !LunExtension->Common.IsFDO);
|
||||||
|
|
||||||
/* Scatter-gather list must be used */
|
/* Scatter-gather list must be used */
|
||||||
SrbInfo = SpiGetSrbData(DeviceExtension,
|
SrbInfo = SpiGetSrbData(DeviceExtension, LunExtension, Srb->QueueTag);
|
||||||
Srb->PathId,
|
|
||||||
Srb->TargetId,
|
|
||||||
Srb->Lun,
|
|
||||||
Srb->QueueTag);
|
|
||||||
|
|
||||||
SGList = SrbInfo->ScatterGather;
|
SGList = SrbInfo->ScatterGather;
|
||||||
|
|
||||||
|
@ -816,7 +844,6 @@ ScsiPortInitialize(
|
||||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = NULL;
|
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = NULL;
|
||||||
PCONFIGURATION_INFORMATION SystemConfig;
|
PCONFIGURATION_INFORMATION SystemConfig;
|
||||||
PPORT_CONFIGURATION_INFORMATION PortConfig;
|
PPORT_CONFIGURATION_INFORMATION PortConfig;
|
||||||
PORT_CONFIGURATION_INFORMATION InitialPortConfig;
|
|
||||||
CONFIGURATION_INFO ConfigInfo;
|
CONFIGURATION_INFO ConfigInfo;
|
||||||
ULONG DeviceExtensionSize;
|
ULONG DeviceExtensionSize;
|
||||||
ULONG PortConfigSize;
|
ULONG PortConfigSize;
|
||||||
|
@ -829,16 +856,10 @@ ScsiPortInitialize(
|
||||||
PCI_SLOT_NUMBER SlotNumber;
|
PCI_SLOT_NUMBER SlotNumber;
|
||||||
|
|
||||||
PDEVICE_OBJECT PortDeviceObject;
|
PDEVICE_OBJECT PortDeviceObject;
|
||||||
WCHAR NameBuffer[80];
|
|
||||||
UNICODE_STRING DeviceName;
|
UNICODE_STRING DeviceName;
|
||||||
WCHAR DosNameBuffer[80];
|
|
||||||
UNICODE_STRING DosDeviceName;
|
|
||||||
PIO_SCSI_CAPABILITIES PortCapabilities;
|
PIO_SCSI_CAPABILITIES PortCapabilities;
|
||||||
|
|
||||||
PCM_RESOURCE_LIST ResourceList;
|
PCM_RESOURCE_LIST ResourceList;
|
||||||
BOOLEAN Conflict;
|
|
||||||
SIZE_T BusConfigSize;
|
|
||||||
|
|
||||||
|
|
||||||
DPRINT ("ScsiPortInitialize() called!\n");
|
DPRINT ("ScsiPortInitialize() called!\n");
|
||||||
|
|
||||||
|
@ -849,15 +870,46 @@ ScsiPortInitialize(
|
||||||
(HwInitializationData->HwFindAdapter == NULL) ||
|
(HwInitializationData->HwFindAdapter == NULL) ||
|
||||||
(HwInitializationData->HwResetBus == NULL))
|
(HwInitializationData->HwResetBus == NULL))
|
||||||
{
|
{
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_REVISION_MISMATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PSCSI_PORT_DRIVER_EXTENSION driverExtension;
|
||||||
|
|
||||||
|
// ScsiPortInitialize may be called multiple times by the same driver
|
||||||
|
driverExtension = IoGetDriverObjectExtension(DriverObject, HwInitializationData->HwInitialize);
|
||||||
|
|
||||||
|
if (!driverExtension)
|
||||||
|
{
|
||||||
|
Status = IoAllocateDriverObjectExtension(DriverObject,
|
||||||
|
HwInitializationData->HwInitialize,
|
||||||
|
sizeof(SCSI_PORT_DRIVER_EXTENSION),
|
||||||
|
(PVOID *)&driverExtension);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to allocate the driver extension! Status 0x%x\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up the driver extension
|
||||||
|
driverExtension->RegistryPath.Buffer =
|
||||||
|
ExAllocatePoolWithTag(PagedPool, RegistryPath->MaximumLength, TAG_SCSIPORT);
|
||||||
|
driverExtension->RegistryPath.MaximumLength = RegistryPath->MaximumLength;
|
||||||
|
RtlCopyUnicodeString(&driverExtension->RegistryPath, RegistryPath);
|
||||||
|
|
||||||
|
driverExtension->DriverObject = DriverObject;
|
||||||
|
|
||||||
/* Set handlers */
|
/* Set handlers */
|
||||||
|
DriverObject->DriverUnload = ScsiPortUnload;
|
||||||
DriverObject->DriverStartIo = ScsiPortStartIo;
|
DriverObject->DriverStartIo = ScsiPortStartIo;
|
||||||
|
DriverObject->DriverExtension->AddDevice = ScsiPortAddDevice;
|
||||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose;
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose;
|
||||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose;
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose;
|
||||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;
|
||||||
DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi;
|
DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_PNP] = ScsiPortDispatchPnp;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_POWER] = ScsiPortDispatchPower;
|
||||||
|
|
||||||
/* Obtain configuration information */
|
/* Obtain configuration information */
|
||||||
SystemConfig = IoGetConfigurationInformation();
|
SystemConfig = IoGetConfigurationInformation();
|
||||||
|
@ -880,8 +932,11 @@ ScsiPortInitialize(
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open registry keys */
|
/* Open registry keys and fill the driverExtension */
|
||||||
SpiInitOpenKeys(&ConfigInfo, (PUNICODE_STRING)Argument2);
|
SpiInitOpenKeys(&ConfigInfo, driverExtension);
|
||||||
|
|
||||||
|
// FIXME: PnP miniports are not supported
|
||||||
|
ASSERT(driverExtension->IsLegacyDriver);
|
||||||
|
|
||||||
/* Last adapter number = not known */
|
/* Last adapter number = not known */
|
||||||
ConfigInfo.LastAdapterNumber = SP_UNINITIALIZED_VALUE;
|
ConfigInfo.LastAdapterNumber = SP_UNINITIALIZED_VALUE;
|
||||||
|
@ -895,11 +950,18 @@ ScsiPortInitialize(
|
||||||
|
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
|
WCHAR NameBuffer[27];
|
||||||
/* Create a unicode device name */
|
/* Create a unicode device name */
|
||||||
swprintf(NameBuffer,
|
swprintf(NameBuffer,
|
||||||
L"\\Device\\ScsiPort%lu",
|
L"\\Device\\ScsiPort%lu",
|
||||||
SystemConfig->ScsiPortCount);
|
SystemConfig->ScsiPortCount);
|
||||||
RtlInitUnicodeString(&DeviceName, NameBuffer);
|
if (!RtlCreateUnicodeString(&DeviceName, NameBuffer))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to allocate memory for device name!\n");
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
PortDeviceObject = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
DPRINT("Creating device: %wZ\n", &DeviceName);
|
DPRINT("Creating device: %wZ\n", &DeviceName);
|
||||||
|
|
||||||
|
@ -908,7 +970,7 @@ ScsiPortInitialize(
|
||||||
DeviceExtensionSize,
|
DeviceExtensionSize,
|
||||||
&DeviceName,
|
&DeviceName,
|
||||||
FILE_DEVICE_CONTROLLER,
|
FILE_DEVICE_CONTROLLER,
|
||||||
0,
|
FILE_DEVICE_SECURE_OPEN,
|
||||||
FALSE,
|
FALSE,
|
||||||
&PortDeviceObject);
|
&PortDeviceObject);
|
||||||
|
|
||||||
|
@ -919,7 +981,7 @@ ScsiPortInitialize(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT ("Created device: %wZ (%p)\n", &DeviceName, PortDeviceObject);
|
DPRINT1("Created device: %wZ (%p)\n", &DeviceName, PortDeviceObject);
|
||||||
|
|
||||||
/* Set the buffering strategy here... */
|
/* Set the buffering strategy here... */
|
||||||
PortDeviceObject->Flags |= DO_DIRECT_IO;
|
PortDeviceObject->Flags |= DO_DIRECT_IO;
|
||||||
|
@ -928,9 +990,11 @@ ScsiPortInitialize(
|
||||||
/* Fill Device Extension */
|
/* Fill Device Extension */
|
||||||
DeviceExtension = PortDeviceObject->DeviceExtension;
|
DeviceExtension = PortDeviceObject->DeviceExtension;
|
||||||
RtlZeroMemory(DeviceExtension, DeviceExtensionSize);
|
RtlZeroMemory(DeviceExtension, DeviceExtensionSize);
|
||||||
|
DeviceExtension->Common.DeviceObject = PortDeviceObject;
|
||||||
|
DeviceExtension->Common.IsFDO = TRUE;
|
||||||
DeviceExtension->Length = DeviceExtensionSize;
|
DeviceExtension->Length = DeviceExtensionSize;
|
||||||
DeviceExtension->DeviceObject = PortDeviceObject;
|
|
||||||
DeviceExtension->PortNumber = SystemConfig->ScsiPortCount;
|
DeviceExtension->PortNumber = SystemConfig->ScsiPortCount;
|
||||||
|
DeviceExtension->DeviceName = DeviceName;
|
||||||
|
|
||||||
/* Driver's routines... */
|
/* Driver's routines... */
|
||||||
DeviceExtension->HwInitialize = HwInitializationData->HwInitialize;
|
DeviceExtension->HwInitialize = HwInitializationData->HwInitialize;
|
||||||
|
@ -941,13 +1005,10 @@ ScsiPortInitialize(
|
||||||
|
|
||||||
/* Extensions sizes */
|
/* Extensions sizes */
|
||||||
DeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize;
|
DeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize;
|
||||||
DeviceExtension->LunExtensionSize = HwInitializationData->SpecificLuExtensionSize;
|
DeviceExtension->LunExtensionSize =
|
||||||
DeviceExtension->SrbExtensionSize = HwInitializationData->SrbExtensionSize;
|
ALIGN_UP(HwInitializationData->SpecificLuExtensionSize, INT64);
|
||||||
|
|
||||||
/* Round Srb extension size to the quadword */
|
|
||||||
DeviceExtension->SrbExtensionSize =
|
DeviceExtension->SrbExtensionSize =
|
||||||
~(sizeof(LONGLONG) - 1) & (DeviceExtension->SrbExtensionSize +
|
ALIGN_UP(HwInitializationData->SrbExtensionSize, INT64);
|
||||||
sizeof(LONGLONG) - 1);
|
|
||||||
|
|
||||||
/* Fill some numbers (bus count, lun count, etc) */
|
/* Fill some numbers (bus count, lun count, etc) */
|
||||||
DeviceExtension->MaxLunCount = SCSI_MAXIMUM_LOGICAL_UNITS;
|
DeviceExtension->MaxLunCount = SCSI_MAXIMUM_LOGICAL_UNITS;
|
||||||
|
@ -975,22 +1036,10 @@ ScsiPortInitialize(
|
||||||
|
|
||||||
CreatePortConfig:
|
CreatePortConfig:
|
||||||
|
|
||||||
Status = SpiCreatePortConfig(DeviceExtension,
|
|
||||||
HwInitializationData,
|
|
||||||
&ConfigInfo,
|
|
||||||
&InitialPortConfig,
|
|
||||||
FirstConfigCall);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("SpiCreatePortConfig() failed with Status 0x%08X\n", Status);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate and initialize port configuration info */
|
/* Allocate and initialize port configuration info */
|
||||||
PortConfigSize = (sizeof(PORT_CONFIGURATION_INFORMATION) +
|
PortConfigSize = sizeof(PORT_CONFIGURATION_INFORMATION) +
|
||||||
HwInitializationData->NumberOfAccessRanges *
|
HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE);
|
||||||
sizeof(ACCESS_RANGE) + 7) & ~7;
|
PortConfigSize = ALIGN_UP(PortConfigSize, INT64);
|
||||||
DeviceExtension->PortConfig = ExAllocatePoolWithTag(NonPagedPool, PortConfigSize, TAG_SCSIPORT);
|
DeviceExtension->PortConfig = ExAllocatePoolWithTag(NonPagedPool, PortConfigSize, TAG_SCSIPORT);
|
||||||
|
|
||||||
/* Fail if failed */
|
/* Fail if failed */
|
||||||
|
@ -1000,14 +1049,20 @@ CreatePortConfig:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status = SpiCreatePortConfig(DeviceExtension,
|
||||||
|
HwInitializationData,
|
||||||
|
&ConfigInfo,
|
||||||
|
DeviceExtension->PortConfig,
|
||||||
|
FirstConfigCall);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("SpiCreatePortConfig() failed with Status 0x%08X\n", Status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
PortConfig = DeviceExtension->PortConfig;
|
PortConfig = DeviceExtension->PortConfig;
|
||||||
|
|
||||||
/* Copy information here */
|
|
||||||
RtlCopyMemory(PortConfig,
|
|
||||||
&InitialPortConfig,
|
|
||||||
sizeof(PORT_CONFIGURATION_INFORMATION));
|
|
||||||
|
|
||||||
|
|
||||||
/* Copy extension sizes into the PortConfig */
|
/* Copy extension sizes into the PortConfig */
|
||||||
PortConfig->SpecificLuExtensionSize = DeviceExtension->LunExtensionSize;
|
PortConfig->SpecificLuExtensionSize = DeviceExtension->LunExtensionSize;
|
||||||
PortConfig->SrbExtensionSize = DeviceExtension->SrbExtensionSize;
|
PortConfig->SrbExtensionSize = DeviceExtension->SrbExtensionSize;
|
||||||
|
@ -1015,11 +1070,7 @@ CreatePortConfig:
|
||||||
/* Initialize Access ranges */
|
/* Initialize Access ranges */
|
||||||
if (HwInitializationData->NumberOfAccessRanges != 0)
|
if (HwInitializationData->NumberOfAccessRanges != 0)
|
||||||
{
|
{
|
||||||
PortConfig->AccessRanges = (PVOID)(PortConfig+1);
|
PortConfig->AccessRanges = ALIGN_UP_POINTER(PortConfig + 1, INT64);
|
||||||
|
|
||||||
/* Align to LONGLONG */
|
|
||||||
PortConfig->AccessRanges = (PVOID)((ULONG_PTR)(PortConfig->AccessRanges) + 7);
|
|
||||||
PortConfig->AccessRanges = (PVOID)((ULONG_PTR)(PortConfig->AccessRanges) & ~7);
|
|
||||||
|
|
||||||
/* Copy the data */
|
/* Copy the data */
|
||||||
RtlCopyMemory(PortConfig->AccessRanges,
|
RtlCopyMemory(PortConfig->AccessRanges,
|
||||||
|
@ -1113,54 +1164,44 @@ CreatePortConfig:
|
||||||
(PortConfig->SrbExtensionSize != DeviceExtension->SrbExtensionSize))
|
(PortConfig->SrbExtensionSize != DeviceExtension->SrbExtensionSize))
|
||||||
{
|
{
|
||||||
/* Set it (rounding to LONGLONG again) */
|
/* Set it (rounding to LONGLONG again) */
|
||||||
DeviceExtension->SrbExtensionSize =
|
DeviceExtension->SrbExtensionSize = ALIGN_UP(PortConfig->SrbExtensionSize, INT64);
|
||||||
(PortConfig->SrbExtensionSize + sizeof(LONGLONG)) & ~(sizeof(LONGLONG) - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The same with LUN extension size */
|
/* The same with LUN extension size */
|
||||||
if (PortConfig->SpecificLuExtensionSize != DeviceExtension->LunExtensionSize)
|
if (PortConfig->SpecificLuExtensionSize != DeviceExtension->LunExtensionSize)
|
||||||
DeviceExtension->LunExtensionSize = PortConfig->SpecificLuExtensionSize;
|
DeviceExtension->LunExtensionSize = PortConfig->SpecificLuExtensionSize;
|
||||||
|
|
||||||
if (!((HwInitializationData->AdapterInterfaceType == PCIBus) &&
|
|
||||||
(HwInitializationData->VendorIdLength > 0) &&
|
|
||||||
(HwInitializationData->VendorId != NULL) &&
|
|
||||||
(HwInitializationData->DeviceIdLength > 0) &&
|
|
||||||
(HwInitializationData->DeviceId != NULL)))
|
|
||||||
{
|
|
||||||
/* Construct a resource list */
|
/* Construct a resource list */
|
||||||
ResourceList = SpiConfigToResource(DeviceExtension, PortConfig);
|
ResourceList = SpiConfigToResource(DeviceExtension, PortConfig);
|
||||||
|
|
||||||
if (ResourceList)
|
PDEVICE_OBJECT LowerPDO = NULL;
|
||||||
{
|
|
||||||
UNICODE_STRING UnicodeString;
|
|
||||||
RtlInitUnicodeString(&UnicodeString, L"ScsiAdapter");
|
|
||||||
DPRINT("Reporting resources\n");
|
|
||||||
Status = IoReportResourceUsage(&UnicodeString,
|
|
||||||
DriverObject,
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
PortDeviceObject,
|
|
||||||
ResourceList,
|
|
||||||
FIELD_OFFSET(CM_RESOURCE_LIST,
|
|
||||||
List[0].PartialResourceList.PartialDescriptors) +
|
|
||||||
ResourceList->List[0].PartialResourceList.Count *
|
|
||||||
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR),
|
|
||||||
FALSE,
|
|
||||||
&Conflict);
|
|
||||||
ExFreePool(ResourceList);
|
|
||||||
|
|
||||||
/* In case of a failure or a conflict, break */
|
Status = IoReportDetectedDevice(DriverObject,
|
||||||
if (Conflict || (!NT_SUCCESS(Status)))
|
HwInitializationData->AdapterInterfaceType,
|
||||||
|
ConfigInfo.BusNumber,
|
||||||
|
PortConfig->SlotNumber,
|
||||||
|
ResourceList,
|
||||||
|
NULL,
|
||||||
|
TRUE,
|
||||||
|
&LowerPDO);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
if (Conflict)
|
DPRINT1("IoReportDetectedDevice failed. Status: 0x%x\n", Status);
|
||||||
Status = STATUS_CONFLICTING_ADDRESSES;
|
__debugbreak();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset the Conflict var */
|
DeviceExtension->Common.LowerDevice = IoAttachDeviceToDeviceStack(PortDeviceObject, LowerPDO);
|
||||||
Conflict = FALSE;
|
|
||||||
|
ASSERT(DeviceExtension->Common.LowerDevice);
|
||||||
|
|
||||||
|
PortDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||||
|
|
||||||
|
if (ResourceList)
|
||||||
|
{
|
||||||
|
ExFreePoolWithTag(ResourceList, TAG_SCSIPORT);
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy all stuff which we ever need from PortConfig to the DeviceExtension */
|
/* Copy all stuff which we ever need from PortConfig to the DeviceExtension */
|
||||||
if (PortConfig->MaximumNumberOfTargets > SCSI_MAXIMUM_TARGETS_PER_BUS)
|
if (PortConfig->MaximumNumberOfTargets > SCSI_MAXIMUM_TARGETS_PER_BUS)
|
||||||
|
@ -1168,12 +1209,30 @@ CreatePortConfig:
|
||||||
else
|
else
|
||||||
DeviceExtension->MaxTargedIds = PortConfig->MaximumNumberOfTargets;
|
DeviceExtension->MaxTargedIds = PortConfig->MaximumNumberOfTargets;
|
||||||
|
|
||||||
DeviceExtension->BusNum = PortConfig->NumberOfBuses;
|
DeviceExtension->NumberOfBuses = PortConfig->NumberOfBuses;
|
||||||
DeviceExtension->CachesData = PortConfig->CachesData;
|
DeviceExtension->CachesData = PortConfig->CachesData;
|
||||||
DeviceExtension->ReceiveEvent = PortConfig->ReceiveEvent;
|
DeviceExtension->ReceiveEvent = PortConfig->ReceiveEvent;
|
||||||
DeviceExtension->SupportsTaggedQueuing = PortConfig->TaggedQueuing;
|
DeviceExtension->SupportsTaggedQueuing = PortConfig->TaggedQueuing;
|
||||||
DeviceExtension->MultipleReqsPerLun = PortConfig->MultipleRequestPerLu;
|
DeviceExtension->MultipleReqsPerLun = PortConfig->MultipleRequestPerLu;
|
||||||
|
|
||||||
|
/* Initialize bus scanning information */
|
||||||
|
size_t BusConfigSize = DeviceExtension->NumberOfBuses * sizeof(*DeviceExtension->Buses);
|
||||||
|
DeviceExtension->Buses = ExAllocatePoolZero(NonPagedPool, BusConfigSize, TAG_SCSIPORT);
|
||||||
|
if (!DeviceExtension->Buses)
|
||||||
|
{
|
||||||
|
DPRINT1("Out of resources!\n");
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize bus data
|
||||||
|
for (UINT8 pathId = 0; pathId < DeviceExtension->NumberOfBuses; pathId++)
|
||||||
|
{
|
||||||
|
DeviceExtension->Buses[pathId].BusIdentifier =
|
||||||
|
DeviceExtension->PortConfig->InitiatorBusId[pathId];
|
||||||
|
InitializeListHead(&DeviceExtension->Buses[pathId].LunsListHead);
|
||||||
|
}
|
||||||
|
|
||||||
/* If something was disabled via registry - apply it */
|
/* If something was disabled via registry - apply it */
|
||||||
if (ConfigInfo.DisableMultipleLun)
|
if (ConfigInfo.DisableMultipleLun)
|
||||||
DeviceExtension->MultipleReqsPerLun = PortConfig->MultipleRequestPerLu = FALSE;
|
DeviceExtension->MultipleReqsPerLun = PortConfig->MultipleRequestPerLu = FALSE;
|
||||||
|
@ -1283,43 +1342,18 @@ CreatePortConfig:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CallHWInitialize(DeviceExtension);
|
FdoCallHWInitialize(DeviceExtension);
|
||||||
|
|
||||||
/* Start our timer */
|
Status = FdoStartAdapter(DeviceExtension);
|
||||||
IoStartTimer(PortDeviceObject);
|
|
||||||
|
|
||||||
/* Initialize bus scanning information */
|
if (!NT_SUCCESS(Status))
|
||||||
BusConfigSize = FIELD_OFFSET(
|
|
||||||
BUSES_CONFIGURATION_INFORMATION,
|
|
||||||
BusScanInfo[DeviceExtension->PortConfig->NumberOfBuses]);
|
|
||||||
DeviceExtension->BusesConfig =
|
|
||||||
ExAllocatePoolWithTag(PagedPool, BusConfigSize, TAG_SCSIPORT);
|
|
||||||
if (!DeviceExtension->BusesConfig)
|
|
||||||
{
|
{
|
||||||
DPRINT1("Out of resources!\n");
|
DPRINT1("Failed to start the legacy adapter. Status 0x%x\n", Status);
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Zero it */
|
FdoScanAdapter(DeviceExtension);
|
||||||
RtlZeroMemory(DeviceExtension->BusesConfig, BusConfigSize);
|
|
||||||
|
|
||||||
/* Store number of buses there */
|
|
||||||
DeviceExtension->BusesConfig->NumberOfBuses = (UCHAR)DeviceExtension->BusNum;
|
|
||||||
|
|
||||||
/* Scan the adapter for devices */
|
|
||||||
SpiScanAdapter(DeviceExtension);
|
|
||||||
|
|
||||||
/* Build the registry device map */
|
|
||||||
SpiBuildDeviceMap(DeviceExtension, (PUNICODE_STRING)Argument2);
|
|
||||||
|
|
||||||
/* Create the dos device link */
|
|
||||||
swprintf(DosNameBuffer, L"\\??\\Scsi%lu:", SystemConfig->ScsiPortCount);
|
|
||||||
RtlInitUnicodeString(&DosDeviceName, DosNameBuffer);
|
|
||||||
IoCreateSymbolicLink(&DosDeviceName, &DeviceName);
|
|
||||||
|
|
||||||
/* Increase the port count */
|
|
||||||
SystemConfig->ScsiPortCount++;
|
|
||||||
FirstConfigCall = FALSE;
|
FirstConfigCall = FALSE;
|
||||||
|
|
||||||
/* Increase adapter number and bus number respectively */
|
/* Increase adapter number and bus number respectively */
|
||||||
|
@ -1334,7 +1368,10 @@ CreatePortConfig:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clean up the mess */
|
/* Clean up the mess */
|
||||||
SpiCleanupAfterInit(DeviceExtension);
|
if (!NT_SUCCESS(Status) && PortDeviceObject)
|
||||||
|
{
|
||||||
|
FdoRemoveAdapter(DeviceExtension);
|
||||||
|
}
|
||||||
|
|
||||||
/* Close registry keys */
|
/* Close registry keys */
|
||||||
if (ConfigInfo.ServiceKey != NULL)
|
if (ConfigInfo.ServiceKey != NULL)
|
||||||
|
@ -1461,9 +1498,12 @@ ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType, IN PVOID HwDevi
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Srb->OriginalRequest);
|
||||||
|
PSCSI_PORT_LUN_EXTENSION LunExtension = IoStack->DeviceObject->DeviceExtension;
|
||||||
|
ASSERT(LunExtension && !LunExtension->Common.IsFDO);
|
||||||
|
|
||||||
/* Get the SRB data */
|
/* Get the SRB data */
|
||||||
SrbData = SpiGetSrbData(
|
SrbData = SpiGetSrbData(DeviceExtension, LunExtension, Srb->QueueTag);
|
||||||
DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun, Srb->QueueTag);
|
|
||||||
|
|
||||||
/* Make sure there are no CompletedRequests and there is a Srb */
|
/* Make sure there are no CompletedRequests and there is a Srb */
|
||||||
ASSERT(SrbData->CompletedRequests == NULL && SrbData->Srb != NULL);
|
ASSERT(SrbData->CompletedRequests == NULL && SrbData->Srb != NULL);
|
||||||
|
@ -1504,7 +1544,7 @@ ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType, IN PVOID HwDevi
|
||||||
DeviceExtension->InterruptData.Flags |= SCSI_PORT_NEXT_REQUEST_READY;
|
DeviceExtension->InterruptData.Flags |= SCSI_PORT_NEXT_REQUEST_READY;
|
||||||
|
|
||||||
/* Get the LUN extension */
|
/* Get the LUN extension */
|
||||||
LunExtension = SpiGetLunExtension(DeviceExtension, PathId, TargetId, Lun);
|
LunExtension = GetLunByPath(DeviceExtension, PathId, TargetId, Lun);
|
||||||
|
|
||||||
/* If returned LunExtension is NULL, break out */
|
/* If returned LunExtension is NULL, break out */
|
||||||
if (!LunExtension)
|
if (!LunExtension)
|
||||||
|
@ -2104,7 +2144,7 @@ ScsiPortIsr(
|
||||||
/* If flag of notification is set - queue a DPC */
|
/* If flag of notification is set - queue a DPC */
|
||||||
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
|
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
|
||||||
{
|
{
|
||||||
IoRequestDpc(DeviceExtension->DeviceObject,
|
IoRequestDpc(DeviceExtension->Common.DeviceObject,
|
||||||
DeviceExtension->CurrentIrp,
|
DeviceExtension->CurrentIrp,
|
||||||
DeviceExtension);
|
DeviceExtension);
|
||||||
}
|
}
|
||||||
|
@ -2140,7 +2180,7 @@ SpiProcessTimeout(PVOID ServiceContext)
|
||||||
{
|
{
|
||||||
DPRINT("Resetting the bus\n");
|
DPRINT("Resetting the bus\n");
|
||||||
|
|
||||||
for (Bus = 0; Bus < DeviceExtension->BusNum; Bus++)
|
for (Bus = 0; Bus < DeviceExtension->NumberOfBuses; Bus++)
|
||||||
{
|
{
|
||||||
DeviceExtension->HwResetBus(DeviceExtension->MiniPortDeviceExtension, Bus);
|
DeviceExtension->HwResetBus(DeviceExtension->MiniPortDeviceExtension, Bus);
|
||||||
|
|
||||||
|
@ -2151,7 +2191,7 @@ SpiProcessTimeout(PVOID ServiceContext)
|
||||||
|
|
||||||
/* If miniport requested - request a dpc for it */
|
/* If miniport requested - request a dpc for it */
|
||||||
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
|
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
|
||||||
IoRequestDpc(DeviceExtension->DeviceObject, NULL, NULL);
|
IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -2176,7 +2216,7 @@ SpiResetBus(PVOID ServiceContext)
|
||||||
|
|
||||||
/* If miniport requested - give him a DPC */
|
/* If miniport requested - give him a DPC */
|
||||||
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
|
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
|
||||||
IoRequestDpc(DeviceExtension->DeviceObject, NULL, NULL);
|
IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -2198,7 +2238,6 @@ ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
|
||||||
{
|
{
|
||||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
||||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
||||||
ULONG Lun;
|
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
|
|
||||||
DPRINT("ScsiPortIoTimer()\n");
|
DPRINT("ScsiPortIoTimer()\n");
|
||||||
|
@ -2219,7 +2258,7 @@ ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
|
||||||
/* Timeout, process it */
|
/* Timeout, process it */
|
||||||
if (KeSynchronizeExecution(DeviceExtension->Interrupt[0],
|
if (KeSynchronizeExecution(DeviceExtension->Interrupt[0],
|
||||||
SpiProcessTimeout,
|
SpiProcessTimeout,
|
||||||
DeviceExtension->DeviceObject))
|
DeviceExtension->Common.DeviceObject))
|
||||||
{
|
{
|
||||||
DPRINT("Error happened during processing timeout, but nothing critical\n");
|
DPRINT("Error happened during processing timeout, but nothing critical\n");
|
||||||
}
|
}
|
||||||
|
@ -2232,12 +2271,16 @@ ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Per-Lun scanning of timeouts is needed... */
|
/* Per-Lun scanning of timeouts is needed... */
|
||||||
for (Lun = 0; Lun < LUS_NUMBER; Lun++)
|
for (UINT8 pathId = 0; pathId < DeviceExtension->NumberOfBuses; pathId++)
|
||||||
{
|
{
|
||||||
LunExtension = DeviceExtension->LunExtensionList[Lun];
|
PSCSI_BUS_INFO bus = &DeviceExtension->Buses[pathId];
|
||||||
|
|
||||||
while (LunExtension)
|
for (PLIST_ENTRY lunEntry = bus->LunsListHead.Flink;
|
||||||
|
lunEntry != &bus->LunsListHead;
|
||||||
|
lunEntry = lunEntry->Flink)
|
||||||
{
|
{
|
||||||
|
LunExtension = CONTAINING_RECORD(lunEntry, SCSI_PORT_LUN_EXTENSION, LunEntry);
|
||||||
|
|
||||||
if (LunExtension->Flags & LUNEX_BUSY)
|
if (LunExtension->Flags & LUNEX_BUSY)
|
||||||
{
|
{
|
||||||
if (!(LunExtension->Flags &
|
if (!(LunExtension->Flags &
|
||||||
|
@ -2283,8 +2326,6 @@ ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
|
||||||
/* Decrement the timeout counter */
|
/* Decrement the timeout counter */
|
||||||
LunExtension->RequestTimeout--;
|
LunExtension->RequestTimeout--;
|
||||||
}
|
}
|
||||||
|
|
||||||
LunExtension = LunExtension->Next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2320,7 +2361,7 @@ SpiMiniportTimerDpc(IN struct _KDPC *Dpc,
|
||||||
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
|
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
|
||||||
{
|
{
|
||||||
ScsiPortDpcForIsr(NULL,
|
ScsiPortDpcForIsr(NULL,
|
||||||
DeviceExtension->DeviceObject,
|
DeviceExtension->Common.DeviceObject,
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
@ -2398,8 +2439,8 @@ TryNextAd:
|
||||||
{
|
{
|
||||||
/* Open registry key for HW database */
|
/* Open registry key for HW database */
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
DeviceExtension->DeviceObject->DriverObject->HardwareDatabase,
|
DeviceExtension->Common.DeviceObject->DriverObject->HardwareDatabase,
|
||||||
OBJ_CASE_INSENSITIVE,
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
@ -2418,7 +2459,7 @@ TryNextAd:
|
||||||
/* Open device key */
|
/* Open device key */
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
&UnicodeString,
|
&UnicodeString,
|
||||||
OBJ_CASE_INSENSITIVE,
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||||
RootKey,
|
RootKey,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
@ -2479,7 +2520,7 @@ TryNextAd:
|
||||||
/* Open the service key */
|
/* Open the service key */
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
&UnicodeString,
|
&UnicodeString,
|
||||||
OBJ_CASE_INSENSITIVE,
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||||
InternalConfigInfo->ServiceKey,
|
InternalConfigInfo->ServiceKey,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
@ -3012,5 +3053,3 @@ ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address)
|
||||||
DPRINT("ScsiPortConvertPhysicalAddressToUlong()\n");
|
DPRINT("ScsiPortConvertPhysicalAddressToUlong()\n");
|
||||||
return(Address.u.LowPart);
|
return(Address.u.LowPart);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
|
||||||
|
|
|
@ -7,15 +7,16 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <wdm.h>
|
#include <ntifs.h>
|
||||||
#include <ntddk.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <scsi.h>
|
#include <scsi.h>
|
||||||
#include <ntddscsi.h>
|
#include <ntddscsi.h>
|
||||||
#include <ntdddisk.h>
|
#include <ntdddisk.h>
|
||||||
#include <mountdev.h>
|
#include <mountdev.h>
|
||||||
|
|
||||||
#define VERSION "0.0.3"
|
#ifdef DBG
|
||||||
|
#include <debug/driverdbg.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TAG_SCSIPORT 'ISCS'
|
#define TAG_SCSIPORT 'ISCS'
|
||||||
|
|
||||||
|
@ -25,20 +26,20 @@
|
||||||
#define MAX_SG_LIST 17
|
#define MAX_SG_LIST 17
|
||||||
|
|
||||||
/* Flags */
|
/* Flags */
|
||||||
#define SCSI_PORT_DEVICE_BUSY 0x0001
|
#define SCSI_PORT_DEVICE_BUSY 0x00001
|
||||||
#define SCSI_PORT_LU_ACTIVE 0x0002
|
#define SCSI_PORT_LU_ACTIVE 0x00002
|
||||||
#define SCSI_PORT_NOTIFICATION_NEEDED 0x0004
|
#define SCSI_PORT_NOTIFICATION_NEEDED 0x00004
|
||||||
#define SCSI_PORT_NEXT_REQUEST_READY 0x0008
|
#define SCSI_PORT_NEXT_REQUEST_READY 0x00008
|
||||||
#define SCSI_PORT_FLUSH_ADAPTERS 0x0010
|
#define SCSI_PORT_FLUSH_ADAPTERS 0x00010
|
||||||
#define SCSI_PORT_MAP_TRANSFER 0x0020
|
#define SCSI_PORT_MAP_TRANSFER 0x00020
|
||||||
#define SCSI_PORT_RESET 0x0080
|
#define SCSI_PORT_RESET 0x00080
|
||||||
#define SCSI_PORT_RESET_REQUEST 0x0100
|
#define SCSI_PORT_RESET_REQUEST 0x00100
|
||||||
#define SCSI_PORT_RESET_REPORTED 0x0200
|
#define SCSI_PORT_RESET_REPORTED 0x00200
|
||||||
#define SCSI_PORT_REQUEST_PENDING 0x0800
|
#define SCSI_PORT_REQUEST_PENDING 0x00800
|
||||||
#define SCSI_PORT_DISCONNECT_ALLOWED 0x1000
|
#define SCSI_PORT_DISCONNECT_ALLOWED 0x01000
|
||||||
#define SCSI_PORT_DISABLE_INT_REQUESET 0x2000
|
#define SCSI_PORT_DISABLE_INT_REQUESET 0x02000
|
||||||
#define SCSI_PORT_DISABLE_INTERRUPTS 0x4000
|
#define SCSI_PORT_DISABLE_INTERRUPTS 0x04000
|
||||||
#define SCSI_PORT_ENABLE_INT_REQUEST 0x8000
|
#define SCSI_PORT_ENABLE_INT_REQUEST 0x08000
|
||||||
#define SCSI_PORT_TIMER_NEEDED 0x10000
|
#define SCSI_PORT_TIMER_NEEDED 0x10000
|
||||||
|
|
||||||
/* LUN Extension flags*/
|
/* LUN Extension flags*/
|
||||||
|
@ -115,18 +116,27 @@ typedef struct _SCSI_REQUEST_BLOCK_INFO
|
||||||
SCSI_SG_ADDRESS ScatterGatherList[MAX_SG_LIST];
|
SCSI_SG_ADDRESS ScatterGatherList[MAX_SG_LIST];
|
||||||
} SCSI_REQUEST_BLOCK_INFO, *PSCSI_REQUEST_BLOCK_INFO;
|
} SCSI_REQUEST_BLOCK_INFO, *PSCSI_REQUEST_BLOCK_INFO;
|
||||||
|
|
||||||
|
typedef struct _SCSI_PORT_COMMON_EXTENSION
|
||||||
|
{
|
||||||
|
PDEVICE_OBJECT DeviceObject;
|
||||||
|
PDEVICE_OBJECT LowerDevice;
|
||||||
|
BOOLEAN IsFDO;
|
||||||
|
} SCSI_PORT_COMMON_EXTENSION, *PSCSI_PORT_COMMON_EXTENSION;
|
||||||
|
|
||||||
|
// PDO device
|
||||||
typedef struct _SCSI_PORT_LUN_EXTENSION
|
typedef struct _SCSI_PORT_LUN_EXTENSION
|
||||||
{
|
{
|
||||||
|
SCSI_PORT_COMMON_EXTENSION Common;
|
||||||
|
|
||||||
UCHAR PathId;
|
UCHAR PathId;
|
||||||
UCHAR TargetId;
|
UCHAR TargetId;
|
||||||
UCHAR Lun;
|
UCHAR Lun;
|
||||||
|
|
||||||
ULONG Flags;
|
ULONG Flags;
|
||||||
|
|
||||||
struct _SCSI_PORT_LUN_EXTENSION *Next;
|
LIST_ENTRY LunEntry;
|
||||||
|
|
||||||
BOOLEAN DeviceClaimed;
|
BOOLEAN DeviceClaimed;
|
||||||
PDEVICE_OBJECT DeviceObject;
|
|
||||||
|
|
||||||
INQUIRYDATA InquiryData;
|
INQUIRYDATA InquiryData;
|
||||||
|
|
||||||
|
@ -146,6 +156,8 @@ typedef struct _SCSI_PORT_LUN_EXTENSION
|
||||||
|
|
||||||
SCSI_REQUEST_BLOCK_INFO SrbInfo;
|
SCSI_REQUEST_BLOCK_INFO SrbInfo;
|
||||||
|
|
||||||
|
HANDLE RegistryMapKey;
|
||||||
|
|
||||||
/* More data? */
|
/* More data? */
|
||||||
|
|
||||||
UCHAR MiniportLunExtension[1]; /* must be the last entry */
|
UCHAR MiniportLunExtension[1]; /* must be the last entry */
|
||||||
|
@ -153,31 +165,14 @@ typedef struct _SCSI_PORT_LUN_EXTENSION
|
||||||
|
|
||||||
/* Structures for inquiries support */
|
/* Structures for inquiries support */
|
||||||
|
|
||||||
typedef struct _SCSI_LUN_INFO
|
typedef struct _SCSI_BUS_INFO
|
||||||
{
|
{
|
||||||
UCHAR PathId;
|
LIST_ENTRY LunsListHead;
|
||||||
UCHAR TargetId;
|
|
||||||
UCHAR Lun;
|
|
||||||
BOOLEAN DeviceClaimed;
|
|
||||||
PVOID DeviceObject;
|
|
||||||
struct _SCSI_LUN_INFO *Next;
|
|
||||||
UCHAR InquiryData[INQUIRYDATABUFFERSIZE];
|
|
||||||
} SCSI_LUN_INFO, *PSCSI_LUN_INFO;
|
|
||||||
|
|
||||||
typedef struct _SCSI_BUS_SCAN_INFO
|
|
||||||
{
|
|
||||||
USHORT Length;
|
|
||||||
UCHAR LogicalUnitsCount;
|
UCHAR LogicalUnitsCount;
|
||||||
|
UCHAR TargetsCount;
|
||||||
UCHAR BusIdentifier;
|
UCHAR BusIdentifier;
|
||||||
PSCSI_LUN_INFO LunInfo;
|
HANDLE RegistryMapKey;
|
||||||
} SCSI_BUS_SCAN_INFO, *PSCSI_BUS_SCAN_INFO;
|
} SCSI_BUS_INFO, *PSCSI_BUS_INFO;
|
||||||
|
|
||||||
typedef struct _BUSES_CONFIGURATION_INFORMATION
|
|
||||||
{
|
|
||||||
UCHAR NumberOfBuses;
|
|
||||||
PSCSI_BUS_SCAN_INFO BusScanInfo[1];
|
|
||||||
} BUSES_CONFIGURATION_INFORMATION, *PBUSES_CONFIGURATION_INFORMATION;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct _SCSI_PORT_INTERRUPT_DATA
|
typedef struct _SCSI_PORT_INTERRUPT_DATA
|
||||||
{
|
{
|
||||||
|
@ -205,12 +200,15 @@ typedef struct _SCSI_PORT_SAVE_INTERRUPT
|
||||||
* part is the miniport-specific device extension.
|
* part is the miniport-specific device extension.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// FDO
|
||||||
typedef struct _SCSI_PORT_DEVICE_EXTENSION
|
typedef struct _SCSI_PORT_DEVICE_EXTENSION
|
||||||
{
|
{
|
||||||
|
SCSI_PORT_COMMON_EXTENSION Common;
|
||||||
|
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
ULONG MiniPortExtensionSize;
|
ULONG MiniPortExtensionSize;
|
||||||
PPORT_CONFIGURATION_INFORMATION PortConfig;
|
PPORT_CONFIGURATION_INFORMATION PortConfig;
|
||||||
PBUSES_CONFIGURATION_INFORMATION BusesConfig;
|
PSCSI_BUS_INFO Buses; // children LUNs are stored here
|
||||||
PVOID NonCachedExtension;
|
PVOID NonCachedExtension;
|
||||||
ULONG PortNumber;
|
ULONG PortNumber;
|
||||||
|
|
||||||
|
@ -218,7 +216,7 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
|
||||||
ULONG SrbFlags;
|
ULONG SrbFlags;
|
||||||
ULONG Flags;
|
ULONG Flags;
|
||||||
|
|
||||||
ULONG BusNum;
|
UCHAR NumberOfBuses;
|
||||||
ULONG MaxTargedIds;
|
ULONG MaxTargedIds;
|
||||||
ULONG MaxLunCount;
|
ULONG MaxLunCount;
|
||||||
|
|
||||||
|
@ -238,7 +236,6 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
|
||||||
PMAPPED_ADDRESS MappedAddressList;
|
PMAPPED_ADDRESS MappedAddressList;
|
||||||
|
|
||||||
ULONG LunExtensionSize;
|
ULONG LunExtensionSize;
|
||||||
PSCSI_PORT_LUN_EXTENSION LunExtensionList[LUS_NUMBER];
|
|
||||||
|
|
||||||
SCSI_PORT_INTERRUPT_DATA InterruptData;
|
SCSI_PORT_INTERRUPT_DATA InterruptData;
|
||||||
|
|
||||||
|
@ -254,7 +251,6 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
|
||||||
|
|
||||||
IO_SCSI_CAPABILITIES PortCapabilities;
|
IO_SCSI_CAPABILITIES PortCapabilities;
|
||||||
|
|
||||||
PDEVICE_OBJECT DeviceObject;
|
|
||||||
PCONTROLLER_OBJECT ControllerObject;
|
PCONTROLLER_OBJECT ControllerObject;
|
||||||
|
|
||||||
PHW_INITIALIZE HwInitialize;
|
PHW_INITIALIZE HwInitialize;
|
||||||
|
@ -294,6 +290,11 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
|
||||||
|
|
||||||
ULONG InterruptCount;
|
ULONG InterruptCount;
|
||||||
|
|
||||||
|
UNICODE_STRING DeviceName;
|
||||||
|
UNICODE_STRING InterfaceName;
|
||||||
|
BOOLEAN DeviceStarted;
|
||||||
|
UINT8 TotalLUCount;
|
||||||
|
|
||||||
UCHAR MiniPortDeviceExtension[1]; /* must be the last entry */
|
UCHAR MiniPortDeviceExtension[1]; /* must be the last entry */
|
||||||
} SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION;
|
} SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION;
|
||||||
|
|
||||||
|
@ -303,6 +304,42 @@ typedef struct _RESETBUS_PARAMS
|
||||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
||||||
} RESETBUS_PARAMS, *PRESETBUS_PARAMS;
|
} RESETBUS_PARAMS, *PRESETBUS_PARAMS;
|
||||||
|
|
||||||
|
typedef struct _SCSIPORT_DRIVER_EXTENSION
|
||||||
|
{
|
||||||
|
PDRIVER_OBJECT DriverObject;
|
||||||
|
UNICODE_STRING RegistryPath;
|
||||||
|
BOOLEAN IsLegacyDriver;
|
||||||
|
} SCSI_PORT_DRIVER_EXTENSION, *PSCSI_PORT_DRIVER_EXTENSION;
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
BOOLEAN
|
||||||
|
VerifyIrpOutBufferSize(
|
||||||
|
_In_ PIRP Irp,
|
||||||
|
_In_ SIZE_T Size)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
if (ioStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = Size;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
BOOLEAN
|
||||||
|
VerifyIrpInBufferSize(
|
||||||
|
_In_ PIRP Irp,
|
||||||
|
_In_ SIZE_T Size)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
if (ioStack->Parameters.DeviceIoControl.InputBufferLength < Size)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = Size;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
// ioctl.c
|
// ioctl.c
|
||||||
|
|
||||||
|
@ -315,25 +352,34 @@ ScsiPortDeviceControl(
|
||||||
// fdo.c
|
// fdo.c
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
SpiScanAdapter(
|
FdoScanAdapter(
|
||||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CallHWInitialize(
|
FdoCallHWInitialize(
|
||||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
||||||
|
|
||||||
VOID
|
NTSTATUS
|
||||||
SpiCleanupAfterInit(
|
FdoRemoveAdapter(
|
||||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
FdoStartAdapter(
|
||||||
|
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
FdoDispatchPnp(
|
||||||
|
_In_ PDEVICE_OBJECT DeviceObject,
|
||||||
|
_Inout_ PIRP Irp);
|
||||||
|
|
||||||
// pdo.c
|
// pdo.c
|
||||||
|
|
||||||
PSCSI_PORT_LUN_EXTENSION
|
PDEVICE_OBJECT
|
||||||
SpiAllocateLunExtension(
|
PdoCreateLunDevice(
|
||||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
||||||
|
|
||||||
PSCSI_PORT_LUN_EXTENSION
|
PSCSI_PORT_LUN_EXTENSION
|
||||||
SpiGetLunExtension(
|
GetLunByPath(
|
||||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
_In_ UCHAR PathId,
|
_In_ UCHAR PathId,
|
||||||
_In_ UCHAR TargetId,
|
_In_ UCHAR TargetId,
|
||||||
|
@ -342,22 +388,32 @@ SpiGetLunExtension(
|
||||||
PSCSI_REQUEST_BLOCK_INFO
|
PSCSI_REQUEST_BLOCK_INFO
|
||||||
SpiGetSrbData(
|
SpiGetSrbData(
|
||||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
_In_ UCHAR PathId,
|
_In_ PSCSI_PORT_LUN_EXTENSION LunExtension,
|
||||||
_In_ UCHAR TargetId,
|
|
||||||
_In_ UCHAR Lun,
|
|
||||||
_In_ UCHAR QueueTag);
|
_In_ UCHAR QueueTag);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
PdoDispatchPnp(
|
||||||
|
_In_ PDEVICE_OBJECT DeviceObject,
|
||||||
|
_Inout_ PIRP Irp);
|
||||||
|
|
||||||
|
// power.c
|
||||||
|
|
||||||
|
DRIVER_DISPATCH ScsiPortDispatchPower;
|
||||||
|
|
||||||
// registry.c
|
// registry.c
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
SpiInitOpenKeys(
|
SpiInitOpenKeys(
|
||||||
_Inout_ PCONFIGURATION_INFO ConfigInfo,
|
_Inout_ PCONFIGURATION_INFO ConfigInfo,
|
||||||
_In_ PUNICODE_STRING RegistryPath);
|
_In_ PSCSI_PORT_DRIVER_EXTENSION DriverExtension);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
SpiBuildDeviceMap(
|
RegistryInitAdapterKey(
|
||||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
_Inout_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
||||||
_In_ PUNICODE_STRING RegistryPath);
|
|
||||||
|
NTSTATUS
|
||||||
|
RegistryInitLunKey(
|
||||||
|
_Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension);
|
||||||
|
|
||||||
// scsi.c
|
// scsi.c
|
||||||
|
|
||||||
|
|
124
drivers/storage/port/scsiport/scsitypes.h
Normal file
124
drivers/storage/port/scsiport/scsitypes.h
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
|
||||||
|
// see https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-scsi-devices
|
||||||
|
// and https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-ide-devices
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
PCSTR
|
||||||
|
GetDeviceType(
|
||||||
|
_In_ PINQUIRYDATA InquiryData)
|
||||||
|
{
|
||||||
|
switch (InquiryData->DeviceType)
|
||||||
|
{
|
||||||
|
case DIRECT_ACCESS_DEVICE:
|
||||||
|
return "Disk";
|
||||||
|
case SEQUENTIAL_ACCESS_DEVICE:
|
||||||
|
return "Sequential";
|
||||||
|
case PRINTER_DEVICE:
|
||||||
|
return "Printer";
|
||||||
|
case PROCESSOR_DEVICE:
|
||||||
|
return "Processor";
|
||||||
|
case WRITE_ONCE_READ_MULTIPLE_DEVICE:
|
||||||
|
return "Worm";
|
||||||
|
case READ_ONLY_DIRECT_ACCESS_DEVICE:
|
||||||
|
return "CdRom";
|
||||||
|
case SCANNER_DEVICE:
|
||||||
|
return "Scanner";
|
||||||
|
case OPTICAL_DEVICE:
|
||||||
|
return "Optical";
|
||||||
|
case MEDIUM_CHANGER:
|
||||||
|
return "Changer";
|
||||||
|
case COMMUNICATION_DEVICE:
|
||||||
|
return "Net";
|
||||||
|
case ARRAY_CONTROLLER_DEVICE:
|
||||||
|
return "Array";
|
||||||
|
case SCSI_ENCLOSURE_DEVICE:
|
||||||
|
return "Enclosure";
|
||||||
|
case REDUCED_BLOCK_DEVICE:
|
||||||
|
return "RBC";
|
||||||
|
case OPTICAL_CARD_READER_WRITER_DEVICE:
|
||||||
|
return "CardReader";
|
||||||
|
case BRIDGE_CONTROLLER_DEVICE:
|
||||||
|
return "Bridge";
|
||||||
|
default:
|
||||||
|
return "Other";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
PCSTR
|
||||||
|
GetGenericType(
|
||||||
|
_In_ PINQUIRYDATA InquiryData)
|
||||||
|
{
|
||||||
|
switch (InquiryData->DeviceType)
|
||||||
|
{
|
||||||
|
case DIRECT_ACCESS_DEVICE:
|
||||||
|
return "GenDisk";
|
||||||
|
case PRINTER_DEVICE:
|
||||||
|
return "GenPrinter";
|
||||||
|
case WRITE_ONCE_READ_MULTIPLE_DEVICE:
|
||||||
|
return "GenWorm";
|
||||||
|
case READ_ONLY_DIRECT_ACCESS_DEVICE:
|
||||||
|
return "GenCdRom";
|
||||||
|
case SCANNER_DEVICE:
|
||||||
|
return "GenScanner";
|
||||||
|
case OPTICAL_DEVICE:
|
||||||
|
return "GenOptical";
|
||||||
|
case MEDIUM_CHANGER:
|
||||||
|
return "ScsiChanger";
|
||||||
|
case COMMUNICATION_DEVICE:
|
||||||
|
return "ScsiNet";
|
||||||
|
case ARRAY_CONTROLLER_DEVICE:
|
||||||
|
return "ScsiArray";
|
||||||
|
case SCSI_ENCLOSURE_DEVICE:
|
||||||
|
return "ScsiEnclosure";
|
||||||
|
case REDUCED_BLOCK_DEVICE:
|
||||||
|
return "ScsiRBC";
|
||||||
|
case OPTICAL_CARD_READER_WRITER_DEVICE:
|
||||||
|
return "ScsiCardReader";
|
||||||
|
case BRIDGE_CONTROLLER_DEVICE:
|
||||||
|
return "ScsiBridge";
|
||||||
|
default:
|
||||||
|
return "ScsiOther";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
PCWSTR
|
||||||
|
GetPeripheralTypeW(
|
||||||
|
_In_ PINQUIRYDATA InquiryData)
|
||||||
|
{
|
||||||
|
switch (InquiryData->DeviceType)
|
||||||
|
{
|
||||||
|
case DIRECT_ACCESS_DEVICE:
|
||||||
|
return L"DiskPeripheral";
|
||||||
|
case SEQUENTIAL_ACCESS_DEVICE:
|
||||||
|
return L"TapePeripheral";
|
||||||
|
case PRINTER_DEVICE:
|
||||||
|
return L"PrinterPeripheral";
|
||||||
|
// case 3: "ProcessorPeripheral", classified as 'other': fall back to default case.
|
||||||
|
case WRITE_ONCE_READ_MULTIPLE_DEVICE:
|
||||||
|
return L"WormPeripheral";
|
||||||
|
case READ_ONLY_DIRECT_ACCESS_DEVICE:
|
||||||
|
return L"CdRomPeripheral";
|
||||||
|
case SCANNER_DEVICE:
|
||||||
|
return L"ScannerPeripheral";
|
||||||
|
case OPTICAL_DEVICE:
|
||||||
|
return L"OpticalDiskPeripheral";
|
||||||
|
case MEDIUM_CHANGER:
|
||||||
|
return L"MediumChangerPeripheral";
|
||||||
|
case COMMUNICATION_DEVICE:
|
||||||
|
return L"CommunicationsPeripheral";
|
||||||
|
case ARRAY_CONTROLLER_DEVICE:
|
||||||
|
return L"ArrayPeripheral";
|
||||||
|
case SCSI_ENCLOSURE_DEVICE:
|
||||||
|
return L"EnclosurePeripheral";
|
||||||
|
case REDUCED_BLOCK_DEVICE:
|
||||||
|
return L"RBCPeripheral";
|
||||||
|
case OPTICAL_CARD_READER_WRITER_DEVICE:
|
||||||
|
return L"CardReaderPeripheral";
|
||||||
|
case BRIDGE_CONTROLLER_DEVICE:
|
||||||
|
return L"BridgePeripheral";
|
||||||
|
default:
|
||||||
|
return L"OtherPeripheral";
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue