]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciIo.c
Clean up ECC.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciIo.c
CommitLineData
eeefcb9d 1/** @file\r
8e8227d1 2 EFI PCI IO protocol functions implementation for PCI Bus module.\r
ead42efc 3\r
8e8227d1 4Copyright (c) 2006 - 2009, Intel Corporation\r
5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
ead42efc 12\r
8e8227d1 13**/\r
ead42efc 14\r
03417d8d 15#include "PciBus.h"\r
ead42efc 16\r
ead42efc 17//\r
18// Pci Io Protocol Interface\r
19//\r
48a9ea7b 20EFI_PCI_IO_PROTOCOL mPciIoInterface = {\r
ead42efc 21 PciIoPollMem,\r
22 PciIoPollIo,\r
23 {\r
24 PciIoMemRead,\r
25 PciIoMemWrite\r
26 },\r
27 {\r
28 PciIoIoRead,\r
29 PciIoIoWrite\r
30 },\r
31 {\r
32 PciIoConfigRead,\r
33 PciIoConfigWrite\r
34 },\r
35 PciIoCopyMem,\r
36 PciIoMap,\r
37 PciIoUnmap,\r
38 PciIoAllocateBuffer,\r
39 PciIoFreeBuffer,\r
40 PciIoFlush,\r
41 PciIoGetLocation,\r
42 PciIoAttributes,\r
43 PciIoGetBarAttributes,\r
44 PciIoSetBarAttributes,\r
45 0,\r
46 NULL\r
47};\r
48\r
9f6531d1 49/**\r
8e8227d1 50 Report a error Status code of PCI bus driver controller.\r
48a9ea7b 51\r
eeefcb9d 52 @param PciIoDevice Pci device instance.\r
8e8227d1 53 @param Code Status code value.\r
54\r
57076f45 55**/\r
ead42efc 56EFI_STATUS\r
57ReportErrorStatusCode (\r
58 IN PCI_IO_DEVICE *PciIoDevice,\r
59 IN EFI_STATUS_CODE_VALUE Code\r
60 )\r
ead42efc 61{\r
62 return REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
63 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
64 Code,\r
65 PciIoDevice->DevicePath\r
66 );\r
67}\r
68\r
bcd70414 69/**\r
eeefcb9d 70 Initializes a PCI I/O Instance.\r
8e8227d1 71\r
72 @param PciIoDevice Pci device instance.\r
73\r
bcd70414 74**/\r
8e6b0dcb 75VOID\r
57076f45 76InitializePciIoInstance (\r
8e8227d1 77 IN PCI_IO_DEVICE *PciIoDevice\r
57076f45 78 )\r
ead42efc 79{\r
48a9ea7b 80 CopyMem (&PciIoDevice->PciIo, &mPciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL));\r
ead42efc 81}\r
82\r
57076f45 83/**\r
8e8227d1 84 Verifies access to a PCI Base Address Register (BAR).\r
85\r
86 @param PciIoDevice Pci device instance.\r
57076f45 87 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
8e8227d1 88 base address for the memory or I/O operation to perform.\r
89 @param Type Operation type could be memory or I/O.\r
57076f45 90 @param Width Signifies the width of the memory or I/O operations.\r
91 @param Count The number of memory or I/O operations to perform.\r
92 @param Offset The offset within the PCI configuration space for the PCI controller.\r
8e8227d1 93\r
57076f45 94 @retval EFI_INVALID_PARAMETER Invalid Width/BarIndex or Bar type.\r
8e8227d1 95 @retval EFI_SUCCESS Successfully verified.\r
96\r
57076f45 97**/\r
ead42efc 98EFI_STATUS\r
99PciIoVerifyBarAccess (\r
8e8227d1 100 IN PCI_IO_DEVICE *PciIoDevice,\r
101 IN UINT8 BarIndex,\r
102 IN PCI_BAR_TYPE Type,\r
103 IN IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
104 IN IN UINTN Count,\r
105 IN UINT64 *Offset\r
ead42efc 106 )\r
ead42efc 107{\r
108 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
109 return EFI_INVALID_PARAMETER;\r
110 }\r
111\r
112 if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) {\r
113 return EFI_SUCCESS;\r
114 }\r
115\r
116 //\r
117 // BarIndex 0-5 is legal\r
118 //\r
119 if (BarIndex >= PCI_MAX_BAR) {\r
120 return EFI_INVALID_PARAMETER;\r
121 }\r
122\r
123 if (!CheckBarType (PciIoDevice, BarIndex, Type)) {\r
124 return EFI_INVALID_PARAMETER;\r
125 }\r
126\r
127 //\r
128 // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX\r
129 // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX\r
130 //\r
131 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
132 Count = 1;\r
133 }\r
134\r
135 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
136\r
137 if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) {\r
138 return EFI_INVALID_PARAMETER;\r
139 }\r
140\r
141 *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress;\r
142\r
143 return EFI_SUCCESS;\r
144}\r
145\r
57076f45 146/**\r
8e8227d1 147 Verifies access to a PCI Configuration Header.\r
148\r
149 @param PciIoDevice Pci device instance.\r
57076f45 150 @param Width Signifies the width of the memory or I/O operations.\r
151 @param Count The number of memory or I/O operations to perform.\r
152 @param Offset The offset within the PCI configuration space for the PCI controller.\r
153\r
154 @retval EFI_INVALID_PARAMETER Invalid Width\r
8e8227d1 155 @retval EFI_UNSUPPORTED Offset overflowed.\r
156 @retval EFI_SUCCESS Successfully verified.\r
157\r
57076f45 158**/\r
ead42efc 159EFI_STATUS\r
160PciIoVerifyConfigAccess (\r
8e8227d1 161 IN PCI_IO_DEVICE *PciIoDevice,\r
ead42efc 162 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
163 IN UINTN Count,\r
164 IN UINT64 *Offset\r
165 )\r
ead42efc 166{\r
167 UINT64 ExtendOffset;\r
168\r
169 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
170 return EFI_INVALID_PARAMETER;\r
171 }\r
172\r
173 //\r
174 // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX\r
175 //\r
176 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
177\r
178 if (PciIoDevice->IsPciExp) {\r
179 if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) {\r
180 return EFI_UNSUPPORTED;\r
181 }\r
182\r
183 ExtendOffset = LShiftU64 (*Offset, 32);\r
184 *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);\r
185 *Offset = (*Offset) | ExtendOffset;\r
186\r
187 } else {\r
188 if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) {\r
189 return EFI_UNSUPPORTED;\r
190 }\r
191\r
192 *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset);\r
193 }\r
194\r
195 return EFI_SUCCESS;\r
196}\r
197\r
57076f45 198/**\r
8e8227d1 199 Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is\r
57076f45 200 satisfied or after a defined duration.\r
8e8227d1 201\r
202 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
203 @param Width Signifies the width of the memory or I/O operations.\r
204 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
205 base address for the memory operation to perform.\r
206 @param Offset The offset within the selected BAR to start the memory operation.\r
207 @param Mask Mask used for the polling criteria.\r
208 @param Value The comparison value used for the polling exit criteria.\r
209 @param Delay The number of 100 ns units to poll.\r
210 @param Result Pointer to the last value read from the memory location.\r
211\r
57076f45 212 @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.\r
8e8227d1 213 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
214 @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of this PCI controller.\r
57076f45 215 @retval EFI_TIMEOUT Delay expired before a match occurred.\r
216 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
217 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
8e8227d1 218\r
57076f45 219**/\r
ead42efc 220EFI_STATUS\r
221EFIAPI\r
222PciIoPollMem (\r
223 IN EFI_PCI_IO_PROTOCOL *This,\r
224 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
225 IN UINT8 BarIndex,\r
226 IN UINT64 Offset,\r
227 IN UINT64 Mask,\r
228 IN UINT64 Value,\r
229 IN UINT64 Delay,\r
230 OUT UINT64 *Result\r
231 )\r
ead42efc 232{\r
233 EFI_STATUS Status;\r
234 PCI_IO_DEVICE *PciIoDevice;\r
235\r
236 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
237\r
238 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
239 return EFI_INVALID_PARAMETER;\r
240 }\r
241\r
242 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset);\r
243 if (EFI_ERROR (Status)) {\r
244 return EFI_UNSUPPORTED;\r
245 }\r
246\r
247 if (Width > EfiPciIoWidthUint64) {\r
248 return EFI_INVALID_PARAMETER;\r
249 }\r
250\r
251 Status = PciIoDevice->PciRootBridgeIo->PollMem (\r
8e8227d1 252 PciIoDevice->PciRootBridgeIo,\r
253 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
254 Offset,\r
255 Mask,\r
256 Value,\r
257 Delay,\r
258 Result\r
259 );\r
ead42efc 260\r
261 if (EFI_ERROR (Status)) {\r
262 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
263 }\r
264\r
265 return Status;\r
266}\r
267\r
8e8227d1 268/**\r
269 Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is\r
57076f45 270 satisfied or after a defined duration.\r
8e8227d1 271\r
272 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
57076f45 273 @param Width Signifies the width of the memory or I/O operations.\r
eeefcb9d 274 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
8e8227d1 275 base address for the memory operation to perform.\r
276 @param Offset The offset within the selected BAR to start the memory operation.\r
57076f45 277 @param Mask Mask used for the polling criteria.\r
278 @param Value The comparison value used for the polling exit criteria.\r
279 @param Delay The number of 100 ns units to poll.\r
280 @param Result Pointer to the last value read from the memory location.\r
8e8227d1 281\r
57076f45 282 @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.\r
8e8227d1 283 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
284 @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of this PCI controller.\r
57076f45 285 @retval EFI_TIMEOUT Delay expired before a match occurred.\r
286 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
287 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
8e8227d1 288\r
57076f45 289**/\r
ead42efc 290EFI_STATUS\r
291EFIAPI\r
292PciIoPollIo (\r
293 IN EFI_PCI_IO_PROTOCOL *This,\r
294 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
295 IN UINT8 BarIndex,\r
296 IN UINT64 Offset,\r
297 IN UINT64 Mask,\r
298 IN UINT64 Value,\r
299 IN UINT64 Delay,\r
300 OUT UINT64 *Result\r
301 )\r
ead42efc 302{\r
303 EFI_STATUS Status;\r
304 PCI_IO_DEVICE *PciIoDevice;\r
305\r
306 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
307\r
308 if (Width < 0 || Width > EfiPciIoWidthUint64) {\r
309 return EFI_INVALID_PARAMETER;\r
310 }\r
311\r
312 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset);\r
313 if (EFI_ERROR (Status)) {\r
314 return EFI_UNSUPPORTED;\r
315 }\r
316\r
317 Status = PciIoDevice->PciRootBridgeIo->PollIo (\r
8e8227d1 318 PciIoDevice->PciRootBridgeIo,\r
319 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
320 Offset,\r
321 Mask,\r
322 Value,\r
323 Delay,\r
324 Result\r
325 );\r
ead42efc 326\r
327 if (EFI_ERROR (Status)) {\r
328 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
329 }\r
330\r
331 return Status;\r
332}\r
333\r
8e8227d1 334/**\r
57076f45 335 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
8e8227d1 336\r
57076f45 337 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
338 @param Width Signifies the width of the memory or I/O operations.\r
339 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
8e8227d1 340 base address for the memory or I/O operation to perform.\r
341 @param Offset The offset within the selected BAR to start the memory or I/O operation.\r
57076f45 342 @param Count The number of memory or I/O operations to perform.\r
343 @param Buffer For read operations, the destination buffer to store the results. For write\r
8e8227d1 344 operations, the source buffer to write data from.\r
345\r
57076f45 346 @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
347 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
348 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
8e8227d1 349 valid for the PCI BAR specified by BarIndex.\r
57076f45 350 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
351 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
8e8227d1 352\r
57076f45 353**/\r
ead42efc 354EFI_STATUS\r
355EFIAPI\r
356PciIoMemRead (\r
357 IN EFI_PCI_IO_PROTOCOL *This,\r
358 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
359 IN UINT8 BarIndex,\r
360 IN UINT64 Offset,\r
361 IN UINTN Count,\r
362 IN OUT VOID *Buffer\r
363 )\r
ead42efc 364{\r
365 EFI_STATUS Status;\r
366 PCI_IO_DEVICE *PciIoDevice;\r
367\r
368 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
369\r
370 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
371 return EFI_INVALID_PARAMETER;\r
372 }\r
373\r
9a2d4fe9 374 if (Buffer == NULL) {\r
375 return EFI_INVALID_PARAMETER;\r
376 }\r
377\r
ead42efc 378 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);\r
379 if (EFI_ERROR (Status)) {\r
380 return EFI_UNSUPPORTED;\r
381 }\r
382\r
383 Status = PciIoDevice->PciRootBridgeIo->Mem.Read (\r
384 PciIoDevice->PciRootBridgeIo,\r
385 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
386 Offset,\r
387 Count,\r
388 Buffer\r
389 );\r
390\r
391 if (EFI_ERROR (Status)) {\r
392 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);\r
393 }\r
394\r
395 return Status;\r
396}\r
397\r
8e8227d1 398/**\r
57076f45 399 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
8e8227d1 400\r
57076f45 401 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
402 @param Width Signifies the width of the memory or I/O operations.\r
403 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
8e8227d1 404 base address for the memory or I/O operation to perform.\r
405 @param Offset The offset within the selected BAR to start the memory or I/O operation.\r
57076f45 406 @param Count The number of memory or I/O operations to perform.\r
407 @param Buffer For read operations, the destination buffer to store the results. For write\r
8e8227d1 408 operations, the source buffer to write data from.\r
409\r
57076f45 410 @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
411 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
412 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
8e8227d1 413 valid for the PCI BAR specified by BarIndex.\r
57076f45 414 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
415 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
8e8227d1 416\r
57076f45 417**/\r
ead42efc 418EFI_STATUS\r
419EFIAPI\r
420PciIoMemWrite (\r
421 IN EFI_PCI_IO_PROTOCOL *This,\r
422 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
423 IN UINT8 BarIndex,\r
424 IN UINT64 Offset,\r
425 IN UINTN Count,\r
426 IN OUT VOID *Buffer\r
427 )\r
ead42efc 428{\r
429 EFI_STATUS Status;\r
430 PCI_IO_DEVICE *PciIoDevice;\r
431\r
432 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
433\r
434 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
435 return EFI_INVALID_PARAMETER;\r
436 }\r
437\r
9a2d4fe9 438 if (Buffer == NULL) {\r
439 return EFI_INVALID_PARAMETER;\r
440 }\r
441\r
ead42efc 442 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);\r
443 if (EFI_ERROR (Status)) {\r
444 return EFI_UNSUPPORTED;\r
445 }\r
446\r
447 Status = PciIoDevice->PciRootBridgeIo->Mem.Write (\r
448 PciIoDevice->PciRootBridgeIo,\r
449 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
450 Offset,\r
451 Count,\r
452 Buffer\r
453 );\r
454\r
455 if (EFI_ERROR (Status)) {\r
456 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);\r
457 }\r
458\r
459 return Status;\r
460}\r
461\r
8e8227d1 462/**\r
57076f45 463 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
8e8227d1 464\r
57076f45 465 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
466 @param Width Signifies the width of the memory or I/O operations.\r
467 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
8e8227d1 468 base address for the memory or I/O operation to perform.\r
469 @param Offset The offset within the selected BAR to start the memory or I/O operation.\r
57076f45 470 @param Count The number of memory or I/O operations to perform.\r
471 @param Buffer For read operations, the destination buffer to store the results. For write\r
8e8227d1 472 operations, the source buffer to write data from.\r
473\r
57076f45 474 @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
475 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
476 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
8e8227d1 477 valid for the PCI BAR specified by BarIndex.\r
57076f45 478 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
479 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
8e8227d1 480\r
57076f45 481**/\r
ead42efc 482EFI_STATUS\r
483EFIAPI\r
484PciIoIoRead (\r
485 IN EFI_PCI_IO_PROTOCOL *This,\r
486 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
487 IN UINT8 BarIndex,\r
488 IN UINT64 Offset,\r
489 IN UINTN Count,\r
490 IN OUT VOID *Buffer\r
491 )\r
ead42efc 492{\r
493 EFI_STATUS Status;\r
494 PCI_IO_DEVICE *PciIoDevice;\r
495\r
496 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
497\r
498 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
499 return EFI_INVALID_PARAMETER;\r
500 }\r
501\r
9a2d4fe9 502 if (Buffer == NULL) {\r
503 return EFI_INVALID_PARAMETER;\r
504 }\r
505\r
ead42efc 506 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);\r
507 if (EFI_ERROR (Status)) {\r
508 return EFI_UNSUPPORTED;\r
509 }\r
510\r
511 Status = PciIoDevice->PciRootBridgeIo->Io.Read (\r
512 PciIoDevice->PciRootBridgeIo,\r
513 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
514 Offset,\r
515 Count,\r
516 Buffer\r
517 );\r
518\r
519 if (EFI_ERROR (Status)) {\r
520 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);\r
521 }\r
522\r
523 return Status;\r
524}\r
525\r
8e8227d1 526/**\r
57076f45 527 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
8e8227d1 528\r
57076f45 529 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
530 @param Width Signifies the width of the memory or I/O operations.\r
531 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
8e8227d1 532 base address for the memory or I/O operation to perform.\r
533 @param Offset The offset within the selected BAR to start the memory or I/O operation.\r
57076f45 534 @param Count The number of memory or I/O operations to perform.\r
535 @param Buffer For read operations, the destination buffer to store the results. For write\r
8e8227d1 536 operations, the source buffer to write data from.\r
537\r
57076f45 538 @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
539 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
540 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
8e8227d1 541 valid for the PCI BAR specified by BarIndex.\r
57076f45 542 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
543 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
8e8227d1 544\r
57076f45 545**/\r
ead42efc 546EFI_STATUS\r
547EFIAPI\r
548PciIoIoWrite (\r
549 IN EFI_PCI_IO_PROTOCOL *This,\r
550 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
551 IN UINT8 BarIndex,\r
552 IN UINT64 Offset,\r
553 IN UINTN Count,\r
554 IN OUT VOID *Buffer\r
555 )\r
ead42efc 556{\r
557 EFI_STATUS Status;\r
558 PCI_IO_DEVICE *PciIoDevice;\r
559\r
560 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
561\r
562 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
563 return EFI_INVALID_PARAMETER;\r
564 }\r
565\r
9a2d4fe9 566 if (Buffer == NULL) {\r
567 return EFI_INVALID_PARAMETER;\r
568 }\r
569\r
ead42efc 570 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);\r
571 if (EFI_ERROR (Status)) {\r
572 return EFI_UNSUPPORTED;\r
573 }\r
574\r
575 Status = PciIoDevice->PciRootBridgeIo->Io.Write (\r
576 PciIoDevice->PciRootBridgeIo,\r
577 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
578 Offset,\r
579 Count,\r
580 Buffer\r
581 );\r
582\r
583 if (EFI_ERROR (Status)) {\r
584 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);\r
585 }\r
586\r
587 return Status;\r
588}\r
589\r
8e8227d1 590/**\r
57076f45 591 Enable a PCI driver to access PCI controller registers in PCI configuration space.\r
8e8227d1 592\r
593 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
57076f45 594 @param Width Signifies the width of the memory operations.\r
595 @param Offset The offset within the PCI configuration space for the PCI controller.\r
596 @param Count The number of PCI configuration operations to perform.\r
597 @param Buffer For read operations, the destination buffer to store the results. For write\r
598 operations, the source buffer to write data from.\r
8e8227d1 599\r
600\r
57076f45 601 @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
602 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
603 valid for the PCI configuration header of the PCI controller.\r
8e8227d1 604 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
605 @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.\r
606\r
57076f45 607**/\r
ead42efc 608EFI_STATUS\r
609EFIAPI\r
610PciIoConfigRead (\r
611 IN EFI_PCI_IO_PROTOCOL *This,\r
612 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
613 IN UINT32 Offset,\r
614 IN UINTN Count,\r
615 IN OUT VOID *Buffer\r
616 )\r
ead42efc 617{\r
618 EFI_STATUS Status;\r
619 PCI_IO_DEVICE *PciIoDevice;\r
620 UINT64 Address;\r
621\r
622 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
623\r
624 Address = Offset;\r
625 Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);\r
626 if (EFI_ERROR (Status)) {\r
627 return Status;\r
628 }\r
629\r
630 Status = PciIoDevice->PciRootBridgeIo->Pci.Read (\r
631 PciIoDevice->PciRootBridgeIo,\r
632 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
633 Address,\r
634 Count,\r
635 Buffer\r
636 );\r
637\r
638 if (EFI_ERROR (Status)) {\r
639 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);\r
640 }\r
641\r
642 return Status;\r
643}\r
644\r
8e8227d1 645/**\r
57076f45 646 Enable a PCI driver to access PCI controller registers in PCI configuration space.\r
8e8227d1 647\r
648 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
57076f45 649 @param Width Signifies the width of the memory operations.\r
650 @param Offset The offset within the PCI configuration space for the PCI controller.\r
651 @param Count The number of PCI configuration operations to perform.\r
652 @param Buffer For read operations, the destination buffer to store the results. For write\r
653 operations, the source buffer to write data from.\r
8e8227d1 654\r
655\r
57076f45 656 @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
657 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
658 valid for the PCI configuration header of the PCI controller.\r
8e8227d1 659 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
660 @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.\r
661\r
57076f45 662**/\r
ead42efc 663EFI_STATUS\r
664EFIAPI\r
665PciIoConfigWrite (\r
666 IN EFI_PCI_IO_PROTOCOL *This,\r
667 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
668 IN UINT32 Offset,\r
669 IN UINTN Count,\r
670 IN OUT VOID *Buffer\r
671 )\r
ead42efc 672{\r
673 EFI_STATUS Status;\r
674 PCI_IO_DEVICE *PciIoDevice;\r
675 UINT64 Address;\r
676\r
677 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
678\r
679 Address = Offset;\r
680 Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);\r
681 if (EFI_ERROR (Status)) {\r
682 return Status;\r
683 }\r
684\r
685 Status = PciIoDevice->PciRootBridgeIo->Pci.Write (\r
686 PciIoDevice->PciRootBridgeIo,\r
687 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
688 Address,\r
689 Count,\r
690 Buffer\r
691 );\r
692\r
693 if (EFI_ERROR (Status)) {\r
694 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);\r
695 }\r
696\r
697 return Status;\r
698}\r
699\r
8e8227d1 700/**\r
57076f45 701 Enables a PCI driver to copy one region of PCI memory space to another region of PCI\r
702 memory space.\r
8e8227d1 703\r
57076f45 704 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
705 @param Width Signifies the width of the memory operations.\r
706 @param DestBarIndex The BAR index in the standard PCI Configuration header to use as the\r
8e8227d1 707 base address for the memory operation to perform.\r
57076f45 708 @param DestOffset The destination offset within the BAR specified by DestBarIndex to\r
8e8227d1 709 start the memory writes for the copy operation.\r
57076f45 710 @param SrcBarIndex The BAR index in the standard PCI Configuration header to use as the\r
8e8227d1 711 base address for the memory operation to perform.\r
57076f45 712 @param SrcOffset The source offset within the BAR specified by SrcBarIndex to start\r
8e8227d1 713 the memory reads for the copy operation.\r
57076f45 714 @param Count The number of memory operations to perform. Bytes moved is Width\r
8e8227d1 715 size * Count, starting at DestOffset and SrcOffset.\r
716\r
57076f45 717 @retval EFI_SUCCESS The data was copied from one memory region to another memory region.\r
718 @retval EFI_UNSUPPORTED DestBarIndex not valid for this PCI controller.\r
719 @retval EFI_UNSUPPORTED SrcBarIndex not valid for this PCI controller.\r
720 @retval EFI_UNSUPPORTED The address range specified by DestOffset, Width, and Count\r
8e8227d1 721 is not valid for the PCI BAR specified by DestBarIndex.\r
57076f45 722 @retval EFI_UNSUPPORTED The address range specified by SrcOffset, Width, and Count is\r
8e8227d1 723 not valid for the PCI BAR specified by SrcBarIndex.\r
57076f45 724 @retval EFI_INVALID_PARAMETER Width is invalid.\r
725 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
8e8227d1 726\r
57076f45 727**/\r
ead42efc 728EFI_STATUS\r
729EFIAPI\r
730PciIoCopyMem (\r
731 IN EFI_PCI_IO_PROTOCOL *This,\r
732 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
733 IN UINT8 DestBarIndex,\r
734 IN UINT64 DestOffset,\r
735 IN UINT8 SrcBarIndex,\r
736 IN UINT64 SrcOffset,\r
737 IN UINTN Count\r
738 )\r
ead42efc 739{\r
740 EFI_STATUS Status;\r
741 PCI_IO_DEVICE *PciIoDevice;\r
742\r
743 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
744\r
745 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
746 return EFI_INVALID_PARAMETER;\r
747 }\r
748\r
749 if (Width == EfiPciIoWidthFifoUint8 ||\r
750 Width == EfiPciIoWidthFifoUint16 ||\r
751 Width == EfiPciIoWidthFifoUint32 ||\r
752 Width == EfiPciIoWidthFifoUint64 ||\r
753 Width == EfiPciIoWidthFillUint8 ||\r
754 Width == EfiPciIoWidthFillUint16 ||\r
755 Width == EfiPciIoWidthFillUint32 ||\r
756 Width == EfiPciIoWidthFillUint64) {\r
757 return EFI_INVALID_PARAMETER;\r
758 }\r
759\r
760 Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset);\r
761 if (EFI_ERROR (Status)) {\r
762 return EFI_UNSUPPORTED;\r
763 }\r
764\r
765 Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset);\r
766 if (EFI_ERROR (Status)) {\r
767 return EFI_UNSUPPORTED;\r
768 }\r
769\r
770 Status = PciIoDevice->PciRootBridgeIo->CopyMem (\r
771 PciIoDevice->PciRootBridgeIo,\r
772 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
773 DestOffset,\r
774 SrcOffset,\r
775 Count\r
776 );\r
777\r
778 if (EFI_ERROR (Status)) {\r
779 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
780 }\r
781\r
782 return Status;\r
783}\r
784\r
8e8227d1 785/**\r
786 Provides the PCI controller-specific addresses needed to access system memory.\r
787\r
57076f45 788 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
789 @param Operation Indicates if the bus master is going to read or write to system memory.\r
790 @param HostAddress The system memory address to map to the PCI controller.\r
791 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes\r
8e8227d1 792 that were mapped.\r
57076f45 793 @param DeviceAddress The resulting map address for the bus master PCI controller to use to\r
8e8227d1 794 access the hosts HostAddress.\r
57076f45 795 @param Mapping A resulting value to pass to Unmap().\r
8e8227d1 796\r
57076f45 797 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.\r
8e8227d1 798 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.\r
57076f45 799 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
800 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
801 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.\r
8e8227d1 802\r
57076f45 803**/\r
ead42efc 804EFI_STATUS\r
805EFIAPI\r
806PciIoMap (\r
807 IN EFI_PCI_IO_PROTOCOL *This,\r
808 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,\r
809 IN VOID *HostAddress,\r
810 IN OUT UINTN *NumberOfBytes,\r
811 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
812 OUT VOID **Mapping\r
813 )\r
ead42efc 814{\r
815 EFI_STATUS Status;\r
816 PCI_IO_DEVICE *PciIoDevice;\r
817\r
818 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
819\r
820 if (Operation < 0 || Operation >= EfiPciIoOperationMaximum) {\r
821 return EFI_INVALID_PARAMETER;\r
822 }\r
823\r
824 if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {\r
825 return EFI_INVALID_PARAMETER;\r
826 }\r
827\r
97404058 828 if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {\r
ead42efc 829 Operation = (EFI_PCI_IO_PROTOCOL_OPERATION) (Operation + EfiPciOperationBusMasterRead64);\r
830 }\r
831\r
832 Status = PciIoDevice->PciRootBridgeIo->Map (\r
833 PciIoDevice->PciRootBridgeIo,\r
834 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,\r
835 HostAddress,\r
836 NumberOfBytes,\r
837 DeviceAddress,\r
838 Mapping\r
839 );\r
840\r
841 if (EFI_ERROR (Status)) {\r
842 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
843 }\r
844\r
845 return Status;\r
846}\r
847\r
8e8227d1 848/**\r
57076f45 849 Completes the Map() operation and releases any corresponding resources.\r
8e8227d1 850\r
851 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
57076f45 852 @param Mapping The mapping value returned from Map().\r
8e8227d1 853\r
57076f45 854 @retval EFI_SUCCESS The range was unmapped.\r
855 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.\r
8e8227d1 856\r
57076f45 857**/\r
ead42efc 858EFI_STATUS\r
859EFIAPI\r
860PciIoUnmap (\r
861 IN EFI_PCI_IO_PROTOCOL *This,\r
862 IN VOID *Mapping\r
863 )\r
ead42efc 864{\r
865 EFI_STATUS Status;\r
866 PCI_IO_DEVICE *PciIoDevice;\r
867\r
868 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
869\r
870 Status = PciIoDevice->PciRootBridgeIo->Unmap (\r
871 PciIoDevice->PciRootBridgeIo,\r
872 Mapping\r
873 );\r
874\r
875 if (EFI_ERROR (Status)) {\r
876 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
877 }\r
878\r
879 return Status;\r
880}\r
881\r
8e8227d1 882/**\r
57076f45 883 Allocates pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer\r
8e8227d1 884 mapping.\r
885\r
57076f45 886 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
887 @param Type This parameter is not used and must be ignored.\r
888 @param MemoryType The type of memory to allocate, EfiBootServicesData or\r
8e8227d1 889 EfiRuntimeServicesData.\r
890 @param Pages The number of pages to allocate.\r
57076f45 891 @param HostAddress A pointer to store the base system memory address of the\r
8e8227d1 892 allocated range.\r
57076f45 893 @param Attributes The requested bit mask of attributes for the allocated range.\r
8e8227d1 894\r
57076f45 895 @retval EFI_SUCCESS The requested memory pages were allocated.\r
896 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are\r
8e8227d1 897 MEMORY_WRITE_COMBINE and MEMORY_CACHED.\r
57076f45 898 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
8e8227d1 899 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.\r
900\r
57076f45 901**/\r
ead42efc 902EFI_STATUS\r
903EFIAPI\r
904PciIoAllocateBuffer (\r
905 IN EFI_PCI_IO_PROTOCOL *This,\r
906 IN EFI_ALLOCATE_TYPE Type,\r
907 IN EFI_MEMORY_TYPE MemoryType,\r
908 IN UINTN Pages,\r
909 OUT VOID **HostAddress,\r
910 IN UINT64 Attributes\r
911 )\r
ead42efc 912{\r
913 EFI_STATUS Status;\r
914 PCI_IO_DEVICE *PciIoDevice;\r
915\r
97404058 916 if ((Attributes &\r
917 (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) != 0){\r
ead42efc 918 return EFI_UNSUPPORTED;\r
919 }\r
920\r
921 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
922\r
97404058 923 if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {\r
ead42efc 924 Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
925 }\r
926\r
927 Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer (\r
928 PciIoDevice->PciRootBridgeIo,\r
929 Type,\r
930 MemoryType,\r
931 Pages,\r
932 HostAddress,\r
933 Attributes\r
934 );\r
935\r
936 if (EFI_ERROR (Status)) {\r
937 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
938 }\r
939\r
940 return Status;\r
941}\r
942\r
8e8227d1 943/**\r
57076f45 944 Frees memory that was allocated with AllocateBuffer().\r
8e8227d1 945\r
946 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
947 @param Pages The number of pages to free.\r
948 @param HostAddress The base system memory address of the allocated range.\r
949\r
57076f45 950 @retval EFI_SUCCESS The requested memory pages were freed.\r
951 @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages\r
952 was not allocated with AllocateBuffer().\r
8e8227d1 953\r
57076f45 954**/\r
ead42efc 955EFI_STATUS\r
956EFIAPI\r
957PciIoFreeBuffer (\r
958 IN EFI_PCI_IO_PROTOCOL *This,\r
959 IN UINTN Pages,\r
960 IN VOID *HostAddress\r
961 )\r
ead42efc 962{\r
963 EFI_STATUS Status;\r
964 PCI_IO_DEVICE *PciIoDevice;\r
965\r
966 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
967\r
968 Status = PciIoDevice->PciRootBridgeIo->FreeBuffer (\r
969 PciIoDevice->PciRootBridgeIo,\r
970 Pages,\r
971 HostAddress\r
972 );\r
973\r
974 if (EFI_ERROR (Status)) {\r
975 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
976 }\r
977\r
978 return Status;\r
979}\r
980\r
8e8227d1 981/**\r
57076f45 982 Flushes all PCI posted write transactions from a PCI host bridge to system memory.\r
8e8227d1 983\r
984 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
985\r
57076f45 986 @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host\r
8e8227d1 987 bridge to system memory.\r
57076f45 988 @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI\r
8e8227d1 989 host bridge due to a hardware error.\r
990\r
57076f45 991**/\r
ead42efc 992EFI_STATUS\r
993EFIAPI\r
994PciIoFlush (\r
995 IN EFI_PCI_IO_PROTOCOL *This\r
996 )\r
ead42efc 997{\r
998 EFI_STATUS Status;\r
999 PCI_IO_DEVICE *PciIoDevice;\r
1000\r
1001 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
1002\r
1003 Status = PciIoDevice->PciRootBridgeIo->Flush (\r
1004 PciIoDevice->PciRootBridgeIo\r
1005 );\r
1006 if (EFI_ERROR (Status)) {\r
1007 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
1008 }\r
1009\r
1010 return Status;\r
1011}\r
1012\r
8e8227d1 1013/**\r
57076f45 1014 Retrieves this PCI controller's current PCI bus number, device number, and function number.\r
8e8227d1 1015\r
1016 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
57076f45 1017 @param SegmentNumber The PCI controller's current PCI segment number.\r
1018 @param BusNumber The PCI controller's current PCI bus number.\r
1019 @param DeviceNumber The PCI controller's current PCI device number.\r
1020 @param FunctionNumber The PCI controller's current PCI function number.\r
8e8227d1 1021\r
1022 @retval EFI_SUCCESS The PCI controller location was returned.\r
1023 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
1024\r
57076f45 1025**/\r
ead42efc 1026EFI_STATUS\r
1027EFIAPI\r
1028PciIoGetLocation (\r
1029 IN EFI_PCI_IO_PROTOCOL *This,\r
1030 OUT UINTN *Segment,\r
1031 OUT UINTN *Bus,\r
1032 OUT UINTN *Device,\r
1033 OUT UINTN *Function\r
1034 )\r
ead42efc 1035{\r
1036 PCI_IO_DEVICE *PciIoDevice;\r
1037\r
1038 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
1039\r
1040 if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) {\r
1041 return EFI_INVALID_PARAMETER;\r
1042 }\r
1043\r
1044 *Segment = PciIoDevice->PciRootBridgeIo->SegmentNumber;\r
1045 *Bus = PciIoDevice->BusNumber;\r
1046 *Device = PciIoDevice->DeviceNumber;\r
1047 *Function = PciIoDevice->FunctionNumber;\r
1048\r
1049 return EFI_SUCCESS;\r
1050}\r
1051\r
57076f45 1052/**\r
1053 Check BAR type for PCI resource.\r
8e8227d1 1054\r
1055 @param PciIoDevice PCI device instance.\r
57076f45 1056 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
8e8227d1 1057 base address for the memory or I/O operation to perform.\r
1058 @param BarType Memory or I/O.\r
1059\r
1060 @retval TRUE Pci device's bar type is same with input BarType.\r
1061 @retval TRUE Pci device's bar type is not same with input BarType.\r
1062\r
57076f45 1063**/\r
ead42efc 1064BOOLEAN\r
1065CheckBarType (\r
8e8227d1 1066 IN PCI_IO_DEVICE *PciIoDevice,\r
1067 IN UINT8 BarIndex,\r
1068 IN PCI_BAR_TYPE BarType\r
ead42efc 1069 )\r
ead42efc 1070{\r
1071 switch (BarType) {\r
1072\r
1073 case PciBarTypeMem:\r
1074\r
1075 if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32 &&\r
1076 PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 &&\r
1077 PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 &&\r
1078 PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64 ) {\r
1079 return FALSE;\r
1080 }\r
1081\r
1082 return TRUE;\r
1083\r
1084 case PciBarTypeIo:\r
1085 if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 &&\r
1086 PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){\r
1087 return FALSE;\r
1088 }\r
1089\r
1090 return TRUE;\r
1091\r
1092 default:\r
1093 break;\r
1094 }\r
1095\r
1096 return FALSE;\r
1097}\r
1098\r
57076f45 1099/**\r
8e8227d1 1100 Set/Disable new attributes to a Root Bridge.\r
1101\r
1102 @param PciIoDevice Pci device instance.\r
1103 @param Attributes New attribute want to be set.\r
1104 @param Operation Set or Disable.\r
1105\r
1106 @retval EFI_UNSUPPORTED If root bridge does not support change attribute.\r
1107 @retval EFI_SUCCESS Successfully set new attributs.\r
1108\r
57076f45 1109**/\r
ead42efc 1110EFI_STATUS\r
1111ModifyRootBridgeAttributes (\r
1112 IN PCI_IO_DEVICE *PciIoDevice,\r
1113 IN UINT64 Attributes,\r
1114 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation\r
1115 )\r
ead42efc 1116{\r
1117 UINT64 PciRootBridgeSupports;\r
1118 UINT64 PciRootBridgeAttributes;\r
1119 UINT64 NewPciRootBridgeAttributes;\r
1120 EFI_STATUS Status;\r
1121\r
1122 //\r
1123 // Get the current attributes of this PCI device's PCI Root Bridge\r
1124 //\r
1125 Status = PciIoDevice->PciRootBridgeIo->GetAttributes (\r
1126 PciIoDevice->PciRootBridgeIo,\r
1127 &PciRootBridgeSupports,\r
1128 &PciRootBridgeAttributes\r
1129 );\r
1130 if (EFI_ERROR (Status)) {\r
1131 return EFI_UNSUPPORTED;\r
1132 }\r
8e8227d1 1133\r
ead42efc 1134 //\r
1135 // Record the new attribute of the Root Bridge\r
1136 //\r
1137 if (Operation == EfiPciIoAttributeOperationEnable) {\r
1138 NewPciRootBridgeAttributes = PciRootBridgeAttributes | Attributes;\r
1139 } else {\r
1140 NewPciRootBridgeAttributes = PciRootBridgeAttributes & (~Attributes);\r
1141 }\r
8e8227d1 1142\r
ead42efc 1143 //\r
1144 // Call the PCI Root Bridge to attempt to modify the attributes\r
1145 //\r
97404058 1146 if ((NewPciRootBridgeAttributes ^ PciRootBridgeAttributes) != 0) {\r
ead42efc 1147\r
1148 Status = PciIoDevice->PciRootBridgeIo->SetAttributes (\r
1149 PciIoDevice->PciRootBridgeIo,\r
1150 NewPciRootBridgeAttributes,\r
1151 NULL,\r
1152 NULL\r
1153 );\r
1154 if (EFI_ERROR (Status)) {\r
1155 //\r
1156 // The PCI Root Bridge could not modify the attributes, so return the error.\r
1157 //\r
1158 return EFI_UNSUPPORTED;\r
1159 }\r
1160 }\r
8e8227d1 1161\r
ead42efc 1162 //\r
1163 // Also update the attributes for this Root Bridge structure\r
1164 //\r
1165 PciIoDevice->Attributes = NewPciRootBridgeAttributes;\r
ead42efc 1166\r
8e8227d1 1167 return EFI_SUCCESS;\r
ead42efc 1168}\r
1169\r
57076f45 1170/**\r
8e8227d1 1171 Check whether this device can be enable/disable to snoop.\r
1172\r
1173 @param PciIoDevice Pci device instance.\r
1174 @param Operation Enable/Disable.\r
1175\r
1176 @retval EFI_UNSUPPORTED Pci device is not GFX device or not support snoop.\r
57076f45 1177 @retval EFI_SUCCESS Snoop can be supported.\r
8e8227d1 1178\r
57076f45 1179**/\r
ead42efc 1180EFI_STATUS\r
1181SupportPaletteSnoopAttributes (\r
8e8227d1 1182 IN PCI_IO_DEVICE *PciIoDevice,\r
1183 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation\r
ead42efc 1184 )\r
ead42efc 1185{\r
1186 PCI_IO_DEVICE *Temp;\r
1187 UINT16 VGACommand;\r
1188\r
1189 //\r
1190 // Snoop attribute can be only modified by GFX\r
1191 //\r
1192 if (!IS_PCI_GFX (&PciIoDevice->Pci)) {\r
1193 return EFI_UNSUPPORTED;\r
1194 }\r
1195\r
1196 //\r
1197 // Get the boot VGA on the same segement\r
1198 //\r
1199 Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);\r
1200\r
97404058 1201 if (Temp == NULL) {\r
ead42efc 1202 //\r
1203 // If there is no VGA device on the segement, set\r
1204 // this graphics card to decode the palette range\r
1205 //\r
1206 return EFI_SUCCESS;\r
1207 }\r
8e8227d1 1208\r
ead42efc 1209 //\r
1210 // Check these two agents are on the same path\r
1211 //\r
1212 if (!PciDevicesOnTheSamePath (Temp, PciIoDevice)) {\r
1213 //\r
1214 // they are not on the same path, so snoop can be enabled or disabled\r
1215 //\r
1216 return EFI_SUCCESS;\r
1217 }\r
1218 //\r
1219 // Check if they are on the same bus\r
1220 //\r
1221 if (Temp->Parent == PciIoDevice->Parent) {\r
1222\r
94b9d5c6 1223 PCI_READ_COMMAND_REGISTER (Temp, &VGACommand);\r
ead42efc 1224\r
1225 //\r
1226 // If they are on the same bus, either one can\r
1227 // be set to snoop, the other set to decode\r
1228 //\r
97404058 1229 if ((VGACommand & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {\r
ead42efc 1230 //\r
1231 // VGA has set to snoop, so GFX can be only set to disable snoop\r
1232 //\r
1233 if (Operation == EfiPciIoAttributeOperationEnable) {\r
1234 return EFI_UNSUPPORTED;\r
1235 }\r
1236 } else {\r
1237 //\r
1238 // VGA has disabled to snoop, so GFX can be only enabled\r
1239 //\r
1240 if (Operation == EfiPciIoAttributeOperationDisable) {\r
1241 return EFI_UNSUPPORTED;\r
1242 }\r
1243 }\r
1244\r
1245 return EFI_SUCCESS;\r
1246 }\r
8e8227d1 1247\r
ead42efc 1248 //\r
1249 // If they are on the same path but on the different bus\r
1250 // The first agent is set to snoop, the second one set to\r
1251 // decode\r
1252 //\r
8e8227d1 1253\r
ead42efc 1254 if (Temp->BusNumber < PciIoDevice->BusNumber) {\r
1255 //\r
1256 // GFX should be set to decode\r
1257 //\r
1258 if (Operation == EfiPciIoAttributeOperationDisable) {\r
94b9d5c6 1259 PCI_ENABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
ead42efc 1260 Temp->Attributes |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
1261 } else {\r
1262 return EFI_UNSUPPORTED;\r
1263 }\r
1264\r
1265 } else {\r
1266 //\r
1267 // GFX should be set to snoop\r
1268 //\r
1269 if (Operation == EfiPciIoAttributeOperationEnable) {\r
94b9d5c6 1270 PCI_DISABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
ead42efc 1271 Temp->Attributes &= (~EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
1272 } else {\r
1273 return EFI_UNSUPPORTED;\r
1274 }\r
1275\r
1276 }\r
1277\r
1278 return EFI_SUCCESS;\r
1279}\r
1280\r
8e8227d1 1281/**\r
57076f45 1282 Performs an operation on the attributes that this PCI controller supports. The operations include\r
8e8227d1 1283 getting the set of supported attributes, retrieving the current attributes, setting the current\r
1284 attributes, enabling attributes, and disabling attributes.\r
1285\r
1286 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
57076f45 1287 @param Operation The operation to perform on the attributes for this PCI controller.\r
1288 @param Attributes The mask of attributes that are used for Set, Enable, and Disable\r
8e8227d1 1289 operations.\r
57076f45 1290 @param Result A pointer to the result mask of attributes that are returned for the Get\r
8e8227d1 1291 and Supported operations.\r
1292\r
57076f45 1293 @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.\r
8e8227d1 1294 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
1295 @retval EFI_UNSUPPORTED one or more of the bits set in\r
57076f45 1296 Attributes are not supported by this PCI controller or one of\r
1297 its parent bridges when Operation is Set, Enable or Disable.\r
8e8227d1 1298\r
57076f45 1299**/\r
ead42efc 1300EFI_STATUS\r
1301EFIAPI\r
1302PciIoAttributes (\r
1303 IN EFI_PCI_IO_PROTOCOL * This,\r
1304 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,\r
1305 IN UINT64 Attributes,\r
1306 OUT UINT64 *Result OPTIONAL\r
1307 )\r
ead42efc 1308{\r
1309 EFI_STATUS Status;\r
1310\r
1311 PCI_IO_DEVICE *PciIoDevice;\r
1312 PCI_IO_DEVICE *UpStreamBridge;\r
1313 PCI_IO_DEVICE *Temp;\r
1314\r
1315 UINT64 Supports;\r
1316 UINT64 UpStreamAttributes;\r
1317 UINT16 BridgeControl;\r
1318 UINT16 Command;\r
1319\r
1320 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
1321\r
1322 switch (Operation) {\r
1323 case EfiPciIoAttributeOperationGet:\r
1324 if (Result == NULL) {\r
1325 return EFI_INVALID_PARAMETER;\r
1326 }\r
1327\r
1328 *Result = PciIoDevice->Attributes;\r
1329 return EFI_SUCCESS;\r
1330\r
1331 case EfiPciIoAttributeOperationSupported:\r
1332 if (Result == NULL) {\r
1333 return EFI_INVALID_PARAMETER;\r
1334 }\r
1335\r
1336 *Result = PciIoDevice->Supports;\r
1337 return EFI_SUCCESS;\r
1338\r
1339 case EfiPciIoAttributeOperationSet:\r
1340 Status = PciIoDevice->PciIo.Attributes (\r
1341 &(PciIoDevice->PciIo),\r
1342 EfiPciIoAttributeOperationEnable,\r
1343 Attributes,\r
1344 NULL\r
1345 );\r
1346 if (EFI_ERROR (Status)) {\r
1347 return EFI_UNSUPPORTED;\r
1348 }\r
1349\r
1350 Status = PciIoDevice->PciIo.Attributes (\r
1351 &(PciIoDevice->PciIo),\r
1352 EfiPciIoAttributeOperationDisable,\r
1353 (~Attributes) & (PciIoDevice->Supports),\r
1354 NULL\r
1355 );\r
1356 if (EFI_ERROR (Status)) {\r
1357 return EFI_UNSUPPORTED;\r
1358 }\r
1359\r
1360 return EFI_SUCCESS;\r
1361\r
1362 case EfiPciIoAttributeOperationEnable:\r
1363 case EfiPciIoAttributeOperationDisable:\r
1364 break;\r
1365\r
1366 default:\r
1367 return EFI_INVALID_PARAMETER;\r
1368 }\r
1369 //\r
1370 // Just a trick for ENABLE attribute\r
96f6af14
LG
1371 // EFI_PCI_DEVICE_ENABLE is not defined in UEFI spec, which is the internal usage.\r
1372 // So, this logic doesn't confrom to UEFI spec, which should be removed.\r
cb33842e 1373 // But this trick logic is still kept for some binary drivers that depend on it.\r
ead42efc 1374 //\r
cb33842e
LG
1375 if ((Attributes & EFI_PCI_DEVICE_ENABLE) == EFI_PCI_DEVICE_ENABLE) {\r
1376 Attributes &= (PciIoDevice->Supports);\r
1377\r
1378 //\r
1379 // Raise the EFI_P_PC_ENABLE Status code\r
1380 //\r
1381 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1382 EFI_PROGRESS_CODE,\r
1383 EFI_IO_BUS_PCI | EFI_P_PC_ENABLE,\r
1384 PciIoDevice->DevicePath\r
1385 );\r
1386 }\r
ead42efc 1387\r
1388 //\r
1389 // If no attributes can be supported, then return.\r
1390 // Otherwise, set the attributes that it can support.\r
1391 //\r
1392 Supports = (PciIoDevice->Supports) & Attributes;\r
1393 if (Supports != Attributes) {\r
1394 return EFI_UNSUPPORTED;\r
1395 }\r
8e8227d1 1396\r
ead42efc 1397 //\r
1398 // For Root Bridge, just call RootBridgeIo to set attributes;\r
1399 //\r
97404058 1400 if (PciIoDevice->Parent == NULL) {\r
ead42efc 1401 Status = ModifyRootBridgeAttributes (PciIoDevice, Attributes, Operation);\r
1402 return Status;\r
1403 }\r
1404\r
1405 Command = 0;\r
1406 BridgeControl = 0;\r
1407\r
1408 //\r
1409 // Check VGA and VGA16, they can not be set at the same time\r
1410 //\r
97404058 1411 if (((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) != 0 &&\r
1412 (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO_16) != 0) ||\r
1413 ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) != 0 &&\r
1414 (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16) != 0) ||\r
1415 ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) != 0 &&\r
1416 (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO_16) != 0) ||\r
1417 ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) != 0 &&\r
1418 (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16) != 0) ) {\r
ead42efc 1419 return EFI_UNSUPPORTED;\r
1420 }\r
1421\r
1422 //\r
1423 // For PPB & P2C, set relevant attribute bits\r
1424 //\r
1425 if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
1426\r
97404058 1427 if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) != 0) {\r
ead42efc 1428 BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA;\r
1429 }\r
1430\r
97404058 1431 if ((Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) != 0) {\r
ead42efc 1432 BridgeControl |= EFI_PCI_BRIDGE_CONTROL_ISA;\r
1433 }\r
1434\r
97404058 1435 if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) != 0) {\r
ead42efc 1436 Command |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;\r
1437 }\r
1438\r
97404058 1439 if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) != 0) {\r
ead42efc 1440 BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA_16;\r
1441 }\r
1442\r
1443 } else {\r
1444 //\r
1445 // Do with the attributes on VGA\r
1446 // Only for VGA's legacy resource, we just can enable once.\r
1447 //\r
97404058 1448 if ((Attributes &\r
ead42efc 1449 (EFI_PCI_IO_ATTRIBUTE_VGA_IO |\r
1450 EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 |\r
97404058 1451 EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY)) != 0) {\r
ead42efc 1452 //\r
1453 // Check if a VGA has been enabled before enabling a new one\r
1454 //\r
1455 if (Operation == EfiPciIoAttributeOperationEnable) {\r
1456 //\r
1457 // Check if there have been an active VGA device on the same segment\r
1458 //\r
1459 Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);\r
eeefcb9d 1460 if (Temp != NULL && Temp != PciIoDevice) {\r
ead42efc 1461 //\r
1462 // An active VGA has been detected, so can not enable another\r
1463 //\r
1464 return EFI_UNSUPPORTED;\r
1465 }\r
1466 }\r
1467 }\r
8e8227d1 1468\r
ead42efc 1469 //\r
1470 // Do with the attributes on GFX\r
1471 //\r
97404058 1472 if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) != 0) {\r
ead42efc 1473\r
1474 if (Operation == EfiPciIoAttributeOperationEnable) {\r
1475 //\r
1476 // Check if snoop can be enabled in current configuration\r
1477 //\r
1478 Status = SupportPaletteSnoopAttributes (PciIoDevice, Operation);\r
1479\r
1480 if (EFI_ERROR (Status)) {\r
8e8227d1 1481\r
ead42efc 1482 //\r
1483 // Enable operation is forbidden, so mask the bit in attributes\r
1484 // so as to keep consistent with the actual Status\r
1485 //\r
1486 // Attributes &= (~EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);\r
1487 //\r
1488 //\r
1489 //\r
1490 return EFI_UNSUPPORTED;\r
1491\r
1492 }\r
1493 }\r
1494\r
1495 //\r
1496 // It can be supported, so get ready to set the bit\r
1497 //\r
1498 Command |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
1499 }\r
1500 }\r
1501\r
97404058 1502 if ((Attributes & EFI_PCI_IO_ATTRIBUTE_IO) != 0) {\r
ead42efc 1503 Command |= EFI_PCI_COMMAND_IO_SPACE;\r
1504 }\r
1505\r
97404058 1506 if ((Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) != 0) {\r
ead42efc 1507 Command |= EFI_PCI_COMMAND_MEMORY_SPACE;\r
1508 }\r
1509\r
97404058 1510 if ((Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) != 0) {\r
ead42efc 1511 Command |= EFI_PCI_COMMAND_BUS_MASTER;\r
1512 }\r
1513 //\r
1514 // The upstream bridge should be also set to revelant attribute\r
1515 // expect for IO, Mem and BusMaster\r
1516 //\r
8e8227d1 1517 UpStreamAttributes = Attributes &\r
ead42efc 1518 (~(EFI_PCI_IO_ATTRIBUTE_IO |\r
1519 EFI_PCI_IO_ATTRIBUTE_MEMORY |\r
1520 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER\r
1521 )\r
1522 );\r
1523 UpStreamBridge = PciIoDevice->Parent;\r
1524\r
1525 if (Operation == EfiPciIoAttributeOperationEnable) {\r
1526 //\r
1527 // Enable relevant attributes to command register and bridge control register\r
1528 //\r
94b9d5c6 1529 Status = PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, Command);\r
eeefcb9d 1530 if (BridgeControl != 0) {\r
94b9d5c6 1531 Status = PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);\r
ead42efc 1532 }\r
1533\r
1534 PciIoDevice->Attributes |= Attributes;\r
1535\r
1536 //\r
1537 // Enable attributes of the upstream bridge\r
1538 //\r
1539 Status = UpStreamBridge->PciIo.Attributes (\r
1540 &(UpStreamBridge->PciIo),\r
1541 EfiPciIoAttributeOperationEnable,\r
1542 UpStreamAttributes,\r
1543 NULL\r
1544 );\r
1545 } else {\r
8e8227d1 1546\r
ead42efc 1547 //\r
1548 // Disable relevant attributes to command register and bridge control register\r
1549 //\r
94b9d5c6 1550 Status = PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, Command);\r
eeefcb9d 1551 if (BridgeControl != 0) {\r
94b9d5c6 1552 Status = PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);\r
ead42efc 1553 }\r
1554\r
1555 PciIoDevice->Attributes &= (~Attributes);\r
1556 Status = EFI_SUCCESS;\r
1557\r
1558 }\r
1559\r
1560 if (EFI_ERROR (Status)) {\r
1561 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
1562 }\r
1563\r
1564 return Status;\r
1565}\r
1566\r
8e8227d1 1567/**\r
57076f45 1568 Gets the attributes that this PCI controller supports setting on a BAR using\r
1569 SetBarAttributes(), and retrieves the list of resource descriptors for a BAR.\r
8e8227d1 1570\r
1571 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
57076f45 1572 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
1573 base address for resource range. The legal range for this field is 0..5.\r
1574 @param Supports A pointer to the mask of attributes that this PCI controller supports\r
8e8227d1 1575 setting for this BAR with SetBarAttributes().\r
57076f45 1576 @param Resources A pointer to the ACPI 2.0 resource descriptors that describe the current\r
8e8227d1 1577 configuration of this BAR of the PCI controller.\r
1578\r
1579 @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI\r
1580 controller supports are returned in Supports. If Resources\r
57076f45 1581 is not NULL, then the ACPI 2.0 resource descriptors that the PCI\r
8e8227d1 1582 controller is currently using are returned in Resources.\r
57076f45 1583 @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.\r
1584 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
1585 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate\r
8e8227d1 1586 Resources.\r
1587\r
57076f45 1588**/\r
ead42efc 1589EFI_STATUS\r
1590EFIAPI\r
1591PciIoGetBarAttributes (\r
1592 IN EFI_PCI_IO_PROTOCOL * This,\r
1593 IN UINT8 BarIndex,\r
1594 OUT UINT64 *Supports, OPTIONAL\r
1595 OUT VOID **Resources OPTIONAL\r
1596 )\r
ead42efc 1597{\r
1598\r
1599 UINT8 *Configuration;\r
1600 UINT8 NumConfig;\r
1601 PCI_IO_DEVICE *PciIoDevice;\r
1602 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
1603 EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;\r
1604\r
1605 NumConfig = 0;\r
1606\r
1607 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
1608\r
1609 if (Supports == NULL && Resources == NULL) {\r
1610 return EFI_INVALID_PARAMETER;\r
1611 }\r
1612\r
1613 if (BarIndex >= PCI_MAX_BAR) {\r
1614 return EFI_UNSUPPORTED;\r
1615 }\r
1616\r
1617 //\r
1618 // This driver does not support modifications to the WRITE_COMBINE or\r
1619 // CACHED attributes for BAR ranges.\r
1620 //\r
1621 if (Supports != NULL) {\r
1622 *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;\r
1623 }\r
1624\r
1625 if (Resources != NULL) {\r
1626\r
1627 if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeUnknown) {\r
1628 NumConfig = 1;\r
1629 }\r
1630\r
1631 Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1632 if (Configuration == NULL) {\r
1633 return EFI_OUT_OF_RESOURCES;\r
1634 }\r
1635\r
1636 ZeroMem (\r
1637 Configuration,\r
1638 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
1639 );\r
1640\r
1641 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
1642\r
1643 if (NumConfig == 1) {\r
1644 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1645 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1646\r
1647 Ptr->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;\r
1648 Ptr->AddrLen = PciIoDevice->PciBar[BarIndex].Length;\r
1649 Ptr->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;\r
1650\r
1651 switch (PciIoDevice->PciBar[BarIndex].BarType) {\r
1652 case PciBarTypeIo16:\r
1653 case PciBarTypeIo32:\r
1654 //\r
1655 // Io\r
1656 //\r
1657 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
1658 break;\r
1659\r
1660 case PciBarTypeMem32:\r
1661 //\r
1662 // Mem\r
1663 //\r
1664 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1665 //\r
1666 // 32 bit\r
1667 //\r
1668 Ptr->AddrSpaceGranularity = 32;\r
1669 break;\r
1670\r
1671 case PciBarTypePMem32:\r
1672 //\r
1673 // Mem\r
1674 //\r
1675 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1676 //\r
1677 // prefechable\r
1678 //\r
1679 Ptr->SpecificFlag = 0x6;\r
1680 //\r
1681 // 32 bit\r
1682 //\r
1683 Ptr->AddrSpaceGranularity = 32;\r
1684 break;\r
1685\r
1686 case PciBarTypeMem64:\r
1687 //\r
1688 // Mem\r
1689 //\r
1690 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1691 //\r
1692 // 64 bit\r
1693 //\r
1694 Ptr->AddrSpaceGranularity = 64;\r
1695 break;\r
1696\r
1697 case PciBarTypePMem64:\r
1698 //\r
1699 // Mem\r
1700 //\r
1701 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1702 //\r
1703 // prefechable\r
1704 //\r
1705 Ptr->SpecificFlag = 0x6;\r
1706 //\r
1707 // 64 bit\r
1708 //\r
1709 Ptr->AddrSpaceGranularity = 64;\r
1710 break;\r
1711\r
1712 default:\r
1713 break;\r
1714 }\r
1715\r
1716 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1717 }\r
8e8227d1 1718\r
ead42efc 1719 //\r
1720 // put the checksum\r
1721 //\r
1722 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);\r
1723 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
1724 PtrEnd->Checksum = 0;\r
1725\r
1726 *Resources = Configuration;\r
1727 }\r
1728\r
1729 return EFI_SUCCESS;\r
1730}\r
1731\r
8e8227d1 1732/**\r
57076f45 1733 Sets the attributes for a range of a BAR on a PCI controller.\r
8e8227d1 1734\r
1735 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
57076f45 1736 @param Attributes The mask of attributes to set for the resource range specified by\r
8e8227d1 1737 BarIndex, Offset, and Length.\r
57076f45 1738 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
1739 base address for resource range. The legal range for this field is 0..5.\r
1740 @param Offset A pointer to the BAR relative base address of the resource range to be\r
8e8227d1 1741 modified by the attributes specified by Attributes.\r
57076f45 1742 @param Length A pointer to the length of the resource range to be modified by the\r
8e8227d1 1743 attributes specified by Attributes.\r
1744\r
1745 @retval EFI_SUCCESS The set of attributes specified by Attributes for the resource\r
1746 range specified by BarIndex, Offset, and Length were\r
57076f45 1747 set on the PCI controller, and the actual resource range is returned\r
8e8227d1 1748 in Offset and Length.\r
57076f45 1749 @retval EFI_INVALID_PARAMETER Offset or Length is NULL.\r
1750 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
1751 @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the attributes on the\r
8e8227d1 1752 resource range specified by BarIndex, Offset, and\r
1753 Length.\r
1754\r
57076f45 1755**/\r
ead42efc 1756EFI_STATUS\r
1757EFIAPI\r
1758PciIoSetBarAttributes (\r
1759 IN EFI_PCI_IO_PROTOCOL *This,\r
1760 IN UINT64 Attributes,\r
1761 IN UINT8 BarIndex,\r
1762 IN OUT UINT64 *Offset,\r
1763 IN OUT UINT64 *Length\r
1764 )\r
ead42efc 1765{\r
1766 EFI_STATUS Status;\r
1767 PCI_IO_DEVICE *PciIoDevice;\r
1768 UINT64 NonRelativeOffset;\r
1769 UINT64 Supports;\r
1770\r
1771 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
1772\r
1773 //\r
1774 // Make sure Offset and Length are not NULL\r
1775 //\r
1776 if (Offset == NULL || Length == NULL) {\r
1777 return EFI_INVALID_PARAMETER;\r
1778 }\r
1779\r
1780 if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) {\r
1781 return EFI_UNSUPPORTED;\r
1782 }\r
1783 //\r
1784 // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.\r
1785 // If Attributes is not 0, then return EFI_UNSUPPORTED.\r
1786 //\r
1787 Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;\r
1788\r
1789 if (Attributes != (Attributes & Supports)) {\r
1790 return EFI_UNSUPPORTED;\r
1791 }\r
1792 //\r
1793 // Attributes must be supported. Make sure the BAR range describd by BarIndex, Offset, and\r
1794 // Length are valid for this PCI device.\r
1795 //\r
1796 NonRelativeOffset = *Offset;\r
1797 Status = PciIoVerifyBarAccess (\r
1798 PciIoDevice,\r
1799 BarIndex,\r
1800 PciBarTypeMem,\r
1801 EfiPciIoWidthUint8,\r
1802 (UINT32) *Length,\r
1803 &NonRelativeOffset\r
1804 );\r
1805 if (EFI_ERROR (Status)) {\r
1806 return EFI_UNSUPPORTED;\r
1807 }\r
1808\r
1809 return EFI_SUCCESS;\r
1810}\r
1811\r
57076f45 1812/**\r
1813 Program parent bridge's attribute recurrently.\r
8e8227d1 1814\r
57076f45 1815 @param PciIoDevice Child Pci device instance\r
1816 @param Operation The operation to perform on the attributes for this PCI controller.\r
1817 @param Attributes The mask of attributes that are used for Set, Enable, and Disable\r
1818 operations.\r
8e8227d1 1819\r
57076f45 1820 @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.\r
8e8227d1 1821 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
1822 @retval EFI_UNSUPPORTED one or more of the bits set in\r
57076f45 1823 Attributes are not supported by this PCI controller or one of\r
1824 its parent bridges when Operation is Set, Enable or Disable.\r
8e8227d1 1825\r
57076f45 1826**/\r
ead42efc 1827EFI_STATUS\r
1828UpStreamBridgesAttributes (\r
8e8227d1 1829 IN PCI_IO_DEVICE *PciIoDevice,\r
1830 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,\r
1831 IN UINT64 Attributes\r
ead42efc 1832 )\r
ead42efc 1833{\r
1834 PCI_IO_DEVICE *Parent;\r
1835 EFI_PCI_IO_PROTOCOL *PciIo;\r
1836\r
1837 Parent = PciIoDevice->Parent;\r
1838\r
eeefcb9d 1839 while (Parent != NULL && IS_PCI_BRIDGE (&Parent->Pci)) {\r
ead42efc 1840\r
1841 //\r
1842 // Get the PciIo Protocol\r
1843 //\r
1844 PciIo = &Parent->PciIo;\r
1845\r
1846 PciIo->Attributes (PciIo, Operation, Attributes, NULL);\r
1847\r
1848 Parent = Parent->Parent;\r
1849 }\r
1850\r
1851 return EFI_SUCCESS;\r
1852}\r
1853\r
57076f45 1854/**\r
8e8227d1 1855 Test whether two Pci devices has same parent bridge.\r
1856\r
1857 @param PciDevice1 The first pci device for testing.\r
1858 @param PciDevice2 The second pci device for testing.\r
1859\r
1860 @retval TRUE Two Pci device has the same parent bridge.\r
1861 @retval FALSE Two Pci device has not the same parent bridge.\r
1862\r
57076f45 1863**/\r
ead42efc 1864BOOLEAN\r
1865PciDevicesOnTheSamePath (\r
1866 IN PCI_IO_DEVICE *PciDevice1,\r
1867 IN PCI_IO_DEVICE *PciDevice2\r
1868 )\r
ead42efc 1869{\r
1870 BOOLEAN Existed1;\r
1871 BOOLEAN Existed2;\r
1872\r
1873 if (PciDevice1->Parent == PciDevice2->Parent) {\r
1874 return TRUE;\r
1875 }\r
1876\r
1877 Existed1 = PciDeviceExisted (PciDevice1->Parent, PciDevice2);\r
1878 Existed2 = PciDeviceExisted (PciDevice2->Parent, PciDevice1);\r
1879\r
1880 return (BOOLEAN) (Existed1 || Existed2);\r
1881}\r
57076f45 1882\r