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.

594 lines
20 KiB

  1. /************************************************************************/
  2. /* */
  3. /* SETUP_M.C */
  4. /* */
  5. /* Aug 27 1993 (c) 1993, ATI Technologies Incorporated. */
  6. /************************************************************************/
  7. /********************** PolyTron RCS Utilities
  8. $Revision: 1.11 $
  9. $Date: 23 Jan 1996 11:52:14 $
  10. $Author: RWolff $
  11. $Log: S:/source/wnt/ms11/miniport/archive/setup_m.c_v $
  12. *
  13. * Rev 1.11 23 Jan 1996 11:52:14 RWolff
  14. * Eliminated level 3 warnings.
  15. *
  16. * Rev 1.10 31 Mar 1995 11:52:06 RWOLFF
  17. * Changed from all-or-nothing debug print statements to thresholds
  18. * depending on importance of the message.
  19. *
  20. * Rev 1.9 14 Mar 1995 18:17:18 ASHANMUG
  21. * Reset engine on fifo space check time-out.
  22. *
  23. * Rev 1.8 14 Mar 1995 15:59:42 ASHANMUG
  24. * Timeout on idle check and fifo check.
  25. *
  26. * Rev 1.7 08 Mar 1995 11:35:50 ASHANMUG
  27. * Modified return values to be correct
  28. *
  29. * Rev 1.5 22 Jul 1994 17:47:28 RWOLFF
  30. * Merged with Richard's non-x86 code stream.
  31. *
  32. * Rev 1.4 06 Jul 1994 16:41:00 RWOLFF
  33. * Changed a few loops that I missed for the last checkin to use
  34. * NUM_IO_ACCESS_RANGES instead of NUM_DRIVER_ACCESS_RANGES.
  35. *
  36. * Rev 1.3 30 Jun 1994 18:23:14 RWOLFF
  37. * Moved IsApertureConflict_m() from QUERY_M.C. Instead of checking to see if
  38. * we can read back a value we write to the aperture, then looking for the
  39. * correct text attribute, we now call VideoPortVerifyAccessRanges() with
  40. * the LFB included in the list of address ranges we are trying to claim.
  41. * If the call succeeds, the aperture is enabled. If it fails, we make another
  42. * call that does not try to claim the LFB (this call shouldn't fail, since
  43. * it's a duplicate of a call which has succeeded previously). Added routine
  44. * IsVGAConflict_m(), which does the same thing except for the VGA aperture
  45. * instead of the LFB.
  46. *
  47. * Rev 1.2 14 Mar 1994 16:36:42 RWOLFF
  48. * Functions used by ATIMPResetHw() are not pageable.
  49. *
  50. * Rev 1.1 07 Feb 1994 14:14:48 RWOLFF
  51. * Added alloc_text() pragmas to allow miniport to be swapped out when
  52. * not needed.
  53. *
  54. * Rev 1.0 31 Jan 1994 11:20:58 RWOLFF
  55. * Initial revision.
  56. *
  57. * Rev 1.4 14 Jan 1994 15:26:36 RWOLFF
  58. * Fixed de-initialization of memory mapped registers, added routine
  59. * to see if memory mapped registers are available.
  60. *
  61. * Rev 1.3 15 Dec 1993 16:02:26 RWOLFF
  62. * No longer allows use of memory mapped registers on EISA machines,
  63. * starts mapping of memory mapped registers at index 0 due to removal
  64. * of placeholder for linear framebuffer.
  65. *
  66. * Rev 1.2 05 Nov 1993 13:32:36 RWOLFF
  67. * Can now unmap I/O address ranges.
  68. *
  69. * Rev 1.1 08 Oct 1993 11:18:24 RWOLFF
  70. * Now checks to see if memory mapped registers can be used, and unmaps them
  71. * if they aren't usable (NCR Dual Pentium fix).
  72. *
  73. * Rev 1.0 03 Sep 1993 14:25:36 RWOLFF
  74. * Initial revision.
  75. End of PolyTron RCS section *****************/
  76. #ifdef DOC
  77. SETUP_M.C - Setup routines for 8514/A compatible accelerators.
  78. DESCRIPTION
  79. This file contains routines which provide services specific to
  80. the 8514/A-compatible family of ATI accelerators.
  81. OTHER FILES
  82. #endif
  83. #include "dderror.h"
  84. #include <stdio.h>
  85. #include <stdlib.h>
  86. #include <string.h>
  87. #include "miniport.h"
  88. #include "ntddvdeo.h"
  89. #include "video.h"
  90. #include "stdtyp.h"
  91. #include "amach.h"
  92. #include "amach1.h"
  93. #include "atimp.h"
  94. #include "services.h"
  95. #define INCLUDE_SETUP_M
  96. #include "setup_m.h"
  97. /*
  98. * Allow miniport to be swapped out when not needed.
  99. *
  100. * WaitForIdle_m() is called by ATIMPResetHw(), which
  101. * must be in nonpageable memory.
  102. */
  103. #if defined (ALLOC_PRAGMA)
  104. #pragma alloc_text(PAGE_M, CompatIORangesUsable_m)
  105. #pragma alloc_text(PAGE_M, CompatMMRangesUsable_m)
  106. #pragma alloc_text(PAGE_M, UnmapIORanges_m)
  107. #pragma alloc_text(PAGE_M, MemoryMappedEnabled_m)
  108. #pragma alloc_text(PAGE_M, CheckFIFOSpace_m)
  109. #pragma alloc_text(PAGE_M, IsApertureConflict_m)
  110. #pragma alloc_text(PAGE_M, IsVGAConflict_m)
  111. #endif
  112. /*
  113. * VP_STATUS CompatIORangesUsable_m(void);
  114. *
  115. * Ask Windows NT for permission to use the I/O space address ranges
  116. * needed by the 8514/A compatible ATI accelerators.
  117. *
  118. * Returns:
  119. * NO_ERROR if successful
  120. * error code if unable to gain access to the ranges we need.
  121. */
  122. VP_STATUS CompatIORangesUsable_m(void)
  123. {
  124. VP_STATUS Status; /* Value returned by operating system calls */
  125. short Count; /* Loop counter */
  126. /*
  127. * Check to see if there is a hardware resource conflict.
  128. */
  129. Status = VideoPortVerifyAccessRanges(phwDeviceExtension,
  130. NUM_IO_ACCESS_RANGES,
  131. DriverIORange_m);
  132. if (Status != NO_ERROR)
  133. {
  134. return Status;
  135. }
  136. /*
  137. * Clear the list of I/O mapped registers. This is done so
  138. * that if the loop below fails because one I/O range can't
  139. * be mapped, and we need to unmap these registers before,
  140. * mapping the registers needed for another accelerator type,
  141. * we don't unmap nonexistant address ranges due to the
  142. * array of processed addresses containing random data.
  143. */
  144. memset(phwDeviceExtension->aVideoAddressIO, 0, NUM_IO_ACCESS_RANGES * sizeof(ULONG));
  145. /*
  146. * Map the video controller address ranges we need to identify
  147. * our cards into the system virtual address space.
  148. *
  149. * Since we only use I/O mapped registers here, set the
  150. * mapped addresses for memory mapped registers to
  151. * 0 (flag to show the registers are not memory mapped)
  152. * in case they were initialized to a nonzero value.
  153. */
  154. for (Count=0; Count < NUM_IO_ACCESS_RANGES; Count++)
  155. {
  156. if ((phwDeviceExtension->aVideoAddressIO[Count] =
  157. VideoPortGetDeviceBase(phwDeviceExtension,
  158. DriverIORange_m[Count].RangeStart,
  159. DriverIORange_m[Count].RangeLength,
  160. DriverIORange_m[Count].RangeInIoSpace)) == NULL)
  161. {
  162. return ERROR_INVALID_PARAMETER;
  163. }
  164. phwDeviceExtension->aVideoAddressMM[Count] = 0;
  165. } /* End for */
  166. return NO_ERROR;
  167. } /* CompatIORangesUsable_m() */
  168. /*
  169. * void CompatMMRangesUsable_m(void);
  170. *
  171. * Ask Windows NT for permission to use the memory mapped registers
  172. * needed by the 8514/A compatible ATI accelerators.
  173. */
  174. void CompatMMRangesUsable_m(void)
  175. {
  176. PHYSICAL_ADDRESS MMrange; /* Used in translating offset to memory address */
  177. USHORT USTemp; /* Used to enable memory mapped registers */
  178. int Count; /* Loop counter */
  179. WORD SrcX; /* Saved contents of SRC_X register */
  180. ULONG_PTR ExtGeStatusMM; /* Memory mapped address for EXT_GE_STATUS */
  181. struct query_structure *QueryPtr; /* Query information for the card */
  182. /*
  183. * Get a formatted pointer into the query section of HwDeviceExtension.
  184. * The CardInfo[] field is an unformatted buffer.
  185. */
  186. QueryPtr = (struct query_structure *) (phwDeviceExtension->CardInfo);
  187. /*
  188. * Memory mapped registers are not available on EISA cards.
  189. */
  190. if (QueryPtr->q_bus_type == BUS_EISA)
  191. {
  192. return;
  193. }
  194. /*
  195. * ALPHA machines crash during the test to see whether memory-mapped
  196. * registers are usable, so on these machines we assume that
  197. * memory-mapped registers are not available.
  198. */
  199. #if defined (ALPHA) || defined (_ALPHA_)
  200. return;
  201. #endif
  202. /*
  203. * Use an I/O mapped read on the register we're going to use to see
  204. * if memory mapped registers are usable, because if they aren't usable
  205. * we won't get a valid result if we wait until we've enabled
  206. * memory mapped registers before reading it.
  207. */
  208. SrcX = INPW(R_SRC_X);
  209. USTemp = INPW(LOCAL_CONTROL);
  210. USTemp |= 0x0020; // Enable memory mapped registers
  211. OUTPW(LOCAL_CONTROL, USTemp);
  212. MMrange.HighPart = 0;
  213. for (Count=0; Count < NUM_IO_ACCESS_RANGES; Count++)
  214. {
  215. /*
  216. * In a 32-bit address space, the high doubleword of all
  217. * physical addresses is zero. Setting this value to DONT_USE
  218. * indicates that this accelerator register isn't memory mapped.
  219. */
  220. if (DriverMMRange_m[Count].RangeStart.HighPart != DONT_USE)
  221. {
  222. /*
  223. * DriverMMRange_m[Count].RangeStart.LowPart is the offset of
  224. * the memory mapped register from the beginning of the
  225. * block of memory mapped registers. We must add the offset
  226. * of the start of the memory mapped register area from
  227. * the start of the linear framebuffer (4M aperture assumed)
  228. * and the physical address of the start of the linear
  229. * framebuffer to get the physical address of this
  230. * memory mapped register.
  231. */
  232. MMrange.LowPart = DriverMMRange_m[Count].RangeStart.LowPart + 0x3FFE00 + phwDeviceExtension->PhysicalFrameAddress.LowPart;
  233. phwDeviceExtension->aVideoAddressMM[Count] =
  234. VideoPortGetDeviceBase(phwDeviceExtension,
  235. MMrange,
  236. DriverMMRange_m[Count].RangeLength,
  237. FALSE); // not in IO space
  238. }
  239. }
  240. /*
  241. * Some cards use an ASIC which is capable of using memory mapped
  242. * registers, but an older board design which doesn't allow their
  243. * use. To test this, check whether the SRC_X register (this register
  244. * is available as memory mapped on any card which is capable of
  245. * supporting memory mapped registers) remembers a value that is written
  246. * to it. If it doesn't, then undo the memory mapping, since this
  247. * test shows that memory mapped registers are not available.
  248. */
  249. VideoDebugPrint((DEBUG_DETAIL, "About to test whether memory mapped registers can be used\n"));
  250. OUTPW(SRC_X, 0x0AAAA);
  251. /*
  252. * WaitForIdle_m() uses the EXT_GE_STATUS register, which is handled
  253. * as memory mapped if available. Since we don't know if memory mapped
  254. * registers are available, work around this by saving the address
  255. * of the memory mapped EXT_GE_STATUS register, setting the address
  256. * to zero to force the use of the I/O mapped EXT_GE_STATUS, then
  257. * restoring the address after WaitForIdle_m() has finished.
  258. */
  259. ExtGeStatusMM = (ULONG_PTR) phwDeviceExtension->aVideoAddressMM[EXT_GE_STATUS];
  260. phwDeviceExtension->aVideoAddressMM[EXT_GE_STATUS] = 0;
  261. WaitForIdle_m();
  262. phwDeviceExtension->aVideoAddressMM[EXT_GE_STATUS] = (PVOID) ExtGeStatusMM;
  263. if (INPW(R_SRC_X) != 0x02AA)
  264. {
  265. VideoDebugPrint((DEBUG_DETAIL, "Can't use memory mapped ranges\n"));
  266. for (Count = 0; Count < NUM_IO_ACCESS_RANGES; Count++)
  267. {
  268. if (phwDeviceExtension->aVideoAddressMM[Count] != 0)
  269. {
  270. VideoPortFreeDeviceBase(phwDeviceExtension,
  271. phwDeviceExtension->aVideoAddressMM[Count]);
  272. phwDeviceExtension->aVideoAddressMM[Count] = 0;
  273. }
  274. }
  275. USTemp = INPW(LOCAL_CONTROL);
  276. USTemp &= 0x0FFDF; /* Disable memory mapped registers */
  277. OUTPW(LOCAL_CONTROL, USTemp);
  278. }
  279. else
  280. {
  281. VideoDebugPrint((DEBUG_DETAIL, "Memory mapped registers are usable\n"));
  282. }
  283. OUTPW(SRC_X, SrcX);
  284. VideoDebugPrint((DEBUG_DETAIL, "Memory mapped register test complete\n"));
  285. return;
  286. } /* CompatMMRangesUsable_m() */
  287. /***************************************************************************
  288. *
  289. * void UnmapIORanges_m(void);
  290. *
  291. * DESCRIPTION:
  292. * Unmap the I/O address ranges mapped by CompatIORangesUsable_m() prior
  293. * to mapping the I/O address ranges used by a non-8514/A-compatible
  294. * ATI accelerator.
  295. *
  296. * GLOBALS CHANGED:
  297. * phwDeviceExtension->aVideoAddressIO[]
  298. *
  299. * CALLED BY:
  300. * ATIMPFindAdapter()
  301. *
  302. * AUTHOR:
  303. * Robert Wolff
  304. *
  305. * CHANGE HISTORY:
  306. *
  307. * TEST HISTORY:
  308. *
  309. ***************************************************************************/
  310. void UnmapIORanges_m(void)
  311. {
  312. short Count; /* Loop counter */
  313. for (Count=1; Count < NUM_IO_ACCESS_RANGES; Count++)
  314. {
  315. /*
  316. * Only unmap those ranges which have been mapped. We don't need
  317. * to worry about unmapping nonexistant addresses (due to
  318. * uninitialized data) if CompatIORangesUsable_m() failed
  319. * partway through mapping because this routine initialized all
  320. * phwDeviceExtension->aVideoAddressIO[] entries to zero
  321. * before it started mapping the I/O ranges.
  322. */
  323. if (phwDeviceExtension->aVideoAddressIO[Count] != 0)
  324. {
  325. VideoPortFreeDeviceBase(phwDeviceExtension,
  326. phwDeviceExtension->aVideoAddressIO[Count]);
  327. phwDeviceExtension->aVideoAddressIO[Count] = 0;
  328. }
  329. }
  330. return;
  331. } /* UnmapIORanges_m() */
  332. /***************************************************************************
  333. *
  334. * BOOL MemoryMappedEnabled_m(void);
  335. *
  336. * DESCRIPTION:
  337. * Check to see whether we are using memory mapped registers.
  338. *
  339. * RETURN VALUE:
  340. * TRUE if memory mapped registers are available
  341. * FALSE if they are not
  342. *
  343. * GLOBALS CHANGED:
  344. * None
  345. *
  346. * CALLED BY:
  347. * May be called by any function after CompatMMRangesUsable_m()
  348. * has been called.
  349. *
  350. * AUTHOR:
  351. * Robert Wolff
  352. *
  353. * CHANGE HISTORY:
  354. *
  355. * TEST HISTORY:
  356. *
  357. ***************************************************************************/
  358. BOOL MemoryMappedEnabled_m(void)
  359. {
  360. /*
  361. * If memory mapped registers are enabled, EXT_GE_STATUS will be
  362. * available in memory mapped form.
  363. */
  364. if (phwDeviceExtension->aVideoAddressMM[EXT_GE_STATUS] != 0)
  365. return TRUE;
  366. else
  367. return FALSE;
  368. } /* MemoryMappedEnabled_m() */
  369. /*
  370. * int WaitForIdle_m(void);
  371. *
  372. * Poll GE_STAT waiting for GE_BUSY to go low. If GE_BUSY does not go
  373. * low within a reasonable number of attempts, time out.
  374. *
  375. * Returns:
  376. * FALSE if timeout: 3 seconds is an arbitrary value
  377. * TRUE if engine is idle
  378. */
  379. int WaitForIdle_m(void)
  380. {
  381. int i;
  382. for (i=0; i<300; i++)
  383. {
  384. if ((INPW(EXT_GE_STATUS) & GE_ACTIVE) == 0)
  385. return(TRUE);
  386. /* Delay for 1/100th of a second */
  387. delay(10);
  388. }
  389. /* Something has happened, reset the engine and return false */
  390. VideoDebugPrint((DEBUG_ERROR, "ATI: Timeout on WaitForIdle_m()\n"));
  391. OUTPW(SUBSYS_CNTL, 0x900F);
  392. OUTPW(SUBSYS_CNTL, 0x500F);
  393. return(FALSE);
  394. } /* WaitForIdle_m() */
  395. /*
  396. * void CheckFIFOSpace_m(SpaceNeeded);
  397. *
  398. * WORD SpaceNeeded; Number of free FIFO entries needed
  399. *
  400. * Wait until the specified number of FIFO entries are free
  401. * on an 8514/A-compatible ATI accelerator.
  402. *
  403. * Timeout after 3 seconds
  404. */
  405. void CheckFIFOSpace_m(WORD SpaceNeeded)
  406. {
  407. int i;
  408. for (i=0; i<300; i++)
  409. {
  410. /* Return from test if no more space is needed */
  411. if ( !(INPW(EXT_FIFO_STATUS)&SpaceNeeded) )
  412. return;
  413. delay(10);
  414. }
  415. /* Something bad has happened, just return */
  416. VideoDebugPrint((DEBUG_ERROR, "ATI: Timeout on CheckFIFOSpace_m()\n"));
  417. OUTPW(SUBSYS_CNTL, 0x900F);
  418. OUTPW(SUBSYS_CNTL, 0x500F);
  419. return;
  420. } /* CheckFIFOSpace_m() */
  421. /*
  422. * BOOL IsApertureConflict_m(QueryPtr);
  423. *
  424. * struct query_structure *QueryPtr; Pointer to query structure
  425. *
  426. * Check to see if the linear aperture conflicts with other memory.
  427. * If a conflict exists, disable the linear aperture.
  428. *
  429. * Returns:
  430. * TRUE if a conflict exists (aperture unusable)
  431. * FALSE if the aperture is usable.
  432. */
  433. BOOL IsApertureConflict_m(struct query_structure *QueryPtr)
  434. {
  435. WORD ApertureData; /* Value read from MEM_CFG register */
  436. VP_STATUS Status; /* Return value from VideoPortVerifyAccessRanges() */
  437. /*
  438. * If there is an aperture conflict, a call to
  439. * VideoPortVerifyAccessRanges() including our linear framebuffer in
  440. * the range list will return an error. If there is no conflict, it
  441. * will return success.
  442. */
  443. DriverIORange_m[FRAMEBUFFER_ENTRY].RangeStart.LowPart = QueryPtr->q_aperture_addr*ONE_MEG;
  444. DriverIORange_m[FRAMEBUFFER_ENTRY].RangeLength = 4*ONE_MEG;
  445. Status = VideoPortVerifyAccessRanges(phwDeviceExtension,
  446. NUM_DRIVER_ACCESS_RANGES,
  447. DriverIORange_m);
  448. if (Status != NO_ERROR)
  449. {
  450. /*
  451. * If there is an aperture conflict, reclaim our I/O ranges without
  452. * asking for the LFB. This call should not fail, since we would not
  453. * have reached this point if there were a conflict.
  454. */
  455. Status = VideoPortVerifyAccessRanges(phwDeviceExtension,
  456. NUM_IO_ACCESS_RANGES,
  457. DriverIORange_m);
  458. if (Status != NO_ERROR)
  459. VideoDebugPrint((DEBUG_ERROR, "ERROR: Can't reclaim I/O ranges\n"));
  460. /*
  461. * Adjust the list of mode tables to take into account the
  462. * fact that we're using the VGA aperture instead of the LFB.
  463. */
  464. ISAPitchAdjust(QueryPtr);
  465. return TRUE;
  466. }
  467. else
  468. {
  469. /*
  470. * Enable the linear aperture
  471. */
  472. ApertureData = INPW(MEM_CFG) & 0x0fffc; /* Preserve bits 2-15 */
  473. ApertureData |= 0x0002; /* 4M aperture */
  474. OUTPW(MEM_CFG, ApertureData);
  475. return FALSE;
  476. }
  477. } /* IsApertureConflict_m() */
  478. /*
  479. * BOOL IsVGAConflict_m(void);
  480. *
  481. * Check to see if the VGA aperture conflicts with other memory.
  482. *
  483. * Returns:
  484. * TRUE if a conflict exists (VGA aperture unusable)
  485. * FALSE if the VGA aperture is usable.
  486. */
  487. BOOL IsVGAConflict_m(void)
  488. {
  489. VP_STATUS Status; /* Return value from VideoPortVerifyAccessRanges() */
  490. /*
  491. * If there is an aperture conflict, a call to
  492. * VideoPortVerifyAccessRanges() including the VGA aperture in
  493. * the range list will return an error. If there is no conflict, it
  494. * will return success.
  495. */
  496. DriverIORange_m[FRAMEBUFFER_ENTRY].RangeStart.LowPart = 0xA0000;
  497. DriverIORange_m[FRAMEBUFFER_ENTRY].RangeLength = 0x10000;
  498. DriverIORange_m[FRAMEBUFFER_ENTRY].RangeShareable = TRUE;
  499. Status = VideoPortVerifyAccessRanges(phwDeviceExtension,
  500. NUM_DRIVER_ACCESS_RANGES,
  501. DriverIORange_m);
  502. if (Status != NO_ERROR)
  503. {
  504. /*
  505. * If there is an aperture conflict, reclaim our I/O ranges without
  506. * asking for the LFB. This call should not fail, since we would not
  507. * have reached this point if there were a conflict.
  508. */
  509. Status = VideoPortVerifyAccessRanges(phwDeviceExtension,
  510. NUM_IO_ACCESS_RANGES,
  511. DriverIORange_m);
  512. if (Status != NO_ERROR)
  513. VideoDebugPrint((DEBUG_ERROR, "ERROR: Can't reclaim I/O ranges\n"));
  514. return TRUE;
  515. }
  516. else
  517. {
  518. return FALSE;
  519. }
  520. } /* IsVGAConflict_m() */