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