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.

1143 lines
37 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. resource.c
  5. Abstract:
  6. Common routines for handling resource requirements
  7. Author:
  8. John Vert (jvert) 10/25/1997
  9. Revision History:
  10. --*/
  11. #include "agplib.h"
  12. PCM_RESOURCE_LIST
  13. ApSplitResourceList(
  14. IN PCM_RESOURCE_LIST ResourceList,
  15. OUT PCM_RESOURCE_LIST *NewResourceList
  16. );
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGE, AgpFilterResourceRequirements)
  19. #pragma alloc_text(PAGE, AgpFilterResourceRequirementsHost)
  20. #pragma alloc_text(PAGE, Agp3FilterResourceRequirementsBridge)
  21. #pragma alloc_text(PAGE, AgpStartTarget)
  22. #pragma alloc_text(PAGE, AgpStartTargetHost)
  23. #pragma alloc_text(PAGE, Agp3StartTargetBridge)
  24. #pragma alloc_text(PAGE, ApSplitResourceList)
  25. #endif
  26. static BOOLEAN ResourceConflict = FALSE;
  27. NTSTATUS
  28. AgpFilterResourceRequirements(
  29. IN PDEVICE_OBJECT DeviceObject,
  30. IN PIRP Irp,
  31. IN PTARGET_EXTENSION Extension
  32. )
  33. /*++
  34. Routine Dexscription:
  35. One level of indirection through fuinction pointer for non-performance
  36. critical filtering of AGP resources during init
  37. Arguments:
  38. DeviceObject - Supplies the device object
  39. Irp - Supplies the IRP_MN_QUERY_RESOURCE_REQUIREMENTS Irp
  40. Extension - Supplies the device extension
  41. Return Value:
  42. NTASTATUS
  43. --*/
  44. {
  45. PAGED_CODE();
  46. return (Extension->FilterResourceRquirements)(DeviceObject,
  47. Irp,
  48. Extension);
  49. }
  50. NTSTATUS
  51. Agp3FilterResourceRequirementsBridge(
  52. IN PDEVICE_OBJECT DeviceObject,
  53. IN PIRP Irp,
  54. IN PTARGET_EXTENSION Extension
  55. )
  56. /*++
  57. Routine Description:
  58. Completion routine for IRP_MN_QUERY_RESOURCE_REQUIREMENTS, we filter in the
  59. alternate AGP bridge resource requirements
  60. Arguments:
  61. DeviceObject - Supplies the device object
  62. Irp - Supplies the IRP_MN_QUERY_RESOURCE_REQUIREMENTS Irp
  63. Extension - Supplies the device extension
  64. Return Value:
  65. NTSTATUS
  66. --*/
  67. {
  68. ULONG ApertureSize;
  69. NTSTATUS Status;
  70. ULONG AddCount;
  71. PHYSICAL_ADDRESS CurrentBase;
  72. ULONG CurrentSizeInPages;
  73. PIO_RESOURCE_REQUIREMENTS_LIST OldRequirements;
  74. PIO_RESOURCE_REQUIREMENTS_LIST NewRequirements;
  75. ULONG NewSize;
  76. ULONG Alternative;
  77. PIO_RESOURCE_LIST OldResourceList;
  78. PIO_RESOURCE_LIST NewResourceList;
  79. PIO_RESOURCE_DESCRIPTOR Descriptor;
  80. PIO_STACK_LOCATION IrpSp;
  81. PIO_RESOURCE_LIST ApertureRequirements = NULL;
  82. BOOLEAN ResourceFound;
  83. BOOLEAN NukeAlternative;
  84. ULONG Index;
  85. ULONG NewIndex;
  86. PAGED_CODE();
  87. AGPLOG(AGP_NOISE,
  88. ("Agp3QueryResourceRequirementsBridge: IRP %08lx, resource %08lx\n",
  89. Irp,
  90. Irp->IoStatus.Information));
  91. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  92. //
  93. // Create a new resource requirements list with our alternate aperture
  94. // settings tacked onto the bridge's BAR
  95. //
  96. OldRequirements =
  97. IrpSp->Parameters.FilterResourceRequirements.IoResourceRequirementList;
  98. if (OldRequirements == NULL) {
  99. //STATUS_INVALID_DEVICE_REQUEST
  100. // PNP helpfully passes us a NULL pointer instead of an empty
  101. // resource list when the bridge is disabled. In this case we will
  102. // ignore this irp and not add on our requirements since they are
  103. // not going to be used anyway.
  104. //
  105. return(STATUS_SUCCESS);
  106. }
  107. //
  108. // Get the current GART aperture.
  109. //
  110. Status = AgpQueryAperture(GET_AGP_CONTEXT(Extension),
  111. &CurrentBase,
  112. &CurrentSizeInPages,
  113. &ApertureRequirements);
  114. if (!NT_SUCCESS(Status)) {
  115. AGPLOG(AGP_CRITICAL,
  116. ("Agp3QueryResourceRequirementsBridge: AgpQueryAperture %08lx "
  117. "failed %08lx\n",
  118. Extension,
  119. Status));
  120. return(Status);
  121. }
  122. AGPLOG(AGP_NOISE,
  123. ("Agp3QueryResourceRequirementsBridge: aperture at %I64x, length "
  124. "%08lx pages, Requirements %08lx\n",
  125. CurrentBase.QuadPart,
  126. CurrentSizeInPages,
  127. ApertureRequirements));
  128. //
  129. // We will add IO_RESOURCE_DESCRIPTORs to each alternative, after the
  130. // current bridge's BAR
  131. //
  132. //
  133. // Find the AGP bridge BAR's position in the list(s)
  134. //
  135. NukeAlternative = FALSE;
  136. ResourceFound = FALSE;
  137. OldResourceList = &OldRequirements->List[0];
  138. for (Alternative = 0; Alternative < OldRequirements->AlternativeLists;
  139. Alternative++) {
  140. for (Index = 0; Index < OldResourceList->Count; Index++) {
  141. Descriptor = &OldResourceList->Descriptors[Index];
  142. if ((Descriptor->Option == IO_RESOURCE_PREFERRED) &&
  143. (Descriptor->Type == CmResourceTypeMemory)) {
  144. if (Descriptor->u.Memory.MinimumAddress.QuadPart ==
  145. CurrentBase.QuadPart) {
  146. Extension->Agp3BridgeResourceIndex = Index;
  147. ResourceFound = TRUE;
  148. //
  149. // Check if PCI already crufted up an alternative
  150. // descriptor that we should nuke
  151. //
  152. if ((Index + 1) < OldResourceList->Count) {
  153. Descriptor++;
  154. if (Descriptor->Option == IO_RESOURCE_ALTERNATIVE) {
  155. NukeAlternative = TRUE;
  156. }
  157. }
  158. break;
  159. }
  160. }
  161. }
  162. OldResourceList = (PIO_RESOURCE_LIST)(OldResourceList->Descriptors +
  163. OldResourceList->Count);
  164. }
  165. //
  166. // No resource in the list matches our current setting!
  167. //
  168. if (!ResourceFound) {
  169. AGPLOG(AGP_CRITICAL, ("AGP3 bridge misconfigured, please contact "
  170. "system manufacturer for a BIOS upgrade.\n"));
  171. AGP_ASSERT(FALSE);
  172. return STATUS_INVALID_PARAMETER; // This should be interesting!
  173. }
  174. //
  175. // Again, this should never happen, but if it ever did, then we'd have
  176. // to exit now...
  177. //
  178. if (ApertureRequirements == NULL) {
  179. return STATUS_SUCCESS;
  180. }
  181. NewSize = (NukeAlternative) ?
  182. OldRequirements->ListSize -
  183. (OldRequirements->AlternativeLists * sizeof(IO_RESOURCE_DESCRIPTOR)):
  184. OldRequirements->ListSize;
  185. NewSize += sizeof(IO_RESOURCE_DESCRIPTOR) *
  186. (ApertureRequirements->Count * OldRequirements->AlternativeLists);
  187. NewRequirements = ExAllocatePool(PagedPool, NewSize);
  188. if (NewRequirements == NULL) {
  189. ExFreePool(ApertureRequirements);
  190. return(STATUS_INSUFFICIENT_RESOURCES);
  191. }
  192. NewRequirements->ListSize = NewSize;
  193. NewRequirements->InterfaceType = OldRequirements->InterfaceType;
  194. NewRequirements->BusNumber = OldRequirements->BusNumber;
  195. NewRequirements->SlotNumber = OldRequirements->SlotNumber;
  196. NewRequirements->AlternativeLists = OldRequirements->AlternativeLists;
  197. //
  198. // Append our requirement to each alternative resource list.
  199. //
  200. NewResourceList = &NewRequirements->List[0];
  201. OldResourceList = &OldRequirements->List[0];
  202. for (Alternative = 0; Alternative < OldRequirements->AlternativeLists;
  203. Alternative++) {
  204. //
  205. // Copy the old resource list into the new one.
  206. //
  207. NewResourceList->Version = OldResourceList->Version;
  208. NewResourceList->Revision = OldResourceList->Revision;
  209. NewResourceList->Count =
  210. OldResourceList->Count + ApertureRequirements->Count;
  211. if (NukeAlternative) {
  212. NewResourceList->Count--;
  213. }
  214. Index = 0;
  215. NewIndex = 0;
  216. while (Index < OldResourceList->Count) {
  217. NewResourceList->Descriptors[NewIndex] =
  218. OldResourceList->Descriptors[Index];
  219. //
  220. // This is the AGP bridge BAR, tack on alternatives here
  221. //
  222. if (Index == Extension->Agp3BridgeResourceIndex) {
  223. AGP_ASSERT((NewIndex + ApertureRequirements->Count) <
  224. NewResourceList->Count);
  225. RtlCopyMemory(&NewResourceList->Descriptors[NewIndex + 1],
  226. &ApertureRequirements->Descriptors[0],
  227. ApertureRequirements->Count *
  228. sizeof(IO_RESOURCE_DESCRIPTOR));
  229. NewIndex += ApertureRequirements->Count;
  230. if (NukeAlternative) {
  231. Index++;
  232. }
  233. }
  234. Index++;
  235. NewIndex++;
  236. }
  237. //
  238. // Advance to next resource list
  239. //
  240. NewResourceList = (PIO_RESOURCE_LIST)(NewResourceList->Descriptors +
  241. NewResourceList->Count);
  242. OldResourceList = (PIO_RESOURCE_LIST)(OldResourceList->Descriptors +
  243. OldResourceList->Count);
  244. }
  245. AGPLOG(AGP_NOISE,
  246. ("Agp3QueryResourceRequirementsBridge: IRP %p, old resources %p, "
  247. "new resources %p\n",
  248. Irp,
  249. OldRequirements,
  250. NewRequirements));
  251. IrpSp->Parameters.FilterResourceRequirements.IoResourceRequirementList =
  252. NewRequirements;
  253. Irp->IoStatus.Information = (ULONG_PTR)NewRequirements;
  254. ExFreePool(OldRequirements);
  255. ExFreePool(ApertureRequirements);
  256. return STATUS_SUCCESS;
  257. }
  258. NTSTATUS
  259. AgpFilterResourceRequirementsHost(
  260. IN PDEVICE_OBJECT DeviceObject,
  261. IN PIRP Irp,
  262. IN PTARGET_EXTENSION Extension
  263. )
  264. /*++
  265. Routine Description:
  266. Completion routine for IRP_MN_QUERY_RESOURCE_REQUIREMENTS. This adds on the
  267. AGP resource requirements.
  268. Arguments:
  269. DeviceObject - Supplies the device object
  270. Irp - Supplies the IRP_MN_QUERY_RESOURCE_REQUIREMENTS Irp
  271. Extension - Supplies the device extension
  272. Return Value:
  273. NTSTATUS
  274. --*/
  275. {
  276. BOOLEAN SwapDescriptor;
  277. ULONG SwapLength;
  278. ULONG ApertureSize;
  279. NTSTATUS Status;
  280. ULONG AddCount;
  281. PHYSICAL_ADDRESS CurrentBase;
  282. PHYSICAL_ADDRESS MaxAddr;
  283. ULONG CurrentSizeInPages;
  284. PIO_RESOURCE_REQUIREMENTS_LIST OldRequirements;
  285. PIO_RESOURCE_REQUIREMENTS_LIST NewRequirements;
  286. ULONG NewSize;
  287. ULONG Alternative;
  288. PIO_RESOURCE_LIST OldResourceList;
  289. PIO_RESOURCE_LIST NewResourceList;
  290. PIO_RESOURCE_DESCRIPTOR Descriptor;
  291. PIO_STACK_LOCATION IrpSp;
  292. PIO_RESOURCE_LIST ApertureRequirements = NULL;
  293. ULONG i;
  294. PAGED_CODE();
  295. AGPLOG(AGP_NOISE,
  296. ("AgpQueryResourceRequirements - IRP %08lx, resource %08lx\n",
  297. Irp,
  298. Irp->IoStatus.Information));
  299. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  300. //
  301. // Create a new resource requirements list with our current aperture
  302. // settings tacked on the end.
  303. //
  304. OldRequirements = IrpSp->Parameters.FilterResourceRequirements.IoResourceRequirementList;
  305. if (OldRequirements == NULL) {
  306. //STATUS_INVALID_DEVICE_REQUEST
  307. // PNP helpfully passes us a NULL pointer instead of an empty resource list
  308. // when the bridge is disabled. In this case we will ignore this irp and not
  309. // add on our requirements since they are not going to be used anyway.
  310. //
  311. return(STATUS_SUCCESS);
  312. }
  313. //
  314. // Get the current GART aperture.
  315. //
  316. Status = AgpQueryAperture(GET_AGP_CONTEXT(Extension),
  317. &CurrentBase,
  318. &CurrentSizeInPages,
  319. &ApertureRequirements);
  320. if (!NT_SUCCESS(Status)) {
  321. AGPLOG(AGP_CRITICAL,
  322. ("AgpQueryResourceRequirements - AgpQueryAperture %08lx failed %08lx\n",
  323. Extension,
  324. Status));
  325. return(Status);
  326. }
  327. ApertureSize = (CurrentSizeInPages * PAGE_SIZE);
  328. MaxAddr.QuadPart = CurrentBase.QuadPart + ApertureSize - 1;
  329. AGPLOG(AGP_NOISE,
  330. ("AgpQueryResourceRequirements - aperture at %I64x, length %08lx pages, Requirements %08lx\n",
  331. CurrentBase.QuadPart,
  332. CurrentSizeInPages,
  333. ApertureRequirements));
  334. //
  335. // We will add IO_RESOURCE_DESCRIPTORs to each alternative.
  336. //
  337. // The first one is a private data type marked with our signature. This is
  338. // a marker so that we know which descriptors are ours so we can remove
  339. // them later.
  340. //
  341. // The second is the actual descriptor for the current aperture settings.
  342. // This is marked as preferred.
  343. //
  344. // Following this is the requirements returned from AgpQueryAperture. These
  345. // get marked as alternatives.
  346. //
  347. AddCount = 2;
  348. //
  349. // Enumerate the old list looking for any preferred descriptor that
  350. // conflicts with our preferred settings; if we find one, then the BIOS
  351. // is whack, and we will throw out our preferred descriptor, and let PnP
  352. // choose from our alternates
  353. //
  354. ResourceConflict = FALSE;
  355. OldResourceList = &OldRequirements->List[0];
  356. for (Alternative = 0; Alternative < OldRequirements->AlternativeLists;
  357. Alternative++) {
  358. for (i = 0; i < OldResourceList->Count; i++) {
  359. Descriptor = &OldResourceList->Descriptors[i];
  360. if ((Descriptor->Option == IO_RESOURCE_PREFERRED) &&
  361. (Descriptor->Type == CmResourceTypeMemory)) {
  362. if (((Descriptor->u.Memory.MinimumAddress.QuadPart >=
  363. CurrentBase.QuadPart) &&
  364. (Descriptor->u.Memory.MinimumAddress.QuadPart <=
  365. MaxAddr.QuadPart)) ||
  366. ((Descriptor->u.Memory.MaximumAddress.QuadPart >=
  367. CurrentBase.QuadPart) &&
  368. (Descriptor->u.Memory.MaximumAddress.QuadPart <=
  369. MaxAddr.QuadPart)) ||
  370. ((Descriptor->u.Memory.MinimumAddress.QuadPart <
  371. CurrentBase.QuadPart) &&
  372. (Descriptor->u.Memory.MaximumAddress.QuadPart >
  373. MaxAddr.QuadPart))) {
  374. AGPLOG(AGP_CRITICAL,
  375. ("AgpQueryResourceRequirements - Conflicted "
  376. "resource detected: %I64X - %I64X\n",
  377. Descriptor->u.Memory.MinimumAddress.QuadPart,
  378. Descriptor->u.Memory.MaximumAddress.QuadPart));
  379. //
  380. // This preferred descriptor is in conflic with our AGP
  381. // preferred setting
  382. //
  383. #if defined(_IA64_)
  384. AGPLOG(AGP_CRITICAL, ("Please contact system manufacturer "
  385. "for a BIOS upgrade.\n"));
  386. #else // _IA64_
  387. AddCount = 1;
  388. ResourceConflict = TRUE;
  389. #endif // _IA64_
  390. break;
  391. }
  392. }
  393. }
  394. OldResourceList = (PIO_RESOURCE_LIST)(OldResourceList->Descriptors +
  395. OldResourceList->Count);
  396. }
  397. //
  398. //
  399. // For IA64, PnP cannot reassign the aperture base, so we can only use
  400. // the "preferred" descriptor
  401. //
  402. if (ApertureRequirements) {
  403. AddCount += ApertureRequirements->Count;
  404. }
  405. NewSize = OldRequirements->ListSize;
  406. NewSize += sizeof(IO_RESOURCE_DESCRIPTOR) *
  407. (AddCount * OldRequirements->AlternativeLists);
  408. NewRequirements = ExAllocatePool(PagedPool, NewSize);
  409. if (NewRequirements == NULL) {
  410. if (ApertureRequirements) {
  411. ExFreePool(ApertureRequirements);
  412. }
  413. return(STATUS_INSUFFICIENT_RESOURCES);
  414. }
  415. NewRequirements->ListSize = NewSize;
  416. NewRequirements->InterfaceType = OldRequirements->InterfaceType;
  417. NewRequirements->BusNumber = OldRequirements->BusNumber;
  418. NewRequirements->SlotNumber = OldRequirements->SlotNumber;
  419. NewRequirements->AlternativeLists = OldRequirements->AlternativeLists;
  420. //
  421. // Append our requirement to each alternative resource list.
  422. //
  423. NewResourceList = &NewRequirements->List[0];
  424. OldResourceList = &OldRequirements->List[0];
  425. for (Alternative = 0; Alternative < OldRequirements->AlternativeLists; Alternative++) {
  426. //
  427. // Copy the old resource list into the new one.
  428. //
  429. NewResourceList->Version = OldResourceList->Version;
  430. NewResourceList->Revision = OldResourceList->Revision;
  431. NewResourceList->Count = OldResourceList->Count + AddCount;
  432. RtlCopyMemory(&NewResourceList->Descriptors[0],
  433. &OldResourceList->Descriptors[0],
  434. OldResourceList->Count * sizeof(IO_RESOURCE_DESCRIPTOR));
  435. Descriptor = &NewResourceList->Descriptors[OldResourceList->Count];
  436. //
  437. // Append the marker descriptor
  438. //
  439. Descriptor->Option = 0;
  440. Descriptor->Flags = 0;
  441. Descriptor->Type = CmResourceTypeDevicePrivate;
  442. Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
  443. Descriptor->u.DevicePrivate.Data[0] = AgpPrivateResource;
  444. Descriptor->u.DevicePrivate.Data[1] = 1;
  445. ++Descriptor;
  446. //
  447. // Append the new descriptor
  448. //
  449. if (!ResourceConflict) {
  450. Descriptor->Option = IO_RESOURCE_PREFERRED;
  451. Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE |
  452. CM_RESOURCE_MEMORY_PREFETCHABLE;
  453. Descriptor->Type = CmResourceTypeMemory;
  454. Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
  455. Descriptor->u.Memory.Length = CurrentSizeInPages * PAGE_SIZE;
  456. Descriptor->u.Memory.Alignment = CurrentSizeInPages * PAGE_SIZE;
  457. Descriptor->u.Memory.MinimumAddress = CurrentBase;
  458. Descriptor->u.Memory.MaximumAddress = MaxAddr;
  459. ++Descriptor;
  460. }
  461. //
  462. // Append the alternatives
  463. //
  464. if (ApertureRequirements) {
  465. SwapDescriptor = FALSE;
  466. for (i = 0; i < ApertureRequirements->Count; i++) {
  467. //
  468. // Make sure this descriptor makes sense
  469. //
  470. ASSERT(ApertureRequirements->Descriptors[i].Flags ==
  471. (CM_RESOURCE_MEMORY_READ_WRITE |
  472. CM_RESOURCE_MEMORY_PREFETCHABLE));
  473. ASSERT(ApertureRequirements->Descriptors[i].Type ==
  474. CmResourceTypeMemory);
  475. ASSERT(ApertureRequirements->Descriptors[i].ShareDisposition ==
  476. CmResourceShareDeviceExclusive);
  477. *Descriptor = ApertureRequirements->Descriptors[i];
  478. //
  479. // In this case we nuked our preferred descriptor so mark the
  480. // first alternate as preferred
  481. //
  482. if ((i == 0) && ResourceConflict) {
  483. Descriptor->Option = IO_RESOURCE_PREFERRED;
  484. if (Descriptor->u.Memory.Length != ApertureSize) {
  485. SwapLength = Descriptor->u.Memory.Length;
  486. Descriptor->u.Memory.Length = ApertureSize;
  487. Descriptor->u.Memory.Alignment = ApertureSize;
  488. SwapDescriptor = TRUE;
  489. }
  490. } else {
  491. Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
  492. if (SwapDescriptor) {
  493. if (Descriptor->u.Memory.Length == ApertureSize) {
  494. Descriptor->u.Memory.Length = SwapLength;
  495. Descriptor->u.Memory.Alignment = SwapLength;
  496. SwapDescriptor = FALSE;
  497. }
  498. }
  499. }
  500. ++Descriptor;
  501. }
  502. }
  503. //
  504. // Advance to next resource list
  505. //
  506. NewResourceList = (PIO_RESOURCE_LIST)(NewResourceList->Descriptors + NewResourceList->Count);
  507. OldResourceList = (PIO_RESOURCE_LIST)(OldResourceList->Descriptors + OldResourceList->Count);
  508. }
  509. AGPLOG(AGP_NOISE,
  510. ("AgpQueryResourceRequirements - IRP %p, old resources %p, new resources %p\n",
  511. Irp,
  512. OldRequirements,
  513. NewRequirements));
  514. IrpSp->Parameters.FilterResourceRequirements.IoResourceRequirementList = NewRequirements;
  515. Irp->IoStatus.Information = (ULONG_PTR)NewRequirements;
  516. ExFreePool(OldRequirements);
  517. if (ApertureRequirements) {
  518. ExFreePool(ApertureRequirements);
  519. }
  520. return(STATUS_SUCCESS);
  521. }
  522. NTSTATUS
  523. AgpQueryResources(
  524. IN PDEVICE_OBJECT DeviceObject,
  525. IN PIRP Irp,
  526. IN PTARGET_EXTENSION Extension
  527. )
  528. /*++
  529. Routine Description:
  530. Completion routine for IRP_MN_QUERY_RESOURCES. This adds on the
  531. AGP resources
  532. Arguments:
  533. DeviceObject - Supplies the device object
  534. Irp - Supplies the IRP_MN_QUERY_RESOURCES Irp
  535. Extension - Supplies the device extension
  536. Return Value:
  537. NTSTATUS
  538. --*/
  539. {
  540. if (Irp->PendingReturned) {
  541. IoMarkIrpPending(Irp);
  542. }
  543. AGPLOG(AGP_NOISE,
  544. ("AgpQueryResources - IRP %08lx, resource %08lx\n",
  545. Irp,
  546. Irp->IoStatus.Information));
  547. return(STATUS_SUCCESS);
  548. }
  549. NTSTATUS
  550. AgpStartTarget(
  551. IN PIRP Irp,
  552. IN PTARGET_EXTENSION Extension
  553. )
  554. /*++
  555. Routine Description:
  556. One level of indirection through fuinction pointer for non-performance
  557. critical initialization of AGP3 target bridge
  558. Arguments:
  559. Irp - supplies the IRP_MN_START_DEVICE Irp.
  560. Extension - Supplies the device extension.
  561. Return Value:
  562. NTSTATUS
  563. --*/
  564. {
  565. PAGED_CODE();
  566. return (Extension->StartTarget)(Irp, Extension);
  567. }
  568. NTSTATUS
  569. AgpStartTargetHost(
  570. IN PIRP Irp,
  571. IN PTARGET_EXTENSION Extension
  572. )
  573. /*++
  574. Routine Description:
  575. Filters out the AGP-specific resource requirements on a
  576. IRP_MN_START_DEVICE Irp.
  577. Arguments:
  578. Irp - supplies the IRP_MN_START_DEVICE Irp.
  579. Extension - Supplies the device extension.
  580. Return Value:
  581. NTSTATUS
  582. --*/
  583. {
  584. PIO_STACK_LOCATION irpSp;
  585. PCM_RESOURCE_LIST NewResources;
  586. PCM_RESOURCE_LIST NewResourcesTranslated;
  587. PCM_RESOURCE_LIST AgpAllocatedResources;
  588. PCM_RESOURCE_LIST AgpAllocatedResourcesTranslated;
  589. NTSTATUS Status;
  590. PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
  591. PAGED_CODE();
  592. irpSp = IoGetCurrentIrpStackLocation(Irp);
  593. AGPLOG(AGP_NOISE,
  594. ("AgpStartTargetHost: IRP %08lx, resource %08lx\n",
  595. Irp,
  596. Irp->IoStatus.Information));
  597. if (irpSp->Parameters.StartDevice.AllocatedResources != NULL) {
  598. KEVENT event;
  599. //
  600. // Find our private descriptors and split them out into
  601. // our own resource list
  602. //
  603. Extension->Resources = ApSplitResourceList(irpSp->Parameters.StartDevice.AllocatedResources,
  604. &NewResources);
  605. Extension->ResourcesTranslated = ApSplitResourceList(irpSp->Parameters.StartDevice.AllocatedResourcesTranslated,
  606. &NewResourcesTranslated);
  607. //
  608. // Split resources will return two NULL lists when we run low
  609. // memory, so we only need to check one of its return values
  610. //
  611. if ((NewResources == NULL) || (NewResourcesTranslated == NULL)) {
  612. Status = STATUS_INSUFFICIENT_RESOURCES;
  613. } else {
  614. ASSERT(Extension->Resources->Count == 1);
  615. ASSERT(Extension->Resources->List[0].PartialResourceList.Count == 1);
  616. Descriptor = &Extension->Resources->List[0].PartialResourceList.PartialDescriptors[0];
  617. ASSERT(Descriptor->Type == CmResourceTypeMemory);
  618. Extension->GartBase = Descriptor->u.Memory.Start;
  619. Extension->GartLengthInPages = Descriptor->u.Memory.Length / PAGE_SIZE;
  620. //
  621. // Set the new GART aperture
  622. //
  623. Status = AgpSetAperture(GET_AGP_CONTEXT(Extension),
  624. Extension->GartBase,
  625. Extension->GartLengthInPages);
  626. }
  627. ASSERT(NT_SUCCESS(Status));
  628. Irp->IoStatus.Status = Status ;
  629. if (!NT_SUCCESS(Status) ) {
  630. AGPLOG(AGP_CRITICAL,
  631. ("AgpStartTargetHost: AgpSetAperture to %I64X, %08lx "
  632. "failed %08lx\n",
  633. Extension->GartBase.QuadPart,
  634. Extension->GartLengthInPages * PAGE_SIZE,
  635. Status));
  636. Irp->IoStatus.Status = Status;
  637. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  638. if (NewResources != NULL) {
  639. ExFreePool(NewResources);
  640. ExFreePool(Extension->Resources);
  641. Extension->Resources = NULL;
  642. }
  643. if (NewResourcesTranslated != NULL) {
  644. ExFreePool(NewResourcesTranslated);
  645. ExFreePool(Extension->ResourcesTranslated);
  646. Extension->ResourcesTranslated = NULL;
  647. }
  648. return(Status);
  649. }
  650. KeInitializeEvent(&event, NotificationEvent, FALSE);
  651. //
  652. // Set up the new parameters for the PCI driver.
  653. //
  654. irpSp->Parameters.StartDevice.AllocatedResources = NewResources;
  655. irpSp->Parameters.StartDevice.AllocatedResourcesTranslated = NewResourcesTranslated;
  656. IoCopyCurrentIrpStackLocationToNext(Irp);
  657. IoSetCompletionRoutine(Irp,
  658. AgpSetEventCompletion,
  659. &event,
  660. TRUE,
  661. TRUE,
  662. TRUE);
  663. //
  664. // Pass down the driver stack
  665. //
  666. Status = IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp);
  667. //
  668. // If we did things asynchronously then wait on our event
  669. //
  670. if (Status == STATUS_PENDING) {
  671. //
  672. // We do a KernelMode wait so that our stack where the event is
  673. // doesn't get paged out!
  674. //
  675. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  676. Status = Irp->IoStatus.Status;
  677. }
  678. ExFreePool(irpSp->Parameters.StartDevice.AllocatedResources);
  679. ExFreePool(irpSp->Parameters.StartDevice.AllocatedResourcesTranslated);
  680. IoCompleteRequest(Irp, IO_NO_INCREMENT) ;
  681. return Status;
  682. }
  683. //
  684. // The bridge is disabled, we have been passed a NULL pointer
  685. // instead of an empty resource list. There is nothing to do other
  686. // than pass down the irp
  687. //
  688. IoSkipCurrentIrpStackLocation(Irp);
  689. return(IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp));
  690. }
  691. NTSTATUS
  692. Agp3StartTargetBridge(
  693. IN PIRP Irp,
  694. IN PTARGET_EXTENSION Extension
  695. )
  696. /*++
  697. Routine Description:
  698. Filters out the AGP-specific resource requirements on a
  699. IRP_MN_START_DEVICE Irp.
  700. Arguments:
  701. Irp - supplies the IRP_MN_START_DEVICE Irp.
  702. Extension - Supplies the device extension.
  703. Return Value:
  704. NTSTATUS
  705. --*/
  706. {
  707. PIO_STACK_LOCATION irpSp;
  708. PCM_RESOURCE_LIST NewResources;
  709. PCM_RESOURCE_LIST NewResourcesTranslated;
  710. PCM_RESOURCE_LIST AgpAllocatedResources;
  711. PCM_RESOURCE_LIST AgpAllocatedResourcesTranslated;
  712. NTSTATUS Status;
  713. PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
  714. PAGED_CODE();
  715. irpSp = IoGetCurrentIrpStackLocation(Irp);
  716. AGPLOG(AGP_NOISE,
  717. ("Agp3StartTargetBridge: IRP %08lx, resource %08lx\n",
  718. Irp,
  719. Irp->IoStatus.Information));
  720. if (irpSp->Parameters.StartDevice.AllocatedResources != NULL) {
  721. KEVENT event;
  722. ASSERT(irpSp->Parameters.StartDevice.AllocatedResources->Count == 1);
  723. //
  724. // We better have located our aperture resource, or we're
  725. // in trouble
  726. //
  727. if (Extension->Agp3BridgeResourceIndex == JUNK_INDEX) {
  728. Status = STATUS_INVALID_PARAMETER;
  729. } else {
  730. ASSERT(irpSp->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList.Count >= Extension->Agp3BridgeResourceIndex);
  731. Descriptor = &irpSp->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList.PartialDescriptors[Extension->Agp3BridgeResourceIndex];
  732. ASSERT(Descriptor->Type == CmResourceTypeMemory);
  733. Extension->GartBase = Descriptor->u.Memory.Start;
  734. Extension->GartLengthInPages =
  735. Descriptor->u.Memory.Length / PAGE_SIZE;
  736. //
  737. // Set the new GART aperture
  738. //
  739. Status = AgpSetAperture(GET_AGP_CONTEXT(Extension),
  740. Extension->GartBase,
  741. Extension->GartLengthInPages);
  742. }
  743. ASSERT(NT_SUCCESS(Status));
  744. Irp->IoStatus.Status = Status;
  745. if (!NT_SUCCESS(Status) ) {
  746. AGPLOG(AGP_CRITICAL,
  747. ("Agp3StartTargetbridge: AgpSetAperture to %I64X, %08lx "
  748. "failed %08lx\n",
  749. Extension->GartBase.QuadPart,
  750. Extension->GartLengthInPages * PAGE_SIZE,
  751. Status));
  752. Irp->IoStatus.Status = Status;
  753. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  754. return(Status);
  755. }
  756. KeInitializeEvent(&event, NotificationEvent, FALSE);
  757. //
  758. // Set up the new parameters for the PCI driver.
  759. //
  760. IoCopyCurrentIrpStackLocationToNext(Irp);
  761. IoSetCompletionRoutine(Irp,
  762. AgpSetEventCompletion,
  763. &event,
  764. TRUE,
  765. TRUE,
  766. TRUE);
  767. //
  768. // Pass down the driver stack
  769. //
  770. Status = IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp);
  771. //
  772. // If we did things asynchronously then wait on our event
  773. //
  774. if (Status == STATUS_PENDING) {
  775. //
  776. // We do a KernelMode wait so that our stack where the event is
  777. // doesn't get paged out!
  778. //
  779. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  780. Status = Irp->IoStatus.Status;
  781. }
  782. IoCompleteRequest(Irp, IO_NO_INCREMENT) ;
  783. return Status;
  784. }
  785. //
  786. // The bridge is disabled, we have been passed a NULL pointer
  787. // instead of an empty resource list. There is nothing to do other
  788. // than pass down the irp
  789. //
  790. IoSkipCurrentIrpStackLocation(Irp);
  791. return(IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp));
  792. }
  793. PCM_RESOURCE_LIST
  794. ApSplitResourceList(
  795. IN PCM_RESOURCE_LIST ResourceList,
  796. OUT PCM_RESOURCE_LIST *NewResourceList
  797. )
  798. /*++
  799. Routine Description:
  800. Splits out the AGP-specific resources from a resource list.
  801. Arguments:
  802. ResourceList - Supplies the resource list.
  803. NewResourceList - Returns the new resource list with the AGP-specific
  804. resources stripped out.
  805. Return Value:
  806. Pointer to the AGP-specific resource list
  807. --*/
  808. {
  809. ULONG Size;
  810. ULONG FullCount;
  811. ULONG PartialCount;
  812. PCM_FULL_RESOURCE_DESCRIPTOR Full, NewFull, AgpFull;
  813. PCM_PARTIAL_RESOURCE_DESCRIPTOR Partial, NewPartial, AgpPartial;
  814. PCM_RESOURCE_LIST NewList;
  815. PCM_RESOURCE_LIST AgpList;
  816. ULONG NextAgp=0;
  817. PAGED_CODE();
  818. //
  819. // First walk through the source resource list and figure out how big it
  820. // is. The two resulting resource lists must be smaller than this, so we
  821. // will just allocate them to be that size and not worry about it.
  822. //
  823. Size = sizeof(CM_RESOURCE_LIST) - sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
  824. Full = &ResourceList->List[0];
  825. for (FullCount=0; FullCount<ResourceList->Count; FullCount++) {
  826. Size += sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
  827. PartialCount = Full->PartialResourceList.Count;
  828. Size += (PartialCount-1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  829. Full = (PCM_FULL_RESOURCE_DESCRIPTOR)(&Full->PartialResourceList.PartialDescriptors[PartialCount]);
  830. }
  831. //
  832. // Allocate two additional lists
  833. //
  834. NewList = ExAllocatePool(PagedPool, Size);
  835. if (NewList == NULL) {
  836. *NewResourceList = NULL;
  837. return(NULL);
  838. }
  839. AgpList = ExAllocatePool(PagedPool, Size);
  840. if (AgpList == NULL) {
  841. ExFreePool(NewList);
  842. *NewResourceList = NULL;
  843. return(NULL);
  844. }
  845. //
  846. // Initialize both new resource lists to have the same number
  847. // of CM_FULL_RESOURCE_DESCRIPTORs. If any turn out to be empty,
  848. // we will adjust the count.
  849. //
  850. NewList->Count = AgpList->Count = ResourceList->Count;
  851. //
  852. // Walk through each CM_FULL_RESOURCE_DESCRIPTOR, copying as we go.
  853. //
  854. Full = &ResourceList->List[0];
  855. NewFull = &NewList->List[0];
  856. AgpFull = &AgpList->List[0];
  857. for (FullCount = 0;FullCount < ResourceList->Count; FullCount++) {
  858. NewFull->InterfaceType = AgpFull->InterfaceType = Full->InterfaceType;
  859. NewFull->BusNumber = AgpFull->BusNumber = Full->BusNumber;
  860. //
  861. // Initialize the partial resource list header
  862. //
  863. NewFull->PartialResourceList.Version = Full->PartialResourceList.Version;
  864. AgpFull->PartialResourceList.Version = Full->PartialResourceList.Version;
  865. NewFull->PartialResourceList.Revision = Full->PartialResourceList.Revision;
  866. AgpFull->PartialResourceList.Revision = Full->PartialResourceList.Revision;
  867. NewFull->PartialResourceList.Count = AgpFull->PartialResourceList.Count = 0;
  868. NewPartial = &NewFull->PartialResourceList.PartialDescriptors[0];
  869. AgpPartial = &AgpFull->PartialResourceList.PartialDescriptors[0];
  870. for (PartialCount = 0; PartialCount < Full->PartialResourceList.Count; PartialCount++) {
  871. Partial = &Full->PartialResourceList.PartialDescriptors[PartialCount];
  872. if ((Partial->Type == CmResourceTypeDevicePrivate) &&
  873. (Partial->u.DevicePrivate.Data[0] == AgpPrivateResource)) {
  874. //
  875. // Found one of our private marker descriptors
  876. //
  877. // For now, the only kind we should see indicates we skip one descriptor
  878. //
  879. ASSERT(NextAgp == 0);
  880. ASSERT(Partial->u.DevicePrivate.Data[1] == 1);
  881. NextAgp = Partial->u.DevicePrivate.Data[1];
  882. ASSERT(PartialCount+NextAgp < Full->PartialResourceList.Count);
  883. } else {
  884. //
  885. // if NextAgp is set, this descriptor goes in the AGP-specific list.
  886. // Otherwise, it goes in the new list.
  887. //
  888. if (NextAgp > 0) {
  889. --NextAgp;
  890. *AgpPartial++ = *Partial;
  891. ++AgpFull->PartialResourceList.Count;
  892. } else {
  893. *NewPartial++ = *Partial;
  894. ++NewFull->PartialResourceList.Count;
  895. }
  896. }
  897. }
  898. //
  899. // Finished this CM_PARTIAL_RESOURCE_LIST, advance to the next CM_FULL_RESOURCE_DESCRIPTOR
  900. //
  901. if (NewFull->PartialResourceList.Count == 0) {
  902. //
  903. // we can just reuse this partial resource descriptor as it is empty
  904. //
  905. --NewList->Count;
  906. } else {
  907. NewFull = (PCM_FULL_RESOURCE_DESCRIPTOR)NewPartial;
  908. }
  909. if (AgpFull->PartialResourceList.Count == 0) {
  910. //
  911. // we can just reuse this partial resource descriptor as it is empty
  912. //
  913. --AgpList->Count;
  914. } else {
  915. AgpFull = (PCM_FULL_RESOURCE_DESCRIPTOR)NewPartial;
  916. }
  917. }
  918. *NewResourceList = NewList;
  919. return(AgpList);
  920. }