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.

1882 lines
57 KiB

  1. /*++
  2. Copyright (c) 1990, 1991 Microsoft Corporation
  3. Module Name:
  4. hwdetect.c
  5. Abstract:
  6. This is the main hardware detection module. Its main function is
  7. to detect various system hardware and build a configuration tree.
  8. N.B. The configuration built in the detection module will needs to
  9. be adjusted later before we switch to FLAT mode. The is because
  10. all the "POINTER" is a far pointer instead of a flat pointer.
  11. Author:
  12. Shie-Lin Tzong (shielint) 16-Jan-92
  13. Environment:
  14. Real mode.
  15. Revision History:
  16. Kenneth Ray (kenray) Jan-1998
  17. - Add: get docking station info from PnP BIOS and add to firmware tree
  18. --*/
  19. #include "hwdetect.h"
  20. typedef VOID (*PINTERFACE_REFERENCE)(PVOID Context);
  21. typedef VOID (*PINTERFACE_DEREFERENCE)(PVOID Context);
  22. typedef PVOID PDEVICE_OBJECT;
  23. #include "pci.h"
  24. #include <string.h>
  25. #include "apm.h"
  26. #include <ntapmsdk.h>
  27. #include "pcibios.h"
  28. #include "pcienum.h"
  29. #if DBG
  30. PUCHAR TypeName[] = {
  31. "ArcSystem",
  32. "CentralProcessor",
  33. "FloatingPointProcessor",
  34. "PrimaryICache",
  35. "PrimaryDCache",
  36. "SecondaryICache",
  37. "SecondaryDCache",
  38. "SecondaryCache",
  39. "EisaAdapter",
  40. "TcaAdapter",
  41. "ScsiAdapter",
  42. "DtiAdapter",
  43. "MultifunctionAdapter",
  44. "DiskController",
  45. "TapeController",
  46. "CdRomController",
  47. "WormController",
  48. "SerialController",
  49. "NetworkController",
  50. "DisplayController",
  51. "ParallelController",
  52. "PointerController",
  53. "KeyboardController",
  54. "AudioController",
  55. "OtherController",
  56. "DiskPeripheral",
  57. "FloppyDiskPeripheral",
  58. "TapePeripheral",
  59. "ModemPeripheral",
  60. "MonitorPeripheral",
  61. "PrinterPeripheral",
  62. "PointerPeripheral",
  63. "KeyboardPeripheral",
  64. "TerminalPeripheral",
  65. "OtherPeripheral",
  66. "LinePeripheral",
  67. "NetworkPeripheral",
  68. "SystemMemory",
  69. "DockingInformation",
  70. "RealModeIrqRoutingTable",
  71. "RealModePCIEnumeration",
  72. "MaximumType"
  73. };
  74. VOID
  75. CheckConfigurationTree(
  76. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
  77. );
  78. extern
  79. USHORT
  80. HwGetKey(
  81. VOID
  82. );
  83. #endif
  84. VOID
  85. GetIrqFromEisaData(
  86. FPFWCONFIGURATION_COMPONENT_DATA ControllerList,
  87. CONFIGURATION_TYPE ControllerType
  88. );
  89. //
  90. // HwBusType - defines the BUS type of the machine.
  91. // This variable is used by detection code only.
  92. //
  93. USHORT HwBusType = 0;
  94. //
  95. // AdapterEntry is the Configuration_Component_data for the bus adapter
  96. //
  97. FPFWCONFIGURATION_COMPONENT_DATA AdapterEntry = NULL;
  98. //
  99. // FpRomBlock - A far pointer to our Rom Block
  100. //
  101. FPUCHAR FpRomBlock = NULL;
  102. USHORT RomBlockLength = 0;
  103. //
  104. // HwEisaConfigurationData - A far pointer to the EISA configuration
  105. // data on EISA machine.
  106. //
  107. FPUCHAR HwEisaConfigurationData = NULL;
  108. ULONG HwEisaConfigurationSize = 0L;
  109. //
  110. // DisableSerialMice - A bit flags to indicate the comports whose serial
  111. // mouse detection should be skipped.
  112. //
  113. USHORT DisableSerialMice = 0x0;
  114. //
  115. // FastDetect - A boolean value indicating if we should skip detection of
  116. // unsupported devices or devices that are detected by NT proper
  117. //
  118. UCHAR FastDetect = 0x0;
  119. //
  120. // DisablePccardIrqScan - A boolean value indicating if we should skip
  121. // detection of usable IRQs connected to pccard controllers
  122. //
  123. UCHAR DisablePccardIrqScan = 0;
  124. //
  125. // NoIRQRouting - Skip calling PCI BIOS to get IRQ routing options.
  126. //
  127. UCHAR NoIRQRouting = 0;
  128. //
  129. // PCIEnum - Enumerating the devices on the PCI Buses. Off by default.
  130. //
  131. UCHAR PCIEnum = 0;
  132. //
  133. // NoLegacy - Skip keyboard and all of the above.
  134. //
  135. UCHAR NoLegacy = 0;
  136. //
  137. // Internal references and definitions.
  138. //
  139. typedef enum _RELATIONSHIP_FLAGS {
  140. Child,
  141. Sibling,
  142. Parent
  143. } RELATIONSHIP_FLAGS;
  144. VOID
  145. HardwareDetection(
  146. ULONG HeapStart,
  147. ULONG HeapSize,
  148. ULONG ConfigurationTree,
  149. ULONG HeapUsed,
  150. ULONG OptionString,
  151. ULONG OptionStringLength
  152. )
  153. /*++
  154. Routine Description:
  155. Main entrypoint of the HW recognizer test. The routine builds
  156. a configuration tree and leaves it in the hardware heap.
  157. Arguments:
  158. HeapStart - Supplies the starting address of the configuaration heap.
  159. HeapSize - Supplies the size of the heap in byte.
  160. ConfigurationTree - Supplies a 32 bit FLAT address of the variable to
  161. receive the hardware configuration tree.
  162. HeapUsed - Supplies a 32 bit FLAT address of the variable to receive
  163. the actual heap size in used.
  164. OptionString - Supplies a 32 bit FLAT address of load option string.
  165. OptionStringLength - Supplies the length of the OptionString
  166. Returns:
  167. None.
  168. --*/
  169. {
  170. FPFWCONFIGURATION_COMPONENT_DATA ConfigurationRoot;
  171. FPFWCONFIGURATION_COMPONENT_DATA FirstCom = NULL, FirstLpt = NULL;
  172. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry, PreviousEntry;
  173. FPFWCONFIGURATION_COMPONENT_DATA AcpiAdapterEntry = NULL;
  174. FPFWCONFIGURATION_COMPONENT Component;
  175. RELATIONSHIP_FLAGS NextRelationship;
  176. CHAR Identifier[256];
  177. USHORT BiosYear, BiosMonth, BiosDay;
  178. PUCHAR MachineId;
  179. USHORT Length, InitialLength, i, Count = 0;
  180. USHORT PnPBiosLength, SMBIOSLength;
  181. FPCHAR IdentifierString;
  182. PMOUSE_INFORMATION MouseInfo = 0;
  183. USHORT KeyboardId = 0;
  184. ULONG VideoAdapterType = 0;
  185. FPULONG BlConfigurationTree = NULL;
  186. FPULONG BlHeapUsed = NULL;
  187. FPCHAR BlOptions, EndOptions;
  188. PUCHAR RomChain;
  189. FPUCHAR FpRomChain = NULL, ConfigurationData, EndConfigurationData;
  190. SHORT FreeSize;
  191. FPHWPARTIAL_RESOURCE_DESCRIPTOR Descriptor;
  192. FPHWRESOURCE_DESCRIPTOR_LIST DescriptorList;
  193. PCI_REGISTRY_INFO PciEntry;
  194. APM_REGISTRY_INFO ApmEntry;
  195. USHORT nDevIt;
  196. USHORT PCIDeviceCount = 0;
  197. DOCKING_STATION_INFO DockInfo = { 0, 0, 0, FW_DOCKINFO_BIOS_NOT_CALLED };
  198. FPPCI_IRQ_ROUTING_TABLE IrqRoutingTable;
  199. //
  200. // First initialize our hardware heap.
  201. //
  202. HwInitializeHeap(HeapStart, HeapSize);
  203. MAKE_FP(BlConfigurationTree, ConfigurationTree);
  204. MAKE_FP(BlHeapUsed, HeapUsed);
  205. MAKE_FP(BlOptions, OptionString);
  206. //
  207. // Parse OptionString to look for various ntdetect options
  208. //
  209. if (BlOptions && OptionStringLength <= 0x1000L && OptionStringLength > 0L) {
  210. EndOptions = BlOptions + OptionStringLength;
  211. if (*EndOptions == '\0') {
  212. if (_fstrstr(BlOptions, "NOIRQSCAN")) {
  213. DisablePccardIrqScan = 1;
  214. }
  215. if (_fstrstr(BlOptions, "NOIRQROUTING")) {
  216. NoIRQRouting = 1;
  217. }
  218. if (_fstrstr(BlOptions, "PCIENUM") ||
  219. _fstrstr(BlOptions, "RDBUILD") ) {
  220. PCIEnum = 1; // enable PCI enumeration
  221. }
  222. if (_fstrstr(BlOptions, "NOLEGACY")) {
  223. DisableSerialMice = 0xffff;
  224. FastDetect = 0x1;
  225. NoLegacy = 1;
  226. }
  227. if (_fstrstr(BlOptions, "FASTDETECT")) {
  228. DisableSerialMice = 0xffff;
  229. FastDetect = 0x1;
  230. } else {
  231. do {
  232. if (BlOptions = _fstrstr(BlOptions, "NOSERIALMICE")) {
  233. BlOptions += strlen("NOSERIALMICE");
  234. while ((*BlOptions == ' ') || (*BlOptions == ':') ||
  235. (*BlOptions == '=')) {
  236. BlOptions++;
  237. }
  238. if (*BlOptions == 'C' && BlOptions[1] == 'O' &&
  239. BlOptions[2] == 'M') {
  240. BlOptions += 3;
  241. while (TRUE) {
  242. while (*BlOptions != '\0' && (*BlOptions == ' ' ||
  243. *BlOptions == ',' || *BlOptions == ';' ||
  244. *BlOptions == '0')) {
  245. BlOptions++;
  246. }
  247. if (*BlOptions >= '0' && *BlOptions <= '9') {
  248. if (BlOptions[1] < '0' || BlOptions[1] > '9') {
  249. DisableSerialMice |= 1 << (*BlOptions - '0');
  250. BlOptions++;
  251. } else {
  252. BlOptions++;
  253. while (*BlOptions && *BlOptions <= '9' &&
  254. *BlOptions >= '0') {
  255. BlOptions++;
  256. }
  257. }
  258. } else {
  259. break;
  260. }
  261. }
  262. } else {
  263. DisableSerialMice = 0xffff;
  264. break;
  265. }
  266. }
  267. } while (BlOptions && *BlOptions && (BlOptions < EndOptions)); // double checking
  268. }
  269. }
  270. }
  271. //
  272. // Determine bus type
  273. //
  274. if (HwIsEisaSystem()) {
  275. HwBusType = MACHINE_TYPE_EISA;
  276. } else {
  277. HwBusType = MACHINE_TYPE_ISA;
  278. }
  279. //
  280. // Allocate heap space for System component and initialize it.
  281. // Also make the System component the root of configuration tree.
  282. //
  283. #if DBG
  284. clrscrn ();
  285. BlPrint("Detecting System Component ...\n");
  286. #endif
  287. ConfigurationRoot = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  288. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  289. Component = &ConfigurationRoot->ComponentEntry;
  290. Component->Class = SystemClass;
  291. Component->Type = MaximumType; // NOTE should be IsaCompatible
  292. Component->Version = 0;
  293. Component->Key = 0;
  294. Component->AffinityMask = 0;
  295. Component->ConfigurationDataLength = 0;
  296. MachineId = "AT/AT COMPATIBLE";
  297. if (MachineId) {
  298. Length = strlen(MachineId) + 1;
  299. IdentifierString = (FPCHAR)HwAllocateHeap(Length, FALSE);
  300. _fstrcpy(IdentifierString, MachineId);
  301. Component->Identifier = IdentifierString;
  302. Component->IdentifierLength = Length;
  303. } else {
  304. Component->Identifier = 0;
  305. Component->IdentifierLength = 0;
  306. }
  307. NextRelationship = Child;
  308. PreviousEntry = ConfigurationRoot;
  309. #if DBG
  310. BlPrint("Reading BIOS date ...\n");
  311. #endif
  312. HwGetBiosDate (0xF0000, 0xFFFF, &BiosYear, &BiosMonth, &BiosDay);
  313. #if DBG
  314. BlPrint("Done reading BIOS date (%d/%d/%d)\n",
  315. BiosMonth, BiosDay, BiosYear);
  316. BlPrint("Detecting PCI Bus Component ...\n");
  317. #endif
  318. if (BiosYear > 1992 || (BiosYear == 1992 && BiosMonth >= 11) ) {
  319. // Bios date valid for pci presence check..
  320. HwGetPciSystemData((PVOID) &PciEntry, TRUE);
  321. } else {
  322. // Bios date not confirmed...
  323. HwGetPciSystemData((PVOID) &PciEntry, FALSE);
  324. }
  325. // If this is a PCI machine, we may need to get the IRQ routing table...
  326. //
  327. if (PciEntry.NoBuses)
  328. {
  329. // Add a PCI BIOS entry under the multi function key.
  330. // This will hold the irq routing table if it can be retrieved.
  331. //
  332. AdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA) HwAllocateHeap (
  333. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  334. Component = &AdapterEntry->ComponentEntry;
  335. Component->Class = AdapterClass;
  336. Component->Type = MultiFunctionAdapter;
  337. strcpy (Identifier, "PCI BIOS");
  338. i = strlen(Identifier) + 1;
  339. IdentifierString = (FPCHAR)HwAllocateHeap(i, FALSE);
  340. _fstrcpy(IdentifierString, Identifier);
  341. Component->Version = 0;
  342. Component->Key = 0;
  343. Component->AffinityMask = 0xffffffff;
  344. Component->IdentifierLength = i;
  345. Component->Identifier = IdentifierString;
  346. //
  347. // Add it to the tree
  348. //
  349. if (NextRelationship == Sibling) {
  350. PreviousEntry->Sibling = AdapterEntry;
  351. AdapterEntry->Parent = PreviousEntry->Parent;
  352. } else {
  353. PreviousEntry->Child = AdapterEntry;
  354. AdapterEntry->Parent = PreviousEntry;
  355. }
  356. NextRelationship = Sibling;
  357. PreviousEntry = AdapterEntry;
  358. //
  359. // Now deal with the IRQ routing table if we need to.
  360. //
  361. if (NoIRQRouting) {
  362. #if DBG
  363. BlPrint("\nSkipping calling PCI BIOS to get IRQ routing table...\n");
  364. #endif
  365. } else {
  366. //
  367. // Add RealMode IRQ Routing Table to the tree
  368. //
  369. #if DBG
  370. BlPrint("\nCalling PCI BIOS to get IRQ Routing table...\n");
  371. #endif // DBG
  372. IrqRoutingTable = HwGetRealModeIrqRoutingTable();
  373. if (IrqRoutingTable)
  374. {
  375. CurrentEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  376. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  377. strcpy (Identifier, "PCI Real-mode IRQ Routing Table");
  378. i = strlen(Identifier) + 1;
  379. IdentifierString = (FPCHAR)HwAllocateHeap(i, FALSE);
  380. _fstrcpy(IdentifierString, Identifier);
  381. Component = &CurrentEntry->ComponentEntry;
  382. Component->Class = PeripheralClass;
  383. Component->Type = RealModeIrqRoutingTable;
  384. Component->Version = 0;
  385. Component->Key = 0;
  386. Component->AffinityMask = 0xffffffff;
  387. Component->IdentifierLength = i;
  388. Component->Identifier = IdentifierString;
  389. Length = IrqRoutingTable->TableSize + DATA_HEADER_SIZE;
  390. CurrentEntry->ConfigurationData =
  391. (FPHWRESOURCE_DESCRIPTOR_LIST) HwAllocateHeap (Length, TRUE);
  392. Component->ConfigurationDataLength = Length;
  393. _fmemcpy((FPUCHAR) CurrentEntry->ConfigurationData + DATA_HEADER_SIZE,
  394. IrqRoutingTable,
  395. Length - DATA_HEADER_SIZE);
  396. HwSetUpFreeFormDataHeader(
  397. (FPHWRESOURCE_DESCRIPTOR_LIST) CurrentEntry->ConfigurationData,
  398. 0,
  399. 0,
  400. 0,
  401. Length - DATA_HEADER_SIZE
  402. );
  403. //
  404. // Add it to tree
  405. //
  406. AdapterEntry->Child = CurrentEntry;
  407. CurrentEntry->Parent = AdapterEntry;
  408. }
  409. #if DBG
  410. BlPrint("Getting IRQ Routing table from PCI BIOS complete...\n");
  411. #endif // DBG
  412. }
  413. }
  414. //
  415. // Add a registry entry for each PCI bus
  416. //
  417. for (i=0; i < PciEntry.NoBuses; i++) {
  418. AdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  419. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  420. Component = &AdapterEntry->ComponentEntry;
  421. Component->Class = AdapterClass;
  422. Component->Type = MultiFunctionAdapter;
  423. strcpy (Identifier, "PCI");
  424. Length = strlen(Identifier) + 1;
  425. IdentifierString = (FPCHAR)HwAllocateHeap(Length, FALSE);
  426. _fstrcpy(IdentifierString, Identifier);
  427. Component->Version = 0;
  428. Component->Key = 0;
  429. Component->AffinityMask = 0xffffffff;
  430. Component->IdentifierLength = Length;
  431. Component->Identifier = IdentifierString;
  432. AdapterEntry->ConfigurationData = NULL;
  433. Component->ConfigurationDataLength = 0;
  434. if (i == 0) {
  435. //
  436. // For the first PCI bus include the PCI_REGISTRY_INFO
  437. //
  438. Length = sizeof(PCI_REGISTRY_INFO) + DATA_HEADER_SIZE;
  439. ConfigurationData = (FPUCHAR) HwAllocateHeap(Length, TRUE);
  440. Component->ConfigurationDataLength = Length;
  441. AdapterEntry->ConfigurationData = ConfigurationData;
  442. _fmemcpy ( ((FPUCHAR) ConfigurationData+DATA_HEADER_SIZE),
  443. (FPVOID) &PciEntry, sizeof (PCI_REGISTRY_INFO));
  444. HwSetUpFreeFormDataHeader(
  445. (FPHWRESOURCE_DESCRIPTOR_LIST) ConfigurationData,
  446. 0,
  447. 0,
  448. 0,
  449. Length - DATA_HEADER_SIZE
  450. );
  451. }
  452. //
  453. // Add it to tree
  454. //
  455. if (NextRelationship == Sibling) {
  456. PreviousEntry->Sibling = AdapterEntry;
  457. AdapterEntry->Parent = PreviousEntry->Parent;
  458. } else {
  459. PreviousEntry->Child = AdapterEntry;
  460. AdapterEntry->Parent = PreviousEntry;
  461. }
  462. NextRelationship = Sibling;
  463. PreviousEntry = AdapterEntry;
  464. }
  465. #if DBG
  466. BlPrint("Detecting PCI Bus Component completes ...\n");
  467. #endif
  468. //
  469. // Enumerate the PCI Devices.
  470. //
  471. if (PCIEnum == 0 || PciEntry.NoBuses == 0) {
  472. #if DBG
  473. BlPrint("\nSkipping enumeration of PCI devices...\n");
  474. #endif
  475. } else {
  476. //
  477. // Enumerate PCI Devices
  478. //
  479. #if DBG
  480. clrscrn ();
  481. BlPrint("\nEnumerating PCI Devices...\n");
  482. #endif // DBG
  483. PciInit(&PciEntry);
  484. //
  485. // Count the devices
  486. //
  487. for (nDevIt = 0; (nDevIt = PciFindDevice(0, 0, nDevIt)) != 0;) {
  488. PCIDeviceCount++;
  489. }
  490. #if DBG
  491. BlPrint("Found %d PCI devices\n", PCIDeviceCount );
  492. #endif
  493. CurrentEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  494. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  495. strcpy (Identifier, "PCI Devices");
  496. i = strlen(Identifier) + 1;
  497. IdentifierString = (FPCHAR)HwAllocateHeap(i, FALSE);
  498. _fstrcpy(IdentifierString, Identifier);
  499. Component = &CurrentEntry->ComponentEntry;
  500. Component->Class = PeripheralClass;
  501. Component->Type = RealModePCIEnumeration;
  502. Component->Version = 0;
  503. Component->Key = 0;
  504. Component->AffinityMask = 0xffffffff;
  505. Component->IdentifierLength = i;
  506. Component->Identifier = IdentifierString;
  507. Length = (( sizeof( USHORT ) + sizeof( PCI_COMMON_CONFIG )) * PCIDeviceCount) + DATA_HEADER_SIZE;
  508. CurrentEntry->ConfigurationData =
  509. (FPHWRESOURCE_DESCRIPTOR_LIST) HwAllocateHeap (Length, TRUE);
  510. #if DBG
  511. if (CurrentEntry->ConfigurationData == NULL ) {
  512. BlPrint("Failed to allocate %d bytes for PCI Devices\n", Length );
  513. }
  514. #endif
  515. Component->ConfigurationDataLength = Length;
  516. //
  517. // Fill in Device Information
  518. //
  519. PCIDeviceCount = 0;
  520. for (nDevIt = 0; (nDevIt = PciFindDevice(0, 0, nDevIt)) != 0;) {
  521. FPUCHAR pCurrent;
  522. PCI_COMMON_CONFIG config;
  523. PciReadConfig(nDevIt, 0, (UCHAR*)&config, sizeof(config));
  524. pCurrent = (FPUCHAR) CurrentEntry->ConfigurationData + DATA_HEADER_SIZE + ( PCIDeviceCount * ( sizeof( USHORT) + sizeof ( PCI_COMMON_CONFIG ) ) );
  525. *(FPUSHORT)pCurrent = nDevIt;
  526. _fmemcpy(pCurrent + sizeof( USHORT ),
  527. &config,
  528. sizeof ( USHORT ) + sizeof ( PCI_COMMON_CONFIG ) );
  529. #if DBG
  530. {
  531. USHORT x = (config.BaseClass << 8) + config.SubClass;
  532. BlPrint("%d: %x %d.%d.%d: PCI\\VEN_%x&DEV_%x&SUBSYS_%x%x&REV_%x&CC_%x",
  533. PCIDeviceCount,
  534. nDevIt,
  535. PCI_ITERATOR_TO_BUS(nDevIt),
  536. PCI_ITERATOR_TO_DEVICE(nDevIt),
  537. PCI_ITERATOR_TO_FUNCTION(nDevIt),
  538. config.VendorID,
  539. config.DeviceID,
  540. config.u.type0.SubSystemID,
  541. config.u.type0.SubVendorID,
  542. config.RevisionID,
  543. x );
  544. if ( (config.HeaderType & (~PCI_MULTIFUNCTION) ) == PCI_BRIDGE_TYPE) {
  545. BlPrint(" Brdg %d->%d\n",
  546. config.u.type1.PrimaryBus,
  547. config.u.type1.SecondaryBus );
  548. } else {
  549. BlPrint("\n");
  550. }
  551. }
  552. #endif
  553. PCIDeviceCount++;
  554. }
  555. HwSetUpFreeFormDataHeader(
  556. (FPHWRESOURCE_DESCRIPTOR_LIST) CurrentEntry->ConfigurationData,
  557. 0,
  558. 0,
  559. 0,
  560. Length - DATA_HEADER_SIZE
  561. );
  562. //
  563. // Add it to tree
  564. //
  565. AdapterEntry->Child = CurrentEntry;
  566. CurrentEntry->Parent = AdapterEntry;
  567. #if DBG
  568. BlPrint("Enumerating PCI devices complete...\n");
  569. while ( ! HwGetKey ());
  570. clrscrn();
  571. #endif // DBG
  572. }
  573. if (!NoLegacy) {
  574. #if DBG
  575. BlPrint("Detecting APM Bus Component ...\n");
  576. #endif
  577. if (HwGetApmSystemData((PVOID) &ApmEntry)) {
  578. AdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  579. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  580. Component = &AdapterEntry->ComponentEntry;
  581. Component->Class = AdapterClass;
  582. Component->Type = MultiFunctionAdapter;
  583. strcpy (Identifier, "APM");
  584. Length = strlen(Identifier) + 1;
  585. IdentifierString = (FPCHAR)HwAllocateHeap(Length, FALSE);
  586. _fstrcpy(IdentifierString, Identifier);
  587. Component->Version = 0;
  588. Component->Key = 0;
  589. Component->AffinityMask = 0xffffffff;
  590. Component->IdentifierLength = Length;
  591. Component->Identifier = IdentifierString;
  592. AdapterEntry->ConfigurationData = NULL;
  593. Component->ConfigurationDataLength = 0;
  594. //
  595. Length = sizeof(APM_REGISTRY_INFO) + DATA_HEADER_SIZE;
  596. ConfigurationData = (FPUCHAR) HwAllocateHeap(Length, TRUE);
  597. Component->ConfigurationDataLength = Length;
  598. AdapterEntry->ConfigurationData = ConfigurationData;
  599. _fmemcpy ( ((FPUCHAR) ConfigurationData+DATA_HEADER_SIZE),
  600. (FPVOID) &ApmEntry, sizeof (APM_REGISTRY_INFO));
  601. HwSetUpFreeFormDataHeader(
  602. (FPHWRESOURCE_DESCRIPTOR_LIST) ConfigurationData,
  603. 0,
  604. 0,
  605. 0,
  606. Length - DATA_HEADER_SIZE
  607. );
  608. //
  609. // Add it to tree
  610. //
  611. if (NextRelationship == Sibling) {
  612. PreviousEntry->Sibling = AdapterEntry;
  613. AdapterEntry->Parent = PreviousEntry->Parent;
  614. } else {
  615. PreviousEntry->Child = AdapterEntry;
  616. AdapterEntry->Parent = PreviousEntry;
  617. }
  618. NextRelationship = Sibling;
  619. PreviousEntry = AdapterEntry;
  620. }
  621. #if DBG
  622. BlPrint("APM Data collection complete...\n");
  623. #endif // DBG
  624. }
  625. #if DBG
  626. BlPrint("Detecting PnP BIOS Bus Component ...\n");
  627. #endif
  628. if (HwGetPnpBiosSystemData(&ConfigurationData,
  629. &PnPBiosLength,
  630. &SMBIOSLength,
  631. &DockInfo)) {
  632. AdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  633. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  634. AdapterEntry->ConfigurationData = ConfigurationData;
  635. Component = &AdapterEntry->ComponentEntry;
  636. Component->ConfigurationDataLength = PnPBiosLength +
  637. SMBIOSLength +
  638. DATA_HEADER_SIZE +
  639. sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR);
  640. Component->Class = AdapterClass;
  641. Component->Type = MultiFunctionAdapter;
  642. strcpy (Identifier, "PNP BIOS");
  643. i = strlen(Identifier) + 1;
  644. IdentifierString = (FPCHAR)HwAllocateHeap(i, FALSE);
  645. _fstrcpy(IdentifierString, Identifier);
  646. Component->Version = 0;
  647. Component->Key = 0;
  648. Component->AffinityMask = 0xffffffff;
  649. Component->IdentifierLength = i;
  650. Component->Identifier = IdentifierString;
  651. HwSetUpFreeFormDataHeader(
  652. (FPHWRESOURCE_DESCRIPTOR_LIST) ConfigurationData,
  653. 0,
  654. 1,
  655. 0,
  656. PnPBiosLength
  657. );
  658. ((FPHWRESOURCE_DESCRIPTOR_LIST)ConfigurationData)->Count = 2;
  659. //
  660. // Setup SMBIOS PartialDescriptor
  661. Descriptor = (FPHWPARTIAL_RESOURCE_DESCRIPTOR)(ConfigurationData +
  662. PnPBiosLength +
  663. DATA_HEADER_SIZE);
  664. Descriptor->Type = RESOURCE_DEVICE_DATA;
  665. Descriptor->ShareDisposition = 0;
  666. Descriptor->Flags = 0;
  667. Descriptor->u.DeviceSpecificData.DataSize = SMBIOSLength;
  668. Descriptor->u.DeviceSpecificData.Reserved1 = 0;
  669. Descriptor->u.DeviceSpecificData.Reserved2 = 0;
  670. //
  671. // Add it to tree
  672. //
  673. if (NextRelationship == Sibling) {
  674. PreviousEntry->Sibling = AdapterEntry;
  675. AdapterEntry->Parent = PreviousEntry->Parent;
  676. } else {
  677. PreviousEntry->Child = AdapterEntry;
  678. AdapterEntry->Parent = PreviousEntry;
  679. }
  680. NextRelationship = Sibling;
  681. PreviousEntry = AdapterEntry;
  682. //
  683. // Add Docking Information to tree
  684. //
  685. CurrentEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  686. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  687. strcpy (Identifier, "Docking State Information");
  688. i = strlen(Identifier) + 1;
  689. IdentifierString = (FPCHAR)HwAllocateHeap(i, FALSE);
  690. _fstrcpy(IdentifierString, Identifier);
  691. Component = &CurrentEntry->ComponentEntry;
  692. Component->Class = PeripheralClass;
  693. Component->Type = DockingInformation;
  694. Component->Version = 0;
  695. Component->Key = 0;
  696. Component->AffinityMask = 0xffffffff;
  697. Component->IdentifierLength = i;
  698. Component->Identifier = IdentifierString;
  699. Length = sizeof (DockInfo) + DATA_HEADER_SIZE;
  700. CurrentEntry->ConfigurationData =
  701. (FPHWRESOURCE_DESCRIPTOR_LIST) HwAllocateHeap (Length, TRUE);
  702. Component->ConfigurationDataLength = Length;
  703. _fmemcpy((FPCHAR) CurrentEntry->ConfigurationData + DATA_HEADER_SIZE,
  704. &DockInfo,
  705. Length - DATA_HEADER_SIZE);
  706. HwSetUpFreeFormDataHeader(
  707. (FPHWRESOURCE_DESCRIPTOR_LIST) CurrentEntry->ConfigurationData,
  708. 0,
  709. 0,
  710. 0,
  711. Length - DATA_HEADER_SIZE
  712. );
  713. AdapterEntry->Child = CurrentEntry;
  714. CurrentEntry->Parent = AdapterEntry;
  715. }
  716. #if DBG
  717. BlPrint("PnP BIOS Data collection complete...\n");
  718. #endif // DBG
  719. //
  720. // Allocate heap space for Bus component and initialize it.
  721. //
  722. #if DBG
  723. BlPrint("Detecting Bus/Adapter Component ...\n");
  724. #endif
  725. AdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  726. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  727. Component = &AdapterEntry->ComponentEntry;
  728. Component->Class = AdapterClass;
  729. //
  730. // The assumption here is that the machine has only one
  731. // type of IO bus. If a machine has more than one types of
  732. // IO buses, it will not use this detection code anyway.
  733. //
  734. if (HwBusType == MACHINE_TYPE_EISA) {
  735. //
  736. // Note We don't collect EISA config data here. Because we may
  737. // exhaust the heap space. We will collect the data after all
  738. // the other components are detected.
  739. //
  740. Component->Type = EisaAdapter;
  741. strcpy(Identifier, "EISA");
  742. AdapterEntry->ConfigurationData = NULL;
  743. Component->ConfigurationDataLength = 0;
  744. } else {
  745. //
  746. // If not EISA, it must be ISA
  747. //
  748. Component->Type = MultiFunctionAdapter;
  749. strcpy(Identifier, "ISA");
  750. }
  751. Length = strlen(Identifier) + 1;
  752. IdentifierString = (FPCHAR)HwAllocateHeap(Length, FALSE);
  753. _fstrcpy(IdentifierString, Identifier);
  754. Component->Version = 0;
  755. Component->Key = 0;
  756. Component->AffinityMask = 0xffffffff;
  757. Component->IdentifierLength = Length;
  758. Component->Identifier = IdentifierString;
  759. //
  760. // Make Adapter component System's child
  761. //
  762. if (NextRelationship == Sibling) {
  763. PreviousEntry->Sibling = AdapterEntry;
  764. AdapterEntry->Parent = PreviousEntry->Parent;
  765. } else {
  766. PreviousEntry->Child = AdapterEntry;
  767. AdapterEntry->Parent = PreviousEntry;
  768. }
  769. NextRelationship = Child;
  770. PreviousEntry = AdapterEntry;
  771. //
  772. // Collect BIOS information for ConfigurationRoot component.
  773. // This step is done here because we need data collected in
  774. // adapter component. The ConfigurationData is:
  775. // HWRESOURCE_DESCRIPTOR_LIST header
  776. // HWPARTIAL_RESOURCE_DESCRIPTOR for Parameter Table
  777. // HWPARTIAL_RESOURCE_DESCRIPTOR for Rom Blocks.
  778. // (Note DATA_HEADER_SIZE contains the size of the first partial
  779. // descriptor already.)
  780. //
  781. #if DBG
  782. BlPrint("Collecting Disk Geometry...\n");
  783. #endif
  784. GetInt13DriveParameters((PVOID)&RomChain, &Length);
  785. InitialLength = (USHORT)(Length + RESERVED_ROM_BLOCK_LIST_SIZE + DATA_HEADER_SIZE +
  786. sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR));
  787. ConfigurationData = (FPUCHAR)HwAllocateHeap(InitialLength, FALSE);
  788. EndConfigurationData = ConfigurationData + DATA_HEADER_SIZE;
  789. if (Length != 0) {
  790. FpRomChain = EndConfigurationData;
  791. _fmemcpy(FpRomChain, (FPVOID)RomChain, Length);
  792. }
  793. EndConfigurationData += (sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR) +
  794. Length);
  795. HwSetUpFreeFormDataHeader((FPHWRESOURCE_DESCRIPTOR_LIST)ConfigurationData,
  796. 0,
  797. 0,
  798. 0,
  799. Length
  800. );
  801. //
  802. // Scan ROM to collect all the ROM blocks, if possible.
  803. //
  804. #if DBG
  805. BlPrint("Detecting ROM Blocks...\n");
  806. #endif
  807. FpRomBlock = EndConfigurationData;
  808. GetRomBlocks(FpRomBlock, &Length);
  809. RomBlockLength = Length;
  810. if (Length != 0) {
  811. EndConfigurationData += Length;
  812. } else {
  813. FpRomBlock = NULL;
  814. }
  815. //
  816. // We have both RomChain and RomBlock information/Headers.
  817. //
  818. DescriptorList = (FPHWRESOURCE_DESCRIPTOR_LIST)ConfigurationData;
  819. DescriptorList->Count = 2;
  820. Descriptor = (FPHWPARTIAL_RESOURCE_DESCRIPTOR)(
  821. EndConfigurationData - Length -
  822. sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR));
  823. Descriptor->Type = RESOURCE_DEVICE_DATA;
  824. Descriptor->ShareDisposition = 0;
  825. Descriptor->Flags = 0;
  826. Descriptor->u.DeviceSpecificData.DataSize = (ULONG)Length;
  827. Descriptor->u.DeviceSpecificData.Reserved1 = 0;
  828. Descriptor->u.DeviceSpecificData.Reserved2 = 0;
  829. Length = (USHORT)(MAKE_FLAT_ADDRESS(EndConfigurationData) -
  830. MAKE_FLAT_ADDRESS(ConfigurationData));
  831. ConfigurationRoot->ComponentEntry.ConfigurationDataLength = Length;
  832. ConfigurationRoot->ConfigurationData = ConfigurationData;
  833. FreeSize = InitialLength - Length;
  834. HwFreeHeap((ULONG)FreeSize);
  835. //
  836. // Set up device information structure for Keyboard.
  837. //
  838. #if DBG
  839. BlPrint("Detecting Keyboard Component ...\n");
  840. #endif
  841. if (NoLegacy) {
  842. //
  843. // Do not touch the hardware because there may not be a ports 60/64 on
  844. // the machine and we will hang if we try to touch them
  845. //
  846. KeyboardId = UNKNOWN_KEYBOARD;
  847. }
  848. else {
  849. //
  850. // Touch the hardware to try to determine an ID
  851. //
  852. KeyboardId = GetKeyboardId();
  853. }
  854. CurrentEntry = SetKeyboardConfigurationData(KeyboardId);
  855. //
  856. // Make display component the child of Adapter component.
  857. //
  858. if (NextRelationship == Sibling) {
  859. PreviousEntry->Sibling = CurrentEntry;
  860. CurrentEntry->Parent = PreviousEntry->Parent;
  861. } else {
  862. PreviousEntry->Child = CurrentEntry;
  863. CurrentEntry->Parent = PreviousEntry;
  864. }
  865. NextRelationship = Sibling;
  866. PreviousEntry = CurrentEntry;
  867. if (!NoLegacy) {
  868. //
  869. // Set up device information for com port (Each COM component
  870. // is treated as a controller class.)
  871. //
  872. #if DBG
  873. BlPrint("Detecting ComPort Component ...\n");
  874. #endif
  875. if (CurrentEntry = GetComportInformation()) {
  876. FirstCom = CurrentEntry;
  877. //
  878. // Make current component the child of Adapter component.
  879. //
  880. if (NextRelationship == Sibling) {
  881. PreviousEntry->Sibling = CurrentEntry;
  882. } else {
  883. PreviousEntry->Child = CurrentEntry;
  884. }
  885. while (CurrentEntry) {
  886. CurrentEntry->Parent = AdapterEntry;
  887. PreviousEntry = CurrentEntry;
  888. CurrentEntry = CurrentEntry->Sibling;
  889. }
  890. NextRelationship = Sibling;
  891. }
  892. //
  893. // Set up device information for parallel port. (Each parallel
  894. // is treated as a controller class.)
  895. //
  896. #if DBG
  897. BlPrint("Detecting Parallel Component ...\n");
  898. #endif
  899. if (CurrentEntry = GetLptInformation()) {
  900. FirstLpt = CurrentEntry;
  901. //
  902. // Make current component the child of Adapter component.
  903. //
  904. if (NextRelationship == Sibling) {
  905. PreviousEntry->Sibling = CurrentEntry;
  906. CurrentEntry->Parent = PreviousEntry->Parent;
  907. } else {
  908. PreviousEntry->Child = CurrentEntry;
  909. CurrentEntry->Parent = PreviousEntry;
  910. }
  911. PreviousEntry = CurrentEntry;
  912. CurrentEntry = CurrentEntry->Sibling;
  913. while (CurrentEntry) {
  914. CurrentEntry->Parent = PreviousEntry->Parent;
  915. PreviousEntry = CurrentEntry;
  916. CurrentEntry = CurrentEntry->Sibling;
  917. }
  918. NextRelationship = Sibling;
  919. }
  920. //
  921. // Set up device information structure for Mouse.
  922. //
  923. #if DBG
  924. BlPrint("Detecting Mouse Component ...\n");
  925. #endif
  926. if (CurrentEntry = GetMouseInformation()) {
  927. //
  928. // Make current component the child of Adapter component.
  929. //
  930. if (NextRelationship == Sibling) {
  931. PreviousEntry->Sibling = CurrentEntry;
  932. CurrentEntry->Parent = PreviousEntry->Parent;
  933. } else {
  934. PreviousEntry->Child = CurrentEntry;
  935. CurrentEntry->Parent = PreviousEntry;
  936. }
  937. PreviousEntry = CurrentEntry;
  938. CurrentEntry = CurrentEntry->Sibling;
  939. while (CurrentEntry) {
  940. CurrentEntry->Parent = PreviousEntry->Parent;
  941. PreviousEntry = CurrentEntry;
  942. CurrentEntry = CurrentEntry->Sibling;
  943. }
  944. NextRelationship = Sibling;
  945. }
  946. }
  947. //
  948. // Set up device information for floppy drives. (The returned information
  949. // is a tree structure.)
  950. //
  951. #if DBG
  952. BlPrint("Detecting Floppy Component ...\n");
  953. #endif
  954. if (CurrentEntry = GetFloppyInformation()) {
  955. //
  956. // Make current component the child of Adapter component.
  957. //
  958. if (NextRelationship == Sibling) {
  959. PreviousEntry->Sibling = CurrentEntry;
  960. } else {
  961. PreviousEntry->Child = CurrentEntry;
  962. }
  963. while (CurrentEntry) {
  964. CurrentEntry->Parent = AdapterEntry;
  965. PreviousEntry = CurrentEntry;
  966. CurrentEntry = CurrentEntry->Sibling;
  967. }
  968. NextRelationship = Sibling;
  969. }
  970. #if DBG
  971. BlPrint("Detecting PcCard ISA IRQ mapping ...\n");
  972. #endif
  973. if (CurrentEntry = GetPcCardInformation()) {
  974. //
  975. // Make current component the child of Adapter component.
  976. //
  977. if (NextRelationship == Sibling) {
  978. PreviousEntry->Sibling = CurrentEntry;
  979. CurrentEntry->Parent = PreviousEntry->Parent;
  980. } else {
  981. PreviousEntry->Child = CurrentEntry;
  982. CurrentEntry->Parent = PreviousEntry;
  983. }
  984. PreviousEntry = CurrentEntry;
  985. CurrentEntry = CurrentEntry->Sibling;
  986. while (CurrentEntry) {
  987. CurrentEntry->Parent = PreviousEntry->Parent;
  988. PreviousEntry = CurrentEntry;
  989. CurrentEntry = CurrentEntry->Sibling;
  990. }
  991. NextRelationship = Sibling;
  992. }
  993. #if DBG
  994. BlPrint("Detecting ACPI Bus Component ...\n");
  995. #endif
  996. if (HwGetAcpiBiosData(&ConfigurationData, &Length)) {
  997. AcpiAdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  998. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  999. AcpiAdapterEntry->ConfigurationData = ConfigurationData;
  1000. Component = &AcpiAdapterEntry->ComponentEntry;
  1001. Component->ConfigurationDataLength = Length;
  1002. Component->Class = AdapterClass;
  1003. Component->Type = MultiFunctionAdapter;
  1004. strcpy (Identifier, "ACPI BIOS");
  1005. i = strlen(Identifier) + 1;
  1006. IdentifierString = (FPCHAR)HwAllocateHeap(i, FALSE);
  1007. _fstrcpy(IdentifierString, Identifier);
  1008. Component->Version = 0;
  1009. Component->Key = 0;
  1010. Component->AffinityMask = 0xffffffff;
  1011. Component->IdentifierLength = i;
  1012. Component->Identifier = IdentifierString;
  1013. HwSetUpFreeFormDataHeader(
  1014. (FPHWRESOURCE_DESCRIPTOR_LIST) ConfigurationData,
  1015. 0,
  1016. 0,
  1017. 0,
  1018. Length - DATA_HEADER_SIZE
  1019. );
  1020. //
  1021. // Add it to tree
  1022. //
  1023. // Big hack here. This code inserts the ACPI node in
  1024. // the tree one level higher than the ISA devices in
  1025. // the code right above. But this doesn't work in
  1026. // the NoLegacy case because these devices haven't
  1027. // been added to the tree.
  1028. //
  1029. // Ideally, this code would just be moved above the ISA
  1030. // device detection code. That would be simpler. But
  1031. // That causes current ACPI machines to fail to dual-boot
  1032. // because their ARC paths would change.
  1033. //
  1034. // if (NoLegacy) {
  1035. //
  1036. // if (NextRelationship == Sibling) {
  1037. // PreviousEntry->Sibling = AcpiAdapterEntry;
  1038. // AcpiAdapterEntry->Parent = PreviousEntry->Parent;
  1039. // } else {
  1040. // PreviousEntry->Child = AdapterEntry;
  1041. // AdapterEntry->Parent = PreviousEntry;
  1042. // }
  1043. //
  1044. // PreviousEntry = AdapterEntry;
  1045. //
  1046. // } else {
  1047. if (NextRelationship == Sibling) {
  1048. PreviousEntry->Parent->Sibling = AcpiAdapterEntry;
  1049. AcpiAdapterEntry->Parent = PreviousEntry->Parent->Parent;
  1050. }
  1051. // }
  1052. NextRelationship = Sibling;
  1053. }
  1054. #if DBG
  1055. BlPrint("ACPI BIOS Data collection complete...\n");
  1056. #endif // DBG
  1057. #if DBG
  1058. BlPrint("Detection done. Press a key to display hardware info ...\n");
  1059. while ( ! HwGetKey ());
  1060. clrscrn ();
  1061. #endif
  1062. //
  1063. // Misc. supports. Note, the information collected here will NOT be
  1064. // written to hardware registry.
  1065. //
  1066. // 1. Collect video font information for vdm
  1067. //
  1068. GetVideoFontInformation();
  1069. //
  1070. // After all the components are detected, we collect EISA config data.
  1071. //
  1072. if (HwBusType == MACHINE_TYPE_EISA) {
  1073. Component = &AdapterEntry->ComponentEntry;
  1074. GetEisaConfigurationData(&AdapterEntry->ConfigurationData,
  1075. &Component->ConfigurationDataLength);
  1076. if (Component->ConfigurationDataLength) {
  1077. HwEisaConfigurationData = (FPUCHAR)AdapterEntry->ConfigurationData +
  1078. DATA_HEADER_SIZE;
  1079. HwEisaConfigurationSize = Component->ConfigurationDataLength -
  1080. DATA_HEADER_SIZE;
  1081. //
  1082. // Misc. detections based on Eisa config data
  1083. //
  1084. // Update Lpt and com controllers' irq information by examining
  1085. // the EISA configuration data.
  1086. //
  1087. GetIrqFromEisaData(FirstLpt, ParallelController);
  1088. GetIrqFromEisaData(FirstCom, SerialController);
  1089. }
  1090. }
  1091. #if DBG
  1092. CheckConfigurationTree(ConfigurationRoot);
  1093. #endif
  1094. //
  1095. // Update all the far pointers in the tree to flat 32 bit pointers
  1096. //
  1097. UpdateConfigurationTree(ConfigurationRoot);
  1098. //
  1099. // Set up returned values:
  1100. // Size of Heap space which should be preserved for configuration tree
  1101. // Pointer to the root of the configuration tree.
  1102. //
  1103. CurrentEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap(0, FALSE);
  1104. *BlHeapUsed = MAKE_FLAT_ADDRESS(CurrentEntry) -
  1105. MAKE_FLAT_ADDRESS(ConfigurationRoot);
  1106. *BlConfigurationTree = (ULONG)MAKE_FLAT_ADDRESS(ConfigurationRoot);
  1107. }
  1108. VOID
  1109. GetIrqFromEisaData(
  1110. FPFWCONFIGURATION_COMPONENT_DATA ControllerList,
  1111. CONFIGURATION_TYPE ControllerType
  1112. )
  1113. /*++
  1114. Routine Description:
  1115. This routine updates all irq information for ControllerType components
  1116. in the controllerList by examinine the eisa configuration data.
  1117. Arguments:
  1118. ControllerList - Supplies a pointer to a component entry whoes irq will
  1119. be updated.
  1120. ControllerType - Supplies the controller type whoes irq will be searched
  1121. for.
  1122. Returns:
  1123. None.
  1124. --*/
  1125. {
  1126. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry;
  1127. FPHWPARTIAL_RESOURCE_DESCRIPTOR Descriptor;
  1128. FPHWRESOURCE_DESCRIPTOR_LIST DescriptorList;
  1129. USHORT i, Port;
  1130. UCHAR Irq, Trigger;
  1131. CurrentEntry = ControllerList;
  1132. while (CurrentEntry &&
  1133. CurrentEntry->ComponentEntry.Type == ControllerType) {
  1134. if (CurrentEntry->ConfigurationData) {
  1135. DescriptorList = (FPHWRESOURCE_DESCRIPTOR_LIST)
  1136. CurrentEntry->ConfigurationData;
  1137. Port = 0;
  1138. for (i = 0; i < (USHORT)DescriptorList->Count; i++) {
  1139. Descriptor = &DescriptorList->PartialDescriptors[i];
  1140. if (Descriptor->Type == CmResourceTypePort) {
  1141. Port = (USHORT)Descriptor->u.Port.Start.LowPart;
  1142. break;
  1143. }
  1144. }
  1145. if (Port != 0) {
  1146. for (i = 0; i < (USHORT)DescriptorList->Count; i++) {
  1147. Descriptor = &DescriptorList->PartialDescriptors[i];
  1148. if (Descriptor->Type == CmResourceTypeInterrupt) {
  1149. if (HwEisaGetIrqFromPort(Port, &Irq, &Trigger)) {
  1150. if (Trigger == 0) { // EISA EDGE_TRIGGER
  1151. Descriptor->Flags = EDGE_TRIGGERED;
  1152. } else {
  1153. Descriptor->Flags = LEVEL_SENSITIVE;
  1154. }
  1155. Descriptor->u.Interrupt.Level = Irq;
  1156. Descriptor->u.Interrupt.Vector = Irq;
  1157. break;
  1158. }
  1159. }
  1160. }
  1161. }
  1162. }
  1163. CurrentEntry = CurrentEntry->Sibling;
  1164. }
  1165. }
  1166. VOID
  1167. UpdateComponentPointers(
  1168. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
  1169. )
  1170. /*++
  1171. Routine Description:
  1172. This routine updates all the "far" pointer to 32 bit flat addresses
  1173. for a component entry.
  1174. Arguments:
  1175. CurrentEntry - Supplies a pointer to a component entry which will
  1176. be updated.
  1177. Returns:
  1178. None.
  1179. --*/
  1180. {
  1181. FPULONG UpdatePointer;
  1182. FPVOID NextEntry;
  1183. ULONG FlatAddress;
  1184. //
  1185. // Update the child, parent, sibling and ConfigurationData
  1186. // far pointers to 32 bit flat addresses.
  1187. // N.B. After we update the pointers to flat addresses, they
  1188. // can no longer be accessed in real mode.
  1189. //
  1190. UpdatePointer = (FPULONG)&CurrentEntry->Child;
  1191. NextEntry = (FPVOID)CurrentEntry->Child;
  1192. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1193. *UpdatePointer = FlatAddress;
  1194. UpdatePointer = (FPULONG)&CurrentEntry->Parent;
  1195. NextEntry = (FPVOID)CurrentEntry->Parent;
  1196. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1197. *UpdatePointer = FlatAddress;
  1198. UpdatePointer = (FPULONG)&CurrentEntry->Sibling;
  1199. NextEntry = (FPVOID)CurrentEntry->Sibling;
  1200. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1201. *UpdatePointer = FlatAddress;
  1202. UpdatePointer = (FPULONG)&CurrentEntry->ComponentEntry.Identifier;
  1203. NextEntry = (FPVOID)CurrentEntry->ComponentEntry.Identifier;
  1204. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1205. *UpdatePointer = FlatAddress;
  1206. UpdatePointer = (FPULONG)&CurrentEntry->ConfigurationData;
  1207. NextEntry = (FPVOID)CurrentEntry->ConfigurationData;
  1208. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1209. *UpdatePointer = FlatAddress;
  1210. }
  1211. VOID
  1212. UpdateConfigurationTree(
  1213. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
  1214. )
  1215. /*++
  1216. Routine Description:
  1217. This routine traverses loader configuration tree and changes
  1218. all the "far" pointer to 32 bit flat addresses.
  1219. Arguments:
  1220. CurrentEntry - Supplies a pointer to a loader configuration
  1221. tree or subtree.
  1222. Returns:
  1223. None.
  1224. --*/
  1225. {
  1226. FPFWCONFIGURATION_COMPONENT_DATA TempEntry;
  1227. while (CurrentEntry)
  1228. {
  1229. //
  1230. // Spin down finding the deepest child
  1231. //
  1232. while (CurrentEntry->Child) {
  1233. CurrentEntry = CurrentEntry->Child;
  1234. }
  1235. //
  1236. // Now we need to either move to the next sibling. If we
  1237. // don't have a sibling we need to walk up through the parents
  1238. // until we find an entry with a sibling. We have to save
  1239. // off the current entry since after we update the entry the
  1240. // pointer are no longer useable.
  1241. //
  1242. while (CurrentEntry) {
  1243. TempEntry = CurrentEntry;
  1244. if (CurrentEntry->Sibling != NULL) {
  1245. CurrentEntry = CurrentEntry->Sibling;
  1246. UpdateComponentPointers(TempEntry);
  1247. break;
  1248. } else {
  1249. CurrentEntry = CurrentEntry->Parent;
  1250. UpdateComponentPointers(TempEntry);
  1251. }
  1252. }
  1253. }
  1254. }
  1255. FPVOID
  1256. HwSetUpResourceDescriptor (
  1257. FPFWCONFIGURATION_COMPONENT Component,
  1258. PUCHAR Identifier,
  1259. PHWCONTROLLER_DATA ControlData,
  1260. USHORT SpecificDataLength,
  1261. PUCHAR SpecificData
  1262. )
  1263. /*++
  1264. Routine Description:
  1265. This routine allocates space from far heap , puts the caller's controller
  1266. information to the space and sets up CONFIGURATION_COMPONENT
  1267. structure for the caller.
  1268. Arguments:
  1269. Component - Supplies the address the component whose configuration data
  1270. should be set up.
  1271. Identifier - Suppies a pointer to the identifier to identify the controller
  1272. ControlData - Supplies a point to a structure which describes
  1273. controller information.
  1274. SpecificDataLength - size of the device specific data. Device specific
  1275. data is the information not defined in the standard format.
  1276. SpecificData - Supplies a pointer to the device specific data.
  1277. Return Value:
  1278. Returns a far pointer to the Configuration data.
  1279. --*/
  1280. {
  1281. FPCHAR fpIdentifier;
  1282. FPHWRESOURCE_DESCRIPTOR_LIST fpDescriptor = NULL;
  1283. USHORT Length;
  1284. SHORT Count, i;
  1285. FPUCHAR fpSpecificData;
  1286. //
  1287. // Set up Identifier string for hardware component, if necessary.
  1288. //
  1289. if (Identifier) {
  1290. Length = strlen(Identifier) + 1;
  1291. Component->IdentifierLength = Length;
  1292. fpIdentifier = (FPUCHAR)HwAllocateHeap(Length, FALSE);
  1293. Component->Identifier = fpIdentifier;
  1294. _fstrcpy(fpIdentifier, Identifier);
  1295. } else {
  1296. Component->IdentifierLength = 0;
  1297. Component->Identifier = NULL;
  1298. }
  1299. //
  1300. // Set up configuration data for hardware component, if necessary
  1301. //
  1302. Count = ControlData->NumberPortEntries + ControlData->NumberIrqEntries +
  1303. ControlData->NumberMemoryEntries + ControlData->NumberDmaEntries;
  1304. if (SpecificDataLength) {
  1305. //
  1306. // if we have device specific data, we need to increment the count
  1307. // by one.
  1308. //
  1309. Count++;
  1310. }
  1311. if (Count >0) {
  1312. Length = (USHORT)(Count * sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR) +
  1313. FIELD_OFFSET(HWRESOURCE_DESCRIPTOR_LIST, PartialDescriptors) +
  1314. SpecificDataLength);
  1315. fpDescriptor = (FPHWRESOURCE_DESCRIPTOR_LIST)HwAllocateHeap(Length, TRUE);
  1316. fpDescriptor->Count = Count;
  1317. //
  1318. // Copy all the partial descriptors to the destination descriptors
  1319. // except the last one. (The last partial descriptor may be a device
  1320. // specific data. It requires special handling.)
  1321. //
  1322. for (i = 0; i < (Count - 1); i++) {
  1323. fpDescriptor->PartialDescriptors[i] =
  1324. ControlData->DescriptorList[i];
  1325. }
  1326. //
  1327. // Set up the last partial descriptor. If it is a port, memory, irq or
  1328. // dma entry, we simply copy it. If the last one is for device specific
  1329. // data, we set up the length and copy the device spcific data to the end
  1330. // of the decriptor.
  1331. //
  1332. if (SpecificData) {
  1333. fpDescriptor->PartialDescriptors[Count - 1].Type =
  1334. RESOURCE_DEVICE_DATA;
  1335. fpDescriptor->PartialDescriptors[Count - 1].Flags = 0;
  1336. fpDescriptor->PartialDescriptors[Count - 1].u.DeviceSpecificData.DataSize =
  1337. SpecificDataLength;
  1338. fpSpecificData = (FPUCHAR)&(fpDescriptor->PartialDescriptors[Count]);
  1339. _fmemcpy(fpSpecificData, SpecificData, SpecificDataLength);
  1340. } else {
  1341. fpDescriptor->PartialDescriptors[Count - 1] =
  1342. ControlData->DescriptorList[Count - 1];
  1343. }
  1344. Component->ConfigurationDataLength = Length;
  1345. }
  1346. return(fpDescriptor);
  1347. }
  1348. VOID
  1349. HwSetUpFreeFormDataHeader (
  1350. FPHWRESOURCE_DESCRIPTOR_LIST Header,
  1351. USHORT Version,
  1352. USHORT Revision,
  1353. USHORT Flags,
  1354. ULONG DataSize
  1355. )
  1356. /*++
  1357. Routine Description:
  1358. This routine initialize free formed data header. Note this routine
  1359. sets the the Header and initialize the FIRST PartialDescriptor only.
  1360. If the header contains more than one descriptor, the caller must handle
  1361. it itself.
  1362. Arguments:
  1363. Header - Supplies a pointer to the header to be initialized.
  1364. Version - Version number for the header.
  1365. Revision - Revision number for the header.
  1366. Flags - Free formed data flags. (Currently, it is undefined and
  1367. should be zero.)
  1368. DataSize - Size of the free formed data.
  1369. Return Value:
  1370. None.
  1371. --*/
  1372. {
  1373. Header->Version = Version;
  1374. Header->Revision = Revision;
  1375. Header->Count = 1;
  1376. Header->PartialDescriptors[0].Type = RESOURCE_DEVICE_DATA;
  1377. Header->PartialDescriptors[0].ShareDisposition = 0;
  1378. Header->PartialDescriptors[0].Flags = Flags;
  1379. Header->PartialDescriptors[0].u.DeviceSpecificData.DataSize = DataSize;
  1380. Header->PartialDescriptors[0].u.DeviceSpecificData.Reserved1 = 0;
  1381. Header->PartialDescriptors[0].u.DeviceSpecificData.Reserved2 = 0;
  1382. }
  1383. #if DBG
  1384. VOID
  1385. CheckComponentNode(
  1386. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
  1387. )
  1388. {
  1389. FPUCHAR NextEntry, DataPointer;
  1390. ULONG FlatAddress;
  1391. ULONG Length;
  1392. UCHAR IdString[40];
  1393. USHORT Count, i;
  1394. UCHAR Type;
  1395. FPHWRESOURCE_DESCRIPTOR_LIST DescriptorList;
  1396. FPHWPARTIAL_RESOURCE_DESCRIPTOR Descriptor;
  1397. FlatAddress = MAKE_FLAT_ADDRESS(CurrentEntry);
  1398. clrscrn ();
  1399. BlPrint("\n");
  1400. BlPrint("Current Node: %lx\n", FlatAddress);
  1401. BlPrint(" Type = %s\n", TypeName[CurrentEntry->ComponentEntry.Type]);
  1402. //
  1403. // Update the child, parent, sibling and ConfigurationData
  1404. // far pointers to 32 bit flat addresses.
  1405. // N.B. After we update the pointers to flat addresses, they
  1406. // can no longer be accessed in real mode.
  1407. //
  1408. NextEntry = (FPUCHAR)CurrentEntry->Child;
  1409. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1410. if (FlatAddress > 0x60000 || (FlatAddress < 0x50000 && FlatAddress != 0)) {
  1411. BlPrint("Invalid address: Child = %lx\n", FlatAddress);
  1412. } else {
  1413. BlPrint("\tChild = %lx\n", FlatAddress);
  1414. }
  1415. NextEntry = (FPUCHAR)CurrentEntry->Parent;
  1416. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1417. if (FlatAddress > 0x60000 || (FlatAddress < 0x50000 && FlatAddress != 0)) {
  1418. BlPrint("Invalid address: Parent = %lx\n", FlatAddress);
  1419. } else {
  1420. BlPrint("\tParent = %lx\n", FlatAddress);
  1421. }
  1422. NextEntry = (FPUCHAR)CurrentEntry->Sibling;
  1423. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1424. if (FlatAddress > 0x60000 || (FlatAddress < 0x50000 && FlatAddress != 0)) {
  1425. BlPrint("Invalid address: Sibling = %lx\n", FlatAddress);
  1426. } else {
  1427. BlPrint("\tSibling = %lx\n", FlatAddress);
  1428. }
  1429. NextEntry = (FPUCHAR)CurrentEntry->ConfigurationData;
  1430. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1431. if (FlatAddress > 0x60000 || (FlatAddress < 0x50000 && FlatAddress != 0)) {
  1432. BlPrint("Invalid address: ConfigurationData = %lx\n", FlatAddress);
  1433. } else {
  1434. BlPrint("\tConfigurationData = %lx\n", FlatAddress);
  1435. }
  1436. Length = CurrentEntry->ComponentEntry.IdentifierLength;
  1437. BlPrint("IdentifierLength = %lx\n", CurrentEntry->ComponentEntry.IdentifierLength);
  1438. if (Length > 0) {
  1439. _fstrcpy(IdString, CurrentEntry->ComponentEntry.Identifier);
  1440. BlPrint("Identifier = %s\n", IdString);
  1441. }
  1442. Length = CurrentEntry->ComponentEntry.ConfigurationDataLength;
  1443. BlPrint("ConfigdataLength = %lx\n", Length);
  1444. if (Length > 0) {
  1445. DescriptorList = (FPHWRESOURCE_DESCRIPTOR_LIST)CurrentEntry->ConfigurationData;
  1446. BlPrint("Version = %x, Revision = %x\n", DescriptorList->Version,
  1447. DescriptorList->Revision);
  1448. Count = (USHORT)DescriptorList->Count;
  1449. Descriptor = &DescriptorList->PartialDescriptors[0];
  1450. BlPrint("Count = %x\n", Count);
  1451. while (Count > 0) {
  1452. Type = Descriptor->Type;
  1453. if (Type == RESOURCE_PORT) {
  1454. BlPrint("Type = Port");
  1455. BlPrint("\tShareDisposition = %x\n", Descriptor->ShareDisposition);
  1456. BlPrint("PortFlags = %x\n", Descriptor->Flags);
  1457. BlPrint("PortStart = %x", Descriptor->u.Port.Start);
  1458. BlPrint("\tPortLength = %x\n", Descriptor->u.Port.Length);
  1459. } else if (Type == RESOURCE_DMA) {
  1460. BlPrint("Type = Dma");
  1461. BlPrint("\tShareDisposition = %x\n", Descriptor->ShareDisposition);
  1462. BlPrint("DmaFlags = %x\n", Descriptor->Flags);
  1463. BlPrint("DmaChannel = %x", Descriptor->u.Dma.Channel);
  1464. BlPrint("\tDmaPort = %lx\n", Descriptor->u.Dma.Port);
  1465. } else if (Type == RESOURCE_INTERRUPT) {
  1466. BlPrint("Type = Interrupt");
  1467. BlPrint("\tShareDisposition = %x\n", Descriptor->ShareDisposition);
  1468. BlPrint("InterruptFlags = %x\n", Descriptor->Flags);
  1469. BlPrint("Level = %x", Descriptor->u.Interrupt.Level);
  1470. BlPrint("\tVector = %x\n", Descriptor->u.Interrupt.Vector);
  1471. } else if (Type == RESOURCE_MEMORY) {
  1472. BlPrint("Type = Memory");
  1473. BlPrint("\tShareDisposition = %x\n", Descriptor->ShareDisposition);
  1474. BlPrint("MemoryFlags = %x\n", Descriptor->Flags);
  1475. BlPrint("Start1 = %lx", (ULONG)Descriptor->u.Memory.Start.LowPart);
  1476. BlPrint("\tStart2 = %lx", (ULONG)Descriptor->u.Memory.Start.HighPart);
  1477. BlPrint("\tLength = %lx\n", Descriptor->u.Memory.Length);
  1478. } else {
  1479. BlPrint("Type = Device Data\n");
  1480. Length = Descriptor->u.DeviceSpecificData.DataSize;
  1481. BlPrint("Size = %lx\n", Length);
  1482. DataPointer = (FPUCHAR)(Descriptor+1);
  1483. for (i = 0; (i < (USHORT)Length) && (i < 64); i++) {
  1484. BlPrint("%x ", *DataPointer);
  1485. DataPointer++;
  1486. }
  1487. break;
  1488. }
  1489. Count--;
  1490. Descriptor++;
  1491. }
  1492. }
  1493. while (HwGetKey() == 0) {
  1494. }
  1495. }
  1496. VOID
  1497. CheckConfigurationTree(
  1498. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
  1499. )
  1500. {
  1501. FPFWCONFIGURATION_COMPONENT_DATA TempEntry;
  1502. while (CurrentEntry)
  1503. {
  1504. //
  1505. // Spin down finding the deepest child
  1506. //
  1507. while (CurrentEntry->Child) {
  1508. CurrentEntry = CurrentEntry->Child;
  1509. }
  1510. //
  1511. // Now we need to either move to the next sibling. If we
  1512. // don't have a sibling we need to walk up through the parents
  1513. // until we find an entry with a sibling. We have to save
  1514. // off the current entry since after we update the entry the
  1515. // pointer are no longer useable.
  1516. //
  1517. while (CurrentEntry) {
  1518. TempEntry = CurrentEntry;
  1519. if (CurrentEntry->Sibling != NULL) {
  1520. CurrentEntry = CurrentEntry->Sibling;
  1521. CheckComponentNode(TempEntry);
  1522. break;
  1523. } else {
  1524. CurrentEntry = CurrentEntry->Parent;
  1525. CheckComponentNode(TempEntry);
  1526. }
  1527. }
  1528. }
  1529. }
  1530. #endif