]> git.proxmox.com Git - mirror_edk2.git/blob - DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeIo.c
ed2aea7dc0053803c70ca5c82e9b0f239dbb0a41
[mirror_edk2.git] / DuetPkg / PciRootBridgeNoEnumerationDxe / PcatPciRootBridgeIo.c
1 /*++
2
3 Copyright (c) 2005 - 2007, 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
295 NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder);
296 if ( Remainder !=0 ) {
297 NumberOfTicks += 1;
298 }
299 NumberOfTicks += 1;
300
301 while ( NumberOfTicks ) {
302
303 gBS->Stall (10);
304
305 Status = This->Mem.Read (This, Width, Address, 1, Result);
306 if ( EFI_ERROR(Status) ) {
307 return Status;
308 }
309
310 if ( (*Result & Mask) == Value ) {
311 return EFI_SUCCESS;
312 }
313
314 NumberOfTicks -= 1;
315 }
316 }
317 return EFI_TIMEOUT;
318 }
319
320 EFI_STATUS
321 EFIAPI
322 PcatRootBridgeIoPollIo (
323 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
324 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
325 IN UINT64 Address,
326 IN UINT64 Mask,
327 IN UINT64 Value,
328 IN UINT64 Delay,
329 OUT UINT64 *Result
330 )
331 {
332 EFI_STATUS Status;
333 UINT64 NumberOfTicks;
334 UINT32 Remainder;
335
336 if (Result == NULL) {
337 return EFI_INVALID_PARAMETER;
338 }
339
340 if (Width < 0 || Width > EfiPciWidthUint64) {
341 return EFI_INVALID_PARAMETER;
342 }
343 //
344 // No matter what, always do a single poll.
345 //
346 Status = This->Io.Read (This, Width, Address, 1, Result);
347 if ( EFI_ERROR(Status) ) {
348 return Status;
349 }
350 if ( (*Result & Mask) == Value ) {
351 return EFI_SUCCESS;
352 }
353
354 if (Delay != 0) {
355
356 NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder);
357 if ( Remainder !=0 ) {
358 NumberOfTicks += 1;
359 }
360 NumberOfTicks += 1;
361
362 while ( NumberOfTicks ) {
363
364 gBS->Stall(10);
365
366 Status = This->Io.Read (This, Width, Address, 1, Result);
367 if ( EFI_ERROR(Status) ) {
368 return Status;
369 }
370
371 if ( (*Result & Mask) == Value ) {
372 return EFI_SUCCESS;
373 }
374
375 NumberOfTicks -= 1;
376 }
377 }
378 return EFI_TIMEOUT;
379 }
380
381 BOOLEAN
382 PcatRootBridgeMemAddressValid (
383 IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
384 IN UINT64 Address
385 )
386 {
387 if ((Address >= PrivateData->PciExpressBaseAddress) && (Address < PrivateData->PciExpressBaseAddress + 0x10000000)) {
388 return TRUE;
389 }
390 if ((Address >= PrivateData->MemBase) && (Address < PrivateData->MemLimit)) {
391 return TRUE;
392 }
393
394 return FALSE;
395 }
396
397 EFI_STATUS
398 EFIAPI
399 PcatRootBridgeIoMemRead (
400 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
401 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
402 IN UINT64 Address,
403 IN UINTN Count,
404 IN OUT VOID *Buffer
405 )
406 {
407 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
408 UINTN AlignMask;
409 PTR In;
410 PTR Out;
411
412 if ( Buffer == NULL ) {
413 return EFI_INVALID_PARAMETER;
414 }
415
416 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
417
418 if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {
419 return EFI_INVALID_PARAMETER;
420 }
421
422 AlignMask = (1 << (Width & 0x03)) - 1;
423 if (Address & AlignMask) {
424 return EFI_INVALID_PARAMETER;
425 }
426
427 Address += PrivateData->PhysicalMemoryBase;
428
429 In.buf = Buffer;
430 Out.buf = (VOID *)(UINTN) Address;
431 if (Width >= EfiPciWidthUint8 && Width <= EfiPciWidthUint64) {
432 return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
433 }
434 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
435 return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
436 }
437 if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
438 return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
439 }
440
441 return EFI_INVALID_PARAMETER;
442 }
443
444 EFI_STATUS
445 EFIAPI
446 PcatRootBridgeIoMemWrite (
447 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
448 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
449 IN UINT64 Address,
450 IN UINTN Count,
451 IN OUT VOID *Buffer
452 )
453 {
454 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
455 UINTN AlignMask;
456 PTR In;
457 PTR Out;
458
459 if ( Buffer == NULL ) {
460 return EFI_INVALID_PARAMETER;
461 }
462
463 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
464
465 if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {
466 return EFI_INVALID_PARAMETER;
467 }
468
469 AlignMask = (1 << (Width & 0x03)) - 1;
470 if (Address & AlignMask) {
471 return EFI_INVALID_PARAMETER;
472 }
473
474 Address += PrivateData->PhysicalMemoryBase;
475
476 In.buf = (VOID *)(UINTN) Address;
477 Out.buf = Buffer;
478 if (Width >= EfiPciWidthUint8 && Width <= EfiPciWidthUint64) {
479 return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
480 }
481 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
482 return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
483 }
484 if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
485 return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
486 }
487
488 return EFI_INVALID_PARAMETER;
489 }
490
491 EFI_STATUS
492 EFIAPI
493 PcatRootBridgeIoCopyMem (
494 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
495 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
496 IN UINT64 DestAddress,
497 IN UINT64 SrcAddress,
498 IN UINTN Count
499 )
500
501 {
502 EFI_STATUS Status;
503 BOOLEAN Direction;
504 UINTN Stride;
505 UINTN Index;
506 UINT64 Result;
507
508 if (Width < 0 || Width > EfiPciWidthUint64) {
509 return EFI_INVALID_PARAMETER;
510 }
511
512 if (DestAddress == SrcAddress) {
513 return EFI_SUCCESS;
514 }
515
516 Stride = (UINTN)1 << Width;
517
518 Direction = TRUE;
519 if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
520 Direction = FALSE;
521 SrcAddress = SrcAddress + (Count-1) * Stride;
522 DestAddress = DestAddress + (Count-1) * Stride;
523 }
524
525 for (Index = 0;Index < Count;Index++) {
526 Status = PcatRootBridgeIoMemRead (
527 This,
528 Width,
529 SrcAddress,
530 1,
531 &Result
532 );
533 if (EFI_ERROR (Status)) {
534 return Status;
535 }
536 Status = PcatRootBridgeIoMemWrite (
537 This,
538 Width,
539 DestAddress,
540 1,
541 &Result
542 );
543 if (EFI_ERROR (Status)) {
544 return Status;
545 }
546 if (Direction) {
547 SrcAddress += Stride;
548 DestAddress += Stride;
549 } else {
550 SrcAddress -= Stride;
551 DestAddress -= Stride;
552 }
553 }
554 return EFI_SUCCESS;
555 }
556
557 EFI_STATUS
558 EFIAPI
559 PcatRootBridgeIoPciRead (
560 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
561 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
562 IN UINT64 Address,
563 IN UINTN Count,
564 IN OUT VOID *Buffer
565 )
566 {
567 if (Buffer == NULL) {
568 return EFI_INVALID_PARAMETER;
569 }
570
571 return PcatRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
572 }
573
574 EFI_STATUS
575 EFIAPI
576 PcatRootBridgeIoPciWrite (
577 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
578 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
579 IN UINT64 Address,
580 IN UINTN Count,
581 IN OUT VOID *Buffer
582 )
583 {
584 if (Buffer == NULL) {
585 return EFI_INVALID_PARAMETER;
586 }
587
588 return PcatRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
589 }
590
591 EFI_STATUS
592 EFIAPI
593 PcatRootBridgeIoMap (
594 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
595 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
596 IN VOID *HostAddress,
597 IN OUT UINTN *NumberOfBytes,
598 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
599 OUT VOID **Mapping
600 )
601
602 {
603 EFI_STATUS Status;
604 EFI_PHYSICAL_ADDRESS PhysicalAddress;
605 MAP_INFO *MapInfo;
606 MAP_INFO_INSTANCE *MapInstance;
607 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
608
609 if ( HostAddress == NULL || NumberOfBytes == NULL ||
610 DeviceAddress == NULL || Mapping == NULL ) {
611
612 return EFI_INVALID_PARAMETER;
613 }
614
615 //
616 // Perform a fence operation to make sure all memory operations are flushed
617 //
618 MemoryFence();
619
620 //
621 // Initialize the return values to their defaults
622 //
623 *Mapping = NULL;
624
625 //
626 // Make sure that Operation is valid
627 //
628 if (Operation < 0 || Operation >= EfiPciOperationMaximum) {
629 return EFI_INVALID_PARAMETER;
630 }
631
632 //
633 // Most PCAT like chipsets can not handle performing DMA above 4GB.
634 // If any part of the DMA transfer being mapped is above 4GB, then
635 // map the DMA transfer to a buffer below 4GB.
636 //
637 PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
638 if ((PhysicalAddress + *NumberOfBytes) > 0x100000000) {
639
640 //
641 // Common Buffer operations can not be remapped. If the common buffer
642 // if above 4GB, then it is not possible to generate a mapping, so return
643 // an error.
644 //
645 if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
646 return EFI_UNSUPPORTED;
647 }
648
649 //
650 // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
651 // called later.
652 //
653 Status = gBS->AllocatePool (
654 EfiBootServicesData,
655 sizeof(MAP_INFO),
656 &MapInfo
657 );
658 if (EFI_ERROR (Status)) {
659 *NumberOfBytes = 0;
660 return Status;
661 }
662
663 //
664 // Return a pointer to the MAP_INFO structure in Mapping
665 //
666 *Mapping = MapInfo;
667
668 //
669 // Initialize the MAP_INFO structure
670 //
671 MapInfo->Operation = Operation;
672 MapInfo->NumberOfBytes = *NumberOfBytes;
673 MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES(*NumberOfBytes);
674 MapInfo->HostAddress = PhysicalAddress;
675 MapInfo->MappedHostAddress = 0x00000000ffffffff;
676
677 //
678 // Allocate a buffer below 4GB to map the transfer to.
679 //
680 Status = gBS->AllocatePages (
681 AllocateMaxAddress,
682 EfiBootServicesData,
683 MapInfo->NumberOfPages,
684 &MapInfo->MappedHostAddress
685 );
686 if (EFI_ERROR(Status)) {
687 gBS->FreePool (MapInfo);
688 *NumberOfBytes = 0;
689 return Status;
690 }
691
692 //
693 // If this is a read operation from the Bus Master's point of view,
694 // then copy the contents of the real buffer into the mapped buffer
695 // so the Bus Master can read the contents of the real buffer.
696 //
697 if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {
698 CopyMem (
699 (VOID *)(UINTN)MapInfo->MappedHostAddress,
700 (VOID *)(UINTN)MapInfo->HostAddress,
701 MapInfo->NumberOfBytes
702 );
703 }
704
705
706 Status =gBS->AllocatePool (
707 EfiBootServicesData,
708 sizeof(MAP_INFO_INSTANCE),
709 &MapInstance
710 );
711 if (EFI_ERROR(Status)) {
712 gBS->FreePages (MapInfo->MappedHostAddress,MapInfo->NumberOfPages);
713 gBS->FreePool (MapInfo);
714 *NumberOfBytes = 0;
715 return Status;
716 }
717
718 MapInstance->Map=MapInfo;
719 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
720 InsertTailList(&PrivateData->MapInfo,&MapInstance->Link);
721
722 //
723 // The DeviceAddress is the address of the maped buffer below 4GB
724 //
725 *DeviceAddress = MapInfo->MappedHostAddress;
726 } else {
727 //
728 // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress
729 //
730 *DeviceAddress = PhysicalAddress;
731 }
732
733 //
734 // Perform a fence operation to make sure all memory operations are flushed
735 //
736 MemoryFence();
737
738 return EFI_SUCCESS;
739 }
740
741 EFI_STATUS
742 EFIAPI
743 PcatRootBridgeIoUnmap (
744 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
745 IN VOID *Mapping
746 )
747
748 {
749 MAP_INFO *MapInfo;
750 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
751 LIST_ENTRY *Link;
752
753 //
754 // Perform a fence operation to make sure all memory operations are flushed
755 //
756 MemoryFence();
757
758 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
759 //
760 // See if the Map() operation associated with this Unmap() required a mapping buffer.
761 // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
762 //
763 if (Mapping != NULL) {
764 //
765 // Get the MAP_INFO structure from Mapping
766 //
767 MapInfo = (MAP_INFO *)Mapping;
768
769 for (Link = PrivateData->MapInfo.ForwardLink; Link != &PrivateData->MapInfo; Link = Link->ForwardLink) {
770 if (((MAP_INFO_INSTANCE*)Link)->Map == MapInfo)
771 break;
772 }
773
774 if (Link == &PrivateData->MapInfo) {
775 return EFI_INVALID_PARAMETER;
776 }
777
778 RemoveEntryList(Link);
779 ((MAP_INFO_INSTANCE*)Link)->Map = NULL;
780 gBS->FreePool((MAP_INFO_INSTANCE*)Link);
781
782 //
783 // If this is a write operation from the Bus Master's point of view,
784 // then copy the contents of the mapped buffer into the real buffer
785 // so the processor can read the contents of the real buffer.
786 //
787 if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) {
788 CopyMem (
789 (VOID *)(UINTN)MapInfo->HostAddress,
790 (VOID *)(UINTN)MapInfo->MappedHostAddress,
791 MapInfo->NumberOfBytes
792 );
793 }
794
795 //
796 // Free the mapped buffer and the MAP_INFO structure.
797 //
798 gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
799 gBS->FreePool (Mapping);
800 }
801
802 //
803 // Perform a fence operation to make sure all memory operations are flushed
804 //
805 MemoryFence();
806
807 return EFI_SUCCESS;
808 }
809
810 EFI_STATUS
811 EFIAPI
812 PcatRootBridgeIoAllocateBuffer (
813 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
814 IN EFI_ALLOCATE_TYPE Type,
815 IN EFI_MEMORY_TYPE MemoryType,
816 IN UINTN Pages,
817 OUT VOID **HostAddress,
818 IN UINT64 Attributes
819 )
820 {
821 EFI_STATUS Status;
822 EFI_PHYSICAL_ADDRESS PhysicalAddress;
823
824 //
825 // Validate Attributes
826 //
827 if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
828 return EFI_UNSUPPORTED;
829 }
830
831 //
832 // Check for invalid inputs
833 //
834 if (HostAddress == NULL) {
835 return EFI_INVALID_PARAMETER;
836 }
837
838 //
839 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
840 //
841 if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
842 return EFI_INVALID_PARAMETER;
843 }
844
845 //
846 // Limit allocations to memory below 4GB
847 //
848 PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(0xffffffff);
849
850 Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);
851 if (EFI_ERROR (Status)) {
852 return Status;
853 }
854
855 *HostAddress = (VOID *)(UINTN)PhysicalAddress;
856
857 return EFI_SUCCESS;
858 }
859
860 EFI_STATUS
861 EFIAPI
862 PcatRootBridgeIoFreeBuffer (
863 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
864 IN UINTN Pages,
865 OUT VOID *HostAddress
866 )
867
868 {
869
870 if( HostAddress == NULL ){
871 return EFI_INVALID_PARAMETER;
872 }
873 return gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Pages);
874 }
875
876 EFI_STATUS
877 EFIAPI
878 PcatRootBridgeIoFlush (
879 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
880 )
881
882 {
883 //
884 // Perform a fence operation to make sure all memory operations are flushed
885 //
886 MemoryFence();
887
888 return EFI_SUCCESS;
889 }
890
891 EFI_STATUS
892 EFIAPI
893 PcatRootBridgeIoGetAttributes (
894 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
895 OUT UINT64 *Supported, OPTIONAL
896 OUT UINT64 *Attributes
897 )
898
899 {
900 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
901
902 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
903
904 if (Attributes == NULL && Supported == NULL) {
905 return EFI_INVALID_PARAMETER;
906 }
907
908 //
909 // Supported is an OPTIONAL parameter. See if it is NULL
910 //
911 if (Supported) {
912 //
913 // This is a generic driver for a PC-AT class system. It does not have any
914 // chipset specific knowlegde, so none of the attributes can be set or
915 // cleared. Any attempt to set attribute that are already set will succeed,
916 // and any attempt to set an attribute that is not supported will fail.
917 //
918 *Supported = PrivateData->Attributes;
919 }
920
921 //
922 // Set Attrbutes to the attributes detected when the PCI Root Bridge was initialized
923 //
924
925 if (Attributes) {
926 *Attributes = PrivateData->Attributes;
927 }
928
929
930 return EFI_SUCCESS;
931 }
932
933 EFI_STATUS
934 EFIAPI
935 PcatRootBridgeIoSetAttributes (
936 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
937 IN UINT64 Attributes,
938 IN OUT UINT64 *ResourceBase,
939 IN OUT UINT64 *ResourceLength
940 )
941
942 {
943 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
944
945 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
946
947 //
948 // This is a generic driver for a PC-AT class system. It does not have any
949 // chipset specific knowlegde, so none of the attributes can be set or
950 // cleared. Any attempt to set attribute that are already set will succeed,
951 // and any attempt to set an attribute that is not supported will fail.
952 //
953 if (Attributes & (~PrivateData->Attributes)) {
954 return EFI_UNSUPPORTED;
955 }
956
957 return EFI_SUCCESS;
958 }
959
960 EFI_STATUS
961 EFIAPI
962 PcatRootBridgeIoConfiguration (
963 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
964 OUT VOID **Resources
965 )
966
967 {
968 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
969
970 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
971
972 *Resources = PrivateData->Configuration;
973
974 return EFI_SUCCESS;
975 }
976
977 //
978 // Internal function
979 //
980
981 EFI_STATUS
982 EFIAPI
983 PcatRootBridgeIoMemRW (
984 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
985 IN UINTN Count,
986 IN BOOLEAN InStrideFlag,
987 IN PTR In,
988 IN BOOLEAN OutStrideFlag,
989 OUT PTR Out
990 )
991 /*++
992
993 Routine Description:
994
995 Private service to provide the memory read/write
996
997 Arguments:
998
999 Width of the Memory Access
1000 Count of the number of accesses to perform
1001
1002 Returns:
1003
1004 Status
1005
1006 EFI_SUCCESS - Successful transaction
1007 EFI_INVALID_PARAMETER - Unsupported width and address combination
1008
1009 --*/
1010 {
1011 UINTN Stride;
1012 UINTN InStride;
1013 UINTN OutStride;
1014
1015
1016 Width = Width & 0x03;
1017 Stride = (UINTN)1 << Width;
1018 InStride = InStrideFlag ? Stride : 0;
1019 OutStride = OutStrideFlag ? Stride : 0;
1020
1021 //
1022 // Loop for each iteration and move the data
1023 //
1024 switch (Width) {
1025 case EfiPciWidthUint8:
1026 for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
1027 MemoryFence();
1028 *In.ui8 = *Out.ui8;
1029 MemoryFence();
1030 }
1031 break;
1032 case EfiPciWidthUint16:
1033 for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
1034 MemoryFence();
1035 *In.ui16 = *Out.ui16;
1036 MemoryFence();
1037 }
1038 break;
1039 case EfiPciWidthUint32:
1040 for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
1041 MemoryFence();
1042 *In.ui32 = *Out.ui32;
1043 MemoryFence();
1044 }
1045 break;
1046 default:
1047 return EFI_INVALID_PARAMETER;
1048 }
1049
1050 return EFI_SUCCESS;
1051 }
1052