Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

379 lines
9.4 KiB

/*++
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;
}