mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[SCSIPORT] Split scsiport.c file into several ones, prepare for the refactoring
CORE-17132
This commit is contained in:
parent
9be9750dc8
commit
1b45d9ee4b
8 changed files with 3462 additions and 3381 deletions
|
@ -2,6 +2,11 @@
|
|||
spec2def(scsiport.sys scsiport.spec ADD_IMPORTLIB)
|
||||
|
||||
list(APPEND SOURCE
|
||||
fdo.c
|
||||
ioctl.c
|
||||
pdo.c
|
||||
registry.c
|
||||
scsi.c
|
||||
scsiport.c
|
||||
stubs.c)
|
||||
|
||||
|
|
694
drivers/storage/port/scsiport/fdo.c
Normal file
694
drivers/storage/port/scsiport/fdo.c
Normal file
|
@ -0,0 +1,694 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Storage Stack / SCSIPORT storage port library
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Adapter device object (FDO) support routines
|
||||
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
||||
* Aleksey Bragin (aleksey@reactos.org)
|
||||
*/
|
||||
|
||||
#include "scsiport.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
SpiSendInquiry(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_Inout_ PSCSI_LUN_INFO LunInfo)
|
||||
{
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
PIO_STACK_LOCATION IrpStack;
|
||||
KEVENT Event;
|
||||
KIRQL Irql;
|
||||
PIRP Irp;
|
||||
NTSTATUS Status;
|
||||
PINQUIRYDATA InquiryBuffer;
|
||||
PSENSE_DATA SenseBuffer;
|
||||
BOOLEAN KeepTrying = TRUE;
|
||||
ULONG RetryCount = 0;
|
||||
SCSI_REQUEST_BLOCK Srb;
|
||||
PCDB Cdb;
|
||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
DPRINT("SpiSendInquiry() called\n");
|
||||
|
||||
DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
InquiryBuffer = ExAllocatePoolWithTag(NonPagedPool, INQUIRYDATABUFFERSIZE, TAG_SCSIPORT);
|
||||
if (InquiryBuffer == NULL)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
SenseBuffer = ExAllocatePoolWithTag(NonPagedPool, SENSE_BUFFER_SIZE, TAG_SCSIPORT);
|
||||
if (SenseBuffer == NULL)
|
||||
{
|
||||
ExFreePoolWithTag(InquiryBuffer, TAG_SCSIPORT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
while (KeepTrying)
|
||||
{
|
||||
/* Initialize event for waiting */
|
||||
KeInitializeEvent(&Event,
|
||||
NotificationEvent,
|
||||
FALSE);
|
||||
|
||||
/* Create an IRP */
|
||||
Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_IN,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
InquiryBuffer,
|
||||
INQUIRYDATABUFFERSIZE,
|
||||
TRUE,
|
||||
&Event,
|
||||
&IoStatusBlock);
|
||||
if (Irp == NULL)
|
||||
{
|
||||
DPRINT("IoBuildDeviceIoControlRequest() failed\n");
|
||||
|
||||
/* Quit the loop */
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
KeepTrying = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Prepare SRB */
|
||||
RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK));
|
||||
|
||||
Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
|
||||
Srb.OriginalRequest = Irp;
|
||||
Srb.PathId = LunInfo->PathId;
|
||||
Srb.TargetId = LunInfo->TargetId;
|
||||
Srb.Lun = LunInfo->Lun;
|
||||
Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
|
||||
Srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
|
||||
Srb.TimeOutValue = 4;
|
||||
Srb.CdbLength = 6;
|
||||
|
||||
Srb.SenseInfoBuffer = SenseBuffer;
|
||||
Srb.SenseInfoBufferLength = SENSE_BUFFER_SIZE;
|
||||
|
||||
Srb.DataBuffer = InquiryBuffer;
|
||||
Srb.DataTransferLength = INQUIRYDATABUFFERSIZE;
|
||||
|
||||
/* Attach Srb to the Irp */
|
||||
IrpStack = IoGetNextIrpStackLocation (Irp);
|
||||
IrpStack->Parameters.Scsi.Srb = &Srb;
|
||||
|
||||
/* Fill in CDB */
|
||||
Cdb = (PCDB)Srb.Cdb;
|
||||
Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
|
||||
Cdb->CDB6INQUIRY.LogicalUnitNumber = LunInfo->Lun;
|
||||
Cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
|
||||
|
||||
/* Call the driver */
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
|
||||
/* Wait for it to complete */
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
DPRINT("SpiSendInquiry(): Waiting for the driver to process request...\n");
|
||||
KeWaitForSingleObject(&Event,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
DPRINT("SpiSendInquiry(): 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,
|
||||
InquiryBuffer,
|
||||
INQUIRYDATABUFFERSIZE);
|
||||
|
||||
/* Quit the loop */
|
||||
Status = STATUS_SUCCESS;
|
||||
KeepTrying = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
DPRINT("Inquiry SRB failed with SrbStatus 0x%08X\n", Srb.SrbStatus);
|
||||
|
||||
/* Check if the queue is frozen */
|
||||
if (Srb.SrbStatus & SRB_STATUS_QUEUE_FROZEN)
|
||||
{
|
||||
/* 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);
|
||||
|
||||
/* Clear frozen flag */
|
||||
LunExtension->Flags &= ~LUNEX_FROZEN_QUEUE;
|
||||
|
||||
/* Acquire the spinlock */
|
||||
KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
|
||||
|
||||
/* Process the request */
|
||||
SpiGetNextRequestFromLun(DeviceObject->DeviceExtension, LunExtension);
|
||||
|
||||
/* SpiGetNextRequestFromLun() releases the spinlock,
|
||||
so we just lower irql back to what it was before */
|
||||
KeLowerIrql(Irql);
|
||||
}
|
||||
|
||||
/* Check if data overrun happened */
|
||||
if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN)
|
||||
{
|
||||
DPRINT("Data overrun at TargetId %d\n", LunInfo->TargetId);
|
||||
|
||||
/* Nothing dramatic, just copy data, but limiting the size */
|
||||
RtlCopyMemory(LunInfo->InquiryData,
|
||||
InquiryBuffer,
|
||||
(Srb.DataTransferLength > INQUIRYDATABUFFERSIZE) ?
|
||||
INQUIRYDATABUFFERSIZE : Srb.DataTransferLength);
|
||||
|
||||
/* Quit the loop */
|
||||
Status = STATUS_SUCCESS;
|
||||
KeepTrying = FALSE;
|
||||
}
|
||||
else if ((Srb.SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
|
||||
SenseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST)
|
||||
{
|
||||
/* LUN is not valid, but some device responds there.
|
||||
Mark it as invalid anyway */
|
||||
|
||||
/* Quit the loop */
|
||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
KeepTrying = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Retry a couple of times if no timeout happened */
|
||||
if ((RetryCount < 2) &&
|
||||
(SRB_STATUS(Srb.SrbStatus) != SRB_STATUS_NO_DEVICE) &&
|
||||
(SRB_STATUS(Srb.SrbStatus) != SRB_STATUS_SELECTION_TIMEOUT))
|
||||
{
|
||||
RetryCount++;
|
||||
KeepTrying = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* That's all, quit the loop */
|
||||
KeepTrying = FALSE;
|
||||
|
||||
/* Set status according to SRB status */
|
||||
if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_BAD_FUNCTION ||
|
||||
SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_BAD_SRB_BLOCK_LENGTH)
|
||||
{
|
||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_IO_DEVICE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Free buffers */
|
||||
ExFreePoolWithTag(InquiryBuffer, TAG_SCSIPORT);
|
||||
ExFreePoolWithTag(SenseBuffer, TAG_SCSIPORT);
|
||||
|
||||
DPRINT("SpiSendInquiry() done with Status 0x%08X\n", Status);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Scans all SCSI buses */
|
||||
VOID
|
||||
SpiScanAdapter(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
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;
|
||||
|
||||
DPRINT("SpiScanAdapter() called\n");
|
||||
|
||||
/* Scan all buses */
|
||||
for (Bus = 0; Bus < DeviceExtension->BusNum; Bus++)
|
||||
{
|
||||
DPRINT(" Scanning bus %d\n", Bus);
|
||||
DevicesFound = 0;
|
||||
|
||||
/* 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);
|
||||
|
||||
/* And send INQUIRY to every target */
|
||||
for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
|
||||
{
|
||||
/* TODO: Support scan bottom-up */
|
||||
|
||||
/* Skip if it's the same address */
|
||||
if (Target == BusScanInfo->BusIdentifier)
|
||||
continue;
|
||||
|
||||
/* Try to find an existing device here */
|
||||
DeviceExists = FALSE;
|
||||
LunInfoExists = BusScanInfo->LunInfo;
|
||||
|
||||
/* Find matching address on this bus */
|
||||
while (LunInfoExists)
|
||||
{
|
||||
if (LunInfoExists->TargetId == Target)
|
||||
{
|
||||
DeviceExists = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Advance to the next one */
|
||||
LunInfoExists = LunInfoExists->Next;
|
||||
}
|
||||
|
||||
/* No need to bother rescanning, since we already did that before */
|
||||
if (DeviceExists)
|
||||
continue;
|
||||
|
||||
/* Scan all logical units */
|
||||
for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
|
||||
{
|
||||
if ((!LunExtension) || (!LunInfo))
|
||||
break;
|
||||
|
||||
/* Add extension to the list */
|
||||
Hint = (Target + Lun) % LUS_NUMBER;
|
||||
LunExtension->Next = DeviceExtension->LunExtensionList[Hint];
|
||||
DeviceExtension->LunExtensionList[Hint] = LunExtension;
|
||||
|
||||
/* Fill Path, Target, Lun fields */
|
||||
LunExtension->PathId = LunInfo->PathId = (UCHAR)Bus;
|
||||
LunExtension->TargetId = LunInfo->TargetId = (UCHAR)Target;
|
||||
LunExtension->Lun = LunInfo->Lun = (UCHAR)Lun;
|
||||
|
||||
/* Set flag to prevent race conditions */
|
||||
LunExtension->Flags |= SCSI_PORT_SCAN_IN_PROGRESS;
|
||||
|
||||
/* Zero LU extension contents */
|
||||
if (DeviceExtension->LunExtensionSize)
|
||||
{
|
||||
RtlZeroMemory(LunExtension + 1,
|
||||
DeviceExtension->LunExtensionSize);
|
||||
}
|
||||
|
||||
/* Finally send the inquiry command */
|
||||
Status = SpiSendInquiry(DeviceExtension->DeviceObject, LunInfo);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Let's see if we really found a device */
|
||||
PINQUIRYDATA InquiryData = (PINQUIRYDATA)LunInfo->InquiryData;
|
||||
|
||||
/* Check if this device is unsupported */
|
||||
if (InquiryData->DeviceTypeQualifier == DEVICE_QUALIFIER_NOT_SUPPORTED)
|
||||
{
|
||||
DeviceExtension->LunExtensionList[Hint] =
|
||||
DeviceExtension->LunExtensionList[Hint]->Next;
|
||||
|
||||
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;
|
||||
|
||||
/* Store the last LUN info */
|
||||
LastLunInfo = LunInfo;
|
||||
|
||||
/* Store DeviceObject */
|
||||
LunInfo->DeviceObject = DeviceExtension->DeviceObject;
|
||||
|
||||
/* Allocate another buffer */
|
||||
LunInfo = ExAllocatePoolWithTag(PagedPool, sizeof(SCSI_LUN_INFO), TAG_SCSIPORT);
|
||||
if (!LunInfo)
|
||||
{
|
||||
DPRINT1("Out of resources!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
RtlZeroMemory(LunInfo, sizeof(SCSI_LUN_INFO));
|
||||
|
||||
/* Create a new LU extension */
|
||||
LunExtension = SpiAllocateLunExtension(DeviceExtension);
|
||||
|
||||
DevicesFound++;
|
||||
}
|
||||
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)
|
||||
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);
|
||||
}
|
||||
|
||||
DPRINT("SpiScanAdapter() done\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calls HwInitialize routine of the miniport and sets up interrupts
|
||||
* Should be called inside ScsiPortInitialize (for legacy drivers)
|
||||
* or inside IRP_MN_START_DEVICE for pnp drivers
|
||||
*
|
||||
* @param[in] DeviceExtension The device extension
|
||||
*
|
||||
* @return NTSTATUS of the operation
|
||||
*/
|
||||
NTSTATUS
|
||||
CallHWInitialize(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
PPORT_CONFIGURATION_INFORMATION PortConfig = DeviceExtension->PortConfig;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
KIRQL OldIrql;
|
||||
|
||||
/* Deal with interrupts */
|
||||
if (DeviceExtension->HwInterrupt == NULL ||
|
||||
(PortConfig->BusInterruptLevel == 0 && PortConfig->BusInterruptVector == 0))
|
||||
{
|
||||
/* No interrupts */
|
||||
DeviceExtension->InterruptCount = 0;
|
||||
|
||||
DPRINT1("Interrupt Count: 0\n");
|
||||
|
||||
UNIMPLEMENTED;
|
||||
|
||||
/* This code path will ALWAYS crash so stop it now */
|
||||
__debugbreak();
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOLEAN InterruptShareable;
|
||||
KINTERRUPT_MODE InterruptMode[2];
|
||||
ULONG InterruptVector[2], i, MappedIrq[2];
|
||||
KIRQL Dirql[2], MaxDirql;
|
||||
KAFFINITY Affinity[2];
|
||||
|
||||
DeviceExtension->InterruptLevel[0] = PortConfig->BusInterruptLevel;
|
||||
DeviceExtension->InterruptLevel[1] = PortConfig->BusInterruptLevel2;
|
||||
|
||||
InterruptVector[0] = PortConfig->BusInterruptVector;
|
||||
InterruptVector[1] = PortConfig->BusInterruptVector2;
|
||||
|
||||
InterruptMode[0] = PortConfig->InterruptMode;
|
||||
InterruptMode[1] = PortConfig->InterruptMode2;
|
||||
|
||||
DeviceExtension->InterruptCount =
|
||||
(PortConfig->BusInterruptLevel2 != 0 ||
|
||||
PortConfig->BusInterruptVector2 != 0) ? 2 : 1;
|
||||
|
||||
for (i = 0; i < DeviceExtension->InterruptCount; i++)
|
||||
{
|
||||
/* Register an interrupt handler for this device */
|
||||
MappedIrq[i] = HalGetInterruptVector(
|
||||
PortConfig->AdapterInterfaceType, PortConfig->SystemIoBusNumber,
|
||||
DeviceExtension->InterruptLevel[i], InterruptVector[i], &Dirql[i],
|
||||
&Affinity[i]);
|
||||
}
|
||||
|
||||
if (DeviceExtension->InterruptCount == 1 || Dirql[0] > Dirql[1])
|
||||
MaxDirql = Dirql[0];
|
||||
else
|
||||
MaxDirql = Dirql[1];
|
||||
|
||||
for (i = 0; i < DeviceExtension->InterruptCount; i++)
|
||||
{
|
||||
/* Determine IRQ sharability as usual */
|
||||
if (PortConfig->AdapterInterfaceType == MicroChannel ||
|
||||
InterruptMode[i] == LevelSensitive)
|
||||
{
|
||||
InterruptShareable = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
InterruptShareable = FALSE;
|
||||
}
|
||||
|
||||
Status = IoConnectInterrupt(
|
||||
&DeviceExtension->Interrupt[i], (PKSERVICE_ROUTINE)ScsiPortIsr, DeviceExtension,
|
||||
&DeviceExtension->IrqLock, MappedIrq[i], Dirql[i], MaxDirql, InterruptMode[i],
|
||||
InterruptShareable, Affinity[i], FALSE);
|
||||
|
||||
if (!(NT_SUCCESS(Status)))
|
||||
{
|
||||
DPRINT1("Could not connect interrupt %d\n", InterruptVector[i]);
|
||||
DeviceExtension->Interrupt[i] = NULL;
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Save IoAddress (from access ranges) */
|
||||
if (PortConfig->NumberOfAccessRanges != 0)
|
||||
{
|
||||
DeviceExtension->IoAddress = ((*(PortConfig->AccessRanges))[0]).RangeStart.LowPart;
|
||||
|
||||
DPRINT("Io Address %x\n", DeviceExtension->IoAddress);
|
||||
}
|
||||
|
||||
/* Set flag that it's allowed to disconnect during this command */
|
||||
DeviceExtension->Flags |= SCSI_PORT_DISCONNECT_ALLOWED;
|
||||
|
||||
/* Initialize counter of active requests (-1 means there are none) */
|
||||
DeviceExtension->ActiveRequestCounter = -1;
|
||||
|
||||
/* Analyze what we have about DMA */
|
||||
if (DeviceExtension->AdapterObject != NULL && PortConfig->Master &&
|
||||
PortConfig->NeedPhysicalAddresses)
|
||||
{
|
||||
DeviceExtension->MapRegisters = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
DeviceExtension->MapRegisters = FALSE;
|
||||
}
|
||||
|
||||
/* Call HwInitialize at DISPATCH_LEVEL */
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
||||
|
||||
if (!KeSynchronizeExecution(
|
||||
DeviceExtension->Interrupt[0], DeviceExtension->HwInitialize,
|
||||
DeviceExtension->MiniPortDeviceExtension))
|
||||
{
|
||||
DPRINT1("HwInitialize() failed!\n");
|
||||
KeLowerIrql(OldIrql);
|
||||
return STATUS_ADAPTER_HARDWARE_ERROR;
|
||||
}
|
||||
|
||||
/* Check if a notification is needed */
|
||||
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);
|
||||
}
|
||||
|
||||
/* Lower irql back to what it was */
|
||||
KeLowerIrql(OldIrql);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID
|
||||
SpiCleanupAfterInit(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
PSCSI_LUN_INFO LunInfo;
|
||||
PVOID Ptr;
|
||||
ULONG Bus, Lun;
|
||||
|
||||
/* Check if we have something to clean up */
|
||||
if (DeviceExtension == NULL)
|
||||
return;
|
||||
|
||||
/* Stop the timer */
|
||||
IoStopTimer(DeviceExtension->DeviceObject);
|
||||
|
||||
/* Disconnect the interrupts */
|
||||
while (DeviceExtension->InterruptCount)
|
||||
{
|
||||
if (DeviceExtension->Interrupt[--DeviceExtension->InterruptCount])
|
||||
IoDisconnectInterrupt(DeviceExtension->Interrupt[DeviceExtension->InterruptCount]);
|
||||
}
|
||||
|
||||
/* Delete ConfigInfo */
|
||||
if (DeviceExtension->BusesConfig)
|
||||
{
|
||||
for (Bus = 0; Bus < DeviceExtension->BusNum; Bus++)
|
||||
{
|
||||
if (!DeviceExtension->BusesConfig->BusScanInfo[Bus])
|
||||
continue;
|
||||
|
||||
LunInfo = DeviceExtension->BusesConfig->BusScanInfo[Bus]->LunInfo;
|
||||
|
||||
while (LunInfo)
|
||||
{
|
||||
/* Free current, but save pointer to the next one */
|
||||
Ptr = LunInfo->Next;
|
||||
ExFreePool(LunInfo);
|
||||
LunInfo = Ptr;
|
||||
}
|
||||
|
||||
ExFreePool(DeviceExtension->BusesConfig->BusScanInfo[Bus]);
|
||||
}
|
||||
|
||||
ExFreePool(DeviceExtension->BusesConfig);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free common buffer (if it exists) */
|
||||
if (DeviceExtension->SrbExtensionBuffer != NULL &&
|
||||
DeviceExtension->CommonBufferLength != 0)
|
||||
{
|
||||
if (!DeviceExtension->AdapterObject)
|
||||
{
|
||||
ExFreePool(DeviceExtension->SrbExtensionBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
HalFreeCommonBuffer(DeviceExtension->AdapterObject,
|
||||
DeviceExtension->CommonBufferLength,
|
||||
DeviceExtension->PhysicalAddress,
|
||||
DeviceExtension->SrbExtensionBuffer,
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free SRB info */
|
||||
if (DeviceExtension->SrbInfo != NULL)
|
||||
ExFreePool(DeviceExtension->SrbInfo);
|
||||
|
||||
/* Unmap mapped addresses */
|
||||
while (DeviceExtension->MappedAddressList != NULL)
|
||||
{
|
||||
MmUnmapIoSpace(DeviceExtension->MappedAddressList->MappedAddress,
|
||||
DeviceExtension->MappedAddressList->NumberOfBytes);
|
||||
|
||||
Ptr = DeviceExtension->MappedAddressList;
|
||||
DeviceExtension->MappedAddressList = DeviceExtension->MappedAddressList->NextMappedAddress;
|
||||
|
||||
ExFreePool(Ptr);
|
||||
}
|
||||
|
||||
/* Finally delete the device object */
|
||||
DPRINT("Deleting device %p\n", DeviceExtension->DeviceObject);
|
||||
IoDeleteDevice(DeviceExtension->DeviceObject);
|
||||
}
|
255
drivers/storage/port/scsiport/ioctl.c
Normal file
255
drivers/storage/port/scsiport/ioctl.c
Normal file
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Storage Stack / SCSIPORT storage port library
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: IOCTL handlers
|
||||
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
||||
* Aleksey Bragin (aleksey@reactos.org)
|
||||
*/
|
||||
|
||||
#include "scsiport.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
SpiGetInquiryData(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
_In_ PIRP Irp)
|
||||
{
|
||||
ULONG InquiryDataSize;
|
||||
PSCSI_LUN_INFO LunInfo;
|
||||
ULONG BusCount, LunCount, 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");
|
||||
|
||||
/* Get pointer to the buffer */
|
||||
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
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;
|
||||
|
||||
/* Calculate size of inquiry data, rounding up to sizeof(ULONG) */
|
||||
InquiryDataSize =
|
||||
((sizeof(SCSI_INQUIRY_DATA) - 1 + INQUIRYDATABUFFERSIZE +
|
||||
sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1));
|
||||
|
||||
/* Calculate data size */
|
||||
Length = sizeof(SCSI_ADAPTER_BUS_INFO) + (BusCount - 1) * sizeof(SCSI_BUS_DATA);
|
||||
|
||||
Length += InquiryDataSize * LunCount;
|
||||
|
||||
/* Check, if all data is going to fit into provided buffer */
|
||||
if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < Length)
|
||||
{
|
||||
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/* Store data size in the IRP */
|
||||
Irp->IoStatus.Information = Length;
|
||||
|
||||
DPRINT("Data size: %lu\n", Length);
|
||||
|
||||
AdapterBusInfo = (PSCSI_ADAPTER_BUS_INFO)Buffer;
|
||||
|
||||
AdapterBusInfo->NumberOfBuses = (UCHAR)BusCount;
|
||||
|
||||
/* Point InquiryData to the corresponding place inside Buffer */
|
||||
InquiryData = (PSCSI_INQUIRY_DATA)(Buffer + sizeof(SCSI_ADAPTER_BUS_INFO) +
|
||||
(BusCount - 1) * sizeof(SCSI_BUS_DATA));
|
||||
|
||||
/* Loop each bus */
|
||||
for (Bus = 0; Bus < BusCount; Bus++)
|
||||
{
|
||||
BusData = &AdapterBusInfo->BusData[Bus];
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Store LUN count */
|
||||
BusData->NumberOfLogicalUnits =
|
||||
DeviceExtension->BusesConfig->BusScanInfo[Bus]->LogicalUnitsCount;
|
||||
|
||||
/* Loop all LUNs */
|
||||
while (LunInfo != NULL)
|
||||
{
|
||||
DPRINT("(Bus %lu Target %lu Lun %lu)\n",
|
||||
Bus, LunInfo->TargetId, LunInfo->Lun);
|
||||
|
||||
/* Fill InquiryData with values */
|
||||
InquiryData->PathId = LunInfo->PathId;
|
||||
InquiryData->TargetId = LunInfo->TargetId;
|
||||
InquiryData->Lun = LunInfo->Lun;
|
||||
InquiryData->InquiryDataLength = INQUIRYDATABUFFERSIZE;
|
||||
InquiryData->DeviceClaimed = LunInfo->DeviceClaimed;
|
||||
InquiryData->NextInquiryDataOffset =
|
||||
(ULONG)((PUCHAR)InquiryData + InquiryDataSize - Buffer);
|
||||
|
||||
/* Copy data in it */
|
||||
RtlCopyMemory(InquiryData->InquiryData,
|
||||
LunInfo->InquiryData,
|
||||
INQUIRYDATABUFFERSIZE);
|
||||
|
||||
/* Move to the next LUN */
|
||||
LunInfo = LunInfo->Next;
|
||||
InquiryData = (PSCSI_INQUIRY_DATA) ((PCHAR)InquiryData + InquiryDataSize);
|
||||
}
|
||||
|
||||
/* Either mark the end, or set offset to 0 */
|
||||
if (BusData->NumberOfLogicalUnits != 0)
|
||||
((PSCSI_INQUIRY_DATA) ((PCHAR)InquiryData - InquiryDataSize))->NextInquiryDataOffset = 0;
|
||||
else
|
||||
BusData->InquiryDataOffset = 0;
|
||||
}
|
||||
|
||||
/* Finish with success */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* NAME INTERNAL
|
||||
* ScsiPortDeviceControl
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Answer requests for device control calls
|
||||
*
|
||||
* RUN LEVEL
|
||||
* PASSIVE_LEVEL
|
||||
*
|
||||
* ARGUMENTS
|
||||
* Standard dispatch arguments
|
||||
*
|
||||
* RETURNS
|
||||
* NTSTATUS
|
||||
*/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ScsiPortDeviceControl(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_ PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION Stack;
|
||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
||||
PDUMP_POINTERS DumpPointers;
|
||||
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))
|
||||
{
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
|
||||
break;
|
||||
}
|
||||
|
||||
DumpPointers = Irp->AssociatedIrp.SystemBuffer;
|
||||
DumpPointers->DeviceObject = DeviceObject;
|
||||
/* More data.. ? */
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
|
||||
break;
|
||||
|
||||
case IOCTL_SCSI_GET_CAPABILITIES:
|
||||
DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
|
||||
if (Stack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(PVOID))
|
||||
{
|
||||
*((PVOID *)Irp->AssociatedIrp.SystemBuffer) = &DeviceExtension->PortCapabilities;
|
||||
|
||||
Irp->IoStatus.Information = sizeof(PVOID);
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(IO_SCSI_CAPABILITIES))
|
||||
{
|
||||
Status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
|
||||
&DeviceExtension->PortCapabilities,
|
||||
sizeof(IO_SCSI_CAPABILITIES));
|
||||
|
||||
Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
case IOCTL_SCSI_GET_INQUIRY_DATA:
|
||||
DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
|
||||
|
||||
/* Copy inquiry data to the port device extension */
|
||||
Status = SpiGetInquiryData(DeviceExtension, Irp);
|
||||
break;
|
||||
|
||||
case IOCTL_SCSI_MINIPORT:
|
||||
DPRINT1("IOCTL_SCSI_MINIPORT unimplemented!\n");
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
|
||||
case IOCTL_SCSI_PASS_THROUGH:
|
||||
DPRINT1("IOCTL_SCSI_PASS_THROUGH unimplemented!\n");
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (DEVICE_TYPE_FROM_CTL_CODE(Stack->Parameters.DeviceIoControl.IoControlCode) == MOUNTDEVCONTROLTYPE)
|
||||
{
|
||||
switch (Stack->Parameters.DeviceIoControl.IoControlCode)
|
||||
{
|
||||
case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
|
||||
DPRINT1("Got unexpected IOCTL_MOUNTDEV_QUERY_DEVICE_NAME\n");
|
||||
break;
|
||||
case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:
|
||||
DPRINT1("Got unexpected IOCTL_MOUNTDEV_QUERY_UNIQUE_ID\n");
|
||||
break;
|
||||
default:
|
||||
DPRINT(" got ioctl intended for the mount manager: 0x%lX\n", Stack->Parameters.DeviceIoControl.IoControlCode);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
DPRINT1(" unknown ioctl code: 0x%lX\n", Stack->Parameters.DeviceIoControl.IoControlCode);
|
||||
}
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Complete the request with the given status */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return Status;
|
||||
}
|
124
drivers/storage/port/scsiport/pdo.c
Normal file
124
drivers/storage/port/scsiport/pdo.c
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Storage Stack / SCSIPORT storage port library
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Logical Unit (PDO) functions
|
||||
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
||||
* Aleksey Bragin (aleksey@reactos.org)
|
||||
*/
|
||||
|
||||
#include "scsiport.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
PSCSI_PORT_LUN_EXTENSION
|
||||
SpiAllocateLunExtension(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
||||
ULONG LunExtensionSize;
|
||||
|
||||
DPRINT("SpiAllocateLunExtension(%p)\n", DeviceExtension);
|
||||
|
||||
/* Round LunExtensionSize first to the sizeof LONGLONG */
|
||||
LunExtensionSize = (DeviceExtension->LunExtensionSize +
|
||||
sizeof(LONGLONG) - 1) & ~(sizeof(LONGLONG) - 1);
|
||||
|
||||
LunExtensionSize += sizeof(SCSI_PORT_LUN_EXTENSION);
|
||||
DPRINT("LunExtensionSize %lu\n", LunExtensionSize);
|
||||
|
||||
LunExtension = ExAllocatePoolWithTag(NonPagedPool, LunExtensionSize, TAG_SCSIPORT);
|
||||
if (LunExtension == NULL)
|
||||
{
|
||||
DPRINT1("Out of resources!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Zero everything */
|
||||
RtlZeroMemory(LunExtension, LunExtensionSize);
|
||||
|
||||
/* Initialize a list of requests */
|
||||
InitializeListHead(&LunExtension->SrbInfo.Requests);
|
||||
|
||||
/* Initialize timeout counter */
|
||||
LunExtension->RequestTimeout = -1;
|
||||
|
||||
/* Set maximum queue size */
|
||||
LunExtension->MaxQueueCount = 256;
|
||||
|
||||
/* Initialize request queue */
|
||||
KeInitializeDeviceQueue(&LunExtension->DeviceQueue);
|
||||
|
||||
return LunExtension;
|
||||
}
|
||||
|
||||
PSCSI_PORT_LUN_EXTENSION
|
||||
SpiGetLunExtension(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
_In_ UCHAR PathId,
|
||||
_In_ UCHAR TargetId,
|
||||
_In_ UCHAR Lun)
|
||||
{
|
||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
||||
|
||||
DPRINT("SpiGetLunExtension(%p %u %u %u) called\n",
|
||||
DeviceExtension, PathId, TargetId, Lun);
|
||||
|
||||
/* Get appropriate list */
|
||||
LunExtension = DeviceExtension->LunExtensionList[(TargetId + Lun) % LUS_NUMBER];
|
||||
|
||||
/* Iterate it until we find what we need */
|
||||
while (LunExtension)
|
||||
{
|
||||
if (LunExtension->TargetId == TargetId &&
|
||||
LunExtension->Lun == Lun &&
|
||||
LunExtension->PathId == PathId)
|
||||
{
|
||||
/* All matches, return */
|
||||
return LunExtension;
|
||||
}
|
||||
|
||||
/* Advance to the next item */
|
||||
LunExtension = LunExtension->Next;
|
||||
}
|
||||
|
||||
/* We did not find anything */
|
||||
DPRINT("Nothing found\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PSCSI_REQUEST_BLOCK_INFO
|
||||
SpiGetSrbData(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
_In_ UCHAR PathId,
|
||||
_In_ UCHAR TargetId,
|
||||
_In_ UCHAR Lun,
|
||||
_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;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make sure the tag is valid, if it is - return the data */
|
||||
if (QueueTag > DeviceExtension->SrbDataCount || QueueTag < 1)
|
||||
return NULL;
|
||||
else
|
||||
return &DeviceExtension->SrbInfo[QueueTag -1];
|
||||
}
|
||||
}
|
520
drivers/storage/port/scsiport/registry.c
Normal file
520
drivers/storage/port/scsiport/registry.c
Normal file
|
@ -0,0 +1,520 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Storage Stack / SCSIPORT storage port library
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Registry operations
|
||||
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
||||
* Aleksey Bragin (aleksey@reactos.org)
|
||||
*/
|
||||
|
||||
#include "scsiport.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
VOID
|
||||
SpiInitOpenKeys(
|
||||
_Inout_ PCONFIGURATION_INFO ConfigInfo,
|
||||
_In_ PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING KeyName;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Open the service key */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
RegistryPath,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
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);
|
||||
ConfigInfo->ServiceKey = NULL;
|
||||
}
|
||||
|
||||
/* If we could open driver's service key, then proceed to the Parameters key */
|
||||
if (ConfigInfo->ServiceKey != NULL)
|
||||
{
|
||||
RtlInitUnicodeString(&KeyName, L"Parameters");
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
ConfigInfo->ServiceKey,
|
||||
(PSECURITY_DESCRIPTOR) NULL);
|
||||
|
||||
/* Try to open it */
|
||||
Status = ZwOpenKey(&ConfigInfo->DeviceKey,
|
||||
KEY_READ,
|
||||
&ObjectAttributes);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Yes, Parameters key exist, and it must be used instead of
|
||||
the Service key */
|
||||
ZwClose(ConfigInfo->ServiceKey);
|
||||
ConfigInfo->ServiceKey = ConfigInfo->DeviceKey;
|
||||
ConfigInfo->DeviceKey = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ConfigInfo->ServiceKey != NULL)
|
||||
{
|
||||
/* Open the Device key */
|
||||
RtlInitUnicodeString(&KeyName, L"Device");
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
ConfigInfo->ServiceKey,
|
||||
NULL);
|
||||
|
||||
/* We don't check for failure here - not needed */
|
||||
ZwOpenKey(&ConfigInfo->DeviceKey,
|
||||
KEY_READ,
|
||||
&ObjectAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* NAME INTERNAL
|
||||
* SpiBuildDeviceMap
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Builds the registry device map of all device which are attached
|
||||
* to the given SCSI HBA port. The device map is located at:
|
||||
* \Registry\Machine\DeviceMap\Scsi
|
||||
*
|
||||
* RUN LEVEL
|
||||
* PASSIVE_LEVEL
|
||||
*
|
||||
* ARGUMENTS
|
||||
* DeviceExtension
|
||||
* ...
|
||||
*
|
||||
* RegistryPath
|
||||
* Name of registry driver service key.
|
||||
*
|
||||
* RETURNS
|
||||
* NTSTATUS
|
||||
*/
|
||||
|
||||
NTSTATUS
|
||||
SpiBuildDeviceMap(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
_In_ PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
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)
|
||||
{
|
||||
DPRINT1("Invalid parameter\n");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Open or create the 'Scsi' subkey */
|
||||
RtlInitUnicodeString(&KeyName,
|
||||
L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi");
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_KERNEL_HANDLE,
|
||||
0,
|
||||
NULL);
|
||||
Status = ZwCreateKey(&ScsiKey,
|
||||
KEY_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
0,
|
||||
NULL,
|
||||
REG_OPTION_VOLATILE,
|
||||
&Disposition);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Create new 'Scsi Port X' subkey */
|
||||
DPRINT("Scsi Port %lu\n", DeviceExtension->PortNumber);
|
||||
|
||||
swprintf(NameBuffer,
|
||||
L"Scsi Port %lu",
|
||||
DeviceExtension->PortNumber);
|
||||
RtlInitUnicodeString(&KeyName, NameBuffer);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_KERNEL_HANDLE,
|
||||
ScsiKey,
|
||||
NULL);
|
||||
Status = ZwCreateKey(&ScsiPortKey,
|
||||
KEY_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
0,
|
||||
NULL,
|
||||
REG_OPTION_VOLATILE,
|
||||
&Disposition);
|
||||
ZwClose(ScsiKey);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create port-specific values
|
||||
*/
|
||||
|
||||
/* Set 'DMA Enabled' (REG_DWORD) value */
|
||||
UlongData = (ULONG)!DeviceExtension->PortCapabilities.AdapterUsesPio;
|
||||
DPRINT(" DMA Enabled = %s\n", UlongData ? "TRUE" : "FALSE");
|
||||
RtlInitUnicodeString(&ValueName, L"DMA Enabled");
|
||||
Status = ZwSetValueKey(ScsiPortKey,
|
||||
&ValueName,
|
||||
0,
|
||||
REG_DWORD,
|
||||
&UlongData,
|
||||
sizeof(UlongData));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ZwSetValueKey('DMA Enabled') failed (Status %lx)\n", Status);
|
||||
ZwClose(ScsiPortKey);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Set 'Driver' (REG_SZ) value */
|
||||
DriverName = wcsrchr(RegistryPath->Buffer, L'\\') + 1;
|
||||
RtlInitUnicodeString(&ValueName, L"Driver");
|
||||
Status = ZwSetValueKey(ScsiPortKey,
|
||||
&ValueName,
|
||||
0,
|
||||
REG_SZ,
|
||||
DriverName,
|
||||
(ULONG)((wcslen(DriverName) + 1) * sizeof(WCHAR)));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ZwSetValueKey('Driver') failed (Status %lx)\n", Status);
|
||||
ZwClose(ScsiPortKey);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Set 'Interrupt' (REG_DWORD) value (NT4 only) */
|
||||
UlongData = (ULONG)DeviceExtension->PortConfig->BusInterruptLevel;
|
||||
DPRINT(" Interrupt = %lu\n", UlongData);
|
||||
RtlInitUnicodeString(&ValueName, L"Interrupt");
|
||||
Status = ZwSetValueKey(ScsiPortKey,
|
||||
&ValueName,
|
||||
0,
|
||||
REG_DWORD,
|
||||
&UlongData,
|
||||
sizeof(UlongData));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ZwSetValueKey('Interrupt') failed (Status %lx)\n", Status);
|
||||
ZwClose(ScsiPortKey);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Set 'IOAddress' (REG_DWORD) value (NT4 only) */
|
||||
UlongData = ScsiPortConvertPhysicalAddressToUlong((*DeviceExtension->PortConfig->AccessRanges)[0].RangeStart);
|
||||
DPRINT(" IOAddress = %lx\n", UlongData);
|
||||
RtlInitUnicodeString(&ValueName, L"IOAddress");
|
||||
Status = ZwSetValueKey(ScsiPortKey,
|
||||
&ValueName,
|
||||
0,
|
||||
REG_DWORD,
|
||||
&UlongData,
|
||||
sizeof(UlongData));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ZwSetValueKey('IOAddress') failed (Status %lx)\n", Status);
|
||||
ZwClose(ScsiPortKey);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Enumerate buses */
|
||||
for (BusNumber = 0; BusNumber < DeviceExtension->PortConfig->NumberOfBuses; BusNumber++)
|
||||
{
|
||||
/* Create 'Scsi Bus X' key */
|
||||
DPRINT(" Scsi Bus %lu\n", BusNumber);
|
||||
swprintf(NameBuffer,
|
||||
L"Scsi Bus %lu",
|
||||
BusNumber);
|
||||
RtlInitUnicodeString(&KeyName, NameBuffer);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
0,
|
||||
ScsiPortKey,
|
||||
NULL);
|
||||
Status = ZwCreateKey(&ScsiBusKey,
|
||||
KEY_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
0,
|
||||
NULL,
|
||||
REG_OPTION_VOLATILE,
|
||||
&Disposition);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
|
||||
goto ByeBye;
|
||||
}
|
||||
|
||||
/* Create 'Initiator Id X' key */
|
||||
DPRINT(" Initiator Id %lu\n",
|
||||
DeviceExtension->PortConfig->InitiatorBusId[BusNumber]);
|
||||
swprintf(NameBuffer,
|
||||
L"Initiator Id %lu",
|
||||
(ULONG)(UCHAR)DeviceExtension->PortConfig->InitiatorBusId[BusNumber]);
|
||||
RtlInitUnicodeString(&KeyName, NameBuffer);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
0,
|
||||
ScsiBusKey,
|
||||
NULL);
|
||||
Status = ZwCreateKey(&ScsiInitiatorKey,
|
||||
KEY_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
0,
|
||||
NULL,
|
||||
REG_OPTION_VOLATILE,
|
||||
&Disposition);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
|
||||
goto ByeBye;
|
||||
}
|
||||
|
||||
/* FIXME: Are there any initiator values (??) */
|
||||
|
||||
ZwClose(ScsiInitiatorKey);
|
||||
ScsiInitiatorKey = NULL;
|
||||
|
||||
|
||||
/* Enumerate targets */
|
||||
CurrentTarget = (ULONG)-1;
|
||||
ScsiTargetKey = NULL;
|
||||
for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
|
||||
{
|
||||
for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
|
||||
{
|
||||
LunExtension = SpiGetLunExtension(DeviceExtension,
|
||||
(UCHAR)BusNumber,
|
||||
(UCHAR)Target,
|
||||
(UCHAR)Lun);
|
||||
if (LunExtension == NULL)
|
||||
continue;
|
||||
|
||||
if (Target != CurrentTarget)
|
||||
{
|
||||
/* Close old target key */
|
||||
if (ScsiTargetKey != NULL)
|
||||
{
|
||||
ZwClose(ScsiTargetKey);
|
||||
ScsiTargetKey = NULL;
|
||||
}
|
||||
|
||||
/* Create 'Target Id X' key */
|
||||
DPRINT(" Target Id %lu\n", Target);
|
||||
swprintf(NameBuffer,
|
||||
L"Target Id %lu",
|
||||
Target);
|
||||
RtlInitUnicodeString(&KeyName, NameBuffer);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
0,
|
||||
ScsiBusKey,
|
||||
NULL);
|
||||
Status = ZwCreateKey(&ScsiTargetKey,
|
||||
KEY_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
0,
|
||||
NULL,
|
||||
REG_OPTION_VOLATILE,
|
||||
&Disposition);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
|
||||
goto ByeBye;
|
||||
}
|
||||
|
||||
CurrentTarget = Target;
|
||||
}
|
||||
|
||||
/* Create 'Logical Unit Id X' key */
|
||||
DPRINT(" Logical Unit Id %lu\n", Lun);
|
||||
swprintf(NameBuffer,
|
||||
L"Logical Unit Id %lu",
|
||||
Lun);
|
||||
RtlInitUnicodeString(&KeyName, NameBuffer);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
0,
|
||||
ScsiTargetKey,
|
||||
NULL);
|
||||
Status = ZwCreateKey(&ScsiLunKey,
|
||||
KEY_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
0,
|
||||
NULL,
|
||||
REG_OPTION_VOLATILE,
|
||||
&Disposition);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
|
||||
goto ByeBye;
|
||||
}
|
||||
|
||||
/* Set 'Identifier' (REG_SZ) value */
|
||||
swprintf(NameBuffer,
|
||||
L"%.8S%.16S%.4S",
|
||||
LunExtension->InquiryData.VendorId,
|
||||
LunExtension->InquiryData.ProductId,
|
||||
LunExtension->InquiryData.ProductRevisionLevel);
|
||||
DPRINT(" Identifier = '%S'\n", NameBuffer);
|
||||
RtlInitUnicodeString(&ValueName, L"Identifier");
|
||||
Status = ZwSetValueKey(ScsiLunKey,
|
||||
&ValueName,
|
||||
0,
|
||||
REG_SZ,
|
||||
NameBuffer,
|
||||
(ULONG)((wcslen(NameBuffer) + 1) * sizeof(WCHAR)));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ZwSetValueKey('Identifier') failed (Status %lx)\n", Status);
|
||||
goto ByeBye;
|
||||
}
|
||||
|
||||
/* Set 'Type' (REG_SZ) value */
|
||||
/*
|
||||
* See https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-ide-devices
|
||||
* and https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-scsi-devices
|
||||
* for a list of types with their human-readable forms.
|
||||
*/
|
||||
switch (LunExtension->InquiryData.DeviceType)
|
||||
{
|
||||
case 0:
|
||||
TypeName = L"DiskPeripheral";
|
||||
break;
|
||||
case 1:
|
||||
TypeName = L"TapePeripheral";
|
||||
break;
|
||||
case 2:
|
||||
TypeName = L"PrinterPeripheral";
|
||||
break;
|
||||
// case 3: "ProcessorPeripheral", classified as 'other': fall back to default case.
|
||||
case 4:
|
||||
TypeName = L"WormPeripheral";
|
||||
break;
|
||||
case 5:
|
||||
TypeName = L"CdRomPeripheral";
|
||||
break;
|
||||
case 6:
|
||||
TypeName = L"ScannerPeripheral";
|
||||
break;
|
||||
case 7:
|
||||
TypeName = L"OpticalDiskPeripheral";
|
||||
break;
|
||||
case 8:
|
||||
TypeName = L"MediumChangerPeripheral";
|
||||
break;
|
||||
case 9:
|
||||
TypeName = L"CommunicationsPeripheral";
|
||||
break;
|
||||
|
||||
/* New peripheral types (SCSI only) */
|
||||
case 10: case 11:
|
||||
TypeName = L"ASCPrePressGraphicsPeripheral";
|
||||
break;
|
||||
case 12:
|
||||
TypeName = L"ArrayPeripheral";
|
||||
break;
|
||||
case 13:
|
||||
TypeName = L"EnclosurePeripheral";
|
||||
break;
|
||||
case 14:
|
||||
TypeName = L"RBCPeripheral";
|
||||
break;
|
||||
case 15:
|
||||
TypeName = L"CardReaderPeripheral";
|
||||
break;
|
||||
case 16:
|
||||
TypeName = L"BridgePeripheral";
|
||||
break;
|
||||
|
||||
default:
|
||||
TypeName = L"OtherPeripheral";
|
||||
break;
|
||||
}
|
||||
DPRINT(" Type = '%S'\n", TypeName);
|
||||
RtlInitUnicodeString(&ValueName, L"Type");
|
||||
Status = ZwSetValueKey(ScsiLunKey,
|
||||
&ValueName,
|
||||
0,
|
||||
REG_SZ,
|
||||
TypeName,
|
||||
(ULONG)((wcslen(TypeName) + 1) * sizeof(WCHAR)));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ZwSetValueKey('Type') failed (Status %lx)\n", Status);
|
||||
goto ByeBye;
|
||||
}
|
||||
|
||||
ZwClose(ScsiLunKey);
|
||||
ScsiLunKey = NULL;
|
||||
}
|
||||
|
||||
/* Close old target key */
|
||||
if (ScsiTargetKey != NULL)
|
||||
{
|
||||
ZwClose(ScsiTargetKey);
|
||||
ScsiTargetKey = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ZwClose(ScsiBusKey);
|
||||
ScsiBusKey = NULL;
|
||||
}
|
||||
|
||||
ByeBye:
|
||||
if (ScsiLunKey != NULL)
|
||||
ZwClose(ScsiLunKey);
|
||||
|
||||
if (ScsiInitiatorKey != NULL)
|
||||
ZwClose(ScsiInitiatorKey);
|
||||
|
||||
if (ScsiTargetKey != NULL)
|
||||
ZwClose(ScsiTargetKey);
|
||||
|
||||
if (ScsiBusKey != NULL)
|
||||
ZwClose(ScsiBusKey);
|
||||
|
||||
if (ScsiPortKey != NULL)
|
||||
ZwClose(ScsiPortKey);
|
||||
|
||||
DPRINT("SpiBuildDeviceMap() done\n");
|
||||
|
||||
return Status;
|
||||
}
|
1768
drivers/storage/port/scsiport/scsi.c
Normal file
1768
drivers/storage/port/scsiport/scsi.c
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -17,13 +17,6 @@
|
|||
|
||||
#define VERSION "0.0.3"
|
||||
|
||||
#ifndef PAGE_ROUND_UP
|
||||
#define PAGE_ROUND_UP(x) ( (((ULONG_PTR)x)%PAGE_SIZE) ? ((((ULONG_PTR)x)&(~(PAGE_SIZE-1)))+PAGE_SIZE) : ((ULONG_PTR)x) )
|
||||
#endif
|
||||
#ifndef ROUND_UP
|
||||
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
|
||||
#endif
|
||||
|
||||
#define TAG_SCSIPORT 'ISCS'
|
||||
|
||||
/* Defines how many logical unit arrays will be in a device extension */
|
||||
|
@ -309,3 +302,92 @@ typedef struct _RESETBUS_PARAMS
|
|||
ULONG PathId;
|
||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
||||
} RESETBUS_PARAMS, *PRESETBUS_PARAMS;
|
||||
|
||||
|
||||
// ioctl.c
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ScsiPortDeviceControl(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_ PIRP Irp);
|
||||
|
||||
// fdo.c
|
||||
|
||||
VOID
|
||||
SpiScanAdapter(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
||||
|
||||
NTSTATUS
|
||||
CallHWInitialize(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
||||
|
||||
VOID
|
||||
SpiCleanupAfterInit(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
||||
|
||||
// pdo.c
|
||||
|
||||
PSCSI_PORT_LUN_EXTENSION
|
||||
SpiAllocateLunExtension(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
||||
|
||||
PSCSI_PORT_LUN_EXTENSION
|
||||
SpiGetLunExtension(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
_In_ UCHAR PathId,
|
||||
_In_ UCHAR TargetId,
|
||||
_In_ UCHAR Lun);
|
||||
|
||||
PSCSI_REQUEST_BLOCK_INFO
|
||||
SpiGetSrbData(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
_In_ UCHAR PathId,
|
||||
_In_ UCHAR TargetId,
|
||||
_In_ UCHAR Lun,
|
||||
_In_ UCHAR QueueTag);
|
||||
|
||||
// registry.c
|
||||
|
||||
VOID
|
||||
SpiInitOpenKeys(
|
||||
_Inout_ PCONFIGURATION_INFO ConfigInfo,
|
||||
_In_ PUNICODE_STRING RegistryPath);
|
||||
|
||||
NTSTATUS
|
||||
SpiBuildDeviceMap(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
_In_ PUNICODE_STRING RegistryPath);
|
||||
|
||||
// scsi.c
|
||||
|
||||
VOID
|
||||
SpiGetNextRequestFromLun(
|
||||
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
_Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension);
|
||||
|
||||
IO_DPC_ROUTINE ScsiPortDpcForIsr;
|
||||
DRIVER_DISPATCH ScsiPortDispatchScsi;
|
||||
KSYNCHRONIZE_ROUTINE ScsiPortStartPacket;
|
||||
DRIVER_STARTIO ScsiPortStartIo;
|
||||
|
||||
|
||||
// scsiport.c
|
||||
|
||||
KSERVICE_ROUTINE ScsiPortIsr;
|
||||
|
||||
IO_ALLOCATION_ACTION
|
||||
NTAPI
|
||||
SpiAdapterControl(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_ PIRP Irp,
|
||||
_In_ PVOID MapRegisterBase,
|
||||
_In_ PVOID Context);
|
||||
|
||||
IO_ALLOCATION_ACTION
|
||||
NTAPI
|
||||
ScsiPortAllocateAdapterChannel(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_ PIRP Irp,
|
||||
_In_ PVOID MapRegisterBase,
|
||||
_In_ PVOID Context);
|
||||
|
|
Loading…
Reference in a new issue