mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +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
|
@ -2,20 +2,25 @@
|
|||
spec2def(scsiport.sys scsiport.spec ADD_IMPORTLIB)
|
||||
|
||||
list(APPEND SOURCE
|
||||
fdo.c
|
||||
ioctl.c
|
||||
pdo.c
|
||||
registry.c
|
||||
scsi.c
|
||||
fdo.c
|
||||
ioctl.c
|
||||
pdo.c
|
||||
power.c
|
||||
registry.c
|
||||
scsi.c
|
||||
scsiport.c
|
||||
stubs.c)
|
||||
|
||||
list(APPEND PCH_SKIP_SOURCE
|
||||
guid.c)
|
||||
|
||||
add_library(scsiport MODULE
|
||||
${SOURCE}
|
||||
${PCH_SKIP_SOURCE}
|
||||
scsiport.rc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/scsiport.def)
|
||||
|
||||
add_pch(scsiport scsiport.h "")
|
||||
add_pch(scsiport scsiport.h "${PCH_SKIP_SOURCE}")
|
||||
set_module_type(scsiport kernelmodedriver)
|
||||
add_importlibs(scsiport ntoskrnl hal)
|
||||
add_cd_file(TARGET scsiport DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* PURPOSE: Adapter device object (FDO) support routines
|
||||
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
||||
* Aleksey Bragin (aleksey@reactos.org)
|
||||
* 2020 Victor Perevertkin (victor.perevertkin@reactos.org)
|
||||
*/
|
||||
|
||||
#include "scsiport.h"
|
||||
|
@ -14,9 +15,8 @@
|
|||
|
||||
static
|
||||
NTSTATUS
|
||||
SpiSendInquiry(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_Inout_ PSCSI_LUN_INFO LunInfo)
|
||||
FdoSendInquiry(
|
||||
_In_ PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
PIO_STACK_LOCATION IrpStack;
|
||||
|
@ -30,12 +30,12 @@ SpiSendInquiry(
|
|||
ULONG RetryCount = 0;
|
||||
SCSI_REQUEST_BLOCK Srb;
|
||||
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);
|
||||
if (InquiryBuffer == NULL)
|
||||
|
@ -80,9 +80,9 @@ SpiSendInquiry(
|
|||
|
||||
Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
|
||||
Srb.OriginalRequest = Irp;
|
||||
Srb.PathId = LunInfo->PathId;
|
||||
Srb.TargetId = LunInfo->TargetId;
|
||||
Srb.Lun = LunInfo->Lun;
|
||||
Srb.PathId = LunExtension->PathId;
|
||||
Srb.TargetId = LunExtension->TargetId;
|
||||
Srb.Lun = LunExtension->Lun;
|
||||
Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
|
||||
Srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
|
||||
Srb.TimeOutValue = 4;
|
||||
|
@ -101,7 +101,7 @@ SpiSendInquiry(
|
|||
/* Fill in CDB */
|
||||
Cdb = (PCDB)Srb.Cdb;
|
||||
Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
|
||||
Cdb->CDB6INQUIRY.LogicalUnitNumber = LunInfo->Lun;
|
||||
Cdb->CDB6INQUIRY.LogicalUnitNumber = LunExtension->Lun;
|
||||
Cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
|
||||
|
||||
/* Call the driver */
|
||||
|
@ -110,7 +110,7 @@ SpiSendInquiry(
|
|||
/* Wait for it to complete */
|
||||
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,
|
||||
Executive,
|
||||
KernelMode,
|
||||
|
@ -119,12 +119,12 @@ SpiSendInquiry(
|
|||
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)
|
||||
{
|
||||
/* All fine, copy data over */
|
||||
RtlCopyMemory(LunInfo->InquiryData,
|
||||
RtlCopyMemory(&LunExtension->InquiryData,
|
||||
InquiryBuffer,
|
||||
INQUIRYDATABUFFERSIZE);
|
||||
|
||||
|
@ -142,12 +142,7 @@ SpiSendInquiry(
|
|||
/* Something weird happened, deal with it (unfreeze the queue) */
|
||||
KeepTrying = FALSE;
|
||||
|
||||
DPRINT("SpiSendInquiry(): the queue is frozen at TargetId %d\n", Srb.TargetId);
|
||||
|
||||
LunExtension = SpiGetLunExtension(DeviceExtension,
|
||||
LunInfo->PathId,
|
||||
LunInfo->TargetId,
|
||||
LunInfo->Lun);
|
||||
DPRINT("FdoSendInquiry(): the queue is frozen at TargetId %d\n", Srb.TargetId);
|
||||
|
||||
/* Clear frozen flag */
|
||||
LunExtension->Flags &= ~LUNEX_FROZEN_QUEUE;
|
||||
|
@ -156,7 +151,7 @@ SpiSendInquiry(
|
|||
KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
|
||||
|
||||
/* Process the request */
|
||||
SpiGetNextRequestFromLun(DeviceObject->DeviceExtension, LunExtension);
|
||||
SpiGetNextRequestFromLun(DeviceExtension, LunExtension);
|
||||
|
||||
/* SpiGetNextRequestFromLun() releases the spinlock,
|
||||
so we just lower irql back to what it was before */
|
||||
|
@ -166,10 +161,10 @@ SpiSendInquiry(
|
|||
/* Check if data overrun happened */
|
||||
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 */
|
||||
RtlCopyMemory(LunInfo->InquiryData,
|
||||
RtlCopyMemory(&LunExtension->InquiryData,
|
||||
InquiryBuffer,
|
||||
(Srb.DataTransferLength > INQUIRYDATABUFFERSIZE) ?
|
||||
INQUIRYDATABUFFERSIZE : Srb.DataTransferLength);
|
||||
|
@ -221,229 +216,141 @@ SpiSendInquiry(
|
|||
ExFreePoolWithTag(InquiryBuffer, 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;
|
||||
}
|
||||
|
||||
/* Scans all SCSI buses */
|
||||
VOID
|
||||
SpiScanAdapter(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
||||
FdoScanAdapter(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION PortExtension)
|
||||
{
|
||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
||||
ULONG Bus;
|
||||
ULONG Target;
|
||||
ULONG Lun;
|
||||
PSCSI_BUS_SCAN_INFO BusScanInfo;
|
||||
PSCSI_LUN_INFO LastLunInfo, LunInfo, LunInfoExists;
|
||||
BOOLEAN DeviceExists;
|
||||
ULONG Hint;
|
||||
NTSTATUS Status;
|
||||
ULONG DevicesFound;
|
||||
NTSTATUS status;
|
||||
UINT32 totalLUNs = PortExtension->TotalLUCount;
|
||||
|
||||
DPRINT("SpiScanAdapter() called\n");
|
||||
DPRINT("FdoScanAdapter() called\n");
|
||||
|
||||
/* Scan all buses */
|
||||
for (Bus = 0; Bus < DeviceExtension->BusNum; Bus++)
|
||||
for (UINT8 pathId = 0; pathId < PortExtension->NumberOfBuses; pathId++)
|
||||
{
|
||||
DPRINT(" Scanning bus %d\n", Bus);
|
||||
DevicesFound = 0;
|
||||
DPRINT(" Scanning bus/pathID %u\n", pathId);
|
||||
|
||||
/* Get pointer to the scan information */
|
||||
BusScanInfo = DeviceExtension->BusesConfig->BusScanInfo[Bus];
|
||||
|
||||
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);
|
||||
PSCSI_BUS_INFO currentBus = &PortExtension->Buses[pathId];
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* Skip if it's the same address */
|
||||
if (Target == BusScanInfo->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)
|
||||
if (targetId == currentBus->BusIdentifier)
|
||||
continue;
|
||||
|
||||
/* Scan all logical units */
|
||||
for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
|
||||
for (UINT8 lun = 0; lun < PortExtension->MaxLunCount; lun++)
|
||||
{
|
||||
if ((!LunExtension) || (!LunInfo))
|
||||
break;
|
||||
// try to find an existing device
|
||||
PSCSI_PORT_LUN_EXTENSION lunExt = GetLunByPath(PortExtension,
|
||||
pathId,
|
||||
targetId,
|
||||
lun);
|
||||
|
||||
/* Add extension to the list */
|
||||
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)
|
||||
if (lunExt)
|
||||
{
|
||||
RtlZeroMemory(LunExtension + 1,
|
||||
DeviceExtension->LunExtensionSize);
|
||||
// check if the device still exists
|
||||
status = FdoSendInquiry(lunExt->Common.DeviceObject);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
// remove the device
|
||||
UNIMPLEMENTED;
|
||||
__debugbreak();
|
||||
}
|
||||
|
||||
if (lunExt->InquiryData.DeviceTypeQualifier == DEVICE_QUALIFIER_NOT_SUPPORTED)
|
||||
{
|
||||
// remove the device
|
||||
UNIMPLEMENTED;
|
||||
__debugbreak();
|
||||
}
|
||||
|
||||
/* Decide whether we are continuing or not */
|
||||
if (status == STATUS_INVALID_DEVICE_REQUEST)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* Finally send the inquiry command */
|
||||
Status = SpiSendInquiry(DeviceExtension->DeviceObject, LunInfo);
|
||||
// create a new LUN device
|
||||
PDEVICE_OBJECT lunPDO = PdoCreateLunDevice(PortExtension);
|
||||
if (!lunPDO)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
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 */
|
||||
PINQUIRYDATA InquiryData = (PINQUIRYDATA)LunInfo->InquiryData;
|
||||
PINQUIRYDATA InquiryData = &lunExt->InquiryData;
|
||||
|
||||
/* Check if this device is unsupported */
|
||||
if (InquiryData->DeviceTypeQualifier == DEVICE_QUALIFIER_NOT_SUPPORTED)
|
||||
{
|
||||
DeviceExtension->LunExtensionList[Hint] =
|
||||
DeviceExtension->LunExtensionList[Hint]->Next;
|
||||
|
||||
IoDeleteDevice(lunPDO);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 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",
|
||||
InquiryData->DeviceType, Bus, Target, Lun);
|
||||
DPRINT("FdoScanAdapter(): Found device of type %d at bus %d tid %d lun %d\n",
|
||||
InquiryData->DeviceType, pathId, targetId, lun);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
InsertTailList(¤tBus->LunsListHead, &lunExt->LunEntry);
|
||||
|
||||
/* Add this info to the linked list */
|
||||
LunInfo->Next = NULL;
|
||||
if (LastLunInfo)
|
||||
LastLunInfo->Next = LunInfo;
|
||||
else
|
||||
BusScanInfo->LunInfo = LunInfo;
|
||||
DPRINT1("SCSIPORT: created lun device: %p Status: %x\n", lunPDO, status);
|
||||
|
||||
/* Store the last LUN info */
|
||||
LastLunInfo = LunInfo;
|
||||
|
||||
/* 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++;
|
||||
totalLUNs++;
|
||||
currentBus->LogicalUnitsCount++;
|
||||
targetFound = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remove this LUN from the list */
|
||||
DeviceExtension->LunExtensionList[Hint] =
|
||||
DeviceExtension->LunExtensionList[Hint]->Next;
|
||||
|
||||
/* Decide whether we are continuing or not */
|
||||
if (Status == STATUS_INVALID_DEVICE_REQUEST)
|
||||
if (status == STATUS_INVALID_DEVICE_REQUEST)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetFound)
|
||||
{
|
||||
currentBus->TargetsCount++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free allocated buffers */
|
||||
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");
|
||||
PortExtension->TotalLUCount = totalLUNs;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -456,11 +363,11 @@ SpiScanAdapter(
|
|||
* @return NTSTATUS of the operation
|
||||
*/
|
||||
NTSTATUS
|
||||
CallHWInitialize(
|
||||
FdoCallHWInitialize(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
PPORT_CONFIGURATION_INFORMATION PortConfig = DeviceExtension->PortConfig;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
NTSTATUS Status;
|
||||
KIRQL OldIrql;
|
||||
|
||||
/* Deal with interrupts */
|
||||
|
@ -508,9 +415,13 @@ CallHWInitialize(
|
|||
}
|
||||
|
||||
if (DeviceExtension->InterruptCount == 1 || Dirql[0] > Dirql[1])
|
||||
{
|
||||
MaxDirql = Dirql[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
MaxDirql = Dirql[1];
|
||||
}
|
||||
|
||||
for (i = 0; i < DeviceExtension->InterruptCount; i++)
|
||||
{
|
||||
|
@ -525,10 +436,16 @@ CallHWInitialize(
|
|||
InterruptShareable = FALSE;
|
||||
}
|
||||
|
||||
Status = IoConnectInterrupt(
|
||||
&DeviceExtension->Interrupt[i], (PKSERVICE_ROUTINE)ScsiPortIsr, DeviceExtension,
|
||||
&DeviceExtension->IrqLock, MappedIrq[i], Dirql[i], MaxDirql, InterruptMode[i],
|
||||
InterruptShareable, Affinity[i], FALSE);
|
||||
Status = IoConnectInterrupt(&DeviceExtension->Interrupt[i],
|
||||
ScsiPortIsr,
|
||||
DeviceExtension,
|
||||
&DeviceExtension->IrqLock,
|
||||
MappedIrq[i], Dirql[i],
|
||||
MaxDirql,
|
||||
InterruptMode[i],
|
||||
InterruptShareable,
|
||||
Affinity[i],
|
||||
FALSE);
|
||||
|
||||
if (!(NT_SUCCESS(Status)))
|
||||
{
|
||||
|
@ -537,9 +454,6 @@ CallHWInitialize(
|
|||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Save IoAddress (from access ranges) */
|
||||
|
@ -583,98 +497,96 @@ CallHWInitialize(
|
|||
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
|
||||
{
|
||||
/* 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 */
|
||||
KeLowerIrql(OldIrql);
|
||||
|
||||
return Status;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
SpiCleanupAfterInit(
|
||||
NTSTATUS
|
||||
FdoRemoveAdapter(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
PSCSI_LUN_INFO LunInfo;
|
||||
PVOID Ptr;
|
||||
ULONG Bus, Lun;
|
||||
IoStopTimer(DeviceExtension->Common.DeviceObject);
|
||||
|
||||
/* Check if we have something to clean up */
|
||||
if (DeviceExtension == NULL)
|
||||
return;
|
||||
// release device interface
|
||||
if (DeviceExtension->InterfaceName.Buffer)
|
||||
{
|
||||
IoSetDeviceInterfaceState(&DeviceExtension->InterfaceName, FALSE);
|
||||
|
||||
/* Stop the timer */
|
||||
IoStopTimer(DeviceExtension->DeviceObject);
|
||||
RtlFreeUnicodeString(&DeviceExtension->InterfaceName);
|
||||
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)
|
||||
{
|
||||
if (DeviceExtension->Interrupt[--DeviceExtension->InterruptCount])
|
||||
IoDisconnectInterrupt(DeviceExtension->Interrupt[DeviceExtension->InterruptCount]);
|
||||
}
|
||||
|
||||
/* Delete ConfigInfo */
|
||||
if (DeviceExtension->BusesConfig)
|
||||
// FIXME: delete LUNs
|
||||
if (DeviceExtension->Buses)
|
||||
{
|
||||
for (Bus = 0; Bus < DeviceExtension->BusNum; Bus++)
|
||||
for (UINT8 pathId = 0; pathId < DeviceExtension->NumberOfBuses; pathId++)
|
||||
{
|
||||
if (!DeviceExtension->BusesConfig->BusScanInfo[Bus])
|
||||
continue;
|
||||
|
||||
LunInfo = DeviceExtension->BusesConfig->BusScanInfo[Bus]->LunInfo;
|
||||
|
||||
while (LunInfo)
|
||||
PSCSI_BUS_INFO bus = &DeviceExtension->Buses[pathId];
|
||||
if (bus->RegistryMapKey)
|
||||
{
|
||||
/* Free current, but save pointer to the next one */
|
||||
Ptr = LunInfo->Next;
|
||||
ExFreePool(LunInfo);
|
||||
LunInfo = Ptr;
|
||||
ZwDeleteKey(bus->RegistryMapKey);
|
||||
ZwClose(bus->RegistryMapKey);
|
||||
bus->RegistryMapKey = NULL;
|
||||
}
|
||||
|
||||
ExFreePool(DeviceExtension->BusesConfig->BusScanInfo[Bus]);
|
||||
}
|
||||
|
||||
ExFreePool(DeviceExtension->BusesConfig);
|
||||
ExFreePoolWithTag(DeviceExtension->Buses, TAG_SCSIPORT);
|
||||
}
|
||||
|
||||
/* Free PortConfig */
|
||||
if (DeviceExtension->PortConfig)
|
||||
ExFreePool(DeviceExtension->PortConfig);
|
||||
|
||||
/* Free LUNs*/
|
||||
for(Lun = 0; Lun < LUS_NUMBER; Lun++)
|
||||
{
|
||||
while (DeviceExtension->LunExtensionList[Lun])
|
||||
{
|
||||
Ptr = DeviceExtension->LunExtensionList[Lun];
|
||||
DeviceExtension->LunExtensionList[Lun] = DeviceExtension->LunExtensionList[Lun]->Next;
|
||||
|
||||
ExFreePool(Ptr);
|
||||
}
|
||||
ExFreePoolWithTag(DeviceExtension->PortConfig, TAG_SCSIPORT);
|
||||
}
|
||||
|
||||
/* Free common buffer (if it exists) */
|
||||
if (DeviceExtension->SrbExtensionBuffer != NULL &&
|
||||
DeviceExtension->CommonBufferLength != 0)
|
||||
if (DeviceExtension->SrbExtensionBuffer != NULL && DeviceExtension->CommonBufferLength != 0)
|
||||
{
|
||||
if (!DeviceExtension->AdapterObject)
|
||||
{
|
||||
ExFreePool(DeviceExtension->SrbExtensionBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
HalFreeCommonBuffer(DeviceExtension->AdapterObject,
|
||||
DeviceExtension->CommonBufferLength,
|
||||
DeviceExtension->PhysicalAddress,
|
||||
DeviceExtension->SrbExtensionBuffer,
|
||||
FALSE);
|
||||
}
|
||||
if (!DeviceExtension->AdapterObject)
|
||||
{
|
||||
ExFreePoolWithTag(DeviceExtension->SrbExtensionBuffer, TAG_SCSIPORT);
|
||||
}
|
||||
else
|
||||
{
|
||||
HalFreeCommonBuffer(DeviceExtension->AdapterObject,
|
||||
DeviceExtension->CommonBufferLength,
|
||||
DeviceExtension->PhysicalAddress,
|
||||
DeviceExtension->SrbExtensionBuffer,
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free SRB info */
|
||||
if (DeviceExtension->SrbInfo != NULL)
|
||||
ExFreePool(DeviceExtension->SrbInfo);
|
||||
ExFreePoolWithTag(DeviceExtension->SrbInfo, TAG_SCSIPORT);
|
||||
|
||||
/* Unmap mapped addresses */
|
||||
while (DeviceExtension->MappedAddressList != NULL)
|
||||
|
@ -682,13 +594,161 @@ SpiCleanupAfterInit(
|
|||
MmUnmapIoSpace(DeviceExtension->MappedAddressList->MappedAddress,
|
||||
DeviceExtension->MappedAddressList->NumberOfBytes);
|
||||
|
||||
Ptr = DeviceExtension->MappedAddressList;
|
||||
PVOID ptr = DeviceExtension->MappedAddressList;
|
||||
DeviceExtension->MappedAddressList = DeviceExtension->MappedAddressList->NextMappedAddress;
|
||||
|
||||
ExFreePool(Ptr);
|
||||
ExFreePoolWithTag(ptr, TAG_SCSIPORT);
|
||||
}
|
||||
|
||||
/* Finally delete the device object */
|
||||
DPRINT("Deleting device %p\n", DeviceExtension->DeviceObject);
|
||||
IoDeleteDevice(DeviceExtension->DeviceObject);
|
||||
IoDeleteDevice(DeviceExtension->Common.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
|
||||
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
||||
* Aleksey Bragin (aleksey@reactos.org)
|
||||
* 2020 Victor Perevertkin (victor.perevertkin@reactos.org)
|
||||
*/
|
||||
|
||||
#include "scsiport.h"
|
||||
|
@ -19,13 +20,10 @@ SpiGetInquiryData(
|
|||
_In_ PIRP Irp)
|
||||
{
|
||||
ULONG InquiryDataSize;
|
||||
PSCSI_LUN_INFO LunInfo;
|
||||
ULONG BusCount, LunCount, Length;
|
||||
ULONG BusCount, Length;
|
||||
PIO_STACK_LOCATION IrpStack;
|
||||
PSCSI_ADAPTER_BUS_INFO AdapterBusInfo;
|
||||
PSCSI_INQUIRY_DATA InquiryData;
|
||||
PSCSI_BUS_DATA BusData;
|
||||
ULONG Bus;
|
||||
PUCHAR Buffer;
|
||||
|
||||
DPRINT("SpiGetInquiryData() called\n");
|
||||
|
@ -35,22 +33,15 @@ SpiGetInquiryData(
|
|||
Buffer = Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
/* Initialize bus and LUN counters */
|
||||
BusCount = DeviceExtension->BusesConfig->NumberOfBuses;
|
||||
LunCount = 0;
|
||||
|
||||
/* Calculate total number of LUNs */
|
||||
for (Bus = 0; Bus < BusCount; Bus++)
|
||||
LunCount += DeviceExtension->BusesConfig->BusScanInfo[Bus]->LogicalUnitsCount;
|
||||
BusCount = DeviceExtension->NumberOfBuses;
|
||||
|
||||
/* Calculate size of inquiry data, rounding up to sizeof(ULONG) */
|
||||
InquiryDataSize =
|
||||
((sizeof(SCSI_INQUIRY_DATA) - 1 + INQUIRYDATABUFFERSIZE +
|
||||
sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1));
|
||||
InquiryDataSize = ALIGN_UP(sizeof(SCSI_INQUIRY_DATA) - 1 + INQUIRYDATABUFFERSIZE, ULONG);
|
||||
|
||||
/* Calculate data size */
|
||||
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 */
|
||||
if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < Length)
|
||||
|
@ -73,47 +64,47 @@ SpiGetInquiryData(
|
|||
(BusCount - 1) * sizeof(SCSI_BUS_DATA));
|
||||
|
||||
/* 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 */
|
||||
BusData->InquiryDataOffset = (ULONG)((PUCHAR)InquiryData - Buffer);
|
||||
|
||||
/* Get a pointer to the LUN information structure */
|
||||
LunInfo = DeviceExtension->BusesConfig->BusScanInfo[Bus]->LunInfo;
|
||||
|
||||
/* Store Initiator Bus Id */
|
||||
BusData->InitiatorBusId =
|
||||
DeviceExtension->BusesConfig->BusScanInfo[Bus]->BusIdentifier;
|
||||
BusData->InitiatorBusId = DeviceExtension->Buses[pathId].BusIdentifier;
|
||||
|
||||
/* Store LUN count */
|
||||
BusData->NumberOfLogicalUnits =
|
||||
DeviceExtension->BusesConfig->BusScanInfo[Bus]->LogicalUnitsCount;
|
||||
BusData->NumberOfLogicalUnits = DeviceExtension->Buses[pathId].LogicalUnitsCount;
|
||||
|
||||
/* 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",
|
||||
Bus, LunInfo->TargetId, LunInfo->Lun);
|
||||
PSCSI_PORT_LUN_EXTENSION lunExt =
|
||||
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 */
|
||||
InquiryData->PathId = LunInfo->PathId;
|
||||
InquiryData->TargetId = LunInfo->TargetId;
|
||||
InquiryData->Lun = LunInfo->Lun;
|
||||
InquiryData->PathId = lunExt->PathId;
|
||||
InquiryData->TargetId = lunExt->TargetId;
|
||||
InquiryData->Lun = lunExt->Lun;
|
||||
InquiryData->InquiryDataLength = INQUIRYDATABUFFERSIZE;
|
||||
InquiryData->DeviceClaimed = LunInfo->DeviceClaimed;
|
||||
InquiryData->DeviceClaimed = lunExt->DeviceClaimed;
|
||||
InquiryData->NextInquiryDataOffset =
|
||||
(ULONG)((PUCHAR)InquiryData + InquiryDataSize - Buffer);
|
||||
|
||||
/* Copy data in it */
|
||||
RtlCopyMemory(InquiryData->InquiryData,
|
||||
LunInfo->InquiryData,
|
||||
&lunExt->InquiryData,
|
||||
INQUIRYDATABUFFERSIZE);
|
||||
|
||||
/* Move to the next LUN */
|
||||
LunInfo = LunInfo->Next;
|
||||
InquiryData = (PSCSI_INQUIRY_DATA) ((PCHAR)InquiryData + InquiryDataSize);
|
||||
InquiryData = (PSCSI_INQUIRY_DATA) ((ULONG_PTR)InquiryData + InquiryDataSize);
|
||||
}
|
||||
|
||||
/* Either mark the end, or set offset to 0 */
|
||||
|
@ -128,6 +119,269 @@ SpiGetInquiryData(
|
|||
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
|
||||
* ScsiPortDeviceControl
|
||||
|
@ -152,104 +406,147 @@ ScsiPortDeviceControl(
|
|||
_In_ PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION Stack;
|
||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
||||
PDUMP_POINTERS DumpPointers;
|
||||
NTSTATUS Status;
|
||||
PSCSI_PORT_COMMON_EXTENSION comExt = DeviceObject->DeviceExtension;
|
||||
PSCSI_PORT_DEVICE_EXTENSION portExt;
|
||||
PSCSI_PORT_LUN_EXTENSION lunExt;
|
||||
NTSTATUS status;
|
||||
|
||||
DPRINT("ScsiPortDeviceControl()\n");
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
DeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
switch (Stack->Parameters.DeviceIoControl.IoControlCode)
|
||||
{
|
||||
case IOCTL_SCSI_GET_DUMP_POINTERS:
|
||||
DPRINT(" IOCTL_SCSI_GET_DUMP_POINTERS\n");
|
||||
|
||||
if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DUMP_POINTERS))
|
||||
case IOCTL_STORAGE_QUERY_PROPERTY:
|
||||
{
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
|
||||
break;
|
||||
}
|
||||
DPRINT(" IOCTL_STORAGE_QUERY_PROPERTY\n");
|
||||
|
||||
DumpPointers = Irp->AssociatedIrp.SystemBuffer;
|
||||
DumpPointers->DeviceObject = DeviceObject;
|
||||
/* More data.. ? */
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
|
||||
break;
|
||||
|
||||
case IOCTL_SCSI_GET_CAPABILITIES:
|
||||
DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
|
||||
if (Stack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(PVOID))
|
||||
{
|
||||
*((PVOID *)Irp->AssociatedIrp.SystemBuffer) = &DeviceExtension->PortCapabilities;
|
||||
|
||||
Irp->IoStatus.Information = sizeof(PVOID);
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(IO_SCSI_CAPABILITIES))
|
||||
{
|
||||
Status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
|
||||
&DeviceExtension->PortCapabilities,
|
||||
sizeof(IO_SCSI_CAPABILITIES));
|
||||
|
||||
Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
case IOCTL_SCSI_GET_INQUIRY_DATA:
|
||||
DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
|
||||
|
||||
/* Copy inquiry data to the port device extension */
|
||||
Status = SpiGetInquiryData(DeviceExtension, Irp);
|
||||
break;
|
||||
|
||||
case IOCTL_SCSI_MINIPORT:
|
||||
DPRINT1("IOCTL_SCSI_MINIPORT unimplemented!\n");
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
|
||||
case IOCTL_SCSI_PASS_THROUGH:
|
||||
DPRINT1("IOCTL_SCSI_PASS_THROUGH unimplemented!\n");
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (DEVICE_TYPE_FROM_CTL_CODE(Stack->Parameters.DeviceIoControl.IoControlCode) == MOUNTDEVCONTROLTYPE)
|
||||
{
|
||||
switch (Stack->Parameters.DeviceIoControl.IoControlCode)
|
||||
if (!VerifyIrpInBufferSize(Irp, sizeof(STORAGE_PROPERTY_QUERY)))
|
||||
{
|
||||
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);
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
DPRINT1(" unknown ioctl code: 0x%lX\n", Stack->Parameters.DeviceIoControl.IoControlCode);
|
||||
}
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
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:
|
||||
{
|
||||
DPRINT(" IOCTL_SCSI_GET_DUMP_POINTERS\n");
|
||||
|
||||
if (!comExt->IsFDO)
|
||||
{
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
return IoCallDriver(comExt->LowerDevice, Irp);
|
||||
}
|
||||
|
||||
PDUMP_POINTERS dumpPointers = Irp->AssociatedIrp.SystemBuffer;
|
||||
if (!VerifyIrpOutBufferSize(Irp, sizeof(*dumpPointers)))
|
||||
{
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
dumpPointers->DeviceObject = DeviceObject;
|
||||
/* More data.. ? */
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
|
||||
break;
|
||||
}
|
||||
case IOCTL_SCSI_GET_CAPABILITIES:
|
||||
{
|
||||
DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
|
||||
|
||||
if (!comExt->IsFDO)
|
||||
{
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!VerifyIrpOutBufferSize(Irp, sizeof(IO_SCSI_CAPABILITIES)))
|
||||
{
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
portExt = DeviceObject->DeviceExtension;
|
||||
|
||||
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
|
||||
&portExt->PortCapabilities,
|
||||
sizeof(IO_SCSI_CAPABILITIES));
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
|
||||
break;
|
||||
}
|
||||
case IOCTL_SCSI_GET_INQUIRY_DATA:
|
||||
{
|
||||
DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
|
||||
|
||||
if (!comExt->IsFDO)
|
||||
{
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy inquiry data to the port device extension */
|
||||
status = SpiGetInquiryData(DeviceObject->DeviceExtension, Irp);
|
||||
break;
|
||||
}
|
||||
case IOCTL_SCSI_MINIPORT:
|
||||
DPRINT1("IOCTL_SCSI_MINIPORT unimplemented!\n");
|
||||
status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
|
||||
case IOCTL_SCSI_PASS_THROUGH:
|
||||
DPRINT1("IOCTL_SCSI_PASS_THROUGH unimplemented!\n");
|
||||
status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINT1("unknown ioctl code: 0x%lX\n", Stack->Parameters.DeviceIoControl.IoControlCode);
|
||||
status = STATUS_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Complete the request with the given status */
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Status = status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return Status;
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -4,40 +4,48 @@
|
|||
* PURPOSE: Logical Unit (PDO) functions
|
||||
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
||||
* Aleksey Bragin (aleksey@reactos.org)
|
||||
* 2020 Victor Perevertkin (victor.perevertkin@reactos.org)
|
||||
*/
|
||||
|
||||
#include "scsiport.h"
|
||||
#include "scsitypes.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
PSCSI_PORT_LUN_EXTENSION
|
||||
SpiAllocateLunExtension(
|
||||
PDEVICE_OBJECT
|
||||
PdoCreateLunDevice(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
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 */
|
||||
LunExtensionSize = (DeviceExtension->LunExtensionSize +
|
||||
sizeof(LONGLONG) - 1) & ~(sizeof(LONGLONG) - 1);
|
||||
NTSTATUS Status = IoCreateDevice(DeviceExtension->Common.DeviceObject->DriverObject,
|
||||
LunExtensionSize,
|
||||
NULL,
|
||||
FILE_DEVICE_DISK,
|
||||
FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN,
|
||||
FALSE,
|
||||
&LunPDO);
|
||||
|
||||
LunExtensionSize += sizeof(SCSI_PORT_LUN_EXTENSION);
|
||||
DPRINT("LunExtensionSize %lu\n", LunExtensionSize);
|
||||
|
||||
LunExtension = ExAllocatePoolWithTag(NonPagedPool, LunExtensionSize, TAG_SCSIPORT);
|
||||
if (LunExtension == NULL)
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Out of resources!\n");
|
||||
DPRINT1("Failed to create a Lun PDO, status: %x\n", Status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LunExtension = LunPDO->DeviceExtension;
|
||||
|
||||
/* Zero everything */
|
||||
RtlZeroMemory(LunExtension, LunExtensionSize);
|
||||
|
||||
LunExtension->Common.IsFDO = FALSE;
|
||||
LunExtension->Common.DeviceObject = LunPDO;
|
||||
LunExtension->Common.LowerDevice = DeviceExtension->Common.DeviceObject;
|
||||
|
||||
/* Initialize a list of requests */
|
||||
InitializeListHead(&LunExtension->SrbInfo.Requests);
|
||||
|
||||
|
@ -50,66 +58,54 @@ SpiAllocateLunExtension(
|
|||
/* Initialize request queue */
|
||||
KeInitializeDeviceQueue(&LunExtension->DeviceQueue);
|
||||
|
||||
return LunExtension;
|
||||
LunPDO->Flags |= DO_DIRECT_IO;
|
||||
LunPDO->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
||||
return LunPDO;
|
||||
}
|
||||
|
||||
PSCSI_PORT_LUN_EXTENSION
|
||||
SpiGetLunExtension(
|
||||
GetLunByPath(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
_In_ UCHAR PathId,
|
||||
_In_ UCHAR TargetId,
|
||||
_In_ UCHAR Lun)
|
||||
{
|
||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
||||
|
||||
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 (PathId >= DeviceExtension->NumberOfBuses)
|
||||
{
|
||||
if (LunExtension->TargetId == TargetId &&
|
||||
LunExtension->Lun == Lun &&
|
||||
LunExtension->PathId == PathId)
|
||||
{
|
||||
/* All matches, return */
|
||||
return LunExtension;
|
||||
}
|
||||
|
||||
/* Advance to the next item */
|
||||
LunExtension = LunExtension->Next;
|
||||
DPRINT1("Invalid PathId: %u\n", PathId);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We did not find anything */
|
||||
DPRINT("Nothing found\n");
|
||||
PSCSI_BUS_INFO bus = &DeviceExtension->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);
|
||||
|
||||
if (lunExt->PathId == PathId &&
|
||||
lunExt->TargetId == TargetId &&
|
||||
lunExt->Lun == Lun)
|
||||
{
|
||||
return lunExt;
|
||||
}
|
||||
}
|
||||
|
||||
DPRINT("SCSI LUN (%u, %u, %u) was not found\n", PathId, TargetId, Lun);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PSCSI_REQUEST_BLOCK_INFO
|
||||
SpiGetSrbData(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
_In_ UCHAR PathId,
|
||||
_In_ UCHAR TargetId,
|
||||
_In_ UCHAR Lun,
|
||||
_In_ PSCSI_PORT_LUN_EXTENSION LunExtension,
|
||||
_In_ UCHAR QueueTag)
|
||||
{
|
||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
||||
|
||||
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 &LunExtension->SrbInfo;
|
||||
}
|
||||
|
@ -122,3 +118,506 @@ SpiGetSrbData(
|
|||
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
|
||||
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
||||
* Aleksey Bragin (aleksey@reactos.org)
|
||||
* 2020 Victor Perevertkin (victor.perevertkin@reactos.org)
|
||||
*/
|
||||
|
||||
#include "scsiport.h"
|
||||
#include "scsitypes.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
@ -15,26 +17,28 @@
|
|||
VOID
|
||||
SpiInitOpenKeys(
|
||||
_Inout_ PCONFIGURATION_INFO ConfigInfo,
|
||||
_In_ PUNICODE_STRING RegistryPath)
|
||||
_In_ PSCSI_PORT_DRIVER_EXTENSION DriverExtension)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING KeyName;
|
||||
NTSTATUS Status;
|
||||
HANDLE parametersKey;
|
||||
|
||||
DriverExtension->IsLegacyDriver = TRUE;
|
||||
|
||||
/* Open the service key */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
RegistryPath,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
&DriverExtension->RegistryPath,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
Status = ZwOpenKey(&ConfigInfo->ServiceKey,
|
||||
KEY_READ,
|
||||
&ObjectAttributes);
|
||||
Status = ZwOpenKey(&ConfigInfo->ServiceKey, KEY_READ, &ObjectAttributes);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -44,14 +48,12 @@ SpiInitOpenKeys(
|
|||
RtlInitUnicodeString(&KeyName, L"Parameters");
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
ConfigInfo->ServiceKey,
|
||||
(PSECURITY_DESCRIPTOR) NULL);
|
||||
NULL);
|
||||
|
||||
/* Try to open it */
|
||||
Status = ZwOpenKey(&ConfigInfo->DeviceKey,
|
||||
KEY_READ,
|
||||
&ObjectAttributes);
|
||||
Status = ZwOpenKey(&ConfigInfo->DeviceKey, KEY_READ, &ObjectAttributes);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -69,14 +71,32 @@ SpiInitOpenKeys(
|
|||
RtlInitUnicodeString(&KeyName, L"Device");
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
ConfigInfo->ServiceKey,
|
||||
NULL);
|
||||
|
||||
/* We don't check for failure here - not needed */
|
||||
ZwOpenKey(&ConfigInfo->DeviceKey,
|
||||
KEY_READ,
|
||||
&ObjectAttributes);
|
||||
ZwOpenKey(&ConfigInfo->DeviceKey, 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
|
||||
SpiBuildDeviceMap(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
_In_ PUNICODE_STRING RegistryPath)
|
||||
RegistryInitAdapterKey(
|
||||
_Inout_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING KeyName;
|
||||
UNICODE_STRING ValueName;
|
||||
WCHAR NameBuffer[64];
|
||||
ULONG Disposition;
|
||||
HANDLE ScsiKey;
|
||||
HANDLE ScsiPortKey = NULL;
|
||||
HANDLE ScsiBusKey = NULL;
|
||||
HANDLE ScsiInitiatorKey = NULL;
|
||||
HANDLE ScsiTargetKey = NULL;
|
||||
HANDLE ScsiLunKey = NULL;
|
||||
ULONG BusNumber;
|
||||
ULONG Target;
|
||||
ULONG CurrentTarget;
|
||||
ULONG Lun;
|
||||
PWCHAR DriverName;
|
||||
ULONG UlongData;
|
||||
PWCHAR TypeName;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("SpiBuildDeviceMap() called\n");
|
||||
|
||||
if (DeviceExtension == NULL || RegistryPath == NULL)
|
||||
if (DeviceExtension == NULL)
|
||||
{
|
||||
DPRINT1("Invalid parameter\n");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
@ -151,7 +161,7 @@ SpiBuildDeviceMap(
|
|||
0,
|
||||
NULL,
|
||||
REG_OPTION_VOLATILE,
|
||||
&Disposition);
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
|
||||
|
@ -165,18 +175,14 @@ SpiBuildDeviceMap(
|
|||
L"Scsi Port %lu",
|
||||
DeviceExtension->PortNumber);
|
||||
RtlInitUnicodeString(&KeyName, NameBuffer);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_KERNEL_HANDLE,
|
||||
ScsiKey,
|
||||
NULL);
|
||||
InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_KERNEL_HANDLE, ScsiKey, NULL);
|
||||
Status = ZwCreateKey(&ScsiPortKey,
|
||||
KEY_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
0,
|
||||
NULL,
|
||||
REG_OPTION_VOLATILE,
|
||||
&Disposition);
|
||||
NULL);
|
||||
ZwClose(ScsiKey);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -206,14 +212,29 @@ SpiBuildDeviceMap(
|
|||
}
|
||||
|
||||
/* 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");
|
||||
Status = ZwSetValueKey(ScsiPortKey,
|
||||
&ValueName,
|
||||
0,
|
||||
REG_SZ,
|
||||
DriverName,
|
||||
(ULONG)((wcslen(DriverName) + 1) * sizeof(WCHAR)));
|
||||
driverName,
|
||||
driverNameU->Length + sizeof(UNICODE_NULL));
|
||||
|
||||
ExFreePoolWithTag(driverName, TAG_SCSIPORT);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ZwSetValueKey('Driver') failed (Status %lx)\n", Status);
|
||||
|
@ -256,7 +277,7 @@ SpiBuildDeviceMap(
|
|||
}
|
||||
|
||||
/* Enumerate buses */
|
||||
for (BusNumber = 0; BusNumber < DeviceExtension->PortConfig->NumberOfBuses; BusNumber++)
|
||||
for (BusNumber = 0; BusNumber < DeviceExtension->NumberOfBuses; BusNumber++)
|
||||
{
|
||||
/* Create 'Scsi Bus X' key */
|
||||
DPRINT(" Scsi Bus %lu\n", BusNumber);
|
||||
|
@ -266,7 +287,7 @@ SpiBuildDeviceMap(
|
|||
RtlInitUnicodeString(&KeyName, NameBuffer);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
0,
|
||||
OBJ_KERNEL_HANDLE,
|
||||
ScsiPortKey,
|
||||
NULL);
|
||||
Status = ZwCreateKey(&ScsiBusKey,
|
||||
|
@ -275,7 +296,7 @@ SpiBuildDeviceMap(
|
|||
0,
|
||||
NULL,
|
||||
REG_OPTION_VOLATILE,
|
||||
&Disposition);
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
|
||||
|
@ -291,7 +312,7 @@ SpiBuildDeviceMap(
|
|||
RtlInitUnicodeString(&KeyName, NameBuffer);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
0,
|
||||
OBJ_KERNEL_HANDLE,
|
||||
ScsiBusKey,
|
||||
NULL);
|
||||
Status = ZwCreateKey(&ScsiInitiatorKey,
|
||||
|
@ -300,7 +321,7 @@ SpiBuildDeviceMap(
|
|||
0,
|
||||
NULL,
|
||||
REG_OPTION_VOLATILE,
|
||||
&Disposition);
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
|
||||
|
@ -312,202 +333,14 @@ SpiBuildDeviceMap(
|
|||
ZwClose(ScsiInitiatorKey);
|
||||
ScsiInitiatorKey = NULL;
|
||||
|
||||
|
||||
/* 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);
|
||||
DeviceExtension->Buses[BusNumber].RegistryMapKey = ScsiBusKey;
|
||||
ScsiBusKey = NULL;
|
||||
}
|
||||
|
||||
ByeBye:
|
||||
if (ScsiLunKey != NULL)
|
||||
ZwClose(ScsiLunKey);
|
||||
|
||||
if (ScsiInitiatorKey != NULL)
|
||||
ZwClose(ScsiInitiatorKey);
|
||||
|
||||
if (ScsiTargetKey != NULL)
|
||||
ZwClose(ScsiTargetKey);
|
||||
|
||||
if (ScsiBusKey != NULL)
|
||||
ZwClose(ScsiBusKey);
|
||||
|
||||
|
@ -518,3 +351,109 @@ ByeBye:
|
|||
|
||||
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
|
||||
NTSTATUS
|
||||
SpiHandleAttachRelease(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
_In_ PSCSI_PORT_LUN_EXTENSION LunExtension,
|
||||
_Inout_ PIRP Irp)
|
||||
{
|
||||
PSCSI_LUN_INFO LunInfo;
|
||||
PIO_STACK_LOCATION IrpStack;
|
||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension =
|
||||
LunExtension->Common.LowerDevice->DeviceExtension;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PSCSI_REQUEST_BLOCK Srb;
|
||||
KIRQL Irql;
|
||||
|
||||
/* Get pointer to the SRB */
|
||||
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
Srb = (PSCSI_REQUEST_BLOCK)IrpStack->Parameters.Others.Argument1;
|
||||
|
||||
/* 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;
|
||||
|
||||
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
PSCSI_REQUEST_BLOCK Srb = IrpStack->Parameters.Scsi.Srb;
|
||||
|
||||
/* Get spinlock */
|
||||
KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
|
||||
|
@ -98,7 +68,7 @@ SpiHandleAttachRelease(
|
|||
/* Release, if asked */
|
||||
if (Srb->Function == SRB_FUNCTION_RELEASE_DEVICE)
|
||||
{
|
||||
LunInfo->DeviceClaimed = FALSE;
|
||||
LunExtension->DeviceClaimed = FALSE;
|
||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
|
||||
Srb->SrbStatus = SRB_STATUS_SUCCESS;
|
||||
|
||||
|
@ -106,7 +76,7 @@ SpiHandleAttachRelease(
|
|||
}
|
||||
|
||||
/* Attach, if not already claimed */
|
||||
if (LunInfo->DeviceClaimed)
|
||||
if (LunExtension->DeviceClaimed)
|
||||
{
|
||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
|
||||
Srb->SrbStatus = SRB_STATUS_BUSY;
|
||||
|
@ -115,13 +85,13 @@ SpiHandleAttachRelease(
|
|||
}
|
||||
|
||||
/* Save the device object */
|
||||
DeviceObject = LunInfo->DeviceObject;
|
||||
DeviceObject = LunExtension->Common.DeviceObject;
|
||||
|
||||
if (Srb->Function == SRB_FUNCTION_CLAIM_DEVICE)
|
||||
LunInfo->DeviceClaimed = TRUE;
|
||||
LunExtension->DeviceClaimed = TRUE;
|
||||
|
||||
if (Srb->Function == SRB_FUNCTION_ATTACH_DEVICE)
|
||||
LunInfo->DeviceObject = Srb->DataBuffer;
|
||||
LunExtension->Common.DeviceObject = Srb->DataBuffer;
|
||||
|
||||
Srb->DataBuffer = DeviceObject;
|
||||
|
||||
|
@ -154,8 +124,8 @@ ScsiPortDispatchScsi(
|
|||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_Inout_ PIRP Irp)
|
||||
{
|
||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
||||
PSCSI_PORT_DEVICE_EXTENSION portExt;
|
||||
PSCSI_PORT_LUN_EXTENSION lunExt;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
PSCSI_REQUEST_BLOCK Srb;
|
||||
KIRQL Irql;
|
||||
|
@ -165,10 +135,12 @@ ScsiPortDispatchScsi(
|
|||
|
||||
DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
|
||||
|
||||
DeviceExtension = DeviceObject->DeviceExtension;
|
||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
Srb = Stack->Parameters.Scsi.Srb;
|
||||
lunExt = DeviceObject->DeviceExtension;
|
||||
ASSERT(!lunExt->Common.IsFDO);
|
||||
portExt = lunExt->Common.LowerDevice->DeviceExtension;
|
||||
|
||||
if (Srb == NULL)
|
||||
{
|
||||
DPRINT1("ScsiPortDispatchScsi() called with Srb = NULL!\n");
|
||||
|
@ -179,15 +151,16 @@ ScsiPortDispatchScsi(
|
|||
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return (Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT("Srb: %p\n", Srb);
|
||||
DPRINT("Srb->Function: %lu\n", Srb->Function);
|
||||
DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
|
||||
DPRINT("Srb: %p, Srb->Function: %lu\n", Srb, Srb->Function);
|
||||
|
||||
LunExtension = SpiGetLunExtension(DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
|
||||
if (LunExtension == NULL)
|
||||
Srb->PathId = lunExt->PathId;
|
||||
Srb->TargetId = lunExt->TargetId;
|
||||
Srb->Lun = lunExt->Lun;
|
||||
|
||||
if (lunExt == NULL)
|
||||
{
|
||||
DPRINT("ScsiPortDispatchScsi() called with an invalid LUN\n");
|
||||
Status = STATUS_NO_SUCH_DEVICE;
|
||||
|
@ -198,7 +171,7 @@ ScsiPortDispatchScsi(
|
|||
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return (Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
switch (Srb->Function)
|
||||
|
@ -206,7 +179,7 @@ ScsiPortDispatchScsi(
|
|||
case SRB_FUNCTION_SHUTDOWN:
|
||||
case SRB_FUNCTION_FLUSH:
|
||||
DPRINT(" SRB_FUNCTION_SHUTDOWN or FLUSH\n");
|
||||
if (DeviceExtension->CachesData == FALSE)
|
||||
if (portExt->CachesData == FALSE)
|
||||
{
|
||||
/* All success here */
|
||||
Srb->SrbStatus = SRB_STATUS_SUCCESS;
|
||||
|
@ -225,7 +198,7 @@ ScsiPortDispatchScsi(
|
|||
if (Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)
|
||||
{
|
||||
/* Start IO directly */
|
||||
IoStartPacket(DeviceObject, Irp, NULL, NULL);
|
||||
IoStartPacket(portExt->Common.DeviceObject, Irp, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -235,13 +208,12 @@ ScsiPortDispatchScsi(
|
|||
KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
|
||||
|
||||
/* Insert IRP into the queue */
|
||||
if (!KeInsertByKeyDeviceQueue(
|
||||
&LunExtension->DeviceQueue,
|
||||
&Irp->Tail.Overlay.DeviceQueueEntry,
|
||||
Srb->QueueSortKey))
|
||||
if (!KeInsertByKeyDeviceQueue(&lunExt->DeviceQueue,
|
||||
&Irp->Tail.Overlay.DeviceQueueEntry,
|
||||
Srb->QueueSortKey))
|
||||
{
|
||||
/* 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 */
|
||||
|
@ -254,39 +226,40 @@ ScsiPortDispatchScsi(
|
|||
DPRINT(" SRB_FUNCTION_CLAIM_DEVICE or ATTACH\n");
|
||||
|
||||
/* Reference device object and keep the device object */
|
||||
Status = SpiHandleAttachRelease(DeviceExtension, Irp);
|
||||
Status = SpiHandleAttachRelease(lunExt, Irp);
|
||||
break;
|
||||
|
||||
case SRB_FUNCTION_RELEASE_DEVICE:
|
||||
DPRINT(" SRB_FUNCTION_RELEASE_DEVICE\n");
|
||||
|
||||
/* Dereference device object and clear the device object */
|
||||
Status = SpiHandleAttachRelease(DeviceExtension, Irp);
|
||||
Status = SpiHandleAttachRelease(lunExt, Irp);
|
||||
break;
|
||||
|
||||
case SRB_FUNCTION_RELEASE_QUEUE:
|
||||
DPRINT(" SRB_FUNCTION_RELEASE_QUEUE\n");
|
||||
|
||||
/* 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");
|
||||
|
||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
|
||||
KeReleaseSpinLock(&portExt->SpinLock, Irql);
|
||||
Srb->SrbStatus = SRB_STATUS_SUCCESS;
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
SpiGetNextRequestFromLun(DeviceExtension, LunExtension);
|
||||
SpiGetNextRequestFromLun(portExt, lunExt);
|
||||
|
||||
/* SpiGetNextRequestFromLun() releases the spinlock */
|
||||
KeLowerIrql(Irql);
|
||||
|
@ -294,7 +267,7 @@ ScsiPortDispatchScsi(
|
|||
else
|
||||
{
|
||||
DPRINT("The queue has active request\n");
|
||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
|
||||
KeReleaseSpinLock(&portExt->SpinLock, Irql);
|
||||
}
|
||||
|
||||
Srb->SrbStatus = SRB_STATUS_SUCCESS;
|
||||
|
@ -305,23 +278,23 @@ ScsiPortDispatchScsi(
|
|||
DPRINT(" SRB_FUNCTION_FLUSH_QUEUE\n");
|
||||
|
||||
/* 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");
|
||||
|
||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
|
||||
KeReleaseSpinLock(&portExt->SpinLock, Irql);
|
||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make sure there is no active request */
|
||||
ASSERT(LunExtension->SrbInfo.Srb == NULL);
|
||||
ASSERT(lunExt->SrbInfo.Srb == NULL);
|
||||
|
||||
/* Compile a list from the device queue */
|
||||
IrpList = NULL;
|
||||
while ((Entry = KeRemoveDeviceQueue(&LunExtension->DeviceQueue)) != NULL)
|
||||
while ((Entry = KeRemoveDeviceQueue(&lunExt->DeviceQueue)) != NULL)
|
||||
{
|
||||
NextIrp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DeviceQueueEntry);
|
||||
|
||||
|
@ -339,10 +312,10 @@ ScsiPortDispatchScsi(
|
|||
}
|
||||
|
||||
/* Unfreeze the queue */
|
||||
LunExtension->Flags &= ~LUNEX_FROZEN_QUEUE;
|
||||
lunExt->Flags &= ~LUNEX_FROZEN_QUEUE;
|
||||
|
||||
/* Release the spinlock */
|
||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
|
||||
KeReleaseSpinLock(&portExt->SpinLock, Irql);
|
||||
|
||||
/* Complete those requests */
|
||||
while (IrpList)
|
||||
|
@ -415,7 +388,7 @@ SpiGetNextRequestFromLun(
|
|||
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
|
||||
|
||||
/* Start the next pending request */
|
||||
IoStartPacket(DeviceExtension->DeviceObject, NextIrp, (PULONG)NULL, NULL);
|
||||
IoStartPacket(DeviceExtension->Common.DeviceObject, NextIrp, (PULONG)NULL, NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -454,7 +427,7 @@ SpiGetNextRequestFromLun(
|
|||
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
|
||||
|
||||
/* Start the next pending request */
|
||||
IoStartPacket(DeviceExtension->DeviceObject, NextIrp, (PULONG)NULL, NULL);
|
||||
IoStartPacket(DeviceExtension->Common.DeviceObject, NextIrp, (PULONG)NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -525,7 +498,7 @@ SpiSenseCompletionRoutine(
|
|||
static
|
||||
VOID
|
||||
SpiSendRequestSense(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
_In_ PSCSI_PORT_LUN_EXTENSION LunExtension,
|
||||
_In_ PSCSI_REQUEST_BLOCK InitialSrb)
|
||||
{
|
||||
PSCSI_REQUEST_BLOCK Srb;
|
||||
|
@ -544,7 +517,7 @@ SpiSendRequestSense(
|
|||
/* Allocate IRP */
|
||||
LargeInt.QuadPart = (LONGLONG) 1;
|
||||
Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_READ,
|
||||
DeviceExtension->DeviceObject,
|
||||
LunExtension->Common.DeviceObject,
|
||||
InitialSrb->SenseInfoBuffer,
|
||||
InitialSrb->SenseInfoBufferLength,
|
||||
&LargeInt,
|
||||
|
@ -621,7 +594,7 @@ SpiSendRequestSense(
|
|||
Srb->NextSrb = 0;
|
||||
|
||||
/* Call the driver */
|
||||
(VOID)IoCallDriver(DeviceExtension->DeviceObject, Irp);
|
||||
(VOID)IoCallDriver(LunExtension->Common.DeviceObject, Irp);
|
||||
|
||||
DPRINT("SpiSendRequestSense() done\n");
|
||||
}
|
||||
|
@ -642,12 +615,11 @@ SpiProcessCompletedRequest(
|
|||
|
||||
Srb = SrbInfo->Srb;
|
||||
Irp = Srb->OriginalRequest;
|
||||
PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* Get Lun extension */
|
||||
LunExtension = SpiGetLunExtension(DeviceExtension,
|
||||
Srb->PathId,
|
||||
Srb->TargetId,
|
||||
Srb->Lun);
|
||||
LunExtension = IoStack->DeviceObject->DeviceExtension;
|
||||
ASSERT(LunExtension && !LunExtension->Common.IsFDO);
|
||||
|
||||
if (Srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION &&
|
||||
DeviceExtension->MapBuffers &&
|
||||
|
@ -697,7 +669,7 @@ SpiProcessCompletedRequest(
|
|||
!(*NeedToCallStartIo))
|
||||
{
|
||||
/* 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);
|
||||
|
||||
/* Send RequestSense */
|
||||
SpiSendRequestSense(DeviceExtension, Srb);
|
||||
SpiSendRequestSense(LunExtension, Srb);
|
||||
|
||||
/* Exit */
|
||||
return;
|
||||
|
@ -950,10 +922,11 @@ NTAPI
|
|||
ScsiPortStartPacket(
|
||||
_In_ PVOID Context)
|
||||
{
|
||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
||||
PIO_STACK_LOCATION IrpStack;
|
||||
PSCSI_REQUEST_BLOCK Srb;
|
||||
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context;
|
||||
PSCSI_PORT_COMMON_EXTENSION CommonExtension = DeviceObject->DeviceExtension;
|
||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
||||
PSCSI_REQUEST_BLOCK_INFO SrbInfo;
|
||||
BOOLEAN Result;
|
||||
|
@ -961,16 +934,20 @@ ScsiPortStartPacket(
|
|||
|
||||
DPRINT("ScsiPortStartPacket() called\n");
|
||||
|
||||
DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
IrpStack = IoGetCurrentIrpStackLocation(DeviceObject->CurrentIrp);
|
||||
Srb = IrpStack->Parameters.Scsi.Srb;
|
||||
|
||||
/* Get LUN extension */
|
||||
LunExtension = SpiGetLunExtension(DeviceExtension,
|
||||
Srb->PathId,
|
||||
Srb->TargetId,
|
||||
Srb->Lun);
|
||||
if (CommonExtension->IsFDO) // IsFDO
|
||||
{
|
||||
DeviceExtension = DeviceObject->DeviceExtension;
|
||||
LunExtension = IrpStack->DeviceObject->DeviceExtension;
|
||||
ASSERT(LunExtension && !LunExtension->Common.IsFDO);
|
||||
}
|
||||
else
|
||||
{
|
||||
LunExtension = DeviceObject->DeviceExtension;
|
||||
DeviceExtension = LunExtension->Common.LowerDevice->DeviceExtension;
|
||||
}
|
||||
|
||||
/* Check if we are in a reset state */
|
||||
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_RESET)
|
||||
|
@ -1006,11 +983,7 @@ ScsiPortStartPacket(
|
|||
if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND)
|
||||
{
|
||||
/* Get pointer to SRB info structure */
|
||||
SrbInfo = SpiGetSrbData(DeviceExtension,
|
||||
Srb->PathId,
|
||||
Srb->TargetId,
|
||||
Srb->Lun,
|
||||
Srb->QueueTag);
|
||||
SrbInfo = SpiGetSrbData(DeviceExtension, LunExtension, Srb->QueueTag);
|
||||
|
||||
/* Check if the request is still "active" */
|
||||
if (SrbInfo == NULL ||
|
||||
|
@ -1036,7 +1009,7 @@ ScsiPortStartPacket(
|
|||
DeviceExtension->MiniPortDeviceExtension);
|
||||
|
||||
/* 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 */
|
||||
return TRUE;
|
||||
|
@ -1096,7 +1069,7 @@ ScsiPortStartPacket(
|
|||
|
||||
/* If notification is needed, then request a DPC */
|
||||
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
|
||||
IoRequestDpc(DeviceExtension->DeviceObject, NULL, NULL);
|
||||
IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
@ -1140,10 +1113,9 @@ SpiSaveInterruptData(IN PVOID Context)
|
|||
/* Get SRB and LunExtension */
|
||||
Srb = SrbInfo->Srb;
|
||||
|
||||
LunExtension = SpiGetLunExtension(DeviceExtension,
|
||||
Srb->PathId,
|
||||
Srb->TargetId,
|
||||
Srb->Lun);
|
||||
PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Srb->OriginalRequest);
|
||||
LunExtension = IoStack->DeviceObject->DeviceExtension;
|
||||
ASSERT(LunExtension && !LunExtension->Common.IsFDO);
|
||||
|
||||
/* We have to check special cases if request is unsuccessful*/
|
||||
if (Srb->SrbStatus != SRB_STATUS_SUCCESS)
|
||||
|
@ -1359,7 +1331,7 @@ TryAgain:
|
|||
|
||||
/* If we ready for next packet, start it */
|
||||
if (InterruptData.Flags & SCSI_PORT_NEXT_REQUEST_READY)
|
||||
IoStartNextPacket(DeviceExtension->DeviceObject, FALSE);
|
||||
IoStartNextPacket(DeviceExtension->Common.DeviceObject, FALSE);
|
||||
|
||||
NeedToStartIo = FALSE;
|
||||
|
||||
|
@ -1456,11 +1428,7 @@ SpiAllocateSrbStructures(
|
|||
/* Treat the abort request in a special way */
|
||||
if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND)
|
||||
{
|
||||
SrbInfo = SpiGetSrbData(DeviceExtension,
|
||||
Srb->PathId,
|
||||
Srb->TargetId,
|
||||
Srb->Lun,
|
||||
Srb->QueueTag);
|
||||
SrbInfo = SpiGetSrbData(DeviceExtension, LunExtension, Srb->QueueTag);
|
||||
}
|
||||
else if (Srb->SrbFlags &
|
||||
(SRB_FLAGS_QUEUE_ACTION_ENABLE | SRB_FLAGS_NO_QUEUE_FREEZE) &&
|
||||
|
@ -1606,20 +1574,18 @@ ScsiPortStartIo(
|
|||
|
||||
DeviceExtension = DeviceObject->DeviceExtension;
|
||||
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;
|
||||
|
||||
/* Apply "default" flags */
|
||||
Srb->SrbFlags |= DeviceExtension->SrbFlags;
|
||||
|
||||
/* Get LUN extension */
|
||||
LunExtension = SpiGetLunExtension(DeviceExtension,
|
||||
Srb->PathId,
|
||||
Srb->TargetId,
|
||||
Srb->Lun);
|
||||
|
||||
if (DeviceExtension->NeedSrbDataAlloc ||
|
||||
DeviceExtension->NeedSrbExtensionAlloc)
|
||||
{
|
||||
|
@ -1699,7 +1665,7 @@ ScsiPortStartIo(
|
|||
|
||||
/* Allocate adapter channel */
|
||||
Status = IoAllocateAdapterChannel(DeviceExtension->AdapterObject,
|
||||
DeviceExtension->DeviceObject,
|
||||
DeviceExtension->Common.DeviceObject,
|
||||
SrbInfo->NumberOfMapRegisters,
|
||||
SpiAdapterControl,
|
||||
SrbInfo);
|
||||
|
@ -1717,7 +1683,7 @@ ScsiPortStartIo(
|
|||
DeviceExtension + 1);
|
||||
|
||||
/* Request DPC for that work */
|
||||
IoRequestDpc(DeviceExtension->DeviceObject, NULL, NULL);
|
||||
IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Control goes to SpiAdapterControl */
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* PURPOSE: Main and exported functions
|
||||
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
||||
* Aleksey Bragin (aleksey@reactos.org)
|
||||
* 2020 Victor Perevertkin (victor.perevertkin@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
@ -112,8 +113,43 @@ NTSTATUS NTAPI
|
|||
DriverEntry(IN PDRIVER_OBJECT DriverObject,
|
||||
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_REQUEST_BLOCK_INFO SrbInfo;
|
||||
PLIST_ENTRY ListEntry;
|
||||
ULONG BusNumber;
|
||||
ULONG Target;
|
||||
|
||||
DPRINT("ScsiPortCompleteRequest() called\n");
|
||||
|
||||
|
@ -212,60 +246,56 @@ ScsiPortCompleteRequest(IN PVOID HwDeviceExtension,
|
|||
MiniPortDeviceExtension);
|
||||
|
||||
/* Go through all buses */
|
||||
for (BusNumber = 0; BusNumber < 8; BusNumber++)
|
||||
for (UINT8 pathId = 0; pathId < DeviceExtension->NumberOfBuses; pathId++)
|
||||
{
|
||||
/* Go through all targets */
|
||||
for (Target = 0; Target < DeviceExtension->MaxTargedIds; Target++)
|
||||
PSCSI_BUS_INFO bus = &DeviceExtension->Buses[pathId];
|
||||
|
||||
/* Go through all logical units */
|
||||
for (PLIST_ENTRY lunEntry = bus->LunsListHead.Flink;
|
||||
lunEntry != &bus->LunsListHead;
|
||||
lunEntry = lunEntry->Flink)
|
||||
{
|
||||
/* Get logical unit list head */
|
||||
LunExtension = DeviceExtension->LunExtensionList[Target % 8];
|
||||
LunExtension = CONTAINING_RECORD(lunEntry, SCSI_PORT_LUN_EXTENSION, LunEntry);
|
||||
|
||||
/* Go through all logical units */
|
||||
while (LunExtension)
|
||||
/* Now match what caller asked with what we are at now */
|
||||
if ((PathId == SP_UNTAGGED || PathId == LunExtension->PathId) &&
|
||||
(TargetId == SP_UNTAGGED || TargetId == LunExtension->TargetId) &&
|
||||
(Lun == SP_UNTAGGED || Lun == LunExtension->Lun))
|
||||
{
|
||||
/* Now match what caller asked with what we are at now */
|
||||
if ((PathId == SP_UNTAGGED || PathId == LunExtension->PathId) &&
|
||||
(TargetId == SP_UNTAGGED || TargetId == LunExtension->TargetId) &&
|
||||
(Lun == SP_UNTAGGED || Lun == LunExtension->Lun))
|
||||
/* Yes, that's what caller asked for. Complete abort requests */
|
||||
if (LunExtension->CompletedAbortRequests)
|
||||
{
|
||||
/* Yes, that's what caller asked for. Complete abort requests */
|
||||
if (LunExtension->CompletedAbortRequests)
|
||||
{
|
||||
/* TODO: Save SrbStatus in this request */
|
||||
DPRINT1("Completing abort request without setting SrbStatus!\n");
|
||||
/* TODO: Save SrbStatus in this request */
|
||||
DPRINT1("Completing abort request without setting SrbStatus!\n");
|
||||
|
||||
/* Issue a notification request */
|
||||
ScsiPortNotification(RequestComplete,
|
||||
HwDeviceExtension,
|
||||
LunExtension->CompletedAbortRequests);
|
||||
}
|
||||
|
||||
/* Complete the request using our helper */
|
||||
SpiCompleteRequest(HwDeviceExtension,
|
||||
&LunExtension->SrbInfo,
|
||||
SrbStatus);
|
||||
|
||||
/* Go through the queue and complete everything there too */
|
||||
ListEntry = LunExtension->SrbInfo.Requests.Flink;
|
||||
while (ListEntry != &LunExtension->SrbInfo.Requests)
|
||||
{
|
||||
/* Get the actual SRB info entry */
|
||||
SrbInfo = CONTAINING_RECORD(ListEntry,
|
||||
SCSI_REQUEST_BLOCK_INFO,
|
||||
Requests);
|
||||
|
||||
/* Complete it */
|
||||
SpiCompleteRequest(HwDeviceExtension,
|
||||
SrbInfo,
|
||||
SrbStatus);
|
||||
|
||||
/* Advance to the next request in queue */
|
||||
ListEntry = SrbInfo->Requests.Flink;
|
||||
}
|
||||
/* Issue a notification request */
|
||||
ScsiPortNotification(RequestComplete,
|
||||
HwDeviceExtension,
|
||||
LunExtension->CompletedAbortRequests);
|
||||
}
|
||||
|
||||
/* Advance to the next one */
|
||||
LunExtension = LunExtension->Next;
|
||||
/* Complete the request using our helper */
|
||||
SpiCompleteRequest(HwDeviceExtension,
|
||||
&LunExtension->SrbInfo,
|
||||
SrbStatus);
|
||||
|
||||
/* Go through the queue and complete everything there too */
|
||||
ListEntry = LunExtension->SrbInfo.Requests.Flink;
|
||||
while (ListEntry != &LunExtension->SrbInfo.Requests)
|
||||
{
|
||||
/* Get the actual SRB info entry */
|
||||
SrbInfo = CONTAINING_RECORD(ListEntry,
|
||||
SCSI_REQUEST_BLOCK_INFO,
|
||||
Requests);
|
||||
|
||||
/* Complete it */
|
||||
SpiCompleteRequest(HwDeviceExtension,
|
||||
SrbInfo,
|
||||
SrbStatus);
|
||||
|
||||
/* Advance to the next request in queue */
|
||||
ListEntry = SrbInfo->Requests.Flink;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -468,10 +498,8 @@ ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
LunExtension = SpiGetLunExtension(DeviceExtension,
|
||||
PathId,
|
||||
TargetId,
|
||||
Lun);
|
||||
LunExtension = GetLunByPath(DeviceExtension, PathId, TargetId, Lun);
|
||||
|
||||
/* Check that the logical unit exists */
|
||||
if (!LunExtension)
|
||||
{
|
||||
|
@ -517,12 +545,12 @@ ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
|
|||
}
|
||||
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 */
|
||||
SrbInfo = SpiGetSrbData(DeviceExtension,
|
||||
Srb->PathId,
|
||||
Srb->TargetId,
|
||||
Srb->Lun,
|
||||
Srb->QueueTag);
|
||||
SrbInfo = SpiGetSrbData(DeviceExtension, LunExtension, Srb->QueueTag);
|
||||
|
||||
SGList = SrbInfo->ScatterGather;
|
||||
|
||||
|
@ -816,7 +844,6 @@ ScsiPortInitialize(
|
|||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = NULL;
|
||||
PCONFIGURATION_INFORMATION SystemConfig;
|
||||
PPORT_CONFIGURATION_INFORMATION PortConfig;
|
||||
PORT_CONFIGURATION_INFORMATION InitialPortConfig;
|
||||
CONFIGURATION_INFO ConfigInfo;
|
||||
ULONG DeviceExtensionSize;
|
||||
ULONG PortConfigSize;
|
||||
|
@ -829,16 +856,10 @@ ScsiPortInitialize(
|
|||
PCI_SLOT_NUMBER SlotNumber;
|
||||
|
||||
PDEVICE_OBJECT PortDeviceObject;
|
||||
WCHAR NameBuffer[80];
|
||||
UNICODE_STRING DeviceName;
|
||||
WCHAR DosNameBuffer[80];
|
||||
UNICODE_STRING DosDeviceName;
|
||||
PIO_SCSI_CAPABILITIES PortCapabilities;
|
||||
|
||||
PCM_RESOURCE_LIST ResourceList;
|
||||
BOOLEAN Conflict;
|
||||
SIZE_T BusConfigSize;
|
||||
|
||||
|
||||
DPRINT ("ScsiPortInitialize() called!\n");
|
||||
|
||||
|
@ -849,15 +870,46 @@ ScsiPortInitialize(
|
|||
(HwInitializationData->HwFindAdapter == 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 */
|
||||
DriverObject->DriverUnload = ScsiPortUnload;
|
||||
DriverObject->DriverStartIo = ScsiPortStartIo;
|
||||
DriverObject->DriverExtension->AddDevice = ScsiPortAddDevice;
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = ScsiPortDispatchPnp;
|
||||
DriverObject->MajorFunction[IRP_MJ_POWER] = ScsiPortDispatchPower;
|
||||
|
||||
/* Obtain configuration information */
|
||||
SystemConfig = IoGetConfigurationInformation();
|
||||
|
@ -880,8 +932,11 @@ ScsiPortInitialize(
|
|||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Open registry keys */
|
||||
SpiInitOpenKeys(&ConfigInfo, (PUNICODE_STRING)Argument2);
|
||||
/* Open registry keys and fill the driverExtension */
|
||||
SpiInitOpenKeys(&ConfigInfo, driverExtension);
|
||||
|
||||
// FIXME: PnP miniports are not supported
|
||||
ASSERT(driverExtension->IsLegacyDriver);
|
||||
|
||||
/* Last adapter number = not known */
|
||||
ConfigInfo.LastAdapterNumber = SP_UNINITIALIZED_VALUE;
|
||||
|
@ -895,11 +950,18 @@ ScsiPortInitialize(
|
|||
|
||||
while (TRUE)
|
||||
{
|
||||
WCHAR NameBuffer[27];
|
||||
/* Create a unicode device name */
|
||||
swprintf(NameBuffer,
|
||||
L"\\Device\\ScsiPort%lu",
|
||||
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);
|
||||
|
||||
|
@ -908,7 +970,7 @@ ScsiPortInitialize(
|
|||
DeviceExtensionSize,
|
||||
&DeviceName,
|
||||
FILE_DEVICE_CONTROLLER,
|
||||
0,
|
||||
FILE_DEVICE_SECURE_OPEN,
|
||||
FALSE,
|
||||
&PortDeviceObject);
|
||||
|
||||
|
@ -919,7 +981,7 @@ ScsiPortInitialize(
|
|||
break;
|
||||
}
|
||||
|
||||
DPRINT ("Created device: %wZ (%p)\n", &DeviceName, PortDeviceObject);
|
||||
DPRINT1("Created device: %wZ (%p)\n", &DeviceName, PortDeviceObject);
|
||||
|
||||
/* Set the buffering strategy here... */
|
||||
PortDeviceObject->Flags |= DO_DIRECT_IO;
|
||||
|
@ -928,9 +990,11 @@ ScsiPortInitialize(
|
|||
/* Fill Device Extension */
|
||||
DeviceExtension = PortDeviceObject->DeviceExtension;
|
||||
RtlZeroMemory(DeviceExtension, DeviceExtensionSize);
|
||||
DeviceExtension->Common.DeviceObject = PortDeviceObject;
|
||||
DeviceExtension->Common.IsFDO = TRUE;
|
||||
DeviceExtension->Length = DeviceExtensionSize;
|
||||
DeviceExtension->DeviceObject = PortDeviceObject;
|
||||
DeviceExtension->PortNumber = SystemConfig->ScsiPortCount;
|
||||
DeviceExtension->DeviceName = DeviceName;
|
||||
|
||||
/* Driver's routines... */
|
||||
DeviceExtension->HwInitialize = HwInitializationData->HwInitialize;
|
||||
|
@ -941,13 +1005,10 @@ ScsiPortInitialize(
|
|||
|
||||
/* Extensions sizes */
|
||||
DeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize;
|
||||
DeviceExtension->LunExtensionSize = HwInitializationData->SpecificLuExtensionSize;
|
||||
DeviceExtension->SrbExtensionSize = HwInitializationData->SrbExtensionSize;
|
||||
|
||||
/* Round Srb extension size to the quadword */
|
||||
DeviceExtension->LunExtensionSize =
|
||||
ALIGN_UP(HwInitializationData->SpecificLuExtensionSize, INT64);
|
||||
DeviceExtension->SrbExtensionSize =
|
||||
~(sizeof(LONGLONG) - 1) & (DeviceExtension->SrbExtensionSize +
|
||||
sizeof(LONGLONG) - 1);
|
||||
ALIGN_UP(HwInitializationData->SrbExtensionSize, INT64);
|
||||
|
||||
/* Fill some numbers (bus count, lun count, etc) */
|
||||
DeviceExtension->MaxLunCount = SCSI_MAXIMUM_LOGICAL_UNITS;
|
||||
|
@ -975,22 +1036,10 @@ ScsiPortInitialize(
|
|||
|
||||
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 */
|
||||
PortConfigSize = (sizeof(PORT_CONFIGURATION_INFORMATION) +
|
||||
HwInitializationData->NumberOfAccessRanges *
|
||||
sizeof(ACCESS_RANGE) + 7) & ~7;
|
||||
PortConfigSize = sizeof(PORT_CONFIGURATION_INFORMATION) +
|
||||
HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE);
|
||||
PortConfigSize = ALIGN_UP(PortConfigSize, INT64);
|
||||
DeviceExtension->PortConfig = ExAllocatePoolWithTag(NonPagedPool, PortConfigSize, TAG_SCSIPORT);
|
||||
|
||||
/* Fail if failed */
|
||||
|
@ -1000,14 +1049,20 @@ CreatePortConfig:
|
|||
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;
|
||||
|
||||
/* Copy information here */
|
||||
RtlCopyMemory(PortConfig,
|
||||
&InitialPortConfig,
|
||||
sizeof(PORT_CONFIGURATION_INFORMATION));
|
||||
|
||||
|
||||
/* Copy extension sizes into the PortConfig */
|
||||
PortConfig->SpecificLuExtensionSize = DeviceExtension->LunExtensionSize;
|
||||
PortConfig->SrbExtensionSize = DeviceExtension->SrbExtensionSize;
|
||||
|
@ -1015,11 +1070,7 @@ CreatePortConfig:
|
|||
/* Initialize Access ranges */
|
||||
if (HwInitializationData->NumberOfAccessRanges != 0)
|
||||
{
|
||||
PortConfig->AccessRanges = (PVOID)(PortConfig+1);
|
||||
|
||||
/* Align to LONGLONG */
|
||||
PortConfig->AccessRanges = (PVOID)((ULONG_PTR)(PortConfig->AccessRanges) + 7);
|
||||
PortConfig->AccessRanges = (PVOID)((ULONG_PTR)(PortConfig->AccessRanges) & ~7);
|
||||
PortConfig->AccessRanges = ALIGN_UP_POINTER(PortConfig + 1, INT64);
|
||||
|
||||
/* Copy the data */
|
||||
RtlCopyMemory(PortConfig->AccessRanges,
|
||||
|
@ -1113,54 +1164,44 @@ CreatePortConfig:
|
|||
(PortConfig->SrbExtensionSize != DeviceExtension->SrbExtensionSize))
|
||||
{
|
||||
/* Set it (rounding to LONGLONG again) */
|
||||
DeviceExtension->SrbExtensionSize =
|
||||
(PortConfig->SrbExtensionSize + sizeof(LONGLONG)) & ~(sizeof(LONGLONG) - 1);
|
||||
DeviceExtension->SrbExtensionSize = ALIGN_UP(PortConfig->SrbExtensionSize, INT64);
|
||||
}
|
||||
|
||||
/* The same with LUN extension size */
|
||||
if (PortConfig->SpecificLuExtensionSize != DeviceExtension->LunExtensionSize)
|
||||
DeviceExtension->LunExtensionSize = PortConfig->SpecificLuExtensionSize;
|
||||
|
||||
if (!((HwInitializationData->AdapterInterfaceType == PCIBus) &&
|
||||
(HwInitializationData->VendorIdLength > 0) &&
|
||||
(HwInitializationData->VendorId != NULL) &&
|
||||
(HwInitializationData->DeviceIdLength > 0) &&
|
||||
(HwInitializationData->DeviceId != NULL)))
|
||||
/* Construct a resource list */
|
||||
ResourceList = SpiConfigToResource(DeviceExtension, PortConfig);
|
||||
|
||||
PDEVICE_OBJECT LowerPDO = NULL;
|
||||
|
||||
Status = IoReportDetectedDevice(DriverObject,
|
||||
HwInitializationData->AdapterInterfaceType,
|
||||
ConfigInfo.BusNumber,
|
||||
PortConfig->SlotNumber,
|
||||
ResourceList,
|
||||
NULL,
|
||||
TRUE,
|
||||
&LowerPDO);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Construct a resource list */
|
||||
ResourceList = SpiConfigToResource(DeviceExtension, PortConfig);
|
||||
|
||||
if (ResourceList)
|
||||
{
|
||||
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 */
|
||||
if (Conflict || (!NT_SUCCESS(Status)))
|
||||
{
|
||||
if (Conflict)
|
||||
Status = STATUS_CONFLICTING_ADDRESSES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
DPRINT1("IoReportDetectedDevice failed. Status: 0x%x\n", Status);
|
||||
__debugbreak();
|
||||
break;
|
||||
}
|
||||
|
||||
/* Reset the Conflict var */
|
||||
Conflict = FALSE;
|
||||
DeviceExtension->Common.LowerDevice = IoAttachDeviceToDeviceStack(PortDeviceObject, LowerPDO);
|
||||
|
||||
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 */
|
||||
if (PortConfig->MaximumNumberOfTargets > SCSI_MAXIMUM_TARGETS_PER_BUS)
|
||||
|
@ -1168,12 +1209,30 @@ CreatePortConfig:
|
|||
else
|
||||
DeviceExtension->MaxTargedIds = PortConfig->MaximumNumberOfTargets;
|
||||
|
||||
DeviceExtension->BusNum = PortConfig->NumberOfBuses;
|
||||
DeviceExtension->NumberOfBuses = PortConfig->NumberOfBuses;
|
||||
DeviceExtension->CachesData = PortConfig->CachesData;
|
||||
DeviceExtension->ReceiveEvent = PortConfig->ReceiveEvent;
|
||||
DeviceExtension->SupportsTaggedQueuing = PortConfig->TaggedQueuing;
|
||||
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 (ConfigInfo.DisableMultipleLun)
|
||||
DeviceExtension->MultipleReqsPerLun = PortConfig->MultipleRequestPerLu = FALSE;
|
||||
|
@ -1283,43 +1342,18 @@ CreatePortConfig:
|
|||
}
|
||||
}
|
||||
|
||||
CallHWInitialize(DeviceExtension);
|
||||
FdoCallHWInitialize(DeviceExtension);
|
||||
|
||||
/* Start our timer */
|
||||
IoStartTimer(PortDeviceObject);
|
||||
Status = FdoStartAdapter(DeviceExtension);
|
||||
|
||||
/* Initialize bus scanning information */
|
||||
BusConfigSize = FIELD_OFFSET(
|
||||
BUSES_CONFIGURATION_INFORMATION,
|
||||
BusScanInfo[DeviceExtension->PortConfig->NumberOfBuses]);
|
||||
DeviceExtension->BusesConfig =
|
||||
ExAllocatePoolWithTag(PagedPool, BusConfigSize, TAG_SCSIPORT);
|
||||
if (!DeviceExtension->BusesConfig)
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Out of resources!\n");
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
DPRINT1("Failed to start the legacy adapter. Status 0x%x\n", Status);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Zero it */
|
||||
RtlZeroMemory(DeviceExtension->BusesConfig, BusConfigSize);
|
||||
FdoScanAdapter(DeviceExtension);
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Increase adapter number and bus number respectively */
|
||||
|
@ -1334,7 +1368,10 @@ CreatePortConfig:
|
|||
}
|
||||
|
||||
/* Clean up the mess */
|
||||
SpiCleanupAfterInit(DeviceExtension);
|
||||
if (!NT_SUCCESS(Status) && PortDeviceObject)
|
||||
{
|
||||
FdoRemoveAdapter(DeviceExtension);
|
||||
}
|
||||
|
||||
/* Close registry keys */
|
||||
if (ConfigInfo.ServiceKey != NULL)
|
||||
|
@ -1461,9 +1498,12 @@ ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType, IN PVOID HwDevi
|
|||
}
|
||||
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 */
|
||||
SrbData = SpiGetSrbData(
|
||||
DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun, Srb->QueueTag);
|
||||
SrbData = SpiGetSrbData(DeviceExtension, LunExtension, Srb->QueueTag);
|
||||
|
||||
/* Make sure there are no CompletedRequests and there is a Srb */
|
||||
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;
|
||||
|
||||
/* Get the LUN extension */
|
||||
LunExtension = SpiGetLunExtension(DeviceExtension, PathId, TargetId, Lun);
|
||||
LunExtension = GetLunByPath(DeviceExtension, PathId, TargetId, Lun);
|
||||
|
||||
/* If returned LunExtension is NULL, break out */
|
||||
if (!LunExtension)
|
||||
|
@ -2104,7 +2144,7 @@ ScsiPortIsr(
|
|||
/* If flag of notification is set - queue a DPC */
|
||||
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
|
||||
{
|
||||
IoRequestDpc(DeviceExtension->DeviceObject,
|
||||
IoRequestDpc(DeviceExtension->Common.DeviceObject,
|
||||
DeviceExtension->CurrentIrp,
|
||||
DeviceExtension);
|
||||
}
|
||||
|
@ -2140,7 +2180,7 @@ SpiProcessTimeout(PVOID ServiceContext)
|
|||
{
|
||||
DPRINT("Resetting the bus\n");
|
||||
|
||||
for (Bus = 0; Bus < DeviceExtension->BusNum; Bus++)
|
||||
for (Bus = 0; Bus < DeviceExtension->NumberOfBuses; Bus++)
|
||||
{
|
||||
DeviceExtension->HwResetBus(DeviceExtension->MiniPortDeviceExtension, Bus);
|
||||
|
||||
|
@ -2151,7 +2191,7 @@ SpiProcessTimeout(PVOID ServiceContext)
|
|||
|
||||
/* If miniport requested - request a dpc for it */
|
||||
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
|
||||
IoRequestDpc(DeviceExtension->DeviceObject, NULL, NULL);
|
||||
IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -2176,7 +2216,7 @@ SpiResetBus(PVOID ServiceContext)
|
|||
|
||||
/* If miniport requested - give him a DPC */
|
||||
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
|
||||
IoRequestDpc(DeviceExtension->DeviceObject, NULL, NULL);
|
||||
IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -2198,7 +2238,6 @@ ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
|
|||
{
|
||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
||||
ULONG Lun;
|
||||
PIRP Irp;
|
||||
|
||||
DPRINT("ScsiPortIoTimer()\n");
|
||||
|
@ -2219,7 +2258,7 @@ ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
|
|||
/* Timeout, process it */
|
||||
if (KeSynchronizeExecution(DeviceExtension->Interrupt[0],
|
||||
SpiProcessTimeout,
|
||||
DeviceExtension->DeviceObject))
|
||||
DeviceExtension->Common.DeviceObject))
|
||||
{
|
||||
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... */
|
||||
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 &
|
||||
|
@ -2283,8 +2326,6 @@ ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
|
|||
/* Decrement the timeout counter */
|
||||
LunExtension->RequestTimeout--;
|
||||
}
|
||||
|
||||
LunExtension = LunExtension->Next;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2320,7 +2361,7 @@ SpiMiniportTimerDpc(IN struct _KDPC *Dpc,
|
|||
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
|
||||
{
|
||||
ScsiPortDpcForIsr(NULL,
|
||||
DeviceExtension->DeviceObject,
|
||||
DeviceExtension->Common.DeviceObject,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
@ -2398,8 +2439,8 @@ TryNextAd:
|
|||
{
|
||||
/* Open registry key for HW database */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
DeviceExtension->DeviceObject->DriverObject->HardwareDatabase,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
DeviceExtension->Common.DeviceObject->DriverObject->HardwareDatabase,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
|
@ -2418,7 +2459,7 @@ TryNextAd:
|
|||
/* Open device key */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&UnicodeString,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
RootKey,
|
||||
NULL);
|
||||
|
||||
|
@ -2479,7 +2520,7 @@ TryNextAd:
|
|||
/* Open the service key */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&UnicodeString,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
InternalConfigInfo->ServiceKey,
|
||||
NULL);
|
||||
|
||||
|
@ -3012,5 +3053,3 @@ ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address)
|
|||
DPRINT("ScsiPortConvertPhysicalAddressToUlong()\n");
|
||||
return(Address.u.LowPart);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -7,15 +7,16 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <wdm.h>
|
||||
#include <ntddk.h>
|
||||
#include <ntifs.h>
|
||||
#include <stdio.h>
|
||||
#include <scsi.h>
|
||||
#include <ntddscsi.h>
|
||||
#include <ntdddisk.h>
|
||||
#include <mountdev.h>
|
||||
|
||||
#define VERSION "0.0.3"
|
||||
#ifdef DBG
|
||||
#include <debug/driverdbg.h>
|
||||
#endif
|
||||
|
||||
#define TAG_SCSIPORT 'ISCS'
|
||||
|
||||
|
@ -25,29 +26,29 @@
|
|||
#define MAX_SG_LIST 17
|
||||
|
||||
/* Flags */
|
||||
#define SCSI_PORT_DEVICE_BUSY 0x0001
|
||||
#define SCSI_PORT_LU_ACTIVE 0x0002
|
||||
#define SCSI_PORT_NOTIFICATION_NEEDED 0x0004
|
||||
#define SCSI_PORT_NEXT_REQUEST_READY 0x0008
|
||||
#define SCSI_PORT_FLUSH_ADAPTERS 0x0010
|
||||
#define SCSI_PORT_MAP_TRANSFER 0x0020
|
||||
#define SCSI_PORT_RESET 0x0080
|
||||
#define SCSI_PORT_RESET_REQUEST 0x0100
|
||||
#define SCSI_PORT_RESET_REPORTED 0x0200
|
||||
#define SCSI_PORT_REQUEST_PENDING 0x0800
|
||||
#define SCSI_PORT_DISCONNECT_ALLOWED 0x1000
|
||||
#define SCSI_PORT_DISABLE_INT_REQUESET 0x2000
|
||||
#define SCSI_PORT_DISABLE_INTERRUPTS 0x4000
|
||||
#define SCSI_PORT_ENABLE_INT_REQUEST 0x8000
|
||||
#define SCSI_PORT_TIMER_NEEDED 0x10000
|
||||
#define SCSI_PORT_DEVICE_BUSY 0x00001
|
||||
#define SCSI_PORT_LU_ACTIVE 0x00002
|
||||
#define SCSI_PORT_NOTIFICATION_NEEDED 0x00004
|
||||
#define SCSI_PORT_NEXT_REQUEST_READY 0x00008
|
||||
#define SCSI_PORT_FLUSH_ADAPTERS 0x00010
|
||||
#define SCSI_PORT_MAP_TRANSFER 0x00020
|
||||
#define SCSI_PORT_RESET 0x00080
|
||||
#define SCSI_PORT_RESET_REQUEST 0x00100
|
||||
#define SCSI_PORT_RESET_REPORTED 0x00200
|
||||
#define SCSI_PORT_REQUEST_PENDING 0x00800
|
||||
#define SCSI_PORT_DISCONNECT_ALLOWED 0x01000
|
||||
#define SCSI_PORT_DISABLE_INT_REQUESET 0x02000
|
||||
#define SCSI_PORT_DISABLE_INTERRUPTS 0x04000
|
||||
#define SCSI_PORT_ENABLE_INT_REQUEST 0x08000
|
||||
#define SCSI_PORT_TIMER_NEEDED 0x10000
|
||||
|
||||
/* LUN Extension flags*/
|
||||
#define LUNEX_FROZEN_QUEUE 0x0001
|
||||
#define LUNEX_NEED_REQUEST_SENSE 0x0004
|
||||
#define LUNEX_BUSY 0x0008
|
||||
#define LUNEX_FULL_QUEUE 0x0010
|
||||
#define LUNEX_REQUEST_PENDING 0x0020
|
||||
#define SCSI_PORT_SCAN_IN_PROGRESS 0x8000
|
||||
#define LUNEX_FROZEN_QUEUE 0x0001
|
||||
#define LUNEX_NEED_REQUEST_SENSE 0x0004
|
||||
#define LUNEX_BUSY 0x0008
|
||||
#define LUNEX_FULL_QUEUE 0x0010
|
||||
#define LUNEX_REQUEST_PENDING 0x0020
|
||||
#define SCSI_PORT_SCAN_IN_PROGRESS 0x8000
|
||||
|
||||
|
||||
typedef enum _SCSI_PORT_TIMER_STATES
|
||||
|
@ -115,18 +116,27 @@ typedef struct _SCSI_REQUEST_BLOCK_INFO
|
|||
SCSI_SG_ADDRESS ScatterGatherList[MAX_SG_LIST];
|
||||
} 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
|
||||
{
|
||||
SCSI_PORT_COMMON_EXTENSION Common;
|
||||
|
||||
UCHAR PathId;
|
||||
UCHAR TargetId;
|
||||
UCHAR Lun;
|
||||
|
||||
ULONG Flags;
|
||||
|
||||
struct _SCSI_PORT_LUN_EXTENSION *Next;
|
||||
LIST_ENTRY LunEntry;
|
||||
|
||||
BOOLEAN DeviceClaimed;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
|
||||
INQUIRYDATA InquiryData;
|
||||
|
||||
|
@ -146,6 +156,8 @@ typedef struct _SCSI_PORT_LUN_EXTENSION
|
|||
|
||||
SCSI_REQUEST_BLOCK_INFO SrbInfo;
|
||||
|
||||
HANDLE RegistryMapKey;
|
||||
|
||||
/* More data? */
|
||||
|
||||
UCHAR MiniportLunExtension[1]; /* must be the last entry */
|
||||
|
@ -153,31 +165,14 @@ typedef struct _SCSI_PORT_LUN_EXTENSION
|
|||
|
||||
/* Structures for inquiries support */
|
||||
|
||||
typedef struct _SCSI_LUN_INFO
|
||||
typedef struct _SCSI_BUS_INFO
|
||||
{
|
||||
UCHAR PathId;
|
||||
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;
|
||||
LIST_ENTRY LunsListHead;
|
||||
UCHAR LogicalUnitsCount;
|
||||
UCHAR TargetsCount;
|
||||
UCHAR BusIdentifier;
|
||||
PSCSI_LUN_INFO LunInfo;
|
||||
} SCSI_BUS_SCAN_INFO, *PSCSI_BUS_SCAN_INFO;
|
||||
|
||||
typedef struct _BUSES_CONFIGURATION_INFORMATION
|
||||
{
|
||||
UCHAR NumberOfBuses;
|
||||
PSCSI_BUS_SCAN_INFO BusScanInfo[1];
|
||||
} BUSES_CONFIGURATION_INFORMATION, *PBUSES_CONFIGURATION_INFORMATION;
|
||||
|
||||
HANDLE RegistryMapKey;
|
||||
} SCSI_BUS_INFO, *PSCSI_BUS_INFO;
|
||||
|
||||
typedef struct _SCSI_PORT_INTERRUPT_DATA
|
||||
{
|
||||
|
@ -201,16 +196,19 @@ typedef struct _SCSI_PORT_SAVE_INTERRUPT
|
|||
* SCSI_PORT_DEVICE_EXTENSION
|
||||
*
|
||||
* DESCRIPTION
|
||||
* First part of the port objects device extension. The second
|
||||
* part is the miniport-specific device extension.
|
||||
* First part of the port objects device extension. The second
|
||||
* part is the miniport-specific device extension.
|
||||
*/
|
||||
|
||||
// FDO
|
||||
typedef struct _SCSI_PORT_DEVICE_EXTENSION
|
||||
{
|
||||
SCSI_PORT_COMMON_EXTENSION Common;
|
||||
|
||||
ULONG Length;
|
||||
ULONG MiniPortExtensionSize;
|
||||
PPORT_CONFIGURATION_INFORMATION PortConfig;
|
||||
PBUSES_CONFIGURATION_INFORMATION BusesConfig;
|
||||
PSCSI_BUS_INFO Buses; // children LUNs are stored here
|
||||
PVOID NonCachedExtension;
|
||||
ULONG PortNumber;
|
||||
|
||||
|
@ -218,7 +216,7 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
|
|||
ULONG SrbFlags;
|
||||
ULONG Flags;
|
||||
|
||||
ULONG BusNum;
|
||||
UCHAR NumberOfBuses;
|
||||
ULONG MaxTargedIds;
|
||||
ULONG MaxLunCount;
|
||||
|
||||
|
@ -238,7 +236,6 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
|
|||
PMAPPED_ADDRESS MappedAddressList;
|
||||
|
||||
ULONG LunExtensionSize;
|
||||
PSCSI_PORT_LUN_EXTENSION LunExtensionList[LUS_NUMBER];
|
||||
|
||||
SCSI_PORT_INTERRUPT_DATA InterruptData;
|
||||
|
||||
|
@ -254,7 +251,6 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
|
|||
|
||||
IO_SCSI_CAPABILITIES PortCapabilities;
|
||||
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PCONTROLLER_OBJECT ControllerObject;
|
||||
|
||||
PHW_INITIALIZE HwInitialize;
|
||||
|
@ -294,6 +290,11 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
|
|||
|
||||
ULONG InterruptCount;
|
||||
|
||||
UNICODE_STRING DeviceName;
|
||||
UNICODE_STRING InterfaceName;
|
||||
BOOLEAN DeviceStarted;
|
||||
UINT8 TotalLUCount;
|
||||
|
||||
UCHAR MiniPortDeviceExtension[1]; /* must be the last entry */
|
||||
} SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION;
|
||||
|
||||
|
@ -303,6 +304,42 @@ typedef struct _RESETBUS_PARAMS
|
|||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
||||
} 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
|
||||
|
||||
|
@ -315,25 +352,34 @@ ScsiPortDeviceControl(
|
|||
// fdo.c
|
||||
|
||||
VOID
|
||||
SpiScanAdapter(
|
||||
FdoScanAdapter(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
||||
|
||||
NTSTATUS
|
||||
CallHWInitialize(
|
||||
FdoCallHWInitialize(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
||||
|
||||
VOID
|
||||
SpiCleanupAfterInit(
|
||||
NTSTATUS
|
||||
FdoRemoveAdapter(
|
||||
_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
|
||||
|
||||
PSCSI_PORT_LUN_EXTENSION
|
||||
SpiAllocateLunExtension(
|
||||
PDEVICE_OBJECT
|
||||
PdoCreateLunDevice(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
||||
|
||||
PSCSI_PORT_LUN_EXTENSION
|
||||
SpiGetLunExtension(
|
||||
GetLunByPath(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
_In_ UCHAR PathId,
|
||||
_In_ UCHAR TargetId,
|
||||
|
@ -342,22 +388,32 @@ SpiGetLunExtension(
|
|||
PSCSI_REQUEST_BLOCK_INFO
|
||||
SpiGetSrbData(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
_In_ UCHAR PathId,
|
||||
_In_ UCHAR TargetId,
|
||||
_In_ UCHAR Lun,
|
||||
_In_ PSCSI_PORT_LUN_EXTENSION LunExtension,
|
||||
_In_ UCHAR QueueTag);
|
||||
|
||||
NTSTATUS
|
||||
PdoDispatchPnp(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_Inout_ PIRP Irp);
|
||||
|
||||
// power.c
|
||||
|
||||
DRIVER_DISPATCH ScsiPortDispatchPower;
|
||||
|
||||
// registry.c
|
||||
|
||||
VOID
|
||||
SpiInitOpenKeys(
|
||||
_Inout_ PCONFIGURATION_INFO ConfigInfo,
|
||||
_In_ PUNICODE_STRING RegistryPath);
|
||||
_In_ PSCSI_PORT_DRIVER_EXTENSION DriverExtension);
|
||||
|
||||
NTSTATUS
|
||||
SpiBuildDeviceMap(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
_In_ PUNICODE_STRING RegistryPath);
|
||||
RegistryInitAdapterKey(
|
||||
_Inout_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
||||
|
||||
NTSTATUS
|
||||
RegistryInitLunKey(
|
||||
_Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension);
|
||||
|
||||
// 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