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