From f43651e238ca30e10efd37e4da47d6c244ceb30a Mon Sep 17 00:00:00 2001 From: evb Date: Sat, 17 Jul 2010 01:31:26 +0000 Subject: [PATCH] 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 --- reactos/drivers/bus/pcix/arb/arb_comn.c | 12 +- reactos/drivers/bus/pcix/debug.c | 19 +- reactos/drivers/bus/pcix/enum.c | 201 +++++++++++++++++++ reactos/drivers/bus/pcix/fdo.c | 22 +- reactos/drivers/bus/pcix/intrface/agpintrf.c | 2 - reactos/drivers/bus/pcix/pci.h | 125 ++++++++++++ reactos/drivers/bus/pcix/pci/config.c | 55 +++++ reactos/drivers/bus/pcix/pci/id.c | 91 +++++++++ 8 files changed, 512 insertions(+), 15 deletions(-) diff --git a/reactos/drivers/bus/pcix/arb/arb_comn.c b/reactos/drivers/bus/pcix/arb/arb_comn.c index 52e0fa43e7e..8d955ed4fd2 100644 --- a/reactos/drivers/bus/pcix/arb/arb_comn.c +++ b/reactos/drivers/bus/pcix/arb/arb_comn.c @@ -38,6 +38,7 @@ NTAPI PciInitializeArbiters(IN PPCI_FDO_EXTENSION FdoExtension) { PPCI_INTERFACE CurrentInterface, *Interfaces; + PPCI_PDO_EXTENSION PdoExtension; PPCI_ARBITER_INSTANCE ArbiterInterface; NTSTATUS Status; PCI_SIGNATURE ArbiterType; @@ -49,19 +50,17 @@ PciInitializeArbiters(IN PPCI_FDO_EXTENSION FdoExtension) /* Check if this is the extension for the Root PCI Bus */ if (!PCI_IS_ROOT_FDO(FdoExtension)) { -#if 0 // at next sync when PDO add /* Get the PDO extension */ PdoExtension = FdoExtension->PhysicalDeviceObject->DeviceExtension; ASSERT_PDO(PdoExtension); /* 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", - PdoExtension->Substractive); + PdoExtension->Dependent.type1.SubtractiveDecode); continue; } -#endif } /* Query all the registered arbiter interfaces */ @@ -127,7 +126,7 @@ NTAPI PciInitializeArbiterRanges(IN PPCI_FDO_EXTENSION DeviceExtension, IN PCM_RESOURCE_LIST Resources) { - //PPCI_PDO_EXTENSION PdoExtension; + PPCI_PDO_EXTENSION PdoExtension; CM_RESOURCE_TYPE DesiredType; PVOID Instance; PCI_SIGNATURE ArbiterType; @@ -144,10 +143,9 @@ PciInitializeArbiterRanges(IN PPCI_FDO_EXTENSION DeviceExtension, if (!PCI_IS_ROOT_FDO(DeviceExtension)) { /* Grab the PDO */ -#if 0 // when pdo support PdoExtension = (PPCI_PDO_EXTENSION)DeviceExtension->PhysicalDeviceObject->DeviceExtension; ASSERT(PdoExtension->ExtensionType == PciPdoExtensionType); -#endif + /* Multiple FDOs are not yet supported */ UNIMPLEMENTED; while (TRUE); diff --git a/reactos/drivers/bus/pcix/debug.c b/reactos/drivers/bus/pcix/debug.c index 0b61df2cacc..f3a9930a880 100644 --- a/reactos/drivers/bus/pcix/debug.c +++ b/reactos/drivers/bus/pcix/debug.c @@ -104,7 +104,7 @@ PciDebugIrpDispatchDisplay(IN PIO_STACK_LOCATION IoStackLocation, IN PPCI_FDO_EXTENSION DeviceExtension, IN USHORT MaxMinor) { - //PPCI_PDO_EXTENSION PdoDeviceExtension; + PPCI_PDO_EXTENSION PdoDeviceExtension; ULONG BreakMask, DebugLevel = 0; PCHAR IrpString; @@ -147,7 +147,7 @@ PciDebugIrpDispatchDisplay(IN PIO_STACK_LOCATION IoStackLocation, { DebugLevel = 0x200; } -#if 0 // after commit PDO support + /* For a PDO, print out the bus, device, and function number */ PdoDeviceExtension = (PVOID)DeviceExtension; 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.FunctionNumber, IrpString); -#endif } else if (DeviceExtension->ExtensionType == PciFdoExtensionType) { @@ -181,4 +180,18 @@ PciDebugIrpDispatchDisplay(IN PIO_STACK_LOCATION IoStackLocation, 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 */ diff --git a/reactos/drivers/bus/pcix/enum.c b/reactos/drivers/bus/pcix/enum.c index d67db2862ae..89cb5f8bfd2 100644 --- a/reactos/drivers/bus/pcix/enum.c +++ b/reactos/drivers/bus/pcix/enum.c @@ -16,4 +16,205 @@ /* 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 ? + "" : ""); + + /* 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 */ diff --git a/reactos/drivers/bus/pcix/fdo.c b/reactos/drivers/bus/pcix/fdo.c index b00b67e55ad..bee6e7b06bf 100644 --- a/reactos/drivers/bus/pcix/fdo.c +++ b/reactos/drivers/bus/pcix/fdo.c @@ -193,9 +193,25 @@ PciFdoIrpQueryDeviceRelations(IN PIRP Irp, IN PIO_STACK_LOCATION IoStackLocation, IN PPCI_FDO_EXTENSION DeviceExtension) { - UNIMPLEMENTED; - while (TRUE); - return STATUS_NOT_SUPPORTED; + NTSTATUS Status; + PAGED_CODE(); + + /* 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 diff --git a/reactos/drivers/bus/pcix/intrface/agpintrf.c b/reactos/drivers/bus/pcix/intrface/agpintrf.c index 41bd8245e6f..a860ad15bfa 100644 --- a/reactos/drivers/bus/pcix/intrface/agpintrf.c +++ b/reactos/drivers/bus/pcix/intrface/agpintrf.c @@ -47,7 +47,6 @@ agpintrf_Constructor(IN PVOID DeviceExtension, IN USHORT Size, IN PINTERFACE Interface) { -#if 0 // when have PDO commit PPCI_PDO_EXTENSION PdoExtension = (PPCI_PDO_EXTENSION)DeviceExtension; /* 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 */ return STATUS_NOT_SUPPORTED; } -#endif /* Not yet implemented */ UNIMPLEMENTED; diff --git a/reactos/drivers/bus/pcix/pci.h b/reactos/drivers/bus/pcix/pci.h index 3c48449c6d9..8c6797db15a 100644 --- a/reactos/drivers/bus/pcix/pci.h +++ b/reactos/drivers/bus/pcix/pci.h @@ -189,6 +189,93 @@ typedef struct _PCI_FDO_EXTENSION LONG BusHackFlags; } 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 // @@ -579,6 +666,16 @@ PciGetConfigHandlers( 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 // @@ -637,6 +734,12 @@ PciDebugIrpDispatchDisplay( IN USHORT MaxMinor ); +VOID +NTAPI +PciDebugDumpCommonConfig( + IN PPCI_COMMON_HEADER PciData +); + // // Interface Support // @@ -856,6 +959,26 @@ devpresent_Constructor( 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 // @@ -875,5 +998,7 @@ extern PCI_INTERFACE PciDevicePresentInterface; extern PCI_INTERFACE PciLocationInterface; extern PCI_INTERFACE AgpTargetInterface; extern PCI_INTERFACE TranslatorInterfaceInterrupt; +extern PDRIVER_OBJECT PciDriverObject; +extern PWATCHDOG_TABLE WdTable; /* EOF */ diff --git a/reactos/drivers/bus/pcix/pci/config.c b/reactos/drivers/bus/pcix/pci/config.c index f48c18736ce..e86d73b4ea2 100644 --- a/reactos/drivers/bus/pcix/pci/config.c +++ b/reactos/drivers/bus/pcix/pci/config.c @@ -18,6 +18,61 @@ BOOLEAN PciAssignBusNumbers; /* 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 NTAPI PciQueryForPciBusInterface(IN PPCI_FDO_EXTENSION FdoExtension) diff --git a/reactos/drivers/bus/pcix/pci/id.c b/reactos/drivers/bus/pcix/pci/id.c index d4fd9102cfc..c1d711b086f 100644 --- a/reactos/drivers/bus/pcix/pci/id.c +++ b/reactos/drivers/bus/pcix/pci/id.c @@ -16,4 +16,95 @@ /* 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 */