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.

1908 lines
48 KiB

  1. /*++
  2. Copyright (c) 1992-1996 Microsoft Corporation
  3. Module Name:
  4. modeset.c
  5. Abstract:
  6. This is the modeset code for the WD VGA miniport driver.
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. Revision History:
  11. --*/
  12. #include "dderror.h"
  13. #include "devioctl.h"
  14. #include "miniport.h"
  15. #include "ntddvdeo.h"
  16. #include "video.h"
  17. #include "wdvga.h"
  18. #include "cmdcnst.h"
  19. #include "pvgaequ.h"
  20. VP_STATUS
  21. VgaInterpretCmdStream(
  22. PHW_DEVICE_EXTENSION HwDeviceExtension,
  23. PUSHORT pusCmdStream
  24. );
  25. VP_STATUS
  26. VgaSetMode(
  27. PHW_DEVICE_EXTENSION HwDeviceExtension,
  28. PVIDEO_MODE Mode,
  29. ULONG ModeSize
  30. );
  31. VP_STATUS
  32. VgaQueryAvailableModes(
  33. PHW_DEVICE_EXTENSION HwDeviceExtension,
  34. PVIDEO_MODE_INFORMATION ModeInformation,
  35. ULONG ModeInformationSize,
  36. PULONG OutputSize
  37. );
  38. VP_STATUS
  39. VgaQueryNumberOfAvailableModes(
  40. PHW_DEVICE_EXTENSION HwDeviceExtension,
  41. PVIDEO_NUM_MODES NumModes,
  42. ULONG NumModesSize,
  43. PULONG OutputSize
  44. );
  45. VP_STATUS
  46. VgaQueryCurrentMode(
  47. PHW_DEVICE_EXTENSION HwDeviceExtension,
  48. PVIDEO_MODE_INFORMATION ModeInformation,
  49. ULONG ModeInformationSize,
  50. PULONG OutputSize
  51. );
  52. VOID
  53. VgaZeroVideoMemory(
  54. PHW_DEVICE_EXTENSION HwDeviceExtension
  55. );
  56. VOID
  57. VgaValidateModes(
  58. PHW_DEVICE_EXTENSION HwDeviceExtension
  59. );
  60. VP_STATUS
  61. VgaSetActiveDisplay(
  62. PHW_DEVICE_EXTENSION HwDeviceExtension,
  63. ULONG ActiveDisplay
  64. );
  65. //
  66. // Private functions
  67. //
  68. VOID
  69. DisableLCD(
  70. PHW_DEVICE_EXTENSION HwDeviceExtension
  71. );
  72. VOID
  73. EnableLCD(
  74. PHW_DEVICE_EXTENSION HwDeviceExtension
  75. );
  76. VOID
  77. DisableCRT(
  78. PHW_DEVICE_EXTENSION HwDeviceExtension
  79. );
  80. VOID
  81. EnableCRT(
  82. PHW_DEVICE_EXTENSION HwDeviceExtension
  83. );
  84. VOID
  85. UnlockAll(
  86. PHW_DEVICE_EXTENSION HwDeviceExtension
  87. );
  88. #if defined(ALLOC_PRAGMA)
  89. #pragma alloc_text(PAGE,VgaSetMode)
  90. #pragma alloc_text(PAGE,VgaQueryAvailableModes)
  91. #pragma alloc_text(PAGE,VgaQueryNumberOfAvailableModes)
  92. #pragma alloc_text(PAGE,VgaQueryCurrentMode)
  93. #pragma alloc_text(PAGE,VgaZeroVideoMemory)
  94. #pragma alloc_text(PAGE,VgaValidateModes)
  95. //
  96. // This routine is NOT pagable because it is called a high IRQL
  97. //
  98. //#pragma alloc_text(PAGE,ExternalMonitorPresent)
  99. //
  100. // This routine is NOT pagable because it is called during WdResetHw,
  101. // which can be called when paging is disabled.
  102. //
  103. //#pragma alloc_text(PAGE,VgaInterpretCmdStream)
  104. #endif
  105. VP_STATUS
  106. VgaInterpretCmdStream(
  107. PHW_DEVICE_EXTENSION HwDeviceExtension,
  108. PUSHORT pusCmdStream
  109. )
  110. /*++
  111. Routine Description:
  112. Interprets the appropriate command array to set up VGA registers for the
  113. requested mode. Typically used to set the VGA into a particular mode by
  114. programming all of the registers
  115. Arguments:
  116. HwDeviceExtension - Pointer to the miniport driver's device extension.
  117. pusCmdStream - array of commands to be interpreted.
  118. Return Value:
  119. The status of the operation (can only fail on a bad command); TRUE for
  120. success, FALSE for failure.
  121. --*/
  122. {
  123. ULONG ulCmd;
  124. ULONG ulPort;
  125. UCHAR jValue;
  126. USHORT usValue;
  127. ULONG culCount;
  128. ULONG ulIndex;
  129. ULONG ulBase;
  130. if (pusCmdStream == NULL) {
  131. VideoDebugPrint((1, "VgaInterpretCmdStream - Invalid pusCmdStream\n"));
  132. return TRUE;
  133. }
  134. ulBase = (ULONG)HwDeviceExtension->IOAddress;
  135. //
  136. // Now set the adapter to the desired mode.
  137. //
  138. while ((ulCmd = *pusCmdStream++) != EOD) {
  139. //
  140. // Determine major command type
  141. //
  142. switch (ulCmd & 0xF0) {
  143. //
  144. // Basic input/output command
  145. //
  146. case INOUT:
  147. //
  148. // Determine type of inout instruction
  149. //
  150. if (!(ulCmd & IO)) {
  151. //
  152. // Out instruction. Single or multiple outs?
  153. //
  154. if (!(ulCmd & MULTI)) {
  155. //
  156. // Single out. Byte or word out?
  157. //
  158. if (!(ulCmd & BW)) {
  159. //
  160. // Single byte out
  161. //
  162. ulPort = *pusCmdStream++;
  163. jValue = (UCHAR) *pusCmdStream++;
  164. VideoPortWritePortUchar((PUCHAR)(ulBase+ulPort),
  165. jValue);
  166. } else {
  167. //
  168. // Single word out
  169. //
  170. ulPort = *pusCmdStream++;
  171. usValue = *pusCmdStream++;
  172. VideoPortWritePortUshort((PUSHORT)(ulBase+ulPort),
  173. usValue);
  174. }
  175. } else {
  176. //
  177. // Output a string of values
  178. // Byte or word outs?
  179. //
  180. if (!(ulCmd & BW)) {
  181. //
  182. // String byte outs. Do in a loop; can't use
  183. // VideoPortWritePortBufferUchar because the data
  184. // is in USHORT form
  185. //
  186. ulPort = ulBase + *pusCmdStream++;
  187. culCount = *pusCmdStream++;
  188. while (culCount--) {
  189. jValue = (UCHAR) *pusCmdStream++;
  190. VideoPortWritePortUchar((PUCHAR)ulPort,
  191. jValue);
  192. }
  193. } else {
  194. //
  195. // String word outs
  196. //
  197. ulPort = *pusCmdStream++;
  198. culCount = *pusCmdStream++;
  199. VideoPortWritePortBufferUshort((PUSHORT)
  200. (ulBase + ulPort), pusCmdStream, culCount);
  201. pusCmdStream += culCount;
  202. }
  203. }
  204. } else {
  205. // In instruction
  206. //
  207. // Currently, string in instructions aren't supported; all
  208. // in instructions are handled as single-byte ins
  209. //
  210. // Byte or word in?
  211. //
  212. if (!(ulCmd & BW)) {
  213. //
  214. // Single byte in
  215. //
  216. ulPort = *pusCmdStream++;
  217. jValue = VideoPortReadPortUchar((PUCHAR)ulBase+ulPort);
  218. } else {
  219. //
  220. // Single word in
  221. //
  222. ulPort = *pusCmdStream++;
  223. usValue = VideoPortReadPortUshort((PUSHORT)
  224. (ulBase+ulPort));
  225. }
  226. }
  227. break;
  228. //
  229. // Higher-level input/output commands
  230. //
  231. case METAOUT:
  232. //
  233. // Determine type of metaout command, based on minor
  234. // command field
  235. //
  236. switch (ulCmd & 0x0F) {
  237. //
  238. // Indexed outs
  239. //
  240. case INDXOUT:
  241. ulPort = ulBase + *pusCmdStream++;
  242. culCount = *pusCmdStream++;
  243. ulIndex = *pusCmdStream++;
  244. while (culCount--) {
  245. usValue = (USHORT) (ulIndex +
  246. (((ULONG)(*pusCmdStream++)) << 8));
  247. VideoPortWritePortUshort((PUSHORT)ulPort, usValue);
  248. ulIndex++;
  249. }
  250. break;
  251. //
  252. // Masked out (read, AND, XOR, write)
  253. //
  254. case MASKOUT:
  255. ulPort = *pusCmdStream++;
  256. jValue = VideoPortReadPortUchar((PUCHAR)ulBase+ulPort);
  257. jValue &= *pusCmdStream++;
  258. jValue ^= *pusCmdStream++;
  259. VideoPortWritePortUchar((PUCHAR)ulBase + ulPort,
  260. jValue);
  261. break;
  262. //
  263. // Attribute Controller out
  264. //
  265. case ATCOUT:
  266. ulPort = ulBase + *pusCmdStream++;
  267. culCount = *pusCmdStream++;
  268. ulIndex = *pusCmdStream++;
  269. while (culCount--) {
  270. // Write Attribute Controller index
  271. VideoPortWritePortUchar((PUCHAR)ulPort,
  272. (UCHAR)ulIndex);
  273. // Write Attribute Controller data
  274. jValue = (UCHAR) *pusCmdStream++;
  275. VideoPortWritePortUchar((PUCHAR)ulPort, jValue);
  276. ulIndex++;
  277. }
  278. break;
  279. //
  280. // None of the above; error
  281. //
  282. default:
  283. return FALSE;
  284. }
  285. break;
  286. //
  287. // NOP
  288. //
  289. case NCMD:
  290. break;
  291. //
  292. // Unknown command; error
  293. //
  294. default:
  295. return FALSE;
  296. }
  297. }
  298. return TRUE;
  299. } // end VgaInterpretCmdStream()
  300. VP_STATUS
  301. VgaSetMode(
  302. PHW_DEVICE_EXTENSION HwDeviceExtension,
  303. PVIDEO_MODE Mode,
  304. ULONG ModeSize
  305. )
  306. /*++
  307. Routine Description:
  308. This routine sets the VGA into the requested mode.
  309. Arguments:
  310. HwDeviceExtension - Pointer to the miniport driver's device extension.
  311. Mode - Pointer to the structure containing the information about the
  312. font to be set.
  313. ModeSize - Length of the input buffer supplied by the user.
  314. Return Value:
  315. ERROR_INSUFFICIENT_BUFFER if the input buffer was not large enough
  316. for the input data.
  317. ERROR_INVALID_PARAMETER if the mode number is invalid.
  318. NO_ERROR if the operation completed successfully.
  319. --*/
  320. {
  321. PVIDEOMODE pRequestedMode;
  322. VP_STATUS status;
  323. UCHAR temp;
  324. UCHAR dummy;
  325. UCHAR bIsColor;
  326. VIDEO_X86_BIOS_ARGUMENTS biosArguments;
  327. UCHAR frequencySetting;
  328. PUCHAR CrtAddressPort, CrtDataPort;
  329. UCHAR bModeFirst = 1;
  330. BOOLEAN bMonitorPresent;
  331. //
  332. // Check if the size of the data in the input buffer is large enough.
  333. //
  334. if (ModeSize < sizeof(VIDEO_MODE)) {
  335. VideoDebugPrint((1, "VgaSetMode: ERROR_INSUFFICIENT_BUFFER\n"));
  336. return ERROR_INSUFFICIENT_BUFFER;
  337. }
  338. //
  339. // Extract the clear memory bit.
  340. //
  341. if (Mode->RequestedMode & VIDEO_MODE_NO_ZERO_MEMORY) {
  342. Mode->RequestedMode &= ~VIDEO_MODE_NO_ZERO_MEMORY;
  343. } else {
  344. VgaZeroVideoMemory(HwDeviceExtension);
  345. }
  346. //
  347. // Check to see if we are requesting a valid mode
  348. //
  349. if ( (Mode->RequestedMode >= NumVideoModes) ||
  350. (!ModesVGA[Mode->RequestedMode].ValidMode) ) {
  351. VideoDebugPrint((1, "VgaSetMode: ERROR_INVALID_PARAMETER\n"));
  352. return ERROR_INVALID_PARAMETER;
  353. }
  354. pRequestedMode = &ModesVGA[Mode->RequestedMode];
  355. #ifdef INT10_MODE_SET
  356. //
  357. // Make sure we unlock extended registers since the BIOS on some machines
  358. // does not do it properly.
  359. //
  360. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  361. GRAPH_ADDRESS_PORT), 0x050F);
  362. //
  363. // Initialize CrtAddressPort, and CrtDataPort
  364. //
  365. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  366. MISC_OUTPUT_REG_READ_PORT) & 0x01) {
  367. bIsColor = TRUE;
  368. CrtAddressPort = HwDeviceExtension->IOAddress + CRTC_ADDRESS_PORT_COLOR;
  369. CrtDataPort = HwDeviceExtension->IOAddress + CRTC_DATA_PORT_COLOR;
  370. } else {
  371. bIsColor = FALSE;
  372. CrtAddressPort = HwDeviceExtension->IOAddress + CRTC_ADDRESS_PORT_MONO;
  373. CrtDataPort = HwDeviceExtension->IOAddress + CRTC_DATA_PORT_MONO;
  374. }
  375. //
  376. // Make sure we unlock extended registers since the BIOS on some machines
  377. // does not do it properly.
  378. //
  379. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  380. GRAPH_ADDRESS_PORT, 0x0F);
  381. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  382. GRAPH_DATA_PORT, 0x05);
  383. VideoPortWritePortUchar(CrtAddressPort, 0x2b);
  384. temp = VideoPortReadPortUchar(CrtDataPort);
  385. //
  386. // Adjust the frequency setting register and write it back out.
  387. // Also support Diamond changes to frequency settings
  388. //
  389. temp &= pRequestedMode->FrequencyMask;
  390. frequencySetting = pRequestedMode->FrequencySetting;
  391. if ( (HwDeviceExtension->BoardID == SPEEDSTAR31) &&
  392. (pRequestedMode->hres == 1024) ) {
  393. //
  394. // Diamond has inversed the refresh rates of interlaced and 72 Hz
  395. // on the 1024 modes
  396. //
  397. if (pRequestedMode->Frequency == 72) {
  398. frequencySetting = 0x00;
  399. } else {
  400. if (pRequestedMode->Frequency == 44) {
  401. frequencySetting = 0x30;
  402. }
  403. }
  404. }
  405. temp |= frequencySetting;
  406. VideoPortWritePortUchar(CrtDataPort, temp);
  407. //
  408. // Mode set block that can be repeated.
  409. //
  410. SetAgain:
  411. //
  412. // Set the mode
  413. //
  414. VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  415. if (HwDeviceExtension->IsIBM &&
  416. (pRequestedMode->Int10ModeNumber & 0xffff0000))
  417. {
  418. biosArguments.Eax = 0x4f02;
  419. biosArguments.Ebx = pRequestedMode->Int10ModeNumber >> 16;
  420. }
  421. else
  422. {
  423. biosArguments.Eax = pRequestedMode->Int10ModeNumber & 0xff;
  424. }
  425. status = VideoPortInt10(HwDeviceExtension, &biosArguments);
  426. if (status != NO_ERROR) {
  427. return status;
  428. }
  429. //
  430. // Check to see if the modeset worked. If not, then if we
  431. // don't have an SVGA Bios, and do have a modetable, then
  432. // set the mode. Else, fail.
  433. //
  434. if (HwDeviceExtension->BoardID == WD90C24A)
  435. {
  436. biosArguments.Eax = 0x0f00;
  437. VideoPortInt10(HwDeviceExtension, &biosArguments);
  438. if ((biosArguments.Eax & 0xff) != (pRequestedMode->Int10ModeNumber & 0xff))
  439. {
  440. if ((HwDeviceExtension->SVGABios < FULL_SVGA_BIOS) &&
  441. (pRequestedMode->ModeTable != NULL))
  442. {
  443. BOOLEAN bLCD=FALSE;
  444. VideoDebugPrint((1, "\n*** Setting mode with mode table!\n\n"));
  445. //
  446. // NOTE: Certain models of IBM Thinkpads can switch
  447. // between LCD, Monitor, and Simultaneous modes while
  448. // the machine is running. Other models cannot.
  449. // Currently we have noticed a coralation between
  450. // machines which have SVGA Bios's and machines which
  451. // can set the mode.
  452. //
  453. // IF MACHINE HAS SVGA BIOS THEN
  454. // MACHINE CAN TURN ON/OFF LCD ON THE FLY
  455. // ELSE
  456. // MACHINE CANNOT TURN ON/OFF LCD ON THE FLY
  457. //
  458. // If a user has a machine where the LCD can be turned
  459. // on dynamically, then it is possible that the user
  460. // will turn on the LCD when we think it is off. Then
  461. // we may try to set a mode which does not work with
  462. // the LCD off. To avoid this problem, we will try
  463. // to determine if the LCD is on/off before setting
  464. // the mode. If the LCD is on, and it needs to be
  465. // off in order for the modeset to succeed, we'll fail
  466. // the modeset.
  467. //
  468. // Unfortunately, this does not solve all of our
  469. // problems. The code which we use to try to detect
  470. // whether or not the LCD is on fails on some
  471. // machines. The code seems to fail on machines
  472. // which do not have SVGA Bios's. As mentioned above
  473. // machines which do not have SVGA Bios's can not
  474. // switch on their LCD's dynamically. Therefore we
  475. // do not need to execute this special code on these
  476. // machines because the LCD state wont change on us
  477. // anyway.
  478. //
  479. if (HwDeviceExtension->SVGABios > NO_SVGA_BIOS)
  480. {
  481. //
  482. // If the LCD is enabled we also need to SET bit 0
  483. // of PR2.
  484. //
  485. // We will check to see if the LCD is enabled by
  486. // checking bit 2 of CRTC register 0x31, and bit
  487. // 4 of CRTC register 0x32. If either of these
  488. // is set, then we'll assume an LCD is enabled.
  489. //
  490. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  491. CRTC_ADDRESS_PORT_COLOR, 0x31);
  492. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  493. CRTC_DATA_PORT_COLOR) & 0x04)
  494. {
  495. bLCD = TRUE;
  496. }
  497. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  498. CRTC_ADDRESS_PORT_COLOR, 0x32);
  499. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  500. CRTC_DATA_PORT_COLOR) & 0x10)
  501. {
  502. bLCD = TRUE;
  503. }
  504. //
  505. // For some reason, on the 755CDV, if we set a high res mode,
  506. // while the LCD is on, then the LCD won't be disabled
  507. // properly. Therefore, fail the mode set if the LCD
  508. // is on, and we need to turn it off to set this mode.
  509. //
  510. if (bLCD &&
  511. !(HwDeviceExtension->DisplayType &
  512. pRequestedMode->LCDtype &
  513. ~MONITOR))
  514. {
  515. return ERROR_INVALID_PARAMETER;
  516. }
  517. }
  518. VgaSetActiveDisplay(HwDeviceExtension, LCD_DISABLE | CRT_ENABLE);
  519. VgaInterpretCmdStream(HwDeviceExtension, pRequestedMode->ModeTable);
  520. //
  521. // if the LCD can do this mode, then turn the LCD
  522. // back on. Else, leave it off.
  523. //
  524. // add the code!!
  525. //
  526. if (pRequestedMode->LCDtype & HwDeviceExtension->DisplayType & ~MONITOR)
  527. {
  528. VgaSetActiveDisplay(HwDeviceExtension, LCD_ENABLE | CRT_ENABLE);
  529. VideoDebugPrint((1, "LCD Enabled!\n"));
  530. }
  531. else
  532. {
  533. VgaSetActiveDisplay(HwDeviceExtension, LCD_DISABLE | CRT_ENABLE);
  534. VideoDebugPrint((1, "LCD Disabled!\n"));
  535. }
  536. }
  537. else
  538. {
  539. return ERROR_INVALID_PARAMETER;
  540. }
  541. }
  542. }
  543. if (pRequestedMode->CmdStrings != NULL)
  544. {
  545. VgaInterpretCmdStream(HwDeviceExtension, pRequestedMode->CmdStrings);
  546. }
  547. if (!(pRequestedMode->fbType & VIDEO_MODE_GRAPHICS)) {
  548. //
  549. // Fix to make sure we always set the colors in text mode to be
  550. // intensity, and not flashing
  551. // For this zero out the Mode Control Regsiter bit 3 (index 0x10
  552. // of the Attribute controller).
  553. //
  554. if (bIsColor) {
  555. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  556. INPUT_STATUS_1_COLOR);
  557. } else {
  558. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  559. INPUT_STATUS_1_MONO);
  560. }
  561. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  562. ATT_ADDRESS_PORT, (0x10 | VIDEO_ENABLE));
  563. temp = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  564. ATT_DATA_READ_PORT);
  565. temp &= 0xF7;
  566. if (bIsColor) {
  567. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  568. INPUT_STATUS_1_COLOR);
  569. } else {
  570. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  571. INPUT_STATUS_1_MONO);
  572. }
  573. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  574. ATT_ADDRESS_PORT, (0x10 | VIDEO_ENABLE));
  575. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  576. ATT_DATA_WRITE_PORT, temp);
  577. }
  578. //
  579. // A few wd cards do not work properly on the first mode set. You have
  580. // to set the mode twice. So lets set it twice!
  581. //
  582. if (bModeFirst == 1 && HwDeviceExtension->BoardID != WD90C24A)
  583. {
  584. bModeFirst = 0;
  585. goto SetAgain;
  586. }
  587. #else
  588. VgaInterpretCmdStream(HwDeviceExtension, pRequestedMode->CmdStrings);
  589. #endif
  590. //
  591. // Make sure we unlock extended registers since the BIOS on some machines
  592. // does not do it properly.
  593. //
  594. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  595. GRAPH_ADDRESS_PORT), 0x050F);
  596. if (HwDeviceExtension->BoardID == WD90C24A)
  597. {
  598. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  599. DAC_PIXEL_MASK_PORT, 0xFF);
  600. }
  601. //
  602. // Update the location of the physical frame buffer within video memory.
  603. //
  604. HwDeviceExtension->PhysicalFrameLength =
  605. MemoryMaps[pRequestedMode->MemMap].MaxSize;
  606. HwDeviceExtension->PhysicalFrameBase.LowPart =
  607. MemoryMaps[pRequestedMode->MemMap].Start;
  608. //
  609. // Store the new mode value.
  610. //
  611. HwDeviceExtension->CurrentMode = pRequestedMode;
  612. HwDeviceExtension->ModeIndex = Mode->RequestedMode;
  613. return NO_ERROR;
  614. } //end VgaSetMode()
  615. VP_STATUS
  616. VgaQueryAvailableModes(
  617. PHW_DEVICE_EXTENSION HwDeviceExtension,
  618. PVIDEO_MODE_INFORMATION ModeInformation,
  619. ULONG ModeInformationSize,
  620. PULONG OutputSize
  621. )
  622. /*++
  623. Routine Description:
  624. This routine returns the list of all available available modes on the
  625. card.
  626. Arguments:
  627. HwDeviceExtension - Pointer to the miniport driver's device extension.
  628. ModeInformation - Pointer to the output buffer supplied by the user.
  629. This is where the list of all valid modes is stored.
  630. ModeInformationSize - Length of the output buffer supplied by the user.
  631. OutputSize - Pointer to a buffer in which to return the actual size of
  632. the data in the buffer. If the buffer was not large enough, this
  633. contains the minimum required buffer size.
  634. Return Value:
  635. ERROR_INSUFFICIENT_BUFFER if the output buffer was not large enough
  636. for the data being returned.
  637. NO_ERROR if the operation completed successfully.
  638. --*/
  639. {
  640. PVIDEO_MODE_INFORMATION videoModes = ModeInformation;
  641. ULONG i;
  642. //
  643. // Find out the size of the data to be put in the buffer and return
  644. // that in the status information (whether or not the information is
  645. // there). If the buffer passed in is not large enough return an
  646. // appropriate error code.
  647. //
  648. if (ModeInformationSize < (*OutputSize =
  649. HwDeviceExtension->NumAvailableModes *
  650. sizeof(VIDEO_MODE_INFORMATION)) ) {
  651. return ERROR_INSUFFICIENT_BUFFER;
  652. }
  653. //
  654. // For each mode supported by the card, store the mode characteristics
  655. // in the output buffer.
  656. //
  657. for (i = 0; i < NumVideoModes; i++) {
  658. if (ModesVGA[i].ValidMode) {
  659. videoModes->Length = sizeof(VIDEO_MODE_INFORMATION);
  660. videoModes->ModeIndex = i;
  661. videoModes->VisScreenWidth = ModesVGA[i].hres;
  662. videoModes->ScreenStride = ModesVGA[i].wbytes;
  663. videoModes->VisScreenHeight = ModesVGA[i].vres;
  664. videoModes->NumberOfPlanes = ModesVGA[i].numPlanes;
  665. videoModes->BitsPerPlane = ModesVGA[i].bitsPerPlane;
  666. videoModes->Frequency = ModesVGA[i].Frequency;
  667. videoModes->XMillimeter = 320; // temporary hardcoded constant
  668. videoModes->YMillimeter = 240; // temporary hardcoded constant
  669. videoModes->AttributeFlags = ModesVGA[i].fbType;
  670. videoModes->AttributeFlags |= ModesVGA[i].Interlaced ?
  671. VIDEO_MODE_INTERLACED : 0;
  672. videoModes->DriverSpecificAttributeFlags = 0;
  673. //
  674. // Calculate the VideoMemoryBitmapWidth
  675. //
  676. {
  677. LONG x;
  678. x = videoModes->BitsPerPlane;
  679. if( x == 15 ) x = 16;
  680. videoModes->VideoMemoryBitmapWidth =
  681. (videoModes->ScreenStride * 8 ) / x;
  682. }
  683. videoModes->VideoMemoryBitmapHeight =
  684. HwDeviceExtension->AdapterMemorySize / videoModes->ScreenStride;
  685. if (ModesVGA[i].bitsPerPlane == 16)
  686. {
  687. videoModes->NumberRedBits = 5;
  688. videoModes->NumberGreenBits = 6;
  689. videoModes->NumberBlueBits = 5;
  690. videoModes->RedMask = 0xF800;
  691. videoModes->GreenMask = 0x07E0;
  692. videoModes->BlueMask = 0x001F;
  693. }
  694. else
  695. {
  696. videoModes->NumberRedBits = 6;
  697. videoModes->NumberGreenBits = 6;
  698. videoModes->NumberBlueBits = 6;
  699. videoModes->RedMask = 0;
  700. videoModes->GreenMask = 0;
  701. videoModes->BlueMask = 0;
  702. videoModes->AttributeFlags |= VIDEO_MODE_PALETTE_DRIVEN |
  703. VIDEO_MODE_MANAGED_PALETTE;
  704. }
  705. videoModes++;
  706. }
  707. }
  708. return NO_ERROR;
  709. } // end VgaGetAvailableModes()
  710. VP_STATUS
  711. VgaQueryNumberOfAvailableModes(
  712. PHW_DEVICE_EXTENSION HwDeviceExtension,
  713. PVIDEO_NUM_MODES NumModes,
  714. ULONG NumModesSize,
  715. PULONG OutputSize
  716. )
  717. /*++
  718. Routine Description:
  719. This routine returns the number of available modes for this particular
  720. video card.
  721. Arguments:
  722. HwDeviceExtension - Pointer to the miniport driver's device extension.
  723. NumModes - Pointer to the output buffer supplied by the user. This is
  724. where the number of modes is stored.
  725. NumModesSize - Length of the output buffer supplied by the user.
  726. OutputSize - Pointer to a buffer in which to return the actual size of
  727. the data in the buffer.
  728. Return Value:
  729. ERROR_INSUFFICIENT_BUFFER if the output buffer was not large enough
  730. for the data being returned.
  731. NO_ERROR if the operation completed successfully.
  732. --*/
  733. {
  734. //
  735. // Find out the size of the data to be put in the the buffer and return
  736. // that in the status information (whether or not the information is
  737. // there). If the buffer passed in is not large enough return an
  738. // appropriate error code.
  739. //
  740. if (NumModesSize < (*OutputSize = sizeof(VIDEO_NUM_MODES)) ) {
  741. return ERROR_INSUFFICIENT_BUFFER;
  742. }
  743. //
  744. // Validate the modes each time on the portables since an external monitor
  745. // can be connected or disconnected dynamically.
  746. //
  747. VgaValidateModes(HwDeviceExtension);
  748. //
  749. // Store the number of modes into the buffer.
  750. //
  751. NumModes->NumModes = HwDeviceExtension->NumAvailableModes;
  752. NumModes->ModeInformationLength = sizeof(VIDEO_MODE_INFORMATION);
  753. return NO_ERROR;
  754. } // end VgaGetNumberOfAvailableModes()
  755. VP_STATUS
  756. VgaQueryCurrentMode(
  757. PHW_DEVICE_EXTENSION HwDeviceExtension,
  758. PVIDEO_MODE_INFORMATION ModeInformation,
  759. ULONG ModeInformationSize,
  760. PULONG OutputSize
  761. )
  762. /*++
  763. Routine Description:
  764. This routine returns a description of the current video mode.
  765. Arguments:
  766. HwDeviceExtension - Pointer to the miniport driver's device extension.
  767. ModeInformation - Pointer to the output buffer supplied by the user.
  768. This is where the current mode information is stored.
  769. ModeInformationSize - Length of the output buffer supplied by the user.
  770. OutputSize - Pointer to a buffer in which to return the actual size of
  771. the data in the buffer. If the buffer was not large enough, this
  772. contains the minimum required buffer size.
  773. Return Value:
  774. ERROR_INSUFFICIENT_BUFFER if the output buffer was not large enough
  775. for the data being returned.
  776. NO_ERROR if the operation completed successfully.
  777. --*/
  778. {
  779. //
  780. //
  781. // check if a mode has been set
  782. //
  783. if (HwDeviceExtension->CurrentMode == NULL) {
  784. return ERROR_INVALID_FUNCTION;
  785. }
  786. //
  787. // Find out the size of the data to be put in the the buffer and return
  788. // that in the status information (whether or not the information is
  789. // there). If the buffer passed in is not large enough return an
  790. // appropriate error code.
  791. //
  792. if (ModeInformationSize < (*OutputSize = sizeof(VIDEO_MODE_INFORMATION))) {
  793. return ERROR_INSUFFICIENT_BUFFER;
  794. }
  795. //
  796. // Store the characteristics of the current mode into the buffer.
  797. //
  798. ModeInformation->Length = sizeof(VIDEO_MODE_INFORMATION);
  799. ModeInformation->ModeIndex = HwDeviceExtension->ModeIndex;
  800. ModeInformation->VisScreenWidth = HwDeviceExtension->CurrentMode->hres;
  801. ModeInformation->ScreenStride = HwDeviceExtension->CurrentMode->wbytes;
  802. ModeInformation->VisScreenHeight = HwDeviceExtension->CurrentMode->vres;
  803. ModeInformation->NumberOfPlanes = HwDeviceExtension->CurrentMode->numPlanes;
  804. ModeInformation->BitsPerPlane = HwDeviceExtension->CurrentMode->bitsPerPlane;
  805. ModeInformation->Frequency = HwDeviceExtension->CurrentMode->Frequency;
  806. ModeInformation->XMillimeter = 320; // temporary hardcoded constant
  807. ModeInformation->YMillimeter = 240; // temporary hardcoded constant
  808. ModeInformation->AttributeFlags = HwDeviceExtension->CurrentMode->fbType |
  809. (HwDeviceExtension->CurrentMode->Interlaced ?
  810. VIDEO_MODE_INTERLACED : 0);
  811. ModeInformation->DriverSpecificAttributeFlags = 0;
  812. if (ModeInformation->BitsPerPlane == 16) {
  813. ModeInformation->NumberRedBits = 5;
  814. ModeInformation->NumberGreenBits = 6;
  815. ModeInformation->NumberBlueBits = 5;
  816. ModeInformation->RedMask = 0xF800;
  817. ModeInformation->GreenMask = 0x07E0;
  818. ModeInformation->BlueMask = 0x1F;
  819. } else {
  820. ModeInformation->NumberRedBits = 6;
  821. ModeInformation->NumberGreenBits = 6;
  822. ModeInformation->NumberBlueBits = 6;
  823. ModeInformation->RedMask = 0;
  824. ModeInformation->GreenMask = 0;
  825. ModeInformation->BlueMask = 0;
  826. ModeInformation->AttributeFlags |=
  827. VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE;
  828. }
  829. //
  830. // Calculate the VideoMemoryBitmapWidth
  831. //
  832. {
  833. LONG x;
  834. x = ModeInformation->BitsPerPlane;
  835. if( x == 15 ) x = 16;
  836. ModeInformation->VideoMemoryBitmapWidth =
  837. (ModeInformation->ScreenStride * 8 ) / x;
  838. }
  839. ModeInformation->VideoMemoryBitmapHeight =
  840. HwDeviceExtension->AdapterMemorySize / ModeInformation->ScreenStride;
  841. return NO_ERROR;
  842. } // end VgaQueryCurrentMode()
  843. VOID
  844. VgaZeroVideoMemory(
  845. PHW_DEVICE_EXTENSION HwDeviceExtension
  846. )
  847. /*++
  848. Routine Description:
  849. This routine zeros the first 256K on the VGA.
  850. Arguments:
  851. HwDeviceExtension - Pointer to the miniport driver's device extension.
  852. Return Value:
  853. None.
  854. --*/
  855. {
  856. UCHAR temp;
  857. //
  858. // Map font buffer at A0000
  859. //
  860. VgaInterpretCmdStream(HwDeviceExtension, EnableA000Data);
  861. //
  862. // Enable all planes.
  863. //
  864. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  865. IND_MAP_MASK);
  866. temp = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  867. SEQ_DATA_PORT) | (UCHAR)0x0F;
  868. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
  869. temp);
  870. //
  871. // Zero the memory.
  872. //
  873. VideoPortZeroDeviceMemory(HwDeviceExtension->VideoMemoryAddress, 0xFFFF);
  874. VgaInterpretCmdStream(HwDeviceExtension, DisableA000Color);
  875. }
  876. VOID
  877. VgaValidateModes(
  878. PHW_DEVICE_EXTENSION HwDeviceExtension
  879. )
  880. /*++
  881. Routine Description:
  882. Determines which modes are valid and which are not.
  883. Arguments:
  884. HwDeviceExtension - Pointer to the miniport driver's device extension.
  885. Return Value:
  886. None.
  887. --*/
  888. {
  889. ULONG i;
  890. HwDeviceExtension->NumAvailableModes = 0;
  891. VideoDebugPrint((1, "VgaValidateModes:\n"));
  892. VideoDebugPrint((1, "Avail Adapter Mem: 0x%x\n"
  893. "Avail Monitor Type: 0x%x\n",
  894. HwDeviceExtension->AdapterMemorySize,
  895. HwDeviceExtension->DisplayType));
  896. for (i = 0; i < NumVideoModes; i++) {
  897. VideoDebugPrint((1, "Mode %d %dx%d at %d bpp\n"
  898. "\tAdapterMemoryRequired: 0x%x\n"
  899. "\tMonitorType 0x%x\n",
  900. i, ModesVGA[i].hres, ModesVGA[i].vres,
  901. ModesVGA[i].bitsPerPlane * ModesVGA[i].numPlanes,
  902. ModesVGA[i].numPlanes * ModesVGA[i].sbytes,
  903. ModesVGA[i].LCDtype));
  904. if ((HwDeviceExtension->AdapterMemorySize >=
  905. ModesVGA[i].numPlanes * ModesVGA[i].sbytes) &&
  906. (HwDeviceExtension->DisplayType &
  907. ModesVGA[i].LCDtype))
  908. {
  909. ModesVGA[i].ValidMode = TRUE;
  910. HwDeviceExtension->NumAvailableModes++;
  911. }
  912. //
  913. // invalidates some modes we may have enabled based on some specific
  914. // chip\machine problems
  915. //
  916. if ( (ModesVGA[i].ValidMode) &&
  917. (HwDeviceExtension->BoardID == WD90C24A))
  918. {
  919. if (HwDeviceExtension->IsIBM == TRUE)
  920. {
  921. //
  922. // get rid of 256 color modes > 640x480 on
  923. // machines with STN displays
  924. //
  925. if ((ModesVGA[i].bitsPerPlane == 8) &&
  926. (ModesVGA[i].hres > 640) &&
  927. (HwDeviceExtension->DisplayType & TOSHIBA_DSTNC))
  928. {
  929. ModesVGA[i].ValidMode = FALSE;
  930. HwDeviceExtension->NumAvailableModes--;
  931. }
  932. //
  933. // get rid of 64K color support for machines without
  934. // SVGABios support
  935. //
  936. else if ((ModesVGA[i].bitsPerPlane == 16) &&
  937. (HwDeviceExtension->SVGABios == NO_SVGA_BIOS))
  938. {
  939. ModesVGA[i].ValidMode = FALSE;
  940. HwDeviceExtension->NumAvailableModes--;
  941. }
  942. }
  943. }
  944. //
  945. // 16bpp modes only work on the WD90C24A chip sets.
  946. //
  947. if( (ModesVGA[i].ValidMode) &&
  948. (HwDeviceExtension->BoardID != WD90C24A) &&
  949. (ModesVGA[i].bitsPerPlane == 16))
  950. {
  951. ModesVGA[i].ValidMode = FALSE;
  952. HwDeviceExtension->NumAvailableModes--;
  953. }
  954. //
  955. // Older boards do not support 72HZ in 1024x768 modes.
  956. // So disable those.
  957. //
  958. if ( (ModesVGA[i].ValidMode) &&
  959. (HwDeviceExtension->BoardID < WD90C31) &&
  960. (ModesVGA[i].hres == 1024) &&
  961. (ModesVGA[i].vres == 768) &&
  962. (ModesVGA[i].Frequency == 72) )
  963. {
  964. ModesVGA[i].ValidMode = FALSE;
  965. HwDeviceExtension->NumAvailableModes--;
  966. }
  967. if (ModesVGA[i].ValidMode == FALSE)
  968. {
  969. VideoDebugPrint((1, "The mode is not valid.\n"));
  970. }
  971. else
  972. {
  973. VideoDebugPrint((1, "The mode is valid.\n"));
  974. }
  975. }
  976. }
  977. BOOLEAN
  978. ExternalMonitorPresent(
  979. PHW_DEVICE_EXTENSION HwDeviceExtension
  980. )
  981. /*++
  982. Routine Description:
  983. Determine whether an external monitor is connected to the
  984. machine. This routine should only be called if the
  985. BoardID == WD90C24A.
  986. Note: This routine expects to be called after the WD extended
  987. registers have been unlocked.
  988. Arguments:
  989. HwDeviceExtension - Pointer to the miniport driver's device extension.
  990. Return Value:
  991. Updated the DisplayType field in HwDeviceExtension to indicate
  992. whether a monitor is connected.
  993. The routine always returns TRUE.
  994. --*/
  995. {
  996. UCHAR dac[3];
  997. UCHAR _pr19, _pr1b;
  998. int i,j;
  999. int bExternal = 0;
  1000. //
  1001. // If we are on an IBM machine, use SMAPI routines
  1002. // instead of detetecting the monitor ourselves.
  1003. //
  1004. if (HwDeviceExtension->IsIBM)
  1005. {
  1006. bExternal = LCDIsMonitorPresent();
  1007. if (bExternal)
  1008. {
  1009. HwDeviceExtension->DisplayType |= MONITOR;
  1010. }
  1011. else
  1012. {
  1013. HwDeviceExtension->DisplayType &= ~MONITOR;
  1014. }
  1015. return TRUE;
  1016. }
  1017. //
  1018. // Only refresh display with value in DAC 0
  1019. //
  1020. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1021. DAC_PIXEL_MASK_PORT, 0x00);
  1022. //
  1023. // lets preserve what's in the DAC
  1024. //
  1025. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1026. DAC_ADDRESS_READ_PORT,
  1027. (UCHAR) 0);
  1028. for (j=0; j<3; j++)
  1029. {
  1030. dac[j]= VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1031. DAC_DATA_REG_PORT);
  1032. }
  1033. //
  1034. // Fill in DAC 0 with a value for the test
  1035. //
  1036. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + DAC_ADDRESS_WRITE_PORT, 0);
  1037. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + DAC_DATA_REG_PORT, 0x04); // Red
  1038. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + DAC_DATA_REG_PORT, 0x12); // Green
  1039. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + DAC_DATA_REG_PORT, 0x04); // Blue
  1040. //
  1041. // We need to check bit 4 of 0x3c2. We only want to check
  1042. // this bit during actual display output. Therefore we will
  1043. // wait for a vertical refresh, and then try to wait 300
  1044. // nanoseconds for the monitor detection circuits to
  1045. // stabalize, and then read the bit. (I may have to adjust
  1046. // crtc registers to prevent refresh cycles).
  1047. //
  1048. // There are two bits in the Input Status #1 Register which
  1049. // will help us to detect if we are in a refresh cycle. If
  1050. // bit 3 is on then we are in a verticle refresh. If bit 0
  1051. // is off (0) then we are in a display mode, else we are in
  1052. // some sort of a refresh.
  1053. //
  1054. // Therefore, for our purposes, we will do the following. We
  1055. // will wait for a verticle refresh (bit 3 = 1) then we will
  1056. // wait for it to turn off. We are now starting to draw the
  1057. // screen. Now we will examine the monitor connection bit
  1058. // (bit 4 of 0x3c2) until the display mode bit (bit 0 of
  1059. // 0x3da) goes high. Now we will use our last recorded value
  1060. // for monitor detection.
  1061. //
  1062. //
  1063. // wait for V retrace
  1064. //
  1065. while ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1066. INPUT_STATUS_1_COLOR) & 0x8) == 0);
  1067. //
  1068. // wait for V retrace to end
  1069. //
  1070. while ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1071. INPUT_STATUS_1_COLOR) & 0x8) != 0);
  1072. //
  1073. // wait for display enable to start
  1074. //
  1075. while ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1076. INPUT_STATUS_1_COLOR) & 0x1) != 0);
  1077. //
  1078. // wait for display enable to end. Use last value of
  1079. // bExternal to determine if an external monitor is
  1080. // connected.
  1081. //
  1082. {
  1083. int LoopCount=0, OnCount=0;
  1084. bExternal = FALSE;
  1085. while ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1086. INPUT_STATUS_1_COLOR) & 0x1) == 0)
  1087. {
  1088. if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1089. INPUT_STATUS_0_PORT) & 0x10) == 0x10)
  1090. {
  1091. OnCount++;
  1092. }
  1093. LoopCount++;
  1094. }
  1095. if (OnCount > (LoopCount / 2)) // should compile as LoopCount >> 1
  1096. {
  1097. bExternal = TRUE;
  1098. }
  1099. }
  1100. //
  1101. // restore the DAC
  1102. //
  1103. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1104. DAC_ADDRESS_WRITE_PORT,
  1105. (UCHAR) 0);
  1106. for (j=0; j<3; j++)
  1107. {
  1108. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1109. DAC_DATA_REG_PORT,
  1110. dac[j]);
  1111. }
  1112. //
  1113. // Re-enable the DAC
  1114. //
  1115. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1116. DAC_PIXEL_MASK_PORT, 0xFF);
  1117. //
  1118. // restore _pr19, and _pr1b state
  1119. //
  1120. if (bExternal)
  1121. {
  1122. HwDeviceExtension->DisplayType |= MONITOR;
  1123. }
  1124. else
  1125. {
  1126. HwDeviceExtension->DisplayType &= ~MONITOR;
  1127. }
  1128. return TRUE;
  1129. }
  1130. VP_STATUS
  1131. VgaSetActiveDisplay(
  1132. PHW_DEVICE_EXTENSION HwDeviceExtension,
  1133. ULONG ActiveDisplay
  1134. )
  1135. /*++
  1136. Routine Description:
  1137. This routine selects the active display device(s).
  1138. Arguments:
  1139. HwDeviceExtension - Pointer to the miniport driver's device extension.
  1140. ActiveDisplay - Devices to be active.
  1141. (See WD90C24A.H for the definition)
  1142. Return Value:
  1143. If successful, return NO_ERROR, else return FALSE.
  1144. --*/
  1145. {
  1146. VP_STATUS status = ERROR_INVALID_PARAMETER;
  1147. //
  1148. // Unlock paradise registers
  1149. //
  1150. UnlockAll(HwDeviceExtension);
  1151. //
  1152. // Enable or Disable LCD output
  1153. //
  1154. // Note: To prevent the fuse of LCD from blowing up, LCD should be turns off
  1155. // while output is disabled.
  1156. //
  1157. // If VideoPortPowerControl() returns an error for the absence of HALPM.SYS,
  1158. // we will try to control LCD by accessing the hardware directly.
  1159. //
  1160. if (ActiveDisplay & LCD_ENABLE) {
  1161. EnableLCD(HwDeviceExtension);
  1162. } else if (ActiveDisplay & LCD_DISABLE) {
  1163. DisableLCD(HwDeviceExtension);
  1164. }
  1165. //
  1166. // Enable or Disable CRT output
  1167. //
  1168. if (ActiveDisplay & CRT_ENABLE) {
  1169. EnableCRT(HwDeviceExtension);
  1170. } else {
  1171. DisableCRT(HwDeviceExtension);
  1172. }
  1173. return NO_ERROR;
  1174. } // end VgaSetActiveDisplay()
  1175. VOID
  1176. DisableLCD(
  1177. PHW_DEVICE_EXTENSION HwDeviceExtension
  1178. )
  1179. /*++
  1180. Routine Description:
  1181. This routine disables LCD interface of WD90C24A/A2.
  1182. Arguments:
  1183. HwDeviceExtension - Pointer to the miniport driver's adapter information.
  1184. Return Value:
  1185. None.
  1186. --*/
  1187. {
  1188. PUCHAR IoBase = HwDeviceExtension->IOAddress;
  1189. //
  1190. // Wait until next vertical retrace interval
  1191. //
  1192. while (0 == (VideoPortReadPortUchar(IoBase + INPUT_STATUS_1_COLOR) & 0x08));
  1193. //
  1194. // Disables LCD interface
  1195. //
  1196. VideoPortWritePortUchar(IoBase + CRTC_ADDRESS_PORT_COLOR, pr19);
  1197. VideoPortWritePortUchar(
  1198. IoBase + CRTC_DATA_PORT_COLOR,
  1199. (UCHAR)(VideoPortReadPortUchar(IoBase + CRTC_DATA_PORT_COLOR) & ~0x10));
  1200. //
  1201. // Tristates LCD control and data signals
  1202. //
  1203. VideoPortWritePortUchar(IoBase + GRAPH_ADDRESS_PORT, pr4);
  1204. VideoPortWritePortUchar(
  1205. IoBase + GRAPH_DATA_PORT,
  1206. (CHAR)(VideoPortReadPortUchar(IoBase + GRAPH_DATA_PORT) | 0x20));
  1207. //
  1208. // Unlocks CRTC shadow registers
  1209. //
  1210. VideoPortWritePortUshort(
  1211. (PUSHORT)(IoBase + CRTC_ADDRESS_PORT_COLOR),
  1212. (USHORT)pr1b | ((USHORT)pr1b_unlock << 8));
  1213. } // end DisableLCD()
  1214. VOID
  1215. EnableLCD(
  1216. PHW_DEVICE_EXTENSION HwDeviceExtension
  1217. )
  1218. /*++
  1219. Routine Description:
  1220. This routine enables LCD interface of WD90C24A/A2.
  1221. Arguments:
  1222. HwDeviceExtension - Pointer to the miniport driver's adapter information.
  1223. Return Value:
  1224. None.
  1225. --*/
  1226. {
  1227. PUCHAR IoBase = HwDeviceExtension->IOAddress;
  1228. //
  1229. // Locks CRTC shadow registers
  1230. //
  1231. VideoPortWritePortUshort(
  1232. (PUSHORT)(IoBase + CRTC_ADDRESS_PORT_COLOR),
  1233. (USHORT)pr1b | ((USHORT)pr1b_unlock_pr << 8));
  1234. //
  1235. // Wait until next vertical retrace interval
  1236. //
  1237. while (0 == (VideoPortReadPortUchar(IoBase + INPUT_STATUS_1_COLOR) & 0x08));
  1238. //
  1239. // Drives LCD control and data signals
  1240. //
  1241. VideoPortWritePortUchar(IoBase + GRAPH_ADDRESS_PORT, pr4);
  1242. VideoPortWritePortUchar(
  1243. IoBase + GRAPH_DATA_PORT,
  1244. (CHAR)(VideoPortReadPortUchar(IoBase + GRAPH_DATA_PORT) & ~0x20));
  1245. //
  1246. // Enables LCD interface
  1247. //
  1248. VideoPortWritePortUchar(IoBase + CRTC_ADDRESS_PORT_COLOR, pr19);
  1249. VideoPortWritePortUchar(
  1250. IoBase + CRTC_DATA_PORT_COLOR,
  1251. (CHAR)(VideoPortReadPortUchar(IoBase + CRTC_DATA_PORT_COLOR) | 0x10));
  1252. } // end EnableLCD()
  1253. VOID
  1254. DisableCRT(
  1255. PHW_DEVICE_EXTENSION HwDeviceExtension
  1256. )
  1257. /*++
  1258. Routine Description:
  1259. This routine disables CRT interface of WD90C24A/A2
  1260. Arguments:
  1261. HwDeviceExtension - Pointer to the miniport driver's adapter information.
  1262. Return Value:
  1263. None.
  1264. --*/
  1265. {
  1266. PUCHAR IoBase = HwDeviceExtension->IOAddress;
  1267. //
  1268. // Disables CRT interface
  1269. //
  1270. VideoPortWritePortUchar(IoBase + CRTC_ADDRESS_PORT_COLOR, pr19);
  1271. VideoPortWritePortUchar(
  1272. IoBase + CRTC_DATA_PORT_COLOR,
  1273. (UCHAR)(VideoPortReadPortUchar(IoBase + CRTC_DATA_PORT_COLOR) & ~0x20));
  1274. //
  1275. // Shuts off internal RAMDAC
  1276. //
  1277. VideoPortWritePortUchar(IoBase + CRTC_ADDRESS_PORT_COLOR, pr18);
  1278. VideoPortWritePortUchar(
  1279. IoBase + CRTC_DATA_PORT_COLOR,
  1280. (UCHAR)(VideoPortReadPortUchar(IoBase + CRTC_DATA_PORT_COLOR) | 0x80));
  1281. //
  1282. // Disables CRT H-sync and V-sync signals
  1283. //
  1284. VideoPortWritePortUchar(IoBase + CRTC_ADDRESS_PORT_COLOR, pr39);
  1285. VideoPortWritePortUchar(
  1286. IoBase + CRTC_DATA_PORT_COLOR,
  1287. (UCHAR)(VideoPortReadPortUchar(IoBase + CRTC_DATA_PORT_COLOR) & ~0x04));
  1288. } // end DisableCRT()
  1289. VOID
  1290. EnableCRT(
  1291. PHW_DEVICE_EXTENSION HwDeviceExtension
  1292. )
  1293. /*++
  1294. Routine Description:
  1295. This routine enables CRT interface of WD90C24A/A2
  1296. Arguments:
  1297. HwDeviceExtension - Pointer to the miniport driver's adapter information.
  1298. Return Value:
  1299. None.
  1300. --*/
  1301. {
  1302. PUCHAR IoBase = HwDeviceExtension->IOAddress;
  1303. //
  1304. // Enables CRT interface
  1305. //
  1306. VideoPortWritePortUchar(IoBase + CRTC_ADDRESS_PORT_COLOR, pr19);
  1307. VideoPortWritePortUchar(
  1308. IoBase + CRTC_DATA_PORT_COLOR,
  1309. (UCHAR)(VideoPortReadPortUchar(IoBase + CRTC_DATA_PORT_COLOR) | 0x20));
  1310. //
  1311. // Enables internal RAMDAC
  1312. //
  1313. VideoPortWritePortUchar(IoBase + CRTC_ADDRESS_PORT_COLOR, pr18);
  1314. VideoPortWritePortUchar(
  1315. IoBase + CRTC_DATA_PORT_COLOR,
  1316. (UCHAR)(VideoPortReadPortUchar(IoBase + CRTC_DATA_PORT_COLOR) & ~0x80));
  1317. //
  1318. // Enables CRT H-sync and V-sync signals
  1319. //
  1320. VideoPortWritePortUchar(IoBase + CRTC_ADDRESS_PORT_COLOR, pr39);
  1321. VideoPortWritePortUchar(
  1322. IoBase + CRTC_DATA_PORT_COLOR,
  1323. (UCHAR)(VideoPortReadPortUchar(IoBase + CRTC_DATA_PORT_COLOR) | 0x04));
  1324. } // end EnableCRT()
  1325. VOID
  1326. UnlockAll(
  1327. PHW_DEVICE_EXTENSION HwDeviceExtension
  1328. )
  1329. /*++
  1330. Routine Description:
  1331. This routine unlocks all WD registers, except CRTC shadow registers
  1332. Arguments:
  1333. HwDeviceExtension - Pointer to the miniport driver's adapter information.
  1334. Return Value:
  1335. None.
  1336. --*/
  1337. {
  1338. PUCHAR IoBase = HwDeviceExtension->IOAddress;
  1339. //
  1340. // Unlocks the all WD registers
  1341. //
  1342. VideoPortWritePortUshort(
  1343. (PUSHORT)(IoBase + GRAPH_ADDRESS_PORT),
  1344. (USHORT)pr5 | ((USHORT)pr5_unlock << 8));
  1345. VideoPortWritePortUshort(
  1346. (PUSHORT)(IoBase + CRTC_ADDRESS_PORT_COLOR),
  1347. (USHORT)pr10 | ((USHORT)pr10_unlock << 8));
  1348. VideoPortWritePortUshort(
  1349. (PUSHORT)(IoBase + CRTC_ADDRESS_PORT_COLOR),
  1350. (USHORT)pr11 | ((USHORT)pr11_unlock << 8));
  1351. VideoPortWritePortUshort(
  1352. (PUSHORT)(IoBase + SEQ_ADDRESS_PORT),
  1353. (USHORT)pr20 | ((USHORT)pr20_unlock << 8));
  1354. VideoPortWritePortUshort(
  1355. (PUSHORT)(IoBase + SEQ_ADDRESS_PORT),
  1356. (USHORT)pr72 | ((USHORT)pr72_unlock << 8));
  1357. VideoPortWritePortUshort(
  1358. (PUSHORT)(IoBase + CRTC_ADDRESS_PORT_COLOR),
  1359. (USHORT)pr1b | ((USHORT)pr1b_unlock_pr << 8));
  1360. VideoPortWritePortUshort(
  1361. (PUSHORT)(IoBase + CRTC_ADDRESS_PORT_COLOR),
  1362. (USHORT)pr30 | ((USHORT)pr30_unlock << 8));
  1363. return;
  1364. } // end UnlockAll()