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