[STORPORT] Improvements to the device enumerator code.
authorEric Kohl <eric.kohl@reactos.org>
Thu, 27 Jun 2019 21:05:46 +0000 (23:05 +0200)
committerEric Kohl <eric.kohl@reactos.org>
Thu, 27 Jun 2019 21:28:41 +0000 (23:28 +0200)
- Create PDO for the device
- Send a SCSIOP_INQUIRY command to the new PDO
- Delete the PDO if the inquiry command failed

drivers/storage/port/storport/fdo.c
drivers/storage/port/storport/pdo.c
drivers/storage/port/storport/precomp.h
drivers/storage/port/storport/storport.c

index a2be47c..bf1ff41 100644 (file)
@@ -243,64 +243,75 @@ PortFdoStartDevice(
 }
 
 
-static NTSTATUS
+static
+NTSTATUS
 PortSendInquiry(
-    _In_ PDEVICE_OBJECT DeviceObject,
-    _In_ ULONG Bus,
-    _In_ ULONG Target,
-    _In_ ULONG Lun)
+    _In_ PPDO_DEVICE_EXTENSION PdoExtension)
 {
-    PINQUIRYDATA InquiryBuffer;
-    PUCHAR /*PSENSE_DATA*/ SenseBuffer;
+    IO_STATUS_BLOCK IoStatusBlock;
+    PIO_STACK_LOCATION IrpStack;
+    KEVENT Event;
+//    KIRQL Irql;
+    PIRP Irp;
+    NTSTATUS Status;
+    PSENSE_DATA SenseBuffer;
     BOOLEAN KeepTrying = TRUE;
     ULONG RetryCount = 0;
     SCSI_REQUEST_BLOCK Srb;
     PCDB Cdb;
-    PFDO_DEVICE_EXTENSION DeviceExtension;
-    PVOID SrbExtension = NULL;
-    BOOLEAN ret;
-    PUNIT_DATA UnitData;
-    NTSTATUS Status;
+//    PSCSI_PORT_LUN_EXTENSION LunExtension;
+//    PFDO_DEVICE_EXTENSION DeviceExtension;
 
-    DPRINT("PortSendInquiry(%p %lu %lu %lu)\n",
-           DeviceObject, Bus, Target, Lun);
-
-    DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    DPRINT("PortSendInquiry(%p)\n", PdoExtension);
 
-    InquiryBuffer = ExAllocatePoolWithTag(NonPagedPool, INQUIRYDATABUFFERSIZE, TAG_INQUIRY_DATA);
-    if (InquiryBuffer == NULL)
-        return STATUS_INSUFFICIENT_RESOURCES;
+    if (PdoExtension->InquiryBuffer == NULL)
+    {
+        PdoExtension->InquiryBuffer = ExAllocatePoolWithTag(NonPagedPool, INQUIRYDATABUFFERSIZE, TAG_INQUIRY_DATA);
+        if (PdoExtension->InquiryBuffer == NULL)
+            return STATUS_INSUFFICIENT_RESOURCES;
+    }
 
     SenseBuffer = ExAllocatePoolWithTag(NonPagedPool, SENSE_BUFFER_SIZE, TAG_SENSE_DATA);
     if (SenseBuffer == NULL)
     {
-        ExFreePoolWithTag(InquiryBuffer, TAG_INQUIRY_DATA);
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
-    if (DeviceExtension->Miniport.PortConfig.SrbExtensionSize != 0)
+    while (KeepTrying)
     {
-        SrbExtension = ExAllocatePoolWithTag(NonPagedPool,
-                                             DeviceExtension->Miniport.PortConfig.SrbExtensionSize,
-                                             TAG_SENSE_DATA);
-        if (SrbExtension == NULL)
+        /* Initialize event for waiting */
+        KeInitializeEvent(&Event,
+                          NotificationEvent,
+                          FALSE);
+
+        /* Create an IRP */
+        Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_IN,
+                                            PdoExtension->Device,
+                                            NULL,
+                                            0,
+                                            PdoExtension->InquiryBuffer,
+                                            INQUIRYDATABUFFERSIZE,
+                                            TRUE,
+                                            &Event,
+                                            &IoStatusBlock);
+        if (Irp == NULL)
         {
-            ExFreePoolWithTag(SenseBuffer, TAG_SENSE_DATA);
-            ExFreePoolWithTag(InquiryBuffer, TAG_INQUIRY_DATA);
-            return STATUS_INSUFFICIENT_RESOURCES;
+            DPRINT("IoBuildDeviceIoControlRequest() failed\n");
+
+            /* Quit the loop */
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            KeepTrying = FALSE;
+            continue;
         }
-    }
 
-    while (KeepTrying)
-    {
         /* Prepare SRB */
         RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK));
 
         Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
-//        Srb.OriginalRequest = Irp;
-        Srb.PathId = Bus;
-        Srb.TargetId = Target;
-        Srb.Lun = Lun;
+        Srb.OriginalRequest = Irp;
+        Srb.PathId = PdoExtension->Bus;
+        Srb.TargetId = PdoExtension->Target;
+        Srb.Lun = PdoExtension->Lun;
         Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
         Srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
         Srb.TimeOutValue = 4;
@@ -309,52 +320,40 @@ PortSendInquiry(
         Srb.SenseInfoBuffer = SenseBuffer;
         Srb.SenseInfoBufferLength = SENSE_BUFFER_SIZE;
 
-        Srb.DataBuffer = InquiryBuffer;
+        Srb.DataBuffer = PdoExtension->InquiryBuffer;
         Srb.DataTransferLength = INQUIRYDATABUFFERSIZE;
 
-        Srb.SrbExtension = SrbExtension;
+        /* Attach Srb to the Irp */
+        IrpStack = IoGetNextIrpStackLocation(Irp);
+        IrpStack->Parameters.Scsi.Srb = &Srb;
 
         /* Fill in CDB */
         Cdb = (PCDB)Srb.Cdb;
-        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);
-        if (ret == FALSE)
+        Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
+        Cdb->CDB6INQUIRY.LogicalUnitNumber = PdoExtension->Lun;
+        Cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
+
+        /* Call the driver */
+        Status = IoCallDriver(PdoExtension->Device, Irp);
+
+        /* Wait for it to complete */
+        if (Status == STATUS_PENDING)
         {
-            Status = STATUS_IO_DEVICE_ERROR;
-            KeepTrying = FALSE;
-            continue;
+            DPRINT1("PortSendInquiry(): Waiting for the driver to process request...\n");
+            KeWaitForSingleObject(&Event,
+                                  Executive,
+                                  KernelMode,
+                                  FALSE,
+                                  NULL);
+            Status = IoStatusBlock.Status;
         }
 
-        DPRINT("SrbStatus 0x%08lx\n", Srb.SrbStatus);
+        DPRINT("PortSendInquiry(): Request processed by driver, status = 0x%08X\n", Status);
+
         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(&UnitData->InquiryData,
-                          Srb.DataBuffer,
-                          Srb.DataTransferLength);
-
-            InsertTailList(&DeviceExtension->UnitListHead,
-                           &UnitData->ListEntry);
-            DeviceExtension->UnitCount++;
-
             /* Quit the loop */
             Status = STATUS_SUCCESS;
             KeepTrying = FALSE;
@@ -363,84 +362,151 @@ PortSendInquiry(
 
         DPRINT("Inquiry SRB failed with SrbStatus 0x%08X\n", Srb.SrbStatus);
 
-        /* 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))
+        /* Check if the queue is frozen */
+        if (Srb.SrbStatus & SRB_STATUS_QUEUE_FROZEN)
         {
-            RetryCount++;
-            KeepTrying = TRUE;
+            /* 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);
         }
-        else
+
+        /* Check if data overrun happened */
+        if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN)
         {
-            /* That's all, quit the loop */
+            DPRINT("Data overrun at TargetId %d\n", PdoExtension->Target);
+
+            /* 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 */
 
-            /* 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)
+            /* 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))
             {
-                Status = STATUS_INVALID_DEVICE_REQUEST;
+                RetryCount++;
+                KeepTrying = TRUE;
             }
             else
             {
-                Status = STATUS_IO_DEVICE_ERROR;
+                /* 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 */
-    if (SrbExtension != NULL)
-        ExFreePoolWithTag(SrbExtension, TAG_SENSE_DATA);
-
+    /* Free the sense buffer */
     ExFreePoolWithTag(SenseBuffer, TAG_SENSE_DATA);
-    ExFreePoolWithTag(InquiryBuffer, TAG_INQUIRY_DATA);
 
-    DPRINT("PortSendInquiry() returns 0x%08lx\n", Status);
+    DPRINT("PortSendInquiry() done with Status 0x%08X\n", Status);
 
     return Status;
 }
 
 
+
 static
 NTSTATUS
 PortFdoScanBus(
     _In_ PFDO_DEVICE_EXTENSION DeviceExtension)
 {
-    ULONG Bus, Target, Lun;
+    PPDO_DEVICE_EXTENSION PdoExtension;
+    ULONG Bus, Target; //, Lun;
     NTSTATUS Status;
 
-    DPRINT1("PortFdoScanBus(%p)\n",
-            DeviceExtension);
+    DPRINT("PortFdoScanBus(%p)\n", DeviceExtension);
 
-    DPRINT1("NumberOfBuses: %lu\n", DeviceExtension->Miniport.PortConfig.NumberOfBuses);
-    DPRINT1("MaximumNumberOfTargets: %lu\n", DeviceExtension->Miniport.PortConfig.MaximumNumberOfTargets);
-    DPRINT1("MaximumNumberOfLogicalUnits: %lu\n", DeviceExtension->Miniport.PortConfig.MaximumNumberOfLogicalUnits);
+    DPRINT("NumberOfBuses: %lu\n", DeviceExtension->Miniport.PortConfig.NumberOfBuses);
+    DPRINT("MaximumNumberOfTargets: %lu\n", DeviceExtension->Miniport.PortConfig.MaximumNumberOfTargets);
+    DPRINT("MaximumNumberOfLogicalUnits: %lu\n", DeviceExtension->Miniport.PortConfig.MaximumNumberOfLogicalUnits);
 
     /* Scan all buses */
     for (Bus = 0; Bus < DeviceExtension->Miniport.PortConfig.NumberOfBuses; Bus++)
     {
-        DPRINT1("Scanning bus %ld\n", Bus);
+        DPRINT("Scanning bus %ld\n", Bus);
 
         /* Scan all targets */
         for (Target = 0; Target < DeviceExtension->Miniport.PortConfig.MaximumNumberOfTargets; Target++)
         {
-            DPRINT1("  Scanning target %ld:%ld\n", Bus, Target);
+            DPRINT("  Scanning target %ld:%ld\n", Bus, Target);
 
-            /* Scan all logical units */
-            for (Lun = 0; Lun < DeviceExtension->Miniport.PortConfig.MaximumNumberOfLogicalUnits; Lun++)
+            DPRINT("    Scanning logical unit %ld:%ld:%ld\n", Bus, Target, 0);
+            Status = PortCreatePdo(DeviceExtension, Bus, Target, 0, &PdoExtension);
+            if (NT_SUCCESS(Status))
             {
-                DPRINT1("    Scanning logical unit %ld:%ld:%ld\n", Bus, Target, Lun);
+                /* Scan LUN 0 */
+                Status = PortSendInquiry(PdoExtension);
+                DPRINT("PortSendInquiry returned 0x%08lx\n", Status);
+                if (!NT_SUCCESS(Status))
+                {
+                    PortDeletePdo(PdoExtension);
+                }
+                else
+                {
+                    DPRINT("VendorId: %.8s\n", PdoExtension->InquiryBuffer->VendorId);
+                    DPRINT("ProductId: %.16s\n", PdoExtension->InquiryBuffer->ProductId);
+                    DPRINT("ProductRevisionLevel: %.4s\n", PdoExtension->InquiryBuffer->ProductRevisionLevel);
+                    DPRINT("VendorSpecific: %.20s\n", PdoExtension->InquiryBuffer->VendorSpecific);
+                }
+            }
 
+#if 0
+            /* Scan all logical units */
+            for (Lun = 1; Lun < DeviceExtension->Miniport.PortConfig.MaximumNumberOfLogicalUnits; Lun++)
+            {
+                DPRINT("    Scanning logical unit %ld:%ld:%ld\n", Bus, Target, Lun);
                 Status = PortSendInquiry(DeviceExtension->Device, Bus, Target, Lun);
-                DPRINT1("PortSendInquiry returned 0x%08lx\n", Status);
+                DPRINT("PortSendInquiry returned 0x%08lx\n", Status);
                 if (!NT_SUCCESS(Status))
                     break;
             }
+#endif
         }
     }
 
-    DPRINT("Done!\n");
+    DPRINT("PortFdoScanBus() done!\n");
 
     return STATUS_SUCCESS;
 }
@@ -459,7 +525,7 @@ PortFdoQueryBusRelations(
 
     Status = PortFdoScanBus(DeviceExtension);
 
-    DPRINT1("Units found: %lu\n", DeviceExtension->UnitCount);
+    DPRINT1("Units found: %lu\n", DeviceExtension->PdoCount);
 
     *Information = 0;
 
@@ -500,8 +566,7 @@ PortFdoScsi(
     ULONG_PTR Information = 0;
     NTSTATUS Status = STATUS_NOT_SUPPORTED;
 
-    DPRINT1("PortFdoScsi(%p %p)\n",
-            DeviceObject, Irp);
+    DPRINT("PortFdoScsi(%p %p)\n", DeviceObject, Irp);
 
     DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
     ASSERT(DeviceExtension);
index 8df3151..5ed727c 100644 (file)
 
 /* FUNCTIONS ******************************************************************/
 
+NTSTATUS
+PortCreatePdo(
+    _In_ PFDO_DEVICE_EXTENSION FdoDeviceExtension,
+    _In_ ULONG Bus,
+    _In_ ULONG Target,
+    _In_ ULONG Lun,
+    _Out_ PPDO_DEVICE_EXTENSION *PdoDeviceExtension)
+{
+    PPDO_DEVICE_EXTENSION DeviceExtension = NULL;
+    PDEVICE_OBJECT Pdo = NULL;
+    KLOCK_QUEUE_HANDLE LockHandle;
+    NTSTATUS Status;
+
+    DPRINT("PortCreatePdo(%p %p)\n",
+           FdoDeviceExtension, PdoDeviceExtension);
+
+    /* Create the port device */
+    Status = IoCreateDevice(FdoDeviceExtension->Device->DriverObject,
+                            sizeof(PDO_DEVICE_EXTENSION),
+                            NULL,
+                            FILE_DEVICE_MASS_STORAGE,
+                            FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,
+                            FALSE,
+                            &Pdo);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("IoCreateDevice() failed (Status 0x%lX)\n", Status);
+        return Status;
+    }
+
+    /* Initialize the device */
+    Pdo->Flags |= DO_DIRECT_IO;
+    Pdo->Flags |= DO_POWER_PAGABLE;
+
+    DeviceExtension = (PPDO_DEVICE_EXTENSION)Pdo->DeviceExtension;
+    RtlZeroMemory(DeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
+
+    DeviceExtension->ExtensionType = PdoExtension;
+
+    DeviceExtension->Device = Pdo;
+    DeviceExtension->FdoExtension = FdoDeviceExtension;
+    DeviceExtension->PnpState = dsStopped;
+
+    /* Add the PDO to the PDO list*/
+    KeAcquireInStackQueuedSpinLock(&FdoDeviceExtension->PdoListLock,
+                                   &LockHandle);
+    InsertHeadList(&FdoDeviceExtension->PdoListHead,
+                   &DeviceExtension->PdoListEntry);
+    FdoDeviceExtension->PdoCount++;
+    KeReleaseInStackQueuedSpinLock(&LockHandle);
+
+    DeviceExtension->Bus = Bus;
+    DeviceExtension->Target = Target;
+    DeviceExtension->Lun = Lun;
+
+
+    // FIXME: More initialization
+
+
+    /* The device has been initialized */
+    Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
+
+    *PdoDeviceExtension = DeviceExtension;
+
+    return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+PortDeletePdo(
+    _In_ PPDO_DEVICE_EXTENSION PdoExtension)
+{
+    KLOCK_QUEUE_HANDLE LockHandle;
+
+    DPRINT("PortDeletePdo(%p)\n", PdoExtension);
+
+    /* Remove the PDO from the PDO list*/
+    KeAcquireInStackQueuedSpinLock(&PdoExtension->FdoExtension->PdoListLock,
+                                   &LockHandle);
+    RemoveEntryList(&PdoExtension->PdoListEntry);
+    PdoExtension->FdoExtension->PdoCount--;
+    KeReleaseInStackQueuedSpinLock(&LockHandle);
+
+    if (PdoExtension->InquiryBuffer)
+    {
+        ExFreePoolWithTag(PdoExtension->InquiryBuffer, TAG_INQUIRY_DATA);
+        PdoExtension->InquiryBuffer = NULL;
+    }
+
+
+    // FIXME: More uninitialization
+
+
+    /* Delete the PDO */
+    IoDeleteDevice(PdoExtension->Device);
+
+    return STATUS_SUCCESS;
+}
+
+
 NTSTATUS
 NTAPI
 PortPdoScsi(
     _In_ PDEVICE_OBJECT DeviceObject,
     _In_ PIRP Irp)
 {
-    DPRINT1("PortPdoScsi()\n");
+    DPRINT1("PortPdoScsi(%p %p)\n", DeviceObject, Irp);
 
     Irp->IoStatus.Information = 0;
     Irp->IoStatus.Status = STATUS_SUCCESS;
@@ -36,7 +136,7 @@ PortPdoPnp(
     _In_ PDEVICE_OBJECT DeviceObject,
     _In_ PIRP Irp)
 {
-    DPRINT1("PortPdoPnp()\n");
+    DPRINT1("PortPdoPnp(%p %p)\n", DeviceObject, Irp);
 
     Irp->IoStatus.Information = 0;
     Irp->IoStatus.Status = STATUS_SUCCESS;
index 046dd0b..6f3436a 100644 (file)
@@ -112,8 +112,9 @@ typedef struct _FDO_DEVICE_EXTENSION
     PKINTERRUPT Interrupt;
     ULONG InterruptIrql;
 
-    ULONG UnitCount;
-    LIST_ENTRY UnitListHead;
+    KSPIN_LOCK PdoListLock;
+    LIST_ENTRY PdoListHead;
+    ULONG PdoCount;
 } FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
 
 
@@ -121,9 +122,16 @@ typedef struct _PDO_DEVICE_EXTENSION
 {
     EXTENSION_TYPE ExtensionType;
 
-    PDEVICE_OBJECT AttachedFdo;
-
+    PDEVICE_OBJECT Device;
+    PFDO_DEVICE_EXTENSION FdoExtension;
     DEVICE_STATE PnpState;
+    LIST_ENTRY PdoListEntry;
+
+    ULONG Bus;
+    ULONG Target;
+    ULONG Lun;
+    PINQUIRYDATA InquiryBuffer;
+
 
 } PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
 
@@ -228,6 +236,18 @@ AllocateAddressMapping(
 
 /* pdo.c */
 
+NTSTATUS
+PortCreatePdo(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension,
+    _In_ ULONG Bus,
+    _In_ ULONG Target,
+    _In_ ULONG Lun,
+    _Out_ PPDO_DEVICE_EXTENSION *PdoExtension);
+
+NTSTATUS
+PortDeletePdo(
+    _In_ PPDO_DEVICE_EXTENSION PdoExtension);
+
 NTSTATUS
 NTAPI
 PortPdoScsi(
index 5bed391..14cd6c7 100644 (file)
@@ -223,7 +223,8 @@ PortAddDevice(
 
     DeviceExtension->PnpState = dsStopped;
 
-    InitializeListHead(&DeviceExtension->UnitListHead);
+    KeInitializeSpinLock(&DeviceExtension->PdoListLock);
+    InitializeListHead(&DeviceExtension->PdoListHead);
 
     /* Attach the FDO to the device stack */
     Status = IoAttachDeviceToDeviceStackSafe(Fdo,