]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
MdeModulePkg/XhciDxe: enable 64-bit PCI DMA
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciHostBridgeDxe / PciRootBridgeIo.c
CommitLineData
4a50cf4e
RN
1/** @file\r
2\r
3 PCI Root Bridge Io Protocol code.\r
4\r
5Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>\r
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "PciHostBridge.h"\r
17#include "PciRootBridge.h"\r
18#include "PciHostResource.h"\r
19\r
ccf66016 20#define NO_MAPPING (VOID *) (UINTN) -1\r
4a50cf4e
RN
21\r
22//\r
23// Lookup table for increment values based on transfer widths\r
24//\r
25UINT8 mInStride[] = {\r
26 1, // EfiPciWidthUint8\r
27 2, // EfiPciWidthUint16\r
28 4, // EfiPciWidthUint32\r
29 8, // EfiPciWidthUint64\r
30 0, // EfiPciWidthFifoUint8\r
31 0, // EfiPciWidthFifoUint16\r
32 0, // EfiPciWidthFifoUint32\r
33 0, // EfiPciWidthFifoUint64\r
34 1, // EfiPciWidthFillUint8\r
35 2, // EfiPciWidthFillUint16\r
36 4, // EfiPciWidthFillUint32\r
37 8 // EfiPciWidthFillUint64\r
38};\r
39\r
40//\r
41// Lookup table for increment values based on transfer widths\r
42//\r
43UINT8 mOutStride[] = {\r
44 1, // EfiPciWidthUint8\r
45 2, // EfiPciWidthUint16\r
46 4, // EfiPciWidthUint32\r
47 8, // EfiPciWidthUint64\r
48 1, // EfiPciWidthFifoUint8\r
49 2, // EfiPciWidthFifoUint16\r
50 4, // EfiPciWidthFifoUint32\r
51 8, // EfiPciWidthFifoUint64\r
52 0, // EfiPciWidthFillUint8\r
53 0, // EfiPciWidthFillUint16\r
54 0, // EfiPciWidthFillUint32\r
55 0 // EfiPciWidthFillUint64\r
56};\r
57\r
58/**\r
59 Construct the Pci Root Bridge instance.\r
60\r
61 @param Bridge The root bridge instance.\r
4a50cf4e
RN
62\r
63 @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created\r
64 or NULL if creation fails.\r
65**/\r
66PCI_ROOT_BRIDGE_INSTANCE *\r
67CreateRootBridge (\r
401f8cd1 68 IN PCI_ROOT_BRIDGE *Bridge\r
4a50cf4e
RN
69 )\r
70{\r
71 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
72 PCI_RESOURCE_TYPE Index;\r
73 CHAR16 *DevicePathStr;\r
401f8cd1 74 PCI_ROOT_BRIDGE_APERTURE *Aperture;\r
4a50cf4e
RN
75\r
76 DevicePathStr = NULL;\r
77\r
78 DEBUG ((EFI_D_INFO, "RootBridge: "));\r
79 DEBUG ((EFI_D_INFO, "%s\n", DevicePathStr = ConvertDevicePathToText (Bridge->DevicePath, FALSE, FALSE)));\r
3da82965
LE
80 DEBUG ((EFI_D_INFO, " Support/Attr: %lx / %lx\n", Bridge->Supports, Bridge->Attributes));\r
81 DEBUG ((EFI_D_INFO, " DmaAbove4G: %s\n", Bridge->DmaAbove4G ? L"Yes" : L"No"));\r
014b4720 82 DEBUG ((EFI_D_INFO, "NoExtConfSpace: %s\n", Bridge->NoExtendedConfigSpace ? L"Yes" : L"No"));\r
3da82965 83 DEBUG ((EFI_D_INFO, " AllocAttr: %lx (%s%s)\n", Bridge->AllocationAttributes,\r
4a50cf4e
RN
84 (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0 ? L"CombineMemPMem " : L"",\r
85 (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0 ? L"Mem64Decode" : L""\r
86 ));\r
3da82965
LE
87 DEBUG ((EFI_D_INFO, " Bus: %lx - %lx\n", Bridge->Bus.Base, Bridge->Bus.Limit));\r
88 DEBUG ((EFI_D_INFO, " Io: %lx - %lx\n", Bridge->Io.Base, Bridge->Io.Limit));\r
89 DEBUG ((EFI_D_INFO, " Mem: %lx - %lx\n", Bridge->Mem.Base, Bridge->Mem.Limit));\r
90 DEBUG ((EFI_D_INFO, " MemAbove4G: %lx - %lx\n", Bridge->MemAbove4G.Base, Bridge->MemAbove4G.Limit));\r
91 DEBUG ((EFI_D_INFO, " PMem: %lx - %lx\n", Bridge->PMem.Base, Bridge->PMem.Limit));\r
92 DEBUG ((EFI_D_INFO, " PMemAbove4G: %lx - %lx\n", Bridge->PMemAbove4G.Base, Bridge->PMemAbove4G.Limit));\r
4a50cf4e
RN
93\r
94 //\r
95 // Make sure Mem and MemAbove4G apertures are valid\r
96 //\r
f9607bef 97 if (Bridge->Mem.Base <= Bridge->Mem.Limit) {\r
4a50cf4e
RN
98 ASSERT (Bridge->Mem.Limit < SIZE_4GB);\r
99 if (Bridge->Mem.Limit >= SIZE_4GB) {\r
100 return NULL;\r
101 }\r
102 }\r
f9607bef 103 if (Bridge->MemAbove4G.Base <= Bridge->MemAbove4G.Limit) {\r
4a50cf4e
RN
104 ASSERT (Bridge->MemAbove4G.Base >= SIZE_4GB);\r
105 if (Bridge->MemAbove4G.Base < SIZE_4GB) {\r
106 return NULL;\r
107 }\r
108 }\r
f9607bef 109 if (Bridge->PMem.Base <= Bridge->PMem.Limit) {\r
4a50cf4e
RN
110 ASSERT (Bridge->PMem.Limit < SIZE_4GB);\r
111 if (Bridge->PMem.Limit >= SIZE_4GB) {\r
112 return NULL;\r
113 }\r
114 }\r
f9607bef 115 if (Bridge->PMemAbove4G.Base <= Bridge->PMemAbove4G.Limit) {\r
4a50cf4e
RN
116 ASSERT (Bridge->PMemAbove4G.Base >= SIZE_4GB);\r
117 if (Bridge->PMemAbove4G.Base < SIZE_4GB) {\r
118 return NULL;\r
119 }\r
120 }\r
121\r
401f8cd1
RN
122 //\r
123 // Ignore AllocationAttributes when resources were already assigned.\r
124 //\r
125 if (!Bridge->ResourceAssigned) {\r
126 if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) {\r
127 //\r
128 // If this bit is set, then the PCI Root Bridge does not\r
129 // support separate windows for Non-prefetchable and Prefetchable\r
130 // memory.\r
131 //\r
132 ASSERT (Bridge->PMem.Base > Bridge->PMem.Limit);\r
133 ASSERT (Bridge->PMemAbove4G.Base > Bridge->PMemAbove4G.Limit);\r
134 if ((Bridge->PMem.Base <= Bridge->PMem.Limit) ||\r
135 (Bridge->PMemAbove4G.Base <= Bridge->PMemAbove4G.Limit)\r
136 ) {\r
137 return NULL;\r
138 }\r
4a50cf4e 139 }\r
4a50cf4e 140\r
401f8cd1
RN
141 if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) == 0) {\r
142 //\r
143 // If this bit is not set, then the PCI Root Bridge does not support\r
144 // 64 bit memory windows.\r
145 //\r
146 ASSERT (Bridge->MemAbove4G.Base > Bridge->MemAbove4G.Limit);\r
147 ASSERT (Bridge->PMemAbove4G.Base > Bridge->PMemAbove4G.Limit);\r
148 if ((Bridge->MemAbove4G.Base <= Bridge->MemAbove4G.Limit) ||\r
149 (Bridge->PMemAbove4G.Base <= Bridge->PMemAbove4G.Limit)\r
150 ) {\r
151 return NULL;\r
152 }\r
4a50cf4e
RN
153 }\r
154 }\r
155\r
156 RootBridge = AllocateZeroPool (sizeof (PCI_ROOT_BRIDGE_INSTANCE));\r
157 ASSERT (RootBridge != NULL);\r
158\r
159 RootBridge->Signature = PCI_ROOT_BRIDGE_SIGNATURE;\r
160 RootBridge->Supports = Bridge->Supports;\r
161 RootBridge->Attributes = Bridge->Attributes;\r
162 RootBridge->DmaAbove4G = Bridge->DmaAbove4G;\r
014b4720 163 RootBridge->NoExtendedConfigSpace = Bridge->NoExtendedConfigSpace;\r
4a50cf4e
RN
164 RootBridge->AllocationAttributes = Bridge->AllocationAttributes;\r
165 RootBridge->DevicePath = DuplicateDevicePath (Bridge->DevicePath);\r
166 RootBridge->DevicePathStr = DevicePathStr;\r
167 RootBridge->ConfigBuffer = AllocatePool (\r
168 TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
169 );\r
170 ASSERT (RootBridge->ConfigBuffer != NULL);\r
171 InitializeListHead (&RootBridge->Maps);\r
172\r
173 CopyMem (&RootBridge->Bus, &Bridge->Bus, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
174 CopyMem (&RootBridge->Io, &Bridge->Io, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
175 CopyMem (&RootBridge->Mem, &Bridge->Mem, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
176 CopyMem (&RootBridge->MemAbove4G, &Bridge->MemAbove4G, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
814f4306
RN
177 CopyMem (&RootBridge->PMem, &Bridge->PMem, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
178 CopyMem (&RootBridge->PMemAbove4G, &Bridge->PMemAbove4G, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
4a50cf4e
RN
179\r
180 for (Index = TypeIo; Index < TypeMax; Index++) {\r
401f8cd1
RN
181 switch (Index) {\r
182 case TypeBus:\r
183 Aperture = &RootBridge->Bus;\r
184 break;\r
185 case TypeIo:\r
186 Aperture = &RootBridge->Io;\r
187 break;\r
188 case TypeMem32:\r
189 Aperture = &RootBridge->Mem;\r
190 break;\r
191 case TypeMem64:\r
192 Aperture = &RootBridge->MemAbove4G;\r
193 break;\r
194 case TypePMem32:\r
195 Aperture = &RootBridge->PMem;\r
196 break;\r
197 case TypePMem64:\r
198 Aperture = &RootBridge->PMemAbove4G;\r
199 break;\r
200 default:\r
201 ASSERT (FALSE);\r
26bd6437 202 Aperture = NULL;\r
401f8cd1
RN
203 break;\r
204 }\r
205 RootBridge->ResAllocNode[Index].Type = Index;\r
206 if (Bridge->ResourceAssigned && (Aperture->Limit >= Aperture->Base)) {\r
207 RootBridge->ResAllocNode[Index].Base = Aperture->Base;\r
208 RootBridge->ResAllocNode[Index].Length = Aperture->Limit - Aperture->Base + 1;\r
209 RootBridge->ResAllocNode[Index].Status = ResAllocated;\r
210 } else {\r
211 RootBridge->ResAllocNode[Index].Base = 0;\r
212 RootBridge->ResAllocNode[Index].Length = 0;\r
213 RootBridge->ResAllocNode[Index].Status = ResNone;\r
214 }\r
4a50cf4e
RN
215 }\r
216\r
217 RootBridge->RootBridgeIo.SegmentNumber = Bridge->Segment;\r
4a50cf4e
RN
218 RootBridge->RootBridgeIo.PollMem = RootBridgeIoPollMem;\r
219 RootBridge->RootBridgeIo.PollIo = RootBridgeIoPollIo;\r
220 RootBridge->RootBridgeIo.Mem.Read = RootBridgeIoMemRead;\r
221 RootBridge->RootBridgeIo.Mem.Write = RootBridgeIoMemWrite;\r
222 RootBridge->RootBridgeIo.Io.Read = RootBridgeIoIoRead;\r
223 RootBridge->RootBridgeIo.Io.Write = RootBridgeIoIoWrite;\r
224 RootBridge->RootBridgeIo.CopyMem = RootBridgeIoCopyMem;\r
225 RootBridge->RootBridgeIo.Pci.Read = RootBridgeIoPciRead;\r
226 RootBridge->RootBridgeIo.Pci.Write = RootBridgeIoPciWrite;\r
227 RootBridge->RootBridgeIo.Map = RootBridgeIoMap;\r
228 RootBridge->RootBridgeIo.Unmap = RootBridgeIoUnmap;\r
229 RootBridge->RootBridgeIo.AllocateBuffer = RootBridgeIoAllocateBuffer;\r
230 RootBridge->RootBridgeIo.FreeBuffer = RootBridgeIoFreeBuffer;\r
231 RootBridge->RootBridgeIo.Flush = RootBridgeIoFlush;\r
232 RootBridge->RootBridgeIo.GetAttributes = RootBridgeIoGetAttributes;\r
233 RootBridge->RootBridgeIo.SetAttributes = RootBridgeIoSetAttributes;\r
234 RootBridge->RootBridgeIo.Configuration = RootBridgeIoConfiguration;\r
235\r
236 return RootBridge;\r
237}\r
238\r
239/**\r
240 Check parameters for IO,MMIO,PCI read/write services of PCI Root Bridge IO.\r
241\r
242 The I/O operations are carried out exactly as requested. The caller is\r
243 responsible for satisfying any alignment and I/O width restrictions that a PI\r
244 System on a platform might require. For example on some platforms, width\r
245 requests of EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other\r
246 hand, will be handled by the driver.\r
247\r
248 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
249\r
250 @param[in] OperationType I/O operation type: IO/MMIO/PCI.\r
251\r
252 @param[in] Width Signifies the width of the I/O or Memory operation.\r
253\r
254 @param[in] Address The base address of the I/O operation.\r
255\r
256 @param[in] Count The number of I/O operations to perform. The number\r
257 of bytes moved is Width size * Count, starting at\r
258 Address.\r
259\r
260 @param[in] Buffer For read operations, the destination buffer to\r
261 store the results. For write operations, the source\r
262 buffer from which to write data.\r
263\r
264 @retval EFI_SUCCESS The parameters for this request pass the\r
265 checks.\r
266\r
267 @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.\r
268\r
269 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
270\r
271 @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
272\r
273 @retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
274 and Count is not valid for this PI system.\r
275**/\r
276EFI_STATUS\r
277RootBridgeIoCheckParameter (\r
278 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
279 IN OPERATION_TYPE OperationType,\r
280 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
281 IN UINT64 Address,\r
282 IN UINTN Count,\r
283 IN VOID *Buffer\r
284 )\r
285{\r
286 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
287 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *PciRbAddr;\r
288 UINT64 Base;\r
289 UINT64 Limit;\r
290 UINT32 Size;\r
291\r
292 //\r
293 // Check to see if Buffer is NULL\r
294 //\r
295 if (Buffer == NULL) {\r
296 return EFI_INVALID_PARAMETER;\r
297 }\r
298\r
299 //\r
300 // Check to see if Width is in the valid range\r
301 //\r
302 if ((UINT32) Width >= EfiPciWidthMaximum) {\r
303 return EFI_INVALID_PARAMETER;\r
304 }\r
305\r
306 //\r
307 // For FIFO type, the target address won't increase during the access,\r
308 // so treat Count as 1\r
309 //\r
310 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
311 Count = 1;\r
312 }\r
313\r
314 Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
315 Size = 1 << Width;\r
316\r
317 //\r
318 // Check to see if Address is aligned\r
319 //\r
320 if ((Address & (Size - 1)) != 0) {\r
321 return EFI_UNSUPPORTED;\r
322 }\r
323\r
324 RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
325\r
326 //\r
327 // Check to see if any address associated with this transfer exceeds the\r
328 // maximum allowed address. The maximum address implied by the parameters\r
329 // passed in is Address + Size * Count. If the following condition is met,\r
330 // then the transfer is not supported.\r
331 //\r
332 // Address + Size * Count > Limit + 1\r
333 //\r
334 // Since Limit can be the maximum integer value supported by the CPU and\r
335 // Count can also be the maximum integer value supported by the CPU, this\r
336 // range check must be adjusted to avoid all oveflow conditions.\r
337 //\r
338 if (OperationType == IoOperation) {\r
339 //\r
340 // Allow Legacy IO access\r
341 //\r
342 if (Address + MultU64x32 (Count, Size) <= 0x1000) {\r
343 if ((RootBridge->Attributes & (\r
344 EFI_PCI_ATTRIBUTE_ISA_IO | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_ATTRIBUTE_VGA_IO |\r
345 EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |\r
346 EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 | EFI_PCI_ATTRIBUTE_VGA_IO_16)) != 0) {\r
347 return EFI_SUCCESS;\r
348 }\r
349 }\r
350 Base = RootBridge->Io.Base;\r
351 Limit = RootBridge->Io.Limit;\r
352 } else if (OperationType == MemOperation) {\r
353 //\r
354 // Allow Legacy MMIO access\r
355 //\r
356 if ((Address >= 0xA0000) && (Address + MultU64x32 (Count, Size)) <= 0xC0000) {\r
357 if ((RootBridge->Attributes & EFI_PCI_ATTRIBUTE_VGA_MEMORY) != 0) {\r
358 return EFI_SUCCESS;\r
359 }\r
360 }\r
361 //\r
362 // By comparing the Address against Limit we know which range to be used\r
363 // for checking\r
364 //\r
365 if (Address + MultU64x32 (Count, Size) <= RootBridge->Mem.Limit + 1) {\r
366 Base = RootBridge->Mem.Base;\r
367 Limit = RootBridge->Mem.Limit;\r
368 } else {\r
369 Base = RootBridge->MemAbove4G.Base;\r
370 Limit = RootBridge->MemAbove4G.Limit;\r
371 }\r
372 } else {\r
373 PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &Address;\r
374 if (PciRbAddr->Bus < RootBridge->Bus.Base ||\r
375 PciRbAddr->Bus > RootBridge->Bus.Limit) {\r
376 return EFI_INVALID_PARAMETER;\r
377 }\r
378\r
379 if (PciRbAddr->Device > PCI_MAX_DEVICE ||\r
380 PciRbAddr->Function > PCI_MAX_FUNC) {\r
381 return EFI_INVALID_PARAMETER;\r
382 }\r
383\r
384 if (PciRbAddr->ExtendedRegister != 0) {\r
385 Address = PciRbAddr->ExtendedRegister;\r
386 } else {\r
387 Address = PciRbAddr->Register;\r
388 }\r
389 Base = 0;\r
014b4720 390 Limit = RootBridge->NoExtendedConfigSpace ? 0xFF : 0xFFF;\r
4a50cf4e
RN
391 }\r
392\r
393 if (Address < Base) {\r
394 return EFI_INVALID_PARAMETER;\r
395 }\r
396\r
397 if (Address + MultU64x32 (Count, Size) > Limit + 1) {\r
398 return EFI_INVALID_PARAMETER;\r
399 }\r
400\r
401 return EFI_SUCCESS;\r
402}\r
403\r
404/**\r
405 Polls an address in memory mapped I/O space until an exit condition is met,\r
406 or a timeout occurs.\r
407\r
408 This function provides a standard way to poll a PCI memory location. A PCI\r
409 memory read operation is performed at the PCI memory address specified by\r
410 Address for the width specified by Width. The result of this PCI memory read\r
411 operation is stored in Result. This PCI memory read operation is repeated\r
412 until either a timeout of Delay 100 ns units has expired, or (Result & Mask)\r
413 is equal to Value.\r
414\r
415 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
416 @param[in] Width Signifies the width of the memory operations.\r
417 @param[in] Address The base address of the memory operations. The caller\r
418 is responsible for aligning Address if required.\r
419 @param[in] Mask Mask used for the polling criteria. Bytes above Width\r
420 in Mask are ignored. The bits in the bytes below Width\r
421 which are zero in Mask are ignored when polling the\r
422 memory address.\r
423 @param[in] Value The comparison value used for the polling exit\r
424 criteria.\r
425 @param[in] Delay The number of 100 ns units to poll. Note that timer\r
426 available may be of poorer granularity.\r
427 @param[out] Result Pointer to the last value read from the memory\r
428 location.\r
429\r
430 @retval EFI_SUCCESS The last data returned from the access matched\r
431 the poll exit criteria.\r
432 @retval EFI_INVALID_PARAMETER Width is invalid.\r
433 @retval EFI_INVALID_PARAMETER Result is NULL.\r
434 @retval EFI_TIMEOUT Delay expired before a match occurred.\r
435 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
436 lack of resources.\r
437**/\r
4a50cf4e
RN
438EFI_STATUS\r
439EFIAPI\r
440RootBridgeIoPollMem (\r
441 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
442 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
443 IN UINT64 Address,\r
444 IN UINT64 Mask,\r
445 IN UINT64 Value,\r
446 IN UINT64 Delay,\r
447 OUT UINT64 *Result\r
448 )\r
449{\r
450 EFI_STATUS Status;\r
451 UINT64 NumberOfTicks;\r
452 UINT32 Remainder;\r
453\r
454 if (Result == NULL) {\r
455 return EFI_INVALID_PARAMETER;\r
456 }\r
457\r
458 if ((UINT32)Width > EfiPciWidthUint64) {\r
459 return EFI_INVALID_PARAMETER;\r
460 }\r
461\r
462 //\r
463 // No matter what, always do a single poll.\r
464 //\r
465 Status = This->Mem.Read (This, Width, Address, 1, Result);\r
466 if (EFI_ERROR (Status)) {\r
467 return Status;\r
468 }\r
469\r
470 if ((*Result & Mask) == Value) {\r
471 return EFI_SUCCESS;\r
472 }\r
473\r
474 if (Delay == 0) {\r
475 return EFI_SUCCESS;\r
476\r
477 } else {\r
478\r
479 //\r
480 // Determine the proper # of metronome ticks to wait for polling the\r
481 // location. The nuber of ticks is Roundup (Delay /\r
482 // mMetronome->TickPeriod)+1\r
483 // The "+1" to account for the possibility of the first tick being short\r
484 // because we started in the middle of a tick.\r
485 //\r
486 // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome\r
487 // protocol definition is updated.\r
488 //\r
489 NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod,\r
490 &Remainder);\r
491 if (Remainder != 0) {\r
492 NumberOfTicks += 1;\r
493 }\r
494 NumberOfTicks += 1;\r
495\r
496 while (NumberOfTicks != 0) {\r
497\r
498 mMetronome->WaitForTick (mMetronome, 1);\r
499\r
500 Status = This->Mem.Read (This, Width, Address, 1, Result);\r
501 if (EFI_ERROR (Status)) {\r
502 return Status;\r
503 }\r
504\r
505 if ((*Result & Mask) == Value) {\r
506 return EFI_SUCCESS;\r
507 }\r
508\r
509 NumberOfTicks -= 1;\r
510 }\r
511 }\r
512 return EFI_TIMEOUT;\r
513}\r
514\r
515/**\r
516 Reads from the I/O space of a PCI Root Bridge. Returns when either the\r
517 polling exit criteria is satisfied or after a defined duration.\r
518\r
519 This function provides a standard way to poll a PCI I/O location. A PCI I/O\r
520 read operation is performed at the PCI I/O address specified by Address for\r
521 the width specified by Width.\r
522 The result of this PCI I/O read operation is stored in Result. This PCI I/O\r
523 read operation is repeated until either a timeout of Delay 100 ns units has\r
524 expired, or (Result & Mask) is equal to Value.\r
525\r
526 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
527 @param[in] Width Signifies the width of the I/O operations.\r
528 @param[in] Address The base address of the I/O operations. The caller is\r
529 responsible for aligning Address if required.\r
530 @param[in] Mask Mask used for the polling criteria. Bytes above Width in\r
531 Mask are ignored. The bits in the bytes below Width\r
532 which are zero in Mask are ignored when polling the I/O\r
533 address.\r
534 @param[in] Value The comparison value used for the polling exit criteria.\r
535 @param[in] Delay The number of 100 ns units to poll. Note that timer\r
536 available may be of poorer granularity.\r
537 @param[out] Result Pointer to the last value read from the memory location.\r
538\r
539 @retval EFI_SUCCESS The last data returned from the access matched\r
540 the poll exit criteria.\r
541 @retval EFI_INVALID_PARAMETER Width is invalid.\r
542 @retval EFI_INVALID_PARAMETER Result is NULL.\r
543 @retval EFI_TIMEOUT Delay expired before a match occurred.\r
544 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
545 lack of resources.\r
546**/\r
547EFI_STATUS\r
548EFIAPI\r
549RootBridgeIoPollIo (\r
550 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
551 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
552 IN UINT64 Address,\r
553 IN UINT64 Mask,\r
554 IN UINT64 Value,\r
555 IN UINT64 Delay,\r
556 OUT UINT64 *Result\r
557 )\r
558{\r
559 EFI_STATUS Status;\r
560 UINT64 NumberOfTicks;\r
561 UINT32 Remainder;\r
562\r
563 //\r
564 // No matter what, always do a single poll.\r
565 //\r
566\r
567 if (Result == NULL) {\r
568 return EFI_INVALID_PARAMETER;\r
569 }\r
570\r
571 if ((UINT32)Width > EfiPciWidthUint64) {\r
572 return EFI_INVALID_PARAMETER;\r
573 }\r
574\r
575 Status = This->Io.Read (This, Width, Address, 1, Result);\r
576 if (EFI_ERROR (Status)) {\r
577 return Status;\r
578 }\r
579 if ((*Result & Mask) == Value) {\r
580 return EFI_SUCCESS;\r
581 }\r
582\r
583 if (Delay == 0) {\r
584 return EFI_SUCCESS;\r
585\r
586 } else {\r
587\r
588 //\r
589 // Determine the proper # of metronome ticks to wait for polling the\r
590 // location. The number of ticks is Roundup (Delay /\r
591 // mMetronome->TickPeriod)+1\r
592 // The "+1" to account for the possibility of the first tick being short\r
593 // because we started in the middle of a tick.\r
594 //\r
595 NumberOfTicks = DivU64x32Remainder (Delay, (UINT32)mMetronome->TickPeriod,\r
596 &Remainder);\r
597 if (Remainder != 0) {\r
598 NumberOfTicks += 1;\r
599 }\r
600 NumberOfTicks += 1;\r
601\r
602 while (NumberOfTicks != 0) {\r
603\r
604 mMetronome->WaitForTick (mMetronome, 1);\r
605\r
606 Status = This->Io.Read (This, Width, Address, 1, Result);\r
607 if (EFI_ERROR (Status)) {\r
608 return Status;\r
609 }\r
610\r
611 if ((*Result & Mask) == Value) {\r
612 return EFI_SUCCESS;\r
613 }\r
614\r
615 NumberOfTicks -= 1;\r
616 }\r
617 }\r
618 return EFI_TIMEOUT;\r
619}\r
620\r
621/**\r
622 Enables a PCI driver to access PCI controller registers in the PCI root\r
623 bridge memory space.\r
624\r
625 The Mem.Read(), and Mem.Write() functions enable a driver to access PCI\r
626 controller registers in the PCI root bridge memory space.\r
627 The memory operations are carried out exactly as requested. The caller is\r
628 responsible for satisfying any alignment and memory width restrictions that a\r
629 PCI Root Bridge on a platform might require.\r
630\r
631 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
632 @param[in] Width Signifies the width of the memory operation.\r
633 @param[in] Address The base address of the memory operation. The caller\r
634 is responsible for aligning the Address if required.\r
635 @param[in] Count The number of memory operations to perform. Bytes\r
636 moved is Width size * Count, starting at Address.\r
637 @param[out] Buffer For read operations, the destination buffer to store\r
638 the results. For write operations, the source buffer\r
639 to write data from.\r
640\r
641 @retval EFI_SUCCESS The data was read from or written to the PCI\r
642 root bridge.\r
643 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
644 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
645 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
646 lack of resources.\r
647**/\r
648EFI_STATUS\r
649EFIAPI\r
650RootBridgeIoMemRead (\r
651 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
652 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
653 IN UINT64 Address,\r
654 IN UINTN Count,\r
655 OUT VOID *Buffer\r
656 )\r
657{\r
658 EFI_STATUS Status;\r
659\r
660 Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address,\r
661 Count, Buffer);\r
662 if (EFI_ERROR (Status)) {\r
663 return Status;\r
664 }\r
665 return mCpuIo->Mem.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);\r
666}\r
667\r
668/**\r
669 Enables a PCI driver to access PCI controller registers in the PCI root\r
670 bridge memory space.\r
671\r
672 The Mem.Read(), and Mem.Write() functions enable a driver to access PCI\r
673 controller registers in the PCI root bridge memory space.\r
674 The memory operations are carried out exactly as requested. The caller is\r
675 responsible for satisfying any alignment and memory width restrictions that a\r
676 PCI Root Bridge on a platform might require.\r
677\r
678 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
679 @param[in] Width Signifies the width of the memory operation.\r
680 @param[in] Address The base address of the memory operation. The caller\r
681 is responsible for aligning the Address if required.\r
682 @param[in] Count The number of memory operations to perform. Bytes\r
683 moved is Width size * Count, starting at Address.\r
684 @param[in] Buffer For read operations, the destination buffer to store\r
685 the results. For write operations, the source buffer\r
686 to write data from.\r
687\r
688 @retval EFI_SUCCESS The data was read from or written to the PCI\r
689 root bridge.\r
690 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
691 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
692 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
693 lack of resources.\r
694**/\r
695EFI_STATUS\r
696EFIAPI\r
697RootBridgeIoMemWrite (\r
698 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
699 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
700 IN UINT64 Address,\r
701 IN UINTN Count,\r
702 IN VOID *Buffer\r
703 )\r
704{\r
705 EFI_STATUS Status;\r
706\r
707 Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address,\r
708 Count, Buffer);\r
709 if (EFI_ERROR (Status)) {\r
710 return Status;\r
711 }\r
712 return mCpuIo->Mem.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);\r
713}\r
714\r
715/**\r
716 Enables a PCI driver to access PCI controller registers in the PCI root\r
717 bridge I/O space.\r
718\r
719 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
720 @param[in] Width Signifies the width of the memory operations.\r
721 @param[in] Address The base address of the I/O operation. The caller is\r
722 responsible for aligning the Address if required.\r
723 @param[in] Count The number of I/O operations to perform. Bytes moved\r
724 is Width size * Count, starting at Address.\r
725 @param[out] Buffer For read operations, the destination buffer to store\r
726 the results. For write operations, the source buffer\r
727 to write data from.\r
728\r
729 @retval EFI_SUCCESS The data was read from or written to the PCI\r
730 root bridge.\r
731 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
732 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
733 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
734 lack of resources.\r
735**/\r
736EFI_STATUS\r
737EFIAPI\r
738RootBridgeIoIoRead (\r
739 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
740 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
741 IN UINT64 Address,\r
742 IN UINTN Count,\r
743 OUT VOID *Buffer\r
744 )\r
745{\r
746 EFI_STATUS Status;\r
747 Status = RootBridgeIoCheckParameter (\r
748 This, IoOperation, Width,\r
749 Address, Count, Buffer\r
750 );\r
751 if (EFI_ERROR (Status)) {\r
752 return Status;\r
753 }\r
754 return mCpuIo->Io.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);\r
755}\r
756\r
757/**\r
758 Enables a PCI driver to access PCI controller registers in the PCI root\r
759 bridge I/O space.\r
760\r
761 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
762 @param[in] Width Signifies the width of the memory operations.\r
763 @param[in] Address The base address of the I/O operation. The caller is\r
764 responsible for aligning the Address if required.\r
765 @param[in] Count The number of I/O operations to perform. Bytes moved\r
766 is Width size * Count, starting at Address.\r
767 @param[in] Buffer For read operations, the destination buffer to store\r
768 the results. For write operations, the source buffer\r
769 to write data from.\r
770\r
771 @retval EFI_SUCCESS The data was read from or written to the PCI\r
772 root bridge.\r
773 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
774 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
775 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
776 lack of resources.\r
777**/\r
778EFI_STATUS\r
779EFIAPI\r
780RootBridgeIoIoWrite (\r
781 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
782 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
783 IN UINT64 Address,\r
784 IN UINTN Count,\r
785 IN VOID *Buffer\r
786 )\r
787{\r
788 EFI_STATUS Status;\r
789 Status = RootBridgeIoCheckParameter (\r
790 This, IoOperation, Width,\r
791 Address, Count, Buffer\r
792 );\r
793 if (EFI_ERROR (Status)) {\r
794 return Status;\r
795 }\r
796 return mCpuIo->Io.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);\r
797}\r
798\r
799/**\r
800 Enables a PCI driver to copy one region of PCI root bridge memory space to\r
801 another region of PCI root bridge memory space.\r
802\r
803 The CopyMem() function enables a PCI driver to copy one region of PCI root\r
804 bridge memory space to another region of PCI root bridge memory space. This\r
805 is especially useful for video scroll operation on a memory mapped video\r
806 buffer.\r
807 The memory operations are carried out exactly as requested. The caller is\r
808 responsible for satisfying any alignment and memory width restrictions that a\r
809 PCI root bridge on a platform might require.\r
810\r
811 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL\r
812 instance.\r
813 @param[in] Width Signifies the width of the memory operations.\r
814 @param[in] DestAddress The destination address of the memory operation. The\r
815 caller is responsible for aligning the DestAddress if\r
816 required.\r
817 @param[in] SrcAddress The source address of the memory operation. The caller\r
818 is responsible for aligning the SrcAddress if\r
819 required.\r
820 @param[in] Count The number of memory operations to perform. Bytes\r
821 moved is Width size * Count, starting at DestAddress\r
822 and SrcAddress.\r
823\r
824 @retval EFI_SUCCESS The data was copied from one memory region\r
825 to another memory region.\r
826 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
827 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
828 lack of resources.\r
829**/\r
830EFI_STATUS\r
831EFIAPI\r
832RootBridgeIoCopyMem (\r
833 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
834 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
835 IN UINT64 DestAddress,\r
836 IN UINT64 SrcAddress,\r
837 IN UINTN Count\r
838 )\r
839{\r
840 EFI_STATUS Status;\r
841 BOOLEAN Forward;\r
842 UINTN Stride;\r
843 UINTN Index;\r
844 UINT64 Result;\r
845\r
846 if ((UINT32) Width > EfiPciWidthUint64) {\r
847 return EFI_INVALID_PARAMETER;\r
848 }\r
849\r
850 if (DestAddress == SrcAddress) {\r
851 return EFI_SUCCESS;\r
852 }\r
853\r
854 Stride = (UINTN) (1 << Width);\r
855\r
856 Forward = TRUE;\r
857 if ((DestAddress > SrcAddress) &&\r
858 (DestAddress < (SrcAddress + Count * Stride))) {\r
859 Forward = FALSE;\r
860 SrcAddress = SrcAddress + (Count - 1) * Stride;\r
861 DestAddress = DestAddress + (Count - 1) * Stride;\r
862 }\r
863\r
864 for (Index = 0; Index < Count; Index++) {\r
865 Status = RootBridgeIoMemRead (\r
866 This,\r
867 Width,\r
868 SrcAddress,\r
869 1,\r
870 &Result\r
871 );\r
872 if (EFI_ERROR (Status)) {\r
873 return Status;\r
874 }\r
875 Status = RootBridgeIoMemWrite (\r
876 This,\r
877 Width,\r
878 DestAddress,\r
879 1,\r
880 &Result\r
881 );\r
882 if (EFI_ERROR (Status)) {\r
883 return Status;\r
884 }\r
885 if (Forward) {\r
886 SrcAddress += Stride;\r
887 DestAddress += Stride;\r
888 } else {\r
889 SrcAddress -= Stride;\r
890 DestAddress -= Stride;\r
891 }\r
892 }\r
893 return EFI_SUCCESS;\r
894}\r
895\r
896\r
897/**\r
898 PCI configuration space access.\r
899\r
900 @param This A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL\r
901 @param Read TRUE indicating it's a read operation.\r
902 @param Width Signifies the width of the memory operation.\r
903 @param Address The address within the PCI configuration space\r
904 for the PCI controller.\r
905 @param Count The number of PCI configuration operations\r
906 to perform.\r
907 @param Buffer The destination buffer to store the results.\r
908\r
909 @retval EFI_SUCCESS The data was read/written from/to the PCI root bridge.\r
910 @retval EFI_INVALID_PARAMETER Invalid parameters found.\r
911**/\r
912EFI_STATUS\r
913EFIAPI\r
914RootBridgeIoPciAccess (\r
915 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
916 IN BOOLEAN Read,\r
917 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
918 IN UINT64 Address,\r
919 IN UINTN Count,\r
920 IN OUT VOID *Buffer\r
921 )\r
922{\r
923 EFI_STATUS Status;\r
924 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
925 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;\r
926 UINT8 *Uint8Buffer;\r
927 UINT8 InStride;\r
928 UINT8 OutStride;\r
929 UINTN Size;\r
930\r
931 Status = RootBridgeIoCheckParameter (This, PciOperation, Width, Address, Count, Buffer);\r
932 if (EFI_ERROR (Status)) {\r
933 return Status;\r
934 }\r
935\r
936 //\r
937 // Read Pci configuration space\r
938 //\r
939 RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
940 CopyMem (&PciAddress, &Address, sizeof (PciAddress));\r
941\r
942 if (PciAddress.ExtendedRegister == 0) {\r
943 PciAddress.ExtendedRegister = PciAddress.Register;\r
944 }\r
945\r
946 Address = PCI_SEGMENT_LIB_ADDRESS (\r
947 RootBridge->RootBridgeIo.SegmentNumber,\r
948 PciAddress.Bus,\r
949 PciAddress.Device,\r
950 PciAddress.Function,\r
951 PciAddress.ExtendedRegister\r
952 );\r
953\r
954 //\r
955 // Select loop based on the width of the transfer\r
956 //\r
957 InStride = mInStride[Width];\r
958 OutStride = mOutStride[Width];\r
959 Size = (UINTN) (1 << (Width & 0x03));\r
960 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
961 if (Read) {\r
962 PciSegmentReadBuffer (Address, Size, Uint8Buffer);\r
963 } else {\r
964 PciSegmentWriteBuffer (Address, Size, Uint8Buffer);\r
965 }\r
966 }\r
967 return EFI_SUCCESS;\r
968}\r
969\r
970/**\r
971 Allows read from PCI configuration space.\r
972\r
973 @param This A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL\r
974 @param Width Signifies the width of the memory operation.\r
975 @param Address The address within the PCI configuration space\r
976 for the PCI controller.\r
977 @param Count The number of PCI configuration operations\r
978 to perform.\r
979 @param Buffer The destination buffer to store the results.\r
980\r
981 @retval EFI_SUCCESS The data was read from the PCI root bridge.\r
982 @retval EFI_INVALID_PARAMETER Invalid parameters found.\r
983**/\r
984EFI_STATUS\r
985EFIAPI\r
986RootBridgeIoPciRead (\r
987 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
988 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
989 IN UINT64 Address,\r
990 IN UINTN Count,\r
991 IN OUT VOID *Buffer\r
992 )\r
993{\r
994 return RootBridgeIoPciAccess (This, TRUE, Width, Address, Count, Buffer);\r
995}\r
996\r
997/**\r
998 Allows write to PCI configuration space.\r
999\r
1000 @param This A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL\r
1001 @param Width Signifies the width of the memory operation.\r
1002 @param Address The address within the PCI configuration space\r
1003 for the PCI controller.\r
1004 @param Count The number of PCI configuration operations\r
1005 to perform.\r
1006 @param Buffer The source buffer to get the results.\r
1007\r
1008 @retval EFI_SUCCESS The data was written to the PCI root bridge.\r
1009 @retval EFI_INVALID_PARAMETER Invalid parameters found.\r
1010**/\r
1011EFI_STATUS\r
1012EFIAPI\r
1013RootBridgeIoPciWrite (\r
1014 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
1015 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
1016 IN UINT64 Address,\r
1017 IN UINTN Count,\r
1018 IN OUT VOID *Buffer\r
1019 )\r
1020{\r
1021 return RootBridgeIoPciAccess (This, FALSE, Width, Address, Count, Buffer);\r
1022}\r
1023\r
1024/**\r
4a50cf4e
RN
1025 Provides the PCI controller-specific address needed to access\r
1026 system memory for DMA.\r
1027\r
1028 @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
1029 @param Operation Indicate if the bus master is going to read or write\r
1030 to system memory.\r
1031 @param HostAddress The system memory address to map on the PCI controller.\r
1032 @param NumberOfBytes On input the number of bytes to map.\r
1033 On output the number of bytes that were mapped.\r
1034 @param DeviceAddress The resulting map address for the bus master PCI\r
1035 controller to use to access the system memory's HostAddress.\r
1036 @param Mapping The value to pass to Unmap() when the bus master DMA\r
1037 operation is complete.\r
1038\r
1039 @retval EFI_SUCCESS Success.\r
1040 @retval EFI_INVALID_PARAMETER Invalid parameters found.\r
1041 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.\r
1042 @retval EFI_DEVICE_ERROR The System hardware could not map the requested address.\r
1043 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of resources.\r
4a50cf4e
RN
1044**/\r
1045EFI_STATUS\r
1046EFIAPI\r
1047RootBridgeIoMap (\r
1048 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
1049 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,\r
1050 IN VOID *HostAddress,\r
1051 IN OUT UINTN *NumberOfBytes,\r
1052 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
1053 OUT VOID **Mapping\r
1054 )\r
1055{\r
1056 EFI_STATUS Status;\r
1057 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
1058 EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
1059 MAP_INFO *MapInfo;\r
1060\r
1061 if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL ||\r
1062 Mapping == NULL) {\r
1063 return EFI_INVALID_PARAMETER;\r
1064 }\r
1065\r
1066 //\r
1067 // Make sure that Operation is valid\r
1068 //\r
1069 if ((UINT32) Operation >= EfiPciOperationMaximum) {\r
1070 return EFI_INVALID_PARAMETER;\r
1071 }\r
1072\r
1073 RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
1074\r
1075 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;\r
1076 if (!RootBridge->DmaAbove4G && ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {\r
1077 //\r
1078 // If the root bridge can not handle performing DMA above 4GB but\r
1079 // any part of the DMA transfer being mapped is above 4GB, then\r
1080 // map the DMA transfer to a buffer below 4GB.\r
1081 //\r
1082\r
1083 if (Operation == EfiPciOperationBusMasterCommonBuffer ||\r
1084 Operation == EfiPciOperationBusMasterCommonBuffer64) {\r
1085 //\r
1086 // Common Buffer operations can not be remapped. If the common buffer\r
1087 // if above 4GB, then it is not possible to generate a mapping, so return\r
1088 // an error.\r
1089 //\r
1090 return EFI_UNSUPPORTED;\r
1091 }\r
1092\r
1093 //\r
1094 // Allocate a MAP_INFO structure to remember the mapping when Unmap() is\r
1095 // called later.\r
1096 //\r
1097 MapInfo = AllocatePool (sizeof (MAP_INFO));\r
1098 if (MapInfo == NULL) {\r
1099 *NumberOfBytes = 0;\r
1100 return EFI_OUT_OF_RESOURCES;\r
1101 }\r
1102\r
1103 //\r
1104 // Initialize the MAP_INFO structure\r
1105 //\r
1106 MapInfo->Signature = MAP_INFO_SIGNATURE;\r
1107 MapInfo->Operation = Operation;\r
1108 MapInfo->NumberOfBytes = *NumberOfBytes;\r
1109 MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes);\r
1110 MapInfo->HostAddress = PhysicalAddress;\r
1111 MapInfo->MappedHostAddress = SIZE_4GB - 1;\r
1112\r
1113 //\r
1114 // Allocate a buffer below 4GB to map the transfer to.\r
1115 //\r
1116 Status = gBS->AllocatePages (\r
1117 AllocateMaxAddress,\r
1118 EfiBootServicesData,\r
1119 MapInfo->NumberOfPages,\r
1120 &MapInfo->MappedHostAddress\r
1121 );\r
1122 if (EFI_ERROR (Status)) {\r
1123 FreePool (MapInfo);\r
1124 *NumberOfBytes = 0;\r
1125 return Status;\r
1126 }\r
1127\r
1128 //\r
1129 // If this is a read operation from the Bus Master's point of view,\r
1130 // then copy the contents of the real buffer into the mapped buffer\r
1131 // so the Bus Master can read the contents of the real buffer.\r
1132 //\r
1133 if (Operation == EfiPciOperationBusMasterRead ||\r
1134 Operation == EfiPciOperationBusMasterRead64) {\r
1135 CopyMem (\r
1136 (VOID *) (UINTN) MapInfo->MappedHostAddress,\r
1137 (VOID *) (UINTN) MapInfo->HostAddress,\r
1138 MapInfo->NumberOfBytes\r
1139 );\r
1140 }\r
1141\r
1142 InsertTailList (&RootBridge->Maps, &MapInfo->Link);\r
1143\r
1144 //\r
1145 // The DeviceAddress is the address of the maped buffer below 4GB\r
1146 //\r
1147 *DeviceAddress = MapInfo->MappedHostAddress;\r
1148 //\r
1149 // Return a pointer to the MAP_INFO structure in Mapping\r
1150 //\r
1151 *Mapping = MapInfo;\r
1152 } else {\r
1153 //\r
1154 // If the root bridge CAN handle performing DMA above 4GB or\r
1155 // the transfer is below 4GB, so the DeviceAddress is simply the\r
1156 // HostAddress\r
1157 //\r
1158 *DeviceAddress = PhysicalAddress;\r
1159 *Mapping = NO_MAPPING;\r
1160 }\r
1161\r
1162 return EFI_SUCCESS;\r
1163}\r
1164\r
1165/**\r
1166 Completes the Map() operation and releases any corresponding resources.\r
1167\r
1168 The Unmap() function completes the Map() operation and releases any\r
1169 corresponding resources.\r
1170 If the operation was an EfiPciOperationBusMasterWrite or\r
1171 EfiPciOperationBusMasterWrite64, the data is committed to the target system\r
1172 memory.\r
1173 Any resources used for the mapping are freed.\r
1174\r
1175 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
1176 @param[in] Mapping The mapping value returned from Map().\r
1177\r
1178 @retval EFI_SUCCESS The range was unmapped.\r
1179 @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().\r
1180 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.\r
1181**/\r
1182EFI_STATUS\r
1183EFIAPI\r
1184RootBridgeIoUnmap (\r
1185 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
1186 IN VOID *Mapping\r
1187 )\r
1188{\r
1189 MAP_INFO *MapInfo;\r
1190 LIST_ENTRY *Link;\r
1191 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
1192\r
1193 RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
1194 //\r
1195 // See if the Map() operation associated with this Unmap() required a mapping\r
1196 // buffer. If a mapping buffer was not required, then this function simply\r
1197 // returns EFI_SUCCESS.\r
1198 //\r
1199 if (Mapping == NO_MAPPING) {\r
1200 return EFI_SUCCESS;\r
1201 }\r
1202\r
1203 MapInfo = NO_MAPPING;\r
1204 for (Link = GetFirstNode (&RootBridge->Maps)\r
1205 ; !IsNull (&RootBridge->Maps, Link)\r
1206 ; Link = GetNextNode (&RootBridge->Maps, Link)\r
1207 ) {\r
1208 MapInfo = MAP_INFO_FROM_LINK (Link);\r
1209 if (MapInfo == Mapping) {\r
1210 break;\r
1211 }\r
1212 }\r
1213 //\r
1214 // Mapping is not a valid value returned by Map()\r
1215 //\r
1216 if (MapInfo != Mapping) {\r
1217 return EFI_INVALID_PARAMETER;\r
1218 }\r
1219 RemoveEntryList (&MapInfo->Link);\r
1220\r
1221 //\r
1222 // If this is a write operation from the Bus Master's point of view,\r
1223 // then copy the contents of the mapped buffer into the real buffer\r
1224 // so the processor can read the contents of the real buffer.\r
1225 //\r
1226 if (MapInfo->Operation == EfiPciOperationBusMasterWrite ||\r
1227 MapInfo->Operation == EfiPciOperationBusMasterWrite64) {\r
1228 CopyMem (\r
1229 (VOID *) (UINTN) MapInfo->HostAddress,\r
1230 (VOID *) (UINTN) MapInfo->MappedHostAddress,\r
1231 MapInfo->NumberOfBytes\r
1232 );\r
1233 }\r
1234\r
1235 //\r
1236 // Free the mapped buffer and the MAP_INFO structure.\r
1237 //\r
1238 gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);\r
1239 FreePool (Mapping);\r
1240 return EFI_SUCCESS;\r
1241}\r
1242\r
1243/**\r
1244 Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer\r
1245 or EfiPciOperationBusMasterCommonBuffer64 mapping.\r
1246\r
1247 @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
1248 @param Type This parameter is not used and must be ignored.\r
1249 @param MemoryType The type of memory to allocate, EfiBootServicesData or\r
1250 EfiRuntimeServicesData.\r
1251 @param Pages The number of pages to allocate.\r
1252 @param HostAddress A pointer to store the base system memory address of the\r
1253 allocated range.\r
1254 @param Attributes The requested bit mask of attributes for the allocated\r
1255 range. Only the attributes\r
1256 EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,\r
1257 EFI_PCI_ATTRIBUTE_MEMORY_CACHED, and\r
1258 EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this\r
1259 function.\r
1260\r
1261 @retval EFI_SUCCESS The requested memory pages were allocated.\r
1262 @retval EFI_INVALID_PARAMETER MemoryType is invalid.\r
1263 @retval EFI_INVALID_PARAMETER HostAddress is NULL.\r
1264 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal\r
1265 attribute bits are MEMORY_WRITE_COMBINE,\r
1266 MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.\r
1267 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.\r
1268**/\r
1269EFI_STATUS\r
1270EFIAPI\r
1271RootBridgeIoAllocateBuffer (\r
1272 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
1273 IN EFI_ALLOCATE_TYPE Type,\r
1274 IN EFI_MEMORY_TYPE MemoryType,\r
1275 IN UINTN Pages,\r
1276 OUT VOID **HostAddress,\r
1277 IN UINT64 Attributes\r
1278 )\r
1279{\r
1280 EFI_STATUS Status;\r
1281 EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
1282 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
1283 EFI_ALLOCATE_TYPE AllocateType;\r
1284\r
1285 //\r
1286 // Validate Attributes\r
1287 //\r
1288 if ((Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {\r
1289 return EFI_UNSUPPORTED;\r
1290 }\r
1291\r
1292 //\r
1293 // Check for invalid inputs\r
1294 //\r
1295 if (HostAddress == NULL) {\r
1296 return EFI_INVALID_PARAMETER;\r
1297 }\r
1298\r
1299 //\r
1300 // The only valid memory types are EfiBootServicesData and\r
1301 // EfiRuntimeServicesData\r
1302 //\r
1303 if (MemoryType != EfiBootServicesData &&\r
1304 MemoryType != EfiRuntimeServicesData) {\r
1305 return EFI_INVALID_PARAMETER;\r
1306 }\r
1307\r
1308 RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
1309\r
1310 AllocateType = AllocateAnyPages;\r
1311 if (!RootBridge->DmaAbove4G) {\r
1312 //\r
1313 // Limit allocations to memory below 4GB\r
1314 //\r
1315 AllocateType = AllocateMaxAddress;\r
1316 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1);\r
1317 }\r
1318 Status = gBS->AllocatePages (\r
1319 AllocateType,\r
1320 MemoryType,\r
1321 Pages,\r
1322 &PhysicalAddress\r
1323 );\r
1324 if (!EFI_ERROR (Status)) {\r
1325 *HostAddress = (VOID *) (UINTN) PhysicalAddress;\r
1326 }\r
1327\r
1328 return Status;\r
1329}\r
1330\r
1331/**\r
1332 Frees memory that was allocated with AllocateBuffer().\r
1333\r
1334 The FreeBuffer() function frees memory that was allocated with\r
1335 AllocateBuffer().\r
1336\r
1337 @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
1338 @param Pages The number of pages to free.\r
1339 @param HostAddress The base system memory address of the allocated range.\r
1340\r
1341 @retval EFI_SUCCESS The requested memory pages were freed.\r
1342 @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and\r
1343 Pages was not allocated with AllocateBuffer().\r
1344**/\r
1345EFI_STATUS\r
1346EFIAPI\r
1347RootBridgeIoFreeBuffer (\r
1348 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
1349 IN UINTN Pages,\r
1350 OUT VOID *HostAddress\r
1351 )\r
1352{\r
1353 return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);\r
1354}\r
1355\r
1356/**\r
1357 Flushes all PCI posted write transactions from a PCI host bridge to system\r
1358 memory.\r
1359\r
1360 The Flush() function flushes any PCI posted write transactions from a PCI\r
1361 host bridge to system memory. Posted write transactions are generated by PCI\r
1362 bus masters when they perform write transactions to target addresses in\r
1363 system memory.\r
1364 This function does not flush posted write transactions from any PCI bridges.\r
1365 A PCI controller specific action must be taken to guarantee that the posted\r
1366 write transactions have been flushed from the PCI controller and from all the\r
1367 PCI bridges into the PCI host bridge. This is typically done with a PCI read\r
1368 transaction from the PCI controller prior to calling Flush().\r
1369\r
1370 @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
1371\r
1372 @retval EFI_SUCCESS The PCI posted write transactions were flushed\r
1373 from the PCI host bridge to system memory.\r
1374 @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed\r
1375 from the PCI host bridge due to a hardware error.\r
1376**/\r
1377EFI_STATUS\r
1378EFIAPI\r
1379RootBridgeIoFlush (\r
1380 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This\r
1381 )\r
1382{\r
1383 return EFI_SUCCESS;\r
1384}\r
1385\r
1386/**\r
1387 Gets the attributes that a PCI root bridge supports setting with\r
1388 SetAttributes(), and the attributes that a PCI root bridge is currently\r
1389 using.\r
1390\r
1391 The GetAttributes() function returns the mask of attributes that this PCI\r
1392 root bridge supports and the mask of attributes that the PCI root bridge is\r
1393 currently using.\r
1394\r
1395 @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
1396 @param Supported A pointer to the mask of attributes that this PCI root\r
1397 bridge supports setting with SetAttributes().\r
1398 @param Attributes A pointer to the mask of attributes that this PCI root\r
1399 bridge is currently using.\r
1400\r
1401 @retval EFI_SUCCESS If Supports is not NULL, then the attributes\r
1402 that the PCI root bridge supports is returned\r
1403 in Supports. If Attributes is not NULL, then\r
1404 the attributes that the PCI root bridge is\r
1405 currently using is returned in Attributes.\r
1406 @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.\r
1407**/\r
1408EFI_STATUS\r
1409EFIAPI\r
1410RootBridgeIoGetAttributes (\r
1411 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
1412 OUT UINT64 *Supported,\r
1413 OUT UINT64 *Attributes\r
1414 )\r
1415{\r
1416 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
1417\r
1418 if (Attributes == NULL && Supported == NULL) {\r
1419 return EFI_INVALID_PARAMETER;\r
1420 }\r
1421\r
1422 RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
1423 //\r
1424 // Set the return value for Supported and Attributes\r
1425 //\r
1426 if (Supported != NULL) {\r
1427 *Supported = RootBridge->Supports;\r
1428 }\r
1429\r
1430 if (Attributes != NULL) {\r
1431 *Attributes = RootBridge->Attributes;\r
1432 }\r
1433\r
1434 return EFI_SUCCESS;\r
1435}\r
1436\r
1437/**\r
1438 Sets attributes for a resource range on a PCI root bridge.\r
1439\r
1440 The SetAttributes() function sets the attributes specified in Attributes for\r
1441 the PCI root bridge on the resource range specified by ResourceBase and\r
1442 ResourceLength. Since the granularity of setting these attributes may vary\r
1443 from resource type to resource type, and from platform to platform, the\r
1444 actual resource range and the one passed in by the caller may differ. As a\r
1445 result, this function may set the attributes specified by Attributes on a\r
1446 larger resource range than the caller requested. The actual range is returned\r
1447 in ResourceBase and ResourceLength. The caller is responsible for verifying\r
1448 that the actual range for which the attributes were set is acceptable.\r
1449\r
1450 @param This A pointer to the\r
1451 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
1452 @param Attributes The mask of attributes to set. If the\r
1453 attribute bit MEMORY_WRITE_COMBINE,\r
1454 MEMORY_CACHED, or MEMORY_DISABLE is set,\r
1455 then the resource range is specified by\r
1456 ResourceBase and ResourceLength. If\r
1457 MEMORY_WRITE_COMBINE, MEMORY_CACHED, and\r
1458 MEMORY_DISABLE are not set, then\r
1459 ResourceBase and ResourceLength are ignored,\r
1460 and may be NULL.\r
1461 @param ResourceBase A pointer to the base address of the\r
1462 resource range to be modified by the\r
1463 attributes specified by Attributes.\r
1464 @param ResourceLength A pointer to the length of the resource\r
1465 range to be modified by the attributes\r
1466 specified by Attributes.\r
1467\r
1468 @retval EFI_SUCCESS The current configuration of this PCI root bridge\r
1469 was returned in Resources.\r
1470 @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge\r
1471 could not be retrieved.\r
1472**/\r
1473EFI_STATUS\r
1474EFIAPI\r
1475RootBridgeIoSetAttributes (\r
1476 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
1477 IN UINT64 Attributes,\r
1478 IN OUT UINT64 *ResourceBase,\r
1479 IN OUT UINT64 *ResourceLength\r
1480 )\r
1481{\r
1482 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
1483\r
1484 RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
1485\r
1486 if ((Attributes & (~RootBridge->Supports)) != 0) {\r
1487 return EFI_UNSUPPORTED;\r
1488 }\r
1489\r
1490 RootBridge->Attributes = Attributes;\r
1491 return EFI_SUCCESS;\r
1492}\r
1493\r
1494/**\r
1495 Retrieves the current resource settings of this PCI root bridge in the form\r
1496 of a set of ACPI 2.0 resource descriptors.\r
1497\r
1498 There are only two resource descriptor types from the ACPI Specification that\r
1499 may be used to describe the current resources allocated to a PCI root bridge.\r
1500 These are the QWORD Address Space Descriptor (ACPI 2.0 Section 6.4.3.5.1),\r
1501 and the End Tag (ACPI 2.0 Section 6.4.2.8). The QWORD Address Space\r
1502 Descriptor can describe memory, I/O, and bus number ranges for dynamic or\r
1503 fixed resources. The configuration of a PCI root bridge is described with one\r
1504 or more QWORD Address Space Descriptors followed by an End Tag.\r
1505\r
1506 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
1507 @param[out] Resources A pointer to the ACPI 2.0 resource descriptors that\r
1508 describe the current configuration of this PCI root\r
1509 bridge. The storage for the ACPI 2.0 resource\r
1510 descriptors is allocated by this function. The\r
1511 caller must treat the return buffer as read-only\r
1512 data, and the buffer must not be freed by the\r
1513 caller.\r
1514\r
1515 @retval EFI_SUCCESS The current configuration of this PCI root bridge\r
1516 was returned in Resources.\r
1517 @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge\r
1518 could not be retrieved.\r
1519**/\r
1520EFI_STATUS\r
1521EFIAPI\r
1522RootBridgeIoConfiguration (\r
1523 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
1524 OUT VOID **Resources\r
1525 )\r
1526{\r
1527 PCI_RESOURCE_TYPE Index;\r
1528 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
1529 PCI_RES_NODE *ResAllocNode;\r
1530 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
1531 EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
1532\r
1533 //\r
1534 // Get this instance of the Root Bridge.\r
1535 //\r
1536 RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
1537 ZeroMem (\r
1538 RootBridge->ConfigBuffer,\r
1539 TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
1540 );\r
1541 Descriptor = RootBridge->ConfigBuffer;\r
1542 for (Index = TypeIo; Index < TypeMax; Index++) {\r
1543\r
1544 ResAllocNode = &RootBridge->ResAllocNode[Index];\r
1545\r
1546 if (ResAllocNode->Status != ResAllocated) {\r
1547 continue;\r
1548 }\r
1549\r
1550 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1551 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1552 Descriptor->AddrRangeMin = ResAllocNode->Base;\r
1553 Descriptor->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;\r
1554 Descriptor->AddrLen = ResAllocNode->Length;\r
1555 switch (ResAllocNode->Type) {\r
1556\r
1557 case TypeIo:\r
1558 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
1559 break;\r
1560\r
1561 case TypePMem32:\r
1562 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
1563 case TypeMem32:\r
1564 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1565 Descriptor->AddrSpaceGranularity = 32;\r
1566 break;\r
1567\r
1568 case TypePMem64:\r
1569 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
1570 case TypeMem64:\r
1571 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1572 Descriptor->AddrSpaceGranularity = 64;\r
1573 break;\r
1574\r
1575 case TypeBus:\r
1576 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
1577 break;\r
1578\r
1579 default:\r
1580 break;\r
1581 }\r
1582\r
1583 Descriptor++;\r
1584 }\r
1585 //\r
1586 // Terminate the entries.\r
1587 //\r
1588 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;\r
1589 End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
1590 End->Checksum = 0x0;\r
1591\r
1592 *Resources = RootBridge->ConfigBuffer;\r
1593 return EFI_SUCCESS;\r
1594}\r