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