1394 lines
40 KiB
C
1394 lines
40 KiB
C
/*++
|
||
|
||
Copyright (c) 1990, 1991 Microsoft Corporation
|
||
|
||
|
||
Module Name:
|
||
|
||
hwdetect.c
|
||
|
||
Abstract:
|
||
|
||
This is the main hardware detection module. Its main function is
|
||
to detect various system hardware and build a configuration tree.
|
||
|
||
N.B. The configuration built in the detection module will needs to
|
||
be adjusted later before we switch to FLAT mode. The is because
|
||
all the "POINTER" is a far pointer instead of a flat pointer.
|
||
|
||
Author:
|
||
|
||
Shie-Lin Tzong (shielint) 16-Jan-92
|
||
|
||
|
||
Environment:
|
||
|
||
Real mode.
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "hwdetect.h"
|
||
#include "pci.h"
|
||
#include <string.h>
|
||
#include "apm.h"
|
||
|
||
|
||
#if DBG
|
||
|
||
PUCHAR TypeName[] = {
|
||
"ArcSystem",
|
||
"CentralProcessor",
|
||
"FloatingPointProcessor",
|
||
"PrimaryICache",
|
||
"PrimaryDCache",
|
||
"SecondaryICache",
|
||
"SecondaryDCache",
|
||
"SecondaryCache",
|
||
"EisaAdapter",
|
||
"TcaAdapter",
|
||
"ScsiAdapter",
|
||
"DtiAdapter",
|
||
"MultifunctionAapter",
|
||
"DiskController",
|
||
"TapeController",
|
||
"CdRomController",
|
||
"WormController",
|
||
"SerialController",
|
||
"NetworkController",
|
||
"DisplayController",
|
||
"ParallelController",
|
||
"PointerController",
|
||
"KeyboardController",
|
||
"AudioController",
|
||
"OtherController",
|
||
"DiskPeripheral",
|
||
"FloppyDiskPeripheral",
|
||
"TapePeripheral",
|
||
"ModemPeripheral",
|
||
"MonitorPeripheral",
|
||
"PrinterPeraipheral",
|
||
"PointerPeripheral",
|
||
"KeyboardPeripheral",
|
||
"TerminalPeripheral",
|
||
"OtherPeripheral",
|
||
"LinePeripheral",
|
||
"NetworkPeripheral",
|
||
"SystemMemory",
|
||
"MaximumType"
|
||
};
|
||
|
||
VOID
|
||
CheckConfigurationTree(
|
||
FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
|
||
);
|
||
|
||
extern
|
||
USHORT
|
||
HwGetKey(
|
||
VOID
|
||
);
|
||
#endif
|
||
|
||
VOID
|
||
GetIrqFromEisaData(
|
||
FPFWCONFIGURATION_COMPONENT_DATA ControllerList,
|
||
CONFIGURATION_TYPE ControllerType
|
||
);
|
||
|
||
//
|
||
// HwBusType - defines the BUS type of the machine.
|
||
// This variable is used by detection code only.
|
||
//
|
||
|
||
USHORT HwBusType = 0;
|
||
|
||
//
|
||
// AdapterEntry is the Configuration_Component_data for the bus adapter
|
||
//
|
||
|
||
FPFWCONFIGURATION_COMPONENT_DATA AdapterEntry = NULL;
|
||
|
||
//
|
||
// FpRomBlock - A far pointer to our Rom Block
|
||
//
|
||
|
||
FPUCHAR FpRomBlock = NULL;
|
||
USHORT RomBlockLength = 0;
|
||
|
||
//
|
||
// HwMcaPosData - A far pointer to the POS data block of MCA machine
|
||
//
|
||
|
||
FPMCA_POS_DATA HwMcaPosData;
|
||
|
||
//
|
||
// HwEisaConfigurationData - A far pointer to the EISA configuration
|
||
// data on EISA machine.
|
||
//
|
||
|
||
FPUCHAR HwEisaConfigurationData = NULL;
|
||
ULONG HwEisaConfigurationSize = 0L;
|
||
|
||
//
|
||
// DisableSerialMice - A bit flags to indicate the comports whose serial
|
||
// mouse detection should be skipped.
|
||
//
|
||
|
||
USHORT DisableSerialMice = 0x0;
|
||
|
||
//
|
||
// Internal references and definitions.
|
||
//
|
||
|
||
typedef enum _RELATIONSHIP_FLAGS {
|
||
Child,
|
||
Sibling,
|
||
Parent
|
||
} RELATIONSHIP_FLAGS;
|
||
|
||
|
||
VOID
|
||
HardwareDetection(
|
||
ULONG HeapStart,
|
||
ULONG HeapSize,
|
||
ULONG ConfigurationTree,
|
||
ULONG HeapUsed,
|
||
ULONG OptionString,
|
||
ULONG OptionStringLength
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Main entrypoint of the HW recognizer test. The routine builds
|
||
a configuration tree and leaves it in the hardware heap.
|
||
|
||
Arguments:
|
||
|
||
HeapStart - Supplies the starting address of the configuaration heap.
|
||
|
||
HeapSize - Supplies the size of the heap in byte.
|
||
|
||
ConfigurationTree - Supplies a 32 bit FLAT address of the variable to
|
||
receive the hardware configuration tree.
|
||
|
||
HeapUsed - Supplies a 32 bit FLAT address of the variable to receive
|
||
the actual heap size in used.
|
||
|
||
OptionString - Supplies a 32 bit FLAT address of load option string.
|
||
|
||
OptionStringLength - Supplies the length of the OptionString
|
||
|
||
Returns:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
FPFWCONFIGURATION_COMPONENT_DATA ConfigurationRoot;
|
||
FPFWCONFIGURATION_COMPONENT_DATA FirstCom = NULL, FirstLpt = NULL;
|
||
FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry, PreviousEntry;
|
||
FPFWCONFIGURATION_COMPONENT Component;
|
||
RELATIONSHIP_FLAGS NextRelationship;
|
||
CHAR Identifier[256];
|
||
USHORT BiosYear, BiosMonth, BiosDay;
|
||
PUCHAR MachineId;
|
||
USHORT Length, InitialLength, i, Count = 0;
|
||
FPCHAR IdentifierString;
|
||
PMOUSE_INFORMATION MouseInfo = 0;
|
||
USHORT KeyboardId = 0;
|
||
ULONG VideoAdapterType = 0;
|
||
FPULONG BlConfigurationTree = NULL;
|
||
FPULONG BlHeapUsed = NULL;
|
||
FPCHAR BlOptions, EndOptions;
|
||
PUCHAR RomChain;
|
||
FPUCHAR FpRomChain = NULL, ConfigurationData, EndConfigurationData;
|
||
SHORT FreeSize;
|
||
FPHWPARTIAL_RESOURCE_DESCRIPTOR Descriptor;
|
||
FPHWRESOURCE_DESCRIPTOR_LIST DescriptorList;
|
||
PCI_REGISTRY_INFO PciEntry;
|
||
APM_REGISTRY_INFO ApmEntry;
|
||
|
||
|
||
//
|
||
// First initialize our hardware heap.
|
||
//
|
||
|
||
HwInitializeHeap(HeapStart, HeapSize);
|
||
|
||
MAKE_FP(BlConfigurationTree, ConfigurationTree);
|
||
MAKE_FP(BlHeapUsed, HeapUsed);
|
||
MAKE_FP(BlOptions, OptionString);
|
||
|
||
//
|
||
// Parse OptionString and see if we need to disable serial mice detection.
|
||
//
|
||
|
||
if (BlOptions && OptionStringLength <= 0x1000L && OptionStringLength > 0L) {
|
||
EndOptions = BlOptions + OptionStringLength;
|
||
if (*EndOptions == '\0') {
|
||
do {
|
||
if (BlOptions = _fstrstr(BlOptions, "NOSERIALMICE")) {
|
||
BlOptions += strlen("NOSERIALMICE");
|
||
while ((*BlOptions == ' ') || (*BlOptions == ':') ||
|
||
(*BlOptions == '=')) {
|
||
BlOptions++;
|
||
}
|
||
if (*BlOptions == 'C' && BlOptions[1] == 'O' &&
|
||
BlOptions[2] == 'M') {
|
||
BlOptions += 3;
|
||
while (TRUE) {
|
||
while (*BlOptions != '\0' && (*BlOptions == ' ' ||
|
||
*BlOptions == ',' || *BlOptions == ';' ||
|
||
*BlOptions == '0')) {
|
||
BlOptions++;
|
||
}
|
||
if (*BlOptions >= '0' && *BlOptions <= '9') {
|
||
if (BlOptions[1] < '0' || BlOptions[1] > '9') {
|
||
DisableSerialMice |= 1 << (*BlOptions - '0');
|
||
BlOptions++;
|
||
} else {
|
||
BlOptions++;
|
||
while (*BlOptions && *BlOptions <= '9' &&
|
||
*BlOptions >= '0') {
|
||
BlOptions++;
|
||
}
|
||
}
|
||
}else {
|
||
break;
|
||
}
|
||
}
|
||
} else {
|
||
DisableSerialMice = 0xffff;
|
||
break;
|
||
}
|
||
}
|
||
} while (BlOptions && *BlOptions && (BlOptions < EndOptions)); // double checking
|
||
}
|
||
}
|
||
|
||
//
|
||
// Determine bus type
|
||
//
|
||
|
||
if (HwIsEisaSystem()) {
|
||
HwBusType = MACHINE_TYPE_EISA;
|
||
} else if (HwIsMcaSystem()) {
|
||
HwBusType = MACHINE_TYPE_MCA;
|
||
} else {
|
||
HwBusType = MACHINE_TYPE_ISA;
|
||
}
|
||
|
||
//
|
||
// Allocate heap space for System component and initialize it.
|
||
// Also make the System component the root of configuration tree.
|
||
//
|
||
|
||
#if DBG
|
||
clrscrn ();
|
||
BlPrint("Detecting System Component ...\n");
|
||
#endif
|
||
|
||
ConfigurationRoot = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
|
||
sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
|
||
Component = &ConfigurationRoot->ComponentEntry;
|
||
|
||
Component->Class = SystemClass;
|
||
Component->Type = MaximumType; // NOTE should be IsaCompatible
|
||
Component->Version = 0;
|
||
Component->Key = 0;
|
||
Component->AffinityMask = 0;
|
||
Component->ConfigurationDataLength = 0;
|
||
MachineId = GetMachineId();
|
||
if (MachineId) {
|
||
Length = strlen(MachineId) + 1;
|
||
IdentifierString = (FPCHAR)HwAllocateHeap(Length, FALSE);
|
||
_fstrcpy(IdentifierString, MachineId);
|
||
Component->Identifier = IdentifierString;
|
||
Component->IdentifierLength = Length;
|
||
} else {
|
||
Component->Identifier = 0;
|
||
Component->IdentifierLength = 0;
|
||
}
|
||
NextRelationship = Child;
|
||
PreviousEntry = ConfigurationRoot;
|
||
|
||
#if DBG
|
||
BlPrint("Reading BIOS date ...\n");
|
||
#endif
|
||
|
||
HwGetBiosDate (0xF0000, 0xFFFF, &BiosYear, &BiosMonth, &BiosDay);
|
||
|
||
#if DBG
|
||
BlPrint("Done reading BIOS date (%d/%d/%d)\n",
|
||
BiosMonth, BiosDay, BiosYear);
|
||
#endif
|
||
|
||
|
||
#if DBG
|
||
BlPrint("Detecting PCI Bus Component ...\n");
|
||
#endif
|
||
|
||
if (BiosYear > 1992 || (BiosYear == 1992 && BiosMonth >= 11) ) {
|
||
|
||
// Bios date valid for pci presence check..
|
||
HwGetPciSystemData((PVOID) &PciEntry, TRUE);
|
||
|
||
} else {
|
||
|
||
// Bios date not confirmed...
|
||
HwGetPciSystemData((PVOID) &PciEntry, FALSE);
|
||
}
|
||
|
||
//
|
||
// Add a registry entry for each PCI bus
|
||
//
|
||
|
||
for (i=0; i < PciEntry.NoBuses; i++) {
|
||
|
||
AdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
|
||
sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
|
||
|
||
Component = &AdapterEntry->ComponentEntry;
|
||
Component->Class = AdapterClass;
|
||
Component->Type = MultiFunctionAdapter;
|
||
|
||
strcpy (Identifier, "PCI");
|
||
Length = strlen(Identifier) + 1;
|
||
IdentifierString = (FPCHAR)HwAllocateHeap(Length, FALSE);
|
||
_fstrcpy(IdentifierString, Identifier);
|
||
|
||
Component->Version = 0;
|
||
Component->Key = 0;
|
||
Component->AffinityMask = 0xffffffff;
|
||
Component->IdentifierLength = Length;
|
||
Component->Identifier = IdentifierString;
|
||
|
||
AdapterEntry->ConfigurationData = NULL;
|
||
Component->ConfigurationDataLength = 0;
|
||
|
||
if (i == 0) {
|
||
//
|
||
// For the first PCI bus include the PCI_REGISTRY_INFO
|
||
//
|
||
|
||
Length = sizeof(PCI_REGISTRY_INFO) + DATA_HEADER_SIZE;
|
||
ConfigurationData = (FPUCHAR) HwAllocateHeap(Length, TRUE);
|
||
|
||
Component->ConfigurationDataLength = Length;
|
||
AdapterEntry->ConfigurationData = ConfigurationData;
|
||
|
||
_fmemcpy ( ((FPUCHAR) ConfigurationData+DATA_HEADER_SIZE),
|
||
(FPVOID) &PciEntry, sizeof (PCI_REGISTRY_INFO));
|
||
|
||
HwSetUpFreeFormDataHeader(
|
||
(FPHWRESOURCE_DESCRIPTOR_LIST) ConfigurationData,
|
||
0,
|
||
0,
|
||
0,
|
||
Length - DATA_HEADER_SIZE
|
||
);
|
||
}
|
||
|
||
//
|
||
// Add it to tree
|
||
//
|
||
|
||
if (NextRelationship == Sibling) {
|
||
PreviousEntry->Sibling = AdapterEntry;
|
||
AdapterEntry->Parent = PreviousEntry->Parent;
|
||
} else {
|
||
PreviousEntry->Child = AdapterEntry;
|
||
AdapterEntry->Parent = PreviousEntry;
|
||
}
|
||
|
||
NextRelationship = Sibling;
|
||
PreviousEntry = AdapterEntry;
|
||
}
|
||
|
||
#if DBG
|
||
BlPrint("Detecting PCI Bus Component completes ...\n");
|
||
#endif
|
||
|
||
#if _PNP_POWER_
|
||
|
||
#if DBG
|
||
BlPrint("Detecting APM Bus Component ...\n");
|
||
#endif
|
||
|
||
if (HwGetApmSystemData((PVOID) &ApmEntry)) {
|
||
AdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
|
||
sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
|
||
|
||
Component = &AdapterEntry->ComponentEntry;
|
||
Component->Class = AdapterClass;
|
||
Component->Type = MultiFunctionAdapter;
|
||
|
||
strcpy (Identifier, "APM");
|
||
Length = strlen(Identifier) + 1;
|
||
IdentifierString = (FPCHAR)HwAllocateHeap(Length, FALSE);
|
||
_fstrcpy(IdentifierString, Identifier);
|
||
|
||
Component->Version = 0;
|
||
Component->Key = 0;
|
||
Component->AffinityMask = 0xffffffff;
|
||
Component->IdentifierLength = Length;
|
||
Component->Identifier = IdentifierString;
|
||
|
||
AdapterEntry->ConfigurationData = NULL;
|
||
Component->ConfigurationDataLength = 0;
|
||
|
||
//
|
||
|
||
Length = sizeof(APM_REGISTRY_INFO) + DATA_HEADER_SIZE;
|
||
ConfigurationData = (FPUCHAR) HwAllocateHeap(Length, TRUE);
|
||
|
||
Component->ConfigurationDataLength = Length;
|
||
AdapterEntry->ConfigurationData = ConfigurationData;
|
||
|
||
_fmemcpy ( ((FPUCHAR) ConfigurationData+DATA_HEADER_SIZE),
|
||
(FPVOID) &ApmEntry, sizeof (APM_REGISTRY_INFO));
|
||
|
||
HwSetUpFreeFormDataHeader(
|
||
(FPHWRESOURCE_DESCRIPTOR_LIST) ConfigurationData,
|
||
0,
|
||
0,
|
||
0,
|
||
Length - DATA_HEADER_SIZE
|
||
);
|
||
|
||
//
|
||
// Add it to tree
|
||
//
|
||
|
||
if (NextRelationship == Sibling) {
|
||
PreviousEntry->Sibling = AdapterEntry;
|
||
AdapterEntry->Parent = PreviousEntry->Parent;
|
||
} else {
|
||
PreviousEntry->Child = AdapterEntry;
|
||
AdapterEntry->Parent = PreviousEntry;
|
||
}
|
||
|
||
NextRelationship = Sibling;
|
||
PreviousEntry = AdapterEntry;
|
||
}
|
||
|
||
#if DBG
|
||
BlPrint("APM Data collection complete...\n");
|
||
#endif // DBG
|
||
|
||
#endif // _PNP_POWER_
|
||
|
||
#if DBG
|
||
BlPrint("Detecting PnP BIOS Bus Component ...\n");
|
||
#endif
|
||
|
||
if (HwGetPnpBiosSystemData(&ConfigurationData, &Length)) {
|
||
AdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
|
||
sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
|
||
|
||
AdapterEntry->ConfigurationData = ConfigurationData;
|
||
Component = &AdapterEntry->ComponentEntry;
|
||
Component->ConfigurationDataLength = Length;
|
||
|
||
Component->Class = AdapterClass;
|
||
Component->Type = MultiFunctionAdapter;
|
||
|
||
strcpy (Identifier, "PNP BIOS");
|
||
i = strlen(Identifier) + 1;
|
||
IdentifierString = (FPCHAR)HwAllocateHeap(i, FALSE);
|
||
_fstrcpy(IdentifierString, Identifier);
|
||
|
||
Component->Version = 0;
|
||
Component->Key = 0;
|
||
Component->AffinityMask = 0xffffffff;
|
||
Component->IdentifierLength = i;
|
||
Component->Identifier = IdentifierString;
|
||
|
||
HwSetUpFreeFormDataHeader(
|
||
(FPHWRESOURCE_DESCRIPTOR_LIST) ConfigurationData,
|
||
0,
|
||
0,
|
||
0,
|
||
Length - DATA_HEADER_SIZE
|
||
);
|
||
|
||
//
|
||
// Add it to tree
|
||
//
|
||
|
||
if (NextRelationship == Sibling) {
|
||
PreviousEntry->Sibling = AdapterEntry;
|
||
AdapterEntry->Parent = PreviousEntry->Parent;
|
||
} else {
|
||
PreviousEntry->Child = AdapterEntry;
|
||
AdapterEntry->Parent = PreviousEntry;
|
||
}
|
||
|
||
NextRelationship = Sibling;
|
||
PreviousEntry = AdapterEntry;
|
||
}
|
||
|
||
#if DBG
|
||
BlPrint("PnP BIOS Data collection complete...\n");
|
||
#endif // DBG
|
||
|
||
//
|
||
// Allocate heap space for Bus component and initialize it.
|
||
//
|
||
|
||
#if DBG
|
||
BlPrint("Detecting Bus/Adapter Component ...\n");
|
||
#endif
|
||
|
||
AdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
|
||
sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
|
||
|
||
Component = &AdapterEntry->ComponentEntry;
|
||
|
||
Component->Class = AdapterClass;
|
||
|
||
//
|
||
// The assumption here is that the machine has only one
|
||
// type of IO bus. If a machine has more than one types of
|
||
// IO buses, it will not use this detection code anyway.
|
||
//
|
||
|
||
if (HwBusType == MACHINE_TYPE_EISA) {
|
||
|
||
//
|
||
// Note We don't collect EISA config data here. Because we may
|
||
// exhaust the heap space. We will collect the data after all
|
||
// the other components are detected.
|
||
//
|
||
|
||
Component->Type = EisaAdapter;
|
||
strcpy(Identifier, "EISA");
|
||
AdapterEntry->ConfigurationData = NULL;
|
||
Component->ConfigurationDataLength = 0;
|
||
|
||
} else if (HwBusType == MACHINE_TYPE_MCA) {
|
||
|
||
Component->Type = MultiFunctionAdapter;
|
||
strcpy(Identifier, "MCA");
|
||
GetMcaPosData(&AdapterEntry->ConfigurationData,
|
||
&Component->ConfigurationDataLength);
|
||
HwMcaPosData = (FPMCA_POS_DATA)
|
||
((FPUCHAR)AdapterEntry->ConfigurationData + DATA_HEADER_SIZE);
|
||
|
||
} else {
|
||
|
||
//
|
||
// If not EISA or MCA, it must be ISA
|
||
//
|
||
|
||
Component->Type = MultiFunctionAdapter;
|
||
strcpy(Identifier, "ISA");
|
||
}
|
||
Length = strlen(Identifier) + 1;
|
||
IdentifierString = (FPCHAR)HwAllocateHeap(Length, FALSE);
|
||
_fstrcpy(IdentifierString, Identifier);
|
||
Component->Version = 0;
|
||
Component->Key = 0;
|
||
Component->AffinityMask = 0xffffffff;
|
||
Component->IdentifierLength = Length;
|
||
Component->Identifier = IdentifierString;
|
||
|
||
//
|
||
// Make Adapter component System's child
|
||
//
|
||
|
||
if (NextRelationship == Sibling) {
|
||
PreviousEntry->Sibling = AdapterEntry;
|
||
AdapterEntry->Parent = PreviousEntry->Parent;
|
||
} else {
|
||
PreviousEntry->Child = AdapterEntry;
|
||
AdapterEntry->Parent = PreviousEntry;
|
||
}
|
||
NextRelationship = Child;
|
||
PreviousEntry = AdapterEntry;
|
||
|
||
//
|
||
// Collect BIOS information for ConfigurationRoot component.
|
||
// This step is done here because we need data collected in
|
||
// adapter component. The ConfigurationData is:
|
||
// HWRESOURCE_DESCRIPTOR_LIST header
|
||
// HWPARTIAL_RESOURCE_DESCRIPTOR for Parameter Table
|
||
// HWPARTIAL_RESOURCE_DESCRIPTOR for Rom Blocks.
|
||
// (Note DATA_HEADER_SIZE contains the size of the first partial
|
||
// descriptor already.)
|
||
//
|
||
|
||
#if DBG
|
||
BlPrint("Collecting Disk Geometry...\n");
|
||
#endif
|
||
|
||
GetInt13DriveParameters((PVOID)&RomChain, &Length);
|
||
InitialLength = (USHORT)(Length + RESERVED_ROM_BLOCK_LIST_SIZE + DATA_HEADER_SIZE +
|
||
sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR));
|
||
ConfigurationData = (FPUCHAR)HwAllocateHeap(InitialLength, FALSE);
|
||
EndConfigurationData = ConfigurationData + DATA_HEADER_SIZE;
|
||
if (Length != 0) {
|
||
FpRomChain = EndConfigurationData;
|
||
_fmemcpy(FpRomChain, (FPVOID)RomChain, Length);
|
||
}
|
||
EndConfigurationData += (sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR) +
|
||
Length);
|
||
HwSetUpFreeFormDataHeader((FPHWRESOURCE_DESCRIPTOR_LIST)ConfigurationData,
|
||
0,
|
||
0,
|
||
0,
|
||
Length
|
||
);
|
||
|
||
//
|
||
// Scan ROM to collect all the ROM blocks, if possible.
|
||
//
|
||
|
||
#if DBG
|
||
BlPrint("Detecting ROM Blocks...\n");
|
||
#endif
|
||
|
||
FpRomBlock = EndConfigurationData;
|
||
GetRomBlocks(FpRomBlock, &Length);
|
||
RomBlockLength = Length;
|
||
if (Length != 0) {
|
||
EndConfigurationData += Length;
|
||
} else {
|
||
FpRomBlock = NULL;
|
||
}
|
||
|
||
//
|
||
// We have both RomChain and RomBlock information/Headers.
|
||
//
|
||
|
||
DescriptorList = (FPHWRESOURCE_DESCRIPTOR_LIST)ConfigurationData;
|
||
DescriptorList->Count = 2;
|
||
Descriptor = (FPHWPARTIAL_RESOURCE_DESCRIPTOR)(
|
||
EndConfigurationData - Length -
|
||
sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR));
|
||
Descriptor->Type = RESOURCE_DEVICE_DATA;
|
||
Descriptor->ShareDisposition = 0;
|
||
Descriptor->Flags = 0;
|
||
Descriptor->u.DeviceSpecificData.DataSize = (ULONG)Length;
|
||
Descriptor->u.DeviceSpecificData.Reserved1 = 0;
|
||
Descriptor->u.DeviceSpecificData.Reserved2 = 0;
|
||
|
||
Length = (USHORT)(MAKE_FLAT_ADDRESS(EndConfigurationData) -
|
||
MAKE_FLAT_ADDRESS(ConfigurationData));
|
||
ConfigurationRoot->ComponentEntry.ConfigurationDataLength = Length;
|
||
ConfigurationRoot->ConfigurationData = ConfigurationData;
|
||
FreeSize = InitialLength - Length;
|
||
|
||
HwFreeHeap((ULONG)FreeSize);
|
||
|
||
//
|
||
// Set up device information structure for Keyboard.
|
||
//
|
||
|
||
#if DBG
|
||
BlPrint("Detecting Keyboard Component ...\n");
|
||
#endif
|
||
|
||
KeyboardId = GetKeyboardId();
|
||
|
||
CurrentEntry = SetKeyboardConfigurationData(KeyboardId);
|
||
|
||
//
|
||
// Make display component the child of Adapter component.
|
||
//
|
||
|
||
if (NextRelationship == Sibling) {
|
||
PreviousEntry->Sibling = CurrentEntry;
|
||
CurrentEntry->Parent = PreviousEntry->Parent;
|
||
} else {
|
||
PreviousEntry->Child = CurrentEntry;
|
||
CurrentEntry->Parent = PreviousEntry;
|
||
}
|
||
NextRelationship = Sibling;
|
||
PreviousEntry = CurrentEntry;
|
||
|
||
//
|
||
// Set up device information for com port (Each COM component
|
||
// is treated as a controller class.)
|
||
//
|
||
|
||
#if DBG
|
||
BlPrint("Detecting ComPort Component ...\n");
|
||
#endif
|
||
|
||
if (CurrentEntry = GetComportInformation()) {
|
||
|
||
FirstCom = CurrentEntry;
|
||
|
||
//
|
||
// Make current component the child of Adapter component.
|
||
//
|
||
|
||
if (NextRelationship == Sibling) {
|
||
PreviousEntry->Sibling = CurrentEntry;
|
||
} else {
|
||
PreviousEntry->Child = CurrentEntry;
|
||
}
|
||
while (CurrentEntry) {
|
||
CurrentEntry->Parent = AdapterEntry;
|
||
PreviousEntry = CurrentEntry;
|
||
CurrentEntry = CurrentEntry->Sibling;
|
||
}
|
||
NextRelationship = Sibling;
|
||
}
|
||
|
||
//
|
||
// Set up device information for parallel port. (Each parallel
|
||
// is treated as a controller class.)
|
||
//
|
||
|
||
#if DBG
|
||
BlPrint("Detecting Parallel Component ...\n");
|
||
#endif
|
||
|
||
if (CurrentEntry = GetLptInformation()) {
|
||
|
||
FirstLpt = CurrentEntry;
|
||
|
||
//
|
||
// Make current component the child of Adapter component.
|
||
//
|
||
|
||
if (NextRelationship == Sibling) {
|
||
PreviousEntry->Sibling = CurrentEntry;
|
||
CurrentEntry->Parent = PreviousEntry->Parent;
|
||
} else {
|
||
PreviousEntry->Child = CurrentEntry;
|
||
CurrentEntry->Parent = PreviousEntry;
|
||
}
|
||
PreviousEntry = CurrentEntry;
|
||
CurrentEntry = CurrentEntry->Sibling;
|
||
while (CurrentEntry) {
|
||
CurrentEntry->Parent = PreviousEntry->Parent;
|
||
PreviousEntry = CurrentEntry;
|
||
CurrentEntry = CurrentEntry->Sibling;
|
||
}
|
||
NextRelationship = Sibling;
|
||
}
|
||
|
||
//
|
||
// Set up device information structure for Mouse.
|
||
//
|
||
|
||
#if DBG
|
||
BlPrint("Detecting Mouse Component ...\n");
|
||
#endif
|
||
|
||
if (CurrentEntry = GetMouseInformation()) {
|
||
|
||
//
|
||
// Make current component the child of Adapter component.
|
||
//
|
||
|
||
if (NextRelationship == Sibling) {
|
||
PreviousEntry->Sibling = CurrentEntry;
|
||
CurrentEntry->Parent = PreviousEntry->Parent;
|
||
} else {
|
||
PreviousEntry->Child = CurrentEntry;
|
||
CurrentEntry->Parent = PreviousEntry;
|
||
}
|
||
PreviousEntry = CurrentEntry;
|
||
CurrentEntry = CurrentEntry->Sibling;
|
||
while (CurrentEntry) {
|
||
CurrentEntry->Parent = PreviousEntry->Parent;
|
||
PreviousEntry = CurrentEntry;
|
||
CurrentEntry = CurrentEntry->Sibling;
|
||
}
|
||
NextRelationship = Sibling;
|
||
}
|
||
|
||
//
|
||
// Set up device information for floppy drives. (The returned information
|
||
// is a tree structure.)
|
||
//
|
||
|
||
#if DBG
|
||
BlPrint("Detecting Floppy Component ...\n");
|
||
#endif
|
||
|
||
if (CurrentEntry = GetFloppyInformation()) {
|
||
|
||
//
|
||
// Make current component the child of Adapter component.
|
||
//
|
||
|
||
if (NextRelationship == Sibling) {
|
||
PreviousEntry->Sibling = CurrentEntry;
|
||
} else {
|
||
PreviousEntry->Child = CurrentEntry;
|
||
}
|
||
while (CurrentEntry) {
|
||
CurrentEntry->Parent = AdapterEntry;
|
||
PreviousEntry = CurrentEntry;
|
||
CurrentEntry = CurrentEntry->Sibling;
|
||
}
|
||
NextRelationship = Sibling;
|
||
}
|
||
|
||
//
|
||
// Set up device information structure for Video Display Adapter.
|
||
//
|
||
|
||
#if DBG
|
||
BlPrint("Detection done. Press a key to display hardware info ...\n");
|
||
while ( ! HwGetKey ());
|
||
clrscrn ();
|
||
// BlPrint("Detecting Video Component ...\n");
|
||
#endif
|
||
|
||
#if 0 // Remove video detection
|
||
if (VideoAdapterType = GetVideoAdapterType()) {
|
||
|
||
CurrentEntry = SetVideoConfigurationData(VideoAdapterType);
|
||
|
||
//
|
||
// Make display component the child of Adapter component.
|
||
//
|
||
|
||
if (NextRelationship == Sibling) {
|
||
PreviousEntry->Sibling = CurrentEntry;
|
||
CurrentEntry->Parent = PreviousEntry->Parent;
|
||
} else {
|
||
PreviousEntry->Child = CurrentEntry;
|
||
CurrentEntry->Parent = PreviousEntry;
|
||
}
|
||
NextRelationship = Sibling;
|
||
PreviousEntry = CurrentEntry;
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Misc. supports. Note, the information collected here will NOT be
|
||
// written to hardware registry.
|
||
//
|
||
// 1. Collect video font information for vdm
|
||
//
|
||
|
||
GetVideoFontInformation();
|
||
|
||
//
|
||
// After all the components are detected, we collect EISA config data.
|
||
//
|
||
|
||
if (HwBusType == MACHINE_TYPE_EISA) {
|
||
|
||
Component = &AdapterEntry->ComponentEntry;
|
||
GetEisaConfigurationData(&AdapterEntry->ConfigurationData,
|
||
&Component->ConfigurationDataLength);
|
||
if (Component->ConfigurationDataLength) {
|
||
HwEisaConfigurationData = (FPUCHAR)AdapterEntry->ConfigurationData +
|
||
DATA_HEADER_SIZE;
|
||
HwEisaConfigurationSize = Component->ConfigurationDataLength -
|
||
DATA_HEADER_SIZE;
|
||
|
||
//
|
||
// Misc. detections based on Eisa config data
|
||
//
|
||
// Update Lpt and com controllers' irq information by examining
|
||
// the EISA configuration data.
|
||
//
|
||
|
||
GetIrqFromEisaData(FirstLpt, ParallelController);
|
||
GetIrqFromEisaData(FirstCom, SerialController);
|
||
}
|
||
}
|
||
|
||
|
||
#if DBG
|
||
CheckConfigurationTree(ConfigurationRoot);
|
||
#endif
|
||
|
||
//
|
||
// Update all the far pointers in the tree to flat 32 bit pointers
|
||
//
|
||
|
||
UpdateConfigurationTree(ConfigurationRoot);
|
||
|
||
//
|
||
// Set up returned values:
|
||
// Size of Heap space which should be preserved for configuration tree
|
||
// Pointer to the root of the configuration tree.
|
||
//
|
||
|
||
CurrentEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap(0, FALSE);
|
||
*BlHeapUsed = MAKE_FLAT_ADDRESS(CurrentEntry) -
|
||
MAKE_FLAT_ADDRESS(ConfigurationRoot);
|
||
*BlConfigurationTree = (ULONG)MAKE_FLAT_ADDRESS(ConfigurationRoot);
|
||
}
|
||
|
||
VOID
|
||
GetIrqFromEisaData(
|
||
FPFWCONFIGURATION_COMPONENT_DATA ControllerList,
|
||
CONFIGURATION_TYPE ControllerType
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine updates all irq information for ControllerType components
|
||
in the controllerList by examinine the eisa configuration data.
|
||
|
||
Arguments:
|
||
|
||
ControllerList - Supplies a pointer to a component entry whoes irq will
|
||
be updated.
|
||
|
||
ControllerType - Supplies the controller type whoes irq will be searched
|
||
for.
|
||
|
||
Returns:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
|
||
FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry;
|
||
FPHWPARTIAL_RESOURCE_DESCRIPTOR Descriptor;
|
||
FPHWRESOURCE_DESCRIPTOR_LIST DescriptorList;
|
||
USHORT i, Port;
|
||
UCHAR Irq, Trigger;
|
||
|
||
CurrentEntry = ControllerList;
|
||
while (CurrentEntry &&
|
||
CurrentEntry->ComponentEntry.Type == ControllerType) {
|
||
if (CurrentEntry->ConfigurationData) {
|
||
DescriptorList = (FPHWRESOURCE_DESCRIPTOR_LIST)
|
||
CurrentEntry->ConfigurationData;
|
||
Port = 0;
|
||
for (i = 0; i < (USHORT)DescriptorList->Count; i++) {
|
||
Descriptor = &DescriptorList->PartialDescriptors[i];
|
||
if (Descriptor->Type == CmResourceTypePort) {
|
||
Port = (USHORT)Descriptor->u.Port.Start.LowPart;
|
||
break;
|
||
}
|
||
}
|
||
if (Port != 0) {
|
||
for (i = 0; i < (USHORT)DescriptorList->Count; i++) {
|
||
Descriptor = &DescriptorList->PartialDescriptors[i];
|
||
if (Descriptor->Type == CmResourceTypeInterrupt) {
|
||
if (HwEisaGetIrqFromPort(Port, &Irq, &Trigger)) {
|
||
if (Trigger == 0) { // EISA EDGE_TRIGGER
|
||
Descriptor->Flags = EDGE_TRIGGERED;
|
||
} else {
|
||
Descriptor->Flags = LEVEL_SENSITIVE;
|
||
}
|
||
Descriptor->u.Interrupt.Level = Irq;
|
||
Descriptor->u.Interrupt.Vector = Irq;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
CurrentEntry = CurrentEntry->Sibling;
|
||
}
|
||
}
|
||
|
||
VOID
|
||
UpdateComponentPointers(
|
||
FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine updates all the "far" pointer to 32 bit flat addresses
|
||
for a component entry.
|
||
|
||
Arguments:
|
||
|
||
CurrentEntry - Supplies a pointer to a component entry which will
|
||
be updated.
|
||
|
||
Returns:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
FPULONG UpdatePointer;
|
||
FPVOID NextEntry;
|
||
ULONG FlatAddress;
|
||
|
||
//
|
||
// Update the child, parent, sibling and ConfigurationData
|
||
// far pointers to 32 bit flat addresses.
|
||
// N.B. After we update the pointers to flat addresses, they
|
||
// can no longer be accessed in real mode.
|
||
//
|
||
|
||
UpdatePointer = (FPULONG)&CurrentEntry->Child;
|
||
NextEntry = (FPVOID)CurrentEntry->Child;
|
||
FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
|
||
*UpdatePointer = FlatAddress;
|
||
|
||
UpdatePointer = (FPULONG)&CurrentEntry->Parent;
|
||
NextEntry = (FPVOID)CurrentEntry->Parent;
|
||
FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
|
||
*UpdatePointer = FlatAddress;
|
||
|
||
UpdatePointer = (FPULONG)&CurrentEntry->Sibling;
|
||
NextEntry = (FPVOID)CurrentEntry->Sibling;
|
||
FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
|
||
*UpdatePointer = FlatAddress;
|
||
|
||
UpdatePointer = (FPULONG)&CurrentEntry->ComponentEntry.Identifier;
|
||
NextEntry = (FPVOID)CurrentEntry->ComponentEntry.Identifier;
|
||
FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
|
||
*UpdatePointer = FlatAddress;
|
||
|
||
UpdatePointer = (FPULONG)&CurrentEntry->ConfigurationData;
|
||
NextEntry = (FPVOID)CurrentEntry->ConfigurationData;
|
||
FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
|
||
*UpdatePointer = FlatAddress;
|
||
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
UpdateConfigurationTree(
|
||
FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine traverses loader configuration tree and changes
|
||
all the "far" pointer to 32 bit flat addresses.
|
||
|
||
Arguments:
|
||
|
||
CurrentEntry - Supplies a pointer to a loader configuration
|
||
tree or subtree.
|
||
|
||
Returns:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
if (CurrentEntry) {
|
||
UpdateConfigurationTree(CurrentEntry->Child);
|
||
UpdateConfigurationTree(CurrentEntry->Sibling);
|
||
UpdateComponentPointers(CurrentEntry);
|
||
}
|
||
}
|
||
|
||
FPVOID
|
||
HwSetUpResourceDescriptor (
|
||
FPFWCONFIGURATION_COMPONENT Component,
|
||
PUCHAR Identifier,
|
||
PHWCONTROLLER_DATA ControlData,
|
||
USHORT SpecificDataLength,
|
||
PUCHAR SpecificData
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allocates space from far heap , puts the caller's controller
|
||
information to the space and sets up CONFIGURATION_COMPONENT
|
||
structure for the caller.
|
||
|
||
Arguments:
|
||
|
||
Component - Supplies the address the component whose configuration data
|
||
should be set up.
|
||
|
||
Identifier - Suppies a pointer to the identifier to identify the controller
|
||
|
||
ControlData - Supplies a point to a structure which describes
|
||
controller information.
|
||
|
||
SpecificDataLength - size of the device specific data. Device specific
|
||
data is the information not defined in the standard format.
|
||
|
||
SpecificData - Supplies a pointer to the device specific data.
|
||
|
||
|
||
Return Value:
|
||
|
||
Returns a far pointer to the Configuration data.
|
||
|
||
--*/
|
||
|
||
{
|
||
FPCHAR fpIdentifier;
|
||
FPHWRESOURCE_DESCRIPTOR_LIST fpDescriptor = NULL;
|
||
USHORT Length;
|
||
SHORT Count, i;
|
||
FPUCHAR fpSpecificData;
|
||
|
||
//
|
||
// Set up Identifier string for hardware component, if necessary.
|
||
//
|
||
|
||
if (Identifier) {
|
||
Length = strlen(Identifier) + 1;
|
||
Component->IdentifierLength = Length;
|
||
fpIdentifier = (FPUCHAR)HwAllocateHeap(Length, FALSE);
|
||
Component->Identifier = fpIdentifier;
|
||
_fstrcpy(fpIdentifier, Identifier);
|
||
} else {
|
||
Component->IdentifierLength = 0;
|
||
Component->Identifier = NULL;
|
||
}
|
||
|
||
//
|
||
// Set up configuration data for hardware component, if necessary
|
||
//
|
||
|
||
Count = ControlData->NumberPortEntries + ControlData->NumberIrqEntries +
|
||
ControlData->NumberMemoryEntries + ControlData->NumberDmaEntries;
|
||
|
||
if (SpecificDataLength) {
|
||
|
||
//
|
||
// if we have device specific data, we need to increment the count
|
||
// by one.
|
||
//
|
||
|
||
Count++;
|
||
}
|
||
|
||
if (Count >0) {
|
||
Length = (USHORT)(Count * sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR) +
|
||
FIELD_OFFSET(HWRESOURCE_DESCRIPTOR_LIST, PartialDescriptors) +
|
||
SpecificDataLength);
|
||
fpDescriptor = (FPHWRESOURCE_DESCRIPTOR_LIST)HwAllocateHeap(Length, TRUE);
|
||
fpDescriptor->Count = Count;
|
||
|
||
//
|
||
// Copy all the partial descriptors to the destination descriptors
|
||
// except the last one. (The last partial descriptor may be a device
|
||
// specific data. It requires special handling.)
|
||
//
|
||
|
||
for (i = 0; i < (Count - 1); i++) {
|
||
fpDescriptor->PartialDescriptors[i] =
|
||
ControlData->DescriptorList[i];
|
||
}
|
||
|
||
//
|
||
// Set up the last partial descriptor. If it is a port, memory, irq or
|
||
// dma entry, we simply copy it. If the last one is for device specific
|
||
// data, we set up the length and copy the device spcific data to the end
|
||
// of the decriptor.
|
||
//
|
||
|
||
if (SpecificData) {
|
||
fpDescriptor->PartialDescriptors[Count - 1].Type =
|
||
RESOURCE_DEVICE_DATA;
|
||
fpDescriptor->PartialDescriptors[Count - 1].Flags = 0;
|
||
fpDescriptor->PartialDescriptors[Count - 1].u.DeviceSpecificData.DataSize =
|
||
SpecificDataLength;
|
||
fpSpecificData = (FPUCHAR)&(fpDescriptor->PartialDescriptors[Count]);
|
||
_fmemcpy(fpSpecificData, SpecificData, SpecificDataLength);
|
||
} else {
|
||
fpDescriptor->PartialDescriptors[Count - 1] =
|
||
ControlData->DescriptorList[Count - 1];
|
||
}
|
||
Component->ConfigurationDataLength = Length;
|
||
}
|
||
return(fpDescriptor);
|
||
}
|
||
VOID
|
||
HwSetUpFreeFormDataHeader (
|
||
FPHWRESOURCE_DESCRIPTOR_LIST Header,
|
||
USHORT Version,
|
||
USHORT Revision,
|
||
USHORT Flags,
|
||
ULONG DataSize
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initialize free formed data header. Note this routine
|
||
sets the the Header and initialize the FIRST PartialDescriptor only.
|
||
If the header contains more than one descriptor, the caller must handle
|
||
it itself.
|
||
|
||
Arguments:
|
||
|
||
Header - Supplies a pointer to the header to be initialized.
|
||
|
||
Version - Version number for the header.
|
||
|
||
Revision - Revision number for the header.
|
||
|
||
Flags - Free formed data flags. (Currently, it is undefined and
|
||
should be zero.)
|
||
|
||
DataSize - Size of the free formed data.
|
||
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
Header->Version = Version;
|
||
Header->Revision = Revision;
|
||
Header->Count = 1;
|
||
Header->PartialDescriptors[0].Type = RESOURCE_DEVICE_DATA;
|
||
Header->PartialDescriptors[0].ShareDisposition = 0;
|
||
Header->PartialDescriptors[0].Flags = Flags;
|
||
Header->PartialDescriptors[0].u.DeviceSpecificData.DataSize = DataSize;
|
||
Header->PartialDescriptors[0].u.DeviceSpecificData.Reserved1 = 0;
|
||
Header->PartialDescriptors[0].u.DeviceSpecificData.Reserved2 = 0;
|
||
}
|
||
#if DBG
|
||
|
||
VOID
|
||
CheckComponentNode(
|
||
FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
|
||
)
|
||
{
|
||
FPUCHAR NextEntry, DataPointer;
|
||
ULONG FlatAddress;
|
||
ULONG Length;
|
||
UCHAR IdString[40];
|
||
USHORT Count, i;
|
||
UCHAR Type;
|
||
FPHWRESOURCE_DESCRIPTOR_LIST DescriptorList;
|
||
FPHWPARTIAL_RESOURCE_DESCRIPTOR Descriptor;
|
||
|
||
FlatAddress = MAKE_FLAT_ADDRESS(CurrentEntry);
|
||
clrscrn ();
|
||
BlPrint("\n");
|
||
BlPrint("Current Node: %lx\n", FlatAddress);
|
||
BlPrint(" Type = %s\n", TypeName[CurrentEntry->ComponentEntry.Type]);
|
||
|
||
//
|
||
// Update the child, parent, sibling and ConfigurationData
|
||
// far pointers to 32 bit flat addresses.
|
||
// N.B. After we update the pointers to flat addresses, they
|
||
// can no longer be accessed in real mode.
|
||
//
|
||
|
||
NextEntry = (FPUCHAR)CurrentEntry->Child;
|
||
FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
|
||
if (FlatAddress > 0x60000 || (FlatAddress < 0x50000 && FlatAddress != 0)) {
|
||
BlPrint("Invalid address: Child = %lx\n", FlatAddress);
|
||
} else {
|
||
BlPrint("\tChild = %lx\n", FlatAddress);
|
||
}
|
||
|
||
NextEntry = (FPUCHAR)CurrentEntry->Parent;
|
||
FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
|
||
if (FlatAddress > 0x60000 || (FlatAddress < 0x50000 && FlatAddress != 0)) {
|
||
BlPrint("Invalid address: Parent = %lx\n", FlatAddress);
|
||
} else {
|
||
BlPrint("\tParent = %lx\n", FlatAddress);
|
||
}
|
||
|
||
NextEntry = (FPUCHAR)CurrentEntry->Sibling;
|
||
FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
|
||
if (FlatAddress > 0x60000 || (FlatAddress < 0x50000 && FlatAddress != 0)) {
|
||
BlPrint("Invalid address: Sibling = %lx\n", FlatAddress);
|
||
} else {
|
||
BlPrint("\tSibling = %lx\n", FlatAddress);
|
||
}
|
||
|
||
NextEntry = (FPUCHAR)CurrentEntry->ConfigurationData;
|
||
FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
|
||
if (FlatAddress > 0x60000 || (FlatAddress < 0x50000 && FlatAddress != 0)) {
|
||
BlPrint("Invalid address: ConfigurationData = %lx\n", FlatAddress);
|
||
} else {
|
||
BlPrint("\tConfigurationData = %lx\n", FlatAddress);
|
||
}
|
||
|
||
Length = CurrentEntry->ComponentEntry.IdentifierLength;
|
||
BlPrint("IdentifierLength = %lx\n", CurrentEntry->ComponentEntry.IdentifierLength);
|
||
if (Length > 0) {
|
||
_fstrcpy(IdString, CurrentEntry->ComponentEntry.Identifier);
|
||
BlPrint("Identifier = %s\n", IdString);
|
||
}
|
||
|
||
Length = CurrentEntry->ComponentEntry.ConfigurationDataLength;
|
||
BlPrint("ConfigdataLength = %lx\n", Length);
|
||
|
||
if (Length > 0) {
|
||
|
||
DescriptorList = (FPHWRESOURCE_DESCRIPTOR_LIST)CurrentEntry->ConfigurationData;
|
||
BlPrint("Version = %x, Revision = %x\n", DescriptorList->Version,
|
||
DescriptorList->Revision);
|
||
Count = (USHORT)DescriptorList->Count;
|
||
Descriptor = &DescriptorList->PartialDescriptors[0];
|
||
BlPrint("Count = %x\n", Count);
|
||
while (Count > 0) {
|
||
Type = Descriptor->Type;
|
||
if (Type == RESOURCE_PORT) {
|
||
BlPrint("Type = Port");
|
||
BlPrint("\tShareDisposition = %x\n", Descriptor->ShareDisposition);
|
||
BlPrint("PortFlags = %x\n", Descriptor->Flags);
|
||
BlPrint("PortStart = %x", Descriptor->u.Port.Start);
|
||
BlPrint("\tPortLength = %x\n", Descriptor->u.Port.Length);
|
||
} else if (Type == RESOURCE_DMA) {
|
||
BlPrint("Type = Dma");
|
||
BlPrint("\tShareDisposition = %x\n", Descriptor->ShareDisposition);
|
||
BlPrint("DmaFlags = %x\n", Descriptor->Flags);
|
||
BlPrint("DmaChannel = %x", Descriptor->u.Dma.Channel);
|
||
BlPrint("\tDmaPort = %lx\n", Descriptor->u.Dma.Port);
|
||
} else if (Type == RESOURCE_INTERRUPT) {
|
||
BlPrint("Type = Interrupt");
|
||
BlPrint("\tShareDisposition = %x\n", Descriptor->ShareDisposition);
|
||
BlPrint("InterruptFlags = %x\n", Descriptor->Flags);
|
||
BlPrint("Level = %x", Descriptor->u.Interrupt.Level);
|
||
BlPrint("\tVector = %x\n", Descriptor->u.Interrupt.Vector);
|
||
} else if (Type == RESOURCE_MEMORY) {
|
||
BlPrint("Type = Memory");
|
||
BlPrint("\tShareDisposition = %x\n", Descriptor->ShareDisposition);
|
||
BlPrint("MemoryFlags = %x\n", Descriptor->Flags);
|
||
BlPrint("Start1 = %lx", (ULONG)Descriptor->u.Memory.Start.LowPart);
|
||
BlPrint("\tStart2 = %lx", (ULONG)Descriptor->u.Memory.Start.HighPart);
|
||
BlPrint("\tLength = %lx\n", Descriptor->u.Memory.Length);
|
||
} else {
|
||
BlPrint("Type = Device Data\n");
|
||
Length = Descriptor->u.DeviceSpecificData.DataSize;
|
||
BlPrint("Size = %lx\n", Length);
|
||
DataPointer = (FPUCHAR)(Descriptor+1);
|
||
for (i = 0; i < Length && i < 64; i++) {
|
||
BlPrint("%x ", *DataPointer);
|
||
DataPointer++;
|
||
}
|
||
break;
|
||
}
|
||
Count--;
|
||
Descriptor++;
|
||
}
|
||
}
|
||
while (HwGetKey() == 0) {
|
||
}
|
||
}
|
||
|
||
VOID
|
||
CheckConfigurationTree(
|
||
FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
|
||
)
|
||
{
|
||
if (CurrentEntry) {
|
||
CheckComponentNode(CurrentEntry);
|
||
CheckConfigurationTree(CurrentEntry->Sibling);
|
||
CheckConfigurationTree(CurrentEntry->Child);
|
||
}
|
||
}
|
||
|
||
#endif
|