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.

1342 lines
51 KiB

  1. /************************************************************************/
  2. /* */
  3. /* SETUP_CX.C */
  4. /* */
  5. /* Aug 27 1993 (c) 1993, ATI Technologies Incorporated. */
  6. /************************************************************************/
  7. /********************** PolyTron RCS Utilities
  8. $Revision: 1.21 $
  9. $Date: 15 May 1996 16:36:04 $
  10. $Author: RWolff $
  11. $Log: S:/source/wnt/ms11/miniport/archive/setup_cx.c_v $
  12. *
  13. * Rev 1.21 15 May 1996 16:36:04 RWolff
  14. * Now records in registry if we have to cut back on BIOS claim
  15. * size (conflict with SCSI card having BIOS segment below 0xD000:0000)
  16. * so we only get event log messages on the first boot, rather
  17. * than on every boot.
  18. *
  19. * Rev 1.20 03 May 1996 15:16:42 RWolff
  20. * Made new temporary variable conditional on platform type to avoid
  21. * warning when compiling for non-Alpha platforms.
  22. *
  23. * Rev 1.19 03 May 1996 14:07:26 RWolff
  24. * Fixed drawing problem with GX-F ASIC on DEC Alpha.
  25. *
  26. * Rev 1.18 15 Apr 1996 13:51:30 RWolff
  27. * Fallback to claiming 32k of BIOS if we can't get the full 64k, to avoid
  28. * conflict with Adaptec 154x adapters with their BIOS segment set to
  29. * 0xC800:0000 or 0xCC00:0000
  30. *
  31. * Rev 1.17 29 Jan 1996 17:01:56 RWolff
  32. * Now uses VideoPortInt10() rather than no-BIOS code on PPC, now
  33. * rejects exhaustive list of non-Mach 64 cards and accepts all
  34. * others when looking for block I/O cards, rather than accepting
  35. * exhaustive list of Mach 64 cards and rejecting all others.
  36. *
  37. * Rev 1.16 23 Jan 1996 17:52:16 RWolff
  38. * Added GT to list of Mach 64 cards capable of supporting block I/O.
  39. *
  40. * Rev 1.15 23 Jan 1996 11:49:38 RWolff
  41. * Eliminated level 3 warnings, added debug print statements, removed
  42. * conditionally-compilec code to use VideoPortGetAccessRanges() to
  43. * find block I/O cards, since this function remaps the I/O base address
  44. * and this is incompatible with the use of INT 10.
  45. *
  46. * Rev 1.14 12 Jan 1996 11:18:50 RWolff
  47. * Reduced size of buffer requested through VideoPortGetBusData()
  48. *
  49. * Rev 1.13 23 Nov 1995 11:31:42 RWolff
  50. * Now searches each PCI slot for our cards, rather than using
  51. * VideoPortGetAccessRanges(), since that routine won't detect
  52. * block-relocatable GX-F2s properly. This change is not sanctioned
  53. * by Microsoft, and must be backed out if they fix their routine.
  54. *
  55. * Rev 1.12 24 Aug 1995 15:39:06 RWolff
  56. * Changed detection of block I/O cards to match Microsoft's
  57. * standard for plug-and-play.
  58. *
  59. * Rev 1.11 13 Jun 1995 15:11:18 RWOLFF
  60. * On Alpha systems, now only uses dense space for the memory mapped
  61. * registers on PCI cards. This is to allow support for ISA cards on
  62. * the Jensen (EISA machine, no PCI support), which doesn't support
  63. * dense space.
  64. *
  65. * Rev 1.10 30 Mar 1995 12:02:14 RWOLFF
  66. * WaitForIdle_cx() and CheckFIFOSpace_cx() now time out and reset
  67. * the engine after 3 seconds (no operation should take this long)
  68. * to clear a hung engine, changed permanent debug print statements
  69. * to use new debug level thresholds.
  70. *
  71. * Rev 1.9 08 Mar 1995 11:35:44 ASHANMUG
  72. * Modified return values to be correct
  73. *
  74. * Rev 1.7 27 Feb 1995 17:53:26 RWOLFF
  75. * Added routine that reports whether the I/O registers are packed
  76. * (relocatable) or not.
  77. *
  78. * Rev 1.6 24 Feb 1995 12:30:44 RWOLFF
  79. * Added code to support relocatable I/O. This is not yet fully
  80. * operational, so it is disabled for this release.
  81. *
  82. * Rev 1.5 23 Dec 1994 10:47:12 ASHANMUG
  83. * ALPHA/Chrontel-DAC
  84. *
  85. * Rev 1.4 18 Nov 1994 11:48:18 RWOLFF
  86. * Added support for Mach 64 with no BIOS, routine to get the I/O base
  87. * address for the card being used.
  88. *
  89. * Rev 1.3 20 Jul 1994 12:59:12 RWOLFF
  90. * Added support for multiple I/O base addresses for accelerator registers.
  91. *
  92. * Rev 1.2 30 Jun 1994 18:16:50 RWOLFF
  93. * Added IsApertureConflict_cx() (moved from QUERY_CX.C). Instead of checking
  94. * to see if we can read back what we have written to the aperture, then
  95. * looking for the proper text attribute, we now make a call to
  96. * VideoPortVerifyAccessRanges() which includes the aperture in the list of
  97. * ranges we are trying to claim. If this call fails, we make another call
  98. * which does not include the LFB. We always claim the VGA aperture (shareable),
  99. * since we need to use it when querying the card.
  100. *
  101. * Rev 1.1 07 Feb 1994 14:14:12 RWOLFF
  102. * Added alloc_text() pragmas to allow miniport to be swapped out when
  103. * not needed.
  104. *
  105. * Rev 1.0 31 Jan 1994 11:20:42 RWOLFF
  106. * Initial revision.
  107. *
  108. * Rev 1.1 30 Nov 1993 18:30:06 RWOLFF
  109. * Fixed calculation of offset for memory mapped address ranges.
  110. *
  111. * Rev 1.0 05 Nov 1993 13:36:14 RWOLFF
  112. * Initial revision.
  113. End of PolyTron RCS section *****************/
  114. #ifdef DOC
  115. SETUP_CX.C - Setup routines for 68800CX accelerators.
  116. DESCRIPTION
  117. This file contains routines which provide services specific to
  118. the 68800CX-compatible family of ATI accelerators.
  119. OTHER FILES
  120. #endif
  121. #include "dderror.h"
  122. #include "miniport.h"
  123. #include "ntddvdeo.h"
  124. #include "video.h"
  125. #include "stdtyp.h"
  126. #include "amachcx.h"
  127. #include "amach1.h"
  128. #include "atimp.h"
  129. #include "query_cx.h"
  130. #include "services.h"
  131. #define INCLUDE_SETUP_CX
  132. #include "setup_cx.h"
  133. static ULONG FindNextBlockATICard(void);
  134. /*
  135. * Allow miniport to be swapped out when not needed.
  136. */
  137. #if defined (ALLOC_PRAGMA)
  138. #pragma alloc_text(PAGE_CX, CompatIORangesUsable_cx)
  139. #pragma alloc_text(PAGE_CX, CompatMMRangesUsable_cx)
  140. #pragma alloc_text(PAGE_CX, WaitForIdle_cx)
  141. #pragma alloc_text(PAGE_CX, CheckFIFOSpace_cx)
  142. #pragma alloc_text(PAGE_CX, IsApertureConflict_cx)
  143. #pragma alloc_text(PAGE_CX, GetIOBase_cx)
  144. #pragma alloc_text(PAGE_CX, IsPackedIO_cx)
  145. #pragma alloc_text(PAGE_CX, FindNextBlockATICard)
  146. #endif
  147. UCHAR LookForAnotherCard = 1;
  148. /***************************************************************************
  149. *
  150. * VP_STATUS CompatIORangesUsable_cx(void);
  151. *
  152. * DESCRIPTION:
  153. * Ask Windows NT for permission to use the I/O space address ranges
  154. * needed by the 68800CX accelerator.
  155. *
  156. * RETURN VALUE:
  157. * NO_ERROR if successful
  158. * error code if unable to gain access to the ranges we need.
  159. *
  160. * GLOBALS CHANGED:
  161. * none
  162. *
  163. * CALLED BY:
  164. * ATIMPFindAdapter()
  165. *
  166. * AUTHOR:
  167. * Robert Wolff
  168. *
  169. * CHANGE HISTORY:
  170. *
  171. * TEST HISTORY:
  172. *
  173. ***************************************************************************/
  174. VP_STATUS CompatIORangesUsable_cx(INTERFACE_TYPE SystemBus)
  175. {
  176. VP_STATUS Status; /* Value returned by operating system calls */
  177. short Count; /* Loop counter */
  178. VIDEO_ACCESS_RANGE SaveFirstMM; /* Place to save the first memory mapped registers */
  179. USHORT BaseIndex; /* Index into register base array */
  180. USHORT VariableIndex; /* Index into array of variable part of register array */
  181. ULONG BaseAddress; /* I/O base address for relocatable I/O */
  182. ULONG ClaimSize; /* Size of VGA aperture/BIOS block to claim */
  183. ULONG InitialClaimSize; /* Initial size of the BIOS block to claim */
  184. BOOL FoundSafeClaim = FALSE; /* Have we found a BIOS block we can claim safely? */
  185. /*
  186. * Check to see if someone has added or deleted I/O ranges without
  187. * changing the defined value. I/O registers start at index 0.
  188. *
  189. * All the I/O mapped registers are before the first register which
  190. * exists only in memory-mapped form.
  191. */
  192. if ((DriverIORange_cx[NUM_IO_REGISTERS-1].RangeStart.HighPart == DONT_USE) ||
  193. (DriverIORange_cx[NUM_IO_REGISTERS].RangeStart.HighPart != DONT_USE))
  194. {
  195. VideoDebugPrint((DEBUG_ERROR, "Wrong defined value for number of I/O ranges\n"));
  196. return ERROR_INSUFFICIENT_BUFFER;
  197. }
  198. /*
  199. * Clear the list of mapped I/O addresses so we can identify
  200. * which ones have been mapped in order to unmap them if
  201. * there is a failure partway through the mapping.
  202. */
  203. for (Count = 0; Count < NUM_IO_REGISTERS; Count++)
  204. {
  205. phwDeviceExtension->aVideoAddressIO[Count] = 0;
  206. }
  207. /*
  208. * Run through the list of base addresses, trying each
  209. * until we find the one that the Mach 64 is using.
  210. */
  211. for (BaseIndex = 0; BaseIndex < NUM_BASE_ADDRESSES; BaseIndex++)
  212. {
  213. /*
  214. * Possible problem area: if this is the first bus to be
  215. * tested which contains a fixed-base Mach 64, but a previous
  216. * bus had at least one block-relocatable card without
  217. * having the maximum number we support (which would have
  218. * been caught in ATIMPFindAdapter()), we don't want to
  219. * look for fixed-base cards. This is because we don't
  220. * support a mixture of fixed-base and block-relocatable
  221. * cards.
  222. */
  223. if (NumBlockCardsFound != 0)
  224. {
  225. VideoDebugPrint((DEBUG_NORMAL, "Skipping fixed base because block cards found\n"));
  226. break;
  227. }
  228. /*
  229. * Build up the accelerator registers using the current
  230. * base address.
  231. */
  232. for (VariableIndex = 0; VariableIndex < NUM_REGS_TO_BUILD; VariableIndex++)
  233. {
  234. DriverIORange_cx[VariableIndex+FIRST_REG_TO_BUILD].RangeStart.LowPart =
  235. VariableRegisterBases[BaseIndex] + VariableRegisterOffsets[VariableIndex];
  236. }
  237. /*
  238. * If we encounter a conflict claiming the full 64k of the BIOS
  239. * area, it will generate two messages in the event log even
  240. * though this is not a fatal error. To avoid this, we must
  241. * store claim restrictions in the registry, and on subsequent
  242. * boots start claiming where we were successful last time.
  243. *
  244. * If we can't read the registry entry, assume that we can
  245. * claim the full 64k area starting at 0xC000:0000.
  246. *
  247. * Don't worry about a user upgrading to a Mach 64 with a 64k
  248. * video BIOS and moving the SCSI card above 0xD000:0000, since
  249. * our install script will clear this registry entry to its
  250. * "claim 64k" value.
  251. */
  252. if (VideoPortGetRegistryParameters(phwDeviceExtension,
  253. L"BiosClaimSize",
  254. FALSE,
  255. RegistryParameterCallback,
  256. NULL) == NO_ERROR)
  257. {
  258. InitialClaimSize = *RegistryBuffer;
  259. VideoDebugPrint((DEBUG_DETAIL, "Read initial claim size 0x%X\n", VgaResourceSize[InitialClaimSize]));
  260. }
  261. else
  262. {
  263. InitialClaimSize = CLAIM_32k_BIOS;
  264. VideoDebugPrint((DEBUG_DETAIL, "Using default initial claim size 0x%X\n", VgaResourceSize[InitialClaimSize]));
  265. }
  266. if ((InitialClaimSize < CLAIM_32k_BIOS) || (InitialClaimSize > CLAIM_APERTURE_ONLY) )
  267. InitialClaimSize = CLAIM_32k_BIOS;
  268. /*
  269. * Claim as much as possible of our BIOS area. If we fail to
  270. * claim the full 64k, try restricting ourselves to 32k and
  271. * finally no BIOS area, only giving up on the current I/O
  272. * base address if we can't claim our access ranges even with
  273. * no BIOS area.
  274. */
  275. for (ClaimSize = InitialClaimSize; ClaimSize <= CLAIM_APERTURE_ONLY; ClaimSize++)
  276. {
  277. /*
  278. * Set up our VGA resource claim size.
  279. */
  280. DriverApertureRange_cx[0].RangeLength = VgaResourceSize[ClaimSize];
  281. /*
  282. * Check to see if there is a hardware resource conflict. We must save
  283. * the information for the first memory mapped register, copy in
  284. * the information for the VGA aperture (which we always need),
  285. * and restore the memory mapped register information after
  286. * we have verified that we can use the required address ranges.
  287. */
  288. VideoPortMoveMemory(&SaveFirstMM, DriverIORange_cx+VGA_APERTURE_ENTRY, sizeof(VIDEO_ACCESS_RANGE));
  289. VideoPortMoveMemory(DriverIORange_cx+VGA_APERTURE_ENTRY, DriverApertureRange_cx, sizeof(VIDEO_ACCESS_RANGE));
  290. Status = VideoPortVerifyAccessRanges(phwDeviceExtension,
  291. NUM_IO_REGISTERS + 1,
  292. DriverIORange_cx);
  293. VideoPortMoveMemory(DriverIORange_cx+VGA_APERTURE_ENTRY, &SaveFirstMM, sizeof(VIDEO_ACCESS_RANGE));
  294. /*
  295. * If there is a hardware resource conflict, we can't use this
  296. * base address and BIOS region size, so try the next. If there
  297. * is no conflict, use the current size.
  298. *
  299. * If the size of the BIOS block we were able to claim
  300. * differs from our initial attempt, record the "maximum
  301. * possible BIOS block size" in the registry so that on
  302. * subsequent boots we won't generate event log entries
  303. * by claiming a BIOS region that conflicts with another
  304. * card.
  305. */
  306. if (Status != NO_ERROR)
  307. {
  308. VideoDebugPrint((DEBUG_DETAIL, "Rejecting VGA aperture/BIOS block size of 0x%X bytes\n", VgaResourceSize[ClaimSize]));
  309. continue;
  310. }
  311. else
  312. {
  313. VideoDebugPrint((DEBUG_DETAIL, "VGA aperture/BIOS block size = 0x%X bytes\n", VgaResourceSize[ClaimSize]));
  314. if (FoundSafeClaim == FALSE)
  315. {
  316. FoundSafeClaim = TRUE;
  317. if (ClaimSize != InitialClaimSize)
  318. {
  319. //ClaimSize = 1;
  320. VideoDebugPrint((DEBUG_DETAIL, "Writing claim size 0x%X\n", VgaResourceSize[ClaimSize]));
  321. VideoPortSetRegistryParameters(phwDeviceExtension,
  322. L"BiosClaimSize",
  323. &ClaimSize,
  324. sizeof(ULONG));
  325. }
  326. }
  327. break;
  328. }
  329. } /* end for (decreasing claim size) */
  330. /*
  331. * If we fell out of the above loop, rather than breaking out,
  332. * go on to the next I/O base address, since we have run into
  333. * a hardware resource conflict.
  334. */
  335. if ((Status != NO_ERROR) && (ClaimSize > CLAIM_APERTURE_ONLY))
  336. continue;
  337. /*
  338. * Map the video controller address ranges we need to identify
  339. * our cards into the system virtual address space. If a register
  340. * only exists in memory-mapped form, set its I/O mapped address
  341. * to zero (won't be used because memory-mapped takes precedence
  342. * over I/O mapped).
  343. *
  344. * Initialize the mapped addresses for memory mapped registers
  345. * to 0 (flag to show the registers are not memory mapped) in
  346. * case they were initialized to a nonzero value.
  347. */
  348. for (Count=0; Count < NUM_DRIVER_ACCESS_RANGES; Count++)
  349. {
  350. if (Count < NUM_IO_REGISTERS)
  351. {
  352. if ((phwDeviceExtension->aVideoAddressIO[Count] =
  353. VideoPortGetDeviceBase(phwDeviceExtension,
  354. DriverIORange_cx[Count].RangeStart,
  355. DriverIORange_cx[Count].RangeLength,
  356. DriverIORange_cx[Count].RangeInIoSpace)) == NULL)
  357. {
  358. /*
  359. * There was an error in mapping. Remember this
  360. * so we don't try to find a Mach 64 without all
  361. * the registers being mapped properly, then
  362. * break out of the mapping loop. We will have
  363. * another shot at mapping all the addresses
  364. * when we try the next base address for the
  365. * accelerator registers.
  366. */
  367. Status = ERROR_INVALID_PARAMETER;
  368. VideoDebugPrint((DEBUG_ERROR, "Mapping error 1\n"));
  369. break;
  370. }
  371. }
  372. else
  373. {
  374. phwDeviceExtension->aVideoAddressIO[Count] = 0;
  375. }
  376. phwDeviceExtension->aVideoAddressMM[Count] = 0;
  377. } /* End for */
  378. /*
  379. * If all I/O registers were successfully mapped, check to see
  380. * if a Mach 64 is present at the current base address. If it
  381. * is, report that we have successfully mapped our registers
  382. * and found a Mach 64. Since this means we have found a
  383. * card which is not block relocatable, we do not want to
  384. * look for further cards. Also, since this is the only
  385. * Mach 64 in the system, assume that its VGA is enabled.
  386. */
  387. if (Status == NO_ERROR)
  388. {
  389. if (DetectMach64() == MACH64_ULTRA)
  390. {
  391. FoundNonBlockCard = TRUE;
  392. LookForAnotherCard = 0;
  393. phwDeviceExtension->BiosPrefix = BIOS_PREFIX_VGA_ENAB;
  394. return NO_ERROR;
  395. }
  396. }
  397. /*
  398. * We did not find a Mach 64 at this base address, so unmap
  399. * the I/O mapped registers in preparation for trying the
  400. * next base address. Only unmap those registers which were
  401. * mapped, in case the mapping loop aborted due to a failure
  402. * to map one register.
  403. */
  404. for (Count = 1; Count < NUM_IO_REGISTERS; Count++)
  405. {
  406. if (phwDeviceExtension->aVideoAddressIO[Count] != 0)
  407. {
  408. VideoPortFreeDeviceBase(phwDeviceExtension,
  409. phwDeviceExtension->aVideoAddressIO[Count]);
  410. phwDeviceExtension->aVideoAddressIO[Count] = 0;
  411. }
  412. }
  413. } /* End for (loop of base addresses) */
  414. /*
  415. * The video card in the machine isn't a Mach 64 that uses one of
  416. * the standard I/O base addresses. Check if it's a Mach 64 with
  417. * relocatable I/O.
  418. *
  419. * All our relocatable cards are PCI implementations. The code we
  420. * use to detect them is PCI-specific, so if the bus we are currently
  421. * dealing with is not PCI, don't look for relocatable cards.
  422. */
  423. if (SystemBus != PCIBus)
  424. {
  425. VideoDebugPrint((DEBUG_DETAIL, "Not PCI bus - can't check for relocatable card\n"));
  426. return ERROR_DEV_NOT_EXIST;
  427. }
  428. BaseAddress = FindNextBlockATICard();
  429. /*
  430. * BaseAddress will be zero if FindNextBlockATICard()
  431. * couldn't find a block-relocatable ATI card.
  432. */
  433. if (BaseAddress == 0)
  434. {
  435. LookForAnotherCard = 0;
  436. VideoDebugPrint((DEBUG_NORMAL, "Finished checking for relocatable cards\n"));
  437. return ERROR_DEV_NOT_EXIST;
  438. }
  439. /*
  440. * We have found a block relocatable ATI card. Save its I/O base
  441. * address so we can (during ATIMPInitialize()) match it up to
  442. * the accelerator prefix for the card, and set the initial prefix
  443. * to show that this card needs its I/O base and accelerator prefix
  444. * matched.
  445. */
  446. phwDeviceExtension->BaseIOAddress = BaseAddress;
  447. phwDeviceExtension->BiosPrefix = BIOS_PREFIX_UNASSIGNED;
  448. NumBlockCardsFound++;
  449. VideoDebugPrint((DEBUG_NORMAL, "Block relocatable card found, I/O base 0x%X\n", BaseAddress));
  450. /*
  451. * We now have the I/O base address. Map in the I/O addresses,
  452. * then check to see if we have a Mach 64 card. Depending on
  453. * the results, either report success or unmap the addresses
  454. * and report failure.
  455. */
  456. VideoDebugPrint((DEBUG_DETAIL, "About to map I/O addresses\n"));
  457. for (VariableIndex = 0; VariableIndex < NUM_REGS_TO_BUILD; VariableIndex++)
  458. {
  459. DriverIORange_cx[VariableIndex+FIRST_REG_TO_BUILD].RangeStart.LowPart =
  460. BaseAddress + (RelocatableRegisterOffsets[VariableIndex] * 4);
  461. }
  462. /*
  463. * Claim as much as possible of our BIOS area. If we fail to
  464. * claim the full 64k, try restricting ourselves to 32k and
  465. * finally no BIOS area, only giving up on the current I/O
  466. * base address if we can't claim our access ranges even with
  467. * no BIOS area.
  468. */
  469. for (ClaimSize = InitialClaimSize; ClaimSize <= CLAIM_APERTURE_ONLY; ClaimSize++)
  470. {
  471. /*
  472. * Set up our VGA resource claim size.
  473. */
  474. DriverApertureRange_cx[0].RangeLength = VgaResourceSize[ClaimSize];
  475. /*
  476. * Check to see if there is a hardware resource conflict. We must save
  477. * the information for the first memory mapped register, copy in
  478. * the information for the VGA aperture (which we always need),
  479. * and restore the memory mapped register information after
  480. * we have verified that we can use the required address ranges.
  481. */
  482. VideoPortMoveMemory(&SaveFirstMM, DriverIORange_cx+VGA_APERTURE_ENTRY, sizeof(VIDEO_ACCESS_RANGE));
  483. VideoPortMoveMemory(DriverIORange_cx+VGA_APERTURE_ENTRY, DriverApertureRange_cx, sizeof(VIDEO_ACCESS_RANGE));
  484. Status = VideoPortVerifyAccessRanges(phwDeviceExtension,
  485. NUM_IO_REGISTERS + 1,
  486. DriverIORange_cx);
  487. VideoPortMoveMemory(DriverIORange_cx+VGA_APERTURE_ENTRY, &SaveFirstMM, sizeof(VIDEO_ACCESS_RANGE));
  488. /*
  489. * If there is a hardware resource conflict, we are either trying
  490. * to claim a bigger BIOS block than we need, and someone else is
  491. * sitting in (and claiming as nonshareable) the "slack", or we have
  492. * a conflict over the I/O base address. Try the next smallest BIOS
  493. * block.
  494. *
  495. * If the size of the BIOS block we were able to claim
  496. * differs from our initial attempt, record the "maximum
  497. * possible BIOS block size" in the registry so that on
  498. * subsequent boots we won't generate event log entries
  499. * by claiming a BIOS region that conflicts with another
  500. * card.
  501. */
  502. if (Status != NO_ERROR)
  503. {
  504. VideoDebugPrint((DEBUG_DETAIL, "Rejecting VGA aperture/BIOS block size of 0x%X bytes\n", VgaResourceSize[ClaimSize]));
  505. continue;
  506. }
  507. else
  508. {
  509. VideoDebugPrint((DEBUG_DETAIL, "VGA aperture/BIOS block size = 0x%X bytes\n", VgaResourceSize[ClaimSize]));
  510. if (FoundSafeClaim == FALSE)
  511. {
  512. FoundSafeClaim = TRUE;
  513. if (ClaimSize != InitialClaimSize)
  514. {
  515. //ClaimSize = 1;
  516. VideoDebugPrint((DEBUG_DETAIL, "Writing claim size 0x%X\n", VgaResourceSize[ClaimSize]));
  517. VideoPortSetRegistryParameters(phwDeviceExtension,
  518. L"BiosClaimSize",
  519. &ClaimSize,
  520. sizeof(ULONG));
  521. }
  522. }
  523. break;
  524. }
  525. } /* end for (decreasing claim size) */
  526. /*
  527. * If there is a conflict over the I/O base address, we can't use
  528. * it. Since this is our last chance to find a Mach 64, report failure.
  529. */
  530. if (Status != NO_ERROR)
  531. {
  532. VideoDebugPrint((DEBUG_ERROR, "VideoPortVerifyAccessRanges() failed in check for relocatable Mach 64\n"));
  533. return ERROR_DEV_NOT_EXIST;
  534. }
  535. /*
  536. * Map the video controller address ranges we need to identify
  537. * our cards into the system virtual address space. If a register
  538. * only exists in memory-mapped form, set its I/O mapped address
  539. * to zero (won't be used because memory-mapped takes precedence
  540. * over I/O mapped).
  541. *
  542. * Initialize the mapped addresses for memory mapped registers
  543. * to 0 (flag to show the registers are not memory mapped) in
  544. * case they were initialized to a nonzero value.
  545. */
  546. for (Count=0; Count < NUM_DRIVER_ACCESS_RANGES; Count++)
  547. {
  548. if (Count < NUM_IO_REGISTERS)
  549. {
  550. if ((phwDeviceExtension->aVideoAddressIO[Count] =
  551. VideoPortGetDeviceBase(phwDeviceExtension,
  552. DriverIORange_cx[Count].RangeStart,
  553. DriverIORange_cx[Count].RangeLength,
  554. DriverIORange_cx[Count].RangeInIoSpace)) == NULL)
  555. {
  556. /*
  557. * There was an error in mapping. Remember this
  558. * so we don't try to find a Mach 64 without all
  559. * the registers being mapped properly, then
  560. * break out of the mapping loop.
  561. */
  562. Status = ERROR_INVALID_PARAMETER;
  563. VideoDebugPrint((DEBUG_ERROR, "Mapping error 2\n"));
  564. break;
  565. }
  566. }
  567. else
  568. {
  569. phwDeviceExtension->aVideoAddressIO[Count] = 0;
  570. }
  571. phwDeviceExtension->aVideoAddressMM[Count] = 0;
  572. } /* End for */
  573. /*
  574. * If all I/O registers were successfully mapped, check to see
  575. * if a Mach 64 is present at the current base address. If it
  576. * is, report that we have successfully mapped our registers
  577. * and found a Mach 64.
  578. */
  579. if (Status == NO_ERROR)
  580. {
  581. if (DetectMach64() == MACH64_ULTRA)
  582. {
  583. return NO_ERROR;
  584. }
  585. }
  586. /*
  587. * We did not find a Mach 64 at this base address, so clean
  588. * up after ourselves by unmapping the I/O mapped registers
  589. * before reporting failure. Only unmap those registers which
  590. * were mapped, in case the mapping loop aborted due to a
  591. * failure to map one register.
  592. */
  593. for (Count = 1; Count < NUM_IO_REGISTERS; Count++)
  594. {
  595. if (phwDeviceExtension->aVideoAddressIO[Count] != 0)
  596. {
  597. VideoPortFreeDeviceBase(phwDeviceExtension,
  598. phwDeviceExtension->aVideoAddressIO[Count]);
  599. phwDeviceExtension->aVideoAddressIO[Count] = 0;
  600. }
  601. }
  602. /*
  603. * We haven't found a Mach 64 at any of the allowable base addresses,
  604. * so report that there is no Mach 64 in the machine.
  605. */
  606. VideoDebugPrint((DEBUG_NORMAL, "No Mach 64 found at this address\n"));
  607. return ERROR_DEV_NOT_EXIST;
  608. } /* CompatIORangesUsable_cx() */
  609. /***************************************************************************
  610. *
  611. * VP_STATUS CompatMMRangesUsable_cx(void);
  612. *
  613. * DESCRIPTION:
  614. * Ask Windows NT for permission to use the memory mapped registers
  615. * needed by the 68800CX accelerator.
  616. *
  617. * RETURN VALUE:
  618. * NO_ERROR if successful
  619. * error code if unable to gain access to the ranges we need.
  620. *
  621. * GLOBALS CHANGED:
  622. * none
  623. *
  624. * CALLED BY:
  625. * ATIMPFindAdapter()
  626. *
  627. * AUTHOR:
  628. * Robert Wolff
  629. *
  630. * CHANGE HISTORY:
  631. *
  632. * TEST HISTORY:
  633. *
  634. ***************************************************************************/
  635. VP_STATUS CompatMMRangesUsable_cx(void)
  636. {
  637. PHYSICAL_ADDRESS MMrange; /* Used in translating offset to memory address */
  638. ULONG RegisterOffset; /* Offset of memory mapped registers start of address space */
  639. int Count; /* Loop counter */
  640. struct query_structure *QueryPtr; /* Query information for the card */
  641. UCHAR InIOSpace;
  642. #if defined (ALPHA)
  643. ULONG Scratch;
  644. #endif
  645. /*
  646. * Get a formatted pointer into the query section of HwDeviceExtension.
  647. * The CardInfo[] field is an unformatted buffer.
  648. */
  649. QueryPtr = (struct query_structure *) (phwDeviceExtension->CardInfo);
  650. /*
  651. * Set the offset of the memory mapped registers from the start of
  652. * the aperture to the appropriate value for the aperture size
  653. * being used.
  654. */
  655. if ((QueryPtr->q_aperture_cfg & BIOS_AP_SIZEMASK) == BIOS_AP_8M)
  656. RegisterOffset = phwDeviceExtension->PhysicalFrameAddress.LowPart + OFFSET_8M;
  657. else if ((QueryPtr->q_aperture_cfg & BIOS_AP_SIZEMASK) == BIOS_AP_4M)
  658. RegisterOffset = phwDeviceExtension->PhysicalFrameAddress.LowPart + OFFSET_4M;
  659. else
  660. RegisterOffset = OFFSET_VGA;
  661. /*
  662. * We are working in a 32 bit address space, so the upper DWORD
  663. * of the quad word address is always zero.
  664. */
  665. MMrange.HighPart = 0;
  666. #if defined (ALPHA)
  667. /*
  668. * All Alpha systems are capable of supporting sparse space
  669. * (normal memory mapped space for the Alpha). Newer systems
  670. * (those that have PCI buses) are also able to support dense
  671. * space, but older systems can't. In almost all cases, non-PCI
  672. * cards are a sign that we are using an older system, but
  673. * assuming this is an older system when it is actually an ISA
  674. * card in a newer system is mostly harmless (slight performance
  675. * penalty). Assuming that dense space is available on all Alpha
  676. * systems will crash a Jensen (older system).
  677. */
  678. if (QueryPtr->q_bus_type == BUS_PCI)
  679. InIOSpace = 4; // DENSE Space
  680. else
  681. InIOSpace = 0;
  682. /*
  683. * The GX-F ASIC has a bug where burst reads of a quadword of
  684. * memory will result in the high doubleword being corrupted.
  685. * The memory-mapped form of CONFIG_CHIP_ID is the high doubleword,
  686. * and on the Alpha in dense space (on PCI cards we always use
  687. * dense space for our memory-mapped registers) all read access
  688. * to memory is by quadwords, so we will run into the burst mode
  689. * problem. The I/O mapped form of this register is safe to use.
  690. */
  691. Scratch = INPD(CONFIG_CHIP_ID);
  692. if (((Scratch & CONFIG_CHIP_ID_TypeMask) == CONFIG_CHIP_ID_TypeGX) &&
  693. ((Scratch & CONFIG_CHIP_ID_RevMask) == CONFIG_CHIP_ID_RevF))
  694. {
  695. VideoDebugPrint((DEBUG_DETAIL, "GX-F detected, must use I/O mapped form of CRTC_OFF_PITCH\n"));
  696. DriverMMRange_cx[CRTC_OFF_PITCH].RangeStart.HighPart = DONT_USE;
  697. }
  698. #else
  699. InIOSpace = 0; // memory mapped I/O Space
  700. #endif
  701. for (Count=1; Count < NUM_DRIVER_ACCESS_RANGES; Count++)
  702. {
  703. /*
  704. * In a 32-bit address space, the high doubleword of all
  705. * physical addresses is zero. Setting this value to DONT_USE
  706. * indicates that this accelerator register isn't memory mapped.
  707. */
  708. if (DriverMMRange_cx[Count].RangeStart.HighPart != DONT_USE)
  709. {
  710. /*
  711. * DriverMMRange_cx[Count].RangeStart.LowPart is the offset
  712. * (in doublewords) of the memory mapped register from the
  713. * beginning of the block of memory mapped registers. We must
  714. * convert this to bytes, add the offset of the start of the
  715. * memory mapped register area from the start of the aperture
  716. * and the physical address of the start of the linear
  717. * framebuffer to get the physical address of this
  718. * memory mapped register.
  719. */
  720. MMrange.LowPart = (DriverMMRange_cx[Count].RangeStart.LowPart * 4) + RegisterOffset;
  721. phwDeviceExtension->aVideoAddressMM[Count] =
  722. VideoPortGetDeviceBase(phwDeviceExtension,
  723. MMrange,
  724. DriverMMRange_cx[Count].RangeLength,
  725. InIOSpace); // not in IO space
  726. /*
  727. * If we were unable to claim the memory-mapped version of
  728. * this register, and it exists only in memory-mapped form,
  729. * then we have a register which we can't access. Report
  730. * this as an error condition.
  731. */
  732. if ((phwDeviceExtension->aVideoAddressMM[Count] == 0) &&
  733. (DriverIORange_cx[Count].RangeStart.HighPart == DONT_USE))
  734. {
  735. VideoDebugPrint((DEBUG_ERROR, "Mapping error 3\n"));
  736. return ERROR_INVALID_PARAMETER;
  737. }
  738. }
  739. }
  740. VideoDebugPrint((DEBUG_DETAIL, "CompatMMRangesUsable_cx() succeeded\n"));
  741. return NO_ERROR;
  742. } /* CompatMMRangesUsable_cx() */
  743. /***************************************************************************
  744. *
  745. * int WaitForIdle_cx(void);
  746. *
  747. * DESCRIPTION:
  748. * Poll GUI_STAT waiting for GuiActive field to go low. If it does not go
  749. * low within 3 seconds (arbitrary value, but no operation should take
  750. * that long), time out.
  751. *
  752. * RETURN VALUE:
  753. * FALSE if timeout
  754. * TRUE if engine is idle
  755. *
  756. * GLOBALS CHANGED:
  757. * none
  758. *
  759. * CALLED BY:
  760. * Any 68800CX-specific routine may call this routine.
  761. *
  762. * AUTHOR:
  763. * Robert Wolff
  764. *
  765. * CHANGE HISTORY:
  766. *
  767. * TEST HISTORY:
  768. *
  769. ***************************************************************************/
  770. int WaitForIdle_cx(void)
  771. {
  772. int i;
  773. ULONG Scratch;
  774. for (i=0; i<300; i++)
  775. {
  776. if ((INPD(GUI_STAT) & GUI_STAT_GuiActive) == 0)
  777. return TRUE;
  778. /*
  779. * Wait 1/100th of a second
  780. */
  781. delay(10);
  782. }
  783. /*
  784. * Something has happened, so reset the engine and return FALSE.
  785. */
  786. VideoDebugPrint((DEBUG_ERROR, "ATI: Timeout on WaitForIdle_cx()\n"));
  787. Scratch = INPD(GEN_TEST_CNTL) & ~GEN_TEST_CNTL_GuiEna;
  788. OUTPD(GEN_TEST_CNTL, Scratch);
  789. Scratch |= GEN_TEST_CNTL_GuiEna;
  790. OUTPD(GEN_TEST_CNTL, Scratch);
  791. return FALSE;
  792. } /* WaitForIdle_cx() */
  793. /***************************************************************************
  794. *
  795. * void CheckFIFOSpace_cx(SpaceNeeded);
  796. *
  797. * WORD SpaceNeeded; Number of free FIFO entries needed
  798. *
  799. * DESCRIPTION:
  800. * Wait until the specified number of FIFO entries are free
  801. * on a 68800CX-compatible ATI accelerator.
  802. *
  803. * If the specified number of entries does not become free in
  804. * 3 seconds (arbitrary value greater than any operation should
  805. * take), assume the engine has locked and reset it.
  806. *
  807. * GLOBALS CHANGED:
  808. * none
  809. *
  810. * CALLED BY:
  811. * Any 68800CX-specific routine may call this routine.
  812. *
  813. * AUTHOR:
  814. * Robert Wolff
  815. *
  816. * CHANGE HISTORY:
  817. *
  818. * TEST HISTORY:
  819. *
  820. ***************************************************************************/
  821. void CheckFIFOSpace_cx(WORD SpaceNeeded)
  822. {
  823. ULONG LoopCount;
  824. ULONG Scratch;
  825. for (LoopCount = 0; LoopCount < 300; LoopCount++)
  826. {
  827. /*
  828. * Return from test if enough entries are free
  829. */
  830. if (!(INPD(FIFO_STAT)&SpaceNeeded))
  831. return;
  832. /*
  833. * Wait 1/100th of a second
  834. */
  835. delay(10);
  836. }
  837. /*
  838. * Something has happened, so reset the engine and return FALSE.
  839. */
  840. VideoDebugPrint((DEBUG_ERROR, "ATI: Timeout on CheckFIFOSpace_cx()\n"));
  841. Scratch = INPD(GEN_TEST_CNTL) & ~GEN_TEST_CNTL_GuiEna;
  842. OUTPD(GEN_TEST_CNTL, Scratch);
  843. Scratch |= GEN_TEST_CNTL_GuiEna;
  844. OUTPD(GEN_TEST_CNTL, Scratch);
  845. return;
  846. } /* CheckFIFOSpace_cx() */
  847. /*
  848. * BOOL IsApertureConflict_cx(QueryPtr);
  849. *
  850. * struct query_structure *QueryPtr; Pointer to query structure
  851. *
  852. * Check to see if the linear aperture conflicts with other memory.
  853. * If a conflict exists, disable the linear aperture.
  854. *
  855. * Returns:
  856. * TRUE if a conflict exists (aperture unusable)
  857. * FALSE if the aperture is usable.
  858. */
  859. BOOL IsApertureConflict_cx(struct query_structure *QueryPtr)
  860. {
  861. DWORD Scratch; /* Used in manipulating registers */
  862. VP_STATUS Status; /* Return value from VideoPortVerifyAccessRanges() */
  863. VIDEO_X86_BIOS_ARGUMENTS Registers; /* Used in VideoPortInt10() calls */
  864. VIDEO_ACCESS_RANGE SaveFirstMM[2]; /* Place to save the first two memory mapped registers */
  865. USHORT VariableIndex; /* Index into array of variable part of register array */
  866. /*
  867. * Set up by disabling the memory boundary (must be disabled in order
  868. * to access accelerator memory through the VGA aperture).
  869. */
  870. Scratch = INPD(MEM_CNTL);
  871. Scratch &= ~MEM_CNTL_MemBndryEn;
  872. OUTPD(MEM_CNTL, Scratch);
  873. /*
  874. * If there is an aperture conflict, a call to
  875. * VideoPortVerifyAccessRanges() including our linear framebuffer in
  876. * the range list will return an error. If there is no conflict, it
  877. * will return success.
  878. *
  879. * We must save the contents of the first 2 memory mapped register
  880. * entries, copy in the aperture ranges (VGA and linear) we need
  881. * to claim, then restore the memory mapped entries after we
  882. * have verified that we can use the aperture(s).
  883. *
  884. * DriverIORange_cx[] contains the physical addresses of the registers
  885. * for the last card we have dealt with. In a single-card setup, this
  886. * is no problem, but in a multi-card setup we must re-load this
  887. * array with the physical addresses of the card we want to claim
  888. * the aperture for.
  889. */
  890. if (NumBlockCardsFound > 1)
  891. {
  892. for (VariableIndex = 0; VariableIndex < NUM_REGS_TO_BUILD; VariableIndex++)
  893. {
  894. DriverIORange_cx[VariableIndex+FIRST_REG_TO_BUILD].RangeStart.LowPart =
  895. phwDeviceExtension->BaseIOAddress + (RelocatableRegisterOffsets[VariableIndex] * 4);
  896. }
  897. }
  898. DriverApertureRange_cx[LFB_ENTRY].RangeStart.LowPart = QueryPtr->q_aperture_addr*ONE_MEG;
  899. if ((QueryPtr->q_aperture_cfg & BIOS_AP_SIZEMASK) == BIOS_AP_8M)
  900. DriverApertureRange_cx[LFB_ENTRY].RangeLength = 8*ONE_MEG;
  901. else
  902. DriverApertureRange_cx[LFB_ENTRY].RangeLength = 4*ONE_MEG;
  903. VideoPortMoveMemory(SaveFirstMM, DriverIORange_cx+VGA_APERTURE_ENTRY, 2*sizeof(VIDEO_ACCESS_RANGE));
  904. VideoPortMoveMemory(DriverIORange_cx+VGA_APERTURE_ENTRY, DriverApertureRange_cx, 2*sizeof(VIDEO_ACCESS_RANGE));
  905. Status = VideoPortVerifyAccessRanges(phwDeviceExtension,
  906. NUM_IO_REGISTERS+2,
  907. DriverIORange_cx);
  908. if (Status != NO_ERROR)
  909. {
  910. /*
  911. * If there is an aperture conflict, reclaim our I/O ranges without
  912. * asking for the LFB. This call should not fail, since we would not
  913. * have reached this point if there were a conflict.
  914. */
  915. Status = VideoPortVerifyAccessRanges(phwDeviceExtension,
  916. NUM_IO_REGISTERS+1,
  917. DriverIORange_cx);
  918. if (Status != NO_ERROR)
  919. VideoDebugPrint((DEBUG_ERROR, "ERROR: Can't reclaim I/O ranges\n"));
  920. VideoPortMoveMemory(DriverIORange_cx+VGA_APERTURE_ENTRY, SaveFirstMM, 2*sizeof(VIDEO_ACCESS_RANGE));
  921. ISAPitchAdjust(QueryPtr);
  922. return TRUE;
  923. }
  924. else
  925. {
  926. VideoPortMoveMemory(DriverIORange_cx+VGA_APERTURE_ENTRY, SaveFirstMM, 2*sizeof(VIDEO_ACCESS_RANGE));
  927. /*
  928. * There is no aperture conflict, so enable the linear aperture.
  929. */
  930. VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  931. Registers.Eax = BIOS_APERTURE;
  932. Registers.Ecx = BIOS_LINEAR_APERTURE;
  933. VideoPortInt10(phwDeviceExtension, &Registers);
  934. return FALSE;
  935. }
  936. } /* IsApertureConflict_cx() */
  937. /***************************************************************************
  938. *
  939. * USHORT GetIOBase_cx(void);
  940. *
  941. * DESCRIPTION:
  942. * Get the I/O base address being used by this card.
  943. *
  944. * RETURN VALUE:
  945. * I/O base register
  946. *
  947. * GLOBALS CHANGED:
  948. * none
  949. *
  950. * CALLED BY:
  951. * Any 68800CX-specific routine may call this routine after
  952. * CompatIORangesUsable_cx() has returned success. Results
  953. * are undefined if this routine is called either before
  954. * CompatIORangesUsable_cx() is called, or after it retunrs
  955. * failure.
  956. *
  957. * AUTHOR:
  958. * Robert Wolff
  959. *
  960. * CHANGE HISTORY:
  961. *
  962. * TEST HISTORY:
  963. *
  964. ***************************************************************************/
  965. USHORT GetIOBase_cx(void)
  966. {
  967. /*
  968. * CRTC_H_TOTAL_DISP is at offset 0 from the base address.
  969. * In a single-card setup, after CompatIORangesUsable_cx()
  970. * returns, the value in
  971. * DriverIORange_cx[CRTC_H_TOTAL_DISP].RangeStart.LowPart
  972. * will be either the I/O base address in use (returned
  973. * success) or the last I/O base address tried (returned
  974. * failure).
  975. *
  976. * In a multi-card setup, this value will hold the I/O base
  977. * for the last card which was set up, but the I/O base for
  978. * each card is stored in its hardware device extension
  979. * structure. This second storage location is not guaranteed
  980. * for single-card setups, so use the DriverIORange location
  981. * for them.
  982. */
  983. if (NumBlockCardsFound > 1)
  984. return (USHORT)(phwDeviceExtension->BaseIOAddress);
  985. else
  986. return (USHORT)(DriverIORange_cx[CRTC_H_TOTAL_DISP].RangeStart.LowPart);
  987. } /* GetIOBase_cx() */
  988. /***************************************************************************
  989. *
  990. * BOOL IsPackedIO_cx(void);
  991. *
  992. * DESCRIPTION:
  993. * Report whether or not we are using packed (relocatable) I/O.
  994. *
  995. * RETURN VALUE:
  996. * TRUE if using packed I/O
  997. * FALSE if using sparse I/O
  998. *
  999. * GLOBALS CHANGED:
  1000. * none
  1001. *
  1002. * CALLED BY:
  1003. * Any 68800CX-specific routine may call this routine after
  1004. * CompatIORangesUsable_cx() has returned success. Results
  1005. * are undefined if this routine is called either before
  1006. * CompatIORangesUsable_cx() is called, or after it retunrs
  1007. * failure.
  1008. *
  1009. * AUTHOR:
  1010. * Robert Wolff
  1011. *
  1012. * CHANGE HISTORY:
  1013. *
  1014. * TEST HISTORY:
  1015. *
  1016. ***************************************************************************/
  1017. BOOL IsPackedIO_cx(void)
  1018. {
  1019. /*
  1020. * CRTC_H_TOTAL_DISP and CRTC_H_SYNC_STRT_WID are the registers
  1021. * with the lowest I/O addresses (CRTC_H_TOTAL_DISP is at
  1022. * offset 0 from the base address). If we are using packed I/O,
  1023. * the DriverIORange_cx[].RangeStart.LowPart entries for these
  1024. * two registers will differ by 4 bytes, while if we are using
  1025. * normal (sparse) I/O, they will differ by 0x400 bytes.
  1026. */
  1027. if (DriverIORange_cx[CRTC_H_SYNC_STRT_WID].RangeStart.LowPart -
  1028. DriverIORange_cx[CRTC_H_TOTAL_DISP].RangeStart.LowPart == 4)
  1029. {
  1030. VideoDebugPrint((DEBUG_DETAIL, "Reporting dense I/O\n"));
  1031. return TRUE;
  1032. }
  1033. else
  1034. {
  1035. VideoDebugPrint((DEBUG_DETAIL, "Reporting sparse I/O\n"));
  1036. return FALSE;
  1037. }
  1038. } /* IsPackedIO_cx() */
  1039. /***************************************************************************
  1040. *
  1041. * ULONG FindNextBlockATICard(void);
  1042. *
  1043. * DESCRIPTION:
  1044. * Find the next Mach 64 which uses block relocatable I/O.
  1045. *
  1046. * RETURN VALUE:
  1047. * I/O base address if card is found
  1048. * 0 if no card is found
  1049. *
  1050. * GLOBALS CHANGED:
  1051. * none
  1052. *
  1053. * CALLED BY:
  1054. * CompatIORangesUsable_cx()
  1055. *
  1056. * AUTHOR:
  1057. * Robert Wolff
  1058. *
  1059. * CHANGE HISTORY:
  1060. *
  1061. * TEST HISTORY:
  1062. *
  1063. ***************************************************************************/
  1064. static ULONG FindNextBlockATICard(void)
  1065. {
  1066. PCI_COMMON_CONFIG ConfigData; /* Configuration information about PCI device */
  1067. PCI_SLOT_NUMBER SlotNumber; /* PCI slot under test */
  1068. static ULONG DeviceNumber=0; /* PCI device number */
  1069. static ULONG FunctionNumber=0; /* PCI function number */
  1070. ULONG BaseAddress=0; /* I/O base address */
  1071. ULONG RetVal; /* Value returned by function calls */
  1072. /*
  1073. * The PCI_SLOT_NUMBER union allows 32 slot numbers with 8
  1074. * function numbers each. The upper 24 bits are reserved.
  1075. */
  1076. while (DeviceNumber < 32)
  1077. {
  1078. while (FunctionNumber < 8)
  1079. {
  1080. VideoDebugPrint((DEBUG_DETAIL, "Checking device 0x%X function 0x%X\n", DeviceNumber, FunctionNumber));
  1081. SlotNumber.u.bits.DeviceNumber = DeviceNumber;
  1082. SlotNumber.u.bits.FunctionNumber = FunctionNumber;
  1083. SlotNumber.u.bits.Reserved = 0;
  1084. ConfigData.VendorID = PCI_INVALID_VENDORID;
  1085. RetVal = VideoPortGetBusData(phwDeviceExtension,
  1086. PCIConfiguration,
  1087. SlotNumber.u.AsULONG,
  1088. &ConfigData,
  1089. 0,
  1090. PCI_COMMON_HDR_LENGTH);
  1091. FunctionNumber++;
  1092. /*
  1093. * If we received an error return, skip to the
  1094. * next possible slot.
  1095. */
  1096. if (RetVal != PCI_COMMON_HDR_LENGTH)
  1097. {
  1098. VideoDebugPrint((DEBUG_DETAIL, "Error return 0x%X, skipping to next slot\n", RetVal));
  1099. continue;
  1100. }
  1101. /*
  1102. * If this is not an ATI card, we are not interested.
  1103. * Instead, go on to the next candidate.
  1104. */
  1105. VideoDebugPrint((DEBUG_DETAIL, "Vendor ID = 0x%X\n", ConfigData.VendorID));
  1106. if (ConfigData.VendorID != 0x1002)
  1107. continue;
  1108. /*
  1109. * We have found an ATI card. On all our block-relocatable
  1110. * cards, we must mask off the lowest order bit of the
  1111. * reported address, since this is always reported as 1
  1112. * (I/O space), but its actual value is always 0.
  1113. *
  1114. * Not all ATI PCI cards are block-relocatable Mach 64
  1115. * cards. Since we only look for block-relocatable cards
  1116. * if we have failed to find a fixed-base Mach 64, we can
  1117. * safely assume that any Mach 64 we find is block-relocatable.
  1118. *
  1119. * Despite this assumption, we must still distinguish Mach 64
  1120. * cards from non-Mach 64 cards, either by recognizing and
  1121. * accepting all Mach 64 device IDs and rejecting other
  1122. * device IDs, or by recognizing and rejecting all non-Mach 64
  1123. * device IDs and accepting other device IDs. The latter
  1124. * route is safer, since new device IDs are more likely
  1125. * to be Mach 64 than non-Mach 64, and this route will
  1126. * not falsely reject new Mach 64 cards. Currently, our
  1127. * only non-Mach 64 PCI card is the Mach 32 AX.
  1128. *
  1129. * Resetting BaseAddress to zero for non-Mach 64 cards
  1130. * will result in the same treatment as for non-ATI
  1131. * cards, i.e. we will treat the current slot as not
  1132. * containing a block-relocatable Mach 64, and search
  1133. * the next slot.
  1134. */
  1135. BaseAddress = (ConfigData.u.type0.BaseAddresses[PCI_ADDRESS_IO_SPACE]) & 0xFFFFFFFE;
  1136. VideoDebugPrint((DEBUG_NORMAL, "Found card with device ID 0x%X\n", ConfigData.DeviceID));
  1137. switch (ConfigData.DeviceID)
  1138. {
  1139. case ATI_DEVID_M32AX:
  1140. VideoDebugPrint((DEBUG_NORMAL, "Mach 32 AX card found, skipping it\n"));
  1141. BaseAddress = 0;
  1142. break;
  1143. // GT, exclude GTBs
  1144. case 0x4754:
  1145. if ((ConfigData.RevisionID == 0x9A) ||
  1146. (ConfigData.RevisionID == 0x5A) ||
  1147. (ConfigData.RevisionID == 0x1A) ||
  1148. (ConfigData.RevisionID == 0x19) ||
  1149. (ConfigData.RevisionID == 0x41) ||
  1150. (ConfigData.RevisionID == 0x01))
  1151. {
  1152. VideoDebugPrint((DEBUG_NORMAL, "Rejecting GT card with revision ID 0x%X, treating as Mach 64\n", ConfigData.RevisionID));
  1153. BaseAddress = 0;
  1154. continue;
  1155. }
  1156. VideoDebugPrint((DEBUG_NORMAL, "Found ATI card with device ID 0x%X, treating as Mach 64\n", ConfigData.DeviceID));
  1157. break;
  1158. // VT, exclude VTBs
  1159. case 0x5654:
  1160. if ((ConfigData.RevisionID == 0x9A) ||
  1161. (ConfigData.RevisionID == 0x5A) ||
  1162. (ConfigData.RevisionID == 0x01))
  1163. {
  1164. VideoDebugPrint((DEBUG_NORMAL, "Rejecting VT card with revision ID 0x%X, treating as Mach 64\n", ConfigData.RevisionID));
  1165. BaseAddress = 0;
  1166. continue;
  1167. }
  1168. VideoDebugPrint((DEBUG_NORMAL, "Found ATI card with device ID 0x%X, treating as Mach 64\n", ConfigData.DeviceID));
  1169. break;
  1170. // Other supported PCI chips.
  1171. case 0x00D7: // mach64 GX
  1172. case 0x0057: // mach64 CX
  1173. case 0x4354: /* CT */
  1174. case 0x4554: /* ET */
  1175. case 0x4C54: /* LT */
  1176. case 0x4D54: /* MT */
  1177. case 0x5254: /* RT */
  1178. case 0x3354: /* 3T */
  1179. VideoDebugPrint((DEBUG_NORMAL, "Found ATI card with device ID 0x%X, treating as Mach 64\n", ConfigData.DeviceID));
  1180. break;
  1181. default:
  1182. VideoDebugPrint((DEBUG_NORMAL, "Unsupported ATI card with device ID 0x%X\n", ConfigData.DeviceID));
  1183. continue;
  1184. }
  1185. /*
  1186. * We will only reach this point if we find an ATI card.
  1187. * If it is a block-relocatable card, BaseAddress will
  1188. * be set to the I/O base address, and we must get out
  1189. * of the loop. If it is not a block-relocatable card,
  1190. * BaseAddress will be zero, and we must continue looking.
  1191. */
  1192. if (BaseAddress != 0)
  1193. break;
  1194. } /* end while (FunctionNumber < 8) */
  1195. /*
  1196. * If we have found a Mach 64 relocatable card, we will have
  1197. * broken out of the inner loop, but we will still be in the
  1198. * outer loop. Since BaseAddress is zero if we have not found
  1199. * a card, and nonzero if we have found one, check this value
  1200. * to determine whether we should break out of the outer loop.
  1201. */
  1202. if (BaseAddress != 0)
  1203. break;
  1204. VideoDebugPrint((DEBUG_DETAIL, "Finished inner loop, zeroing function number and incrementing device number\n"));
  1205. FunctionNumber = 0;
  1206. DeviceNumber++;
  1207. } /* end while (DeviceNumber < 32) */
  1208. return BaseAddress;
  1209. } /* FindNextBlockATICard() */