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