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