Windows NT 4.0 source code leak
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.

1261 lines
27 KiB

4 years ago
  1. // #pragma comment(exestr, "@(#) x86bios.c 1.1 95/09/28 18:40:12 nec")
  2. /*++
  3. Copyright (c) 1994 Microsoft Corporation
  4. Module Name:
  5. x86bios.c
  6. Abstract:
  7. This module implements the platform specific interface between a device
  8. driver and the execution of x86 ROM bios code for the device.
  9. Author:
  10. David N. Cutler (davec) 17-Jun-1994
  11. Environment:
  12. Kernel mode only.
  13. Revision History:
  14. M001 kuriyama@oa2.kb.nec.co.jp Tue Jul 18 15:45:09 JST 1995
  15. - add check intel based bios flag
  16. M002 kuriyama@oa2.kb.nec.co.jp Thu Jul 20 15:16:52 JST 1995
  17. - add for DPI support (NO PCI DATA structure)
  18. S003 kuriyama@oa2.kb.nec.co.jp Tue Aug 15 14:09:30 JST 1995
  19. - bug fix for canopus PowerWindows 864PCI
  20. --*/
  21. #define USE_BIOS_EMULATOR
  22. #include "halp.h"
  23. #include "pci.h"
  24. #include "pcip.h"
  25. #include "xm86.h"
  26. #include "x86new.h"
  27. VOID
  28. HalpReadPCIConfigUlongByOffset (
  29. IN PCI_SLOT_NUMBER Slot,
  30. IN PULONG Buffer,
  31. IN ULONG Offset
  32. );
  33. VOID
  34. HalpWritePCIConfigUlongByOffset (
  35. IN PCI_SLOT_NUMBER Slot,
  36. IN PULONG Buffer,
  37. IN ULONG Offset
  38. );
  39. VOID
  40. HalpReadPCIConfigUshortByOffset (
  41. IN PCI_SLOT_NUMBER Slot,
  42. IN PSHORT Buffer,
  43. IN ULONG Offset
  44. );
  45. VOID
  46. HalpWritePCIConfigUshortByOffset (
  47. IN PCI_SLOT_NUMBER Slot,
  48. IN PSHORT Buffer,
  49. IN ULONG Offset
  50. );
  51. // M001 +++
  52. VOID
  53. HalpReadPCIConfigUcharByOffset (
  54. IN PCI_SLOT_NUMBER Slot,
  55. IN PUCHAR Buffer,
  56. IN ULONG Offset
  57. );
  58. VOID
  59. HalpWritePCIConfigUcharByOffset (
  60. IN PCI_SLOT_NUMBER Slot,
  61. IN PUCHAR Buffer,
  62. IN ULONG Offset
  63. );
  64. // M001 ---
  65. //
  66. // Define global data.
  67. //
  68. ULONG HalpX86BiosInitialized = FALSE;
  69. ULONG HalpEnableInt10Calls = FALSE;
  70. PVOID HalpIoMemoryBase = NULL;
  71. PVOID HalpIoControlBase=NULL;
  72. PUCHAR HalpRomBase = NULL;
  73. ULONG ROM_Length;
  74. #define BUFFER_SIZE (64*1024)
  75. UCHAR ROM_Buffer[BUFFER_SIZE];
  76. //#define R98_PCICONFIG_START ((PULONG)(0x18ca8800 | KSEG1_BASE))
  77. extern KSPIN_LOCK HalpPCIConfigLock;
  78. BOOLEAN HalpInitX86Emulator(
  79. VOID)
  80. {
  81. ULONG ROM_size = 0;
  82. PHYSICAL_ADDRESS PhysAddr;
  83. UCHAR BaseClass, SubClass, ProgIf;// M001
  84. USHORT Cmd,SetCmd, VendorID, DeviceID, Slot; // M002
  85. PUCHAR ROM_Ptr, ROM_Shadow;
  86. ULONG i;
  87. ULONG r;
  88. USHORT PciDataOffset; // M001
  89. PCI_SLOT_NUMBER PciSlot;
  90. UCHAR header;
  91. KIRQL Irql;
  92. PhysAddr.HighPart = 0x00000000;
  93. #if 1
  94. KeInitializeSpinLock (&HalpPCIConfigLock);
  95. //kuku
  96. KeRaiseIrql (PROFILE_LEVEL, &Irql);
  97. KiAcquireSpinLock (&HalpPCIConfigLock);
  98. #if 0 //tmp 707 // M001
  99. // First Check ISA BIOS.Becase PCEB 0-1M Positive Decode So
  100. // I Can See ROM Image.
  101. // Create a mapping to ISA memory space, unless one already exists
  102. //
  103. HalpIoMemoryBase= (PVOID)0x40000000;
  104. ROM_size = 0xD0000; // Map to end of option ROM space
  105. //
  106. // Look for ISA option video ROM signature
  107. //
  108. ROM_Ptr = (PUCHAR) HalpIoMemoryBase + 0xC0000;
  109. HalpRomBase = ROM_Ptr;
  110. if (*ROM_Ptr == 0x55 && *(ROM_Ptr+1) == 0xAA) {
  111. //
  112. // Copy ROM to RAM. PCI Spec says you can't execute from ROM.
  113. // ROM and video RAM sometimes can't co-exist.
  114. //
  115. ROM_Length = *(ROM_Ptr+2) << 9;
  116. if (ROM_Length <= BUFFER_SIZE) {
  117. for (i=0; i<ROM_Length; i++)
  118. ROM_Buffer[i] = *ROM_Ptr++;
  119. }
  120. #if defined(_X86_DBG_)
  121. DbgPrint("\n EISA ROM BIOS Found \n"); //DBGDBG
  122. #endif // _X86_DBG_
  123. HalpRomBase = (PUCHAR) ROM_Buffer;
  124. HalpIoControlBase= (PVOID)0x403f0000;
  125. KiReleaseSpinLock (&HalpPCIConfigLock);
  126. KeLowerIrql (Irql);
  127. return TRUE;
  128. }
  129. #endif
  130. //
  131. // Scan PCI slots for video BIOS ROMs, except 3 PCI "slots" on motherboard
  132. //
  133. // Slot 0: Hurrucane (host bridge)
  134. // Slot 1: Typhoon (Internal-bus bridge)
  135. // Slot 2: PCI-EISA bridge
  136. //
  137. for (Slot = 3; Slot < 6; Slot++) {
  138. #if defined(_X86_DBG_)
  139. DbgPrint("\n PCI SLot Number=%x\n",Slot); //DBGDBG
  140. #endif // _X86_DBG_
  141. //
  142. // Create a mapping to PCI configuration space
  143. //
  144. PciSlot.u.bits.FunctionNumber = 0;
  145. PciSlot.u.bits.DeviceNumber = Slot ;
  146. //
  147. // Read Vendor ID and check if slot is empty
  148. //
  149. HalpReadPCIConfigUshortByOffset(PciSlot,&VendorID,FIELD_OFFSET (PCI_COMMON_CONFIG, VendorID));
  150. #if defined(_X86_DBG_)
  151. DbgPrint("\n Vendor ID=%x\n",VendorID); //DBGDBG
  152. #endif // _X86_DBG_
  153. if (VendorID == 0xFFFF){
  154. continue; // Slot is empty; go to next slot
  155. }
  156. // M002 +++
  157. //
  158. // Read Device ID and check if slot is empty
  159. //
  160. HalpReadPCIConfigUshortByOffset(PciSlot,&DeviceID,FIELD_OFFSET (PCI_COMMON_CONFIG, DeviceID));
  161. //
  162. // Check for GLINT or DEC-GA board.
  163. //
  164. if ( (VendorID == 0x3d3d && DeviceID == 0x0001) ||
  165. (VendorID == 0x1011 && DeviceID == 0x0004) ) {
  166. continue;
  167. }
  168. // M002 ---
  169. // M001 +++
  170. //
  171. // Check Base Class Code
  172. //
  173. HalpReadPCIConfigUcharByOffset(PciSlot,&BaseClass,FIELD_OFFSET (PCI_COMMON_CONFIG, BaseClass));
  174. #if defined(_X86_DBG_)
  175. DbgPrint("\n BaseClass =%x\n",BaseClass); //DBGDBG
  176. #endif // _X86_DBG_
  177. //
  178. // Check Sub Class Code
  179. //
  180. HalpReadPCIConfigUcharByOffset(PciSlot,&SubClass,FIELD_OFFSET (PCI_COMMON_CONFIG, SubClass));
  181. #if defined(_X86_DBG_)
  182. DbgPrint("\n SubClass =%x\n",SubClass); //DBGDBG
  183. #endif // _X86_DBG_
  184. //
  185. // Check Proglamming Interface
  186. //
  187. HalpReadPCIConfigUcharByOffset(PciSlot,&ProgIf,FIELD_OFFSET (PCI_COMMON_CONFIG, ProgIf));
  188. #if defined(_X86_DBG_)
  189. DbgPrint("\n ProgIf =%x\n",ProgIf); //DBGDBG
  190. #endif // _X86_DBG_
  191. //
  192. // check if video card
  193. //
  194. if ( ( (BaseClass == 0) && (SubClass == 1) && (ProgIf == 0) ) || //S003
  195. ( (BaseClass == 3) && (SubClass == 0) && (ProgIf == 0) ) ||
  196. ( (BaseClass == 3) && (SubClass == 1) && (ProgIf == 0) ) ||
  197. ( (BaseClass == 3) && (SubClass == 0x80) && (ProgIf == 0) ) ) {
  198. #if defined(_X86_DBG_)
  199. DbgPrint("\n This is Video card \n");
  200. #endif // _X86_DBG_
  201. } else {
  202. #if defined(_X86_DBG_)
  203. DbgPrint("\n This is not Video card \n");
  204. #endif // _X86_DBG_
  205. continue;
  206. }
  207. // M001 ---
  208. //
  209. // Get size of ROM
  210. //
  211. ROM_size=0xFFFFFFFF;
  212. #if defined(_X86_DBG_)
  213. DbgPrint("ROM size config offset = %x\n",FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
  214. #endif // _X86_DBG_
  215. HalpWritePCIConfigUlongByOffset(PciSlot,&ROM_size,FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
  216. HalpReadPCIConfigUlongByOffset(PciSlot,&ROM_size,FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
  217. #if defined(_X86_DBG_)
  218. DbgPrint("\nROM_Size = %0x\n",ROM_size);
  219. #endif // _X86_DBG_
  220. if ((ROM_size != 0xFFFFFFFF) && (ROM_size != 0)) {
  221. ROM_size = 0xD0000; // Map to end of option ROM space
  222. //
  223. // Set Expansion ROM Base Address & enable ROM
  224. //
  225. PhysAddr.LowPart = 0x000C0000 | PCI_ROMADDRESS_ENABLED;
  226. HalpWritePCIConfigUlongByOffset(PciSlot,&(PhysAddr.LowPart),FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
  227. //
  228. // Enable Memory & I/O spaces in command register
  229. //
  230. HalpReadPCIConfigUshortByOffset(PciSlot,&Cmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command));
  231. #if defined(_X86_DBG_)
  232. DbgPrint("\nREAD CMD=%0x\n",Cmd);
  233. #endif // _X86_DBG_
  234. SetCmd = Cmd|0x3;
  235. HalpWritePCIConfigUshortByOffset(PciSlot,&SetCmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command));
  236. // Map Phys C0000000-C00D0000
  237. // Create a mapping to the PCI memory space
  238. //
  239. PhysAddr.HighPart = 1;
  240. PhysAddr.LowPart=0;
  241. #if 1
  242. HalpIoMemoryBase= (PVOID)0x40000000;
  243. #else
  244. HalpIoMemoryBase = MmMapIoSpace(PhysAddr, ROM_size,FALSE);
  245. if (HalpIoMemoryBase == NULL) {
  246. #if defined(_X86_DBG_)
  247. DbgPrint("\nCan't create mapping to PCI memory space\n");
  248. #endif // _X86_DBG_
  249. KiReleaseSpinLock (&HalpPCIConfigLock);
  250. KeLowerIrql (Irql);
  251. return FALSE;
  252. }
  253. #endif
  254. //
  255. // Look for PCI option video ROM signature
  256. //
  257. HalpRomBase = ROM_Ptr = (PUCHAR) HalpIoMemoryBase + 0xC0000;
  258. #if defined(_X86_DBG_)
  259. DbgPrint("\nHalpRomBase=%x\n",HalpRomBase);
  260. #endif // _X86_DBG_
  261. if (*ROM_Ptr == 0x55 && *(ROM_Ptr+1) == 0xAA) {
  262. //
  263. // Copy ROM to RAM. PCI Spec says you can't execute from ROM.
  264. // Sometimes option ROM and video RAM can't co-exist.
  265. //
  266. ROM_Length = *(ROM_Ptr+2) << 9;
  267. if (ROM_Length <= BUFFER_SIZE) {
  268. for (i=0; i<ROM_Length; i++)
  269. ROM_Buffer[i] = *ROM_Ptr++;
  270. HalpRomBase = (PUCHAR) ROM_Buffer;
  271. #if defined(_X86_DBG_)
  272. DbgPrint("\nROM Short HalpRomBase=%x\n",HalpRomBase);
  273. #endif // _X86_DBG_
  274. }
  275. #if 0 // M002
  276. // M001 +++
  277. //
  278. // check rom code is INTEL BASE
  279. //
  280. PciDataOffset = *(PUSHORT)(0x400c0000 + 0x18);
  281. #if defined(_X86_DBG_)
  282. DbgPrint("PciDataOffset = %x\n",PciDataOffset);
  283. #endif // _X86_DBG_
  284. if ( *(PUCHAR)(0x400c0000 + (ULONG)PciDataOffset + 0x14) == 0 ) {
  285. // DbgPrint("check PCI rom\n");
  286. // DbgBreakPoint();
  287. #if defined(_X86_DBG_)
  288. DbgPrint("\n This is intel base rom \n");
  289. #endif // _X86_DBG_
  290. } else {
  291. #if defined(_X86_DBG_)
  292. DbgPrint("\n This is not intel base rom \n");
  293. #endif // _X86_DBG_
  294. //
  295. // Disable Rom address
  296. //
  297. PhysAddr.LowPart = 0x000C0000;
  298. HalpWritePCIConfigUlongByOffset(PciSlot,&(PhysAddr.LowPart),FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
  299. continue;
  300. }
  301. // M001 ---
  302. #endif // 0 // M002
  303. //
  304. // Io Map.
  305. //
  306. HalpIoControlBase= (PVOID)0x403f0000;
  307. #if 0 // M001---
  308. PhysAddr.LowPart = 0x000C0000;
  309. HalpWritePCIConfigUlongByOffset(PciSlot,&(PhysAddr.LowPart),FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress));
  310. #endif // M001---
  311. #if 0 //706
  312. // Found PCI VIDEO ROM.
  313. // 1.Map ISA Memory Space
  314. // 2.
  315. #if defined(_X86_DBG_)
  316. DbgPrint("\nFound PCI ROM BIOS\n");
  317. #endif // _X86_DBG_
  318. // 0: rom enable so do PCI
  319. // 1: rom disable so do EISA vga
  320. HalpWritePCIConfigUshortByOffset(PciSlot,&Cmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command));
  321. #endif
  322. KiReleaseSpinLock (&HalpPCIConfigLock);
  323. KeLowerIrql (Irql);
  324. return TRUE; // Exit slot scan after finding 1st option ROM
  325. }
  326. // MmUnmapIoSpace ( HalpIoMemoryBase, ROM_size);
  327. // Not Found So Reset!!.
  328. // Delete mapping to PCI memory space
  329. #if 1 //706
  330. // Found PCI VIDEO ROM.
  331. // 1.Map ISA Memory Space
  332. // 2.
  333. #if defined(_X86_DBG_)
  334. DbgPrint("\nFound PCI ROM BIOS\n");
  335. #endif // _X86_DBG_
  336. // 0: rom enable so do PCI
  337. // 1: rom disable so do EISA vga
  338. HalpWritePCIConfigUshortByOffset(PciSlot,&Cmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command));
  339. #endif
  340. } // end of if clause
  341. #if defined(_X86_DBG_)
  342. DbgPrint("\n ROM SIZE invalid\n"); //DBGDBG
  343. #endif // _X86_DBG_
  344. } // end of for loop
  345. #else
  346. // ROM_size = 0xD0000; // Map to end of option ROM space
  347. #endif
  348. KiReleaseSpinLock (&HalpPCIConfigLock);
  349. KeLowerIrql (Irql);
  350. #if 1 //tmp 707 // M001
  351. // No PCI BIOS SO Search ISA BIOS.
  352. // Create a mapping to ISA memory space, unless one already exists
  353. //
  354. HalpIoMemoryBase= (PULONG)0x40000000;
  355. ROM_size = 0xD0000; // Map to end of option ROM space
  356. //
  357. // Look for ISA option video ROM signature
  358. //
  359. ROM_Ptr = (PUCHAR) HalpIoMemoryBase + 0xC0000;
  360. HalpRomBase = ROM_Ptr;
  361. if (*ROM_Ptr == 0x55 && *(ROM_Ptr+1) == 0xAA) {
  362. // DbgPrint("check PCI rom\n");
  363. // DbgBreakPoint();
  364. //
  365. // Copy ROM to RAM. PCI Spec says you can't execute from ROM.
  366. // ROM and video RAM sometimes can't co-exist.
  367. //
  368. ROM_Length = *(ROM_Ptr+2) << 9;
  369. if (ROM_Length <= BUFFER_SIZE) {
  370. for (i=0; i<ROM_Length; i++)
  371. ROM_Buffer[i] = *ROM_Ptr++;
  372. }
  373. #if defined(_X86_DBG_)
  374. DbgPrint("\n EISA ROM BIOS Found \n"); //DBGDBG
  375. #endif // _X86_DBG_
  376. HalpRomBase = (PUCHAR) ROM_Buffer;
  377. HalpIoControlBase= (PVOID)0x403f0000;
  378. return TRUE;
  379. }
  380. #endif
  381. //
  382. // No video option ROM was found. Delete mapping to PCI memory space.
  383. //
  384. #if defined(_X86_DBG_)
  385. DbgPrint("\n 55AA BIOS Not \n"); //DBGDBG
  386. #endif // _X86_DBG_
  387. return FALSE;
  388. }
  389. //--------------------
  390. BOOLEAN
  391. HalCallBios (
  392. IN ULONG BiosCommand,
  393. IN OUT PULONG Eax,
  394. IN OUT PULONG Ebx,
  395. IN OUT PULONG Ecx,
  396. IN OUT PULONG Edx,
  397. IN OUT PULONG Esi,
  398. IN OUT PULONG Edi,
  399. IN OUT PULONG Ebp
  400. )
  401. /*++
  402. Routine Description:
  403. This function provides the platform specific interface between a device
  404. driver and the execution of the x86 ROM bios code for the specified ROM
  405. bios command.
  406. Arguments:
  407. BiosCommand - Supplies the ROM bios command to be emulated.
  408. Eax to Ebp - Supplies the x86 emulation context.
  409. Return Value:
  410. A value of TRUE is returned if the specified function is executed.
  411. Otherwise, a value of FALSE is returned.
  412. --*/
  413. {
  414. #if defined(USE_BIOS_EMULATOR)
  415. XM86_CONTEXT Context;
  416. //
  417. // If the x86 BIOS Emulator has not been initialized, then return FALSE.
  418. //
  419. if (HalpX86BiosInitialized == FALSE) {
  420. return FALSE;
  421. }
  422. //
  423. // If the Video Adapter initialization failed and an Int10 command is
  424. // specified, then return FALSE.
  425. //
  426. if ((BiosCommand == 0x10) && (HalpEnableInt10Calls == FALSE)) {
  427. return FALSE;
  428. }
  429. //
  430. // Copy the x86 bios context and emulate the specified command.
  431. //
  432. Context.Eax = *Eax;
  433. Context.Ebx = *Ebx;
  434. Context.Ecx = *Ecx;
  435. Context.Edx = *Edx;
  436. Context.Esi = *Esi;
  437. Context.Edi = *Edi;
  438. Context.Ebp = *Ebp;
  439. if (x86BiosExecuteInterrupt((UCHAR)BiosCommand,
  440. &Context,
  441. HalpIoControlBase,
  442. HalpIoMemoryBase) != XM_SUCCESS) {
  443. return FALSE;
  444. }
  445. //
  446. // Copy the x86 bios context and return TRUE.
  447. //
  448. *Eax = Context.Eax;
  449. *Ebx = Context.Ebx;
  450. *Ecx = Context.Ecx;
  451. *Edx = Context.Edx;
  452. *Esi = Context.Esi;
  453. *Edi = Context.Edi;
  454. *Ebp = Context.Ebp;
  455. return TRUE;
  456. #else
  457. return FALSE;
  458. #endif
  459. }
  460. BOOLEAN
  461. HalpInitializeX86DisplayAdapter(
  462. VOID
  463. )
  464. /*++
  465. Routine Description:
  466. This function initializes a display adapter using the x86 bios emulator.
  467. Arguments:
  468. None.
  469. Return Value:
  470. None.
  471. --*/
  472. {
  473. #if defined(USE_BIOS_EMULATOR)
  474. //
  475. // If EISA I/O Ports or EISA memory could not be mapped, then don't
  476. // attempt to initialize the display adapter.
  477. //
  478. if (!HalpInitX86Emulator())
  479. return FALSE;
  480. if (HalpIoControlBase == NULL || HalpIoMemoryBase == NULL) {
  481. return FALSE;
  482. }
  483. //
  484. // Initialize the x86 bios emulator.
  485. //
  486. x86BiosInitializeBios(HalpIoControlBase, HalpIoMemoryBase);
  487. HalpX86BiosInitialized = TRUE;
  488. //
  489. // Attempt to initialize the display adapter by executing its ROM bios
  490. // code. The standard ROM bios code address for PC video adapters is
  491. // 0xC000:0000 on the ISA bus.
  492. //
  493. if (x86BiosInitializeAdapter(0xc0000, NULL, HalpIoControlBase, HalpIoMemoryBase) != XM_SUCCESS) {
  494. HalpEnableInt10Calls = FALSE;
  495. return FALSE;
  496. }
  497. HalpEnableInt10Calls = TRUE;
  498. #endif
  499. return TRUE;
  500. }
  501. VOID
  502. HalpResetX86DisplayAdapter(
  503. VOID
  504. )
  505. /*++
  506. Routine Description:
  507. This function resets a display adapter using the x86 bios emulator.
  508. Arguments:
  509. None.
  510. Return Value:
  511. None.
  512. --*/
  513. {
  514. #if defined(USE_BIOS_EMULATOR)
  515. XM86_CONTEXT Context;
  516. //
  517. // Initialize the x86 bios context and make the INT 10 call to initialize
  518. // the display adapter to 80x25 color text mode.
  519. //
  520. Context.Eax = 0x0003; // Function 0, Mode 3
  521. Context.Ebx = 0;
  522. Context.Ecx = 0;
  523. Context.Edx = 0;
  524. Context.Esi = 0;
  525. Context.Edi = 0;
  526. Context.Ebp = 0;
  527. HalCallBios(0x10,
  528. &Context.Eax,
  529. &Context.Ebx,
  530. &Context.Ecx,
  531. &Context.Edx,
  532. &Context.Esi,
  533. &Context.Edi,
  534. &Context.Ebp);
  535. #endif
  536. return;
  537. }
  538. //
  539. // This code came from ..\..\x86new\x86bios.c
  540. //
  541. #define LOW_MEMORY_SIZE 0x800
  542. extern UCHAR x86BiosLowMemory[LOW_MEMORY_SIZE + 3];
  543. extern ULONG x86BiosScratchMemory;
  544. extern ULONG x86BiosIoMemory;
  545. extern ULONG x86BiosIoSpace;
  546. PVOID
  547. x86BiosTranslateAddress (
  548. IN USHORT Segment,
  549. IN USHORT Offset
  550. )
  551. /*++
  552. Routine Description:
  553. This translates a segment/offset address into a memory address.
  554. Arguments:
  555. Segment - Supplies the segment register value.
  556. Offset - Supplies the offset within segment.
  557. Return Value:
  558. The memory address of the translated segment/offset pair is
  559. returned as the function value.
  560. --*/
  561. {
  562. ULONG Value;
  563. //
  564. // Compute the logical memory address and case on high hex digit of
  565. // the resultant address.
  566. //
  567. Value = Offset + (Segment << 4);
  568. Offset = (USHORT)(Value & 0xffff);
  569. Value &= 0xf0000;
  570. switch ((Value >> 16) & 0xf) {
  571. //
  572. // Interrupt vector/stack space.
  573. //
  574. case 0x0:
  575. if (Offset > LOW_MEMORY_SIZE) {
  576. x86BiosScratchMemory = 0;
  577. return (PVOID)&x86BiosScratchMemory;
  578. } else {
  579. return (PVOID)(&x86BiosLowMemory[0] + Offset);
  580. }
  581. //
  582. // The memory range from 0x10000 to 0x9ffff reads as zero
  583. // and writes are ignored.
  584. //
  585. case 0x1:
  586. case 0x2:
  587. case 0x3:
  588. case 0x4:
  589. case 0x5:
  590. case 0x6:
  591. case 0x7:
  592. case 0x8:
  593. case 0x9:
  594. x86BiosScratchMemory = 0;
  595. return (PVOID)&x86BiosScratchMemory;
  596. //
  597. // The memory range from 0xa0000 to 0xdffff maps to I/O memory.
  598. //
  599. case 0xa:
  600. case 0xb:
  601. return (PVOID)(x86BiosIoMemory + Offset + Value);
  602. case 0xc:
  603. case 0xd:
  604. return (PVOID)(HalpRomBase + Offset);
  605. //
  606. // The memory range from 0x10000 to 0x9ffff reads as zero
  607. // and writes are ignored.
  608. //
  609. case 0xe:
  610. case 0xf:
  611. x86BiosScratchMemory = 0;
  612. return (PVOID)&x86BiosScratchMemory;
  613. }
  614. // NOT REACHED - NOT EXECUTED - Prevents Compiler Warning.
  615. return (PVOID)NULL;
  616. }
  617. VOID HalpCopyROMs(VOID)
  618. {
  619. ULONG i;
  620. PUCHAR ROM_Shadow;
  621. if (ROM_Buffer[0] == 0x55 && ROM_Buffer[1] == 0xAA) {
  622. HalpRomBase = ROM_Shadow = ExAllocatePool(NonPagedPool, ROM_Length);
  623. #if defined(_X86_DBG_)
  624. DbgPrint("HalpRomBase=%0x\n",HalpRomBase);
  625. #endif // _X86_DBG_
  626. for (i=0; i<ROM_Length; i++) {
  627. *ROM_Shadow++ = ROM_Buffer[i];
  628. }
  629. }
  630. }
  631. /****Include File x86new\x86bios.c Here - except the routine x86BiosTranslateAddress. ****/
  632. /*++
  633. Copyright (c) 1994 Microsoft Corporation
  634. Module Name:
  635. x86bios.c
  636. Abstract:
  637. This module implements supplies the HAL interface to the 386/486
  638. real mode emulator for the purpose of emulating BIOS calls..
  639. Author:
  640. David N. Cutler (davec) 13-Nov-1994
  641. Environment:
  642. Kernel mode only.
  643. Revision History:
  644. --*/
  645. #include "nthal.h"
  646. #include "hal.h"
  647. #include "xm86.h"
  648. #include "x86new.h"
  649. //
  650. // Define the size of low memory.
  651. //
  652. #define LOW_MEMORY_SIZE 0x800
  653. //
  654. // Define storage for low emulated memory.
  655. //
  656. UCHAR x86BiosLowMemory[LOW_MEMORY_SIZE + 3];
  657. ULONG x86BiosScratchMemory;
  658. //
  659. // Define storage to capture the base address of I/O space and the
  660. // base address of I/O memory space.
  661. //
  662. ULONG x86BiosIoMemory;
  663. ULONG x86BiosIoSpace;
  664. //
  665. // Define BIOS initialized state.
  666. //
  667. BOOLEAN x86BiosInitialized = FALSE;
  668. ULONG
  669. x86BiosReadIoSpace (
  670. IN XM_OPERATION_DATATYPE DataType,
  671. IN USHORT PortNumber
  672. )
  673. /*++
  674. Routine Description:
  675. This function reads from emulated I/O space.
  676. Arguments:
  677. DataType - Supplies the datatype for the read operation.
  678. PortNumber - Supplies the port number in I/O space to read from.
  679. Return Value:
  680. The value read from I/O space is returned as the function value.
  681. N.B. If an aligned operation is specified, then the individual
  682. bytes are read from the specified port one at a time and
  683. assembled into the specified datatype.
  684. --*/
  685. {
  686. ULONG Result;
  687. union {
  688. PUCHAR Byte;
  689. PUSHORT Word;
  690. PULONG Long;
  691. } u;
  692. //
  693. // Compute port address and read port.
  694. //
  695. u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
  696. // DbgPrint("read port %x translate %x\n",PortNumber,u.Long);
  697. if (DataType == BYTE_DATA) {
  698. Result = READ_REGISTER_UCHAR(u.Byte);
  699. } else if (DataType == LONG_DATA) {
  700. if (((ULONG)u.Long & 0x3) != 0) {
  701. Result = (READ_REGISTER_UCHAR(u.Byte + 0)) |
  702. (READ_REGISTER_UCHAR(u.Byte + 1) << 8) |
  703. (READ_REGISTER_UCHAR(u.Byte + 2) << 16) |
  704. (READ_REGISTER_UCHAR(u.Byte + 3) << 24);
  705. } else {
  706. Result = READ_REGISTER_ULONG(u.Long);
  707. }
  708. } else {
  709. if (((ULONG)u.Word & 0x1) != 0) {
  710. Result = (READ_REGISTER_UCHAR(u.Byte + 0)) |
  711. (READ_REGISTER_UCHAR(u.Byte + 1) << 8);
  712. } else {
  713. Result = READ_REGISTER_USHORT(u.Word);
  714. }
  715. }
  716. return Result;
  717. }
  718. VOID
  719. x86BiosWriteIoSpace (
  720. IN XM_OPERATION_DATATYPE DataType,
  721. IN USHORT PortNumber,
  722. IN ULONG Value
  723. )
  724. /*++
  725. Routine Description:
  726. This function write to emulated I/O space.
  727. N.B. If an aligned operation is specified, then the individual
  728. bytes are written to the specified port one at a time.
  729. Arguments:
  730. DataType - Supplies the datatype for the write operation.
  731. PortNumber - Supplies the port number in I/O space to write to.
  732. Value - Supplies the value to write.
  733. Return Value:
  734. None.
  735. --*/
  736. {
  737. union {
  738. PUCHAR Byte;
  739. PUSHORT Word;
  740. PULONG Long;
  741. } u;
  742. //
  743. // Compute port address and read port.
  744. //
  745. u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
  746. // DbgPrint("write port %x translate %x\n",PortNumber,u.Long);
  747. if (DataType == BYTE_DATA) {
  748. WRITE_REGISTER_UCHAR(u.Byte, (UCHAR)Value);
  749. } else if (DataType == LONG_DATA) {
  750. if (((ULONG)u.Long & 0x3) != 0) {
  751. WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value));
  752. WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
  753. WRITE_REGISTER_UCHAR(u.Byte + 2, (UCHAR)(Value >> 16));
  754. WRITE_REGISTER_UCHAR(u.Byte + 3, (UCHAR)(Value >> 24));
  755. } else {
  756. WRITE_REGISTER_ULONG(u.Long, Value);
  757. }
  758. } else {
  759. if (((ULONG)u.Word & 0x1) != 0) {
  760. WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value));
  761. WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
  762. } else {
  763. WRITE_REGISTER_USHORT(u.Word, (USHORT)Value);
  764. }
  765. }
  766. return;
  767. }
  768. VOID
  769. x86BiosInitializeBios (
  770. IN PVOID BiosIoSpace,
  771. IN PVOID BiosIoMemory
  772. )
  773. /*++
  774. Routine Description:
  775. This function initializes x86 BIOS emulation.
  776. Arguments:
  777. BiosIoSpace - Supplies the base address of the I/O space to be used
  778. for BIOS emulation.
  779. BiosIoMemory - Supplies the base address of the I/O memory to be
  780. used for BIOS emulation.
  781. Return Value:
  782. None.
  783. --*/
  784. {
  785. //
  786. // Zero low memory.
  787. //
  788. memset(&x86BiosLowMemory, 0, LOW_MEMORY_SIZE);
  789. //
  790. // Save base address of I/O memory and I/O space.
  791. //
  792. x86BiosIoSpace = (ULONG)BiosIoSpace;
  793. x86BiosIoMemory = (ULONG)BiosIoMemory;
  794. //
  795. // Initialize the emulator and the BIOS.
  796. //
  797. XmInitializeEmulator(0,
  798. LOW_MEMORY_SIZE,
  799. x86BiosReadIoSpace,
  800. x86BiosWriteIoSpace,
  801. x86BiosTranslateAddress);
  802. #if defined(_X86_DBG_)
  803. DbgPrint("\n EMU INIT \n"); //DBGDBG
  804. #endif // _X86_DBG_
  805. x86BiosInitialized = TRUE;
  806. return;
  807. }
  808. XM_STATUS
  809. x86BiosExecuteInterrupt (
  810. IN UCHAR Number,
  811. IN OUT PXM86_CONTEXT Context,
  812. IN PVOID BiosIoSpace OPTIONAL,
  813. IN PVOID BiosIoMemory OPTIONAL
  814. )
  815. /*++
  816. Routine Description:
  817. This function executes an interrupt by calling the x86 emulator.
  818. Arguments:
  819. Number - Supplies the number of the interrupt that is to be emulated.
  820. Context - Supplies a pointer to an x86 context structure.
  821. Return Value:
  822. The emulation completion status.
  823. --*/
  824. {
  825. XM_STATUS Status;
  826. //
  827. // If a new base address is specified, then set the appropriate base.
  828. //
  829. if (BiosIoSpace != NULL) {
  830. x86BiosIoSpace = (ULONG)BiosIoSpace;
  831. }
  832. if (BiosIoMemory != NULL) {
  833. x86BiosIoMemory = (ULONG)BiosIoMemory;
  834. }
  835. //
  836. // Execute the specified interrupt.
  837. //
  838. Status = XmEmulateInterrupt(Number, Context);
  839. if (Status != XM_SUCCESS) {
  840. #if defined(_X86_DBG_)
  841. DbgPrint("HAL: Interrupt emulation failed, status %lx\n", Status);
  842. #endif // _X86_DBG_
  843. }
  844. return Status;
  845. }
  846. XM_STATUS
  847. x86BiosInitializeAdapter (
  848. IN ULONG Adapter,
  849. IN OUT PXM86_CONTEXT Context OPTIONAL,
  850. IN PVOID BiosIoSpace OPTIONAL,
  851. IN PVOID BiosIoMemory OPTIONAL
  852. )
  853. /*++
  854. Routine Description:
  855. This function initializes the adapter whose BIOS starts at the
  856. specified 20-bit address.
  857. Arguments:
  858. Adpater - Supplies the 20-bit address of the BIOS for the adapter
  859. to be initialized.
  860. Return Value:
  861. The emulation completion status.
  862. --*/
  863. {
  864. PUCHAR Byte;
  865. XM86_CONTEXT State;
  866. USHORT Offset;
  867. USHORT Segment;
  868. XM_STATUS Status;
  869. #if defined(_X86_DBG_)
  870. DbgPrint("\n BIOS INIT \n"); //DBGDBG
  871. #endif // _X86_DBG_
  872. //
  873. // If BIOS emulation has not been initialized, then return an error.
  874. //
  875. if (x86BiosInitialized == FALSE) {
  876. return XM_EMULATOR_NOT_INITIALIZED;
  877. }
  878. //
  879. // If an emulator context is not specified, then use a default
  880. // context.
  881. //
  882. if (ARGUMENT_PRESENT(Context) == FALSE) {
  883. State.Eax = 0;
  884. State.Ecx = 0;
  885. State.Edx = 0;
  886. State.Ebx = 0;
  887. State.Ebp = 0;
  888. State.Esi = 0;
  889. State.Edi = 0;
  890. Context = &State;
  891. }
  892. //
  893. // If a new base address is specified, then set the appropriate base.
  894. //
  895. if (BiosIoSpace != NULL) {
  896. x86BiosIoSpace = (ULONG)BiosIoSpace;
  897. }
  898. if (BiosIoMemory != NULL) {
  899. x86BiosIoMemory = (ULONG)BiosIoMemory;
  900. }
  901. //
  902. // If the specified adpater is not BIOS code, then return an error.
  903. //
  904. Segment = (USHORT)((Adapter >> 4) & 0xf000);
  905. Offset = (USHORT)(Adapter & 0xffff);
  906. Byte = (PUCHAR)x86BiosTranslateAddress(Segment, Offset);
  907. if ((*Byte++ != 0x55) || (*Byte != 0xaa)) {
  908. return XM_ILLEGAL_CODE_SEGMENT;
  909. }
  910. //
  911. // Call the BIOS code to initialize the specified adapter.
  912. //
  913. Adapter += 3;
  914. Segment = (USHORT)((Adapter >> 4) & 0xf000);
  915. Offset = (USHORT)(Adapter & 0xffff);
  916. #if defined(_X86_DBG_)
  917. DbgPrint("\n Emcall BIOS start \n"); //DBGDBG
  918. #endif // _X86_DBG_
  919. Status = XmEmulateFarCall(Segment, Offset, Context);
  920. #if defined(_X86_DBG_)
  921. DbgPrint("\n Emcall BIOS End \n"); //DBGDBG
  922. #endif // _X86_DBG_
  923. if (Status != XM_SUCCESS) {
  924. #if defined(_X86_DBG_)
  925. DbgPrint("HAL: Adapter initialization falied, status %lx\n", Status);
  926. #endif // _X86_DBG_
  927. }
  928. return Status;
  929. }