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.

549 lines
15 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. pmapic.c
  5. Abstract:
  6. Implements functions specific to ISA busses
  7. in ACPI-APIC machines.
  8. Author:
  9. Jake Oshins (jakeo) 11-October-1997
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "halp.h"
  15. #include "acpitabl.h"
  16. NTSTATUS
  17. TranslateGlobalVectorToIsaVector(
  18. IN ULONG GlobalVector,
  19. OUT PULONG IsaVector
  20. );
  21. NTSTATUS
  22. HalacpiIrqTranslateResourceRequirementsIsa(
  23. IN PVOID Context,
  24. IN PIO_RESOURCE_DESCRIPTOR Source,
  25. IN PDEVICE_OBJECT PhysicalDeviceObject,
  26. OUT PULONG TargetCount,
  27. OUT PIO_RESOURCE_DESCRIPTOR *Target
  28. );
  29. NTSTATUS
  30. HalacpiIrqTranslateResourcesIsa(
  31. IN PVOID Context,
  32. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
  33. IN RESOURCE_TRANSLATION_DIRECTION Direction,
  34. IN ULONG AlternativesCount, OPTIONAL
  35. IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
  36. IN PDEVICE_OBJECT PhysicalDeviceObject,
  37. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
  38. );
  39. extern ULONG HalpPicVectorRedirect[];
  40. extern FADT HalpFixedAcpiDescTable;
  41. #ifdef ALLOC_PRAGMA
  42. #pragma alloc_text(PAGE, TranslateGlobalVectorToIsaVector)
  43. #pragma alloc_text(PAGE, HalacpiIrqTranslateResourceRequirementsIsa)
  44. #pragma alloc_text(PAGE, HalacpiIrqTranslateResourcesIsa)
  45. #pragma alloc_text(PAGE, HalacpiGetInterruptTranslator)
  46. #endif
  47. #define TranslateIsaVectorToGlobalVector(vector) \
  48. (HalpPicVectorRedirect[vector])
  49. NTSTATUS
  50. TranslateGlobalVectorToIsaVector(
  51. IN ULONG GlobalVector,
  52. OUT PULONG IsaVector
  53. )
  54. {
  55. UCHAR i;
  56. for (i = 0; i < PIC_VECTORS; i++) {
  57. if (HalpPicVectorRedirect[i] == GlobalVector) {
  58. *IsaVector = i;
  59. return STATUS_SUCCESS;
  60. }
  61. }
  62. return STATUS_NOT_FOUND;
  63. }
  64. NTSTATUS
  65. HalacpiIrqTranslateResourceRequirementsIsa(
  66. IN PVOID Context,
  67. IN PIO_RESOURCE_DESCRIPTOR Source,
  68. IN PDEVICE_OBJECT PhysicalDeviceObject,
  69. OUT PULONG TargetCount,
  70. OUT PIO_RESOURCE_DESCRIPTOR *Target
  71. )
  72. /*++
  73. Routine Description:
  74. This function is basically a wrapper for
  75. HalIrqTranslateResourceRequirementsRoot that understands
  76. the weirdnesses of the ISA bus.
  77. Arguments:
  78. Return Value:
  79. status
  80. --*/
  81. {
  82. PIO_RESOURCE_DESCRIPTOR modSource, target, rootTarget;
  83. NTSTATUS status;
  84. BOOLEAN deleteResource;
  85. ULONG sourceCount = 0;
  86. ULONG targetCount = 0;
  87. ULONG resource, resourceLength;
  88. ULONG rootCount;
  89. ULONG irq, startIrq, endIrq;
  90. ULONG maxTargets;
  91. PAGED_CODE();
  92. ASSERT(Source->Type == CmResourceTypeInterrupt);
  93. maxTargets = Source->u.Interrupt.MaximumVector -
  94. Source->u.Interrupt.MinimumVector + 3;
  95. resourceLength = sizeof(IO_RESOURCE_DESCRIPTOR) * maxTargets;
  96. modSource = ExAllocatePoolWithTag(PagedPool, resourceLength, HAL_POOL_TAG);
  97. if (!modSource) {
  98. return STATUS_INSUFFICIENT_RESOURCES;
  99. }
  100. RtlZeroMemory(modSource, resourceLength);
  101. //
  102. // Is the PIC_SLAVE_IRQ in this resource?
  103. //
  104. if ((Source->u.Interrupt.MinimumVector <= PIC_SLAVE_IRQ) &&
  105. (Source->u.Interrupt.MaximumVector >= PIC_SLAVE_IRQ)) {
  106. //
  107. // Clip the maximum
  108. //
  109. if (Source->u.Interrupt.MinimumVector < PIC_SLAVE_IRQ) {
  110. modSource[sourceCount] = *Source;
  111. modSource[sourceCount].u.Interrupt.MinimumVector =
  112. Source->u.Interrupt.MinimumVector;
  113. modSource[sourceCount].u.Interrupt.MaximumVector =
  114. PIC_SLAVE_IRQ - 1;
  115. sourceCount++;
  116. }
  117. //
  118. // Clip the minimum
  119. //
  120. if (Source->u.Interrupt.MaximumVector > PIC_SLAVE_IRQ) {
  121. modSource[sourceCount] = *Source;
  122. modSource[sourceCount].u.Interrupt.MaximumVector =
  123. Source->u.Interrupt.MaximumVector;
  124. modSource[sourceCount].u.Interrupt.MinimumVector =
  125. PIC_SLAVE_IRQ + 1;
  126. sourceCount++;
  127. }
  128. //
  129. // In ISA machines, the PIC_SLAVE_IRQ is rerouted
  130. // to PIC_SLAVE_REDIRECT. So find out if PIC_SLAVE_REDIRECT
  131. // is within this list. If it isn't we need to add it.
  132. //
  133. if (!((Source->u.Interrupt.MinimumVector <= PIC_SLAVE_REDIRECT) &&
  134. (Source->u.Interrupt.MaximumVector >= PIC_SLAVE_REDIRECT))) {
  135. modSource[sourceCount] = *Source;
  136. modSource[sourceCount].u.Interrupt.MinimumVector = PIC_SLAVE_REDIRECT;
  137. modSource[sourceCount].u.Interrupt.MaximumVector = PIC_SLAVE_REDIRECT;
  138. sourceCount++;
  139. }
  140. } else {
  141. *modSource = *Source;
  142. sourceCount = 1;
  143. }
  144. //
  145. // Clip out the SCI vector, if it is here.
  146. //
  147. for (resource = 0; resource < sourceCount; resource++) {
  148. if ((modSource[resource].u.Interrupt.MinimumVector <=
  149. HalpFixedAcpiDescTable.sci_int_vector) &&
  150. (modSource[resource].u.Interrupt.MaximumVector >=
  151. HalpFixedAcpiDescTable.sci_int_vector)) {
  152. //
  153. // The SCI vector is within this range.
  154. //
  155. if (modSource[resource].u.Interrupt.MinimumVector <
  156. HalpFixedAcpiDescTable.sci_int_vector) {
  157. //
  158. // Put a new range on the end of modSource.
  159. //
  160. modSource[sourceCount].u.Interrupt.MinimumVector =
  161. modSource[resource].u.Interrupt.MinimumVector;
  162. modSource[sourceCount].u.Interrupt.MaximumVector =
  163. HalpFixedAcpiDescTable.sci_int_vector - 1;
  164. sourceCount++;
  165. }
  166. if (modSource[resource].u.Interrupt.MaximumVector >
  167. HalpFixedAcpiDescTable.sci_int_vector) {
  168. //
  169. // Put a new range on the end of modSource.
  170. //
  171. modSource[sourceCount].u.Interrupt.MinimumVector =
  172. HalpFixedAcpiDescTable.sci_int_vector + 1;
  173. modSource[sourceCount].u.Interrupt.MaximumVector =
  174. modSource[resource].u.Interrupt.MaximumVector;
  175. sourceCount++;
  176. }
  177. //
  178. // Now remove the range that we just broke up.
  179. //
  180. RtlMoveMemory(modSource + resource,
  181. modSource + resource + 1,
  182. sizeof(IO_RESOURCE_DESCRIPTOR) *
  183. (sourceCount - resource));
  184. sourceCount--;
  185. }
  186. }
  187. target = ExAllocatePoolWithTag(PagedPool, resourceLength, HAL_POOL_TAG);
  188. if (!target) {
  189. ExFreePool(modSource);
  190. return STATUS_INSUFFICIENT_RESOURCES;
  191. }
  192. RtlZeroMemory(target, resourceLength);
  193. //
  194. // Now translate each range from ISA vectors to ACPI
  195. // "global system interrupt vectors." Since GSIVs aren't
  196. // necessarily contiguous with respect to the ISA vectors,
  197. // this may involve breaking each range up into smaller
  198. // ranges, each independently translated into the GSIV space.
  199. //
  200. for (resource = 0; resource < sourceCount; resource++) {
  201. //
  202. // For each existing resource, start with the minimum
  203. // and maximum, unchanged.
  204. //
  205. irq = modSource[resource].u.Interrupt.MinimumVector;
  206. endIrq = modSource[resource].u.Interrupt.MaximumVector;
  207. do {
  208. //
  209. // Now cycle through every IRQ in this range, testing
  210. // to see if its translated value is contiguous
  211. // with respect to the translated value of the next
  212. // IRQ in the range.
  213. //
  214. startIrq = irq;
  215. for (; irq < endIrq; irq++) {
  216. if (TranslateIsaVectorToGlobalVector(irq) + 1 !=
  217. TranslateIsaVectorToGlobalVector(irq + 1)) {
  218. //
  219. // This range is not contiguous. Stop now
  220. // and create a target range.
  221. //
  222. break;
  223. }
  224. }
  225. //
  226. // Clone the source descriptor
  227. //
  228. target[targetCount] = *Source;
  229. //
  230. // Fill in the relevant changes.
  231. //
  232. target[targetCount].u.Interrupt.MinimumVector =
  233. TranslateIsaVectorToGlobalVector(startIrq);
  234. target[targetCount].u.Interrupt.MaximumVector =
  235. TranslateIsaVectorToGlobalVector(irq);
  236. ASSERT(target[targetCount].u.Interrupt.MinimumVector <=
  237. target[targetCount].u.Interrupt.MaximumVector);
  238. targetCount++;
  239. } while (irq != endIrq);
  240. }
  241. *TargetCount = targetCount;
  242. if (targetCount > 0) {
  243. *Target = target;
  244. } else {
  245. ExFreePool(target);
  246. }
  247. ExFreePool(modSource);
  248. return STATUS_SUCCESS;
  249. }
  250. NTSTATUS
  251. HalacpiIrqTranslateResourcesIsa(
  252. IN PVOID Context,
  253. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
  254. IN RESOURCE_TRANSLATION_DIRECTION Direction,
  255. IN ULONG AlternativesCount, OPTIONAL
  256. IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
  257. IN PDEVICE_OBJECT PhysicalDeviceObject,
  258. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
  259. )
  260. /*++
  261. Routine Description:
  262. This function is basically a wrapper for
  263. HalIrqTranslateResourcesRoot that understands
  264. the weirdnesses of the ISA bus.
  265. Arguments:
  266. Return Value:
  267. status
  268. --*/
  269. {
  270. NTSTATUS status;
  271. BOOLEAN usePicSlave = FALSE;
  272. ULONG i;
  273. ULONG vector;
  274. PAGED_CODE();
  275. ASSERT(Source->Type == CmResourceTypeInterrupt);
  276. //
  277. // Copy everything
  278. //
  279. *Target = *Source;
  280. switch (Direction) {
  281. case TranslateChildToParent:
  282. Target->u.Interrupt.Level =
  283. TranslateIsaVectorToGlobalVector(Source->u.Interrupt.Level);
  284. Target->u.Interrupt.Vector =
  285. TranslateIsaVectorToGlobalVector(Source->u.Interrupt.Vector);
  286. break;
  287. case TranslateParentToChild:
  288. status = TranslateGlobalVectorToIsaVector(Source->u.Interrupt.Level,
  289. &vector);
  290. if (!NT_SUCCESS(status)) {
  291. return status;
  292. }
  293. Target->u.Interrupt.Level = vector;
  294. status = TranslateGlobalVectorToIsaVector(Source->u.Interrupt.Vector,
  295. &vector);
  296. if (!NT_SUCCESS(status)) {
  297. return status;
  298. }
  299. Target->u.Interrupt.Vector = vector;
  300. //
  301. // Because the ISA interrupt controller is
  302. // cascaded, there is one case where there is
  303. // a two-to-one mapping for interrupt sources.
  304. // (On a PC, both 2 and 9 trigger vector 9.)
  305. //
  306. // We need to account for this and deliver the
  307. // right value back to the driver.
  308. //
  309. if (Target->u.Interrupt.Level == PIC_SLAVE_REDIRECT) {
  310. //
  311. // Search the Alternatives list. If it contains
  312. // PIC_SLAVE_IRQ but not PIC_SLAVE_REDIRECT,
  313. // we should return PIC_SLAVE_IRQ.
  314. //
  315. for (i = 0; i < AlternativesCount; i++) {
  316. if ((Alternatives[i].u.Interrupt.MinimumVector >= PIC_SLAVE_REDIRECT) &&
  317. (Alternatives[i].u.Interrupt.MaximumVector <= PIC_SLAVE_REDIRECT)) {
  318. //
  319. // The list contains, PIC_SLAVE_REDIRECT. Stop
  320. // looking.
  321. //
  322. usePicSlave = FALSE;
  323. break;
  324. }
  325. if ((Alternatives[i].u.Interrupt.MinimumVector >= PIC_SLAVE_IRQ) &&
  326. (Alternatives[i].u.Interrupt.MaximumVector <= PIC_SLAVE_IRQ)) {
  327. //
  328. // The list contains, PIC_SLAVE_IRQ. Use it
  329. // unless we find PIC_SLAVE_REDIRECT later.
  330. //
  331. usePicSlave = TRUE;
  332. }
  333. }
  334. if (usePicSlave) {
  335. Target->u.Interrupt.Level = PIC_SLAVE_IRQ;
  336. Target->u.Interrupt.Vector = PIC_SLAVE_IRQ;
  337. }
  338. }
  339. break;
  340. }
  341. return STATUS_SUCCESS;
  342. }
  343. NTSTATUS
  344. HalacpiGetInterruptTranslator(
  345. IN INTERFACE_TYPE ParentInterfaceType,
  346. IN ULONG ParentBusNumber,
  347. IN INTERFACE_TYPE BridgeInterfaceType,
  348. IN USHORT Size,
  349. IN USHORT Version,
  350. OUT PTRANSLATOR_INTERFACE Translator,
  351. OUT PULONG BridgeBusNumber
  352. )
  353. /*++
  354. Routine Description:
  355. Arguments:
  356. ParentInterfaceType - The type of the bus the bridge lives on (normally PCI).
  357. ParentBusNumber - The number of the bus the bridge lives on.
  358. ParentSlotNumber - The slot number the bridge lives in (where valid).
  359. BridgeInterfaceType - The bus type the bridge provides (ie ISA for a PCI-ISA bridge).
  360. ResourceType - The resource type we want to translate.
  361. Size - The size of the translator buffer.
  362. Version - The version of the translator interface requested.
  363. Translator - Pointer to the buffer where the translator should be returned
  364. BridgeBusNumber - Pointer to where the bus number of the bridge bus should be returned
  365. Return Value:
  366. Returns the status of this operation.
  367. --*/
  368. {
  369. PAGED_CODE();
  370. UNREFERENCED_PARAMETER(ParentInterfaceType);
  371. UNREFERENCED_PARAMETER(ParentBusNumber);
  372. ASSERT(Version == HAL_IRQ_TRANSLATOR_VERSION);
  373. ASSERT(Size >= sizeof (TRANSLATOR_INTERFACE));
  374. switch (BridgeInterfaceType) {
  375. case Eisa:
  376. case Isa:
  377. case InterfaceTypeUndefined: // special "IDE" cookie
  378. //
  379. // Pass back an interface for an IRQ translator for
  380. // the (E)ISA interrupts.
  381. //
  382. RtlZeroMemory(Translator, sizeof (TRANSLATOR_INTERFACE));
  383. Translator->Size = sizeof (TRANSLATOR_INTERFACE);
  384. Translator->Version = HAL_IRQ_TRANSLATOR_VERSION;
  385. Translator->InterfaceReference = &HalTranslatorReference;
  386. Translator->InterfaceDereference = &HalTranslatorDereference;
  387. Translator->TranslateResources = &HalacpiIrqTranslateResourcesIsa;
  388. Translator->TranslateResourceRequirements = &HalacpiIrqTranslateResourceRequirementsIsa;
  389. return STATUS_SUCCESS;
  390. default:
  391. return STATUS_NOT_IMPLEMENTED;
  392. }
  393. }