https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a97c6e0aa92749a4c29f1…
commit a97c6e0aa92749a4c29f180e42a63d0fdec1d2d4
Author: Victor Perevertkin <victor.perevertkin(a)reactos.org>
AuthorDate: Wed Oct 28 02:42:56 2020 +0300
Commit: Victor Perevertkin <victor.perevertkin(a)reactos.org>
CommitDate: Sat Dec 5 22:28:54 2020 +0300
[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
---
drivers/storage/port/scsiport/CMakeLists.txt | 17 +-
drivers/storage/port/scsiport/fdo.c | 572 +++++++++++++------------
drivers/storage/port/scsiport/guid.c | 11 +
drivers/storage/port/scsiport/ioctl.c | 495 +++++++++++++++++-----
drivers/storage/port/scsiport/pdo.c | 595 ++++++++++++++++++++++++---
drivers/storage/port/scsiport/power.c | 41 ++
drivers/storage/port/scsiport/registry.c | 405 ++++++++----------
drivers/storage/port/scsiport/scsi.c | 204 ++++-----
drivers/storage/port/scsiport/scsiport.c | 425 ++++++++++---------
drivers/storage/port/scsiport/scsiport.h | 192 ++++++---
drivers/storage/port/scsiport/scsitypes.h | 124 ++++++
11 files changed, 2059 insertions(+), 1022 deletions(-)
diff --git a/drivers/storage/port/scsiport/CMakeLists.txt
b/drivers/storage/port/scsiport/CMakeLists.txt
index 13c4407e4d9..e0f3ce08a78 100644
--- a/drivers/storage/port/scsiport/CMakeLists.txt
+++ b/drivers/storage/port/scsiport/CMakeLists.txt
@@ -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)
diff --git a/drivers/storage/port/scsiport/fdo.c b/drivers/storage/port/scsiport/fdo.c
index 95a0f3b4ed5..2cc89ea7353 100644
--- a/drivers/storage/port/scsiport/fdo.c
+++ b/drivers/storage/port/scsiport/fdo.c
@@ -4,6 +4,7 @@
* PURPOSE: Adapter device object (FDO) support routines
* COPYRIGHT: Eric Kohl (eric.kohl(a)reactos.org)
* Aleksey Bragin (aleksey(a)reactos.org)
+ * 2020 Victor Perevertkin (victor.perevertkin(a)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)
+ if (targetId == currentBus->BusIdentifier)
continue;
- /* Try to find an existing device here */
- DeviceExists = FALSE;
- LunInfoExists = BusScanInfo->LunInfo;
-
- /* Find matching address on this bus */
- while (LunInfoExists)
+ /* Scan all logical units */
+ for (UINT8 lun = 0; lun < PortExtension->MaxLunCount; lun++)
{
- if (LunInfoExists->TargetId == Target)
+ // try to find an existing device
+ PSCSI_PORT_LUN_EXTENSION lunExt = GetLunByPath(PortExtension,
+ pathId,
+ targetId,
+ lun);
+
+ if (lunExt)
{
- DeviceExists = TRUE;
- break;
- }
+ // check if the device still exists
+ status = FdoSendInquiry(lunExt->Common.DeviceObject);
+ if (!NT_SUCCESS(status))
+ {
+ // remove the device
+ UNIMPLEMENTED;
+ __debugbreak();
+ }
- /* Advance to the next one */
- LunInfoExists = LunInfoExists->Next;
- }
+ if (lunExt->InquiryData.DeviceTypeQualifier ==
DEVICE_QUALIFIER_NOT_SUPPORTED)
+ {
+ // remove the device
+ UNIMPLEMENTED;
+ __debugbreak();
+ }
- /* No need to bother rescanning, since we already did that before */
- if (DeviceExists)
- continue;
+ /* Decide whether we are continuing or not */
+ if (status == STATUS_INVALID_DEVICE_REQUEST)
+ continue;
+ else
+ break;
+ }
- /* Scan all logical units */
- for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
- {
- if ((!LunExtension) || (!LunInfo))
- break;
+ // create a new LUN device
+ PDEVICE_OBJECT lunPDO = PdoCreateLunDevice(PortExtension);
+ if (!lunPDO)
+ {
+ continue;
+ }
- /* Add extension to the list */
- Hint = (Target + Lun) % LUS_NUMBER;
- LunExtension->Next = DeviceExtension->LunExtensionList[Hint];
- DeviceExtension->LunExtensionList[Hint] = LunExtension;
+ lunExt = lunPDO->DeviceExtension;
- /* Fill Path, Target, Lun fields */
- LunExtension->PathId = LunInfo->PathId = (UCHAR)Bus;
- LunExtension->TargetId = LunInfo->TargetId = (UCHAR)Target;
- LunExtension->Lun = LunInfo->Lun = (UCHAR)Lun;
+ lunExt->PathId = pathId;
+ lunExt->TargetId = targetId;
+ lunExt->Lun = lun;
- /* Set flag to prevent race conditions */
- LunExtension->Flags |= SCSI_PORT_SCAN_IN_PROGRESS;
+ DPRINT("Add PDO to list: PDO: %p, FDOExt: %p, PDOExt: %p\n",
lunPDO, PortExtension, lunExt);
- /* Zero LU extension contents */
- if (DeviceExtension->LunExtensionSize)
- {
- RtlZeroMemory(LunExtension + 1,
- DeviceExtension->LunExtensionSize);
- }
+ /* Set flag to prevent race conditions */
+ lunExt->Flags |= SCSI_PORT_SCAN_IN_PROGRESS;
/* Finally send the inquiry command */
- Status = SpiSendInquiry(DeviceExtension->DeviceObject, LunInfo);
+ status = FdoSendInquiry(lunPDO);
- if (NT_SUCCESS(Status))
+ 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;
-
- DPRINT("SpiScanAdapter(): Found device of type %d at bus %d tid
%d lun %d\n",
- InquiryData->DeviceType, Bus, Target, 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);
-
- /* Add this info to the linked list */
- LunInfo->Next = NULL;
- if (LastLunInfo)
- LastLunInfo->Next = LunInfo;
- else
- BusScanInfo->LunInfo = LunInfo;
+ lunExt->Flags &= ~SCSI_PORT_SCAN_IN_PROGRESS;
- /* Store the last LUN info */
- LastLunInfo = LunInfo;
+ DPRINT("FdoScanAdapter(): Found device of type %d at bus %d tid
%d lun %d\n",
+ InquiryData->DeviceType, pathId, targetId, lun);
- /* Store DeviceObject */
- LunInfo->DeviceObject = DeviceExtension->DeviceObject;
+ InsertTailList(¤tBus->LunsListHead,
&lunExt->LunEntry);
- /* 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);
+ DPRINT1("SCSIPORT: created lun device: %p Status: %x\n",
lunPDO, status);
- 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;
}
}
- }
-
- /* 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);
+ if (targetFound)
+ {
+ currentBus->TargetsCount++;
+ }
+ }
}
- 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);
+
+ // release device interface
+ if (DeviceExtension->InterfaceName.Buffer)
+ {
+ IoSetDeviceInterfaceState(&DeviceExtension->InterfaceName, FALSE);
+
+ RtlFreeUnicodeString(&DeviceExtension->InterfaceName);
+ RtlInitUnicodeString(&DeviceExtension->InterfaceName, NULL);
+ }
- /* Check if we have something to clean up */
- if (DeviceExtension == NULL)
- return;
+ // remove the dos device link
+ WCHAR dosNameBuffer[12];
+ UNICODE_STRING dosDeviceName;
- /* Stop the timer */
- IoStopTimer(DeviceExtension->DeviceObject);
+ 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 */
+ // 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);
+ }
+
+ 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);
}
- /* Finally delete the device object */
- DPRINT("Deleting device %p\n", DeviceExtension->DeviceObject);
- IoDeleteDevice(DeviceExtension->DeviceObject);
+ return status;
}
diff --git a/drivers/storage/port/scsiport/guid.c b/drivers/storage/port/scsiport/guid.c
new file mode 100644
index 00000000000..757901b4222
--- /dev/null
+++ b/drivers/storage/port/scsiport/guid.c
@@ -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 */
diff --git a/drivers/storage/port/scsiport/ioctl.c
b/drivers/storage/port/scsiport/ioctl.c
index 08de2260961..7346f7f3228 100644
--- a/drivers/storage/port/scsiport/ioctl.c
+++ b/drivers/storage/port/scsiport/ioctl.c
@@ -4,6 +4,7 @@
* PURPOSE: IOCTL handlers
* COPYRIGHT: Eric Kohl (eric.kohl(a)reactos.org)
* Aleksey Bragin (aleksey(a)reactos.org)
+ * 2020 Victor Perevertkin (victor.perevertkin(a)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");
+
+ if (!VerifyIrpInBufferSize(Irp, sizeof(STORAGE_PROPERTY_QUERY)))
+ {
+ status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ if (comExt->IsFDO)
+ return FdoHandleQueryProperty(DeviceObject, Irp);
+ else
+ return PdoHandleQueryProperty(DeviceObject, Irp);
}
+ case IOCTL_SCSI_GET_ADDRESS:
+ {
+ DPRINT(" IOCTL_SCSI_GET_ADDRESS\n");
- DumpPointers = Irp->AssociatedIrp.SystemBuffer;
- DumpPointers->DeviceObject = DeviceObject;
- /* More data.. ? */
+ if (comExt->IsFDO)
+ {
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ break;
+ }
- Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
- break;
+ PSCSI_ADDRESS address = Irp->AssociatedIrp.SystemBuffer;
+ if (!VerifyIrpOutBufferSize(Irp, sizeof(*address)))
+ {
+ status = STATUS_BUFFER_TOO_SMALL;
+ 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;
+ 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(PVOID);
- Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
+ status = STATUS_SUCCESS;
break;
}
-
- if (Stack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(IO_SCSI_CAPABILITIES))
+ case IOCTL_SCSI_GET_DUMP_POINTERS:
{
- Status = STATUS_BUFFER_TOO_SMALL;
+ 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");
- RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
- &DeviceExtension->PortCapabilities,
- sizeof(IO_SCSI_CAPABILITIES));
-
- Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
- Status = STATUS_SUCCESS;
- break;
+ if (!comExt->IsFDO)
+ {
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ break;
+ }
- case IOCTL_SCSI_GET_INQUIRY_DATA:
- DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
+ if (!VerifyIrpOutBufferSize(Irp, sizeof(IO_SCSI_CAPABILITIES)))
+ {
+ status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
- /* Copy inquiry data to the port device extension */
- Status = SpiGetInquiryData(DeviceExtension, Irp);
- break;
+ portExt = DeviceObject->DeviceExtension;
- case IOCTL_SCSI_MINIPORT:
- DPRINT1("IOCTL_SCSI_MINIPORT unimplemented!\n");
- Status = STATUS_NOT_IMPLEMENTED;
- break;
+ RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
+ &portExt->PortCapabilities,
+ sizeof(IO_SCSI_CAPABILITIES));
- case IOCTL_SCSI_PASS_THROUGH:
- DPRINT1("IOCTL_SCSI_PASS_THROUGH unimplemented!\n");
- Status = STATUS_NOT_IMPLEMENTED;
- break;
+ status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
+ break;
+ }
+ case IOCTL_SCSI_GET_INQUIRY_DATA:
+ {
+ DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
- default:
- if
(DEVICE_TYPE_FROM_CTL_CODE(Stack->Parameters.DeviceIoControl.IoControlCode) ==
MOUNTDEVCONTROLTYPE)
- {
- switch (Stack->Parameters.DeviceIoControl.IoControlCode)
+ if (!comExt->IsFDO)
{
- 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_INVALID_DEVICE_REQUEST;
break;
}
- } else {
- DPRINT1(" unknown ioctl code: 0x%lX\n",
Stack->Parameters.DeviceIoControl.IoControlCode);
- }
- Status = STATUS_NOT_IMPLEMENTED;
- 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;
}
diff --git a/drivers/storage/port/scsiport/pdo.c b/drivers/storage/port/scsiport/pdo.c
index 7365f42e443..182f2b029ec 100644
--- a/drivers/storage/port/scsiport/pdo.c
+++ b/drivers/storage/port/scsiport/pdo.c
@@ -4,40 +4,48 @@
* PURPOSE: Logical Unit (PDO) functions
* COPYRIGHT: Eric Kohl (eric.kohl(a)reactos.org)
* Aleksey Bragin (aleksey(a)reactos.org)
+ * 2020 Victor Perevertkin (victor.perevertkin(a)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;
-
- DPRINT("SpiAllocateLunExtension(%p)\n", DeviceExtension);
+ PDEVICE_OBJECT LunPDO;
- /* Round LunExtensionSize first to the sizeof LONGLONG */
- LunExtensionSize = (DeviceExtension->LunExtensionSize +
- sizeof(LONGLONG) - 1) & ~(sizeof(LONGLONG) - 1);
+ ULONG LunExtensionSize = DeviceExtension->LunExtensionSize +
sizeof(SCSI_PORT_LUN_EXTENSION);
- LunExtensionSize += sizeof(SCSI_PORT_LUN_EXTENSION);
- DPRINT("LunExtensionSize %lu\n", LunExtensionSize);
+ NTSTATUS Status =
IoCreateDevice(DeviceExtension->Common.DeviceObject->DriverObject,
+ LunExtensionSize,
+ NULL,
+ FILE_DEVICE_DISK,
+ FILE_AUTOGENERATED_DEVICE_NAME |
FILE_DEVICE_SECURE_OPEN,
+ FALSE,
+ &LunPDO);
- 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);
+ if (PathId >= DeviceExtension->NumberOfBuses)
+ {
+ DPRINT1("Invalid PathId: %u\n", PathId);
+ return NULL;
+ }
- /* Get appropriate list */
- LunExtension = DeviceExtension->LunExtensionList[(TargetId + Lun) % LUS_NUMBER];
+ PSCSI_BUS_INFO bus = &DeviceExtension->Buses[PathId];
- /* Iterate it until we find what we need */
- while (LunExtension)
+ for (PLIST_ENTRY lunEntry = bus->LunsListHead.Flink;
+ lunEntry != &bus->LunsListHead;
+ lunEntry = lunEntry->Flink)
{
- if (LunExtension->TargetId == TargetId &&
- LunExtension->Lun == Lun &&
- LunExtension->PathId == PathId)
+ PSCSI_PORT_LUN_EXTENSION lunExt =
+ CONTAINING_RECORD(lunEntry, SCSI_PORT_LUN_EXTENSION, LunEntry);
+
+ if (lunExt->PathId == PathId &&
+ lunExt->TargetId == TargetId &&
+ lunExt->Lun == Lun)
{
- /* All matches, return */
- return LunExtension;
+ return lunExt;
}
-
- /* Advance to the next item */
- LunExtension = LunExtension->Next;
}
- /* We did not find anything */
- DPRINT("Nothing found\n");
+ 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;
+}
diff --git a/drivers/storage/port/scsiport/power.c
b/drivers/storage/port/scsiport/power.c
new file mode 100644
index 00000000000..b3c7b4ce89a
--- /dev/null
+++ b/drivers/storage/port/scsiport/power.c
@@ -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(a)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;
+ }
+}
diff --git a/drivers/storage/port/scsiport/registry.c
b/drivers/storage/port/scsiport/registry.c
index 5deaf85c8e9..3b9e235d752 100644
--- a/drivers/storage/port/scsiport/registry.c
+++ b/drivers/storage/port/scsiport/registry.c
@@ -4,9 +4,11 @@
* PURPOSE: Registry operations
* COPYRIGHT: Eric Kohl (eric.kohl(a)reactos.org)
* Aleksey Bragin (aleksey(a)reactos.org)
+ * 2020 Victor Perevertkin (victor.perevertkin(a)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/identifie…
- * and
https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifie…
- * 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;
+}
diff --git a/drivers/storage/port/scsiport/scsi.c b/drivers/storage/port/scsiport/scsi.c
index 7feb6da5cdf..29b683d10c0 100644
--- a/drivers/storage/port/scsiport/scsi.c
+++ b/drivers/storage/port/scsiport/scsi.c
@@ -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 */
diff --git a/drivers/storage/port/scsiport/scsiport.c
b/drivers/storage/port/scsiport/scsiport.c
index 1f527947d25..8e6e3e3c198 100644
--- a/drivers/storage/port/scsiport/scsiport.c
+++ b/drivers/storage/port/scsiport/scsiport.c
@@ -4,6 +4,7 @@
* PURPOSE: Main and exported functions
* COPYRIGHT: Eric Kohl (eric.kohl(a)reactos.org)
* Aleksey Bragin (aleksey(a)reactos.org)
+ * 2020 Victor Perevertkin (victor.perevertkin(a)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);
- }
+ /* Issue a notification request */
+ ScsiPortNotification(RequestComplete,
+ HwDeviceExtension,
+ LunExtension->CompletedAbortRequests);
+ }
+
+ /* Complete the request using our helper */
+ SpiCompleteRequest(HwDeviceExtension,
+ &LunExtension->SrbInfo,
+ SrbStatus);
- /* Complete the request using our helper */
+ /* 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,
- &LunExtension->SrbInfo,
+ 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;
- }
+ /* Advance to the next request in queue */
+ ListEntry = SrbInfo->Requests.Flink;
}
-
- /* Advance to the next one */
- LunExtension = LunExtension->Next;
}
}
}
@@ -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,13 +1049,19 @@ CreatePortConfig:
break;
}
- PortConfig = DeviceExtension->PortConfig;
+ Status = SpiCreatePortConfig(DeviceExtension,
+ HwInitializationData,
+ &ConfigInfo,
+ DeviceExtension->PortConfig,
+ FirstConfigCall);
- /* Copy information here */
- RtlCopyMemory(PortConfig,
- &InitialPortConfig,
- sizeof(PORT_CONFIGURATION_INFORMATION));
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("SpiCreatePortConfig() failed with Status 0x%08X\n",
Status);
+ break;
+ }
+ PortConfig = DeviceExtension->PortConfig;
/* Copy extension sizes into the PortConfig */
PortConfig->SpecificLuExtensionSize = DeviceExtension->LunExtensionSize;
@@ -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);
+ /* 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;
- }
- }
+ PDEVICE_OBJECT LowerPDO = NULL;
+
+ Status = IoReportDetectedDevice(DriverObject,
+ HwInitializationData->AdapterInterfaceType,
+ ConfigInfo.BusNumber,
+ PortConfig->SlotNumber,
+ ResourceList,
+ NULL,
+ TRUE,
+ &LowerPDO);
+
+ if (!NT_SUCCESS(Status))
+ {
+ 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);
-
- /* 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);
+ FdoScanAdapter(DeviceExtension);
- /* 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 */
diff --git a/drivers/storage/port/scsiport/scsiport.h
b/drivers/storage/port/scsiport/scsiport.h
index 73c9a91599b..b2db80654f0 100644
--- a/drivers/storage/port/scsiport/scsiport.h
+++ b/drivers/storage/port/scsiport/scsiport.h
@@ -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
-{
- 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
+typedef struct _SCSI_BUS_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
diff --git a/drivers/storage/port/scsiport/scsitypes.h
b/drivers/storage/port/scsiport/scsitypes.h
new file mode 100644
index 00000000000..984c6db4e7a
--- /dev/null
+++ b/drivers/storage/port/scsiport/scsitypes.h
@@ -0,0 +1,124 @@
+
+// see
https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifie…
+// and
https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifie…
+
+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";
+ }
+}