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.

988 lines
29 KiB

  1. /*++
  2. Copyright (c) 1993, 1994 Weitek Corporation
  3. Module Name:
  4. p91supp.c
  5. Abstract:
  6. This module contains functions for calculating memconf and srtcrl values
  7. for the Weitek P9 miniport device driver.
  8. Environment:
  9. Kernel mode
  10. Revision History may be found at the end of this file.
  11. --*/
  12. #include "p9.h"
  13. #include "p9gbl.h"
  14. #include "p91regs.h"
  15. extern VOID
  16. ProgramClockSynth(
  17. PHW_DEVICE_EXTENSION HwDeviceExtension,
  18. USHORT usFrequency,
  19. BOOLEAN bSetMemclk,
  20. BOOLEAN bUseClockDoubler
  21. );
  22. //
  23. // Local function Prototypes
  24. //
  25. VOID
  26. CalcP9100MemConfig (
  27. PHW_DEVICE_EXTENSION HwDeviceExtension
  28. );
  29. VOID
  30. P91SizeVideoMemory(
  31. PHW_DEVICE_EXTENSION HwDeviceExtension
  32. );
  33. BOOLEAN
  34. P91TestVideoMemory(
  35. PHW_DEVICE_EXTENSION HwDeviceExtension,
  36. USHORT iNumLongWords
  37. );
  38. ULONG
  39. Logbase2(
  40. ULONG ulValue
  41. );
  42. VOID
  43. CalcP9100MemConfig (
  44. PHW_DEVICE_EXTENSION HwDeviceExtension
  45. )
  46. /*++
  47. Routine Description:
  48. Calculate the value to be stored in the Power 9100 memory configuration
  49. field as well as the srtctl field.
  50. Argumentss:
  51. PHW_DEVICE_EXTENSION HwDeviceExtension.
  52. Return Values:
  53. FALSE - If the operation is not successful.
  54. TRUE - If the operation is successful.
  55. --*/
  56. {
  57. BOOLEAN fDacDividesClock;
  58. USHORT usShiftClockIndex;
  59. USHORT usSrtctlSrcIncIndex;
  60. USHORT usLoadClock;
  61. USHORT usDivisionFactor;
  62. USHORT usClkFreqIndex;
  63. USHORT usBlankDlyIndex;
  64. USHORT usSamIndex;
  65. USHORT usDacWidthIndex;
  66. USHORT usNumBanksIndex;
  67. USHORT usEffectiveBackendBanks;
  68. USHORT usDepthOfOneSAM;
  69. USHORT usEffectiveSAMDepth;
  70. USHORT usEffectiveRowDepth;
  71. USHORT usMemClkInUse;
  72. ULONG ulMemConfig;
  73. ULONG ulSrtCtl;
  74. //
  75. // Define the positive (rising edge) blank delay index table for when the
  76. // Power 9100 is dividing the clock.
  77. //
  78. USHORT usPositiveBlnkDly[2][2][3] =
  79. {
  80. //
  81. // Define blank delay for 128K deep VRAM
  82. // 1Bnk 2Bnk 4Bnk
  83. //
  84. {
  85. {0xFF, 0x00, 0x00}, // 32-Bit RAMDAC
  86. {0xFF, 0x00, 0x00} // 64-Bit RAMDAC
  87. },
  88. //
  89. // Define blank delay for 256K deep VRAM
  90. // 1Bnk 2Bnk 4Bnk
  91. //
  92. {
  93. {0x01, 0x02, 0x00}, // 32-Bit RAMDAC
  94. {0xFF, 0x01, 0x02} // 64-Bit RAMDAC
  95. }
  96. };
  97. //
  98. // Define the negative (falling edge) blank delay index table for when the
  99. // Power 9100 is dividing the clock.
  100. //
  101. USHORT usNegativeBlnkDly[2][2][3] =
  102. {
  103. //
  104. // Define blank delay for 128K deep VRAM
  105. // 1Bnk 2Bnk 4Bnk
  106. //
  107. {
  108. {0xFF, 0x02, 0x03}, // 32-Bit RAMDAC
  109. {0xFF, 0x01, 0x02} // 64-Bit RAMDAC
  110. },
  111. //
  112. // Define blank delay for 256K deep VRAM
  113. // 1Bnk 2Bnk 4Bnk
  114. //
  115. {
  116. {0x01, 0x02, 0x03}, // 32-Bit RAMDAC
  117. {0xFF, 0x01, 0x02} // 64-Bit RAMDAC
  118. }
  119. };
  120. //
  121. // Define the VRAM configuration mem_config.config lookup table.
  122. //
  123. ULONG ulMemConfTable[] =
  124. {
  125. 0,
  126. P91_MC_CNFG_1,
  127. 0,
  128. P91_MC_CNFG_3,
  129. P91_MC_CNFG_4,
  130. P91_MC_CNFG_5,
  131. 0,
  132. P91_MC_CNFG_7,
  133. 0,
  134. 0,
  135. 0,
  136. P91_MC_CNFG_11,
  137. 0,
  138. 0,
  139. P91_MC_CNFG_14,
  140. P91_MC_CNFG_15
  141. };
  142. //
  143. // Define the mem_config.shiftclk_mode and mem_config.soe_mode lookup table.
  144. //
  145. ULONG ulShiftClockMode[] =
  146. {
  147. P91_MC_SHFT_CLK_1_BANK | P91_MC_SERIAL_OUT_1_BANK,
  148. P91_MC_SHFT_CLK_2_BANK | P91_MC_SERIAL_OUT_2_BANK,
  149. P91_MC_SHFT_CLK_4_BANK | P91_MC_SERIAL_OUT_4_BANK
  150. };
  151. //
  152. // Define the mem_config.shiftclk_freq and mem_config.crtc_freq lookup table.
  153. //
  154. ULONG ulClockFreq[] =
  155. {
  156. P91_MC_SHFT_CLK_DIV_1 | P91_MC_CRTC_CLK_DIV_1,
  157. P91_MC_SHFT_CLK_DIV_2 | P91_MC_CRTC_CLK_DIV_2,
  158. P91_MC_SHFT_CLK_DIV_4 | P91_MC_CRTC_CLK_DIV_4,
  159. P91_MC_SHFT_CLK_DIV_8 | P91_MC_CRTC_CLK_DIV_8,
  160. P91_MC_SHFT_CLK_DIV_16 | P91_MC_CRTC_CLK_DIV_16
  161. };
  162. //
  163. // Define the mem_config.blank_dly field lookup table.
  164. //
  165. ULONG ulBlankDly[] =
  166. {
  167. P91_MC_BLNKDLY_0_CLK,
  168. P91_MC_BLNKDLY_1_CLK,
  169. P91_MC_BLNKDLY_2_CLK,
  170. P91_MC_BLNKDLY_3_CLK
  171. };
  172. //
  173. // Define the srtctl.src_incs field lookup table.
  174. //
  175. ULONG ulSrtctlSrcInc[] =
  176. {
  177. P91_SRTCTL_SRC_INC_256,
  178. P91_SRTCTL_SRC_INC_512,
  179. P91_SRTCTL_SRC_INC_1024
  180. };
  181. //
  182. // A1/A2 silicon SPLIT SHIFT TRANSFER BUG FIX
  183. //
  184. // First initialize the memory clock that is being used. This value may
  185. // need to be changed if it is determined that the conditions are right
  186. // for the split shift transfer bug to occur.
  187. //
  188. // First choose the default value for the clock being used just in case
  189. // there was not a value passed in.
  190. //
  191. usMemClkInUse = (HwDeviceExtension->p91State.usRevisionID ==
  192. WTK_9100_REV1) ? DEF_P9100_REV1_MEMCLK :
  193. DEF_P9100_MEMCLK;
  194. //
  195. // A1/A2 silicon SPLIT SHIFT TRANSFER BUG FIX
  196. //
  197. // Now select either the default memory clock or the value passed in.
  198. //
  199. // usMemClkInUse = (*pusMemClock) ? *pusMemClock : usMemClkInUse;
  200. //
  201. // Initialize the constant fields of the Screen Repaint Timing Control
  202. // register value.
  203. //
  204. ulSrtCtl = P91_SRTCTL_DISP_BUFF_0 | // display_buffer (3)
  205. P91_SRTCTL_HR_NORMAL | // hblnk_relaod (4)
  206. P91_SRTCTL_ENABLE_VIDEO | // enable_video (5)
  207. P91_SRTCTL_HSYNC_INT | // internal_hsync (7)
  208. P91_SRTCTL_VSYNC_INT; // internal_vsync (8)
  209. //
  210. // Initialize the memory configuration fields to start things off.
  211. //
  212. ulMemConfig = ulMemConfTable[HwDeviceExtension->p91State.usMemConfNum];
  213. //
  214. // Initialize all of the constant fields.
  215. //
  216. ulMemConfig |= P91_MC_MISS_ADJ_1 | // vram_miss_adj (3)
  217. P91_MC_READ_ADJ_1 | // vram_read_adj (4)
  218. P91_MC_WRITE_ADJ_1 | // vram_write_adj (5)
  219. P91_MC_VCP_PRIORITY_HI | // priority_select (6)
  220. P91_MC_DAC_ACCESS_ADJ_0 | // dac_access_adj (7)
  221. P91_MC_DAC_MODE_0 | // dac_mode (8)
  222. P91_MC_MEM_VID_NORMAL | // hold_reset (9)
  223. P91_MC_MUXSEL_NORMAL | // reserved (16-17)
  224. P91_MC_SLOW_HOST_ADJ_1 | // slow_host_hifc (30)
  225. P91_MC_READ_SMPL_ADJ_1; // vram_read_sample (31)
  226. //
  227. // Calculate the number of effective back-end banks in the current configuration. This
  228. // value is used to calculate several fields in the memory configuration register.
  229. //
  230. usEffectiveBackendBanks = (32*HwDeviceExtension->p91State.usNumVramBanks)
  231. / HwDeviceExtension->Dac.usRamdacWidth;
  232. //
  233. // Determine the depth of one shift register as follows:
  234. // 128k deep VRAM has a row size of 256 => depth of one shift register is 256
  235. // 256k deep VRAM has a row size of 512 => depth of one shift register is 512
  236. //
  237. usDepthOfOneSAM = (HwDeviceExtension->p91State.ulPuConfig &
  238. P91_PUC_128K_VRAMS) ? 256 : 512;
  239. //
  240. // Calculate the effective SAM and Row depths. These values are used to calculate the
  241. // initial value for the SRTCTL register.
  242. //
  243. usEffectiveSAMDepth = usDepthOfOneSAM * usEffectiveBackendBanks;
  244. usEffectiveRowDepth = usDepthOfOneSAM *
  245. HwDeviceExtension->p91State.usNumVramBanks;
  246. //
  247. // Calculate the index into the Shift Clock Mode lookup table. The index is calculated
  248. // as Logbase2(usEffectiveBakendBanks) should give either a 0, 1 or 2.
  249. //
  250. usShiftClockIndex = usEffectiveBackendBanks >> 1;
  251. VideoDebugPrint((2, "CalcP9100MemConfig: usEffectiveBackendBanks = %d\n",
  252. usEffectiveBackendBanks));
  253. VideoDebugPrint((2, "CalcP9100MemConfig: usShiftClockIndex = %d\n",
  254. usShiftClockIndex));
  255. VideoDebugPrint((2, "CalcP9100MemConfig: usShiftClockMode[] = %lx\n",
  256. ulShiftClockMode[usShiftClockIndex]));
  257. //
  258. // Now, using the Shift Clock Mode lookup table index, set both the shiftclk_mode (22-23)
  259. // and soe_mode (24-25) fields.
  260. //
  261. ulMemConfig |= ulShiftClockMode[usShiftClockIndex];
  262. switch (HwDeviceExtension->p91State.ulPuConfig & P91_PUC_VRAM_SAM_SIZE)
  263. {
  264. case P91_PUC_FULL_SIZE_SHIFT:
  265. {
  266. //
  267. // Calculate the initial value for the SRTCTL register.
  268. //
  269. // First set srtctl.src_incs...
  270. //
  271. usSrtctlSrcIncIndex = (USHORT) (Logbase2 ((ULONG) usEffectiveRowDepth) - 9);
  272. ulSrtCtl |= ulSrtctlSrcInc[usSrtctlSrcIncIndex];
  273. //
  274. // And then srtctl.qsfselect
  275. //
  276. ulSrtCtl |= Logbase2((ULONG) usEffectiveSAMDepth) - 5;
  277. //
  278. // Set the vad_shft field for full size SAMs.
  279. //
  280. ulMemConfig |= P91_MC_VAD_DIV_1;
  281. break;
  282. }
  283. case P91_PUC_HALF_SIZE_SHIFT:
  284. {
  285. //
  286. // Calculate the initial value for the SRTCTL register.
  287. //
  288. // First set srtctl.src_incs...
  289. //
  290. usSrtctlSrcIncIndex = (USHORT) (Logbase2 ((ULONG) usEffectiveRowDepth) - 9);
  291. if (usSrtctlSrcIncIndex)
  292. {
  293. //
  294. // For half size SAMs, if src_incs is not already equal to 0 then it will get
  295. // decremented by one...
  296. //
  297. --usSrtctlSrcIncIndex;
  298. ulSrtCtl |= ulSrtctlSrcInc[usSrtctlSrcIncIndex];
  299. //
  300. // And vad_shft will be set to 0.
  301. //
  302. ulMemConfig |= P91_MC_VAD_DIV_1;
  303. }
  304. else
  305. {
  306. //
  307. // If src_incs is already equal to 0, then it will be left as is...
  308. //
  309. ulSrtCtl |= ulSrtctlSrcInc[usSrtctlSrcIncIndex];
  310. //
  311. // And vad_shft will be set to 1.
  312. //
  313. ulMemConfig |= P91_MC_VAD_DIV_2;
  314. }
  315. //
  316. // Now set srtctl.qsfselect for half size SAMs.
  317. //
  318. ulSrtCtl |= Logbase2 ((ULONG) usEffectiveSAMDepth) - 6;
  319. break;
  320. }
  321. }
  322. //
  323. // Determine if the RAMDAC should divide the clock.
  324. //
  325. usLoadClock = (USHORT) ((HwDeviceExtension->VideoData.dotfreq1 /
  326. HwDeviceExtension->Dac.usRamdacWidth) *
  327. HwDeviceExtension->usBitsPixel);
  328. // start of non-JEDEC memory bug fix
  329. if (
  330. (HwDeviceExtension->p91State.usRevisionID < WTK_9100_REV3) &&
  331. (HwDeviceExtension->usBitsPixel <= 16) &&
  332. ( ( (HwDeviceExtension->p91State.usNumVramBanks == 2) &&
  333. (HwDeviceExtension->Dac.usRamdacWidth == 64) &&
  334. ((HwDeviceExtension->p91State.ulPuConfig &
  335. P91_PUC_FREQ_SYNTH_TYPE) != P91_PUC_FIXED_MEMCLK) &&
  336. (usLoadClock < 1200)
  337. ) ||
  338. ( usLoadClock < 800 )
  339. )
  340. #ifdef _MIPS_
  341. && !( HwDeviceExtension->MachineType == SIEMENS_P9100_VLB
  342. || HwDeviceExtension->MachineType == SIEMENS_P9100_PCi)
  343. // SNI-Od: 22-1-96:
  344. // hum!! (HwDeviceExtension->Dac.usRamdacID != DAC_ID_IBM525) ??
  345. #endif
  346. )
  347. {
  348. if (HwDeviceExtension->VideoData.dotfreq1 <= 6750 )
  349. {
  350. ulMemConfig |= ((2 - (HwDeviceExtension->usBitsPixel/8) +
  351. (HwDeviceExtension->Dac.usRamdacWidth/32)) << 10) // shiftclk_freq (10-12)
  352. |
  353. ((2 - (HwDeviceExtension->usBitsPixel/8) +
  354. (HwDeviceExtension->Dac.usRamdacWidth/32)) << 13); // crtc_freq (13-15)
  355. }
  356. else
  357. {
  358. ulMemConfig |= ((1 - (HwDeviceExtension->usBitsPixel/8) +
  359. (HwDeviceExtension->Dac.usRamdacWidth/32)) << 10) // shiftclk_freq (10-12)
  360. |
  361. ((1 - (HwDeviceExtension->usBitsPixel/8) +
  362. (HwDeviceExtension->Dac.usRamdacWidth/32)) << 13); // crtc_freq (13-15)
  363. }
  364. fDacDividesClock = FALSE;
  365. }
  366. else
  367. {
  368. //
  369. // A1/A2 silicon SPLIT SHIFT TRANSFER BUG FIX
  370. //
  371. // This is the main logic for the split shift transfer bug software work
  372. // around. The current assumption is that the RAMDAC will always be doing
  373. // the dividing of the clock.
  374. //
  375. fDacDividesClock = TRUE;
  376. //
  377. // A1/A2 silicon SPLIT SHIFT TRANSFER BUG FIX
  378. //
  379. // Special attention is required for A1/A2 silicon for low resolution modes
  380. // such as 640x480x8, 640x480x15, 640x480x16 and 800x600x8. Furthormore,
  381. // the problem only occurs on boards with 2 megabytes of VRAM, a 64-bit
  382. // RAMDAC and when the following condition is met.
  383. //
  384. // (SCLK * 7) < MEMCLK
  385. //
  386. // Note: The value calculated for LCLK can also be used in place of SCLK
  387. // in the computations.
  388. //
  389. if ((HwDeviceExtension->p91State.usRevisionID < WTK_9100_REV3) &&
  390. (HwDeviceExtension->usBitsPixel != 24) &&
  391. ((HwDeviceExtension->p91State.ulPuConfig &
  392. P91_PUC_MEMORY_DEPTH) == P91_PUC_256K_VRAMS) &&
  393. (HwDeviceExtension->p91State.usNumVramBanks == 2) &&
  394. (HwDeviceExtension->Dac.usRamdacWidth == 64) &&
  395. ((HwDeviceExtension->p91State.ulPuConfig &
  396. P91_PUC_FREQ_SYNTH_TYPE) != P91_PUC_FIXED_MEMCLK) &&
  397. ((usLoadClock * 7) < usMemClkInUse))
  398. {
  399. //
  400. // All the conditions are right for the split shift transfer bug to occur.
  401. // The software fix for this bug requires that the memory clock is adjusted
  402. // so that the (SCLK * 7) < MEMCLK equation is no longer satisfied. This is
  403. // done easily enough by setting MEMCLK = SCLK * 7. By doing this, MEMCLK is
  404. // not reduced any more than neccessary.
  405. //
  406. usMemClkInUse = (usLoadClock * 7);
  407. }
  408. //
  409. // Reprogram MEMCLK...
  410. //
  411. ProgramClockSynth(HwDeviceExtension, usMemClkInUse, TRUE, FALSE);
  412. //
  413. // A1/A2 silicon SPLIT SHIFT TRANSFER BUG FIX
  414. //
  415. // Because of the current work around, the RAMDAC always does the dividing of
  416. // of the clock and the DDOTCLK is always used, so set those bit here.
  417. //
  418. // Set the shiftclk_freq (10-12), crtc_freq (13-15) and video_clk_sel (20) fields for
  419. // when the RAMDAC is dividing the clock.
  420. //
  421. ulMemConfig |= P91_MC_SHFT_CLK_DIV_1 | // shiftclk_freq (10-12)
  422. P91_MC_CRTC_CLK_DIV_1 | // crtc_freq (13-15)
  423. P91_MC_VCLK_SRC_DDOTCLK; // video_clk_sel (20)
  424. }
  425. VideoDebugPrint((2, "CalcP9100MemConfig: usLoadClock = %d\n",
  426. usLoadClock));
  427. VideoDebugPrint((2, "CalcP9100MemConfig: fDacDividesClock = %d\n",
  428. fDacDividesClock));
  429. #if 0
  430. if (fDacDividesClock)
  431. {
  432. //
  433. // Set the shiftclk_freq (10-12), crtc_freq (13-15) and video_clk_sel (20) fields for
  434. // when the RAMDAC is dividing the clock.
  435. //
  436. ulMemConfig |= P91_MC_SHFT_CLK_DIV_1 | // shiftclk_freq (10-12)
  437. P91_MC_CRTC_CLK_DIV_1 | // crtc_freq (13-15)
  438. P91_MC_VCLK_SRC_DDOTCLK; // video_clk_sel (20)
  439. }
  440. else
  441. {
  442. //
  443. // Set the shiftclk_freq (10-12), crtc_freq (13-15) and video_clk_sel (20) fields for
  444. // when the Power 9100 is dividing the clock.
  445. //
  446. usDivisionFactor = (USHORT) (HwDeviceExtension->Dac.usRamdacWidth /
  447. HwDeviceExtension->usBitsPixel);
  448. usClkFreqIndex = (USHORT) Logbase2 ((ULONG) usDivisionFactor);
  449. VideoDebugPrint((2, "CalcP9100MemConfig: usClkFreqIndex#1 = %d\n",
  450. usClkFreqIndex));
  451. if (HwDeviceExtension->VideoData.dotfreq1 >
  452. HwDeviceExtension->Dac.ulMaxClkFreq) // was if (usFreqRatio == 2)
  453. {
  454. --usClkFreqIndex;
  455. VideoDebugPrint((2, "CalcP9100MemConfig: usClkFreqIndex#2 = %d\n",
  456. usClkFreqIndex));
  457. }
  458. VideoDebugPrint((2, "CalcP9100MemConfig: usClkFreqIndex = %d\n",
  459. usClkFreqIndex));
  460. VideoDebugPrint((2, "CalcP9100MemConfig: ulClockFreq[] = %lx\n",
  461. ulClockFreq[usClkFreqIndex]));
  462. ulMemConfig |= ulClockFreq[usClkFreqIndex];
  463. //
  464. // video_clk_sel is always PIXCLK when the 9100 is dividing the clock.
  465. //
  466. ulMemConfig |= P91_MC_VCLK_SRC_PIXCLK;
  467. }
  468. #endif
  469. //
  470. // Determine the setting for the blank_edge (19) field
  471. //
  472. if ((usLoadClock <= 3300) ||
  473. (HwDeviceExtension->p91State.usRevisionID >= WTK_9100_REV3))
  474. {
  475. ulMemConfig |= P91_MC_SYNC_FALL_EDGE;
  476. }
  477. else
  478. {
  479. ulMemConfig |= P91_MC_SYNC_RISE_EDGE;
  480. }
  481. //
  482. // Do the magic for the blank_dly (27-28) field.
  483. //
  484. if (HwDeviceExtension->p91State.usRevisionID >= WTK_9100_REV3)
  485. {
  486. //
  487. // For A3 silicon, this is simply a 1.
  488. //
  489. usBlankDlyIndex = 1;
  490. //
  491. // Now special case for the number of banks and the DAC width.
  492. //
  493. if ((HwDeviceExtension->p91State.usNumVramBanks == 4) &&
  494. (HwDeviceExtension->Dac.usRamdacWidth == 32))
  495. {
  496. ++usBlankDlyIndex;
  497. }
  498. }
  499. else if (fDacDividesClock)
  500. {
  501. //
  502. // When not on A3 and the DAC is dividing the clock, there's a little
  503. // more to this field.
  504. //
  505. if ((ulMemConfig & P91_MC_BLANK_EDGE_MSK) == P91_MC_SYNC_RISE_EDGE)
  506. {
  507. usBlankDlyIndex = 1;
  508. }
  509. else
  510. {
  511. usBlankDlyIndex = 2;
  512. }
  513. //
  514. // Now special case for the number of banks and the DAC width.
  515. //
  516. if ((HwDeviceExtension->p91State.usNumVramBanks == 4) &&
  517. (HwDeviceExtension->Dac.usRamdacWidth == 32))
  518. {
  519. ++usBlankDlyIndex;
  520. }
  521. }
  522. else
  523. {
  524. //
  525. // When the Power 9100 is dividing the clock this gets really messy.
  526. //
  527. usSamIndex = ((HwDeviceExtension->p91State.ulPuConfig &
  528. P91_PUC_VRAM_SAM_SIZE) == P91_PUC_FULL_SIZE_SHIFT) ? 1 : 0;
  529. usDacWidthIndex = (HwDeviceExtension->Dac.usRamdacWidth / 32) - 1;
  530. usNumBanksIndex = HwDeviceExtension->p91State.usNumVramBanks >> 1;
  531. if ((ulMemConfig & P91_MC_BLANK_EDGE_MSK) == P91_MC_SYNC_RISE_EDGE)
  532. {
  533. usBlankDlyIndex = usPositiveBlnkDly[usSamIndex]
  534. [usDacWidthIndex]
  535. [usNumBanksIndex];
  536. }
  537. else
  538. {
  539. usBlankDlyIndex = usNegativeBlnkDly[usSamIndex]
  540. [usDacWidthIndex]
  541. [usNumBanksIndex];
  542. }
  543. //
  544. // Now special case for the number of banks, the DAC width, the SAM size and
  545. // the pixel depth.
  546. //
  547. if ((HwDeviceExtension->usBitsPixel == 32) &&
  548. (HwDeviceExtension->p91State.usNumVramBanks == 1) &&
  549. (usSamIndex == 1) &&
  550. (HwDeviceExtension->Dac.usRamdacWidth == 32))
  551. {
  552. usBlankDlyIndex = 2;
  553. }
  554. if ((HwDeviceExtension->usBitsPixel == 32) &&
  555. (HwDeviceExtension->p91State.usNumVramBanks == 2) &&
  556. (usSamIndex == 1) &&
  557. (HwDeviceExtension->Dac.usRamdacWidth == 32))
  558. {
  559. usBlankDlyIndex = 1;
  560. }
  561. }
  562. //
  563. // Now use the blank delay index to set the blank_dly (27-38) field in the
  564. // memory configuration regsiter.
  565. //
  566. ulMemConfig |= ulBlankDly[usBlankDlyIndex];
  567. //
  568. // Now calculate the blank delay adjustment used when calculating the timing
  569. // values.
  570. //
  571. HwDeviceExtension->p91State.ulBlnkDlyAdj = (ULONG) usBlankDlyIndex;
  572. //
  573. // As if everything wasn't bad enough!!! One more special case.
  574. //
  575. if ((HwDeviceExtension->p91State.usRevisionID >= WTK_9100_REV3) &&
  576. (HwDeviceExtension->p91State.usNumVramBanks == 2) &&
  577. ((HwDeviceExtension->p91State.ulPuConfig & P91_PUC_VRAM_SAM_SIZE)
  578. == P91_PUC_HALF_SIZE_SHIFT) &&
  579. (HwDeviceExtension->Dac.usRamdacWidth == 64) &&
  580. (HwDeviceExtension->usBitsPixel == 8) &&
  581. (HwDeviceExtension->VideoData.XSize == 640) &&
  582. (HwDeviceExtension->VideoData.YSize == 480))
  583. {
  584. //
  585. // Fix up for A3 silicon.
  586. //
  587. HwDeviceExtension->p91State.ulBlnkDlyAdj++;
  588. }
  589. //
  590. // Set the return values.
  591. //
  592. HwDeviceExtension->p91State.ulMemConfVal = ulMemConfig;
  593. HwDeviceExtension->p91State.ulSrctlVal = ulSrtCtl;
  594. HwDeviceExtension->Dac.bRamdacDivides = fDacDividesClock;
  595. return;
  596. } // End CalcP9100MemConfig ()
  597. ULONG
  598. Logbase2 (
  599. ULONG ulValue
  600. )
  601. /*++
  602. Routine Description:
  603. This routine calculates the LOG Base 2 of the passed in value.
  604. Argumentss:
  605. ulValue - Value to calculate LOG Base 2 for.
  606. Return Values:
  607. ulResult - LOG Base 2 of ulValue.
  608. --*/
  609. {
  610. ULONG ulResult;
  611. ulResult = 0;
  612. while (ulValue != 1)
  613. {
  614. ++ulResult;
  615. ulValue >>= 1;
  616. }
  617. return (ulResult);
  618. } // End of Logbase2()
  619. BOOLEAN
  620. P91TestVideoMemory(
  621. PHW_DEVICE_EXTENSION HwDeviceExtension,
  622. USHORT iNumLongWords
  623. )
  624. /*++
  625. Routine Description:
  626. Routine to check if our memory configuration is set right.
  627. Argumentss:
  628. HwDeviceExtension - Pointer to the miniport driver's device extension.
  629. Specified number of longwords to test.
  630. Return Values:
  631. TRUE == if video memory checks out OK.
  632. FALSE == otherwise.
  633. --*/
  634. {
  635. unsigned long i;
  636. ULONG ulOtherBankBits;
  637. ULONG aulOldBits[32];
  638. BOOLEAN bRet = TRUE;
  639. //
  640. // The SandleFoot blue screen showed corruption from this test.
  641. // We tried to not save this data, but we had to.
  642. // In addition to saving the screen data around the test, we have also
  643. // saved the state of the Memory Configuration register.
  644. ulOtherBankBits =
  645. VideoPortReadRegisterUlong((PULONG) HwDeviceExtension->FrameAddress + 0x8000);
  646. for (i = 0; i < 32; i++)
  647. {
  648. aulOldBits[i] =
  649. VideoPortReadRegisterUlong((PULONG) HwDeviceExtension->FrameAddress + i);
  650. }
  651. //
  652. // Make sure you cause a row change at the beginning of the memory
  653. // by first accessing a location that is guaranteed to be in another row.
  654. //
  655. VideoPortWriteRegisterUlong((PULONG) HwDeviceExtension->FrameAddress + 0x8000,
  656. 0x5A5A5A5A);
  657. //
  658. // Test iNumLongWords doubleword locations by writing the inverse of the
  659. // address to each memory location.
  660. //
  661. for (i = 0 ; i < iNumLongWords; i++)
  662. {
  663. VideoPortWriteRegisterUlong((PULONG) HwDeviceExtension->FrameAddress + i,
  664. ~i);
  665. }
  666. //
  667. // Now read them back and test for failure
  668. //
  669. for (i = 0 ; i < iNumLongWords; i++)
  670. {
  671. //
  672. // If any one fails, return error...
  673. //
  674. if (VideoPortReadRegisterUlong((PULONG) HwDeviceExtension->FrameAddress + i)
  675. != ~i)
  676. {
  677. bRet = FALSE;
  678. break;
  679. }
  680. }
  681. //
  682. // Restore everything.
  683. //
  684. VideoPortWriteRegisterUlong((PULONG) HwDeviceExtension->FrameAddress + 0x8000,
  685. ulOtherBankBits);
  686. for (i = 0; i < 32; i++)
  687. {
  688. VideoPortWriteRegisterUlong((PULONG) HwDeviceExtension->FrameAddress + i,
  689. aulOldBits[i]);
  690. }
  691. //
  692. // If all of them work, return success
  693. //
  694. return(bRet);
  695. } // End of int P91TestVideoMemory()
  696. VOID
  697. P91SizeVideoMemory(
  698. PHW_DEVICE_EXTENSION HwDeviceExtension
  699. )
  700. /*++
  701. Routine Description:
  702. Routine to determine the amount of memory and what memory configuration
  703. bits to set.
  704. This routine assumes that the board is already initialized.
  705. It also sets (...)
  706. Argumentss:
  707. HwDeviceExtension - Pointer to the miniport driver's device extension.
  708. Return Values:
  709. None.
  710. Modifies:
  711. HwDeviceExtension->p91State.usNumVramBanks = 1,2 or 4;
  712. HwDeviceExtension->p91State.ulFrameBufferSize = 0x0100000,
  713. 0x0200000 or 0x0400000;
  714. --*/
  715. {
  716. ULONG ulMemConfig;
  717. VideoDebugPrint((2, "P91SizeVideoMemory - Entry\n"));
  718. ulMemConfig = P9_RD_REG(P91_MEM_CONFIG);
  719. if (HwDeviceExtension->p91State.bVram256)
  720. {
  721. //
  722. // Assume 4 banks and test assertion...
  723. //
  724. HwDeviceExtension->p91State.usMemConfNum = 7;
  725. HwDeviceExtension->p91State.usNumVramBanks = 4;
  726. HwDeviceExtension->p91State.ulFrameBufferSize = 0x0400000;
  727. P9_WR_REG(P91_MEM_CONFIG, 0x00000007);
  728. if (!P91TestVideoMemory(HwDeviceExtension, 32))
  729. {
  730. //
  731. // Assertion failed, so assume 2 banks and test assertion...
  732. //
  733. HwDeviceExtension->p91State.usMemConfNum = 5;
  734. HwDeviceExtension->p91State.usNumVramBanks = 2;
  735. HwDeviceExtension->p91State.ulFrameBufferSize = 0x0200000L;
  736. P9_WR_REG(P91_MEM_CONFIG, 0x00000005);
  737. if (!P91TestVideoMemory(HwDeviceExtension, 32))
  738. {
  739. //
  740. // If second assertion fails, assume 1 bank
  741. //
  742. HwDeviceExtension->p91State.usMemConfNum = 4;
  743. HwDeviceExtension->p91State.usNumVramBanks = 1;
  744. HwDeviceExtension->p91State.ulFrameBufferSize = 0x0100000;
  745. }
  746. }
  747. }
  748. else
  749. {
  750. //
  751. // Assume 4 banks and test assertion...
  752. //
  753. HwDeviceExtension->p91State.usMemConfNum = 3;
  754. HwDeviceExtension->p91State.usNumVramBanks = 4;
  755. HwDeviceExtension->p91State.ulFrameBufferSize = 0x0200000;
  756. P9_WR_REG(P91_MEM_CONFIG, 0x00000003);
  757. if (!P91TestVideoMemory(HwDeviceExtension, 32))
  758. {
  759. //
  760. // Assertion failed, so assume 2 banks
  761. //
  762. HwDeviceExtension->p91State.usMemConfNum = 1;
  763. HwDeviceExtension->p91State.usNumVramBanks = 2;
  764. HwDeviceExtension->p91State.ulFrameBufferSize = 0x0100000L;
  765. }
  766. }
  767. VideoDebugPrint((3, "P91SizeVideoMemory: usNumVramBanks = %d\n",
  768. HwDeviceExtension->p91State.usNumVramBanks));
  769. VideoDebugPrint((3, "P91SizeVideoMemory: usFrameBufferSize = %lx\n",
  770. HwDeviceExtension->p91State.ulFrameBufferSize));
  771. VideoDebugPrint((2, "P91SizeVideoMemory - Exit\n"));
  772. P9_WR_REG(P91_MEM_CONFIG, ulMemConfig);
  773. } // End of P91SizeVideoMemory()
  774. BOOLEAN
  775. ValidateMode(
  776. PHW_DEVICE_EXTENSION HwDeviceExtension,
  777. PVIDEO_MODE_INFORMATION ModeInformation
  778. )
  779. /*++
  780. Routine Description:
  781. Function to determine if the mode is valid based on the current
  782. adapter. The factors that determine if the mode is valid are the
  783. DAC and the size of video ram.
  784. Argumentss:
  785. HwDeviceExtension - Pointer to the miniport driver's device extension.
  786. ModeInformation - Pointer to the resolution information.
  787. Return Values:
  788. TRUE == The resolution is valid,
  789. FALSE == The resolution is invalid.
  790. --*/
  791. {
  792. //
  793. // Check to see if 24BPP mode is specified and if this DAC supports it...
  794. //
  795. if ( (ModeInformation->BitsPerPlane == 24) &&
  796. (!HwDeviceExtension->Dac.bRamdac24BPP) )
  797. return(FALSE); // 24Bpp not supported by this DAC...
  798. //
  799. // Check to see if we have enough video ram to support this resolution...
  800. //
  801. if ( ((ULONG) (ModeInformation->BitsPerPlane/8) *
  802. ModeInformation->VisScreenWidth *
  803. ModeInformation->VisScreenHeight) >
  804. HwDeviceExtension->FrameLength )
  805. {
  806. VideoDebugPrint((2, "ValidateMode: VisScreenWidth = %d\n",
  807. ModeInformation->VisScreenWidth));
  808. VideoDebugPrint((2, "ValidateMode: VisScreenHeight = %d\n",
  809. ModeInformation->VisScreenHeight));
  810. VideoDebugPrint((2, "ValidateMode: BitsPerPlane = %d\n",
  811. ModeInformation->BitsPerPlane));
  812. VideoDebugPrint((2, "ValidateMode: Vram needed = %ld\n",
  813. ((ULONG) (ModeInformation->BitsPerPlane/8) *
  814. ModeInformation->VisScreenWidth *
  815. ModeInformation->VisScreenHeight) ));
  816. return(FALSE); // Not enough video memory for this mode...
  817. }
  818. else
  819. return(TRUE);
  820. } // End of ValidateMode()