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