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