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.

636 lines
26 KiB

  1. /************************************************************************/
  2. /* */
  3. /* CVTDDC.C */
  4. /* */
  5. /* November 10 1995 (c) 1995 ATI Technologies Incorporated. */
  6. /************************************************************************/
  7. /********************** PolyTron RCS Utilities
  8. $Revision: 1.5 $
  9. $Date: 10 Apr 1996 16:58:22 $
  10. $Author: RWolff $
  11. $Log: S:/source/wnt/ms11/miniport/archive/cvtddc.c_v $
  12. //
  13. // Rev 1.5 10 Apr 1996 16:58:22 RWolff
  14. //Temorarily treats all cards as non-DDC to avoid system hang due to
  15. //conflict over system timer registers. Final solution is to make DDC
  16. //query in the miniport, using the StallExecution function, rather than
  17. //calling the BIOS function which can hang the machine.
  18. //
  19. // Rev 1.4 01 Mar 1996 12:13:28 RWolff
  20. //Now saves and restores the portion of video memory used as
  21. //a buffer to hold data returned by the DDC query call.
  22. //
  23. // Rev 1.3 02 Feb 1996 17:15:44 RWolff
  24. //Now gets DDC/VDIF merge source information from hardware device
  25. //extension rather than storing it in static variables, moved code to
  26. //obtain a buffer in VGA memory to a separate routine.
  27. //
  28. // Rev 1.2 29 Jan 1996 16:54:40 RWolff
  29. //Now uses VideoPortInt10() rather than no-BIOS code on PPC.
  30. //
  31. // Rev 1.1 11 Jan 1996 19:37:44 RWolff
  32. //Now restricts "canned" mode tables by both maximum index and maximum
  33. //pixel clock frequency, and EDID mode tables by maximum pixel clock
  34. //frequency only, rather than both by maximum refresh rate.
  35. //
  36. // Rev 1.0 21 Nov 1995 11:04:38 RWolff
  37. //Initial revision.
  38. End of PolyTron RCS section *****************/
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include <errno.h>
  43. #include <math.h>
  44. #include "dderror.h"
  45. #include "miniport.h"
  46. #include "ntddvdeo.h"
  47. #include "video.h" /* for VP_STATUS definition */
  48. #include "stdtyp.h"
  49. #include "amachcx.h"
  50. #include "amach1.h"
  51. #include "atimp.h"
  52. #include "cvtvga.h"
  53. #include "services.h"
  54. #include "vdptocrt.h"
  55. #include "cvtvdif.h"
  56. #define INCLUDE_CVTDDC
  57. #include "cvtddc.h"
  58. /*
  59. * Allow miniport to be swapped out when not needed.
  60. */
  61. #if defined (ALLOC_PRAGMA)
  62. #pragma alloc_text(PAGE_CX, IsDDCSupported)
  63. #pragma alloc_text(PAGE_DDC, MergeEDIDTables)
  64. #endif
  65. /*****************************************************************************
  66. *
  67. * ULONG IsDDCSupported(void);
  68. *
  69. * DESCRIPTION:
  70. * Reports the degree of DDC support for the available monitor/graphics
  71. * card combination.
  72. *
  73. * RETURN VALUE:
  74. * MERGE_EDID_DDC if DDC can return EDID data structures
  75. * MERGE_VDIF_FILE if no monitor data available from DDC
  76. *
  77. * GLOBALS CHANGED:
  78. * None
  79. *
  80. * CALLED BY:
  81. * SetFixedModes()
  82. *
  83. * AUTHOR:
  84. * Robert Wolff
  85. *
  86. * CHANGE HISTORY:
  87. *
  88. * TEST HISTORY:
  89. *
  90. ***************************************************************************/
  91. ULONG IsDDCSupported(void)
  92. {
  93. VIDEO_X86_BIOS_ARGUMENTS Registers; /* Used in VideoPortInt10() calls */
  94. VP_STATUS RetVal; /* Status returned by VideoPortInt10() */
  95. ULONG MergeSource; /* Source of mode tables to merge with "canned" tables */
  96. VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  97. Registers.Eax = BIOS_DDC_SUPPORT;
  98. Registers.Ebx = 0;
  99. if ((RetVal = VideoPortInt10(phwDeviceExtension, &Registers)) != NO_ERROR)
  100. /*
  101. * If we can't find out DDC status from the BIOS,
  102. * assume DDC is not supported.
  103. */
  104. {
  105. VideoDebugPrint((DEBUG_ERROR, "Error querying DDC status, assume it's not supported\n"));
  106. MergeSource = MERGE_VDIF_FILE;
  107. }
  108. else
  109. {
  110. #if 0
  111. /*
  112. * Workaround: Our BIOS call to obtain the DDC information uses
  113. * the system timer (0x40/0x43) registers, which (according to
  114. * Microsoft) the video BIOS is not supposed to touch. This
  115. * causes some machines to hang during the DDC query. Until
  116. * we can bring the DDC query into the miniport (using approved
  117. * time delay routines), report that this card doesn't support
  118. * DDC.
  119. */
  120. if ((Registers.Eax & 0x00000002) && (Registers.Ebx & 0x00000002))
  121. {
  122. /*
  123. * DDC2 supported by both BIOS and monitor. Check separately
  124. * for DDC1 and DDC2 in case we decide to handle them
  125. * differently in future.
  126. */
  127. VideoDebugPrint((DEBUG_NORMAL, "DDC2 supported\n"));
  128. MergeSource = MERGE_EDID_DDC;
  129. }
  130. else if ((Registers.Eax & 0x00000001) && (Registers.Ebx & 0x00000001))
  131. {
  132. /*
  133. * DDC1 supported by both BIOS and monitor.
  134. */
  135. VideoDebugPrint((DEBUG_NORMAL, "DDC1 supported\n"));
  136. MergeSource = MERGE_EDID_DDC;
  137. }
  138. else
  139. {
  140. /*
  141. * Either the BIOS or the monitor does not support DDC.
  142. */
  143. VideoDebugPrint((DEBUG_NORMAL, "DDC not supported\n"));
  144. MergeSource = MERGE_VDIF_FILE;
  145. }
  146. #else
  147. MergeSource = MERGE_VDIF_FILE;
  148. #endif
  149. }
  150. return MergeSource;
  151. } /* IsDDCSupported() */
  152. /*****************************************************************************
  153. *
  154. * VP_STATUS MergeEDIDTables(void);
  155. *
  156. * DESCRIPTION:
  157. * Merges canned mode tables from BookValues[] with tables found in an
  158. * EDID structure retrieved via DDC. Global pointer variable pCallbackArgs
  159. * is used to point to a structure that passes data in both directions
  160. * between this function and SetFixedModes(). For details on input and
  161. * output data see definition of stVDIFCallbackData structure.
  162. *
  163. * RETURN VALUE:
  164. * NO_ERROR if tables retrieved correctly
  165. * ERROR_INVALID_PARAMETER if unable to retrieve data via DDC
  166. *
  167. * GLOBALS CHANGED:
  168. * None
  169. *
  170. * CALLED BY:
  171. * SetFixedModes()
  172. *
  173. * AUTHOR:
  174. * Robert Wolff
  175. *
  176. * CHANGE HISTORY:
  177. *
  178. * TEST HISTORY:
  179. *
  180. ***************************************************************************/
  181. VP_STATUS MergeEDIDTables(void)
  182. {
  183. VIDEO_X86_BIOS_ARGUMENTS Registers; /* Used in VideoPortInt10() calls */
  184. VP_STATUS RetVal; /* Status returned by VideoPortInt10() */
  185. ULONG BufferSeg; /* Segment to use for buffer */
  186. ULONG BufferSize = 128; /* EDID structure is 128 bytes long */
  187. PUCHAR MappedBuffer; /* Pointer to buffer used for BIOS query */
  188. static UCHAR FixedBuffer[128]; /* Buffer used to avoid repeated BIOS queries */
  189. struct EdidDetailTiming *EdidPtr; /* Used in extracting information from buffer */
  190. ULONG DetailOffset; /* Offset of detailed timing into EDID structure */
  191. ULONG Scratch; /* Temporary variable */
  192. struct stVDIFCallbackData *pArgs; /* Pointer to arguments structure */
  193. struct st_mode_table BuildTbl; /* Mode table being built */
  194. struct st_mode_table LiveTables[4]; /* Tables already extracted */
  195. USHORT NumTablesFound = 0; /* Number of valid entries in LiveTables[] */
  196. USHORT NumLowerTables; /* Number of tables with a lower refresh rate than BuildTbl */
  197. USHORT HorTotal; /* Horizontal total */
  198. USHORT VerTotal; /* Vertical total */
  199. USHORT SyncStrt; /* Sync start */
  200. USHORT HighBound; /* Highest frame rate to look for */
  201. UCHAR SavedScreen[128]; /* Data saved from screen buffer used for DDC query */
  202. pArgs = pCallbackArgs;
  203. /*
  204. * If we haven't already retrieved the EDID information into local
  205. * storage, do it now.
  206. */
  207. if (phwDeviceExtension->EdidChecksum == 0)
  208. {
  209. MappedBuffer = GetVgaBuffer(BufferSize, 0x500, &BufferSeg, SavedScreen);
  210. /*
  211. * We now have a buffer big enough to hold the EDID structure,
  212. * so make the BIOS call to fill it in.
  213. */
  214. VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  215. Registers.Eax = BIOS_DDC_SUPPORT;
  216. Registers.Ebx = 1;
  217. Registers.Ecx = BufferSize;
  218. Registers.Edx = BufferSeg;
  219. Registers.Edi = 0;
  220. if ((RetVal = VideoPortInt10(phwDeviceExtension, &Registers)) != NO_ERROR)
  221. {
  222. VideoDebugPrint((DEBUG_ERROR, "MergeEDIDTables() - failed BIOS_DDC_SUPPORT call\n"));
  223. VideoPortFreeDeviceBase(phwDeviceExtension, MappedBuffer);
  224. return RetVal;
  225. }
  226. /*
  227. * Copy the EDID structure into local storage, then restore
  228. * the contents of the buffer we used for the DDC query.
  229. */
  230. for (Scratch = 0; Scratch < 128; Scratch++)
  231. {
  232. FixedBuffer[Scratch] = VideoPortReadRegisterUchar(&(MappedBuffer[Scratch]));
  233. phwDeviceExtension->EdidChecksum += FixedBuffer[Scratch];
  234. VideoPortWriteRegisterUchar(&(MappedBuffer[Scratch]), SavedScreen[Scratch]);
  235. }
  236. /*
  237. * Check if we have a valid EDID header. If we don't, then
  238. * we can't extract EDID information. Occasionally, a
  239. * monitor hooked up to a switchbox will return corrupt
  240. * EDID data.
  241. */
  242. if ((FixedBuffer[0] != 0) ||
  243. (FixedBuffer[1] != 0xFF) ||
  244. (FixedBuffer[2] != 0xFF) ||
  245. (FixedBuffer[3] != 0xFF) ||
  246. (FixedBuffer[4] != 0xFF) ||
  247. (FixedBuffer[5] != 0xFF) ||
  248. (FixedBuffer[6] != 0xFF) ||
  249. (FixedBuffer[7] != 0))
  250. {
  251. VideoDebugPrint((DEBUG_ERROR, "Invalid EDID header\n"));
  252. return ERROR_INVALID_PARAMETER;
  253. }
  254. /*
  255. * We now have the EDID structure in local storage, so we can free
  256. * the buffer we collected it into. If the lower 8 bits of the
  257. * checksum are nonzero, the structure is invalid.
  258. */
  259. VideoPortFreeDeviceBase(phwDeviceExtension, MappedBuffer);
  260. if ((phwDeviceExtension->EdidChecksum & 0x000000FF) != 0)
  261. {
  262. VideoDebugPrint((DEBUG_ERROR, "MergeEDIDTables() - invalid checksum 0x%X\n", phwDeviceExtension->EdidChecksum));
  263. return ERROR_INVALID_PARAMETER;
  264. }
  265. } /* endif (phwDeviceExtension->EdidChecksum == 0) */
  266. /*
  267. * There are 4 detailed timing blocks in the EDID structure. Read
  268. * each of them in turn.
  269. */
  270. for (DetailOffset = 54; DetailOffset <= 108; DetailOffset += 18)
  271. {
  272. ((PUCHAR)EdidPtr) = FixedBuffer + DetailOffset;
  273. /*
  274. * Initially check only the horizontal and vertical
  275. * resolution. If they don't match the resolution we
  276. * are working on, skip to the next detailed timing block.
  277. */
  278. BuildTbl.m_x_size = ((EdidPtr->HorHighNybbles & 0xF0) << 4) | EdidPtr->HorActiveLowByte;
  279. BuildTbl.m_y_size = ((EdidPtr->VerHighNybbles & 0xF0) << 4) | EdidPtr->VerActiveLowByte;
  280. if ((BuildTbl.m_x_size != pArgs->HorRes) || (BuildTbl.m_y_size != pArgs->VerRes))
  281. {
  282. VideoDebugPrint((DEBUG_DETAIL, "EDID mode %dx%d doesn't match desired mode %dx%d, skipping\n",
  283. BuildTbl.m_x_size, BuildTbl.m_y_size, pArgs->HorRes, pArgs->VerRes));
  284. continue;
  285. }
  286. /*
  287. * The table we are looking at matches the resolution we are
  288. * working on. Fill in the remaining parameters.
  289. */
  290. BuildTbl.m_h_disp = (UCHAR)(BuildTbl.m_x_size / 8 - 1);
  291. BuildTbl.m_v_disp = (short) normal_to_skip2((long)(BuildTbl.m_y_size - 1));
  292. BuildTbl.ClockFreq = (ULONG)(EdidPtr->PixClock) * 10000L;
  293. /*
  294. * If the pixel clock frequency for this mode is greater than
  295. * the maximum pixel clock frequency the graphics card supports
  296. * for the current resolution and pixel depth (this routine deals
  297. * with only one resolution/pixel depth combination at a time,
  298. * so our limiting pixel clock rate will always be for the current
  299. * resolution/pixel depth combination), we can't use this mode.
  300. */
  301. if (BuildTbl.ClockFreq > pArgs->MaxDotClock)
  302. {
  303. VideoDebugPrint((DEBUG_NORMAL, "Skipping table because pixel clock rate is too high\n"));
  304. continue;
  305. }
  306. HorTotal = ((EdidPtr->HorHighNybbles & 0x0F) << 8) | EdidPtr->HorBlankLowByte;
  307. HorTotal += BuildTbl.m_x_size;
  308. BuildTbl.m_h_total = (UCHAR)(HorTotal / 8 - 1);
  309. VerTotal = ((EdidPtr->VerHighNybbles & 0x0F) << 8) | EdidPtr->VerBlankLowByte;
  310. VerTotal += BuildTbl.m_y_size;
  311. BuildTbl.m_v_total = (short) normal_to_skip2((long)(VerTotal - 1));
  312. SyncStrt = ((EdidPtr->SyncHighBits & 0xC0) << 2) | EdidPtr->HSyncOffsetLB;
  313. SyncStrt += BuildTbl.m_x_size;
  314. BuildTbl.m_h_sync_strt = (UCHAR)(SyncStrt / 8 - 1);
  315. SyncStrt = ((EdidPtr->SyncHighBits & 0x0C) << 2) | ((EdidPtr->VSyncOffWidLN & 0xF0) >> 4);
  316. SyncStrt += BuildTbl.m_y_size;
  317. BuildTbl.m_v_sync_strt = (short) normal_to_skip2((long)(SyncStrt - 1));
  318. /*
  319. * We only support digital separate sync monitors.
  320. */
  321. if ((EdidPtr->Flags & EDID_FLAGS_SYNC_TYPE_MASK) != EDID_FLAGS_SYNC_DIGITAL_SEP)
  322. {
  323. VideoDebugPrint((DEBUG_NORMAL, "Skipping table due to wrong sync type\n"));
  324. continue;
  325. }
  326. Scratch = ((EdidPtr->SyncHighBits & 0x30) << 4) | EdidPtr->HSyncWidthLB;
  327. if (!(EdidPtr->Flags & EDID_FLAGS_H_SYNC_POS))
  328. Scratch |= 0x20;
  329. BuildTbl.m_h_sync_wid = (UCHAR)Scratch;
  330. Scratch = ((EdidPtr->SyncHighBits & 0x03) << 4) | (EdidPtr->VSyncOffWidLN & 0x0F);
  331. if (!(EdidPtr->Flags & EDID_FLAGS_V_SYNC_POS))
  332. Scratch |= 0x20;
  333. BuildTbl.m_v_sync_wid = (UCHAR)Scratch;
  334. BuildTbl.m_status_flags = 0;
  335. BuildTbl.m_vfifo_16 = 8;
  336. BuildTbl.m_vfifo_24 = 8;
  337. BuildTbl.m_clock_select = 0x800;
  338. BuildTbl.m_h_overscan = 0;
  339. BuildTbl.m_v_overscan = 0;
  340. BuildTbl.m_overscan_8b = 0;
  341. BuildTbl.m_overscan_gr = 0;
  342. if (EdidPtr->Flags & EDID_FLAGS_INTERLACE)
  343. BuildTbl.m_disp_cntl = 0x33;
  344. else
  345. BuildTbl.m_disp_cntl = 0x23;
  346. /*
  347. * The EDID detailed timing tables don't include the refresh
  348. * rate. In our VDIF to monitor timings routines, we obtain
  349. * the horizontal and vertical totals from the equations
  350. *
  351. * Htot = PixClk/HorFreq
  352. * Vtot = HorFreq/FrameRate
  353. *
  354. * These equations can be rearranged to
  355. *
  356. * HorFreq = PixClk/Htot
  357. * FrameRate = HorFreq/Vtot = (PixClk/Htot)/Vtot = PixClk/(Htot*Vtot)
  358. *
  359. * The multiplication, addition, and division below is to
  360. * round up to the nearest whole number, since we don't
  361. * have access to floating point.
  362. */
  363. Scratch = (BuildTbl.ClockFreq * 10)/(HorTotal*VerTotal);
  364. Scratch += 5;
  365. Scratch /= 10;
  366. BuildTbl.Refresh = (short)Scratch;
  367. VideoDebugPrint((DEBUG_DETAIL, "Refresh rate = %dHz\n", BuildTbl.Refresh));
  368. /*
  369. * Set the pixel depth and pitch, and adjust the clock frequency
  370. * if the DAC needs multiple clocks per pixel.
  371. */
  372. SetOtherModeParameters(pArgs->PixelDepth, pArgs->Pitch,
  373. pArgs->Multiplier, &BuildTbl);
  374. /*
  375. * We now have a mode table for the resolution we are
  376. * looking at. If this is the first table we have found
  377. * at this resolution, we can simply fill in the first
  378. * entry in LiveTables[]. If not, we must put the table
  379. * into the list in order by refresh rate.
  380. */
  381. if (NumTablesFound == 0)
  382. {
  383. VideoDebugPrint((DEBUG_DETAIL, "First DDC table for this resolution\n"));
  384. VideoPortMoveMemory(&(LiveTables[0]), &BuildTbl, sizeof(struct st_mode_table));
  385. NumTablesFound = 1;
  386. }
  387. else
  388. {
  389. /*
  390. * Run through the list of tables we have already found.
  391. * Skip over the tables which have refresh rates lower than
  392. * the new table, and shift tables with higher refresh
  393. * rates up one position to make room for the new table.
  394. * There is no need to check for available spaces in the
  395. * LiveTables[] array, since this array has 4 entries and
  396. * the EDID structure can hold a maximum of 4 detailed
  397. * timings.
  398. */
  399. for (NumLowerTables = 0; NumLowerTables < NumTablesFound; NumLowerTables++)
  400. {
  401. if (LiveTables[NumLowerTables].Refresh < BuildTbl.Refresh)
  402. {
  403. VideoDebugPrint((DEBUG_DETAIL, "Skipping table %d, since %dHz is less than %dHz\n",
  404. NumLowerTables, LiveTables[NumLowerTables].Refresh, BuildTbl.Refresh));
  405. continue;
  406. }
  407. /*
  408. * NumLowerTables now holds the number of tables in LiveTables[] which
  409. * have refresh rates lower than that in BuildTbl. We must now move
  410. * the tables in LiveTables[] with refresh rates higher than that in
  411. * BuildTbl up one space to make room for BuildTbl to be inserted.
  412. * After moving the tables, break out of the outer loop.
  413. */
  414. for (Scratch = NumTablesFound; Scratch >= NumLowerTables; Scratch--)
  415. {
  416. VideoDebugPrint((DEBUG_DETAIL, "Moving table %d, since %dHz is more than %dHz\n",
  417. Scratch, LiveTables[Scratch].Refresh, BuildTbl.Refresh));
  418. VideoPortMoveMemory(&(LiveTables[Scratch+1]), &(LiveTables[Scratch]), sizeof(struct st_mode_table));
  419. }
  420. break;
  421. }
  422. /*
  423. * When we get here, one of two conditions is satisfied:
  424. *
  425. * 1. All the existing tables in LiveTables[] have a refresh
  426. * rate less than that in BuildTbl, so the outer loop will
  427. * have exited with NumLowerTables equal to NumTablesFound.
  428. *
  429. * 2. There are some tables in LiveTables[] which have a refresh
  430. * rate greater than that in BuildTbl. The inner loop will
  431. * have exited after moving these tables up one space, then
  432. * we will have broken out of the outer loop. NumLowerTables
  433. * is equal to the number of existing tables which have a
  434. * refresh rate less than that in BuildTbl.
  435. *
  436. * In both cases, LiveTables[NumLowerTables] is a free slot
  437. * at the location where BuildTbl should be copied.
  438. */
  439. VideoDebugPrint((DEBUG_DETAIL, "Copying new table to entry %d\n", NumLowerTables));
  440. VideoPortMoveMemory(&(LiveTables[NumLowerTables]), &BuildTbl, sizeof(struct st_mode_table));
  441. NumTablesFound++;
  442. } /* end if (NumTablesFound != 0) */
  443. } /* end for (look at next detailed timing block) */
  444. /*
  445. * We now have all the mode tables from the EDID structure which
  446. * match the desired resolution stored in LiveTables[] in order
  447. * of increasing refresh rate, with the number of such tables
  448. * in NumTablesFound. Now we must merge the results with the
  449. * "canned" mode tables.
  450. */
  451. HighBound = BookValues[pArgs->EndIndex].Refresh;
  452. /*
  453. * Use NumLowerTables to go through the list of tables from
  454. * the EDID structure.
  455. *
  456. * Since there will never be a legitimate mode table with a
  457. * pixel clock frequency of zero hertz, we can use this value
  458. * as a flag to show that we don't want to use the tables from
  459. * the EDID structure. Initially, we only want to lock out the
  460. * use of these tables if none exist, but we will later lock
  461. * them out if we have already used all of them.
  462. */
  463. NumLowerTables = 0;
  464. if (NumTablesFound == 0)
  465. LiveTables[0].ClockFreq = 0;
  466. while (pArgs->FreeTables > 0)
  467. {
  468. /*
  469. * If the EDID table exists, and either it has a refresh rate
  470. * less than or equal to that of the next "canned" table or
  471. * we have run out of acceptable "canned" tables, use the EDID
  472. * table. We know that any EDID table will have an acceptable
  473. * pixel clock frequency because we have already discarded any
  474. * that are out of range.
  475. */
  476. if ((LiveTables[NumLowerTables].ClockFreq != 0) &&
  477. ((LiveTables[NumLowerTables].Refresh <= BookValues[pArgs->Index].Refresh) ||
  478. (pArgs->Index > pArgs->EndIndex) ||
  479. (BookValues[pArgs->Index].ClockFreq > pArgs->MaxDotClock)))
  480. {
  481. VideoDebugPrint((DEBUG_DETAIL, "Copying %dHz table from EDID\n", LiveTables[NumLowerTables].Refresh));
  482. VideoPortMoveMemory((*pArgs->ppFreeTables), &(LiveTables[NumLowerTables]), sizeof(struct st_mode_table));
  483. NumLowerTables++;
  484. }
  485. /*
  486. * The above check will have failed if the EDID table did not exist,
  487. * or if it did but an acceptable "canned" table with a lower
  488. * refresh rate also exists. Check to see if we have an acceptable
  489. * "canned" table, and use it if we do.
  490. */
  491. else if ((pArgs->Index <= pArgs->EndIndex) &&
  492. (BookValues[pArgs->Index].ClockFreq <= pArgs->MaxDotClock))
  493. {
  494. VideoDebugPrint((DEBUG_DETAIL, "Copying %dHz \"canned\" table\n", BookValues[pArgs->Index].Refresh));
  495. BookVgaTable(pArgs->Index, *pArgs->ppFreeTables);
  496. SetOtherModeParameters(pArgs->PixelDepth, pArgs->Pitch,
  497. pArgs->Multiplier, *pArgs->ppFreeTables);
  498. pArgs->Index++;
  499. }
  500. /*
  501. * The only way we will fail both of the above checks is if there
  502. * are no acceptable mode tables remaining, either from the EDID
  503. * structure or from our list of "canned" tables. If this is the
  504. * case, we don't need to look for more mode tables to add to
  505. * our list.
  506. */
  507. else
  508. {
  509. break;
  510. }
  511. /*
  512. * Update the lower bound, since we don't want to consider
  513. * tables with refresh rates lower than or equal to the one
  514. * in the table we just added to the list. After we have
  515. * done this, skip ahead in both the "canned" and EDID tables
  516. * to get past those which are below the new lower bound.
  517. *
  518. * Don't skip a mode table from the EDID structure with a pixel
  519. * clock frequency of zero, since this is a flag to show that we
  520. * have already used all of the suitable mode tables from the
  521. * EDID structure, rather than a legitimate mode table.
  522. */
  523. pArgs->LowBound = (*pArgs->ppFreeTables)->Refresh + 1;
  524. while ((pArgs->Index <= pArgs->EndIndex) &&
  525. (BookValues[pArgs->Index].Refresh < pArgs->LowBound))
  526. {
  527. VideoDebugPrint((DEBUG_DETAIL, "Skipping %dHz \"canned\" table\n", BookValues[pArgs->Index].Refresh));
  528. pArgs->Index++;
  529. }
  530. while ((NumLowerTables < NumTablesFound) &&
  531. (LiveTables[NumLowerTables].ClockFreq != 0) &&
  532. (LiveTables[NumLowerTables].Refresh < pArgs->LowBound))
  533. {
  534. VideoDebugPrint((DEBUG_DETAIL, "Skipping %dHz table from EDID\n", LiveTables[NumLowerTables].Refresh));
  535. NumLowerTables++;
  536. }
  537. /*
  538. * If we have run out of EDID tables, mark the EDID tables
  539. * with our flag to show that they should be ignored (no
  540. * legitimate mode will have a pixel clock rate of zero
  541. * hertz).
  542. *
  543. * We must do this in the first entry of the structure then
  544. * reset the "next EDID table to use" index to point to the
  545. * first entry, rather than modifying whatever happens to be
  546. * the next entry, to avoid trampling data outside our array
  547. * in the (unlikely) event that all of the possible detailed
  548. * timings in the EDID structure were valid mode tables with
  549. * in-range pixel clock frequencies for the resolution we are
  550. * looking at.
  551. *
  552. * There is no need to set a flag if we run out of "canned"
  553. * tables because we identify this condition by the index
  554. * being higher than the highest index we want to look for,
  555. * which is an input parameter.
  556. */
  557. if (NumLowerTables == NumTablesFound)
  558. {
  559. VideoDebugPrint((DEBUG_DETAIL, "Ran out of EDID tables\n"));
  560. NumLowerTables = 0;
  561. LiveTables[0].ClockFreq = 0;
  562. }
  563. /*
  564. * Adjust the free tables pointer and count to reflect the
  565. * table we have just added.
  566. */
  567. (*pArgs->ppFreeTables)++;
  568. pArgs->NumModes++;
  569. pArgs->FreeTables--;
  570. } /* end while (more tables and not yet reached high bound) */
  571. return NO_ERROR;
  572. } /* MergeEDIDTables() */