1 /*++
2
3 Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
4 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 PcatRootBridgeIoCopyMem (
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
82 EFI_STATUS
83 EFIAPI
84 PcatRootBridgeIoPciRead (
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
92 EFI_STATUS
93 EFIAPI
94 PcatRootBridgeIoPciWrite (
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
102 EFI_STATUS
103 EFIAPI
104 PcatRootBridgeIoMap (
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
113 EFI_STATUS
114 EFIAPI
115 PcatRootBridgeIoUnmap (
116 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
117 IN VOID *Mapping
118 );
119
120 EFI_STATUS
121 EFIAPI
122 PcatRootBridgeIoAllocateBuffer (
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
131 EFI_STATUS
132 EFIAPI
133 PcatRootBridgeIoFreeBuffer (
134 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
135 IN UINTN Pages,
136 OUT VOID *HostAddress
137 );
138
139 EFI_STATUS
140 EFIAPI
141 PcatRootBridgeIoFlush (
142 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
143 );
144
145 EFI_STATUS
146 EFIAPI
147 PcatRootBridgeIoGetAttributes (
148 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
149 OUT UINT64 *Supported,
150 OUT UINT64 *Attributes
151 );
152
153 EFI_STATUS
154 EFIAPI
155 PcatRootBridgeIoSetAttributes (
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
162 EFI_STATUS
163 EFIAPI
164 PcatRootBridgeIoConfiguration (
165 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
166 OUT VOID **Resources
167 );
168
169 //
170 // Private Function Prototypes
171 //
172 EFI_STATUS
173 EFIAPI
174 PcatRootBridgeIoMemRW (
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
183 EFI_STATUS
PcatRootBridgeIoConstructor(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * Protocol,IN UINTN SegmentNumber)184 PcatRootBridgeIoConstructor (
185 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
186 IN UINTN SegmentNumber
187 )
188 /*++
189
190 Routine Description:
191
192 Contruct the Pci Root Bridge Io protocol
193
194 Arguments:
195
196 Protocol - protocol to initialize
197
198 Returns:
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
238 EFI_STATUS
239 EFIAPI
PcatRootBridgeIoPollMem(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINT64 Mask,IN UINT64 Value,IN UINT64 Delay,OUT UINT64 * Result)240 PcatRootBridgeIoPollMem (
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
302 EFI_STATUS
303 EFIAPI
PcatRootBridgeIoPollIo(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINT64 Mask,IN UINT64 Value,IN UINT64 Delay,OUT UINT64 * Result)304 PcatRootBridgeIoPollIo (
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
365 BOOLEAN
PcatRootBridgeMemAddressValid(IN PCAT_PCI_ROOT_BRIDGE_INSTANCE * PrivateData,IN UINT64 Address)366 PcatRootBridgeMemAddressValid (
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
381 EFI_STATUS
382 EFIAPI
PcatRootBridgeIoMemRead(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)383 PcatRootBridgeIoMemRead (
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
428 EFI_STATUS
429 EFIAPI
PcatRootBridgeIoMemWrite(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)430 PcatRootBridgeIoMemWrite (
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
475 EFI_STATUS
476 EFIAPI
PcatRootBridgeIoCopyMem(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 DestAddress,IN UINT64 SrcAddress,IN UINTN Count)477 PcatRootBridgeIoCopyMem (
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
541 EFI_STATUS
542 EFIAPI
PcatRootBridgeIoPciRead(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)543 PcatRootBridgeIoPciRead (
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
558 EFI_STATUS
559 EFIAPI
PcatRootBridgeIoPciWrite(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)560 PcatRootBridgeIoPciWrite (
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
575 EFI_STATUS
576 EFIAPI
PcatRootBridgeIoMap(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,IN VOID * HostAddress,IN OUT UINTN * NumberOfBytes,OUT EFI_PHYSICAL_ADDRESS * DeviceAddress,OUT VOID ** Mapping)577 PcatRootBridgeIoMap (
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
725 EFI_STATUS
726 EFIAPI
PcatRootBridgeIoUnmap(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN VOID * Mapping)727 PcatRootBridgeIoUnmap (
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
794 EFI_STATUS
795 EFIAPI
PcatRootBridgeIoAllocateBuffer(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_ALLOCATE_TYPE Type,IN EFI_MEMORY_TYPE MemoryType,IN UINTN Pages,OUT VOID ** HostAddress,IN UINT64 Attributes)796 PcatRootBridgeIoAllocateBuffer (
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
844 EFI_STATUS
845 EFIAPI
PcatRootBridgeIoFreeBuffer(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN UINTN Pages,OUT VOID * HostAddress)846 PcatRootBridgeIoFreeBuffer (
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
860 EFI_STATUS
861 EFIAPI
PcatRootBridgeIoFlush(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This)862 PcatRootBridgeIoFlush (
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
875 EFI_STATUS
876 EFIAPI
PcatRootBridgeIoGetAttributes(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,OUT UINT64 * Supported,OPTIONAL OUT UINT64 * Attributes)877 PcatRootBridgeIoGetAttributes (
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
917 EFI_STATUS
918 EFIAPI
PcatRootBridgeIoSetAttributes(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN UINT64 Attributes,IN OUT UINT64 * ResourceBase,IN OUT UINT64 * ResourceLength)919 PcatRootBridgeIoSetAttributes (
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
944 EFI_STATUS
945 EFIAPI
PcatRootBridgeIoConfiguration(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,OUT VOID ** Resources)946 PcatRootBridgeIoConfiguration (
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
965 EFI_STATUS
966 EFIAPI
PcatRootBridgeIoMemRW(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINTN Count,IN BOOLEAN InStrideFlag,IN PTR In,IN BOOLEAN OutStrideFlag,OUT PTR Out)967 PcatRootBridgeIoMemRW (
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
977 Routine Description:
978
979 Private service to provide the memory read/write
980
981 Arguments:
982
983 Width of the Memory Access
984 Count of the number of accesses to perform
985
986 Returns:
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
1037