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