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.

861 lines
23 KiB

  1. /*++
  2. Copyright (c) 1990-2000 Microsoft Corporation
  3. Module Name:
  4. bootvid.c
  5. Abstract:
  6. This is the device independent portion of the graphical boot dll.
  7. Author:
  8. Erick Smith (ericks) Oct. 1997
  9. Environment:
  10. kernel mode only
  11. Revision History:
  12. --*/
  13. #include <nthal.h>
  14. #include <hal.h>
  15. #include "cmdcnst.h"
  16. #include <bootvid.h>
  17. #include "vga.h"
  18. extern USHORT VGA_640x480[];
  19. extern USHORT AT_Initialization[];
  20. extern int curr_x;
  21. extern int curr_y;
  22. PUCHAR VgaBase;
  23. PUCHAR VgaRegisterBase;
  24. NTSTATUS
  25. InitBusCallback(
  26. IN PVOID Context,
  27. IN PUNICODE_STRING PathName,
  28. IN INTERFACE_TYPE BusType,
  29. IN ULONG BusNumber,
  30. IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
  31. IN CONFIGURATION_TYPE ControllerType,
  32. IN ULONG ControllerNumber,
  33. IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
  34. IN CONFIGURATION_TYPE PeripheralType,
  35. IN ULONG PeripheralNumber,
  36. IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
  37. )
  38. {
  39. return STATUS_SUCCESS;
  40. }
  41. BOOLEAN
  42. VidInitialize(
  43. BOOLEAN SetMode
  44. )
  45. /*++
  46. Routine Description:
  47. This routine checks for the existance of a VGA chip, and initializes
  48. it.
  49. Arguments:
  50. SetMode - Set to true if you want this routine to initialize mode.
  51. Return Value:
  52. TRUE - if the boot driver found vga and initialized correctly,
  53. FALSE - otherwise.
  54. --*/
  55. {
  56. PHYSICAL_ADDRESS IoAddress;
  57. PHYSICAL_ADDRESS MemoryAddress;
  58. ULONG AddressSpace;
  59. PHYSICAL_ADDRESS TranslatedAddress;
  60. PUCHAR mappedAddress;
  61. ULONG_PTR TranslateContext;
  62. //
  63. // Saftey check. Allows migration from old HalDisplayString
  64. // support to bootvid, if the HAL didn't supply the routine
  65. //
  66. // HALPDISPATCH->HalFindBusAddressTranslation
  67. //
  68. // this routine cannot succeed.
  69. //
  70. if (!HALPDISPATCH->HalFindBusAddressTranslation) {
  71. return FALSE;
  72. }
  73. //
  74. // Start search with "no previous" context.
  75. //
  76. TranslateContext = 0;
  77. //
  78. // Set up the addresses we need to translate.
  79. //
  80. IoAddress.LowPart = 0x0;
  81. IoAddress.HighPart = 0;
  82. MemoryAddress.LowPart = 0xa0000;
  83. MemoryAddress.HighPart = 0;
  84. //
  85. // While there are more busses to examine try to map the VGA
  86. // registers.
  87. //
  88. while (TRUE) {
  89. AddressSpace = 1; // we are requesting IO space.
  90. if (!HALPDISPATCH->HalFindBusAddressTranslation(
  91. IoAddress,
  92. &AddressSpace,
  93. &TranslatedAddress,
  94. &TranslateContext,
  95. TRUE)) {
  96. //
  97. // Failed to find a bus with the VGA device on it.
  98. //
  99. return FALSE;
  100. }
  101. //
  102. // We were able to translate the address. Now, map the
  103. // translated address.
  104. //
  105. if (AddressSpace & 0x1) {
  106. VgaRegisterBase = (PUCHAR)(DWORD_PTR) TranslatedAddress.QuadPart;
  107. } else {
  108. VgaRegisterBase = (PUCHAR) MmMapIoSpace(TranslatedAddress,
  109. 0x400,
  110. FALSE);
  111. }
  112. //
  113. // Now that we have the VGA I/O ports, check to see if a VGA
  114. // device is present.
  115. //
  116. if (!VgaIsPresent()) {
  117. if (!(AddressSpace & 0x1)) {
  118. MmUnmapIoSpace(VgaRegisterBase, 0x400);
  119. }
  120. //
  121. // Continue on next bus that has this IO address.
  122. //
  123. continue;
  124. }
  125. //
  126. //
  127. // Map the frame buffer.
  128. //
  129. AddressSpace = 0; // we are requesting memory not IO.
  130. //
  131. // Map the video memory so that we can write to the screen after
  132. // setting a mode.
  133. //
  134. // Note: We assume the memory will be on the same bus as the IO.
  135. //
  136. if (HALPDISPATCH->HalFindBusAddressTranslation(
  137. MemoryAddress,
  138. &AddressSpace,
  139. &TranslatedAddress,
  140. &TranslateContext,
  141. FALSE)) {
  142. //
  143. // We were able to translate the address. Now, map the
  144. // translated address.
  145. //
  146. if (AddressSpace & 0x1) {
  147. VgaBase = (PUCHAR)(DWORD_PTR) TranslatedAddress.QuadPart;
  148. } else {
  149. VgaBase = (PUCHAR) MmMapIoSpace(TranslatedAddress,
  150. 0x20000, // 128k
  151. FALSE);
  152. }
  153. //
  154. // Life is good.
  155. //
  156. break;
  157. }
  158. }
  159. //
  160. // Initialize the display
  161. //
  162. if (SetMode) {
  163. curr_x = curr_y = 0;
  164. if (HalResetDisplay()) {
  165. VgaInterpretCmdStream(AT_Initialization);
  166. } else {
  167. VgaInterpretCmdStream(VGA_640x480);
  168. }
  169. }
  170. return TRUE;
  171. }
  172. VOID
  173. VidResetDisplay(
  174. BOOLEAN SetMode
  175. )
  176. {
  177. curr_x = curr_y = 0;
  178. if (SetMode) {
  179. if (!HalResetDisplay()) {
  180. VgaInterpretCmdStream(VGA_640x480);
  181. }
  182. }
  183. VgaInterpretCmdStream(AT_Initialization);
  184. InitializePalette();
  185. VidSolidColorFill(0,0,639,479,0);
  186. }
  187. BOOLEAN
  188. VgaInterpretCmdStream(
  189. PUSHORT pusCmdStream
  190. )
  191. /*++
  192. Routine Description:
  193. Interprets the appropriate command array to set up VGA registers for the
  194. requested mode. Typically used to set the VGA into a particular mode by
  195. programming all of the registers
  196. Arguments:
  197. pusCmdStream - array of commands to be interpreted.
  198. Return Value:
  199. The status of the operation (can only fail on a bad command); TRUE for
  200. success, FALSE for failure.
  201. --*/
  202. {
  203. ULONG ulCmd;
  204. ULONG_PTR ulPort;
  205. UCHAR jValue;
  206. USHORT usValue;
  207. ULONG culCount;
  208. ULONG ulIndex;
  209. ULONG_PTR ulBase;
  210. if (pusCmdStream == NULL) {
  211. //KdPrint(("VgaInterpretCmdStream: pusCmdStream == NULL\n"));
  212. return TRUE;
  213. }
  214. ulBase = (ULONG_PTR) VgaRegisterBase;
  215. //
  216. // Now set the adapter to the desired mode.
  217. //
  218. while ((ulCmd = *pusCmdStream++) != EOD) {
  219. //
  220. // Determine major command type
  221. //
  222. switch (ulCmd & 0xF0) {
  223. //
  224. // Basic input/output command
  225. //
  226. case INOUT:
  227. //
  228. // Determine type of inout instruction
  229. //
  230. if (!(ulCmd & IO)) {
  231. //
  232. // Out instruction. Single or multiple outs?
  233. //
  234. if (!(ulCmd & MULTI)) {
  235. //
  236. // Single out. Byte or word out?
  237. //
  238. if (!(ulCmd & BW)) {
  239. //
  240. // Single byte out
  241. //
  242. ulPort = *pusCmdStream++;
  243. jValue = (UCHAR) *pusCmdStream++;
  244. WRITE_PORT_UCHAR((PUCHAR)(ulBase+ulPort),
  245. jValue);
  246. } else {
  247. //
  248. // Single word out
  249. //
  250. ulPort = *pusCmdStream++;
  251. usValue = *pusCmdStream++;
  252. WRITE_PORT_USHORT((PUSHORT)(ulBase+ulPort),
  253. usValue);
  254. }
  255. } else {
  256. //
  257. // Output a string of values
  258. // Byte or word outs?
  259. //
  260. if (!(ulCmd & BW)) {
  261. //
  262. // String byte outs. Do in a loop; can't use
  263. // VideoPortWritePortBufferUchar because the data
  264. // is in USHORT form
  265. //
  266. ulPort = ulBase + *pusCmdStream++;
  267. culCount = *pusCmdStream++;
  268. while (culCount--) {
  269. jValue = (UCHAR) *pusCmdStream++;
  270. WRITE_PORT_UCHAR((PUCHAR)ulPort,
  271. jValue);
  272. }
  273. } else {
  274. //
  275. // String word outs
  276. //
  277. ulPort = *pusCmdStream++;
  278. culCount = *pusCmdStream++;
  279. WRITE_PORT_BUFFER_USHORT((PUSHORT)
  280. (ulBase + ulPort), pusCmdStream, culCount);
  281. pusCmdStream += culCount;
  282. }
  283. }
  284. } else {
  285. // In instruction
  286. //
  287. // Currently, string in instructions aren't supported; all
  288. // in instructions are handled as single-byte ins
  289. //
  290. // Byte or word in?
  291. //
  292. if (!(ulCmd & BW)) {
  293. //
  294. // Single byte in
  295. //
  296. ulPort = *pusCmdStream++;
  297. jValue = READ_PORT_UCHAR((PUCHAR)ulBase+ulPort);
  298. } else {
  299. //
  300. // Single word in
  301. //
  302. ulPort = *pusCmdStream++;
  303. usValue = READ_PORT_USHORT((PUSHORT)
  304. (ulBase+ulPort));
  305. }
  306. }
  307. break;
  308. //
  309. // Higher-level input/output commands
  310. //
  311. case METAOUT:
  312. //
  313. // Determine type of metaout command, based on minor
  314. // command field
  315. //
  316. switch (ulCmd & 0x0F) {
  317. //
  318. // Indexed outs
  319. //
  320. case INDXOUT:
  321. ulPort = ulBase + *pusCmdStream++;
  322. culCount = *pusCmdStream++;
  323. ulIndex = *pusCmdStream++;
  324. while (culCount--) {
  325. usValue = (USHORT) (ulIndex +
  326. (((ULONG)(*pusCmdStream++)) << 8));
  327. WRITE_PORT_USHORT((PUSHORT)ulPort, usValue);
  328. ulIndex++;
  329. }
  330. break;
  331. //
  332. // Masked out (read, AND, XOR, write)
  333. //
  334. case MASKOUT:
  335. ulPort = *pusCmdStream++;
  336. jValue = READ_PORT_UCHAR((PUCHAR)ulBase+ulPort);
  337. jValue &= *pusCmdStream++;
  338. jValue ^= *pusCmdStream++;
  339. WRITE_PORT_UCHAR((PUCHAR)ulBase + ulPort,
  340. jValue);
  341. break;
  342. //
  343. // Attribute Controller out
  344. //
  345. case ATCOUT:
  346. ulPort = ulBase + *pusCmdStream++;
  347. culCount = *pusCmdStream++;
  348. ulIndex = *pusCmdStream++;
  349. while (culCount--) {
  350. // Write Attribute Controller index
  351. WRITE_PORT_UCHAR((PUCHAR)ulPort,
  352. (UCHAR)ulIndex);
  353. // Write Attribute Controller data
  354. jValue = (UCHAR) *pusCmdStream++;
  355. WRITE_PORT_UCHAR((PUCHAR)ulPort, jValue);
  356. ulIndex++;
  357. }
  358. break;
  359. //
  360. // None of the above; error
  361. //
  362. default:
  363. return FALSE;
  364. }
  365. break;
  366. //
  367. // NOP
  368. //
  369. case NCMD:
  370. break;
  371. //
  372. // Unknown command; error
  373. //
  374. default:
  375. return FALSE;
  376. }
  377. }
  378. return TRUE;
  379. } // end VgaInterpretCmdStream()
  380. BOOLEAN
  381. VgaIsPresent(
  382. VOID
  383. )
  384. /*++
  385. Routine Description:
  386. This routine returns TRUE if a VGA is present. Determining whether a VGA
  387. is present is a two-step process. First, this routine walks bits through
  388. the Bit Mask register, to establish that there are readable indexed
  389. registers (EGAs normally don't have readable registers, and other adapters
  390. are unlikely to have indexed registers). This test is done first because
  391. it's a non-destructive EGA rejection test (correctly rejects EGAs, but
  392. doesn't potentially mess up the screen or the accessibility of display
  393. memory). Normally, this would be an adequate test, but some EGAs have
  394. readable registers, so next, we check for the existence of the Chain4 bit
  395. in the Memory Mode register; this bit doesn't exist in EGAs. It's
  396. conceivable that there are EGAs with readable registers and a register bit
  397. where Chain4 is stored, although I don't know of any; if a better test yet
  398. is needed, memory could be written to in Chain4 mode, and then examined
  399. plane by plane in non-Chain4 mode to make sure the Chain4 bit did what it's
  400. supposed to do. However, the current test should be adequate to eliminate
  401. just about all EGAs, and 100% of everything else.
  402. If this function fails to find a VGA, it attempts to undo any damage it
  403. may have inadvertently done while testing. The underlying assumption for
  404. the damage control is that if there's any non-VGA adapter at the tested
  405. ports, it's an EGA or an enhanced EGA, because: a) I don't know of any
  406. other adapters that use 3C4/5 or 3CE/F, and b), if there are other
  407. adapters, I certainly don't know how to restore their original states. So
  408. all error recovery is oriented toward putting an EGA back in a writable
  409. state, so that error messages are visible. The EGA's state on entry is
  410. assumed to be text mode, so the Memory Mode register is restored to the
  411. default state for text mode.
  412. If a VGA is found, the VGA is returned to its original state after
  413. testing is finished.
  414. Arguments:
  415. None.
  416. Return Value:
  417. TRUE if a VGA is present, FALSE if not.
  418. --*/
  419. {
  420. UCHAR originalGCAddr;
  421. UCHAR originalSCAddr;
  422. UCHAR originalBitMask;
  423. UCHAR originalReadMap;
  424. UCHAR originalMemoryMode;
  425. UCHAR testMask;
  426. BOOLEAN returnStatus;
  427. //
  428. // Remember the original state of the Graphics Controller Address register.
  429. //
  430. originalGCAddr = READ_PORT_UCHAR(VgaRegisterBase +
  431. GRAPH_ADDRESS_PORT);
  432. //
  433. // Write the Read Map register with a known state so we can verify
  434. // that it isn't changed after we fool with the Bit Mask. This ensures
  435. // that we're dealing with indexed registers, since both the Read Map and
  436. // the Bit Mask are addressed at GRAPH_DATA_PORT.
  437. //
  438. WRITE_PORT_UCHAR(VgaRegisterBase +
  439. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  440. //
  441. // If we can't read back the Graphics Address register setting we just
  442. // performed, it's not readable and this isn't a VGA.
  443. //
  444. if ((READ_PORT_UCHAR(VgaRegisterBase +
  445. GRAPH_ADDRESS_PORT) & GRAPH_ADDR_MASK) != IND_READ_MAP) {
  446. return FALSE;
  447. }
  448. //
  449. // Set the Read Map register to a known state.
  450. //
  451. originalReadMap = READ_PORT_UCHAR(VgaRegisterBase +
  452. GRAPH_DATA_PORT);
  453. WRITE_PORT_UCHAR(VgaRegisterBase +
  454. GRAPH_DATA_PORT, READ_MAP_TEST_SETTING);
  455. if (READ_PORT_UCHAR(VgaRegisterBase +
  456. GRAPH_DATA_PORT) != READ_MAP_TEST_SETTING) {
  457. //
  458. // The Read Map setting we just performed can't be read back; not a
  459. // VGA. Restore the default Read Map state.
  460. //
  461. WRITE_PORT_UCHAR(VgaRegisterBase +
  462. GRAPH_DATA_PORT, READ_MAP_DEFAULT);
  463. return FALSE;
  464. }
  465. //
  466. // Remember the original setting of the Bit Mask register.
  467. //
  468. WRITE_PORT_UCHAR(VgaRegisterBase +
  469. GRAPH_ADDRESS_PORT, IND_BIT_MASK);
  470. if ((READ_PORT_UCHAR(VgaRegisterBase +
  471. GRAPH_ADDRESS_PORT) & GRAPH_ADDR_MASK) != IND_BIT_MASK) {
  472. //
  473. // The Graphics Address register setting we just made can't be read
  474. // back; not a VGA. Restore the default Read Map state.
  475. //
  476. WRITE_PORT_UCHAR(VgaRegisterBase +
  477. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  478. WRITE_PORT_UCHAR(VgaRegisterBase +
  479. GRAPH_DATA_PORT, READ_MAP_DEFAULT);
  480. return FALSE;
  481. }
  482. originalBitMask = READ_PORT_UCHAR(VgaRegisterBase +
  483. GRAPH_DATA_PORT);
  484. //
  485. // Set up the initial test mask we'll write to and read from the Bit Mask.
  486. //
  487. testMask = 0xBB;
  488. do {
  489. //
  490. // Write the test mask to the Bit Mask.
  491. //
  492. WRITE_PORT_UCHAR(VgaRegisterBase +
  493. GRAPH_DATA_PORT, testMask);
  494. //
  495. // Make sure the Bit Mask remembered the value.
  496. //
  497. if (READ_PORT_UCHAR(VgaRegisterBase +
  498. GRAPH_DATA_PORT) != testMask) {
  499. //
  500. // The Bit Mask is not properly writable and readable; not a VGA.
  501. // Restore the Bit Mask and Read Map to their default states.
  502. //
  503. WRITE_PORT_UCHAR(VgaRegisterBase +
  504. GRAPH_DATA_PORT, BIT_MASK_DEFAULT);
  505. WRITE_PORT_UCHAR(VgaRegisterBase +
  506. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  507. WRITE_PORT_UCHAR(VgaRegisterBase +
  508. GRAPH_DATA_PORT, READ_MAP_DEFAULT);
  509. return FALSE;
  510. }
  511. //
  512. // Cycle the mask for next time.
  513. //
  514. testMask >>= 1;
  515. } while (testMask != 0);
  516. //
  517. // There's something readable at GRAPH_DATA_PORT; now switch back and
  518. // make sure that the Read Map register hasn't changed, to verify that
  519. // we're dealing with indexed registers.
  520. //
  521. WRITE_PORT_UCHAR(VgaRegisterBase +
  522. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  523. if (READ_PORT_UCHAR(VgaRegisterBase +
  524. GRAPH_DATA_PORT) != READ_MAP_TEST_SETTING) {
  525. //
  526. // The Read Map is not properly writable and readable; not a VGA.
  527. // Restore the Bit Mask and Read Map to their default states, in case
  528. // this is an EGA, so subsequent writes to the screen aren't garbled.
  529. //
  530. WRITE_PORT_UCHAR(VgaRegisterBase +
  531. GRAPH_DATA_PORT, READ_MAP_DEFAULT);
  532. WRITE_PORT_UCHAR(VgaRegisterBase +
  533. GRAPH_ADDRESS_PORT, IND_BIT_MASK);
  534. WRITE_PORT_UCHAR(VgaRegisterBase +
  535. GRAPH_DATA_PORT, BIT_MASK_DEFAULT);
  536. return FALSE;
  537. }
  538. //
  539. // We've pretty surely verified the existence of the Bit Mask register.
  540. // Put the Graphics Controller back to the original state.
  541. //
  542. WRITE_PORT_UCHAR(VgaRegisterBase +
  543. GRAPH_DATA_PORT, originalReadMap);
  544. WRITE_PORT_UCHAR(VgaRegisterBase +
  545. GRAPH_ADDRESS_PORT, IND_BIT_MASK);
  546. WRITE_PORT_UCHAR(VgaRegisterBase +
  547. GRAPH_DATA_PORT, originalBitMask);
  548. WRITE_PORT_UCHAR(VgaRegisterBase +
  549. GRAPH_ADDRESS_PORT, originalGCAddr);
  550. //
  551. // Now, check for the existence of the Chain4 bit.
  552. //
  553. //
  554. // Remember the original states of the Sequencer Address and Memory Mode
  555. // registers.
  556. //
  557. originalSCAddr = READ_PORT_UCHAR(VgaRegisterBase +
  558. SEQ_ADDRESS_PORT);
  559. WRITE_PORT_UCHAR(VgaRegisterBase +
  560. SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
  561. if ((READ_PORT_UCHAR(VgaRegisterBase +
  562. SEQ_ADDRESS_PORT) & SEQ_ADDR_MASK) != IND_MEMORY_MODE) {
  563. //
  564. // Couldn't read back the Sequencer Address register setting we just
  565. // performed.
  566. //
  567. return FALSE;
  568. }
  569. originalMemoryMode = READ_PORT_UCHAR(VgaRegisterBase +
  570. SEQ_DATA_PORT);
  571. //
  572. // Toggle the Chain4 bit and read back the result. This must be done during
  573. // sync reset, since we're changing the chaining state.
  574. //
  575. //
  576. // Begin sync reset.
  577. //
  578. WRITE_PORT_USHORT((PUSHORT)(VgaRegisterBase +
  579. SEQ_ADDRESS_PORT),
  580. (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
  581. //
  582. // Toggle the Chain4 bit.
  583. //
  584. WRITE_PORT_UCHAR(VgaRegisterBase +
  585. SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
  586. WRITE_PORT_UCHAR(VgaRegisterBase +
  587. SEQ_DATA_PORT, (UCHAR)(originalMemoryMode ^ CHAIN4_MASK));
  588. if (READ_PORT_UCHAR(VgaRegisterBase +
  589. SEQ_DATA_PORT) != (UCHAR) (originalMemoryMode ^ CHAIN4_MASK)) {
  590. //
  591. // Chain4 bit not there; not a VGA.
  592. // Set text mode default for Memory Mode register.
  593. //
  594. WRITE_PORT_UCHAR(VgaRegisterBase +
  595. SEQ_DATA_PORT, MEMORY_MODE_TEXT_DEFAULT);
  596. //
  597. // End sync reset.
  598. //
  599. WRITE_PORT_USHORT((PUSHORT) (VgaRegisterBase +
  600. SEQ_ADDRESS_PORT),
  601. (IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
  602. returnStatus = FALSE;
  603. } else {
  604. //
  605. // It's a VGA.
  606. //
  607. //
  608. // Restore the original Memory Mode setting.
  609. //
  610. WRITE_PORT_UCHAR(VgaRegisterBase +
  611. SEQ_DATA_PORT, originalMemoryMode);
  612. //
  613. // End sync reset.
  614. //
  615. WRITE_PORT_USHORT((PUSHORT)(VgaRegisterBase +
  616. SEQ_ADDRESS_PORT),
  617. (USHORT)(IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
  618. //
  619. // Restore the original Sequencer Address setting.
  620. //
  621. WRITE_PORT_UCHAR(VgaRegisterBase +
  622. SEQ_ADDRESS_PORT, originalSCAddr);
  623. returnStatus = TRUE;
  624. }
  625. return returnStatus;
  626. } // VgaIsPresent()