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.

587 lines
14 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. ixslpsup.c
  5. Abstract:
  6. This file provides the code that saves and restores
  7. state for traditional motherboard devices when the
  8. system goes into a sleep state that removes power.
  9. This code is included in multiple HALs.
  10. Author:
  11. Jake Oshins (jakeo) May 6, 1997
  12. Revision History:
  13. --*/
  14. #include "halp.h"
  15. #include "ixsleep.h"
  16. #if (defined(APIC_HAL) || defined(ACPI_HAL))
  17. #include "apic.inc"
  18. #include "..\..\halmps\i386\pcmp_nt.inc"
  19. #if !defined(_AMD64_)
  20. VOID
  21. StartPx_RMStub(
  22. VOID
  23. );
  24. #endif
  25. #endif
  26. typedef struct _SAVE_CONTEXT_DPC_CONTEXT {
  27. PVOID SaveArea;
  28. volatile ULONG Complete;
  29. } SAVE_CONTEXT_DPC_CONTEXT, *PSAVE_CONTEXT_DPC_CONTEXT;
  30. VOID
  31. HalpSaveContextTargetProcessor (
  32. IN PKDPC Dpc,
  33. IN PVOID DeferredContext,
  34. IN PVOID SystemArgument1,
  35. IN PVOID SystemArgument2
  36. );
  37. #ifdef WANT_IRQ_ROUTING
  38. #include "ixpciir.h"
  39. #endif
  40. extern UCHAR HalpAsmDataMarker;
  41. extern PVOID HalpEisaControlBase;
  42. extern ULONG HalpIrqMiniportInitialized;
  43. PKPROCESSOR_STATE HalpHiberProcState;
  44. ULONG CurTiledCr3LowPart;
  45. PPHYSICAL_ADDRESS HalpTiledCr3Addresses;
  46. #ifdef ALLOC_PRAGMA
  47. #pragma alloc_text(PAGE, HaliLocateHiberRanges)
  48. #pragma alloc_text(PAGELK, HalpSavePicState)
  49. #pragma alloc_text(PAGELK, HalpSaveDmaControllerState)
  50. #pragma alloc_text(PAGELK, HalpSaveTimerState)
  51. #pragma alloc_text(PAGELK, HalpRestorePicState)
  52. #pragma alloc_text(PAGELK, HalpRestoreDmaControllerState)
  53. #pragma alloc_text(PAGELK, HalpRestoreTimerState)
  54. #pragma alloc_text(PAGELK, HalpBuildResumeStructures)
  55. #pragma alloc_text(PAGELK, HalpFreeResumeStructures)
  56. #pragma alloc_text(PAGELK, HalpSaveContextTargetProcessor)
  57. #endif
  58. #define EISA_CONTROL (PUCHAR)&((PEISA_CONTROL) HalpEisaControlBase)
  59. VOID
  60. HalpPowerStateCallback(
  61. IN PVOID CallbackContext,
  62. IN PVOID Argument1,
  63. IN PVOID Argument2
  64. )
  65. {
  66. ULONG action = PtrToUlong(Argument1);
  67. ULONG state = PtrToUlong(Argument2);
  68. if (action == PO_CB_SYSTEM_STATE_LOCK) {
  69. switch (state) {
  70. case 0:
  71. //
  72. // Lock down everything in the PAGELK code section. (We chose
  73. // HalpSaveDmaControllerState because it exists in every HAL.)
  74. //
  75. HalpSleepPageLock = MmLockPagableCodeSection((PVOID)HalpSaveDmaControllerState);
  76. #if (defined(APIC_HAL) || defined(ACPI_HAL)) && !defined(_AMD64_)
  77. HalpSleepPage16Lock = MmLockPagableCodeSection((PVOID) StartPx_RMStub );
  78. #endif
  79. #ifdef ACPI_HAL
  80. HalpMapNvsArea();
  81. #endif
  82. break;
  83. case 1: // unlock it all
  84. MmUnlockPagableImageSection(HalpSleepPageLock);
  85. #if (defined(APIC_HAL) || defined(ACPI_HAL)) && !defined(_AMD64_)
  86. MmUnlockPagableImageSection(HalpSleepPage16Lock);
  87. #endif
  88. #ifdef ACPI_HAL
  89. HalpFreeNvsBuffers();
  90. #endif
  91. }
  92. }
  93. return;
  94. }
  95. VOID
  96. HalpSavePicState(
  97. VOID
  98. )
  99. {
  100. HalpMotherboardState.PicState.MasterMask =
  101. READ_PORT_UCHAR(EISA_CONTROL->Interrupt1ControlPort1);
  102. HalpMotherboardState.PicState.SlaveMask =
  103. READ_PORT_UCHAR(EISA_CONTROL->Interrupt2ControlPort1);
  104. #if !defined(ACPI_HAL)
  105. #ifdef WANT_IRQ_ROUTING
  106. if(HalpIrqMiniportInitialized)
  107. {
  108. ULONG elcrMask = 0;
  109. PciirqmpGetTrigger(&elcrMask);
  110. HalpMotherboardState.PicState.MasterEdgeLevelControl = (UCHAR)((elcrMask >> 8) & 0xFF);
  111. HalpMotherboardState.PicState.SlaveEdgeLevelControl = (UCHAR)(elcrMask & 0xFF);
  112. }
  113. else
  114. {
  115. #endif
  116. if (HalpBusType == MACHINE_TYPE_EISA) {
  117. #endif
  118. HalpMotherboardState.PicState.MasterEdgeLevelControl =
  119. READ_PORT_UCHAR(EISA_CONTROL->Interrupt1EdgeLevel);
  120. HalpMotherboardState.PicState.SlaveEdgeLevelControl =
  121. READ_PORT_UCHAR(EISA_CONTROL->Interrupt2EdgeLevel);
  122. #if !defined(ACPI_HAL)
  123. }
  124. #ifdef WANT_IRQ_ROUTING
  125. }
  126. #endif
  127. #endif
  128. }
  129. VOID
  130. HalpRestorePicState(
  131. VOID
  132. )
  133. {
  134. ULONG flags;
  135. flags = HalpDisableInterrupts();
  136. HalpInitializePICs(FALSE);
  137. WRITE_PORT_UCHAR(EISA_CONTROL->Interrupt1ControlPort1,
  138. HalpMotherboardState.PicState.MasterMask);
  139. WRITE_PORT_UCHAR(EISA_CONTROL->Interrupt2ControlPort1,
  140. HalpMotherboardState.PicState.SlaveMask);
  141. //
  142. // For halx86, the PCI interrupt vector programming
  143. // is static, so this code can just restore everything.
  144. //
  145. HalpRestorePicEdgeLevelRegister();
  146. HalpRestoreInterrupts(flags);
  147. }
  148. VOID
  149. HalpRestorePicEdgeLevelRegister(
  150. VOID
  151. )
  152. {
  153. #if !defined(ACPI_HAL)
  154. #ifdef WANT_IRQ_ROUTING
  155. if(HalpIrqMiniportInitialized)
  156. {
  157. PLINK_NODE linkNode;
  158. PLINK_STATE temp;
  159. ULONG elcrMask = (HalpMotherboardState.PicState.MasterEdgeLevelControl << 8) |
  160. HalpMotherboardState.PicState.SlaveEdgeLevelControl;
  161. PciirqmpSetTrigger(elcrMask);
  162. //
  163. // Reprogram all links.
  164. //
  165. for ( linkNode = HalpPciIrqRoutingInfo.LinkNodeHead;
  166. linkNode;
  167. linkNode = linkNode->Next)
  168. {
  169. //
  170. // Swap the possible with the allocation.
  171. //
  172. temp = linkNode->Allocation;
  173. linkNode->Allocation = linkNode->PossibleAllocation;
  174. linkNode->PossibleAllocation = temp;
  175. HalpCommitLink(linkNode);
  176. }
  177. }
  178. else
  179. {
  180. #endif
  181. if (HalpBusType == MACHINE_TYPE_EISA) {
  182. #endif
  183. WRITE_PORT_UCHAR(EISA_CONTROL->Interrupt1EdgeLevel,
  184. HalpMotherboardState.PicState.MasterEdgeLevelControl);
  185. WRITE_PORT_UCHAR(EISA_CONTROL->Interrupt2EdgeLevel,
  186. HalpMotherboardState.PicState.SlaveEdgeLevelControl);
  187. #if !defined(ACPI_HAL)
  188. }
  189. #ifdef WANT_IRQ_ROUTING
  190. }
  191. #endif
  192. #endif
  193. }
  194. VOID
  195. HalpSaveDmaControllerState(
  196. VOID
  197. )
  198. {
  199. }
  200. VOID
  201. HalpRestoreDmaControllerState(
  202. VOID
  203. )
  204. /*++
  205. Routine Description:
  206. This function puts the DMA controller back into the
  207. same state it was in before the machine went to sleep.
  208. Arguments:
  209. None.
  210. Notes:
  211. Normally, the DMA controller structures would be guarded
  212. by spinlocks. But this function is called with interrupts
  213. turned off and all but one processor spinning.
  214. --*/
  215. {
  216. UCHAR i;
  217. WRITE_PORT_UCHAR(EISA_CONTROL->Dma1BasePort.AllMask,0xF);
  218. WRITE_PORT_UCHAR(EISA_CONTROL->Dma2BasePort.AllMask,0xE);
  219. HalpIoDelay();
  220. //
  221. //Reset the DMA command registers
  222. //
  223. #if defined(NEC_98)
  224. WRITE_PORT_UCHAR(EISA_CONTROL->Dma1BasePort.DmaStatus,0x40);
  225. WRITE_PORT_UCHAR(EISA_CONTROL->Dma2BasePort.DmaStatus,0x40);
  226. #else
  227. WRITE_PORT_UCHAR(EISA_CONTROL->Dma1BasePort.DmaStatus,0);
  228. WRITE_PORT_UCHAR(EISA_CONTROL->Dma2BasePort.DmaStatus,0);
  229. #endif
  230. HalpIoDelay();
  231. for (i = 0; i < (EISA_DMA_CHANNELS / 2); i++) {
  232. //
  233. // Check to see if the array contains a value for this channel.
  234. //
  235. if (HalpDmaChannelState[i].ChannelProgrammed) {
  236. WRITE_PORT_UCHAR(EISA_CONTROL->Dma1BasePort.Mode,
  237. HalpDmaChannelState[i].ChannelMode);
  238. if (HalpEisaDma) {
  239. WRITE_PORT_UCHAR(EISA_CONTROL->Dma1ExtendedModePort,
  240. HalpDmaChannelState[i].ChannelExtendedMode);
  241. }
  242. WRITE_PORT_UCHAR(EISA_CONTROL->Dma1BasePort.SingleMask,
  243. HalpDmaChannelState[i].ChannelMask);
  244. HalpIoDelay();
  245. }
  246. }
  247. for (i = (EISA_DMA_CHANNELS / 2); i < EISA_DMA_CHANNELS; i++) {
  248. //
  249. // Check to see if the array contains a value for this channel.
  250. //
  251. if (HalpDmaChannelState[i].ChannelProgrammed) {
  252. WRITE_PORT_UCHAR(EISA_CONTROL->Dma2BasePort.Mode,
  253. HalpDmaChannelState[i].ChannelMode);
  254. if (HalpEisaDma) {
  255. WRITE_PORT_UCHAR(EISA_CONTROL->Dma2ExtendedModePort,
  256. HalpDmaChannelState[i].ChannelExtendedMode);
  257. }
  258. WRITE_PORT_UCHAR(EISA_CONTROL->Dma2BasePort.SingleMask,
  259. HalpDmaChannelState[i].ChannelMask);
  260. HalpIoDelay();
  261. }
  262. }
  263. }
  264. VOID
  265. HalpSaveTimerState(
  266. VOID
  267. )
  268. {
  269. }
  270. VOID
  271. HalpRestoreTimerState(
  272. VOID
  273. )
  274. {
  275. HalpInitializeClock();
  276. }
  277. VOID
  278. HaliLocateHiberRanges (
  279. IN PVOID MemoryMap
  280. )
  281. {
  282. //
  283. // Mark the hal's data section as needed to be cloned
  284. //
  285. PoSetHiberRange (
  286. MemoryMap,
  287. PO_MEM_CLONE,
  288. (PVOID) &HalpFeatureBits,
  289. 0,
  290. 'dlah'
  291. );
  292. #if defined(_HALPAE_)
  293. //
  294. // Mark DMA buffers as not needing to be saved.
  295. //
  296. if (MasterAdapter24.MapBufferSize != 0) {
  297. PoSetHiberRange( MemoryMap,
  298. PO_MEM_DISCARD | PO_MEM_PAGE_ADDRESS,
  299. (PVOID)(ULONG_PTR)(MasterAdapter24.MapBufferPhysicalAddress.LowPart >>
  300. PAGE_SHIFT),
  301. MasterAdapter24.MapBufferSize >> PAGE_SHIFT,
  302. 'mlah' );
  303. }
  304. if (MasterAdapter32.MapBufferSize != 0) {
  305. PoSetHiberRange( MemoryMap,
  306. PO_MEM_DISCARD | PO_MEM_PAGE_ADDRESS,
  307. (PVOID)(ULONG_PTR)(MasterAdapter32.MapBufferPhysicalAddress.LowPart >>
  308. PAGE_SHIFT),
  309. MasterAdapter32.MapBufferSize >> PAGE_SHIFT,
  310. 'mlah' );
  311. }
  312. #else
  313. //
  314. // Mark DMA buffer has not needing saved
  315. //
  316. if (HalpMapBufferSize) {
  317. PoSetHiberRange (
  318. MemoryMap,
  319. PO_MEM_DISCARD | PO_MEM_PAGE_ADDRESS,
  320. (PVOID) (HalpMapBufferPhysicalAddress.LowPart >> PAGE_SHIFT),
  321. HalpMapBufferSize >> PAGE_SHIFT,
  322. 'mlah'
  323. );
  324. }
  325. #endif
  326. }
  327. NTSTATUS
  328. HalpBuildResumeStructures(
  329. VOID
  330. )
  331. {
  332. KAFFINITY CurrentAffinity, ActiveProcessors;
  333. ULONG ProcNum, Processor, NumberProcessors = 1;
  334. KDPC Dpc;
  335. SAVE_CONTEXT_DPC_CONTEXT Context;
  336. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  337. #if defined(APIC_HAL)
  338. //
  339. // If KeActiveProcessors() were callable at
  340. // DISPATCH_LEVEL, I would use that.
  341. //
  342. NumberProcessors = HalpMpInfoTable.NtProcessors;
  343. #endif
  344. ActiveProcessors = (1 << NumberProcessors) - 1;
  345. #if defined(APIC_HAL) || defined(ACPI_HAL)
  346. //
  347. // Allocate space to save processor context for other processors
  348. //
  349. HalpTiledCr3Addresses = NULL;
  350. HalpHiberProcState =
  351. ExAllocatePoolWithTag(NonPagedPool,
  352. (NumberProcessors * sizeof(KPROCESSOR_STATE)),
  353. HAL_POOL_TAG);
  354. if (!HalpHiberProcState) {
  355. goto BuildResumeStructuresError;
  356. }
  357. RtlZeroMemory(HalpHiberProcState,
  358. NumberProcessors * sizeof(KPROCESSOR_STATE));
  359. //
  360. // Allocate space for tiled CR3 for all processors
  361. //
  362. HalpTiledCr3Addresses =
  363. ExAllocatePoolWithTag(NonPagedPool,
  364. (NumberProcessors * sizeof(PHYSICAL_ADDRESS)),
  365. HAL_POOL_TAG);
  366. if (!HalpTiledCr3Addresses) {
  367. goto BuildResumeStructuresError;
  368. }
  369. RtlZeroMemory(HalpTiledCr3Addresses,
  370. (NumberProcessors * sizeof(PHYSICAL_ADDRESS)));
  371. //
  372. // Get IDT and GDT for all processors except BSP,
  373. // map and save tiled CR3
  374. //
  375. KeInitializeDpc (&Dpc, HalpSaveContextTargetProcessor, &Context);
  376. KeSetImportanceDpc (&Dpc, HighImportance);
  377. ProcNum = 0;
  378. CurrentAffinity = 1;
  379. Processor = 0;
  380. while (ActiveProcessors) {
  381. if (ActiveProcessors & CurrentAffinity) {
  382. ActiveProcessors &= ~CurrentAffinity;
  383. RtlZeroMemory(&Context, sizeof(Context));
  384. Context.SaveArea = &(HalpHiberProcState[ProcNum]);
  385. if (Processor == CurrentPrcb(KeGetPcr())->Number) {
  386. //
  387. // We're running on this processor. Just call
  388. // the DPC routine from here.
  389. HalpSaveContextTargetProcessor(&Dpc, &Context, NULL, NULL);
  390. } else {
  391. //
  392. // Issue DPC to target processor
  393. //
  394. KeSetTargetProcessorDpc (&Dpc, (CCHAR) Processor);
  395. KeInsertQueueDpc (&Dpc, NULL, NULL);
  396. //
  397. // Wait for DPC to be complete.
  398. //
  399. while (Context.Complete == FALSE);
  400. }
  401. ProcNum++;
  402. }
  403. Processor++;
  404. CurrentAffinity <<= 1;
  405. }
  406. for (ProcNum = 0; ProcNum < NumberProcessors; ProcNum++) {
  407. HalpTiledCr3Addresses[ProcNum].LowPart =
  408. HalpBuildTiledCR3Ex(&(HalpHiberProcState[ProcNum]),ProcNum);
  409. }
  410. #endif
  411. return STATUS_SUCCESS;
  412. #if defined(APIC_HAL) || defined(ACPI_HAL)
  413. BuildResumeStructuresError:
  414. if (HalpHiberProcState) ExFreePool(HalpHiberProcState);
  415. if (HalpTiledCr3Addresses) ExFreePool(HalpTiledCr3Addresses);
  416. return STATUS_UNSUCCESSFUL;
  417. #endif
  418. }
  419. NTSTATUS
  420. HalpFreeResumeStructures(
  421. VOID
  422. )
  423. {
  424. ULONG ProcNum, NumberProcessors = 1;
  425. #if defined(APIC_HAL)
  426. NumberProcessors = HalpMpInfoTable.NtProcessors;
  427. #endif
  428. #if defined(APIC_HAL) || defined(ACPI_HAL)
  429. if (HalpHiberProcState) {
  430. ExFreePool(HalpHiberProcState);
  431. HalpHiberProcState = NULL;
  432. }
  433. if (HalpTiledCr3Addresses) {
  434. ExFreePool(HalpTiledCr3Addresses);
  435. HalpTiledCr3Addresses = NULL;
  436. }
  437. for (ProcNum = 0; ProcNum < NumberProcessors; ProcNum++) {
  438. HalpFreeTiledCR3Ex(ProcNum);
  439. }
  440. #endif
  441. return STATUS_SUCCESS;
  442. }
  443. VOID
  444. HalpSaveContextTargetProcessor (
  445. IN PKDPC Dpc,
  446. IN PVOID DeferredContext,
  447. IN PVOID SystemArgument1,
  448. IN PVOID SystemArgument2
  449. )
  450. {
  451. PSAVE_CONTEXT_DPC_CONTEXT Context = (PSAVE_CONTEXT_DPC_CONTEXT)DeferredContext;
  452. KeSaveStateForHibernate(Context->SaveArea);
  453. InterlockedIncrement(&Context->Complete);
  454. }