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.

495 lines
12 KiB

  1. //
  2. /**
  3. *** Copyright (C) 1996-97 Intel Corporation. All rights reserved.
  4. ***
  5. *** The information and source code contained herein is the exclusive
  6. *** property of Intel Corporation and may not be disclosed, examined
  7. *** or reproduced in whole or in part without explicit written authorization
  8. *** from the company.
  9. **/
  10. /*++
  11. Copyright (c) 1995 Intel Corporation
  12. Module Name:
  13. i64sxint.c copied from simsxint.c
  14. Abstract:
  15. This module implements the routines to manage the
  16. system interrupt and IRQL.
  17. Author:
  18. William K. Cheung (wcheung) 14-Apr-1995
  19. Bernard Lint
  20. M. Jayakumar (Muthurajan.Jayakumar@intel.com)
  21. Environment:
  22. Kernel mode
  23. Revision History:
  24. Todd Kjos (HP) (v-tkjos) 1-Jun-1998 : Added I/O Sapic support
  25. Thierry Fevrier (HP) (v-thief) 8-Feb-2000 : Profiling support
  26. --*/
  27. #include "halp.h"
  28. #include "iosapic.h"
  29. VOID HalpInitLINT(VOID);
  30. extern KSPIN_LOCK HalpIoSapicLock;
  31. extern PULONG_PTR *HalEOITable[];
  32. PULONG_PTR HalpEOITableP0[MAX_INTR_VECTOR];
  33. VOID
  34. HalpInitializeInterrupts (
  35. VOID
  36. )
  37. /*++
  38. Routine Description:
  39. This function initializes interrupts for an IA64 system.
  40. Arguments:
  41. None.
  42. Return Value:
  43. None.
  44. Note:
  45. In KiInitializeKernel(), PCR.InterruptRoutine[] entries have been first initialized
  46. with the Unexpected Interrupt code then entries index-0, APC_VECTOR, DISPATCH_VECTOR
  47. have been initialized with their respective interrupt handlers.
  48. --*/
  49. {
  50. //
  51. // Turn off LINT0 LINT1 (disable 8259)
  52. //
  53. // We used to call HalpInitLINT here. However it was unnecessary since we
  54. // already called it in HalInitializeProcessor. Also it meant that if a
  55. // CPE occurred prior to this point we would lose it.
  56. //
  57. // interval timer interrupt; 10ms by default
  58. //
  59. HalpInitializeClockInterrupts();
  60. //
  61. // Initialize SpuriousInterrupt
  62. //
  63. HalpSetInternalVector(SAPIC_SPURIOUS_VECTOR, HalpSpuriousHandler);
  64. //
  65. // Initialize CMCI Interrupt
  66. //
  67. // Note that it is possible that HAL_CMC_PRESENT is not set.
  68. // With the current implementation, we always connect the vector to the ISR.
  69. //
  70. HalpSetInternalVector(CMCI_VECTOR, HalpCMCIHandler);
  71. //
  72. // Initialize CPEI Interrupt
  73. //
  74. // Note that it is possible that HAL_CPE_PRESENT is not set.
  75. // With the current implementation, we always connect the vector to the ISR.
  76. //
  77. HalpSetInternalVector(CPEI_VECTOR, HalpCPEIHandler);
  78. //
  79. // Initialiaze MC Rendezvous Interrupt
  80. //
  81. HalpSetInternalVector(MC_RZ_VECTOR, HalpMcRzHandler);
  82. //
  83. // Initialize MC Wakeup Interrupt
  84. //
  85. HalpSetInternalVector(MC_WKUP_VECTOR, HalpMcWkupHandler);
  86. //
  87. // IPI Interrupt
  88. //
  89. HalpSetInternalVector(IPI_VECTOR, HalpIpiInterruptHandler);
  90. //
  91. // profile timer interrupt; turned off initially
  92. //
  93. HalpSetInternalVector(PROFILE_VECTOR, HalpProfileInterrupt);
  94. //
  95. // Performance monitor interrupt
  96. //
  97. HalpSetInternalVector(PERF_VECTOR, HalpPerfInterrupt);
  98. } // HalpInitializeInterrupts()
  99. VOID
  100. HalpInitEOITable(
  101. VOID
  102. )
  103. {
  104. USHORT Index;
  105. ULONG ProcessorNumber;
  106. // Allocate and Initialize EOI table on current processor
  107. ProcessorNumber = PCR->Prcb->Number;
  108. if (ProcessorNumber == 0) {
  109. HalEOITable[ProcessorNumber] = HalpEOITableP0;
  110. } else {
  111. HalEOITable[ProcessorNumber] = ExAllocatePool(NonPagedPool,
  112. MAX_INTR_VECTOR*sizeof(HalEOITable[0]));
  113. }
  114. // For kernel access to eoi table
  115. PCR->EOITable = HalEOITable[ProcessorNumber];
  116. for (Index=0; Index < MAX_INTR_VECTOR; Index++) {
  117. HalEOITable[ProcessorNumber][Index] = 0;
  118. }
  119. }
  120. VOID
  121. HalpWriteEOITable(
  122. IN ULONG Vector,
  123. IN PULONG_PTR EoiAddress,
  124. IN ULONG Number
  125. )
  126. /*++
  127. Routine Description:
  128. This routine updates the EOI table for a processor
  129. Arguments:
  130. Vector - Entry to update (IDT entry)
  131. EoiAddress - Address to write (SAPIC address)
  132. Number - Logical (NT) processor number
  133. Return Value:
  134. None
  135. --*/
  136. {
  137. if (HalEOITable != NULL && HalEOITable[Number] != NULL) {
  138. HalEOITable[Number][Vector] = EoiAddress;
  139. }
  140. }
  141. BOOLEAN
  142. HalEnableSystemInterrupt (
  143. IN ULONG Vector,
  144. IN KIRQL Irql,
  145. IN KINTERRUPT_MODE InterruptMode
  146. )
  147. /*++
  148. Routine Description:
  149. This routine enables the specified system interrupt.
  150. N.B. This routine assumes that the caller has provided any required
  151. synchronization to enable a system interrupt.
  152. Arguments:
  153. Vector - Supplies the vector of the system interrupt that is enabled.
  154. Irql - Supplies the IRQL of the interrupting source.
  155. InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
  156. Latched.
  157. Return Value:
  158. TRUE if the system interrupt was enabled
  159. --*/
  160. {
  161. ULONG Entry, Destination;
  162. ULONG OldLevel;
  163. ULONG Inti;
  164. ULONG LevelAndPolarity;
  165. USHORT ThisCpuApicID;
  166. ULONG InterruptType;
  167. BOOLEAN RetVal = TRUE;
  168. UCHAR IDTEntry;
  169. ASSERT(Vector < (ULONG)((1+HAL_MAXIMUM_PROCESSOR)*0x100-1));
  170. ASSERT(Irql <= HIGH_LEVEL);
  171. HalDebugPrint(( HAL_VERBOSE, "HAL: HalpEnableSystemInterrupt - INTI=0x%x Vector=0x%x IRQL=0x%x\n",
  172. HalpVectorToINTI[Vector],
  173. Vector,
  174. Irql ));
  175. if ( (Inti = HalpVectorToINTI[Vector]) == ~0UL ) {
  176. return FALSE;
  177. }
  178. if (HalpIsInternalInterruptVector(Vector)) {
  179. //
  180. // There is no external device associated with this interrupt,
  181. // but it might be an internal interrupt i.e. one that never
  182. // involves the IOSAPIC.
  183. //
  184. return TRUE;
  185. }
  186. // Make sure the passed-in level matches our settings...
  187. if ((InterruptMode == LevelSensitive && !HalpIsLevelTriggered(Inti)) ||
  188. (InterruptMode != LevelSensitive && HalpIsLevelTriggered(Inti)) ) {
  189. // It doesn't match!
  190. HalDebugPrint(( HAL_INFO, "HAL: HalpEnableSystemInterrupt - Warning device interrupt mode overridden\n"));
  191. }
  192. LevelAndPolarity =
  193. (HalpIsLevelTriggered(Inti) ? LEVEL_TRIGGERED : EDGE_TRIGGERED) |
  194. (HalpIsActiveLow(Inti) ? ACTIVE_LOW : ACTIVE_HIGH);
  195. //
  196. // Block interrupts and synchronize until we're done
  197. //
  198. OldLevel = HalpAcquireHighLevelLock (&HalpIoSapicLock);
  199. ThisCpuApicID = (USHORT)KeGetPcr()->HalReserved[PROCESSOR_ID_INDEX];
  200. // Get Interrupt type
  201. HalpGetRedirEntry(Inti,&Entry,&Destination);
  202. InterruptType = Entry & INT_TYPE_MASK;
  203. IDTEntry = HalVectorToIDTEntry(Vector);
  204. switch (InterruptType) {
  205. case DELIVER_FIXED:
  206. case DELIVER_LOW_PRIORITY:
  207. //
  208. // Normal external interrupt...
  209. // Enable the interrupt in the I/O SAPIC redirection table
  210. //
  211. if (IDTEntry < 16) {
  212. // Reserved vectors: Extint, NMI, IntelReserved
  213. // No vectors in this range can be assigned
  214. ASSERT(0);
  215. RetVal = FALSE;
  216. break;
  217. }
  218. //
  219. // All external interrupts are delivered as Fixed interrupts
  220. // without the "redirectable" bit set (aka Lowest Priority). This
  221. // disallows hardware to redirect the interrupts using the XTP mechanism.
  222. //
  223. Entry = (ULONG)IDTEntry | LevelAndPolarity;
  224. HalpSetRedirEntry ( Inti, Entry, ThisCpuApicID );
  225. break;
  226. case DELIVER_EXTINT:
  227. //
  228. // This is an interrupt that uses the IO Sapic to route PIC
  229. // events. This configuration is not supported in IA64.
  230. //
  231. ASSERT(0);
  232. RetVal = FALSE;
  233. break;
  234. default:
  235. HalDebugPrint(( HAL_ERROR, "HAL: HalEnableSystemInterrupt - Unknown Interrupt Type: %d\n",
  236. InterruptType));
  237. RetVal = FALSE;
  238. break;
  239. } // switch (InterruptType)
  240. HalpReleaseHighLevelLock (&HalpIoSapicLock, OldLevel);
  241. return(RetVal);
  242. }
  243. VOID
  244. HalDisableSystemInterrupt (
  245. IN ULONG Vector,
  246. IN KIRQL Irql
  247. )
  248. /*++
  249. Routine Description:
  250. This routine disables the specified system interrupt.
  251. In the simulation environment, this function does nothing and returns.
  252. N.B. This routine assumes that the caller has provided any required
  253. synchronization to disable a system interrupt.
  254. Arguments:
  255. Vector - Supplies the vector of the system interrupt that is disabled.
  256. Irql - Supplies the IRQL of the interrupting source.
  257. Return Value:
  258. None.
  259. --*/
  260. {
  261. ULONG Entry, Destination;
  262. ULONG OldLevel;
  263. ULONG Inti;
  264. ULONG LevelAndPolarity;
  265. ULONG ThisCpuApicID;
  266. ULONG InterruptType;
  267. ASSERT(Vector < (1+HAL_MAXIMUM_PROCESSOR)*0x100-1);
  268. ASSERT(Irql <= HIGH_LEVEL);
  269. HalDebugPrint(( HAL_INFO, "HAL: HalpDisableSystemInterrupt: INTI=%x Vector=%x IRQL=%x\n",
  270. HalpVectorToINTI[Vector],
  271. Vector,
  272. Irql));
  273. if ( (Inti = HalpVectorToINTI[Vector]) == (ULONG)-1 ) {
  274. //
  275. // There is no external device associated with this interrupt
  276. //
  277. return;
  278. }
  279. //
  280. // Block interrupts and synchronize until we're done
  281. //
  282. OldLevel = HalpAcquireHighLevelLock(&HalpIoSapicLock);
  283. ThisCpuApicID = (USHORT)KeGetPcr()->HalReserved[PROCESSOR_ID_INDEX];
  284. // Get Interrupt Type and Destination
  285. HalpGetRedirEntry(Inti, &Entry, &Destination);
  286. if (ThisCpuApicID != Destination) {
  287. // The interrupt is not enabled on this Cpu
  288. HalpReleaseHighLevelLock (&HalpIoSapicLock, OldLevel);
  289. return;
  290. }
  291. InterruptType = Entry & INT_TYPE_MASK;
  292. switch (InterruptType) {
  293. case DELIVER_FIXED:
  294. //
  295. // Normal external interrupt...
  296. // Disable the interrupt in the I/O SAPIC redirection table
  297. //
  298. if (Vector < 16) {
  299. // Reserved vectors: Extint, NMI, IntelReserved
  300. // No vectors in this range can be assigned
  301. ASSERT(0);
  302. break;
  303. }
  304. HalpDisableRedirEntry (Inti);
  305. break;
  306. case DELIVER_EXTINT:
  307. //
  308. // This is an interrupt that uses the IO Sapic to route PIC
  309. // events. This configuration is not supported in IA64.
  310. //
  311. ASSERT(0);
  312. break;
  313. default:
  314. HalDebugPrint(( HAL_INFO, "HAL: HalDisableSystemInterrupt - Unknown Interrupt Type: %d\n",
  315. InterruptType ));
  316. break;
  317. } // switch (InterruptType)
  318. HalpReleaseHighLevelLock (&HalpIoSapicLock, OldLevel);
  319. }
  320. ULONG
  321. HalpGetProcessorNumberByApicId(
  322. USHORT ApicId
  323. )
  324. /*++
  325. Routine Description:
  326. This routine returns the logical processor number for a given
  327. physical processor id (extended local sapic id)
  328. Arguments:
  329. ApicId -- Extended ID of processor (16 bit id)
  330. Return Value:
  331. Logical (NT) processor number
  332. --*/
  333. {
  334. ULONG index;
  335. for (index = 0; index < HalpMpInfo.ProcessorCount; index++) {
  336. if (ApicId == HalpProcessorInfo[index].LocalApicID) {
  337. return HalpProcessorInfo[index].NtProcessorNumber;
  338. }
  339. }
  340. ASSERT (index < HalpMpInfo.ProcessorCount);
  341. //
  342. // Note: The previous code returned an invalid index (HalpMpInfo.ProcessorCount
  343. // which is 1 greater than the number of processors) we should probably
  344. // just bugcheck here.
  345. //
  346. return 0;
  347. }