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.

1058 lines
28 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. ULONG BusNumber;
  271. WCHAR BusString[] = L"00";
  272. UNICODE_STRING RootName, BusName = {0};
  273. UNICODE_STRING ConfigDataName;
  274. NTSTATUS NtStatus;
  275. PKEY_VALUE_FULL_INFORMATION ValueInformation;
  276. PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
  277. PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
  278. PCM_EISA_SLOT_INFORMATION SlotInformation;
  279. ULONG PartialCount;
  280. ULONG TotalDataSize, SlotDataSize;
  281. HANDLE EisaHandle = INVALID_HANDLE;
  282. HANDLE BusHandle = INVALID_HANDLE;
  283. ULONG BytesWritten, BytesNeeded;
  284. PUCHAR KeyValueBuffer = NULL;
  285. ULONG i;
  286. ULONG DataLength = 0;
  287. PUCHAR DataBuffer = Buffer;
  288. BOOLEAN Found = FALSE;
  289. PAGED_CODE ();
  290. RtlInitUnicodeString(
  291. &RootName,
  292. EisaPath
  293. );
  294. InitializeObjectAttributes(
  295. &ObjectAttributes,
  296. &RootName,
  297. OBJ_CASE_INSENSITIVE,
  298. (HANDLE)NULL,
  299. NULL
  300. );
  301. //
  302. // Open the EISA root
  303. //
  304. NtStatus = ZwOpenKey(
  305. &EisaHandle,
  306. KEY_READ,
  307. &ObjectAttributes
  308. );
  309. if (!NT_SUCCESS(NtStatus)) {
  310. DataLength = 0;
  311. goto HalpGetEisaDataExit;
  312. }
  313. //
  314. // Init bus number path
  315. //
  316. BusNumber = BusHandler->BusNumber;
  317. if (BusNumber > 99) {
  318. DataLength = 0;
  319. goto HalpGetEisaDataExit;
  320. }
  321. if (BusNumber > 9) {
  322. BusString[0] += (WCHAR) (BusNumber/10);
  323. BusString[1] += (WCHAR) (BusNumber % 10);
  324. } else {
  325. BusString[0] += (WCHAR) BusNumber;
  326. BusString[1] = '\0';
  327. }
  328. RtlInitUnicodeString(
  329. &BusName,
  330. BusString
  331. );
  332. InitializeObjectAttributes(
  333. &BusObjectAttributes,
  334. &BusName,
  335. OBJ_CASE_INSENSITIVE,
  336. (HANDLE)EisaHandle,
  337. NULL
  338. );
  339. //
  340. // Open the EISA root + Bus Number
  341. //
  342. NtStatus = ZwOpenKey(
  343. &BusHandle,
  344. KEY_READ,
  345. &BusObjectAttributes
  346. );
  347. // Done with Eisa Handle
  348. ZwClose(EisaHandle);
  349. EisaHandle = INVALID_HANDLE;
  350. if (!NT_SUCCESS(NtStatus)) {
  351. DbgPrint("HAL: Opening Bus Number: Status = %x\n",NtStatus);
  352. DataLength = 0;
  353. goto HalpGetEisaDataExit;
  354. }
  355. //
  356. // opening the configuration data. This first call tells us how
  357. // much memory we need to allocate
  358. //
  359. RtlInitUnicodeString(
  360. &ConfigDataName,
  361. ConfigData
  362. );
  363. //
  364. // This should fail. We need to make this call so we can
  365. // get the actual size of the buffer to allocate.
  366. //
  367. ValueInformation = (PKEY_VALUE_FULL_INFORMATION) &i;
  368. NtStatus = ZwQueryValueKey(
  369. BusHandle,
  370. &ConfigDataName,
  371. KeyValueFullInformation,
  372. ValueInformation,
  373. 0,
  374. &BytesNeeded
  375. );
  376. KeyValueBuffer = ExAllocatePoolWithTag(
  377. NonPagedPool,
  378. BytesNeeded,
  379. HAL_POOL_TAG
  380. );
  381. if (KeyValueBuffer == NULL) {
  382. #if DBG
  383. DbgPrint("HAL: Cannot allocate Key Value Buffer\n");
  384. #endif
  385. ZwClose(BusHandle);
  386. DataLength = 0;
  387. goto HalpGetEisaDataExit;
  388. }
  389. ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
  390. NtStatus = ZwQueryValueKey(
  391. BusHandle,
  392. &ConfigDataName,
  393. KeyValueFullInformation,
  394. ValueInformation,
  395. BytesNeeded,
  396. &BytesWritten
  397. );
  398. ZwClose(BusHandle);
  399. if (!NT_SUCCESS(NtStatus)) {
  400. #if DBG
  401. DbgPrint("HAL: Query Config Data: Status = %x\n",NtStatus);
  402. #endif
  403. DataLength = 0;
  404. goto HalpGetEisaDataExit;
  405. }
  406. //
  407. // We get back a Full Resource Descriptor List
  408. //
  409. Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
  410. ValueInformation->DataOffset);
  411. PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
  412. &(Descriptor->PartialResourceList.PartialDescriptors);
  413. PartialCount = Descriptor->PartialResourceList.Count;
  414. for (i = 0; i < PartialCount; i++) {
  415. //
  416. // Do each partial Resource
  417. //
  418. switch (PartialResource->Type) {
  419. case CmResourceTypeNull:
  420. case CmResourceTypePort:
  421. case CmResourceTypeInterrupt:
  422. case CmResourceTypeMemory:
  423. case CmResourceTypeDma:
  424. //
  425. // We dont care about these.
  426. //
  427. PartialResource++;
  428. break;
  429. case CmResourceTypeDeviceSpecific:
  430. //
  431. // Bingo!
  432. //
  433. TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
  434. SlotInformation = (PCM_EISA_SLOT_INFORMATION)
  435. ((PUCHAR)PartialResource +
  436. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
  437. while (((LONG)TotalDataSize) > 0) {
  438. if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
  439. SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
  440. } else {
  441. SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
  442. SlotInformation->NumberFunctions *
  443. sizeof(CM_EISA_FUNCTION_INFORMATION);
  444. }
  445. if (SlotDataSize > TotalDataSize) {
  446. //
  447. // Something is wrong again
  448. //
  449. DataLength = 0;
  450. goto HalpGetEisaDataExit;
  451. }
  452. if (SlotNumber != 0) {
  453. SlotNumber--;
  454. SlotInformation = (PCM_EISA_SLOT_INFORMATION)
  455. ((PUCHAR)SlotInformation + SlotDataSize);
  456. TotalDataSize -= SlotDataSize;
  457. continue;
  458. }
  459. //
  460. // This is our slot
  461. //
  462. Found = TRUE;
  463. break;
  464. }
  465. //
  466. // End loop
  467. //
  468. i = PartialCount;
  469. break;
  470. default:
  471. #if DBG
  472. DbgPrint("Bad Data in registry!\n");
  473. #endif
  474. DataLength = 0;
  475. goto HalpGetEisaDataExit;
  476. }
  477. }
  478. if (Found) {
  479. i = Length + Offset;
  480. if (i > SlotDataSize) {
  481. i = SlotDataSize;
  482. }
  483. DataLength = i - Offset;
  484. RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
  485. }
  486. HalpGetEisaDataExit:
  487. if (EisaHandle != INVALID_HANDLE)
  488. {
  489. ZwClose(EisaHandle);
  490. }
  491. if (KeyValueBuffer) ExFreePool(KeyValueBuffer);
  492. return DataLength;
  493. }
  494. NTSTATUS
  495. HalIrqTranslateResourceRequirementsIsa(
  496. IN PVOID Context,
  497. IN PIO_RESOURCE_DESCRIPTOR Source,
  498. IN PDEVICE_OBJECT PhysicalDeviceObject,
  499. OUT PULONG TargetCount,
  500. OUT PIO_RESOURCE_DESCRIPTOR *Target
  501. )
  502. /*++
  503. Routine Description:
  504. This function is basically a wrapper for
  505. HalIrqTranslateResourceRequirementsRoot that understands
  506. the weirdnesses of the ISA bus.
  507. Arguments:
  508. Return Value:
  509. status
  510. --*/
  511. {
  512. PIO_RESOURCE_DESCRIPTOR modSource, target, rootTarget;
  513. NTSTATUS status;
  514. BOOLEAN picSlaveDeleted = FALSE;
  515. BOOLEAN deleteResource;
  516. ULONG sourceCount = 0;
  517. ULONG targetCount = 0;
  518. ULONG resource;
  519. ULONG rootCount;
  520. ULONG invalidIrq;
  521. BOOLEAN pciIsaConflict = FALSE;
  522. PAGED_CODE();
  523. ASSERT(Source->Type == CmResourceTypeInterrupt);
  524. modSource = ExAllocatePoolWithTag(PagedPool,
  525. // we will have at most nine ranges when we are done
  526. sizeof(IO_RESOURCE_DESCRIPTOR) * 9,
  527. HAL_POOL_TAG
  528. );
  529. if (!modSource) {
  530. return STATUS_INSUFFICIENT_RESOURCES;
  531. }
  532. RtlZeroMemory(modSource, sizeof(IO_RESOURCE_DESCRIPTOR) * 9);
  533. //
  534. // Is the PIC_SLAVE_IRQ in this resource?
  535. //
  536. if ((Source->u.Interrupt.MinimumVector <= PIC_SLAVE_IRQ) &&
  537. (Source->u.Interrupt.MaximumVector >= PIC_SLAVE_IRQ)) {
  538. //
  539. // Clip the maximum
  540. //
  541. if (Source->u.Interrupt.MinimumVector < PIC_SLAVE_IRQ) {
  542. modSource[sourceCount] = *Source;
  543. modSource[sourceCount].u.Interrupt.MinimumVector =
  544. Source->u.Interrupt.MinimumVector;
  545. modSource[sourceCount].u.Interrupt.MaximumVector =
  546. PIC_SLAVE_IRQ - 1;
  547. sourceCount++;
  548. }
  549. //
  550. // Clip the minimum
  551. //
  552. if (Source->u.Interrupt.MaximumVector > PIC_SLAVE_IRQ) {
  553. modSource[sourceCount] = *Source;
  554. modSource[sourceCount].u.Interrupt.MaximumVector =
  555. Source->u.Interrupt.MaximumVector;
  556. modSource[sourceCount].u.Interrupt.MinimumVector =
  557. PIC_SLAVE_IRQ + 1;
  558. sourceCount++;
  559. }
  560. //
  561. // In ISA machines, the PIC_SLAVE_IRQ is rerouted
  562. // to PIC_SLAVE_REDIRECT. So find out if PIC_SLAVE_REDIRECT
  563. // is within this list. If it isn't we need to add it.
  564. //
  565. if (!((Source->u.Interrupt.MinimumVector <= PIC_SLAVE_REDIRECT) &&
  566. (Source->u.Interrupt.MaximumVector >= PIC_SLAVE_REDIRECT))) {
  567. modSource[sourceCount] = *Source;
  568. modSource[sourceCount].u.Interrupt.MinimumVector = PIC_SLAVE_REDIRECT;
  569. modSource[sourceCount].u.Interrupt.MaximumVector = PIC_SLAVE_REDIRECT;
  570. sourceCount++;
  571. }
  572. } else {
  573. *modSource = *Source;
  574. sourceCount = 1;
  575. }
  576. //
  577. // Now that the PIC_SLAVE_IRQ has been handled, we have
  578. // to take into account IRQs that may have been steered
  579. // away to the PCI bus.
  580. //
  581. // N.B. The algorithm used below may produce resources
  582. // with minimums greater than maximums. Those will
  583. // be stripped out later.
  584. //
  585. for (invalidIrq = 0; invalidIrq < PIC_VECTORS; invalidIrq++) {
  586. //
  587. // Look through all the resources, possibly removing
  588. // this IRQ from them.
  589. //
  590. for (resource = 0; resource < sourceCount; resource++) {
  591. deleteResource = FALSE;
  592. if (HalpPciIrqMask & (1 << invalidIrq)) {
  593. //
  594. // This IRQ belongs to the PCI bus.
  595. //
  596. if (!((HalpBusType == MACHINE_TYPE_EISA) &&
  597. ((modSource[resource].Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE)))) {
  598. //
  599. // And this resource is not an EISA-style,
  600. // level-triggered interrupt.
  601. //
  602. // N.B. Only the system BIOS truely knows
  603. // whether an IRQ on a PCI bus can be
  604. // shared with an IRQ on an ISA bus.
  605. // This code assumes that, in the case
  606. // that the BIOS set an EISA device to
  607. // the same interrupt as a PCI device,
  608. // the machine can actually function.
  609. //
  610. deleteResource = TRUE;
  611. }
  612. }
  613. #ifndef MCA
  614. if ((HalpBusType == MACHINE_TYPE_EISA) &&
  615. !(HalpEisaIrqIgnore & (1 << invalidIrq))) {
  616. if (modSource[resource].Flags != HalpGetIsaIrqState(invalidIrq)) {
  617. //
  618. // This driver has requested a level-triggered interrupt
  619. // and this particular interrupt is set to be edge, or
  620. // vice-versa.
  621. //
  622. deleteResource = TRUE;
  623. pciIsaConflict = TRUE;
  624. }
  625. }
  626. #endif
  627. if (deleteResource) {
  628. if (modSource[resource].u.Interrupt.MinimumVector == invalidIrq) {
  629. modSource[resource].u.Interrupt.MinimumVector++;
  630. } else if (modSource[resource].u.Interrupt.MaximumVector == invalidIrq) {
  631. modSource[resource].u.Interrupt.MaximumVector--;
  632. } else if ((modSource[resource].u.Interrupt.MinimumVector < invalidIrq) &&
  633. (modSource[resource].u.Interrupt.MaximumVector > invalidIrq)) {
  634. //
  635. // Copy the current resource into a new resource.
  636. //
  637. modSource[sourceCount] = modSource[resource];
  638. //
  639. // Clip the current resource to a range below invalidIrq.
  640. //
  641. modSource[resource].u.Interrupt.MaximumVector = invalidIrq - 1;
  642. //
  643. // Clip the new resource to a range above invalidIrq.
  644. //
  645. modSource[sourceCount].u.Interrupt.MinimumVector = invalidIrq + 1;
  646. sourceCount++;
  647. }
  648. }
  649. }
  650. }
  651. target = ExAllocatePoolWithTag(PagedPool,
  652. sizeof(IO_RESOURCE_DESCRIPTOR) * sourceCount,
  653. HAL_POOL_TAG
  654. );
  655. if (!target) {
  656. ExFreePool(modSource);
  657. return STATUS_INSUFFICIENT_RESOURCES;
  658. }
  659. //
  660. // Now send each of these ranges through
  661. // HalIrqTranslateResourceRequirementsRoot.
  662. //
  663. for (resource = 0; resource < sourceCount; resource++) {
  664. //
  665. // Skip over resources that we have previously
  666. // clobbered (while deleting PCI IRQs.)
  667. //
  668. if (modSource[resource].u.Interrupt.MinimumVector >
  669. modSource[resource].u.Interrupt.MaximumVector) {
  670. continue;
  671. }
  672. status = HalIrqTranslateResourceRequirementsRoot(
  673. Context,
  674. &modSource[resource],
  675. PhysicalDeviceObject,
  676. &rootCount,
  677. &rootTarget
  678. );
  679. if (!NT_SUCCESS(status)) {
  680. ExFreePool(target);
  681. goto HalIrqTranslateResourceRequirementsIsaExit;
  682. }
  683. //
  684. // HalIrqTranslateResourceRequirementsRoot should return
  685. // either one resource or, occasionally, zero.
  686. //
  687. ASSERT(rootCount <= 1);
  688. if (rootCount == 1) {
  689. target[targetCount] = *rootTarget;
  690. targetCount++;
  691. ExFreePool(rootTarget);
  692. }
  693. }
  694. status = STATUS_TRANSLATION_COMPLETE;
  695. *TargetCount = targetCount;
  696. if (targetCount > 0) {
  697. *Target = target;
  698. } else {
  699. ExFreePool(target);
  700. if (pciIsaConflict == TRUE) {
  701. status = STATUS_PNP_IRQ_TRANSLATION_FAILED;
  702. }
  703. }
  704. HalIrqTranslateResourceRequirementsIsaExit:
  705. ExFreePool(modSource);
  706. return status;
  707. }
  708. NTSTATUS
  709. HalIrqTranslateResourcesIsa(
  710. IN PVOID Context,
  711. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
  712. IN RESOURCE_TRANSLATION_DIRECTION Direction,
  713. IN ULONG AlternativesCount, OPTIONAL
  714. IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
  715. IN PDEVICE_OBJECT PhysicalDeviceObject,
  716. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
  717. )
  718. /*++
  719. Routine Description:
  720. This function is basically a wrapper for
  721. HalIrqTranslateResourcesRoot that understands
  722. the weirdnesses of the ISA bus.
  723. Arguments:
  724. Return Value:
  725. status
  726. --*/
  727. {
  728. CM_PARTIAL_RESOURCE_DESCRIPTOR modSource;
  729. NTSTATUS status;
  730. BOOLEAN usePicSlave = FALSE;
  731. ULONG i;
  732. modSource = *Source;
  733. if (Direction == TranslateChildToParent) {
  734. if (Source->u.Interrupt.Vector == PIC_SLAVE_IRQ) {
  735. modSource.u.Interrupt.Vector = PIC_SLAVE_REDIRECT;
  736. modSource.u.Interrupt.Level = PIC_SLAVE_REDIRECT;
  737. }
  738. }
  739. status = HalIrqTranslateResourcesRoot(
  740. Context,
  741. &modSource,
  742. Direction,
  743. AlternativesCount,
  744. Alternatives,
  745. PhysicalDeviceObject,
  746. Target);
  747. if (!NT_SUCCESS(status)) {
  748. return status;
  749. }
  750. if (Direction == TranslateParentToChild) {
  751. //
  752. // Because the ISA interrupt controller is
  753. // cascaded, there is one case where there is
  754. // a two-to-one mapping for interrupt sources.
  755. // (On a PC, both 2 and 9 trigger vector 9.)
  756. //
  757. // We need to account for this and deliver the
  758. // right value back to the driver.
  759. //
  760. if (Target->u.Interrupt.Level == PIC_SLAVE_REDIRECT) {
  761. //
  762. // Search the Alternatives list. If it contains
  763. // PIC_SLAVE_IRQ but not PIC_SLAVE_REDIRECT,
  764. // we should return PIC_SLAVE_IRQ.
  765. //
  766. for (i = 0; i < AlternativesCount; i++) {
  767. if ((Alternatives[i].u.Interrupt.MinimumVector >= PIC_SLAVE_REDIRECT) &&
  768. (Alternatives[i].u.Interrupt.MaximumVector <= PIC_SLAVE_REDIRECT)) {
  769. //
  770. // The list contains, PIC_SLAVE_REDIRECT. Stop
  771. // looking.
  772. //
  773. usePicSlave = FALSE;
  774. break;
  775. }
  776. if ((Alternatives[i].u.Interrupt.MinimumVector >= PIC_SLAVE_IRQ) &&
  777. (Alternatives[i].u.Interrupt.MaximumVector <= PIC_SLAVE_IRQ)) {
  778. //
  779. // The list contains, PIC_SLAVE_IRQ. Use it
  780. // unless we find PIC_SLAVE_REDIRECT later.
  781. //
  782. usePicSlave = TRUE;
  783. }
  784. }
  785. if (usePicSlave) {
  786. Target->u.Interrupt.Level = PIC_SLAVE_IRQ;
  787. Target->u.Interrupt.Vector = PIC_SLAVE_IRQ;
  788. }
  789. }
  790. }
  791. return status;
  792. }
  793. VOID
  794. HalpRecordEisaInterruptVectors(
  795. VOID
  796. )
  797. {
  798. HalpEisaIrqMask = READ_PORT_UCHAR((PUCHAR)EISA_EDGE_LEVEL0) & 0xff;
  799. HalpEisaIrqMask |= READ_PORT_UCHAR((PUCHAR)EISA_EDGE_LEVEL1) << 8;
  800. if ((HalpEisaIrqMask == 0xffff) ||
  801. (HalpEisaIrqMask == 0x0000)) {
  802. HalpEisaIrqIgnore = 0xffff;
  803. }
  804. }