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