Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1709 lines
45 KiB

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