]>
Commit | Line | Data |
---|---|---|
3cbfba02 DW |
1 | /*++\r |
2 | \r | |
3 | Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved\r | |
4 | \r\r | |
5 | This program and the accompanying materials are licensed and made available under\r\r | |
6 | the terms and conditions of the BSD License that accompanies this distribution. \r\r | |
7 | The full text of the license may be found at \r\r | |
8 | http://opensource.org/licenses/bsd-license.php. \r\r | |
9 | \r\r | |
10 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r\r | |
11 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r\r | |
12 | \r\r | |
13 | \r | |
14 | \r | |
15 | Module Name:\r | |
16 | \r | |
17 | SmmIo.c\r | |
18 | \r | |
19 | Abstract:\r | |
20 | \r | |
21 | SMM I/O access utility implementation file, for Ia32\r | |
22 | \r | |
23 | --*/\r | |
24 | \r | |
25 | //\r | |
26 | // Include files\r | |
27 | //\r | |
28 | #include "Library/StallSmmLib.h"\r | |
29 | #include "Pi/PiSmmCis.h"\r | |
30 | #include "PiDxe.h"\r | |
31 | #include <Library/IoLib.h>\r | |
32 | #include <Library/PcdLib.h>\r | |
33 | #include "PchAccess.h"\r | |
34 | \r | |
35 | /**\r | |
36 | Delay for at least the request number of microseconds.\r | |
37 | Timer used is ACPI time counter, which has 1us granularity.\r | |
38 | \r | |
39 | @param Microseconds Number of microseconds to delay.\r | |
40 | \r | |
41 | @retval None\r | |
42 | \r | |
43 | **/\r | |
44 | VOID\r | |
45 | SmmStall (\r | |
46 | IN UINTN Microseconds\r | |
47 | )\r | |
48 | {\r | |
49 | UINTN Ticks;\r | |
50 | UINTN Counts;\r | |
51 | UINTN CurrentTick;\r | |
52 | UINTN OriginalTick;\r | |
53 | UINTN RemainingTick;\r | |
54 | UINT16 AcpiBaseAddr;\r | |
55 | \r | |
56 | if (Microseconds == 0) {\r | |
57 | return;\r | |
58 | }\r | |
59 | \r | |
60 | AcpiBaseAddr = PchLpcPciCfg16 (R_PCH_LPC_ACPI_BASE) & B_PCH_LPC_ACPI_BASE_BAR;\r | |
61 | \r | |
62 | OriginalTick = IoRead32 (AcpiBaseAddr + R_PCH_ACPI_PM1_TMR);\r | |
63 | CurrentTick = OriginalTick;\r | |
64 | \r | |
65 | //\r | |
66 | // The timer frequency is 3.579545 MHz, so 1 ms corresponds 3.58 clocks\r | |
67 | //\r | |
68 | Ticks = Microseconds * 358 / 100 + OriginalTick + 1;\r | |
69 | \r | |
70 | //\r | |
71 | // The loops needed by timer overflow\r | |
72 | //\r | |
73 | Counts = Ticks / V_PCH_ACPI_PM1_TMR_MAX_VAL;\r | |
74 | \r | |
75 | //\r | |
76 | // Remaining clocks within one loop\r | |
77 | //\r | |
78 | RemainingTick = Ticks % V_PCH_ACPI_PM1_TMR_MAX_VAL;\r | |
79 | \r | |
80 | //\r | |
81 | // not intend to use TMROF_STS bit of register PM1_STS, because this adds extra\r | |
82 | // one I/O operation, and maybe generate SMI\r | |
83 | //\r | |
84 | while ((Counts != 0) || (RemainingTick > CurrentTick)) {\r | |
85 | CurrentTick = IoRead32 (AcpiBaseAddr + R_PCH_ACPI_PM1_TMR);\r | |
86 | //\r | |
87 | // Check if timer overflow\r | |
88 | //\r | |
89 | if (CurrentTick < OriginalTick) {\r | |
90 | Counts--;\r | |
91 | }\r | |
92 | OriginalTick = CurrentTick;\r | |
93 | }\r | |
94 | }\r |