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