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.

539 lines
18 KiB

  1. /************************************************************************/
  2. /* */
  3. /* DETECT_M.C */
  4. /* */
  5. /* Aug 25 1993 (c) 1993, ATI Technologies Incorporated. */
  6. /************************************************************************/
  7. /********************** PolyTron RCS Utilities
  8. $Revision: 1.9 $
  9. $Date: 31 Mar 1995 11:55:44 $
  10. $Author: RWOLFF $
  11. $Log: S:/source/wnt/ms11/miniport/vcs/detect_m.c $
  12. *
  13. * Rev 1.9 31 Mar 1995 11:55:44 RWOLFF
  14. * Changed from all-or-nothing debug print statements to thresholds
  15. * depending on importance of the message.
  16. *
  17. * Rev 1.8 11 Jan 1995 13:58:46 RWOLFF
  18. * Fixed bug introduced in rev. 1.4 - COM4: was detected as being a Mach8
  19. * or Mach32 card, which would leave the triple-boot with no valid video
  20. * driver.
  21. *
  22. * Rev 1.7 04 Jan 1995 12:02:06 RWOLFF
  23. * Get_BIOS_Seg() moved to SERVICES.C as part of fix for non-ATI cards
  24. * being detected as Mach64.
  25. *
  26. * Rev 1.6 23 Dec 1994 10:48:10 ASHANMUG
  27. * ALPHA/Chrontel-DAC
  28. *
  29. * Rev 1.5 19 Aug 1994 17:10:56 RWOLFF
  30. * Added support for Graphics Wonder, fixed search for BIOS signature,
  31. * removed dead code.
  32. *
  33. * Rev 1.4 22 Jul 1994 17:46:56 RWOLFF
  34. * Merged with Richard's non-x86 code stream.
  35. *
  36. * Rev 1.3 20 Jul 1994 13:03:44 RWOLFF
  37. * Fixed debug print statment.
  38. *
  39. * Rev 1.2 31 Mar 1994 15:06:42 RWOLFF
  40. * Added debugging code.
  41. *
  42. * Rev 1.1 07 Feb 1994 14:06:42 RWOLFF
  43. * Added alloc_text() pragmas to allow miniport to be swapped out when
  44. * not needed.
  45. *
  46. * Rev 1.0 31 Jan 1994 11:05:48 RWOLFF
  47. * Initial revision.
  48. *
  49. * Rev 1.3 05 Nov 1993 13:23:36 RWOLFF
  50. * Fixed BIOS segment detection (used to always get C000).
  51. *
  52. * Rev 1.2 08 Oct 1993 11:09:26 RWOLFF
  53. * Added "_m" to function names to identify them as being specific to the
  54. * 8514/A-compatible family of ATI accelerators.
  55. *
  56. * Rev 1.1 24 Sep 1993 11:41:58 RWOLFF
  57. * Removed mapping of identification-only registers for all card families,
  58. * added additional 8514/A-compatible information gathering formerly done
  59. * in ATIMP.C.
  60. *
  61. * Rev 1.0 03 Sep 1993 14:22:48 RWOLFF
  62. * Initial revision.
  63. End of PolyTron RCS section *****************/
  64. #ifdef DOC
  65. DETECT_M.C - Identify which (if any) ATI card is present in the system.
  66. DESCRIPTION
  67. This file contains routines which check for the presence of various
  68. ATI graphics accelerators.
  69. NOTE: This module only has access to those I/O registers needed
  70. to uniquely identify which ATI card is present.
  71. OTHER FILES
  72. #endif
  73. #include "dderror.h"
  74. #include "miniport.h"
  75. #include "ntddvdeo.h"
  76. #include "video.h"
  77. #include "stdtyp.h"
  78. #include "amach.h"
  79. #include "amach1.h"
  80. #include "atimp.h"
  81. #define INCLUDE_DETECT_M
  82. #include "detect_m.h"
  83. #include "eeprom.h"
  84. #include "modes_m.h"
  85. #include "services.h"
  86. #include "setup_m.h"
  87. /*
  88. * Allow miniport to be swapped out when not needed.
  89. */
  90. #if defined (ALLOC_PRAGMA)
  91. #pragma alloc_text(PAGE_M, WhichATIAccelerator_m)
  92. #pragma alloc_text(PAGE_M, GetExtraData_m)
  93. #pragma alloc_text(PAGE_M, ATIFindExtFcn_m)
  94. #pragma alloc_text(PAGE_M, ATIFindEEPROM_m)
  95. #pragma alloc_text(PAGE_M, ATIGetSpecialHandling_m)
  96. #endif
  97. /*
  98. * Static variables used by this module.
  99. */
  100. static BYTE *p; // Used to address ROM directly
  101. static BYTE GraphicsWonderSignature[] = "GRAPHICS WONDER";
  102. /*
  103. * int WhichATIAccelerator_m(void);
  104. *
  105. * Determine which (if any) ATI 8514/A-compatible
  106. * accelerator is present.
  107. *
  108. * Returns: Accelerator type
  109. * _8514_ULTRA - 8514/Ultra
  110. * GRAPHICS_ULTRA - Graphics ULTRA/Graphics VANTAGE
  111. * MACH32_ULTRA - 68800 detected
  112. * NO_ATI_ACCEL - no ATI 8514/A-compatible accelerator
  113. */
  114. int WhichATIAccelerator_m(void)
  115. {
  116. int status;
  117. WORD Scratch; /* Temporary variable */
  118. /*
  119. * All current ATI accelerators are 8514/A compatible. Check
  120. * for 8514/A, and if not present assume that no ATI accelerator
  121. * is present.
  122. */
  123. /*
  124. * Ensure that the DAC gets clocks (not guaranteed in ISA machines
  125. * in VGA passthrough mode because the cable might not be connected).
  126. */
  127. Passth8514_m(SHOW_ACCEL);
  128. /*
  129. * Cut the pixel clock down to low speed. The value given will yield
  130. * 25 MHz on most of the clock chips we are dealing with.
  131. */
  132. Scratch=(INPW(CLOCK_SEL) & 0xff00) | 0x51;
  133. OUTPW(CLOCK_SEL,Scratch);
  134. /************************************************************************
  135. * DAC index read/write test
  136. * This test writes to the read index and reads it back
  137. * (it should be incremented by one). This tests for the
  138. * presence of a standard DAC in an 8514/A adapter. This
  139. * test is sufficient to ensure the presence of an 8514/A
  140. * type adapter.
  141. ************************************************************************/
  142. OUTP(DAC_R_INDEX,0xa4);
  143. short_delay(); /* This delay must be greater than */
  144. /* than the minimum delay required */
  145. /* by the DAC (see the DAC spec) */
  146. if (INP(DAC_W_INDEX) == 0xa5)
  147. {
  148. /*
  149. * Reading back A5 from DAC_W_INDEX always means an 8514-compatible
  150. * card is present, but not all 8514-compatible cards will
  151. * produce this value.
  152. */
  153. status=TRUE;
  154. VideoDebugPrint((DEBUG_DETAIL, "First test - this is an 8514/A\n"));
  155. }
  156. else{
  157. /*
  158. * Secondary test for 8514/compatible card. Reset the draw engine,
  159. * then write an alternating bit pattern to the ERR_TERM register.
  160. */
  161. OUTPW(SUBSYS_CNTL, 0x900F);
  162. OUTPW(SUBSYS_CNTL, 0x400F);
  163. OUTPW(ERR_TERM, 0x5555);
  164. WaitForIdle_m();
  165. /*
  166. * If we don't read back the value we wrote, then there is
  167. * no 8514-compatible card in the system. If we do read back
  168. * what we wrote, we must repeat the test with the opposite
  169. * bit pattern.
  170. */
  171. if (INPW(ERR_TERM) != 0x5555)
  172. {
  173. status=FALSE;
  174. VideoDebugPrint((DEBUG_DETAIL, "Second test - 0x5555 not found, no 8514/A\n"));
  175. }
  176. else{
  177. OUTPW(ERR_TERM, 0x0AAAA);
  178. WaitForIdle_m();
  179. if (INPW(ERR_TERM) != 0x0AAAA)
  180. {
  181. status=FALSE;
  182. VideoDebugPrint((DEBUG_DETAIL, "Second test - 0xAAAA not found, no 8514/A\n"));
  183. }
  184. else
  185. {
  186. status=TRUE;
  187. VideoDebugPrint((DEBUG_DETAIL, "Second test - this is an 8514/A\n"));
  188. }
  189. }
  190. }
  191. /*
  192. * Turn on passthrough so display is driven by VGA.
  193. */
  194. Passth8514_m(SHOW_VGA);
  195. if (status == FALSE)
  196. {
  197. VideoDebugPrint((DEBUG_DETAIL, "No 8514/A-compatible card found\n"));
  198. return NO_ATI_ACCEL;
  199. }
  200. /*
  201. * We now know that the video card is 8514/A compatible. Now check
  202. * to see if it has the ATI extensions.
  203. */
  204. Scratch = INPW (ROM_ADDR_1); // save original value
  205. OUTPW (ROM_ADDR_1,0x5555); // bits 7 and 15 must be zero
  206. WaitForIdle_m();
  207. status = INPW(ROM_ADDR_1) == 0x5555 ? TRUE : FALSE;
  208. OUTPW (ROM_ADDR_1, Scratch);
  209. if (status == FALSE)
  210. {
  211. VideoDebugPrint((DEBUG_DETAIL, "8514/A-compatible card found, but it doesn't have ATI extensions\n"));
  212. return NO_ATI_ACCEL;
  213. }
  214. /*
  215. * We know that an ATI accelerator is present. Determine which one.
  216. */
  217. VideoDebugPrint((DEBUG_DETAIL, "8514/A-compatible card found with ATI extensions\n"));
  218. #if !defined (i386) && !defined (_i386_)
  219. /*
  220. * Alpha Jensen under test falsely reports Mach 32 as Mach 8
  221. */
  222. Scratch = 0x02aa;
  223. #else
  224. // This is not a R/W register in the Mach 8 but it is in the Mach 32
  225. OUTPW (SRC_X,0xaaaa); // fill with a dummy value
  226. WaitForIdle_m();
  227. Scratch = INPW(R_SRC_X);
  228. #endif
  229. if (Scratch == 0x02aa)
  230. {
  231. status = MACH32_ULTRA;
  232. if (INPW(CONFIG_STATUS_1) & 1) //is 8514 or VGA enabled decides eeprom
  233. {
  234. Mach32DescribeEEPROM(STYLE_8514);
  235. }
  236. else
  237. {
  238. Mach32DescribeEEPROM(STYLE_VGA);
  239. }
  240. }
  241. else{
  242. /*
  243. * Mach 8 card found, determine which one.
  244. *
  245. * Only the 8514/ULTRA shares its clock with the VGA.
  246. * We can't check for the IBM 8514 ROM pages to be
  247. * enabled, because if we did an 8514/ULTRA with the
  248. * jumper set to disable the EEPROM would be falsely
  249. * recognized as a Graphics ULTRA.
  250. *
  251. * Even if this jumper is set to "disabled", we can
  252. * still read from the EEPROM.
  253. */
  254. if (INPW(CONFIG_STATUS_2) & SHARE_CLOCK)
  255. {
  256. status = _8514_ULTRA;
  257. /*
  258. * Only the 8514/Ultra has a hardware bug that prevents it
  259. * from writing to the EEPROM when it is in an 8 bit ISA bus.
  260. */
  261. if ( ((INPW(CONFIG_STATUS_1) & MC_BUS) == 0) // ISA bus only
  262. && ((INPW(CONFIG_STATUS_1) & BUS_16) == 0)) // 8 bit BUS
  263. {
  264. Mach8UltraDescribeEEPROM(BUS_8BIT);
  265. }
  266. else
  267. {
  268. Mach8UltraDescribeEEPROM(BUS_16BIT);
  269. }
  270. }
  271. else{
  272. /*
  273. * Graphics ULTRA or Graphics VANTAGE found. For our purposes,
  274. * they are identical.
  275. */
  276. status = GRAPHICS_ULTRA;
  277. Mach8ComboDescribeEEPROM();
  278. }
  279. }
  280. phwDeviceExtension->ee = &g_ee;
  281. return (status);
  282. } /* WhichATIAccelerator_m() */
  283. /*
  284. * void GetExtraData_m(void);
  285. *
  286. * Collect additional data (register locations and revision-specific
  287. * card capabilities) for the 8514/A-compatible family of ATI accelerators.
  288. */
  289. void GetExtraData_m(void)
  290. {
  291. struct query_structure *QueryPtr; /* Query information for the card */
  292. QueryPtr = (struct query_structure *) (phwDeviceExtension->CardInfo);
  293. ati_reg = reg1CE; // ATI VGA extended register
  294. vga_chip = VideoPortReadRegisterUchar (&((QueryPtr->q_bios)[VGA_CHIP_OFFSET])); /* VGA chip revision as ASCII */
  295. // Find out whether extended BIOS functions and the EEPROM are available.
  296. QueryPtr->q_ext_bios_fcn = ATIFindExtFcn_m(QueryPtr);
  297. QueryPtr->q_eeprom = ATIFindEEPROM_m(QueryPtr);
  298. ATIGetSpecialHandling_m(QueryPtr); // special card distinctions
  299. return;
  300. } /* GetExtraData_m() */
  301. /*
  302. * BOOL ATIFindExtFcn_m(QueryPtr)
  303. *
  304. * struct query_structure *QueryPtr; Pointer to query structure
  305. *
  306. * Routine to see if extended BIOS functions for setting the accelerator
  307. * mode are present in the BIOS of an ATI accelerator card. Assumes that
  308. * an ATI accleratore with a ROM BIOS is present, results are undefined
  309. * if this assumption is invalid.
  310. */
  311. BOOL ATIFindExtFcn_m(struct query_structure *QueryPtr)
  312. {
  313. /*
  314. * TEMPORARY WORKAROUND: Windows NT does not yet provide a hook
  315. * to make an absolute far call to real mode code. To avoid
  316. * branching into code which depends on this service being available,
  317. * report that no extended BIOS functions are available.
  318. *
  319. * Once this hook becomes available so that we can use
  320. * extended BIOS functions, we can check the BIOS to see
  321. * if it contains entry points. On Mach 8 and Mach 32
  322. * accelerators with extended BIOS functions, there will
  323. * be an unconditional jump located at the entry point
  324. * for each extended function.
  325. */
  326. return FALSE;
  327. } /* ATIFindExtFcn_m() */
  328. /*
  329. * BOOL ATIFindEEPROM_m(QueryPtr);
  330. *
  331. * struct query_structure *QueryPtr; Pointer to query structure
  332. *
  333. * Routine to see if an EEPROM is present on an ATI accelerator card.
  334. * Assumes that an ATI accelerator is present and the model is known,
  335. * results are undefined if this assumption is invalid.
  336. *
  337. * Returns:
  338. * TRUE if an EEPROM is present on the card
  339. * FALSE if no EEPROM is present
  340. */
  341. BOOL ATIFindEEPROM_m(struct query_structure *QueryPtr)
  342. {
  343. WORD ValueRead; /* Value read from the EEPROM */
  344. /*
  345. * The EEPROM read will return all bits the same if no EEPROM
  346. * is present. If an EEPROM is present, word 2 will have at least
  347. * one bit set and at least one bit cleared regardless of
  348. * accelerator type (8514/ULTRA, Graphics Ultra, or Mach 32).
  349. */
  350. ValueRead = (g_ee.EEread) (2);
  351. VideoDebugPrint((DEBUG_NORMAL, "Value read from second EEPROM word is 0x%X\n", ValueRead));
  352. if ((ValueRead == 0x0FFFF) || !ValueRead)
  353. {
  354. VideoDebugPrint((DEBUG_NORMAL, "Will check for OEM accelerator\n"));
  355. return FALSE;
  356. }
  357. else
  358. {
  359. VideoDebugPrint((DEBUG_NORMAL, "Won't check for OEM accelerator\n"));
  360. return TRUE;
  361. }
  362. } /* ATIFindEEPROM_m() */
  363. /*
  364. * void ATIGetSpecialHandling_m(QueryPtr);
  365. *
  366. * struct query_structure *QueryPtr; Pointer to query structure
  367. *
  368. * Finds out from ROM BIOS whether or not 1280x1024 is available on
  369. * a Mach 8 card, and whether or not all bits of memory aperture
  370. * location are found in MEM_CFG register on a Mach 32. Assumes
  371. * that an ATI accelerator with a ROM BIOS is present, results
  372. * are undefined if this assumption is invalid.
  373. */
  374. void ATIGetSpecialHandling_m(struct query_structure *QueryPtr)
  375. {
  376. USHORT SearchLoop; /* Used in finding beginning of Graphics Wonder ID string */
  377. USHORT ScanLoop; /* Used in stepping through Graphics Wonder ID string */
  378. /*
  379. * Check the BIOS revision number. Mach 8 cards with a BIOS
  380. * revision prior to 1.4 can't do 1280x1024, but use the same
  381. * mode table for 132 column text mode.
  382. *
  383. * Some BIOS revisions (including 1.40 on a Graphics Ultra)
  384. * only contain the first digit of the minor revision in the
  385. * BIOS, while others (including 1.35 on an 8514/ULTRA) contain
  386. * the entire minor revision.
  387. *
  388. * The q_ignore1280 field is ignored for Mach 32 cards.
  389. */
  390. if((VideoPortReadRegisterUchar (&((QueryPtr->q_bios)[MACH8_REV_OFFSET])) < 1) || // Major revision
  391. (VideoPortReadRegisterUchar (&((QueryPtr->q_bios)[MACH8_REV_OFFSET+1])) < 4) || // Single-digit minor revision
  392. ((VideoPortReadRegisterUchar (&((QueryPtr->q_bios)[MACH8_REV_OFFSET+1])) >= 10) && // 2-digit minor revision
  393. (VideoPortReadRegisterUchar (&((QueryPtr->q_bios)[MACH8_REV_OFFSET+1])) < 40)))
  394. QueryPtr->q_ignore1280 = TRUE;
  395. else
  396. QueryPtr->q_ignore1280 = FALSE;
  397. /*
  398. * On the Mach 32, bit 0 of BIOS byte MACH32_EXTRA_OFFSET will
  399. * be set if bits 7 through 11 of the aperture address are to
  400. * located in SCRATCH_PAD_0 and clear if all the bits are in
  401. * MEM_CFG.
  402. *
  403. * The q_m32_aper_calc field is ignored for Mach 8 cards.
  404. */
  405. if (VideoPortReadRegisterUchar (&((QueryPtr->q_bios)[MACH32_EXTRA_OFFSET])) & 0x0001)
  406. QueryPtr->q_m32_aper_calc = TRUE;
  407. else
  408. QueryPtr->q_m32_aper_calc = FALSE;
  409. /*
  410. * The Graphics Wonder (low-cost version of the Mach 32) is
  411. * available with either the BT48x or the TI34075 DAC.
  412. *
  413. * These cards may be built with ASICs which passed tests on
  414. * modes supported by the BT48x DAC but failed tests on modes
  415. * only supported by the TI34075. Such a card may appear to work
  416. * in TI-only modes, but experience problems (not necessarily
  417. * reproducable on other Graphics Wonder cards, even from the
  418. * same production run) ranging from drawing bugs to hardware
  419. * damage. For this reason, Graphics Wonder cards MUST NOT be
  420. * run in modes not supported by the BT48x DAC.
  421. *
  422. * Initially assume that we do not have a Graphics Wonder. If
  423. * we find the beginning of the ID string, we can change our
  424. * assumption.
  425. */
  426. QueryPtr->q_GraphicsWonder = FALSE;
  427. for (SearchLoop = GW_AREA_START; SearchLoop < GW_AREA_END; SearchLoop++)
  428. {
  429. /*
  430. * Loop until we have found what might be the Graphics Wonder
  431. * identification string, but might also be a byte which
  432. * happens to match the first character in the string.
  433. * If we find a match, initially assume that we have
  434. * found the start of the string.
  435. */
  436. if (VideoPortReadRegisterUchar(&((QueryPtr->q_bios)[SearchLoop])) != GraphicsWonderSignature[0])
  437. continue;
  438. QueryPtr->q_GraphicsWonder = TRUE;
  439. /*
  440. * Check to see whether this is actually the start of the
  441. * Graphics Wonder identification string. If it isn't,
  442. * keep looking.
  443. */
  444. for (ScanLoop = 0; GraphicsWonderSignature[ScanLoop] != 0; ScanLoop++)
  445. {
  446. if (VideoPortReadRegisterUchar(&((QueryPtr->q_bios)[SearchLoop + ScanLoop]))
  447. != GraphicsWonderSignature[ScanLoop])
  448. {
  449. QueryPtr->q_GraphicsWonder = FALSE;
  450. break;
  451. }
  452. }
  453. /*
  454. * If this is a Graphics Wonder, restrict the maximum pixel
  455. * depth of the TI34075 DAC to that supported by the BT48x.
  456. *
  457. * Once we have found the Graphics Wonder ID string, we don't
  458. * need to keep looking for it.
  459. */
  460. if (QueryPtr->q_GraphicsWonder == TRUE)
  461. {
  462. for (ScanLoop = RES_640; ScanLoop <= RES_1280; ScanLoop++)
  463. {
  464. MaxDepth[DAC_TI34075][ScanLoop] = MaxDepth[DAC_BT48x][ScanLoop];
  465. }
  466. QueryPtr->q_GraphicsWonder = TRUE;
  467. break;
  468. }
  469. } /* end search for Graphics Wonder */
  470. return;
  471. } /* ATIGetSpecialHandling_m() */