]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciRootBridge.c
ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe: Fix for PCI Dual Address Cycle
[mirror_edk2.git] / ArmPlatformPkg / ArmJunoPkg / Drivers / PciHostBridgeDxe / PciRootBridge.c
CommitLineData
4595449b
OM
1/** @file\r
2* Implementation of the PCI Root Bridge Protocol for XPress-RICH3 PCIe Root Complex\r
3*\r
4* Copyright (c) 2011-2015, ARM Ltd. All rights reserved.\r
5*\r
6* This program and the accompanying materials\r
7* are licensed and made available under the terms and conditions of the BSD License\r
8* which accompanies this distribution. The full text of the license may be found at\r
9* http://opensource.org/licenses/bsd-license.php\r
10*\r
11* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13*\r
14**/\r
15\r
16#include "PciHostBridge.h"\r
17\r
18#include <Library/DevicePathLib.h>\r
19#include <Library/DmaLib.h>\r
20\r
21#define CPUIO_FROM_ROOT_BRIDGE_INSTANCE(Instance) (Instance->HostBridge->CpuIo)\r
22#define METRONOME_FROM_ROOT_BRIDGE_INSTANCE(Instance) (Instance->HostBridge->Metronome)\r
23\r
24/**\r
25 * PCI Root Bridge Instance Templates\r
26 */\r
27STATIC CONST EFI_PCI_ROOT_BRIDGE_DEVICE_PATH gDevicePathTemplate = {\r
28 {\r
29 { ACPI_DEVICE_PATH,\r
30 ACPI_DP,\r
31 { (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),\r
32 (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) }\r
33 },\r
34 EISA_PNP_ID (0x0A03),\r
35 0\r
36 },\r
37 {\r
38 END_DEVICE_PATH_TYPE,\r
39 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
40 { END_DEVICE_PATH_LENGTH, 0 }\r
41 }\r
42};\r
43\r
44STATIC CONST EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL gIoTemplate = {\r
45 0,\r
46 PciRbPollMem,\r
47 PciRbPollIo,\r
48 {\r
49 PciRbMemRead,\r
50 PciRbMemWrite\r
51 },\r
52 {\r
53 PciRbIoRead,\r
54 PciRbIoWrite\r
55 },\r
56 {\r
57 PciRbPciRead,\r
58 PciRbPciWrite\r
59 },\r
60 PciRbCopyMem,\r
61 PciRbMap,\r
62 PciRbUnMap,\r
63 PciRbAllocateBuffer,\r
64 PciRbFreeBuffer,\r
65 PciRbFlush,\r
66 PciRbGetAttributes,\r
67 PciRbSetAttributes,\r
68 PciRbConfiguration,\r
69 0\r
70 };\r
71\r
72typedef struct {\r
73 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR SpaceDesp[ResTypeMax+1];\r
74 EFI_ACPI_END_TAG_DESCRIPTOR EndDesp;\r
75} RESOURCE_CONFIGURATION;\r
76\r
77\r
78RESOURCE_CONFIGURATION Configuration = {\r
79 {{ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_IO , 0, 0, 0, 0, 0, 0, 0},\r
80 {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 0, 32, 0, 0, 0, 0},\r
81 {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 6, 32, 0, 0, 0, 0},\r
82 {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 0, 64, 0, 0, 0, 0},\r
83 {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 6, 64, 0, 0, 0, 0},\r
84 {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_BUS, 0, 0, 0, 0, 255, 0, 255}},\r
85 {ACPI_END_TAG_DESCRIPTOR, 0}\r
86};\r
87\r
88\r
89EFI_STATUS\r
90PciRbPollMem (\r
91 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
92 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
93 IN UINT64 Address,\r
94 IN UINT64 Mask,\r
95 IN UINT64 Value,\r
96 IN UINT64 Delay,\r
97 OUT UINT64 *Result\r
98 )\r
99{\r
100 EFI_STATUS Status;\r
101 UINT64 NumberOfTicks;\r
102 UINT32 Remainder;\r
103 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
104 EFI_METRONOME_ARCH_PROTOCOL *Metronome;\r
105\r
106 PCI_TRACE ("PciRbPollMem()");\r
107\r
108 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);\r
109 Metronome = METRONOME_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);\r
110\r
111 if (Result == NULL) {\r
112 return EFI_INVALID_PARAMETER;\r
113 }\r
114\r
115 if (Width > EfiPciWidthUint64) {\r
116 return EFI_INVALID_PARAMETER;\r
117 }\r
118\r
119 // No matter what, always do a single poll.\r
120 Status = This->Mem.Read (This, Width, Address, 1, Result);\r
121 if (EFI_ERROR (Status)) {\r
122 return Status;\r
123 }\r
124 if ((*Result & Mask) == Value) {\r
125 return EFI_SUCCESS;\r
126 }\r
127\r
128 if (Delay == 0) {\r
129 return EFI_SUCCESS;\r
130 }\r
131\r
132 NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) Metronome->TickPeriod, &Remainder);\r
133 if (Remainder != 0) {\r
134 NumberOfTicks += 1;\r
135 }\r
136 NumberOfTicks += 1;\r
137\r
138 while (NumberOfTicks) {\r
139 Metronome->WaitForTick (Metronome, 1);\r
140\r
141 Status = This->Mem.Read (This, Width, Address, 1, Result);\r
142 if (EFI_ERROR (Status)) {\r
143 return Status;\r
144 }\r
145\r
146 if ((*Result & Mask) == Value) {\r
147 return EFI_SUCCESS;\r
148 }\r
149\r
150 NumberOfTicks -= 1;\r
151 }\r
152\r
153 return EFI_TIMEOUT;\r
154}\r
155\r
156EFI_STATUS\r
157PciRbPollIo (\r
158 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
159 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
160 IN UINT64 Address,\r
161 IN UINT64 Mask,\r
162 IN UINT64 Value,\r
163 IN UINT64 Delay,\r
164 OUT UINT64 *Result\r
165 )\r
166{\r
167 EFI_STATUS Status;\r
168 UINT64 NumberOfTicks;\r
169 UINT32 Remainder;\r
170 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
171 EFI_METRONOME_ARCH_PROTOCOL *Metronome;\r
172\r
173 PCI_TRACE ("PciRbPollIo()");\r
174\r
175 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);\r
176 Metronome = METRONOME_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);\r
177\r
178 if (Result == NULL) {\r
179 return EFI_INVALID_PARAMETER;\r
180 }\r
181\r
182 if (Width > EfiPciWidthUint64) {\r
183 return EFI_INVALID_PARAMETER;\r
184 }\r
185\r
186 // No matter what, always do a single poll.\r
187 Status = This->Io.Read (This, Width, Address, 1, Result);\r
188 if (EFI_ERROR (Status)) {\r
189 return Status;\r
190 }\r
191 if ((*Result & Mask) == Value) {\r
192 return EFI_SUCCESS;\r
193 }\r
194\r
195 if (Delay == 0) {\r
196 return EFI_SUCCESS;\r
197 }\r
198\r
199 NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) Metronome->TickPeriod, &Remainder);\r
200 if (Remainder != 0) {\r
201 NumberOfTicks += 1;\r
202 }\r
203 NumberOfTicks += 1;\r
204\r
205 while (NumberOfTicks) {\r
206 Metronome->WaitForTick (Metronome, 1);\r
207\r
208 Status = This->Io.Read (This, Width, Address, 1, Result);\r
209 if (EFI_ERROR (Status)) {\r
210 return Status;\r
211 }\r
212\r
213 if ((*Result & Mask) == Value) {\r
214 return EFI_SUCCESS;\r
215 }\r
216\r
217 NumberOfTicks -= 1;\r
218 }\r
219\r
220 return EFI_TIMEOUT;\r
221}\r
222\r
223EFI_STATUS\r
224PciRbMemRead (\r
225 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
226 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
227 IN UINT64 Address,\r
228 IN UINTN Count,\r
229 IN OUT VOID *Buffer\r
230 )\r
231{\r
232 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
233 EFI_CPU_IO2_PROTOCOL *CpuIo;\r
234\r
235 PCI_TRACE ("PciRbMemRead()");\r
236\r
237 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);\r
238 CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);\r
239\r
240 if (Buffer == NULL) {\r
241 return EFI_INVALID_PARAMETER;\r
242 }\r
243\r
244 if (Width >= EfiPciWidthMaximum) {\r
245 return EFI_INVALID_PARAMETER;\r
246 }\r
247\r
248 if (((Address < PCI_MEM32_BASE) || (Address > (PCI_MEM32_BASE + PCI_MEM32_SIZE))) &&\r
249 ((Address < PCI_MEM64_BASE) || (Address > (PCI_MEM64_BASE + PCI_MEM64_SIZE)))) {\r
250 return EFI_INVALID_PARAMETER;\r
251 }\r
252\r
253 return CpuIo->Mem.Read (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);\r
254}\r
255\r
256EFI_STATUS\r
257PciRbMemWrite (\r
258 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
259 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
260 IN UINT64 Address,\r
261 IN UINTN Count,\r
262 IN OUT VOID *Buffer\r
263 )\r
264{\r
265 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
266 EFI_CPU_IO2_PROTOCOL *CpuIo;\r
267\r
268 PCI_TRACE ("PciRbMemWrite()");\r
269\r
270 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);\r
271 CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);\r
272\r
273 if (Buffer == NULL) {\r
274 return EFI_INVALID_PARAMETER;\r
275 }\r
276\r
277 if (Width >= EfiPciWidthMaximum) {\r
278 return EFI_INVALID_PARAMETER;\r
279 }\r
280\r
281 if (((Address < PCI_MEM32_BASE) || (Address > (PCI_MEM32_BASE + PCI_MEM32_SIZE))) &&\r
282 ((Address < PCI_MEM64_BASE) || (Address > (PCI_MEM64_BASE + PCI_MEM64_SIZE)))) {\r
283 return EFI_INVALID_PARAMETER;\r
284 }\r
285\r
286 return CpuIo->Mem.Write (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);\r
287}\r
288\r
289EFI_STATUS\r
290PciRbIoRead (\r
291 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
292 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
293 IN UINT64 Address,\r
294 IN UINTN Count,\r
295 IN OUT VOID *Buffer\r
296 )\r
297{\r
298 PCI_TRACE ("PciRbIoRead()");\r
299\r
300 if (Buffer == NULL) {\r
301 return EFI_INVALID_PARAMETER;\r
302 }\r
303\r
304 if (Width >= EfiPciWidthMaximum) {\r
305 return EFI_INVALID_PARAMETER;\r
306 }\r
307\r
308 // IO currently unsupported\r
309 return EFI_INVALID_PARAMETER;\r
310}\r
311\r
312EFI_STATUS\r
313PciRbIoWrite (\r
314 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
315 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
316 IN UINT64 Address,\r
317 IN UINTN Count,\r
318 IN OUT VOID *Buffer\r
319 )\r
320{\r
321 PCI_TRACE ("PciRbIoWrite()");\r
322\r
323 if (Buffer == NULL) {\r
324 return EFI_INVALID_PARAMETER;\r
325 }\r
326\r
327 if (Width >= EfiPciWidthMaximum) {\r
328 return EFI_INVALID_PARAMETER;\r
329 }\r
330\r
331 // IO currently unsupported\r
332 return EFI_INVALID_PARAMETER;\r
333}\r
334\r
335EFI_STATUS\r
336PciRbPciRead (\r
337 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
338 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
339 IN UINT64 EfiAddress,\r
340 IN UINTN Count,\r
341 IN OUT VOID *Buffer\r
342 )\r
343{\r
344 UINT32 Offset;\r
345 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
346 EFI_CPU_IO2_PROTOCOL *CpuIo;\r
347 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *EfiPciAddress;\r
348 UINT64 Address;\r
349\r
350 EfiPciAddress = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&EfiAddress;\r
351 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);\r
352 CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);\r
353\r
354 if (Buffer == NULL) {\r
355 return EFI_INVALID_PARAMETER;\r
356 }\r
357\r
358 if (Width >= EfiPciWidthMaximum) {\r
359 return EFI_INVALID_PARAMETER;\r
360 }\r
361\r
362 if (EfiPciAddress->ExtendedRegister) {\r
363 Offset = EfiPciAddress->ExtendedRegister;\r
364 } else {\r
365 Offset = EfiPciAddress->Register;\r
366 }\r
367\r
368 // The UEFI PCI enumerator scans for devices at all possible addresses,\r
369 // and ignores some PCI rules - this results in some hardware being\r
370 // detected multiple times. We work around this by faking absent\r
371 // devices\r
372 if ((EfiPciAddress->Bus == 0) && ((EfiPciAddress->Device != 0) || (EfiPciAddress->Function != 0))) {\r
373 *((UINT32 *)Buffer) = 0xffffffff;\r
374 return EFI_SUCCESS;\r
375 }\r
376 if ((EfiPciAddress->Bus == 1) && ((EfiPciAddress->Device != 0) || (EfiPciAddress->Function != 0))) {\r
377 *((UINT32 *)Buffer) = 0xffffffff;\r
378 return EFI_SUCCESS;\r
379 }\r
380\r
381 // Work around incorrect class ID in the root bridge\r
382 if ((EfiPciAddress->Bus == 0) && (EfiPciAddress->Device == 0) && (EfiPciAddress->Function == 0) && (Offset == 8)) {\r
383 *((UINT32 *)Buffer) = 0x06040001;\r
384 return EFI_SUCCESS;\r
385 }\r
386\r
387 Address = PCI_ECAM_BASE + ((EfiPciAddress->Bus << 20) |\r
388 (EfiPciAddress->Device << 15) |\r
389 (EfiPciAddress->Function << 12) | Offset);\r
390\r
391 if ((Address < PCI_ECAM_BASE) || (Address > PCI_ECAM_BASE + PCI_ECAM_SIZE)) {\r
392 return EFI_INVALID_PARAMETER;\r
393 }\r
394\r
395 return CpuIo->Mem.Read (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);\r
396}\r
397\r
398EFI_STATUS\r
399PciRbPciWrite (\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 EfiAddress,\r
403 IN UINTN Count,\r
404 IN OUT VOID *Buffer\r
405 )\r
406{\r
407 UINT32 Offset;\r
408 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
409 EFI_CPU_IO2_PROTOCOL *CpuIo;\r
410 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *EfiPciAddress;\r
411 UINT64 Address;\r
412\r
413 EfiPciAddress = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&EfiAddress;\r
414 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);\r
415 CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);\r
416\r
417 if (Buffer == NULL) {\r
418 return EFI_INVALID_PARAMETER;\r
419 }\r
420\r
421 if (Width >= EfiPciWidthMaximum) {\r
422 return EFI_INVALID_PARAMETER;\r
423 }\r
424\r
425 if (EfiPciAddress->ExtendedRegister)\r
426 Offset = EfiPciAddress->ExtendedRegister;\r
427 else\r
428 Offset = EfiPciAddress->Register;\r
429\r
430 Address = PCI_ECAM_BASE + ((EfiPciAddress->Bus << 20) |\r
431 (EfiPciAddress->Device << 15) |\r
432 (EfiPciAddress->Function << 12) | Offset);\r
433\r
434 if (Address < PCI_ECAM_BASE || Address > PCI_ECAM_BASE + PCI_ECAM_SIZE) {\r
435 return EFI_INVALID_PARAMETER;\r
436 }\r
437\r
438 return CpuIo->Mem.Write (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);\r
439}\r
440\r
441EFI_STATUS\r
442PciRbCopyMem (\r
443 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
444 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
445 IN UINT64 DestAddress,\r
446 IN UINT64 SrcAddress,\r
447 IN UINTN Count\r
448 )\r
449{\r
450 EFI_STATUS Status;\r
451 BOOLEAN Direction;\r
452 UINTN Stride;\r
453 UINTN Index;\r
454 UINT64 Result;\r
455\r
456 PCI_TRACE ("PciRbCopyMem()");\r
457\r
458 if (Width > EfiPciWidthUint64) {\r
459 return EFI_INVALID_PARAMETER;\r
460 }\r
461\r
462 if (DestAddress == SrcAddress) {\r
463 return EFI_SUCCESS;\r
464 }\r
465\r
466 Stride = (UINTN)(1 << Width);\r
467\r
468 Direction = TRUE;\r
469 if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {\r
470 Direction = FALSE;\r
471 SrcAddress = SrcAddress + (Count-1) * Stride;\r
472 DestAddress = DestAddress + (Count-1) * Stride;\r
473 }\r
474\r
475 for (Index = 0; Index < Count; Index++) {\r
476 Status = PciRbMemRead (\r
477 This,\r
478 Width,\r
479 SrcAddress,\r
480 1,\r
481 &Result\r
482 );\r
483 if (EFI_ERROR (Status)) {\r
484 return Status;\r
485 }\r
486 Status = PciRbMemWrite (\r
487 This,\r
488 Width,\r
489 DestAddress,\r
490 1,\r
491 &Result\r
492 );\r
493 if (EFI_ERROR (Status)) {\r
494 return Status;\r
495 }\r
496 if (Direction) {\r
497 SrcAddress += Stride;\r
498 DestAddress += Stride;\r
499 } else {\r
500 SrcAddress -= Stride;\r
501 DestAddress -= Stride;\r
502 }\r
503 }\r
504 return EFI_SUCCESS;\r
505}\r
506\r
507EFI_STATUS\r
508PciRbMap (\r
509 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
510 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,\r
511 IN VOID *HostAddress,\r
512 IN OUT UINTN *NumberOfBytes,\r
513 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
514 OUT VOID **Mapping\r
515 )\r
516{\r
517 DMA_MAP_OPERATION DmaOperation;\r
518\r
519 PCI_TRACE ("PciRbMap()");\r
520\r
50d4be4f
DE
521 if (Operation == EfiPciOperationBusMasterRead ||\r
522 Operation == EfiPciOperationBusMasterRead64) {\r
4595449b 523 DmaOperation = MapOperationBusMasterRead;\r
50d4be4f
DE
524 } else if (Operation == EfiPciOperationBusMasterWrite ||\r
525 Operation == EfiPciOperationBusMasterWrite64) {\r
4595449b 526 DmaOperation = MapOperationBusMasterWrite;\r
50d4be4f
DE
527 } else if (Operation == EfiPciOperationBusMasterCommonBuffer ||\r
528 Operation == EfiPciOperationBusMasterCommonBuffer64) {\r
4595449b
OM
529 DmaOperation = MapOperationBusMasterCommonBuffer;\r
530 } else {\r
531 return EFI_INVALID_PARAMETER;\r
532 }\r
533 return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);\r
534}\r
535\r
536EFI_STATUS\r
537PciRbUnMap (\r
538 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
539 IN VOID *Mapping\r
540 )\r
541{\r
542 PCI_TRACE ("PciRbUnMap()");\r
543 return DmaUnmap (Mapping);\r
544}\r
545\r
546EFI_STATUS\r
547PciRbAllocateBuffer (\r
548 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
549 IN EFI_ALLOCATE_TYPE Type,\r
550 IN EFI_MEMORY_TYPE MemoryType,\r
551 IN UINTN Pages,\r
552 IN OUT VOID **HostAddress,\r
553 IN UINT64 Attributes\r
554 )\r
555{\r
556 PCI_TRACE ("PciRbAllocateBuffer()");\r
557\r
558 if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {\r
559 return EFI_UNSUPPORTED;\r
560 }\r
561\r
562 return DmaAllocateBuffer (MemoryType, Pages, HostAddress);\r
563}\r
564\r
565EFI_STATUS\r
566PciRbFreeBuffer (\r
567 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
568 IN UINTN Pages,\r
569 IN VOID *HostAddress\r
570 )\r
571{\r
572 PCI_TRACE ("PciRbFreeBuffer()");\r
573 return DmaFreeBuffer (Pages, HostAddress);\r
574}\r
575\r
576EFI_STATUS\r
577PciRbFlush (\r
578 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This\r
579 )\r
580{\r
581 PCI_TRACE ("PciRbFlush()");\r
582\r
583 //TODO: Not supported yet\r
584\r
585 return EFI_SUCCESS;\r
586}\r
587\r
588EFI_STATUS\r
589PciRbSetAttributes (\r
590 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
591 IN UINT64 Attributes,\r
592 IN OUT UINT64 *ResourceBase,\r
593 IN OUT UINT64 *ResourceLength\r
594 )\r
595{\r
596 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
597\r
598 PCI_TRACE ("PciRbSetAttributes()");\r
599\r
600 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);\r
601\r
602 if (Attributes) {\r
603 if ((Attributes & (~(RootBridgeInstance->Supports))) != 0) {\r
604 return EFI_UNSUPPORTED;\r
605 }\r
606 }\r
607\r
608 //TODO: Cannot allowed to change attributes\r
609 if (Attributes & ~RootBridgeInstance->Attributes) {\r
610 return EFI_UNSUPPORTED;\r
611 }\r
612\r
613 return EFI_SUCCESS;\r
614}\r
615\r
616EFI_STATUS\r
617PciRbGetAttributes (\r
618 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
619 OUT UINT64 *Supported,\r
620 OUT UINT64 *Attributes\r
621 )\r
622{\r
623 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
624\r
625 PCI_TRACE ("PciRbGetAttributes()");\r
626\r
627 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);\r
628\r
629 if (Attributes == NULL && Supported == NULL) {\r
630 return EFI_INVALID_PARAMETER;\r
631 }\r
632\r
633 // Set the return value for Supported and Attributes\r
634 if (Supported) {\r
635 *Supported = RootBridgeInstance->Supports;\r
636 }\r
637\r
638 if (Attributes) {\r
639 *Attributes = RootBridgeInstance->Attributes;\r
640 }\r
641\r
642 return EFI_SUCCESS;\r
643}\r
644\r
645EFI_STATUS\r
646PciRbConfiguration (\r
647 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
648 OUT VOID **Resources\r
649 )\r
650{\r
651 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
652 UINTN Index;\r
653\r
654 PCI_TRACE ("PciRbConfiguration()");\r
655\r
656 RootBridge = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);\r
657\r
658 for (Index = 0; Index < ResTypeMax; Index++) {\r
659 //if (ResAlloc[Index].Length != 0) => Resource allocated\r
660 if (RootBridge->ResAlloc[Index].Length != 0) {\r
661 Configuration.SpaceDesp[Index].AddrRangeMin = RootBridge->ResAlloc[Index].Base;\r
662 Configuration.SpaceDesp[Index].AddrRangeMax = RootBridge->ResAlloc[Index].Base + RootBridge->ResAlloc[Index].Length - 1;\r
663 Configuration.SpaceDesp[Index].AddrLen = RootBridge->ResAlloc[Index].Length;\r
664 }\r
665 }\r
666\r
667 // Set up Configuration for the bus\r
668 Configuration.SpaceDesp[Index].AddrRangeMin = RootBridge->BusStart;\r
669 Configuration.SpaceDesp[Index].AddrLen = RootBridge->BusLength;\r
670\r
671 *Resources = &Configuration;\r
672 return EFI_SUCCESS;\r
673}\r
674\r
675EFI_STATUS\r
676PciRbConstructor (\r
677 IN PCI_HOST_BRIDGE_INSTANCE *HostBridge,\r
678 IN UINT32 PciAcpiUid,\r
679 IN UINT64 MemAllocAttributes\r
680 )\r
681{\r
682 PCI_ROOT_BRIDGE_INSTANCE* RootBridge;\r
683 EFI_STATUS Status;\r
684\r
685 PCI_TRACE ("PciRbConstructor()");\r
686\r
687 // Allocate Memory for the Instance from a Template\r
688 RootBridge = AllocateZeroPool (sizeof (PCI_ROOT_BRIDGE_INSTANCE));\r
689 if (RootBridge == NULL) {\r
690 PCI_TRACE ("PciRbConstructor(): ERROR: Out of Resources");\r
691 return EFI_OUT_OF_RESOURCES;\r
692 }\r
693 RootBridge->Signature = PCI_ROOT_BRIDGE_SIGNATURE;\r
694 CopyMem (&(RootBridge->DevicePath), &gDevicePathTemplate, sizeof (EFI_PCI_ROOT_BRIDGE_DEVICE_PATH));\r
695 CopyMem (&(RootBridge->Io), &gIoTemplate, sizeof (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL));\r
696\r
697 // Set Parent Handle\r
698 RootBridge->Io.ParentHandle = HostBridge->Handle;\r
699\r
700 // Attach the Root Bridge to the PCI Host Bridge Instance\r
701 RootBridge->HostBridge = HostBridge;\r
702\r
703 // Set Device Path for this Root Bridge\r
704 RootBridge->DevicePath.Acpi.UID = PciAcpiUid;\r
705\r
706 RootBridge->BusStart = FixedPcdGet32 (PcdPciBusMin);\r
707 RootBridge->BusLength = FixedPcdGet32 (PcdPciBusMax) - FixedPcdGet32 (PcdPciBusMin) + 1;\r
708\r
709 // PCI Attributes\r
710 RootBridge->Supports = 0;\r
711 RootBridge->Attributes = 0;\r
712\r
713 // Install Protocol Instances. It will also generate a device handle for the PCI Root Bridge\r
714 Status = gBS->InstallMultipleProtocolInterfaces (\r
715 &RootBridge->Handle,\r
716 &gEfiDevicePathProtocolGuid, &RootBridge->DevicePath,\r
717 &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->Io,\r
718 NULL\r
719 );\r
720 ASSERT (RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);\r
721 if (EFI_ERROR (Status)) {\r
722 PCI_TRACE ("PciRbConstructor(): ERROR: Fail to install Protocol Interfaces");\r
723 FreePool (RootBridge);\r
724 return EFI_DEVICE_ERROR;\r
725 }\r
726\r
727 HostBridge->RootBridge = RootBridge;\r
728 return EFI_SUCCESS;\r
729}\r
730\r
731EFI_STATUS\r
732PciRbDestructor (\r
733 IN PCI_ROOT_BRIDGE_INSTANCE* RootBridge\r
734 )\r
735{\r
736 EFI_STATUS Status;\r
737\r
738 Status = gBS->UninstallMultipleProtocolInterfaces (\r
739 RootBridge->Handle,\r
740 &gEfiDevicePathProtocolGuid, &RootBridge->DevicePath,\r
741 &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->Io,\r
742 NULL\r
743 );\r
744\r
745 FreePool (RootBridge);\r
746\r
747 return Status;\r
748}\r