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.

1565 lines
46 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. gart.c
  5. Abstract:
  6. Routines for querying and setting the Intel 440xx GART aperture
  7. Author:
  8. John Vert (jvert) 10/30/1997
  9. Modified by:
  10. Chi-Ming Cheng 06/24/1998 Acer Labs, Inc.
  11. Wang-Kai Tsai 08/28/2000 Acer Labs, Inc. - ACPI power up GART reinitialization
  12. Revision History:
  13. --*/
  14. #include "ALiM1541.h"
  15. //
  16. // Local function prototypes
  17. //
  18. NTSTATUS
  19. AgpALiSetRate(
  20. IN PVOID AgpContext,
  21. IN ULONG AgpRate
  22. );
  23. NTSTATUS
  24. AgpALiCreateGart(
  25. IN PAGPALi_EXTENSION AgpContext,
  26. IN ULONG MinimumPages
  27. );
  28. PGART_PTE
  29. AgpALiFindRangeInGart(
  30. IN PGART_PTE StartPte,
  31. IN PGART_PTE EndPte,
  32. IN ULONG Length,
  33. IN BOOLEAN SearchBackward,
  34. IN ULONG SearchState
  35. );
  36. NTSTATUS
  37. AgpQueryAperture(
  38. IN PAGPALi_EXTENSION AgpContext,
  39. OUT PHYSICAL_ADDRESS *CurrentBase,
  40. OUT ULONG *CurrentSizeInPages,
  41. OUT OPTIONAL PIO_RESOURCE_LIST *ApertureRequirements
  42. )
  43. /*++
  44. Routine Description:
  45. Queries the current size of the GART aperture. Optionally returns
  46. the possible GART settings.
  47. Arguments:
  48. AgpContext - Supplies the AGP context.
  49. CurrentBase - Returns the current physical address of the GART.
  50. CurrentSizeInPages - Returns the current GART size.
  51. ApertureRequirements - if present, returns the possible GART settings
  52. Return Value:
  53. NTSTATUS
  54. --*/
  55. {
  56. ULONG ApBase;
  57. APCTRL ApCtrl;
  58. PIO_RESOURCE_LIST Requirements;
  59. ULONG i;
  60. ULONG Length;
  61. //
  62. // Get the current APBASE and APSIZE settings
  63. //
  64. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ApBase, APBASE_OFFSET);
  65. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ApCtrl, APCTRL_OFFSET);
  66. ASSERT(ApBase != 0);
  67. CurrentBase->QuadPart = ApBase & 0xFFFFFFF0; //PCI_ADDRESS_MEMORY_ADDRESS_MASK;
  68. //
  69. // Convert APSIZE into the actual size of the aperture
  70. //
  71. switch (ApCtrl.ApSize) {
  72. case AP_SIZE_4MB:
  73. *CurrentSizeInPages = (4 * 1024*1024) / PAGE_SIZE;
  74. break;
  75. case AP_SIZE_8MB:
  76. *CurrentSizeInPages = 8 * (1024*1024 / PAGE_SIZE);
  77. break;
  78. case AP_SIZE_16MB:
  79. *CurrentSizeInPages = 16 * (1024*1024 / PAGE_SIZE);
  80. break;
  81. case AP_SIZE_32MB:
  82. *CurrentSizeInPages = 32 * (1024*1024 / PAGE_SIZE);
  83. break;
  84. case AP_SIZE_64MB:
  85. *CurrentSizeInPages = 64 * (1024*1024 / PAGE_SIZE);
  86. break;
  87. case AP_SIZE_128MB:
  88. *CurrentSizeInPages = 128 * (1024*1024 / PAGE_SIZE);
  89. break;
  90. case AP_SIZE_256MB:
  91. *CurrentSizeInPages = 256 * (1024*1024 / PAGE_SIZE);
  92. break;
  93. default:
  94. AGPLOG(AGP_CRITICAL,
  95. ("AGPALi - AgpQueryAperture - Unexpected value %x for ApSize!\n",
  96. ApCtrl.ApSize));
  97. ASSERT(FALSE);
  98. AgpContext->ApertureStart.QuadPart = 0;
  99. AgpContext->ApertureLength = 0;
  100. return(STATUS_UNSUCCESSFUL);
  101. }
  102. //
  103. // Remember the current aperture settings
  104. //
  105. AgpContext->ApertureStart.QuadPart = CurrentBase->QuadPart;
  106. AgpContext->ApertureLength = *CurrentSizeInPages * PAGE_SIZE;
  107. if (ApertureRequirements != NULL) {
  108. //
  109. // 1541 supports 7 different aperture sizes, all must be
  110. // naturally aligned. Start with the largest aperture and
  111. // work downwards so that we get the biggest possible aperture.
  112. //
  113. Requirements = ExAllocatePoolWithTag(PagedPool,
  114. sizeof(IO_RESOURCE_LIST) + (AP_SIZE_COUNT-1)*sizeof(IO_RESOURCE_DESCRIPTOR),
  115. 'RpgA');
  116. if (Requirements == NULL) {
  117. return(STATUS_INSUFFICIENT_RESOURCES);
  118. }
  119. Requirements->Version = Requirements->Revision = 1;
  120. Requirements->Count = AP_SIZE_COUNT;
  121. Length = AP_MAX_SIZE;
  122. for (i=0; i<AP_SIZE_COUNT; i++) {
  123. Requirements->Descriptors[i].Option = IO_RESOURCE_ALTERNATIVE;
  124. Requirements->Descriptors[i].Type = CmResourceTypeMemory;
  125. Requirements->Descriptors[i].ShareDisposition = CmResourceShareDeviceExclusive;
  126. Requirements->Descriptors[i].Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_PREFETCHABLE;
  127. Requirements->Descriptors[i].u.Memory.Length = Length;
  128. Requirements->Descriptors[i].u.Memory.Alignment = Length;
  129. Requirements->Descriptors[i].u.Memory.MinimumAddress.QuadPart = 0;
  130. Requirements->Descriptors[i].u.Memory.MaximumAddress.QuadPart = (ULONG)-1;
  131. Length = Length/2;
  132. }
  133. *ApertureRequirements = Requirements;
  134. }
  135. return(STATUS_SUCCESS);
  136. }
  137. NTSTATUS
  138. AgpSetAperture(
  139. IN PAGPALi_EXTENSION AgpContext,
  140. IN PHYSICAL_ADDRESS NewBase,
  141. IN ULONG NewSizeInPages
  142. )
  143. /*++
  144. Routine Description:
  145. Sets the GART aperture to the supplied settings
  146. Arguments:
  147. AgpContext - Supplies the AGP context
  148. NewBase - Supplies the new physical memory base for the GART.
  149. NewSizeInPages - Supplies the new size for the GART
  150. Return Value:
  151. NTSTATUS
  152. --*/
  153. {
  154. ULONG ApBase;
  155. ULONG ApSize;
  156. APCTRL ApCtrl;
  157. GTLBCTRL GTLBCtrl;
  158. ULONG GTLBDisable;
  159. PHYSICAL_ADDRESS GartPhysical;
  160. GartPhysical = AgpContext->GartPhysical;
  161. //
  162. // Reprogram Special Target settings when the chip
  163. // is powered off, but ignore rate changes as those were already
  164. // applied during MasterInit
  165. //
  166. if (AgpContext->SpecialTarget & ~AGP_FLAG_SPECIAL_RESERVE) {
  167. AgpSpecialTarget(AgpContext,
  168. AgpContext->SpecialTarget &
  169. ~AGP_FLAG_SPECIAL_RESERVE);
  170. }
  171. //
  172. // Set GART base
  173. //
  174. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ApCtrl, APCTRL_OFFSET);
  175. ApCtrl.ATTBase = GartPhysical.LowPart / PAGE_SIZE;
  176. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ApCtrl, APCTRL_OFFSET);
  177. //
  178. // If the new settings match the current settings, leave everything
  179. // alone.
  180. //
  181. if ((NewBase.QuadPart == AgpContext->ApertureStart.QuadPart) &&
  182. (NewSizeInPages == AgpContext->ApertureLength / PAGE_SIZE)) {
  183. //
  184. // Enable GART table
  185. //
  186. if ((AgpContext->ChipsetType != ALi1647) && (AgpContext->ChipsetType != ALi1651) &&
  187. (AgpContext->ChipsetType != ALi1644) && (AgpContext->ChipsetType != ALi1646) &&
  188. (AgpContext->ChipsetType != ALi1671) && (AgpContext->ChipsetType != ALi1672))
  189. {
  190. if (AgpContext->Gart) {
  191. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  192. GTLBCtrl.GTLB_ENJ = 0;
  193. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  194. }
  195. }
  196. AgpWorkaround(AgpContext);
  197. return(STATUS_SUCCESS);
  198. }
  199. //
  200. // Figure out the new APSIZE setting, make sure it is valid.
  201. //
  202. switch (NewSizeInPages) {
  203. case 4 * 1024 * 1024 / PAGE_SIZE:
  204. ApSize = AP_SIZE_4MB;
  205. break;
  206. case 8 * 1024 * 1024 / PAGE_SIZE:
  207. ApSize = AP_SIZE_8MB;
  208. break;
  209. case 16 * 1024 * 1024 / PAGE_SIZE:
  210. ApSize = AP_SIZE_16MB;
  211. break;
  212. case 32 * 1024 * 1024 / PAGE_SIZE:
  213. ApSize = AP_SIZE_32MB;
  214. break;
  215. case 64 * 1024 * 1024 / PAGE_SIZE:
  216. ApSize = AP_SIZE_64MB;
  217. break;
  218. case 128 * 1024 * 1024 / PAGE_SIZE:
  219. ApSize = AP_SIZE_128MB;
  220. break;
  221. case 256 * 1024 * 1024 / PAGE_SIZE:
  222. ApSize = AP_SIZE_256MB;
  223. break;
  224. default:
  225. AGPLOG(AGP_CRITICAL,
  226. ("AgpSetAperture - invalid GART size of %lx pages specified, aperture at %I64X.\n",
  227. NewSizeInPages,
  228. NewBase.QuadPart));
  229. ASSERT(FALSE);
  230. return(STATUS_INVALID_PARAMETER);
  231. }
  232. //
  233. // Make sure the supplied size is aligned on the appropriate boundary.
  234. //
  235. ASSERT(NewBase.HighPart == 0);
  236. ASSERT((NewBase.QuadPart & ((NewSizeInPages * PAGE_SIZE) - 1)) == 0);
  237. if ((NewBase.QuadPart & ((NewSizeInPages * PAGE_SIZE) - 1)) != 0 ) {
  238. AGPLOG(AGP_CRITICAL,
  239. ("AgpSetAperture - invalid base %I64X specified for GART aperture of %lx pages\n",
  240. NewBase.QuadPart,
  241. NewSizeInPages));
  242. return(STATUS_INVALID_PARAMETER);
  243. }
  244. //
  245. // Need to reset the hardware to match the supplied settings
  246. //
  247. // If the GTLB is enabled, disable it, write the new settings, then reenable the GTLB
  248. //
  249. GTLBDisable = 1;
  250. if ((AgpContext->ChipsetType != ALi1647) && (AgpContext->ChipsetType != ALi1651) &&
  251. (AgpContext->ChipsetType != ALi1644) && (AgpContext->ChipsetType != ALi1646) &&
  252. (AgpContext->ChipsetType != ALi1671) && (AgpContext->ChipsetType != ALi1672))
  253. {
  254. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  255. GTLBDisable = GTLBCtrl.GTLB_ENJ;
  256. if (!GTLBDisable)
  257. {
  258. GTLBCtrl.GTLB_ENJ = 1;
  259. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  260. }
  261. }
  262. //
  263. // update APBASE
  264. //
  265. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ApBase, APBASE_OFFSET);
  266. ApBase = (ApBase & 0x0000000F) | NewBase.LowPart;
  267. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ApBase, APBASE_OFFSET);
  268. //
  269. // update APSIZE
  270. //
  271. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ApCtrl, APCTRL_OFFSET);
  272. ApCtrl.ApSize = ApSize;
  273. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ApCtrl, APCTRL_OFFSET);
  274. //
  275. // Only 1541 chipset supports NLVM_BASE and NLVM_TOP
  276. //
  277. if (AgpContext->ChipsetType == ALi1541) {
  278. //
  279. // update NLVM_BASE and NLVM_TOP
  280. //
  281. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  282. GTLBCtrl.NLVM_Base = NewBase.LowPart >> 20;
  283. GTLBCtrl.NLVM_Top = (NewBase.LowPart + NewSizeInPages * PAGE_SIZE - 0x100000) >> 20;
  284. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  285. }
  286. #if DBG
  287. //
  288. // Read back what we wrote, make sure it worked
  289. //
  290. {
  291. APCTRL DbgSize;
  292. ULONG DbgBase;
  293. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &DbgSize, APCTRL_OFFSET);
  294. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &DbgBase, APBASE_OFFSET);
  295. ASSERT(DbgSize.ApSize == ApSize);
  296. ASSERT(DbgBase == ApBase);
  297. }
  298. #endif
  299. //
  300. // Now enable the GTLB if it was enabled before
  301. //
  302. if ((AgpContext->ChipsetType != ALi1647) && (AgpContext->ChipsetType != ALi1651) &&
  303. (AgpContext->ChipsetType != ALi1644) && (AgpContext->ChipsetType != ALi1646) &&
  304. (AgpContext->ChipsetType != ALi1671) && (AgpContext->ChipsetType != ALi1672))
  305. {
  306. if (!GTLBDisable)
  307. {
  308. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  309. GTLBCtrl.GTLB_ENJ = 0;
  310. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  311. }
  312. }
  313. //
  314. // Update our extension to reflect the new GART setting
  315. //
  316. AgpContext->ApertureStart = NewBase;
  317. AgpContext->ApertureLength = NewSizeInPages * PAGE_SIZE;
  318. return(STATUS_SUCCESS);
  319. }
  320. VOID
  321. AgpDisableAperture(
  322. IN PAGPALi_EXTENSION AgpContext
  323. )
  324. /*++
  325. Routine Description:
  326. Disables the GART aperture so that this resource is available
  327. for other devices
  328. Arguments:
  329. AgpContext - Supplies the AGP context
  330. Return Value:
  331. None - this routine must always succeed.
  332. --*/
  333. {
  334. GTLBCTRL GTLBCtrl;
  335. ULONG GTLBDisable;
  336. //
  337. // Disable the aperture
  338. //
  339. if ((AgpContext->ChipsetType != ALi1647) && (AgpContext->ChipsetType != ALi1651) &&
  340. (AgpContext->ChipsetType != ALi1644) && (AgpContext->ChipsetType != ALi1646) &&
  341. (AgpContext->ChipsetType != ALi1671) && (AgpContext->ChipsetType != ALi1672))
  342. {
  343. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  344. GTLBDisable = GTLBCtrl.GTLB_ENJ;
  345. if (!GTLBDisable)
  346. {
  347. GTLBCtrl.GTLB_ENJ = 1;
  348. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  349. }
  350. }
  351. //
  352. // Nuke the Gart! (It's meaningless now...)
  353. //
  354. if (AgpContext->Gart != NULL) {
  355. MmFreeContiguousMemory(AgpContext->Gart);
  356. AgpContext->Gart = NULL;
  357. AgpContext->GartLength = 0;
  358. }
  359. }
  360. NTSTATUS
  361. AgpReserveMemory(
  362. IN PAGPALi_EXTENSION AgpContext,
  363. IN OUT AGP_RANGE *Range
  364. )
  365. /*++
  366. Routine Description:
  367. Reserves a range of memory in the GART.
  368. Arguments:
  369. AgpContext - Supplies the AGP Context
  370. Range - Supplies the AGP_RANGE structure. AGPLIB
  371. will have filled in NumberOfPages and Type. This
  372. routine will fill in MemoryBase and Context.
  373. Return Value:
  374. NTSTATUS
  375. --*/
  376. {
  377. ULONG Index;
  378. ULONG NewState;
  379. NTSTATUS Status;
  380. PGART_PTE FoundRange;
  381. BOOLEAN Backwards;
  382. ASSERT((Range->Type == MmNonCached) || (Range->Type == MmWriteCombined));
  383. ASSERT(Range->NumberOfPages <= (AgpContext->ApertureLength / PAGE_SIZE));
  384. //
  385. // If we have not allocated our GART yet, now is the time to do so
  386. //
  387. if (AgpContext->Gart == NULL) {
  388. ASSERT(AgpContext->GartLength == 0);
  389. Status = AgpALiCreateGart(AgpContext,Range->NumberOfPages);
  390. if (!NT_SUCCESS(Status)) {
  391. AGPLOG(AGP_CRITICAL,
  392. ("AgpALiCreateGart failed %08lx to create GART of size %lx\n",
  393. Status,
  394. AgpContext->ApertureLength));
  395. return(Status);
  396. }
  397. }
  398. ASSERT(AgpContext->GartLength != 0);
  399. //
  400. // Now that we have a GART, try and find enough contiguous entries to satisfy
  401. // the request. Requests for uncached memory will scan from high addresses to
  402. // low addresses. Requests for write-combined memory will scan from low addresses
  403. // to high addresses. We will use a first-fit algorithm to try and keep the allocations
  404. // packed and contiguous.
  405. //
  406. Backwards = (Range->Type == MmNonCached) ? TRUE : FALSE;
  407. FoundRange = AgpALiFindRangeInGart(&AgpContext->Gart[0],
  408. &AgpContext->Gart[(AgpContext->GartLength / sizeof(GART_PTE)) - 1],
  409. Range->NumberOfPages,
  410. Backwards,
  411. GART_ENTRY_FREE);
  412. if (FoundRange == NULL) {
  413. //
  414. // A big enough chunk was not found.
  415. //
  416. AGPLOG(AGP_CRITICAL,
  417. ("AgpReserveMemory - Could not find %d contiguous free pages of type %d in GART at %08lx\n",
  418. Range->NumberOfPages,
  419. Range->Type,
  420. AgpContext->Gart));
  421. //
  422. // This is where we could try and grow the GART
  423. //
  424. return(STATUS_INSUFFICIENT_RESOURCES);
  425. }
  426. AGPLOG(AGP_NOISE,
  427. ("AgpReserveMemory - reserved %d pages at GART PTE %08lx\n",
  428. Range->NumberOfPages,
  429. FoundRange));
  430. //
  431. // Set these pages to reserved
  432. //
  433. if (Range->Type == MmNonCached) {
  434. NewState = GART_ENTRY_RESERVED_UC;
  435. } else {
  436. NewState = GART_ENTRY_RESERVED_WC;
  437. }
  438. for (Index = 0;Index < Range->NumberOfPages; Index++) {
  439. ASSERT(FoundRange[Index].Soft.State == GART_ENTRY_FREE);
  440. FoundRange[Index].AsUlong = 0;
  441. FoundRange[Index].Soft.State = NewState;
  442. }
  443. Range->MemoryBase.QuadPart = AgpContext->ApertureStart.QuadPart + (FoundRange - &AgpContext->Gart[0]) * PAGE_SIZE;
  444. Range->Context = FoundRange;
  445. ASSERT(Range->MemoryBase.HighPart == 0);
  446. AGPLOG(AGP_NOISE,
  447. ("AgpReserveMemory - reserved memory handle %lx at PA %08lx\n",
  448. FoundRange,
  449. Range->MemoryBase.LowPart));
  450. return(STATUS_SUCCESS);
  451. }
  452. NTSTATUS
  453. AgpReleaseMemory(
  454. IN PAGPALi_EXTENSION AgpContext,
  455. IN PAGP_RANGE Range
  456. )
  457. /*++
  458. Routine Description:
  459. Releases memory previously reserved with AgpReserveMemory
  460. Arguments:
  461. AgpContext - Supplies the AGP context
  462. AgpRange - Supplies the range to be released.
  463. Return Value:
  464. NTSTATUS
  465. --*/
  466. {
  467. PGART_PTE Pte;
  468. ULONG Start;
  469. GTLBTAGCLR ClearTag;
  470. //
  471. // Go through and free all the PTEs. None of these should still
  472. // be valid at this point.
  473. //
  474. for (Pte = Range->Context;
  475. Pte < (PGART_PTE)Range->Context + Range->NumberOfPages;
  476. Pte++) {
  477. if (Range->Type == MmNonCached) {
  478. ASSERT(Pte->Soft.State == GART_ENTRY_RESERVED_UC);
  479. } else {
  480. ASSERT(Pte->Soft.State == GART_ENTRY_RESERVED_WC);
  481. }
  482. Pte->Soft.State = GART_ENTRY_FREE;
  483. }
  484. //
  485. // Clear All Tag
  486. //
  487. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ClearTag, GTLBTAGCLR_OFFSET);
  488. ClearTag.GTLBTagClear = 1;
  489. ClearTag.ClearAllTag = 1;
  490. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ClearTag, GTLBTAGCLR_OFFSET);
  491. Range->MemoryBase.QuadPart = 0;
  492. return(STATUS_SUCCESS);
  493. }
  494. NTSTATUS
  495. AgpALiCreateGart(
  496. IN PAGPALi_EXTENSION AgpContext,
  497. IN ULONG MinimumPages
  498. )
  499. /*++
  500. Routine Description:
  501. Allocates and initializes an empty GART. The current implementation
  502. attempts to allocate the entire GART on the first reserve.
  503. Arguments:
  504. AgpContext - Supplies the AGP context
  505. MinimumPages - Supplies the minimum size (in pages) of the GART to be
  506. created.
  507. Return Value:
  508. NTSTATUS
  509. --*/
  510. {
  511. PGART_PTE Gart;
  512. ULONG GartLength;
  513. PHYSICAL_ADDRESS LowestAcceptable;
  514. PHYSICAL_ADDRESS BoundaryMultiple;
  515. PHYSICAL_ADDRESS HighestAcceptable;
  516. PHYSICAL_ADDRESS GartPhysical;
  517. ULONG i;
  518. CACHECTRL FlushCache;
  519. APCTRL ApCtrl;
  520. GTLBCTRL GTLBCtrl;
  521. //
  522. // Try and get a chunk of contiguous memory big enough to map the
  523. // entire aperture.
  524. //
  525. HighestAcceptable.QuadPart = 0xFFFFFFFF;
  526. LowestAcceptable.QuadPart = 0;
  527. BoundaryMultiple.QuadPart = 0;
  528. GartLength = BYTES_TO_PAGES(AgpContext->ApertureLength) * sizeof(GART_PTE);
  529. Gart = MmAllocateContiguousMemorySpecifyCache(GartLength,
  530. LowestAcceptable,
  531. HighestAcceptable,
  532. BoundaryMultiple,
  533. MmNonCached);
  534. if (Gart == NULL) {
  535. AGPLOG(AGP_CRITICAL,
  536. ("AgpALiCreateGart - MmAllocateContiguousMemory %lx failed\n",
  537. GartLength));
  538. return(STATUS_INSUFFICIENT_RESOURCES);
  539. }
  540. //
  541. // We successfully allocated a contiguous chunk of memory.
  542. // It should be page aligned already.
  543. //
  544. ASSERT(((ULONG_PTR)Gart & (PAGE_SIZE-1)) == 0);
  545. //
  546. // Get the physical address.
  547. //
  548. GartPhysical = MmGetPhysicalAddress(Gart);
  549. AGPLOG(AGP_NOISE,
  550. ("AgpALiCreateGart - GART of length %lx created at VA %08lx, PA %08lx\n",
  551. GartLength,
  552. Gart,
  553. GartPhysical.LowPart));
  554. ASSERT(GartPhysical.HighPart == 0);
  555. ASSERT((GartPhysical.LowPart & (PAGE_SIZE-1)) == 0);
  556. //
  557. // Initialize all the PTEs to free
  558. //
  559. for (i=0; i<GartLength/sizeof(GART_PTE); i++) {
  560. Gart[i].AsUlong = 0;
  561. }
  562. //
  563. // Only 1541 chipset has L1_2_CACHE_FLUSH_CTRL
  564. //
  565. if (AgpContext->ChipsetType == ALi1541) {
  566. //
  567. // Flush GART table region
  568. //
  569. FlushCache.Flush_Enable = 1;
  570. for (i=0; i < GartLength/PAGE_SIZE; i++)
  571. {
  572. FlushCache.Address = (GartPhysical.LowPart / PAGE_SIZE) + i;
  573. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &FlushCache, L1_2_CACHE_FLUSH_CTRL);
  574. }
  575. }
  576. //
  577. // Set GART base
  578. //
  579. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ApCtrl, APCTRL_OFFSET);
  580. ApCtrl.ATTBase = GartPhysical.LowPart / PAGE_SIZE;
  581. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ApCtrl, APCTRL_OFFSET);
  582. //
  583. // Enable GART table
  584. //
  585. if ((AgpContext->ChipsetType != ALi1647) && (AgpContext->ChipsetType != ALi1651) &&
  586. (AgpContext->ChipsetType != ALi1644) && (AgpContext->ChipsetType != ALi1646) &&
  587. (AgpContext->ChipsetType != ALi1671) && (AgpContext->ChipsetType != ALi1672))
  588. {
  589. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  590. GTLBCtrl.GTLB_ENJ = 0;
  591. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  592. }
  593. //
  594. // Update our extension to reflect the current state.
  595. //
  596. AgpContext->Gart = Gart;
  597. AgpContext->GartLength = GartLength;
  598. AgpContext->GartPhysical = GartPhysical;
  599. return(STATUS_SUCCESS);
  600. }
  601. NTSTATUS
  602. Agp1541FlushPages(
  603. IN PAGPALi_EXTENSION AgpContext,
  604. IN PMDL Mdl
  605. )
  606. /*++
  607. Routine Description:
  608. Flush entries in the GART.
  609. Arguments:
  610. AgpContext - Supplies the AGP context
  611. Mdl - Supplies the MDL describing the physical pages to be flushed
  612. Return Value:
  613. VOID
  614. --*/
  615. {
  616. ULONG PageCount;
  617. CACHECTRL FlushCache;
  618. ULONG Index;
  619. PULONG Page;
  620. ASSERT(Mdl->Next == NULL);
  621. PageCount = BYTES_TO_PAGES(Mdl->ByteCount);
  622. Page = (PULONG)(Mdl + 1);
  623. //
  624. // Flush GART table entry
  625. //
  626. FlushCache.Flush_Enable = 1;
  627. for (Index = 0; Index < PageCount; Index++) {
  628. FlushCache.Address = Page[Index];
  629. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &FlushCache, L1_2_CACHE_FLUSH_CTRL);
  630. }
  631. return STATUS_SUCCESS;
  632. }
  633. NTSTATUS
  634. AgpMapMemory(
  635. IN PAGPALi_EXTENSION AgpContext,
  636. IN PAGP_RANGE Range,
  637. IN PMDL Mdl,
  638. IN ULONG OffsetInPages,
  639. OUT PHYSICAL_ADDRESS *MemoryBase
  640. )
  641. /*++
  642. Routine Description:
  643. Maps physical memory into the GART somewhere in the specified range.
  644. Arguments:
  645. AgpContext - Supplies the AGP context
  646. Range - Supplies the AGP range that the memory should be mapped into
  647. Mdl - Supplies the MDL describing the physical pages to be mapped
  648. OffsetInPages - Supplies the offset into the reserved range where the
  649. mapping should begin.
  650. MemoryBase - Returns the physical memory in the aperture where the pages
  651. were mapped.
  652. Return Value:
  653. NTSTATUS
  654. --*/
  655. {
  656. ULONG PageCount;
  657. PGART_PTE Pte;
  658. PGART_PTE StartPte;
  659. ULONG Index;
  660. ULONG TargetState;
  661. PULONG Page;
  662. BOOLEAN Backwards;
  663. GART_PTE NewPte;
  664. GTLBTAGCLR ClearTag;
  665. ASSERT(Mdl->Next == NULL);
  666. StartPte = Range->Context;
  667. PageCount = BYTES_TO_PAGES(Mdl->ByteCount);
  668. ASSERT(PageCount <= Range->NumberOfPages);
  669. ASSERT(OffsetInPages <= Range->NumberOfPages);
  670. ASSERT(PageCount + OffsetInPages <= Range->NumberOfPages);
  671. ASSERT(PageCount > 0);
  672. TargetState = (Range->Type == MmNonCached) ? GART_ENTRY_RESERVED_UC : GART_ENTRY_RESERVED_WC;
  673. Pte = StartPte + OffsetInPages;
  674. //
  675. // We have a suitable range, now fill it in with the supplied MDL.
  676. //
  677. ASSERT(Pte >= StartPte);
  678. ASSERT(Pte + PageCount <= StartPte + Range->NumberOfPages);
  679. NewPte.AsUlong = 0;
  680. NewPte.Soft.State = (Range->Type == MmNonCached) ? GART_ENTRY_VALID_UC :
  681. GART_ENTRY_VALID_WC;
  682. Page = (PULONG)(Mdl + 1);
  683. // Fill the physical memory address into GART
  684. for (Index = 0; Index < PageCount; Index++) {
  685. AGPLOG(AGP_NOISE,
  686. ("AgpMapMemory: Pte=%p, Page=%x\n", &Pte[Index], *Page));
  687. NewPte.Hard.Page = *Page++;
  688. Pte[Index].AsUlong = NewPte.AsUlong;
  689. }
  690. //
  691. // Clear All Tag
  692. //
  693. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ClearTag, GTLBTAGCLR_OFFSET);
  694. ClearTag.GTLBTagClear = 1;
  695. ClearTag.ClearAllTag = 1;
  696. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ClearTag, GTLBTAGCLR_OFFSET);
  697. MemoryBase->QuadPart = Range->MemoryBase.QuadPart + (Pte - StartPte) * PAGE_SIZE;
  698. return(STATUS_SUCCESS);
  699. }
  700. NTSTATUS
  701. AgpUnMapMemory(
  702. IN PAGPALi_EXTENSION AgpContext,
  703. IN PAGP_RANGE AgpRange,
  704. IN ULONG NumberOfPages,
  705. IN ULONG PageOffset
  706. )
  707. /*++
  708. Routine Description:
  709. Unmaps previously mapped memory in the GART.
  710. Arguments:
  711. AgpContext - Supplies the AGP context
  712. AgpRange - Supplies the AGP range that the memory should be mapped into
  713. NumberOfPages - Supplies the number of pages in the range to be freed.
  714. PageOffset - Supplies the offset into the range where the freeing should begin.
  715. Return Value:
  716. NTSTATUS
  717. --*/
  718. {
  719. ULONG i;
  720. PGART_PTE Pte;
  721. PGART_PTE StartPte;
  722. GTLBTAGCLR ClearTag;
  723. ULONG NewState;
  724. ASSERT(PageOffset + NumberOfPages <= AgpRange->NumberOfPages);
  725. StartPte = AgpRange->Context;
  726. Pte = &StartPte[PageOffset];
  727. if (AgpRange->Type == MmNonCached) {
  728. NewState = GART_ENTRY_RESERVED_UC;
  729. } else {
  730. NewState = GART_ENTRY_RESERVED_WC;
  731. }
  732. //
  733. // Clear the GART entry.
  734. //
  735. for (i=0; i<NumberOfPages; i++) {
  736. if (Pte[i].Hard.Valid) {
  737. Pte[i].Soft.State = NewState;
  738. } else {
  739. //
  740. // This page is not mapped, just skip it.
  741. //
  742. AGPLOG(AGP_NOISE,
  743. ("AgpUnMapMemory - PTE %08lx (%08lx) at offset %d not mapped\n",
  744. &Pte[i],
  745. Pte[i].AsUlong,
  746. i));
  747. }
  748. }
  749. //
  750. // Clear All Tag
  751. //
  752. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ClearTag, GTLBTAGCLR_OFFSET);
  753. ClearTag.GTLBTagClear = 1;
  754. ClearTag.ClearAllTag = 1;
  755. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ClearTag, GTLBTAGCLR_OFFSET);
  756. return(STATUS_SUCCESS);
  757. }
  758. PGART_PTE
  759. AgpALiFindRangeInGart(
  760. IN PGART_PTE StartPte,
  761. IN PGART_PTE EndPte,
  762. IN ULONG Length,
  763. IN BOOLEAN SearchBackward,
  764. IN ULONG SearchState
  765. )
  766. /*++
  767. Routine Description:
  768. Finds a contiguous range in the GART. This routine can
  769. search either from the beginning of the GART forwards or
  770. the end of the GART backwards.
  771. Arguments:
  772. StartIndex - Supplies the first GART pte to search
  773. EndPte - Supplies the last GART to search (inclusive)
  774. Length - Supplies the number of contiguous free entries
  775. to search for.
  776. SearchBackward - TRUE indicates that the search should begin
  777. at EndPte and search backwards. FALSE indicates that the
  778. search should begin at StartPte and search forwards
  779. SearchState - Supplies the PTE state to look for.
  780. Return Value:
  781. Pointer to the first PTE in the GART if a suitable range
  782. is found.
  783. NULL if no suitable range exists.
  784. --*/
  785. {
  786. PGART_PTE Current;
  787. PGART_PTE Last;
  788. LONG Delta;
  789. ULONG Found;
  790. PGART_PTE Candidate;
  791. ASSERT(EndPte >= StartPte);
  792. ASSERT(Length <= (ULONG)(EndPte - StartPte + 1));
  793. ASSERT(Length != 0);
  794. if (SearchBackward) {
  795. Current = EndPte;
  796. Last = StartPte-1;
  797. Delta = -1;
  798. } else {
  799. Current = StartPte;
  800. Last = EndPte+1;
  801. Delta = 1;
  802. }
  803. Found = 0;
  804. while (Current != Last) {
  805. if (Current->Soft.State == SearchState) {
  806. if (++Found == Length) {
  807. //
  808. // A suitable range was found, return it
  809. //
  810. if (SearchBackward) {
  811. return(Current);
  812. } else {
  813. return(Current - Length + 1);
  814. }
  815. }
  816. } else {
  817. Found = 0;
  818. }
  819. Current += Delta;
  820. }
  821. //
  822. // A suitable range was not found.
  823. //
  824. return(NULL);
  825. }
  826. VOID
  827. AgpFindFreeRun(
  828. IN PVOID AgpContext,
  829. IN PAGP_RANGE AgpRange,
  830. IN ULONG NumberOfPages,
  831. IN ULONG OffsetInPages,
  832. OUT ULONG *FreePages,
  833. OUT ULONG *FreeOffset
  834. )
  835. /*++
  836. Routine Description:
  837. Finds the first contiguous run of free pages in the specified
  838. part of the reserved range.
  839. Arguments:
  840. AgpContext - Supplies the AGP context
  841. AgpRange - Supplies the AGP range
  842. NumberOfPages - Supplies the size of the region to be searched for free pages
  843. OffsetInPages - Supplies the start of the region to be searched for free pages
  844. FreePages - Returns the length of the first contiguous run of free pages
  845. FreeOffset - Returns the start of the first contiguous run of free pages
  846. Return Value:
  847. None. FreePages == 0 if there are no free pages in the specified range.
  848. --*/
  849. {
  850. PGART_PTE Pte;
  851. ULONG i;
  852. Pte = (PGART_PTE)(AgpRange->Context) + OffsetInPages;
  853. //
  854. // Find the first free PTE
  855. //
  856. for (i=0; i<NumberOfPages; i++) {
  857. if (Pte[i].Hard.Valid == 0) {
  858. //
  859. // Found a free PTE, count the contiguous ones.
  860. //
  861. *FreeOffset = i + OffsetInPages;
  862. *FreePages = 0;
  863. while ((i<NumberOfPages) && (Pte[i].Hard.Valid == 0)) {
  864. *FreePages += 1;
  865. ++i;
  866. }
  867. return;
  868. }
  869. }
  870. //
  871. // No free PTEs in the specified range
  872. //
  873. *FreePages = 0;
  874. return;
  875. }
  876. VOID
  877. AgpGetMappedPages(
  878. IN PVOID AgpContext,
  879. IN PAGP_RANGE AgpRange,
  880. IN ULONG NumberOfPages,
  881. IN ULONG OffsetInPages,
  882. OUT PMDL Mdl
  883. )
  884. /*++
  885. Routine Description:
  886. Returns the list of physical pages mapped into the specified
  887. range in the GART.
  888. Arguments:
  889. AgpContext - Supplies the AGP context
  890. AgpRange - Supplies the AGP range
  891. NumberOfPages - Supplies the number of pages to be returned
  892. OffsetInPages - Supplies the start of the region
  893. Mdl - Returns the list of physical pages mapped in the specified range.
  894. Return Value:
  895. None
  896. --*/
  897. {
  898. PGART_PTE Pte;
  899. ULONG i;
  900. PULONG Pages;
  901. ASSERT(NumberOfPages * PAGE_SIZE == Mdl->ByteCount);
  902. Pages = (PULONG)(Mdl + 1);
  903. Pte = (PGART_PTE)(AgpRange->Context) + OffsetInPages;
  904. for (i=0; i<NumberOfPages; i++) {
  905. ASSERT(Pte[i].Hard.Valid == 1);
  906. Pages[i] = Pte[i].Hard.Page;
  907. }
  908. return;
  909. }
  910. VOID
  911. AgpWorkaround(
  912. IN PVOID AgpExtension
  913. )
  914. {
  915. PAGPALi_EXTENSION Extension = AgpExtension;
  916. ULONG ulTemp, ulTemp1, ulLockRW, i, j, k, ulQD;
  917. ULONG ulType, ulSize, ulTmp0, ulTmp1, ulChipVersion;
  918. BOOLEAN blPrefetchFound, blSupportAGP, blnVidia=FALSE, blMatrox=FALSE, blAtiRage128=FALSE;
  919. UCHAR ID, Address, Data;
  920. NTSTATUS Status;
  921. ReadConfigUchar(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, CHIP_REVISION_OFFSET);
  922. ulChipVersion = ulTemp & 0xFF;
  923. ulTemp = (ULONG)-1;
  924. ReadConfigUlongSafe(AGP_VGA_BUS_ID, AGP_VGA_SLOT_ID, &ulTemp, 0);
  925. //
  926. // Come back after you splurge for an AGP card!!!
  927. //
  928. if (ulTemp == (ULONG)-1) {
  929. return;
  930. }
  931. if ((ulTemp & 0xFFFF) == 0x10DE) // nVidia chip detected
  932. blnVidia=TRUE;
  933. else if ((ulTemp & 0xFFFF) == 0x102B)
  934. blMatrox=TRUE;
  935. else if ((ulTemp & 0xFFFF) == 0x1002)
  936. {
  937. if ((ulTemp == 0x52451002) || (ulTemp == 0x52461002) || (ulTemp == 0x524B1002) || (ulTemp == 0x524C1002) ||
  938. (ulTemp == 0x53451002) || (ulTemp == 0x53461002) || (ulTemp == 0x53471002) || (ulTemp == 0x534B1002) ||
  939. (ulTemp == 0x534C1002) || (ulTemp == 0x534D1002))
  940. blAtiRage128=TRUE;
  941. }
  942. switch (Extension->ChipsetType)
  943. {
  944. case ALi1541:
  945. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, AGP_STATUS_OFFSET); // adjust queue depth to avoid ambiguous
  946. if (((ulTemp & 0xFF000000) >= 0x1C000000) && ((ulTemp & 0xFF000000) <= 0x20000000))
  947. {
  948. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulLockRW, M1541_Lock_WR);
  949. ulTemp1 = ulLockRW | 0x40;
  950. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp1, M1541_Lock_WR);
  951. ulTemp = (ulTemp & 0x00FFFFFF) | 0x1B000000;
  952. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, AGP_STATUS_OFFSET);
  953. ulLockRW = ulLockRW & 0xFFFFFFBF;
  954. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulLockRW, M1541_Lock_WR);
  955. }
  956. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x40); // 0x43 bit 7 -> 1
  957. ulTemp = ulTemp | 0x80000000;
  958. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x40);
  959. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_P2P_SLOT_ID, &ulTemp, 0x88); // P2P 0x88 bit 7,5,3 -> 1
  960. ulTemp = ulTemp | 0x000000A8;
  961. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_P2P_SLOT_ID, &ulTemp, 0x88);
  962. // fix frame buffer here
  963. i=0;
  964. blPrefetchFound=FALSE;
  965. while ((i<6) && (!blPrefetchFound)) // Jump out loop when first prefetch found
  966. { // Two or more prefetch case should be considered in the future
  967. ReadConfigUlong(AGP_VGA_BUS_ID, AGP_VGA_SLOT_ID, &ulTemp1, 0x10+i*0x4); // read VGA base address
  968. if ((ulTemp1 & 0x0000000F) == 0x8) blPrefetchFound=TRUE;
  969. i++;
  970. }
  971. if (blPrefetchFound) // AGP VGA prefetchable address is found. Modify M1541 write buffer
  972. {
  973. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_P2P_SLOT_ID, &ulTemp, 0x84);
  974. if ((ulTemp & 0x00010000) == 0x00010000) // Write buffer is enabled
  975. {
  976. ulTemp = (ulTemp & 0xFFFF0000) | ((ulTemp1 & 0xFFF00000) >> 16) | 0x4;
  977. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_P2P_SLOT_ID, &ulTemp, 0x84);
  978. }
  979. }
  980. else // AGP VGA prefetchable address is not found. Disable M1541 write buffer
  981. {
  982. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_P2P_SLOT_ID, &ulTemp, 0x84);
  983. ulTemp = ulTemp & 0xFFFE0000;
  984. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_P2P_SLOT_ID, &ulTemp, 0x84);
  985. }
  986. if (blnVidia) // Set aperture size to 4M as a temporatory solution
  987. {
  988. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, APCTRL_OFFSET);
  989. ulTemp = (ulTemp & 0xFFFFFFF0) | AP_SIZE_4MB;
  990. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, APCTRL_OFFSET);
  991. }
  992. break;
  993. case ALi1621:
  994. // Check AGP VGA is a pipeline(SBA disabled) device. If yes, adjust queue depth to 0x2(3 queues)
  995. ReadConfigUlong(AGP_VGA_BUS_ID, AGP_VGA_SLOT_ID, &ulTemp1, PCI_STATUS_REG);
  996. ulQD = 0;
  997. blSupportAGP = FALSE;
  998. if ((ulTemp1 & 0x00100000) != 0)
  999. {
  1000. ReadConfigUlong(AGP_VGA_BUS_ID, AGP_VGA_SLOT_ID, &ulTemp1, CAP_PTR);
  1001. ulTemp = ulTemp1 & 0xFF;
  1002. while (!blSupportAGP)
  1003. {
  1004. if ((ulTemp < 0x40) || (ulTemp > 0xF4)) break;
  1005. ReadConfigUlong(AGP_VGA_BUS_ID, AGP_VGA_SLOT_ID, &ulTemp1, ulTemp);
  1006. if ((ulTemp1 & 0xFF) == AGP_ID)
  1007. blSupportAGP = TRUE;
  1008. else
  1009. ulTemp = (ulTemp1 & 0xFF00) >> 8;
  1010. }
  1011. if (blSupportAGP)
  1012. {
  1013. ReadConfigUlong(AGP_VGA_BUS_ID, AGP_VGA_SLOT_ID, &ulTemp1, ulTemp+4); // Read AGP status register
  1014. if ((ulTemp1 & 0x00000200) == 0x0) ulQD = 0x2; // AGP VGA supports pipeline only
  1015. }
  1016. }
  1017. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, AGP_STATUS_OFFSET); // adjust queue depth to avoid ambiguous
  1018. if ((((ulTemp & 0xFF000000) >= 0x1C000000) && ((ulTemp & 0xFF000000) <= 0x20000000)) || (ulQD != 0))
  1019. {
  1020. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulLockRW, M1621_Lock_WR);
  1021. ulTemp1 = ulLockRW | 0x1000;
  1022. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp1, M1621_Lock_WR);
  1023. if (ulQD != 0)
  1024. ulTemp = (ulTemp & 0x00FFFFFF) | (ulQD << 24);
  1025. else
  1026. ulTemp = (ulTemp & 0x00FFFFFF) | 0x1B000000;
  1027. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, AGP_STATUS_OFFSET);
  1028. ulLockRW = ulLockRW & 0xFFFFEFFF;
  1029. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulLockRW, M1621_Lock_WR);
  1030. }
  1031. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x80);
  1032. ulTemp = ulTemp & 0xFFFFF3FF; // set offset 0x81 bit 2~3 to 0
  1033. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x80);
  1034. if (blnVidia)
  1035. {
  1036. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x50);
  1037. ulTemp = ulTemp | 0x40; // set M1621 index 0x50 bit 6 to 1
  1038. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x50);
  1039. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x60);
  1040. ulTemp = ulTemp | 0x40; // set M1621 index 0x60 bit 6 to 1
  1041. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x60);
  1042. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x7C);
  1043. ulTemp = ulTemp & 0xCFFFFFFF; // set M1621 index 0x7F bit 4~5 to 0
  1044. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x7C);
  1045. }
  1046. if (blMatrox)
  1047. {
  1048. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x50);
  1049. ulTemp = ulTemp | 0xFF000000; // set M1621 index 0x53 to 0xFF
  1050. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x50);
  1051. }
  1052. break;
  1053. case ALi1631:
  1054. case ALi1632:
  1055. break;
  1056. case ALi1641:
  1057. if (blMatrox)
  1058. {
  1059. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x50);
  1060. ulTemp = ulTemp | 0xFF000000; // set M1621 index 0x53 to 0xFF
  1061. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x50);
  1062. }
  1063. break;
  1064. case ALi1644:
  1065. case ALi1646:
  1066. case ALi1647:
  1067. case ALi1651:
  1068. if (blAtiRage128 && (ulChipVersion < 0xB0))
  1069. {
  1070. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, APCTRL_OFFSET);
  1071. ulTemp = (ulTemp & 0xFFFFFFF0) | AP_SIZE_4MB;
  1072. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, APCTRL_OFFSET);
  1073. }
  1074. if ( ulChipVersion < 0xB2)
  1075. {
  1076. for (k=0; k<32; k++) {
  1077. ReadConfigUlongSafe(0, k, &ulTmp0, 0x08);
  1078. ulTmp0 = ulTmp0 & 0xFFFF0000;
  1079. if ( ulTmp0 == 0x04000000 )
  1080. {
  1081. ReadConfigUlong(0, k, &ulTmp0, 0x0C);
  1082. ulTmp1 = ulTmp0 & 0xFFFF00FF;
  1083. ulTmp1 = ulTmp1 | 0x0A00;
  1084. WriteConfigUlong(0, k, &ulTmp1, 0x0C);
  1085. ReadConfigUlong(0, k, &ulTmp0, 0x0);
  1086. if ((ulTmp0 & 0xFFFF) == 0x109E)
  1087. {
  1088. ReadConfigUlong(0, k, &ulTmp0, 0x40);
  1089. ulTmp1 = ulTmp0 & 0xFFFFFFFD;
  1090. ulTmp1 = ulTmp1 | 0x02;
  1091. WriteConfigUlong(0, k, &ulTmp1, 0x40);
  1092. }
  1093. }
  1094. }
  1095. }
  1096. break;
  1097. case ALi1671:
  1098. break;
  1099. case ALi1672:
  1100. break;
  1101. default:
  1102. break;
  1103. }
  1104. }
  1105. NTSTATUS
  1106. AgpSpecialTarget(
  1107. IN PAGPALi_EXTENSION AgpContext,
  1108. IN ULONGLONG DeviceFlags
  1109. )
  1110. /*++
  1111. Routine Description:
  1112. This routine makes "special" tweaks to the AGP chipset
  1113. Arguments:
  1114. AgpContext - Supplies the AGP context
  1115. DeviceFlags - Flags indicating what tweaks to perform
  1116. Return Value:
  1117. STATUS_SUCCESS, or error
  1118. --*/
  1119. {
  1120. NTSTATUS Status;
  1121. //
  1122. // Should we change the AGP rate?
  1123. //
  1124. if (DeviceFlags & AGP_FLAG_SPECIAL_RESERVE) {
  1125. Status = AgpALiSetRate(AgpContext,
  1126. (ULONG)((DeviceFlags & AGP_FLAG_SPECIAL_RESERVE)
  1127. >> AGP_FLAG_SET_RATE_SHIFT));
  1128. if (!NT_SUCCESS(Status)) {
  1129. return Status;
  1130. }
  1131. }
  1132. //
  1133. // Add more tweaks here...
  1134. //
  1135. AgpContext->SpecialTarget |= DeviceFlags;
  1136. return STATUS_SUCCESS;
  1137. }
  1138. NTSTATUS
  1139. AgpALiSetRate(
  1140. IN PAGPALi_EXTENSION AgpContext,
  1141. IN ULONG AgpRate
  1142. )
  1143. /*++
  1144. Routine Description:
  1145. This routine sets the AGP rate
  1146. Arguments:
  1147. AgpContext - Supplies the AGP context
  1148. AgpRate - Rate to set
  1149. note: this routine assumes that AGP has already been enabled, and that
  1150. whatever rate we've been asked to set is supported by master
  1151. Return Value:
  1152. STATUS_SUCCESS, or error status
  1153. --*/
  1154. {
  1155. NTSTATUS Status;
  1156. ULONG TargetEnable;
  1157. ULONG MasterEnable;
  1158. PCI_AGP_CAPABILITY TargetCap;
  1159. PCI_AGP_CAPABILITY MasterCap;
  1160. BOOLEAN ReverseInit;
  1161. //
  1162. // Read capabilities
  1163. //
  1164. Status = AgpLibGetPciDeviceCapability(0, 0, &TargetCap);
  1165. if (!NT_SUCCESS(Status)) {
  1166. AGPLOG(AGP_WARNING, ("AGPALiSetRate: AgpLibGetPciDeviceCapability "
  1167. "failed %08lx\n", Status));
  1168. return Status;
  1169. }
  1170. Status = AgpLibGetMasterCapability(AgpContext, &MasterCap);
  1171. if (!NT_SUCCESS(Status)) {
  1172. AGPLOG(AGP_WARNING, ("AGPALiSetRate: AgpLibGetMasterCapability "
  1173. "failed %08lx\n", Status));
  1174. return Status;
  1175. }
  1176. //
  1177. // Verify the requested rate is supported by both master and target
  1178. //
  1179. if (!(AgpRate & TargetCap.AGPStatus.Rate & MasterCap.AGPStatus.Rate)) {
  1180. return STATUS_INVALID_PARAMETER;
  1181. }
  1182. //
  1183. // Disable AGP while the pull the rug out from underneath
  1184. //
  1185. TargetEnable = TargetCap.AGPCommand.AGPEnable;
  1186. TargetCap.AGPCommand.AGPEnable = 0;
  1187. Status = AgpLibSetPciDeviceCapability(0, 0, &TargetCap);
  1188. if (!NT_SUCCESS(Status)) {
  1189. AGPLOG(AGP_WARNING,
  1190. ("AGPALiSetRate: AgpLibSetPciDeviceCapability %08lx for "
  1191. "Target failed %08lx\n",
  1192. &TargetCap,
  1193. Status));
  1194. return Status;
  1195. }
  1196. MasterEnable = MasterCap.AGPCommand.AGPEnable;
  1197. MasterCap.AGPCommand.AGPEnable = 0;
  1198. Status = AgpLibSetMasterCapability(AgpContext, &MasterCap);
  1199. if (!NT_SUCCESS(Status)) {
  1200. AGPLOG(AGP_WARNING,
  1201. ("AGPALiSetRate: AgpLibSetMasterCapability %08lx failed "
  1202. "%08lx\n",
  1203. &MasterCap,
  1204. Status));
  1205. return Status;
  1206. }
  1207. //
  1208. // Fire up AGP with new rate
  1209. //
  1210. ReverseInit =
  1211. (AgpContext->SpecialTarget & AGP_FLAG_REVERSE_INITIALIZATION) ==
  1212. AGP_FLAG_REVERSE_INITIALIZATION;
  1213. if (ReverseInit) {
  1214. MasterCap.AGPCommand.Rate = AgpRate;
  1215. MasterCap.AGPCommand.AGPEnable = MasterEnable;
  1216. Status = AgpLibSetMasterCapability(AgpContext, &MasterCap);
  1217. if (!NT_SUCCESS(Status)) {
  1218. AGPLOG(AGP_WARNING,
  1219. ("AGPALiSetRate: AgpLibSetMasterCapability %08lx failed "
  1220. "%08lx\n",
  1221. &MasterCap,
  1222. Status));
  1223. }
  1224. }
  1225. TargetCap.AGPCommand.Rate = AgpRate;
  1226. TargetCap.AGPCommand.AGPEnable = TargetEnable;
  1227. Status = AgpLibSetPciDeviceCapability(0, 0, &TargetCap);
  1228. if (!NT_SUCCESS(Status)) {
  1229. AGPLOG(AGP_WARNING,
  1230. ("AGPALiSetRate: AgpLibSetPciDeviceCapability %08lx for "
  1231. "Target failed %08lx\n",
  1232. &TargetCap,
  1233. Status));
  1234. return Status;
  1235. }
  1236. if (!ReverseInit) {
  1237. MasterCap.AGPCommand.Rate = AgpRate;
  1238. MasterCap.AGPCommand.AGPEnable = MasterEnable;
  1239. Status = AgpLibSetMasterCapability(AgpContext, &MasterCap);
  1240. if (!NT_SUCCESS(Status)) {
  1241. AGPLOG(AGP_WARNING,
  1242. ("AGPALiSetRate: AgpLibSetMasterCapability %08lx failed "
  1243. "%08lx\n",
  1244. &MasterCap,
  1245. Status));
  1246. }
  1247. }
  1248. return Status;
  1249. }