Ejemplo n.º 1
0
NTSTATUS
NTAPI
PciFdoIrpStartDevice(IN PIRP Irp,
                     IN PIO_STACK_LOCATION IoStackLocation,
                     IN PPCI_FDO_EXTENSION DeviceExtension)
{
    NTSTATUS Status;
    PCM_RESOURCE_LIST Resources;
    PAGED_CODE();

    /* The device stack must be starting the FDO in a success path */
    if (!NT_SUCCESS(Irp->IoStatus.Status)) return STATUS_NOT_SUPPORTED;

    /* Attempt to switch the state machine to the started state */
    Status = PciBeginStateTransition(DeviceExtension, PciStarted);
    if (!NT_SUCCESS(Status)) return Status;

    /* Check for any boot-provided resources */
    Resources = IoStackLocation->Parameters.StartDevice.AllocatedResources;
    if ((Resources) && !(PCI_IS_ROOT_FDO(DeviceExtension)))
    {
        /* These resources would only be for non-root FDOs, unhandled for now */
        ASSERT(Resources->Count == 1);
        UNIMPLEMENTED_DBGBREAK();
    }

    /* Initialize the arbiter for this FDO */
    Status = PciInitializeArbiterRanges(DeviceExtension, Resources);
    if (!NT_SUCCESS(Status))
    {
        /* Cancel the transition if this failed */
        PciCancelStateTransition(DeviceExtension, PciStarted);
        return Status;
    }

    /* Again, check for boot-provided resources for non-root FDO */
    if ((Resources) && !(PCI_IS_ROOT_FDO(DeviceExtension)))
    {
        /* Unhandled for now */
        ASSERT(Resources->Count == 1);
        UNIMPLEMENTED_DBGBREAK();
    }

    /* Commit the transition to the started state */
    PciCommitStateTransition(DeviceExtension, PciStarted);
    return STATUS_SUCCESS;
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
NTSTATUS
NTAPI
PciGetConfigHandlers(IN PPCI_FDO_EXTENSION FdoExtension)
{
    PBUS_HANDLER BusHandler;
    NTSTATUS Status;
    ASSERT(FdoExtension->BusHandler == NULL);

    /* Check if this is the FDO for the root bus */
    if (PCI_IS_ROOT_FDO(FdoExtension))
    {
        /* Query the PCI Bus Interface that ACPI exposes */
        ASSERT(FdoExtension->PciBusInterface == NULL);
        Status = PciQueryForPciBusInterface(FdoExtension);
        if (!NT_SUCCESS(Status))
        {
            /* No ACPI, so Bus Numbers should be maintained by BIOS */
            ASSERT(!PciAssignBusNumbers);
        }
        else
        {
            /* ACPI detected, PCI Bus Driver will reconfigure bus numbers*/
            PciAssignBusNumbers = TRUE;
        }
    }
    else
    {
        /* Check if the root bus already has the interface set up */
        if (FdoExtension->BusRootFdoExtension->PciBusInterface)
        {
            /* Nothing for this FDO to do */
            return STATUS_SUCCESS;
        }

        /* Fail into case below so we can query the HAL interface */
        Status = STATUS_NOT_SUPPORTED;
    }

    /* If the ACPI PCI Bus Interface couldn't be obtained, try the HAL */
    if (!NT_SUCCESS(Status))
    {
        /* Bus number assignment should be static */
        ASSERT(Status == STATUS_NOT_SUPPORTED);
        ASSERT(!PciAssignBusNumbers);

        /* Call the HAL to obtain the bus handler for PCI */
        BusHandler = HalReferenceHandlerForBus(PCIBus, FdoExtension->BaseBus);
        FdoExtension->BusHandler = BusHandler;

        /* Fail if the HAL does not have a PCI Bus Handler for this bus */
        if (!BusHandler) return STATUS_INVALID_DEVICE_REQUEST;
    }

    /* Appropriate interface was obtained */
    return STATUS_SUCCESS;
}
Ejemplo n.º 4
0
VOID
NTAPI
PciGetHotPlugParameters(IN PPCI_FDO_EXTENSION FdoExtension)
{
    ACPI_EVAL_INPUT_BUFFER InputBuffer;
    PACPI_EVAL_OUTPUT_BUFFER OutputBuffer;
    ULONG Length;
    NTSTATUS Status;
    PAGED_CODE();

    /* We should receive 4 parameters, per the HPP specification */
    Length = sizeof(ACPI_EVAL_OUTPUT_BUFFER) + 4 * sizeof(ACPI_METHOD_ARGUMENT);

    /* Allocate the buffer to hold the parameters */
    OutputBuffer = ExAllocatePoolWithTag(PagedPool, Length, PCI_POOL_TAG);
    if (!OutputBuffer) return;

    /* Initialize the output and input buffers. The method is _HPP */
    RtlZeroMemory(OutputBuffer, Length);
    *(PULONG)InputBuffer.MethodName = 'PPH_';
    InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
    do
    {
        /* Send the IOCTL to the ACPI driver */
        Status = PciSendIoctl(FdoExtension->PhysicalDeviceObject,
                              IOCTL_ACPI_EVAL_METHOD,
                              &InputBuffer,
                              sizeof(InputBuffer),
                              OutputBuffer,
                              Length);
        if (!NT_SUCCESS(Status))
        {
            /* The method failed, check if we can salvage data from parent */
            if (!PCI_IS_ROOT_FDO(FdoExtension))
            {
                /* Copy the root bus' hot plug parameters */
                FdoExtension->HotPlugParameters = FdoExtension->ParentFdoExtension->HotPlugParameters;
            }

            /* Nothing more to do on this path */
            break;
        }

        /* ACPI sent back some data. 4 parameters are expected in the output */
        if (OutputBuffer->Count != 4) break;

        /* HotPlug PCI Support not yet implemented */
        UNIMPLEMENTED_DBGBREAK();
    } while (FALSE);

    /* Free the buffer and return */
    ExFreePoolWithTag(OutputBuffer, 0);
}
Ejemplo n.º 5
0
VOID
NTAPI
PciReadWriteConfigSpace(IN PPCI_FDO_EXTENSION DeviceExtension,
                        IN PCI_SLOT_NUMBER Slot,
                        IN PVOID Buffer,
                        IN ULONG Offset,
                        IN ULONG Length,
                        IN BOOLEAN Read)
{
    PPCI_BUS_INTERFACE_STANDARD PciInterface;
    PBUS_HANDLER BusHandler;
    PPCIBUSDATA BusData;
    PciReadWriteConfig HalFunction;

    /* Only the root FDO can access configuration space */
    ASSERT(PCI_IS_ROOT_FDO(DeviceExtension->BusRootFdoExtension));

    /* Get the ACPI-compliant PCI interface */
    PciInterface = DeviceExtension->BusRootFdoExtension->PciBusInterface;
    if (PciInterface)
    {
        /* Currently this driver only supports the legacy HAL interface */
        UNIMPLEMENTED;
        while (TRUE);
    }
    else
    {
        /* Make sure there's a registered HAL bus handler */
        ASSERT(DeviceExtension->BusHandler);

        /* PCI Bus Number assignment is only valid on ACPI systems */
        ASSERT(!PciAssignBusNumbers);

        /* Grab the HAL PCI Bus Handler data */
        BusHandler = (PBUS_HANDLER)DeviceExtension->BusHandler;
        BusData = (PPCIBUSDATA)BusHandler->BusData;

        /* Choose the appropriate read or write function, and call it */
        HalFunction = Read ? BusData->ReadConfig : BusData->WriteConfig;
        HalFunction(BusHandler, Slot, Buffer, Offset, Length);
    }
}
Ejemplo n.º 6
0
VOID
NTAPI
ario_ApplyBrokenVideoHack(IN PPCI_FDO_EXTENSION FdoExtension)
{
    PPCI_ARBITER_INSTANCE PciArbiter;
    //PARBITER_INSTANCE CommonInstance;
    //NTSTATUS Status;

    /* Only valid for root FDOs who are being applied the hack for the first time */
    ASSERT(!FdoExtension->BrokenVideoHackApplied);
    ASSERT(PCI_IS_ROOT_FDO(FdoExtension));

    /* Find the I/O arbiter */
    PciArbiter = (PVOID)PciFindNextSecondaryExtension(FdoExtension->
                                                      SecondaryExtension.Next,
                                                      PciArb_Io);
    ASSERT(PciArbiter);
#if 0 // when arb exist
    /* Get the Arb instance */
    CommonInstance = &PciArbiter->CommonInstance;

    /* Free the two lists, enabling full VGA access */
    ArbFreeOrderingList(&CommonInstance->OrderingList);
    ArbFreeOrderingList(&CommonInstance->ReservedList);

    /* Build the ordering for broken video PCI access */
    Status = ArbBuildAssignmentOrdering(CommonInstance,
                                        L"Pci",
                                        L"BrokenVideo",
                                        NULL);
    ASSERT(NT_SUCCESS(Status));
#else
    //Status = STATUS_SUCCESS;
    UNIMPLEMENTED;
    while (TRUE);
#endif
    /* Now the hack has been applied */
    FdoExtension->BrokenVideoHackApplied = TRUE;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
NTSTATUS
NTAPI
PciInitializeArbiterRanges(IN PPCI_FDO_EXTENSION DeviceExtension,
                           IN PCM_RESOURCE_LIST Resources)
{
    PPCI_PDO_EXTENSION PdoExtension;
    //CM_RESOURCE_TYPE DesiredType;
    PVOID Instance;
    PCI_SIGNATURE ArbiterType;

    UNREFERENCED_PARAMETER(Resources);

    /* Arbiters should not already be initialized */
    if (DeviceExtension->ArbitersInitialized)
    {
        /* Duplicated start request, fail initialization */
        DPRINT1("PCI Warning hot start FDOx %p, resource ranges not checked.\n", DeviceExtension);
        return STATUS_INVALID_DEVICE_REQUEST;
    }

    /* Check for non-root FDO */
    if (!PCI_IS_ROOT_FDO(DeviceExtension))
    {
        /* Grab the PDO */
        PdoExtension = (PPCI_PDO_EXTENSION)DeviceExtension->PhysicalDeviceObject->DeviceExtension;
        ASSERT_PDO(PdoExtension);

        /* Check if this is a subtractive bus */
        if (PdoExtension->Dependent.type1.SubtractiveDecode)
        {
            /* There is nothing to do regarding arbitration of resources */
            DPRINT1("PCI Skipping arbiter initialization for subtractive bridge FDOX %p\n", DeviceExtension);
            return STATUS_SUCCESS;
        }
    }

    /* Loop all arbiters */
    for (ArbiterType = PciArb_Io; ArbiterType <= PciArb_Memory; ArbiterType++)
    {
        /* Pick correct resource type for each arbiter */
        if (ArbiterType == PciArb_Io)
        {
            /* I/O Port */
            //DesiredType = CmResourceTypePort;
        }
        else if (ArbiterType == PciArb_Memory)
        {
            /* Device RAM */
            //DesiredType = CmResourceTypeMemory;
        }
        else
        {
            /* Ignore anything else */
            continue;
        }

        /* Find an arbiter of this type */
        Instance = PciFindNextSecondaryExtension(&DeviceExtension->SecondaryExtension,
                                                 ArbiterType);
        if (Instance)
        {
            /*
             * Now we should initialize it, not yet implemented because Arb
             * library isn't yet implemented, not even the headers.
             */
            UNIMPLEMENTED;
            //while (TRUE);
        }
        else
        {
            /* The arbiter was not found, this is an error! */
            DPRINT1("PCI - FDO ext 0x%p %s arbiter (REQUIRED) is missing.\n",
                    DeviceExtension,
                    PciArbiterNames[ArbiterType - PciArb_Io]);
        }
    }

    /* Arbiters are now initialized */
    DeviceExtension->ArbitersInitialized = TRUE;
    return STATUS_SUCCESS;
}
Ejemplo n.º 9
0
NTSTATUS
NTAPI
PciQueryId(IN PPCI_PDO_EXTENSION DeviceExtension,
           IN BUS_QUERY_ID_TYPE QueryType,
           OUT PWCHAR *Buffer)
{
    ULONG SubsysId;
    CHAR VendorString[22];
    PPCI_PDO_EXTENSION PdoExtension;
    PPCI_FDO_EXTENSION ParentExtension;
    PWCHAR StringBuffer;
    ULONG i, Size;
    NTSTATUS Status;
    PANSI_STRING NextString;
    UNICODE_STRING DestinationString;
    PCI_ID_BUFFER IdBuffer;
    PAGED_CODE();
  
    /* Assume failure */
    Status = STATUS_SUCCESS;
    *Buffer = NULL;
    
    /* Start with the genric vendor string, which is the vendor ID + device ID */
    sprintf(VendorString,
            "PCI\\VEN_%04X&DEV_%04X",
            DeviceExtension->VendorId,
            DeviceExtension->DeviceId);
    
    /* Initialize the PCI ID Buffer */
    PciInitIdBuffer(&IdBuffer);
    
    /* Build the subsystem ID as shown in PCI ID Strings */
    SubsysId = DeviceExtension->SubsystemVendorId | (DeviceExtension->SubsystemId << 16);
  
    /* Check what the caller is requesting */
    switch (QueryType)
    {
        case BusQueryDeviceID:
        
            /* A single ID, the vendor string + the revision ID */
            PciIdPrintf(&IdBuffer,
                        "%s&SUBSYS_%08X&REV_%02X",
                        VendorString,
                        SubsysId,
                        DeviceExtension->RevisionId);
            break;
        
        case BusQueryHardwareIDs:
        
            /* First the vendor string + the subsystem ID + the revision ID */
            PciIdPrintf(&IdBuffer,
                        "%s&SUBSYS_%08X&REV_%02X",
                        VendorString,
                        SubsysId,
                        DeviceExtension->RevisionId);
            
            /* Next, without the revision */
            PciIdPrintf(&IdBuffer,
                        "%s&SUBSYS_%08X",
                        VendorString,
                        SubsysId);
            
            /* Next, the vendor string + the base class + sub class + progif */
            PciIdPrintf(&IdBuffer,
                        "%s&CC_%02X%02X%02X",
                        VendorString,
                        DeviceExtension->BaseClass,
                        DeviceExtension->SubClass,
                        DeviceExtension->ProgIf);

            /* Next, without the progif */
            PciIdPrintf(&IdBuffer,
                        "%s&CC_%02X%02X",
                        VendorString,
                        DeviceExtension->BaseClass,
                        DeviceExtension->SubClass);
            
            /* And finally, a terminator */
            PciIdPrintf(&IdBuffer, "\0");
            break;
        
        case BusQueryCompatibleIDs:
        
            /* First, the vendor + revision ID only */
            PciIdPrintf(&IdBuffer,
                        "%s&REV_%02X",
                        VendorString,
                        DeviceExtension->RevisionId);

            /* Next, the vendor string alone */
            PciIdPrintf(&IdBuffer, "%s", VendorString);
            
            /* Next, the vendor ID + the base class + the sub class + progif */
            PciIdPrintf(&IdBuffer,
                         "PCI\\VEN_%04X&CC_%02X%02X%02X",
                         DeviceExtension->VendorId,
                         DeviceExtension->BaseClass,
                         DeviceExtension->SubClass,
                         DeviceExtension->ProgIf);

            /* Now without the progif */
            PciIdPrintf(&IdBuffer,
                        "PCI\\VEN_%04X&CC_%02X%02X",
                        DeviceExtension->VendorId,
                        DeviceExtension->BaseClass,
                        DeviceExtension->SubClass);

            /* And then just the vendor ID itself */
            PciIdPrintf(&IdBuffer,
                        "PCI\\VEN_%04X",
                        DeviceExtension->VendorId);

            /* Then the base class + subclass + progif, without any vendor */
            PciIdPrintf(&IdBuffer,
                        "PCI\\CC_%02X%02X%02X",
                        DeviceExtension->BaseClass,
                        DeviceExtension->SubClass,
                        DeviceExtension->ProgIf);

            /* Next, without the progif */
            PciIdPrintf(&IdBuffer,
                        "PCI\\CC_%02X%02X",
                        DeviceExtension->BaseClass,
                        DeviceExtension->SubClass);
                        
            /* And finally, a terminator */
            PciIdPrintf(&IdBuffer, "\0");
            break;
        
        case BusQueryInstanceID:
        
            /* Start with a terminator */
            PciIdPrintf(&IdBuffer, "\0");
        
            /* And then encode the device and function number */
            PciIdPrintfAppend(&IdBuffer,
                              "%02X",
                              (DeviceExtension->Slot.u.bits.DeviceNumber << 3) |
                              DeviceExtension->Slot.u.bits.FunctionNumber);
          
            /* Loop every parent until the root */
            ParentExtension = DeviceExtension->ParentFdoExtension;
            while (!PCI_IS_ROOT_FDO(ParentExtension))
            {
                /* And encode the parent's device and function number as well */
                PdoExtension = ParentExtension->PhysicalDeviceObject->DeviceExtension;
                PciIdPrintfAppend(&IdBuffer,
                                  "%02X",
                                  (PdoExtension->Slot.u.bits.DeviceNumber << 3) |
                                  PdoExtension->Slot.u.bits.FunctionNumber);
            }
            break;
        
        default:
        
            /* Unknown query type */
            DPRINT1("PciQueryId expected ID type = %d\n", QueryType);
            return STATUS_NOT_SUPPORTED;
    }
    
    /* Something should've been generated if this has been reached */
    ASSERT(IdBuffer.Count > 0);
    
    /* Allocate the final string buffer to hold the ID */
    StringBuffer = ExAllocatePoolWithTag(PagedPool, IdBuffer.TotalLength, 'BicP');
    if (!StringBuffer) return STATUS_INSUFFICIENT_RESOURCES;
    
    /* Build the UNICODE_STRING structure for it */
    DPRINT1("PciQueryId(%d)\n", QueryType);
    DestinationString.Buffer = StringBuffer;
    DestinationString.MaximumLength = IdBuffer.TotalLength;
    
    /* Loop every ID in the buffer */
    for (i = 0; i < IdBuffer.Count; i++)
    {
        /* Select the ANSI_STRING for the ID */
        NextString = &IdBuffer.Strings[i];
        DPRINT1("    <- \"%s\"\n", NextString->Buffer);
        
        /* Convert it to a UNICODE_STRING */
        Status = RtlAnsiStringToUnicodeString(&DestinationString, NextString, FALSE);
        ASSERT(NT_SUCCESS(Status));
        
        /* Add it into the final destination buffer */
        Size = IdBuffer.StringSize[i];
        DestinationString.MaximumLength -= Size;
        DestinationString.Buffer += (Size / sizeof(WCHAR));
    }

    /* Return the buffer to the caller and return status (should be success) */
    *Buffer = StringBuffer;
    return Status;
}
Ejemplo n.º 10
0
NTSTATUS
NTAPI
PciQueryInterface(IN PPCI_FDO_EXTENSION DeviceExtension,
                  IN CONST GUID* InterfaceType,
                  IN ULONG Size,
                  IN ULONG Version,
                  IN PVOID InterfaceData,
                  IN PINTERFACE Interface,
                  IN BOOLEAN LastChance)
{
    UNICODE_STRING GuidString;
    NTSTATUS Status;
    PPCI_INTERFACE *InterfaceList;
    PPCI_INTERFACE PciInterface;
    RtlStringFromGUID(InterfaceType, &GuidString);
    DPRINT1("PCI - PciQueryInterface TYPE = %wZ\n", &GuidString);
    RtlFreeUnicodeString(&GuidString);
    DPRINT1("      Size = %u, Version = %u, InterfaceData = %p, LastChance = %s\n",
            Size,
            Version,
            InterfaceData,
            LastChance ? "TRUE" : "FALSE");

    /* Loop all the available interfaces */
    for (InterfaceList = LastChance ? PciInterfacesLastResort : PciInterfaces;
         *InterfaceList;
         InterfaceList++)
    {
        /* Get the current interface */
        PciInterface = *InterfaceList;

        /* For debugging, construct the GUID string */
        RtlStringFromGUID(PciInterface->InterfaceType, &GuidString);

        /* Check if this is an FDO or PDO */
        if (DeviceExtension->ExtensionType == PciFdoExtensionType)
        {
            /* Check if the interface is for FDOs */
            if (!(PciInterface->Flags & PCI_INTERFACE_FDO))
            {
                /* This interface is not for FDOs, skip it */
                DPRINT1("PCI - PciQueryInterface: guid = %wZ only for FDOs\n",
                        &GuidString);
                RtlFreeUnicodeString(&GuidString);
                continue;
            }

            /* Check if the interface is for root FDO only */
            if ((PciInterface->Flags & PCI_INTERFACE_ROOT) &&
                (!PCI_IS_ROOT_FDO(DeviceExtension)))
            {
                /* This FDO isn't the root, skip the interface */
                DPRINT1("PCI - PciQueryInterface: guid = %wZ only for ROOT\n",
                        &GuidString);
                RtlFreeUnicodeString(&GuidString);
                continue;
            }
        }
        else
        {
            /* This is a PDO, check if the interface is for PDOs too */
            if (!(PciInterface->Flags & PCI_INTERFACE_PDO))
            {
                /* It isn't, skip it */
                DPRINT1("PCI - PciQueryInterface: guid = %wZ only for PDOs\n",
                        &GuidString);
                RtlFreeUnicodeString(&GuidString);
                continue;
            }
        }

        /* Print the GUID for debugging, and then free the string */
        DPRINT1("PCI - PciQueryInterface looking at guid = %wZ\n", &GuidString);
        RtlFreeUnicodeString(&GuidString);

        /* Check if the GUID, version, and size all match */
        if ((IsEqualGUIDAligned(PciInterface->InterfaceType, InterfaceType)) &&
            (Version >= PciInterface->MinVersion) &&
            (Version <= PciInterface->MaxVersion) &&
            (Size >= PciInterface->MinSize))
        {
            /* Call the interface's constructor */
            Status = PciInterface->Constructor(DeviceExtension,
                                               PciInterface,
                                               InterfaceData,
                                               Version,
                                               Size,
                                               Interface);
            if (!NT_SUCCESS(Status))
            {
                /* This interface was not initialized correctly, skip it */
                DPRINT1("PCI - PciQueryInterface - Contructor %p = %08lx\n",
                        PciInterface->Constructor, Status);
                continue;
            }

            /* Reference the interface and return success, all is good */
            Interface->InterfaceReference(Interface->Context);
            DPRINT1("PCI - PciQueryInterface returning SUCCESS\n");
            return Status;
        }
    }

    /* An interface of this type, and for this device, could not be found */
    DPRINT1("PCI - PciQueryInterface FAILED TO FIND INTERFACE\n");
    return STATUS_NOT_SUPPORTED;
}
Ejemplo n.º 11
0
NTSTATUS
NTAPI
PciQueryForPciBusInterface(IN PPCI_FDO_EXTENSION FdoExtension)
{
    PDEVICE_OBJECT AttachedDevice;
    IO_STATUS_BLOCK IoStatusBlock;
    KEVENT Event;
    NTSTATUS Status;
    PIRP Irp;
    PIO_STACK_LOCATION IoStackLocation;
    PPCI_BUS_INTERFACE_STANDARD PciInterface;
    PAGED_CODE();
    ASSERT(PCI_IS_ROOT_FDO(FdoExtension));

    /* Allocate space for the inteface */
    PciInterface = ExAllocatePoolWithTag(NonPagedPool,
                                         sizeof(PCI_BUS_INTERFACE_STANDARD),
                                         PCI_POOL_TAG);
    if (!PciInterface) return STATUS_INSUFFICIENT_RESOURCES;

    /* Get the device the PDO is attached to, should be the Root (ACPI) */
    AttachedDevice = IoGetAttachedDeviceReference(FdoExtension->PhysicalDeviceObject);

    /* Build an IRP for this request */
    KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
                                       AttachedDevice,
                                       NULL,
                                       0,
                                       NULL,
                                       &Event,
                                       &IoStatusBlock);
    if (Irp)
    {
        /* Initialize the default PnP response */
        Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
        Irp->IoStatus.Information = 0;

        /* Make it a Query Interface IRP */
        IoStackLocation = IoGetNextIrpStackLocation(Irp);
        ASSERT(IoStackLocation->MajorFunction == IRP_MJ_PNP);
        IoStackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
        IoStackLocation->Parameters.QueryInterface.InterfaceType = &GUID_PCI_BUS_INTERFACE_STANDARD;
        IoStackLocation->Parameters.QueryInterface.Size = sizeof(GUID_PCI_BUS_INTERFACE_STANDARD);
        IoStackLocation->Parameters.QueryInterface.Version = PCI_BUS_INTERFACE_STANDARD_VERSION;
        IoStackLocation->Parameters.QueryInterface.Interface = (PINTERFACE)PciInterface;
        IoStackLocation->Parameters.QueryInterface.InterfaceSpecificData = NULL;

        /* Send it to the root PDO */
        Status = IoCallDriver(AttachedDevice, Irp);
        if (Status == STATUS_PENDING)
        {
            /* Wait for completion */
            KeWaitForSingleObject(&Event,
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL);
            Status = Irp->IoStatus.Status;
        }

        /* Check if an interface was returned */
        if (!NT_SUCCESS(Status))
        {
            /* No interface was returned by the root PDO */
            FdoExtension->PciBusInterface = NULL;
            ExFreePoolWithTag(PciInterface, 0);
        }
        else
        {
            /* An interface was returned, save it */
            FdoExtension->PciBusInterface = PciInterface;
        }

        /* Dereference the device object because we took a reference earlier */
        ObfDereferenceObject(AttachedDevice);
    }
    else
    {
        /* Failure path, dereference the device object and set failure code */
        if (AttachedDevice) ObfDereferenceObject(AttachedDevice);
        ExFreePoolWithTag(PciInterface, 0);
        Status = STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Return status code to caller */
    return Status;
}