From be88574f5953bfc3e08f1ed7c094387adc34cf7e Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sun, 2 Jun 2019 23:30:02 +0200 Subject: [PATCH] [STORPORT] Detect attached devices --- drivers/storage/port/storport/fdo.c | 222 ++++++++--------------- drivers/storage/port/storport/precomp.h | 9 + drivers/storage/port/storport/storport.c | 14 ++ 3 files changed, 95 insertions(+), 150 deletions(-) diff --git a/drivers/storage/port/storport/fdo.c b/drivers/storage/port/storport/fdo.c index e20fd68bcc2..a2be47c30e0 100644 --- a/drivers/storage/port/storport/fdo.c +++ b/drivers/storage/port/storport/fdo.c @@ -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; diff --git a/drivers/storage/port/storport/precomp.h b/drivers/storage/port/storport/precomp.h index 84925ef1bc6..046dd0b186a 100644 --- a/drivers/storage/port/storport/precomp.h +++ b/drivers/storage/port/storport/precomp.h @@ -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; diff --git a/drivers/storage/port/storport/storport.c b/drivers/storage/port/storport/storport.c index 03ec5639491..5bed3915af7 100644 --- a/drivers/storage/port/storport/storport.c +++ b/drivers/storage/port/storport/storport.c @@ -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*);