Add config interface start (PciReadWriteConfigSpace, PciReadSlotConfig)

Add PDO_EXTENSION structure and PCI_FUNCTION_RESOURCES, now delete #if0 in old code since PDO_EXTENSION is now exist defintion
Add ID Class/Subclass to description functions (PciGetDeviceDescriptionMessage, PciGetDescriptionMessage), use pciclass.mc from sir_richard
New debug: PciDebugDumpCommonConfig
Implement IRP_MN_QUERY_DEVICE_RELATIONS with PciFdoIrpQueryDeviceRelations and PciQueryDeviceRelations
Begin PciScanBus, now just dump all found device with no more work (0 QDR return)

svn path=/trunk/; revision=48091
This commit is contained in:
evb 2010-07-17 01:31:26 +00:00
parent 4234345b03
commit f43651e238
8 changed files with 512 additions and 15 deletions

View file

@ -38,6 +38,7 @@ NTAPI
PciInitializeArbiters(IN PPCI_FDO_EXTENSION FdoExtension) PciInitializeArbiters(IN PPCI_FDO_EXTENSION FdoExtension)
{ {
PPCI_INTERFACE CurrentInterface, *Interfaces; PPCI_INTERFACE CurrentInterface, *Interfaces;
PPCI_PDO_EXTENSION PdoExtension;
PPCI_ARBITER_INSTANCE ArbiterInterface; PPCI_ARBITER_INSTANCE ArbiterInterface;
NTSTATUS Status; NTSTATUS Status;
PCI_SIGNATURE ArbiterType; PCI_SIGNATURE ArbiterType;
@ -49,19 +50,17 @@ PciInitializeArbiters(IN PPCI_FDO_EXTENSION FdoExtension)
/* Check if this is the extension for the Root PCI Bus */ /* Check if this is the extension for the Root PCI Bus */
if (!PCI_IS_ROOT_FDO(FdoExtension)) if (!PCI_IS_ROOT_FDO(FdoExtension))
{ {
#if 0 // at next sync when PDO add
/* Get the PDO extension */ /* Get the PDO extension */
PdoExtension = FdoExtension->PhysicalDeviceObject->DeviceExtension; PdoExtension = FdoExtension->PhysicalDeviceObject->DeviceExtension;
ASSERT_PDO(PdoExtension); ASSERT_PDO(PdoExtension);
/* Skip this bus if it does subtractive decode */ /* Skip this bus if it does subtractive decode */
if (PdoExtension->Substractive) if (PdoExtension->Dependent.type1.SubtractiveDecode)
{ {
DPRINT1("PCI Not creating arbiters for subtractive bus %d\n", DPRINT1("PCI Not creating arbiters for subtractive bus %d\n",
PdoExtension->Substractive); PdoExtension->Dependent.type1.SubtractiveDecode);
continue; continue;
} }
#endif
} }
/* Query all the registered arbiter interfaces */ /* Query all the registered arbiter interfaces */
@ -127,7 +126,7 @@ NTAPI
PciInitializeArbiterRanges(IN PPCI_FDO_EXTENSION DeviceExtension, PciInitializeArbiterRanges(IN PPCI_FDO_EXTENSION DeviceExtension,
IN PCM_RESOURCE_LIST Resources) IN PCM_RESOURCE_LIST Resources)
{ {
//PPCI_PDO_EXTENSION PdoExtension; PPCI_PDO_EXTENSION PdoExtension;
CM_RESOURCE_TYPE DesiredType; CM_RESOURCE_TYPE DesiredType;
PVOID Instance; PVOID Instance;
PCI_SIGNATURE ArbiterType; PCI_SIGNATURE ArbiterType;
@ -144,10 +143,9 @@ PciInitializeArbiterRanges(IN PPCI_FDO_EXTENSION DeviceExtension,
if (!PCI_IS_ROOT_FDO(DeviceExtension)) if (!PCI_IS_ROOT_FDO(DeviceExtension))
{ {
/* Grab the PDO */ /* Grab the PDO */
#if 0 // when pdo support
PdoExtension = (PPCI_PDO_EXTENSION)DeviceExtension->PhysicalDeviceObject->DeviceExtension; PdoExtension = (PPCI_PDO_EXTENSION)DeviceExtension->PhysicalDeviceObject->DeviceExtension;
ASSERT(PdoExtension->ExtensionType == PciPdoExtensionType); ASSERT(PdoExtension->ExtensionType == PciPdoExtensionType);
#endif
/* Multiple FDOs are not yet supported */ /* Multiple FDOs are not yet supported */
UNIMPLEMENTED; UNIMPLEMENTED;
while (TRUE); while (TRUE);

View file

@ -104,7 +104,7 @@ PciDebugIrpDispatchDisplay(IN PIO_STACK_LOCATION IoStackLocation,
IN PPCI_FDO_EXTENSION DeviceExtension, IN PPCI_FDO_EXTENSION DeviceExtension,
IN USHORT MaxMinor) IN USHORT MaxMinor)
{ {
//PPCI_PDO_EXTENSION PdoDeviceExtension; PPCI_PDO_EXTENSION PdoDeviceExtension;
ULONG BreakMask, DebugLevel = 0; ULONG BreakMask, DebugLevel = 0;
PCHAR IrpString; PCHAR IrpString;
@ -147,7 +147,7 @@ PciDebugIrpDispatchDisplay(IN PIO_STACK_LOCATION IoStackLocation,
{ {
DebugLevel = 0x200; DebugLevel = 0x200;
} }
#if 0 // after commit PDO support
/* For a PDO, print out the bus, device, and function number */ /* For a PDO, print out the bus, device, and function number */
PdoDeviceExtension = (PVOID)DeviceExtension; PdoDeviceExtension = (PVOID)DeviceExtension;
DPRINT1("PDO(b=0x%x, d=0x%x, f=0x%x)<-%s\n", DPRINT1("PDO(b=0x%x, d=0x%x, f=0x%x)<-%s\n",
@ -155,7 +155,6 @@ PciDebugIrpDispatchDisplay(IN PIO_STACK_LOCATION IoStackLocation,
PdoDeviceExtension->Slot.u.bits.DeviceNumber, PdoDeviceExtension->Slot.u.bits.DeviceNumber,
PdoDeviceExtension->Slot.u.bits.FunctionNumber, PdoDeviceExtension->Slot.u.bits.FunctionNumber,
IrpString); IrpString);
#endif
} }
else if (DeviceExtension->ExtensionType == PciFdoExtensionType) else if (DeviceExtension->ExtensionType == PciFdoExtensionType)
{ {
@ -181,4 +180,18 @@ PciDebugIrpDispatchDisplay(IN PIO_STACK_LOCATION IoStackLocation,
return ((1 << IoStackLocation->MinorFunction) & BreakMask); return ((1 << IoStackLocation->MinorFunction) & BreakMask);
} }
VOID
NTAPI
PciDebugDumpCommonConfig(IN PPCI_COMMON_HEADER PciData)
{
USHORT i;
/* Loop the PCI header */
for (i = 0; i < PCI_COMMON_HDR_LENGTH; i += 4)
{
/* Dump each DWORD and its offset */
DPRINT1(" %02x - %08x\n", i, *(PULONG)((ULONG_PTR)PciData + i));
}
}
/* EOF */ /* EOF */

View file

@ -16,4 +16,205 @@
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
NTSTATUS
NTAPI
PciScanBus(IN PPCI_FDO_EXTENSION DeviceExtension)
{
ULONG MaxDevice = PCI_MAX_DEVICES;
ULONG i, j, k;
UCHAR Buffer[PCI_COMMON_HDR_LENGTH];
PPCI_COMMON_HEADER PciData = (PVOID)Buffer;
PCI_SLOT_NUMBER PciSlot;
PWCHAR DescriptionText;
DPRINT1("PCI Scan Bus: FDO Extension @ 0x%x, Base Bus = 0x%x\n",
DeviceExtension, DeviceExtension->BaseBus);
/* Is this the root FDO? */
if (!PCI_IS_ROOT_FDO(DeviceExtension))
{
/* Other FDOs are not currently supported */
UNIMPLEMENTED;
while (TRUE);
}
/* Loop every device on the bus */
PciSlot.u.bits.Reserved = 0;
i = DeviceExtension->BaseBus;
for (j = 0; j < MaxDevice; j++)
{
/* Loop every function of each device */
PciSlot.u.bits.DeviceNumber = j;
for (k = 0; k < PCI_MAX_FUNCTION; k++)
{
/* Build the final slot structure */
PciSlot.u.bits.FunctionNumber = k;
/* Read the vendor for this slot */
PciReadSlotConfig(DeviceExtension,
PciSlot,
PciData,
0,
sizeof(USHORT));
/* Skip invalid device */
if (PciData->VendorID == PCI_INVALID_VENDORID) continue;
/* Now read the whole header */
PciReadSlotConfig(DeviceExtension,
PciSlot,
&PciData->DeviceID,
sizeof(USHORT),
PCI_COMMON_HDR_LENGTH - sizeof(USHORT));
/* Dump device that was found */
DPRINT1("Scan Found Device 0x%x (b=0x%x, d=0x%x, f=0x%x)\n",
PciSlot.u.AsULONG,
i,
j,
k);
/* Dump the device's header */
PciDebugDumpCommonConfig(PciData);
/* Find description for this device for the debugger's sake */
DescriptionText = PciGetDeviceDescriptionMessage(PciData->BaseClass,
PciData->SubClass);
DPRINT1("Device Description \"%S\".\n", DescriptionText ? DescriptionText : L"(NULL)");
if (DescriptionText) ExFreePoolWithTag(DescriptionText, 0);
/* Check if there is an ACPI Watchdog Table */
if (WdTable)
{
/* Check if this PCI device is the ACPI Watchdog Device... */
UNIMPLEMENTED;
while (TRUE);
}
}
}
/* Enumeration is completed */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
PciQueryDeviceRelations(IN PPCI_FDO_EXTENSION DeviceExtension,
IN OUT PDEVICE_RELATIONS *pDeviceRelations)
{
NTSTATUS Status;
PPCI_PDO_EXTENSION PdoExtension;
ULONG PdoCount = 0;
PDEVICE_RELATIONS DeviceRelations, NewRelations;
SIZE_T Size;
PDEVICE_OBJECT DeviceObject, *ObjectArray;
PAGED_CODE();
/* Make sure the FDO is started */
ASSERT(DeviceExtension->DeviceState == PciStarted);
/* Synchronize while we enumerate the bus */
Status = PciBeginStateTransition(DeviceExtension, PciSynchronizedOperation);
if (!NT_SUCCESS(Status)) return Status;
/* Scan all children PDO */
for (PdoExtension = DeviceExtension->ChildPdoList;
PdoExtension;
PdoExtension = PdoExtension->Next)
{
/* Invalidate them */
PdoExtension->NotPresent = TRUE;
}
/* Scan the PCI Bus */
Status = PciScanBus(DeviceExtension);
ASSERT(NT_SUCCESS(Status));
/* Enumerate all children PDO again */
for (PdoExtension = DeviceExtension->ChildPdoList;
PdoExtension;
PdoExtension = PdoExtension->Next)
{
/* Check for PDOs that are still invalidated */
if (PdoExtension->NotPresent)
{
/* This means this PDO existed before, but not anymore */
PdoExtension->ReportedMissing = TRUE;
DPRINT1("PCI - Old device (pdox) %08x not found on rescan.\n",
PdoExtension);
}
else
{
/* Increase count of detected PDOs */
PdoCount++;
}
}
/* Read the current relations and add the newly discovered relations */
DeviceRelations = *pDeviceRelations;
Size = FIELD_OFFSET(DEVICE_RELATIONS, Objects) +
PdoCount * sizeof(PDEVICE_OBJECT);
if (DeviceRelations) Size += sizeof(PDEVICE_OBJECT) * DeviceRelations->Count;
/* Allocate the device relations */
NewRelations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(0, Size, 'BicP');
if (!NewRelations)
{
/* Out of space, cancel the operation */
PciCancelStateTransition(DeviceExtension, PciSynchronizedOperation);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Check if there were any older relations */
NewRelations->Count = 0;
if (DeviceRelations)
{
/* Copy the old relations into the new buffer, then free the old one */
RtlCopyMemory(NewRelations,
DeviceRelations,
FIELD_OFFSET(DEVICE_RELATIONS, Objects) +
DeviceRelations->Count * sizeof(PDEVICE_OBJECT));
ExFreePoolWithTag(DeviceRelations, 0);
}
/* Print out that we're ready to dump relations */
DPRINT1("PCI QueryDeviceRelations/BusRelations FDOx %08x (bus 0x%02x)\n",
DeviceExtension,
DeviceExtension->BaseBus);
/* Loop the current PDO children and the device relation object array */
PdoExtension = DeviceExtension->ChildPdoList;
ObjectArray = &NewRelations->Objects[NewRelations->Count];
while (PdoExtension)
{
/* Dump this relation */
DPRINT1(" QDR PDO %08x (x %08x)%s\n",
PdoExtension->PhysicalDeviceObject,
PdoExtension,
PdoExtension->NotPresent ?
"<Omitted, device flaged not present>" : "");
/* Is this PDO present? */
if (!PdoExtension->NotPresent)
{
/* Reference it and add it to the array */
DeviceObject = PdoExtension->PhysicalDeviceObject;
ObfReferenceObject(DeviceObject);
*ObjectArray++ = DeviceObject;
}
/* Go to the next PDO */
PdoExtension = PdoExtension->Next;
}
/* Terminate dumping the relations */
DPRINT1(" QDR Total PDO count = %d (%d already in list)\n",
NewRelations->Count + PdoCount,
NewRelations->Count);
/* Return the final count and the new buffer */
NewRelations->Count += PdoCount;
*pDeviceRelations = NewRelations;
return STATUS_SUCCESS;
}
/* EOF */ /* EOF */

View file

@ -193,9 +193,25 @@ PciFdoIrpQueryDeviceRelations(IN PIRP Irp,
IN PIO_STACK_LOCATION IoStackLocation, IN PIO_STACK_LOCATION IoStackLocation,
IN PPCI_FDO_EXTENSION DeviceExtension) IN PPCI_FDO_EXTENSION DeviceExtension)
{ {
UNIMPLEMENTED; NTSTATUS Status;
while (TRUE); PAGED_CODE();
return STATUS_NOT_SUPPORTED;
/* Are bus relations being queried? */
if (IoStackLocation->Parameters.QueryDeviceRelations.Type != BusRelations)
{
/* The FDO is a bus, so only bus relations can be obtained */
Status = STATUS_NOT_SUPPORTED;
}
else
{
/* Scan the PCI bus and build the device relations for the caller */
Status = PciQueryDeviceRelations(DeviceExtension,
(PDEVICE_RELATIONS*)
&Irp->IoStatus.Information);
}
/* Return the enumeration status back */
return Status;
} }
NTSTATUS NTSTATUS

View file

@ -47,7 +47,6 @@ agpintrf_Constructor(IN PVOID DeviceExtension,
IN USHORT Size, IN USHORT Size,
IN PINTERFACE Interface) IN PINTERFACE Interface)
{ {
#if 0 // when have PDO commit
PPCI_PDO_EXTENSION PdoExtension = (PPCI_PDO_EXTENSION)DeviceExtension; PPCI_PDO_EXTENSION PdoExtension = (PPCI_PDO_EXTENSION)DeviceExtension;
/* Only AGP bridges are supported (which are PCI-to-PCI Bridge Devices) */ /* Only AGP bridges are supported (which are PCI-to-PCI Bridge Devices) */
@ -57,7 +56,6 @@ agpintrf_Constructor(IN PVOID DeviceExtension,
/* Fail any other PDO */ /* Fail any other PDO */
return STATUS_NOT_SUPPORTED; return STATUS_NOT_SUPPORTED;
} }
#endif
/* Not yet implemented */ /* Not yet implemented */
UNIMPLEMENTED; UNIMPLEMENTED;

View file

@ -189,6 +189,93 @@ typedef struct _PCI_FDO_EXTENSION
LONG BusHackFlags; LONG BusHackFlags;
} PCI_FDO_EXTENSION, *PPCI_FDO_EXTENSION; } PCI_FDO_EXTENSION, *PPCI_FDO_EXTENSION;
typedef struct _PCI_FUNCTION_RESOURCES
{
IO_RESOURCE_DESCRIPTOR Limit[7];
CM_PARTIAL_RESOURCE_DESCRIPTOR Current[7];
} PCI_FUNCTION_RESOURCES, *PPCI_FUNCTION_RESOURCES;
typedef union _PCI_HEADER_TYPE_DEPENDENT
{
struct
{
UCHAR Spare[4];
} type0;
struct
{
UCHAR PrimaryBus;
UCHAR SecondaryBus;
UCHAR SubordinateBus;
UCHAR SubtractiveDecode:1;
UCHAR IsaBitSet:1;
UCHAR VgaBitSet:1;
UCHAR WeChangedBusNumbers:1;
UCHAR IsaBitRequired:1;
} type1;
struct
{
UCHAR Spare[4];
} type2;
} PCI_HEADER_TYPE_DEPENDENT, *PPCI_HEADER_TYPE_DEPENDENT;
typedef struct _PCI_PDO_EXTENSION
{
PVOID Next;
ULONG ExtensionType;
struct _PCI_MJ_DISPATCH_TABLE *IrpDispatchTable;
BOOLEAN DeviceState;
BOOLEAN TentativeNextState;
KEVENT SecondaryExtLock;
PCI_SLOT_NUMBER Slot;
PDEVICE_OBJECT PhysicalDeviceObject;
PPCI_FDO_EXTENSION ParentFdoExtension;
SINGLE_LIST_ENTRY SecondaryExtension;
LONG BusInterfaceReferenceCount;
LONG AgpInterfaceReferenceCount;
USHORT VendorId;
USHORT DeviceId;
USHORT SubsystemVendorId;
USHORT SubsystemId;
BOOLEAN RevisionId;
BOOLEAN ProgIf;
BOOLEAN SubClass;
BOOLEAN BaseClass;
BOOLEAN AdditionalResourceCount;
BOOLEAN AdjustedInterruptLine;
BOOLEAN InterruptPin;
BOOLEAN RawInterruptLine;
BOOLEAN CapabilitiesPtr;
BOOLEAN SavedLatencyTimer;
BOOLEAN SavedCacheLineSize;
BOOLEAN HeaderType;
BOOLEAN NotPresent;
BOOLEAN ReportedMissing;
BOOLEAN ExpectedWritebackFailure;
BOOLEAN NoTouchPmeEnable;
BOOLEAN LegacyDriver;
BOOLEAN UpdateHardware;
BOOLEAN MovedDevice;
BOOLEAN DisablePowerDown;
BOOLEAN NeedsHotPlugConfiguration;
BOOLEAN SwitchedIDEToNativeMode;
BOOLEAN BIOSAllowsIDESwitchToNativeMode;
BOOLEAN IoSpaceUnderNativeIdeControl;
BOOLEAN OnDebugPath;
PCI_POWER_STATE PowerState;
PCI_HEADER_TYPE_DEPENDENT Dependent;
ULONGLONG HackFlags;
PCI_FUNCTION_RESOURCES *Resources;
PCI_FDO_EXTENSION *BridgeFdoExtension;
struct _PCI_PDO_EXTENSION *NextBridge;
struct _PCI_PDO_EXTENSION *NextHashEntry;
PCI_LOCK Lock;
PCI_PMC PowerCapabilities;
BOOLEAN TargetAgpCapabilityId;
USHORT CommandEnables;
USHORT InitialCommand;
} PCI_PDO_EXTENSION, *PPCI_PDO_EXTENSION;
// //
// IRP Dispatch Function Type // IRP Dispatch Function Type
// //
@ -579,6 +666,16 @@ PciGetConfigHandlers(
IN PPCI_FDO_EXTENSION FdoExtension IN PPCI_FDO_EXTENSION FdoExtension
); );
VOID
NTAPI
PciReadSlotConfig(
IN PPCI_FDO_EXTENSION DeviceExtension,
IN PCI_SLOT_NUMBER Slot,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
);
// //
// State Machine Logic Transition Routines // State Machine Logic Transition Routines
// //
@ -637,6 +734,12 @@ PciDebugIrpDispatchDisplay(
IN USHORT MaxMinor IN USHORT MaxMinor
); );
VOID
NTAPI
PciDebugDumpCommonConfig(
IN PPCI_COMMON_HEADER PciData
);
// //
// Interface Support // Interface Support
// //
@ -856,6 +959,26 @@ devpresent_Constructor(
IN PINTERFACE Interface IN PINTERFACE Interface
); );
//
// PCI Enumeration and Resources
//
NTSTATUS
NTAPI
PciQueryDeviceRelations(
IN PPCI_FDO_EXTENSION DeviceExtension,
IN OUT PDEVICE_RELATIONS *pDeviceRelations
);
//
// Identification Functions
//
PWCHAR
NTAPI
PciGetDeviceDescriptionMessage(
IN UCHAR BaseClass,
IN UCHAR SubClass
);
// //
// External Resources // External Resources
// //
@ -875,5 +998,7 @@ extern PCI_INTERFACE PciDevicePresentInterface;
extern PCI_INTERFACE PciLocationInterface; extern PCI_INTERFACE PciLocationInterface;
extern PCI_INTERFACE AgpTargetInterface; extern PCI_INTERFACE AgpTargetInterface;
extern PCI_INTERFACE TranslatorInterfaceInterrupt; extern PCI_INTERFACE TranslatorInterfaceInterrupt;
extern PDRIVER_OBJECT PciDriverObject;
extern PWATCHDOG_TABLE WdTable;
/* EOF */ /* EOF */

View file

@ -18,6 +18,61 @@ BOOLEAN PciAssignBusNumbers;
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
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);
}
}
VOID
NTAPI
PciReadSlotConfig(IN PPCI_FDO_EXTENSION DeviceExtension,
IN PCI_SLOT_NUMBER Slot,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length)
{
/* Call the generic worker function */
PciReadWriteConfigSpace(DeviceExtension, Slot, Buffer, Offset, Length, TRUE);
}
NTSTATUS NTSTATUS
NTAPI NTAPI
PciQueryForPciBusInterface(IN PPCI_FDO_EXTENSION FdoExtension) PciQueryForPciBusInterface(IN PPCI_FDO_EXTENSION FdoExtension)

View file

@ -16,4 +16,95 @@
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
PWCHAR
NTAPI
PciGetDescriptionMessage(IN ULONG Identifier,
OUT PULONG Length)
{
PMESSAGE_RESOURCE_ENTRY Entry;
ULONG TextLength;
PWCHAR Description, Buffer;
ANSI_STRING MessageString;
UNICODE_STRING UnicodeString;
NTSTATUS Status;
/* Find the message identifier in the message table */
MessageString.Buffer = NULL;
Status = RtlFindMessage(PciDriverObject->DriverStart,
11, // RT_MESSAGETABLE
LANG_NEUTRAL,
Identifier,
&Entry);
if (!NT_SUCCESS(Status)) return NULL;
/* Check if the resource data is Unicode or ANSI */
if (Entry->Flags & MESSAGE_RESOURCE_UNICODE)
{
/* Subtract one space for the end-of-message terminator */
TextLength = Entry->Length -
FIELD_OFFSET(MESSAGE_RESOURCE_ENTRY, Text) -
sizeof(WCHAR);
/* Grab the text */
Description = (PWCHAR)Entry->Text;
/* Validate valid message length, ending with a newline character */
ASSERT(TextLength > 1);
ASSERT(Description[TextLength / sizeof(WCHAR) == L'\n']);
/* Allocate the buffer to hold the message string */
Buffer = ExAllocatePoolWithTag(PagedPool, TextLength, 'BicP');
if (!Buffer) return NULL;
/* Copy the message, minus the newline character, and terminate it */
RtlCopyMemory(Buffer, Entry->Text, TextLength - 1);
Buffer[TextLength / sizeof(WCHAR)] = UNICODE_NULL;
/* Return the length to the caller */
if (Length) *Length = UnicodeString.Length;
}
else
{
/* Initialize the entry as a string */
RtlInitAnsiString(&MessageString, (PCHAR)Entry->Text);
/* Remove the newline character */
MessageString.Length -= sizeof(CHAR);
/* Convert it to Unicode */
RtlAnsiStringToUnicodeString(&UnicodeString, &MessageString, TRUE);
Buffer = UnicodeString.Buffer;
/* Return the length to the caller */
if (Length) *Length = UnicodeString.Length;
}
/* Return the message buffer to the caller */
return Buffer;
}
PWCHAR
NTAPI
PciGetDeviceDescriptionMessage(IN UCHAR BaseClass,
IN UCHAR SubClass)
{
PWCHAR Message;
ULONG Identifier;
/* The message identifier in the table is encoded based on the PCI class */
Identifier = (BaseClass << 8) | SubClass;
/* Go grab the description message for this device */
Message = PciGetDescriptionMessage(Identifier, NULL);
if (!Message)
{
/* It wasn't found, allocate a buffer for a generic description */
Message = ExAllocatePoolWithTag(PagedPool, sizeof(L"PCI Device"), 'bicP');
if (Message) RtlCopyMemory(Message, L"PCI Device", sizeof(L"PCI Device"));
}
/* Return the description message */
return Message;
}
/* EOF */ /* EOF */