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