]> git.proxmox.com Git - mirror_edk2.git/blame - CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeIo.c
IntelFsp2Pkg/Tools: Add BSF bit field support in GenCfgOpt tool
[mirror_edk2.git] / CorebootModulePkg / PciRootBridgeNoEnumerationDxe / PcatPciRootBridgeIo.c
CommitLineData
81a23a0f
LL
1/*++
2
3Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
4This program and the accompanying materials
5are licensed and made available under the terms and conditions of the BSD License
6which accompanies this distribution. The full text of the license may be found at
7http://opensource.org/licenses/bsd-license.php
8
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12Module Name:
13 PcatPciRootBridgeIo.c
14
15Abstract:
16
17 EFI PC AT PCI Root Bridge Io Protocol
18
19Revision History
20
21--*/
22
23#include "PcatPciRootBridge.h"
24
25//
26// Protocol Member Function Prototypes
27//
28EFI_STATUS
29EFIAPI
30PcatRootBridgeIoPollMem (
31 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
32 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
33 IN UINT64 Address,
34 IN UINT64 Mask,
35 IN UINT64 Value,
36 IN UINT64 Delay,
37 OUT UINT64 *Result
38 );
39
40EFI_STATUS
41EFIAPI
42PcatRootBridgeIoPollIo (
43 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
44 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
45 IN UINT64 Address,
46 IN UINT64 Mask,
47 IN UINT64 Value,
48 IN UINT64 Delay,
49 OUT UINT64 *Result
50 );
51
52EFI_STATUS
53EFIAPI
54PcatRootBridgeIoMemRead (
55 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
56 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
57 IN UINT64 Address,
58 IN UINTN Count,
59 IN OUT VOID *Buffer
60 );
61
62EFI_STATUS
63EFIAPI
64PcatRootBridgeIoMemWrite (
65 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
66 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
67 IN UINT64 Address,
68 IN UINTN Count,
69 IN OUT VOID *Buffer
70 );
71
72EFI_STATUS
73EFIAPI
74PcatRootBridgeIoCopyMem (
75 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
76 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
77 IN UINT64 DestAddress,
78 IN UINT64 SrcAddress,
79 IN UINTN Count
80 );
81
82EFI_STATUS
83EFIAPI
84PcatRootBridgeIoPciRead (
85 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
86 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
87 IN UINT64 Address,
88 IN UINTN Count,
89 IN OUT VOID *Buffer
90 );
91
92EFI_STATUS
93EFIAPI
94PcatRootBridgeIoPciWrite (
95 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
96 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
97 IN UINT64 Address,
98 IN UINTN Count,
99 IN OUT VOID *Buffer
100 );
101
102EFI_STATUS
103EFIAPI
104PcatRootBridgeIoMap (
105 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
106 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
107 IN VOID *HostAddress,
108 IN OUT UINTN *NumberOfBytes,
109 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
110 OUT VOID **Mapping
111 );
112
113EFI_STATUS
114EFIAPI
115PcatRootBridgeIoUnmap (
116 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
117 IN VOID *Mapping
118 );
119
120EFI_STATUS
121EFIAPI
122PcatRootBridgeIoAllocateBuffer (
123 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
124 IN EFI_ALLOCATE_TYPE Type,
125 IN EFI_MEMORY_TYPE MemoryType,
126 IN UINTN Pages,
127 OUT VOID **HostAddress,
128 IN UINT64 Attributes
129 );
130
131EFI_STATUS
132EFIAPI
133PcatRootBridgeIoFreeBuffer (
134 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
135 IN UINTN Pages,
136 OUT VOID *HostAddress
137 );
138
139EFI_STATUS
140EFIAPI
141PcatRootBridgeIoFlush (
142 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
143 );
144
145EFI_STATUS
146EFIAPI
147PcatRootBridgeIoGetAttributes (
148 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
149 OUT UINT64 *Supported,
150 OUT UINT64 *Attributes
151 );
152
153EFI_STATUS
154EFIAPI
155PcatRootBridgeIoSetAttributes (
156 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
157 IN UINT64 Attributes,
158 IN OUT UINT64 *ResourceBase,
159 IN OUT UINT64 *ResourceLength
160 );
161
162EFI_STATUS
163EFIAPI
164PcatRootBridgeIoConfiguration (
165 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
166 OUT VOID **Resources
167 );
168
169//
170// Private Function Prototypes
171//
172EFI_STATUS
173EFIAPI
174PcatRootBridgeIoMemRW (
175 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
176 IN UINTN Count,
177 IN BOOLEAN InStrideFlag,
178 IN PTR In,
179 IN BOOLEAN OutStrideFlag,
180 OUT PTR Out
181 );
182
183EFI_STATUS
184PcatRootBridgeIoConstructor (
185 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
186 IN UINTN SegmentNumber
187 )
188/*++
189
190Routine Description:
191
192 Contruct the Pci Root Bridge Io protocol
193
194Arguments:
195
196 Protocol - protocol to initialize
197
198Returns:
199
200 None
201
202--*/
203{
204 Protocol->ParentHandle = NULL;
205
206 Protocol->PollMem = PcatRootBridgeIoPollMem;
207 Protocol->PollIo = PcatRootBridgeIoPollIo;
208
209 Protocol->Mem.Read = PcatRootBridgeIoMemRead;
210 Protocol->Mem.Write = PcatRootBridgeIoMemWrite;
211
212 Protocol->Io.Read = PcatRootBridgeIoIoRead;
213 Protocol->Io.Write = PcatRootBridgeIoIoWrite;
214
215 Protocol->CopyMem = PcatRootBridgeIoCopyMem;
216
217 Protocol->Pci.Read = PcatRootBridgeIoPciRead;
218 Protocol->Pci.Write = PcatRootBridgeIoPciWrite;
219
220 Protocol->Map = PcatRootBridgeIoMap;
221 Protocol->Unmap = PcatRootBridgeIoUnmap;
222
223 Protocol->AllocateBuffer = PcatRootBridgeIoAllocateBuffer;
224 Protocol->FreeBuffer = PcatRootBridgeIoFreeBuffer;
225
226 Protocol->Flush = PcatRootBridgeIoFlush;
227
228 Protocol->GetAttributes = PcatRootBridgeIoGetAttributes;
229 Protocol->SetAttributes = PcatRootBridgeIoSetAttributes;
230
231 Protocol->Configuration = PcatRootBridgeIoConfiguration;
232
233 Protocol->SegmentNumber = (UINT32)SegmentNumber;
234
235 return EFI_SUCCESS;
236}
237
238EFI_STATUS
239EFIAPI
240PcatRootBridgeIoPollMem (
241 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
242 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
243 IN UINT64 Address,
244 IN UINT64 Mask,
245 IN UINT64 Value,
246 IN UINT64 Delay,
247 OUT UINT64 *Result
248 )
249{
250 EFI_STATUS Status;
251 UINT64 NumberOfTicks;
252 UINT32 Remainder;
253
254 if (Result == NULL) {
255 return EFI_INVALID_PARAMETER;
256 }
257
258
259 if ((UINT32)Width > EfiPciWidthUint64) {
260 return EFI_INVALID_PARAMETER;
261 }
262 //
263 // No matter what, always do a single poll.
264 //
265 Status = This->Mem.Read (This, Width, Address, 1, Result);
266 if ( EFI_ERROR(Status) ) {
267 return Status;
268 }
269 if ( (*Result & Mask) == Value ) {
270 return EFI_SUCCESS;
271 }
272
273 if (Delay == 0) {
274 return EFI_SUCCESS;
275 } else {
276
277 NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder);
278 if ( Remainder !=0 ) {
279 NumberOfTicks += 1;
280 }
281 NumberOfTicks += 1;
282
283 while ( NumberOfTicks ) {
284
285 gBS->Stall (10);
286
287 Status = This->Mem.Read (This, Width, Address, 1, Result);
288 if ( EFI_ERROR(Status) ) {
289 return Status;
290 }
291
292 if ( (*Result & Mask) == Value ) {
293 return EFI_SUCCESS;
294 }
295
296 NumberOfTicks -= 1;
297 }
298 }
299 return EFI_TIMEOUT;
300}
301
302EFI_STATUS
303EFIAPI
304PcatRootBridgeIoPollIo (
305 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
306 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
307 IN UINT64 Address,
308 IN UINT64 Mask,
309 IN UINT64 Value,
310 IN UINT64 Delay,
311 OUT UINT64 *Result
312 )
313{
314 EFI_STATUS Status;
315 UINT64 NumberOfTicks;
316 UINT32 Remainder;
317
318 if (Result == NULL) {
319 return EFI_INVALID_PARAMETER;
320 }
321
322 if ((UINT32)Width > EfiPciWidthUint64) {
323 return EFI_INVALID_PARAMETER;
324 }
325 //
326 // No matter what, always do a single poll.
327 //
328 Status = This->Io.Read (This, Width, Address, 1, Result);
329 if ( EFI_ERROR(Status) ) {
330 return Status;
331 }
332 if ( (*Result & Mask) == Value ) {
333 return EFI_SUCCESS;
334 }
335
336 if (Delay == 0) {
337 return EFI_SUCCESS;
338 } else {
339
340 NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder);
341 if ( Remainder !=0 ) {
342 NumberOfTicks += 1;
343 }
344 NumberOfTicks += 1;
345
346 while ( NumberOfTicks ) {
347
348 gBS->Stall(10);
349
350 Status = This->Io.Read (This, Width, Address, 1, Result);
351 if ( EFI_ERROR(Status) ) {
352 return Status;
353 }
354
355 if ( (*Result & Mask) == Value ) {
356 return EFI_SUCCESS;
357 }
358
359 NumberOfTicks -= 1;
360 }
361 }
362 return EFI_TIMEOUT;
363}
364
365BOOLEAN
366PcatRootBridgeMemAddressValid (
367 IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
368 IN UINT64 Address
369 )
370{
371 if ((Address >= PrivateData->PciExpressBaseAddress) && (Address < PrivateData->PciExpressBaseAddress + 0x10000000)) {
372 return TRUE;
373 }
374 if ((Address >= PrivateData->MemBase) && (Address < PrivateData->MemLimit)) {
375 return TRUE;
376 }
377
378 return FALSE;
379}
380
381EFI_STATUS
382EFIAPI
383PcatRootBridgeIoMemRead (
384 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
385 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
386 IN UINT64 Address,
387 IN UINTN Count,
388 IN OUT VOID *Buffer
389 )
390{
391 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
392 UINTN AlignMask;
393 PTR In;
394 PTR Out;
395
396 if ( Buffer == NULL ) {
397 return EFI_INVALID_PARAMETER;
398 }
399
400 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
401
402 if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {
403 return EFI_INVALID_PARAMETER;
404 }
405
406 AlignMask = (1 << (Width & 0x03)) - 1;
407 if (Address & AlignMask) {
408 return EFI_INVALID_PARAMETER;
409 }
410
411 Address += PrivateData->PhysicalMemoryBase;
412
413 In.buf = Buffer;
414 Out.buf = (VOID *)(UINTN) Address;
415 if ((UINT32)Width <= EfiPciWidthUint64) {
416 return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
417 }
418 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
419 return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
420 }
421 if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
422 return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
423 }
424
425 return EFI_INVALID_PARAMETER;
426}
427
428EFI_STATUS
429EFIAPI
430PcatRootBridgeIoMemWrite (
431 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
432 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
433 IN UINT64 Address,
434 IN UINTN Count,
435 IN OUT VOID *Buffer
436 )
437{
438 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
439 UINTN AlignMask;
440 PTR In;
441 PTR Out;
442
443 if ( Buffer == NULL ) {
444 return EFI_INVALID_PARAMETER;
445 }
446
447 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
448
449 if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {
450 return EFI_INVALID_PARAMETER;
451 }
452
453 AlignMask = (1 << (Width & 0x03)) - 1;
454 if (Address & AlignMask) {
455 return EFI_INVALID_PARAMETER;
456 }
457
458 Address += PrivateData->PhysicalMemoryBase;
459
460 In.buf = (VOID *)(UINTN) Address;
461 Out.buf = Buffer;
462 if ((UINT32)Width <= EfiPciWidthUint64) {
463 return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
464 }
465 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
466 return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
467 }
468 if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
469 return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
470 }
471
472 return EFI_INVALID_PARAMETER;
473}
474
475EFI_STATUS
476EFIAPI
477PcatRootBridgeIoCopyMem (
478 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
479 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
480 IN UINT64 DestAddress,
481 IN UINT64 SrcAddress,
482 IN UINTN Count
483 )
484
485{
486 EFI_STATUS Status;
487 BOOLEAN Direction;
488 UINTN Stride;
489 UINTN Index;
490 UINT64 Result;
491
492 if ((UINT32)Width > EfiPciWidthUint64) {
493 return EFI_INVALID_PARAMETER;
494 }
495
496 if (DestAddress == SrcAddress) {
497 return EFI_SUCCESS;
498 }
499
500 Stride = (UINTN)1 << Width;
501
502 Direction = TRUE;
503 if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
504 Direction = FALSE;
505 SrcAddress = SrcAddress + (Count-1) * Stride;
506 DestAddress = DestAddress + (Count-1) * Stride;
507 }
508
509 for (Index = 0;Index < Count;Index++) {
510 Status = PcatRootBridgeIoMemRead (
511 This,
512 Width,
513 SrcAddress,
514 1,
515 &Result
516 );
517 if (EFI_ERROR (Status)) {
518 return Status;
519 }
520 Status = PcatRootBridgeIoMemWrite (
521 This,
522 Width,
523 DestAddress,
524 1,
525 &Result
526 );
527 if (EFI_ERROR (Status)) {
528 return Status;
529 }
530 if (Direction) {
531 SrcAddress += Stride;
532 DestAddress += Stride;
533 } else {
534 SrcAddress -= Stride;
535 DestAddress -= Stride;
536 }
537 }
538 return EFI_SUCCESS;
539}
540
541EFI_STATUS
542EFIAPI
543PcatRootBridgeIoPciRead (
544 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
545 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
546 IN UINT64 Address,
547 IN UINTN Count,
548 IN OUT VOID *Buffer
549 )
550{
551 if (Buffer == NULL) {
552 return EFI_INVALID_PARAMETER;
553 }
554
555 return PcatRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
556}
557
558EFI_STATUS
559EFIAPI
560PcatRootBridgeIoPciWrite (
561 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
562 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
563 IN UINT64 Address,
564 IN UINTN Count,
565 IN OUT VOID *Buffer
566 )
567{
568 if (Buffer == NULL) {
569 return EFI_INVALID_PARAMETER;
570 }
571
572 return PcatRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
573}
574
575EFI_STATUS
576EFIAPI
577PcatRootBridgeIoMap (
578 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
579 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
580 IN VOID *HostAddress,
581 IN OUT UINTN *NumberOfBytes,
582 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
583 OUT VOID **Mapping
584 )
585
586{
587 EFI_STATUS Status;
588 EFI_PHYSICAL_ADDRESS PhysicalAddress;
589 MAP_INFO *MapInfo;
590 MAP_INFO_INSTANCE *MapInstance;
591 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
592
593 if ( HostAddress == NULL || NumberOfBytes == NULL ||
594 DeviceAddress == NULL || Mapping == NULL ) {
595
596 return EFI_INVALID_PARAMETER;
597 }
598
599 //
600 // Perform a fence operation to make sure all memory operations are flushed
601 //
602 MemoryFence();
603
604 //
605 // Initialize the return values to their defaults
606 //
607 *Mapping = NULL;
608
609 //
610 // Make sure that Operation is valid
611 //
612 if ((UINT32)Operation >= EfiPciOperationMaximum) {
613 return EFI_INVALID_PARAMETER;
614 }
615
616 //
617 // Most PCAT like chipsets can not handle performing DMA above 4GB.
618 // If any part of the DMA transfer being mapped is above 4GB, then
619 // map the DMA transfer to a buffer below 4GB.
620 //
621 PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
622 if ((PhysicalAddress + *NumberOfBytes) > 0x100000000ULL) {
623
624 //
625 // Common Buffer operations can not be remapped. If the common buffer
626 // if above 4GB, then it is not possible to generate a mapping, so return
627 // an error.
628 //
629 if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
630 return EFI_UNSUPPORTED;
631 }
632
633 //
634 // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
635 // called later.
636 //
637 Status = gBS->AllocatePool (
638 EfiBootServicesData,
639 sizeof(MAP_INFO),
640 (VOID **)&MapInfo
641 );
642 if (EFI_ERROR (Status)) {
643 *NumberOfBytes = 0;
644 return Status;
645 }
646
647 //
648 // Return a pointer to the MAP_INFO structure in Mapping
649 //
650 *Mapping = MapInfo;
651
652 //
653 // Initialize the MAP_INFO structure
654 //
655 MapInfo->Operation = Operation;
656 MapInfo->NumberOfBytes = *NumberOfBytes;
657 MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES(*NumberOfBytes);
658 MapInfo->HostAddress = PhysicalAddress;
659 MapInfo->MappedHostAddress = 0x00000000ffffffff;
660
661 //
662 // Allocate a buffer below 4GB to map the transfer to.
663 //
664 Status = gBS->AllocatePages (
665 AllocateMaxAddress,
666 EfiBootServicesData,
667 MapInfo->NumberOfPages,
668 &MapInfo->MappedHostAddress
669 );
670 if (EFI_ERROR(Status)) {
671 gBS->FreePool (MapInfo);
672 *NumberOfBytes = 0;
673 return Status;
674 }
675
676 //
677 // If this is a read operation from the Bus Master's point of view,
678 // then copy the contents of the real buffer into the mapped buffer
679 // so the Bus Master can read the contents of the real buffer.
680 //
681 if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {
682 CopyMem (
683 (VOID *)(UINTN)MapInfo->MappedHostAddress,
684 (VOID *)(UINTN)MapInfo->HostAddress,
685 MapInfo->NumberOfBytes
686 );
687 }
688
689
690 Status =gBS->AllocatePool (
691 EfiBootServicesData,
692 sizeof(MAP_INFO_INSTANCE),
693 (VOID **)&MapInstance
694 );
695 if (EFI_ERROR(Status)) {
696 gBS->FreePages (MapInfo->MappedHostAddress,MapInfo->NumberOfPages);
697 gBS->FreePool (MapInfo);
698 *NumberOfBytes = 0;
699 return Status;
700 }
701
702 MapInstance->Map=MapInfo;
703 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
704 InsertTailList(&PrivateData->MapInfo,&MapInstance->Link);
705
706 //
707 // The DeviceAddress is the address of the maped buffer below 4GB
708 //
709 *DeviceAddress = MapInfo->MappedHostAddress;
710 } else {
711 //
712 // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress
713 //
714 *DeviceAddress = PhysicalAddress;
715 }
716
717 //
718 // Perform a fence operation to make sure all memory operations are flushed
719 //
720 MemoryFence();
721
722 return EFI_SUCCESS;
723}
724
725EFI_STATUS
726EFIAPI
727PcatRootBridgeIoUnmap (
728 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
729 IN VOID *Mapping
730 )
731
732{
733 MAP_INFO *MapInfo;
734 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
735 LIST_ENTRY *Link;
736
737 //
738 // Perform a fence operation to make sure all memory operations are flushed
739 //
740 MemoryFence();
741
742 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
743 //
744 // See if the Map() operation associated with this Unmap() required a mapping buffer.
745 // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
746 //
747 if (Mapping != NULL) {
748 //
749 // Get the MAP_INFO structure from Mapping
750 //
751 MapInfo = (MAP_INFO *)Mapping;
752
753 for (Link = PrivateData->MapInfo.ForwardLink; Link != &PrivateData->MapInfo; Link = Link->ForwardLink) {
754 if (((MAP_INFO_INSTANCE*)Link)->Map == MapInfo)
755 break;
756 }
757
758 if (Link == &PrivateData->MapInfo) {
759 return EFI_INVALID_PARAMETER;
760 }
761
762 RemoveEntryList(Link);
763 ((MAP_INFO_INSTANCE*)Link)->Map = NULL;
764 gBS->FreePool((MAP_INFO_INSTANCE*)Link);
765
766 //
767 // If this is a write operation from the Bus Master's point of view,
768 // then copy the contents of the mapped buffer into the real buffer
769 // so the processor can read the contents of the real buffer.
770 //
771 if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) {
772 CopyMem (
773 (VOID *)(UINTN)MapInfo->HostAddress,
774 (VOID *)(UINTN)MapInfo->MappedHostAddress,
775 MapInfo->NumberOfBytes
776 );
777 }
778
779 //
780 // Free the mapped buffer and the MAP_INFO structure.
781 //
782 gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
783 gBS->FreePool (Mapping);
784 }
785
786 //
787 // Perform a fence operation to make sure all memory operations are flushed
788 //
789 MemoryFence();
790
791 return EFI_SUCCESS;
792}
793
794EFI_STATUS
795EFIAPI
796PcatRootBridgeIoAllocateBuffer (
797 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
798 IN EFI_ALLOCATE_TYPE Type,
799 IN EFI_MEMORY_TYPE MemoryType,
800 IN UINTN Pages,
801 OUT VOID **HostAddress,
802 IN UINT64 Attributes
803 )
804{
805 EFI_STATUS Status;
806 EFI_PHYSICAL_ADDRESS PhysicalAddress;
807
808 //
809 // Validate Attributes
810 //
811 if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
812 return EFI_UNSUPPORTED;
813 }
814
815 //
816 // Check for invalid inputs
817 //
818 if (HostAddress == NULL) {
819 return EFI_INVALID_PARAMETER;
820 }
821
822 //
823 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
824 //
825 if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
826 return EFI_INVALID_PARAMETER;
827 }
828
829 //
830 // Limit allocations to memory below 4GB
831 //
832 PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(0xffffffff);
833
834 Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);
835 if (EFI_ERROR (Status)) {
836 return Status;
837 }
838
839 *HostAddress = (VOID *)(UINTN)PhysicalAddress;
840
841 return EFI_SUCCESS;
842}
843
844EFI_STATUS
845EFIAPI
846PcatRootBridgeIoFreeBuffer (
847 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
848 IN UINTN Pages,
849 OUT VOID *HostAddress
850 )
851
852{
853
854 if( HostAddress == NULL ){
855 return EFI_INVALID_PARAMETER;
856 }
857 return gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Pages);
858}
859
860EFI_STATUS
861EFIAPI
862PcatRootBridgeIoFlush (
863 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
864 )
865
866{
867 //
868 // Perform a fence operation to make sure all memory operations are flushed
869 //
870 MemoryFence();
871
872 return EFI_SUCCESS;
873}
874
875EFI_STATUS
876EFIAPI
877PcatRootBridgeIoGetAttributes (
878 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
879 OUT UINT64 *Supported, OPTIONAL
880 OUT UINT64 *Attributes
881 )
882
883{
884 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
885
886 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
887
888 if (Attributes == NULL && Supported == NULL) {
889 return EFI_INVALID_PARAMETER;
890 }
891
892 //
893 // Supported is an OPTIONAL parameter. See if it is NULL
894 //
895 if (Supported) {
896 //
897 // This is a generic driver for a PC-AT class system. It does not have any
898 // chipset specific knowlegde, so none of the attributes can be set or
899 // cleared. Any attempt to set attribute that are already set will succeed,
900 // and any attempt to set an attribute that is not supported will fail.
901 //
902 *Supported = PrivateData->Attributes;
903 }
904
905 //
906 // Set Attrbutes to the attributes detected when the PCI Root Bridge was initialized
907 //
908
909 if (Attributes) {
910 *Attributes = PrivateData->Attributes;
911 }
912
913
914 return EFI_SUCCESS;
915}
916
917EFI_STATUS
918EFIAPI
919PcatRootBridgeIoSetAttributes (
920 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
921 IN UINT64 Attributes,
922 IN OUT UINT64 *ResourceBase,
923 IN OUT UINT64 *ResourceLength
924 )
925
926{
927 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
928
929 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
930
931 //
932 // This is a generic driver for a PC-AT class system. It does not have any
933 // chipset specific knowlegde, so none of the attributes can be set or
934 // cleared. Any attempt to set attribute that are already set will succeed,
935 // and any attempt to set an attribute that is not supported will fail.
936 //
937 if (Attributes & (~PrivateData->Attributes)) {
938 return EFI_UNSUPPORTED;
939 }
940
941 return EFI_SUCCESS;
942}
943
944EFI_STATUS
945EFIAPI
946PcatRootBridgeIoConfiguration (
947 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
948 OUT VOID **Resources
949 )
950
951{
952 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
953
954 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
955
956 *Resources = PrivateData->Configuration;
957
958 return EFI_SUCCESS;
959}
960
961//
962// Internal function
963//
964
965EFI_STATUS
966EFIAPI
967PcatRootBridgeIoMemRW (
968 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
969 IN UINTN Count,
970 IN BOOLEAN InStrideFlag,
971 IN PTR In,
972 IN BOOLEAN OutStrideFlag,
973 OUT PTR Out
974 )
975/*++
976
977Routine Description:
978
979 Private service to provide the memory read/write
980
981Arguments:
982
983 Width of the Memory Access
984 Count of the number of accesses to perform
985
986Returns:
987
988 Status
989
990 EFI_SUCCESS - Successful transaction
991 EFI_INVALID_PARAMETER - Unsupported width and address combination
992
993--*/
994{
995 UINTN Stride;
996 UINTN InStride;
997 UINTN OutStride;
998
999
1000 Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
1001 Stride = (UINTN)1 << Width;
1002 InStride = InStrideFlag ? Stride : 0;
1003 OutStride = OutStrideFlag ? Stride : 0;
1004
1005 //
1006 // Loop for each iteration and move the data
1007 //
1008 switch (Width) {
1009 case EfiPciWidthUint8:
1010 for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
1011 MemoryFence();
1012 *In.ui8 = *Out.ui8;
1013 MemoryFence();
1014 }
1015 break;
1016 case EfiPciWidthUint16:
1017 for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
1018 MemoryFence();
1019 *In.ui16 = *Out.ui16;
1020 MemoryFence();
1021 }
1022 break;
1023 case EfiPciWidthUint32:
1024 for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
1025 MemoryFence();
1026 *In.ui32 = *Out.ui32;
1027 MemoryFence();
1028 }
1029 break;
1030 default:
1031 return EFI_INVALID_PARAMETER;
1032 }
1033
1034 return EFI_SUCCESS;
1035}
1036