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