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.

437 lines
12 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. BOOLEAN
  12. HalpTranslateIsaBusAddress (
  13. IN PVOID BusHandler,
  14. IN PVOID RootHandler,
  15. IN PHYSICAL_ADDRESS BusAddress,
  16. IN OUT PULONG AddressSpace,
  17. OUT PPHYSICAL_ADDRESS TranslatedAddress
  18. );
  19. BOOLEAN
  20. HalpTranslateEisaBusAddress (
  21. IN PVOID BusHandler,
  22. IN PVOID RootHandler,
  23. IN PHYSICAL_ADDRESS BusAddress,
  24. IN OUT PULONG AddressSpace,
  25. OUT PPHYSICAL_ADDRESS TranslatedAddress
  26. );
  27. BOOLEAN
  28. HalpTranslateSystemBusAddress (
  29. IN PVOID BusHandler,
  30. IN PVOID RootHandler,
  31. IN PHYSICAL_ADDRESS BusAddress,
  32. IN OUT PULONG AddressSpace,
  33. OUT PPHYSICAL_ADDRESS TranslatedAddress
  34. );
  35. #ifdef ALLOC_PRAGMA
  36. #pragma alloc_text(PAGE,HalIrqTranslateResourceRequirementsIsa)
  37. #pragma alloc_text(PAGE,HalIrqTranslateResourcesIsa)
  38. #endif
  39. NTSTATUS
  40. HalIrqTranslateResourceRequirementsIsa(
  41. IN PVOID Context,
  42. IN PIO_RESOURCE_DESCRIPTOR Source,
  43. IN PDEVICE_OBJECT PhysicalDeviceObject,
  44. OUT PULONG TargetCount,
  45. OUT PIO_RESOURCE_DESCRIPTOR *Target
  46. )
  47. /*++
  48. Routine Description:
  49. This function is basically a wrapper for
  50. HalIrqTranslateResourceRequirementsRoot that understands
  51. the weirdnesses of the ISA bus.
  52. Arguments:
  53. Return Value:
  54. status
  55. --*/
  56. {
  57. PIO_RESOURCE_DESCRIPTOR modSource, target, rootTarget;
  58. NTSTATUS status;
  59. BOOLEAN picSlaveDeleted = FALSE;
  60. BOOLEAN deleteResource;
  61. ULONG sourceCount = 0;
  62. ULONG targetCount = 0;
  63. ULONG resource;
  64. ULONG rootCount;
  65. ULONG invalidIrq;
  66. PAGED_CODE();
  67. ASSERT(Source->Type == CmResourceTypeInterrupt);
  68. modSource = ExAllocatePoolWithTag(
  69. NonPagedPool,
  70. //
  71. // we will have at most nine ranges when we are done
  72. //
  73. sizeof(IO_RESOURCE_DESCRIPTOR) * 9,
  74. HAL_POOL_TAG
  75. );
  76. if (!modSource) {
  77. return STATUS_INSUFFICIENT_RESOURCES;
  78. }
  79. RtlZeroMemory(modSource, sizeof(IO_RESOURCE_DESCRIPTOR) * 9);
  80. //
  81. // Is the PIC_SLAVE_IRQ in this resource?
  82. //
  83. if ((Source->u.Interrupt.MinimumVector <= PIC_SLAVE_IRQ) &&
  84. (Source->u.Interrupt.MaximumVector >= PIC_SLAVE_IRQ)) {
  85. //
  86. // Clip the maximum
  87. //
  88. if (Source->u.Interrupt.MinimumVector < PIC_SLAVE_IRQ) {
  89. modSource[sourceCount] = *Source;
  90. modSource[sourceCount].u.Interrupt.MinimumVector =
  91. Source->u.Interrupt.MinimumVector;
  92. modSource[sourceCount].u.Interrupt.MaximumVector =
  93. PIC_SLAVE_IRQ - 1;
  94. sourceCount++;
  95. }
  96. //
  97. // Clip the minimum
  98. //
  99. if (Source->u.Interrupt.MaximumVector > PIC_SLAVE_IRQ) {
  100. modSource[sourceCount] = *Source;
  101. modSource[sourceCount].u.Interrupt.MaximumVector =
  102. Source->u.Interrupt.MaximumVector;
  103. modSource[sourceCount].u.Interrupt.MinimumVector =
  104. PIC_SLAVE_IRQ + 1;
  105. sourceCount++;
  106. }
  107. //
  108. // In ISA machines, the PIC_SLAVE_IRQ is rerouted
  109. // to PIC_SLAVE_REDIRECT. So find out if PIC_SLAVE_REDIRECT
  110. // is within this list. If it isn't we need to add it.
  111. //
  112. if (!((Source->u.Interrupt.MinimumVector <= PIC_SLAVE_REDIRECT) &&
  113. (Source->u.Interrupt.MaximumVector >= PIC_SLAVE_REDIRECT))) {
  114. modSource[sourceCount] = *Source;
  115. modSource[sourceCount].u.Interrupt.MinimumVector=PIC_SLAVE_REDIRECT;
  116. modSource[sourceCount].u.Interrupt.MaximumVector=PIC_SLAVE_REDIRECT;
  117. sourceCount++;
  118. }
  119. } else {
  120. *modSource = *Source;
  121. sourceCount = 1;
  122. }
  123. //
  124. // Now that the PIC_SLAVE_IRQ has been handled, we have
  125. // to take into account IRQs that may have been steered
  126. // away to the PCI bus.
  127. //
  128. // N.B. The algorithm used below may produce resources
  129. // with minimums greater than maximums. Those will
  130. // be stripped out later.
  131. //
  132. for (invalidIrq = 0; invalidIrq < PIC_VECTORS; invalidIrq++) {
  133. //
  134. // Look through all the resources, possibly removing
  135. // this IRQ from them.
  136. //
  137. for (resource = 0; resource < sourceCount; resource++) {
  138. deleteResource = FALSE;
  139. if (HalpPciIrqMask & (1 << invalidIrq)) {
  140. //
  141. // This IRQ belongs to the PCI bus.
  142. //
  143. if (!((HalpBusType == MACHINE_TYPE_EISA) &&
  144. ((modSource[resource].Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE)))) {
  145. //
  146. // And this resource is not an EISA-style,
  147. // level-triggered interrupt.
  148. //
  149. // N.B. Only the system BIOS truely knows
  150. // whether an IRQ on a PCI bus can be
  151. // shared with an IRQ on an ISA bus.
  152. // This code assumes that, in the case
  153. // that the BIOS set an EISA device to
  154. // the same interrupt as a PCI device,
  155. // the machine can actually function.
  156. //
  157. deleteResource = TRUE;
  158. }
  159. }
  160. if (deleteResource) {
  161. if (modSource[resource].u.Interrupt.MinimumVector == invalidIrq) {
  162. modSource[resource].u.Interrupt.MinimumVector++;
  163. } else if (modSource[resource].u.Interrupt.MaximumVector == invalidIrq) {
  164. modSource[resource].u.Interrupt.MaximumVector--;
  165. } else if ((modSource[resource].u.Interrupt.MinimumVector < invalidIrq) &&
  166. (modSource[resource].u.Interrupt.MaximumVector > invalidIrq)) {
  167. //
  168. // Copy the current resource into a new resource.
  169. //
  170. modSource[sourceCount] = modSource[resource];
  171. //
  172. // Clip the current resource to a range below invalidIrq.
  173. //
  174. modSource[resource].u.Interrupt.MaximumVector = invalidIrq - 1;
  175. //
  176. // Clip the new resource to a range above invalidIrq.
  177. //
  178. modSource[sourceCount].u.Interrupt.MinimumVector = invalidIrq + 1;
  179. sourceCount++;
  180. }
  181. }
  182. }
  183. }
  184. target = ExAllocatePoolWithTag(PagedPool,
  185. sizeof(IO_RESOURCE_DESCRIPTOR) * sourceCount,
  186. HAL_POOL_TAG
  187. );
  188. if (!target) {
  189. ExFreePool(modSource);
  190. return STATUS_INSUFFICIENT_RESOURCES;
  191. }
  192. //
  193. // Now send each of these ranges through
  194. // HalIrqTranslateResourceRequirementsRoot.
  195. //
  196. for (resource = 0; resource < sourceCount; resource++) {
  197. //
  198. // Skip over resources that we have previously
  199. // clobbered (while deleting PCI IRQs.)
  200. //
  201. if (modSource[resource].u.Interrupt.MinimumVector >
  202. modSource[resource].u.Interrupt.MaximumVector) {
  203. continue;
  204. }
  205. status = HalIrqTranslateResourceRequirementsRoot(
  206. Context,
  207. &modSource[resource],
  208. PhysicalDeviceObject,
  209. &rootCount,
  210. &rootTarget
  211. );
  212. if (!NT_SUCCESS(status)) {
  213. ExFreePool(target);
  214. goto HalIrqTranslateResourceRequirementsIsaExit;
  215. }
  216. //
  217. // HalIrqTranslateResourceRequirementsRoot should return
  218. // either one resource or, occasionally, zero.
  219. //
  220. ASSERT(rootCount <= 1);
  221. if (rootCount == 1) {
  222. target[targetCount] = *rootTarget;
  223. targetCount++;
  224. ExFreePool(rootTarget);
  225. }
  226. }
  227. *TargetCount = targetCount;
  228. if (targetCount > 0) {
  229. *Target = target;
  230. } else {
  231. ExFreePool(target);
  232. }
  233. status = STATUS_TRANSLATION_COMPLETE;
  234. HalIrqTranslateResourceRequirementsIsaExit:
  235. ExFreePool(modSource);
  236. return status;
  237. }
  238. NTSTATUS
  239. HalIrqTranslateResourcesIsa(
  240. IN PVOID Context,
  241. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
  242. IN RESOURCE_TRANSLATION_DIRECTION Direction,
  243. IN ULONG AlternativesCount, OPTIONAL
  244. IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
  245. IN PDEVICE_OBJECT PhysicalDeviceObject,
  246. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
  247. )
  248. /*++
  249. Routine Description:
  250. This function is basically a wrapper for
  251. HalIrqTranslateResourcesRoot that understands
  252. the weirdnesses of the ISA bus.
  253. Arguments:
  254. Return Value:
  255. status
  256. --*/
  257. {
  258. CM_PARTIAL_RESOURCE_DESCRIPTOR modSource;
  259. NTSTATUS status;
  260. BOOLEAN usePicSlave = FALSE;
  261. ULONG i;
  262. modSource = *Source;
  263. if (Direction == TranslateChildToParent) {
  264. if (Source->u.Interrupt.Vector == PIC_SLAVE_IRQ) {
  265. modSource.u.Interrupt.Vector = PIC_SLAVE_REDIRECT;
  266. modSource.u.Interrupt.Level = PIC_SLAVE_REDIRECT;
  267. }
  268. }
  269. status = HalIrqTranslateResourcesRoot(
  270. Context,
  271. &modSource,
  272. Direction,
  273. AlternativesCount,
  274. Alternatives,
  275. PhysicalDeviceObject,
  276. Target);
  277. if (!NT_SUCCESS(status)) {
  278. return status;
  279. }
  280. if (Direction == TranslateParentToChild) {
  281. //
  282. // Because the ISA interrupt controller is
  283. // cascaded, there is one case where there is
  284. // a two-to-one mapping for interrupt sources.
  285. // (On a PC, both 2 and 9 trigger vector 9.)
  286. //
  287. // We need to account for this and deliver the
  288. // right value back to the driver.
  289. //
  290. if (Target->u.Interrupt.Level == PIC_SLAVE_REDIRECT) {
  291. //
  292. // Search the Alternatives list. If it contains
  293. // PIC_SLAVE_IRQ but not PIC_SLAVE_REDIRECT,
  294. // we should return PIC_SLAVE_IRQ.
  295. //
  296. for (i = 0; i < AlternativesCount; i++) {
  297. if ((Alternatives[i].u.Interrupt.MinimumVector >= PIC_SLAVE_REDIRECT) &&
  298. (Alternatives[i].u.Interrupt.MaximumVector <= PIC_SLAVE_REDIRECT)) {
  299. //
  300. // The list contains, PIC_SLAVE_REDIRECT. Stop
  301. // looking.
  302. //
  303. usePicSlave = FALSE;
  304. break;
  305. }
  306. if ((Alternatives[i].u.Interrupt.MinimumVector >= PIC_SLAVE_IRQ) &&
  307. (Alternatives[i].u.Interrupt.MaximumVector <= PIC_SLAVE_IRQ)) {
  308. //
  309. // The list contains, PIC_SLAVE_IRQ. Use it
  310. // unless we find PIC_SLAVE_REDIRECT later.
  311. //
  312. usePicSlave = TRUE;
  313. }
  314. }
  315. if (usePicSlave) {
  316. Target->u.Interrupt.Level = PIC_SLAVE_IRQ;
  317. Target->u.Interrupt.Vector = PIC_SLAVE_IRQ;
  318. }
  319. }
  320. }
  321. return status;
  322. }