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.

1580 lines
41 KiB

  1. /*++
  2. Copyright (2) 2002 Microsoft Corporation
  3. Module Name:
  4. gart.c
  5. Abstract:
  6. This module contains the Graphics Aperture Redirection Table support
  7. routines for the MS AGP v3 Filter Driver
  8. Author:
  9. Eric F. Nelson (enelson) June 6, 2002
  10. Revision History:
  11. --*/
  12. #include "agp.h"
  13. #include "uagp35.h"
  14. NTSTATUS
  15. Uagp35CreateGart(
  16. IN PUAGP35_EXTENSION AgpContext,
  17. IN ULONG MinimumPages
  18. );
  19. VOID
  20. Uagp35EnableGTLB(
  21. IN PUAGP35_EXTENSION AgpContext,
  22. IN BOOLEAN Enable
  23. );
  24. NTSTATUS
  25. Uagp35SetRate(
  26. IN PUAGP35_EXTENSION AgpContext,
  27. IN ULONG AgpRate
  28. );
  29. PGART_PTE32
  30. Uagp35FindRangeInGart32(
  31. IN PVOID StartPte,
  32. IN PVOID EndPte,
  33. IN ULONG Length,
  34. IN BOOLEAN SearchBackward,
  35. IN ULONG SearchState
  36. );
  37. #ifdef ALLOC_PRAGMA
  38. #pragma alloc_text(PAGE, AgpDisableAperture)
  39. #pragma alloc_text(PAGE, AgpQueryAperture)
  40. #pragma alloc_text(PAGE, AgpReserveMemory)
  41. #pragma alloc_text(PAGE, AgpReleaseMemory)
  42. #pragma alloc_text(PAGE, Uagp35CreateGart)
  43. #pragma alloc_text(PAGE, AgpMapMemory)
  44. #pragma alloc_text(PAGE, AgpUnMapMemory)
  45. #pragma alloc_text(PAGE, Uagp35FindRangeInGart32)
  46. #pragma alloc_text(PAGE, AgpFindFreeRun)
  47. #pragma alloc_text(PAGE, AgpGetMappedPages)
  48. #endif
  49. #define Uagp35EnableTB(_x_) Uagp35EnableGTLB((_x_), TRUE)
  50. #define Uagp35DisableTB(_x_) Uagp35EnableGTLB((_x_), FALSE)
  51. NTSTATUS
  52. AgpQueryAperture(
  53. IN PUAGP35_EXTENSION AgpContext,
  54. OUT PHYSICAL_ADDRESS *CurrentBase,
  55. OUT ULONG *CurrentSizeInPages,
  56. OUT OPTIONAL PIO_RESOURCE_LIST *pApertureRequirements
  57. )
  58. /*++
  59. Routine Description:
  60. Queries the current size of the GART aperture, and optionally returns
  61. the possible GART settings
  62. Arguments:
  63. AgpContext - Supplies our AGP3 context
  64. CurrentBase - Returns the current physical address of the GART
  65. CurrentSizeInPages - Returns the current GART size
  66. ApertureRequirements - If present, returns the possible GART settings
  67. Return Value:
  68. STATUS_SUCCESS, or an appropriate error status
  69. --*/
  70. {
  71. PHYSICAL_ADDRESS ApertureBase;
  72. PIO_RESOURCE_LIST Requirements;
  73. ULONG Index;
  74. ULONG Length;
  75. USHORT ApSize;
  76. ULONG AltCount;
  77. PAGED_CODE();
  78. //
  79. // Get the current aperture base and size settings
  80. //
  81. if (!AgpContext->FourGBEnable) {
  82. AgpLibReadAgpTargetConfig(AgpContext,
  83. &ApertureBase.LowPart,
  84. APERTURE_BASE,
  85. sizeof(ApertureBase.LowPart));
  86. } else {
  87. AgpLibReadAgpTargetConfig(AgpContext,
  88. &ApertureBase,
  89. APERTURE_BASE,
  90. sizeof(ApertureBase));
  91. }
  92. AgpLibGetExtendedTargetCapability(AgpContext, ApertureSize, &ApSize);
  93. ASSERT(ApertureBase.QuadPart != 0);
  94. CurrentBase->QuadPart =
  95. ApertureBase.QuadPart & PCI_ADDRESS_MEMORY_ADDRESS_MASK;
  96. //
  97. // Convert APSIZE into the actual size of the aperture
  98. //
  99. switch (ApSize) {
  100. case AP_SIZE_4MB:
  101. AltCount = 1;
  102. *CurrentSizeInPages = 4 * (1024 * 1024 / PAGE_SIZE);
  103. break;
  104. case AP_SIZE_8MB:
  105. AltCount = 2;
  106. *CurrentSizeInPages = 8 * (1024 * 1024 / PAGE_SIZE);
  107. break;
  108. case AP_SIZE_16MB:
  109. AltCount = 3;
  110. *CurrentSizeInPages = 16 * (1024 * 1024 / PAGE_SIZE);
  111. break;
  112. case AP_SIZE_32MB:
  113. AltCount = 4;
  114. *CurrentSizeInPages = 32 * (1024 * 1024 / PAGE_SIZE);
  115. break;
  116. case AP_SIZE_64MB:
  117. AltCount = 5;
  118. *CurrentSizeInPages = 64 * (1024 * 1024 / PAGE_SIZE);
  119. break;
  120. case AP_SIZE_128MB:
  121. AltCount = 6;
  122. *CurrentSizeInPages = 128 * (1024 * 1024 / PAGE_SIZE);
  123. break;
  124. case AP_SIZE_256MB:
  125. AltCount = 7;
  126. *CurrentSizeInPages = 256 * (1024 * 1024 / PAGE_SIZE);
  127. break;
  128. case AP_SIZE_512MB:
  129. AltCount = 8;
  130. *CurrentSizeInPages = 512 * (1024 * 1024 / PAGE_SIZE);
  131. break;
  132. case AP_SIZE_1024MB:
  133. AltCount = 9;
  134. *CurrentSizeInPages = 1024 * (1024 * 1024 / PAGE_SIZE);
  135. break;
  136. case AP_SIZE_2048MB:
  137. AltCount = 10;
  138. *CurrentSizeInPages = 2048 * (1024 * 1024 / PAGE_SIZE);
  139. break;
  140. //
  141. // IO Resource descriptor's size is only 32-bits!
  142. //
  143. // case AP_SIZE_4096MB:
  144. // AltCount = 11;
  145. // *CurrentSizeInPages = 4096 * (1024 * 1024 / PAGE_SIZE);
  146. // break;
  147. default:
  148. AGPLOG(AGP_CRITICAL,
  149. ("AgpQueryAperture - Unexpected value %x for ApSize!\n",
  150. ApSize));
  151. ASSERT(FALSE);
  152. AgpContext->ApertureStart.QuadPart = 0;
  153. AgpContext->ApertureLength = 0;
  154. return STATUS_UNSUCCESSFUL;
  155. }
  156. //
  157. // Remember the current aperture settings
  158. //
  159. AgpContext->ApertureStart.QuadPart = CurrentBase->QuadPart;
  160. AgpContext->ApertureLength = *CurrentSizeInPages * PAGE_SIZE;
  161. if (pApertureRequirements != NULL) {
  162. //
  163. // Since the BIOS probably describes the desired size, we
  164. // will only attempt alternates of the same size, or less
  165. //
  166. Requirements =
  167. ExAllocatePoolWithTag(PagedPool,
  168. sizeof(IO_RESOURCE_LIST) +
  169. (AltCount - 1) *
  170. sizeof(IO_RESOURCE_DESCRIPTOR),
  171. 'RpgA');
  172. if (Requirements == NULL) {
  173. return STATUS_INSUFFICIENT_RESOURCES;
  174. }
  175. Requirements->Version = Requirements->Revision = 1;
  176. Requirements->Count = AltCount;
  177. Length = AgpContext->ApertureLength;
  178. for (Index = 0; Index < Requirements->Count; Index++) {
  179. Requirements->Descriptors[Index].Option = IO_RESOURCE_ALTERNATIVE;
  180. Requirements->Descriptors[Index].Type = CmResourceTypeMemory;
  181. Requirements->Descriptors[Index].ShareDisposition =
  182. CmResourceShareDeviceExclusive;
  183. Requirements->Descriptors[Index].Flags =
  184. CM_RESOURCE_MEMORY_READ_WRITE |
  185. CM_RESOURCE_MEMORY_PREFETCHABLE;
  186. Requirements->Descriptors[Index].u.Memory.Length = Length;
  187. Requirements->Descriptors[Index].u.Memory.Alignment = Length;
  188. Requirements->Descriptors[Index].u.Memory.MinimumAddress.QuadPart =
  189. 0;
  190. Requirements->Descriptors[Index].u.Memory.MaximumAddress.QuadPart =
  191. (ULONG)-1;
  192. Length /= 2;
  193. }
  194. *pApertureRequirements = Requirements;
  195. }
  196. return STATUS_SUCCESS;
  197. }
  198. NTSTATUS
  199. AgpSetAperture(
  200. IN PUAGP35_EXTENSION AgpContext,
  201. IN PHYSICAL_ADDRESS NewBase,
  202. IN ULONG NewSizeInPages
  203. )
  204. /*++
  205. Routine Description:
  206. Sets the GART aperture to the supplied settings
  207. Arguments:
  208. AgpContext - Supplies our AGP3 context
  209. NewBase - Supplies the new physical memory base for the GART
  210. NewSizeInPages - Supplies the new size for the GART
  211. Return Value:
  212. STATUS_SUCCESS, or an appropriate error status
  213. --*/
  214. {
  215. PCI_AGP_CONTROL AgpCtrl;
  216. USHORT ApSize;
  217. PHYSICAL_ADDRESS ApBase;
  218. //
  219. // Figure out the new APSIZE setting, make sure it is valid.
  220. //
  221. switch (NewSizeInPages) {
  222. case 4 * (1024 * 1024 / PAGE_SIZE):
  223. ApSize = AP_SIZE_4MB;
  224. break;
  225. case 8 * (1024 * 1024 / PAGE_SIZE):
  226. ApSize = AP_SIZE_8MB;
  227. break;
  228. case 16 * (1024 * 1024 / PAGE_SIZE):
  229. ApSize = AP_SIZE_16MB;
  230. break;
  231. case 32 * (1024 * 1024 / PAGE_SIZE):
  232. ApSize = AP_SIZE_32MB;
  233. break;
  234. case 64 * (1024 * 1024 / PAGE_SIZE):
  235. ApSize = AP_SIZE_64MB;
  236. break;
  237. case 128 * (1024 * 1024 / PAGE_SIZE):
  238. ApSize = AP_SIZE_128MB;
  239. break;
  240. case 256 * (1024 * 1024 / PAGE_SIZE):
  241. ApSize = AP_SIZE_256MB;
  242. break;
  243. case 512 * (1024 * 1024 / PAGE_SIZE):
  244. ApSize = AP_SIZE_512MB;
  245. break;
  246. case 1024 * (1024 * 1024 / PAGE_SIZE):
  247. ApSize = AP_SIZE_1024MB;
  248. break;
  249. case 2048 * (1024 * 1024 / PAGE_SIZE):
  250. ApSize = AP_SIZE_2048MB;
  251. break;
  252. //
  253. // IO Resource descriptor's size is only 32-bits!
  254. //
  255. // case AP_SIZE_4096MB:
  256. // AltCount = 11;
  257. // *CurrentSizeInPages = 4096 * (1024 * 1024 / PAGE_SIZE);
  258. // break;
  259. // case 4096 * (1024 * 1024 / PAGE_SIZE):
  260. // ApSize = AP_SIZE_4096MB;
  261. // break;
  262. default:
  263. AGPLOG(AGP_CRITICAL,
  264. ("AgpSetAperture - invalid GART size of %lx pages "
  265. "specified, aperture at %I64X.\n",
  266. NewSizeInPages,
  267. NewBase.QuadPart));
  268. ASSERT(FALSE);
  269. return STATUS_INVALID_PARAMETER;
  270. }
  271. //
  272. // Make sure the supplied size is aligned on the appropriate boundary
  273. //
  274. ASSERT((NewBase.QuadPart & ((NewSizeInPages * PAGE_SIZE) - 1)) == 0);
  275. if ((NewBase.QuadPart & ((NewSizeInPages * PAGE_SIZE) - 1)) != 0 ) {
  276. AGPLOG(AGP_CRITICAL,
  277. ("AgpSetAperture - invalid base %I64X specified for GART "
  278. "aperture of %lx pages\n",
  279. NewBase.QuadPart,
  280. NewSizeInPages));
  281. return STATUS_INVALID_PARAMETER;
  282. }
  283. //
  284. // Reprogram Special Target settings when the chip
  285. // is powered off, but ignore rate changes as those were already
  286. // applied during MasterInit
  287. //
  288. if (AgpContext->SpecialTarget & ~AGP_FLAG_SPECIAL_RESERVE) {
  289. AgpSpecialTarget(AgpContext,
  290. AgpContext->SpecialTarget &
  291. ~AGP_FLAG_SPECIAL_RESERVE);
  292. }
  293. //
  294. // Need to reset the hardware to match the supplied settings
  295. //
  296. // If the aperture is enabled, disable it, write the new settings,
  297. // then reenable the aperture
  298. //
  299. //
  300. // Disable the aperture
  301. //
  302. AgpLibGetExtendedTargetCapability(AgpContext, AgpControl, &AgpCtrl);
  303. if (AgpCtrl.AP_Enable == ON) {
  304. AgpCtrl.AP_Enable = OFF;
  305. if (!(AgpContext->SpecialTarget &
  306. AGP_FLAG_SPECIAL_NO_APERTURE_DISABLE)) {
  307. AgpLibSetExtendedTargetCapability(AgpContext,
  308. AgpControl,
  309. &AgpCtrl);
  310. } else {
  311. AGPLOG(AGP_WARNING,
  312. ("UAGP35MasterInit: AGP_FLAG_SPECIAL_NO_APERTURE_DISABLE\n")
  313. );
  314. }
  315. }
  316. //
  317. // Write APSIZE first, as this will enable the correct bits in APBASE
  318. // that need to be written next
  319. //
  320. AgpLibSetExtendedTargetCapability(AgpContext, ApertureSize, &ApSize);
  321. //
  322. // Now we can update APBASE
  323. //
  324. ApBase.QuadPart = NewBase.LowPart & PCI_ADDRESS_MEMORY_ADDRESS_MASK;
  325. if (AgpContext->CapabilityId != PCI_CAPABILITY_ID_AGP_TARGET) {
  326. if (!AgpContext->FourGBEnable) {
  327. ASSERT(ApBase.HighPart == 0);
  328. AgpLibWriteAgpTargetConfig(AgpContext,
  329. &ApBase.LowPart,
  330. APERTURE_BASE,
  331. sizeof(ApBase.LowPart));
  332. } else {
  333. AgpLibWriteAgpTargetConfig(AgpContext,
  334. &ApBase,
  335. APERTURE_BASE,
  336. sizeof(ApBase));
  337. }
  338. }
  339. #if DBG
  340. //
  341. // Read back what we wrote, make sure it worked
  342. //
  343. {
  344. PHYSICAL_ADDRESS DbgBase;
  345. USHORT DbgSize;
  346. ULONGLONG ApBaseMask;
  347. ApBaseMask = AP_BASE_MASK(ApSize);
  348. AgpLibGetExtendedTargetCapability(AgpContext, ApertureSize, &DbgSize);
  349. if (!AgpContext->FourGBEnable) {
  350. DbgBase.HighPart = 0;
  351. AgpLibReadAgpTargetConfig(AgpContext,
  352. &DbgBase.LowPart,
  353. APERTURE_BASE,
  354. sizeof(DbgBase.LowPart));
  355. } else {
  356. AgpLibReadAgpTargetConfig(AgpContext,
  357. &DbgBase,
  358. APERTURE_BASE,
  359. sizeof(DbgBase));
  360. }
  361. ASSERT(DbgSize == ApSize);
  362. //
  363. // If this fires, it means our BAR has moved, might be good to track
  364. // this during AGP3 debug
  365. //
  366. ASSERT((DbgBase.QuadPart & ApBaseMask) == ApBase.QuadPart);
  367. }
  368. #endif
  369. //
  370. // Now enable the aperture if it was enabled before
  371. //
  372. if (AgpContext->GlobalEnable) {
  373. AgpLibGetExtendedTargetCapability(AgpContext,
  374. AgpControl,
  375. &AgpCtrl);
  376. ASSERT((AgpCtrl.AP_Enable == OFF) ||
  377. (AgpContext->SpecialTarget &
  378. AGP_FLAG_SPECIAL_NO_APERTURE_DISABLE));
  379. AgpCtrl.AP_Enable = ON;
  380. AgpLibSetExtendedTargetCapability(AgpContext,
  381. AgpControl,
  382. &AgpCtrl);
  383. }
  384. //
  385. // Update our extension to reflect the new GART setting
  386. //
  387. AgpContext->ApertureStart = NewBase;
  388. AgpContext->ApertureLength = NewSizeInPages * PAGE_SIZE;
  389. //
  390. // Enable the TB in case we are resuming from S3 or S4
  391. //
  392. Uagp35EnableTB(AgpContext);
  393. //
  394. // If the GART has been allocated, rewrite the ATTBASE
  395. //
  396. if (AgpContext->Gart != NULL) {
  397. AgpLibSetExtendedTargetCapability(AgpContext,
  398. GartLow,
  399. &AgpContext->GartPhysical.LowPart);
  400. #ifdef _WIN64
  401. AgpLibSetExtendedTargetCapability(AgpContext,
  402. GartHigh,
  403. &AgpContext->GartPhysical.HighPart);
  404. #endif
  405. }
  406. return STATUS_SUCCESS;
  407. }
  408. VOID
  409. AgpDisableAperture(
  410. IN PUAGP35_EXTENSION AgpContext
  411. )
  412. /*++
  413. Routine Description:
  414. Disables the GART aperture so that this resource is available
  415. for other devices
  416. Arguments:
  417. AgpContext - Supplies our AGP3 context
  418. Return Value:
  419. None
  420. --*/
  421. {
  422. PCI_AGP_CONTROL AgpCtrl;
  423. //
  424. // Disable the aperture
  425. //
  426. AgpLibGetExtendedTargetCapability(AgpContext,
  427. AgpControl,
  428. &AgpCtrl);
  429. if (AgpCtrl.AP_Enable == ON) {
  430. AgpCtrl.AP_Enable = OFF;
  431. AgpLibSetExtendedTargetCapability(AgpContext,
  432. AgpControl,
  433. &AgpCtrl);
  434. }
  435. AgpContext->GlobalEnable = FALSE;
  436. //
  437. // Nuke the Gart! (It's meaningless now...)
  438. //
  439. if (AgpContext->Gart != NULL) {
  440. MmFreeContiguousMemory(AgpContext->Gart);
  441. AgpContext->Gart = NULL;
  442. AgpContext->GartLength = 0;
  443. }
  444. }
  445. NTSTATUS
  446. AgpReserveMemory(
  447. IN PUAGP35_EXTENSION AgpContext,
  448. IN OUT AGP_RANGE *Range
  449. )
  450. /*++
  451. Routine Description:
  452. Reserves a range of memory in the GART
  453. Arguments:
  454. AgpContext - Supplies our AGP3 Context
  455. Range - Supplies the AGP_RANGE structure (AGPLIB will have filled
  456. in NumberOfPages and Type, and this routine will fill in
  457. MemoryBase and Context)
  458. Return Value:
  459. STATUS_SUCCESS, or an appropriate error status
  460. --*/
  461. {
  462. ULONG Index;
  463. ULONG NewState;
  464. NTSTATUS Status;
  465. PGART_PTE32 FoundRange;
  466. BOOLEAN Backwards;
  467. PAGED_CODE();
  468. ASSERT((Range->Type == MmNonCached) || (Range->Type == MmWriteCombined));
  469. if (Range->NumberOfPages > (AgpContext->ApertureLength / PAGE_SIZE)) {
  470. return STATUS_INSUFFICIENT_RESOURCES;
  471. }
  472. //
  473. // If we have not allocated our GART yet, now is the time to do so
  474. //
  475. if (AgpContext->Gart == NULL) {
  476. ASSERT(AgpContext->GartLength == 0);
  477. Status = Uagp35CreateGart(AgpContext, Range->NumberOfPages);
  478. if (!NT_SUCCESS(Status)) {
  479. AGPLOG(AGP_CRITICAL,
  480. ("UAGP35CreateGart failed %08lx to create GART of size "
  481. "%lx\n",
  482. Status,
  483. AgpContext->ApertureLength));
  484. return Status;
  485. }
  486. }
  487. ASSERT(AgpContext->GartLength != 0);
  488. //
  489. // Now that we have a GART, try and find enough contiguous entries to
  490. // satisfy the request, requests for uncached memory will scan from high
  491. // addresses to low addresses, requests for write-combined memory will
  492. // scan from low addresses to high addresses, we will use a first-fit
  493. // algorithm to try and keep the allocations
  494. // packed and contiguous
  495. //
  496. Backwards = (Range->Type == MmNonCached) ? TRUE : FALSE;
  497. FoundRange =
  498. Uagp35FindRangeInGart32(&AgpContext->Gart[0],
  499. &AgpContext->Gart[(AgpContext->GartLength /
  500. sizeof(GART_PTE32)) - 1],
  501. Range->NumberOfPages,
  502. Backwards,
  503. GART_ENTRY_FREE);
  504. if (FoundRange == NULL) {
  505. //
  506. // A big enough chunk was not found.
  507. //
  508. AGPLOG(AGP_CRITICAL,
  509. ("AgpReserveMemory: Could not find %d contiguous free pages "
  510. "of type %d in GART at %08lx\n",
  511. Range->NumberOfPages,
  512. Range->Type,
  513. AgpContext->Gart));
  514. //
  515. // This is where we could try and grow the GART
  516. //
  517. return STATUS_INSUFFICIENT_RESOURCES;
  518. }
  519. AGPLOG(AGP_NOISE,
  520. ("AgpReserveMemory: reserved %d pages at GART PTE %08lx\n",
  521. Range->NumberOfPages,
  522. FoundRange));
  523. //
  524. // Set these pages to reserved
  525. //
  526. switch (Range->Type) {
  527. case MmNonCached:
  528. NewState = GART_ENTRY_RESERVED_UC;
  529. break;
  530. case MmWriteCombined:
  531. NewState = GART_ENTRY_RESERVED_WC;
  532. break;
  533. default:
  534. //
  535. // Unknown cache type, default to HW coherent cached
  536. //
  537. AGPLOG(AGP_NOISE,
  538. ("AgpReserveMemory: Unknown cache type %d\n",
  539. Range->Type));
  540. case MmHardwareCoherentCached:
  541. NewState = GART_ENTRY_RESERVED_CC;
  542. }
  543. for (Index = 0; Index < Range->NumberOfPages; Index++) {
  544. ASSERT(FoundRange[Index].Soft.State == GART_ENTRY_FREE);
  545. FoundRange[Index].AsULONG = 0;
  546. FoundRange[Index].Soft.State = NewState;
  547. }
  548. Range->MemoryBase.QuadPart = AgpContext->ApertureStart.QuadPart +
  549. (FoundRange - &AgpContext->Gart[0]) * PAGE_SIZE;
  550. Range->Context = FoundRange;
  551. ASSERT(Range->MemoryBase.HighPart == 0);
  552. AGPLOG(AGP_NOISE,
  553. ("AgpReserveMemory: reserved memory handle %lx at PA %08lx\n",
  554. FoundRange,
  555. Range->MemoryBase.LowPart));
  556. return STATUS_SUCCESS;
  557. }
  558. NTSTATUS
  559. AgpReleaseMemory(
  560. IN PUAGP35_EXTENSION AgpContext,
  561. IN PAGP_RANGE Range
  562. )
  563. /*++
  564. Routine Description:
  565. Releases memory previously reserved with AgpReserveMemory
  566. Arguments:
  567. AgpContext - Supplies our AGP3 context
  568. AgpRange - Supplies the range to be released
  569. Return Value:
  570. STATUS_SUCCESS, or an appropriate error status
  571. --*/
  572. {
  573. PGART_PTE32 Pte;
  574. ULONG Start;
  575. PAGED_CODE();
  576. //
  577. // Go through and free all the PTEs, none of these should still
  578. // be valid at this point
  579. //
  580. for (Pte = Range->Context;
  581. Pte < ((PGART_PTE32)Range->Context + Range->NumberOfPages);
  582. Pte++) {
  583. switch (Range->Type) {
  584. case MmNonCached:
  585. ASSERT(Pte->Soft.State == GART_ENTRY_RESERVED_UC);
  586. break;
  587. case MmWriteCombined:
  588. ASSERT(Pte->Soft.State == GART_ENTRY_RESERVED_WC);
  589. break;
  590. default:
  591. //
  592. // Unknown cache type, default to HW coherent cached
  593. //
  594. AGPLOG(AGP_NOISE,
  595. ("AgpReleaseMemory: Unknown cache type %d\n",
  596. Range->Type));
  597. case MmHardwareCoherentCached:
  598. ASSERT(Pte->Soft.State == GART_ENTRY_RESERVED_CC);
  599. }
  600. Pte->Soft.State = GART_ENTRY_FREE;
  601. }
  602. Range->MemoryBase.QuadPart = 0;
  603. return STATUS_SUCCESS;
  604. }
  605. NTSTATUS
  606. Uagp35CreateGart(
  607. IN PUAGP35_EXTENSION AgpContext,
  608. IN ULONG MinimumPages
  609. )
  610. /*++
  611. Routine Description:
  612. Allocates and initializes an empty GART, the current implementation
  613. attempts to allocate the entire GART on the first reserve
  614. Arguments:
  615. AgpContext - Supplies our AGP3 context
  616. MinimumPages - Supplies the minimum size (in pages) of the GART to be
  617. created
  618. Return Value:
  619. STATUS_SUCCESS, or an appropriate error status
  620. --*/
  621. {
  622. PGART_PTE32 Gart;
  623. ULONG GartLength;
  624. PHYSICAL_ADDRESS HighestAcceptable;
  625. PHYSICAL_ADDRESS LowestAcceptable;
  626. PHYSICAL_ADDRESS BoundaryMultiple;
  627. PHYSICAL_ADDRESS GartPhysical;
  628. ULONG Index;
  629. PAGED_CODE();
  630. //
  631. // Try and get a chunk of contiguous memory big enough to map the
  632. // entire aperture
  633. //
  634. LowestAcceptable.QuadPart = 0;
  635. BoundaryMultiple.QuadPart = 0;
  636. #ifdef _WIN64
  637. HighestAcceptable.QuadPart = (ULONGLONG)-1;
  638. #else
  639. HighestAcceptable.QuadPart = (ULONG)-1;
  640. #endif
  641. GartLength =
  642. BYTES_TO_PAGES(AgpContext->ApertureLength) * sizeof(GART_PTE32);
  643. Gart = MmAllocateContiguousMemorySpecifyCache(GartLength,
  644. LowestAcceptable,
  645. HighestAcceptable,
  646. BoundaryMultiple,
  647. MmNonCached);
  648. if (Gart == NULL) {
  649. AGPLOG(AGP_CRITICAL,
  650. ("UAGP35CreateGart: MmAllocateContiguousMemorySpecifyCache %lx "
  651. "failed\n",
  652. GartLength));
  653. return STATUS_INSUFFICIENT_RESOURCES;
  654. }
  655. //
  656. // We successfully allocated a contiguous chunk of memory.
  657. // It should be page aligned already.
  658. //
  659. ASSERT(((ULONG_PTR)Gart & (PAGE_SIZE - 1)) == 0);
  660. //
  661. // Get the physical address
  662. //
  663. GartPhysical = MmGetPhysicalAddress(Gart);
  664. AGPLOG(AGP_NOISE,
  665. ("UAGP35CreateGart: GART of length %lx created at VA %08lx, "
  666. "PA %08lx\n",
  667. GartLength,
  668. Gart,
  669. GartPhysical.LowPart));
  670. ASSERT(GartPhysical.HighPart == 0);
  671. ASSERT((GartPhysical.LowPart & (PAGE_SIZE - 1)) == 0);
  672. //
  673. // Initialize all the PTEs to free
  674. //
  675. for (Index = 0; Index < (GartLength / sizeof(GART_PTE32)); Index++) {
  676. Gart[Index].Soft.State = GART_ENTRY_FREE;
  677. }
  678. AgpLibSetExtendedTargetCapability(AgpContext,
  679. GartLow,
  680. &GartPhysical.LowPart);
  681. #ifdef _WIN64
  682. AgpLibSetExtendedTargetCapability(AgpContext,
  683. GartHigh,
  684. &GartPhysical.HighPart);
  685. #endif
  686. //
  687. // Update our extension to reflect the current state.
  688. //
  689. AgpContext->Gart = Gart;
  690. AgpContext->GartLength = GartLength;
  691. AgpContext->GartPhysical = GartPhysical;
  692. return STATUS_SUCCESS;
  693. }
  694. NTSTATUS
  695. AgpMapMemory(
  696. IN PUAGP35_EXTENSION AgpContext,
  697. IN PAGP_RANGE Range,
  698. IN PMDL Mdl,
  699. IN ULONG OffsetInPages,
  700. OUT PHYSICAL_ADDRESS *MemoryBase
  701. )
  702. /*++
  703. Routine Description:
  704. Maps physical memory into the GART somewhere in the specified range
  705. Arguments:
  706. AgpContext - Supplies our AGP3 context
  707. Range - Supplies the AGP range that the memory should be mapped into
  708. Mdl - Supplies the MDL describing the physical pages to be mapped
  709. OffsetInPages - Supplies the offset into the reserved range where the
  710. mapping should begin
  711. MemoryBase - Returns the physical memory in the aperture where the pages
  712. were mapped
  713. Return Value:
  714. STATUS_SUCCESS, or an appropriate error status
  715. --*/
  716. {
  717. ULONG PageCount;
  718. PGART_PTE32 Pte;
  719. PGART_PTE32 StartPte;
  720. ULONG Index;
  721. ULONG TargetState;
  722. PPFN_NUMBER Page;
  723. BOOLEAN Backwards;
  724. GART_PTE32 NewPte;
  725. PCI_AGP_CONTROL AgpCtrl;
  726. PAGED_CODE();
  727. ASSERT(Mdl->Next == NULL);
  728. NewPte.AsULONG = 0;
  729. StartPte = Range->Context;
  730. PageCount = BYTES_TO_PAGES(Mdl->ByteCount);
  731. ASSERT(PageCount <= Range->NumberOfPages);
  732. ASSERT(OffsetInPages <= Range->NumberOfPages);
  733. ASSERT(PageCount + OffsetInPages <= Range->NumberOfPages);
  734. ASSERT(PageCount > 0);
  735. switch (Range->Type) {
  736. case MmNonCached:
  737. TargetState = GART_ENTRY_RESERVED_UC;
  738. NewPte.Soft.State = GART_ENTRY_VALID_UC;
  739. break;
  740. case MmWriteCombined:
  741. TargetState = GART_ENTRY_RESERVED_WC;
  742. NewPte.Soft.State = GART_ENTRY_VALID_WC;
  743. break;
  744. default:
  745. //
  746. // Unknown cache type, default to HW coherent cached
  747. //
  748. AGPLOG(AGP_NOISE,
  749. ("AgpMapMemory: Unknown cache type %d\n",
  750. Range->Type));
  751. case MmHardwareCoherentCached:
  752. TargetState = GART_ENTRY_RESERVED_CC;
  753. NewPte.Soft.State = GART_ENTRY_VALID_CC;
  754. }
  755. Pte = StartPte + OffsetInPages;
  756. //
  757. // We have a suitable range, now fill it in with the supplied MDL
  758. //
  759. ASSERT(Pte >= StartPte);
  760. ASSERT((Pte + PageCount) <= (StartPte + Range->NumberOfPages));
  761. Page = (PPFN_NUMBER)(Mdl + 1);
  762. //
  763. // Disable the TB as per the (440?) spec, this is probably unnecessary
  764. // as there should be no valid entries in this range, and there should
  765. // be no invalid entries still in the TB, so flushing the TB seems
  766. // a little gratuitous but that's what the old spec said to do
  767. //
  768. Uagp35DisableTB(AgpContext);
  769. for (Index = 0; Index < PageCount; Index++) {
  770. ASSERT(Pte[Index].Soft.State == TargetState);
  771. #ifndef _WIN64
  772. NewPte.Hard.PageLow = *Page++;
  773. #else
  774. NewPte.Hard.PageLow = (ULONG)*Page;
  775. NewPte.Hard.PageHigh = (ULONG)(*Page++ >> PAGE_HIGH_SHIFT);
  776. #endif
  777. Pte[Index].AsULONG = NewPte.AsULONG;
  778. ASSERT(Pte[Index].Hard.Valid == ON);
  779. }
  780. //
  781. // We have filled in all the PTEs, read back the last one we wrote
  782. // in order to flush the write buffers
  783. //
  784. NewPte.AsULONG = *(volatile ULONG *)&Pte[PageCount - 1].AsULONG;
  785. //
  786. // Re-enable the TB
  787. //
  788. Uagp35EnableTB(AgpContext);
  789. //
  790. // If we have not yet gotten around to enabling the GART aperture,
  791. // do it now
  792. //
  793. if (!AgpContext->GlobalEnable) {
  794. AGPLOG(AGP_NOISE, ("AgpMapMemory: Enabling global aperture access\n"));
  795. AgpLibGetExtendedTargetCapability(AgpContext, AgpControl, &AgpCtrl);
  796. AgpCtrl.AP_Enable = ON;
  797. AgpLibSetExtendedTargetCapability(AgpContext,
  798. AgpControl,
  799. &AgpCtrl);
  800. AgpContext->GlobalEnable = TRUE;
  801. }
  802. MemoryBase->QuadPart = Range->MemoryBase.QuadPart +
  803. ((Pte - StartPte) * PAGE_SIZE);
  804. return STATUS_SUCCESS;
  805. }
  806. NTSTATUS
  807. AgpUnMapMemory(
  808. IN PUAGP35_EXTENSION AgpContext,
  809. IN PAGP_RANGE AgpRange,
  810. IN ULONG NumberOfPages,
  811. IN ULONG OffsetInPages
  812. )
  813. /*++
  814. Routine Description:
  815. Unmaps previously mapped memory in the GART
  816. Arguments:
  817. AgpContext - Supplies our AGP3 context
  818. AgpRange - Supplies the AGP range that the memory should be freed from
  819. NumberOfPages - Supplies the number of pages in the range to be freed
  820. OffsetInPages - Supplies the offset into the range where the freeing
  821. should begin
  822. Return Value:
  823. STATUS_SUCCESS, or an appropriate error status
  824. --*/
  825. {
  826. ULONG Index;
  827. PGART_PTE32 Pte;
  828. PGART_PTE32 LastChanged = NULL;
  829. PGART_PTE32 StartPte;
  830. ULONG NewState;
  831. PAGED_CODE();
  832. ASSERT(OffsetInPages + NumberOfPages <= AgpRange->NumberOfPages);
  833. StartPte = AgpRange->Context;
  834. Pte = &StartPte[OffsetInPages];
  835. if (AgpRange->Type == MmNonCached) {
  836. NewState = GART_ENTRY_RESERVED_UC;
  837. } else if (AgpRange->Type == MmWriteCombined) {
  838. NewState = GART_ENTRY_RESERVED_WC;
  839. } else {
  840. NewState = GART_ENTRY_RESERVED_CC;
  841. }
  842. //
  843. // Disable the TB to flush it
  844. //
  845. Uagp35DisableTB(AgpContext);
  846. for (Index = 0; Index < NumberOfPages; Index++) {
  847. if (Pte[Index].Hard.Valid) {
  848. Pte[Index].Soft.State = NewState;
  849. LastChanged = &Pte[Index];
  850. } else {
  851. //
  852. // This page is not mapped, just skip it
  853. //
  854. AGPLOG(AGP_NOISE,
  855. ("AgpUnMapMemory: PTE %08lx (%08lx) at offset %d not "
  856. "mapped\n",
  857. &Pte[Index],
  858. Pte[Index].AsULONG,
  859. Index));
  860. ASSERT(Pte[Index].Soft.State == NewState);
  861. }
  862. }
  863. //
  864. // We have invalidated all the PTEs, read back the last one we wrote
  865. // in order to flush the write buffers
  866. //
  867. if (LastChanged != NULL) {
  868. ULONG FlushWB;
  869. FlushWB = *(volatile ULONG *)&LastChanged->AsULONG;
  870. }
  871. //
  872. // Reenable the TB
  873. //
  874. Uagp35EnableTB(AgpContext);
  875. return STATUS_SUCCESS;
  876. }
  877. PGART_PTE32
  878. Uagp35FindRangeInGart32(
  879. IN PGART_PTE32 StartPte,
  880. IN PGART_PTE32 EndPte,
  881. IN ULONG Length,
  882. IN BOOLEAN SearchBackward,
  883. IN ULONG SearchState
  884. )
  885. /*++
  886. Routine Description:
  887. Finds a contiguous range in a 32-bit PTE format GART, this
  888. routine can search either from the beginning of the GART
  889. forwards or the end of the GART backwards
  890. Arguments:
  891. StartIndex - Supplies the first GART PTE to search
  892. EndPte - Supplies the last GART PTE to search (inclusive)
  893. Length - Supplies the number of contiguous free entries
  894. to search for
  895. SearchBackward - TRUE indicates that the search should begin
  896. at EndPte and search backwards, FALSE indicates
  897. that the search should begin at StartPte and
  898. search forwards
  899. SearchState - Supplies the PTE state to look for
  900. Return Value:
  901. Pointer to the first PTE in the GART if a suitable range
  902. is found, and NULL if no suitable range exists
  903. --*/
  904. {
  905. PGART_PTE32 Current;
  906. PGART_PTE32 Last;
  907. LONG Delta;
  908. ULONG Found;
  909. PGART_PTE32 Candidate;
  910. PAGED_CODE();
  911. ASSERT(EndPte >= StartPte);
  912. ASSERT(Length <= (ULONG)(EndPte - StartPte + 1));
  913. ASSERT(Length != 0);
  914. if (SearchBackward) {
  915. Current = EndPte;
  916. Last = StartPte - 1;
  917. Delta = -1;
  918. } else {
  919. Current = StartPte;
  920. Last = EndPte + 1;
  921. Delta = 1;
  922. }
  923. Found = 0;
  924. while (Current != Last) {
  925. if (Current->Soft.State == SearchState) {
  926. if (++Found == Length) {
  927. //
  928. // A suitable range was found, return it
  929. //
  930. if (SearchBackward) {
  931. return Current;
  932. } else {
  933. return(Current - Length + 1);
  934. }
  935. }
  936. } else {
  937. Found = 0;
  938. }
  939. Current += Delta;
  940. }
  941. //
  942. // A suitable range was not found
  943. //
  944. return NULL;
  945. }
  946. VOID
  947. Uagp35EnableGTLB(
  948. IN PUAGP35_EXTENSION AgpContext,
  949. IN BOOLEAN Enable
  950. )
  951. /*++
  952. Routine Description:
  953. Enables or disables the GTLB by setting or clearing the GTLB_Enable bit
  954. in the AGPCTRL register
  955. Arguments:
  956. AgpContext - Supplies our AGP3 context
  957. Enable - TRUE, GTLB_Enable is set to ON
  958. FALSE, GTLB_Enable is set to OFF
  959. Return Value:
  960. None
  961. --*/
  962. {
  963. PCI_AGP_CONTROL AgpCtrl;
  964. AgpLibGetExtendedTargetCapability(AgpContext, AgpControl, &AgpCtrl);
  965. AgpCtrl.GTLB_Enable = (Enable) ? ON: OFF;
  966. AgpLibSetExtendedTargetCapability(AgpContext, AgpControl, &AgpCtrl);
  967. }
  968. VOID
  969. AgpFindFreeRun(
  970. IN PVOID AgpContext,
  971. IN PAGP_RANGE AgpRange,
  972. IN ULONG NumberOfPages,
  973. IN ULONG OffsetInPages,
  974. OUT ULONG *FreePages,
  975. OUT ULONG *FreeOffset
  976. )
  977. /*++
  978. Routine Description:
  979. Finds the first contiguous run of free pages in the specified
  980. part of the reserved range
  981. Arguments:
  982. AgpContext - Supplies our AGP3 context
  983. AgpRange - Supplies the AGP range
  984. NumberOfPages - Supplies the size of the region to be searched for free
  985. pages
  986. OffsetInPages - Supplies the start of the region to be searched for free
  987. pages
  988. FreePages - Returns the length of the first contiguous run of free pages
  989. FreeOffset - Returns the start of the first contiguous run of free pages
  990. Return Value:
  991. None
  992. --*/
  993. {
  994. PGART_PTE32 Pte;
  995. ULONG Index;
  996. Pte = (PGART_PTE32)(AgpRange->Context) + OffsetInPages;
  997. //
  998. // Find the first free PTE
  999. //
  1000. for (Index = 0; Index < NumberOfPages; Index++) {
  1001. if (Pte[Index].Hard.Valid == OFF) {
  1002. //
  1003. // Found a free PTE, count the contiguous ones.
  1004. //
  1005. *FreeOffset = Index + OffsetInPages;
  1006. *FreePages = 0;
  1007. while ((Index < NumberOfPages) && (Pte[Index].Hard.Valid == OFF)) {
  1008. *FreePages += 1;
  1009. ++Index;
  1010. }
  1011. return;
  1012. }
  1013. }
  1014. //
  1015. // No free PTEs in the specified range
  1016. //
  1017. *FreePages = 0;
  1018. }
  1019. VOID
  1020. AgpGetMappedPages(
  1021. IN PVOID AgpContext,
  1022. IN PAGP_RANGE AgpRange,
  1023. IN ULONG NumberOfPages,
  1024. IN ULONG OffsetInPages,
  1025. OUT PMDL Mdl
  1026. )
  1027. /*++
  1028. Routine Description:
  1029. Returns the list of physical pages mapped into the specified
  1030. range in the GART
  1031. Arguments:
  1032. AgpContext - Supplies our AGP3 context
  1033. AgpRange - Supplies the AGP range
  1034. NumberOfPages - Supplies the number of pages to be returned
  1035. OffsetInPages - Supplies the start of the region
  1036. Mdl - Returns the list of physical pages mapped in the specified range
  1037. Return Value:
  1038. None
  1039. --*/
  1040. {
  1041. PGART_PTE32 Pte;
  1042. ULONG Index;
  1043. PULONG Pages;
  1044. ASSERT((NumberOfPages * PAGE_SIZE) == Mdl->ByteCount);
  1045. Pages = (PULONG)(Mdl + 1);
  1046. Pte = (PGART_PTE32)(AgpRange->Context) + OffsetInPages;
  1047. for (Index = 0; Index < NumberOfPages; Index++) {
  1048. ASSERT(Pte[Index].Hard.Valid == ON);
  1049. Pages[Index] = Pte[Index].Hard.PageLow;
  1050. }
  1051. }
  1052. NTSTATUS
  1053. AgpSpecialTarget(
  1054. IN PUAGP35_EXTENSION AgpContext,
  1055. IN ULONGLONG DeviceFlags
  1056. )
  1057. /*++
  1058. Routine Description:
  1059. This routine makes "special" tweaks to the AGP chipset
  1060. Arguments:
  1061. AgpContext - Supplies the AGP context
  1062. DeviceFlags - Flags indicating what tweaks to perform
  1063. Return Value:
  1064. STATUS_SUCCESS, or error
  1065. --*/
  1066. {
  1067. NTSTATUS Status;
  1068. Status = STATUS_SUCCESS;
  1069. //
  1070. // Should we change the AGP rate?
  1071. //
  1072. if (DeviceFlags & AGP_FLAG_SPECIAL_RESERVE) {
  1073. Status = Uagp35SetRate(AgpContext,
  1074. (ULONG)((DeviceFlags & AGP_FLAG_SPECIAL_RESERVE)
  1075. >> AGP_FLAG_SET_RATE_SHIFT));
  1076. if (!NT_SUCCESS(Status)) {
  1077. return Status;
  1078. }
  1079. }
  1080. //
  1081. // Add more tweaks here...
  1082. //
  1083. AgpContext->SpecialTarget |= DeviceFlags;
  1084. return Status;
  1085. }
  1086. NTSTATUS
  1087. Uagp35SetRate(
  1088. IN PUAGP35_EXTENSION AgpContext,
  1089. IN ULONG AgpRate
  1090. )
  1091. /*++
  1092. Routine Description:
  1093. This routine sets the AGP rate
  1094. Arguments:
  1095. AgpContext - Supplies our AGP3 context
  1096. AgpRate - Rate to set
  1097. Return Value:
  1098. STATUS_SUCCESS, or error status
  1099. --*/
  1100. {
  1101. NTSTATUS Status;
  1102. ULONG TargetEnable;
  1103. ULONG MasterEnable;
  1104. PCI_AGP_CAPABILITY TargetCap;
  1105. PCI_AGP_CAPABILITY MasterCap;
  1106. BOOLEAN ReverseInit;
  1107. //
  1108. // Read capabilities
  1109. //
  1110. Status = AgpLibGetTargetCapability(AgpContext, &TargetCap);
  1111. if (!NT_SUCCESS(Status)) {
  1112. AGPLOG(AGP_WARNING, ("UAGP35SetRate: AgpLibGetTargetCapability "
  1113. "failed %08lx\n", Status));
  1114. return Status;
  1115. }
  1116. Status = AgpLibGetMasterCapability(AgpContext, &MasterCap);
  1117. if (!NT_SUCCESS(Status)) {
  1118. AGPLOG(AGP_WARNING, ("UAGP35SetRate: AgpLibGetMasterCapability "
  1119. "failed %08lx\n", Status));
  1120. return Status;
  1121. }
  1122. //
  1123. // Map AGP3 mode rates (4X/8X) into AGP2 rate bits, checking one should
  1124. // be good enough, so we'll just ASSERT for busted video cards
  1125. //
  1126. if (TargetCap.AGPStatus.Agp3Mode == ON) {
  1127. ASSERT(MasterCap.AGPStatus.Agp3Mode == ON);
  1128. if ((AgpRate != PCI_AGP_RATE_4X) && (AgpRate != 8)) {
  1129. return STATUS_INVALID_PARAMETER;
  1130. }
  1131. AgpRate >>= 2;
  1132. }
  1133. //
  1134. // Verify the requested rate is supported by both master and target
  1135. //
  1136. if (!(AgpRate & TargetCap.AGPStatus.Rate & MasterCap.AGPStatus.Rate)) {
  1137. return STATUS_INVALID_PARAMETER;
  1138. }
  1139. //
  1140. // Disable AGP while the pull the rug out from underneath
  1141. //
  1142. TargetEnable = TargetCap.AGPCommand.AGPEnable;
  1143. TargetCap.AGPCommand.AGPEnable = 0;
  1144. Status = AgpLibSetTargetCapability(AgpContext, &TargetCap);
  1145. if (!NT_SUCCESS(Status)) {
  1146. AGPLOG(AGP_WARNING,
  1147. ("UAGP35SetRate: AgpLibSetTargetCapability %08lx for "
  1148. "Target failed %08lx\n",
  1149. &TargetCap,
  1150. Status));
  1151. return Status;
  1152. }
  1153. MasterEnable = MasterCap.AGPCommand.AGPEnable;
  1154. MasterCap.AGPCommand.AGPEnable = 0;
  1155. Status = AgpLibSetMasterCapability(AgpContext, &MasterCap);
  1156. if (!NT_SUCCESS(Status)) {
  1157. AGPLOG(AGP_WARNING,
  1158. ("UAGP35SetRate: AgpLibSetMasterCapability %08lx failed "
  1159. "%08lx\n",
  1160. &MasterCap,
  1161. Status));
  1162. return Status;
  1163. }
  1164. MasterCap.AGPCommand.Rate = AgpRate;
  1165. TargetCap.AGPCommand.Rate = AgpRate;
  1166. MasterCap.AGPCommand.AGPEnable = MasterEnable;
  1167. TargetCap.AGPCommand.AGPEnable = TargetEnable;
  1168. //
  1169. // Patch rate for early rev VIA 8X silicon errata
  1170. //
  1171. if ((AgpContext->SpecialTarget & AGP_FLAG_SPECIAL_VIA_AGP2_RATE_PATCH) &&
  1172. (TargetCap.AGPStatus.Agp3Mode == OFF)) {
  1173. switch (AgpRate) {
  1174. case PCI_AGP_RATE_1X:
  1175. case PCI_AGP_RATE_2X:
  1176. MasterCap.AGPCommand.Rate = PCI_AGP_RATE_1X;
  1177. TargetCap.AGPCommand.Rate = PCI_AGP_RATE_4X;
  1178. break;
  1179. case PCI_AGP_RATE_4X:
  1180. MasterCap.AGPCommand.Rate = PCI_AGP_RATE_4X;
  1181. TargetCap.AGPCommand.Rate = PCI_AGP_RATE_1X;
  1182. }
  1183. AGPLOG(AGP_WARNING,
  1184. ("UAGP35SetRate: AGP_FLAG_SPECIAL_VIA_AGP2_RATE_PATCH\n"));
  1185. }
  1186. //
  1187. // Fire up AGP with new rate
  1188. //
  1189. ReverseInit =
  1190. (AgpContext->SpecialTarget & AGP_FLAG_REVERSE_INITIALIZATION) ==
  1191. AGP_FLAG_REVERSE_INITIALIZATION;
  1192. if (ReverseInit) {
  1193. Status = AgpLibSetMasterCapability(AgpContext, &MasterCap);
  1194. if (!NT_SUCCESS(Status)) {
  1195. AGPLOG(AGP_WARNING,
  1196. ("UAGP35SetRate: AgpLibSetMasterCapability %08lx failed "
  1197. "%08lx\n",
  1198. &MasterCap,
  1199. Status));
  1200. return Status;
  1201. }
  1202. }
  1203. Status = AgpLibSetTargetCapability(AgpContext, &TargetCap);
  1204. if (!NT_SUCCESS(Status)) {
  1205. AGPLOG(AGP_WARNING,
  1206. ("UAGP35SetRate: AgpLibSetTargetCapability %08lx for "
  1207. "Target failed %08lx\n",
  1208. &TargetCap,
  1209. Status));
  1210. return Status;
  1211. }
  1212. if (!ReverseInit) {
  1213. Status = AgpLibSetMasterCapability(AgpContext, &MasterCap);
  1214. if (!NT_SUCCESS(Status)) {
  1215. AGPLOG(AGP_WARNING,
  1216. ("UAGP35SetRate: AgpLibSetMasterCapability %08lx failed "
  1217. "%08lx\n",
  1218. &MasterCap,
  1219. Status));
  1220. }
  1221. }
  1222. return Status;
  1223. }