[STORPORT] Detect attached devices

This commit is contained in:
Eric Kohl 2019-06-02 23:30:02 +02:00
parent fd4752450f
commit be88574f59
3 changed files with 95 additions and 150 deletions

View file

@ -244,29 +244,26 @@ PortFdoStartDevice(
static NTSTATUS
SpiSendInquiry(IN PDEVICE_OBJECT DeviceObject,
ULONG Bus, ULONG Target, ULONG Lun)
PortSendInquiry(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ ULONG Bus,
_In_ ULONG Target,
_In_ ULONG Lun)
{
// IO_STATUS_BLOCK IoStatusBlock;
// PIO_STACK_LOCATION IrpStack;
// KEVENT Event;
// KIRQL Irql;
// PIRP Irp;
NTSTATUS Status;
PINQUIRYDATA InquiryBuffer;
PUCHAR /*PSENSE_DATA*/ SenseBuffer;
// BOOLEAN KeepTrying = TRUE;
// ULONG RetryCount = 0;
BOOLEAN KeepTrying = TRUE;
ULONG RetryCount = 0;
SCSI_REQUEST_BLOCK Srb;
PCDB Cdb;
// PSCSI_PORT_LUN_EXTENSION LunExtension;
// PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
PFDO_DEVICE_EXTENSION DeviceExtension;
PFDO_DEVICE_EXTENSION DeviceExtension;
PVOID SrbExtension = NULL;
BOOLEAN ret;
PUNIT_DATA UnitData;
NTSTATUS Status;
DPRINT1("SpiSendInquiry() called\n");
DPRINT("PortSendInquiry(%p %lu %lu %lu)\n",
DeviceObject, Bus, Target, Lun);
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
@ -283,7 +280,9 @@ PFDO_DEVICE_EXTENSION DeviceExtension;
if (DeviceExtension->Miniport.PortConfig.SrbExtensionSize != 0)
{
SrbExtension = ExAllocatePoolWithTag(NonPagedPool, DeviceExtension->Miniport.PortConfig.SrbExtensionSize, TAG_SENSE_DATA);
SrbExtension = ExAllocatePoolWithTag(NonPagedPool,
DeviceExtension->Miniport.PortConfig.SrbExtensionSize,
TAG_SENSE_DATA);
if (SrbExtension == NULL)
{
ExFreePoolWithTag(SenseBuffer, TAG_SENSE_DATA);
@ -292,33 +291,8 @@ PFDO_DEVICE_EXTENSION DeviceExtension;
}
}
// while (KeepTrying)
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)
// {
// DPRINT1("IoBuildDeviceIoControlRequest() failed\n");
/* Quit the loop */
// Status = STATUS_INSUFFICIENT_RESOURCES;
// KeepTrying = FALSE;
// continue;
// }
/* Prepare SRB */
RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK));
@ -340,134 +314,79 @@ PFDO_DEVICE_EXTENSION DeviceExtension;
Srb.SrbExtension = SrbExtension;
/* 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 = Lun;
Cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
/* Call the driver */
Cdb->CDB6INQUIRY3.OperationCode = SCSIOP_INQUIRY;
Cdb->CDB6INQUIRY3.EnableVitalProductData = 1;
Cdb->CDB6INQUIRY3.CommandSupportData = 0;
Cdb->CDB6INQUIRY3.PageCode = 0; //??
Cdb->CDB6INQUIRY3.AllocationLength = INQUIRYDATABUFFERSIZE;
Cdb->CDB6INQUIRY3.Control = 0;
/* Call the miniport driver */
ret = MiniportStartIo(&DeviceExtension->Miniport,
&Srb);
DPRINT1("MiniportStartIo returned %u\n", ret);
// Status = IoCallDriver(DeviceObject, Irp);
/* Wait for it to complete */
// if (Status == STATUS_PENDING)
// {
// DPRINT1("SpiSendInquiry(): Waiting for the driver to process request...\n");
// KeWaitForSingleObject(&Event,
// Executive,
// KernelMode,
// FALSE,
// NULL);
// Status = IoStatusBlock.Status;
// }
// DPRINT1("SpiSendInquiry(): Request processed by driver, status = 0x%08X\n", Status);
if (ret == FALSE)
{
Status = STATUS_IO_DEVICE_ERROR;
KeepTrying = FALSE;
continue;
}
DPRINT("SrbStatus 0x%08lx\n", Srb.SrbStatus);
if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_SUCCESS)
{
DPRINT("Found a device!\n");
UnitData = ExAllocatePool(NonPagedPool, sizeof(UNIT_DATA));
if (UnitData == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
KeepTrying = FALSE;
continue;
}
/* All fine, copy data over */
// RtlCopyMemory(LunInfo->InquiryData,
// InquiryBuffer,
// INQUIRYDATABUFFERSIZE);
RtlCopyMemory(&UnitData->InquiryData,
Srb.DataBuffer,
Srb.DataTransferLength);
InsertTailList(&DeviceExtension->UnitListHead,
&UnitData->ListEntry);
DeviceExtension->UnitCount++;
/* Quit the loop */
Status = STATUS_SUCCESS;
// KeepTrying = FALSE;
// continue;
KeepTrying = FALSE;
continue;
}
DPRINT("Inquiry SRB failed with SrbStatus 0x%08X\n", Srb.SrbStatus);
#if 0
/* Check if the queue is frozen */
if (Srb.SrbStatus & SRB_STATUS_QUEUE_FROZEN)
/* 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))
{
/* 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;
RetryCount++;
KeepTrying = TRUE;
}
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))
/* 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)
{
RetryCount++;
KeepTrying = TRUE;
Status = STATUS_INVALID_DEVICE_REQUEST;
}
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;
}
Status = STATUS_IO_DEVICE_ERROR;
}
}
#endif
}
/* Free buffers */
@ -477,7 +396,7 @@ DPRINT1("MiniportStartIo returned %u\n", ret);
ExFreePoolWithTag(SenseBuffer, TAG_SENSE_DATA);
ExFreePoolWithTag(InquiryBuffer, TAG_INQUIRY_DATA);
DPRINT("SpiSendInquiry() done with Status 0x%08X\n", Status);
DPRINT("PortSendInquiry() returns 0x%08lx\n", Status);
return Status;
}
@ -491,7 +410,6 @@ PortFdoScanBus(
ULONG Bus, Target, Lun;
NTSTATUS Status;
DPRINT1("PortFdoScanBus(%p)\n",
DeviceExtension);
@ -514,13 +432,15 @@ PortFdoScanBus(
{
DPRINT1(" Scanning logical unit %ld:%ld:%ld\n", Bus, Target, Lun);
Status = SpiSendInquiry(DeviceExtension->Device, Bus, Target, Lun);
DPRINT1("SpiSendInquiry returned 0x%08lx\n", Status);
Status = PortSendInquiry(DeviceExtension->Device, Bus, Target, Lun);
DPRINT1("PortSendInquiry returned 0x%08lx\n", Status);
if (!NT_SUCCESS(Status))
break;
}
}
}
DPRINT1("Done!\n");
DPRINT("Done!\n");
return STATUS_SUCCESS;
}
@ -539,6 +459,8 @@ PortFdoQueryBusRelations(
Status = PortFdoScanBus(DeviceExtension);
DPRINT1("Units found: %lu\n", DeviceExtension->UnitCount);
*Information = 0;
return Status;

View file

@ -81,6 +81,12 @@ typedef struct _MINIPORT
PMINIPORT_DEVICE_EXTENSION MiniportExtension;
} MINIPORT, *PMINIPORT;
typedef struct _UNIT_DATA
{
LIST_ENTRY ListEntry;
INQUIRYDATA InquiryData;
} UNIT_DATA, *PUNIT_DATA;
typedef struct _FDO_DEVICE_EXTENSION
{
EXTENSION_TYPE ExtensionType;
@ -105,6 +111,9 @@ typedef struct _FDO_DEVICE_EXTENSION
PHW_PASSIVE_INITIALIZE_ROUTINE HwPassiveInitRoutine;
PKINTERRUPT Interrupt;
ULONG InterruptIrql;
ULONG UnitCount;
LIST_ENTRY UnitListHead;
} FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;

View file

@ -223,6 +223,8 @@ PortAddDevice(
DeviceExtension->PnpState = dsStopped;
InitializeListHead(&DeviceExtension->UnitListHead);
/* Attach the FDO to the device stack */
Status = IoAttachDeviceToDeviceStackSafe(Fdo,
PhysicalDeviceObject,
@ -1104,6 +1106,7 @@ StorPortNotification(
STOR_SPINLOCK SpinLock;
PVOID LockContext;
PSTOR_LOCK_HANDLE LockHandle;
PSCSI_REQUEST_BLOCK Srb;
DPRINT1("StorPortNotification(%x %p)\n",
NotificationType, HwDeviceExtension);
@ -1124,6 +1127,17 @@ StorPortNotification(
switch (NotificationType)
{
case RequestComplete:
DPRINT1("RequestComplete\n");
Srb = (PSCSI_REQUEST_BLOCK)va_arg(ap, PSCSI_REQUEST_BLOCK);
DPRINT1("Srb %p\n", Srb);
if (Srb->OriginalRequest != NULL)
{
DPRINT1("Need to complete the IRP!\n");
}
break;
case GetExtendedFunctionTable:
DPRINT1("GetExtendedFunctionTable\n");
ppExtendedFunctions = (PSTORPORT_EXTENDED_FUNCTIONS*)va_arg(ap, PSTORPORT_EXTENDED_FUNCTIONS*);