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.

1678 lines
47 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. --*/
  17. #include "hwdetect.h"
  18. typedef VOID (*PINTERFACE_REFERENCE)(PVOID Context);
  19. typedef VOID (*PINTERFACE_DEREFERENCE)(PVOID Context);
  20. typedef PVOID PDEVICE_OBJECT;
  21. #include "pci.h"
  22. #if defined(NEC_98)
  23. #include "string.h"
  24. #else // PC98
  25. #include <string.h>
  26. #endif // PC98
  27. #include "apm.h"
  28. #include <ntapmsdk.h>
  29. #if defined(_GAMBIT_)
  30. //
  31. // Hard Disk Drive
  32. //
  33. #define SIZE_OF_PARAMETER 12 // size of disk params
  34. #define MAX_DRIVE_NUMBER 8 // max number of drives
  35. #pragma pack(1)
  36. typedef struct _HARD_DISK_PARAMETERS {
  37. USHORT DriveSelect;
  38. ULONG MaxCylinders;
  39. USHORT SectorsPerTrack;
  40. USHORT MaxHeads;
  41. USHORT NumberDrives;
  42. } HARD_DISK_PARAMETERS, *PHARD_DISK_PARAMETERS;
  43. #pragma pack()
  44. USHORT NumberBiosDisks;
  45. #endif // _GAMBIT_
  46. #if DBG
  47. PUCHAR TypeName[] = {
  48. "ArcSystem",
  49. "CentralProcessor",
  50. "FloatingPointProcessor",
  51. "PrimaryICache",
  52. "PrimaryDCache",
  53. "SecondaryICache",
  54. "SecondaryDCache",
  55. "SecondaryCache",
  56. "EisaAdapter",
  57. "TcaAdapter",
  58. "ScsiAdapter",
  59. "DtiAdapter",
  60. #if defined(NEC_98)
  61. "MultifunctionAdapter",
  62. #else // PC98
  63. "MultifunctionAapter",
  64. #endif // PC98
  65. "DiskController",
  66. "TapeController",
  67. "CdRomController",
  68. "WormController",
  69. "SerialController",
  70. "NetworkController",
  71. "DisplayController",
  72. "ParallelController",
  73. "PointerController",
  74. "KeyboardController",
  75. "AudioController",
  76. "OtherController",
  77. "DiskPeripheral",
  78. "FloppyDiskPeripheral",
  79. "TapePeripheral",
  80. "ModemPeripheral",
  81. "MonitorPeripheral",
  82. #if defined(NEC_98)
  83. "PrinterPeripheral",
  84. #else // PC98
  85. "PrinterPeraipheral",
  86. #endif // PC98
  87. "PointerPeripheral",
  88. "KeyboardPeripheral",
  89. "TerminalPeripheral",
  90. "OtherPeripheral",
  91. "LinePeripheral",
  92. "NetworkPeripheral",
  93. "SystemMemory",
  94. "MaximumType"
  95. };
  96. VOID
  97. CheckConfigurationTree(
  98. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
  99. );
  100. extern
  101. USHORT
  102. HwGetKey(
  103. VOID
  104. );
  105. #endif
  106. VOID
  107. GetIrqFromEisaData(
  108. FPFWCONFIGURATION_COMPONENT_DATA ControllerList,
  109. CONFIGURATION_TYPE ControllerType
  110. );
  111. #if defined(NEC_98)
  112. FPFWCONFIGURATION_COMPONENT_DATA
  113. GetScsiDiskInformation(
  114. VOID
  115. );
  116. FPFWCONFIGURATION_COMPONENT_DATA
  117. GetArrayDiskInformation(
  118. VOID
  119. );
  120. BOOLEAN
  121. ArrayBootCheck(
  122. VOID
  123. );
  124. #endif // PC98
  125. //
  126. // HwBusType - defines the BUS type of the machine.
  127. // This variable is used by detection code only.
  128. //
  129. USHORT HwBusType = 0;
  130. //
  131. // AdapterEntry is the Configuration_Component_data for the bus adapter
  132. //
  133. FPFWCONFIGURATION_COMPONENT_DATA AdapterEntry = NULL;
  134. //
  135. // FpRomBlock - A far pointer to our Rom Block
  136. //
  137. FPUCHAR FpRomBlock = NULL;
  138. USHORT RomBlockLength = 0;
  139. //
  140. // HwEisaConfigurationData - A far pointer to the EISA configuration
  141. // data on EISA machine.
  142. //
  143. FPUCHAR HwEisaConfigurationData = NULL;
  144. ULONG HwEisaConfigurationSize = 0L;
  145. //
  146. // DisableSerialMice - A bit flags to indicate the comports whose serial
  147. // mouse detection should be skipped.
  148. //
  149. USHORT DisableSerialMice = 0x0;
  150. //
  151. // Internal references and definitions.
  152. //
  153. typedef enum _RELATIONSHIP_FLAGS {
  154. Child,
  155. Sibling,
  156. Parent
  157. } RELATIONSHIP_FLAGS;
  158. #if defined(NEC_98)
  159. USHORT
  160. Get0Seg(
  161. IN USHORT OffsetAddress
  162. )
  163. /*++
  164. Routine Description:
  165. This routine have the function that get common data and return.
  166. Arguments:
  167. OffsetAddress - Physical address 0:xxxx
  168. Return Value:
  169. Return a common data.
  170. ++*/
  171. {
  172. UCHAR Data=0;
  173. _asm {
  174. push es
  175. push bx
  176. push ax
  177. xor ax,ax
  178. mov es,ax
  179. mov bx,word ptr OffsetAddress
  180. mov al,es:[bx]
  181. mov Data,al
  182. pop ax
  183. pop bx
  184. pop es
  185. }
  186. return ((USHORT)Data);
  187. }
  188. USHORT
  189. GetF8E8Seg(
  190. IN USHORT OffsetAddress
  191. )
  192. /*++
  193. Routine Description:
  194. This routine have the function that get byte data in ROM system common aria.
  195. Arguments:
  196. Offset - Physical address 0:xxxx
  197. Return Value:
  198. Byte data
  199. --*/
  200. {
  201. UCHAR Data=0;
  202. _asm {
  203. push es
  204. push bx
  205. push ax
  206. mov ax, 0F8E8h
  207. mov es, ax
  208. mov bx, word ptr OffsetAddress
  209. mov al, es:[bx]
  210. mov Data, al
  211. pop ax
  212. pop bx
  213. pop es
  214. }
  215. return ((USHORT)Data);
  216. }
  217. VOID
  218. IoDelay(
  219. USHORT counter
  220. )
  221. /*++
  222. Routine Description:
  223. This routine is IoDelay function.
  224. I think time of one "out 5f" is 0.6 micro second.
  225. Arguments:
  226. --*/
  227. {
  228. USHORT i;
  229. for (i = 1 ; i <= counter ; i++) {
  230. WRITE_PORT_UCHAR((PCHAR)0x5f,0);
  231. }
  232. }
  233. #endif
  234. VOID
  235. HardwareDetection(
  236. ULONG HeapStart,
  237. ULONG HeapSize,
  238. ULONG_PTR ConfigurationTree,
  239. ULONG_PTR HeapUsed,
  240. ULONG_PTR OptionString,
  241. ULONG OptionStringLength
  242. )
  243. /*++
  244. Routine Description:
  245. Main entrypoint of the HW recognizer test. The routine builds
  246. a configuration tree and leaves it in the hardware heap.
  247. Arguments:
  248. HeapStart - Supplies the starting address of the configuaration heap.
  249. HeapSize - Supplies the size of the heap in byte.
  250. ConfigurationTree - Supplies a 32 bit FLAT address of the variable to
  251. receive the hardware configuration tree.
  252. HeapUsed - Supplies a 32 bit FLAT address of the variable to receive
  253. the actual heap size in used.
  254. OptionString - Supplies a 32 bit FLAT address of load option string.
  255. OptionStringLength - Supplies the length of the OptionString
  256. Returns:
  257. None.
  258. --*/
  259. {
  260. FPFWCONFIGURATION_COMPONENT_DATA ConfigurationRoot;
  261. FPFWCONFIGURATION_COMPONENT_DATA FirstCom = NULL, FirstLpt = NULL;
  262. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry, PreviousEntry;
  263. FPFWCONFIGURATION_COMPONENT_DATA AcpiAdapterEntry = NULL;
  264. FPFWCONFIGURATION_COMPONENT Component;
  265. RELATIONSHIP_FLAGS NextRelationship;
  266. CHAR Identifier[256];
  267. USHORT BiosYear, BiosMonth, BiosDay;
  268. PUCHAR MachineId;
  269. USHORT Length, InitialLength, i, Count = 0;
  270. FPCHAR IdentifierString;
  271. PMOUSE_INFORMATION MouseInfo = 0;
  272. USHORT KeyboardId = 0;
  273. ULONG VideoAdapterType = 0;
  274. PULONG_PTR BlConfigurationTree = NULL;
  275. FPULONG BlHeapUsed = NULL;
  276. FPCHAR BlOptions, EndOptions;
  277. #if defined(_GAMBIT_)
  278. PHARD_DISK_PARAMETERS RomChain;
  279. #else
  280. PUCHAR RomChain;
  281. #endif
  282. FPUCHAR FpRomChain = NULL, ConfigurationData, EndConfigurationData;
  283. SHORT FreeSize;
  284. FPHWPARTIAL_RESOURCE_DESCRIPTOR Descriptor;
  285. FPHWRESOURCE_DESCRIPTOR_LIST DescriptorList;
  286. PCI_REGISTRY_INFO PciEntry;
  287. #if defined(NEC_98)
  288. FPFWCONFIGURATION_COMPONENT_DATA ScsiAdapterEntry;
  289. USHORT BootID, Equips, Work;
  290. #endif // PC98
  291. APM_REGISTRY_INFO ApmEntry;
  292. //
  293. // First initialize our hardware heap.
  294. //
  295. HwInitializeHeap(HeapStart, HeapSize);
  296. MAKE_FP(BlConfigurationTree, ConfigurationTree);
  297. MAKE_FP(BlHeapUsed, HeapUsed);
  298. MAKE_FP(BlOptions, OptionString);
  299. //
  300. // Parse OptionString and see if we need to disable serial mice detection.
  301. //
  302. if (BlOptions && OptionStringLength <= 0x1000L && OptionStringLength > 0L) {
  303. EndOptions = BlOptions + OptionStringLength;
  304. if (*EndOptions == '\0') {
  305. do {
  306. if (BlOptions = _fstrstr(BlOptions, "NOSERIALMICE")) {
  307. BlOptions += strlen("NOSERIALMICE");
  308. while ((*BlOptions == ' ') || (*BlOptions == ':') ||
  309. (*BlOptions == '=')) {
  310. BlOptions++;
  311. }
  312. if (*BlOptions == 'C' && BlOptions[1] == 'O' &&
  313. BlOptions[2] == 'M') {
  314. BlOptions += 3;
  315. while (TRUE) {
  316. while (*BlOptions != '\0' && (*BlOptions == ' ' ||
  317. *BlOptions == ',' || *BlOptions == ';' ||
  318. *BlOptions == '0')) {
  319. BlOptions++;
  320. }
  321. if (*BlOptions >= '0' && *BlOptions <= '9') {
  322. if (BlOptions[1] < '0' || BlOptions[1] > '9') {
  323. DisableSerialMice |= 1 << (*BlOptions - '0');
  324. BlOptions++;
  325. } else {
  326. BlOptions++;
  327. while (*BlOptions && *BlOptions <= '9' &&
  328. *BlOptions >= '0') {
  329. BlOptions++;
  330. }
  331. }
  332. }else {
  333. break;
  334. }
  335. }
  336. } else {
  337. DisableSerialMice = 0xffff;
  338. break;
  339. }
  340. }
  341. } while (BlOptions && *BlOptions && (BlOptions < EndOptions)); // double checking
  342. }
  343. }
  344. //
  345. // Determine bus type
  346. //
  347. #if defined(NEC_98) || defined(_GAMBIT_)
  348. //
  349. // PC98 have only MACHINE_TYPE_ISA.
  350. //
  351. HwBusType = MACHINE_TYPE_ISA;
  352. #else // PC98
  353. if (HwIsEisaSystem()) {
  354. HwBusType = MACHINE_TYPE_EISA;
  355. } else {
  356. HwBusType = MACHINE_TYPE_ISA;
  357. }
  358. #endif // PC98 || _GAMBIT_
  359. //
  360. // Allocate heap space for System component and initialize it.
  361. // Also make the System component the root of configuration tree.
  362. //
  363. #if DBG
  364. clrscrn ();
  365. BlPrint("Detecting System Component ...\n");
  366. #endif
  367. ConfigurationRoot = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  368. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  369. Component = &ConfigurationRoot->ComponentEntry;
  370. Component->Class = SystemClass;
  371. Component->Type = MaximumType; // NOTE should be IsaCompatible
  372. Component->Version = 0;
  373. Component->Key = 0;
  374. Component->AffinityMask = 0;
  375. Component->ConfigurationDataLength = 0;
  376. #if defined(NEC_98) || defined(_GAMBIT_)
  377. MachineId = "NEC PC-98";
  378. #else // PC98 || _GAMBIT_
  379. MachineId = GetMachineId();
  380. #endif // PC98 || _GAMBIT_
  381. if (MachineId) {
  382. Length = strlen(MachineId) + 1;
  383. IdentifierString = (FPCHAR)HwAllocateHeap(Length, FALSE);
  384. _fstrcpy(IdentifierString, MachineId);
  385. Component->Identifier = IdentifierString;
  386. Component->IdentifierLength = Length;
  387. } else {
  388. Component->Identifier = 0;
  389. Component->IdentifierLength = 0;
  390. }
  391. NextRelationship = Child;
  392. PreviousEntry = ConfigurationRoot;
  393. #if DBG
  394. BlPrint("Reading BIOS date ...\n");
  395. #endif
  396. HwGetBiosDate (0xF0000, 0xFFFF, &BiosYear, &BiosMonth, &BiosDay);
  397. #if DBG
  398. BlPrint("Done reading BIOS date (%d/%d/%d)\n",
  399. BiosMonth, BiosDay, BiosYear);
  400. #endif
  401. #if DBG
  402. BlPrint("Detecting PCI Bus Component ...\n");
  403. #endif
  404. #if _GAMBIT_
  405. PciEntry.NoBuses = 1;
  406. #else
  407. if (BiosYear > 1992 || (BiosYear == 1992 && BiosMonth >= 11) ) {
  408. // Bios date valid for pci presence check..
  409. HwGetPciSystemData((PVOID) &PciEntry, TRUE);
  410. } else {
  411. // Bios date not confirmed...
  412. HwGetPciSystemData((PVOID) &PciEntry, FALSE);
  413. }
  414. #endif // _GAMBIT_
  415. //
  416. // Add a registry entry for each PCI bus
  417. //
  418. for (i=0; i < PciEntry.NoBuses; i++) {
  419. AdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  420. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  421. Component = &AdapterEntry->ComponentEntry;
  422. Component->Class = AdapterClass;
  423. Component->Type = MultiFunctionAdapter;
  424. strcpy (Identifier, "PCI");
  425. Length = strlen(Identifier) + 1;
  426. IdentifierString = (FPCHAR)HwAllocateHeap(Length, FALSE);
  427. _fstrcpy(IdentifierString, Identifier);
  428. Component->Version = 0;
  429. Component->Key = 0;
  430. Component->AffinityMask = 0xffffffff;
  431. Component->IdentifierLength = Length;
  432. Component->Identifier = IdentifierString;
  433. AdapterEntry->ConfigurationData = NULL;
  434. Component->ConfigurationDataLength = 0;
  435. if (i == 0) {
  436. //
  437. // For the first PCI bus include the PCI_REGISTRY_INFO
  438. //
  439. Length = sizeof(PCI_REGISTRY_INFO) + DATA_HEADER_SIZE;
  440. ConfigurationData = (FPUCHAR) HwAllocateHeap(Length, TRUE);
  441. Component->ConfigurationDataLength = Length;
  442. AdapterEntry->ConfigurationData = ConfigurationData;
  443. _fmemcpy ( ((FPUCHAR) ConfigurationData+DATA_HEADER_SIZE),
  444. (FPVOID) &PciEntry, sizeof (PCI_REGISTRY_INFO));
  445. HwSetUpFreeFormDataHeader(
  446. (FPHWRESOURCE_DESCRIPTOR_LIST) ConfigurationData,
  447. 0,
  448. 0,
  449. 0,
  450. Length - DATA_HEADER_SIZE
  451. );
  452. }
  453. //
  454. // Add it to tree
  455. //
  456. if (NextRelationship == Sibling) {
  457. PreviousEntry->Sibling = AdapterEntry;
  458. AdapterEntry->Parent = PreviousEntry->Parent;
  459. } else {
  460. PreviousEntry->Child = AdapterEntry;
  461. AdapterEntry->Parent = PreviousEntry;
  462. }
  463. NextRelationship = Sibling;
  464. PreviousEntry = AdapterEntry;
  465. }
  466. #if DBG
  467. BlPrint("Detecting PCI Bus Component completes ...\n");
  468. #endif
  469. #if defined(NEC_98)
  470. #define _PNP_POWER_ 1
  471. #endif
  472. #if _PNP_POWER_
  473. #if DBG
  474. BlPrint("Detecting APM Bus Component ...\n");
  475. #endif
  476. if (HwGetApmSystemData((PVOID) &ApmEntry)) {
  477. AdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  478. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  479. Component = &AdapterEntry->ComponentEntry;
  480. Component->Class = AdapterClass;
  481. Component->Type = MultiFunctionAdapter;
  482. strcpy (Identifier, "APM");
  483. Length = strlen(Identifier) + 1;
  484. IdentifierString = (FPCHAR)HwAllocateHeap(Length, FALSE);
  485. _fstrcpy(IdentifierString, Identifier);
  486. Component->Version = 0;
  487. Component->Key = 0;
  488. Component->AffinityMask = 0xffffffff;
  489. Component->IdentifierLength = Length;
  490. Component->Identifier = IdentifierString;
  491. AdapterEntry->ConfigurationData = NULL;
  492. Component->ConfigurationDataLength = 0;
  493. //
  494. Length = sizeof(APM_REGISTRY_INFO) + DATA_HEADER_SIZE;
  495. ConfigurationData = (FPUCHAR) HwAllocateHeap(Length, TRUE);
  496. Component->ConfigurationDataLength = Length;
  497. AdapterEntry->ConfigurationData = ConfigurationData;
  498. _fmemcpy ( ((FPUCHAR) ConfigurationData+DATA_HEADER_SIZE),
  499. (FPVOID) &ApmEntry, sizeof (APM_REGISTRY_INFO));
  500. HwSetUpFreeFormDataHeader(
  501. (FPHWRESOURCE_DESCRIPTOR_LIST) ConfigurationData,
  502. 0,
  503. 0,
  504. 0,
  505. Length - DATA_HEADER_SIZE
  506. );
  507. //
  508. // Add it to tree
  509. //
  510. if (NextRelationship == Sibling) {
  511. PreviousEntry->Sibling = AdapterEntry;
  512. AdapterEntry->Parent = PreviousEntry->Parent;
  513. } else {
  514. PreviousEntry->Child = AdapterEntry;
  515. AdapterEntry->Parent = PreviousEntry;
  516. }
  517. NextRelationship = Sibling;
  518. PreviousEntry = AdapterEntry;
  519. }
  520. #if DBG
  521. BlPrint("APM Data collection complete...\n");
  522. #endif // DBG
  523. #endif // _PNP_POWER_
  524. #if DBG
  525. BlPrint("Detecting PnP BIOS Bus Component ...\n");
  526. #endif
  527. if (HwGetPnpBiosSystemData(&ConfigurationData, &Length)) {
  528. AdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  529. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  530. AdapterEntry->ConfigurationData = ConfigurationData;
  531. Component = &AdapterEntry->ComponentEntry;
  532. Component->ConfigurationDataLength = Length;
  533. Component->Class = AdapterClass;
  534. Component->Type = MultiFunctionAdapter;
  535. strcpy (Identifier, "PNP BIOS");
  536. i = strlen(Identifier) + 1;
  537. IdentifierString = (FPCHAR)HwAllocateHeap(i, FALSE);
  538. _fstrcpy(IdentifierString, Identifier);
  539. Component->Version = 0;
  540. Component->Key = 0;
  541. Component->AffinityMask = 0xffffffff;
  542. Component->IdentifierLength = i;
  543. Component->Identifier = IdentifierString;
  544. HwSetUpFreeFormDataHeader(
  545. (FPHWRESOURCE_DESCRIPTOR_LIST) ConfigurationData,
  546. 0,
  547. 0,
  548. 0,
  549. Length - DATA_HEADER_SIZE
  550. );
  551. //
  552. // Add it to tree
  553. //
  554. if (NextRelationship == Sibling) {
  555. PreviousEntry->Sibling = AdapterEntry;
  556. AdapterEntry->Parent = PreviousEntry->Parent;
  557. } else {
  558. PreviousEntry->Child = AdapterEntry;
  559. AdapterEntry->Parent = PreviousEntry;
  560. }
  561. NextRelationship = Sibling;
  562. PreviousEntry = AdapterEntry;
  563. }
  564. #if DBG
  565. BlPrint("PnP BIOS Data collection complete...\n");
  566. #endif // DBG
  567. //
  568. // Allocate heap space for Bus component and initialize it.
  569. //
  570. #if DBG
  571. BlPrint("Detecting Bus/Adapter Component ...\n");
  572. #endif
  573. AdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  574. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  575. Component = &AdapterEntry->ComponentEntry;
  576. Component->Class = AdapterClass;
  577. //
  578. // The assumption here is that the machine has only one
  579. // type of IO bus. If a machine has more than one types of
  580. // IO buses, it will not use this detection code anyway.
  581. //
  582. if (HwBusType == MACHINE_TYPE_EISA) {
  583. //
  584. // Note We don't collect EISA config data here. Because we may
  585. // exhaust the heap space. We will collect the data after all
  586. // the other components are detected.
  587. //
  588. Component->Type = EisaAdapter;
  589. strcpy(Identifier, "EISA");
  590. AdapterEntry->ConfigurationData = NULL;
  591. Component->ConfigurationDataLength = 0;
  592. } else {
  593. //
  594. // If not EISA, it must be ISA
  595. //
  596. Component->Type = MultiFunctionAdapter;
  597. strcpy(Identifier, "ISA");
  598. }
  599. #if defined(NEC_98)
  600. //
  601. // Some drivers for PC-98 want to get information of the BIOS Common aria.
  602. // So, enter them to the registry.
  603. // If evey drivers are changed to do not show them, then clear following codes
  604. // and (*) marked!
  605. //
  606. Component->Type = MultiFunctionAdapter;
  607. strcpy(Identifier, "ISA");
  608. AdapterEntry->ConfigurationData = HwAllocateHeap (DATA_HEADER_SIZE + 512 + 64, TRUE); //921208
  609. _fmemcpy ((UCHAR far *) (AdapterEntry->ConfigurationData)+DATA_HEADER_SIZE,(unsigned far *) SYSTEM_SEGMENT, 512);
  610. _fmemcpy ((UCHAR far *) (AdapterEntry->ConfigurationData)+DATA_HEADER_SIZE+512,(unsigned far *) SYSTEM_SEGMENT_2, 64);
  611. Component->ConfigurationDataLength = DATA_HEADER_SIZE + 512 + 64;
  612. HwSetUpFreeFormDataHeader((FPHWRESOURCE_DESCRIPTOR_LIST)(AdapterEntry->ConfigurationData),
  613. 0,
  614. 0,
  615. 0,
  616. 512 + 64
  617. );
  618. #endif // PC98
  619. Length = strlen(Identifier) + 1;
  620. IdentifierString = (FPCHAR)HwAllocateHeap(Length, FALSE);
  621. _fstrcpy(IdentifierString, Identifier);
  622. Component->Version = 0;
  623. Component->Key = 0;
  624. Component->AffinityMask = 0xffffffff;
  625. Component->IdentifierLength = Length;
  626. Component->Identifier = IdentifierString;
  627. //
  628. // Make Adapter component System's child
  629. //
  630. if (NextRelationship == Sibling) {
  631. PreviousEntry->Sibling = AdapterEntry;
  632. AdapterEntry->Parent = PreviousEntry->Parent;
  633. } else {
  634. PreviousEntry->Child = AdapterEntry;
  635. AdapterEntry->Parent = PreviousEntry;
  636. }
  637. NextRelationship = Child;
  638. PreviousEntry = AdapterEntry;
  639. //
  640. // Collect BIOS information for ConfigurationRoot component.
  641. // This step is done here because we need data collected in
  642. // adapter component. The ConfigurationData is:
  643. // HWRESOURCE_DESCRIPTOR_LIST header
  644. // HWPARTIAL_RESOURCE_DESCRIPTOR for Parameter Table
  645. // HWPARTIAL_RESOURCE_DESCRIPTOR for Rom Blocks.
  646. // (Note DATA_HEADER_SIZE contains the size of the first partial
  647. // descriptor already.)
  648. //
  649. #if DBG
  650. BlPrint("Collecting Disk Geometry...\n");
  651. #endif
  652. #if defined(_GAMBIT_)
  653. RomChain = (PHARD_DISK_PARAMETERS)
  654. HwAllocateHeap(SIZE_OF_PARAMETER * MAX_DRIVE_NUMBER, FALSE);
  655. //
  656. // Just hardcode it:
  657. // SscGetDriveParameters((PVOID)&RomChain, &Length);
  658. //
  659. RomChain[0].DriveSelect = 0x82; // drive e:
  660. RomChain[0].MaxCylinders = 0; // dummy value
  661. RomChain[0].SectorsPerTrack = 0; // dummy value
  662. RomChain[0].MaxHeads = 0; // dummy value
  663. RomChain[0].NumberDrives = 1; // Gambit only access 1 drive
  664. NumberBiosDisks = 1; // was defined in diska.asm
  665. #else
  666. GetInt13DriveParameters((PVOID)&RomChain, &Length);
  667. #endif // _GAMBIT_
  668. InitialLength = (USHORT)(Length + RESERVED_ROM_BLOCK_LIST_SIZE + DATA_HEADER_SIZE +
  669. sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR));
  670. ConfigurationData = (FPUCHAR)HwAllocateHeap(InitialLength, FALSE);
  671. EndConfigurationData = ConfigurationData + DATA_HEADER_SIZE;
  672. if (Length != 0) {
  673. FpRomChain = EndConfigurationData;
  674. _fmemcpy(FpRomChain, (FPVOID)RomChain, Length);
  675. }
  676. EndConfigurationData += (sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR) +
  677. Length);
  678. HwSetUpFreeFormDataHeader((FPHWRESOURCE_DESCRIPTOR_LIST)ConfigurationData,
  679. 0,
  680. 0,
  681. 0,
  682. Length
  683. );
  684. //
  685. // Scan ROM to collect all the ROM blocks, if possible.
  686. //
  687. #if DBG
  688. BlPrint("Detecting ROM Blocks...\n");
  689. #endif
  690. FpRomBlock = EndConfigurationData;
  691. GetRomBlocks(FpRomBlock, &Length);
  692. RomBlockLength = Length;
  693. if (Length != 0) {
  694. EndConfigurationData += Length;
  695. } else {
  696. FpRomBlock = NULL;
  697. }
  698. //
  699. // We have both RomChain and RomBlock information/Headers.
  700. //
  701. DescriptorList = (FPHWRESOURCE_DESCRIPTOR_LIST)ConfigurationData;
  702. DescriptorList->Count = 2;
  703. Descriptor = (FPHWPARTIAL_RESOURCE_DESCRIPTOR)(
  704. EndConfigurationData - Length -
  705. sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR));
  706. Descriptor->Type = RESOURCE_DEVICE_DATA;
  707. Descriptor->ShareDisposition = 0;
  708. Descriptor->Flags = 0;
  709. Descriptor->u.DeviceSpecificData.DataSize = (ULONG)Length;
  710. Descriptor->u.DeviceSpecificData.Reserved1 = 0;
  711. Descriptor->u.DeviceSpecificData.Reserved2 = 0;
  712. Length = (USHORT)(MAKE_FLAT_ADDRESS(EndConfigurationData) -
  713. MAKE_FLAT_ADDRESS(ConfigurationData));
  714. ConfigurationRoot->ComponentEntry.ConfigurationDataLength = Length;
  715. ConfigurationRoot->ConfigurationData = ConfigurationData;
  716. FreeSize = InitialLength - Length;
  717. HwFreeHeap((ULONG)FreeSize);
  718. //
  719. // Set up device information structure for Keyboard.
  720. //
  721. #if DBG
  722. BlPrint("Detecting Keyboard Component ...\n");
  723. #endif
  724. KeyboardId = GetKeyboardId();
  725. CurrentEntry = SetKeyboardConfigurationData(KeyboardId);
  726. //
  727. // Make display component the child of Adapter component.
  728. //
  729. if (NextRelationship == Sibling) {
  730. PreviousEntry->Sibling = CurrentEntry;
  731. CurrentEntry->Parent = PreviousEntry->Parent;
  732. } else {
  733. PreviousEntry->Child = CurrentEntry;
  734. CurrentEntry->Parent = PreviousEntry;
  735. }
  736. NextRelationship = Sibling;
  737. PreviousEntry = CurrentEntry;
  738. //
  739. // Set up device information for com port (Each COM component
  740. // is treated as a controller class.)
  741. //
  742. #if DBG
  743. BlPrint("Detecting ComPort Component ...\n");
  744. #endif
  745. if (CurrentEntry = GetComportInformation()) {
  746. FirstCom = CurrentEntry;
  747. //
  748. // Make current component the child of Adapter component.
  749. //
  750. if (NextRelationship == Sibling) {
  751. PreviousEntry->Sibling = CurrentEntry;
  752. } else {
  753. PreviousEntry->Child = CurrentEntry;
  754. }
  755. while (CurrentEntry) {
  756. CurrentEntry->Parent = AdapterEntry;
  757. PreviousEntry = CurrentEntry;
  758. CurrentEntry = CurrentEntry->Sibling;
  759. }
  760. NextRelationship = Sibling;
  761. }
  762. //
  763. // Set up device information for parallel port. (Each parallel
  764. // is treated as a controller class.)
  765. //
  766. #if DBG
  767. BlPrint("Detecting Parallel Component ...\n");
  768. #endif
  769. #if !defined(_GAMBIT_)
  770. if (CurrentEntry = GetLptInformation()) {
  771. FirstLpt = CurrentEntry;
  772. //
  773. // Make current component the child of Adapter component.
  774. //
  775. if (NextRelationship == Sibling) {
  776. PreviousEntry->Sibling = CurrentEntry;
  777. CurrentEntry->Parent = PreviousEntry->Parent;
  778. } else {
  779. PreviousEntry->Child = CurrentEntry;
  780. CurrentEntry->Parent = PreviousEntry;
  781. }
  782. PreviousEntry = CurrentEntry;
  783. CurrentEntry = CurrentEntry->Sibling;
  784. while (CurrentEntry) {
  785. CurrentEntry->Parent = PreviousEntry->Parent;
  786. PreviousEntry = CurrentEntry;
  787. CurrentEntry = CurrentEntry->Sibling;
  788. }
  789. NextRelationship = Sibling;
  790. }
  791. #endif // _GAMBIT_
  792. //
  793. // Set up device information structure for Mouse.
  794. //
  795. #if DBG
  796. BlPrint("Detecting Mouse Component ...\n");
  797. #endif
  798. if (CurrentEntry = GetMouseInformation()) {
  799. //
  800. // Make current component the child of Adapter component.
  801. //
  802. if (NextRelationship == Sibling) {
  803. PreviousEntry->Sibling = CurrentEntry;
  804. CurrentEntry->Parent = PreviousEntry->Parent;
  805. } else {
  806. PreviousEntry->Child = CurrentEntry;
  807. CurrentEntry->Parent = PreviousEntry;
  808. }
  809. PreviousEntry = CurrentEntry;
  810. CurrentEntry = CurrentEntry->Sibling;
  811. while (CurrentEntry) {
  812. CurrentEntry->Parent = PreviousEntry->Parent;
  813. PreviousEntry = CurrentEntry;
  814. CurrentEntry = CurrentEntry->Sibling;
  815. }
  816. NextRelationship = Sibling;
  817. }
  818. //
  819. // Set up device information for floppy drives. (The returned information
  820. // is a tree structure.)
  821. //
  822. #if DBG
  823. BlPrint("Detecting Floppy Component ...\n");
  824. #endif
  825. if (CurrentEntry = GetFloppyInformation()) {
  826. //
  827. // Make current component the child of Adapter component.
  828. //
  829. if (NextRelationship == Sibling) {
  830. PreviousEntry->Sibling = CurrentEntry;
  831. } else {
  832. PreviousEntry->Child = CurrentEntry;
  833. }
  834. while (CurrentEntry) {
  835. CurrentEntry->Parent = AdapterEntry;
  836. PreviousEntry = CurrentEntry;
  837. CurrentEntry = CurrentEntry->Sibling;
  838. }
  839. NextRelationship = Sibling;
  840. }
  841. #if DBG
  842. BlPrint("Detecting ACPI Bus Component ...\n");
  843. #endif
  844. #if !defined(_GAMBIT_)
  845. if (HwGetAcpiBiosData(&ConfigurationData, &Length)) {
  846. AcpiAdapterEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  847. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  848. AcpiAdapterEntry->ConfigurationData = ConfigurationData;
  849. Component = &AcpiAdapterEntry->ComponentEntry;
  850. Component->ConfigurationDataLength = Length;
  851. Component->Class = AdapterClass;
  852. Component->Type = MultiFunctionAdapter;
  853. strcpy (Identifier, "ACPI BIOS");
  854. i = strlen(Identifier) + 1;
  855. IdentifierString = (FPCHAR)HwAllocateHeap(i, FALSE);
  856. _fstrcpy(IdentifierString, Identifier);
  857. Component->Version = 0;
  858. Component->Key = 0;
  859. Component->AffinityMask = 0xffffffff;
  860. Component->IdentifierLength = i;
  861. Component->Identifier = IdentifierString;
  862. HwSetUpFreeFormDataHeader(
  863. (FPULONG) ConfigurationData,
  864. 0,
  865. 0,
  866. 0,
  867. Length - DATA_HEADER_SIZE
  868. );
  869. //
  870. // Add it to tree
  871. //
  872. if (NextRelationship == Sibling) {
  873. PreviousEntry->Parent->Sibling = AcpiAdapterEntry;
  874. AcpiAdapterEntry->Parent = PreviousEntry->Parent->Parent;
  875. }
  876. NextRelationship = Sibling;
  877. }
  878. #if DBG
  879. BlPrint("ACPI BIOS Data collection complete...\n");
  880. #endif // DBG
  881. #endif // _GAMBIT_
  882. //
  883. // Set up device information structure for Video Display Adapter.
  884. //
  885. #if DBG
  886. BlPrint("Detection done. Press a key to display hardware info ...\n");
  887. #if !defined(_GAMBIT_)
  888. while ( ! HwGetKey ());
  889. #endif
  890. clrscrn ();
  891. // BlPrint("Detecting Video Component ...\n");
  892. #endif
  893. #if 0 // Remove video detection
  894. if (VideoAdapterType = GetVideoAdapterType()) {
  895. CurrentEntry = SetVideoConfigurationData(VideoAdapterType);
  896. //
  897. // Make display component the child of Adapter component.
  898. //
  899. if (NextRelationship == Sibling) {
  900. PreviousEntry->Sibling = CurrentEntry;
  901. CurrentEntry->Parent = PreviousEntry->Parent;
  902. } else {
  903. PreviousEntry->Child = CurrentEntry;
  904. CurrentEntry->Parent = PreviousEntry;
  905. }
  906. NextRelationship = Sibling;
  907. PreviousEntry = CurrentEntry;
  908. }
  909. #endif
  910. #if defined(NEC_98)
  911. #if DBG
  912. BlPrint("Detecting SCSI Component ...\n");
  913. #endif
  914. if (CurrentEntry = GetScsiDiskInformation()) {
  915. //
  916. // Make current component the child of Adapter component.
  917. //
  918. if (NextRelationship == Sibling) {
  919. PreviousEntry->Sibling = CurrentEntry;
  920. } else {
  921. PreviousEntry->Child = CurrentEntry;
  922. }
  923. NextRelationship = Sibling;
  924. PreviousEntry = CurrentEntry;
  925. }
  926. #endif // PC98
  927. #if defined(NEC_98) || defined(_GAMBIT_)
  928. #else // PC98 || _GAMBIT_
  929. //
  930. // Misc. supports. Note, the information collected here will NOT be
  931. // written to hardware registry.
  932. //
  933. // 1. Collect video font information for vdm
  934. //
  935. GetVideoFontInformation();
  936. //
  937. // After all the components are detected, we collect EISA config data.
  938. //
  939. if (HwBusType == MACHINE_TYPE_EISA) {
  940. Component = &AdapterEntry->ComponentEntry;
  941. GetEisaConfigurationData(&AdapterEntry->ConfigurationData,
  942. &Component->ConfigurationDataLength);
  943. if (Component->ConfigurationDataLength) {
  944. HwEisaConfigurationData = (FPUCHAR)AdapterEntry->ConfigurationData +
  945. DATA_HEADER_SIZE;
  946. HwEisaConfigurationSize = Component->ConfigurationDataLength -
  947. DATA_HEADER_SIZE;
  948. //
  949. // Misc. detections based on Eisa config data
  950. //
  951. // Update Lpt and com controllers' irq information by examining
  952. // the EISA configuration data.
  953. //
  954. GetIrqFromEisaData(FirstLpt, ParallelController);
  955. GetIrqFromEisaData(FirstCom, SerialController);
  956. }
  957. }
  958. #endif // PC98 || _GAMBIT_
  959. #if DBG
  960. CheckConfigurationTree(ConfigurationRoot);
  961. #endif
  962. //
  963. // Update all the far pointers in the tree to flat 32 bit pointers
  964. //
  965. UpdateConfigurationTree(ConfigurationRoot);
  966. //
  967. // Set up returned values:
  968. // Size of Heap space which should be preserved for configuration tree
  969. // Pointer to the root of the configuration tree.
  970. //
  971. CurrentEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap(0, FALSE);
  972. *BlHeapUsed = (ULONG) (MAKE_FLAT_ADDRESS(CurrentEntry) -
  973. MAKE_FLAT_ADDRESS(ConfigurationRoot));
  974. *BlConfigurationTree = (ULONG_PTR)MAKE_FLAT_ADDRESS(ConfigurationRoot);
  975. }
  976. #if defined(NEC_98) || defined(_GAMBIT_)
  977. #else
  978. VOID
  979. GetIrqFromEisaData(
  980. FPFWCONFIGURATION_COMPONENT_DATA ControllerList,
  981. CONFIGURATION_TYPE ControllerType
  982. )
  983. /*++
  984. Routine Description:
  985. This routine updates all irq information for ControllerType components
  986. in the controllerList by examinine the eisa configuration data.
  987. Arguments:
  988. ControllerList - Supplies a pointer to a component entry whoes irq will
  989. be updated.
  990. ControllerType - Supplies the controller type whoes irq will be searched
  991. for.
  992. Returns:
  993. None.
  994. --*/
  995. {
  996. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry;
  997. FPHWPARTIAL_RESOURCE_DESCRIPTOR Descriptor;
  998. FPHWRESOURCE_DESCRIPTOR_LIST DescriptorList;
  999. USHORT i, Port;
  1000. UCHAR Irq, Trigger;
  1001. CurrentEntry = ControllerList;
  1002. while (CurrentEntry &&
  1003. CurrentEntry->ComponentEntry.Type == ControllerType) {
  1004. if (CurrentEntry->ConfigurationData) {
  1005. DescriptorList = (FPHWRESOURCE_DESCRIPTOR_LIST)
  1006. CurrentEntry->ConfigurationData;
  1007. Port = 0;
  1008. for (i = 0; i < (USHORT)DescriptorList->Count; i++) {
  1009. Descriptor = &DescriptorList->PartialDescriptors[i];
  1010. if (Descriptor->Type == CmResourceTypePort) {
  1011. Port = (USHORT)Descriptor->u.Port.Start.LowPart;
  1012. break;
  1013. }
  1014. }
  1015. if (Port != 0) {
  1016. for (i = 0; i < (USHORT)DescriptorList->Count; i++) {
  1017. Descriptor = &DescriptorList->PartialDescriptors[i];
  1018. if (Descriptor->Type == CmResourceTypeInterrupt) {
  1019. if (HwEisaGetIrqFromPort(Port, &Irq, &Trigger)) {
  1020. if (Trigger == 0) { // EISA EDGE_TRIGGER
  1021. Descriptor->Flags = EDGE_TRIGGERED;
  1022. } else {
  1023. Descriptor->Flags = LEVEL_SENSITIVE;
  1024. }
  1025. Descriptor->u.Interrupt.Level = Irq;
  1026. Descriptor->u.Interrupt.Vector = Irq;
  1027. break;
  1028. }
  1029. }
  1030. }
  1031. }
  1032. }
  1033. CurrentEntry = CurrentEntry->Sibling;
  1034. }
  1035. }
  1036. #endif
  1037. VOID
  1038. UpdateComponentPointers(
  1039. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
  1040. )
  1041. /*++
  1042. Routine Description:
  1043. This routine updates all the "far" pointer to 32 bit flat addresses
  1044. for a component entry.
  1045. Arguments:
  1046. CurrentEntry - Supplies a pointer to a component entry which will
  1047. be updated.
  1048. Returns:
  1049. None.
  1050. --*/
  1051. {
  1052. PULONG_PTR UpdatePointer;
  1053. FPVOID NextEntry;
  1054. ULONG_PTR FlatAddress;
  1055. //
  1056. // Update the child, parent, sibling and ConfigurationData
  1057. // far pointers to 32 bit flat addresses.
  1058. // N.B. After we update the pointers to flat addresses, they
  1059. // can no longer be accessed in real mode.
  1060. //
  1061. UpdatePointer = (PULONG_PTR)&CurrentEntry->Child;
  1062. NextEntry = (FPVOID)CurrentEntry->Child;
  1063. FlatAddress = (ULONG_PTR)MAKE_FLAT_ADDRESS(NextEntry);
  1064. *UpdatePointer = FlatAddress;
  1065. UpdatePointer = (PULONG_PTR)&CurrentEntry->Parent;
  1066. NextEntry = (FPVOID)CurrentEntry->Parent;
  1067. FlatAddress = (ULONG_PTR)MAKE_FLAT_ADDRESS(NextEntry);
  1068. *UpdatePointer = FlatAddress;
  1069. UpdatePointer = (PULONG_PTR)&CurrentEntry->Sibling;
  1070. NextEntry = (FPVOID)CurrentEntry->Sibling;
  1071. FlatAddress = (ULONG_PTR)MAKE_FLAT_ADDRESS(NextEntry);
  1072. *UpdatePointer = FlatAddress;
  1073. UpdatePointer = (PULONG_PTR)&CurrentEntry->ComponentEntry.Identifier;
  1074. NextEntry = (FPVOID)CurrentEntry->ComponentEntry.Identifier;
  1075. FlatAddress = (ULONG_PTR)MAKE_FLAT_ADDRESS(NextEntry);
  1076. *UpdatePointer = FlatAddress;
  1077. UpdatePointer = (PULONG_PTR)&CurrentEntry->ConfigurationData;
  1078. NextEntry = (FPVOID)CurrentEntry->ConfigurationData;
  1079. FlatAddress = (ULONG_PTR)MAKE_FLAT_ADDRESS(NextEntry);
  1080. *UpdatePointer = FlatAddress;
  1081. }
  1082. VOID
  1083. UpdateConfigurationTree(
  1084. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
  1085. )
  1086. /*++
  1087. Routine Description:
  1088. This routine traverses loader configuration tree and changes
  1089. all the "far" pointer to 32 bit flat addresses.
  1090. Arguments:
  1091. CurrentEntry - Supplies a pointer to a loader configuration
  1092. tree or subtree.
  1093. Returns:
  1094. None.
  1095. --*/
  1096. {
  1097. if (CurrentEntry) {
  1098. UpdateConfigurationTree(CurrentEntry->Child);
  1099. UpdateConfigurationTree(CurrentEntry->Sibling);
  1100. UpdateComponentPointers(CurrentEntry);
  1101. }
  1102. }
  1103. FPVOID
  1104. HwSetUpResourceDescriptor (
  1105. FPFWCONFIGURATION_COMPONENT Component,
  1106. PUCHAR Identifier,
  1107. PHWCONTROLLER_DATA ControlData,
  1108. USHORT SpecificDataLength,
  1109. PUCHAR SpecificData
  1110. )
  1111. /*++
  1112. Routine Description:
  1113. This routine allocates space from far heap , puts the caller's controller
  1114. information to the space and sets up CONFIGURATION_COMPONENT
  1115. structure for the caller.
  1116. Arguments:
  1117. Component - Supplies the address the component whose configuration data
  1118. should be set up.
  1119. Identifier - Suppies a pointer to the identifier to identify the controller
  1120. ControlData - Supplies a point to a structure which describes
  1121. controller information.
  1122. SpecificDataLength - size of the device specific data. Device specific
  1123. data is the information not defined in the standard format.
  1124. SpecificData - Supplies a pointer to the device specific data.
  1125. Return Value:
  1126. Returns a far pointer to the Configuration data.
  1127. --*/
  1128. {
  1129. FPCHAR fpIdentifier;
  1130. FPHWRESOURCE_DESCRIPTOR_LIST fpDescriptor = NULL;
  1131. USHORT Length;
  1132. SHORT Count, i;
  1133. FPUCHAR fpSpecificData;
  1134. //
  1135. // Set up Identifier string for hardware component, if necessary.
  1136. //
  1137. if (Identifier) {
  1138. Length = strlen(Identifier) + 1;
  1139. Component->IdentifierLength = Length;
  1140. fpIdentifier = (FPUCHAR)HwAllocateHeap(Length, FALSE);
  1141. Component->Identifier = fpIdentifier;
  1142. _fstrcpy(fpIdentifier, Identifier);
  1143. } else {
  1144. Component->IdentifierLength = 0;
  1145. Component->Identifier = NULL;
  1146. }
  1147. //
  1148. // Set up configuration data for hardware component, if necessary
  1149. //
  1150. Count = ControlData->NumberPortEntries + ControlData->NumberIrqEntries +
  1151. ControlData->NumberMemoryEntries + ControlData->NumberDmaEntries;
  1152. if (SpecificDataLength) {
  1153. //
  1154. // if we have device specific data, we need to increment the count
  1155. // by one.
  1156. //
  1157. Count++;
  1158. }
  1159. if (Count >0) {
  1160. Length = (USHORT)(Count * sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR) +
  1161. FIELD_OFFSET(HWRESOURCE_DESCRIPTOR_LIST, PartialDescriptors) +
  1162. SpecificDataLength);
  1163. fpDescriptor = (FPHWRESOURCE_DESCRIPTOR_LIST)HwAllocateHeap(Length, TRUE);
  1164. fpDescriptor->Count = Count;
  1165. //
  1166. // Copy all the partial descriptors to the destination descriptors
  1167. // except the last one. (The last partial descriptor may be a device
  1168. // specific data. It requires special handling.)
  1169. //
  1170. for (i = 0; i < (Count - 1); i++) {
  1171. fpDescriptor->PartialDescriptors[i] =
  1172. ControlData->DescriptorList[i];
  1173. }
  1174. //
  1175. // Set up the last partial descriptor. If it is a port, memory, irq or
  1176. // dma entry, we simply copy it. If the last one is for device specific
  1177. // data, we set up the length and copy the device spcific data to the end
  1178. // of the decriptor.
  1179. //
  1180. if (SpecificData) {
  1181. fpDescriptor->PartialDescriptors[Count - 1].Type =
  1182. RESOURCE_DEVICE_DATA;
  1183. fpDescriptor->PartialDescriptors[Count - 1].Flags = 0;
  1184. fpDescriptor->PartialDescriptors[Count - 1].u.DeviceSpecificData.DataSize =
  1185. SpecificDataLength;
  1186. fpSpecificData = (FPUCHAR)&(fpDescriptor->PartialDescriptors[Count]);
  1187. _fmemcpy(fpSpecificData, SpecificData, SpecificDataLength);
  1188. } else {
  1189. fpDescriptor->PartialDescriptors[Count - 1] =
  1190. ControlData->DescriptorList[Count - 1];
  1191. }
  1192. Component->ConfigurationDataLength = Length;
  1193. }
  1194. return(fpDescriptor);
  1195. }
  1196. VOID
  1197. HwSetUpFreeFormDataHeader (
  1198. FPHWRESOURCE_DESCRIPTOR_LIST Header,
  1199. USHORT Version,
  1200. USHORT Revision,
  1201. USHORT Flags,
  1202. ULONG DataSize
  1203. )
  1204. /*++
  1205. Routine Description:
  1206. This routine initialize free formed data header. Note this routine
  1207. sets the the Header and initialize the FIRST PartialDescriptor only.
  1208. If the header contains more than one descriptor, the caller must handle
  1209. it itself.
  1210. Arguments:
  1211. Header - Supplies a pointer to the header to be initialized.
  1212. Version - Version number for the header.
  1213. Revision - Revision number for the header.
  1214. Flags - Free formed data flags. (Currently, it is undefined and
  1215. should be zero.)
  1216. DataSize - Size of the free formed data.
  1217. Return Value:
  1218. None.
  1219. --*/
  1220. {
  1221. Header->Version = Version;
  1222. Header->Revision = Revision;
  1223. Header->Count = 1;
  1224. Header->PartialDescriptors[0].Type = RESOURCE_DEVICE_DATA;
  1225. Header->PartialDescriptors[0].ShareDisposition = 0;
  1226. Header->PartialDescriptors[0].Flags = Flags;
  1227. Header->PartialDescriptors[0].u.DeviceSpecificData.DataSize = DataSize;
  1228. Header->PartialDescriptors[0].u.DeviceSpecificData.Reserved1 = 0;
  1229. Header->PartialDescriptors[0].u.DeviceSpecificData.Reserved2 = 0;
  1230. }
  1231. #if DBG
  1232. VOID
  1233. CheckComponentNode(
  1234. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
  1235. )
  1236. {
  1237. FPUCHAR NextEntry, DataPointer;
  1238. ULONG_PTR FlatAddress;
  1239. ULONG Length;
  1240. UCHAR IdString[40];
  1241. USHORT Count, i;
  1242. UCHAR Type;
  1243. FPHWRESOURCE_DESCRIPTOR_LIST DescriptorList;
  1244. FPHWPARTIAL_RESOURCE_DESCRIPTOR Descriptor;
  1245. FlatAddress = MAKE_FLAT_ADDRESS(CurrentEntry);
  1246. clrscrn ();
  1247. BlPrint("\n");
  1248. BlPrint("Current Node: %lx\n", FlatAddress);
  1249. BlPrint(" Type = %s\n", TypeName[CurrentEntry->ComponentEntry.Type]);
  1250. //
  1251. // Update the child, parent, sibling and ConfigurationData
  1252. // far pointers to 32 bit flat addresses.
  1253. // N.B. After we update the pointers to flat addresses, they
  1254. // can no longer be accessed in real mode.
  1255. //
  1256. NextEntry = (FPUCHAR)CurrentEntry->Child;
  1257. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1258. if (FlatAddress > 0x60000 || (FlatAddress < 0x50000 && FlatAddress != 0)) {
  1259. BlPrint("Invalid address: Child = %lx\n", FlatAddress);
  1260. } else {
  1261. BlPrint("\tChild = %lx\n", FlatAddress);
  1262. }
  1263. NextEntry = (FPUCHAR)CurrentEntry->Parent;
  1264. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1265. if (FlatAddress > 0x60000 || (FlatAddress < 0x50000 && FlatAddress != 0)) {
  1266. BlPrint("Invalid address: Parent = %lx\n", FlatAddress);
  1267. } else {
  1268. BlPrint("\tParent = %lx\n", FlatAddress);
  1269. }
  1270. NextEntry = (FPUCHAR)CurrentEntry->Sibling;
  1271. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1272. if (FlatAddress > 0x60000 || (FlatAddress < 0x50000 && FlatAddress != 0)) {
  1273. BlPrint("Invalid address: Sibling = %lx\n", FlatAddress);
  1274. } else {
  1275. BlPrint("\tSibling = %lx\n", FlatAddress);
  1276. }
  1277. NextEntry = (FPUCHAR)CurrentEntry->ConfigurationData;
  1278. FlatAddress = MAKE_FLAT_ADDRESS(NextEntry);
  1279. if (FlatAddress > 0x60000 || (FlatAddress < 0x50000 && FlatAddress != 0)) {
  1280. BlPrint("Invalid address: ConfigurationData = %lx\n", FlatAddress);
  1281. } else {
  1282. BlPrint("\tConfigurationData = %lx\n", FlatAddress);
  1283. }
  1284. Length = CurrentEntry->ComponentEntry.IdentifierLength;
  1285. BlPrint("IdentifierLength = %lx\n", CurrentEntry->ComponentEntry.IdentifierLength);
  1286. if (Length > 0) {
  1287. _fstrcpy(IdString, CurrentEntry->ComponentEntry.Identifier);
  1288. BlPrint("Identifier = %s\n", IdString);
  1289. }
  1290. Length = CurrentEntry->ComponentEntry.ConfigurationDataLength;
  1291. BlPrint("ConfigdataLength = %lx\n", Length);
  1292. if (Length > 0) {
  1293. DescriptorList = (FPHWRESOURCE_DESCRIPTOR_LIST)CurrentEntry->ConfigurationData;
  1294. BlPrint("Version = %x, Revision = %x\n", DescriptorList->Version,
  1295. DescriptorList->Revision);
  1296. Count = (USHORT)DescriptorList->Count;
  1297. Descriptor = &DescriptorList->PartialDescriptors[0];
  1298. BlPrint("Count = %x\n", Count);
  1299. while (Count > 0) {
  1300. Type = Descriptor->Type;
  1301. if (Type == RESOURCE_PORT) {
  1302. BlPrint("Type = Port");
  1303. BlPrint("\tShareDisposition = %x\n", Descriptor->ShareDisposition);
  1304. BlPrint("PortFlags = %x\n", Descriptor->Flags);
  1305. BlPrint("PortStart = %x", Descriptor->u.Port.Start);
  1306. BlPrint("\tPortLength = %x\n", Descriptor->u.Port.Length);
  1307. } else if (Type == RESOURCE_DMA) {
  1308. BlPrint("Type = Dma");
  1309. BlPrint("\tShareDisposition = %x\n", Descriptor->ShareDisposition);
  1310. BlPrint("DmaFlags = %x\n", Descriptor->Flags);
  1311. BlPrint("DmaChannel = %x", Descriptor->u.Dma.Channel);
  1312. BlPrint("\tDmaPort = %lx\n", Descriptor->u.Dma.Port);
  1313. } else if (Type == RESOURCE_INTERRUPT) {
  1314. BlPrint("Type = Interrupt");
  1315. BlPrint("\tShareDisposition = %x\n", Descriptor->ShareDisposition);
  1316. BlPrint("InterruptFlags = %x\n", Descriptor->Flags);
  1317. BlPrint("Level = %x", Descriptor->u.Interrupt.Level);
  1318. BlPrint("\tVector = %x\n", Descriptor->u.Interrupt.Vector);
  1319. } else if (Type == RESOURCE_MEMORY) {
  1320. BlPrint("Type = Memory");
  1321. BlPrint("\tShareDisposition = %x\n", Descriptor->ShareDisposition);
  1322. BlPrint("MemoryFlags = %x\n", Descriptor->Flags);
  1323. BlPrint("Start1 = %lx", (ULONG)Descriptor->u.Memory.Start.LowPart);
  1324. BlPrint("\tStart2 = %lx", (ULONG)Descriptor->u.Memory.Start.HighPart);
  1325. BlPrint("\tLength = %lx\n", Descriptor->u.Memory.Length);
  1326. } else {
  1327. BlPrint("Type = Device Data\n");
  1328. Length = Descriptor->u.DeviceSpecificData.DataSize;
  1329. BlPrint("Size = %lx\n", Length);
  1330. DataPointer = (FPUCHAR)(Descriptor+1);
  1331. for (i = 0; i < Length && i < 64; i++) {
  1332. BlPrint("%x ", *DataPointer);
  1333. DataPointer++;
  1334. }
  1335. break;
  1336. }
  1337. Count--;
  1338. Descriptor++;
  1339. }
  1340. }
  1341. #if defined(NEC_98)
  1342. HwGetKey ();
  1343. #elif !defined(_GAMBIT_)
  1344. while (HwGetKey() == 0) {
  1345. }
  1346. #endif // PC98 || _GAMBIT_
  1347. }
  1348. VOID
  1349. CheckConfigurationTree(
  1350. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry
  1351. )
  1352. {
  1353. if (CurrentEntry) {
  1354. CheckComponentNode(CurrentEntry);
  1355. CheckConfigurationTree(CurrentEntry->Sibling);
  1356. CheckConfigurationTree(CurrentEntry->Child);
  1357. }
  1358. }
  1359. #endif