add SR-IOV support in EDK II.
[edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciCommand.c
blob601af309b7c2e76d7aa2b9f2944d39146e7b5ea5
1 /** @file
2 PCI command register operations supporting functions implementation for PCI Bus module.
4 Copyright (c) 2006 - 2009, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 **/
15 #include "PciBus.h"
17 /**
18 Operate the PCI register via PciIo function interface.
20 @param PciIoDevice Pointer to instance of PCI_IO_DEVICE.
21 @param Command Operator command.
22 @param Offset The address within the PCI configuration space for the PCI controller.
23 @param Operation Type of Operation.
24 @param PtrCommand Return buffer holding old PCI command, if operation is not EFI_SET_REGISTER.
26 @return Status of PciIo operation.
28 **/
29 EFI_STATUS
30 PciOperateRegister (
31 IN PCI_IO_DEVICE *PciIoDevice,
32 IN UINT16 Command,
33 IN UINT8 Offset,
34 IN UINT8 Operation,
35 OUT UINT16 *PtrCommand
38 UINT16 OldCommand;
39 EFI_STATUS Status;
40 EFI_PCI_IO_PROTOCOL *PciIo;
42 OldCommand = 0;
43 PciIo = &PciIoDevice->PciIo;
45 if (Operation != EFI_SET_REGISTER) {
46 Status = PciIo->Pci.Read (
47 PciIo,
48 EfiPciIoWidthUint16,
49 Offset,
51 &OldCommand
54 if (Operation == EFI_GET_REGISTER) {
55 *PtrCommand = OldCommand;
56 return Status;
60 if (Operation == EFI_ENABLE_REGISTER) {
61 OldCommand = (UINT16) (OldCommand | Command);
62 } else if (Operation == EFI_DISABLE_REGISTER) {
63 OldCommand = (UINT16) (OldCommand & ~(Command));
64 } else {
65 OldCommand = Command;
68 return PciIo->Pci.Write (
69 PciIo,
70 EfiPciIoWidthUint16,
71 Offset,
73 &OldCommand
77 /**
78 Check the cpability supporting by given device.
80 @param PciIoDevice Pointer to instance of PCI_IO_DEVICE.
82 @retval TRUE Cpability supportted.
83 @retval FALSE Cpability not supportted.
85 **/
86 BOOLEAN
87 PciCapabilitySupport (
88 IN PCI_IO_DEVICE *PciIoDevice
91 if ((PciIoDevice->Pci.Hdr.Status & EFI_PCI_STATUS_CAPABILITY) != 0) {
92 return TRUE;
95 return FALSE;
98 /**
99 Locate capability register block per capability ID.
101 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
102 @param CapId The capability ID.
103 @param Offset A pointer to the offset returned.
104 @param NextRegBlock A pointer to the next block returned.
106 @retval EFI_SUCCESS Successfuly located capability register block.
107 @retval EFI_UNSUPPORTED Pci device does not support capability.
108 @retval EFI_NOT_FOUND Pci device support but can not find register block.
111 EFI_STATUS
112 LocateCapabilityRegBlock (
113 IN PCI_IO_DEVICE *PciIoDevice,
114 IN UINT8 CapId,
115 IN OUT UINT8 *Offset,
116 OUT UINT8 *NextRegBlock OPTIONAL
119 UINT8 CapabilityPtr;
120 UINT16 CapabilityEntry;
121 UINT8 CapabilityID;
124 // To check the cpability of this device supports
126 if (!PciCapabilitySupport (PciIoDevice)) {
127 return EFI_UNSUPPORTED;
130 if (*Offset != 0) {
131 CapabilityPtr = *Offset;
132 } else {
134 CapabilityPtr = 0;
135 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
137 PciIoDevice->PciIo.Pci.Read (
138 &PciIoDevice->PciIo,
139 EfiPciIoWidthUint8,
140 EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR,
142 &CapabilityPtr
144 } else {
146 PciIoDevice->PciIo.Pci.Read (
147 &PciIoDevice->PciIo,
148 EfiPciIoWidthUint8,
149 PCI_CAPBILITY_POINTER_OFFSET,
151 &CapabilityPtr
156 while ((CapabilityPtr >= 0x40) && ((CapabilityPtr & 0x03) == 0x00)) {
157 PciIoDevice->PciIo.Pci.Read (
158 &PciIoDevice->PciIo,
159 EfiPciIoWidthUint16,
160 CapabilityPtr,
162 &CapabilityEntry
165 CapabilityID = (UINT8) CapabilityEntry;
167 if (CapabilityID == CapId) {
168 *Offset = CapabilityPtr;
169 if (NextRegBlock != NULL) {
170 *NextRegBlock = (UINT8) (CapabilityEntry >> 8);
173 return EFI_SUCCESS;
176 CapabilityPtr = (UINT8) (CapabilityEntry >> 8);
179 return EFI_NOT_FOUND;
183 Locate PciExpress capability register block per capability ID.
185 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
186 @param CapId The capability ID.
187 @param Offset A pointer to the offset returned.
188 @param NextRegBlock A pointer to the next block returned.
190 @retval EFI_SUCCESS Successfuly located capability register block.
191 @retval EFI_UNSUPPORTED Pci device does not support capability.
192 @retval EFI_NOT_FOUND Pci device support but can not find register block.
195 EFI_STATUS
196 LocatePciExpressCapabilityRegBlock (
197 IN PCI_IO_DEVICE *PciIoDevice,
198 IN UINT16 CapId,
199 IN OUT UINT32 *Offset,
200 OUT UINT32 *NextRegBlock OPTIONAL
203 UINT32 CapabilityPtr;
204 UINT32 CapabilityEntry;
205 UINT16 CapabilityID;
208 // To check the capability of this device supports
210 if (!PciIoDevice->IsPciExp) {
211 return EFI_UNSUPPORTED;
214 if (*Offset != 0) {
215 CapabilityPtr = *Offset;
216 } else {
217 CapabilityPtr = EFI_PCIE_CAPABILITY_BASE_OFFSET;
220 while (CapabilityPtr != 0) {
222 // Mask it to DWORD alignment per PCI spec
224 CapabilityPtr &= 0xFFC;
225 PciIoDevice->PciIo.Pci.Read (
226 &PciIoDevice->PciIo,
227 EfiPciIoWidthUint32,
228 CapabilityPtr,
230 &CapabilityEntry
233 CapabilityID = (UINT16) CapabilityEntry;
235 if (CapabilityID == CapId) {
236 *Offset = CapabilityPtr;
237 if (NextRegBlock != NULL) {
238 *NextRegBlock = (CapabilityEntry >> 20) & 0xFFF;
241 return EFI_SUCCESS;
244 CapabilityPtr = (CapabilityEntry >> 20) & 0xFFF;
247 return EFI_NOT_FOUND;