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