Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1524 lines
43 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 != ALi1661) && (AgpContext->ChipsetType != ALi1667))
  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. if ((AgpContext->ChipsetType != ALi1647) && (AgpContext->ChipsetType != ALi1651) &&
  250. (AgpContext->ChipsetType != ALi1644) && (AgpContext->ChipsetType != ALi1646) &&
  251. (AgpContext->ChipsetType != ALi1661) && (AgpContext->ChipsetType != ALi1667))
  252. {
  253. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  254. GTLBDisable = GTLBCtrl.GTLB_ENJ;
  255. if (!GTLBDisable)
  256. {
  257. GTLBCtrl.GTLB_ENJ = 1;
  258. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  259. }
  260. }
  261. //
  262. // update APBASE
  263. //
  264. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ApBase, APBASE_OFFSET);
  265. ApBase = (ApBase & 0x0000000F) | NewBase.LowPart;
  266. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ApBase, APBASE_OFFSET);
  267. //
  268. // update APSIZE
  269. //
  270. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ApCtrl, APCTRL_OFFSET);
  271. ApCtrl.ApSize = ApSize;
  272. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ApCtrl, APCTRL_OFFSET);
  273. //
  274. // Only 1541 chipset supports NLVM_BASE and NLVM_TOP
  275. //
  276. if (AgpContext->ChipsetType == ALi1541) {
  277. //
  278. // update NLVM_BASE and NLVM_TOP
  279. //
  280. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  281. GTLBCtrl.NLVM_Base = NewBase.LowPart >> 20;
  282. GTLBCtrl.NLVM_Top = (NewBase.LowPart + NewSizeInPages * PAGE_SIZE - 0x100000) >> 20;
  283. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  284. }
  285. #if DBG
  286. //
  287. // Read back what we wrote, make sure it worked
  288. //
  289. {
  290. APCTRL DbgSize;
  291. ULONG DbgBase;
  292. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &DbgSize, APCTRL_OFFSET);
  293. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &DbgBase, APBASE_OFFSET);
  294. ASSERT(DbgSize.ApSize == ApSize);
  295. ASSERT(DbgBase == ApBase);
  296. }
  297. #endif
  298. //
  299. // Now enable the GTLB if it was enabled before
  300. //
  301. if ((AgpContext->ChipsetType != ALi1647) && (AgpContext->ChipsetType != ALi1651) &&
  302. (AgpContext->ChipsetType != ALi1644) && (AgpContext->ChipsetType != ALi1646) &&
  303. (AgpContext->ChipsetType != ALi1661) && (AgpContext->ChipsetType != ALi1667))
  304. {
  305. if (!GTLBDisable)
  306. {
  307. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  308. GTLBCtrl.GTLB_ENJ = 0;
  309. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  310. }
  311. }
  312. //
  313. // Update our extension to reflect the new GART setting
  314. //
  315. AgpContext->ApertureStart = NewBase;
  316. AgpContext->ApertureLength = NewSizeInPages * PAGE_SIZE;
  317. return(STATUS_SUCCESS);
  318. }
  319. VOID
  320. AgpDisableAperture(
  321. IN PAGPALi_EXTENSION AgpContext
  322. )
  323. /*++
  324. Routine Description:
  325. Disables the GART aperture so that this resource is available
  326. for other devices
  327. Arguments:
  328. AgpContext - Supplies the AGP context
  329. Return Value:
  330. None - this routine must always succeed.
  331. --*/
  332. {
  333. GTLBCTRL GTLBCtrl;
  334. ULONG GTLBDisable;
  335. //
  336. // Disable the aperture
  337. //
  338. if ((AgpContext->ChipsetType != ALi1647) && (AgpContext->ChipsetType != ALi1651) &&
  339. (AgpContext->ChipsetType != ALi1644) && (AgpContext->ChipsetType != ALi1646) &&
  340. (AgpContext->ChipsetType != ALi1661) && (AgpContext->ChipsetType != ALi1667))
  341. {
  342. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  343. GTLBDisable = GTLBCtrl.GTLB_ENJ;
  344. if (!GTLBDisable)
  345. {
  346. GTLBCtrl.GTLB_ENJ = 1;
  347. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  348. }
  349. }
  350. //
  351. // Nuke the Gart! (It's meaningless now...)
  352. //
  353. if (AgpContext->Gart != NULL) {
  354. MmFreeContiguousMemory(AgpContext->Gart);
  355. AgpContext->Gart = NULL;
  356. AgpContext->GartLength = 0;
  357. }
  358. }
  359. NTSTATUS
  360. AgpReserveMemory(
  361. IN PAGPALi_EXTENSION AgpContext,
  362. IN OUT AGP_RANGE *Range
  363. )
  364. /*++
  365. Routine Description:
  366. Reserves a range of memory in the GART.
  367. Arguments:
  368. AgpContext - Supplies the AGP Context
  369. Range - Supplies the AGP_RANGE structure. AGPLIB
  370. will have filled in NumberOfPages and Type. This
  371. routine will fill in MemoryBase and Context.
  372. Return Value:
  373. NTSTATUS
  374. --*/
  375. {
  376. ULONG Index;
  377. ULONG NewState;
  378. NTSTATUS Status;
  379. PGART_PTE FoundRange;
  380. BOOLEAN Backwards;
  381. ASSERT((Range->Type == MmNonCached) || (Range->Type == MmWriteCombined));
  382. ASSERT(Range->NumberOfPages <= (AgpContext->ApertureLength / PAGE_SIZE));
  383. //
  384. // If we have not allocated our GART yet, now is the time to do so
  385. //
  386. if (AgpContext->Gart == NULL) {
  387. ASSERT(AgpContext->GartLength == 0);
  388. Status = AgpALiCreateGart(AgpContext,Range->NumberOfPages);
  389. if (!NT_SUCCESS(Status)) {
  390. AGPLOG(AGP_CRITICAL,
  391. ("AgpALiCreateGart failed %08lx to create GART of size %lx\n",
  392. Status,
  393. AgpContext->ApertureLength));
  394. return(Status);
  395. }
  396. }
  397. ASSERT(AgpContext->GartLength != 0);
  398. //
  399. // Now that we have a GART, try and find enough contiguous entries to satisfy
  400. // the request. Requests for uncached memory will scan from high addresses to
  401. // low addresses. Requests for write-combined memory will scan from low addresses
  402. // to high addresses. We will use a first-fit algorithm to try and keep the allocations
  403. // packed and contiguous.
  404. //
  405. Backwards = (Range->Type == MmNonCached) ? TRUE : FALSE;
  406. FoundRange = AgpALiFindRangeInGart(&AgpContext->Gart[0],
  407. &AgpContext->Gart[(AgpContext->GartLength / sizeof(GART_PTE)) - 1],
  408. Range->NumberOfPages,
  409. Backwards,
  410. GART_ENTRY_FREE);
  411. if (FoundRange == NULL) {
  412. //
  413. // A big enough chunk was not found.
  414. //
  415. AGPLOG(AGP_CRITICAL,
  416. ("AgpReserveMemory - Could not find %d contiguous free pages of type %d in GART at %08lx\n",
  417. Range->NumberOfPages,
  418. Range->Type,
  419. AgpContext->Gart));
  420. //
  421. // This is where we could try and grow the GART
  422. //
  423. return(STATUS_INSUFFICIENT_RESOURCES);
  424. }
  425. AGPLOG(AGP_NOISE,
  426. ("AgpReserveMemory - reserved %d pages at GART PTE %08lx\n",
  427. Range->NumberOfPages,
  428. FoundRange));
  429. //
  430. // Set these pages to reserved
  431. //
  432. if (Range->Type == MmNonCached) {
  433. NewState = GART_ENTRY_RESERVED_UC;
  434. } else {
  435. NewState = GART_ENTRY_RESERVED_WC;
  436. }
  437. for (Index = 0;Index < Range->NumberOfPages; Index++) {
  438. ASSERT(FoundRange[Index].Soft.State == GART_ENTRY_FREE);
  439. FoundRange[Index].AsUlong = 0;
  440. FoundRange[Index].Soft.State = NewState;
  441. }
  442. Range->MemoryBase.QuadPart = AgpContext->ApertureStart.QuadPart + (FoundRange - &AgpContext->Gart[0]) * PAGE_SIZE;
  443. Range->Context = FoundRange;
  444. ASSERT(Range->MemoryBase.HighPart == 0);
  445. AGPLOG(AGP_NOISE,
  446. ("AgpReserveMemory - reserved memory handle %lx at PA %08lx\n",
  447. FoundRange,
  448. Range->MemoryBase.LowPart));
  449. return(STATUS_SUCCESS);
  450. }
  451. NTSTATUS
  452. AgpReleaseMemory(
  453. IN PAGPALi_EXTENSION AgpContext,
  454. IN PAGP_RANGE Range
  455. )
  456. /*++
  457. Routine Description:
  458. Releases memory previously reserved with AgpReserveMemory
  459. Arguments:
  460. AgpContext - Supplies the AGP context
  461. AgpRange - Supplies the range to be released.
  462. Return Value:
  463. NTSTATUS
  464. --*/
  465. {
  466. PGART_PTE Pte;
  467. ULONG Start;
  468. GTLBTAGCLR ClearTag;
  469. //
  470. // Go through and free all the PTEs. None of these should still
  471. // be valid at this point.
  472. //
  473. for (Pte = Range->Context;
  474. Pte < (PGART_PTE)Range->Context + Range->NumberOfPages;
  475. Pte++) {
  476. if (Range->Type == MmNonCached) {
  477. ASSERT(Pte->Soft.State == GART_ENTRY_RESERVED_UC);
  478. } else {
  479. ASSERT(Pte->Soft.State == GART_ENTRY_RESERVED_WC);
  480. }
  481. Pte->Soft.State = GART_ENTRY_FREE;
  482. }
  483. //
  484. // Clear All Tag
  485. //
  486. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ClearTag, GTLBTAGCLR_OFFSET);
  487. ClearTag.GTLBTagClear = 1;
  488. ClearTag.ClearAllTag = 1;
  489. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ClearTag, GTLBTAGCLR_OFFSET);
  490. Range->MemoryBase.QuadPart = 0;
  491. return(STATUS_SUCCESS);
  492. }
  493. NTSTATUS
  494. AgpALiCreateGart(
  495. IN PAGPALi_EXTENSION AgpContext,
  496. IN ULONG MinimumPages
  497. )
  498. /*++
  499. Routine Description:
  500. Allocates and initializes an empty GART. The current implementation
  501. attempts to allocate the entire GART on the first reserve.
  502. Arguments:
  503. AgpContext - Supplies the AGP context
  504. MinimumPages - Supplies the minimum size (in pages) of the GART to be
  505. created.
  506. Return Value:
  507. NTSTATUS
  508. --*/
  509. {
  510. PGART_PTE Gart;
  511. ULONG GartLength;
  512. PHYSICAL_ADDRESS LowestAcceptable;
  513. PHYSICAL_ADDRESS BoundaryMultiple;
  514. PHYSICAL_ADDRESS HighestAcceptable;
  515. PHYSICAL_ADDRESS GartPhysical;
  516. ULONG i;
  517. CACHECTRL FlushCache;
  518. APCTRL ApCtrl;
  519. GTLBCTRL GTLBCtrl;
  520. //
  521. // Try and get a chunk of contiguous memory big enough to map the
  522. // entire aperture.
  523. //
  524. HighestAcceptable.QuadPart = 0xFFFFFFFF;
  525. LowestAcceptable.QuadPart = 0;
  526. BoundaryMultiple.QuadPart = 0;
  527. GartLength = BYTES_TO_PAGES(AgpContext->ApertureLength) * sizeof(GART_PTE);
  528. Gart = MmAllocateContiguousMemorySpecifyCache(GartLength,
  529. LowestAcceptable,
  530. HighestAcceptable,
  531. BoundaryMultiple,
  532. MmNonCached);
  533. if (Gart == NULL) {
  534. AGPLOG(AGP_CRITICAL,
  535. ("AgpALiCreateGart - MmAllocateContiguousMemory %lx failed\n",
  536. GartLength));
  537. return(STATUS_INSUFFICIENT_RESOURCES);
  538. }
  539. //
  540. // We successfully allocated a contiguous chunk of memory.
  541. // It should be page aligned already.
  542. //
  543. ASSERT(((ULONG_PTR)Gart & (PAGE_SIZE-1)) == 0);
  544. //
  545. // Get the physical address.
  546. //
  547. GartPhysical = MmGetPhysicalAddress(Gart);
  548. AGPLOG(AGP_NOISE,
  549. ("AgpALiCreateGart - GART of length %lx created at VA %08lx, PA %08lx\n",
  550. GartLength,
  551. Gart,
  552. GartPhysical.LowPart));
  553. ASSERT(GartPhysical.HighPart == 0);
  554. ASSERT((GartPhysical.LowPart & (PAGE_SIZE-1)) == 0);
  555. //
  556. // Initialize all the PTEs to free
  557. //
  558. for (i=0; i<GartLength/sizeof(GART_PTE); i++) {
  559. Gart[i].AsUlong = 0;
  560. }
  561. //
  562. // Only 1541 chipset has L1_2_CACHE_FLUSH_CTRL
  563. //
  564. if (AgpContext->ChipsetType == ALi1541) {
  565. //
  566. // Flush GART table region
  567. //
  568. FlushCache.Flush_Enable = 1;
  569. for (i=0; i < GartLength/PAGE_SIZE; i++)
  570. {
  571. FlushCache.Address = (GartPhysical.LowPart / PAGE_SIZE) + i;
  572. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &FlushCache, L1_2_CACHE_FLUSH_CTRL);
  573. }
  574. }
  575. //
  576. // Set GART base
  577. //
  578. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ApCtrl, APCTRL_OFFSET);
  579. ApCtrl.ATTBase = GartPhysical.LowPart / PAGE_SIZE;
  580. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ApCtrl, APCTRL_OFFSET);
  581. //
  582. // Enable GART table
  583. //
  584. if ((AgpContext->ChipsetType != ALi1647) && (AgpContext->ChipsetType != ALi1651) &&
  585. (AgpContext->ChipsetType != ALi1644) && (AgpContext->ChipsetType != ALi1646) &&
  586. (AgpContext->ChipsetType != ALi1661) && (AgpContext->ChipsetType != ALi1667))
  587. {
  588. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  589. GTLBCtrl.GTLB_ENJ = 0;
  590. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &GTLBCtrl, GTLBCTRL_OFFSET);
  591. }
  592. //
  593. // Update our extension to reflect the current state.
  594. //
  595. AgpContext->Gart = Gart;
  596. AgpContext->GartLength = GartLength;
  597. AgpContext->GartPhysical = GartPhysical;
  598. return(STATUS_SUCCESS);
  599. }
  600. NTSTATUS
  601. Agp1541FlushPages(
  602. IN PAGPALi_EXTENSION AgpContext,
  603. IN PMDL Mdl
  604. )
  605. /*++
  606. Routine Description:
  607. Flush entries in the GART.
  608. Arguments:
  609. AgpContext - Supplies the AGP context
  610. Mdl - Supplies the MDL describing the physical pages to be flushed
  611. Return Value:
  612. VOID
  613. --*/
  614. {
  615. ULONG PageCount;
  616. CACHECTRL FlushCache;
  617. ULONG Index;
  618. PULONG Page;
  619. ASSERT(Mdl->Next == NULL);
  620. PageCount = BYTES_TO_PAGES(Mdl->ByteCount);
  621. Page = (PULONG)(Mdl + 1);
  622. //
  623. // Flush GART table entry
  624. //
  625. FlushCache.Flush_Enable = 1;
  626. for (Index = 0; Index < PageCount; Index++) {
  627. FlushCache.Address = Page[Index];
  628. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &FlushCache, L1_2_CACHE_FLUSH_CTRL);
  629. }
  630. return STATUS_SUCCESS;
  631. }
  632. NTSTATUS
  633. AgpMapMemory(
  634. IN PAGPALi_EXTENSION AgpContext,
  635. IN PAGP_RANGE Range,
  636. IN PMDL Mdl,
  637. IN ULONG OffsetInPages,
  638. OUT PHYSICAL_ADDRESS *MemoryBase
  639. )
  640. /*++
  641. Routine Description:
  642. Maps physical memory into the GART somewhere in the specified range.
  643. Arguments:
  644. AgpContext - Supplies the AGP context
  645. Range - Supplies the AGP range that the memory should be mapped into
  646. Mdl - Supplies the MDL describing the physical pages to be mapped
  647. OffsetInPages - Supplies the offset into the reserved range where the
  648. mapping should begin.
  649. MemoryBase - Returns the physical memory in the aperture where the pages
  650. were mapped.
  651. Return Value:
  652. NTSTATUS
  653. --*/
  654. {
  655. ULONG PageCount;
  656. PGART_PTE Pte;
  657. PGART_PTE StartPte;
  658. ULONG Index;
  659. ULONG TargetState;
  660. PULONG Page;
  661. BOOLEAN Backwards;
  662. GART_PTE NewPte;
  663. GTLBTAGCLR ClearTag;
  664. ASSERT(Mdl->Next == NULL);
  665. StartPte = Range->Context;
  666. PageCount = BYTES_TO_PAGES(Mdl->ByteCount);
  667. ASSERT(PageCount <= Range->NumberOfPages);
  668. ASSERT(OffsetInPages <= Range->NumberOfPages);
  669. ASSERT(PageCount + OffsetInPages <= Range->NumberOfPages);
  670. ASSERT(PageCount > 0);
  671. TargetState = (Range->Type == MmNonCached) ? GART_ENTRY_RESERVED_UC : GART_ENTRY_RESERVED_WC;
  672. Pte = StartPte + OffsetInPages;
  673. //
  674. // We have a suitable range, now fill it in with the supplied MDL.
  675. //
  676. ASSERT(Pte >= StartPte);
  677. ASSERT(Pte + PageCount <= StartPte + Range->NumberOfPages);
  678. NewPte.AsUlong = 0;
  679. NewPte.Soft.State = (Range->Type == MmNonCached) ? GART_ENTRY_VALID_UC :
  680. GART_ENTRY_VALID_WC;
  681. Page = (PULONG)(Mdl + 1);
  682. // Fill the physical memory address into GART
  683. for (Index = 0; Index < PageCount; Index++) {
  684. AGPLOG(AGP_NOISE,
  685. ("AgpMapMemory: Pte=%p, Page=%x\n", &Pte[Index], *Page));
  686. NewPte.Hard.Page = *Page++;
  687. Pte[Index].AsUlong = NewPte.AsUlong;
  688. }
  689. //
  690. // Clear All Tag
  691. //
  692. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ClearTag, GTLBTAGCLR_OFFSET);
  693. ClearTag.GTLBTagClear = 1;
  694. ClearTag.ClearAllTag = 1;
  695. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ClearTag, GTLBTAGCLR_OFFSET);
  696. MemoryBase->QuadPart = Range->MemoryBase.QuadPart + (Pte - StartPte) * PAGE_SIZE;
  697. return(STATUS_SUCCESS);
  698. }
  699. NTSTATUS
  700. AgpUnMapMemory(
  701. IN PAGPALi_EXTENSION AgpContext,
  702. IN PAGP_RANGE AgpRange,
  703. IN ULONG NumberOfPages,
  704. IN ULONG PageOffset
  705. )
  706. /*++
  707. Routine Description:
  708. Unmaps previously mapped memory in the GART.
  709. Arguments:
  710. AgpContext - Supplies the AGP context
  711. AgpRange - Supplies the AGP range that the memory should be mapped into
  712. NumberOfPages - Supplies the number of pages in the range to be freed.
  713. PageOffset - Supplies the offset into the range where the freeing should begin.
  714. Return Value:
  715. NTSTATUS
  716. --*/
  717. {
  718. ULONG i;
  719. PGART_PTE Pte;
  720. PGART_PTE StartPte;
  721. GTLBTAGCLR ClearTag;
  722. ULONG NewState;
  723. ASSERT(PageOffset + NumberOfPages <= AgpRange->NumberOfPages);
  724. StartPte = AgpRange->Context;
  725. Pte = &StartPte[PageOffset];
  726. if (AgpRange->Type == MmNonCached) {
  727. NewState = GART_ENTRY_RESERVED_UC;
  728. } else {
  729. NewState = GART_ENTRY_RESERVED_WC;
  730. }
  731. //
  732. // Clear the GART entry.
  733. //
  734. for (i=0; i<NumberOfPages; i++) {
  735. if (Pte[i].Hard.Valid) {
  736. Pte[i].Soft.State = NewState;
  737. } else {
  738. //
  739. // This page is not mapped, just skip it.
  740. //
  741. AGPLOG(AGP_NOISE,
  742. ("AgpUnMapMemory - PTE %08lx (%08lx) at offset %d not mapped\n",
  743. &Pte[i],
  744. Pte[i].AsUlong,
  745. i));
  746. }
  747. }
  748. //
  749. // Clear All Tag
  750. //
  751. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ClearTag, GTLBTAGCLR_OFFSET);
  752. ClearTag.GTLBTagClear = 1;
  753. ClearTag.ClearAllTag = 1;
  754. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ClearTag, GTLBTAGCLR_OFFSET);
  755. return(STATUS_SUCCESS);
  756. }
  757. PGART_PTE
  758. AgpALiFindRangeInGart(
  759. IN PGART_PTE StartPte,
  760. IN PGART_PTE EndPte,
  761. IN ULONG Length,
  762. IN BOOLEAN SearchBackward,
  763. IN ULONG SearchState
  764. )
  765. /*++
  766. Routine Description:
  767. Finds a contiguous range in the GART. This routine can
  768. search either from the beginning of the GART forwards or
  769. the end of the GART backwards.
  770. Arguments:
  771. StartIndex - Supplies the first GART pte to search
  772. EndPte - Supplies the last GART to search (inclusive)
  773. Length - Supplies the number of contiguous free entries
  774. to search for.
  775. SearchBackward - TRUE indicates that the search should begin
  776. at EndPte and search backwards. FALSE indicates that the
  777. search should begin at StartPte and search forwards
  778. SearchState - Supplies the PTE state to look for.
  779. Return Value:
  780. Pointer to the first PTE in the GART if a suitable range
  781. is found.
  782. NULL if no suitable range exists.
  783. --*/
  784. {
  785. PGART_PTE Current;
  786. PGART_PTE Last;
  787. LONG Delta;
  788. ULONG Found;
  789. PGART_PTE Candidate;
  790. ASSERT(EndPte >= StartPte);
  791. ASSERT(Length <= (ULONG)(EndPte - StartPte + 1));
  792. ASSERT(Length != 0);
  793. if (SearchBackward) {
  794. Current = EndPte;
  795. Last = StartPte-1;
  796. Delta = -1;
  797. } else {
  798. Current = StartPte;
  799. Last = EndPte+1;
  800. Delta = 1;
  801. }
  802. Found = 0;
  803. while (Current != Last) {
  804. if (Current->Soft.State == SearchState) {
  805. if (++Found == Length) {
  806. //
  807. // A suitable range was found, return it
  808. //
  809. if (SearchBackward) {
  810. return(Current);
  811. } else {
  812. return(Current - Length + 1);
  813. }
  814. }
  815. } else {
  816. Found = 0;
  817. }
  818. Current += Delta;
  819. }
  820. //
  821. // A suitable range was not found.
  822. //
  823. return(NULL);
  824. }
  825. VOID
  826. AgpFindFreeRun(
  827. IN PVOID AgpContext,
  828. IN PAGP_RANGE AgpRange,
  829. IN ULONG NumberOfPages,
  830. IN ULONG OffsetInPages,
  831. OUT ULONG *FreePages,
  832. OUT ULONG *FreeOffset
  833. )
  834. /*++
  835. Routine Description:
  836. Finds the first contiguous run of free pages in the specified
  837. part of the reserved range.
  838. Arguments:
  839. AgpContext - Supplies the AGP context
  840. AgpRange - Supplies the AGP range
  841. NumberOfPages - Supplies the size of the region to be searched for free pages
  842. OffsetInPages - Supplies the start of the region to be searched for free pages
  843. FreePages - Returns the length of the first contiguous run of free pages
  844. FreeOffset - Returns the start of the first contiguous run of free pages
  845. Return Value:
  846. None. FreePages == 0 if there are no free pages in the specified range.
  847. --*/
  848. {
  849. PGART_PTE Pte;
  850. ULONG i;
  851. Pte = (PGART_PTE)(AgpRange->Context) + OffsetInPages;
  852. //
  853. // Find the first free PTE
  854. //
  855. for (i=0; i<NumberOfPages; i++) {
  856. if (Pte[i].Hard.Valid == 0) {
  857. //
  858. // Found a free PTE, count the contiguous ones.
  859. //
  860. *FreeOffset = i + OffsetInPages;
  861. *FreePages = 0;
  862. while ((i<NumberOfPages) && (Pte[i].Hard.Valid == 0)) {
  863. *FreePages += 1;
  864. ++i;
  865. }
  866. return;
  867. }
  868. }
  869. //
  870. // No free PTEs in the specified range
  871. //
  872. *FreePages = 0;
  873. return;
  874. }
  875. VOID
  876. AgpGetMappedPages(
  877. IN PVOID AgpContext,
  878. IN PAGP_RANGE AgpRange,
  879. IN ULONG NumberOfPages,
  880. IN ULONG OffsetInPages,
  881. OUT PMDL Mdl
  882. )
  883. /*++
  884. Routine Description:
  885. Returns the list of physical pages mapped into the specified
  886. range in the GART.
  887. Arguments:
  888. AgpContext - Supplies the AGP context
  889. AgpRange - Supplies the AGP range
  890. NumberOfPages - Supplies the number of pages to be returned
  891. OffsetInPages - Supplies the start of the region
  892. Mdl - Returns the list of physical pages mapped in the specified range.
  893. Return Value:
  894. None
  895. --*/
  896. {
  897. PGART_PTE Pte;
  898. ULONG i;
  899. PULONG Pages;
  900. ASSERT(NumberOfPages * PAGE_SIZE == Mdl->ByteCount);
  901. Pages = (PULONG)(Mdl + 1);
  902. Pte = (PGART_PTE)(AgpRange->Context) + OffsetInPages;
  903. for (i=0; i<NumberOfPages; i++) {
  904. ASSERT(Pte[i].Hard.Valid == 1);
  905. Pages[i] = Pte[i].Hard.Page;
  906. }
  907. return;
  908. }
  909. VOID
  910. AgpWorkaround(
  911. IN PVOID AgpExtension
  912. )
  913. {
  914. PAGPALi_EXTENSION Extension = AgpExtension;
  915. ULONG ulTemp, ulTemp1, ulLockRW, i, j, ulQD;
  916. ULONG ulType, ulSize;
  917. BOOLEAN blPrefetchFound, blSupportAGP, blnVidia=FALSE, blMatrox=FALSE;
  918. UCHAR ID, Address, Data;
  919. NTSTATUS Status;
  920. ulTemp = (ULONG)-1;
  921. ReadConfigUlongSafe(AGP_VGA_BUS_ID, AGP_VGA_SLOT_ID, &ulTemp, 0);
  922. //
  923. // Come back after you splurge for an AGP card!!!
  924. //
  925. if (ulTemp == (ULONG)-1) {
  926. return;
  927. }
  928. if ((ulTemp & 0xFFFF) == 0x10DE) // nVidia chip detected
  929. blnVidia=TRUE;
  930. else if ((ulTemp & 0xFFFF) == 0x102B)
  931. blMatrox=TRUE;
  932. switch (Extension->ChipsetType)
  933. {
  934. case ALi1541:
  935. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, AGP_STATUS_OFFSET); // adjust queue depth to avoid ambiguous
  936. if (((ulTemp & 0xFF000000) >= 0x1C000000) && ((ulTemp & 0xFF000000) <= 0x20000000))
  937. {
  938. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulLockRW, M1541_Lock_WR);
  939. ulTemp1 = ulLockRW | 0x40;
  940. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp1, M1541_Lock_WR);
  941. ulTemp = (ulTemp & 0x00FFFFFF) | 0x1B000000;
  942. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, AGP_STATUS_OFFSET);
  943. ulLockRW = ulLockRW & 0xFFFFFFBF;
  944. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulLockRW, M1541_Lock_WR);
  945. }
  946. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x40); // 0x43 bit 7 -> 1
  947. ulTemp = ulTemp | 0x80000000;
  948. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x40);
  949. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_P2P_SLOT_ID, &ulTemp, 0x88); // P2P 0x88 bit 7,5,3 -> 1
  950. ulTemp = ulTemp | 0x000000A8;
  951. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_P2P_SLOT_ID, &ulTemp, 0x88);
  952. // fix frame buffer here
  953. i=0;
  954. blPrefetchFound=FALSE;
  955. while ((i<6) && (!blPrefetchFound)) // Jump out loop when first prefetch found
  956. { // Two or more prefetch case should be considered in the future
  957. ReadConfigUlong(AGP_VGA_BUS_ID, AGP_VGA_SLOT_ID, &ulTemp1, 0x10+i*0x4); // read VGA base address
  958. if ((ulTemp1 & 0x0000000F) == 0x8) blPrefetchFound=TRUE;
  959. i++;
  960. }
  961. if (blPrefetchFound) // AGP VGA prefetchable address is found. Modify M1541 write buffer
  962. {
  963. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_P2P_SLOT_ID, &ulTemp, 0x84);
  964. if ((ulTemp & 0x00010000) == 0x00010000) // Write buffer is enabled
  965. {
  966. ulTemp = (ulTemp & 0xFFFF0000) | ((ulTemp1 & 0xFFF00000) >> 16) | 0x4;
  967. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_P2P_SLOT_ID, &ulTemp, 0x84);
  968. }
  969. }
  970. else // AGP VGA prefetchable address is not found. Disable M1541 write buffer
  971. {
  972. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_P2P_SLOT_ID, &ulTemp, 0x84);
  973. ulTemp = ulTemp & 0xFFFE0000;
  974. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_P2P_SLOT_ID, &ulTemp, 0x84);
  975. }
  976. if (blnVidia) // Set aperture size to 4M as a temporatory solution
  977. {
  978. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, APCTRL_OFFSET);
  979. ulTemp = (ulTemp & 0xFFFFFFF0) | AP_SIZE_4MB;
  980. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, APCTRL_OFFSET);
  981. }
  982. break;
  983. case ALi1621:
  984. // Check AGP VGA is a pipeline(SBA disabled) device. If yes, adjust queue depth to 0x2(3 queues)
  985. ReadConfigUlong(AGP_VGA_BUS_ID, AGP_VGA_SLOT_ID, &ulTemp1, PCI_STATUS_REG);
  986. ulQD = 0;
  987. blSupportAGP = FALSE;
  988. if ((ulTemp1 & 0x00100000) != 0)
  989. {
  990. ReadConfigUlong(AGP_VGA_BUS_ID, AGP_VGA_SLOT_ID, &ulTemp1, CAP_PTR);
  991. ulTemp = ulTemp1 & 0xFF;
  992. while (!blSupportAGP)
  993. {
  994. if ((ulTemp < 0x40) || (ulTemp > 0xF4)) break;
  995. ReadConfigUlong(AGP_VGA_BUS_ID, AGP_VGA_SLOT_ID, &ulTemp1, ulTemp);
  996. if ((ulTemp1 & 0xFF) == AGP_ID)
  997. blSupportAGP = TRUE;
  998. else
  999. ulTemp = (ulTemp1 & 0xFF00) >> 8;
  1000. }
  1001. if (blSupportAGP)
  1002. {
  1003. ReadConfigUlong(AGP_VGA_BUS_ID, AGP_VGA_SLOT_ID, &ulTemp1, ulTemp+4); // Read AGP status register
  1004. if ((ulTemp1 & 0x00000200) == 0x0) ulQD = 0x2; // AGP VGA supports pipeline only
  1005. }
  1006. }
  1007. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, AGP_STATUS_OFFSET); // adjust queue depth to avoid ambiguous
  1008. if ((((ulTemp & 0xFF000000) >= 0x1C000000) && ((ulTemp & 0xFF000000) <= 0x20000000)) || (ulQD != 0))
  1009. {
  1010. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulLockRW, M1621_Lock_WR);
  1011. ulTemp1 = ulLockRW | 0x1000;
  1012. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp1, M1621_Lock_WR);
  1013. if (ulQD != 0)
  1014. ulTemp = (ulTemp & 0x00FFFFFF) | (ulQD << 24);
  1015. else
  1016. ulTemp = (ulTemp & 0x00FFFFFF) | 0x1B000000;
  1017. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, AGP_STATUS_OFFSET);
  1018. ulLockRW = ulLockRW & 0xFFFFEFFF;
  1019. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulLockRW, M1621_Lock_WR);
  1020. }
  1021. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x80);
  1022. ulTemp = ulTemp & 0xFFFFF3FF; // set offset 0x81 bit 2~3 to 0
  1023. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x80);
  1024. if (blnVidia)
  1025. {
  1026. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x50);
  1027. ulTemp = ulTemp | 0x40; // set M1621 index 0x50 bit 6 to 1
  1028. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x50);
  1029. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x60);
  1030. ulTemp = ulTemp | 0x40; // set M1621 index 0x60 bit 6 to 1
  1031. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x60);
  1032. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x7C);
  1033. ulTemp = ulTemp & 0xCFFFFFFF; // set M1621 index 0x7F bit 4~5 to 0
  1034. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x7C);
  1035. }
  1036. if (blMatrox)
  1037. {
  1038. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x50);
  1039. ulTemp = ulTemp | 0xFF000000; // set M1621 index 0x53 to 0xFF
  1040. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x50);
  1041. }
  1042. break;
  1043. case ALi1631:
  1044. case ALi1632:
  1045. break;
  1046. case ALi1641:
  1047. if (blMatrox)
  1048. {
  1049. ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x50);
  1050. ulTemp = ulTemp | 0xFF000000; // set M1621 index 0x53 to 0xFF
  1051. WriteConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &ulTemp, 0x50);
  1052. }
  1053. break;
  1054. case ALi1644:
  1055. case ALi1646:
  1056. case ALi1647:
  1057. case ALi1651:
  1058. case ALi1661:
  1059. case ALi1667:
  1060. break;
  1061. default:
  1062. break;
  1063. }
  1064. }
  1065. NTSTATUS
  1066. AgpSpecialTarget(
  1067. IN PAGPALi_EXTENSION AgpContext,
  1068. IN ULONGLONG DeviceFlags
  1069. )
  1070. /*++
  1071. Routine Description:
  1072. This routine makes "special" tweaks to the AGP chipset
  1073. Arguments:
  1074. AgpContext - Supplies the AGP context
  1075. DeviceFlags - Flags indicating what tweaks to perform
  1076. Return Value:
  1077. STATUS_SUCCESS, or error
  1078. --*/
  1079. {
  1080. NTSTATUS Status;
  1081. //
  1082. // Should we change the AGP rate?
  1083. //
  1084. if (DeviceFlags & AGP_FLAG_SPECIAL_RESERVE) {
  1085. Status = AgpALiSetRate(AgpContext,
  1086. (ULONG)((DeviceFlags & AGP_FLAG_SPECIAL_RESERVE)
  1087. >> AGP_FLAG_SET_RATE_SHIFT));
  1088. if (!NT_SUCCESS(Status)) {
  1089. return Status;
  1090. }
  1091. }
  1092. //
  1093. // Add more tweaks here...
  1094. //
  1095. AgpContext->SpecialTarget |= DeviceFlags;
  1096. return STATUS_SUCCESS;
  1097. }
  1098. NTSTATUS
  1099. AgpALiSetRate(
  1100. IN PAGPALi_EXTENSION AgpContext,
  1101. IN ULONG AgpRate
  1102. )
  1103. /*++
  1104. Routine Description:
  1105. This routine sets the AGP rate
  1106. Arguments:
  1107. AgpContext - Supplies the AGP context
  1108. AgpRate - Rate to set
  1109. note: this routine assumes that AGP has already been enabled, and that
  1110. whatever rate we've been asked to set is supported by master
  1111. Return Value:
  1112. STATUS_SUCCESS, or error status
  1113. --*/
  1114. {
  1115. NTSTATUS Status;
  1116. ULONG TargetEnable;
  1117. ULONG MasterEnable;
  1118. PCI_AGP_CAPABILITY TargetCap;
  1119. PCI_AGP_CAPABILITY MasterCap;
  1120. BOOLEAN ReverseInit;
  1121. //
  1122. // Read capabilities
  1123. //
  1124. Status = AgpLibGetPciDeviceCapability(0, 0, &TargetCap);
  1125. if (!NT_SUCCESS(Status)) {
  1126. AGPLOG(AGP_WARNING, ("AGPALiSetRate: AgpLibGetPciDeviceCapability "
  1127. "failed %08lx\n", Status));
  1128. return Status;
  1129. }
  1130. Status = AgpLibGetMasterCapability(AgpContext, &MasterCap);
  1131. if (!NT_SUCCESS(Status)) {
  1132. AGPLOG(AGP_WARNING, ("AGPALiSetRate: AgpLibGetMasterCapability "
  1133. "failed %08lx\n", Status));
  1134. return Status;
  1135. }
  1136. //
  1137. // Verify the requested rate is supported by both master and target
  1138. //
  1139. if (!(AgpRate & TargetCap.AGPStatus.Rate & MasterCap.AGPStatus.Rate)) {
  1140. return STATUS_INVALID_PARAMETER;
  1141. }
  1142. //
  1143. // Disable AGP while the pull the rug out from underneath
  1144. //
  1145. TargetEnable = TargetCap.AGPCommand.AGPEnable;
  1146. TargetCap.AGPCommand.AGPEnable = 0;
  1147. Status = AgpLibSetPciDeviceCapability(0, 0, &TargetCap);
  1148. if (!NT_SUCCESS(Status)) {
  1149. AGPLOG(AGP_WARNING,
  1150. ("AGPALiSetRate: AgpLibSetPciDeviceCapability %08lx for "
  1151. "Target failed %08lx\n",
  1152. &TargetCap,
  1153. Status));
  1154. return Status;
  1155. }
  1156. MasterEnable = MasterCap.AGPCommand.AGPEnable;
  1157. MasterCap.AGPCommand.AGPEnable = 0;
  1158. Status = AgpLibSetMasterCapability(AgpContext, &MasterCap);
  1159. if (!NT_SUCCESS(Status)) {
  1160. AGPLOG(AGP_WARNING,
  1161. ("AGPALiSetRate: AgpLibSetMasterCapability %08lx failed "
  1162. "%08lx\n",
  1163. &MasterCap,
  1164. Status));
  1165. return Status;
  1166. }
  1167. //
  1168. // Fire up AGP with new rate
  1169. //
  1170. ReverseInit =
  1171. (AgpContext->SpecialTarget & AGP_FLAG_REVERSE_INITIALIZATION) ==
  1172. AGP_FLAG_REVERSE_INITIALIZATION;
  1173. if (ReverseInit) {
  1174. MasterCap.AGPCommand.Rate = AgpRate;
  1175. MasterCap.AGPCommand.AGPEnable = MasterEnable;
  1176. Status = AgpLibSetMasterCapability(AgpContext, &MasterCap);
  1177. if (!NT_SUCCESS(Status)) {
  1178. AGPLOG(AGP_WARNING,
  1179. ("AGPALiSetRate: AgpLibSetMasterCapability %08lx failed "
  1180. "%08lx\n",
  1181. &MasterCap,
  1182. Status));
  1183. }
  1184. }
  1185. TargetCap.AGPCommand.Rate = AgpRate;
  1186. TargetCap.AGPCommand.AGPEnable = TargetEnable;
  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. if (!ReverseInit) {
  1197. MasterCap.AGPCommand.Rate = AgpRate;
  1198. MasterCap.AGPCommand.AGPEnable = MasterEnable;
  1199. Status = AgpLibSetMasterCapability(AgpContext, &MasterCap);
  1200. if (!NT_SUCCESS(Status)) {
  1201. AGPLOG(AGP_WARNING,
  1202. ("AGPALiSetRate: AgpLibSetMasterCapability %08lx failed "
  1203. "%08lx\n",
  1204. &MasterCap,
  1205. Status));
  1206. }
  1207. }
  1208. return Status;
  1209. }