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.

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