]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Foundation/Library/RuntimeDxe/EfiRuntimeLib/Ia32/PlatformIoLib.c
Update the copyright notice format
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / RuntimeDxe / EfiRuntimeLib / Ia32 / PlatformIoLib.c
CommitLineData
3eb9473e 1/*++\r
2\r
4ea9375a
HT
3Copyright (c) 2004 - 2006, Intel Corporation. All rights reserved.<BR>\r
4This program and the accompanying materials \r
3eb9473e 5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 PlatformIoLib.c\r
15\r
16Abstract:\r
17\r
18--*/\r
19\r
20#include "Tiano.h"\r
21#include "EfiRuntimeLib.h"\r
22#include EFI_PROTOCOL_DEFINITION (CpuIo)\r
23\r
24#define PCI_CONFIG_INDEX_PORT 0xcf8\r
25#define PCI_CONFIG_DATA_PORT 0xcfc\r
26#define REFRESH_CYCLE_TOGGLE_BIT 0x10\r
27\r
28UINT32\r
29GetPciAddress (\r
30 UINT8 Segment,\r
31 UINT8 Bus,\r
32 UINT8 DevFunc,\r
33 UINT8 Register\r
34 )\r
35/*++\r
36\r
37Routine Description:\r
38 Constructs PCI Address 32 bits\r
39 \r
40Arguments:\r
41 Segment - PCI Segment ACPI _SEG\r
42 Bus - PCI Bus\r
43 DevFunc - PCI Device(7:3) and Func(2:0)\r
44 Register - PCI config space register\r
45\r
46Returns:\r
47 PciAddress to be written to Config Port\r
48\r
49--*/\r
50{\r
51 UINT32 Data;\r
52\r
53 Data = (((UINT32) Segment) << 24);\r
54 Data |= (((UINT32) Bus) << 16);\r
55 Data |= (((UINT32) DevFunc) << 8);\r
56 Data |= (UINT32) Register;\r
57\r
58 return Data;\r
59\r
60}\r
61\r
62UINT8\r
63PciRead8 (\r
64 UINT8 Segment,\r
65 UINT8 Bus,\r
66 UINT8 DevFunc,\r
67 UINT8 Register\r
68 )\r
69/*++\r
70\r
71Routine Description:\r
72 Perform an one byte PCI config cycle read\r
73 \r
74Arguments:\r
75 Segment - PCI Segment ACPI _SEG\r
76 Bus - PCI Bus\r
77 DevFunc - PCI Device(7:3) and Func(2:0)\r
78 Register - PCI config space register\r
79\r
80Returns:\r
81 Data read from PCI config space\r
82\r
83--*/\r
84{\r
85 EFI_STATUS Status;\r
86 UINT32 PciAddress;\r
87 UINT32 PciAddress1;\r
88 UINT8 Data;\r
89\r
90 PciAddress = GetPciAddress (Segment, Bus, DevFunc, Register);\r
91 //\r
92 // Set bit 31 for PCI config access\r
93 //\r
94 PciAddress1 = PciAddress;\r
95 PciAddress = ((PciAddress & 0xFFFFFFFC) | (0x80000000));\r
96\r
97 Status = EfiIoWrite (EfiCpuIoWidthUint32, PCI_CONFIG_INDEX_PORT, 1, &PciAddress);\r
98\r
99 if (EFI_ERROR (Status)) {\r
100 return 0;\r
101 }\r
102\r
103 EfiIoRead (EfiCpuIoWidthUint8, (PCI_CONFIG_DATA_PORT + (PciAddress1 & 0x3)), 1, &Data);\r
104\r
105 return Data;\r
106}\r
107\r
108UINT16\r
109PciRead16 (\r
110 UINT8 Segment,\r
111 UINT8 Bus,\r
112 UINT8 DevFunc,\r
113 UINT8 Register\r
114 )\r
115/*++\r
116\r
117Routine Description:\r
118 Perform an two byte PCI config cycle read\r
119 \r
120Arguments:\r
121 Segment - PCI Segment ACPI _SEG\r
122 Bus - PCI Bus\r
123 DevFunc - PCI Device(7:3) and Func(2:0)\r
124 Register - PCI config space register\r
125\r
126Returns:\r
127 Data read from PCI config space\r
128\r
129--*/\r
130{\r
131 EFI_STATUS Status;\r
132 UINT32 PciAddress;\r
133 UINT32 PciAddress1;\r
134 UINT16 Data;\r
135\r
136 PciAddress = GetPciAddress (Segment, Bus, DevFunc, Register);\r
137 //\r
138 // Set bit 31 for PCI config access\r
139 //\r
140 PciAddress1 = PciAddress;\r
141 PciAddress = ((PciAddress & 0xFFFFFFFC) | (0x80000000));\r
142\r
143 Status = EfiIoWrite (EfiCpuIoWidthUint32, PCI_CONFIG_INDEX_PORT, 1, &PciAddress);\r
144\r
145 if (EFI_ERROR (Status)) {\r
146 return 0;\r
147 }\r
148\r
149 EfiIoRead (EfiCpuIoWidthUint16, (PCI_CONFIG_DATA_PORT + (PciAddress1 & 0x3)), 1, &Data);\r
150\r
151 return Data;\r
152}\r
153\r
154UINT32\r
155PciRead32 (\r
156 UINT8 Segment,\r
157 UINT8 Bus,\r
158 UINT8 DevFunc,\r
159 UINT8 Register\r
160 )\r
161/*++\r
162\r
163Routine Description:\r
164 Perform an four byte PCI config cycle read\r
165 \r
166Arguments:\r
167 Segment - PCI Segment ACPI _SEG\r
168 Bus - PCI Bus\r
169 DevFunc - PCI Device(7:3) and Func(2:0)\r
170 Register - PCI config space register\r
171\r
172Returns:\r
173 Data read from PCI config space\r
174\r
175--*/\r
176{\r
177 EFI_STATUS Status;\r
178 UINT32 PciAddress;\r
179 UINT32 PciAddress1;\r
180 UINT32 Data;\r
181\r
182 PciAddress = GetPciAddress (Segment, Bus, DevFunc, Register);\r
183 //\r
184 // Set bit 31 for PCI config access\r
185 //\r
186 PciAddress1 = PciAddress;\r
187 PciAddress = ((PciAddress & 0xFFFFFFFC) | (0x80000000));\r
188\r
189 Status = EfiIoWrite (EfiCpuIoWidthUint32, PCI_CONFIG_INDEX_PORT, 1, &PciAddress);\r
190\r
191 if (EFI_ERROR (Status)) {\r
192 return 0;\r
193 }\r
194\r
195 EfiIoRead (EfiCpuIoWidthUint32, (PCI_CONFIG_DATA_PORT + (PciAddress1 & 0x3)), 1, &Data);\r
196\r
197 return Data;\r
198}\r
199\r
200VOID\r
201PciWrite8 (\r
202 UINT8 Segment,\r
203 UINT8 Bus,\r
204 UINT8 DevFunc,\r
205 UINT8 Register,\r
206 UINT8 Data\r
207 )\r
208/*++\r
209\r
210Routine Description:\r
211 Perform an one byte PCI config cycle write\r
212 \r
213Arguments:\r
214 Segment - PCI Segment ACPI _SEG\r
215 Bus - PCI Bus\r
216 DevFunc - PCI Device(7:3) and Func(2:0)\r
217 Register - PCI config space register\r
218 Data - Data to write\r
219\r
220Returns:\r
221 NONE\r
222\r
223--*/\r
224{\r
225 EFI_STATUS Status;\r
226 UINT32 PciAddress;\r
227 UINT32 PciAddress1;\r
228\r
229 PciAddress = GetPciAddress (Segment, Bus, DevFunc, Register);\r
230 //\r
231 // Set bit 31 for PCI config access\r
232 //\r
233 PciAddress1 = PciAddress;\r
234 PciAddress = ((PciAddress & 0xFFFFFFFC) | (0x80000000));\r
235\r
236 Status = EfiIoWrite (EfiCpuIoWidthUint32, PCI_CONFIG_INDEX_PORT, 1, &PciAddress);\r
237\r
238 if (EFI_ERROR (Status)) {\r
239 return ;\r
240 }\r
241\r
242 EfiIoWrite (EfiCpuIoWidthUint8, (PCI_CONFIG_DATA_PORT + (PciAddress1 & 0x3)), 1, &Data);\r
243}\r
244\r
245VOID\r
246PciWrite16 (\r
247 UINT8 Segment,\r
248 UINT8 Bus,\r
249 UINT8 DevFunc,\r
250 UINT8 Register,\r
251 UINT16 Data\r
252 )\r
253/*++\r
254\r
255Routine Description:\r
256 Perform an two byte PCI config cycle write\r
257 \r
258Arguments:\r
259 Segment - PCI Segment ACPI _SEG\r
260 Bus - PCI Bus\r
261 DevFunc - PCI Device(7:3) and Func(2:0)\r
262 Register - PCI config space register\r
263 Data - Data to write\r
264\r
265Returns:\r
266 NONE\r
267\r
268--*/\r
269{\r
270 EFI_STATUS Status;\r
271 UINT32 PciAddress;\r
272 UINT32 PciAddress1;\r
273\r
274 PciAddress = GetPciAddress (Segment, Bus, DevFunc, Register);\r
275 //\r
276 // Set bit 31 for PCI config access\r
277 //\r
278 PciAddress1 = PciAddress;\r
279 PciAddress = ((PciAddress & 0xFFFFFFFC) | (0x80000000));\r
280\r
281 Status = EfiIoWrite (EfiCpuIoWidthUint32, PCI_CONFIG_INDEX_PORT, 1, &PciAddress);\r
282\r
283 if (EFI_ERROR (Status)) {\r
284 return ;\r
285 }\r
286\r
287 EfiIoWrite (EfiCpuIoWidthUint16, (PCI_CONFIG_DATA_PORT + (PciAddress1 & 0x3)), 1, &Data);\r
288}\r
289\r
290VOID\r
291PciWrite32 (\r
292 UINT8 Segment,\r
293 UINT8 Bus,\r
294 UINT8 DevFunc,\r
295 UINT8 Register,\r
296 UINT32 Data\r
297 )\r
298/*++\r
299\r
300Routine Description:\r
301 Perform an four byte PCI config cycle write\r
302 \r
303Arguments:\r
304 Segment - PCI Segment ACPI _SEG\r
305 Bus - PCI Bus\r
306 DevFunc - PCI Device(7:3) and Func(2:0)\r
307 Register - PCI config space register\r
308 Data - Data to write\r
309\r
310Returns:\r
311 NONE\r
312\r
313--*/\r
314{\r
315 EFI_STATUS Status;\r
316 UINT32 PciAddress;\r
317 UINT32 PciAddress1;\r
318\r
319 PciAddress = GetPciAddress (Segment, Bus, DevFunc, Register);\r
320 //\r
321 // Set bit 31 for PCI config access\r
322 //\r
323 PciAddress1 = PciAddress;\r
324 PciAddress = ((PciAddress & 0xFFFFFFFC) | (0x80000000));\r
325\r
326 Status = EfiIoWrite (EfiCpuIoWidthUint32, PCI_CONFIG_INDEX_PORT, 1, &PciAddress);\r
327\r
328 if (EFI_ERROR (Status)) {\r
329 return ;\r
330 }\r
331\r
332 EfiIoWrite (EfiCpuIoWidthUint32, (PCI_CONFIG_DATA_PORT + (PciAddress1 & 0x3)), 1, &Data);\r
333}\r
334//\r
335// Delay Primative\r
336//\r
337VOID\r
338EfiStall (\r
339 IN UINTN Microseconds\r
340 )\r
341/*++\r
342\r
343Routine Description:\r
344 Delay for at least the request number of microseconds\r
345 \r
346Arguments:\r
347 Microseconds - Number of microseconds to delay.\r
348\r
349Returns:\r
350 NONE\r
351\r
352--*/\r
353{\r
354 UINT8 Data;\r
355 UINT8 InitialState;\r
356 UINTN CycleIterations;\r
357\r
358 CycleIterations = 0;\r
359 Data = 0;\r
360 InitialState = 0;\r
361\r
362 if (EfiAtRuntime ()) {\r
363 //\r
364 // The time-source is 30 us granular, so calibrate the timing loop\r
365 // based on this baseline\r
366 // Error is possible 30us.\r
367 //\r
368 CycleIterations = (Microseconds - 1) / 30 + 1;\r
369\r
370 //\r
371 // Use the DMA Refresh timer in port 0x61. Cheap but effective.\r
372 // The only issue is that the granularity is 30us, and we want to\r
373 // guarantee "at least" one full transition to avoid races.\r
374 //\r
375 //\r
376 // _____________/----------\__________/--------\r
377 //\r
378 // |<--15us-->|<--15us-->|\r
379 //\r
380 // --------------------------------------------------> Time (us)\r
381 //\r
382 while (CycleIterations--) {\r
383 EfiIoRead (EfiCpuIoWidthUint8, 0x61, 1, &Data);\r
384 Data &= REFRESH_CYCLE_TOGGLE_BIT;\r
385 InitialState = Data;\r
386\r
387 //\r
388 // Capture first transition (strictly less than one period)\r
389 //\r
390 while (InitialState == Data) {\r
391 EfiIoRead (EfiCpuIoWidthUint8, 0x61, 1, &Data);\r
392 Data &= REFRESH_CYCLE_TOGGLE_BIT;\r
393 }\r
394\r
395 InitialState = Data;\r
396 //\r
397 // Capture next transition (guarantee at least one full pulse)\r
398 //\r
399 while (InitialState == Data) {\r
400 EfiIoRead (EfiCpuIoWidthUint8, 0x61, 1, &Data);\r
401 Data &= REFRESH_CYCLE_TOGGLE_BIT;\r
402 }\r
403 }\r
404 } else {\r
405 gBS->Stall (Microseconds);\r
406 }\r
407}\r