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.

1126 lines
32 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. clddc2b.c
  5. Abstract:
  6. This module checks for a DDC monitor, and returns the
  7. established Timings value from the EDID if found.
  8. Environment:
  9. Kernel mode only
  10. Notes:
  11. Revision History:
  12. * plc3 10-23-95 VESA DDC2B support.
  13. *
  14. * sge01 09-25-96 Non DDC Moniotr table support
  15. *
  16. * sge02 10-14-96 Detailed timing calculation in EDID
  17. *
  18. * sge03 12-05-96 Only check active pixel clock in detailed timing.
  19. *
  20. --*/
  21. //---------------------------------------------------------------------------
  22. #include <dderror.h>
  23. #include <devioctl.h>
  24. #include <miniport.h>
  25. #include <ntddvdeo.h>
  26. #include <video.h>
  27. #include "cirrus.h"
  28. #define ERROR 0
  29. #define OFF 0
  30. #define ON 1
  31. #define SDA_BIT 2
  32. #define SCL_BIT 1
  33. #define SCL_BIT_ON 1
  34. #define SCL_BIT_OFF 0
  35. #define DELAY_COUNT 255
  36. UCHAR WaitCount ;
  37. UCHAR Err ;
  38. VOID ReadVESATiming(
  39. PHW_DEVICE_EXTENSION HwDeviceExtension
  40. );
  41. VOID EnableDDC(
  42. PHW_DEVICE_EXTENSION HwDeviceExtension
  43. );
  44. BOOLEAN IsDDC2(
  45. PHW_DEVICE_EXTENSION HwDeviceExtension
  46. );
  47. VOID DisableDDC(
  48. PHW_DEVICE_EXTENSION HwDeviceExtension
  49. );
  50. VOID StartDDC(
  51. PHW_DEVICE_EXTENSION HwDeviceExtension
  52. );
  53. VOID StopDDC(
  54. PHW_DEVICE_EXTENSION HwDeviceExtension
  55. );
  56. VOID ProcessDDC2(
  57. PHW_DEVICE_EXTENSION HwDeviceExtension
  58. );
  59. BOOLEAN ReadSDA(
  60. PHW_DEVICE_EXTENSION HwDeviceExtension
  61. );
  62. BOOLEAN ReadSCL(
  63. PHW_DEVICE_EXTENSION HwDeviceExtension
  64. );
  65. BOOLEAN ReadBit(
  66. PHW_DEVICE_EXTENSION HwDeviceExtension
  67. );
  68. BOOLEAN ReadByte(
  69. PHW_DEVICE_EXTENSION HwDeviceExtension
  70. );
  71. VOID SetSCL(
  72. PHW_DEVICE_EXTENSION HwDeviceExtension,
  73. UCHAR status
  74. );
  75. VOID SetData(
  76. PHW_DEVICE_EXTENSION HwDeviceExtension
  77. );
  78. BOOLEAN SetClock(
  79. PHW_DEVICE_EXTENSION HwDeviceExtension
  80. );
  81. VOID WaitVerticalRetrace(
  82. PHW_DEVICE_EXTENSION HwDeviceExtension,
  83. UCHAR count
  84. );
  85. VOID WaitDelay(
  86. PHW_DEVICE_EXTENSION HwDeviceExtension
  87. );
  88. VOID ClearData(
  89. PHW_DEVICE_EXTENSION HwDeviceExtension
  90. );
  91. BOOLEAN SendByte(
  92. PHW_DEVICE_EXTENSION HwDeviceExtension,
  93. UCHAR data
  94. );
  95. BOOLEAN SendDDCCommand(
  96. PHW_DEVICE_EXTENSION HwDeviceExtension
  97. );
  98. BOOLEAN
  99. CheckDDC2BMonitor(
  100. PHW_DEVICE_EXTENSION HwDeviceExtension,
  101. ULONG i
  102. );
  103. ULONG
  104. CalculateMaxinumTiming(
  105. );
  106. VOID ProcessNonDDC(
  107. PHW_DEVICE_EXTENSION HwDeviceExtension
  108. );
  109. VP_STATUS
  110. CirrusNonDDCRegistryCallback(
  111. PVOID HwDeviceExtension,
  112. PVOID Context,
  113. PWSTR ValueName,
  114. PVOID ValueData,
  115. ULONG ValueLength
  116. );
  117. #if defined(ALLOC_PRAGMA)
  118. #pragma alloc_text (PAGE,ReadVESATiming)
  119. #pragma alloc_text (PAGE,EnableDDC)
  120. #pragma alloc_text (PAGE,IsDDC2)
  121. #pragma alloc_text (PAGE,DisableDDC)
  122. #pragma alloc_text (PAGE,StartDDC)
  123. #pragma alloc_text (PAGE,StopDDC)
  124. #pragma alloc_text (PAGE,ProcessDDC2)
  125. #pragma alloc_text (PAGE,ReadSDA)
  126. #pragma alloc_text (PAGE,ReadSCL)
  127. #pragma alloc_text (PAGE,ReadBit)
  128. #pragma alloc_text (PAGE,ReadByte)
  129. #pragma alloc_text (PAGE,SetSCL)
  130. #pragma alloc_text (PAGE,SetData)
  131. #pragma alloc_text (PAGE,SetClock)
  132. #pragma alloc_text (PAGE,WaitVerticalRetrace)
  133. #pragma alloc_text (PAGE,WaitDelay)
  134. #pragma alloc_text (PAGE,ClearData)
  135. #pragma alloc_text (PAGE,SendByte)
  136. #pragma alloc_text (PAGE,SendDDCCommand)
  137. #pragma alloc_text (PAGE,CheckDDC2BMonitor)
  138. #pragma alloc_text (PAGE,CalculateMaxinumTiming)
  139. #pragma alloc_text (PAGE,ProcessNonDDC)
  140. #pragma alloc_text (PAGE,CirrusNonDDCRegistryCallback)
  141. #endif
  142. UCHAR EDIDBuffer[128] ;
  143. UCHAR EDIDTiming_I ;
  144. UCHAR EDIDTiming_II ;
  145. UCHAR EDIDTiming_III ;
  146. UCHAR DDC2BFlag ;
  147. UCHAR NonDDCTable ;
  148. ULONG ulEDIDMaxTiming ;
  149. UCHAR SDAValue ;
  150. /*-------------------------------------------------------------------------*/
  151. VOID EnableDDC (
  152. /*-------------------------------------------------------------------------*/
  153. PHW_DEVICE_EXTENSION HwDeviceExtension
  154. )
  155. {
  156. UCHAR ReadSR08 ;
  157. UCHAR WaitCount = 2 ;
  158. VideoDebugPrint((1, "CLDDC2B!EnableDDC\n"));
  159. VideoPortWritePortUchar (HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  160. 0x08) ;
  161. ReadSR08 = VideoPortReadPortUchar (HwDeviceExtension->IOAddress +
  162. SEQ_DATA_PORT) ;
  163. // Enable DDC2B Configuration
  164. ReadSR08 |= 0x43 ;
  165. VideoPortWritePortUchar (HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
  166. ReadSR08) ;
  167. WaitVerticalRetrace (HwDeviceExtension, WaitCount) ;
  168. } /*----- EnableDDC -----*/
  169. /*-------------------------------------------------------------------------*/
  170. VOID DisableDDC (
  171. /*-------------------------------------------------------------------------*/
  172. PHW_DEVICE_EXTENSION HwDeviceExtension
  173. )
  174. {
  175. UCHAR ReadSEQADDR, ReadSEQDATA ;
  176. UCHAR DDCStatus ;
  177. VideoDebugPrint((1, "CLDDC2B!DisableDDC\n"));
  178. if ((DDCStatus = SendDDCCommand ( HwDeviceExtension )) == 1)
  179. goto DDC_ERROR ;
  180. // i 3c5 ReadSEQDATA
  181. ReadSEQDATA = VideoPortReadPortUchar ( HwDeviceExtension->IOAddress +
  182. SEQ_DATA_PORT ) ;
  183. // Disable DDC2B Configuration
  184. ReadSEQDATA &= 0xBC ;
  185. // o 3c5 ReadSEQDATA
  186. VideoPortWritePortUchar ( HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
  187. ReadSEQDATA ) ;
  188. DDC_ERROR:
  189. return ;
  190. } /*------- DisableDDC -------*/
  191. /*-------------------------------------------------------------------------*/
  192. VOID ProcessDDC2 (
  193. /*-------------------------------------------------------------------------*/
  194. PHW_DEVICE_EXTENSION HwDeviceExtension
  195. )
  196. {
  197. UCHAR DDCStatus, i ;
  198. UCHAR checksum, header ;
  199. VideoDebugPrint((1, "CLDDC2B!ProcessDDC2\n"));
  200. DDC2BFlag = 0 ;
  201. if ((DDCStatus = SendDDCCommand ( HwDeviceExtension )) == 1) {
  202. VideoDebugPrint((0, "CLDDC2B!ProcessDDC2: Infinite wait state ...\n"));
  203. goto PROCESSDDC_EXIT ;
  204. }
  205. for (i = 0; i < 128; i++) {
  206. EDIDBuffer[i] = ReadByte (HwDeviceExtension) ;
  207. if (Err) {
  208. VideoDebugPrint((0, "CLDDC2B!ProcessDDC2: Infinite wait state ...\n"));
  209. goto PROCESSDDC_EXIT ;
  210. }
  211. }
  212. //
  213. // Check EDID table 8-byte header
  214. // The correct first 8 bytes of EDID table is 0x00, 0xFF, 0xFF, 0xFF,
  215. // 0xFF, 0xFF, 0xFF, 0x00
  216. //
  217. if ((EDIDBuffer[0] != 0) ||
  218. (EDIDBuffer[7] != 0)) {
  219. VideoDebugPrint((1, "CLDDC2B: Invalid EDID header table\n"));
  220. StopDDC (HwDeviceExtension) ;
  221. return ;
  222. }
  223. for (i = 1; i < 7; i++) {
  224. if (EDIDBuffer[i] != 0xFF) {
  225. VideoDebugPrint((1, "CLDDC2B: Invalid EDID header table\n"));
  226. StopDDC (HwDeviceExtension) ;
  227. return ;
  228. }
  229. }
  230. //
  231. // Calculate checksum of 128-byte EDID table.
  232. //
  233. checksum = 0x00 ;
  234. for (i = 0; i < 128; i++) {
  235. checksum += EDIDBuffer[i] ;
  236. }
  237. VideoDebugPrint((1, "CLDDC2B: EDID Table check sum = %d\n", checksum));
  238. //
  239. // EDID table checksum must be zero.
  240. //
  241. if (checksum) {
  242. VideoDebugPrint((1, "CLDDC2B: Invalid checksum of EDID table\n"));
  243. }
  244. else
  245. {
  246. //
  247. // Set DDC2B Flag and find timing values.
  248. //
  249. DDC2BFlag = 1 ;
  250. EDIDTiming_I = EDIDBuffer[35] ;
  251. EDIDTiming_II = EDIDBuffer[36] ;
  252. EDIDTiming_III = EDIDBuffer[37] ;
  253. ulEDIDMaxTiming= CalculateMaxinumTiming();
  254. VideoDebugPrint((1, "CLDDC2B: DDC2B is supported\n"));
  255. }
  256. PROCESSDDC_EXIT:
  257. StopDDC (HwDeviceExtension) ;
  258. return ;
  259. } /*------- ProcessDDC2 -------*/
  260. /*-------------------------------------------------------------------------*/
  261. VOID StartDDC (
  262. /*-------------------------------------------------------------------------*/
  263. PHW_DEVICE_EXTENSION HwDeviceExtension
  264. )
  265. {
  266. VideoDebugPrint((1, "DDC2B!StartDDC\n"));
  267. SetSCL (HwDeviceExtension, ON) ;
  268. ClearData (HwDeviceExtension) ;
  269. SetSCL (HwDeviceExtension, OFF) ;
  270. } /*------- StartDDC -------*/
  271. /*-------------------------------------------------------------------------*/
  272. VOID StopDDC (
  273. /*-------------------------------------------------------------------------*/
  274. PHW_DEVICE_EXTENSION HwDeviceExtension
  275. )
  276. {
  277. VideoDebugPrint((1, "DDC2B!StopDDC\n"));
  278. SetSCL (HwDeviceExtension, ON) ;
  279. SetData (HwDeviceExtension) ;
  280. } /*------- StopDDC -------*/
  281. /*-------------------------------------------------------------------------*/
  282. BOOLEAN ReadSCL (
  283. /*-------------------------------------------------------------------------*/
  284. PHW_DEVICE_EXTENSION HwDeviceExtension
  285. )
  286. {
  287. UCHAR ReadSEQDATA, status ;
  288. // i 3c5 ReadSEQDATA
  289. ReadSEQDATA = VideoPortReadPortUchar ( HwDeviceExtension->IOAddress +
  290. SEQ_DATA_PORT ) ;
  291. // Read SR08.B2
  292. ReadSEQDATA = ( (ReadSEQDATA) & 0x04 ) >> 2 ;
  293. return (ReadSEQDATA) ;
  294. } /*------- ReadSCL -------*/
  295. /*-------------------------------------------------------------------------*/
  296. VOID SetSCL(
  297. /*-------------------------------------------------------------------------*/
  298. PHW_DEVICE_EXTENSION HwDeviceExtension,
  299. UCHAR status
  300. )
  301. {
  302. UCHAR ReadSEQADDR, ReadSEQDATA ;
  303. // i 3c5 ReadSEQDATA
  304. ReadSEQDATA = VideoPortReadPortUchar (HwDeviceExtension->IOAddress +
  305. SEQ_DATA_PORT) ;
  306. ReadSEQDATA = ( ( ReadSEQDATA & 0xFE ) | status ) ;
  307. // o 3c5 ReadSEQDATA
  308. VideoPortWritePortUchar (HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
  309. ReadSEQDATA) ;
  310. WaitDelay (HwDeviceExtension) ;
  311. } /*------- SetSCL -------*/
  312. /*-------------------------------------------------------------------------*/
  313. BOOLEAN ReadSDA (
  314. /*-------------------------------------------------------------------------*/
  315. PHW_DEVICE_EXTENSION HwDeviceExtension
  316. )
  317. {
  318. UCHAR ReadSEQADDR, ReadSEQDATA ;
  319. // i 3c5 ReadSEQDATA
  320. ReadSEQDATA = VideoPortReadPortUchar (HwDeviceExtension->IOAddress +
  321. SEQ_DATA_PORT) ;
  322. ReadSEQDATA = ( ReadSEQDATA & 0x80 ) >> 7 ;
  323. return ( ReadSEQDATA ) ;
  324. } /*------- ReadSDA -------*/
  325. /*-------------------------------------------------------------------------*/
  326. VOID ClearData
  327. /*-------------------------------------------------------------------------*/
  328. (
  329. PHW_DEVICE_EXTENSION HwDeviceExtension
  330. )
  331. {
  332. UCHAR ReadSEQADDR, ReadSEQDATA ;
  333. // i 3c5 ReadSEQDATA
  334. ReadSEQDATA = VideoPortReadPortUchar (HwDeviceExtension->IOAddress +
  335. SEQ_DATA_PORT) ;
  336. ReadSEQDATA &= 0xFD ;
  337. // o 3c5 ReadSEQDATA
  338. VideoPortWritePortUchar (HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
  339. ReadSEQDATA) ;
  340. WaitDelay (HwDeviceExtension) ;
  341. } /*------- ClearData -------*/
  342. /*-------------------------------------------------------------------------*/
  343. VOID SetData
  344. /*-------------------------------------------------------------------------*/
  345. (
  346. PHW_DEVICE_EXTENSION HwDeviceExtension
  347. )
  348. {
  349. UCHAR ReadSEQADDR, ReadSEQDATA ;
  350. // i 3c5 ReadSEQDATA
  351. ReadSEQDATA = VideoPortReadPortUchar (HwDeviceExtension->IOAddress +
  352. SEQ_DATA_PORT) ;
  353. ReadSEQDATA |= 0x02 ;
  354. // o 3c5 ReadSEQDATA
  355. VideoPortWritePortUchar (HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
  356. ReadSEQDATA) ;
  357. WaitDelay (HwDeviceExtension) ;
  358. } /*------- SetData -------*/
  359. /*-------------------------------------------------------------------------*/
  360. BOOLEAN SetClock
  361. /*-------------------------------------------------------------------------*/
  362. (
  363. PHW_DEVICE_EXTENSION HwDeviceExtension
  364. )
  365. {
  366. ULONG i ;
  367. UCHAR status ;
  368. SetSCL (HwDeviceExtension, ON) ;
  369. for (i = 0; i < DELAY_COUNT; i++)
  370. status = ReadSCL (HwDeviceExtension) ;
  371. SetSCL (HwDeviceExtension, OFF) ;
  372. if (!status)
  373. VideoDebugPrint((0, "DDC2B!SetClock: Infinite wait state ...\n"));
  374. if (status == 1)
  375. return ( FALSE ) ; // retuern 0 -> OK
  376. else
  377. return ( TRUE ) ; // retuern 1 -> Infinite wait state
  378. } /*------- SetClock -------*/
  379. /*-------------------------------------------------------------------------*/
  380. BOOLEAN ReadBit
  381. /*-------------------------------------------------------------------------*/
  382. (
  383. PHW_DEVICE_EXTENSION HwDeviceExtension
  384. )
  385. {
  386. USHORT i ;
  387. UCHAR bit ;
  388. SetSCL (HwDeviceExtension, ON) ;
  389. for (i = 0; i < DELAY_COUNT; i++)
  390. ReadSCL (HwDeviceExtension) ;
  391. bit = ReadSDA (HwDeviceExtension) ;
  392. SetSCL (HwDeviceExtension, OFF) ;
  393. return ( bit ) ;
  394. } /*------- ReadBit -------*/
  395. /*-------------------------------------------------------------------------*/
  396. BOOLEAN ReadByte
  397. /*-------------------------------------------------------------------------*/
  398. (
  399. PHW_DEVICE_EXTENSION HwDeviceExtension
  400. )
  401. {
  402. UCHAR ReadByteValue, bit, i ;
  403. SetData ( HwDeviceExtension ) ;
  404. ReadByteValue = 0 ;
  405. for (i = 0; i < 8; i++) {
  406. ReadByteValue <<= 1 ;
  407. bit = ReadBit ( HwDeviceExtension ) ;
  408. ReadByteValue |= bit ;
  409. }
  410. if ((bit & 0x02) != 0) {
  411. SetData ( HwDeviceExtension ) ;
  412. } else {
  413. ClearData ( HwDeviceExtension ) ;
  414. }
  415. SetClock ( HwDeviceExtension ) ;
  416. SetData ( HwDeviceExtension ) ;
  417. return (ReadByteValue) ;
  418. } /*----- ReadByte -----*/
  419. /*-------------------------------------------------------------------------*/
  420. BOOLEAN SendByte (
  421. /*-------------------------------------------------------------------------*/
  422. PHW_DEVICE_EXTENSION HwDeviceExtension,
  423. UCHAR data
  424. )
  425. {
  426. UCHAR i ;
  427. UCHAR Mask[8] = { 0x80, 0x40, 0x20, 0x10,
  428. 0x08, 0x04, 0x02, 0x01 } ;
  429. for (i = 0; i < 8; i++)
  430. {
  431. if (data & Mask[i]) {
  432. SetData ( HwDeviceExtension ) ;
  433. } else {
  434. ClearData ( HwDeviceExtension ) ;
  435. }
  436. Err = SetClock ( HwDeviceExtension ) ;
  437. }
  438. if (Err) {
  439. SetSCL ( HwDeviceExtension, OFF ) ;
  440. ClearData (HwDeviceExtension) ;
  441. } else {
  442. SetData ( HwDeviceExtension ) ;
  443. SetSCL ( HwDeviceExtension, ON ) ;
  444. ReadBit ( HwDeviceExtension ) ; // Discard acknowledge bit
  445. }
  446. return (Err) ;
  447. } /*------- SendByte -------*/
  448. /*-------------------------------------------------------------------------*/
  449. BOOLEAN IsDDC2
  450. /*-------------------------------------------------------------------------*/
  451. (
  452. PHW_DEVICE_EXTENSION HwDeviceExtension
  453. )
  454. {
  455. UCHAR DDCStatus, SCLStatus ;
  456. VideoDebugPrint((1, "DDC2B!IsDDC2\n"));
  457. SetSCL (HwDeviceExtension, OFF) ;
  458. SCLStatus = ReadSCL(HwDeviceExtension) ;
  459. if (SCLStatus != 0) {
  460. return ( FALSE ) ;
  461. }
  462. SetSCL (HwDeviceExtension, ON) ;
  463. SCLStatus = ReadSCL (HwDeviceExtension) ;
  464. if (SCLStatus != 1) {
  465. return ( FALSE ) ;
  466. }
  467. return ( TRUE ) ;
  468. } /*------- IsDDC2 -------*/
  469. /*-------------------------------------------------------------------------*/
  470. BOOLEAN SendDDCCommand
  471. /*-------------------------------------------------------------------------*/
  472. (
  473. PHW_DEVICE_EXTENSION HwDeviceExtension
  474. )
  475. {
  476. UCHAR ClockStatus ;
  477. VideoDebugPrint((1, "DDC2B!SendDDCCommand\n"));
  478. StartDDC ( HwDeviceExtension ) ;
  479. ClockStatus = SendByte ( HwDeviceExtension, 0xA0 ) ;
  480. if (ClockStatus)
  481. VideoDebugPrint((0, "DDC2B!SendDDCCommand: Infinite wait state ...\n"));
  482. ClockStatus = SendByte ( HwDeviceExtension, 0x00 ) ;
  483. if (ClockStatus)
  484. VideoDebugPrint((0, "DDC2B!SendDDCCommand: Infinite wait state ...\n"));
  485. StopDDC ( HwDeviceExtension ) ;
  486. StartDDC ( HwDeviceExtension ) ;
  487. ClockStatus = SendByte ( HwDeviceExtension, 0xA1 ) ;
  488. if (ClockStatus)
  489. VideoDebugPrint((0, "DDC2B!SendDDCCommand: Infinite wait state ...\n"));
  490. SetData ( HwDeviceExtension ) ;
  491. return (ClockStatus) ;
  492. } /*------- SendDDCCommand -------*/
  493. /*-------------------------------------------------------------------------*/
  494. VOID WaitDelay
  495. /*-------------------------------------------------------------------------*/
  496. (
  497. PHW_DEVICE_EXTENSION HwDeviceExtension
  498. )
  499. {
  500. PUCHAR InStatPort ;
  501. //
  502. // Set up port addresses for color/mono
  503. //
  504. if (VideoPortReadPortUchar (HwDeviceExtension->IOAddress +
  505. MISC_OUTPUT_REG_READ_PORT) & 0x01) {
  506. InStatPort = HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR ;
  507. } else {
  508. InStatPort = HwDeviceExtension->IOAddress + INPUT_STATUS_1_MONO ;
  509. }
  510. while ((VideoPortReadPortUchar (InStatPort) & 0x01) != 0) ;
  511. while ((VideoPortReadPortUchar (InStatPort) & 0x01) == 0) ;
  512. while ((VideoPortReadPortUchar (InStatPort) & 0x01) != 0) ;
  513. } /*------- wait_delay -------*/
  514. /*-------------------------------------------------------------------------*/
  515. VOID WaitVerticalRetrace
  516. /*-------------------------------------------------------------------------*/
  517. (
  518. PHW_DEVICE_EXTENSION HwDeviceExtension,
  519. UCHAR waitcount
  520. )
  521. {
  522. PUCHAR InStatPort ;
  523. ULONG i ;
  524. //
  525. // Set up port addresses for color/mono
  526. //
  527. if (VideoPortReadPortUchar (HwDeviceExtension->IOAddress +
  528. MISC_OUTPUT_REG_READ_PORT) & 0x01) {
  529. InStatPort = INPUT_STATUS_1_COLOR + HwDeviceExtension->IOAddress;
  530. } else {
  531. InStatPort = INPUT_STATUS_1_MONO + HwDeviceExtension->IOAddress;
  532. }
  533. for (i = 0; i < waitcount; i++)
  534. {
  535. while ((VideoPortReadPortUchar (InStatPort) & 0x08) != 0) ;
  536. while ((VideoPortReadPortUchar (InStatPort) & 0x08) == 0) ;
  537. }
  538. } /*------- WaitVerticalRetrace -------*/
  539. /*-------------------------------------------------------------------------*/
  540. VOID ReadVESATiming
  541. /*-------------------------------------------------------------------------*/
  542. (
  543. PHW_DEVICE_EXTENSION HwDeviceExtension
  544. )
  545. {
  546. UCHAR status ;
  547. VideoDebugPrint((1, "DDC2B!ReadVESATiming\n"));
  548. #if 1 // NonDDC #sge
  549. //
  550. // clear flag.
  551. //
  552. NonDDCTable = 0;
  553. DDC2BFlag = 0;
  554. #endif
  555. EnableDDC (HwDeviceExtension) ;
  556. if ((status = IsDDC2 (HwDeviceExtension)) != 0x00) {
  557. ProcessDDC2 (HwDeviceExtension) ;
  558. }
  559. #if 1 // NonDDC #sge
  560. if(!DDC2BFlag)
  561. ProcessNonDDC(HwDeviceExtension);
  562. #endif
  563. DisableDDC (HwDeviceExtension) ;
  564. return ;
  565. } /*----- ReadVESATiming -----*/
  566. BOOLEAN
  567. CheckDDC2BMonitor(
  568. PHW_DEVICE_EXTENSION HwDeviceExtension,
  569. ULONG i
  570. )
  571. /*++
  572. Routine Description:
  573. Determines if refresh rate support according to DDC2B standard.
  574. Arguments:
  575. HwDeviceExtension - Pointer to the miniport driver's device extension.
  576. Return Value:
  577. None.
  578. --*/
  579. {
  580. ULONG ulCurrTiming ;
  581. #if 1 // NonDDC #sge
  582. if (!DDC2BFlag && !NonDDCTable)
  583. return TRUE ;
  584. #else
  585. if (!DDC2BFlag)
  586. return TRUE ;
  587. #endif
  588. VideoDebugPrint((4, "CheckDDC2B\n"));
  589. VideoDebugPrint((4, "refresh rate = %ld\n", ModesVGA[i].Frequency));
  590. VideoDebugPrint((4, "hres = %d\n", ModesVGA[i].hres));
  591. VideoDebugPrint((4, "vres = %d\n", ModesVGA[i].vres));
  592. ulCurrTiming = ModesVGA[i].Frequency *
  593. ModesVGA[i].hres *
  594. ModesVGA[i].vres ;
  595. VideoDebugPrint((4, "ulCurrTiming = %d\n", ulCurrTiming)) ;
  596. VideoDebugPrint((4, "ulEDIDMaxTiming = %d\n", ulEDIDMaxTiming)) ;
  597. if ( ulCurrTiming > ulEDIDMaxTiming )
  598. return FALSE ;
  599. else
  600. return TRUE ;
  601. } // end of CheckDDC2bMonitor
  602. ULONG
  603. CalculateMaxinumTiming(
  604. )
  605. /*++
  606. Routine Description:
  607. Determines maximum allowablt VESA timing value.
  608. Arguments:
  609. None.
  610. Return Value:
  611. None.
  612. --*/
  613. {
  614. ULONG current_timing_value ;
  615. ULONG freq ;
  616. SHORT i ;
  617. USHORT usHzActive, usHzBlanking, usVtActive, usVtBlanking;
  618. ULONG maximum_allowable_timing_value = ulEDIDMaxTiming;
  619. VideoDebugPrint((1, "CLDDC2B: CalculateMaxinumTiming\n")) ;
  620. //
  621. // Calculate established timing values
  622. //
  623. /* 720 * 400 * 70 = 20160000 */
  624. if ( EDIDTiming_I & 0x80 ) {
  625. VideoDebugPrint((1, "CLDDC2B: 720 * 400 * 70\n")) ;
  626. if (maximum_allowable_timing_value < ((ULONG) 20160000)) {
  627. maximum_allowable_timing_value = ((ULONG) 20160000) ;
  628. }
  629. }
  630. /* 720 * 400 * 88 = 25344000 */
  631. if ( EDIDTiming_I & 0x40 ) {
  632. VideoDebugPrint((1, "CLDDC2B: 720 * 400 * 88\n")) ;
  633. if (maximum_allowable_timing_value < ((ULONG) 25344000)) {
  634. maximum_allowable_timing_value = ((ULONG) 25344000) ;
  635. }
  636. }
  637. /* 640 * 480 * 60 = 18432000 */
  638. if ( EDIDTiming_I & 0x20 ) {
  639. VideoDebugPrint((1, "CLDDC2B: 640 * 480 * 60\n"));
  640. if (maximum_allowable_timing_value < ((ULONG) 18432000)) {
  641. maximum_allowable_timing_value = ((ULONG) 18432000) ;
  642. }
  643. }
  644. /* 640 * 480 * 67 = 20582400 */
  645. if ( EDIDTiming_I & 0x10 ) {
  646. VideoDebugPrint((1, "CLDDC2B: 640 * 480 * 67\n"));
  647. if (maximum_allowable_timing_value < ((ULONG) 20582400)) {
  648. maximum_allowable_timing_value = ((ULONG) 20582400) ;
  649. }
  650. }
  651. /* 640 * 480 * 72 = 22118400 */
  652. if ( EDIDTiming_I & 0x08 ) {
  653. VideoDebugPrint((1, "CLDDC2B: 640 * 480 * 72\n"));
  654. if (maximum_allowable_timing_value < ((ULONG) 22118400)) {
  655. maximum_allowable_timing_value = ((ULONG) 22118400) ;
  656. }
  657. }
  658. /* 640 * 480 * 75 = 23040000 */
  659. if ( EDIDTiming_I & 0x04 ) {
  660. VideoDebugPrint((1, "CLDDC2B: 640 * 480 * 75\n"));
  661. if (maximum_allowable_timing_value < ((ULONG) 23040000)) {
  662. maximum_allowable_timing_value = ((ULONG) 23040000) ;
  663. }
  664. }
  665. /* 800 * 600 * 56 = 26880000 */
  666. if ( EDIDTiming_I & 0x02 ) {
  667. VideoDebugPrint((1, "CLDDC2B: 800 * 600 * 56\n"));
  668. if (maximum_allowable_timing_value < ((ULONG) 26880000)) {
  669. maximum_allowable_timing_value = ((ULONG) 26880000) ;
  670. }
  671. }
  672. /* 800 * 600 * 60 = 28800000 */
  673. if ( EDIDTiming_I & 0x01 ) {
  674. VideoDebugPrint((1, "CLDDC2B: 800 * 600 * 60\n"));
  675. if (maximum_allowable_timing_value < ((ULONG) 28800000)) {
  676. maximum_allowable_timing_value = ((ULONG) 28800000) ;
  677. }
  678. }
  679. /* 800 * 600 * 72 = 34560000 */
  680. if ( EDIDTiming_II & 0x80 ) {
  681. VideoDebugPrint((1, "CLDDC2B: 800 * 600 * 72\n"));
  682. if (maximum_allowable_timing_value < ((ULONG) 34560000)) {
  683. maximum_allowable_timing_value = ((ULONG) 34560000) ;
  684. }
  685. }
  686. /* 800 * 600 * 75 = 36000000 */
  687. if ( EDIDTiming_II & 0x40 ) {
  688. VideoDebugPrint((1, "CLDDC2B: 800 * 600 * 75\n"));
  689. if (maximum_allowable_timing_value < ((ULONG) 36000000)) {
  690. maximum_allowable_timing_value = ((ULONG) 36000000) ;
  691. }
  692. }
  693. /* 832 * 624 * 75 = 38937600 */
  694. if ( EDIDTiming_II & 0x20 ) {
  695. VideoDebugPrint((1, "CLDDC2B: 832 * 624 * 75\n"));
  696. if (maximum_allowable_timing_value < ((ULONG) 38937600)) {
  697. maximum_allowable_timing_value = ((ULONG) 38937600) ;
  698. }
  699. }
  700. /* 1024 * 768 * 43 = 33816576 */
  701. if ( EDIDTiming_II & 0x10 ) {
  702. VideoDebugPrint((1, "CLDDC2B: 1024 * 768 * 43\n"));
  703. if (maximum_allowable_timing_value < ((ULONG) 33816576)) {
  704. maximum_allowable_timing_value = ((ULONG) 33816576) ;
  705. }
  706. }
  707. /* 1024 * 768 * 60 = 47185920 */
  708. if ( EDIDTiming_II & 0x08 ) {
  709. VideoDebugPrint((1, "CLDDC2B: 1024 * 768 * 60\n"));
  710. if (maximum_allowable_timing_value < ((ULONG) 47185920)) {
  711. maximum_allowable_timing_value = ((ULONG) 47185920) ;
  712. }
  713. }
  714. /* 1024 * 768 * 70 = 55050240 */
  715. if ( EDIDTiming_II & 0x04 ) {
  716. VideoDebugPrint((1, "CLDDC2B: 1024 * 768 * 70\n"));
  717. if (maximum_allowable_timing_value < ((ULONG) 55050240)) {
  718. maximum_allowable_timing_value = ((ULONG) 55050240) ;
  719. }
  720. }
  721. /* 1024 * 768 * 75 = 58982400 */
  722. if ( EDIDTiming_II & 0x02 ) {
  723. VideoDebugPrint((1, "CLDDC2B: 1024 * 768 * 75\n"));
  724. if (maximum_allowable_timing_value < ((ULONG) 58982400)) {
  725. maximum_allowable_timing_value = ((ULONG) 58982400) ;
  726. }
  727. }
  728. /* 1280 * 1024 * 75 = 98304000 */
  729. if ( EDIDTiming_II & 0x01 ) {
  730. VideoDebugPrint((1, "CLDDC2B: 1280 * 1024 * 75\n"));
  731. if (maximum_allowable_timing_value < ((ULONG) 98304000)) {
  732. maximum_allowable_timing_value = ((ULONG) 98304000) ;
  733. }
  734. }
  735. /* 1152 * 870 * 75 = 75168000 */
  736. if ( EDIDTiming_III & 0x80 ) {
  737. VideoDebugPrint((1, "CLDDC2B: 1152 * 870 * 75\n"));
  738. if (maximum_allowable_timing_value < ((ULONG) 75168000)) {
  739. maximum_allowable_timing_value = ((ULONG) 75168000) ;
  740. }
  741. }
  742. //
  743. // Calculate standard timing values
  744. //
  745. for ( i = 0x26 ; i <= 0x35 ; i+=2 ) {
  746. current_timing_value = 0L ;
  747. freq = ( EDIDBuffer[i+1] & 0x3F ) + 60 ;
  748. switch ( EDIDBuffer[i] ) {
  749. case 0x31 : // 640 * 480 = 307200
  750. current_timing_value = ((ULONG) freq) * 307200 ;
  751. VideoDebugPrint((1, "CLDDC2B: 640 * 480 * %d\n", freq));
  752. break ;
  753. case 0x3B : // 720 * 400 = 288000
  754. current_timing_value = ((ULONG) freq) * 288000 ;
  755. VideoDebugPrint((1, "CLDDC2B: 640 * 480 * %d\n", freq));
  756. break ;
  757. case 0x45 : // 800 * 600 = 480000
  758. current_timing_value = ((ULONG) freq) * 480000 ;
  759. VideoDebugPrint((1, "CLDDC2B: 800 * 600 * %d\n", freq));
  760. break ;
  761. case 0x61 : // 1024 * 768 = 786432
  762. current_timing_value = ((ULONG) freq) * 786432 ;
  763. VideoDebugPrint((1, "CLDDC2B: 1024 * 768 * %d\n", freq));
  764. break ;
  765. case 0x71 : // 1152 * 870 = 1002240
  766. current_timing_value = ((ULONG) freq) * 1002240 ;
  767. VideoDebugPrint((1, "CLDDC2B: 1152 * 870 * %d\n", freq));
  768. break ;
  769. case 0x81 : // 1280 * 1024 = 1310720
  770. current_timing_value = ((ULONG) freq) * 1310720 ;
  771. VideoDebugPrint((1, "CLDDC2B: 1280 * 1024 * %d\n", freq));
  772. break ;
  773. case 0xA9 : // 1600 * 1200 = 1920000
  774. current_timing_value = ((ULONG) freq) * 1920000 ;
  775. VideoDebugPrint((1, "CLDDC2B: 1600 * 1200 * %d\n", freq));
  776. break ;
  777. default :
  778. ;
  779. }
  780. if (maximum_allowable_timing_value < current_timing_value)
  781. maximum_allowable_timing_value = current_timing_value ;
  782. }
  783. // sge02
  784. //
  785. // Calculate detailed timing values
  786. //
  787. for ( i = 0x36 ; i <= 0x7D; i+=18 )
  788. {
  789. current_timing_value = EDIDBuffer[i] ;
  790. current_timing_value += EDIDBuffer[i+1] * 256;
  791. //
  792. // Validation.
  793. //
  794. // sge03
  795. if (current_timing_value <= 0x0101 )
  796. continue;
  797. current_timing_value *= 10000;
  798. //
  799. // Calculate Horizontal Active and Blanking
  800. //
  801. usHzActive = (EDIDBuffer[i+4] & 0xf0);
  802. usHzActive <<= 4;
  803. usHzActive |= EDIDBuffer[i+2];
  804. usHzBlanking = (EDIDBuffer[i+4] & 0x0f);
  805. usHzBlanking <<= 8;
  806. usHzBlanking |= EDIDBuffer[i+3];
  807. //
  808. // Calculate Vertical Active and Blanking
  809. //
  810. usVtActive = (EDIDBuffer[i+7] & 0xf0);
  811. usVtActive <<= 4;
  812. usVtActive |= EDIDBuffer[i+5];
  813. usVtBlanking = (EDIDBuffer[i+7] & 0x0f);
  814. usVtBlanking <<= 8;
  815. usVtBlanking |= EDIDBuffer[i+6];
  816. current_timing_value = (current_timing_value + usHzActive + usHzBlanking - 1) / (usHzActive + usHzBlanking);
  817. current_timing_value = (current_timing_value + usVtActive + usVtBlanking - 1) / (usVtActive + usVtBlanking);
  818. current_timing_value *= usHzActive;
  819. current_timing_value *= usVtActive;
  820. if (maximum_allowable_timing_value < current_timing_value)
  821. maximum_allowable_timing_value = current_timing_value ;
  822. }
  823. return (maximum_allowable_timing_value);
  824. } // end of CalculateMaxinumTiming
  825. //---------------------------------------------------------------------------
  826. //
  827. // Function:
  828. // Read NonDDC Table from Registry and Set NonDDCTable Flag.
  829. //
  830. // Input:
  831. // HwDeviceExtension - Pointer to the miniport driver's device extension.
  832. //
  833. // Output:
  834. // None
  835. //
  836. //---------------------------------------------------------------------------
  837. VOID ProcessNonDDC(
  838. PHW_DEVICE_EXTENSION HwDeviceExtension
  839. )
  840. {
  841. ULONG i ;
  842. VideoDebugPrint((1, "NonDDC!ProcessNonDDC\n"));
  843. NonDDCTable = 0 ;
  844. if (NO_ERROR == VideoPortGetRegistryParameters(HwDeviceExtension,
  845. L"NonDDCMonitor.Data",
  846. FALSE,
  847. CirrusNonDDCRegistryCallback,
  848. NULL))
  849. {
  850. //
  851. // We got the table
  852. //
  853. //
  854. // Check EDID table 8-byte header
  855. // The correct first 8 bytes of EDID table is 0x00, 0xFF, 0xFF, 0xFF,
  856. // 0xFF, 0xFF, 0xFF, 0x00
  857. //
  858. if ((EDIDBuffer[0] != 0) ||
  859. (EDIDBuffer[7] != 0))
  860. {
  861. VideoDebugPrint((1, "CLNonDDC: Invalid EDID header table\n"));
  862. return ;
  863. }
  864. for (i = 1; i < 7; i++)
  865. {
  866. if (EDIDBuffer[i] != 0xFF)
  867. {
  868. VideoDebugPrint((1, "CLNonDDC: Invalid EDID header table\n"));
  869. return ;
  870. }
  871. }
  872. //
  873. // Set NonDDCTable Flag and find timing values.
  874. //
  875. NonDDCTable = 1 ;
  876. EDIDTiming_I = EDIDBuffer[35] ;
  877. EDIDTiming_II = EDIDBuffer[36] ;
  878. EDIDTiming_III = EDIDBuffer[37] ;
  879. ulEDIDMaxTiming= CalculateMaxinumTiming();
  880. VideoDebugPrint((1, "NonDDC: NonDDC is supported\n"));
  881. }
  882. } // end of ProcessNonDDC