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.

290 lines
7.8 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. ddc.c
  5. Abstract:
  6. This module contains the code that support DDC querying..
  7. Environment:
  8. Kernel mode
  9. Revision History:
  10. --*/
  11. #include "s3.h"
  12. #include "s3ddc.h"
  13. #if defined(ALLOC_PRAGMA)
  14. #pragma alloc_text(PAGE,GetDdcInformation)
  15. #endif
  16. VOID WriteClockLine(PHW_DEVICE_EXTENSION HwDeviceExtension, UCHAR ucData);
  17. VOID WriteDataLine(PHW_DEVICE_EXTENSION HwDeviceExtension, UCHAR ucData);
  18. BOOLEAN ReadClockLine(PHW_DEVICE_EXTENSION HwDeviceExtension);
  19. BOOLEAN ReadDataLine(PHW_DEVICE_EXTENSION HwDeviceExtension);
  20. VOID WaitForVsyncActive(PHW_DEVICE_EXTENSION HwDeviceExtension);
  21. /****************************************************************
  22. ; DDC register
  23. ;
  24. ; Controls the individual toggling of bits in MMFF20 to produce
  25. ; clock and data pulses, and in the end provides a delay.
  26. ;
  27. ; MMIO FF20h is defined as follows:
  28. ;
  29. ; ... 3 2 1 0 SCW = CLK Write
  30. ; --------|---|---|---|---| SDW = DATA Write
  31. ; ...|SDR|SCR|SDW|SCW| SCR = CLK Read
  32. ; ------------------------- SDR = DATA Read
  33. ;
  34. ; Input:
  35. ; Using MMIO Base in PHW_DEVICE_EXTENSION
  36. ; UCHAR ucData
  37. ; Bit 7:2 = 0
  38. ; Bit 1 = SDA
  39. ; Bit 0 = SCL
  40. ; Output:
  41. ;
  42. ;****************************************************************/
  43. VOID WriteClockLine(PHW_DEVICE_EXTENSION HwDeviceExtension, UCHAR ucData)
  44. {
  45. UCHAR ucPortData;
  46. //
  47. // read the current value and reset the clock line.
  48. //
  49. ucPortData = (VideoPortReadRegisterUchar(MMFF20) & 0xFE) | ucData;
  50. VideoPortWriteRegisterUchar(MMFF20, ucPortData);
  51. }
  52. VOID WriteDataLine(PHW_DEVICE_EXTENSION HwDeviceExtension, UCHAR ucData)
  53. {
  54. UCHAR ucPortData;
  55. //
  56. // read the current value and reset the data line.
  57. //
  58. ucPortData = (VideoPortReadRegisterUchar(MMFF20) & 0xFD) | (ucData << 1);
  59. VideoPortWriteRegisterUchar(MMFF20, ucPortData);
  60. }
  61. BOOLEAN ReadClockLine(PHW_DEVICE_EXTENSION HwDeviceExtension)
  62. {
  63. return ((VideoPortReadRegisterUchar(MMFF20) & 0x04) >> 2);
  64. }
  65. BOOLEAN ReadDataLine(PHW_DEVICE_EXTENSION HwDeviceExtension)
  66. {
  67. return ((VideoPortReadRegisterUchar(MMFF20) & 0x08) >> 3);
  68. }
  69. VOID WaitForVsyncActive(PHW_DEVICE_EXTENSION HwDeviceExtension)
  70. {
  71. PUCHAR InStatPort = SYSTEM_CONTROL_REG;
  72. while ((VideoPortReadPortUchar(InStatPort) & VSYNC_ACTIVE) != 0) ;
  73. while ((VideoPortReadPortUchar(InStatPort) & VSYNC_ACTIVE) == 0) ;
  74. }
  75. BOOLEAN
  76. GetDdcInformation(
  77. PHW_DEVICE_EXTENSION HwDeviceExtension,
  78. PUCHAR QueryBuffer,
  79. ULONG BufferSize)
  80. /*++
  81. Routine Description:
  82. Reads the basic EDID structure from the monitor using DDC2.
  83. Arguments:
  84. HwDeviceExtension - Points to per-adapter device extension.
  85. QueryBuffer - Buffer where information will be stored.
  86. BufferSize - Size of the buffer to fill.
  87. Return Value:
  88. Whether the call succeeded or not.
  89. --*/
  90. {
  91. ULONG ulKey;
  92. UCHAR ucOldCr40;
  93. UCHAR ucOldCr53;
  94. UCHAR ucOldCr55;
  95. UCHAR ucOldCr5C;
  96. UCHAR ucOldSr0D;
  97. UCHAR ucOldSr08;
  98. UCHAR ucOldSeqIdx;
  99. UCHAR ucOldMMFF20;
  100. UCHAR ucData;
  101. BOOLEAN bRet = FALSE;
  102. I2C_FNC_TABLE i2c;
  103. ULONG i;
  104. //
  105. // Right now we only support DDC querying for newer than 732
  106. //
  107. if (HwDeviceExtension->SubTypeID == SUBTYPE_765) {
  108. //
  109. // unlock the Extended registers
  110. //
  111. ulKey = UnlockExtendedRegs(HwDeviceExtension);
  112. //
  113. // save the Sequencer index register
  114. //
  115. ucOldSeqIdx = VideoPortReadPortUchar (SEQ_ADDRESS_REG);
  116. //
  117. // unlock the Sequencer registers
  118. //
  119. VideoPortWritePortUchar (SEQ_ADDRESS_REG, UNLOCK_SEQREG);
  120. ucOldSr08 = VideoPortReadPortUchar (SEQ_DATA_REG);
  121. VideoPortWritePortUchar (SEQ_DATA_REG, UNLOCK_SEQ);
  122. VideoPortWritePortUchar (SEQ_ADDRESS_REG, SRD_SEQREG);
  123. ucOldSr0D = ucData = VideoPortReadPortUchar (SEQ_DATA_REG);
  124. ucData &= DISAB_FEATURE_BITS; // Disable feature connector
  125. VideoPortWritePortUchar (SEQ_DATA_REG, ucData);
  126. //
  127. // Enable access to the enhanced registers
  128. //
  129. VideoPortWritePortUchar (CRT_ADDRESS_REG, SYS_CONFIG_S3EXTREG);
  130. ucOldCr40 = ucData = VideoPortReadPortUchar (CRT_DATA_REG);
  131. ucData |= ENABLE_ENH_REG_ACCESS;
  132. VideoPortWritePortUchar (CRT_DATA_REG, ucData);
  133. //
  134. // Enable MMIO
  135. //
  136. VideoPortWritePortUchar (CRT_ADDRESS_REG, EXT_MEM_CTRL1_S3EXTREG);
  137. ucOldCr53 = ucData = VideoPortReadPortUchar (CRT_DATA_REG);
  138. ucData &= ~ENABLE_OLDMMIO;
  139. ucData |= ENABLE_NEWMMIO;
  140. VideoPortWritePortUchar (CRT_DATA_REG, ucData);
  141. //
  142. // GOP_1:0=00b, select MUX channel 0
  143. //
  144. VideoPortWritePortUchar (CRT_ADDRESS_REG, GENERAL_OUT_S3EXTREG);
  145. ucOldCr5C = ucData = VideoPortReadPortUchar (CRT_DATA_REG);
  146. ucData |= 0x03;
  147. VideoPortWritePortUchar (CRT_DATA_REG, ucData);
  148. //
  149. // enable general input port
  150. //
  151. VideoPortWritePortUchar (CRT_ADDRESS_REG, EXT_DAC_S3EXTREG);
  152. ucOldCr55 = VideoPortReadPortUchar (CRT_DATA_REG);
  153. //
  154. // Map the MmIoSpace so that we can use it in DDC detectin.
  155. //
  156. HwDeviceExtension->MmIoBase =
  157. VideoPortGetDeviceBase(HwDeviceExtension,
  158. HwDeviceExtension->PhysicalMmIoAddress,
  159. HwDeviceExtension->MmIoLength,
  160. 0);
  161. if (HwDeviceExtension->MmIoBase) {
  162. //
  163. // enable the serial port
  164. //
  165. ucOldMMFF20 = VideoPortReadRegisterUchar (MMFF20);
  166. VideoPortWriteRegisterUchar (MMFF20, 0x13);
  167. //
  168. // Get DDC Information if all the registers are setup properly.
  169. //
  170. i2c.WriteClockLine = WriteClockLine;
  171. i2c.WriteDataLine = WriteDataLine;
  172. i2c.ReadClockLine = ReadClockLine;
  173. i2c.ReadDataLine = ReadDataLine;
  174. i2c.WaitVsync = WaitForVsyncActive;
  175. i2c.Size = sizeof(I2C_FNC_TABLE);
  176. bRet = VideoPortDDCMonitorHelper(HwDeviceExtension,
  177. &i2c,
  178. QueryBuffer,
  179. BufferSize);
  180. //
  181. // restore the original register values
  182. //
  183. VideoPortWriteRegisterUchar (MMFF20, ucOldMMFF20);
  184. VideoPortFreeDeviceBase(HwDeviceExtension,
  185. HwDeviceExtension->MmIoBase);
  186. }
  187. VideoPortWritePortUchar (CRT_ADDRESS_REG, EXT_DAC_S3EXTREG);
  188. VideoPortWritePortUchar (CRT_DATA_REG, ucOldCr55);
  189. VideoPortWritePortUchar (CRT_ADDRESS_REG, GENERAL_OUT_S3EXTREG);
  190. VideoPortWritePortUchar (CRT_DATA_REG, ucOldCr5C);
  191. VideoPortWritePortUchar (CRT_ADDRESS_REG, EXT_MEM_CTRL1_S3EXTREG);
  192. VideoPortWritePortUchar (CRT_DATA_REG, ucOldCr53);
  193. VideoPortWritePortUchar (CRT_ADDRESS_REG, SYS_CONFIG_S3EXTREG);
  194. VideoPortWritePortUchar (CRT_DATA_REG, ucOldCr40);
  195. VideoPortWritePortUchar (SEQ_ADDRESS_REG, SRD_SEQREG);
  196. VideoPortWritePortUchar (SEQ_DATA_REG, ucOldSr0D);
  197. VideoPortWritePortUchar (SEQ_ADDRESS_REG, UNLOCK_SEQREG);
  198. VideoPortWritePortUchar (SEQ_DATA_REG, ucOldSr08);
  199. VideoPortWritePortUchar (SEQ_ADDRESS_REG, ucOldSeqIdx);
  200. LockExtendedRegs(HwDeviceExtension, ulKey);
  201. }
  202. return (bRet);
  203. }