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.

444 lines
9.4 KiB

  1. //
  2. // No Check-in Source Code.
  3. //
  4. // Do not make this code available to non-Microsoft personnel
  5. // without Intel's express permission
  6. //
  7. /**
  8. *** Copyright (C) 1996-97 Intel Corporation. All rights reserved.
  9. ***
  10. *** The information and source code contained herein is the exclusive
  11. *** property of Intel Corporation and may not be disclosed, examined
  12. *** or reproduced in whole or in part without explicit written authorization
  13. *** from the company.
  14. **/
  15. /*++
  16. Copyright (c) 1995 Intel Corporation
  17. Module Name:
  18. simsxint.c
  19. Abstract:
  20. This module implements the routines to manage the
  21. system interrupt and IRQL.
  22. Author:
  23. William K. Cheung (wcheung) 14-Apr-1995
  24. Environment:
  25. Kernel mode
  26. Revision History:
  27. --*/
  28. #include "halp.h"
  29. PULONGLONG HalEOITable[256];
  30. VOID
  31. HalpInitEOITable(
  32. VOID
  33. )
  34. {
  35. USHORT Index;
  36. for (Index=0; Index < 256; Index++) {
  37. HalEOITable[Index] = 0;
  38. }
  39. }
  40. VOID
  41. HalpInitializeInterrupts (
  42. VOID
  43. )
  44. {
  45. ULONG Index;
  46. ULONG InterruptVector;
  47. //
  48. // Interrupt routine table initialization in KiInitializeKernel.
  49. //
  50. //
  51. // interval timer interrupt; 10ms by default
  52. //
  53. InterruptVector = CLOCK_LEVEL << VECTOR_IRQL_SHIFT;
  54. PCR->InterruptRoutine[InterruptVector] = (PKINTERRUPT_ROUTINE)HalpClockInterrupt;
  55. SscConnectInterrupt(SSC_CLOCK_TIMER_INTERRUPT, InterruptVector);
  56. SscSetPeriodicInterruptInterval(
  57. SSC_CLOCK_TIMER_INTERRUPT,
  58. DEFAULT_CLOCK_INTERVAL * 100
  59. );
  60. //
  61. // profile timer interrupt; turned off initially
  62. //
  63. InterruptVector = PROFILE_LEVEL << VECTOR_IRQL_SHIFT;
  64. PCR->InterruptRoutine[InterruptVector] = (PKINTERRUPT_ROUTINE)HalpProfileInterrupt;
  65. SscConnectInterrupt(SSC_PROFILE_TIMER_INTERRUPT, InterruptVector);
  66. SscSetPeriodicInterruptInterval (SSC_PROFILE_TIMER_INTERRUPT, 0);
  67. //
  68. // s/w interrupts; corresponding ISRs provided by kernel.
  69. //
  70. SscConnectInterrupt (SSC_APC_INTERRUPT, APC_VECTOR);
  71. SscConnectInterrupt (SSC_DPC_INTERRUPT, DISPATCH_VECTOR);
  72. }
  73. BOOLEAN
  74. HalEnableSystemInterrupt (
  75. IN ULONG Vector,
  76. IN KIRQL Irql,
  77. IN KINTERRUPT_MODE InterruptMode
  78. )
  79. /*++
  80. Routine Description:
  81. This routine enables the specified system interrupt.
  82. N.B. This routine assumes that the caller has provided any required
  83. synchronization to enable a system interrupt.
  84. Arguments:
  85. Vector - Supplies the vector of the system interrupt that is enabled.
  86. Irql - Supplies the IRQL of the interrupting source.
  87. InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
  88. Latched.
  89. Return Value:
  90. TRUE if the system interrupt was enabled
  91. --*/
  92. {
  93. KIRQL OldIrql;
  94. BOOLEAN Result = TRUE;
  95. //
  96. // Raise IRQL to the highest level.
  97. //
  98. KeRaiseIrql (HIGH_LEVEL, &OldIrql);
  99. switch (Irql) {
  100. case DISK_IRQL:
  101. SscConnectInterrupt (SSC_DISK_INTERRUPT, Vector);
  102. break;
  103. case MOUSE_IRQL:
  104. SscConnectInterrupt (SSC_MOUSE_INTERRUPT, Vector);
  105. break;
  106. case KEYBOARD_IRQL:
  107. SscConnectInterrupt (SSC_KEYBOARD_INTERRUPT, Vector);
  108. break;
  109. case SERIAL_IRQL:
  110. SscConnectInterrupt (SSC_SERIAL_INTERRUPT, Vector);
  111. break;
  112. default:
  113. //
  114. // Invalid Device Interrupt Source; only three devices
  115. // defined in the Gambit platform.
  116. //
  117. Result = FALSE;
  118. DbgPrint("HalEnableSystemInterrupt: Invalid Device Interrupt Source");
  119. break;
  120. }
  121. //
  122. // Restore the original IRQL
  123. //
  124. KeLowerIrql (OldIrql);
  125. return (Result);
  126. }
  127. VOID
  128. HalDisableSystemInterrupt (
  129. IN ULONG Vector,
  130. IN KIRQL Irql
  131. )
  132. /*++
  133. Routine Description:
  134. This routine disables the specified system interrupt.
  135. In the simulation environment, this function does nothing and returns.
  136. N.B. This routine assumes that the caller has provided any required
  137. synchronization to disable a system interrupt.
  138. Arguments:
  139. Vector - Supplies the vector of the system interrupt that is disabled.
  140. Irql - Supplies the IRQL of the interrupting source.
  141. Return Value:
  142. None.
  143. --*/
  144. {
  145. return;
  146. }
  147. ULONG
  148. HalGetInterruptVector(
  149. IN INTERFACE_TYPE InterfaceType,
  150. IN ULONG BusNumber,
  151. IN ULONG BusInterruptLevel,
  152. IN ULONG BusInterruptVector,
  153. OUT PKIRQL Irql,
  154. OUT PKAFFINITY Affinity
  155. )
  156. /*++
  157. Routine Description:
  158. This function returns the system interrupt vector and IRQL level
  159. corresponding to the specified bus interrupt level and/or vector. The
  160. system interrupt vector and IRQL are suitable for use in a subsequent call
  161. to KeInitializeInterrupt.
  162. In the simulation environment, just return the parameters passed in
  163. from the caller - the device driver.
  164. Arguments:
  165. InterfaceType - Supplies the type of bus which the vector is for.
  166. BusNumber - Supplies the bus number for the device.
  167. BusInterruptLevel - Supplies the bus specific interrupt level.
  168. BusInterruptVector - Supplies the bus specific interrupt vector.
  169. Irql - Returns the system request priority.
  170. Affinity - Returns the affinity for the requested vector
  171. Return Value:
  172. Returns the system interrupt vector corresponding to the specified device.
  173. --*/
  174. {
  175. //
  176. // Just return the passed parameters.
  177. //
  178. *Irql = (KIRQL) BusInterruptLevel;
  179. *Affinity = 1;
  180. return( BusInterruptLevel << VECTOR_IRQL_SHIFT );
  181. }
  182. BOOLEAN
  183. HalBeginSystemInterrupt(
  184. IN KIRQL Irql,
  185. IN CCHAR Vector,
  186. OUT PKIRQL OldIrql
  187. )
  188. /*++
  189. Routine Description:
  190. This routine raises the IRQL to the level of the specified
  191. interrupt vector. It is called by the hardware interrupt
  192. handler before any other interrupt service routine code is
  193. executed. The CPU interrupt flag is set on exit.
  194. Arguments:
  195. Irql - Supplies the IRQL to raise to
  196. Vector - Supplies the vector of the interrupt to be
  197. dismissed
  198. OldIrql- Location to return OldIrql
  199. Return Value:
  200. TRUE - Interrupt successfully dismissed and Irql raised.
  201. This routine cannot fail.
  202. --*/
  203. {
  204. return (TRUE);
  205. }
  206. VOID
  207. HalEndSystemInterrupt (
  208. IN KIRQL NewIrql,
  209. IN ULONG Vector
  210. )
  211. /*++
  212. Routine Description:
  213. This routine is used to lower IRQL to the specified value.
  214. The IRQL and PIRQL will be updated accordingly.
  215. NOTE: This routine simulates software interrupt as long as
  216. any pending SW interrupt level is higher than the current
  217. IRQL, even when interrupts are disabled.
  218. Arguments:
  219. NewIrql - the new irql to be set.
  220. Vector - Vector number of the interrupt
  221. Return Value:
  222. None.
  223. --*/
  224. {
  225. return;
  226. }
  227. //
  228. // Almost all of the last 4MB of virtual memory address range are available
  229. // to the HAL to map physical memory. The kernel may use some of these
  230. // PTEs for special purposes.
  231. //
  232. //
  233. // The kernel now uses one PTE in this
  234. // area to map the area from which interrupt messages are to be retrieved.
  235. //
  236. #define HAL_VA_START 0xffd00000
  237. PVOID HalpHeapStart=(PVOID)(KADDRESS_BASE+HAL_VA_START);
  238. PVOID
  239. HalMapPhysicalMemory(
  240. IN PHYSICAL_ADDRESS PhysicalAddress,
  241. IN ULONG NumberPages
  242. )
  243. /*++
  244. Routine Description:
  245. This routine maps physical memory into the area of virtual memory
  246. reserved for the HAL. It does this by directly inserting the PTE
  247. into the Page Table which the OS Loader has provided.
  248. N.B. This routine does *NOT* update the MemoryDescriptorList. The
  249. caller is responsible for either removing the appropriate
  250. physical memory from the list, or creating a new descriptor to
  251. describe it.
  252. Arguments:
  253. PhysicalAddress - Supplies the physical address of the start of the
  254. area of physical memory to be mapped.
  255. NumberPages - Supplies the number of pages contained in the area of
  256. physical memory to be mapped.
  257. Return Value:
  258. PVOID - Virtual address at which the requested block of physical memory
  259. was mapped
  260. NULL - The requested block of physical memory could not be mapped.
  261. --*/
  262. {
  263. PHARDWARE_PTE PTE;
  264. ULONG PagesMapped;
  265. PVOID VirtualAddress;
  266. //
  267. // The OS Loader sets up hyperspace for us, so we know that the Page
  268. // Tables are magically mapped starting at V.A. 0xC0000000.
  269. //
  270. PagesMapped = 0;
  271. while (PagesMapped < NumberPages) {
  272. //
  273. // Look for enough consecutive free ptes to honor mapping
  274. //
  275. PagesMapped = 0;
  276. VirtualAddress = HalpHeapStart;
  277. while (PagesMapped < NumberPages) {
  278. PTE=MiGetPteAddress(VirtualAddress);
  279. if (*(PULONGLONG)PTE != 0) {
  280. //
  281. // Pte is not free, skip up to the next pte and start over
  282. //
  283. HalpHeapStart = (PVOID) ((ULONG_PTR)VirtualAddress + PAGE_SIZE);
  284. break;
  285. }
  286. VirtualAddress = (PVOID) ((ULONG_PTR)VirtualAddress + PAGE_SIZE);
  287. PagesMapped++;
  288. }
  289. }
  290. PagesMapped = 0;
  291. VirtualAddress = (PVOID) ((ULONG_PTR) HalpHeapStart | BYTE_OFFSET (PhysicalAddress.QuadPart));
  292. while (PagesMapped < NumberPages) {
  293. PTE=MiGetPteAddress(HalpHeapStart);
  294. PTE->PageFrameNumber = (PhysicalAddress.QuadPart >> PAGE_SHIFT);
  295. PTE->Valid = 1;
  296. PTE->Write = 1;
  297. // TBD PTE->MemAttribute = 0;
  298. PhysicalAddress.QuadPart = PhysicalAddress.QuadPart + PAGE_SIZE;
  299. HalpHeapStart = (PVOID)((ULONG_PTR)HalpHeapStart + PAGE_SIZE);
  300. ++PagesMapped;
  301. }
  302. return(VirtualAddress);
  303. }