⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pci.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
    }

    /* Now we still have something to copy */
    if (Length)
    {
        /* Check if it's vendor-specific data */
        if (Offset >= PCI_COMMON_HDR_LENGTH)
        {
            /* Read it now */
            HalpWritePCIConfig(BusHandler, Slot, Buffer, Offset, Length);
            Len += Length;
        }
    }

    /* Update the total length read */
    return Len;
}

NTSTATUS
NTAPI
HalpSetupPciDeviceForDebugging(IN PVOID LoaderBlock,
                               IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice)
{
    DPRINT1("Unimplemented!\n");
    return STATUS_NOT_IMPLEMENTED;
}

NTSTATUS
NTAPI
HalpReleasePciDeviceForDebugging(IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice)
{
    DPRINT1("Unimplemented!\n");
    return STATUS_NOT_IMPLEMENTED;
}

static ULONG STDCALL
PciSize(ULONG Base, ULONG Mask)
{
    ULONG Size = Mask & Base; /* Find the significant bits */
    Size = Size & ~(Size - 1); /* Get the lowest of them to find the decode size */
    return Size;
}

NTSTATUS
NTAPI
HalpAssignPCISlotResources(IN PBUS_HANDLER BusHandler,
                           IN PBUS_HANDLER RootHandler,
                           IN PUNICODE_STRING RegistryPath,
                           IN PUNICODE_STRING DriverClassName OPTIONAL,
                           IN PDRIVER_OBJECT DriverObject,
                           IN PDEVICE_OBJECT DeviceObject OPTIONAL,
                           IN ULONG Slot,
                           IN OUT PCM_RESOURCE_LIST *AllocatedResources)
{
    PCI_COMMON_CONFIG PciConfig;
    SIZE_T Address;
    SIZE_T ResourceCount;
    ULONG Size[PCI_TYPE0_ADDRESSES];
    NTSTATUS Status = STATUS_SUCCESS;
    UCHAR Offset;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
    PCI_SLOT_NUMBER SlotNumber;
    ULONG WriteBuffer;

    /* FIXME: Should handle 64-bit addresses */

    /* Read configuration data */
    SlotNumber.u.AsULONG = Slot;
    HalpReadPCIConfig(BusHandler, SlotNumber, &PciConfig, 0, PCI_COMMON_HDR_LENGTH);

    /* Check if we read it correctly */
    if (PciConfig.VendorID == PCI_INVALID_VENDORID)
        return STATUS_NO_SUCH_DEVICE;

    /* Read the PCI configuration space for the device and store base address and
    size information in temporary storage. Count the number of valid base addresses */
    ResourceCount = 0;
    for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++)
    {
        if (0xffffffff == PciConfig.u.type0.BaseAddresses[Address])
            PciConfig.u.type0.BaseAddresses[Address] = 0;

        /* Memory resource */
        if (0 != PciConfig.u.type0.BaseAddresses[Address])
        {
            ResourceCount++;

            Offset = FIELD_OFFSET(PCI_COMMON_CONFIG, u.type0.BaseAddresses[Address]);

            /* Write 0xFFFFFFFF there */
            WriteBuffer = 0xffffffff;
            HalpWritePCIConfig(BusHandler, SlotNumber, &WriteBuffer, Offset, sizeof(ULONG));

            /* Read that figure back from the config space */
            HalpReadPCIConfig(BusHandler, SlotNumber, &Size[Address], Offset, sizeof(ULONG));

            /* Write back initial value */
            HalpWritePCIConfig(BusHandler, SlotNumber, &PciConfig.u.type0.BaseAddresses[Address], Offset, sizeof(ULONG));
        }
    }

    /* Interrupt resource */
    if (0 != PciConfig.u.type0.InterruptLine)
        ResourceCount++;

    /* Allocate output buffer and initialize */
    *AllocatedResources = ExAllocatePoolWithTag(
        PagedPool,
        sizeof(CM_RESOURCE_LIST) +
        (ResourceCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR),
        TAG('H','a','l',' '));

    if (NULL == *AllocatedResources)
        return STATUS_NO_MEMORY;

    (*AllocatedResources)->Count = 1;
    (*AllocatedResources)->List[0].InterfaceType = PCIBus;
    (*AllocatedResources)->List[0].BusNumber = BusHandler->BusNumber;
    (*AllocatedResources)->List[0].PartialResourceList.Version = 1;
    (*AllocatedResources)->List[0].PartialResourceList.Revision = 1;
    (*AllocatedResources)->List[0].PartialResourceList.Count = ResourceCount;
    Descriptor = (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors;

    /* Store configuration information */
    for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++)
    {
        if (0 != PciConfig.u.type0.BaseAddresses[Address])
        {
            if (/*PCI_BASE_ADDRESS_SPACE_MEMORY*/ 0 ==
                (PciConfig.u.type0.BaseAddresses[Address] & 0x1))
            {
                Descriptor->Type = CmResourceTypeMemory;
                Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */
                Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;             /* FIXME Just a guess */
                Descriptor->u.Memory.Start.QuadPart = (PciConfig.u.type0.BaseAddresses[Address] & PCI_ADDRESS_MEMORY_ADDRESS_MASK);
                Descriptor->u.Memory.Length = PciSize(Size[Address], PCI_ADDRESS_MEMORY_ADDRESS_MASK);
            }
            else if (PCI_ADDRESS_IO_SPACE ==
                (PciConfig.u.type0.BaseAddresses[Address] & 0x1))
            {
                Descriptor->Type = CmResourceTypePort;
                Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */
                Descriptor->Flags = CM_RESOURCE_PORT_IO;                       /* FIXME Just a guess */
                Descriptor->u.Port.Start.QuadPart = PciConfig.u.type0.BaseAddresses[Address] &= PCI_ADDRESS_IO_ADDRESS_MASK;
                Descriptor->u.Port.Length = PciSize(Size[Address], PCI_ADDRESS_IO_ADDRESS_MASK & 0xffff);
            }
            else
            {
                ASSERT(FALSE);
                return STATUS_UNSUCCESSFUL;
            }
            Descriptor++;
        }
    }

    if (0 != PciConfig.u.type0.InterruptLine)
    {
        Descriptor->Type = CmResourceTypeInterrupt;
        Descriptor->ShareDisposition = CmResourceShareShared;          /* FIXME Just a guess */
        Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;     /* FIXME Just a guess */
        Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine;
        Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
        Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;

        Descriptor++;
    }

    ASSERT(Descriptor == (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors + ResourceCount);

    /* FIXME: Should store the resources in the registry resource map */

    return Status;
}

ULONG
NTAPI
HaliPciInterfaceReadConfig(IN PBUS_HANDLER RootBusHandler,
                           IN ULONG BusNumber,
                           IN PCI_SLOT_NUMBER SlotNumber,
                           IN PVOID Buffer,
                           IN ULONG Offset,
                           IN ULONG Length)
{
    BUS_HANDLER BusHandler;
    PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)Buffer;

    /* Setup fake PCI Bus handler */
    RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER));
    BusHandler.BusNumber = BusNumber;

    /* Read configuration data */
    HalpReadPCIConfig(&BusHandler, SlotNumber, Buffer, Offset, Length);

    /* Check if caller only wanted at least Vendor ID */
    if (Length >= 2)
    {
        /* Validate it */
        if (PciData->VendorID != PCI_INVALID_VENDORID)
        {
            /* Check if this is the new maximum bus number */
            if (HalpMaxPciBus < BusHandler.BusNumber)
            {
                /* Set it */
                HalpMaxPciBus = BusHandler.BusNumber;
            }
        }
    }

    /* Return length */
    return Length;
}

PPCI_REGISTRY_INFO_INTERNAL
NTAPI
HalpQueryPciRegistryInfo(VOID)
{
    WCHAR NameBuffer[8];
    OBJECT_ATTRIBUTES   ObjectAttributes;
    UNICODE_STRING KeyName, ConfigName, IdentName;
    HANDLE KeyHandle, BusKeyHandle;
    NTSTATUS Status;
    UCHAR KeyBuffer[sizeof(PPCI_REGISTRY_INFO) + 100];
    PKEY_VALUE_FULL_INFORMATION ValueInfo = (PVOID)KeyBuffer;
    ULONG ResultLength;
    PWSTR Tag;
    ULONG i;
    PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
    PPCI_REGISTRY_INFO PciRegInfo;
    PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo;

    /* Setup the object attributes for the key */
    RtlInitUnicodeString(&KeyName,
                         L"\\Registry\\Machine\\Hardware\\Description\\"
                         L"System\\MultiFunctionAdapter");
    InitializeObjectAttributes(&ObjectAttributes,
                               &KeyName,
                               OBJ_CASE_INSENSITIVE,
                               NULL,
                               NULL);

    /* Open the key */
    Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
    if (!NT_SUCCESS(Status)) return NULL;

    /* Setup the receiving string */
    KeyName.Buffer = NameBuffer;
    KeyName.MaximumLength = sizeof(NameBuffer);

    /* Setup the configuration and identifier key names */
    RtlInitUnicodeString(&ConfigName, L"ConfigurationData");
    RtlInitUnicodeString(&IdentName, L"Identifier");

    /* Keep looping for each ID */
    for (i = 0; TRUE; i++)
    {
        /* Setup the key name */
        RtlIntegerToUnicodeString(i, 10, &KeyName);
        InitializeObjectAttributes(&ObjectAttributes,
                                   &KeyName,
                                   OBJ_CASE_INSENSITIVE,
                                   KeyHandle,
                                   NULL);

        /* Open it */
        Status = ZwOpenKey(&BusKeyHandle, KEY_READ, &ObjectAttributes);
        if (!NT_SUCCESS(Status))
        {
            /* None left, fail */
            ZwClose(KeyHandle);
            return NULL;
        }

        /* Read the registry data */
        Status = ZwQueryValueKey(BusKeyHandle,
                                 &IdentName,
                                 KeyValueFullInformation,
                                 ValueInfo,
                                 sizeof(KeyBuffer),
                                 &ResultLength);
        if (!NT_SUCCESS(Status))
        {
            /* Failed, try the next one */
            ZwClose(BusKeyHandle);
            continue;
        }

        /* Get the PCI Tag and validate it */
        Tag = (PWSTR)((ULONG_PTR)ValueInfo + ValueInfo->DataOffset);
        if ((Tag[0] != L'P') ||
            (Tag[1] != L'C') ||
            (Tag[2] != L'I') ||
            (Tag[3]))
        {
            /* Not a valid PCI entry, skip it */
            ZwClose(BusKeyHandle);
            continue;
        }

        /* Now read our PCI structure */
        Status = ZwQueryValueKey(BusKeyHandle,
                                 &ConfigName,
                                 KeyValueFullInformation,
                                 ValueInfo,
                                 sizeof(KeyBuffer),
                                 &ResultLength);
        ZwClose(BusKeyHandle);
        if (!NT_SUCCESS(Status)) continue;

        /* We read it OK! Get the actual resource descriptors */
        FullDescriptor  = (PCM_FULL_RESOURCE_DESCRIPTOR)
                          ((ULONG_PTR)ValueInfo + ValueInfo->DataOffset);
        PartialDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
                            ((ULONG_PTR)FullDescriptor->
                                        PartialResourceList.PartialDescriptors);

        /* Check if this is our PCI Registry Information */
        if (PartialDescriptor->Type == CmResourceTypeDeviceSpecific)
        {
            /* Close the key */
            ZwClose(KeyHandle);

            /* FIXME: Check PnP\PCI\CardList */

            /* Get the PCI information */
            PciRegInfo = (PPCI_REGISTRY_INFO)(PartialDescriptor + 1);

            /* Allocate the return structure */
            PciRegistryInfo = ExAllocatePoolWithTag(NonPagedPool,
                                                    sizeof(PCI_REGISTRY_INFO_INTERNAL),
                                                    TAG('H', 'a', 'l', ' '));
            if (!PciRegistryInfo) return NULL;

            /* Fill it out */
            PciRegistryInfo->HardwareMechanism = PciRegInfo->HardwareMechanism;
            PciRegistryInfo->NoBuses = PciRegInfo->NoBuses;
            PciRegistryInfo->MajorRevision = PciRegInfo->MajorRevision;
            PciRegistryInfo->MinorRevision = PciRegInfo->MinorRevision;
            PciRegistryInfo->ElementCount = 0;
        }
    }
}

VOID
NTAPI
HalpInitializePciStubs(VOID)
{
    PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo;
    UCHAR PciType;
    PPCIPBUSDATA BusData = (PPCIPBUSDATA)HalpFakePciBusHandler.BusData;
    ULONG i;
    PCI_SLOT_NUMBER j;
    ULONG VendorId = 0;

    /* Query registry information */
    PciRegistryInfo = HalpQueryPciRegistryInfo();
    if (!PciRegistryInfo)
    {
        /* Assume type 1 */
        PciType = 1;
    }
    else
    {
        /* Get the type and free the info structure */
        PciType = PciRegistryInfo->HardwareMechanism & 0xF;
        ExFreePool(PciRegistryInfo);
    }

    /* Initialize the PCI lock */
    KeInitializeSpinLock(&HalpPCIConfigLock);

    /* Check the type of PCI bus */
    switch (PciType)
    {
        /* Type 1 PCI Bus */
        case 1:

            /* Copy the Type 1 handler data */
            RtlCopyMemory(&PCIConfigHandler,
                          &PCIConfigHandlerType1,
                          sizeof(PCIConfigHandler));

            /* Set correct I/O Ports */
            BusData->Config.Type1.Address = PCI_TYPE1_ADDRESS_PORT;
            BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
            break;

        /* Type 2 PCI Bus */
        case 2:

            /* Copy the Type 1 handler data */
            RtlCopyMemory(&PCIConfigHandler,
                          &PCIConfigHandlerType2,
                          sizeof (PCIConfigHandler));

            /* Set correct I/O Ports */
            BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
            BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
            BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;

            /* Only 16 devices supported, not 32 */
            BusData->MaxDevice = 16;
            break;

        default:

            /* Invalid type */
            DbgPrint("HAL: Unnkown PCI type\n");
    }

    /* Loop all possible buses */
    for (i = 0; i < 256; i++)
    {
        /* Loop all devices */
        for (j.u.AsULONG = 0; j.u.AsULONG < 32; j.u.AsULONG++)
        {
            /* Query the interface */
            if (HaliPciInterfaceReadConfig(NULL,
                                           i,
                                           j,
                                           &VendorId,
                                           0,
                                           sizeof(ULONG)))
            {
                /* Validate the vendor ID */
                if ((USHORT)VendorId != PCI_INVALID_VENDORID)
                {
                    /* Set this as the maximum ID */
                    HalpMaxPciBus = i;
                    break;
                }
            }
        }
    }

    /* We're done */
    HalpPCIConfigInitialized = TRUE;
}

VOID
NTAPI
HalpInitializePciBus(VOID)
{
    /* Initialize the stubs */
    HalpInitializePciStubs();

    /* FIXME: Initialize NMI Crash Flag */
}

/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -