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