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.

2780 lines
72 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. ar_memio.c
  5. Abstract:
  6. This module implements the PCI Memory and IO resource Arbiters.
  7. Most functionality for these two arbiters is common and distinguished
  8. by the "context".
  9. Author:
  10. Andrew Thornton (andrewth) 21-May-1997
  11. Revision History:
  12. --*/
  13. #include "pcip.h"
  14. #define BUGFEST_HACKS
  15. #define ARMEMIO_VERSION 0
  16. //
  17. // Flags for WorkSpace
  18. //
  19. #define PORT_ARBITER_PREPROCESSED 0x00000001
  20. #define PORT_ARBITER_IMPROVISED_DECODE 0x00000002
  21. #define PORT_ARBITER_ISA_BIT_SET 0x00000004
  22. #define PORT_ARBITER_BRIDGE_WINDOW 0x00000008
  23. //
  24. // ALLOCATE_ALIASES - this turns on the allocation of 10 & 12 bit decoded
  25. // aliases.
  26. //
  27. #define ALLOCATE_ALIASES 1
  28. #define IGNORE_PREFETCH_FOR_LEGACY_REPORTED 1
  29. #define PASSIVE_DECODE_SUPPORTED 1
  30. #define PREFETCHABLE_SUPPORTED 1
  31. #define ISA_BIT_SUPPORTED 1
  32. //
  33. // Flags for range attributes
  34. //
  35. #define MEMORY_RANGE_ROM 0x10
  36. //
  37. // Constants
  38. //
  39. #define PCI_BRIDGE_WINDOW_GRANULARITY 0x1000
  40. #define PCI_BRIDGE_ISA_BIT_STRIDE 0x400
  41. #define PCI_BRIDGE_ISA_BIT_WIDTH 0x100
  42. #define PCI_BRIDGE_ISA_BIT_MAX 0xFFFF
  43. //
  44. // Static data
  45. //
  46. ARBITER_ORDERING PciBridgeOrderings[] = {
  47. { 0x10000, MAXULONGLONG },
  48. { 0, 0xFFFF }
  49. };
  50. ARBITER_ORDERING_LIST PciBridgeOrderingList = {
  51. sizeof(PciBridgeOrderings) / sizeof (ARBITER_ORDERING),
  52. sizeof(PciBridgeOrderings) / sizeof (ARBITER_ORDERING),
  53. PciBridgeOrderings
  54. };
  55. //
  56. // Prototypes for routines exposed only thru the "interface"
  57. // mechanism.
  58. //
  59. NTSTATUS
  60. ario_Constructor(
  61. PVOID DeviceExtension,
  62. PVOID PciInterface,
  63. PVOID InterfaceSpecificData,
  64. USHORT Version,
  65. USHORT Size,
  66. PINTERFACE InterfaceReturn
  67. );
  68. NTSTATUS
  69. ario_Initializer(
  70. IN PPCI_ARBITER_INSTANCE Instance
  71. );
  72. NTSTATUS
  73. armem_Constructor(
  74. PVOID DeviceExtension,
  75. PVOID PciInterface,
  76. PVOID InterfaceSpecificData,
  77. USHORT Version,
  78. USHORT Size,
  79. PINTERFACE InterfaceReturn
  80. );
  81. NTSTATUS
  82. armem_Initializer(
  83. IN PPCI_ARBITER_INSTANCE Instance
  84. );
  85. PCI_INTERFACE ArbiterInterfaceMemory = {
  86. &GUID_ARBITER_INTERFACE_STANDARD, // InterfaceType
  87. sizeof(ARBITER_INTERFACE), // MinSize
  88. ARMEMIO_VERSION, // MinVersion
  89. ARMEMIO_VERSION, // MaxVersion
  90. PCIIF_FDO, // Flags
  91. 0, // ReferenceCount
  92. PciArb_Memory, // Signature
  93. armem_Constructor, // Constructor
  94. armem_Initializer // Instance Initializer
  95. };
  96. PCI_INTERFACE ArbiterInterfaceIo = {
  97. &GUID_ARBITER_INTERFACE_STANDARD, // InterfaceType
  98. sizeof(ARBITER_INTERFACE), // MinSize
  99. ARMEMIO_VERSION, // MinVersion
  100. ARMEMIO_VERSION, // MaxVersion
  101. PCIIF_FDO, // Flags
  102. 0, // ReferenceCount
  103. PciArb_Io, // Signature
  104. ario_Constructor, // Constructor
  105. ario_Initializer // Instance Initializer
  106. };
  107. //
  108. // Arbiter helper functions.
  109. //
  110. NTSTATUS
  111. armemio_UnpackRequirement(
  112. IN PIO_RESOURCE_DESCRIPTOR Descriptor,
  113. OUT PULONGLONG Minimum,
  114. OUT PULONGLONG Maximum,
  115. OUT PULONG Length,
  116. OUT PULONG Alignment
  117. );
  118. NTSTATUS
  119. armemio_PackResource(
  120. IN PIO_RESOURCE_DESCRIPTOR Requirement,
  121. IN ULONGLONG Start,
  122. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
  123. );
  124. NTSTATUS
  125. armemio_UnpackResource(
  126. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
  127. OUT PULONGLONG Start,
  128. OUT PULONG Length
  129. );
  130. NTSTATUS
  131. armemio_ScoreRequirement(
  132. IN PIO_RESOURCE_DESCRIPTOR Descriptor
  133. );
  134. VOID
  135. ario_BacktrackAllocation(
  136. IN PARBITER_INSTANCE Arbiter,
  137. IN PARBITER_ALLOCATION_STATE State
  138. );
  139. BOOLEAN
  140. ario_FindSuitableRange(
  141. PARBITER_INSTANCE Arbiter,
  142. PARBITER_ALLOCATION_STATE State
  143. );
  144. BOOLEAN
  145. ario_GetNextAlias(
  146. ULONG IoDescriptorFlags,
  147. ULONGLONG LastAlias,
  148. PULONGLONG NextAlias
  149. );
  150. BOOLEAN
  151. ario_IsAliasedRangeAvailable(
  152. PARBITER_INSTANCE Arbiter,
  153. PARBITER_ALLOCATION_STATE State
  154. );
  155. VOID
  156. ario_AddAllocation(
  157. IN PARBITER_INSTANCE Arbiter,
  158. IN PARBITER_ALLOCATION_STATE State
  159. );
  160. BOOLEAN
  161. ario_OverrideConflict(
  162. IN PARBITER_INSTANCE Arbiter,
  163. IN PARBITER_ALLOCATION_STATE State
  164. );
  165. NTSTATUS
  166. ario_PreprocessEntry(
  167. IN PARBITER_INSTANCE Arbiter,
  168. IN PARBITER_ALLOCATION_STATE State
  169. );
  170. NTSTATUS
  171. armem_StartArbiter(
  172. IN PARBITER_INSTANCE Arbiter,
  173. IN PCM_RESOURCE_LIST StartResources
  174. );
  175. NTSTATUS
  176. armem_PreprocessEntry(
  177. IN PARBITER_INSTANCE Arbiter,
  178. IN PARBITER_ALLOCATION_STATE State
  179. );
  180. BOOLEAN
  181. armem_GetNextAllocationRange(
  182. IN PARBITER_INSTANCE Arbiter,
  183. IN PARBITER_ALLOCATION_STATE State
  184. );
  185. BOOLEAN
  186. ario_GetNextAllocationRange(
  187. IN PARBITER_INSTANCE Arbiter,
  188. IN PARBITER_ALLOCATION_STATE State
  189. );
  190. NTSTATUS
  191. ario_StartArbiter(
  192. IN PARBITER_INSTANCE Arbiter,
  193. IN PCM_RESOURCE_LIST StartResources
  194. );
  195. VOID
  196. ario_AddOrBacktrackAllocation(
  197. IN PARBITER_INSTANCE Arbiter,
  198. IN PARBITER_ALLOCATION_STATE State,
  199. IN PARBITER_BACKTRACK_ALLOCATION Callback
  200. );
  201. BOOLEAN
  202. armem_FindSuitableRange(
  203. PARBITER_INSTANCE Arbiter,
  204. PARBITER_ALLOCATION_STATE State
  205. );
  206. #ifdef ALLOC_PRAGMA
  207. #pragma alloc_text(PAGE, ario_Constructor)
  208. #pragma alloc_text(PAGE, armem_Constructor)
  209. #pragma alloc_text(PAGE, ario_Initializer)
  210. #pragma alloc_text(PAGE, armem_Initializer)
  211. #pragma alloc_text(PAGE, armemio_UnpackRequirement)
  212. #pragma alloc_text(PAGE, armemio_PackResource)
  213. #pragma alloc_text(PAGE, armemio_UnpackResource)
  214. #pragma alloc_text(PAGE, armemio_ScoreRequirement)
  215. #pragma alloc_text(PAGE, ario_OverrideConflict)
  216. #pragma alloc_text(PAGE, ario_BacktrackAllocation)
  217. #pragma alloc_text(PAGE, ario_GetNextAlias)
  218. #pragma alloc_text(PAGE, ario_FindSuitableRange)
  219. #pragma alloc_text(PAGE, ario_GetNextAlias)
  220. #pragma alloc_text(PAGE, ario_IsAliasedRangeAvailable)
  221. #pragma alloc_text(PAGE, ario_AddAllocation)
  222. #pragma alloc_text(PAGE, ario_PreprocessEntry)
  223. #pragma alloc_text(PAGE, armem_StartArbiter)
  224. #pragma alloc_text(PAGE, armem_PreprocessEntry)
  225. #pragma alloc_text(PAGE, armem_GetNextAllocationRange)
  226. #pragma alloc_text(PAGE, ario_AddOrBacktrackAllocation)
  227. #pragma alloc_text(PAGE, armem_FindSuitableRange)
  228. #endif
  229. //
  230. // Prefetchable memory support.
  231. //
  232. // Prefetchable memory is device memory that can be treated like normal memory
  233. // in that reads have no side effects and we can combine writes. The
  234. // CM_RESOURCE_MEMORY_PREFETCHABLE flag means that the device would *like*
  235. // prefetchable memory but normal memory is just fine as well.
  236. //
  237. NTSTATUS
  238. ario_Constructor(
  239. PVOID DeviceExtension,
  240. PVOID PciInterface,
  241. PVOID InterfaceSpecificData,
  242. USHORT Version,
  243. USHORT Size,
  244. PINTERFACE InterfaceReturn
  245. )
  246. /*++
  247. Routine Description:
  248. Check the InterfaceSpecificData to see if this is the correct
  249. arbiter (we already know the required interface is an arbiter
  250. from the GUID) and if so, allocate (and reference) a context
  251. for this interface.
  252. Arguments:
  253. PciInterface Pointer to the PciInterface record for this
  254. interface type.
  255. InterfaceSpecificData
  256. A ULONG containing the resource type for which
  257. arbitration is required.
  258. InterfaceReturn
  259. Return Value:
  260. TRUE is this device is not known to cause problems, FALSE
  261. if the device should be skipped altogether.
  262. --*/
  263. {
  264. PARBITER_INTERFACE arbiterInterface;
  265. NTSTATUS status;
  266. PAGED_CODE();
  267. //
  268. // This arbiter handles I/O ports, is that what they want?
  269. //
  270. if ((ULONG_PTR)InterfaceSpecificData != CmResourceTypePort) {
  271. //
  272. // No, it's not us then.
  273. //
  274. return STATUS_INVALID_PARAMETER_5;
  275. }
  276. //
  277. // Have already verified that the InterfaceReturn variable
  278. // points to an area in memory large enough to contain an
  279. // ARBITER_INTERFACE. Fill it in for the caller.
  280. //
  281. arbiterInterface = (PARBITER_INTERFACE)InterfaceReturn;
  282. arbiterInterface->Size = sizeof(ARBITER_INTERFACE);
  283. arbiterInterface->Version = ARMEMIO_VERSION;
  284. arbiterInterface->InterfaceReference = PciReferenceArbiter;
  285. arbiterInterface->InterfaceDereference = PciDereferenceArbiter;
  286. arbiterInterface->ArbiterHandler = ArbArbiterHandler;
  287. arbiterInterface->Flags = 0;
  288. status = PciArbiterInitializeInterface(DeviceExtension,
  289. PciArb_Io,
  290. arbiterInterface);
  291. return status;
  292. }
  293. NTSTATUS
  294. armem_Constructor(
  295. PVOID DeviceExtension,
  296. PVOID PciInterface,
  297. PVOID InterfaceSpecificData,
  298. USHORT Version,
  299. USHORT Size,
  300. PINTERFACE InterfaceReturn
  301. )
  302. /*++
  303. Routine Description:
  304. Check the InterfaceSpecificData to see if this is the correct
  305. arbiter (we already know the required interface is an arbiter
  306. from the GUID) and if so, allocate (and reference) a context
  307. for this interface.
  308. Arguments:
  309. PciInterface Pointer to the PciInterface record for this
  310. interface type.
  311. InterfaceSpecificData
  312. A ULONG containing the resource type for which
  313. arbitration is required.
  314. InterfaceReturn
  315. Return Value:
  316. TRUE is this device is not known to cause problems, FALSE
  317. if the device should be skipped altogether.
  318. --*/
  319. {
  320. PARBITER_INTERFACE arbiterInterface;
  321. NTSTATUS status;
  322. PAGED_CODE();
  323. //
  324. // This arbiter handles memory, is that what they want?
  325. //
  326. if ((ULONG_PTR)InterfaceSpecificData != CmResourceTypeMemory) {
  327. //
  328. // No, it's not us then.
  329. //
  330. return STATUS_INVALID_PARAMETER_5;
  331. }
  332. //
  333. // Have already verified that the InterfaceReturn variable
  334. // points to an area in memory large enough to contain an
  335. // ARBITER_INTERFACE. Fill it in for the caller.
  336. //
  337. arbiterInterface = (PARBITER_INTERFACE)InterfaceReturn;
  338. arbiterInterface->Size = sizeof(ARBITER_INTERFACE);
  339. arbiterInterface->Version = ARMEMIO_VERSION;
  340. arbiterInterface->InterfaceReference = PciReferenceArbiter;
  341. arbiterInterface->InterfaceDereference = PciDereferenceArbiter;
  342. arbiterInterface->ArbiterHandler = ArbArbiterHandler;
  343. arbiterInterface->Flags = 0;
  344. status = PciArbiterInitializeInterface(DeviceExtension,
  345. PciArb_Memory,
  346. arbiterInterface);
  347. return status;
  348. }
  349. NTSTATUS
  350. armem_Initializer(
  351. IN PPCI_ARBITER_INSTANCE Instance
  352. )
  353. /*++
  354. Routine Description:
  355. This routine is called once per instantiation of an arbiter.
  356. Performs initialization of this instantiation's context.
  357. Arguments:
  358. Instance Pointer to the arbiter context.
  359. Return Value:
  360. Returns the status of this operation.
  361. --*/
  362. {
  363. NTSTATUS status;
  364. RtlZeroMemory(&Instance->CommonInstance, sizeof(ARBITER_INSTANCE));
  365. PAGED_CODE();
  366. //
  367. // Set the Action Handler entry points.
  368. //
  369. Instance->CommonInstance.UnpackRequirement = armemio_UnpackRequirement;
  370. Instance->CommonInstance.PackResource = armemio_PackResource;
  371. Instance->CommonInstance.UnpackResource = armemio_UnpackResource;
  372. Instance->CommonInstance.ScoreRequirement = armemio_ScoreRequirement;
  373. Instance->CommonInstance.FindSuitableRange = armem_FindSuitableRange;
  374. #if PREFETCHABLE_SUPPORTED
  375. Instance->CommonInstance.PreprocessEntry = armem_PreprocessEntry;
  376. Instance->CommonInstance.StartArbiter = armem_StartArbiter;
  377. Instance->CommonInstance.GetNextAllocationRange
  378. = armem_GetNextAllocationRange;
  379. //
  380. // NTRAID #54671 - 2000/03/31 - andrewth
  381. // When reference counting is working we need to release this
  382. // extension when we dereference the arbiter to 0
  383. //
  384. //
  385. // Allocate and zero the arbiter extension, it is initialized in
  386. // armem_StartArbiter
  387. //
  388. Instance->CommonInstance.Extension
  389. = ExAllocatePool(PagedPool | POOL_COLD_ALLOCATION, sizeof(ARBITER_MEMORY_EXTENSION));
  390. if (!Instance->CommonInstance.Extension) {
  391. return STATUS_INSUFFICIENT_RESOURCES;
  392. }
  393. RtlZeroMemory(Instance->CommonInstance.Extension,
  394. sizeof(ARBITER_MEMORY_EXTENSION)
  395. );
  396. #endif // PREFETCHABLE_SUPPORTED
  397. //
  398. // Initialize the rest of the common instance
  399. //
  400. return ArbInitializeArbiterInstance(&Instance->CommonInstance,
  401. Instance->BusFdoExtension->FunctionalDeviceObject,
  402. CmResourceTypeMemory,
  403. Instance->InstanceName,
  404. L"Pci",
  405. NULL
  406. );
  407. }
  408. NTSTATUS
  409. ario_Initializer(
  410. IN PPCI_ARBITER_INSTANCE Instance
  411. )
  412. /*++
  413. Routine Description:
  414. This routine is called once per instantiation of an arbiter.
  415. Performs initialization of this instantiation's context.
  416. Arguments:
  417. Instance Pointer to the arbiter context.
  418. Return Value:
  419. Returns the status of this operation.
  420. --*/
  421. {
  422. PAGED_CODE();
  423. ASSERT(!(Instance->BusFdoExtension->BrokenVideoHackApplied));
  424. RtlZeroMemory(&Instance->CommonInstance, sizeof(ARBITER_INSTANCE));
  425. //
  426. // Set the Action Handler entry points.
  427. //
  428. #if ALLOCATE_ALIASES
  429. Instance->CommonInstance.PreprocessEntry = ario_PreprocessEntry;
  430. Instance->CommonInstance.FindSuitableRange = ario_FindSuitableRange;
  431. Instance->CommonInstance.AddAllocation = ario_AddAllocation;
  432. Instance->CommonInstance.BacktrackAllocation = ario_BacktrackAllocation;
  433. #endif
  434. #if PASSIVE_DECODE_SUPPORTED
  435. Instance->CommonInstance.OverrideConflict = ario_OverrideConflict;
  436. #endif
  437. #if ISA_BIT_SUPPORTED
  438. Instance->CommonInstance.GetNextAllocationRange = ario_GetNextAllocationRange;
  439. Instance->CommonInstance.StartArbiter = ario_StartArbiter;
  440. #endif
  441. Instance->CommonInstance.UnpackRequirement = armemio_UnpackRequirement;
  442. Instance->CommonInstance.PackResource = armemio_PackResource;
  443. Instance->CommonInstance.UnpackResource = armemio_UnpackResource;
  444. Instance->CommonInstance.ScoreRequirement = armemio_ScoreRequirement;
  445. //
  446. // Initialize the rest of the common instance
  447. //
  448. return ArbInitializeArbiterInstance(&Instance->CommonInstance,
  449. Instance->BusFdoExtension->FunctionalDeviceObject,
  450. CmResourceTypePort,
  451. Instance->InstanceName,
  452. L"Pci",
  453. NULL
  454. );
  455. }
  456. NTSTATUS
  457. armemio_UnpackRequirement(
  458. IN PIO_RESOURCE_DESCRIPTOR Descriptor,
  459. OUT PULONGLONG Minimum,
  460. OUT PULONGLONG Maximum,
  461. OUT PULONG Length,
  462. OUT PULONG Alignment
  463. )
  464. /*++
  465. Routine Description:
  466. This routine unpacks an resource requirement descriptor.
  467. Arguments:
  468. Descriptor - The descriptor describing the requirement to unpack.
  469. Minimum - Pointer to where the minimum acceptable start value should be
  470. unpacked to.
  471. Maximum - Pointer to where the maximum acceptable end value should be
  472. unpacked to.
  473. Length - Pointer to where the required length should be unpacked to.
  474. Minimum - Pointer to where the required alignment should be unpacked to.
  475. Return Value:
  476. Returns the status of this operation.
  477. --*/
  478. {
  479. NTSTATUS status = STATUS_SUCCESS;
  480. PAGED_CODE();
  481. ASSERT(Descriptor);
  482. ASSERT((Descriptor->Type == CmResourceTypePort) ||
  483. (Descriptor->Type == CmResourceTypeMemory));
  484. *Minimum = (ULONGLONG)Descriptor->u.Generic.MinimumAddress.QuadPart;
  485. *Maximum = (ULONGLONG)Descriptor->u.Generic.MaximumAddress.QuadPart;
  486. *Length = Descriptor->u.Generic.Length;
  487. *Alignment = Descriptor->u.Generic.Alignment;
  488. //
  489. // Fix the broken hardware that reports 0 alignment
  490. //
  491. if (*Alignment == 0) {
  492. *Alignment = 1;
  493. }
  494. //
  495. // Fix broken INF's that report they support 24bit memory > 0xFFFFFF
  496. //
  497. if (Descriptor->Type == CmResourceTypeMemory
  498. && Descriptor->Flags & CM_RESOURCE_MEMORY_24
  499. && Descriptor->u.Memory.MaximumAddress.QuadPart > 0xFFFFFF) {
  500. if (Descriptor->u.Memory.MinimumAddress.QuadPart > 0xFFFFFF) {
  501. PciDebugPrintf(0, "24 bit decode specified but both min and max are greater than 0xFFFFFF, most probably due to broken INF!\n");
  502. ASSERT(Descriptor->u.Memory.MinimumAddress.QuadPart <= 0xFFFFFF);
  503. status = STATUS_UNSUCCESSFUL;
  504. } else {
  505. *Maximum = 0xFFFFFF;
  506. }
  507. }
  508. return status;
  509. }
  510. NTSTATUS
  511. armemio_PackResource(
  512. IN PIO_RESOURCE_DESCRIPTOR Requirement,
  513. IN ULONGLONG Start,
  514. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
  515. )
  516. /*++
  517. Routine Description:
  518. This routine packs an resource descriptor.
  519. Arguments:
  520. Requirement - The requirement from which this resource was chosen.
  521. Start - The start value of the resource.
  522. Descriptor - Pointer to the descriptor to pack into.
  523. Return Value:
  524. Returns the status of this operation.
  525. --*/
  526. {
  527. PAGED_CODE();
  528. ASSERT(Descriptor);
  529. ASSERT(Requirement);
  530. ASSERT((Requirement->Type == CmResourceTypePort) ||
  531. (Requirement->Type == CmResourceTypeMemory));
  532. Descriptor->Type = Requirement->Type;
  533. Descriptor->Flags = Requirement->Flags;
  534. Descriptor->ShareDisposition = Requirement->ShareDisposition;
  535. Descriptor->u.Generic.Start.QuadPart = Start;
  536. Descriptor->u.Generic.Length = Requirement->u.Generic.Length;
  537. return STATUS_SUCCESS;
  538. }
  539. NTSTATUS
  540. armemio_UnpackResource(
  541. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
  542. OUT PULONGLONG Start,
  543. OUT PULONG Length
  544. )
  545. /*++
  546. Routine Description:
  547. This routine unpacks an resource descriptor.
  548. Arguments:
  549. Descriptor - The descriptor describing the resource to unpack.
  550. Start - Pointer to where the start value should be unpacked to.
  551. End - Pointer to where the end value should be unpacked to.
  552. Return Value:
  553. Returns the status of this operation.
  554. --*/
  555. {
  556. PAGED_CODE();
  557. ASSERT(Descriptor);
  558. ASSERT(Start);
  559. ASSERT(Length);
  560. ASSERT((Descriptor->Type == CmResourceTypePort) ||
  561. (Descriptor->Type == CmResourceTypeMemory));
  562. *Start = Descriptor->u.Generic.Start.QuadPart;
  563. *Length= Descriptor->u.Generic.Length;
  564. return STATUS_SUCCESS;
  565. }
  566. LONG
  567. armemio_ScoreRequirement(
  568. IN PIO_RESOURCE_DESCRIPTOR Descriptor
  569. )
  570. /*++
  571. Routine Description:
  572. This routine scores a requirement based on how flexible it is. The least
  573. flexible devices are scored the least and so when the arbitration list is
  574. sorted we try to allocate their resources first.
  575. Arguments:
  576. Descriptor - The descriptor describing the requirement to score.
  577. Return Value:
  578. The score.
  579. --*/
  580. {
  581. LONG score;
  582. ULONGLONG start, end;
  583. ULONGLONG bigscore;
  584. ULONG alignment;
  585. PAGED_CODE();
  586. ASSERT(Descriptor);
  587. ASSERT((Descriptor->Type == CmResourceTypePort) ||
  588. (Descriptor->Type == CmResourceTypeMemory));
  589. alignment = Descriptor->u.Generic.Alignment;
  590. //
  591. // Fix the broken hardware that reports 0 alignment
  592. //
  593. if (alignment == 0) {
  594. //
  595. // Set this to 1 here, because we arbitrate ISA
  596. // devices in the context of PCI. If you don't understand
  597. // you don't want to. Trust me. (hint: subtractive decode)
  598. //
  599. // Any PCI device that has alignment 0 will also
  600. // have Length 0, which is horribly wrong to begin with.
  601. // and we deal with it elsewhere.
  602. //
  603. alignment = 1;
  604. }
  605. start = ALIGN_ADDRESS_UP(
  606. Descriptor->u.Generic.MinimumAddress.QuadPart,
  607. alignment
  608. );
  609. end = Descriptor->u.Generic.MaximumAddress.QuadPart;
  610. //
  611. // The score is the number of possible allocations that could be made
  612. // given the alignment and length constraints
  613. //
  614. bigscore = (((end - Descriptor->u.Generic.Length + 1) - start)
  615. / alignment) + 1;
  616. //
  617. // Note, the scores for each possibility are added together. To
  618. // avoid overflowing the total, we need to limit the range returned.
  619. //
  620. // Make it a sort of logarithmic score. Find the highest byte
  621. // set, weight it (add 0x100) and use the log (I said "sort of").
  622. //
  623. // This puts the result in the range 0xff80 down to 0x0100.
  624. //
  625. for (score = sizeof(bigscore) - 1; score >= 0; score--) {
  626. UCHAR v = *(((PUCHAR)&bigscore) + score);
  627. if (v != 0) {
  628. score = (v + 0x100) << score;
  629. break;
  630. }
  631. }
  632. //
  633. // The resulting TOTAL from scoring all the alternatives is used
  634. // to sort the list. The highest total is considered the easiest
  635. // to place,.... which is probably true,... What if we got some-
  636. // thing like a single fit preferred setting followed by a fits
  637. // anywhere setting? We don't want that to score higher than
  638. // another device which only specified the fit anywhere setting,
  639. // the preferred setting is harder to achieve.
  640. //
  641. // And, are two alternatives, each half as good an a 'fit anywhere'
  642. // as good as the 'fit anywhere'. Not really.
  643. //
  644. // So, we weight the result even further depending on what options
  645. // are set in this resource.
  646. //
  647. if (Descriptor->Option &
  648. (IO_RESOURCE_PREFERRED | IO_RESOURCE_ALTERNATIVE)) {
  649. score -= 0x100;
  650. }
  651. ARB_PRINT(
  652. 3,
  653. (" %s resource %08x(0x%I64x-0x%I64x) => %i\n",
  654. Descriptor->Type == CmResourceTypeMemory ? "Memory" : "Io",
  655. Descriptor,
  656. Descriptor->u.Generic.MinimumAddress.QuadPart,
  657. end,
  658. score
  659. ));
  660. return score;
  661. }
  662. VOID
  663. ario_BacktrackAllocation(
  664. IN PARBITER_INSTANCE Arbiter,
  665. IN PARBITER_ALLOCATION_STATE State
  666. )
  667. /*++
  668. Routine Description:
  669. This routine is called from AllocateEntry if the possible solution
  670. (State->Start - State->End) does not allow us to allocate resources to
  671. the rest of the devices being considered. It deletes the ranges that were
  672. added to Arbiter->PossibleAllocation by AddAllocation including those
  673. associated with ISA aliases.
  674. Arguments:
  675. Arbiter - The instance data of the arbiter who was called.
  676. State - The state of the current arbitration.
  677. Return Value:
  678. None.
  679. --*/
  680. {
  681. PAGED_CODE();
  682. ario_AddOrBacktrackAllocation(Arbiter,
  683. State,
  684. ArbBacktrackAllocation
  685. );
  686. }
  687. VOID
  688. ario_AddOrBacktrackAllocation(
  689. IN PARBITER_INSTANCE Arbiter,
  690. IN PARBITER_ALLOCATION_STATE State,
  691. IN PARBITER_BACKTRACK_ALLOCATION Callback
  692. )
  693. /*++
  694. Routine Description:
  695. This relies on the fact that PARBITER_BACKTRACK_ALLOCATION and
  696. PARBITER_ADD_ALLOCATION are of the same type
  697. Arguments:
  698. Arbiter - The instance data of the arbiter who was called.
  699. State - The state of the current arbitration.
  700. Backtrack - TRUE for backtrack, false for ADD
  701. Return Value:
  702. None.
  703. --*/
  704. {
  705. NTSTATUS status;
  706. ARBITER_ALLOCATION_STATE localState;
  707. PAGED_CODE();
  708. ASSERT(Arbiter);
  709. ASSERT(State);
  710. //
  711. // We are going to mess with the state so make our own local copy
  712. //
  713. RtlCopyMemory(&localState, State, sizeof(ARBITER_ALLOCATION_STATE));
  714. #if ISA_BIT_SUPPORTED
  715. //
  716. // Check if this is a window for a bridge with the ISA bit set that is
  717. // in 16 bit IO space. If so we need to do some special processing
  718. //
  719. if (State->WorkSpace & PORT_ARBITER_BRIDGE_WINDOW
  720. && State->WorkSpace & PORT_ARBITER_ISA_BIT_SET
  721. && State->Start < 0xFFFF) {
  722. //
  723. // We don't support IO windows that straddle the 16/32 bit boundry
  724. //
  725. ASSERT(State->End <= 0xFFFF);
  726. //
  727. // If the ISA bit is set on a bridge it means that the bridge only
  728. // decodes the first 0x100 ports for each 0x400 ports in 16 bit IO space.
  729. // Just remove these to the range list.
  730. //
  731. for (;
  732. localState.Start < State->End && localState.Start < 0xFFFF;
  733. localState.Start += 0x400) {
  734. localState.End = localState.Start + 0xFF;
  735. Callback(Arbiter, &localState);
  736. }
  737. return;
  738. }
  739. #endif
  740. //
  741. // Process the base range
  742. //
  743. Callback(Arbiter, State);
  744. //
  745. // Process any aliases with the alias flag set
  746. //
  747. ARB_PRINT(2, ("Adding aliases\n"));
  748. //
  749. // Lets see if we are processing positively decoded alases - yes you read that
  750. // right - on a PCI-PCI or Cardbus brigde with the VGA bit set (and seeing
  751. // as our friends now like AGP cards this is rather common) we decode all
  752. // VGA ranges together with their 10bit aliases. This means that the normal
  753. // rules of engagement with aliases don't apply so don't set the alias bit.
  754. //
  755. if (!(State->CurrentAlternative->Descriptor->Flags & CM_RESOURCE_PORT_POSITIVE_DECODE)) {
  756. //
  757. // We're processing aliases so set the alias flag
  758. //
  759. localState.RangeAttributes |= ARBITER_RANGE_ALIAS;
  760. }
  761. while (ario_GetNextAlias(State->CurrentAlternative->Descriptor->Flags,
  762. localState.Start,
  763. &localState.Start)) {
  764. localState.End = localState.Start + State->CurrentAlternative->Length - 1;
  765. Callback(Arbiter, &localState);
  766. }
  767. }
  768. NTSTATUS
  769. ario_PreprocessEntry(
  770. IN PARBITER_INSTANCE Arbiter,
  771. IN PARBITER_ALLOCATION_STATE State
  772. )
  773. /*++
  774. Routine Description:
  775. This routine is called from AllocateEntry to allow preprocessing of
  776. entries
  777. Arguments:
  778. Arbiter - The instance data of the arbiter who was called.
  779. State - The state of the current arbitration.
  780. Return Value:
  781. None.
  782. --*/
  783. {
  784. PARBITER_ALTERNATIVE current;
  785. ULONG defaultDecode;
  786. BOOLEAN improviseDecode = FALSE, windowDetected = FALSE;
  787. ULONGLONG greatestPort = 0;
  788. PCI_OBJECT_TYPE type;
  789. PPCI_PDO_EXTENSION pdoExtension;
  790. PAGED_CODE();
  791. if (State->WorkSpace & PORT_ARBITER_PREPROCESSED) {
  792. //
  793. // We have already proprocessed this entry so don't repeat the work
  794. //
  795. return STATUS_SUCCESS;
  796. } else {
  797. State->WorkSpace |= PORT_ARBITER_PREPROCESSED;
  798. }
  799. //
  800. // Scan the alternatives and check if we have set any of the decode flags
  801. // are set or if we have to improvise
  802. //
  803. FOR_ALL_IN_ARRAY(State->Alternatives,
  804. State->AlternativeCount,
  805. current) {
  806. ASSERT(current->Descriptor->Type == CmResourceTypePort);
  807. ASSERT(current->Descriptor->Flags == State->Alternatives->Descriptor->Flags);
  808. //
  809. // Remember the greatest value we come across
  810. //
  811. if (current->Maximum > greatestPort) {
  812. greatestPort = current->Maximum;
  813. }
  814. //
  815. // Remember if we ever encounter a bridge window
  816. //
  817. if (current->Descriptor->Flags & CM_RESOURCE_PORT_WINDOW_DECODE) {
  818. //
  819. // If the request is marked with the window flag all alternatives
  820. // should also be marked with the window flag
  821. //
  822. #if DBG
  823. if (current != State->Alternatives) {
  824. //
  825. // This is an alternative - make sure we have already set the
  826. // window detected flag
  827. //
  828. ASSERT(windowDetected);
  829. }
  830. #endif
  831. windowDetected = TRUE;
  832. }
  833. if (!(current->Descriptor->Flags &
  834. (CM_RESOURCE_PORT_10_BIT_DECODE
  835. | CM_RESOURCE_PORT_12_BIT_DECODE
  836. | CM_RESOURCE_PORT_16_BIT_DECODE
  837. | CM_RESOURCE_PORT_POSITIVE_DECODE))) {
  838. improviseDecode = TRUE;
  839. // ASSERT(LEGACY_REQUEST(State->Entry->Source)
  840. if (!LEGACY_REQUEST(State->Entry)) {
  841. ARB_PRINT(0,
  842. ("Pnp device (%p) did not specify decodes for IO ports\n",
  843. State->Entry->PhysicalDeviceObject
  844. ));
  845. }
  846. }
  847. }
  848. if (improviseDecode) {
  849. //
  850. // Remember we improvised this
  851. //
  852. State->WorkSpace |= PORT_ARBITER_IMPROVISED_DECODE;
  853. ARB_PRINT(1, ("Improvising decode "));
  854. //
  855. // Work out the default
  856. //
  857. switch (State->Entry->InterfaceType) {
  858. case PNPISABus:
  859. case Isa:
  860. //
  861. // if machine is NEC98, default decode is 16 bit.
  862. //
  863. if(IsNEC_98) {
  864. defaultDecode = CM_RESOURCE_PORT_16_BIT_DECODE;
  865. ARB_PRINT(1, ("of 16bit for NEC98 Isa\n"));
  866. } else {
  867. //
  868. // If any of the ports is greater than can be decoded in 10 bits
  869. // assume a 16 bit decode
  870. //
  871. if (greatestPort >= (1<<10)) {
  872. defaultDecode = CM_RESOURCE_PORT_16_BIT_DECODE;
  873. ARB_PRINT(1, ("of 16bit for Isa with ports > 0x3FF\n"));
  874. } else {
  875. defaultDecode = CM_RESOURCE_PORT_10_BIT_DECODE;
  876. ARB_PRINT(1, ("of 10bit for Isa\n"));
  877. }
  878. }
  879. break;
  880. case Eisa:
  881. case MicroChannel:
  882. case PCMCIABus:
  883. ARB_PRINT(1, ("of 16bit for Eisa/MicroChannel/Pcmcia\n"));
  884. defaultDecode = CM_RESOURCE_PORT_16_BIT_DECODE;
  885. break;
  886. case PCIBus:
  887. ARB_PRINT(1, ("of positive for PCI\n"));
  888. defaultDecode = CM_RESOURCE_PORT_POSITIVE_DECODE;
  889. break;
  890. default:
  891. //
  892. // In NT < 5 we considered everything to be 16 bit decode so in the
  893. // absence of better information continue that tradition.
  894. //
  895. ARB_PRINT(1, ("of 16bit for unknown bus\n"));
  896. defaultDecode = CM_RESOURCE_PORT_16_BIT_DECODE;
  897. break;
  898. }
  899. //
  900. // Now set the flags
  901. //
  902. FOR_ALL_IN_ARRAY(State->Alternatives,
  903. State->AlternativeCount,
  904. current) {
  905. current->Descriptor->Flags |= defaultDecode;
  906. }
  907. } else {
  908. //
  909. // Even if we are not improvising decodes make sure that they didn't
  910. // report 10 bit decode for a range over 0x3FF - if so we assume 16 bit
  911. // decode - think EISA net cards that say they're ISA
  912. //
  913. FOR_ALL_IN_ARRAY(State->Alternatives,
  914. State->AlternativeCount,
  915. current) {
  916. if ((current->Descriptor->Flags & CM_RESOURCE_PORT_10_BIT_DECODE)
  917. && (greatestPort >= (1<<10) )) {
  918. current->Descriptor->Flags &= ~CM_RESOURCE_PORT_10_BIT_DECODE;
  919. current->Descriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
  920. }
  921. }
  922. }
  923. //
  924. // If we detected a bridge window then check if the ISA bit is set on the bridge
  925. //
  926. if (windowDetected) {
  927. //
  928. // Make sure its a PCI bridge...
  929. //
  930. if (State->Entry->PhysicalDeviceObject->DriverObject != PciDriverObject) {
  931. ASSERT(State->Entry->PhysicalDeviceObject->DriverObject == PciDriverObject);
  932. return STATUS_INVALID_PARAMETER;
  933. }
  934. pdoExtension = (PPCI_PDO_EXTENSION) State->Entry->PhysicalDeviceObject->DeviceExtension;
  935. if (pdoExtension->ExtensionType != PciPdoExtensionType) {
  936. ASSERT(pdoExtension->ExtensionType == PciPdoExtensionType);
  937. return STATUS_INVALID_PARAMETER;
  938. }
  939. type = PciClassifyDeviceType(pdoExtension);
  940. if (type != PciTypePciBridge && type != PciTypeCardbusBridge) {
  941. ASSERT(type == PciTypePciBridge || type == PciTypeCardbusBridge);
  942. return STATUS_INVALID_PARAMETER;
  943. }
  944. if (pdoExtension->Dependent.type1.IsaBitSet) {
  945. if (type == PciTypePciBridge) {
  946. State->WorkSpace |= PORT_ARBITER_ISA_BIT_SET;
  947. } else {
  948. ASSERT(type == PciTypePciBridge);
  949. }
  950. }
  951. State->WorkSpace |= PORT_ARBITER_BRIDGE_WINDOW;
  952. }
  953. //
  954. // If this device is positive decode then we want the range to be added to
  955. // the list with the positive decode flag set
  956. //
  957. if (State->Alternatives->Descriptor->Flags & CM_RESOURCE_PORT_POSITIVE_DECODE) {
  958. State->RangeAttributes |= ARBITER_RANGE_POSITIVE_DECODE;
  959. }
  960. return STATUS_SUCCESS;
  961. }
  962. BOOLEAN
  963. ario_FindWindowWithIsaBit(
  964. IN PARBITER_INSTANCE Arbiter,
  965. IN PARBITER_ALLOCATION_STATE State
  966. )
  967. {
  968. NTSTATUS status;
  969. ULONGLONG start, current;
  970. BOOLEAN available = FALSE;
  971. ULONG findRangeFlags = 0;
  972. //
  973. // We only support the ISA bit on Pci bridges
  974. //
  975. ASSERT_PCI_DEVICE_OBJECT(State->Entry->PhysicalDeviceObject);
  976. ASSERT(PciClassifyDeviceType(((PPCI_PDO_EXTENSION) State->Entry->PhysicalDeviceObject->DeviceExtension)
  977. ) == PciTypePciBridge);
  978. //
  979. // Bridges with windows perform positive decode and so can conflict with
  980. // aliases
  981. //
  982. ASSERT(State->CurrentAlternative->Descriptor->Flags & CM_RESOURCE_PORT_POSITIVE_DECODE);
  983. State->RangeAvailableAttributes |= ARBITER_RANGE_ALIAS;
  984. //
  985. // The request should be correctly aligned - we generated it!
  986. //
  987. ASSERT(State->CurrentAlternative->Length % State->CurrentAlternative->Alignment == 0);
  988. //
  989. // CurrentMinimum/CurrentMaximum should have been correctly aligned by
  990. // GetNextAllocationRange
  991. //
  992. ASSERT(State->CurrentMinimum % State->CurrentAlternative->Alignment == 0);
  993. ASSERT((State->CurrentMaximum + 1) % State->CurrentAlternative->Alignment == 0);
  994. //
  995. // Conflicts with NULL occur when our parents IO space is sparse, for
  996. // bridges that is if the ISA bit is set and so everything will line
  997. // up here. If the root we are on is sparse then things arn't as easy.
  998. if (State->Flags & ARBITER_STATE_FLAG_NULL_CONFLICT_OK) {
  999. findRangeFlags |= RTL_RANGE_LIST_NULL_CONFLICT_OK;
  1000. }
  1001. //
  1002. // ...or we are shareable...
  1003. //
  1004. if (State->CurrentAlternative->Flags & ARBITER_ALTERNATIVE_FLAG_SHARED) {
  1005. findRangeFlags |= RTL_RANGE_LIST_SHARED_OK;
  1006. }
  1007. //
  1008. // Check the length is reasonable
  1009. //
  1010. if (State->CurrentMaximum < (State->CurrentAlternative->Length + 1)) {
  1011. return FALSE;
  1012. }
  1013. //
  1014. // Iterate through the possible window positions, top down like the rest of
  1015. // arbitration.
  1016. //
  1017. start = State->CurrentMaximum - State->CurrentAlternative->Length + 1;
  1018. while (!available) {
  1019. //
  1020. // Check the range is within the constraints specified
  1021. //
  1022. if (start < State->CurrentMinimum) {
  1023. break;
  1024. }
  1025. //
  1026. // Check if the ISA windows are available we don't care about the rest
  1027. // of the ranges are we don't decode them.
  1028. //
  1029. for (current = start;
  1030. (current < (start + State->CurrentAlternative->Length - 1)) && (current < PCI_BRIDGE_ISA_BIT_MAX);
  1031. current += PCI_BRIDGE_ISA_BIT_STRIDE) {
  1032. status = RtlIsRangeAvailable(
  1033. Arbiter->PossibleAllocation,
  1034. current,
  1035. current + PCI_BRIDGE_ISA_BIT_WIDTH - 1,
  1036. findRangeFlags,
  1037. State->RangeAvailableAttributes,
  1038. Arbiter->ConflictCallbackContext,
  1039. Arbiter->ConflictCallback,
  1040. &available
  1041. );
  1042. ASSERT(NT_SUCCESS(status));
  1043. if (!available) {
  1044. break;
  1045. }
  1046. }
  1047. //
  1048. // Now available indicates if all the ISA windows were available
  1049. //
  1050. if (available) {
  1051. State->Start = start;
  1052. State->End = start + State->CurrentAlternative->Length - 1;
  1053. ASSERT(State->Start >= State->CurrentMinimum);
  1054. ASSERT(State->End <= State->CurrentMaximum);
  1055. break;
  1056. } else {
  1057. //
  1058. // Move to next range if we can
  1059. //
  1060. if (start < PCI_BRIDGE_WINDOW_GRANULARITY) {
  1061. break;
  1062. }
  1063. start -= PCI_BRIDGE_WINDOW_GRANULARITY; // IO windows are 1000 byte aligned
  1064. continue;
  1065. }
  1066. }
  1067. return available;
  1068. }
  1069. BOOLEAN
  1070. ario_FindSuitableRange(
  1071. IN PARBITER_INSTANCE Arbiter,
  1072. IN PARBITER_ALLOCATION_STATE State
  1073. )
  1074. /*++
  1075. Routine Description:
  1076. This routine is called from AllocateEntry once we have decided where we want
  1077. to allocate from. It tries to find a free range that matches the
  1078. requirements in State while restricting its possible solutions to the range
  1079. State->Start to State->CurrentMaximum. On success State->Start and
  1080. State->End represent this range. Conflicts with ISA aliases are considered.
  1081. Arguments:
  1082. Arbiter - The instance data of the arbiter who was called.
  1083. State - The state of the current arbitration.
  1084. Return Value:
  1085. TRUE if we found a range, FALSE otherwise.
  1086. --*/
  1087. {
  1088. NTSTATUS status;
  1089. PPCI_PDO_EXTENSION parentPdo, childPdo;
  1090. PAGED_CODE();
  1091. //
  1092. // Assume we won't be allowing null conflicts
  1093. //
  1094. State->Flags &= ~ARBITER_STATE_FLAG_NULL_CONFLICT_OK;
  1095. //
  1096. // Now check if we really wanted to allow them
  1097. //
  1098. if (State->WorkSpace & PORT_ARBITER_BRIDGE_WINDOW) {
  1099. //
  1100. // If this isn't a PCI PDO we already failed in PreprocessEntry but
  1101. // paranoia reigns.
  1102. //
  1103. ASSERT_PCI_DEVICE_OBJECT(State->Entry->PhysicalDeviceObject);
  1104. childPdo = (PPCI_PDO_EXTENSION) State->Entry->PhysicalDeviceObject->DeviceExtension;
  1105. if (!PCI_PDO_ON_ROOT(childPdo)) {
  1106. parentPdo = PCI_BRIDGE_PDO(PCI_PARENT_FDOX(childPdo));
  1107. ASSERT(parentPdo);
  1108. } else {
  1109. parentPdo = NULL;
  1110. }
  1111. //
  1112. // Check if this is a PCI-PCI bridge that the bios configured that
  1113. // we have not moved or it is a root bus (which be definition was
  1114. // bios configured ...
  1115. //
  1116. if ((parentPdo == NULL ||
  1117. (parentPdo->HeaderType == PCI_BRIDGE_TYPE && !parentPdo->MovedDevice))
  1118. && (State->CurrentAlternative->Flags & ARBITER_ALTERNATIVE_FLAG_FIXED)) {
  1119. //
  1120. // The BIOS configured and we have not moved its parent (thus
  1121. // invalidating the bioses configuration) then we will leave well
  1122. // alone. We then allow the null conflicts and only configure the
  1123. // arbiter to give out ranges that make it to this bus.
  1124. //
  1125. State->Flags |= ARBITER_STATE_FLAG_NULL_CONFLICT_OK;
  1126. } else {
  1127. //
  1128. // If the BIOS didn't configure it then we need to find somewhere to
  1129. // put the bridge. This will involve trying to find a contiguous 1000
  1130. // port window and then if one is not available, examining all locations
  1131. // to find the one with the most IO.
  1132. //
  1133. //
  1134. // NTRAID #62581 - 04/03/2000 - andrewth
  1135. // We are punting on this for Win2K, if 1000 contiguous ports
  1136. // arn't available then we are not going to configure the bridge. A fix
  1137. // for this will be required for hot plug to work. Setting the ISA bit
  1138. // on the bridge will increase the chances of configuring this
  1139. //
  1140. }
  1141. //
  1142. // Check if this is a window for a bridge with the ISA bit set in 16 bit IO
  1143. // space. If so we need to do some special processing...
  1144. //
  1145. if (State->WorkSpace & PORT_ARBITER_ISA_BIT_SET
  1146. && State->CurrentMaximum <= 0xFFFF) {
  1147. return ario_FindWindowWithIsaBit(Arbiter, State);
  1148. }
  1149. }
  1150. //
  1151. // For legacy requests from IoAssignResources (directly or by way of
  1152. // HalAssignSlotResources) or IoReportResourceUsage we consider preallocated
  1153. // resources to be available for backward compatibility reasons.
  1154. //
  1155. // If we are allocating a devices boot config then we consider all other
  1156. // boot configs to be available.
  1157. //
  1158. if (State->Entry->RequestSource == ArbiterRequestLegacyReported
  1159. || State->Entry->RequestSource == ArbiterRequestLegacyAssigned
  1160. || State->Entry->Flags & ARBITER_FLAG_BOOT_CONFIG) {
  1161. State->RangeAvailableAttributes |= ARBITER_RANGE_BOOT_ALLOCATED;
  1162. }
  1163. //
  1164. // This request is for a device which performs positive decode so all
  1165. // aliased ranges should be considered available
  1166. //
  1167. if (State->CurrentAlternative->Descriptor->Flags & CM_RESOURCE_PORT_POSITIVE_DECODE) {
  1168. State->RangeAvailableAttributes |= ARBITER_RANGE_ALIAS;
  1169. }
  1170. while (State->CurrentMaximum >= State->CurrentMinimum) {
  1171. //
  1172. // Try to satisfy the request
  1173. //
  1174. if (ArbFindSuitableRange(Arbiter, State)) {
  1175. if (State->CurrentAlternative->Length == 0) {
  1176. ARB_PRINT(2,
  1177. ("Zero length solution solution for %p = 0x%I64x-0x%I64x, %s\n",
  1178. State->Entry->PhysicalDeviceObject,
  1179. State->Start,
  1180. State->End,
  1181. State->CurrentAlternative->Flags & ARBITER_ALTERNATIVE_FLAG_SHARED ?
  1182. "shared" : "non-shared"
  1183. ));
  1184. //
  1185. // Set the result in the arbiter appropriatley so that we
  1186. // don't try and translate this zero requirement - it won't!
  1187. //
  1188. State->Entry->Result = ArbiterResultNullRequest;
  1189. return TRUE;
  1190. } else if (ario_IsAliasedRangeAvailable(Arbiter, State)) {
  1191. //
  1192. // We found a suitable range so return
  1193. //
  1194. return TRUE;
  1195. } else {
  1196. //
  1197. // Check if we wrap on start - if so then we're finished.
  1198. //
  1199. if (State->Start - 1 > State->Start) {
  1200. break;
  1201. }
  1202. //
  1203. // This range's aliases arn't available so reduce allocation
  1204. // window to not include the range just returned and try again
  1205. //
  1206. State->CurrentMaximum = State->Start - 1;
  1207. continue;
  1208. }
  1209. } else {
  1210. //
  1211. // We couldn't find a base range
  1212. //
  1213. break;
  1214. }
  1215. }
  1216. return FALSE;
  1217. }
  1218. BOOLEAN
  1219. ario_GetNextAlias(
  1220. ULONG IoDescriptorFlags,
  1221. ULONGLONG LastAlias,
  1222. PULONGLONG NextAlias
  1223. )
  1224. /*++
  1225. Routine Description:
  1226. This routine calculates the next alias of an IO port up to 0xFFFF.
  1227. Arguments:
  1228. IoDescriptorFlags - The flags from the requirement descriptor indicating the
  1229. type of alias if any.
  1230. LastAlias - The alias previous to this one.
  1231. NextAlias - Point to where the next alias should be returned
  1232. Return Value:
  1233. TRUE if we found an alias, FALSE otherwise.
  1234. --*/
  1235. {
  1236. ULONGLONG next;
  1237. PAGED_CODE();
  1238. if (IoDescriptorFlags & CM_RESOURCE_PORT_10_BIT_DECODE) {
  1239. next = LastAlias + (1 << 10);
  1240. } else if (IoDescriptorFlags & CM_RESOURCE_PORT_12_BIT_DECODE) {
  1241. next = LastAlias + (1 << 12);
  1242. } else if ((IoDescriptorFlags & CM_RESOURCE_PORT_POSITIVE_DECODE)
  1243. || (IoDescriptorFlags & CM_RESOURCE_PORT_16_BIT_DECODE)) {
  1244. //
  1245. // Positive decode implies 16 bit decode unless 10 or 12 bit flags are set
  1246. // There are no aliases as we decode all the bits... what a good idea
  1247. //
  1248. return FALSE;
  1249. } else {
  1250. //
  1251. // None of the CM_RESOURCE_PORT_*_DECODE flags are set - we should never
  1252. // get here as we should have set them in Preprocess
  1253. //
  1254. ASSERT(FALSE);
  1255. return FALSE;
  1256. }
  1257. //
  1258. // Check that we are below the maximum aliased port
  1259. //
  1260. if (next > 0xFFFF) {
  1261. return FALSE;
  1262. } else {
  1263. *NextAlias = next;
  1264. return TRUE;
  1265. }
  1266. }
  1267. BOOLEAN
  1268. ario_IsAliasedRangeAvailable(
  1269. PARBITER_INSTANCE Arbiter,
  1270. PARBITER_ALLOCATION_STATE State
  1271. )
  1272. /*++
  1273. Routine Description:
  1274. This routine determines if the range (Start-(Length-1)) is available taking
  1275. into account any aliases.
  1276. Arguments:
  1277. Arbiter - The instance data of the arbiter who was called.
  1278. State - The state of the current arbitration.
  1279. Return Value:
  1280. TRUE if the range is available, FALSE otherwise.
  1281. --*/
  1282. {
  1283. NTSTATUS status;
  1284. ULONGLONG alias = State->Start;
  1285. BOOLEAN aliasAvailable;
  1286. UCHAR userFlagsMask;
  1287. PAGED_CODE();
  1288. //
  1289. // If we improvised the decode then add the aliases but don't care it they
  1290. // conflict - more 4.0 compatibility.
  1291. //
  1292. if (State->WorkSpace & PORT_ARBITER_IMPROVISED_DECODE) {
  1293. return TRUE;
  1294. }
  1295. //
  1296. // Positive decode devices can conflict with aliases
  1297. //
  1298. userFlagsMask = ARBITER_RANGE_POSITIVE_DECODE;
  1299. //
  1300. // For legacy requests from IoAssignResources (directly or by way of
  1301. // HalAssignSlotResources) or IoReportResourceUsage we consider preallocated
  1302. // resources to be available for backward compatibility reasons.
  1303. //
  1304. if (State->Entry->RequestSource == ArbiterRequestLegacyReported
  1305. || State->Entry->RequestSource == ArbiterRequestLegacyAssigned
  1306. || State->Entry->Flags & ARBITER_FLAG_BOOT_CONFIG) {
  1307. userFlagsMask |= ARBITER_RANGE_BOOT_ALLOCATED;
  1308. }
  1309. while (ario_GetNextAlias(State->CurrentAlternative->Descriptor->Flags,
  1310. alias,
  1311. &alias)) {
  1312. status = RtlIsRangeAvailable(
  1313. Arbiter->PossibleAllocation,
  1314. alias,
  1315. alias + State->CurrentAlternative->Length - 1,
  1316. RTL_RANGE_LIST_NULL_CONFLICT_OK |
  1317. (State->CurrentAlternative->Flags & ARBITER_ALTERNATIVE_FLAG_SHARED ?
  1318. RTL_RANGE_LIST_SHARED_OK : 0),
  1319. userFlagsMask,
  1320. Arbiter->ConflictCallbackContext,
  1321. Arbiter->ConflictCallback,
  1322. &aliasAvailable
  1323. );
  1324. ASSERT(NT_SUCCESS(status));
  1325. if (!aliasAvailable) {
  1326. ARBITER_ALLOCATION_STATE tempState;
  1327. //
  1328. // Check if we allow this conflict by calling OverrideConflict -
  1329. // we will need to falsify ourselves an allocation state first
  1330. //
  1331. // NTRAID #62583 - 04/03/2000 - andrewth
  1332. // This works but relies on knowing what OverrideConflict
  1333. // looks at. A better fix invloves storing the aliases in another
  1334. // list but this it too much of a change for Win2k
  1335. //
  1336. RtlCopyMemory(&tempState, State, sizeof(ARBITER_ALLOCATION_STATE));
  1337. tempState.CurrentMinimum = alias;
  1338. tempState.CurrentMaximum = alias + State->CurrentAlternative->Length - 1;
  1339. if (Arbiter->OverrideConflict(Arbiter, &tempState)) {
  1340. //
  1341. // We decided this conflict was ok so contine checking the rest
  1342. // of the aliases
  1343. //
  1344. continue;
  1345. }
  1346. //
  1347. // An alias isn't available - get another possibility
  1348. //
  1349. ARB_PRINT(2,
  1350. ("\t\tAlias 0x%x-0x%x not available\n",
  1351. alias,
  1352. alias + State->CurrentAlternative->Length - 1
  1353. ));
  1354. return FALSE;
  1355. }
  1356. }
  1357. return TRUE;
  1358. }
  1359. VOID
  1360. ario_AddAllocation(
  1361. IN PARBITER_INSTANCE Arbiter,
  1362. IN PARBITER_ALLOCATION_STATE State
  1363. )
  1364. /*++
  1365. Routine Description:
  1366. This routine is called from AllocateEntry once we have found a possible
  1367. solution (State->Start - State->End). It adds the ranges that will not be
  1368. available if we commit to this solution to Arbiter->PossibleAllocation.
  1369. Arguments:
  1370. Arbiter - The instance data of the arbiter who was called.
  1371. State - The state of the current arbitration.
  1372. Return Value:
  1373. None.
  1374. --*/
  1375. {
  1376. PAGED_CODE();
  1377. ario_AddOrBacktrackAllocation(Arbiter,
  1378. State,
  1379. ArbAddAllocation
  1380. );
  1381. }
  1382. NTSTATUS
  1383. armem_PreprocessEntry(
  1384. IN PARBITER_INSTANCE Arbiter,
  1385. IN PARBITER_ALLOCATION_STATE State
  1386. )
  1387. {
  1388. PARBITER_MEMORY_EXTENSION extension = Arbiter->Extension;
  1389. BOOLEAN prefetchable;
  1390. PAGED_CODE();
  1391. ASSERT(extension);
  1392. //
  1393. // Check if this is a request for a ROM - it must be a fixed request with
  1394. // only 1 alternative and the ROM bit set
  1395. //
  1396. if ((State->Alternatives[0].Descriptor->Flags & CM_RESOURCE_MEMORY_READ_ONLY) ||
  1397. ((State->Alternatives[0].Flags & ARBITER_ALTERNATIVE_FLAG_FIXED) &&
  1398. State->AlternativeCount == 1 &&
  1399. State->Entry->RequestSource == ArbiterRequestLegacyReported)) {
  1400. if (State->Alternatives[0].Descriptor->Flags & CM_RESOURCE_MEMORY_READ_ONLY) {
  1401. ASSERT(State->Alternatives[0].Flags & ARBITER_ALTERNATIVE_FLAG_FIXED);
  1402. // ASSERT(State->AlternativeCount == 1);
  1403. }
  1404. //
  1405. // Consider other ROMS to be available
  1406. //
  1407. State->RangeAvailableAttributes |= MEMORY_RANGE_ROM;
  1408. //
  1409. // Mark this range as a ROM
  1410. //
  1411. State->RangeAttributes |= MEMORY_RANGE_ROM;
  1412. //
  1413. // Allow NULL conflicts
  1414. //
  1415. State->Flags |= ARBITER_STATE_FLAG_NULL_CONFLICT_OK;
  1416. }
  1417. //
  1418. // Check if this is a request for prefetchable memory and select
  1419. // the correct ordering list
  1420. //
  1421. if (extension->PrefetchablePresent) {
  1422. #if IGNORE_PREFETCH_FOR_LEGACY_REPORTED
  1423. //
  1424. // In NT < 5 IoReportResourceUsage had no notion of prefetchable memory
  1425. // so in order to be backward compatible we hope the BIOS/firmware got
  1426. // it right!
  1427. //
  1428. if (State->Entry->RequestSource == ArbiterRequestLegacyReported) {
  1429. Arbiter->OrderingList = extension->OriginalOrdering;
  1430. return STATUS_SUCCESS;
  1431. }
  1432. #endif
  1433. prefetchable =
  1434. State->Alternatives[0].Descriptor->Flags
  1435. & CM_RESOURCE_MEMORY_PREFETCHABLE;
  1436. if (prefetchable) {
  1437. Arbiter->OrderingList = extension->PrefetchableOrdering;
  1438. } else {
  1439. Arbiter->OrderingList = extension->NonprefetchableOrdering;
  1440. }
  1441. #if DBG
  1442. {
  1443. PARBITER_ALTERNATIVE current;
  1444. //
  1445. // Make sure that all the alternatives are of the same type
  1446. //
  1447. FOR_ALL_IN_ARRAY(State->Alternatives,
  1448. State->AlternativeCount,
  1449. current) {
  1450. ASSERT((current->Descriptor->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE)
  1451. == prefetchable
  1452. );
  1453. }
  1454. }
  1455. #endif
  1456. }
  1457. return STATUS_SUCCESS;
  1458. }
  1459. BOOLEAN
  1460. armem_GetNextAllocationRange(
  1461. IN PARBITER_INSTANCE Arbiter,
  1462. IN PARBITER_ALLOCATION_STATE State
  1463. )
  1464. {
  1465. PARBITER_MEMORY_EXTENSION extension = Arbiter->Extension;
  1466. //
  1467. // Call the default implementation
  1468. //
  1469. if (!ArbGetNextAllocationRange(Arbiter, State)) {
  1470. return FALSE;
  1471. }
  1472. if (extension->PrefetchablePresent
  1473. && State->Entry->RequestSource != ArbiterRequestLegacyReported) {
  1474. //
  1475. // We have already precalculated the reserved ranges into the ordering
  1476. // so if we end up in the reserved ranges we're out of luck...
  1477. //
  1478. if (State->CurrentAlternative->Priority > ARBITER_PRIORITY_PREFERRED_RESERVED) {
  1479. return FALSE;
  1480. }
  1481. }
  1482. return TRUE;
  1483. }
  1484. NTSTATUS
  1485. armem_StartArbiter(
  1486. IN PARBITER_INSTANCE Arbiter,
  1487. IN PCM_RESOURCE_LIST StartResources
  1488. )
  1489. /*++
  1490. This is called after ArbInitializeArbiterInstance as it uses
  1491. information initialized there. The arbiter lock should be held.
  1492. Seeing as this is only applicable to memory descriptors we maniulate
  1493. the resource descriptors directlty as oppose to useing the pack/upack
  1494. routines in the arbiter.
  1495. Example:
  1496. StartResources contain the prefetchable range 0xfff00000 - 0xfffeffff
  1497. OriginalOrdering (from the registry) says:
  1498. 0x00100000 - 0xFFFFFFFF
  1499. 0x000F0000 - 0x000FFFFF
  1500. 0x00080000 - 0x000BFFFF
  1501. 0x00080000 - 0x000FFFFF
  1502. 0x00080000 - 0xFFBFFFFF
  1503. ReservedList contains 0xfff0a000-0xfff0afff
  1504. Then out ordering lists will be:
  1505. PrefetchableOrdering NonprefetchableOrdering
  1506. 0xFFF0B000 - 0xFFFEFFFF
  1507. 0xFFF00000 - 0xFFF09FFF
  1508. 0xFFFF0000 - 0xFFFFFFFF 0xFFF0b000 - 0xFFFFFFFF
  1509. 0x00100000 - 0xFFFEFFFF 0x00100000 - 0xFFF09FFF
  1510. 0x000F0000 - 0x000FFFFF 0x000F0000 - 0x000FFFFF
  1511. 0x00080000 - 0x000BFFFF 0x00080000 - 0x000BFFFF
  1512. 0x00080000 - 0x000FFFFF 0x00080000 - 0x000FFFFF
  1513. This means that when following the prefetchable ordering we try to
  1514. allocate in the prefetchable range and if we can't then we allocate
  1515. none prefetchable memory. In the Nonprefetchable ordering we avoid the
  1516. prefetchable ranges. GetNextAllocationRange is changed so that it will not
  1517. allow
  1518. --*/
  1519. {
  1520. NTSTATUS status;
  1521. PCM_PARTIAL_RESOURCE_DESCRIPTOR current;
  1522. PARBITER_MEMORY_EXTENSION extension = Arbiter->Extension;
  1523. PARBITER_ORDERING currentOrdering;
  1524. ULONGLONG start, end;
  1525. #if PCIFLAG_IGNORE_PREFETCHABLE_MEMORY_AT_ROOT_HACK
  1526. PPCI_FDO_EXTENSION fdoExtension;
  1527. #endif
  1528. PAGED_CODE();
  1529. //
  1530. // If this is the first time we have initialized the extension do some one
  1531. // only initialization
  1532. //
  1533. if (!extension->Initialized) {
  1534. //
  1535. // Copy the default memory ordering list from the arbiter
  1536. //
  1537. extension->OriginalOrdering = Arbiter->OrderingList;
  1538. RtlZeroMemory(&Arbiter->OrderingList, sizeof(ARBITER_ORDERING_LIST));
  1539. } else {
  1540. //
  1541. // We are reinitializing the arbiter
  1542. //
  1543. if (extension->PrefetchablePresent) {
  1544. //
  1545. // We had prefetchable memory before so free the orderings we
  1546. // created last time.
  1547. //
  1548. ArbFreeOrderingList(&extension->PrefetchableOrdering);
  1549. ArbFreeOrderingList(&extension->NonprefetchableOrdering);
  1550. }
  1551. }
  1552. extension->PrefetchablePresent = FALSE;
  1553. extension->PrefetchableCount = 0;
  1554. if (StartResources != NULL) {
  1555. ASSERT(StartResources->Count == 1);
  1556. //
  1557. // Check if we have any prefetchable memory - if not we're done
  1558. //
  1559. FOR_ALL_IN_ARRAY(StartResources->List[0].PartialResourceList.PartialDescriptors,
  1560. StartResources->List[0].PartialResourceList.Count,
  1561. current) {
  1562. if ((current->Type == CmResourceTypeMemory)
  1563. && (current->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE)) {
  1564. extension->PrefetchablePresent = TRUE;
  1565. break;
  1566. }
  1567. }
  1568. }
  1569. #if PCIFLAG_IGNORE_PREFETCHABLE_MEMORY_AT_ROOT_HACK
  1570. if (PciSystemWideHackFlags&PCIFLAG_IGNORE_PREFETCHABLE_MEMORY_AT_ROOT_HACK) {
  1571. fdoExtension = (PPCI_FDO_EXTENSION) Arbiter->BusDeviceObject->DeviceExtension;
  1572. ASSERT_PCI_FDO_EXTENSION(fdoExtension);
  1573. if (PCI_IS_ROOT_FDO(fdoExtension)) {
  1574. extension->PrefetchablePresent = FALSE;
  1575. }
  1576. }
  1577. #endif
  1578. if (!extension->PrefetchablePresent) {
  1579. //
  1580. // Restore the original ordering list
  1581. //
  1582. Arbiter->OrderingList = extension->OriginalOrdering;
  1583. return STATUS_SUCCESS;
  1584. }
  1585. status = ArbInitializeOrderingList(&extension->PrefetchableOrdering);
  1586. if (!NT_SUCCESS(status)) {
  1587. goto cleanup;
  1588. }
  1589. status = ArbInitializeOrderingList(&extension->NonprefetchableOrdering);
  1590. if (!NT_SUCCESS(status)) {
  1591. goto cleanup;
  1592. }
  1593. //
  1594. // Copy of the original ordering into the new Nonprefetchable ordering
  1595. //
  1596. status = ArbCopyOrderingList(&extension->NonprefetchableOrdering,
  1597. &extension->OriginalOrdering
  1598. );
  1599. if (!NT_SUCCESS(status)) {
  1600. goto cleanup;
  1601. }
  1602. //
  1603. // Add the range 0-MAXULONGLONG to the list so we will calculate the reserved
  1604. // orderings in the list. This will ensure that we don't give a half
  1605. // prefetchable and half not range to a device. Prefetchable devices should
  1606. // probably be able to deal with this but its asking for trouble!
  1607. //
  1608. status = ArbAddOrdering(&extension->NonprefetchableOrdering,
  1609. 0,
  1610. MAXULONGLONG
  1611. );
  1612. if (!NT_SUCCESS(status)) {
  1613. goto cleanup;
  1614. }
  1615. //
  1616. // For each prefetchable range delete it from the nonprefetchabe ordering
  1617. // and add it to the prefetchable one.
  1618. //
  1619. // NB - We take it "to be self evident that that all prefetchable memory is
  1620. // created equal" and therefore initialize the ordering list in the order
  1621. // the prefetchable memory desciptors are found in the resource list.
  1622. //
  1623. FOR_ALL_IN_ARRAY(StartResources->List[0].PartialResourceList.PartialDescriptors,
  1624. StartResources->List[0].PartialResourceList.Count,
  1625. current) {
  1626. if ((current->Type == CmResourceTypeMemory)
  1627. && (current->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE)) {
  1628. extension->PrefetchableCount++;
  1629. start = current->u.Memory.Start.QuadPart,
  1630. end = current->u.Memory.Start.QuadPart + current->u.Memory.Length - 1;
  1631. //
  1632. // Add to the prefetchable ordering
  1633. //
  1634. status = ArbAddOrdering(&extension->PrefetchableOrdering,
  1635. start,
  1636. end
  1637. );
  1638. if (!NT_SUCCESS(status)) {
  1639. goto cleanup;
  1640. }
  1641. //
  1642. // And prune it from the Nonprefetchable ordering
  1643. //
  1644. status = ArbPruneOrdering(&extension->NonprefetchableOrdering, start, end);
  1645. if (!NT_SUCCESS(status)) {
  1646. goto cleanup;
  1647. }
  1648. ARB_PRINT(1,("Processed prefetchable range 0x%I64x-0x%I64x\n",
  1649. start,
  1650. end
  1651. ));
  1652. }
  1653. }
  1654. //
  1655. // Now prune out any explicitly reserved ranges from our new prefetchable
  1656. // ordering - these have already been precalculated into the Nonprefetchable
  1657. // ordering
  1658. //
  1659. FOR_ALL_IN_ARRAY(Arbiter->ReservedList.Orderings,
  1660. Arbiter->ReservedList.Count,
  1661. currentOrdering) {
  1662. status = ArbPruneOrdering(&extension->PrefetchableOrdering,
  1663. currentOrdering->Start,
  1664. currentOrdering->End
  1665. );
  1666. if (!NT_SUCCESS(status)) {
  1667. goto cleanup;
  1668. }
  1669. }
  1670. //
  1671. // Finally append the Nonprefetchable ordering onto the end of the prefetchable
  1672. //
  1673. FOR_ALL_IN_ARRAY(extension->NonprefetchableOrdering.Orderings,
  1674. extension->NonprefetchableOrdering.Count,
  1675. currentOrdering) {
  1676. status = ArbAddOrdering(&extension->PrefetchableOrdering,
  1677. currentOrdering->Start,
  1678. currentOrdering->End
  1679. );
  1680. if (!NT_SUCCESS(status)) {
  1681. goto cleanup;
  1682. }
  1683. }
  1684. extension->Initialized = TRUE;
  1685. return STATUS_SUCCESS;
  1686. cleanup:
  1687. return status;
  1688. }
  1689. BOOLEAN
  1690. ario_IsBridge(
  1691. IN PDEVICE_OBJECT Pdo
  1692. )
  1693. /*++
  1694. Routine Description:
  1695. Determines if this device is a PCI enumberated PCI-PCI or Cardbus bridge
  1696. Arguments:
  1697. Pdo - The Pdo representing the device in question
  1698. Return Value:
  1699. TRUE if this Pdo is for a bridge
  1700. --*/
  1701. {
  1702. PSINGLE_LIST_ENTRY nextEntry;
  1703. PPCI_FDO_EXTENSION fdoExtension;
  1704. PCI_OBJECT_TYPE type;
  1705. PAGED_CODE();
  1706. //
  1707. // First of all see if this is a PCI FDO by walking the list of all our FDOs
  1708. //
  1709. for ( nextEntry = PciFdoExtensionListHead.Next;
  1710. nextEntry != NULL;
  1711. nextEntry = nextEntry->Next ) {
  1712. fdoExtension = CONTAINING_RECORD(nextEntry,
  1713. PCI_FDO_EXTENSION,
  1714. List);
  1715. if (fdoExtension->PhysicalDeviceObject == Pdo) {
  1716. //
  1717. // Ok this is our FDO so we can look at it and see if it is a
  1718. // PCI-PCI or Cardbus bridge
  1719. //
  1720. type = PciClassifyDeviceType(Pdo->DeviceExtension);
  1721. if (type == PciTypePciBridge || type == PciTypeCardbusBridge) {
  1722. return TRUE;
  1723. }
  1724. }
  1725. }
  1726. return FALSE;
  1727. }
  1728. BOOLEAN
  1729. ario_OverrideConflict(
  1730. IN PARBITER_INSTANCE Arbiter,
  1731. IN PARBITER_ALLOCATION_STATE State
  1732. )
  1733. /*++
  1734. Routine Description:
  1735. This is the default implementation of override conflict which
  1736. Arguments:
  1737. Arbiter - The instance data of the arbiter who was called.
  1738. State - The state of the current arbitration.
  1739. Return Value:
  1740. TRUE if the conflict is allowable, false otherwise
  1741. --*/
  1742. {
  1743. PRTL_RANGE current;
  1744. RTL_RANGE_LIST_ITERATOR iterator;
  1745. BOOLEAN ok = FALSE;
  1746. PAGED_CODE();
  1747. if (!(State->CurrentAlternative->Flags & ARBITER_ALTERNATIVE_FLAG_FIXED)) {
  1748. return FALSE;
  1749. }
  1750. FOR_ALL_RANGES(Arbiter->PossibleAllocation, &iterator, current) {
  1751. //
  1752. // Only test the overlapping ones
  1753. //
  1754. if (INTERSECT(current->Start, current->End, State->CurrentMinimum, State->CurrentMaximum)) {
  1755. if (current->Attributes & State->RangeAvailableAttributes) {
  1756. //
  1757. // We DON'T set ok to true because we are just ignoring the range,
  1758. // as RtlFindRange would have and thus it can't be the cause of
  1759. // RtlFindRange failing, so ignoring it can't fix the conflict.
  1760. //
  1761. continue;
  1762. }
  1763. //
  1764. // Check if we are conflicting with ourselves and the conflicting
  1765. // range is a fixed requirement
  1766. //
  1767. if (current->Owner == State->Entry->PhysicalDeviceObject
  1768. && State->CurrentAlternative->Flags & ARBITER_ALTERNATIVE_FLAG_FIXED) {
  1769. ARB_PRINT(1,
  1770. ("PnP Warning: Device reported self-conflicting requirement\n"
  1771. ));
  1772. State->Start=State->CurrentMinimum;
  1773. State->End=State->CurrentMaximum;
  1774. ok = TRUE;
  1775. continue;
  1776. }
  1777. //
  1778. // If the passive decode flag is set and we conflict with a bridge then
  1779. // allow the conflict. We also allow the conflict if the range never
  1780. // makes it onto the bus (Owner == NULL)
  1781. //
  1782. // NTRAID #62584 - 04/03/2000 - andrewth
  1783. // Once the PCI bridge code is in we need to ensure that we
  1784. // don't put anything into the ranges that are being passively decoded
  1785. //
  1786. if (State->CurrentAlternative->Descriptor->Flags & CM_RESOURCE_PORT_PASSIVE_DECODE
  1787. && (ario_IsBridge(current->Owner) || current->Owner == NULL)) {
  1788. State->Start=State->CurrentMinimum;
  1789. State->End=State->CurrentMaximum;
  1790. ok = TRUE;
  1791. continue;
  1792. }
  1793. //
  1794. // The conflict is still valid
  1795. //
  1796. return FALSE;
  1797. }
  1798. }
  1799. return ok;
  1800. }
  1801. VOID
  1802. ario_ApplyBrokenVideoHack(
  1803. IN PPCI_FDO_EXTENSION FdoExtension
  1804. )
  1805. {
  1806. NTSTATUS status;
  1807. PPCI_ARBITER_INSTANCE pciArbiter;
  1808. PARBITER_INSTANCE arbiter;
  1809. ASSERT(!FdoExtension->BrokenVideoHackApplied);
  1810. ASSERT(PCI_IS_ROOT_FDO(FdoExtension));
  1811. //
  1812. // Find the arbiter - we should always have one for a root bus.
  1813. //
  1814. pciArbiter = PciFindSecondaryExtension(FdoExtension, PciArb_Io);
  1815. ASSERT(pciArbiter);
  1816. arbiter = &pciArbiter->CommonInstance;
  1817. //
  1818. // We are reinitializing the orderings free the old ones
  1819. //
  1820. ArbFreeOrderingList(&arbiter->OrderingList);
  1821. ArbFreeOrderingList(&arbiter->ReservedList);
  1822. //
  1823. // Rebuild the ordering list reserving all the places these broken S3 and
  1824. // ATI cards might want to live - this should not fail.
  1825. //
  1826. status = ArbBuildAssignmentOrdering(arbiter,
  1827. L"Pci",
  1828. L"BrokenVideo",
  1829. NULL
  1830. );
  1831. ASSERT(NT_SUCCESS(status));
  1832. FdoExtension->BrokenVideoHackApplied = TRUE;
  1833. }
  1834. BOOLEAN
  1835. ario_GetNextAllocationRange(
  1836. IN PARBITER_INSTANCE Arbiter,
  1837. IN PARBITER_ALLOCATION_STATE State
  1838. )
  1839. {
  1840. BOOLEAN rangeFound, doIsaBit;
  1841. ARBITER_ORDERING_LIST savedOrderingList;
  1842. //
  1843. // If this is a bridge with the ISA bit set use the bridge ordering list
  1844. //
  1845. doIsaBit = (State->WorkSpace & PORT_ARBITER_BRIDGE_WINDOW)
  1846. && (State->WorkSpace & PORT_ARBITER_ISA_BIT_SET);
  1847. if (doIsaBit) {
  1848. savedOrderingList = Arbiter->OrderingList;
  1849. Arbiter->OrderingList = PciBridgeOrderingList;
  1850. }
  1851. //
  1852. // Call the base function
  1853. //
  1854. rangeFound = ArbGetNextAllocationRange(Arbiter, State);
  1855. if (doIsaBit) {
  1856. //
  1857. // If we have reached preferred reserved priority then we fail as we
  1858. // have already considered both the 16 and 32 bit IO cases and using
  1859. // the reserved may allow us to stradle the boundry.
  1860. //
  1861. if (rangeFound
  1862. && State->CurrentAlternative->Priority > ARBITER_PRIORITY_PREFERRED_RESERVED) {
  1863. rangeFound = FALSE;
  1864. }
  1865. Arbiter->OrderingList = savedOrderingList;
  1866. }
  1867. return rangeFound;
  1868. }
  1869. NTSTATUS
  1870. ario_StartArbiter(
  1871. IN PARBITER_INSTANCE Arbiter,
  1872. IN PCM_RESOURCE_LIST StartResources
  1873. )
  1874. {
  1875. NTSTATUS status;
  1876. PPCI_FDO_EXTENSION fdoExtension;
  1877. PPCI_PDO_EXTENSION pdoExtension = NULL;
  1878. PRTL_RANGE_LIST exclusionList = NULL;
  1879. PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;
  1880. PPCI_FDO_EXTENSION rootFdo;
  1881. PPCI_ARBITER_INSTANCE pciArbiter;
  1882. BOOLEAN foundResource;
  1883. ULONGLONG dummy;
  1884. ArbAcquireArbiterLock(Arbiter);
  1885. fdoExtension = (PPCI_FDO_EXTENSION) Arbiter->BusDeviceObject->DeviceExtension;
  1886. ASSERT_PCI_FDO_EXTENSION(fdoExtension);
  1887. if (StartResources == NULL || PCI_IS_ROOT_FDO(fdoExtension)) {
  1888. //
  1889. // Root bridges don't have ISA bits - at least that we can see...
  1890. // Bridges with no resources also arn't effected by the ISA bit
  1891. //
  1892. status = STATUS_SUCCESS;
  1893. goto exit;
  1894. }
  1895. ASSERT(StartResources->Count == 1);
  1896. pdoExtension = PCI_BRIDGE_PDO(fdoExtension);
  1897. //
  1898. // Select the appropriate exclusion list
  1899. //
  1900. if (pdoExtension->Dependent.type1.IsaBitSet) {
  1901. if (pdoExtension->Dependent.type1.VgaBitSet) {
  1902. exclusionList = &PciVgaAndIsaBitExclusionList;
  1903. } else {
  1904. exclusionList = &PciIsaBitExclusionList;
  1905. }
  1906. }
  1907. //
  1908. // Find the port window and process it if the ISA bit is set
  1909. //
  1910. foundResource = FALSE;
  1911. FOR_ALL_IN_ARRAY(StartResources->List[0].PartialResourceList.PartialDescriptors,
  1912. StartResources->List[0].PartialResourceList.Count,
  1913. descriptor) {
  1914. //
  1915. // NTRAID #62585 - 04/03/2000 - andrewth
  1916. // Again we don't deal with bridges with BARS - for now assume
  1917. // that the first IO descriptor we encounter is for the window
  1918. //
  1919. if (descriptor->Type == CmResourceTypePort) {
  1920. if (exclusionList) {
  1921. status = PciExcludeRangesFromWindow(
  1922. descriptor->u.Port.Start.QuadPart,
  1923. descriptor->u.Port.Start.QuadPart
  1924. + descriptor->u.Port.Length - 1,
  1925. Arbiter->Allocation,
  1926. exclusionList
  1927. );
  1928. if (!NT_SUCCESS(status)) {
  1929. return status;
  1930. }
  1931. }
  1932. foundResource = TRUE;
  1933. break;
  1934. }
  1935. }
  1936. if (foundResource == FALSE) {
  1937. //
  1938. // There are no IO resourcres on this bus so don't try
  1939. // to handle the sparse root case.
  1940. //
  1941. status = STATUS_SUCCESS;
  1942. goto exit;
  1943. }
  1944. //
  1945. // Now deal with sparse root busses
  1946. //
  1947. rootFdo = PCI_ROOT_FDOX(fdoExtension);
  1948. //
  1949. // Find the root FDO's arbiter
  1950. //
  1951. pciArbiter = PciFindSecondaryExtension(rootFdo, PciArb_Io);
  1952. if (!pciArbiter) {
  1953. status = STATUS_INVALID_PARAMETER;
  1954. goto exit;
  1955. }
  1956. //
  1957. // Use it as the exclusion list for this arbiter
  1958. //
  1959. ArbAcquireArbiterLock(&pciArbiter->CommonInstance);
  1960. status = PciExcludeRangesFromWindow(
  1961. descriptor->u.Port.Start.QuadPart,
  1962. descriptor->u.Port.Start.QuadPart
  1963. + descriptor->u.Port.Length - 1,
  1964. Arbiter->Allocation,
  1965. pciArbiter->CommonInstance.Allocation
  1966. );
  1967. ArbReleaseArbiterLock(&pciArbiter->CommonInstance);
  1968. //
  1969. // Sanity check this to make sure that at least one port is available - if
  1970. // not then fail start. You could argue that we should really have this
  1971. // marked as insufficient resources (code 12) as oppose to failed start
  1972. // (code 10) but that is much harder and this has the desired effect.
  1973. // We check by seeing if we can find a range for the minimal PCI requirements
  1974. // of 4 ports alignment 4.
  1975. //
  1976. status = RtlFindRange(Arbiter->Allocation,
  1977. 0,
  1978. MAXULONGLONG,
  1979. 4,
  1980. 4,
  1981. 0, // Flags
  1982. 0, // AttribureAvailableMask
  1983. NULL, // Context
  1984. NULL, // Callback
  1985. &dummy
  1986. );
  1987. if (!NT_SUCCESS(status)) {
  1988. //
  1989. // We can't start this bridge
  1990. //
  1991. status = STATUS_INSUFFICIENT_RESOURCES;
  1992. }
  1993. exit:
  1994. ArbReleaseArbiterLock(Arbiter);
  1995. return status;
  1996. }
  1997. BOOLEAN
  1998. armem_FindSuitableRange(
  1999. PARBITER_INSTANCE Arbiter,
  2000. PARBITER_ALLOCATION_STATE State
  2001. )
  2002. /*++
  2003. Routine Description:
  2004. This routine is called from AllocateEntry once we have decided where we want
  2005. to allocate from. It tries to find a free range that matches the
  2006. requirements in State while restricting its possible solutions to the range
  2007. State->Start to State->CurrentMaximum. On success State->Start and
  2008. State->End represent this range. Conflicts between boot configs are allowed
  2009. Arguments:
  2010. Arbiter - The instance data of the arbiter who was called.
  2011. State - The state of the current arbitration.
  2012. Return Value:
  2013. TRUE if we found a range, FALSE otherwise.
  2014. --*/
  2015. {
  2016. //
  2017. // If this was a boot config then consider other boot configs to be
  2018. // available
  2019. //
  2020. if (State->Entry->Flags & ARBITER_FLAG_BOOT_CONFIG) {
  2021. State->RangeAvailableAttributes |= ARBITER_RANGE_BOOT_ALLOCATED;
  2022. }
  2023. //
  2024. // Do the default thing
  2025. //
  2026. return ArbFindSuitableRange(Arbiter, State);
  2027. }