]> git.proxmox.com Git - mirror_edk2.git/blame - PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c
Remove svn:executable on *.c, *.h, *.asm, *.S, *.inf and *.asl*
[mirror_edk2.git] / PcAtChipsetPkg / PciHostBridgeDxe / PciRootBridgeIo.c
CommitLineData
21b404d1 1/** @file\r
2 PCI Root Bridge Io Protocol implementation\r
3\r
4 Copyright (c) 2008 - 2009, Intel Corporation<BR> All rights\r
5 reserved. This program and the accompanying materials are\r
6 licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9 \r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/ \r
14\r
15#include "PciHostBridge.h"\r
16\r
17typedef struct {\r
18 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR SpaceDesp[TypeMax];\r
19 EFI_ACPI_END_TAG_DESCRIPTOR EndDesp;\r
20} RESOURCE_CONFIGURATION;\r
21\r
22RESOURCE_CONFIGURATION Configuration = {\r
23 {{0x8A, 0x2B, 1, 0, 0, 0, 0, 0, 0, 0},\r
24 {0x8A, 0x2B, 0, 0, 0, 32, 0, 0, 0, 0}, \r
25 {0x8A, 0x2B, 0, 0, 6, 32, 0, 0, 0, 0},\r
26 {0x8A, 0x2B, 0, 0, 0, 64, 0, 0, 0, 0},\r
27 {0x8A, 0x2B, 0, 0, 6, 64, 0, 0, 0, 0},\r
28 {0x8A, 0x2B, 2, 0, 0, 0, 0, 0, 0, 0}},\r
29 {0x79, 0}\r
30};\r
31\r
32//\r
33// Protocol Member Function Prototypes\r
34//\r
35\r
36EFI_STATUS\r
37EFIAPI\r
38RootBridgeIoPollMem ( \r
39 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
40 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
41 IN UINT64 Address,\r
42 IN UINT64 Mask,\r
43 IN UINT64 Value,\r
44 IN UINT64 Delay,\r
45 OUT UINT64 *Result\r
46 );\r
47 \r
48EFI_STATUS\r
49EFIAPI\r
50RootBridgeIoPollIo ( \r
51 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
52 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
53 IN UINT64 Address,\r
54 IN UINT64 Mask,\r
55 IN UINT64 Value,\r
56 IN UINT64 Delay,\r
57 OUT UINT64 *Result\r
58 );\r
59 \r
60EFI_STATUS\r
61EFIAPI\r
62RootBridgeIoMemRead (\r
63 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
64 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
65 IN UINT64 Address,\r
66 IN UINTN Count,\r
67 IN OUT VOID *Buffer\r
68 );\r
69\r
70EFI_STATUS\r
71EFIAPI\r
72RootBridgeIoMemWrite (\r
73 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
74 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
75 IN UINT64 Address,\r
76 IN UINTN Count,\r
77 IN OUT VOID *Buffer\r
78 );\r
79\r
80EFI_STATUS\r
81EFIAPI\r
82RootBridgeIoIoRead (\r
83 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
84 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
85 IN UINT64 UserAddress,\r
86 IN UINTN Count,\r
87 IN OUT VOID *UserBuffer\r
88 );\r
89\r
90EFI_STATUS\r
91EFIAPI\r
92RootBridgeIoIoWrite (\r
93 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
94 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
95 IN UINT64 UserAddress,\r
96 IN UINTN Count,\r
97 IN OUT VOID *UserBuffer\r
98 );\r
99\r
100EFI_STATUS\r
101EFIAPI\r
102RootBridgeIoCopyMem (\r
103 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
104 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
105 IN UINT64 DestAddress,\r
106 IN UINT64 SrcAddress,\r
107 IN UINTN Count\r
108 );\r
109\r
110EFI_STATUS\r
111EFIAPI\r
112RootBridgeIoPciRead (\r
113 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
114 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
115 IN UINT64 Address,\r
116 IN UINTN Count,\r
117 IN OUT VOID *Buffer\r
118 );\r
119\r
120EFI_STATUS\r
121EFIAPI\r
122RootBridgeIoPciWrite (\r
123 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
124 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
125 IN UINT64 Address,\r
126 IN UINTN Count,\r
127 IN OUT VOID *Buffer\r
128 );\r
129\r
130EFI_STATUS\r
131EFIAPI\r
132RootBridgeIoMap (\r
133 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
134 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,\r
135 IN VOID *HostAddress,\r
136 IN OUT UINTN *NumberOfBytes,\r
137 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
138 OUT VOID **Mapping\r
139 );\r
140\r
141EFI_STATUS\r
142EFIAPI\r
143RootBridgeIoUnmap (\r
144 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
145 IN VOID *Mapping\r
146 );\r
147\r
148EFI_STATUS\r
149EFIAPI\r
150RootBridgeIoAllocateBuffer (\r
151 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
152 IN EFI_ALLOCATE_TYPE Type,\r
153 IN EFI_MEMORY_TYPE MemoryType,\r
154 IN UINTN Pages,\r
155 OUT VOID **HostAddress,\r
156 IN UINT64 Attributes\r
157 );\r
158\r
159EFI_STATUS\r
160EFIAPI\r
161RootBridgeIoFreeBuffer (\r
162 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
163 IN UINTN Pages,\r
164 OUT VOID *HostAddress\r
165 );\r
166\r
167EFI_STATUS\r
168EFIAPI\r
169RootBridgeIoFlush (\r
170 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This\r
171 );\r
172\r
173EFI_STATUS\r
174EFIAPI\r
175RootBridgeIoGetAttributes (\r
176 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
177 OUT UINT64 *Supported,\r
178 OUT UINT64 *Attributes\r
179 );\r
180\r
181EFI_STATUS\r
182EFIAPI\r
183RootBridgeIoSetAttributes (\r
184 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
185 IN UINT64 Attributes,\r
186 IN OUT UINT64 *ResourceBase,\r
187 IN OUT UINT64 *ResourceLength \r
188 ); \r
189\r
190EFI_STATUS\r
191EFIAPI\r
192RootBridgeIoConfiguration (\r
193 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
194 OUT VOID **Resources\r
195 );\r
196\r
197//\r
198// Sub Function Prototypes\r
199//\r
200EFI_STATUS\r
201RootBridgeIoPciRW (\r
202 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
203 IN BOOLEAN Write,\r
204 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
205 IN UINT64 UserAddress,\r
206 IN UINTN Count,\r
207 IN OUT VOID *UserBuffer\r
208 );\r
209\r
210//\r
211// Memory Controller Pci Root Bridge Io Module Variables\r
212//\r
213EFI_METRONOME_ARCH_PROTOCOL *mMetronome;\r
8e9778c9 214EFI_CPU_IO2_PROTOCOL *mCpuIo;\r
21b404d1 215\r
216EFI_STATUS\r
217RootBridgeConstructor (\r
218 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,\r
219 IN EFI_HANDLE HostBridgeHandle,\r
220 IN UINT64 Attri,\r
221 IN PCI_ROOT_BRIDGE_RESOURCE_APPETURE *ResAppeture\r
222 )\r
223/*++\r
224\r
225Routine Description:\r
226\r
227 Construct the Pci Root Bridge Io protocol\r
228\r
229Arguments:\r
230\r
231 Protocol - protocol to initialize\r
232 \r
233Returns:\r
234\r
235 None\r
236\r
237--*/\r
238{\r
239 EFI_STATUS Status;\r
240 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
241 PCI_RESOURCE_TYPE Index;\r
242\r
243 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol);\r
244\r
245 //\r
246 // The host to pci bridge, the host memory and io addresses are\r
247 // direct mapped to pci addresses, so no need translate, set bases to 0.\r
248 //\r
249 PrivateData->MemBase = ResAppeture->MemBase;\r
250 PrivateData->IoBase = ResAppeture->IoBase;\r
251\r
252 //\r
253 // The host bridge only supports 32bit addressing for memory\r
254 // and standard IA32 16bit io\r
255 //\r
256 PrivateData->MemLimit = ResAppeture->MemLimit;\r
257 PrivateData->IoLimit = ResAppeture->IoLimit;\r
258\r
259 //\r
260 // Bus Appeture for this Root Bridge (Possible Range)\r
261 //\r
262 PrivateData->BusBase = ResAppeture->BusBase;\r
263 PrivateData->BusLimit = ResAppeture->BusLimit;\r
264 \r
265 //\r
266 // Specific for this chipset\r
267 //\r
268 for (Index = TypeIo; Index < TypeMax; Index++) {\r
269 PrivateData->ResAllocNode[Index].Type = Index;\r
270 PrivateData->ResAllocNode[Index].Base = 0;\r
271 PrivateData->ResAllocNode[Index].Length = 0;\r
272 PrivateData->ResAllocNode[Index].Status = ResNone;\r
273 }\r
274 \r
275\r
276 EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL);\r
277 PrivateData->PciAddress = 0xCF8;\r
278 PrivateData->PciData = 0xCFC;\r
279\r
280 PrivateData->RootBridgeAttrib = Attri;\r
281 \r
282 PrivateData->Attributes = 0;\r
283 PrivateData->Supports = 0;\r
284\r
285 Protocol->ParentHandle = HostBridgeHandle;\r
286 \r
287 Protocol->PollMem = RootBridgeIoPollMem;\r
288 Protocol->PollIo = RootBridgeIoPollIo;\r
289\r
290 Protocol->Mem.Read = RootBridgeIoMemRead;\r
291 Protocol->Mem.Write = RootBridgeIoMemWrite;\r
292\r
293 Protocol->Io.Read = RootBridgeIoIoRead;\r
294 Protocol->Io.Write = RootBridgeIoIoWrite;\r
295\r
296 Protocol->CopyMem = RootBridgeIoCopyMem;\r
297\r
298 Protocol->Pci.Read = RootBridgeIoPciRead;\r
299 Protocol->Pci.Write = RootBridgeIoPciWrite;\r
300\r
301 Protocol->Map = RootBridgeIoMap;\r
302 Protocol->Unmap = RootBridgeIoUnmap;\r
303\r
304 Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer;\r
305 Protocol->FreeBuffer = RootBridgeIoFreeBuffer;\r
306\r
307 Protocol->Flush = RootBridgeIoFlush;\r
308\r
309 Protocol->GetAttributes = RootBridgeIoGetAttributes;\r
310 Protocol->SetAttributes = RootBridgeIoSetAttributes;\r
311\r
312 Protocol->Configuration = RootBridgeIoConfiguration;\r
313\r
314 Protocol->SegmentNumber = 0;\r
315\r
8e9778c9 316 Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)&mCpuIo);\r
21b404d1 317 ASSERT_EFI_ERROR (Status);\r
318\r
319 Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **)&mMetronome);\r
320 ASSERT_EFI_ERROR (Status);\r
321\r
322 return EFI_SUCCESS;\r
323}\r
324\r
325EFI_STATUS\r
326EFIAPI\r
327RootBridgeIoPollMem ( \r
328 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
329 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
330 IN UINT64 Address,\r
331 IN UINT64 Mask,\r
332 IN UINT64 Value,\r
333 IN UINT64 Delay,\r
334 OUT UINT64 *Result\r
335 )\r
336/*++\r
337\r
338Routine Description:\r
339 Memory Poll\r
340 \r
341Arguments:\r
342 \r
343Returns:\r
344\r
345--*/ \r
346{\r
347 EFI_STATUS Status;\r
348 UINT64 NumberOfTicks;\r
349 UINT32 Remainder;\r
350\r
351 if (Result == NULL) {\r
352 return EFI_INVALID_PARAMETER;\r
353 }\r
354\r
355 if (Width < 0 || Width > EfiPciWidthUint64) {\r
356 return EFI_INVALID_PARAMETER;\r
357 }\r
358\r
359 //\r
360 // No matter what, always do a single poll.\r
361 //\r
362 Status = This->Mem.Read (This, Width, Address, 1, Result);\r
363 if (EFI_ERROR (Status)) {\r
364 return Status;\r
365 } \r
366 if ((*Result & Mask) == Value) {\r
367 return EFI_SUCCESS;\r
368 }\r
369\r
370 if (Delay == 0) {\r
371 return EFI_SUCCESS;\r
372 \r
373 } else {\r
374\r
375 //\r
376 // Determine the proper # of metronome ticks to wait for polling the\r
377 // location. The nuber of ticks is Roundup (Delay / mMetronome->TickPeriod)+1\r
378 // The "+1" to account for the possibility of the first tick being short\r
379 // because we started in the middle of a tick.\r
380 //\r
381 // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome\r
382 // protocol definition is updated.\r
383 //\r
384 NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod, &Remainder);\r
385 if (Remainder != 0) {\r
386 NumberOfTicks += 1;\r
387 }\r
388 NumberOfTicks += 1;\r
389 \r
390 while (NumberOfTicks) {\r
391\r
392 mMetronome->WaitForTick (mMetronome, 1);\r
393 \r
394 Status = This->Mem.Read (This, Width, Address, 1, Result);\r
395 if (EFI_ERROR (Status)) {\r
396 return Status;\r
397 }\r
398 \r
399 if ((*Result & Mask) == Value) {\r
400 return EFI_SUCCESS;\r
401 }\r
402\r
403 NumberOfTicks -= 1;\r
404 }\r
405 }\r
406 return EFI_TIMEOUT;\r
407}\r
408 \r
409EFI_STATUS\r
410EFIAPI\r
411RootBridgeIoPollIo ( \r
412 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
413 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
414 IN UINT64 Address,\r
415 IN UINT64 Mask,\r
416 IN UINT64 Value,\r
417 IN UINT64 Delay,\r
418 OUT UINT64 *Result\r
419 )\r
420/*++\r
421\r
422Routine Description:\r
423 Io Poll\r
424 \r
425Arguments:\r
426 \r
427Returns:\r
428\r
429--*/ \r
430{\r
431 EFI_STATUS Status;\r
432 UINT64 NumberOfTicks;\r
433 UINT32 Remainder;\r
434\r
435 //\r
436 // No matter what, always do a single poll.\r
437 //\r
438\r
439 if (Result == NULL) {\r
440 return EFI_INVALID_PARAMETER;\r
441 }\r
442\r
443 if (Width < 0 || Width > EfiPciWidthUint64) {\r
444 return EFI_INVALID_PARAMETER;\r
445 }\r
446 \r
447 Status = This->Io.Read (This, Width, Address, 1, Result);\r
448 if (EFI_ERROR (Status)) {\r
449 return Status;\r
450 } \r
451 if ((*Result & Mask) == Value) {\r
452 return EFI_SUCCESS;\r
453 }\r
454\r
455 if (Delay == 0) {\r
456 return EFI_SUCCESS;\r
457 \r
458 } else {\r
459\r
460 //\r
461 // Determine the proper # of metronome ticks to wait for polling the\r
462 // location. The number of ticks is Roundup (Delay / mMetronome->TickPeriod)+1\r
463 // The "+1" to account for the possibility of the first tick being short\r
464 // because we started in the middle of a tick.\r
465 //\r
466 NumberOfTicks = DivU64x32Remainder (Delay, (UINT32)mMetronome->TickPeriod, &Remainder);\r
467 if (Remainder != 0) {\r
468 NumberOfTicks += 1;\r
469 }\r
470 NumberOfTicks += 1;\r
471 \r
472 while (NumberOfTicks) {\r
473\r
474 mMetronome->WaitForTick (mMetronome, 1);\r
475 \r
476 Status = This->Io.Read (This, Width, Address, 1, Result);\r
477 if (EFI_ERROR (Status)) {\r
478 return Status;\r
479 }\r
480 \r
481 if ((*Result & Mask) == Value) {\r
482 return EFI_SUCCESS;\r
483 }\r
484\r
485 NumberOfTicks -= 1;\r
486 }\r
487 }\r
488 return EFI_TIMEOUT;\r
489}\r
490\r
491EFI_STATUS\r
492EFIAPI\r
493RootBridgeIoMemRead (\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 Address,\r
497 IN UINTN Count,\r
498 IN OUT VOID *Buffer\r
499 )\r
500/*++\r
501\r
502Routine Description:\r
503 Memory read\r
504 \r
505Arguments:\r
506 \r
507Returns:\r
508\r
509--*/ \r
510{\r
511 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
512 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth;\r
513 UINTN OldCount;\r
514 \r
515 if (Buffer == NULL) {\r
516 return EFI_INVALID_PARAMETER;\r
517 }\r
518\r
519 if (Width < 0 || Width >= EfiPciWidthMaximum) {\r
520 return EFI_INVALID_PARAMETER;\r
521 }\r
522\r
523 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
524\r
525 //\r
526 // Check memory access limit\r
527 //\r
528 if (Address < PrivateData->MemBase) {\r
529 return EFI_INVALID_PARAMETER;\r
530 }\r
531\r
532 OldWidth = Width;\r
533 OldCount = Count;\r
534\r
535 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
536 Count = 1;\r
537 }\r
538\r
539 Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03);\r
540\r
541 if (Address + (((UINTN)1 << Width) * Count) - 1 > PrivateData->MemLimit) {\r
542 return EFI_INVALID_PARAMETER;\r
543 }\r
544\r
545 return mCpuIo->Mem.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth, \r
546 Address, OldCount, Buffer);\r
547}\r
548\r
549EFI_STATUS\r
550EFIAPI\r
551RootBridgeIoMemWrite (\r
552 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
553 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
554 IN UINT64 Address,\r
555 IN UINTN Count,\r
556 IN OUT VOID *Buffer\r
557 )\r
558/*++\r
559\r
560Routine Description:\r
561 Memory write\r
562 \r
563Arguments:\r
564 \r
565Returns:\r
566\r
567--*/ \r
568{\r
569 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
570 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth;\r
571 UINTN OldCount;\r
572\r
573 if (Buffer == NULL) {\r
574 return EFI_INVALID_PARAMETER;\r
575 }\r
576\r
577 if (Width < 0 || Width >= EfiPciWidthMaximum) {\r
578 return EFI_INVALID_PARAMETER;\r
579 }\r
580\r
581 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
582\r
583 //\r
584 // Check memory access limit\r
585 //\r
586 if (Address < PrivateData->MemBase) {\r
587 return EFI_INVALID_PARAMETER;\r
588 }\r
589\r
590 OldWidth = Width;\r
591 OldCount = Count;\r
592 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
593 Count = 1;\r
594 }\r
595\r
596 Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03);\r
597\r
598 if (Address + (((UINTN)1 << Width) * Count) - 1 > PrivateData->MemLimit) {\r
599 return EFI_INVALID_PARAMETER;\r
600 }\r
601\r
602 return mCpuIo->Mem.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth, \r
603 Address, OldCount, Buffer);\r
604}\r
605\r
606EFI_STATUS\r
607EFIAPI\r
608RootBridgeIoIoRead (\r
609 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
610 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
611 IN UINT64 Address,\r
612 IN UINTN Count,\r
613 IN OUT VOID *Buffer\r
614 )\r
615/*++\r
616\r
617Routine Description:\r
618 Io read\r
619 \r
620Arguments:\r
621 \r
622Returns:\r
623\r
624--*/ \r
625{\r
626 \r
627 \r
628 UINTN AlignMask;\r
629 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
630 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth;\r
631 UINTN OldCount;\r
632\r
633 if (Buffer == NULL) {\r
634 return EFI_INVALID_PARAMETER;\r
635 }\r
636 \r
637 if (Width < 0 || Width >= EfiPciWidthMaximum) {\r
638 return EFI_INVALID_PARAMETER;\r
639 }\r
640 \r
641 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
642\r
643 //AlignMask = (1 << Width) - 1;\r
644 AlignMask = (1 << (Width & 0x03)) - 1;\r
645\r
646 //\r
647 // check Io access limit\r
648 //\r
649 if (Address < PrivateData->IoBase) {\r
650 return EFI_INVALID_PARAMETER;\r
651 }\r
652\r
653 OldWidth = Width;\r
654 OldCount = Count;\r
655 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
656 Count = 1;\r
657 }\r
658\r
659 Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03);\r
660 \r
661 if (Address + (((UINTN)1 << Width) * Count) - 1 >= PrivateData->IoLimit) {\r
662 return EFI_INVALID_PARAMETER;\r
663 }\r
664\r
665 if (Address & AlignMask) {\r
666 return EFI_INVALID_PARAMETER;\r
667 }\r
668\r
669 return mCpuIo->Io.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth, \r
670 Address, OldCount, Buffer);\r
671\r
672}\r
673\r
674EFI_STATUS\r
675EFIAPI\r
676RootBridgeIoIoWrite (\r
677 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
678 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
679 IN UINT64 Address,\r
680 IN UINTN Count,\r
681 IN OUT VOID *Buffer\r
682 )\r
683/*++\r
684\r
685Routine Description:\r
686 Io write\r
687 \r
688Arguments:\r
689 \r
690Returns:\r
691\r
692--*/ \r
693{\r
694 UINTN AlignMask;\r
695 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
696 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth;\r
697 UINTN OldCount;\r
698\r
699 if (Buffer == NULL) {\r
700 return EFI_INVALID_PARAMETER;\r
701 }\r
702\r
703 if (Width < 0 || Width >= EfiPciWidthMaximum) {\r
704 return EFI_INVALID_PARAMETER;\r
705 }\r
706\r
707 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
708\r
709 //AlignMask = (1 << Width) - 1;\r
710 AlignMask = (1 << (Width & 0x03)) - 1;\r
711\r
712 //\r
713 // Check Io access limit\r
714 //\r
715 if (Address < PrivateData->IoBase) {\r
716 return EFI_INVALID_PARAMETER;\r
717 }\r
718\r
719 OldWidth = Width;\r
720 OldCount = Count;\r
721 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
722 Count = 1;\r
723 }\r
724\r
725 Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03);\r
726 \r
727 if (Address + (((UINTN)1 << Width) * Count) - 1 >= PrivateData->IoLimit) {\r
728 return EFI_INVALID_PARAMETER;\r
729 }\r
730\r
731 if (Address & AlignMask) {\r
732 return EFI_INVALID_PARAMETER;\r
733 }\r
734\r
735 return mCpuIo->Io.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth, \r
736 Address, OldCount, Buffer);\r
737\r
738}\r
739\r
740EFI_STATUS\r
741EFIAPI\r
742RootBridgeIoCopyMem (\r
743 IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
744 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
745 IN UINT64 DestAddress,\r
746 IN UINT64 SrcAddress,\r
747 IN UINTN Count\r
748 )\r
749/*++\r
750\r
751Routine Description:\r
752 Memory copy\r
753 \r
754Arguments:\r
755 \r
756Returns:\r
757\r
758--*/\r
759{\r
760 EFI_STATUS Status;\r
761 BOOLEAN Direction;\r
762 UINTN Stride;\r
763 UINTN Index;\r
764 UINT64 Result;\r
765\r
766 if (Width < 0 || Width > EfiPciWidthUint64) {\r
767 return EFI_INVALID_PARAMETER;\r
768 } \r
769\r
770 if (DestAddress == SrcAddress) {\r
771 return EFI_SUCCESS;\r
772 }\r
773\r
774 Stride = (UINTN)(1 << Width);\r
775\r
776 Direction = TRUE;\r
777 if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {\r
778 Direction = FALSE;\r
779 SrcAddress = SrcAddress + (Count-1) * Stride;\r
780 DestAddress = DestAddress + (Count-1) * Stride;\r
781 }\r
782\r
783 for (Index = 0;Index < Count;Index++) {\r
784 Status = RootBridgeIoMemRead (\r
785 This,\r
786 Width,\r
787 SrcAddress,\r
788 1,\r
789 &Result\r
790 );\r
791 if (EFI_ERROR (Status)) {\r
792 return Status;\r
793 }\r
794 Status = RootBridgeIoMemWrite (\r
795 This,\r
796 Width,\r
797 DestAddress,\r
798 1,\r
799 &Result\r
800 );\r
801 if (EFI_ERROR (Status)) {\r
802 return Status;\r
803 }\r
804 if (Direction) {\r
805 SrcAddress += Stride;\r
806 DestAddress += Stride;\r
807 } else {\r
808 SrcAddress -= Stride;\r
809 DestAddress -= Stride;\r
810 }\r
811 }\r
812 return EFI_SUCCESS;\r
813}\r
814\r
815EFI_STATUS\r
816EFIAPI\r
817RootBridgeIoPciRead (\r
818 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
819 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
820 IN UINT64 Address,\r
821 IN UINTN Count,\r
822 IN OUT VOID *Buffer\r
823 )\r
824/*++\r
825\r
826Routine Description:\r
827 Pci read\r
828 \r
829Arguments:\r
830 \r
831Returns:\r
832\r
833--*/ \r
834{\r
835 \r
836 if (Buffer == NULL) {\r
837 return EFI_INVALID_PARAMETER;\r
838 }\r
839\r
840 if (Width < 0 || Width >= EfiPciWidthMaximum) {\r
841 return EFI_INVALID_PARAMETER;\r
842 }\r
843 //\r
844 // Read Pci configuration space\r
845 //\r
846 return RootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);\r
847}\r
848\r
849EFI_STATUS\r
850EFIAPI\r
851RootBridgeIoPciWrite (\r
852 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
853 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
854 IN UINT64 Address,\r
855 IN UINTN Count,\r
856 IN OUT VOID *Buffer\r
857 )\r
858/*++\r
859\r
860Routine Description:\r
861 Pci write\r
862 \r
863Arguments:\r
864 \r
865Returns:\r
866\r
867--*/ \r
868{\r
869 \r
870 if (Buffer == NULL) {\r
871 return EFI_INVALID_PARAMETER;\r
872 }\r
873\r
874 if (Width < 0 || Width >= EfiPciWidthMaximum) {\r
875 return EFI_INVALID_PARAMETER;\r
876 }\r
877 //\r
878 // Write Pci configuration space\r
879 //\r
880 return RootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);\r
881}\r
882\r
883EFI_STATUS\r
884EFIAPI\r
885RootBridgeIoMap (\r
886 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
887 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,\r
888 IN VOID *HostAddress,\r
889 IN OUT UINTN *NumberOfBytes,\r
890 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
891 OUT VOID **Mapping\r
892 )\r
893\r
894{\r
895 EFI_STATUS Status;\r
896 EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
897 MAP_INFO *MapInfo;\r
898\r
899 if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {\r
900 return EFI_INVALID_PARAMETER;\r
901 }\r
902 \r
903 //\r
904 // Initialize the return values to their defaults\r
905 //\r
906 *Mapping = NULL;\r
907\r
908 //\r
909 // Make sure that Operation is valid\r
910 //\r
911 if (Operation < 0 || Operation >= EfiPciOperationMaximum) {\r
912 return EFI_INVALID_PARAMETER;\r
913 }\r
914\r
915 //\r
916 // Most PCAT like chipsets can not handle performing DMA above 4GB.\r
917 // If any part of the DMA transfer being mapped is above 4GB, then\r
918 // map the DMA transfer to a buffer below 4GB.\r
919 //\r
920 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;\r
921 if ((PhysicalAddress + *NumberOfBytes) > 0x100000000ULL) {\r
922\r
923 //\r
924 // Common Buffer operations can not be remapped. If the common buffer\r
925 // if above 4GB, then it is not possible to generate a mapping, so return \r
926 // an error.\r
927 //\r
928 if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {\r
929 return EFI_UNSUPPORTED;\r
930 }\r
931\r
932 //\r
933 // Allocate a MAP_INFO structure to remember the mapping when Unmap() is\r
934 // called later.\r
935 //\r
936 Status = gBS->AllocatePool (\r
937 EfiBootServicesData, \r
938 sizeof(MAP_INFO), \r
939 (VOID **)&MapInfo\r
940 );\r
941 if (EFI_ERROR (Status)) {\r
942 *NumberOfBytes = 0;\r
943 return Status;\r
944 }\r
945\r
946 //\r
947 // Return a pointer to the MAP_INFO structure in Mapping\r
948 //\r
949 *Mapping = MapInfo;\r
950\r
951 //\r
952 // Initialize the MAP_INFO structure\r
953 //\r
954 MapInfo->Operation = Operation;\r
955 MapInfo->NumberOfBytes = *NumberOfBytes;\r
956 MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES(*NumberOfBytes);\r
957 MapInfo->HostAddress = PhysicalAddress;\r
958 MapInfo->MappedHostAddress = 0x00000000ffffffff;\r
959\r
960 //\r
961 // Allocate a buffer below 4GB to map the transfer to.\r
962 //\r
963 Status = gBS->AllocatePages (\r
964 AllocateMaxAddress, \r
965 EfiBootServicesData, \r
966 MapInfo->NumberOfPages,\r
967 &MapInfo->MappedHostAddress\r
968 );\r
969 if (EFI_ERROR (Status)) {\r
970 gBS->FreePool (MapInfo);\r
971 *NumberOfBytes = 0;\r
972 return Status;\r
973 }\r
974\r
975 //\r
976 // If this is a read operation from the Bus Master's point of view,\r
977 // then copy the contents of the real buffer into the mapped buffer\r
978 // so the Bus Master can read the contents of the real buffer.\r
979 //\r
980 if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {\r
981 CopyMem (\r
982 (VOID *)(UINTN)MapInfo->MappedHostAddress, \r
983 (VOID *)(UINTN)MapInfo->HostAddress,\r
984 MapInfo->NumberOfBytes\r
985 );\r
986 }\r
987\r
988 //\r
989 // The DeviceAddress is the address of the maped buffer below 4GB\r
990 //\r
991 *DeviceAddress = MapInfo->MappedHostAddress;\r
992 } else {\r
993 //\r
994 // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress\r
995 //\r
996 *DeviceAddress = PhysicalAddress;\r
997 }\r
998\r
999 return EFI_SUCCESS;\r
1000}\r
1001\r
1002EFI_STATUS\r
1003EFIAPI\r
1004RootBridgeIoUnmap (\r
1005 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
1006 IN VOID *Mapping\r
1007 )\r
1008\r
1009{\r
1010 MAP_INFO *MapInfo;\r
1011\r
1012 //\r
1013 // See if the Map() operation associated with this Unmap() required a mapping buffer.\r
1014 // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.\r
1015 //\r
1016 if (Mapping != NULL) {\r
1017 //\r
1018 // Get the MAP_INFO structure from Mapping\r
1019 //\r
1020 MapInfo = (MAP_INFO *)Mapping;\r
1021\r
1022 //\r
1023 // If this is a write operation from the Bus Master's point of view,\r
1024 // then copy the contents of the mapped buffer into the real buffer\r
1025 // so the processor can read the contents of the real buffer.\r
1026 //\r
1027 if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) {\r
1028 CopyMem (\r
1029 (VOID *)(UINTN)MapInfo->HostAddress, \r
1030 (VOID *)(UINTN)MapInfo->MappedHostAddress,\r
1031 MapInfo->NumberOfBytes\r
1032 );\r
1033 }\r
1034\r
1035 //\r
1036 // Free the mapped buffer and the MAP_INFO structure.\r
1037 //\r
1038 gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);\r
1039 gBS->FreePool (Mapping);\r
1040 }\r
1041 return EFI_SUCCESS;\r
1042}\r
1043\r
1044EFI_STATUS\r
1045EFIAPI\r
1046RootBridgeIoAllocateBuffer (\r
1047 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
1048 IN EFI_ALLOCATE_TYPE Type,\r
1049 IN EFI_MEMORY_TYPE MemoryType,\r
1050 IN UINTN Pages,\r
1051 OUT VOID **HostAddress,\r
1052 IN UINT64 Attributes\r
1053 )\r
1054\r
1055{\r
1056 EFI_STATUS Status;\r
1057 EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
1058\r
1059 //\r
1060 // Validate Attributes\r
1061 //\r
1062 if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {\r
1063 return EFI_UNSUPPORTED;\r
1064 }\r
1065\r
1066 //\r
1067 // Check for invalid inputs\r
1068 //\r
1069 if (HostAddress == NULL) {\r
1070 return EFI_INVALID_PARAMETER;\r
1071 }\r
1072 \r
1073 //\r
1074 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData\r
1075 //\r
1076 if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {\r
1077 return EFI_INVALID_PARAMETER;\r
1078 }\r
1079\r
1080 //\r
1081 // Limit allocations to memory below 4GB\r
1082 //\r
1083 PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(0xffffffff);\r
1084\r
1085 Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);\r
1086 if (EFI_ERROR (Status)) {\r
1087 return Status;\r
1088 }\r
1089\r
1090 *HostAddress = (VOID *)(UINTN)PhysicalAddress;\r
1091\r
1092 return EFI_SUCCESS;\r
1093}\r
1094\r
1095EFI_STATUS\r
1096EFIAPI\r
1097RootBridgeIoFreeBuffer (\r
1098 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
1099 IN UINTN Pages,\r
1100 OUT VOID *HostAddress\r
1101 )\r
1102\r
1103{\r
1104 return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);\r
1105}\r
1106\r
1107EFI_STATUS\r
1108EFIAPI\r
1109RootBridgeIoFlush (\r
1110 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This\r
1111 )\r
1112/*++\r
1113\r
1114Routine Description:\r
1115\r
1116Arguments:\r
1117 \r
1118Returns:\r
1119\r
1120--*/\r
1121{\r
1122 //\r
1123 // not supported yet\r
1124 //\r
1125 return EFI_SUCCESS;\r
1126}\r
1127\r
1128EFI_STATUS\r
1129EFIAPI\r
1130RootBridgeIoGetAttributes (\r
1131 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
1132 OUT UINT64 *Supported,\r
1133 OUT UINT64 *Attributes\r
1134 )\r
1135/*++\r
1136\r
1137Routine Description:\r
1138\r
1139Arguments:\r
1140 \r
1141Returns:\r
1142\r
1143--*/\r
1144{\r
1145 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
1146\r
1147 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
1148\r
1149 if (Attributes == NULL && Supported == NULL) {\r
1150 return EFI_INVALID_PARAMETER;\r
1151 }\r
1152\r
1153 //\r
1154 // Set the return value for Supported and Attributes\r
1155 //\r
1156 if (Supported) {\r
1157 *Supported = PrivateData->Supports; \r
1158 }\r
1159\r
1160 if (Attributes) {\r
1161 *Attributes = PrivateData->Attributes;\r
1162 }\r
1163 \r
1164 return EFI_SUCCESS;\r
1165}\r
1166\r
1167EFI_STATUS\r
1168EFIAPI\r
1169RootBridgeIoSetAttributes (\r
1170 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
1171 IN UINT64 Attributes,\r
1172 IN OUT UINT64 *ResourceBase,\r
1173 IN OUT UINT64 *ResourceLength \r
1174 )\r
1175/*++\r
1176\r
1177Routine Description:\r
1178\r
1179Arguments:\r
1180 \r
1181Returns:\r
1182\r
1183--*/\r
1184{\r
1185 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
1186 \r
1187 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
1188 \r
1189 if (Attributes) {\r
1190 if ((Attributes & (~(PrivateData->Supports))) != 0) {\r
1191 return EFI_UNSUPPORTED;\r
1192 }\r
1193 }\r
1194 \r
1195 //\r
1196 // This is a generic driver for a PC-AT class system. It does not have any\r
1197 // chipset specific knowlegde, so none of the attributes can be set or \r
1198 // cleared. Any attempt to set attribute that are already set will succeed, \r
1199 // and any attempt to set an attribute that is not supported will fail.\r
1200 //\r
1201 if (Attributes & (~PrivateData->Attributes)) {\r
1202 return EFI_UNSUPPORTED;\r
1203 }\r
1204\r
1205 return EFI_SUCCESS;\r
1206}\r
1207\r
1208EFI_STATUS\r
1209EFIAPI\r
1210RootBridgeIoConfiguration (\r
1211 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
1212 OUT VOID **Resources\r
1213 )\r
1214/*++\r
1215\r
1216Routine Description:\r
1217\r
1218Arguments:\r
1219 \r
1220Returns:\r
1221\r
1222--*/\r
1223{\r
1224 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
1225 UINTN Index;\r
1226\r
1227 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);\r
1228 \r
1229 for (Index = 0; Index < TypeMax; Index++) {\r
1230 if (PrivateData->ResAllocNode[Index].Status == ResAllocated) {\r
1231 Configuration.SpaceDesp[Index].AddrRangeMin = PrivateData->ResAllocNode[Index].Base;\r
1232 Configuration.SpaceDesp[Index].AddrRangeMax = PrivateData->ResAllocNode[Index].Base + PrivateData->ResAllocNode[Index].Length - 1;\r
1233 Configuration.SpaceDesp[Index].AddrLen = PrivateData->ResAllocNode[Index].Length;\r
1234 } \r
1235 } \r
1236 \r
1237 *Resources = &Configuration; \r
1238 return EFI_SUCCESS;\r
1239}\r
1240\r
1241//\r
1242// Internal function\r
1243//\r
1244EFI_STATUS\r
1245RootBridgeIoPciRW (\r
1246 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
1247 IN BOOLEAN Write,\r
1248 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
1249 IN UINT64 UserAddress,\r
1250 IN UINTN Count,\r
1251 IN OUT VOID *UserBuffer\r
1252 )\r
1253{\r
1254 PCI_CONFIG_ACCESS_CF8 Pci;\r
1255 PCI_CONFIG_ACCESS_CF8 PciAligned;\r
1256 UINT32 InStride;\r
1257 UINT32 OutStride;\r
1258 UINTN PciData;\r
1259 UINTN PciDataStride;\r
1260 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
1261 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;\r
1262\r
1263 if (Width < 0 || Width >= EfiPciWidthMaximum) {\r
1264 return EFI_INVALID_PARAMETER;\r
1265 }\r
1266 \r
1267 if ((Width & 0x03) >= EfiPciWidthUint64) {\r
1268 return EFI_INVALID_PARAMETER;\r
1269 }\r
1270 \r
1271 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
1272\r
1273 InStride = 1 << (Width & 0x03);\r
1274 OutStride = InStride;\r
1275 if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
1276 InStride = 0;\r
1277 }\r
1278\r
1279 if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {\r
1280 OutStride = 0;\r
1281 }\r
1282\r
1283 CopyMem (&PciAddress, &UserAddress, sizeof(UINT64));\r
1284\r
1285 if (PciAddress.ExtendedRegister > 0xFF) {\r
1286 return EFI_UNSUPPORTED;\r
1287 }\r
1288\r
1289 if (PciAddress.ExtendedRegister != 0) {\r
1290 Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF;\r
1291 } else {\r
1292 Pci.Bits.Reg = PciAddress.Register;\r
1293 }\r
1294\r
1295 Pci.Bits.Func = PciAddress.Function;\r
1296 Pci.Bits.Dev = PciAddress.Device;\r
1297 Pci.Bits.Bus = PciAddress.Bus;\r
1298 Pci.Bits.Reserved = 0;\r
1299 Pci.Bits.Enable = 1;\r
1300\r
1301 //\r
1302 // PCI Config access are all 32-bit alligned, but by accessing the\r
1303 // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types\r
1304 // are possible on PCI.\r
1305 //\r
1306 // To read a byte of PCI config space you load 0xcf8 and \r
1307 // read 0xcfc, 0xcfd, 0xcfe, 0xcff\r
1308 //\r
1309 PciDataStride = Pci.Bits.Reg & 0x03;\r
1310\r
1311 while (Count) {\r
1312 CopyMem (&PciAligned, &Pci, sizeof (PciAligned));\r
1313 PciAligned.Bits.Reg &= 0xfc;\r
1314 PciData = (UINTN)PrivateData->PciData + PciDataStride;\r
1315 EfiAcquireLock(&PrivateData->PciLock);\r
1316 This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned);\r
1317 if (Write) {\r
1318 This->Io.Write (This, Width, PciData, 1, UserBuffer);\r
1319 } else {\r
1320 This->Io.Read (This, Width, PciData, 1, UserBuffer);\r
1321 }\r
1322 EfiReleaseLock(&PrivateData->PciLock);\r
1323 UserBuffer = ((UINT8 *)UserBuffer) + OutStride;\r
1324 PciDataStride = (PciDataStride + InStride) % 4;\r
1325 Pci.Bits.Reg += InStride;\r
1326 Count -= 1;\r
1327 }\r
1328 \r
1329 return EFI_SUCCESS;\r
1330}\r