380 lines
9.4 KiB
C
380 lines
9.4 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1990 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
pcienum.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Enumerates the PCI bus and puts all the found PCI information
|
||
|
into the registery.
|
||
|
|
||
|
This is done for debugging & support reasons.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Ken Reneris
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "stdarg.h"
|
||
|
#include "stdio.h"
|
||
|
#include "ntddk.h"
|
||
|
|
||
|
WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
|
||
|
WCHAR rgzConfigurationData[] = L"Configuration Data";
|
||
|
WCHAR rgzIdentifier[] = L"Identifier";
|
||
|
WCHAR rgzPCIIndetifier[] = L"PCI";
|
||
|
WCHAR rgzPCIDump[] = L"PCI configuration space dump";
|
||
|
WCHAR rgzPCIConfigData[] = L"PCIConfigSpaceData";
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
DriverEntry(
|
||
|
IN PDRIVER_OBJECT DriverObject,
|
||
|
IN PUNICODE_STRING RegistryPath
|
||
|
);
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
FindRegisterLocation (
|
||
|
PHANDLE RegHandle
|
||
|
)
|
||
|
{
|
||
|
UNICODE_STRING unicodeString, ConfigName, IdentName;
|
||
|
OBJECT_ATTRIBUTES objectAttributes;
|
||
|
HANDLE hMFunc, hBus;
|
||
|
NTSTATUS status;
|
||
|
ULONG i, junk, disposition;
|
||
|
WCHAR wstr[8];
|
||
|
PKEY_VALUE_FULL_INFORMATION ValueInfo;
|
||
|
UCHAR buffer [200];
|
||
|
PWSTR p;
|
||
|
|
||
|
//
|
||
|
// Search the hardware description looking for any reported
|
||
|
// PCI bus. The first ARC entry for a PCI bus will contain
|
||
|
// the PCI_REGISTRY_INFO.
|
||
|
//
|
||
|
|
||
|
RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
|
||
|
InitializeObjectAttributes (
|
||
|
&objectAttributes,
|
||
|
&unicodeString,
|
||
|
OBJ_CASE_INSENSITIVE,
|
||
|
NULL, // handle
|
||
|
NULL);
|
||
|
|
||
|
|
||
|
status = ZwOpenKey (&hMFunc, KEY_READ | KEY_WRITE, &objectAttributes);
|
||
|
if (!NT_SUCCESS(status)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
unicodeString.Buffer = wstr;
|
||
|
unicodeString.MaximumLength = sizeof (wstr);
|
||
|
|
||
|
RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
|
||
|
RtlInitUnicodeString (&IdentName, rgzIdentifier);
|
||
|
|
||
|
ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
|
||
|
|
||
|
for (i=0; TRUE; i++) {
|
||
|
RtlIntegerToUnicodeString (i, 10, &unicodeString);
|
||
|
InitializeObjectAttributes (
|
||
|
&objectAttributes,
|
||
|
&unicodeString,
|
||
|
OBJ_CASE_INSENSITIVE,
|
||
|
hMFunc,
|
||
|
NULL);
|
||
|
|
||
|
status = ZwOpenKey (&hBus, KEY_READ | KEY_WRITE, &objectAttributes);
|
||
|
if (!NT_SUCCESS(status)) {
|
||
|
//
|
||
|
// Out of Multifunction adapter entries...
|
||
|
//
|
||
|
|
||
|
ZwClose (hMFunc);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Check the Indentifier to see if this is a PCI entry
|
||
|
//
|
||
|
|
||
|
status = ZwQueryValueKey (
|
||
|
hBus,
|
||
|
&IdentName,
|
||
|
KeyValueFullInformation,
|
||
|
ValueInfo,
|
||
|
sizeof (buffer),
|
||
|
&junk
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS (status)) {
|
||
|
ZwClose (hBus);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset);
|
||
|
if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) {
|
||
|
ZwClose (hBus);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// found it...
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Initialize the object for the key.
|
||
|
//
|
||
|
|
||
|
RtlInitUnicodeString (&unicodeString, rgzPCIDump);
|
||
|
|
||
|
InitializeObjectAttributes(
|
||
|
&objectAttributes,
|
||
|
&unicodeString,
|
||
|
OBJ_CASE_INSENSITIVE,
|
||
|
hBus,
|
||
|
(PSECURITY_DESCRIPTOR) NULL
|
||
|
);
|
||
|
|
||
|
status = ZwCreateKey (
|
||
|
RegHandle,
|
||
|
KEY_READ | KEY_WRITE,
|
||
|
&objectAttributes,
|
||
|
0,
|
||
|
NULL,
|
||
|
REG_OPTION_VOLATILE,
|
||
|
&disposition
|
||
|
);
|
||
|
|
||
|
return NT_SUCCESS(status);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
VOID
|
||
|
DumpPciConfigSpaceIntoRegistry (
|
||
|
HANDLE RegHandle
|
||
|
)
|
||
|
{
|
||
|
|
||
|
PCI_SLOT_NUMBER SlotNumber;
|
||
|
ULONG BusNo, DeviceNo, FunctionNo, BytesRead;
|
||
|
BOOLEAN ScanFlag;
|
||
|
PCI_COMMON_CONFIG PciData;
|
||
|
HANDLE HBus, HDevice;
|
||
|
UNICODE_STRING unicodeString;
|
||
|
OBJECT_ATTRIBUTES objectAttributes;
|
||
|
NTSTATUS status;
|
||
|
ULONG len, disposition;
|
||
|
WCHAR wstr[80];
|
||
|
|
||
|
SlotNumber.u.bits.Reserved = 0;
|
||
|
BusNo = 0;
|
||
|
ScanFlag = TRUE;
|
||
|
|
||
|
while (ScanFlag) {
|
||
|
for (DeviceNo=0; ScanFlag && DeviceNo < PCI_MAX_DEVICES; DeviceNo++) {
|
||
|
SlotNumber.u.bits.DeviceNumber = DeviceNo;
|
||
|
|
||
|
for (FunctionNo = 0; FunctionNo < PCI_MAX_FUNCTION; FunctionNo++) {
|
||
|
SlotNumber.u.bits.FunctionNumber = FunctionNo;
|
||
|
|
||
|
BytesRead = HalGetBusData (
|
||
|
PCIConfiguration,
|
||
|
BusNo,
|
||
|
SlotNumber.u.AsULONG,
|
||
|
&PciData,
|
||
|
PCI_COMMON_HDR_LENGTH
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// If end-of-scan
|
||
|
//
|
||
|
|
||
|
if (BytesRead == 0) {
|
||
|
ScanFlag = FALSE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If not present, next device
|
||
|
//
|
||
|
|
||
|
if (PciData.VendorID == PCI_INVALID_VENDORID) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If Intel Device ID, then read complete state
|
||
|
//
|
||
|
|
||
|
if (PciData.VendorID == 0x8086) {
|
||
|
if (PciData.DeviceID == 0x04A3 ||
|
||
|
PciData.DeviceID == 0x0482 ||
|
||
|
PciData.DeviceID == 0x0484) {
|
||
|
|
||
|
BytesRead = HalGetBusData (
|
||
|
PCIConfiguration,
|
||
|
BusNo,
|
||
|
SlotNumber.u.AsULONG,
|
||
|
&PciData,
|
||
|
sizeof (PciData)
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Open/Create bus entry in registry
|
||
|
//
|
||
|
|
||
|
swprintf (wstr, L"PCI bus%d", BusNo);
|
||
|
RtlInitUnicodeString (&unicodeString, wstr);
|
||
|
|
||
|
InitializeObjectAttributes(
|
||
|
&objectAttributes,
|
||
|
&unicodeString,
|
||
|
OBJ_CASE_INSENSITIVE,
|
||
|
RegHandle,
|
||
|
(PSECURITY_DESCRIPTOR) NULL
|
||
|
);
|
||
|
|
||
|
status = ZwCreateKey (
|
||
|
&HBus,
|
||
|
KEY_READ | KEY_WRITE,
|
||
|
&objectAttributes,
|
||
|
0,
|
||
|
NULL,
|
||
|
REG_OPTION_VOLATILE,
|
||
|
&disposition
|
||
|
);
|
||
|
|
||
|
|
||
|
if (!NT_SUCCESS(status)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Open/Create device function key
|
||
|
//
|
||
|
|
||
|
swprintf (wstr, L"Device %02d Function %d", DeviceNo, FunctionNo);
|
||
|
RtlInitUnicodeString (&unicodeString, wstr);
|
||
|
|
||
|
InitializeObjectAttributes(
|
||
|
&objectAttributes,
|
||
|
&unicodeString,
|
||
|
OBJ_CASE_INSENSITIVE,
|
||
|
HBus,
|
||
|
(PSECURITY_DESCRIPTOR) NULL
|
||
|
);
|
||
|
|
||
|
status = ZwCreateKey (
|
||
|
&HDevice,
|
||
|
KEY_READ | KEY_WRITE,
|
||
|
&objectAttributes,
|
||
|
0,
|
||
|
NULL,
|
||
|
REG_OPTION_VOLATILE,
|
||
|
&disposition
|
||
|
);
|
||
|
|
||
|
|
||
|
ZwClose (HBus);
|
||
|
if (!NT_SUCCESS(status)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Write PCI config information to registry
|
||
|
//
|
||
|
|
||
|
len = swprintf (wstr, L"%04x-%04x rev %x",
|
||
|
PciData.VendorID,
|
||
|
PciData.DeviceID,
|
||
|
PciData.RevisionID
|
||
|
);
|
||
|
|
||
|
RtlInitUnicodeString (&unicodeString, L"Device ID");
|
||
|
ZwSetValueKey (
|
||
|
HDevice,
|
||
|
&unicodeString,
|
||
|
0L,
|
||
|
REG_SZ,
|
||
|
wstr,
|
||
|
sizeof (WCHAR) * len
|
||
|
);
|
||
|
|
||
|
|
||
|
RtlInitUnicodeString (&unicodeString, L"RawData");
|
||
|
ZwSetValueKey (
|
||
|
HDevice,
|
||
|
&unicodeString,
|
||
|
0L,
|
||
|
REG_BINARY,
|
||
|
&PciData,
|
||
|
BytesRead
|
||
|
);
|
||
|
|
||
|
ZwClose (HDevice);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
BusNo += 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
DriverEntry(
|
||
|
IN PDRIVER_OBJECT DriverObject,
|
||
|
IN PUNICODE_STRING RegistryPath
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DriverObject - Pointer to driver object created by system.
|
||
|
|
||
|
RegistryPath - Pointer to the Unicode name of the registry path
|
||
|
for this driver.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The function value is the final status from the initialization operation.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
BOOLEAN flag;
|
||
|
HANDLE RegHandle;
|
||
|
|
||
|
flag = FindRegisterLocation (&RegHandle);
|
||
|
if (flag) {
|
||
|
DumpPciConfigSpaceIntoRegistry (RegHandle);
|
||
|
ZwClose (RegHandle);
|
||
|
}
|
||
|
|
||
|
// never load
|
||
|
return STATUS_UNSUCCESSFUL;
|
||
|
}
|