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