コード例 #1
0
ファイル: fdo.c プロジェクト: hoangduit/reactos
NTSTATUS
NTAPI
PciFdoIrpQueryCapabilities(IN PIRP Irp,
                           IN PIO_STACK_LOCATION IoStackLocation,
                           IN PPCI_FDO_EXTENSION DeviceExtension)
{
    PDEVICE_CAPABILITIES Capabilities;
    PAGED_CODE();
    ASSERT_FDO(DeviceExtension);

    UNREFERENCED_PARAMETER(Irp);

    /* Get the capabilities */
    Capabilities = IoStackLocation->Parameters.DeviceCapabilities.Capabilities;

    /* Inherit wake levels and power mappings from the higher-up capabilities */
    DeviceExtension->PowerState.SystemWakeLevel = Capabilities->SystemWake;
    DeviceExtension->PowerState.DeviceWakeLevel = Capabilities->DeviceWake;
    RtlCopyMemory(DeviceExtension->PowerState.SystemStateMapping,
                  Capabilities->DeviceState,
                  sizeof(DeviceExtension->PowerState.SystemStateMapping));

    /* Dump the capabilities and return success */
    PciDebugDumpQueryCapabilities(Capabilities);
    return STATUS_SUCCESS;
}
コード例 #2
0
ファイル: dispatch.c プロジェクト: hoangduit/reactos
NTSTATUS
NTAPI
PciCallDownIrpStack(IN PPCI_FDO_EXTENSION DeviceExtension,
                    IN PIRP Irp)
{
    NTSTATUS Status;
    KEVENT Event;
    PAGED_CODE();
    DPRINT1("PciCallDownIrpStack ...\n");
    ASSERT_FDO(DeviceExtension);

    /* Initialize the wait event */
    KeInitializeEvent(&Event, SynchronizationEvent, 0);

    /* Setup a completion routine */
    IoCopyCurrentIrpStackLocationToNext(Irp);
    IoSetCompletionRoutine(Irp, PciSetEventCompletion, &Event, TRUE, TRUE, TRUE);

    /* Call the attached device */
    Status = IoCallDriver(DeviceExtension->AttachedDeviceObject, Irp);
    if (Status == STATUS_PENDING)
    {
        /* Wait for it to complete the request, and get its status */
        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
        Status = Irp->IoStatus.Status;
    }

    /* Return that status back to the caller */
    return Status;
}
コード例 #3
0
ファイル: tr_irq.c プロジェクト: hoangduit/reactos
NTSTATUS
NTAPI
tranirq_Constructor(IN PVOID DeviceExtension,
                    IN PVOID Instance,
                    IN PVOID InterfaceData,
                    IN USHORT Version,
                    IN USHORT Size,
                    IN PINTERFACE Interface)
{
    PPCI_FDO_EXTENSION FdoExtension = (PPCI_FDO_EXTENSION)DeviceExtension;
    ULONG BaseBus, ParentBus;
    INTERFACE_TYPE ParentInterface;
    ASSERT_FDO(FdoExtension);

    UNREFERENCED_PARAMETER(Instance);
    UNREFERENCED_PARAMETER(Version);
    UNREFERENCED_PARAMETER(Size);

    /* Make sure it's the right resource type */
    if ((ULONG)InterfaceData != CmResourceTypeInterrupt)
    {
        /* Fail this invalid request */
        DPRINT1("PCI - IRQ trans constructor doesn't like %p in InterfaceSpecificData\n",
                InterfaceData);
        return STATUS_INVALID_PARAMETER_3;
    }

    /* Get the bus, and use this as the interface-specific data */
    BaseBus = FdoExtension->BaseBus;
    InterfaceData = (PVOID)BaseBus;

    /* Check if this is the root bus */
    if (PCI_IS_ROOT_FDO(FdoExtension))
    {
        /* It is, so there is no parent, and it's connected on the system bus */
        ParentBus = 0;
        ParentInterface = Internal;
        DPRINT1("      Is root FDO\n");
    }
    else
    {
        /* It's not, so we have to get the root bus' bus number instead */
        #if 0 // when have PDO commit
        ParentBus = FdoExtension->PhysicalDeviceObject->DeviceExtension->ParentFdoExtension->BaseBus;
        ParentInterface = PCIBus;
        DPRINT1("      Is bridge FDO, parent bus %x, secondary bus %x\n",
                ParentBus, BaseBus);
        #endif
    }

    /* Now call the legacy HAL interface to get the correct translator */
    return HalGetInterruptTranslator(ParentInterface,
                                     ParentBus,
                                     PCIBus,
                                     sizeof(TRANSLATOR_INTERFACE),
                                     0,
                                     (PTRANSLATOR_INTERFACE)Interface,
                                     (PULONG)&InterfaceData);
}
コード例 #4
0
ファイル: geometry.c プロジェクト: hoangduit/reactos
NTSTATUS
NTAPI
DiskUpdateRemovableGeometry (
    IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
    )

/*++

Routine Description:

    This routine updates the geometry of the disk.  It will query the port 
    driver to see if it can provide any geometry info.  If not it will use 
    the current head & sector count.
    
    Based on these values & the capacity of the drive as reported by 
    ClassReadDriveCapacity it will determine a new cylinder count for the 
    device.

Arguments:

    Fdo - Supplies the functional device object whos size needs to be updated.

Return Value:

    Returns the status of the opertion.

--*/
{
    PCOMMON_DEVICE_EXTENSION commonExtension = &(FdoExtension->CommonExtension);
    PDISK_DATA diskData = commonExtension->DriverData;
    PDISK_GEOMETRY geometry = &(diskData->RealGeometry);

    NTSTATUS status;

    PAGED_CODE();

    ASSERT_FDO(commonExtension->DeviceObject);
    if (FdoExtension->DeviceDescriptor) {
        ASSERT(FdoExtension->DeviceDescriptor->RemovableMedia);
    }
    ASSERT(TEST_FLAG(FdoExtension->DeviceObject->Characteristics,
                     FILE_REMOVABLE_MEDIA));

    //
    // Attempt to determine the disk geometry.  First we'll check with the 
    // port driver to see what it suggests for a value.
    //

    status = DiskGetPortGeometry(FdoExtension, geometry);

    if(NT_SUCCESS(status) && 
       ((geometry->TracksPerCylinder * geometry->SectorsPerTrack) != 0)) {

        FdoExtension->DiskGeometry = (*geometry);
    }

    return status;
}
コード例 #5
0
ファイル: enum.c プロジェクト: hoangduit/reactos
VOID
NTAPI
DiskReleasePartitioningLock(
    IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
    )
{
    PDISK_DATA diskData = FdoExtension->CommonExtension.DriverData;

    PAGED_CODE();

    ASSERT_FDO(FdoExtension->DeviceObject);

    KeSetEvent(&(diskData->PartitioningEvent), IO_NO_INCREMENT, FALSE);
    return;
}
コード例 #6
0
ファイル: geometry.c プロジェクト: hoangduit/reactos
NTSTATUS
NTAPI
DiskReadDriveCapacity(
    IN PDEVICE_OBJECT Fdo
    )
/*++

Routine Description:

    This routine is used by disk.sys as a wrapper for the classpnp API 
    ClassReadDriveCapacity.  It will perform some additional operations to 
    attempt to determine drive geometry before it calls the classpnp version 
    of the routine.
    
    For fixed disks this involves calling DiskUpdateGeometry which will check 
    various sources (the BIOS, the port driver) for geometry information.
    
Arguments:

    Fdo - a pointer to the device object to be checked.    

Return Value:

    status of ClassReadDriveCapacity.
    
--*/        

{
    PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
    //PDISK_DATA diskData = fdoExtension->CommonExtension.DriverData;
    //DISK_GEOMETRY_SOURCE diskGeometrySource = DiskGeometryUnknown;
    NTSTATUS status;

    ASSERT_FDO(Fdo);

    if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
        DiskUpdateRemovableGeometry(fdoExtension);
    } else {
        /* diskGeometrySource =*/ DiskUpdateGeometry(fdoExtension);
    }

    status = ClassReadDriveCapacity(Fdo);

    return status;
}
コード例 #7
0
ファイル: enum.c プロジェクト: hoangduit/reactos
VOID
NTAPI
DiskAcquirePartitioningLock(
    IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
    )
{
    PDISK_DATA diskData = FdoExtension->CommonExtension.DriverData;

    PAGED_CODE();

    ASSERT_FDO(FdoExtension->DeviceObject);

    KeWaitForSingleObject(&(diskData->PartitioningEvent),
                          UserRequest,
                          UserMode,
                          FALSE,
                          NULL);
    return;
}
コード例 #8
0
ファイル: enum.c プロジェクト: kcrazy/winekit
/*
 *  DiskAcquirePartitioningLock
 *
 *      Acquire the PartitioningEvent.
 *
 *      NOTE:   This function is called by several ioctl handlers which run in user context.
 *                  Because we are acquiring an exclusion object in a user thread, we have to make sure
 *                  that the thread is not killed or suspended while we are holding the event.
 *                  So we call KeEnterCriticalRegion/KeLeaveCriticalRegion while holding the PartitioningEvent.
 *                  THEREFORE, it is VERY IMPORTANT that DiskAcquirePartitioningLock and DiskReleasePartitioningLock
 *                  are called on the SAME THREAD.
 */
VOID
DiskAcquirePartitioningLock(
    IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
    )
{
    PDISK_DATA diskData = FdoExtension->CommonExtension.DriverData;

    PAGED_CODE();

    ASSERT_FDO(FdoExtension->DeviceObject);

    /*
     *  Don't let user-mode thread get suspended while we are holding the partitioning lock
     */
    KeEnterCriticalRegion();

    KeWaitForSingleObject(&(diskData->PartitioningEvent),
                          UserRequest,
                          KernelMode,
                          FALSE,
                          NULL);
    return;
}
コード例 #9
0
ファイル: arb_comn.c プロジェクト: hoangduit/reactos
NTSTATUS
NTAPI
PciInitializeArbiters(IN PPCI_FDO_EXTENSION FdoExtension)
{
    PPCI_INTERFACE CurrentInterface, *Interfaces;
    PPCI_PDO_EXTENSION PdoExtension;
    PPCI_ARBITER_INSTANCE ArbiterInterface;
    NTSTATUS Status;
    PCI_SIGNATURE ArbiterType;
    ASSERT_FDO(FdoExtension);

    /* Loop all the arbiters */
    for (ArbiterType = PciArb_Io; ArbiterType <= PciArb_BusNumber; ArbiterType++)
    {
        /* Check if this is the extension for the Root PCI Bus */
        if (!PCI_IS_ROOT_FDO(FdoExtension))
        {
            /* Get the PDO extension */
            PdoExtension = FdoExtension->PhysicalDeviceObject->DeviceExtension;
            ASSERT_PDO(PdoExtension);

            /* Skip this bus if it does subtractive decode */
            if (PdoExtension->Dependent.type1.SubtractiveDecode)
            {
                DPRINT1("PCI Not creating arbiters for subtractive bus %u\n",
                        PdoExtension->Dependent.type1.SubtractiveDecode);
                continue;
            }
        }

        /* Query all the registered arbiter interfaces */
        Interfaces = PciInterfaces;
        while (*Interfaces)
        {
            /* Find the one that matches the arbiter currently being setup */
            CurrentInterface = *Interfaces;
            if (CurrentInterface->Signature == ArbiterType) break;
            Interfaces++;
        }

        /* Check if the required arbiter was not found in the list */
        if (!*Interfaces)
        {
            /* Skip this arbiter and try the next one */
            DPRINT1("PCI - FDO ext 0x%p no %s arbiter.\n",
                    FdoExtension,
                    PciArbiterNames[ArbiterType - PciArb_Io]);
            continue;
        }

        /* An arbiter was found, allocate an instance for it */
        Status = STATUS_INSUFFICIENT_RESOURCES;
        ArbiterInterface = ExAllocatePoolWithTag(PagedPool,
                                                 sizeof(PCI_ARBITER_INSTANCE),
                                                 PCI_POOL_TAG);
        if (!ArbiterInterface) break;

        /* Setup the instance */
        ArbiterInterface->BusFdoExtension = FdoExtension;
        ArbiterInterface->Interface = CurrentInterface;
        swprintf(ArbiterInterface->InstanceName,
                 L"PCI %S (b=%02x)",
                 PciArbiterNames[ArbiterType - PciArb_Io],
                 FdoExtension->BaseBus);

        /* Call the interface initializer for it */
        Status = CurrentInterface->Initializer(ArbiterInterface);
        if (!NT_SUCCESS(Status)) break;

        /* Link it with this FDO */
        PcipLinkSecondaryExtension(&FdoExtension->SecondaryExtension,
                                   &FdoExtension->SecondaryExtLock,
                                   &ArbiterInterface->Header,
                                   ArbiterType,
                                   PciArbiterDestructor);

        /* This arbiter is now initialized, move to the next one */
        DPRINT1("PCI - FDO ext 0x%p %S arbiter initialized (context 0x%p).\n",
                FdoExtension,
                L"ARBITER HEADER MISSING", //ArbiterInterface->CommonInstance.Name,
                ArbiterInterface);
        Status = STATUS_SUCCESS;
    }

    /* Return to caller */
    return Status;
}
コード例 #10
0
ファイル: pdo.c プロジェクト: tigtigtig/ndas4windows
NTSTATUS
SpPagingPathNotificationCompletion(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP LowerIrp,
    IN PDEVICE_OBJECT Fdo
    )
{
    PIRP upperIrp = LowerIrp->AssociatedIrp.MasterIrp;

    PIO_STACK_LOCATION lowerStack = IoGetCurrentIrpStackLocation(LowerIrp);
    PIO_STACK_LOCATION upperStack = IoGetCurrentIrpStackLocation(upperIrp);

    PDEVICE_OBJECT pdo = upperStack->DeviceObject;

    PADAPTER_EXTENSION lowerExtension;
    PLOGICAL_UNIT_EXTENSION upperExtension;

    ASSERT(Fdo != NULL);
    ASSERT(pdo != NULL);

    DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: Completion of "
                   "paging notification irp %#p sent due to irp %#p\n",
                LowerIrp, upperIrp));

    lowerExtension = (PADAPTER_EXTENSION) Fdo->DeviceExtension;
    upperExtension = (PLOGICAL_UNIT_EXTENSION) pdo->DeviceExtension;

    ASSERT_FDO(lowerExtension->DeviceObject);
    ASSERT_PDO(upperExtension->DeviceObject);

    DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: irp status %#08lx\n",
                LowerIrp->IoStatus.Status));

    if(NT_SUCCESS(LowerIrp->IoStatus.Status)) {

        PUCHAR typeName = "INSERT TYPE HERE";
        PULONG lowerCount;
        PULONG upperCount;

        //
        // The parameters have already been erased from the lower irp stack
        // location - use the parameters from the upper once since they're
        // just a copy.
        //

        switch(upperStack->Parameters.UsageNotification.Type) {

            case DeviceUsageTypePaging: {

                lowerCount = &(lowerExtension->CommonExtension.PagingPathCount);
                upperCount = &(upperExtension->CommonExtension.PagingPathCount);
                typeName = "PagingPathCount";
                break;
            }

            case DeviceUsageTypeHibernation: {

                lowerCount = &(lowerExtension->CommonExtension.HibernatePathCount);
                upperCount = &(upperExtension->CommonExtension.HibernatePathCount);
                typeName = "HibernatePathCount";
                break;
            }

            case DeviceUsageTypeDumpFile: {

                lowerCount = &(lowerExtension->CommonExtension.DumpPathCount);
                upperCount = &(upperExtension->CommonExtension.DumpPathCount);
                typeName = "DumpPathCount";
                break;
            }

            default: {

                typeName = "unknown type";
                lowerCount = upperCount = NULL;
                break;
            }
        }

        if(lowerCount != NULL) {
            IoAdjustPagingPathCount(
                lowerCount,
                upperStack->Parameters.UsageNotification.InPath
                );
            DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: "
                           "Fdo %s count - %d\n",
                        typeName, *lowerCount));
            IoInvalidateDeviceState(lowerExtension->LowerPdo);
        }

        if(upperCount != NULL) {
            IoAdjustPagingPathCount(
                upperCount,
                upperStack->Parameters.UsageNotification.InPath
                );
            DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: "
                           "Pdo %s count - %d\n",
                        typeName, *upperCount));
            IoInvalidateDeviceState(upperExtension->DeviceObject);
        }
    }

    upperIrp->IoStatus = LowerIrp->IoStatus;

    SpReleaseRemoveLock(lowerExtension->CommonExtension.DeviceObject, LowerIrp);
    SpReleaseRemoveLock(upperExtension->CommonExtension.DeviceObject, upperIrp);

    IoMarkIrpPending(upperIrp);

    SpCompleteRequest(upperExtension->CommonExtension.DeviceObject,
                      upperIrp,
                      NULL,
                      IO_NO_INCREMENT);

    IoFreeIrp(LowerIrp);

    return STATUS_MORE_PROCESSING_REQUIRED;
}
コード例 #11
0
ファイル: pnp.c プロジェクト: hoangduit/reactos
VOID
NTAPI
DiskDeleteSymbolicLinks(
    IN PDEVICE_OBJECT DeviceObject
    )

/*++

Routine Description:

    This routine will delete the well known name (symlink) for the specified
    device.  It generates the link name using information stored in the
    device extension

Arguments:

    DeviceObject - the device object we are unlinking

Return Value:

    status

--*/

{
    PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
    PDISK_DATA diskData = commonExtension->DriverData;

    WCHAR wideLinkName[64];
    UNICODE_STRING unicodeLinkName;

    PAGED_CODE();

    if(diskData->LinkStatus.WellKnownNameCreated) {

        swprintf(wideLinkName,
                 L"\\Device\\Harddisk%d\\Partition%d",
                 commonExtension->PartitionZeroExtension->DeviceNumber,
                 (commonExtension->IsFdo ? 0 :
                                           commonExtension->PartitionNumber));

        RtlInitUnicodeString(&unicodeLinkName, wideLinkName);

        IoDeleteSymbolicLink(&unicodeLinkName);

        diskData->LinkStatus.WellKnownNameCreated = FALSE;
    }

    if(diskData->LinkStatus.PhysicalDriveLinkCreated) {

        ASSERT_FDO(DeviceObject);

        swprintf(wideLinkName,
                 L"\\DosDevices\\PhysicalDrive%d",
                 commonExtension->PartitionZeroExtension->DeviceNumber);

        RtlInitUnicodeString(&unicodeLinkName, wideLinkName);

        IoDeleteSymbolicLink(&unicodeLinkName);

        diskData->LinkStatus.PhysicalDriveLinkCreated = FALSE;
    }

    return;
}
コード例 #12
0
ファイル: remove.c プロジェクト: JanD1943/ndas4windows
VOID
ScsiPortRemoveAdapter(
    IN PDEVICE_OBJECT AdapterObject,
    IN BOOLEAN Surprise
    )
{
    PADAPTER_EXTENSION adapter = AdapterObject->DeviceExtension;
    PCOMMON_EXTENSION commonExtension = AdapterObject->DeviceExtension;

    NTSTATUS status = STATUS_SUCCESS;

    PAGED_CODE();

    ASSERT_FDO(AdapterObject);
    ASSERT(adapter->IsPnp);

    //
    // Set the flag PD_ADAPTER_REMOVED to keep scsiport from calling into the 
    // miniport after we've started this teardown.
    //

    if(Surprise == FALSE) {
        PVOID sectionHandle;
        KIRQL oldIrql;

        //
        // Wait until all outstanding requests have been completed.
        //
    
        SpWaitForRemoveLock(AdapterObject, AdapterObject);

        //
        // If the device is started we should uninitialize the miniport and 
        // release it's resources.  Fortunately this is exactly what stop does.  
        //

        if((commonExtension->CurrentPnpState != IRP_MN_SURPRISE_REMOVAL) &&
           ((commonExtension->CurrentPnpState == IRP_MN_START_DEVICE) ||
            (commonExtension->PreviousPnpState == IRP_MN_START_DEVICE))) {

            //
            // Okay.  If this adapter can't support remove then we're dead
            //

            ASSERT(SpIsAdapterControlTypeSupported(adapter, ScsiStopAdapter) == TRUE);

            //
            // Stop the miniport now that it's safe.
            //

            SpEnableDisableAdapter(adapter, FALSE);

            //
            // Mark the adapter as removed.
            //
    
    #ifdef ALLOC_PRAGMA
            sectionHandle = MmLockPagableCodeSection(ScsiPortRemoveAdapter);
            InterlockedIncrement(&SpPAGELOCKLockCount);
    #endif
            KeAcquireSpinLock(&(adapter->SpinLock), &oldIrql);
            adapter->SynchronizeExecution(adapter->InterruptObject,
                                          SpRemoveAdapterSynchronized,
                                          adapter);
    
            KeReleaseSpinLock(&(adapter->SpinLock), oldIrql);
    
    #ifdef ALLOC_PRAGMA
            InterlockedDecrement(&SpPAGELOCKLockCount);
            MmUnlockPagableImageSection(sectionHandle);
    #endif

        }
        SpReapChildren(adapter);
    }

    if(commonExtension->WmiInitialized == TRUE) {

        //
        // Destroy all our WMI resources and unregister with WMI.
        //

        IoWMIRegistrationControl(AdapterObject, WMIREG_ACTION_DEREGISTER);
        SpWmiRemoveFreeMiniPortRequestItems(adapter);
        commonExtension->WmiInitialized = FALSE;
    }

    //
    // If we were surprise removed then this has already been done once.  
    // In that case don't try to run the cleanup code a second time even though 
    // it's safe to do so.
    //

    SpDeleteDeviceMapEntry(AdapterObject);
    SpDestroyAdapter(adapter, Surprise);

    return;
}
コード例 #13
0
ファイル: wmi.c プロジェクト: tigtigtig/ndas4windows
NTSTATUS
SpWmiInitializeFreeRequestList(
    IN PDEVICE_OBJECT DeviceObject,
    IN ULONG          NumberOfItems
    )
/*++

Routine Description:

    Call that initializes the WmiFreeMiniPortRequestList, this call MUST
    be completed prior to any manipulatio of the WmiFreeMiniPortRequestList

    The list will be initialized with at most the number of cells requested.

    If the list has already been initialized, we raise the watermark by the number
    of Items requested.

Arguments:

    DeviceObject    - Device Object that this list belongs to
    NumberOfItems   - requested number of free cells

Return Value:

    Return the SUCESS if list was initialized succesfully

    STATUS_INSUFFICIENT_REOSOURCES  - Indicates that we could not allocate
                                      enough memory for the list header

Notes:


--*/
{
    PADAPTER_EXTENSION  fdoExtension;
    ULONG               itemsInserted;
    KIRQL               oldIrql;

    PAGED_CODE();               // Routine is paged until locked down.

    //
    // Obtain a pointer to the functional device extension (for the adapter).
    //
    if ( ((PCOMMON_EXTENSION)DeviceObject->DeviceExtension)->IsPdo ) {
        fdoExtension = ((PLOGICAL_UNIT_EXTENSION)DeviceObject->DeviceExtension)
                       ->AdapterExtension;
    } else {
        fdoExtension = DeviceObject->DeviceExtension;
    }

    // If the list has been initalized increase the watermark
    if (fdoExtension->WmiFreeMiniPortRequestInitialized) {
        DebugPrint((2, "SpWmiInitializeFreeRequestList:"
                    " Increased watermark for : %p\n", fdoExtension));

        InterlockedExchangeAdd
            (&(fdoExtension->WmiFreeMiniPortRequestWatermark),
             NumberOfItems);

        while (fdoExtension->WmiFreeMiniPortRequestCount <
            fdoExtension->WmiFreeMiniPortRequestWatermark) {

            // Add free cells until the count reaches the watermark
            SpWmiPushFreeRequestItem(fdoExtension);
        }

        return (STATUS_SUCCESS);
    }

    // Only PDO's should be calling when the list has not been initialized
    ASSERT_FDO(DeviceObject);

    // Assignt he list we just initialized to the pointer in the
    // fdoExtension (and save the lock pointer also)
    KeInitializeSpinLock(&(fdoExtension->WmiFreeMiniPortRequestLock));
    ExInitializeSListHead(&(fdoExtension->WmiFreeMiniPortRequestList));

    DebugPrint((1, "SpWmiInitializeFreeRequestList:"
                " Initialized WmiFreeRequestList for: %p\n", fdoExtension));

    // Set the initialized flag
    fdoExtension->WmiFreeMiniPortRequestInitialized = TRUE;

    // Set the watermark, and the count to 0
    fdoExtension->WmiFreeMiniPortRequestWatermark = 0;
    fdoExtension->WmiFreeMiniPortRequestCount = 0;

    // Attempt to add free cells to the free list
    for (itemsInserted = 0; itemsInserted < NumberOfItems;
         itemsInserted++) {

        // Make a request to push a NULL item, so that the
        // allocation will be done by the next function
        //
        // At this point we don't care about the return value
        // because after we set the watermark, scsiport's free-cell
        // repopulation code will try to get the free list cell count
        // back to the watermark. (So if we fail to add all the requested
        // free cells, the repopulation code will attempt again for us
        // at a later time)
        SpWmiPushFreeRequestItem(fdoExtension);
    }


    // Now set the watermark to the correct value
    fdoExtension->WmiFreeMiniPortRequestWatermark = NumberOfItems;

    return(STATUS_SUCCESS);
}