]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciCommand.c
CommitLineData
9060e3ec 1/** @file\r
2 PCI command register operations supporting functions implementation for PCI Bus module.\r
3\r
fcdfcdbf 4Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
9060e3ec 6\r
7**/\r
8\r
9#include "PciBus.h"\r
10\r
11/**\r
12 Operate the PCI register via PciIo function interface.\r
13\r
14 @param PciIoDevice Pointer to instance of PCI_IO_DEVICE.\r
15 @param Command Operator command.\r
16 @param Offset The address within the PCI configuration space for the PCI controller.\r
17 @param Operation Type of Operation.\r
18 @param PtrCommand Return buffer holding old PCI command, if operation is not EFI_SET_REGISTER.\r
19\r
20 @return Status of PciIo operation.\r
21\r
22**/\r
23EFI_STATUS\r
24PciOperateRegister (\r
1436aea4
MK
25 IN PCI_IO_DEVICE *PciIoDevice,\r
26 IN UINT16 Command,\r
27 IN UINT8 Offset,\r
28 IN UINT8 Operation,\r
29 OUT UINT16 *PtrCommand\r
9060e3ec 30 )\r
31{\r
1436aea4
MK
32 UINT16 OldCommand;\r
33 EFI_STATUS Status;\r
34 EFI_PCI_IO_PROTOCOL *PciIo;\r
9060e3ec 35\r
1436aea4
MK
36 OldCommand = 0;\r
37 PciIo = &PciIoDevice->PciIo;\r
9060e3ec 38\r
39 if (Operation != EFI_SET_REGISTER) {\r
40 Status = PciIo->Pci.Read (\r
41 PciIo,\r
42 EfiPciIoWidthUint16,\r
43 Offset,\r
44 1,\r
45 &OldCommand\r
46 );\r
47\r
48 if (Operation == EFI_GET_REGISTER) {\r
49 *PtrCommand = OldCommand;\r
50 return Status;\r
51 }\r
52 }\r
53\r
54 if (Operation == EFI_ENABLE_REGISTER) {\r
1436aea4 55 OldCommand = (UINT16)(OldCommand | Command);\r
9060e3ec 56 } else if (Operation == EFI_DISABLE_REGISTER) {\r
1436aea4 57 OldCommand = (UINT16)(OldCommand & ~(Command));\r
9060e3ec 58 } else {\r
59 OldCommand = Command;\r
60 }\r
61\r
62 return PciIo->Pci.Write (\r
63 PciIo,\r
64 EfiPciIoWidthUint16,\r
65 Offset,\r
66 1,\r
67 &OldCommand\r
68 );\r
69}\r
70\r
71/**\r
fcdfcdbf 72 Check the capability supporting by given device.\r
9060e3ec 73\r
74 @param PciIoDevice Pointer to instance of PCI_IO_DEVICE.\r
75\r
fcdfcdbf
RN
76 @retval TRUE Capability supported.\r
77 @retval FALSE Capability not supported.\r
9060e3ec 78\r
79**/\r
80BOOLEAN\r
81PciCapabilitySupport (\r
82 IN PCI_IO_DEVICE *PciIoDevice\r
83 )\r
84{\r
85 if ((PciIoDevice->Pci.Hdr.Status & EFI_PCI_STATUS_CAPABILITY) != 0) {\r
86 return TRUE;\r
87 }\r
88\r
89 return FALSE;\r
90}\r
91\r
92/**\r
93 Locate capability register block per capability ID.\r
94\r
95 @param PciIoDevice A pointer to the PCI_IO_DEVICE.\r
96 @param CapId The capability ID.\r
97 @param Offset A pointer to the offset returned.\r
98 @param NextRegBlock A pointer to the next block returned.\r
99\r
fcdfcdbf 100 @retval EFI_SUCCESS Successfully located capability register block.\r
9060e3ec 101 @retval EFI_UNSUPPORTED Pci device does not support capability.\r
102 @retval EFI_NOT_FOUND Pci device support but can not find register block.\r
103\r
104**/\r
105EFI_STATUS\r
106LocateCapabilityRegBlock (\r
107 IN PCI_IO_DEVICE *PciIoDevice,\r
108 IN UINT8 CapId,\r
109 IN OUT UINT8 *Offset,\r
110 OUT UINT8 *NextRegBlock OPTIONAL\r
111 )\r
112{\r
113 UINT8 CapabilityPtr;\r
114 UINT16 CapabilityEntry;\r
115 UINT8 CapabilityID;\r
116\r
117 //\r
fcdfcdbf 118 // To check the capability of this device supports\r
9060e3ec 119 //\r
120 if (!PciCapabilitySupport (PciIoDevice)) {\r
121 return EFI_UNSUPPORTED;\r
122 }\r
123\r
124 if (*Offset != 0) {\r
125 CapabilityPtr = *Offset;\r
126 } else {\r
9060e3ec 127 CapabilityPtr = 0;\r
128 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
9060e3ec 129 PciIoDevice->PciIo.Pci.Read (\r
130 &PciIoDevice->PciIo,\r
131 EfiPciIoWidthUint8,\r
132 EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR,\r
133 1,\r
134 &CapabilityPtr\r
135 );\r
136 } else {\r
9060e3ec 137 PciIoDevice->PciIo.Pci.Read (\r
138 &PciIoDevice->PciIo,\r
139 EfiPciIoWidthUint8,\r
140 PCI_CAPBILITY_POINTER_OFFSET,\r
141 1,\r
142 &CapabilityPtr\r
143 );\r
144 }\r
145 }\r
146\r
147 while ((CapabilityPtr >= 0x40) && ((CapabilityPtr & 0x03) == 0x00)) {\r
148 PciIoDevice->PciIo.Pci.Read (\r
149 &PciIoDevice->PciIo,\r
150 EfiPciIoWidthUint16,\r
151 CapabilityPtr,\r
152 1,\r
153 &CapabilityEntry\r
154 );\r
155\r
1436aea4 156 CapabilityID = (UINT8)CapabilityEntry;\r
9060e3ec 157\r
158 if (CapabilityID == CapId) {\r
159 *Offset = CapabilityPtr;\r
160 if (NextRegBlock != NULL) {\r
1436aea4 161 *NextRegBlock = (UINT8)(CapabilityEntry >> 8);\r
9060e3ec 162 }\r
163\r
164 return EFI_SUCCESS;\r
165 }\r
166\r
7d9340a3
RN
167 //\r
168 // Certain PCI device may incorrectly have capability pointing to itself,\r
169 // break to avoid dead loop.\r
170 //\r
1436aea4 171 if (CapabilityPtr == (UINT8)(CapabilityEntry >> 8)) {\r
7d9340a3
RN
172 break;\r
173 }\r
174\r
1436aea4 175 CapabilityPtr = (UINT8)(CapabilityEntry >> 8);\r
9060e3ec 176 }\r
177\r
178 return EFI_NOT_FOUND;\r
179}\r
180\r
181/**\r
182 Locate PciExpress capability register block per capability ID.\r
183\r
184 @param PciIoDevice A pointer to the PCI_IO_DEVICE.\r
185 @param CapId The capability ID.\r
186 @param Offset A pointer to the offset returned.\r
187 @param NextRegBlock A pointer to the next block returned.\r
188\r
fcdfcdbf 189 @retval EFI_SUCCESS Successfully located capability register block.\r
9060e3ec 190 @retval EFI_UNSUPPORTED Pci device does not support capability.\r
191 @retval EFI_NOT_FOUND Pci device support but can not find register block.\r
192\r
193**/\r
194EFI_STATUS\r
195LocatePciExpressCapabilityRegBlock (\r
1436aea4
MK
196 IN PCI_IO_DEVICE *PciIoDevice,\r
197 IN UINT16 CapId,\r
198 IN OUT UINT32 *Offset,\r
199 OUT UINT32 *NextRegBlock OPTIONAL\r
9060e3ec 200 )\r
201{\r
1436aea4
MK
202 EFI_STATUS Status;\r
203 UINT32 CapabilityPtr;\r
204 UINT32 CapabilityEntry;\r
205 UINT16 CapabilityID;\r
9060e3ec 206\r
207 //\r
208 // To check the capability of this device supports\r
209 //\r
210 if (!PciIoDevice->IsPciExp) {\r
211 return EFI_UNSUPPORTED;\r
212 }\r
213\r
214 if (*Offset != 0) {\r
215 CapabilityPtr = *Offset;\r
216 } else {\r
217 CapabilityPtr = EFI_PCIE_CAPABILITY_BASE_OFFSET;\r
218 }\r
219\r
220 while (CapabilityPtr != 0) {\r
221 //\r
222 // Mask it to DWORD alignment per PCI spec\r
223 //\r
224 CapabilityPtr &= 0xFFC;\r
1436aea4
MK
225 Status = PciIoDevice->PciIo.Pci.Read (\r
226 &PciIoDevice->PciIo,\r
227 EfiPciIoWidthUint32,\r
228 CapabilityPtr,\r
229 1,\r
230 &CapabilityEntry\r
231 );\r
edf28968
RN
232 if (EFI_ERROR (Status)) {\r
233 break;\r
234 }\r
9060e3ec 235\r
e5b4d825
LE
236 if (CapabilityEntry == MAX_UINT32) {\r
237 DEBUG ((\r
238 DEBUG_WARN,\r
239 "%a: [%02x|%02x|%02x] failed to access config space at offset 0x%x\n",\r
240 __FUNCTION__,\r
241 PciIoDevice->BusNumber,\r
242 PciIoDevice->DeviceNumber,\r
243 PciIoDevice->FunctionNumber,\r
244 CapabilityPtr\r
245 ));\r
246 break;\r
247 }\r
248\r
1436aea4 249 CapabilityID = (UINT16)CapabilityEntry;\r
9060e3ec 250\r
251 if (CapabilityID == CapId) {\r
252 *Offset = CapabilityPtr;\r
253 if (NextRegBlock != NULL) {\r
254 *NextRegBlock = (CapabilityEntry >> 20) & 0xFFF;\r
255 }\r
256\r
257 return EFI_SUCCESS;\r
258 }\r
259\r
260 CapabilityPtr = (CapabilityEntry >> 20) & 0xFFF;\r
261 }\r
262\r
263 return EFI_NOT_FOUND;\r
264}\r