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.

1067 lines
27 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. ixisabus.c
  5. Abstract:
  6. Author:
  7. Environment:
  8. Revision History:
  9. --*/
  10. #include "halp.h"
  11. ULONG
  12. HalpGetEisaInterruptVector(
  13. IN PBUS_HANDLER BusHandler,
  14. IN PBUS_HANDLER RootHandler,
  15. IN ULONG BusInterruptLevel,
  16. IN ULONG BusInterruptVector,
  17. OUT PKIRQL Irql,
  18. OUT PKAFFINITY Affinity
  19. );
  20. BOOLEAN
  21. HalpTranslateIsaBusAddress (
  22. IN PVOID BusHandler,
  23. IN PVOID RootHandler,
  24. IN PHYSICAL_ADDRESS BusAddress,
  25. IN OUT PULONG AddressSpace,
  26. OUT PPHYSICAL_ADDRESS TranslatedAddress
  27. );
  28. BOOLEAN
  29. HalpTranslateEisaBusAddress (
  30. IN PVOID BusHandler,
  31. IN PVOID RootHandler,
  32. IN PHYSICAL_ADDRESS BusAddress,
  33. IN OUT PULONG AddressSpace,
  34. OUT PPHYSICAL_ADDRESS TranslatedAddress
  35. );
  36. NTSTATUS
  37. HalpAdjustEisaResourceList (
  38. IN PBUS_HANDLER BusHandler,
  39. IN PBUS_HANDLER RootHandler,
  40. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
  41. );
  42. HalpGetEisaData (
  43. IN PBUS_HANDLER BusHandler,
  44. IN PBUS_HANDLER RootHandler,
  45. IN ULONG SlotNumber,
  46. IN PVOID Buffer,
  47. IN ULONG Offset,
  48. IN ULONG Length
  49. );
  50. extern USHORT HalpEisaIrqMask;
  51. extern USHORT HalpEisaIrqIgnore;
  52. #ifdef ALLOC_PRAGMA
  53. #pragma alloc_text(PAGE,HalpGetEisaInterruptVector)
  54. #pragma alloc_text(PAGE,HalpAdjustEisaResourceList)
  55. #pragma alloc_text(PAGE,HalpGetEisaData)
  56. #pragma alloc_text(PAGE,HalIrqTranslateResourceRequirementsIsa)
  57. #pragma alloc_text(PAGE,HalIrqTranslateResourcesIsa)
  58. #pragma alloc_text(PAGE,HalpRecordEisaInterruptVectors)
  59. #endif
  60. #ifndef ACPI_HAL
  61. ULONG
  62. HalpGetEisaInterruptVector(
  63. IN PBUS_HANDLER BusHandler,
  64. IN PBUS_HANDLER RootHandler,
  65. IN ULONG BusInterruptLevel,
  66. IN ULONG BusInterruptVector,
  67. OUT PKIRQL Irql,
  68. OUT PKAFFINITY Affinity
  69. )
  70. /*++
  71. Routine Description:
  72. This function returns the system interrupt vector and IRQL level
  73. corresponding to the specified bus interrupt level and/or vector. The
  74. system interrupt vector and IRQL are suitable for use in a subsequent call
  75. to KeInitializeInterrupt.
  76. Arguments:
  77. BusHandle - Per bus specific structure
  78. Irql - Returns the system request priority.
  79. Affinity - Returns the system wide irq affinity.
  80. Return Value:
  81. Returns the system interrupt vector corresponding to the specified device.
  82. --*/
  83. {
  84. UNREFERENCED_PARAMETER( BusInterruptVector );
  85. //
  86. // On standard PCs, IRQ 2 is the cascaded interrupt, and it really shows
  87. // up on IRQ 9.
  88. //
  89. #if defined(NEC_98)
  90. if (BusInterruptLevel == 7) {
  91. BusInterruptLevel = 8;
  92. }
  93. #else // defined(NEC_98)
  94. if (BusInterruptLevel == 2) {
  95. BusInterruptLevel = 9;
  96. }
  97. #endif // defined(NEC_98)
  98. if (BusInterruptLevel > 15) {
  99. return 0;
  100. }
  101. //
  102. // Get parent's translation from here..
  103. //
  104. return BusHandler->ParentHandler->GetInterruptVector (
  105. BusHandler->ParentHandler,
  106. RootHandler,
  107. BusInterruptLevel,
  108. BusInterruptVector,
  109. Irql,
  110. Affinity
  111. );
  112. }
  113. NTSTATUS
  114. HalpAdjustEisaResourceList (
  115. IN PBUS_HANDLER BusHandler,
  116. IN PBUS_HANDLER RootHandler,
  117. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
  118. )
  119. {
  120. SUPPORTED_RANGE InterruptRange;
  121. RtlZeroMemory (&InterruptRange, sizeof InterruptRange);
  122. InterruptRange.Base = 0;
  123. InterruptRange.Limit = 15;
  124. return HaliAdjustResourceListRange (
  125. BusHandler->BusAddresses,
  126. &InterruptRange,
  127. pResourceList
  128. );
  129. }
  130. BOOLEAN
  131. HalpTranslateIsaBusAddress(
  132. IN PBUS_HANDLER BusHandler,
  133. IN PBUS_HANDLER RootHandler,
  134. IN PHYSICAL_ADDRESS BusAddress,
  135. IN OUT PULONG AddressSpace,
  136. OUT PPHYSICAL_ADDRESS TranslatedAddress
  137. )
  138. /*++
  139. Routine Description:
  140. This function translates a bus-relative address space and address into
  141. a system physical address.
  142. Arguments:
  143. BusAddress - Supplies the bus-relative address
  144. AddressSpace - Supplies the address space number.
  145. Returns the host address space number.
  146. AddressSpace == 0 => memory space
  147. AddressSpace == 1 => I/O space
  148. TranslatedAddress - Supplies a pointer to return the translated address
  149. Return Value:
  150. A return value of TRUE indicates that a system physical address
  151. corresponding to the supplied bus relative address and bus address
  152. number has been returned in TranslatedAddress.
  153. A return value of FALSE occurs if the translation for the address was
  154. not possible
  155. --*/
  156. {
  157. BOOLEAN Status;
  158. //
  159. // Translated normally
  160. //
  161. Status = HalpTranslateSystemBusAddress (
  162. BusHandler,
  163. RootHandler,
  164. BusAddress,
  165. AddressSpace,
  166. TranslatedAddress
  167. );
  168. //
  169. // If it could not be translated, and it's memory space
  170. // then we allow the translation as it would occur on it's
  171. // corrisponding EISA bus. We're allowing this because
  172. // many VLBus drivers are claiming to be ISA devices.
  173. // (yes, they should claim to be VLBus devices, but VLBus is
  174. // run by video cards and like everything else about video
  175. // there's no hope of fixing it. (At least according to
  176. // Andre))
  177. //
  178. if (Status == FALSE && *AddressSpace == 0) {
  179. Status = HalTranslateBusAddress (
  180. Eisa,
  181. BusHandler->BusNumber,
  182. BusAddress,
  183. AddressSpace,
  184. TranslatedAddress
  185. );
  186. }
  187. return Status;
  188. }
  189. BOOLEAN
  190. HalpTranslateEisaBusAddress(
  191. IN PBUS_HANDLER BusHandler,
  192. IN PBUS_HANDLER RootHandler,
  193. IN PHYSICAL_ADDRESS BusAddress,
  194. IN OUT PULONG AddressSpace,
  195. OUT PPHYSICAL_ADDRESS TranslatedAddress
  196. )
  197. /*++
  198. Routine Description:
  199. This function translates a bus-relative address space and address into
  200. a system physical address.
  201. Arguments:
  202. BusAddress - Supplies the bus-relative address
  203. AddressSpace - Supplies the address space number.
  204. Returns the host address space number.
  205. AddressSpace == 0 => memory space
  206. AddressSpace == 1 => I/O space
  207. TranslatedAddress - Supplies a pointer to return the translated address
  208. Return Value:
  209. A return value of TRUE indicates that a system physical address
  210. corresponding to the supplied bus relative address and bus address
  211. number has been returned in TranslatedAddress.
  212. A return value of FALSE occurs if the translation for the address was
  213. not possible
  214. --*/
  215. {
  216. BOOLEAN Status;
  217. //
  218. // Translated normally
  219. //
  220. Status = HalpTranslateSystemBusAddress (
  221. BusHandler,
  222. RootHandler,
  223. BusAddress,
  224. AddressSpace,
  225. TranslatedAddress
  226. );
  227. //
  228. // If it could not be translated, and it's in the 640k - 1m
  229. // range then (for compatibility) try translating it on the
  230. // Internal bus for
  231. //
  232. if (Status == FALSE &&
  233. *AddressSpace == 0 &&
  234. BusAddress.HighPart == 0 &&
  235. BusAddress.LowPart >= 0xA0000 &&
  236. BusAddress.LowPart < 0xFFFFF) {
  237. Status = HalTranslateBusAddress (
  238. Internal,
  239. 0,
  240. BusAddress,
  241. AddressSpace,
  242. TranslatedAddress
  243. );
  244. }
  245. return Status;
  246. }
  247. #endif
  248. HalpGetEisaData (
  249. IN PBUS_HANDLER BusHandler,
  250. IN PBUS_HANDLER RootHandler,
  251. IN ULONG SlotNumber,
  252. IN PVOID Buffer,
  253. IN ULONG Offset,
  254. IN ULONG Length
  255. )
  256. /*++
  257. Routine Description:
  258. The function returns the Eisa bus data for a slot or address.
  259. Arguments:
  260. Buffer - Supplies the space to store the data.
  261. Length - Supplies a count in bytes of the maximum amount to return.
  262. Return Value:
  263. Returns the amount of data stored into the buffer.
  264. --*/
  265. {
  266. OBJECT_ATTRIBUTES ObjectAttributes;
  267. OBJECT_ATTRIBUTES BusObjectAttributes;
  268. PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
  269. PWSTR ConfigData = L"Configuration Data";
  270. ANSI_STRING TmpString;
  271. ULONG BusNumber;
  272. UCHAR BusString[] = "00";
  273. UNICODE_STRING RootName, BusName = {0};
  274. UNICODE_STRING ConfigDataName;
  275. NTSTATUS NtStatus;
  276. PKEY_VALUE_FULL_INFORMATION ValueInformation;
  277. PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
  278. PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
  279. PCM_EISA_SLOT_INFORMATION SlotInformation;
  280. ULONG PartialCount;
  281. ULONG TotalDataSize, SlotDataSize;
  282. HANDLE EisaHandle = INVALID_HANDLE;
  283. HANDLE BusHandle = INVALID_HANDLE;
  284. ULONG BytesWritten, BytesNeeded;
  285. PUCHAR KeyValueBuffer = NULL;
  286. ULONG i;
  287. ULONG DataLength = 0;
  288. PUCHAR DataBuffer = Buffer;
  289. BOOLEAN Found = FALSE;
  290. PAGED_CODE ();
  291. RtlInitUnicodeString(
  292. &RootName,
  293. EisaPath
  294. );
  295. InitializeObjectAttributes(
  296. &ObjectAttributes,
  297. &RootName,
  298. OBJ_CASE_INSENSITIVE,
  299. (HANDLE)NULL,
  300. NULL
  301. );
  302. //
  303. // Open the EISA root
  304. //
  305. NtStatus = ZwOpenKey(
  306. &EisaHandle,
  307. KEY_READ,
  308. &ObjectAttributes
  309. );
  310. if (!NT_SUCCESS(NtStatus)) {
  311. DataLength = 0;
  312. goto HalpGetEisaDataExit;
  313. }
  314. //
  315. // Init bus number path
  316. //
  317. BusNumber = BusHandler->BusNumber;
  318. if (BusNumber > 99) {
  319. DataLength = 0;
  320. goto HalpGetEisaDataExit;
  321. }
  322. if (BusNumber > 9) {
  323. BusString[0] += (UCHAR) (BusNumber/10);
  324. BusString[1] += (UCHAR) (BusNumber % 10);
  325. } else {
  326. BusString[0] += (UCHAR) BusNumber;
  327. BusString[1] = '\0';
  328. }
  329. RtlInitAnsiString(
  330. &TmpString,
  331. BusString
  332. );
  333. RtlAnsiStringToUnicodeString(
  334. &BusName,
  335. &TmpString,
  336. TRUE
  337. );
  338. InitializeObjectAttributes(
  339. &BusObjectAttributes,
  340. &BusName,
  341. OBJ_CASE_INSENSITIVE,
  342. (HANDLE)EisaHandle,
  343. NULL
  344. );
  345. //
  346. // Open the EISA root + Bus Number
  347. //
  348. NtStatus = ZwOpenKey(
  349. &BusHandle,
  350. KEY_READ,
  351. &BusObjectAttributes
  352. );
  353. // Done with Eisa Handle
  354. ZwClose(EisaHandle);
  355. EisaHandle = INVALID_HANDLE;
  356. if (!NT_SUCCESS(NtStatus)) {
  357. DbgPrint("HAL: Opening Bus Number: Status = %x\n",NtStatus);
  358. DataLength = 0;
  359. goto HalpGetEisaDataExit;
  360. }
  361. //
  362. // opening the configuration data. This first call tells us how
  363. // much memory we need to allocate
  364. //
  365. RtlInitUnicodeString(
  366. &ConfigDataName,
  367. ConfigData
  368. );
  369. //
  370. // This should fail. We need to make this call so we can
  371. // get the actual size of the buffer to allocate.
  372. //
  373. ValueInformation = (PKEY_VALUE_FULL_INFORMATION) &i;
  374. NtStatus = ZwQueryValueKey(
  375. BusHandle,
  376. &ConfigDataName,
  377. KeyValueFullInformation,
  378. ValueInformation,
  379. 0,
  380. &BytesNeeded
  381. );
  382. KeyValueBuffer = ExAllocatePoolWithTag(
  383. NonPagedPool,
  384. BytesNeeded,
  385. HAL_POOL_TAG
  386. );
  387. if (KeyValueBuffer == NULL) {
  388. #if DBG
  389. DbgPrint("HAL: Cannot allocate Key Value Buffer\n");
  390. #endif
  391. ZwClose(BusHandle);
  392. DataLength = 0;
  393. goto HalpGetEisaDataExit;
  394. }
  395. ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
  396. NtStatus = ZwQueryValueKey(
  397. BusHandle,
  398. &ConfigDataName,
  399. KeyValueFullInformation,
  400. ValueInformation,
  401. BytesNeeded,
  402. &BytesWritten
  403. );
  404. ZwClose(BusHandle);
  405. if (!NT_SUCCESS(NtStatus)) {
  406. #if DBG
  407. DbgPrint("HAL: Query Config Data: Status = %x\n",NtStatus);
  408. #endif
  409. DataLength = 0;
  410. goto HalpGetEisaDataExit;
  411. }
  412. //
  413. // We get back a Full Resource Descriptor List
  414. //
  415. Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
  416. ValueInformation->DataOffset);
  417. PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
  418. &(Descriptor->PartialResourceList.PartialDescriptors);
  419. PartialCount = Descriptor->PartialResourceList.Count;
  420. for (i = 0; i < PartialCount; i++) {
  421. //
  422. // Do each partial Resource
  423. //
  424. switch (PartialResource->Type) {
  425. case CmResourceTypeNull:
  426. case CmResourceTypePort:
  427. case CmResourceTypeInterrupt:
  428. case CmResourceTypeMemory:
  429. case CmResourceTypeDma:
  430. //
  431. // We dont care about these.
  432. //
  433. PartialResource++;
  434. break;
  435. case CmResourceTypeDeviceSpecific:
  436. //
  437. // Bingo!
  438. //
  439. TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
  440. SlotInformation = (PCM_EISA_SLOT_INFORMATION)
  441. ((PUCHAR)PartialResource +
  442. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
  443. while (((LONG)TotalDataSize) > 0) {
  444. if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
  445. SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
  446. } else {
  447. SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
  448. SlotInformation->NumberFunctions *
  449. sizeof(CM_EISA_FUNCTION_INFORMATION);
  450. }
  451. if (SlotDataSize > TotalDataSize) {
  452. //
  453. // Something is wrong again
  454. //
  455. DataLength = 0;
  456. goto HalpGetEisaDataExit;
  457. }
  458. if (SlotNumber != 0) {
  459. SlotNumber--;
  460. SlotInformation = (PCM_EISA_SLOT_INFORMATION)
  461. ((PUCHAR)SlotInformation + SlotDataSize);
  462. TotalDataSize -= SlotDataSize;
  463. continue;
  464. }
  465. //
  466. // This is our slot
  467. //
  468. Found = TRUE;
  469. break;
  470. }
  471. //
  472. // End loop
  473. //
  474. i = PartialCount;
  475. break;
  476. default:
  477. #if DBG
  478. DbgPrint("Bad Data in registry!\n");
  479. #endif
  480. DataLength = 0;
  481. goto HalpGetEisaDataExit;
  482. }
  483. }
  484. if (Found) {
  485. i = Length + Offset;
  486. if (i > SlotDataSize) {
  487. i = SlotDataSize;
  488. }
  489. DataLength = i - Offset;
  490. RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
  491. }
  492. HalpGetEisaDataExit:
  493. if (EisaHandle != INVALID_HANDLE)
  494. {
  495. ZwClose(EisaHandle);
  496. }
  497. if (KeyValueBuffer) ExFreePool(KeyValueBuffer);
  498. if (BusName.Buffer) RtlFreeUnicodeString(&BusName);
  499. return DataLength;
  500. }
  501. NTSTATUS
  502. HalIrqTranslateResourceRequirementsIsa(
  503. IN PVOID Context,
  504. IN PIO_RESOURCE_DESCRIPTOR Source,
  505. IN PDEVICE_OBJECT PhysicalDeviceObject,
  506. OUT PULONG TargetCount,
  507. OUT PIO_RESOURCE_DESCRIPTOR *Target
  508. )
  509. /*++
  510. Routine Description:
  511. This function is basically a wrapper for
  512. HalIrqTranslateResourceRequirementsRoot that understands
  513. the weirdnesses of the ISA bus.
  514. Arguments:
  515. Return Value:
  516. status
  517. --*/
  518. {
  519. PIO_RESOURCE_DESCRIPTOR modSource, target, rootTarget;
  520. NTSTATUS status;
  521. BOOLEAN picSlaveDeleted = FALSE;
  522. BOOLEAN deleteResource;
  523. ULONG sourceCount = 0;
  524. ULONG targetCount = 0;
  525. ULONG resource;
  526. ULONG rootCount;
  527. ULONG invalidIrq;
  528. BOOLEAN pciIsaConflict = FALSE;
  529. PAGED_CODE();
  530. ASSERT(Source->Type == CmResourceTypeInterrupt);
  531. modSource = ExAllocatePoolWithTag(PagedPool,
  532. // we will have at most nine ranges when we are done
  533. sizeof(IO_RESOURCE_DESCRIPTOR) * 9,
  534. HAL_POOL_TAG
  535. );
  536. if (!modSource) {
  537. return STATUS_INSUFFICIENT_RESOURCES;
  538. }
  539. RtlZeroMemory(modSource, sizeof(IO_RESOURCE_DESCRIPTOR) * 9);
  540. //
  541. // Is the PIC_SLAVE_IRQ in this resource?
  542. //
  543. if ((Source->u.Interrupt.MinimumVector <= PIC_SLAVE_IRQ) &&
  544. (Source->u.Interrupt.MaximumVector >= PIC_SLAVE_IRQ)) {
  545. //
  546. // Clip the maximum
  547. //
  548. if (Source->u.Interrupt.MinimumVector < PIC_SLAVE_IRQ) {
  549. modSource[sourceCount] = *Source;
  550. modSource[sourceCount].u.Interrupt.MinimumVector =
  551. Source->u.Interrupt.MinimumVector;
  552. modSource[sourceCount].u.Interrupt.MaximumVector =
  553. PIC_SLAVE_IRQ - 1;
  554. sourceCount++;
  555. }
  556. //
  557. // Clip the minimum
  558. //
  559. if (Source->u.Interrupt.MaximumVector > PIC_SLAVE_IRQ) {
  560. modSource[sourceCount] = *Source;
  561. modSource[sourceCount].u.Interrupt.MaximumVector =
  562. Source->u.Interrupt.MaximumVector;
  563. modSource[sourceCount].u.Interrupt.MinimumVector =
  564. PIC_SLAVE_IRQ + 1;
  565. sourceCount++;
  566. }
  567. //
  568. // In ISA machines, the PIC_SLAVE_IRQ is rerouted
  569. // to PIC_SLAVE_REDIRECT. So find out if PIC_SLAVE_REDIRECT
  570. // is within this list. If it isn't we need to add it.
  571. //
  572. if (!((Source->u.Interrupt.MinimumVector <= PIC_SLAVE_REDIRECT) &&
  573. (Source->u.Interrupt.MaximumVector >= PIC_SLAVE_REDIRECT))) {
  574. modSource[sourceCount] = *Source;
  575. modSource[sourceCount].u.Interrupt.MinimumVector = PIC_SLAVE_REDIRECT;
  576. modSource[sourceCount].u.Interrupt.MaximumVector = PIC_SLAVE_REDIRECT;
  577. sourceCount++;
  578. }
  579. } else {
  580. *modSource = *Source;
  581. sourceCount = 1;
  582. }
  583. //
  584. // Now that the PIC_SLAVE_IRQ has been handled, we have
  585. // to take into account IRQs that may have been steered
  586. // away to the PCI bus.
  587. //
  588. // N.B. The algorithm used below may produce resources
  589. // with minimums greater than maximums. Those will
  590. // be stripped out later.
  591. //
  592. for (invalidIrq = 0; invalidIrq < PIC_VECTORS; invalidIrq++) {
  593. //
  594. // Look through all the resources, possibly removing
  595. // this IRQ from them.
  596. //
  597. for (resource = 0; resource < sourceCount; resource++) {
  598. deleteResource = FALSE;
  599. if (HalpPciIrqMask & (1 << invalidIrq)) {
  600. //
  601. // This IRQ belongs to the PCI bus.
  602. //
  603. if (!((HalpBusType == MACHINE_TYPE_EISA) &&
  604. ((modSource[resource].Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE)))) {
  605. //
  606. // And this resource is not an EISA-style,
  607. // level-triggered interrupt.
  608. //
  609. // N.B. Only the system BIOS truely knows
  610. // whether an IRQ on a PCI bus can be
  611. // shared with an IRQ on an ISA bus.
  612. // This code assumes that, in the case
  613. // that the BIOS set an EISA device to
  614. // the same interrupt as a PCI device,
  615. // the machine can actually function.
  616. //
  617. deleteResource = TRUE;
  618. }
  619. }
  620. #ifndef MCA
  621. if ((HalpBusType == MACHINE_TYPE_EISA) &&
  622. !(HalpEisaIrqIgnore & (1 << invalidIrq))) {
  623. if (modSource[resource].Flags != HalpGetIsaIrqState(invalidIrq)) {
  624. //
  625. // This driver has requested a level-triggered interrupt
  626. // and this particular interrupt is set to be edge, or
  627. // vice-versa.
  628. //
  629. deleteResource = TRUE;
  630. pciIsaConflict = TRUE;
  631. }
  632. }
  633. #endif
  634. if (deleteResource) {
  635. if (modSource[resource].u.Interrupt.MinimumVector == invalidIrq) {
  636. modSource[resource].u.Interrupt.MinimumVector++;
  637. } else if (modSource[resource].u.Interrupt.MaximumVector == invalidIrq) {
  638. modSource[resource].u.Interrupt.MaximumVector--;
  639. } else if ((modSource[resource].u.Interrupt.MinimumVector < invalidIrq) &&
  640. (modSource[resource].u.Interrupt.MaximumVector > invalidIrq)) {
  641. //
  642. // Copy the current resource into a new resource.
  643. //
  644. modSource[sourceCount] = modSource[resource];
  645. //
  646. // Clip the current resource to a range below invalidIrq.
  647. //
  648. modSource[resource].u.Interrupt.MaximumVector = invalidIrq - 1;
  649. //
  650. // Clip the new resource to a range above invalidIrq.
  651. //
  652. modSource[sourceCount].u.Interrupt.MinimumVector = invalidIrq + 1;
  653. sourceCount++;
  654. }
  655. }
  656. }
  657. }
  658. target = ExAllocatePoolWithTag(PagedPool,
  659. sizeof(IO_RESOURCE_DESCRIPTOR) * sourceCount,
  660. HAL_POOL_TAG
  661. );
  662. if (!target) {
  663. ExFreePool(modSource);
  664. return STATUS_INSUFFICIENT_RESOURCES;
  665. }
  666. //
  667. // Now send each of these ranges through
  668. // HalIrqTranslateResourceRequirementsRoot.
  669. //
  670. for (resource = 0; resource < sourceCount; resource++) {
  671. //
  672. // Skip over resources that we have previously
  673. // clobbered (while deleting PCI IRQs.)
  674. //
  675. if (modSource[resource].u.Interrupt.MinimumVector >
  676. modSource[resource].u.Interrupt.MaximumVector) {
  677. continue;
  678. }
  679. status = HalIrqTranslateResourceRequirementsRoot(
  680. Context,
  681. &modSource[resource],
  682. PhysicalDeviceObject,
  683. &rootCount,
  684. &rootTarget
  685. );
  686. if (!NT_SUCCESS(status)) {
  687. ExFreePool(target);
  688. goto HalIrqTranslateResourceRequirementsIsaExit;
  689. }
  690. //
  691. // HalIrqTranslateResourceRequirementsRoot should return
  692. // either one resource or, occasionally, zero.
  693. //
  694. ASSERT(rootCount <= 1);
  695. if (rootCount == 1) {
  696. target[targetCount] = *rootTarget;
  697. targetCount++;
  698. ExFreePool(rootTarget);
  699. }
  700. }
  701. status = STATUS_TRANSLATION_COMPLETE;
  702. *TargetCount = targetCount;
  703. if (targetCount > 0) {
  704. *Target = target;
  705. } else {
  706. ExFreePool(target);
  707. if (pciIsaConflict == TRUE) {
  708. status = STATUS_PNP_IRQ_TRANSLATION_FAILED;
  709. }
  710. }
  711. HalIrqTranslateResourceRequirementsIsaExit:
  712. ExFreePool(modSource);
  713. return status;
  714. }
  715. NTSTATUS
  716. HalIrqTranslateResourcesIsa(
  717. IN PVOID Context,
  718. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
  719. IN RESOURCE_TRANSLATION_DIRECTION Direction,
  720. IN ULONG AlternativesCount, OPTIONAL
  721. IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
  722. IN PDEVICE_OBJECT PhysicalDeviceObject,
  723. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
  724. )
  725. /*++
  726. Routine Description:
  727. This function is basically a wrapper for
  728. HalIrqTranslateResourcesRoot that understands
  729. the weirdnesses of the ISA bus.
  730. Arguments:
  731. Return Value:
  732. status
  733. --*/
  734. {
  735. CM_PARTIAL_RESOURCE_DESCRIPTOR modSource;
  736. NTSTATUS status;
  737. BOOLEAN usePicSlave = FALSE;
  738. ULONG i;
  739. modSource = *Source;
  740. if (Direction == TranslateChildToParent) {
  741. if (Source->u.Interrupt.Vector == PIC_SLAVE_IRQ) {
  742. modSource.u.Interrupt.Vector = PIC_SLAVE_REDIRECT;
  743. modSource.u.Interrupt.Level = PIC_SLAVE_REDIRECT;
  744. }
  745. }
  746. status = HalIrqTranslateResourcesRoot(
  747. Context,
  748. &modSource,
  749. Direction,
  750. AlternativesCount,
  751. Alternatives,
  752. PhysicalDeviceObject,
  753. Target);
  754. if (!NT_SUCCESS(status)) {
  755. return status;
  756. }
  757. if (Direction == TranslateParentToChild) {
  758. //
  759. // Because the ISA interrupt controller is
  760. // cascaded, there is one case where there is
  761. // a two-to-one mapping for interrupt sources.
  762. // (On a PC, both 2 and 9 trigger vector 9.)
  763. //
  764. // We need to account for this and deliver the
  765. // right value back to the driver.
  766. //
  767. if (Target->u.Interrupt.Level == PIC_SLAVE_REDIRECT) {
  768. //
  769. // Search the Alternatives list. If it contains
  770. // PIC_SLAVE_IRQ but not PIC_SLAVE_REDIRECT,
  771. // we should return PIC_SLAVE_IRQ.
  772. //
  773. for (i = 0; i < AlternativesCount; i++) {
  774. if ((Alternatives[i].u.Interrupt.MinimumVector >= PIC_SLAVE_REDIRECT) &&
  775. (Alternatives[i].u.Interrupt.MaximumVector <= PIC_SLAVE_REDIRECT)) {
  776. //
  777. // The list contains, PIC_SLAVE_REDIRECT. Stop
  778. // looking.
  779. //
  780. usePicSlave = FALSE;
  781. break;
  782. }
  783. if ((Alternatives[i].u.Interrupt.MinimumVector >= PIC_SLAVE_IRQ) &&
  784. (Alternatives[i].u.Interrupt.MaximumVector <= PIC_SLAVE_IRQ)) {
  785. //
  786. // The list contains, PIC_SLAVE_IRQ. Use it
  787. // unless we find PIC_SLAVE_REDIRECT later.
  788. //
  789. usePicSlave = TRUE;
  790. }
  791. }
  792. if (usePicSlave) {
  793. Target->u.Interrupt.Level = PIC_SLAVE_IRQ;
  794. Target->u.Interrupt.Vector = PIC_SLAVE_IRQ;
  795. }
  796. }
  797. }
  798. return status;
  799. }
  800. VOID
  801. HalpRecordEisaInterruptVectors(
  802. VOID
  803. )
  804. {
  805. HalpEisaIrqMask = READ_PORT_UCHAR((PUCHAR)EISA_EDGE_LEVEL0) & 0xff;
  806. HalpEisaIrqMask |= READ_PORT_UCHAR((PUCHAR)EISA_EDGE_LEVEL1) << 8;
  807. if ((HalpEisaIrqMask == 0xffff) ||
  808. (HalpEisaIrqMask == 0x0000)) {
  809. HalpEisaIrqIgnore = 0xffff;
  810. }
  811. }