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.

1722 lines
47 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. ixirqarb.c
  5. Abstract:
  6. This module implements an arbiter for IRQs.
  7. Author:
  8. Santosh Jodh (santoshj) 22-June-1998
  9. Environment:
  10. NT Kernel Model Driver only
  11. --*/
  12. #include <nthal.h>
  13. #include <arbiter.h>
  14. #ifndef _IN_KERNEL_
  15. #define _IN_KERNEL_
  16. #include <regstr.h>
  17. #undef _IN_KERNEL_
  18. #else
  19. #include <regstr.h>
  20. #endif
  21. #if defined(NEC_98)
  22. #include <pci.h>
  23. #endif
  24. #include "ixpciir.h"
  25. #define ARBITER_CONTEXT_TO_INSTANCE(x) (x)
  26. #define ARBITER_INTERRUPT_LEVEL 0x10
  27. #define ARBITER_INTERRUPT_EDGE 0x20
  28. #define ARBITER_INTERRUPT_BITS (ARBITER_INTERRUPT_LEVEL | ARBITER_INTERRUPT_EDGE)
  29. #define NUM_IRQS 16
  30. #if defined(NEC_98)
  31. #define PIC_SLAVE_IRQ 7
  32. #else
  33. #define PIC_SLAVE_IRQ 2
  34. #endif
  35. extern ULONG HalDebug;
  36. #if defined(NEC_98)
  37. extern ULONG NEC98SpecialIRQMask;
  38. #endif
  39. #if DBG
  40. #define DEBUG_PRINT(Level, Message) { \
  41. if (HalDebug >= Level) { \
  42. DbgPrint("HAL: "); \
  43. DbgPrint Message; \
  44. DbgPrint("\n"); \
  45. } \
  46. }
  47. #else
  48. #define DEBUG_PRINT(Level, Message)
  49. #endif
  50. typedef struct {
  51. ARBITER_INSTANCE ArbiterState;
  52. } HAL_ARBITER, *PHAL_ARBITER;
  53. NTSTATUS
  54. HalpInitIrqArbiter (
  55. IN PDEVICE_OBJECT HalFdo
  56. );
  57. NTSTATUS
  58. HalpFillInIrqArbiter (
  59. IN PDEVICE_OBJECT DeviceObject,
  60. IN LPCGUID InterfaceType,
  61. IN USHORT Version,
  62. IN PVOID InterfaceSpecificData,
  63. IN ULONG InterfaceBufferSize,
  64. IN OUT PINTERFACE Interface,
  65. IN OUT PULONG Length
  66. );
  67. NTSTATUS
  68. HalpArbUnpackRequirement (
  69. IN PIO_RESOURCE_DESCRIPTOR Descriptor,
  70. OUT PULONGLONG Minimum,
  71. OUT PULONGLONG Maximum,
  72. OUT PULONG Length,
  73. OUT PULONG Alignment
  74. );
  75. NTSTATUS
  76. HalpArbPackResource (
  77. IN PIO_RESOURCE_DESCRIPTOR Requirement,
  78. IN ULONGLONG Start,
  79. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
  80. );
  81. NTSTATUS
  82. HalpArbUnpackResource (
  83. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
  84. OUT PULONGLONG Start,
  85. OUT PULONG Length
  86. );
  87. LONG
  88. HalpArbScoreRequirement (
  89. IN PIO_RESOURCE_DESCRIPTOR Descriptor
  90. );
  91. NTSTATUS
  92. HalpArbTestAllocation (
  93. IN PARBITER_INSTANCE Arbiter,
  94. IN OUT PLIST_ENTRY ArbitrationList
  95. );
  96. NTSTATUS
  97. HalpArbRetestAllocation (
  98. IN PARBITER_INSTANCE Arbiter,
  99. IN OUT PLIST_ENTRY ArbitrationList
  100. );
  101. NTSTATUS
  102. HalpArbCommitAllocation(
  103. IN PARBITER_INSTANCE Arbiter
  104. );
  105. NTSTATUS
  106. HalpArbRollbackAllocation (
  107. PARBITER_INSTANCE Arbiter
  108. );
  109. NTSTATUS
  110. HalpArbPreprocessEntry(
  111. IN PARBITER_INSTANCE Arbiter,
  112. IN PARBITER_ALLOCATION_STATE State
  113. );
  114. BOOLEAN
  115. HalpArbFindSuitableRange (
  116. PARBITER_INSTANCE Arbiter,
  117. PARBITER_ALLOCATION_STATE State
  118. );
  119. VOID
  120. HalpArbAddAllocation (
  121. IN PARBITER_INSTANCE Arbiter,
  122. IN PARBITER_ALLOCATION_STATE State
  123. );
  124. VOID
  125. HalpArbBacktrackAllocation (
  126. IN PARBITER_INSTANCE Arbiter,
  127. IN PARBITER_ALLOCATION_STATE State
  128. );
  129. NTSTATUS
  130. HalpArbBootAllocation(
  131. IN PARBITER_INSTANCE Arbiter,
  132. IN OUT PLIST_ENTRY ArbitrationList
  133. );
  134. BOOLEAN
  135. HalpArbGetNextAllocationRange(
  136. IN PARBITER_INSTANCE Arbiter,
  137. IN OUT PARBITER_ALLOCATION_STATE State
  138. );
  139. ULONG
  140. HalpFindLinkInterrupt (
  141. IN PRTL_RANGE_LIST RangeList,
  142. IN ULONG Mask,
  143. IN ULONG Start,
  144. IN ULONG End,
  145. IN ULONG Flags,
  146. IN UCHAR UserFlags
  147. );
  148. BOOLEAN
  149. HalpArbQueryConflictCallback(
  150. IN PVOID Context,
  151. IN PRTL_RANGE Range
  152. );
  153. VOID
  154. HalpIrqArbiterInterfaceReference(
  155. IN PVOID Context
  156. );
  157. VOID
  158. HalpIrqArbiterInterfaceDereference(
  159. IN PVOID Context
  160. );
  161. #ifdef ALLOC_PRAGMA
  162. #pragma alloc_text(PAGE, HalpInitIrqArbiter)
  163. #pragma alloc_text(PAGE, HalpFillInIrqArbiter)
  164. #pragma alloc_text(PAGE, HalpArbUnpackRequirement)
  165. #pragma alloc_text(PAGE, HalpArbPackResource)
  166. #pragma alloc_text(PAGE, HalpArbUnpackResource)
  167. #pragma alloc_text(PAGE, HalpArbScoreRequirement)
  168. #pragma alloc_text(PAGE, HalpArbTestAllocation)
  169. #pragma alloc_text(PAGE, HalpArbRetestAllocation)
  170. #pragma alloc_text(PAGE, HalpArbCommitAllocation)
  171. #pragma alloc_text(PAGE, HalpArbRollbackAllocation)
  172. #pragma alloc_text(PAGE, HalpArbPreprocessEntry)
  173. #pragma alloc_text(PAGE, HalpArbFindSuitableRange)
  174. #pragma alloc_text(PAGE, HalpArbAddAllocation)
  175. #pragma alloc_text(PAGE, HalpArbBacktrackAllocation)
  176. #pragma alloc_text(PAGE, HalpArbBootAllocation)
  177. #pragma alloc_text(PAGE, HalpArbGetNextAllocationRange)
  178. #pragma alloc_text(PAGE, HalpFindLinkInterrupt)
  179. #pragma alloc_text(PAGE, HalpArbQueryConflictCallback)
  180. #pragma alloc_text(PAGE, HalpIrqArbiterInterfaceReference)
  181. #pragma alloc_text(PAGE, HalpIrqArbiterInterfaceDereference)
  182. #endif
  183. #ifdef ALLOC_DATA_PRAGMA
  184. #pragma data_seg()
  185. #endif
  186. HAL_ARBITER HalpArbiter = {{
  187. 0,//Signature
  188. NULL,//MutexEvent
  189. NULL,//Name
  190. {0},//ResourceType
  191. NULL,//Allocation
  192. NULL,//PossibleAllocation
  193. {0},//OrderingList
  194. {0},//ReservedList
  195. 0,//ReferenceCount
  196. NULL,//Interface
  197. 0,//AllocationStackMaxSize
  198. NULL,//AllocationStack
  199. HalpArbUnpackRequirement,//UnpackRequirement
  200. HalpArbPackResource,//PackResource
  201. HalpArbUnpackResource,//UnpackResource
  202. HalpArbScoreRequirement,//ScoreRequirement
  203. HalpArbTestAllocation,//TestAllocation
  204. HalpArbRetestAllocation,//RetestAllocation
  205. HalpArbCommitAllocation,//CommitAllocation
  206. HalpArbRollbackAllocation,//RollbackAllocation
  207. HalpArbBootAllocation,//BootAllocation
  208. NULL,//QueryArbitrate
  209. NULL,//QueryConflict
  210. NULL,//AddReserved
  211. NULL,//StartArbiter
  212. HalpArbPreprocessEntry,//PreprocessEntry
  213. NULL,//AllocateEntry
  214. HalpArbGetNextAllocationRange,//GetNextAllocationRange
  215. HalpArbFindSuitableRange,//FindSuitableRange
  216. HalpArbAddAllocation,//AddAllocation
  217. HalpArbBacktrackAllocation,//BacktrackAllocation
  218. NULL,//OverrideConflict
  219. FALSE,//TransactionInProgress
  220. &HalpPciIrqRoutingInfo,//Extension
  221. NULL,//BusDeviceObject
  222. NULL,//ConflictCallbackContext
  223. NULL,//ConflictCallback
  224. }};
  225. BOOLEAN
  226. HalpArbQueryConflictCallback(
  227. IN PVOID Context,
  228. IN PRTL_RANGE Range
  229. )
  230. {
  231. PAGED_CODE();
  232. if (Range->Attributes & ARBITER_INTERRUPT_LEVEL)
  233. {
  234. if(Range->Flags & RTL_RANGE_SHARED)
  235. {
  236. return (TRUE);
  237. }
  238. else
  239. {
  240. DEBUG_PRINT(1, ("Exclusive level interrupt %02x cannot be shared!", (ULONG)Context));
  241. return (FALSE);
  242. }
  243. }
  244. DEBUG_PRINT(1, ("Refusing to share edge and level interrupts on %02x", (ULONG)Context));
  245. return (FALSE);
  246. }
  247. NTSTATUS
  248. HalpArbPreprocessEntry(
  249. IN PARBITER_INSTANCE Arbiter,
  250. IN PARBITER_ALLOCATION_STATE State
  251. )
  252. /*++
  253. Routine Description:
  254. This routine is called from AllocateEntry to allow preprocessing of
  255. entries
  256. Arguments:
  257. Arbiter - The instance data of the arbiter who was called.
  258. State - The state of the current arbitration.
  259. Return Value:
  260. None.
  261. --*/
  262. {
  263. #define CM_RESOURE_INTERRUPT_LEVEL_LATCHED_BITS 0x0001
  264. PARBITER_ALTERNATIVE current;
  265. PAGED_CODE();
  266. //
  267. // Validate arguments.
  268. //
  269. ASSERT(Arbiter);
  270. ASSERT(State);
  271. //
  272. // We should never be here if Pci Irq routing is not enabled.
  273. //
  274. ASSERT(IsPciIrqRoutingEnabled());
  275. //
  276. // Check if this is a level (PCI) or latched (ISA (edge)) interrupt and set
  277. // RangeAttributes accordingly so we set the appropriate flag when we add the
  278. // range
  279. //
  280. if ((State->Alternatives[0].Descriptor->Flags
  281. & CM_RESOURE_INTERRUPT_LEVEL_LATCHED_BITS)
  282. == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE)
  283. {
  284. State->RangeAttributes &= ~ARBITER_INTERRUPT_BITS;
  285. State->RangeAttributes |= ARBITER_INTERRUPT_LEVEL;
  286. } else
  287. {
  288. ASSERT(State->Alternatives[0].Descriptor->Flags
  289. & CM_RESOURCE_INTERRUPT_LATCHED);
  290. State->RangeAttributes &= ~ARBITER_INTERRUPT_BITS;
  291. State->RangeAttributes |= ARBITER_INTERRUPT_EDGE;
  292. }
  293. return (STATUS_SUCCESS);
  294. }
  295. BOOLEAN
  296. HalpArbGetNextAllocationRange(
  297. IN PARBITER_INSTANCE Arbiter,
  298. IN OUT PARBITER_ALLOCATION_STATE State
  299. )
  300. {
  301. //
  302. // Default to having no next range.
  303. //
  304. BOOLEAN nextRange = FALSE;
  305. PAGED_CODE();
  306. //
  307. // Try all possible interrupts on first call.
  308. //
  309. if (State->CurrentAlternative) {
  310. if (++State->CurrentAlternative < &State->Alternatives[State->AlternativeCount]) {
  311. DEBUG_PRINT(3, ("No next allocation range, exhausted all %08X alternatives", State->AlternativeCount));
  312. nextRange = TRUE;
  313. }
  314. }
  315. else {
  316. //
  317. // First call, try the first alternative.
  318. //
  319. State->CurrentAlternative = &State->Alternatives[0];
  320. nextRange = TRUE;
  321. }
  322. if (nextRange) {
  323. State->CurrentMinimum = State->CurrentAlternative->Minimum;
  324. State->CurrentMaximum = State->CurrentAlternative->Maximum;
  325. DEBUG_PRINT(3, ("Next allocation range 0x%I64x-0x%I64x", State->CurrentMinimum, State->CurrentMaximum));
  326. }
  327. return nextRange;
  328. }
  329. ULONG
  330. HalpFindLinkInterrupt (
  331. IN PRTL_RANGE_LIST RangeList,
  332. IN ULONG Mask,
  333. IN ULONG Start,
  334. IN ULONG End,
  335. IN ULONG Flags,
  336. IN UCHAR UserFlags
  337. )
  338. /*++
  339. Routine Description:
  340. This routine scans the mask from MSB to LSB for the first
  341. value that is available in the range list.
  342. Input Parameters:
  343. RangeList - List to be searched.
  344. Mask - Interrupt mask to be scanned.
  345. Start - Start scan AFTER this interrupt.
  346. Flags - Flags for the range list.
  347. UserFlags - Special flags.
  348. Return Value:
  349. First available interrupt from the mask iff successful. Else 0.
  350. --*/
  351. {
  352. ULONG interrupt;
  353. ULONG test;
  354. NTSTATUS status;
  355. BOOLEAN available;
  356. PAGED_CODE();
  357. if (Start > 0x0F)
  358. {
  359. Start = 0x0F;
  360. }
  361. if (Start != 0 && Start >= End)
  362. {
  363. interrupt = Start;
  364. test = 1 << interrupt;
  365. do
  366. {
  367. //
  368. // If this interrupt is supported, see if it is free.
  369. //
  370. if (Mask & test)
  371. {
  372. available = FALSE;
  373. status = RtlIsRangeAvailable( RangeList,
  374. interrupt,
  375. interrupt,
  376. Flags,
  377. UserFlags,
  378. (PVOID)interrupt,
  379. HalpArbQueryConflictCallback,
  380. &available);
  381. if (NT_SUCCESS(status) && available)
  382. {
  383. return (interrupt);
  384. }
  385. }
  386. interrupt--;
  387. test >>= 1;
  388. }
  389. while (interrupt > End);
  390. }
  391. return (0);
  392. }
  393. BOOLEAN
  394. HalpArbFindSuitableRange (
  395. PARBITER_INSTANCE Arbiter,
  396. PARBITER_ALLOCATION_STATE State
  397. )
  398. /*++
  399. Routine Description:
  400. This
  401. Input Parameters:
  402. Return Value:
  403. --*/
  404. {
  405. PPCI_IRQ_ROUTING_INFO pciIrqRoutingInfo;
  406. NTSTATUS status;
  407. PLINK_NODE linkNode;
  408. ULONG interrupt;
  409. ULONG freeInterrupt;
  410. PLINK_NODE current;
  411. ULONG busNumber;
  412. ULONG slotNumber;
  413. #if defined(NEC_98)
  414. PINT_ROUTE_INTERFACE_STANDARD pciInterface;
  415. ULONG dummy;
  416. UCHAR classCode;
  417. UCHAR subClassCode;
  418. ROUTING_TOKEN routingToken;
  419. UCHAR pin;
  420. #endif
  421. PAGED_CODE();
  422. //
  423. // Validate arguments.
  424. //
  425. ASSERT(Arbiter);
  426. ASSERT(State);
  427. //
  428. // We should never be here if Pci Irq routing is not enabled.
  429. //
  430. ASSERT(IsPciIrqRoutingEnabled());
  431. pciIrqRoutingInfo = Arbiter->Extension;
  432. ASSERT(pciIrqRoutingInfo);
  433. ASSERT(pciIrqRoutingInfo == &HalpPciIrqRoutingInfo);
  434. if (State->Entry->InterfaceType == PCIBus)
  435. {
  436. #if defined(NEC_98)
  437. pciInterface = pciIrqRoutingInfo->PciInterface;
  438. //
  439. // Call Pci driver to get info about the Pdo.
  440. //
  441. status = pciInterface->GetInterruptRouting( State->Entry->PhysicalDeviceObject,
  442. &busNumber,
  443. &slotNumber,
  444. (PUCHAR)&dummy,
  445. &pin,
  446. &classCode,
  447. &subClassCode,
  448. (PDEVICE_OBJECT *)&dummy,
  449. &routingToken,
  450. (PUCHAR)&dummy);
  451. //
  452. // This means that it is not a Pci device.
  453. //
  454. if (!NT_SUCCESS(status))
  455. {
  456. return (FALSE);
  457. }
  458. #endif
  459. busNumber = State->Entry->BusNumber;
  460. slotNumber = State->Entry->SlotNumber;
  461. }
  462. else
  463. {
  464. busNumber = (ULONG)-1;
  465. slotNumber = (ULONG)-1;
  466. }
  467. //
  468. // See if there is link information for this device.
  469. //
  470. linkNode = NULL;
  471. status = HalpFindLinkNode ( pciIrqRoutingInfo,
  472. State->Entry->PhysicalDeviceObject,
  473. busNumber,
  474. slotNumber,
  475. &linkNode);
  476. switch (status)
  477. {
  478. case STATUS_SUCCESS:
  479. if (linkNode == NULL)
  480. {
  481. DEBUG_PRINT(1, ("Link does not exist for Pci PDO %08x. Hopefully, device can live without an interrupt!", State->Entry->PhysicalDeviceObject));
  482. return (FALSE);
  483. }
  484. //
  485. // If we have already decided an interrupt for this link,
  486. // everyone using it gets the same interrupt.
  487. //
  488. if (linkNode->PossibleAllocation->RefCount > 0)
  489. {
  490. if ( State->CurrentMinimum <= linkNode->PossibleAllocation->Interrupt &&
  491. linkNode->PossibleAllocation->Interrupt <= State->CurrentMaximum)
  492. {
  493. State->Start = linkNode->PossibleAllocation->Interrupt;
  494. State->End = State->Start;
  495. State->CurrentAlternative->Length = 1;
  496. DEBUG_PRINT(2, ("Found Irq (%04x) for Pci PDO %08x using link %02x", (ULONG)State->Start, State->Entry->PhysicalDeviceObject, linkNode->Link));
  497. return (TRUE);
  498. }
  499. else
  500. {
  501. DEBUG_PRINT(1, ("Found Irq (%04x) for Pci PDO %08x using link %02x but is outside the range (%04x-%04x)!", (ULONG)State->Start, State->Entry->PhysicalDeviceObject, linkNode->Link, State->CurrentMinimum, State->CurrentMaximum));
  502. return (FALSE);
  503. }
  504. }
  505. else
  506. {
  507. //
  508. // We want to spread out the links as much as we can for
  509. // performance.
  510. //
  511. //
  512. // First see if this link is programmed for some IRQ.
  513. //
  514. interrupt = 0;
  515. status = PciirqmpGetIrq((PUCHAR)&interrupt, (UCHAR)linkNode->Link);
  516. if (NT_SUCCESS(status) && interrupt)
  517. {
  518. if (State->CurrentMinimum <= interrupt && interrupt <= State->CurrentMaximum)
  519. {
  520. //
  521. // Make sure the BIOS did not mess up
  522. //
  523. freeInterrupt = HalpFindLinkInterrupt ( Arbiter->PossibleAllocation,
  524. linkNode->InterruptMap,
  525. interrupt,
  526. interrupt,
  527. 0,
  528. 0);
  529. if(freeInterrupt == 0)
  530. {
  531. DEBUG_PRINT(1, ("BIOS failure. Assigned Irq (%02x) to link %02x which is unavailable or impossible according to mask %04x", interrupt, linkNode->Link, linkNode->InterruptMap));
  532. }
  533. interrupt = freeInterrupt;
  534. }
  535. else
  536. {
  537. DEBUG_PRINT(1, ("Found Irq (%04x) pre-programmedfor link %02x but is outside the range (%04x-%04x)!", interrupt, linkNode->Link, State->CurrentMinimum, State->CurrentMaximum));
  538. return (FALSE);
  539. }
  540. }
  541. if (interrupt == 0)
  542. {
  543. #if defined(NEC_98)
  544. if (NEC98SpecialIRQMask){
  545. linkNode->InterruptMap &= ~( 1 << NEC98SpecialIRQMask);
  546. }
  547. #endif
  548. //
  549. // Try to get an interrupt by itself for this link.
  550. //
  551. interrupt = HalpFindLinkInterrupt ( Arbiter->PossibleAllocation,
  552. linkNode->InterruptMap,
  553. (ULONG)State->CurrentMaximum,
  554. (ULONG)State->CurrentMinimum,
  555. 0,
  556. 0);
  557. #if defined(NEC_98)
  558. //
  559. // Force to share CardBus IRQ with another PCI Device
  560. //
  561. if ( interrupt &&
  562. classCode == PCI_CLASS_BRIDGE_DEV &&
  563. subClassCode == PCI_SUBCLASS_BR_CARDBUS )
  564. {
  565. //
  566. // Remember this.
  567. //
  568. freeInterrupt = interrupt;
  569. do
  570. {
  571. //
  572. // Is this being used by another link?
  573. //
  574. current = pciIrqRoutingInfo->LinkNodeHead;
  575. while ( current != NULL) {
  576. if ( current->PossibleAllocation->Interrupt == interrupt )
  577. {
  578. //
  579. // somebody use this. Cardbus controller use this, too.
  580. //
  581. interrupt = 0;
  582. break;
  583. }
  584. current = current->Next;
  585. }
  586. if (interrupt){
  587. interrupt = HalpFindLinkInterrupt ( Arbiter->PossibleAllocation,
  588. linkNode->InterruptMap,
  589. interrupt - 1,
  590. (ULONG)State->CurrentMinimum,
  591. 0,
  592. 0);
  593. if (interrupt) {
  594. //
  595. // Remember this, if find new interrupt.
  596. //
  597. freeInterrupt = interrupt;
  598. }
  599. }
  600. }
  601. while (interrupt);
  602. if (!interrupt)
  603. {
  604. interrupt = freeInterrupt;
  605. }
  606. } else if ( interrupt )
  607. #else
  608. if (interrupt)
  609. #endif
  610. {
  611. //
  612. // Remember this.
  613. //
  614. freeInterrupt = interrupt;
  615. do
  616. {
  617. //
  618. // Is this being used by another link?
  619. //
  620. for ( current = pciIrqRoutingInfo->LinkNodeHead;
  621. current && current->PossibleAllocation->Interrupt != interrupt;
  622. current = current->Next);
  623. if (current == NULL)
  624. {
  625. break;
  626. }
  627. interrupt = HalpFindLinkInterrupt ( Arbiter->PossibleAllocation,
  628. linkNode->InterruptMap,
  629. interrupt - 1,
  630. (ULONG)State->CurrentMinimum,
  631. 0,
  632. 0);
  633. }
  634. while (interrupt);
  635. if (!interrupt)
  636. {
  637. if (!(pciIrqRoutingInfo->Parameters & PCIIR_FLAG_EXCLUSIVE)) {
  638. interrupt = freeInterrupt;
  639. }
  640. }
  641. }
  642. }
  643. if (interrupt)
  644. {
  645. State->Start = interrupt;
  646. State->End = interrupt;
  647. State->CurrentAlternative->Length = 1;
  648. DEBUG_PRINT(2, ("Found Irq (%04x) for Pci PDO %08x using link %02x", (ULONG)State->Start, State->Entry->PhysicalDeviceObject, linkNode->Link));
  649. return (TRUE);
  650. }
  651. }
  652. //
  653. // There is no interrupt this link can use, too bad.
  654. //
  655. return (FALSE);
  656. case STATUS_RESOURCE_REQUIREMENTS_CHANGED:
  657. //
  658. // Pci Ide device does not share Irqs.
  659. //
  660. if (State->CurrentAlternative->Flags & ARBITER_ALTERNATIVE_FLAG_SHARED) {
  661. State->CurrentAlternative->Flags &= ~ARBITER_ALTERNATIVE_FLAG_SHARED;
  662. }
  663. default:
  664. //
  665. // Non Pci device.
  666. //
  667. break;
  668. }
  669. //
  670. // HACKHACK: This is to allow boot conflict on IRQ 14 and 15.
  671. // This is so that broken machines which report both PNP06xx and
  672. // the PCI IDE controller work. One of them (no order guarantee)
  673. // will come up with a conflict.
  674. //
  675. if (State->Entry->Flags & ARBITER_FLAG_BOOT_CONFIG) {
  676. if ( State->CurrentMinimum == State->CurrentMaximum &&
  677. (State->CurrentMinimum == 14 || State->CurrentMinimum == 15)) {
  678. State->RangeAvailableAttributes |= ARBITER_RANGE_BOOT_ALLOCATED;
  679. }
  680. }
  681. return (ArbFindSuitableRange(Arbiter, State));
  682. }
  683. VOID
  684. HalpArbAddAllocation(
  685. IN PARBITER_INSTANCE Arbiter,
  686. IN PARBITER_ALLOCATION_STATE State
  687. )
  688. {
  689. PPCI_IRQ_ROUTING_INFO pciIrqRoutingInfo;
  690. NTSTATUS status;
  691. PLINK_NODE linkNode;
  692. PAGED_CODE();
  693. //
  694. // Validate arguments.
  695. //
  696. ASSERT(Arbiter);
  697. ASSERT(State);
  698. //
  699. // We should never be here if Pci Irq routing is not enabled.
  700. //
  701. ASSERT(IsPciIrqRoutingEnabled());
  702. pciIrqRoutingInfo = Arbiter->Extension;
  703. ASSERT(pciIrqRoutingInfo);
  704. ASSERT(pciIrqRoutingInfo == &HalpPciIrqRoutingInfo);
  705. DEBUG_PRINT(3, ("Adding Irq (%04x) allocation for PDO %08x", (ULONG)State->Start, State->Entry->PhysicalDeviceObject));
  706. linkNode = NULL;
  707. status = HalpFindLinkNode ( pciIrqRoutingInfo,
  708. State->Entry->PhysicalDeviceObject,
  709. State->Entry->BusNumber,
  710. State->Entry->SlotNumber,
  711. &linkNode);
  712. if (NT_SUCCESS(status) && status != STATUS_RESOURCE_REQUIREMENTS_CHANGED)
  713. {
  714. if (linkNode)
  715. {
  716. if (linkNode->PossibleAllocation->RefCount)
  717. {
  718. if (linkNode->PossibleAllocation->Interrupt != State->Start)
  719. {
  720. DEBUG_PRINT(1, ("Two different interrupts (old = %08x, new = %08x) for the same link %08x!", linkNode->PossibleAllocation->Interrupt, State->Start, linkNode->Link));
  721. ASSERT(linkNode->PossibleAllocation->Interrupt == State->Start);
  722. }
  723. }
  724. else
  725. {
  726. DEBUG_PRINT(3, ("Adding new Irq (%04x) allocation for Pci PDO %08x using link %02x", (ULONG)State->Start, State->Entry->PhysicalDeviceObject, linkNode->Link));
  727. linkNode->PossibleAllocation->Interrupt = (ULONG)State->Start;
  728. }
  729. linkNode->PossibleAllocation->RefCount++;
  730. }
  731. else
  732. {
  733. DEBUG_PRINT(1, ("This should never happen!"));
  734. ASSERT(linkNode);
  735. }
  736. }
  737. status = RtlAddRange( Arbiter->PossibleAllocation,
  738. State->Start,
  739. State->End,
  740. State->RangeAttributes,
  741. RTL_RANGE_LIST_ADD_IF_CONFLICT +
  742. ((State->CurrentAlternative->Flags &
  743. ARBITER_ALTERNATIVE_FLAG_SHARED)?
  744. RTL_RANGE_LIST_ADD_SHARED : 0),
  745. linkNode, // This line is different from the default function
  746. State->Entry->PhysicalDeviceObject);
  747. ASSERT(NT_SUCCESS(status));
  748. }
  749. VOID
  750. HalpArbBacktrackAllocation (
  751. IN PARBITER_INSTANCE Arbiter,
  752. IN PARBITER_ALLOCATION_STATE State
  753. )
  754. {
  755. PPCI_IRQ_ROUTING_INFO pciIrqRoutingInfo;
  756. NTSTATUS status;
  757. PLINK_NODE linkNode;
  758. PAGED_CODE();
  759. //
  760. // Validate arguments.
  761. //
  762. ASSERT(Arbiter);
  763. ASSERT(State);
  764. //
  765. // We should never be here if Pci Irq routing is not enabled.
  766. //
  767. ASSERT(IsPciIrqRoutingEnabled());
  768. pciIrqRoutingInfo = Arbiter->Extension;
  769. ASSERT(pciIrqRoutingInfo);
  770. ASSERT(pciIrqRoutingInfo == &HalpPciIrqRoutingInfo);
  771. DEBUG_PRINT(3, ("Backtracking Irq (%04x) allocation for PDO %08x", (ULONG)State->Start, State->Entry->PhysicalDeviceObject));
  772. linkNode = NULL;
  773. status = HalpFindLinkNode ( pciIrqRoutingInfo,
  774. State->Entry->PhysicalDeviceObject,
  775. State->Entry->BusNumber,
  776. State->Entry->SlotNumber,
  777. &linkNode);
  778. if (NT_SUCCESS(status) && status == STATUS_SUCCESS)
  779. {
  780. if (linkNode)
  781. {
  782. if (linkNode->PossibleAllocation->RefCount == 0)
  783. {
  784. DEBUG_PRINT(1, ("Negative ref count during backtracking!"));
  785. ASSERT(linkNode->PossibleAllocation->RefCount);
  786. }
  787. else
  788. {
  789. DEBUG_PRINT(3, ("Backtracking Irq (%04x) allocation for Pci PDO %08x using link %02x", (ULONG)State->Start, State->Entry->PhysicalDeviceObject, linkNode->Link));
  790. linkNode->PossibleAllocation->RefCount--;
  791. if (linkNode->PossibleAllocation->RefCount == 0)
  792. {
  793. linkNode->PossibleAllocation->Interrupt = 0;
  794. }
  795. }
  796. }
  797. else
  798. {
  799. DEBUG_PRINT(1, ("This should never happen!"));
  800. ASSERT(linkNode);
  801. }
  802. }
  803. //
  804. // Let the default function do most of the work.
  805. //
  806. ArbBacktrackAllocation(Arbiter, State);
  807. }
  808. NTSTATUS
  809. HalpArbCommitAllocation(
  810. IN PARBITER_INSTANCE Arbiter
  811. )
  812. {
  813. PPCI_IRQ_ROUTING_INFO pciIrqRoutingInfo;
  814. RTL_RANGE_LIST_ITERATOR iterator;
  815. PRTL_RANGE current;
  816. PLINK_NODE linkNode;
  817. NTSTATUS status;
  818. PAGED_CODE();
  819. //
  820. // Validate arguments.
  821. //
  822. ASSERT(Arbiter);
  823. //
  824. // We should never be here if Pci Irq routing is not enabled.
  825. //
  826. ASSERT(IsPciIrqRoutingEnabled());
  827. pciIrqRoutingInfo = Arbiter->Extension;
  828. ASSERT(pciIrqRoutingInfo);
  829. ASSERT(pciIrqRoutingInfo == &HalpPciIrqRoutingInfo);
  830. //
  831. // Program the int line register for all Pci devices.
  832. //
  833. FOR_ALL_RANGES(Arbiter->PossibleAllocation, &iterator, current)
  834. {
  835. if (current->UserData)
  836. {
  837. HalpProgramInterruptLine ( pciIrqRoutingInfo,
  838. current->Owner,
  839. (ULONG)current->Start);
  840. }
  841. }
  842. //
  843. // Program all links to their possible value if
  844. // there is a reference to them.
  845. //
  846. for ( linkNode = pciIrqRoutingInfo->LinkNodeHead;
  847. linkNode;
  848. linkNode = linkNode->Next)
  849. {
  850. status = HalpCommitLink(linkNode);
  851. if (!NT_SUCCESS(status))
  852. {
  853. return (status);
  854. }
  855. }
  856. //
  857. // Let the default function do the rest of the work.
  858. //
  859. return (ArbCommitAllocation(Arbiter));
  860. }
  861. NTSTATUS
  862. HalpArbTestAllocation (
  863. IN PARBITER_INSTANCE Arbiter,
  864. IN OUT PLIST_ENTRY ArbitrationList
  865. )
  866. {
  867. PPCI_IRQ_ROUTING_INFO pciIrqRoutingInfo;
  868. PLINK_NODE linkNode;
  869. NTSTATUS status;
  870. PARBITER_LIST_ENTRY current;
  871. PDEVICE_OBJECT previousOwner;
  872. PDEVICE_OBJECT currentOwner;
  873. RTL_RANGE_LIST_ITERATOR iterator;
  874. PRTL_RANGE currentRange;
  875. PAGED_CODE();
  876. //
  877. // Validate arguments.
  878. //
  879. ASSERT(Arbiter);
  880. ASSERT(ArbitrationList);
  881. //
  882. // We should never be here if Pci Irq routing is not enabled.
  883. //
  884. ASSERT(IsPciIrqRoutingEnabled());
  885. pciIrqRoutingInfo = Arbiter->Extension;
  886. ASSERT(pciIrqRoutingInfo);
  887. ASSERT(pciIrqRoutingInfo == &HalpPciIrqRoutingInfo);
  888. //
  889. // Copy the allocation into the possible allocation for
  890. // for links.
  891. //
  892. for ( linkNode = pciIrqRoutingInfo->LinkNodeHead;
  893. linkNode;
  894. linkNode = linkNode->Next)
  895. {
  896. *linkNode->PossibleAllocation = *linkNode->Allocation;
  897. }
  898. previousOwner = NULL;
  899. FOR_ALL_IN_LIST(ARBITER_LIST_ENTRY, ArbitrationList, current)
  900. {
  901. currentOwner = current->PhysicalDeviceObject;
  902. if (previousOwner != currentOwner) {
  903. previousOwner = currentOwner;
  904. FOR_ALL_RANGES(Arbiter->Allocation, &iterator, currentRange)
  905. {
  906. if (currentRange->Owner == currentOwner)
  907. {
  908. status = HalpFindLinkNode ( pciIrqRoutingInfo,
  909. currentOwner,
  910. current->BusNumber,
  911. current->SlotNumber,
  912. &linkNode);
  913. if (NT_SUCCESS(status) && status == STATUS_SUCCESS)
  914. {
  915. if (linkNode)
  916. {
  917. if (linkNode->PossibleAllocation->RefCount > 0)
  918. {
  919. DEBUG_PRINT(3, ("Decrementing link (%02x) usage to %d during test allocation", linkNode->Link, linkNode->PossibleAllocation->RefCount - 1));
  920. linkNode->PossibleAllocation->RefCount--;
  921. if (linkNode->PossibleAllocation->RefCount == 0)
  922. {
  923. DEBUG_PRINT(3, ("Deleting Irq (%04x) allocation for link (%02x) during test allocation", linkNode->PossibleAllocation->Interrupt, linkNode->Link));
  924. linkNode->PossibleAllocation->Interrupt = 0;
  925. }
  926. }
  927. }
  928. }
  929. }
  930. }
  931. }
  932. }
  933. //
  934. // Let the default function do most of the work.
  935. //
  936. return (ArbTestAllocation(Arbiter, ArbitrationList));
  937. }
  938. NTSTATUS
  939. HalpArbRetestAllocation (
  940. IN PARBITER_INSTANCE Arbiter,
  941. IN OUT PLIST_ENTRY ArbitrationList
  942. )
  943. {
  944. PPCI_IRQ_ROUTING_INFO pciIrqRoutingInfo;
  945. PLINK_NODE linkNode;
  946. NTSTATUS status;
  947. PARBITER_LIST_ENTRY current;
  948. PDEVICE_OBJECT previousOwner;
  949. PDEVICE_OBJECT currentOwner;
  950. RTL_RANGE_LIST_ITERATOR iterator;
  951. PRTL_RANGE currentRange;
  952. PAGED_CODE();
  953. //
  954. // Validate arguments.
  955. //
  956. ASSERT(Arbiter);
  957. ASSERT(ArbitrationList);
  958. //
  959. // We should never be here if Pci Irq routing is not enabled.
  960. //
  961. ASSERT(IsPciIrqRoutingEnabled());
  962. pciIrqRoutingInfo = Arbiter->Extension;
  963. ASSERT(pciIrqRoutingInfo);
  964. ASSERT(pciIrqRoutingInfo == &HalpPciIrqRoutingInfo);
  965. //
  966. // Copy the allocation into the possible allocation for
  967. // for links.
  968. //
  969. for ( linkNode = pciIrqRoutingInfo->LinkNodeHead;
  970. linkNode;
  971. linkNode = linkNode->Next)
  972. {
  973. *linkNode->PossibleAllocation = *linkNode->Allocation;
  974. }
  975. previousOwner = NULL;
  976. FOR_ALL_IN_LIST(ARBITER_LIST_ENTRY, ArbitrationList, current)
  977. {
  978. currentOwner = current->PhysicalDeviceObject;
  979. if (previousOwner != currentOwner) {
  980. previousOwner = currentOwner;
  981. FOR_ALL_RANGES(Arbiter->Allocation, &iterator, currentRange)
  982. {
  983. if (currentRange->Owner == currentOwner)
  984. {
  985. status = HalpFindLinkNode ( pciIrqRoutingInfo,
  986. currentOwner,
  987. current->BusNumber,
  988. current->SlotNumber,
  989. &linkNode);
  990. if (NT_SUCCESS(status) && status == STATUS_SUCCESS)
  991. {
  992. if (linkNode)
  993. {
  994. if (linkNode->PossibleAllocation->RefCount > 0)
  995. {
  996. DEBUG_PRINT(3, ("Decrementing link (%02x) usage to %d during retest allocation", linkNode->Link, linkNode->PossibleAllocation->RefCount - 1));
  997. linkNode->PossibleAllocation->RefCount--;
  998. if (linkNode->PossibleAllocation->RefCount == 0)
  999. {
  1000. DEBUG_PRINT(3, ("Deleting Irq (%04x) allocation for link (%02x) during retest allocation", linkNode->PossibleAllocation->Interrupt, linkNode->Link));
  1001. linkNode->PossibleAllocation->Interrupt = 0;
  1002. }
  1003. }
  1004. }
  1005. }
  1006. }
  1007. }
  1008. }
  1009. }
  1010. return (ArbRetestAllocation(Arbiter, ArbitrationList));
  1011. }
  1012. NTSTATUS
  1013. HalpArbBootAllocation(
  1014. IN PARBITER_INSTANCE Arbiter,
  1015. IN OUT PLIST_ENTRY ArbitrationList
  1016. )
  1017. {
  1018. PPCI_IRQ_ROUTING_INFO pciIrqRoutingInfo;
  1019. PLINK_NODE linkNode;
  1020. NTSTATUS status;
  1021. PAGED_CODE();
  1022. //
  1023. // Validate arguments.
  1024. //
  1025. ASSERT(Arbiter);
  1026. ASSERT(ArbitrationList);
  1027. //
  1028. // We should never be here if Pci Irq routing is not enabled.
  1029. //
  1030. ASSERT(IsPciIrqRoutingEnabled());
  1031. pciIrqRoutingInfo = Arbiter->Extension;
  1032. ASSERT(pciIrqRoutingInfo);
  1033. ASSERT(pciIrqRoutingInfo == &HalpPciIrqRoutingInfo);
  1034. //
  1035. // Copy the allocation into the possible allocation for
  1036. // for links.
  1037. //
  1038. for ( linkNode = pciIrqRoutingInfo->LinkNodeHead;
  1039. linkNode;
  1040. linkNode = linkNode->Next)
  1041. {
  1042. *linkNode->PossibleAllocation = *linkNode->Allocation;
  1043. }
  1044. status = ArbBootAllocation(Arbiter, ArbitrationList);
  1045. //
  1046. // Copy possible allocation back into allocation for links.
  1047. //
  1048. for ( linkNode = pciIrqRoutingInfo->LinkNodeHead;
  1049. linkNode;
  1050. linkNode = linkNode->Next)
  1051. {
  1052. *linkNode->Allocation = *linkNode->PossibleAllocation;
  1053. }
  1054. return status;
  1055. }
  1056. NTSTATUS
  1057. HalpArbRollbackAllocation (
  1058. PARBITER_INSTANCE Arbiter
  1059. )
  1060. {
  1061. PPCI_IRQ_ROUTING_INFO pciIrqRoutingInfo;
  1062. PLINK_NODE linkNode;
  1063. ULONG interrupt;
  1064. PAGED_CODE();
  1065. //
  1066. // Validate arguments.
  1067. //
  1068. ASSERT(Arbiter);
  1069. //
  1070. // We should never be here if Pci Irq routing is not enabled.
  1071. //
  1072. ASSERT(IsPciIrqRoutingEnabled());
  1073. pciIrqRoutingInfo = Arbiter->Extension;
  1074. ASSERT(pciIrqRoutingInfo);
  1075. ASSERT(pciIrqRoutingInfo == &HalpPciIrqRoutingInfo);
  1076. //
  1077. // Clear the possible allocation.
  1078. //
  1079. for ( linkNode = pciIrqRoutingInfo->LinkNodeHead;
  1080. linkNode;
  1081. linkNode = linkNode->Next)
  1082. {
  1083. linkNode->PossibleAllocation->Interrupt = 0;
  1084. linkNode->PossibleAllocation->RefCount = 0;
  1085. }
  1086. //
  1087. // Let the default function do rest of the work.
  1088. //
  1089. return (ArbRollbackAllocation(Arbiter));
  1090. }
  1091. NTSTATUS
  1092. HalpArbUnpackRequirement (
  1093. IN PIO_RESOURCE_DESCRIPTOR Descriptor,
  1094. OUT PULONGLONG Minimum,
  1095. OUT PULONGLONG Maximum,
  1096. OUT PULONG Length,
  1097. OUT PULONG Alignment
  1098. )
  1099. /*++
  1100. Routine Description:
  1101. This routine unpacks the requirement descriptor into a minimum, maximum value
  1102. and the length and its alignment.
  1103. Input Parameters:
  1104. Descriptor - Requirement to be unpacked.
  1105. Minimum - Receives the minimum value for the requirement.
  1106. Maximum - Receives the maximum value for this requirement.
  1107. Length - Length of the requirement.
  1108. Alignment - Alignment of this requirement.
  1109. Return Value:
  1110. Standard NT status value.
  1111. --*/
  1112. {
  1113. PAGED_CODE();
  1114. //
  1115. // Validate arguments.
  1116. //
  1117. ASSERT(Descriptor);
  1118. ASSERT(Minimum);
  1119. ASSERT(Maximum);
  1120. ASSERT(Length);
  1121. ASSERT(Alignment);
  1122. //
  1123. // Make sure we are dealing with the correct resource.
  1124. //
  1125. ASSERT(Descriptor->Type == CmResourceTypeInterrupt);
  1126. //
  1127. // We should never be here if Pci Irq routing is not enabled.
  1128. //
  1129. ASSERT(IsPciIrqRoutingEnabled());
  1130. //
  1131. // Do unpacking.
  1132. //
  1133. *Minimum = (ULONGLONG) Descriptor->u.Interrupt.MinimumVector;
  1134. *Maximum = (ULONGLONG) Descriptor->u.Interrupt.MaximumVector;
  1135. *Length = 1;
  1136. *Alignment = 1;
  1137. DEBUG_PRINT(3, ("Unpacking Irq requirement %p = 0x%04lx - 0x%04lx", Descriptor, *Minimum, *Maximum));
  1138. return (STATUS_SUCCESS);
  1139. }
  1140. NTSTATUS
  1141. HalpArbPackResource (
  1142. IN PIO_RESOURCE_DESCRIPTOR Requirement,
  1143. IN ULONGLONG Start,
  1144. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
  1145. )
  1146. /*++
  1147. Routine Description:
  1148. This routine packs the resource descriptor from a starting value and the requirement.
  1149. Input Parameters:
  1150. Requirement - Resource requirement to be packed into the resource descriptor.
  1151. Start - Starting value for this resource.
  1152. Descriptor - Resource descriptor to be packed.
  1153. Return Value:
  1154. STATUS_SUCCESS.
  1155. --*/
  1156. {
  1157. PAGED_CODE();
  1158. //
  1159. // Validate arguments.
  1160. //
  1161. ASSERT(Requirement);
  1162. ASSERT(Start < (ULONG)-1);
  1163. ASSERT(Descriptor);
  1164. //
  1165. // Make sure we are dealing with the correct resource.
  1166. //
  1167. ASSERT(Requirement->Type == CmResourceTypeInterrupt);
  1168. //
  1169. // We should never be here if Pci Irq routing is not enabled.
  1170. //
  1171. ASSERT(IsPciIrqRoutingEnabled());
  1172. Descriptor->Type = CmResourceTypeInterrupt;
  1173. Descriptor->Flags = Requirement->Flags;
  1174. Descriptor->ShareDisposition = Requirement->ShareDisposition;
  1175. Descriptor->u.Interrupt.Vector = (ULONG) Start;
  1176. Descriptor->u.Interrupt.Level = (ULONG) Start;
  1177. Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
  1178. DEBUG_PRINT(3, ("Packing Irq resource %p = 0x%04lx", Descriptor, (ULONG)Start));
  1179. return (STATUS_SUCCESS);
  1180. }
  1181. NTSTATUS
  1182. HalpArbUnpackResource (
  1183. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
  1184. OUT PULONGLONG Start,
  1185. OUT PULONG Length
  1186. )
  1187. /*++
  1188. Routine Description:
  1189. This routine unpacks the resource descriptor into a starting value and length.
  1190. Input Parameters:
  1191. Descriptor - Resource descriptor to be unpacked.
  1192. Start - Receives the starting value for this descriptor.
  1193. Length - Receives the length of this resource.
  1194. Return Value:
  1195. STATUS_SUCCESS.
  1196. --*/
  1197. {
  1198. PAGED_CODE();
  1199. //
  1200. // Validate arguments.
  1201. //
  1202. ASSERT(Descriptor);
  1203. ASSERT(Start);
  1204. ASSERT(Length);
  1205. //
  1206. // Make sure we are dealing with the correct resource.
  1207. //
  1208. ASSERT(Descriptor->Type == CmResourceTypeInterrupt);
  1209. //
  1210. // We should never be here if Pci Irq routing is not enabled.
  1211. //
  1212. ASSERT(IsPciIrqRoutingEnabled());
  1213. //
  1214. // Do unpacking.
  1215. //
  1216. *Start = Descriptor->u.Interrupt.Vector;
  1217. *Length = 1;
  1218. DEBUG_PRINT(3, ("Unpacking Irq resource %p = 0x%04lx", Descriptor, (ULONG)*Start));
  1219. return (STATUS_SUCCESS);
  1220. }
  1221. LONG
  1222. HalpArbScoreRequirement (
  1223. IN PIO_RESOURCE_DESCRIPTOR Descriptor
  1224. )
  1225. /*++
  1226. Routine Description:
  1227. This routine returns a score that indicates the flexibility of this
  1228. device's requirements. Less flexible devices get low scores so that
  1229. they get assigned resources before more flexible devices.
  1230. Input Parameters:
  1231. Descriptor - Resource descriptor to be scored.
  1232. Return Value:
  1233. Returns the score for the descriptor.
  1234. --*/
  1235. {
  1236. LONG score;
  1237. PAGED_CODE();
  1238. //
  1239. // Validate argument.
  1240. //
  1241. ASSERT(Descriptor);
  1242. //
  1243. // Make sure we are dealing with the correct resource.
  1244. //
  1245. ASSERT(Descriptor->Type == CmResourceTypeInterrupt);
  1246. //
  1247. // We should never be here if Pci Irq routing is not enabled.
  1248. //
  1249. ASSERT(IsPciIrqRoutingEnabled());
  1250. //
  1251. // Score is directly determined by number of irqs in the decriptor.
  1252. //
  1253. score = Descriptor->u.Interrupt.MaximumVector -
  1254. Descriptor->u.Interrupt.MinimumVector + 1;
  1255. DEBUG_PRINT(3, ("Scoring Irq resource %p = %i", Descriptor, score));
  1256. return (score);
  1257. }
  1258. NTSTATUS
  1259. HalpInitIrqArbiter (
  1260. IN PDEVICE_OBJECT HalFdo
  1261. )
  1262. {
  1263. NTSTATUS status;
  1264. PAGED_CODE();
  1265. if (HalpArbiter.ArbiterState.MutexEvent)
  1266. {
  1267. return STATUS_SUCCESS;
  1268. }
  1269. DEBUG_PRINT(3, ("Initialzing Irq arbiter!"));
  1270. status = ArbInitializeArbiterInstance( &HalpArbiter.ArbiterState,
  1271. HalFdo,
  1272. CmResourceTypeInterrupt,
  1273. L"HalIRQ",
  1274. L"Root",
  1275. NULL);
  1276. if (NT_SUCCESS(status))
  1277. {
  1278. //
  1279. // Make interrupts >= 16 unavailable.
  1280. //
  1281. status = RtlAddRange( HalpArbiter.ArbiterState.Allocation,
  1282. 16,
  1283. MAXULONGLONG,
  1284. 0,
  1285. RTL_RANGE_LIST_ADD_IF_CONFLICT,
  1286. NULL,
  1287. NULL);
  1288. status = RtlAddRange( HalpArbiter.ArbiterState.Allocation,
  1289. PIC_SLAVE_IRQ,
  1290. PIC_SLAVE_IRQ,
  1291. 0,
  1292. RTL_RANGE_LIST_ADD_IF_CONFLICT,
  1293. NULL,
  1294. NULL);
  1295. DEBUG_PRINT(1, ("Irq arbiter successfully initialized!"));
  1296. }
  1297. else
  1298. {
  1299. //
  1300. // Keep us "uninitialized"
  1301. //
  1302. HalpArbiter.ArbiterState.MutexEvent = NULL;
  1303. ASSERT(NT_SUCCESS(status));
  1304. }
  1305. return (status);
  1306. }
  1307. VOID
  1308. HalpIrqArbiterInterfaceReference(
  1309. IN PVOID Context
  1310. )
  1311. {
  1312. //HalPnpInterfaceReference
  1313. PAGED_CODE();
  1314. return;
  1315. }
  1316. VOID
  1317. HalpIrqArbiterInterfaceDereference(
  1318. IN PVOID Context
  1319. )
  1320. {
  1321. //HalPnpInterfaceDereference
  1322. PAGED_CODE();
  1323. return;
  1324. }
  1325. #ifdef ALLOC_DATA_PRAGMA
  1326. #pragma const_seg("PAGECONST")
  1327. #endif // ALLOC_DATA_PRAGMA
  1328. const ARBITER_INTERFACE ArbInterface = {
  1329. sizeof(ARBITER_INTERFACE),//Size
  1330. 1,//Version
  1331. &HalpArbiter.ArbiterState,//Context
  1332. HalpIrqArbiterInterfaceReference,//InterfaceReference
  1333. HalpIrqArbiterInterfaceDereference,//InterfaceDereference
  1334. &ArbArbiterHandler,//ArbiterHandler
  1335. 0//Flags -- Do not set ARBITER_PARTIAL here
  1336. };
  1337. #ifdef ALLOC_DATA_PRAGMA
  1338. #pragma const_seg()
  1339. #endif // ALLOC_DATA_PRAGMA
  1340. NTSTATUS
  1341. HalpFillInIrqArbiter (
  1342. IN PDEVICE_OBJECT DeviceObject,
  1343. IN LPCGUID InterfaceType,
  1344. IN USHORT Version,
  1345. IN PVOID InterfaceSpecificData,
  1346. IN ULONG InterfaceBufferSize,
  1347. IN OUT PINTERFACE Interface,
  1348. IN OUT PULONG Length
  1349. )
  1350. {
  1351. PAGED_CODE();
  1352. *Length = sizeof(ARBITER_INTERFACE);
  1353. if (InterfaceBufferSize < sizeof(ARBITER_INTERFACE)) {
  1354. return STATUS_BUFFER_TOO_SMALL;
  1355. }
  1356. *(PARBITER_INTERFACE)Interface = ArbInterface;
  1357. DEBUG_PRINT(3, ("Providing Irq Arbiter for FDO %08x since Pci Irq Routing is enabled!", DeviceObject));
  1358. return STATUS_SUCCESS;
  1359. }