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