MdeModulePkg/PciBus: Correct typos
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciCommand.c
1 /** @file
2 PCI command register operations supporting functions implementation for PCI Bus module.
3
4 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
5 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
9
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.
12
13 **/
14
15 #include "PciBus.h"
16
17 /**
18 Operate the PCI register via PciIo function interface.
19
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.
25
26 @return Status of PciIo operation.
27
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
36 )
37 {
38 UINT16 OldCommand;
39 EFI_STATUS Status;
40 EFI_PCI_IO_PROTOCOL *PciIo;
41
42 OldCommand = 0;
43 PciIo = &PciIoDevice->PciIo;
44
45 if (Operation != EFI_SET_REGISTER) {
46 Status = PciIo->Pci.Read (
47 PciIo,
48 EfiPciIoWidthUint16,
49 Offset,
50 1,
51 &OldCommand
52 );
53
54 if (Operation == EFI_GET_REGISTER) {
55 *PtrCommand = OldCommand;
56 return Status;
57 }
58 }
59
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;
66 }
67
68 return PciIo->Pci.Write (
69 PciIo,
70 EfiPciIoWidthUint16,
71 Offset,
72 1,
73 &OldCommand
74 );
75 }
76
77 /**
78 Check the capability supporting by given device.
79
80 @param PciIoDevice Pointer to instance of PCI_IO_DEVICE.
81
82 @retval TRUE Capability supported.
83 @retval FALSE Capability not supported.
84
85 **/
86 BOOLEAN
87 PciCapabilitySupport (
88 IN PCI_IO_DEVICE *PciIoDevice
89 )
90 {
91 if ((PciIoDevice->Pci.Hdr.Status & EFI_PCI_STATUS_CAPABILITY) != 0) {
92 return TRUE;
93 }
94
95 return FALSE;
96 }
97
98 /**
99 Locate capability register block per capability ID.
100
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.
105
106 @retval EFI_SUCCESS Successfully 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.
109
110 **/
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
117 )
118 {
119 UINT8 CapabilityPtr;
120 UINT16 CapabilityEntry;
121 UINT8 CapabilityID;
122
123 //
124 // To check the capability of this device supports
125 //
126 if (!PciCapabilitySupport (PciIoDevice)) {
127 return EFI_UNSUPPORTED;
128 }
129
130 if (*Offset != 0) {
131 CapabilityPtr = *Offset;
132 } else {
133
134 CapabilityPtr = 0;
135 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
136
137 PciIoDevice->PciIo.Pci.Read (
138 &PciIoDevice->PciIo,
139 EfiPciIoWidthUint8,
140 EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR,
141 1,
142 &CapabilityPtr
143 );
144 } else {
145
146 PciIoDevice->PciIo.Pci.Read (
147 &PciIoDevice->PciIo,
148 EfiPciIoWidthUint8,
149 PCI_CAPBILITY_POINTER_OFFSET,
150 1,
151 &CapabilityPtr
152 );
153 }
154 }
155
156 while ((CapabilityPtr >= 0x40) && ((CapabilityPtr & 0x03) == 0x00)) {
157 PciIoDevice->PciIo.Pci.Read (
158 &PciIoDevice->PciIo,
159 EfiPciIoWidthUint16,
160 CapabilityPtr,
161 1,
162 &CapabilityEntry
163 );
164
165 CapabilityID = (UINT8) CapabilityEntry;
166
167 if (CapabilityID == CapId) {
168 *Offset = CapabilityPtr;
169 if (NextRegBlock != NULL) {
170 *NextRegBlock = (UINT8) (CapabilityEntry >> 8);
171 }
172
173 return EFI_SUCCESS;
174 }
175
176 //
177 // Certain PCI device may incorrectly have capability pointing to itself,
178 // break to avoid dead loop.
179 //
180 if (CapabilityPtr == (UINT8) (CapabilityEntry >> 8)) {
181 break;
182 }
183
184 CapabilityPtr = (UINT8) (CapabilityEntry >> 8);
185 }
186
187 return EFI_NOT_FOUND;
188 }
189
190 /**
191 Locate PciExpress capability register block per capability ID.
192
193 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
194 @param CapId The capability ID.
195 @param Offset A pointer to the offset returned.
196 @param NextRegBlock A pointer to the next block returned.
197
198 @retval EFI_SUCCESS Successfully located capability register block.
199 @retval EFI_UNSUPPORTED Pci device does not support capability.
200 @retval EFI_NOT_FOUND Pci device support but can not find register block.
201
202 **/
203 EFI_STATUS
204 LocatePciExpressCapabilityRegBlock (
205 IN PCI_IO_DEVICE *PciIoDevice,
206 IN UINT16 CapId,
207 IN OUT UINT32 *Offset,
208 OUT UINT32 *NextRegBlock OPTIONAL
209 )
210 {
211 EFI_STATUS Status;
212 UINT32 CapabilityPtr;
213 UINT32 CapabilityEntry;
214 UINT16 CapabilityID;
215
216 //
217 // To check the capability of this device supports
218 //
219 if (!PciIoDevice->IsPciExp) {
220 return EFI_UNSUPPORTED;
221 }
222
223 if (*Offset != 0) {
224 CapabilityPtr = *Offset;
225 } else {
226 CapabilityPtr = EFI_PCIE_CAPABILITY_BASE_OFFSET;
227 }
228
229 while (CapabilityPtr != 0) {
230 //
231 // Mask it to DWORD alignment per PCI spec
232 //
233 CapabilityPtr &= 0xFFC;
234 Status = PciIoDevice->PciIo.Pci.Read (
235 &PciIoDevice->PciIo,
236 EfiPciIoWidthUint32,
237 CapabilityPtr,
238 1,
239 &CapabilityEntry
240 );
241 if (EFI_ERROR (Status)) {
242 break;
243 }
244
245 CapabilityID = (UINT16) CapabilityEntry;
246
247 if (CapabilityID == CapId) {
248 *Offset = CapabilityPtr;
249 if (NextRegBlock != NULL) {
250 *NextRegBlock = (CapabilityEntry >> 20) & 0xFFF;
251 }
252
253 return EFI_SUCCESS;
254 }
255
256 CapabilityPtr = (CapabilityEntry >> 20) & 0xFFF;
257 }
258
259 return EFI_NOT_FOUND;
260 }