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.

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