Leaked source code of windows server 2003
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.

1889 lines
59 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. ULONG 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 = PCI_ITERATOR_TO_BUSDEVFUNC(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: %d.%d.%d: PCI\\VEN_%x&DEV_%x&SUBSYS_%x%x&REV_%x&CC_%x",
  533. PCIDeviceCount,
  534. PCI_ITERATOR_TO_BUS(nDevIt),
  535. PCI_ITERATOR_TO_DEVICE(nDevIt),
  536. PCI_ITERATOR_TO_FUNCTION(nDevIt),
  537. config.VendorID,
  538. config.DeviceID,
  539. config.u.type0.SubSystemID,
  540. config.u.type0.SubVendorID,
  541. config.RevisionID,
  542. x );
  543. if ( (config.HeaderType & (~PCI_MULTIFUNCTION) ) == PCI_BRIDGE_TYPE) {
  544. BlPrint(" Brdg %d->%d\n",
  545. config.u.type1.PrimaryBus,
  546. config.u.type1.SecondaryBus );
  547. } else {
  548. BlPrint("\n");
  549. }
  550. }
  551. #endif
  552. PCIDeviceCount++;
  553. }
  554. HwSetUpFreeFormDataHeader(
  555. (FPHWRESOURCE_DESCRIPTOR_LIST) CurrentEntry->ConfigurationData,
  556. 0,
  557. 0,
  558. 0,
  559. Length - DATA_HEADER_SIZE
  560. );
  561. //
  562. // Add it to tree
  563. //
  564. AdapterEntry->Child = CurrentEntry;
  565. CurrentEntry->Parent = AdapterEntry;
  566. #if DBG
  567. BlPrint("Enumerating PCI devices complete...\n");
  568. while ( ! HwGetKey ());
  569. clrscrn();
  570. #endif // DBG
  571. #if DBG
  572. //
  573. // Scan the PCI Bus via the bios
  574. //
  575. ScanPCIViaBIOS(&PciEntry);
  576. #endif
  577. }
  578. if (!NoLegacy) {
  579. #if DBG
  580. BlPrint("Detecting APM Bus Component ...\n");
  581. #endif
  582. if (HwGetApmSystemData((PVOID) &ApmEntry)) {
  583. AdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  584. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  585. Component = &AdapterEntry->ComponentEntry;
  586. Component->Class = AdapterClass;
  587. Component->Type = MultiFunctionAdapter;
  588. strcpy (Identifier, "APM");
  589. Length = strlen(Identifier) + 1;
  590. IdentifierString = (FPCHAR)HwAllocateHeap(Length, FALSE);
  591. _fstrcpy(IdentifierString, Identifier);
  592. Component->Version = 0;
  593. Component->Key = 0;
  594. Component->AffinityMask = 0xffffffff;
  595. Component->IdentifierLength = Length;
  596. Component->Identifier = IdentifierString;
  597. AdapterEntry->ConfigurationData = NULL;
  598. Component->ConfigurationDataLength = 0;
  599. //
  600. Length = sizeof(APM_REGISTRY_INFO) + DATA_HEADER_SIZE;
  601. ConfigurationData = (FPUCHAR) HwAllocateHeap(Length, TRUE);
  602. Component->ConfigurationDataLength = Length;
  603. AdapterEntry->ConfigurationData = ConfigurationData;
  604. _fmemcpy ( ((FPUCHAR) ConfigurationData+DATA_HEADER_SIZE),
  605. (FPVOID) &ApmEntry, sizeof (APM_REGISTRY_INFO));
  606. HwSetUpFreeFormDataHeader(
  607. (FPHWRESOURCE_DESCRIPTOR_LIST) ConfigurationData,
  608. 0,
  609. 0,
  610. 0,
  611. Length - DATA_HEADER_SIZE
  612. );
  613. //
  614. // Add it to tree
  615. //
  616. if (NextRelationship == Sibling) {
  617. PreviousEntry->Sibling = AdapterEntry;
  618. AdapterEntry->Parent = PreviousEntry->Parent;
  619. } else {
  620. PreviousEntry->Child = AdapterEntry;
  621. AdapterEntry->Parent = PreviousEntry;
  622. }
  623. NextRelationship = Sibling;
  624. PreviousEntry = AdapterEntry;
  625. }
  626. #if DBG
  627. BlPrint("APM Data collection complete...\n");
  628. #endif // DBG
  629. }
  630. #if DBG
  631. BlPrint("Detecting PnP BIOS Bus Component ...\n");
  632. #endif
  633. if (HwGetPnpBiosSystemData(&ConfigurationData,
  634. &PnPBiosLength,
  635. &SMBIOSLength,
  636. &DockInfo)) {
  637. AdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  638. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  639. AdapterEntry->ConfigurationData = ConfigurationData;
  640. Component = &AdapterEntry->ComponentEntry;
  641. Component->ConfigurationDataLength = PnPBiosLength +
  642. SMBIOSLength +
  643. DATA_HEADER_SIZE +
  644. sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR);
  645. Component->Class = AdapterClass;
  646. Component->Type = MultiFunctionAdapter;
  647. strcpy (Identifier, "PNP BIOS");
  648. i = strlen(Identifier) + 1;
  649. IdentifierString = (FPCHAR)HwAllocateHeap(i, FALSE);
  650. _fstrcpy(IdentifierString, Identifier);
  651. Component->Version = 0;
  652. Component->Key = 0;
  653. Component->AffinityMask = 0xffffffff;
  654. Component->IdentifierLength = i;
  655. Component->Identifier = IdentifierString;
  656. HwSetUpFreeFormDataHeader(
  657. (FPHWRESOURCE_DESCRIPTOR_LIST) ConfigurationData,
  658. 0,
  659. 1,
  660. 0,
  661. PnPBiosLength
  662. );
  663. ((FPHWRESOURCE_DESCRIPTOR_LIST)ConfigurationData)->Count = 2;
  664. //
  665. // Setup SMBIOS PartialDescriptor
  666. Descriptor = (FPHWPARTIAL_RESOURCE_DESCRIPTOR)(ConfigurationData +
  667. PnPBiosLength +
  668. DATA_HEADER_SIZE);
  669. Descriptor->Type = RESOURCE_DEVICE_DATA;
  670. Descriptor->ShareDisposition = 0;
  671. Descriptor->Flags = 0;
  672. Descriptor->u.DeviceSpecificData.DataSize = SMBIOSLength;
  673. Descriptor->u.DeviceSpecificData.Reserved1 = 0;
  674. Descriptor->u.DeviceSpecificData.Reserved2 = 0;
  675. //
  676. // Add it to tree
  677. //
  678. if (NextRelationship == Sibling) {
  679. PreviousEntry->Sibling = AdapterEntry;
  680. AdapterEntry->Parent = PreviousEntry->Parent;
  681. } else {
  682. PreviousEntry->Child = AdapterEntry;
  683. AdapterEntry->Parent = PreviousEntry;
  684. }
  685. NextRelationship = Sibling;
  686. PreviousEntry = AdapterEntry;
  687. //
  688. // Add Docking Information to tree
  689. //
  690. CurrentEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  691. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  692. strcpy (Identifier, "Docking State Information");
  693. i = strlen(Identifier) + 1;
  694. IdentifierString = (FPCHAR)HwAllocateHeap(i, FALSE);
  695. _fstrcpy(IdentifierString, Identifier);
  696. Component = &CurrentEntry->ComponentEntry;
  697. Component->Class = PeripheralClass;
  698. Component->Type = DockingInformation;
  699. Component->Version = 0;
  700. Component->Key = 0;
  701. Component->AffinityMask = 0xffffffff;
  702. Component->IdentifierLength = i;
  703. Component->Identifier = IdentifierString;
  704. Length = sizeof (DockInfo) + DATA_HEADER_SIZE;
  705. CurrentEntry->ConfigurationData =
  706. (FPHWRESOURCE_DESCRIPTOR_LIST) HwAllocateHeap (Length, TRUE);
  707. Component->ConfigurationDataLength = Length;
  708. _fmemcpy((FPCHAR) CurrentEntry->ConfigurationData + DATA_HEADER_SIZE,
  709. &DockInfo,
  710. Length - DATA_HEADER_SIZE);
  711. HwSetUpFreeFormDataHeader(
  712. (FPHWRESOURCE_DESCRIPTOR_LIST) CurrentEntry->ConfigurationData,
  713. 0,
  714. 0,
  715. 0,
  716. Length - DATA_HEADER_SIZE
  717. );
  718. AdapterEntry->Child = CurrentEntry;
  719. CurrentEntry->Parent = AdapterEntry;
  720. }
  721. #if DBG
  722. BlPrint("PnP BIOS Data collection complete...\n");
  723. #endif // DBG
  724. //
  725. // Allocate heap space for Bus component and initialize it.
  726. //
  727. #if DBG
  728. BlPrint("Detecting Bus/Adapter Component ...\n");
  729. #endif
  730. AdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  731. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  732. Component = &AdapterEntry->ComponentEntry;
  733. Component->Class = AdapterClass;
  734. //
  735. // The assumption here is that the machine has only one
  736. // type of IO bus. If a machine has more than one types of
  737. // IO buses, it will not use this detection code anyway.
  738. //
  739. if (HwBusType == MACHINE_TYPE_EISA) {
  740. //
  741. // Note We don't collect EISA config data here. Because we may
  742. // exhaust the heap space. We will collect the data after all
  743. // the other components are detected.
  744. //
  745. Component->Type = EisaAdapter;
  746. strcpy(Identifier, "EISA");
  747. AdapterEntry->ConfigurationData = NULL;
  748. Component->ConfigurationDataLength = 0;
  749. } else {
  750. //
  751. // If not EISA, it must be ISA
  752. //
  753. Component->Type = MultiFunctionAdapter;
  754. strcpy(Identifier, "ISA");
  755. }
  756. Length = strlen(Identifier) + 1;
  757. IdentifierString = (FPCHAR)HwAllocateHeap(Length, FALSE);
  758. _fstrcpy(IdentifierString, Identifier);
  759. Component->Version = 0;
  760. Component->Key = 0;
  761. Component->AffinityMask = 0xffffffff;
  762. Component->IdentifierLength = Length;
  763. Component->Identifier = IdentifierString;
  764. //
  765. // Make Adapter component System's child
  766. //
  767. if (NextRelationship == Sibling) {
  768. PreviousEntry->Sibling = AdapterEntry;
  769. AdapterEntry->Parent = PreviousEntry->Parent;
  770. } else {
  771. PreviousEntry->Child = AdapterEntry;
  772. AdapterEntry->Parent = PreviousEntry;
  773. }
  774. NextRelationship = Child;
  775. PreviousEntry = AdapterEntry;
  776. //
  777. // Collect BIOS information for ConfigurationRoot component.
  778. // This step is done here because we need data collected in
  779. // adapter component. The ConfigurationData is:
  780. // HWRESOURCE_DESCRIPTOR_LIST header
  781. // HWPARTIAL_RESOURCE_DESCRIPTOR for Parameter Table
  782. // HWPARTIAL_RESOURCE_DESCRIPTOR for Rom Blocks.
  783. // (Note DATA_HEADER_SIZE contains the size of the first partial
  784. // descriptor already.)
  785. //
  786. #if DBG
  787. BlPrint("Collecting Disk Geometry...\n");
  788. #endif
  789. GetInt13DriveParameters((PVOID)&RomChain, &Length);
  790. InitialLength = (USHORT)(Length + RESERVED_ROM_BLOCK_LIST_SIZE + DATA_HEADER_SIZE +
  791. sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR));
  792. ConfigurationData = (FPUCHAR)HwAllocateHeap(InitialLength, FALSE);
  793. EndConfigurationData = ConfigurationData + DATA_HEADER_SIZE;
  794. if (Length != 0) {
  795. FpRomChain = EndConfigurationData;
  796. _fmemcpy(FpRomChain, (FPVOID)RomChain, Length);
  797. }
  798. EndConfigurationData += (sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR) +
  799. Length);
  800. HwSetUpFreeFormDataHeader((FPHWRESOURCE_DESCRIPTOR_LIST)ConfigurationData,
  801. 0,
  802. 0,
  803. 0,
  804. Length
  805. );
  806. //
  807. // Scan ROM to collect all the ROM blocks, if possible.
  808. //
  809. #if DBG
  810. BlPrint("Detecting ROM Blocks...\n");
  811. #endif
  812. FpRomBlock = EndConfigurationData;
  813. GetRomBlocks(FpRomBlock, &Length);
  814. RomBlockLength = Length;
  815. if (Length != 0) {
  816. EndConfigurationData += Length;
  817. } else {
  818. FpRomBlock = NULL;
  819. }
  820. //
  821. // We have both RomChain and RomBlock information/Headers.
  822. //
  823. DescriptorList = (FPHWRESOURCE_DESCRIPTOR_LIST)ConfigurationData;
  824. DescriptorList->Count = 2;
  825. Descriptor = (FPHWPARTIAL_RESOURCE_DESCRIPTOR)(
  826. EndConfigurationData - Length -
  827. sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR));
  828. Descriptor->Type = RESOURCE_DEVICE_DATA;
  829. Descriptor->ShareDisposition = 0;
  830. Descriptor->Flags = 0;
  831. Descriptor->u.DeviceSpecificData.DataSize = (ULONG)Length;
  832. Descriptor->u.DeviceSpecificData.Reserved1 = 0;
  833. Descriptor->u.DeviceSpecificData.Reserved2 = 0;
  834. Length = (USHORT)(MAKE_FLAT_ADDRESS(EndConfigurationData) -
  835. MAKE_FLAT_ADDRESS(ConfigurationData));
  836. ConfigurationRoot->ComponentEntry.ConfigurationDataLength = Length;
  837. ConfigurationRoot->ConfigurationData = ConfigurationData;
  838. FreeSize = InitialLength - Length;
  839. HwFreeHeap((ULONG)FreeSize);
  840. //
  841. // Set up device information structure for Keyboard.
  842. //
  843. #if DBG
  844. BlPrint("Detecting Keyboard Component ...\n");
  845. #endif
  846. if (NoLegacy) {
  847. //
  848. // Do not touch the hardware because there may not be a ports 60/64 on
  849. // the machine and we will hang if we try to touch them
  850. //
  851. KeyboardId = UNKNOWN_KEYBOARD;
  852. }
  853. else {
  854. //
  855. // Touch the hardware to try to determine an ID
  856. //
  857. KeyboardId = GetKeyboardId();
  858. }
  859. CurrentEntry = SetKeyboardConfigurationData(KeyboardId);
  860. //
  861. // Make display component the child of Adapter component.
  862. //
  863. if (NextRelationship == Sibling) {
  864. PreviousEntry->Sibling = CurrentEntry;
  865. CurrentEntry->Parent = PreviousEntry->Parent;
  866. } else {
  867. PreviousEntry->Child = CurrentEntry;
  868. CurrentEntry->Parent = PreviousEntry;
  869. }
  870. NextRelationship = Sibling;
  871. PreviousEntry = CurrentEntry;
  872. if (!NoLegacy) {
  873. //
  874. // Set up device information for com port (Each COM component
  875. // is treated as a controller class.)
  876. //
  877. #if DBG
  878. BlPrint("Detecting ComPort Component ...\n");
  879. #endif
  880. if (CurrentEntry = GetComportInformation()) {
  881. FirstCom = CurrentEntry;
  882. //
  883. // Make current component the child of Adapter component.
  884. //
  885. if (NextRelationship == Sibling) {
  886. PreviousEntry->Sibling = CurrentEntry;
  887. } else {
  888. PreviousEntry->Child = CurrentEntry;
  889. }
  890. while (CurrentEntry) {
  891. CurrentEntry->Parent = AdapterEntry;
  892. PreviousEntry = CurrentEntry;
  893. CurrentEntry = CurrentEntry->Sibling;
  894. }
  895. NextRelationship = Sibling;
  896. }
  897. //
  898. // Set up device information for parallel port. (Each parallel
  899. // is treated as a controller class.)
  900. //
  901. #if DBG
  902. BlPrint("Detecting Parallel Component ...\n");
  903. #endif
  904. if (CurrentEntry = GetLptInformation()) {
  905. FirstLpt = CurrentEntry;
  906. //
  907. // Make current component the child of Adapter component.
  908. //
  909. if (NextRelationship == Sibling) {
  910. PreviousEntry->Sibling = CurrentEntry;
  911. CurrentEntry->Parent = PreviousEntry->Parent;
  912. } else {
  913. PreviousEntry->Child = CurrentEntry;
  914. CurrentEntry->Parent = PreviousEntry;
  915. }
  916. PreviousEntry = CurrentEntry;
  917. CurrentEntry = CurrentEntry->Sibling;
  918. while (CurrentEntry) {
  919. CurrentEntry->Parent = PreviousEntry->Parent;
  920. PreviousEntry = CurrentEntry;
  921. CurrentEntry = CurrentEntry->Sibling;
  922. }
  923. NextRelationship = Sibling;
  924. }
  925. //
  926. // Set up device information structure for Mouse.
  927. //
  928. #if DBG
  929. BlPrint("Detecting Mouse Component ...\n");
  930. #endif
  931. if (CurrentEntry = GetMouseInformation()) {
  932. //
  933. // Make current component the child of Adapter component.
  934. //
  935. if (NextRelationship == Sibling) {
  936. PreviousEntry->Sibling = CurrentEntry;
  937. CurrentEntry->Parent = PreviousEntry->Parent;
  938. } else {
  939. PreviousEntry->Child = CurrentEntry;
  940. CurrentEntry->Parent = PreviousEntry;
  941. }
  942. PreviousEntry = CurrentEntry;
  943. CurrentEntry = CurrentEntry->Sibling;
  944. while (CurrentEntry) {
  945. CurrentEntry->Parent = PreviousEntry->Parent;
  946. PreviousEntry = CurrentEntry;
  947. CurrentEntry = CurrentEntry->Sibling;
  948. }
  949. NextRelationship = Sibling;
  950. }
  951. }
  952. //
  953. // Set up device information for floppy drives. (The returned information
  954. // is a tree structure.)
  955. //
  956. #if DBG
  957. BlPrint("Detecting Floppy Component ...\n");
  958. #endif
  959. if (CurrentEntry = GetFloppyInformation()) {
  960. //
  961. // Make current component the child of Adapter component.
  962. //
  963. if (NextRelationship == Sibling) {
  964. PreviousEntry->Sibling = CurrentEntry;
  965. } else {
  966. PreviousEntry->Child = CurrentEntry;
  967. }
  968. while (CurrentEntry) {
  969. CurrentEntry->Parent = AdapterEntry;
  970. PreviousEntry = CurrentEntry;
  971. CurrentEntry = CurrentEntry->Sibling;
  972. }
  973. NextRelationship = Sibling;
  974. }
  975. #if DBG
  976. BlPrint("Detecting PcCard ISA IRQ mapping ...\n");
  977. #endif
  978. if (CurrentEntry = GetPcCardInformation()) {
  979. //
  980. // Make current component the child of Adapter component.
  981. //
  982. if (NextRelationship == Sibling) {
  983. PreviousEntry->Sibling = CurrentEntry;
  984. CurrentEntry->Parent = PreviousEntry->Parent;
  985. } else {
  986. PreviousEntry->Child = CurrentEntry;
  987. CurrentEntry->Parent = PreviousEntry;
  988. }
  989. PreviousEntry = CurrentEntry;
  990. CurrentEntry = CurrentEntry->Sibling;
  991. while (CurrentEntry) {
  992. CurrentEntry->Parent = PreviousEntry->Parent;
  993. PreviousEntry = CurrentEntry;
  994. CurrentEntry = CurrentEntry->Sibling;
  995. }
  996. NextRelationship = Sibling;
  997. }
  998. #if DBG
  999. BlPrint("Detecting ACPI Bus Component ...\n");
  1000. #endif
  1001. if (HwGetAcpiBiosData(&ConfigurationData, &Length)) {
  1002. AcpiAdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  1003. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  1004. AcpiAdapterEntry->ConfigurationData = ConfigurationData;
  1005. Component = &AcpiAdapterEntry->ComponentEntry;
  1006. Component->ConfigurationDataLength = Length;
  1007. Component->Class = AdapterClass;
  1008. Component->Type = MultiFunctionAdapter;
  1009. strcpy (Identifier, "ACPI BIOS");
  1010. i = strlen(Identifier) + 1;
  1011. IdentifierString = (FPCHAR)HwAllocateHeap(i, FALSE);
  1012. _fstrcpy(IdentifierString, Identifier);
  1013. Component->Version = 0;
  1014. Component->Key = 0;
  1015. Component->AffinityMask = 0xffffffff;
  1016. Component->IdentifierLength = i;
  1017. Component->Identifier = IdentifierString;
  1018. HwSetUpFreeFormDataHeader(
  1019. (FPHWRESOURCE_DESCRIPTOR_LIST) ConfigurationData,
  1020. 0,
  1021. 0,
  1022. 0,
  1023. Length - DATA_HEADER_SIZE
  1024. );
  1025. //
  1026. // Add it to tree
  1027. //
  1028. // Big hack here. This code inserts the ACPI node in
  1029. // the tree one level higher than the ISA devices in
  1030. // the code right above. But this doesn't work in
  1031. // the NoLegacy case because these devices haven't
  1032. // been added to the tree.
  1033. //
  1034. // Ideally, this code would just be moved above the ISA
  1035. // device detection code. That would be simpler. But
  1036. // That causes current ACPI machines to fail to dual-boot
  1037. // because their ARC paths would change.
  1038. //
  1039. // if (NoLegacy) {
  1040. //
  1041. // if (NextRelationship == Sibling) {
  1042. // PreviousEntry->Sibling = AcpiAdapterEntry;
  1043. // AcpiAdapterEntry->Parent = PreviousEntry->Parent;
  1044. // } else {
  1045. // PreviousEntry->Child = AdapterEntry;
  1046. // AdapterEntry->Parent = PreviousEntry;
  1047. // }
  1048. //
  1049. // PreviousEntry = AdapterEntry;
  1050. //
  1051. // } else {
  1052. if (NextRelationship == Sibling) {
  1053. PreviousEntry->Parent->Sibling = AcpiAdapterEntry;
  1054. AcpiAdapterEntry->Parent = PreviousEntry->Parent->Parent;
  1055. }
  1056. // }
  1057. NextRelationship = Sibling;
  1058. }
  1059. #if DBG
  1060. BlPrint("ACPI BIOS Data collection complete...\n");
  1061. #endif // DBG
  1062. #if DBG
  1063. BlPrint("Detection done. Press a key to display hardware info ...\n");
  1064. while ( ! HwGetKey ());
  1065. clrscrn ();
  1066. #endif
  1067. //
  1068. // Misc. supports. Note, the information collected here will NOT be
  1069. // written to hardware registry.
  1070. //
  1071. // 1. Collect video font information for vdm
  1072. //
  1073. GetVideoFontInformation();
  1074. //
  1075. // After all the components are detected, we collect EISA config data.
  1076. //
  1077. if (HwBusType == MACHINE_TYPE_EISA) {
  1078. Component = &AdapterEntry->ComponentEntry;
  1079. GetEisaConfigurationData(&AdapterEntry->ConfigurationData,
  1080. &Component->ConfigurationDataLength);
  1081. if (Component->ConfigurationDataLength) {
  1082. HwEisaConfigurationData = (FPUCHAR)AdapterEntry->ConfigurationData +
  1083. DATA_HEADER_SIZE;
  1084. HwEisaConfigurationSize = Component->ConfigurationDataLength -
  1085. DATA_HEADER_SIZE;
  1086. //
  1087. // Misc. detections based on Eisa config data
  1088. //
  1089. // Update Lpt and com controllers' irq information by examining
  1090. // the EISA configuration data.
  1091. //
  1092. GetIrqFromEisaData(FirstLpt, ParallelController);
  1093. GetIrqFromEisaData(FirstCom, SerialController);
  1094. }
  1095. }
  1096. #if DBG
  1097. CheckConfigurationTree(ConfigurationRoot);
  1098. #endif
  1099. //
  1100. // Update all the far pointers in the tree to flat 32 bit pointers
  1101. //
  1102. UpdateConfigurationTree(ConfigurationRoot);
  1103. //
  1104. // Set up returned values:
  1105. // Size of Heap space which should be preserved for configuration tree
  1106. // Pointer to the root of the configuration tree.
  1107. //
  1108. CurrentEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap(0, FALSE);
  1109. *BlHeapUsed = MAKE_FLAT_ADDRESS(CurrentEntry) -
  1110. MAKE_FLAT_ADDRESS(ConfigurationRoot);
  1111. *BlConfigurationTree = (ULONG)MAKE_FLAT_ADDRESS(ConfigurationRoot);
  1112. }
  1113. VOID
  1114. GetIrqFromEisaData(
  1115. FPFWCONFIGURATION_COMPONENT_DATA ControllerList,
  1116. CONFIGURATION_TYPE ControllerType
  1117. )
  1118. /*++
  1119. Routine Description:
  1120. This routine updates all irq information for ControllerType components
  1121. in the controllerList by examinine the eisa configuration data.
  1122. Arguments:
  1123. ControllerList - Supplies a pointer to a component entry whoes irq will
  1124. be updated.
  1125. ControllerType - Supplies the controller type whoes irq will be searched
  1126. for.
  1127. Returns:
  1128. None.
  1129. --*/
  1130. {
  1131. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry;
  1132. FPHWPARTIAL_RESOURCE_DESCRIPTOR Descriptor;
  1133. FPHWRESOURCE_DESCRIPTOR_LIST DescriptorList;
  1134. USHORT i, Port;
  1135. UCHAR Irq, Trigger;
  1136. CurrentEntry = ControllerList;
  1137. while (CurrentEntry &&
  1138. CurrentEntry->ComponentEntry.Type == ControllerType) {
  1139. if (CurrentEntry->ConfigurationData) {
  1140. DescriptorList = (FPHWRESOURCE_DESCRIPTOR_LIST)
  1141. CurrentEntry->ConfigurationData;
  1142. Port = 0;
  1143. for (i = 0; i < (USHORT)DescriptorList->Count; i++) {
  1144. Descriptor = &DescriptorList->PartialDescriptors[i];
  1145. if (Descriptor->Type == CmResourceTypePort) {
  1146. Port = (USHORT)Descriptor->u.Port.Start.LowPart;
  1147. break;
  1148. }
  1149. }
  1150. if (Port != 0) {
  1151. for (i = 0; i < (USHORT)DescriptorList->Count; i++) {
  1152. Descriptor = &DescriptorList->PartialDescriptors[i];
  1153. if (Descriptor->Type == CmResourceTypeInterrupt) {
  1154. if (HwEisaGetIrqFromPort(Port, &Irq, &Trigger)) {
  1155. if (Trigger == 0) { // EISA EDGE_TRIGGER
  1156. Descriptor->Flags = EDGE_TRIGGERED;
  1157. } else {
  1158. Descriptor->Flags = LEVEL_SENSITIVE;
  1159. }
  1160. Descriptor->u.Interrupt.Level = Irq;
  1161. Descriptor->u.Interrupt.Vector = Irq;
  1162. break;
  1163. }
  1164. }
  1165. }
  1166. }
  1167. }
  1168. CurrentEntry = CurrentEntry->Sibling;
  1169. }
  1170. }
  1171. VOID
  1172. UpdateComponentPointers(
  1173. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
  1174. )
  1175. /*++
  1176. Routine Description:
  1177. This routine updates all the "far" pointer to 32 bit flat addresses
  1178. for a component entry.
  1179. Arguments:
  1180. CurrentEntry - Supplies a pointer to a component entry which will
  1181. be updated.
  1182. Returns:
  1183. None.
  1184. --*/
  1185. {
  1186. FPULONG UpdatePointer;
  1187. FPVOID NextEntry;
  1188. ULONG FlatAddress;
  1189. //
  1190. // Update the child, parent, sibling and ConfigurationData
  1191. // far pointers to 32 bit flat addresses.
  1192. // N.B. After we update the pointers to flat addresses, they
  1193. // can no longer be accessed in real mode.
  1194. //
  1195. UpdatePointer = (FPULONG)&CurrentEntry->Child;
  1196. NextEntry = (FPVOID)CurrentEntry->Child;
  1197. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1198. *UpdatePointer = FlatAddress;
  1199. UpdatePointer = (FPULONG)&CurrentEntry->Parent;
  1200. NextEntry = (FPVOID)CurrentEntry->Parent;
  1201. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1202. *UpdatePointer = FlatAddress;
  1203. UpdatePointer = (FPULONG)&CurrentEntry->Sibling;
  1204. NextEntry = (FPVOID)CurrentEntry->Sibling;
  1205. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1206. *UpdatePointer = FlatAddress;
  1207. UpdatePointer = (FPULONG)&CurrentEntry->ComponentEntry.Identifier;
  1208. NextEntry = (FPVOID)CurrentEntry->ComponentEntry.Identifier;
  1209. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1210. *UpdatePointer = FlatAddress;
  1211. UpdatePointer = (FPULONG)&CurrentEntry->ConfigurationData;
  1212. NextEntry = (FPVOID)CurrentEntry->ConfigurationData;
  1213. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1214. *UpdatePointer = FlatAddress;
  1215. }
  1216. VOID
  1217. UpdateConfigurationTree(
  1218. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
  1219. )
  1220. /*++
  1221. Routine Description:
  1222. This routine traverses loader configuration tree and changes
  1223. all the "far" pointer to 32 bit flat addresses.
  1224. Arguments:
  1225. CurrentEntry - Supplies a pointer to a loader configuration
  1226. tree or subtree.
  1227. Returns:
  1228. None.
  1229. --*/
  1230. {
  1231. FPFWCONFIGURATION_COMPONENT_DATA TempEntry;
  1232. while (CurrentEntry)
  1233. {
  1234. //
  1235. // Spin down finding the deepest child
  1236. //
  1237. while (CurrentEntry->Child) {
  1238. CurrentEntry = CurrentEntry->Child;
  1239. }
  1240. //
  1241. // Now we need to either move to the next sibling. If we
  1242. // don't have a sibling we need to walk up through the parents
  1243. // until we find an entry with a sibling. We have to save
  1244. // off the current entry since after we update the entry the
  1245. // pointer are no longer useable.
  1246. //
  1247. while (CurrentEntry) {
  1248. TempEntry = CurrentEntry;
  1249. if (CurrentEntry->Sibling != NULL) {
  1250. CurrentEntry = CurrentEntry->Sibling;
  1251. UpdateComponentPointers(TempEntry);
  1252. break;
  1253. } else {
  1254. CurrentEntry = CurrentEntry->Parent;
  1255. UpdateComponentPointers(TempEntry);
  1256. }
  1257. }
  1258. }
  1259. }
  1260. FPVOID
  1261. HwSetUpResourceDescriptor (
  1262. FPFWCONFIGURATION_COMPONENT Component,
  1263. PUCHAR Identifier,
  1264. PHWCONTROLLER_DATA ControlData,
  1265. USHORT SpecificDataLength,
  1266. PUCHAR SpecificData
  1267. )
  1268. /*++
  1269. Routine Description:
  1270. This routine allocates space from far heap , puts the caller's controller
  1271. information to the space and sets up CONFIGURATION_COMPONENT
  1272. structure for the caller.
  1273. Arguments:
  1274. Component - Supplies the address the component whose configuration data
  1275. should be set up.
  1276. Identifier - Suppies a pointer to the identifier to identify the controller
  1277. ControlData - Supplies a point to a structure which describes
  1278. controller information.
  1279. SpecificDataLength - size of the device specific data. Device specific
  1280. data is the information not defined in the standard format.
  1281. SpecificData - Supplies a pointer to the device specific data.
  1282. Return Value:
  1283. Returns a far pointer to the Configuration data.
  1284. --*/
  1285. {
  1286. FPCHAR fpIdentifier;
  1287. FPHWRESOURCE_DESCRIPTOR_LIST fpDescriptor = NULL;
  1288. USHORT Length;
  1289. SHORT Count, i;
  1290. FPUCHAR fpSpecificData;
  1291. //
  1292. // Set up Identifier string for hardware component, if necessary.
  1293. //
  1294. if (Identifier) {
  1295. Length = strlen(Identifier) + 1;
  1296. Component->IdentifierLength = Length;
  1297. fpIdentifier = (FPUCHAR)HwAllocateHeap(Length, FALSE);
  1298. Component->Identifier = fpIdentifier;
  1299. _fstrcpy(fpIdentifier, Identifier);
  1300. } else {
  1301. Component->IdentifierLength = 0;
  1302. Component->Identifier = NULL;
  1303. }
  1304. //
  1305. // Set up configuration data for hardware component, if necessary
  1306. //
  1307. Count = ControlData->NumberPortEntries + ControlData->NumberIrqEntries +
  1308. ControlData->NumberMemoryEntries + ControlData->NumberDmaEntries;
  1309. if (SpecificDataLength) {
  1310. //
  1311. // if we have device specific data, we need to increment the count
  1312. // by one.
  1313. //
  1314. Count++;
  1315. }
  1316. if (Count >0) {
  1317. Length = (USHORT)(Count * sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR) +
  1318. FIELD_OFFSET(HWRESOURCE_DESCRIPTOR_LIST, PartialDescriptors) +
  1319. SpecificDataLength);
  1320. fpDescriptor = (FPHWRESOURCE_DESCRIPTOR_LIST)HwAllocateHeap(Length, TRUE);
  1321. fpDescriptor->Count = Count;
  1322. //
  1323. // Copy all the partial descriptors to the destination descriptors
  1324. // except the last one. (The last partial descriptor may be a device
  1325. // specific data. It requires special handling.)
  1326. //
  1327. for (i = 0; i < (Count - 1); i++) {
  1328. fpDescriptor->PartialDescriptors[i] =
  1329. ControlData->DescriptorList[i];
  1330. }
  1331. //
  1332. // Set up the last partial descriptor. If it is a port, memory, irq or
  1333. // dma entry, we simply copy it. If the last one is for device specific
  1334. // data, we set up the length and copy the device spcific data to the end
  1335. // of the decriptor.
  1336. //
  1337. if (SpecificData) {
  1338. fpDescriptor->PartialDescriptors[Count - 1].Type =
  1339. RESOURCE_DEVICE_DATA;
  1340. fpDescriptor->PartialDescriptors[Count - 1].Flags = 0;
  1341. fpDescriptor->PartialDescriptors[Count - 1].u.DeviceSpecificData.DataSize =
  1342. SpecificDataLength;
  1343. fpSpecificData = (FPUCHAR)&(fpDescriptor->PartialDescriptors[Count]);
  1344. _fmemcpy(fpSpecificData, SpecificData, SpecificDataLength);
  1345. } else {
  1346. fpDescriptor->PartialDescriptors[Count - 1] =
  1347. ControlData->DescriptorList[Count - 1];
  1348. }
  1349. Component->ConfigurationDataLength = Length;
  1350. }
  1351. return(fpDescriptor);
  1352. }
  1353. VOID
  1354. HwSetUpFreeFormDataHeader (
  1355. FPHWRESOURCE_DESCRIPTOR_LIST Header,
  1356. USHORT Version,
  1357. USHORT Revision,
  1358. USHORT Flags,
  1359. ULONG DataSize
  1360. )
  1361. /*++
  1362. Routine Description:
  1363. This routine initialize free formed data header. Note this routine
  1364. sets the the Header and initialize the FIRST PartialDescriptor only.
  1365. If the header contains more than one descriptor, the caller must handle
  1366. it itself.
  1367. Arguments:
  1368. Header - Supplies a pointer to the header to be initialized.
  1369. Version - Version number for the header.
  1370. Revision - Revision number for the header.
  1371. Flags - Free formed data flags. (Currently, it is undefined and
  1372. should be zero.)
  1373. DataSize - Size of the free formed data.
  1374. Return Value:
  1375. None.
  1376. --*/
  1377. {
  1378. Header->Version = Version;
  1379. Header->Revision = Revision;
  1380. Header->Count = 1;
  1381. Header->PartialDescriptors[0].Type = RESOURCE_DEVICE_DATA;
  1382. Header->PartialDescriptors[0].ShareDisposition = 0;
  1383. Header->PartialDescriptors[0].Flags = Flags;
  1384. Header->PartialDescriptors[0].u.DeviceSpecificData.DataSize = DataSize;
  1385. Header->PartialDescriptors[0].u.DeviceSpecificData.Reserved1 = 0;
  1386. Header->PartialDescriptors[0].u.DeviceSpecificData.Reserved2 = 0;
  1387. }
  1388. #if DBG
  1389. VOID
  1390. CheckComponentNode(
  1391. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
  1392. )
  1393. {
  1394. FPUCHAR NextEntry, DataPointer;
  1395. ULONG FlatAddress;
  1396. ULONG Length;
  1397. UCHAR IdString[40];
  1398. USHORT Count, i;
  1399. UCHAR Type;
  1400. FPHWRESOURCE_DESCRIPTOR_LIST DescriptorList;
  1401. FPHWPARTIAL_RESOURCE_DESCRIPTOR Descriptor;
  1402. FlatAddress = MAKE_FLAT_ADDRESS(CurrentEntry);
  1403. clrscrn ();
  1404. BlPrint("\n");
  1405. BlPrint("Current Node: %lx\n", FlatAddress);
  1406. BlPrint(" Type = %s\n", TypeName[CurrentEntry->ComponentEntry.Type]);
  1407. //
  1408. // Update the child, parent, sibling and ConfigurationData
  1409. // far pointers to 32 bit flat addresses.
  1410. // N.B. After we update the pointers to flat addresses, they
  1411. // can no longer be accessed in real mode.
  1412. //
  1413. NextEntry = (FPUCHAR)CurrentEntry->Child;
  1414. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1415. if (FlatAddress > 0x60000 || (FlatAddress < 0x50000 && FlatAddress != 0)) {
  1416. BlPrint("Invalid address: Child = %lx\n", FlatAddress);
  1417. } else {
  1418. BlPrint("\tChild = %lx\n", FlatAddress);
  1419. }
  1420. NextEntry = (FPUCHAR)CurrentEntry->Parent;
  1421. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1422. if (FlatAddress > 0x60000 || (FlatAddress < 0x50000 && FlatAddress != 0)) {
  1423. BlPrint("Invalid address: Parent = %lx\n", FlatAddress);
  1424. } else {
  1425. BlPrint("\tParent = %lx\n", FlatAddress);
  1426. }
  1427. NextEntry = (FPUCHAR)CurrentEntry->Sibling;
  1428. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1429. if (FlatAddress > 0x60000 || (FlatAddress < 0x50000 && FlatAddress != 0)) {
  1430. BlPrint("Invalid address: Sibling = %lx\n", FlatAddress);
  1431. } else {
  1432. BlPrint("\tSibling = %lx\n", FlatAddress);
  1433. }
  1434. NextEntry = (FPUCHAR)CurrentEntry->ConfigurationData;
  1435. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1436. if (FlatAddress > 0x60000 || (FlatAddress < 0x50000 && FlatAddress != 0)) {
  1437. BlPrint("Invalid address: ConfigurationData = %lx\n", FlatAddress);
  1438. } else {
  1439. BlPrint("\tConfigurationData = %lx\n", FlatAddress);
  1440. }
  1441. Length = CurrentEntry->ComponentEntry.IdentifierLength;
  1442. BlPrint("IdentifierLength = %lx\n", CurrentEntry->ComponentEntry.IdentifierLength);
  1443. if (Length > 0) {
  1444. _fstrcpy(IdString, CurrentEntry->ComponentEntry.Identifier);
  1445. BlPrint("Identifier = %s\n", IdString);
  1446. }
  1447. Length = CurrentEntry->ComponentEntry.ConfigurationDataLength;
  1448. BlPrint("ConfigdataLength = %lx\n", Length);
  1449. if (Length > 0) {
  1450. DescriptorList = (FPHWRESOURCE_DESCRIPTOR_LIST)CurrentEntry->ConfigurationData;
  1451. BlPrint("Version = %x, Revision = %x\n", DescriptorList->Version,
  1452. DescriptorList->Revision);
  1453. Count = (USHORT)DescriptorList->Count;
  1454. Descriptor = &DescriptorList->PartialDescriptors[0];
  1455. BlPrint("Count = %x\n", Count);
  1456. while (Count > 0) {
  1457. Type = Descriptor->Type;
  1458. if (Type == RESOURCE_PORT) {
  1459. BlPrint("Type = Port");
  1460. BlPrint("\tShareDisposition = %x\n", Descriptor->ShareDisposition);
  1461. BlPrint("PortFlags = %x\n", Descriptor->Flags);
  1462. BlPrint("PortStart = %x", Descriptor->u.Port.Start);
  1463. BlPrint("\tPortLength = %x\n", Descriptor->u.Port.Length);
  1464. } else if (Type == RESOURCE_DMA) {
  1465. BlPrint("Type = Dma");
  1466. BlPrint("\tShareDisposition = %x\n", Descriptor->ShareDisposition);
  1467. BlPrint("DmaFlags = %x\n", Descriptor->Flags);
  1468. BlPrint("DmaChannel = %x", Descriptor->u.Dma.Channel);
  1469. BlPrint("\tDmaPort = %lx\n", Descriptor->u.Dma.Port);
  1470. } else if (Type == RESOURCE_INTERRUPT) {
  1471. BlPrint("Type = Interrupt");
  1472. BlPrint("\tShareDisposition = %x\n", Descriptor->ShareDisposition);
  1473. BlPrint("InterruptFlags = %x\n", Descriptor->Flags);
  1474. BlPrint("Level = %x", Descriptor->u.Interrupt.Level);
  1475. BlPrint("\tVector = %x\n", Descriptor->u.Interrupt.Vector);
  1476. } else if (Type == RESOURCE_MEMORY) {
  1477. BlPrint("Type = Memory");
  1478. BlPrint("\tShareDisposition = %x\n", Descriptor->ShareDisposition);
  1479. BlPrint("MemoryFlags = %x\n", Descriptor->Flags);
  1480. BlPrint("Start1 = %lx", (ULONG)Descriptor->u.Memory.Start.LowPart);
  1481. BlPrint("\tStart2 = %lx", (ULONG)Descriptor->u.Memory.Start.HighPart);
  1482. BlPrint("\tLength = %lx\n", Descriptor->u.Memory.Length);
  1483. } else {
  1484. BlPrint("Type = Device Data\n");
  1485. Length = Descriptor->u.DeviceSpecificData.DataSize;
  1486. BlPrint("Size = %lx\n", Length);
  1487. DataPointer = (FPUCHAR)(Descriptor+1);
  1488. for (i = 0; (i < (USHORT)Length) && (i < 64); i++) {
  1489. BlPrint("%x ", *DataPointer);
  1490. DataPointer++;
  1491. }
  1492. break;
  1493. }
  1494. Count--;
  1495. Descriptor++;
  1496. }
  1497. }
  1498. while (HwGetKey() == 0) {
  1499. }
  1500. }
  1501. VOID
  1502. CheckConfigurationTree(
  1503. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
  1504. )
  1505. {
  1506. FPFWCONFIGURATION_COMPONENT_DATA TempEntry;
  1507. while (CurrentEntry)
  1508. {
  1509. //
  1510. // Spin down finding the deepest child
  1511. //
  1512. while (CurrentEntry->Child) {
  1513. CurrentEntry = CurrentEntry->Child;
  1514. }
  1515. //
  1516. // Now we need to either move to the next sibling. If we
  1517. // don't have a sibling we need to walk up through the parents
  1518. // until we find an entry with a sibling. We have to save
  1519. // off the current entry since after we update the entry the
  1520. // pointer are no longer useable.
  1521. //
  1522. while (CurrentEntry) {
  1523. TempEntry = CurrentEntry;
  1524. if (CurrentEntry->Sibling != NULL) {
  1525. CurrentEntry = CurrentEntry->Sibling;
  1526. CheckComponentNode(TempEntry);
  1527. break;
  1528. } else {
  1529. CurrentEntry = CurrentEntry->Parent;
  1530. CheckComponentNode(TempEntry);
  1531. }
  1532. }
  1533. }
  1534. }
  1535. #endif