]>
Commit | Line | Data |
---|---|---|
e1f414b6 | 1 | /** @file\r |
5c57f3ea | 2 | PCI CF8 Library functions that use I/O ports 0xCF8 and 0xCFC to perform PCI Configuration cycles.\r |
3 | Layers on top of an I/O Library instance.\r | |
e1f414b6 | 4 | \r |
9095d37b | 5 | Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r |
9344f092 | 6 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
e1f414b6 | 7 | \r |
e1f414b6 | 8 | **/\r |
9 | \r | |
c7d265a9 | 10 | #include <Base.h>\r |
c892d846 | 11 | \r |
0c62737d | 12 | #include <Library/BaseLib.h>\r |
c7d265a9 | 13 | #include <Library/PciCf8Lib.h>\r |
14 | #include <Library/IoLib.h>\r | |
15 | #include <Library/DebugLib.h>\r | |
e1f414b6 | 16 | \r |
17 | //\r | |
18 | // Declare I/O Ports used to perform PCI Confguration Cycles\r | |
19 | //\r | |
20 | #define PCI_CONFIGURATION_ADDRESS_PORT 0xCF8\r | |
21 | #define PCI_CONFIGURATION_DATA_PORT 0xCFC\r | |
22 | \r | |
e1f414b6 | 23 | /**\r |
ad400b07 | 24 | Convert a PCI Library address to PCI CF8 formatted address.\r |
25 | \r | |
26 | Declare macro to convert PCI Library address to PCI CF8 formatted address.\r | |
27 | Bit fields of PCI Library and CF8 formatted address is as follows:\r | |
28 | PCI Library formatted address CF8 Formatted Address\r | |
29 | ============================= ======================\r | |
30 | Bits 00..11 Register Bits 00..07 Register\r | |
31 | Bits 12..14 Function Bits 08..10 Function\r | |
32 | Bits 15..19 Device Bits 11..15 Device\r | |
33 | Bits 20..27 Bus Bits 16..23 Bus\r | |
34 | Bits 28..31 Reserved(MBZ) Bits 24..30 Reserved(MBZ)\r | |
35 | Bits 31..31 Must be 1\r | |
e1f414b6 | 36 | \r |
37 | @param A The address to convert.\r | |
38 | \r | |
39 | @retval The coverted address.\r | |
40 | \r | |
41 | **/\r | |
42 | #define PCI_TO_CF8_ADDRESS(A) \\r | |
43 | ((UINT32) ((((A) >> 4) & 0x00ffff00) | ((A) & 0xfc) | 0x80000000))\r | |
44 | \r | |
ad400b07 | 45 | /**\r |
46 | Assert the validity of a PCI CF8 address. A valid PCI CF8 address should contain 1's\r | |
47 | only in the low 28 bits, excluding bits 08..11.\r | |
48 | \r | |
49 | @param A The address to validate.\r | |
50 | @param M Additional bits to assert to be zero.\r | |
51 | \r | |
52 | **/\r | |
2f88bd3a | 53 | #define ASSERT_INVALID_PCI_ADDRESS(A, M) \\r |
ad400b07 | 54 | ASSERT (((A) & (~0xffff0ff | (M))) == 0)\r |
55 | \r | |
3e3ae634 | 56 | /**\r |
9095d37b | 57 | Registers a PCI device so PCI configuration registers may be accessed after\r |
3e3ae634 | 58 | SetVirtualAddressMap().\r |
9095d37b LG |
59 | \r |
60 | Registers the PCI device specified by Address so all the PCI configuration registers\r | |
d11195a3 | 61 | associated with that PCI device may be accessed after SetVirtualAddressMap() is called.\r |
9095d37b | 62 | \r |
3e3ae634 | 63 | If Address > 0x0FFFFFFF, then ASSERT().\r |
59ceeabe | 64 | If the register specified by Address >= 0x100, then ASSERT().\r |
3e3ae634 | 65 | \r |
2fc59a00 | 66 | @param Address The address that encodes the PCI Bus, Device, Function and\r |
3e3ae634 | 67 | Register.\r |
9095d37b | 68 | \r |
3e3ae634 | 69 | @retval RETURN_SUCCESS The PCI device was registered for runtime access.\r |
9095d37b | 70 | @retval RETURN_UNSUPPORTED An attempt was made to call this function\r |
3e3ae634 | 71 | after ExitBootServices().\r |
72 | @retval RETURN_UNSUPPORTED The resources required to access the PCI device\r | |
73 | at runtime could not be mapped.\r | |
74 | @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to\r | |
75 | complete the registration.\r | |
76 | \r | |
77 | **/\r | |
78 | RETURN_STATUS\r | |
79 | EFIAPI\r | |
80 | PciCf8RegisterForRuntimeAccess (\r | |
81 | IN UINTN Address\r | |
82 | )\r | |
83 | {\r | |
59ceeabe | 84 | ASSERT_INVALID_PCI_ADDRESS (Address, 0);\r |
3e3ae634 | 85 | return RETURN_SUCCESS;\r |
86 | }\r | |
87 | \r | |
e1f414b6 | 88 | /**\r |
89 | Reads an 8-bit PCI configuration register.\r | |
90 | \r | |
91 | Reads and returns the 8-bit PCI configuration register specified by Address.\r | |
92 | This function must guarantee that all PCI read and write operations are\r | |
93 | serialized.\r | |
94 | \r | |
95 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
96 | If the register specified by Address >= 0x100, then ASSERT().\r | |
97 | \r | |
2fc59a00 | 98 | @param Address The address that encodes the PCI Bus, Device, Function and\r |
e1f414b6 | 99 | Register.\r |
100 | \r | |
101 | @return The read value from the PCI configuration register.\r | |
102 | \r | |
103 | **/\r | |
104 | UINT8\r | |
105 | EFIAPI\r | |
106 | PciCf8Read8 (\r | |
2f88bd3a | 107 | IN UINTN Address\r |
e1f414b6 | 108 | )\r |
109 | {\r | |
96dd57ee | 110 | BOOLEAN InterruptState;\r |
111 | UINT32 AddressPort;\r | |
112 | UINT8 Result;\r | |
9095d37b | 113 | \r |
e1f414b6 | 114 | ASSERT_INVALID_PCI_ADDRESS (Address, 0);\r |
96dd57ee | 115 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 116 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 117 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 118 | Result = IoRead8 (PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3));\r |
119 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
120 | SetInterruptState (InterruptState);\r | |
121 | return Result;\r | |
e1f414b6 | 122 | }\r |
123 | \r | |
124 | /**\r | |
125 | Writes an 8-bit PCI configuration register.\r | |
126 | \r | |
127 | Writes the 8-bit PCI configuration register specified by Address with the\r | |
128 | value specified by Value. Value is returned. This function must guarantee\r | |
129 | that all PCI read and write operations are serialized.\r | |
130 | \r | |
131 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
132 | If the register specified by Address >= 0x100, then ASSERT().\r | |
133 | \r | |
2fc59a00 | 134 | @param Address The address that encodes the PCI Bus, Device, Function and\r |
e1f414b6 | 135 | Register.\r |
136 | @param Value The value to write.\r | |
137 | \r | |
138 | @return The value written to the PCI configuration register.\r | |
139 | \r | |
140 | **/\r | |
141 | UINT8\r | |
142 | EFIAPI\r | |
143 | PciCf8Write8 (\r | |
2f88bd3a MK |
144 | IN UINTN Address,\r |
145 | IN UINT8 Value\r | |
e1f414b6 | 146 | )\r |
147 | {\r | |
96dd57ee | 148 | BOOLEAN InterruptState;\r |
149 | UINT32 AddressPort;\r | |
150 | UINT8 Result;\r | |
9095d37b | 151 | \r |
e1f414b6 | 152 | ASSERT_INVALID_PCI_ADDRESS (Address, 0);\r |
96dd57ee | 153 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 154 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 155 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 156 | Result = IoWrite8 (\r |
157 | PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3),\r | |
158 | Value\r | |
159 | );\r | |
160 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
161 | SetInterruptState (InterruptState);\r | |
162 | return Result;\r | |
e1f414b6 | 163 | }\r |
164 | \r | |
165 | /**\r | |
62991af2 | 166 | Performs a bitwise OR of an 8-bit PCI configuration register with\r |
e1f414b6 | 167 | an 8-bit value.\r |
168 | \r | |
169 | Reads the 8-bit PCI configuration register specified by Address, performs a\r | |
62991af2 | 170 | bitwise OR between the read result and the value specified by\r |
e1f414b6 | 171 | OrData, and writes the result to the 8-bit PCI configuration register\r |
172 | specified by Address. The value written to the PCI configuration register is\r | |
173 | returned. This function must guarantee that all PCI read and write operations\r | |
174 | are serialized.\r | |
175 | \r | |
176 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
177 | If the register specified by Address >= 0x100, then ASSERT().\r | |
178 | \r | |
2fc59a00 | 179 | @param Address The address that encodes the PCI Bus, Device, Function and\r |
e1f414b6 | 180 | Register.\r |
181 | @param OrData The value to OR with the PCI configuration register.\r | |
182 | \r | |
183 | @return The value written back to the PCI configuration register.\r | |
184 | \r | |
185 | **/\r | |
186 | UINT8\r | |
187 | EFIAPI\r | |
188 | PciCf8Or8 (\r | |
2f88bd3a MK |
189 | IN UINTN Address,\r |
190 | IN UINT8 OrData\r | |
e1f414b6 | 191 | )\r |
192 | {\r | |
96dd57ee | 193 | BOOLEAN InterruptState;\r |
194 | UINT32 AddressPort;\r | |
195 | UINT8 Result;\r | |
9095d37b | 196 | \r |
e1f414b6 | 197 | ASSERT_INVALID_PCI_ADDRESS (Address, 0);\r |
96dd57ee | 198 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 199 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 200 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 201 | Result = IoOr8 (\r |
202 | PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3),\r | |
203 | OrData\r | |
204 | );\r | |
205 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
206 | SetInterruptState (InterruptState);\r | |
207 | return Result;\r | |
e1f414b6 | 208 | }\r |
209 | \r | |
210 | /**\r | |
211 | Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit\r | |
212 | value.\r | |
213 | \r | |
214 | Reads the 8-bit PCI configuration register specified by Address, performs a\r | |
215 | bitwise AND between the read result and the value specified by AndData, and\r | |
216 | writes the result to the 8-bit PCI configuration register specified by\r | |
217 | Address. The value written to the PCI configuration register is returned.\r | |
218 | This function must guarantee that all PCI read and write operations are\r | |
219 | serialized.\r | |
220 | \r | |
221 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
222 | If the register specified by Address >= 0x100, then ASSERT().\r | |
223 | \r | |
2fc59a00 | 224 | @param Address The address that encodes the PCI Bus, Device, Function and\r |
e1f414b6 | 225 | Register.\r |
226 | @param AndData The value to AND with the PCI configuration register.\r | |
227 | \r | |
228 | @return The value written back to the PCI configuration register.\r | |
229 | \r | |
230 | **/\r | |
231 | UINT8\r | |
232 | EFIAPI\r | |
233 | PciCf8And8 (\r | |
2f88bd3a MK |
234 | IN UINTN Address,\r |
235 | IN UINT8 AndData\r | |
e1f414b6 | 236 | )\r |
237 | {\r | |
96dd57ee | 238 | BOOLEAN InterruptState;\r |
239 | UINT32 AddressPort;\r | |
240 | UINT8 Result;\r | |
9095d37b | 241 | \r |
e1f414b6 | 242 | ASSERT_INVALID_PCI_ADDRESS (Address, 0);\r |
96dd57ee | 243 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 244 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 245 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 246 | Result = IoAnd8 (\r |
247 | PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3),\r | |
248 | AndData\r | |
249 | );\r | |
250 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
251 | SetInterruptState (InterruptState);\r | |
252 | return Result;\r | |
e1f414b6 | 253 | }\r |
254 | \r | |
255 | /**\r | |
256 | Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit\r | |
62991af2 | 257 | value, followed a bitwise OR with another 8-bit value.\r |
e1f414b6 | 258 | \r |
259 | Reads the 8-bit PCI configuration register specified by Address, performs a\r | |
260 | bitwise AND between the read result and the value specified by AndData,\r | |
62991af2 | 261 | performs a bitwise OR between the result of the AND operation and\r |
e1f414b6 | 262 | the value specified by OrData, and writes the result to the 8-bit PCI\r |
263 | configuration register specified by Address. The value written to the PCI\r | |
264 | configuration register is returned. This function must guarantee that all PCI\r | |
265 | read and write operations are serialized.\r | |
266 | \r | |
267 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
268 | If the register specified by Address >= 0x100, then ASSERT().\r | |
269 | \r | |
2fc59a00 | 270 | @param Address The address that encodes the PCI Bus, Device, Function and\r |
e1f414b6 | 271 | Register.\r |
272 | @param AndData The value to AND with the PCI configuration register.\r | |
273 | @param OrData The value to OR with the result of the AND operation.\r | |
274 | \r | |
275 | @return The value written back to the PCI configuration register.\r | |
276 | \r | |
277 | **/\r | |
278 | UINT8\r | |
279 | EFIAPI\r | |
280 | PciCf8AndThenOr8 (\r | |
2f88bd3a MK |
281 | IN UINTN Address,\r |
282 | IN UINT8 AndData,\r | |
283 | IN UINT8 OrData\r | |
e1f414b6 | 284 | )\r |
285 | {\r | |
96dd57ee | 286 | BOOLEAN InterruptState;\r |
287 | UINT32 AddressPort;\r | |
288 | UINT8 Result;\r | |
9095d37b | 289 | \r |
e1f414b6 | 290 | ASSERT_INVALID_PCI_ADDRESS (Address, 0);\r |
96dd57ee | 291 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 292 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 293 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 294 | Result = IoAndThenOr8 (\r |
295 | PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3),\r | |
296 | AndData,\r | |
297 | OrData\r | |
298 | );\r | |
299 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
300 | SetInterruptState (InterruptState);\r | |
301 | return Result;\r | |
e1f414b6 | 302 | }\r |
303 | \r | |
304 | /**\r | |
305 | Reads a bit field of a PCI configuration register.\r | |
306 | \r | |
307 | Reads the bit field in an 8-bit PCI configuration register. The bit field is\r | |
308 | specified by the StartBit and the EndBit. The value of the bit field is\r | |
309 | returned.\r | |
310 | \r | |
311 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
312 | If the register specified by Address >= 0x100, then ASSERT().\r | |
313 | If StartBit is greater than 7, then ASSERT().\r | |
314 | If EndBit is greater than 7, then ASSERT().\r | |
315 | If EndBit is less than StartBit, then ASSERT().\r | |
316 | \r | |
2fc59a00 | 317 | @param Address The PCI configuration register to read.\r |
e1f414b6 | 318 | @param StartBit The ordinal of the least significant bit in the bit field.\r |
319 | Range 0..7.\r | |
320 | @param EndBit The ordinal of the most significant bit in the bit field.\r | |
321 | Range 0..7.\r | |
322 | \r | |
323 | @return The value of the bit field read from the PCI configuration register.\r | |
324 | \r | |
325 | **/\r | |
326 | UINT8\r | |
327 | EFIAPI\r | |
328 | PciCf8BitFieldRead8 (\r | |
2f88bd3a MK |
329 | IN UINTN Address,\r |
330 | IN UINTN StartBit,\r | |
331 | IN UINTN EndBit\r | |
e1f414b6 | 332 | )\r |
333 | {\r | |
96dd57ee | 334 | BOOLEAN InterruptState;\r |
335 | UINT32 AddressPort;\r | |
336 | UINT8 Result;\r | |
9095d37b | 337 | \r |
e1f414b6 | 338 | ASSERT_INVALID_PCI_ADDRESS (Address, 0);\r |
96dd57ee | 339 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 340 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 341 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 342 | Result = IoBitFieldRead8 (\r |
343 | PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3),\r | |
344 | StartBit,\r | |
345 | EndBit\r | |
346 | );\r | |
347 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
348 | SetInterruptState (InterruptState);\r | |
349 | return Result;\r | |
e1f414b6 | 350 | }\r |
351 | \r | |
352 | /**\r | |
353 | Writes a bit field to a PCI configuration register.\r | |
354 | \r | |
355 | Writes Value to the bit field of the PCI configuration register. The bit\r | |
356 | field is specified by the StartBit and the EndBit. All other bits in the\r | |
357 | destination PCI configuration register are preserved. The new value of the\r | |
358 | 8-bit register is returned.\r | |
359 | \r | |
360 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
361 | If the register specified by Address >= 0x100, then ASSERT().\r | |
362 | If StartBit is greater than 7, then ASSERT().\r | |
363 | If EndBit is greater than 7, then ASSERT().\r | |
364 | If EndBit is less than StartBit, then ASSERT().\r | |
94952554 | 365 | If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().\r |
e1f414b6 | 366 | \r |
2fc59a00 | 367 | @param Address The PCI configuration register to write.\r |
e1f414b6 | 368 | @param StartBit The ordinal of the least significant bit in the bit field.\r |
369 | Range 0..7.\r | |
370 | @param EndBit The ordinal of the most significant bit in the bit field.\r | |
371 | Range 0..7.\r | |
2fc59a00 | 372 | @param Value The new value of the bit field.\r |
e1f414b6 | 373 | \r |
374 | @return The value written back to the PCI configuration register.\r | |
375 | \r | |
376 | **/\r | |
377 | UINT8\r | |
378 | EFIAPI\r | |
379 | PciCf8BitFieldWrite8 (\r | |
2f88bd3a MK |
380 | IN UINTN Address,\r |
381 | IN UINTN StartBit,\r | |
382 | IN UINTN EndBit,\r | |
383 | IN UINT8 Value\r | |
e1f414b6 | 384 | )\r |
385 | {\r | |
96dd57ee | 386 | BOOLEAN InterruptState;\r |
387 | UINT32 AddressPort;\r | |
388 | UINT8 Result;\r | |
9095d37b | 389 | \r |
e1f414b6 | 390 | ASSERT_INVALID_PCI_ADDRESS (Address, 0);\r |
96dd57ee | 391 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 392 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 393 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 394 | Result = IoBitFieldWrite8 (\r |
395 | PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3),\r | |
396 | StartBit,\r | |
397 | EndBit,\r | |
398 | Value\r | |
399 | );\r | |
400 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
401 | SetInterruptState (InterruptState);\r | |
402 | return Result;\r | |
e1f414b6 | 403 | }\r |
404 | \r | |
405 | /**\r | |
406 | Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and\r | |
407 | writes the result back to the bit field in the 8-bit port.\r | |
408 | \r | |
409 | Reads the 8-bit PCI configuration register specified by Address, performs a\r | |
62991af2 | 410 | bitwise OR between the read result and the value specified by\r |
e1f414b6 | 411 | OrData, and writes the result to the 8-bit PCI configuration register\r |
412 | specified by Address. The value written to the PCI configuration register is\r | |
413 | returned. This function must guarantee that all PCI read and write operations\r | |
414 | are serialized. Extra left bits in OrData are stripped.\r | |
415 | \r | |
416 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
417 | If the register specified by Address >= 0x100, then ASSERT().\r | |
418 | If StartBit is greater than 7, then ASSERT().\r | |
419 | If EndBit is greater than 7, then ASSERT().\r | |
420 | If EndBit is less than StartBit, then ASSERT().\r | |
94952554 | 421 | If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().\r |
e1f414b6 | 422 | \r |
2fc59a00 | 423 | @param Address The PCI configuration register to write.\r |
e1f414b6 | 424 | @param StartBit The ordinal of the least significant bit in the bit field.\r |
425 | Range 0..7.\r | |
426 | @param EndBit The ordinal of the most significant bit in the bit field.\r | |
427 | Range 0..7.\r | |
428 | @param OrData The value to OR with the PCI configuration register.\r | |
429 | \r | |
430 | @return The value written back to the PCI configuration register.\r | |
431 | \r | |
432 | **/\r | |
433 | UINT8\r | |
434 | EFIAPI\r | |
435 | PciCf8BitFieldOr8 (\r | |
2f88bd3a MK |
436 | IN UINTN Address,\r |
437 | IN UINTN StartBit,\r | |
438 | IN UINTN EndBit,\r | |
439 | IN UINT8 OrData\r | |
e1f414b6 | 440 | )\r |
441 | {\r | |
96dd57ee | 442 | BOOLEAN InterruptState;\r |
443 | UINT32 AddressPort;\r | |
444 | UINT8 Result;\r | |
9095d37b | 445 | \r |
e1f414b6 | 446 | ASSERT_INVALID_PCI_ADDRESS (Address, 0);\r |
96dd57ee | 447 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 448 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 449 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 450 | Result = IoBitFieldOr8 (\r |
451 | PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3),\r | |
452 | StartBit,\r | |
453 | EndBit,\r | |
454 | OrData\r | |
455 | );\r | |
456 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
457 | SetInterruptState (InterruptState);\r | |
458 | return Result;\r | |
e1f414b6 | 459 | }\r |
460 | \r | |
461 | /**\r | |
462 | Reads a bit field in an 8-bit PCI configuration register, performs a bitwise\r | |
463 | AND, and writes the result back to the bit field in the 8-bit register.\r | |
464 | \r | |
465 | Reads the 8-bit PCI configuration register specified by Address, performs a\r | |
466 | bitwise AND between the read result and the value specified by AndData, and\r | |
467 | writes the result to the 8-bit PCI configuration register specified by\r | |
468 | Address. The value written to the PCI configuration register is returned.\r | |
469 | This function must guarantee that all PCI read and write operations are\r | |
470 | serialized. Extra left bits in AndData are stripped.\r | |
471 | \r | |
472 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
473 | If the register specified by Address >= 0x100, then ASSERT().\r | |
474 | If StartBit is greater than 7, then ASSERT().\r | |
475 | If EndBit is greater than 7, then ASSERT().\r | |
476 | If EndBit is less than StartBit, then ASSERT().\r | |
94952554 | 477 | If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().\r |
e1f414b6 | 478 | \r |
2fc59a00 | 479 | @param Address The PCI configuration register to write.\r |
e1f414b6 | 480 | @param StartBit The ordinal of the least significant bit in the bit field.\r |
481 | Range 0..7.\r | |
482 | @param EndBit The ordinal of the most significant bit in the bit field.\r | |
483 | Range 0..7.\r | |
484 | @param AndData The value to AND with the PCI configuration register.\r | |
485 | \r | |
486 | @return The value written back to the PCI configuration register.\r | |
487 | \r | |
488 | **/\r | |
489 | UINT8\r | |
490 | EFIAPI\r | |
491 | PciCf8BitFieldAnd8 (\r | |
2f88bd3a MK |
492 | IN UINTN Address,\r |
493 | IN UINTN StartBit,\r | |
494 | IN UINTN EndBit,\r | |
495 | IN UINT8 AndData\r | |
e1f414b6 | 496 | )\r |
497 | {\r | |
96dd57ee | 498 | BOOLEAN InterruptState;\r |
499 | UINT32 AddressPort;\r | |
500 | UINT8 Result;\r | |
9095d37b | 501 | \r |
e1f414b6 | 502 | ASSERT_INVALID_PCI_ADDRESS (Address, 0);\r |
96dd57ee | 503 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 504 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 505 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 506 | Result = IoBitFieldAnd8 (\r |
507 | PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3),\r | |
508 | StartBit,\r | |
509 | EndBit,\r | |
510 | AndData\r | |
511 | );\r | |
512 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
513 | SetInterruptState (InterruptState);\r | |
514 | return Result;\r | |
e1f414b6 | 515 | }\r |
516 | \r | |
517 | /**\r | |
518 | Reads a bit field in an 8-bit port, performs a bitwise AND followed by a\r | |
62991af2 | 519 | bitwise OR, and writes the result back to the bit field in the\r |
e1f414b6 | 520 | 8-bit port.\r |
521 | \r | |
522 | Reads the 8-bit PCI configuration register specified by Address, performs a\r | |
62991af2 | 523 | bitwise AND followed by a bitwise OR between the read result and\r |
e1f414b6 | 524 | the value specified by AndData, and writes the result to the 8-bit PCI\r |
525 | configuration register specified by Address. The value written to the PCI\r | |
526 | configuration register is returned. This function must guarantee that all PCI\r | |
527 | read and write operations are serialized. Extra left bits in both AndData and\r | |
528 | OrData are stripped.\r | |
529 | \r | |
530 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
531 | If the register specified by Address >= 0x100, then ASSERT().\r | |
532 | If StartBit is greater than 7, then ASSERT().\r | |
533 | If EndBit is greater than 7, then ASSERT().\r | |
534 | If EndBit is less than StartBit, then ASSERT().\r | |
94952554 LG |
535 | If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().\r |
536 | If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().\r | |
e1f414b6 | 537 | \r |
2fc59a00 | 538 | @param Address The PCI configuration register to write.\r |
e1f414b6 | 539 | @param StartBit The ordinal of the least significant bit in the bit field.\r |
540 | Range 0..7.\r | |
541 | @param EndBit The ordinal of the most significant bit in the bit field.\r | |
542 | Range 0..7.\r | |
543 | @param AndData The value to AND with the PCI configuration register.\r | |
544 | @param OrData The value to OR with the result of the AND operation.\r | |
545 | \r | |
546 | @return The value written back to the PCI configuration register.\r | |
547 | \r | |
548 | **/\r | |
549 | UINT8\r | |
550 | EFIAPI\r | |
2f88bd3a MK |
551 | PciCf8BitFieldAndThenOr8 (\r |
552 | IN UINTN Address,\r | |
553 | IN UINTN StartBit,\r | |
554 | IN UINTN EndBit,\r | |
555 | IN UINT8 AndData,\r | |
556 | IN UINT8 OrData\r | |
e1f414b6 | 557 | )\r |
558 | {\r | |
96dd57ee | 559 | BOOLEAN InterruptState;\r |
560 | UINT32 AddressPort;\r | |
561 | UINT8 Result;\r | |
9095d37b | 562 | \r |
e1f414b6 | 563 | ASSERT_INVALID_PCI_ADDRESS (Address, 0);\r |
96dd57ee | 564 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 565 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 566 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 567 | Result = IoBitFieldAndThenOr8 (\r |
568 | PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3),\r | |
569 | StartBit,\r | |
570 | EndBit,\r | |
571 | AndData,\r | |
572 | OrData\r | |
573 | );\r | |
574 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
575 | SetInterruptState (InterruptState);\r | |
576 | return Result;\r | |
e1f414b6 | 577 | }\r |
578 | \r | |
579 | /**\r | |
580 | Reads a 16-bit PCI configuration register.\r | |
581 | \r | |
582 | Reads and returns the 16-bit PCI configuration register specified by Address.\r | |
583 | This function must guarantee that all PCI read and write operations are\r | |
584 | serialized.\r | |
585 | \r | |
586 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
587 | If Address is not aligned on a 16-bit boundary, then ASSERT().\r | |
588 | If the register specified by Address >= 0x100, then ASSERT().\r | |
589 | \r | |
2fc59a00 | 590 | @param Address The address that encodes the PCI Bus, Device, Function and\r |
e1f414b6 | 591 | Register.\r |
592 | \r | |
593 | @return The read value from the PCI configuration register.\r | |
594 | \r | |
595 | **/\r | |
596 | UINT16\r | |
597 | EFIAPI\r | |
598 | PciCf8Read16 (\r | |
2f88bd3a | 599 | IN UINTN Address\r |
e1f414b6 | 600 | )\r |
601 | {\r | |
96dd57ee | 602 | BOOLEAN InterruptState;\r |
603 | UINT32 AddressPort;\r | |
604 | UINT16 Result;\r | |
9095d37b | 605 | \r |
e1f414b6 | 606 | ASSERT_INVALID_PCI_ADDRESS (Address, 1);\r |
96dd57ee | 607 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 608 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 609 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 610 | Result = IoRead16 (PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2));\r |
611 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
612 | SetInterruptState (InterruptState);\r | |
613 | return Result;\r | |
e1f414b6 | 614 | }\r |
615 | \r | |
616 | /**\r | |
617 | Writes a 16-bit PCI configuration register.\r | |
618 | \r | |
619 | Writes the 16-bit PCI configuration register specified by Address with the\r | |
620 | value specified by Value. Value is returned. This function must guarantee\r | |
621 | that all PCI read and write operations are serialized.\r | |
622 | \r | |
623 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
624 | If Address is not aligned on a 16-bit boundary, then ASSERT().\r | |
625 | If the register specified by Address >= 0x100, then ASSERT().\r | |
626 | \r | |
2fc59a00 | 627 | @param Address The address that encodes the PCI Bus, Device, Function and\r |
e1f414b6 | 628 | Register.\r |
629 | @param Value The value to write.\r | |
630 | \r | |
631 | @return The value written to the PCI configuration register.\r | |
632 | \r | |
633 | **/\r | |
634 | UINT16\r | |
635 | EFIAPI\r | |
636 | PciCf8Write16 (\r | |
2f88bd3a MK |
637 | IN UINTN Address,\r |
638 | IN UINT16 Value\r | |
e1f414b6 | 639 | )\r |
640 | {\r | |
96dd57ee | 641 | BOOLEAN InterruptState;\r |
642 | UINT32 AddressPort;\r | |
643 | UINT16 Result;\r | |
9095d37b | 644 | \r |
e1f414b6 | 645 | ASSERT_INVALID_PCI_ADDRESS (Address, 1);\r |
96dd57ee | 646 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 647 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 648 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 649 | Result = IoWrite16 (\r |
650 | PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2),\r | |
651 | Value\r | |
652 | );\r | |
653 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
654 | SetInterruptState (InterruptState);\r | |
655 | return Result;\r | |
e1f414b6 | 656 | }\r |
657 | \r | |
658 | /**\r | |
62991af2 | 659 | Performs a bitwise OR of a 16-bit PCI configuration register with\r |
e1f414b6 | 660 | a 16-bit value.\r |
661 | \r | |
662 | Reads the 16-bit PCI configuration register specified by Address, performs a\r | |
62991af2 | 663 | bitwise OR between the read result and the value specified by\r |
e1f414b6 | 664 | OrData, and writes the result to the 16-bit PCI configuration register\r |
665 | specified by Address. The value written to the PCI configuration register is\r | |
666 | returned. This function must guarantee that all PCI read and write operations\r | |
667 | are serialized.\r | |
668 | \r | |
669 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
670 | If Address is not aligned on a 16-bit boundary, then ASSERT().\r | |
671 | If the register specified by Address >= 0x100, then ASSERT().\r | |
672 | \r | |
2fc59a00 | 673 | @param Address The address that encodes the PCI Bus, Device, Function and\r |
e1f414b6 | 674 | Register.\r |
675 | @param OrData The value to OR with the PCI configuration register.\r | |
676 | \r | |
677 | @return The value written back to the PCI configuration register.\r | |
678 | \r | |
679 | **/\r | |
680 | UINT16\r | |
681 | EFIAPI\r | |
682 | PciCf8Or16 (\r | |
2f88bd3a MK |
683 | IN UINTN Address,\r |
684 | IN UINT16 OrData\r | |
e1f414b6 | 685 | )\r |
686 | {\r | |
96dd57ee | 687 | BOOLEAN InterruptState;\r |
688 | UINT32 AddressPort;\r | |
689 | UINT16 Result;\r | |
9095d37b | 690 | \r |
e1f414b6 | 691 | ASSERT_INVALID_PCI_ADDRESS (Address, 1);\r |
96dd57ee | 692 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 693 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 694 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 695 | Result = IoOr16 (\r |
696 | PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2),\r | |
697 | OrData\r | |
698 | );\r | |
699 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
700 | SetInterruptState (InterruptState);\r | |
701 | return Result;\r | |
e1f414b6 | 702 | }\r |
703 | \r | |
704 | /**\r | |
705 | Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit\r | |
706 | value.\r | |
707 | \r | |
708 | Reads the 16-bit PCI configuration register specified by Address, performs a\r | |
709 | bitwise AND between the read result and the value specified by AndData, and\r | |
710 | writes the result to the 16-bit PCI configuration register specified by\r | |
711 | Address. The value written to the PCI configuration register is returned.\r | |
712 | This function must guarantee that all PCI read and write operations are\r | |
713 | serialized.\r | |
714 | \r | |
715 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
716 | If Address is not aligned on a 16-bit boundary, then ASSERT().\r | |
717 | If the register specified by Address >= 0x100, then ASSERT().\r | |
718 | \r | |
2fc59a00 | 719 | @param Address The address that encodes the PCI Bus, Device, Function and\r |
e1f414b6 | 720 | Register.\r |
721 | @param AndData The value to AND with the PCI configuration register.\r | |
722 | \r | |
723 | @return The value written back to the PCI configuration register.\r | |
724 | \r | |
725 | **/\r | |
726 | UINT16\r | |
727 | EFIAPI\r | |
728 | PciCf8And16 (\r | |
2f88bd3a MK |
729 | IN UINTN Address,\r |
730 | IN UINT16 AndData\r | |
e1f414b6 | 731 | )\r |
732 | {\r | |
96dd57ee | 733 | BOOLEAN InterruptState;\r |
734 | UINT32 AddressPort;\r | |
735 | UINT16 Result;\r | |
9095d37b | 736 | \r |
e1f414b6 | 737 | ASSERT_INVALID_PCI_ADDRESS (Address, 1);\r |
96dd57ee | 738 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 739 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 740 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 741 | Result = IoAnd16 (\r |
742 | PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2),\r | |
743 | AndData\r | |
744 | );\r | |
745 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
746 | SetInterruptState (InterruptState);\r | |
747 | return Result;\r | |
e1f414b6 | 748 | }\r |
749 | \r | |
750 | /**\r | |
751 | Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit\r | |
62991af2 | 752 | value, followed a bitwise OR with another 16-bit value.\r |
e1f414b6 | 753 | \r |
754 | Reads the 16-bit PCI configuration register specified by Address, performs a\r | |
755 | bitwise AND between the read result and the value specified by AndData,\r | |
62991af2 | 756 | performs a bitwise OR between the result of the AND operation and\r |
e1f414b6 | 757 | the value specified by OrData, and writes the result to the 16-bit PCI\r |
758 | configuration register specified by Address. The value written to the PCI\r | |
759 | configuration register is returned. This function must guarantee that all PCI\r | |
760 | read and write operations are serialized.\r | |
761 | \r | |
762 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
763 | If Address is not aligned on a 16-bit boundary, then ASSERT().\r | |
764 | If the register specified by Address >= 0x100, then ASSERT().\r | |
765 | \r | |
2fc59a00 | 766 | @param Address The address that encodes the PCI Bus, Device, Function and\r |
e1f414b6 | 767 | Register.\r |
768 | @param AndData The value to AND with the PCI configuration register.\r | |
769 | @param OrData The value to OR with the result of the AND operation.\r | |
770 | \r | |
771 | @return The value written back to the PCI configuration register.\r | |
772 | \r | |
773 | **/\r | |
774 | UINT16\r | |
775 | EFIAPI\r | |
776 | PciCf8AndThenOr16 (\r | |
2f88bd3a MK |
777 | IN UINTN Address,\r |
778 | IN UINT16 AndData,\r | |
779 | IN UINT16 OrData\r | |
e1f414b6 | 780 | )\r |
781 | {\r | |
96dd57ee | 782 | BOOLEAN InterruptState;\r |
783 | UINT32 AddressPort;\r | |
784 | UINT16 Result;\r | |
9095d37b | 785 | \r |
e1f414b6 | 786 | ASSERT_INVALID_PCI_ADDRESS (Address, 1);\r |
96dd57ee | 787 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 788 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 789 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 790 | Result = IoAndThenOr16 (\r |
791 | PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2),\r | |
792 | AndData,\r | |
793 | OrData\r | |
794 | );\r | |
795 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
796 | SetInterruptState (InterruptState);\r | |
797 | return Result;\r | |
e1f414b6 | 798 | }\r |
799 | \r | |
800 | /**\r | |
801 | Reads a bit field of a PCI configuration register.\r | |
802 | \r | |
803 | Reads the bit field in a 16-bit PCI configuration register. The bit field is\r | |
804 | specified by the StartBit and the EndBit. The value of the bit field is\r | |
805 | returned.\r | |
806 | \r | |
807 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
808 | If Address is not aligned on a 16-bit boundary, then ASSERT().\r | |
809 | If the register specified by Address >= 0x100, then ASSERT().\r | |
810 | If StartBit is greater than 15, then ASSERT().\r | |
811 | If EndBit is greater than 15, then ASSERT().\r | |
812 | If EndBit is less than StartBit, then ASSERT().\r | |
813 | \r | |
2fc59a00 | 814 | @param Address The PCI configuration register to read.\r |
e1f414b6 | 815 | @param StartBit The ordinal of the least significant bit in the bit field.\r |
816 | Range 0..15.\r | |
817 | @param EndBit The ordinal of the most significant bit in the bit field.\r | |
818 | Range 0..15.\r | |
819 | \r | |
820 | @return The value of the bit field read from the PCI configuration register.\r | |
821 | \r | |
822 | **/\r | |
823 | UINT16\r | |
824 | EFIAPI\r | |
825 | PciCf8BitFieldRead16 (\r | |
2f88bd3a MK |
826 | IN UINTN Address,\r |
827 | IN UINTN StartBit,\r | |
828 | IN UINTN EndBit\r | |
e1f414b6 | 829 | )\r |
830 | {\r | |
96dd57ee | 831 | BOOLEAN InterruptState;\r |
832 | UINT32 AddressPort;\r | |
833 | UINT16 Result;\r | |
9095d37b | 834 | \r |
e1f414b6 | 835 | ASSERT_INVALID_PCI_ADDRESS (Address, 1);\r |
96dd57ee | 836 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 837 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 838 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 839 | Result = IoBitFieldRead16 (\r |
840 | PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2),\r | |
841 | StartBit,\r | |
842 | EndBit\r | |
843 | );\r | |
844 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
845 | SetInterruptState (InterruptState);\r | |
846 | return Result;\r | |
e1f414b6 | 847 | }\r |
848 | \r | |
849 | /**\r | |
850 | Writes a bit field to a PCI configuration register.\r | |
851 | \r | |
852 | Writes Value to the bit field of the PCI configuration register. The bit\r | |
853 | field is specified by the StartBit and the EndBit. All other bits in the\r | |
854 | destination PCI configuration register are preserved. The new value of the\r | |
855 | 16-bit register is returned.\r | |
856 | \r | |
857 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
858 | If Address is not aligned on a 16-bit boundary, then ASSERT().\r | |
859 | If the register specified by Address >= 0x100, then ASSERT().\r | |
860 | If StartBit is greater than 15, then ASSERT().\r | |
861 | If EndBit is greater than 15, then ASSERT().\r | |
862 | If EndBit is less than StartBit, then ASSERT().\r | |
94952554 | 863 | If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().\r |
e1f414b6 | 864 | \r |
2fc59a00 | 865 | @param Address The PCI configuration register to write.\r |
e1f414b6 | 866 | @param StartBit The ordinal of the least significant bit in the bit field.\r |
867 | Range 0..15.\r | |
868 | @param EndBit The ordinal of the most significant bit in the bit field.\r | |
869 | Range 0..15.\r | |
2fc59a00 | 870 | @param Value The new value of the bit field.\r |
e1f414b6 | 871 | \r |
872 | @return The value written back to the PCI configuration register.\r | |
873 | \r | |
874 | **/\r | |
875 | UINT16\r | |
876 | EFIAPI\r | |
877 | PciCf8BitFieldWrite16 (\r | |
2f88bd3a MK |
878 | IN UINTN Address,\r |
879 | IN UINTN StartBit,\r | |
880 | IN UINTN EndBit,\r | |
881 | IN UINT16 Value\r | |
e1f414b6 | 882 | )\r |
883 | {\r | |
96dd57ee | 884 | BOOLEAN InterruptState;\r |
885 | UINT32 AddressPort;\r | |
886 | UINT16 Result;\r | |
9095d37b | 887 | \r |
e1f414b6 | 888 | ASSERT_INVALID_PCI_ADDRESS (Address, 1);\r |
96dd57ee | 889 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 890 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 891 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 892 | Result = IoBitFieldWrite16 (\r |
893 | PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2),\r | |
894 | StartBit,\r | |
895 | EndBit,\r | |
896 | Value\r | |
897 | );\r | |
898 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
899 | SetInterruptState (InterruptState);\r | |
900 | return Result;\r | |
e1f414b6 | 901 | }\r |
902 | \r | |
903 | /**\r | |
904 | Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and\r | |
905 | writes the result back to the bit field in the 16-bit port.\r | |
906 | \r | |
907 | Reads the 16-bit PCI configuration register specified by Address, performs a\r | |
62991af2 | 908 | bitwise OR between the read result and the value specified by\r |
e1f414b6 | 909 | OrData, and writes the result to the 16-bit PCI configuration register\r |
910 | specified by Address. The value written to the PCI configuration register is\r | |
911 | returned. This function must guarantee that all PCI read and write operations\r | |
912 | are serialized. Extra left bits in OrData are stripped.\r | |
913 | \r | |
914 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
915 | If Address is not aligned on a 16-bit boundary, then ASSERT().\r | |
916 | If the register specified by Address >= 0x100, then ASSERT().\r | |
917 | If StartBit is greater than 15, then ASSERT().\r | |
918 | If EndBit is greater than 15, then ASSERT().\r | |
919 | If EndBit is less than StartBit, then ASSERT().\r | |
94952554 | 920 | If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().\r |
e1f414b6 | 921 | \r |
2fc59a00 | 922 | @param Address The PCI configuration register to write.\r |
e1f414b6 | 923 | @param StartBit The ordinal of the least significant bit in the bit field.\r |
924 | Range 0..15.\r | |
925 | @param EndBit The ordinal of the most significant bit in the bit field.\r | |
926 | Range 0..15.\r | |
927 | @param OrData The value to OR with the PCI configuration register.\r | |
928 | \r | |
929 | @return The value written back to the PCI configuration register.\r | |
930 | \r | |
931 | **/\r | |
932 | UINT16\r | |
933 | EFIAPI\r | |
934 | PciCf8BitFieldOr16 (\r | |
2f88bd3a MK |
935 | IN UINTN Address,\r |
936 | IN UINTN StartBit,\r | |
937 | IN UINTN EndBit,\r | |
938 | IN UINT16 OrData\r | |
e1f414b6 | 939 | )\r |
940 | {\r | |
96dd57ee | 941 | BOOLEAN InterruptState;\r |
942 | UINT32 AddressPort;\r | |
943 | UINT16 Result;\r | |
9095d37b | 944 | \r |
e1f414b6 | 945 | ASSERT_INVALID_PCI_ADDRESS (Address, 1);\r |
96dd57ee | 946 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 947 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 948 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 949 | Result = IoBitFieldOr16 (\r |
950 | PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2),\r | |
951 | StartBit,\r | |
952 | EndBit,\r | |
953 | OrData\r | |
954 | );\r | |
955 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
956 | SetInterruptState (InterruptState);\r | |
957 | return Result;\r | |
e1f414b6 | 958 | }\r |
959 | \r | |
960 | /**\r | |
961 | Reads a bit field in a 16-bit PCI configuration register, performs a bitwise\r | |
962 | AND, and writes the result back to the bit field in the 16-bit register.\r | |
963 | \r | |
964 | Reads the 16-bit PCI configuration register specified by Address, performs a\r | |
965 | bitwise AND between the read result and the value specified by AndData, and\r | |
966 | writes the result to the 16-bit PCI configuration register specified by\r | |
967 | Address. The value written to the PCI configuration register is returned.\r | |
968 | This function must guarantee that all PCI read and write operations are\r | |
969 | serialized. Extra left bits in AndData are stripped.\r | |
970 | \r | |
971 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
972 | If Address is not aligned on a 16-bit boundary, then ASSERT().\r | |
973 | If the register specified by Address >= 0x100, then ASSERT().\r | |
974 | If StartBit is greater than 15, then ASSERT().\r | |
975 | If EndBit is greater than 15, then ASSERT().\r | |
976 | If EndBit is less than StartBit, then ASSERT().\r | |
94952554 | 977 | If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().\r |
e1f414b6 | 978 | \r |
2fc59a00 | 979 | @param Address The PCI configuration register to write.\r |
e1f414b6 | 980 | @param StartBit The ordinal of the least significant bit in the bit field.\r |
981 | Range 0..15.\r | |
982 | @param EndBit The ordinal of the most significant bit in the bit field.\r | |
983 | Range 0..15.\r | |
984 | @param AndData The value to AND with the PCI configuration register.\r | |
985 | \r | |
986 | @return The value written back to the PCI configuration register.\r | |
987 | \r | |
988 | **/\r | |
989 | UINT16\r | |
990 | EFIAPI\r | |
991 | PciCf8BitFieldAnd16 (\r | |
2f88bd3a MK |
992 | IN UINTN Address,\r |
993 | IN UINTN StartBit,\r | |
994 | IN UINTN EndBit,\r | |
995 | IN UINT16 AndData\r | |
e1f414b6 | 996 | )\r |
997 | {\r | |
96dd57ee | 998 | BOOLEAN InterruptState;\r |
999 | UINT32 AddressPort;\r | |
1000 | UINT16 Result;\r | |
9095d37b | 1001 | \r |
e1f414b6 | 1002 | ASSERT_INVALID_PCI_ADDRESS (Address, 1);\r |
96dd57ee | 1003 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 1004 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 1005 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 1006 | Result = IoBitFieldAnd16 (\r |
1007 | PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2),\r | |
1008 | StartBit,\r | |
1009 | EndBit,\r | |
1010 | AndData\r | |
1011 | );\r | |
1012 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
1013 | SetInterruptState (InterruptState);\r | |
1014 | return Result;\r | |
e1f414b6 | 1015 | }\r |
1016 | \r | |
1017 | /**\r | |
1018 | Reads a bit field in a 16-bit port, performs a bitwise AND followed by a\r | |
62991af2 | 1019 | bitwise OR, and writes the result back to the bit field in the\r |
e1f414b6 | 1020 | 16-bit port.\r |
1021 | \r | |
1022 | Reads the 16-bit PCI configuration register specified by Address, performs a\r | |
62991af2 | 1023 | bitwise AND followed by a bitwise OR between the read result and\r |
e1f414b6 | 1024 | the value specified by AndData, and writes the result to the 16-bit PCI\r |
1025 | configuration register specified by Address. The value written to the PCI\r | |
1026 | configuration register is returned. This function must guarantee that all PCI\r | |
1027 | read and write operations are serialized. Extra left bits in both AndData and\r | |
1028 | OrData are stripped.\r | |
1029 | \r | |
1030 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
1031 | If Address is not aligned on a 16-bit boundary, then ASSERT().\r | |
1032 | If the register specified by Address >= 0x100, then ASSERT().\r | |
1033 | If StartBit is greater than 15, then ASSERT().\r | |
1034 | If EndBit is greater than 15, then ASSERT().\r | |
1035 | If EndBit is less than StartBit, then ASSERT().\r | |
94952554 LG |
1036 | If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().\r |
1037 | If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().\r | |
e1f414b6 | 1038 | \r |
2fc59a00 | 1039 | @param Address The PCI configuration register to write.\r |
e1f414b6 | 1040 | @param StartBit The ordinal of the least significant bit in the bit field.\r |
1041 | Range 0..15.\r | |
1042 | @param EndBit The ordinal of the most significant bit in the bit field.\r | |
1043 | Range 0..15.\r | |
1044 | @param AndData The value to AND with the PCI configuration register.\r | |
1045 | @param OrData The value to OR with the result of the AND operation.\r | |
1046 | \r | |
1047 | @return The value written back to the PCI configuration register.\r | |
1048 | \r | |
1049 | **/\r | |
1050 | UINT16\r | |
1051 | EFIAPI\r | |
2f88bd3a MK |
1052 | PciCf8BitFieldAndThenOr16 (\r |
1053 | IN UINTN Address,\r | |
1054 | IN UINTN StartBit,\r | |
1055 | IN UINTN EndBit,\r | |
1056 | IN UINT16 AndData,\r | |
1057 | IN UINT16 OrData\r | |
e1f414b6 | 1058 | )\r |
1059 | {\r | |
96dd57ee | 1060 | BOOLEAN InterruptState;\r |
1061 | UINT32 AddressPort;\r | |
1062 | UINT16 Result;\r | |
9095d37b | 1063 | \r |
e1f414b6 | 1064 | ASSERT_INVALID_PCI_ADDRESS (Address, 1);\r |
96dd57ee | 1065 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 1066 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 1067 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 1068 | Result = IoBitFieldAndThenOr16 (\r |
1069 | PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2),\r | |
1070 | StartBit,\r | |
1071 | EndBit,\r | |
1072 | AndData,\r | |
1073 | OrData\r | |
1074 | );\r | |
1075 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
1076 | SetInterruptState (InterruptState);\r | |
1077 | return Result;\r | |
e1f414b6 | 1078 | }\r |
1079 | \r | |
1080 | /**\r | |
1081 | Reads a 32-bit PCI configuration register.\r | |
1082 | \r | |
1083 | Reads and returns the 32-bit PCI configuration register specified by Address.\r | |
1084 | This function must guarantee that all PCI read and write operations are\r | |
1085 | serialized.\r | |
1086 | \r | |
1087 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
1088 | If Address is not aligned on a 32-bit boundary, then ASSERT().\r | |
1089 | If the register specified by Address >= 0x100, then ASSERT().\r | |
1090 | \r | |
2fc59a00 | 1091 | @param Address The address that encodes the PCI Bus, Device, Function and\r |
e1f414b6 | 1092 | Register.\r |
1093 | \r | |
1094 | @return The read value from the PCI configuration register.\r | |
1095 | \r | |
1096 | **/\r | |
1097 | UINT32\r | |
1098 | EFIAPI\r | |
1099 | PciCf8Read32 (\r | |
2f88bd3a | 1100 | IN UINTN Address\r |
e1f414b6 | 1101 | )\r |
1102 | {\r | |
96dd57ee | 1103 | BOOLEAN InterruptState;\r |
1104 | UINT32 AddressPort;\r | |
1105 | UINT32 Result;\r | |
9095d37b | 1106 | \r |
e1f414b6 | 1107 | ASSERT_INVALID_PCI_ADDRESS (Address, 3);\r |
96dd57ee | 1108 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 1109 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 1110 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 1111 | Result = IoRead32 (PCI_CONFIGURATION_DATA_PORT);\r |
1112 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
1113 | SetInterruptState (InterruptState);\r | |
1114 | return Result;\r | |
e1f414b6 | 1115 | }\r |
1116 | \r | |
1117 | /**\r | |
1118 | Writes a 32-bit PCI configuration register.\r | |
1119 | \r | |
1120 | Writes the 32-bit PCI configuration register specified by Address with the\r | |
1121 | value specified by Value. Value is returned. This function must guarantee\r | |
1122 | that all PCI read and write operations are serialized.\r | |
1123 | \r | |
1124 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
1125 | If Address is not aligned on a 32-bit boundary, then ASSERT().\r | |
1126 | If the register specified by Address >= 0x100, then ASSERT().\r | |
1127 | \r | |
2fc59a00 | 1128 | @param Address The address that encodes the PCI Bus, Device, Function and\r |
e1f414b6 | 1129 | Register.\r |
1130 | @param Value The value to write.\r | |
1131 | \r | |
1132 | @return The value written to the PCI configuration register.\r | |
1133 | \r | |
1134 | **/\r | |
1135 | UINT32\r | |
1136 | EFIAPI\r | |
1137 | PciCf8Write32 (\r | |
2f88bd3a MK |
1138 | IN UINTN Address,\r |
1139 | IN UINT32 Value\r | |
e1f414b6 | 1140 | )\r |
1141 | {\r | |
96dd57ee | 1142 | BOOLEAN InterruptState;\r |
1143 | UINT32 AddressPort;\r | |
1144 | UINT32 Result;\r | |
9095d37b | 1145 | \r |
e1f414b6 | 1146 | ASSERT_INVALID_PCI_ADDRESS (Address, 3);\r |
96dd57ee | 1147 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 1148 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 1149 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 1150 | Result = IoWrite32 (\r |
1151 | PCI_CONFIGURATION_DATA_PORT,\r | |
1152 | Value\r | |
1153 | );\r | |
1154 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
1155 | SetInterruptState (InterruptState);\r | |
1156 | return Result;\r | |
e1f414b6 | 1157 | }\r |
1158 | \r | |
1159 | /**\r | |
62991af2 | 1160 | Performs a bitwise OR of a 32-bit PCI configuration register with\r |
e1f414b6 | 1161 | a 32-bit value.\r |
1162 | \r | |
1163 | Reads the 32-bit PCI configuration register specified by Address, performs a\r | |
62991af2 | 1164 | bitwise OR between the read result and the value specified by\r |
e1f414b6 | 1165 | OrData, and writes the result to the 32-bit PCI configuration register\r |
1166 | specified by Address. The value written to the PCI configuration register is\r | |
1167 | returned. This function must guarantee that all PCI read and write operations\r | |
1168 | are serialized.\r | |
1169 | \r | |
1170 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
1171 | If Address is not aligned on a 32-bit boundary, then ASSERT().\r | |
1172 | If the register specified by Address >= 0x100, then ASSERT().\r | |
1173 | \r | |
2fc59a00 | 1174 | @param Address The address that encodes the PCI Bus, Device, Function and\r |
e1f414b6 | 1175 | Register.\r |
1176 | @param OrData The value to OR with the PCI configuration register.\r | |
1177 | \r | |
1178 | @return The value written back to the PCI configuration register.\r | |
1179 | \r | |
1180 | **/\r | |
1181 | UINT32\r | |
1182 | EFIAPI\r | |
1183 | PciCf8Or32 (\r | |
2f88bd3a MK |
1184 | IN UINTN Address,\r |
1185 | IN UINT32 OrData\r | |
e1f414b6 | 1186 | )\r |
1187 | {\r | |
96dd57ee | 1188 | BOOLEAN InterruptState;\r |
1189 | UINT32 AddressPort;\r | |
1190 | UINT32 Result;\r | |
9095d37b | 1191 | \r |
e1f414b6 | 1192 | ASSERT_INVALID_PCI_ADDRESS (Address, 3);\r |
96dd57ee | 1193 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 1194 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 1195 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 1196 | Result = IoOr32 (\r |
1197 | PCI_CONFIGURATION_DATA_PORT,\r | |
1198 | OrData\r | |
1199 | );\r | |
1200 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
1201 | SetInterruptState (InterruptState);\r | |
1202 | return Result;\r | |
e1f414b6 | 1203 | }\r |
1204 | \r | |
1205 | /**\r | |
1206 | Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit\r | |
1207 | value.\r | |
1208 | \r | |
1209 | Reads the 32-bit PCI configuration register specified by Address, performs a\r | |
1210 | bitwise AND between the read result and the value specified by AndData, and\r | |
1211 | writes the result to the 32-bit PCI configuration register specified by\r | |
1212 | Address. The value written to the PCI configuration register is returned.\r | |
1213 | This function must guarantee that all PCI read and write operations are\r | |
1214 | serialized.\r | |
1215 | \r | |
1216 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
1217 | If Address is not aligned on a 32-bit boundary, then ASSERT().\r | |
1218 | If the register specified by Address >= 0x100, then ASSERT().\r | |
1219 | \r | |
2fc59a00 | 1220 | @param Address The address that encodes the PCI Bus, Device, Function and\r |
e1f414b6 | 1221 | Register.\r |
1222 | @param AndData The value to AND with the PCI configuration register.\r | |
1223 | \r | |
1224 | @return The value written back to the PCI configuration register.\r | |
1225 | \r | |
1226 | **/\r | |
1227 | UINT32\r | |
1228 | EFIAPI\r | |
1229 | PciCf8And32 (\r | |
2f88bd3a MK |
1230 | IN UINTN Address,\r |
1231 | IN UINT32 AndData\r | |
e1f414b6 | 1232 | )\r |
1233 | {\r | |
96dd57ee | 1234 | BOOLEAN InterruptState;\r |
1235 | UINT32 AddressPort;\r | |
1236 | UINT32 Result;\r | |
9095d37b | 1237 | \r |
e1f414b6 | 1238 | ASSERT_INVALID_PCI_ADDRESS (Address, 3);\r |
96dd57ee | 1239 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 1240 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 1241 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 1242 | Result = IoAnd32 (\r |
1243 | PCI_CONFIGURATION_DATA_PORT,\r | |
1244 | AndData\r | |
1245 | );\r | |
1246 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
1247 | SetInterruptState (InterruptState);\r | |
1248 | return Result;\r | |
e1f414b6 | 1249 | }\r |
1250 | \r | |
1251 | /**\r | |
1252 | Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit\r | |
62991af2 | 1253 | value, followed a bitwise OR with another 32-bit value.\r |
e1f414b6 | 1254 | \r |
1255 | Reads the 32-bit PCI configuration register specified by Address, performs a\r | |
1256 | bitwise AND between the read result and the value specified by AndData,\r | |
62991af2 | 1257 | performs a bitwise OR between the result of the AND operation and\r |
e1f414b6 | 1258 | the value specified by OrData, and writes the result to the 32-bit PCI\r |
1259 | configuration register specified by Address. The value written to the PCI\r | |
1260 | configuration register is returned. This function must guarantee that all PCI\r | |
1261 | read and write operations are serialized.\r | |
1262 | \r | |
1263 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
1264 | If Address is not aligned on a 32-bit boundary, then ASSERT().\r | |
1265 | If the register specified by Address >= 0x100, then ASSERT().\r | |
1266 | \r | |
2fc59a00 | 1267 | @param Address The address that encodes the PCI Bus, Device, Function and\r |
e1f414b6 | 1268 | Register.\r |
1269 | @param AndData The value to AND with the PCI configuration register.\r | |
1270 | @param OrData The value to OR with the result of the AND operation.\r | |
1271 | \r | |
1272 | @return The value written back to the PCI configuration register.\r | |
1273 | \r | |
1274 | **/\r | |
1275 | UINT32\r | |
1276 | EFIAPI\r | |
1277 | PciCf8AndThenOr32 (\r | |
2f88bd3a MK |
1278 | IN UINTN Address,\r |
1279 | IN UINT32 AndData,\r | |
1280 | IN UINT32 OrData\r | |
e1f414b6 | 1281 | )\r |
1282 | {\r | |
96dd57ee | 1283 | BOOLEAN InterruptState;\r |
1284 | UINT32 AddressPort;\r | |
1285 | UINT32 Result;\r | |
9095d37b | 1286 | \r |
e1f414b6 | 1287 | ASSERT_INVALID_PCI_ADDRESS (Address, 3);\r |
96dd57ee | 1288 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 1289 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 1290 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 1291 | Result = IoAndThenOr32 (\r |
1292 | PCI_CONFIGURATION_DATA_PORT,\r | |
1293 | AndData,\r | |
1294 | OrData\r | |
1295 | );\r | |
1296 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
1297 | SetInterruptState (InterruptState);\r | |
1298 | return Result;\r | |
e1f414b6 | 1299 | }\r |
1300 | \r | |
1301 | /**\r | |
1302 | Reads a bit field of a PCI configuration register.\r | |
1303 | \r | |
1304 | Reads the bit field in a 32-bit PCI configuration register. The bit field is\r | |
1305 | specified by the StartBit and the EndBit. The value of the bit field is\r | |
1306 | returned.\r | |
1307 | \r | |
1308 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
1309 | If Address is not aligned on a 32-bit boundary, then ASSERT().\r | |
1310 | If the register specified by Address >= 0x100, then ASSERT().\r | |
1311 | If StartBit is greater than 31, then ASSERT().\r | |
1312 | If EndBit is greater than 31, then ASSERT().\r | |
1313 | If EndBit is less than StartBit, then ASSERT().\r | |
1314 | \r | |
2fc59a00 | 1315 | @param Address The PCI configuration register to read.\r |
e1f414b6 | 1316 | @param StartBit The ordinal of the least significant bit in the bit field.\r |
1317 | Range 0..31.\r | |
1318 | @param EndBit The ordinal of the most significant bit in the bit field.\r | |
1319 | Range 0..31.\r | |
1320 | \r | |
1321 | @return The value of the bit field read from the PCI configuration register.\r | |
1322 | \r | |
1323 | **/\r | |
1324 | UINT32\r | |
1325 | EFIAPI\r | |
1326 | PciCf8BitFieldRead32 (\r | |
2f88bd3a MK |
1327 | IN UINTN Address,\r |
1328 | IN UINTN StartBit,\r | |
1329 | IN UINTN EndBit\r | |
e1f414b6 | 1330 | )\r |
1331 | {\r | |
96dd57ee | 1332 | BOOLEAN InterruptState;\r |
1333 | UINT32 AddressPort;\r | |
1334 | UINT32 Result;\r | |
9095d37b | 1335 | \r |
e1f414b6 | 1336 | ASSERT_INVALID_PCI_ADDRESS (Address, 3);\r |
96dd57ee | 1337 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 1338 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 1339 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 1340 | Result = IoBitFieldRead32 (\r |
1341 | PCI_CONFIGURATION_DATA_PORT,\r | |
1342 | StartBit,\r | |
1343 | EndBit\r | |
1344 | );\r | |
1345 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
1346 | SetInterruptState (InterruptState);\r | |
1347 | return Result;\r | |
e1f414b6 | 1348 | }\r |
1349 | \r | |
1350 | /**\r | |
1351 | Writes a bit field to a PCI configuration register.\r | |
1352 | \r | |
1353 | Writes Value to the bit field of the PCI configuration register. The bit\r | |
1354 | field is specified by the StartBit and the EndBit. All other bits in the\r | |
1355 | destination PCI configuration register are preserved. The new value of the\r | |
1356 | 32-bit register is returned.\r | |
1357 | \r | |
1358 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
1359 | If Address is not aligned on a 32-bit boundary, then ASSERT().\r | |
1360 | If the register specified by Address >= 0x100, then ASSERT().\r | |
1361 | If StartBit is greater than 31, then ASSERT().\r | |
1362 | If EndBit is greater than 31, then ASSERT().\r | |
1363 | If EndBit is less than StartBit, then ASSERT().\r | |
94952554 | 1364 | If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().\r |
e1f414b6 | 1365 | \r |
2fc59a00 | 1366 | @param Address The PCI configuration register to write.\r |
e1f414b6 | 1367 | @param StartBit The ordinal of the least significant bit in the bit field.\r |
1368 | Range 0..31.\r | |
1369 | @param EndBit The ordinal of the most significant bit in the bit field.\r | |
1370 | Range 0..31.\r | |
2fc59a00 | 1371 | @param Value The new value of the bit field.\r |
e1f414b6 | 1372 | \r |
1373 | @return The value written back to the PCI configuration register.\r | |
1374 | \r | |
1375 | **/\r | |
1376 | UINT32\r | |
1377 | EFIAPI\r | |
1378 | PciCf8BitFieldWrite32 (\r | |
2f88bd3a MK |
1379 | IN UINTN Address,\r |
1380 | IN UINTN StartBit,\r | |
1381 | IN UINTN EndBit,\r | |
1382 | IN UINT32 Value\r | |
e1f414b6 | 1383 | )\r |
1384 | {\r | |
96dd57ee | 1385 | BOOLEAN InterruptState;\r |
1386 | UINT32 AddressPort;\r | |
1387 | UINT32 Result;\r | |
9095d37b | 1388 | \r |
e1f414b6 | 1389 | ASSERT_INVALID_PCI_ADDRESS (Address, 3);\r |
96dd57ee | 1390 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 1391 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 1392 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 1393 | Result = IoBitFieldWrite32 (\r |
1394 | PCI_CONFIGURATION_DATA_PORT,\r | |
1395 | StartBit,\r | |
1396 | EndBit,\r | |
1397 | Value\r | |
1398 | );\r | |
1399 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
1400 | SetInterruptState (InterruptState);\r | |
1401 | return Result;\r | |
e1f414b6 | 1402 | }\r |
1403 | \r | |
1404 | /**\r | |
1405 | Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and\r | |
1406 | writes the result back to the bit field in the 32-bit port.\r | |
1407 | \r | |
1408 | Reads the 32-bit PCI configuration register specified by Address, performs a\r | |
62991af2 | 1409 | bitwise OR between the read result and the value specified by\r |
e1f414b6 | 1410 | OrData, and writes the result to the 32-bit PCI configuration register\r |
1411 | specified by Address. The value written to the PCI configuration register is\r | |
1412 | returned. This function must guarantee that all PCI read and write operations\r | |
1413 | are serialized. Extra left bits in OrData are stripped.\r | |
1414 | \r | |
1415 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
1416 | If Address is not aligned on a 32-bit boundary, then ASSERT().\r | |
1417 | If the register specified by Address >= 0x100, then ASSERT().\r | |
1418 | If StartBit is greater than 31, then ASSERT().\r | |
1419 | If EndBit is greater than 31, then ASSERT().\r | |
1420 | If EndBit is less than StartBit, then ASSERT().\r | |
94952554 | 1421 | If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().\r |
e1f414b6 | 1422 | \r |
2fc59a00 | 1423 | @param Address The PCI configuration register to write.\r |
e1f414b6 | 1424 | @param StartBit The ordinal of the least significant bit in the bit field.\r |
1425 | Range 0..31.\r | |
1426 | @param EndBit The ordinal of the most significant bit in the bit field.\r | |
1427 | Range 0..31.\r | |
1428 | @param OrData The value to OR with the PCI configuration register.\r | |
1429 | \r | |
1430 | @return The value written back to the PCI configuration register.\r | |
1431 | \r | |
1432 | **/\r | |
1433 | UINT32\r | |
1434 | EFIAPI\r | |
1435 | PciCf8BitFieldOr32 (\r | |
2f88bd3a MK |
1436 | IN UINTN Address,\r |
1437 | IN UINTN StartBit,\r | |
1438 | IN UINTN EndBit,\r | |
1439 | IN UINT32 OrData\r | |
e1f414b6 | 1440 | )\r |
1441 | {\r | |
96dd57ee | 1442 | BOOLEAN InterruptState;\r |
1443 | UINT32 AddressPort;\r | |
1444 | UINT32 Result;\r | |
9095d37b | 1445 | \r |
e1f414b6 | 1446 | ASSERT_INVALID_PCI_ADDRESS (Address, 3);\r |
96dd57ee | 1447 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 1448 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 1449 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 1450 | Result = IoBitFieldOr32 (\r |
1451 | PCI_CONFIGURATION_DATA_PORT,\r | |
1452 | StartBit,\r | |
1453 | EndBit,\r | |
1454 | OrData\r | |
1455 | );\r | |
1456 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
1457 | SetInterruptState (InterruptState);\r | |
1458 | return Result;\r | |
e1f414b6 | 1459 | }\r |
1460 | \r | |
1461 | /**\r | |
1462 | Reads a bit field in a 32-bit PCI configuration register, performs a bitwise\r | |
1463 | AND, and writes the result back to the bit field in the 32-bit register.\r | |
1464 | \r | |
1465 | Reads the 32-bit PCI configuration register specified by Address, performs a\r | |
1466 | bitwise AND between the read result and the value specified by AndData, and\r | |
1467 | writes the result to the 32-bit PCI configuration register specified by\r | |
1468 | Address. The value written to the PCI configuration register is returned.\r | |
1469 | This function must guarantee that all PCI read and write operations are\r | |
1470 | serialized. Extra left bits in AndData are stripped.\r | |
1471 | \r | |
1472 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
1473 | If Address is not aligned on a 32-bit boundary, then ASSERT().\r | |
1474 | If the register specified by Address >= 0x100, then ASSERT().\r | |
1475 | If StartBit is greater than 31, then ASSERT().\r | |
1476 | If EndBit is greater than 31, then ASSERT().\r | |
1477 | If EndBit is less than StartBit, then ASSERT().\r | |
94952554 | 1478 | If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().\r |
e1f414b6 | 1479 | \r |
2fc59a00 | 1480 | @param Address The PCI configuration register to write.\r |
e1f414b6 | 1481 | @param StartBit The ordinal of the least significant bit in the bit field.\r |
1482 | Range 0..31.\r | |
1483 | @param EndBit The ordinal of the most significant bit in the bit field.\r | |
1484 | Range 0..31.\r | |
1485 | @param AndData The value to AND with the PCI configuration register.\r | |
1486 | \r | |
1487 | @return The value written back to the PCI configuration register.\r | |
1488 | \r | |
1489 | **/\r | |
1490 | UINT32\r | |
1491 | EFIAPI\r | |
1492 | PciCf8BitFieldAnd32 (\r | |
2f88bd3a MK |
1493 | IN UINTN Address,\r |
1494 | IN UINTN StartBit,\r | |
1495 | IN UINTN EndBit,\r | |
1496 | IN UINT32 AndData\r | |
e1f414b6 | 1497 | )\r |
1498 | {\r | |
96dd57ee | 1499 | BOOLEAN InterruptState;\r |
1500 | UINT32 AddressPort;\r | |
1501 | UINT32 Result;\r | |
9095d37b | 1502 | \r |
e1f414b6 | 1503 | ASSERT_INVALID_PCI_ADDRESS (Address, 3);\r |
96dd57ee | 1504 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 1505 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 1506 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 1507 | Result = IoBitFieldAnd32 (\r |
1508 | PCI_CONFIGURATION_DATA_PORT,\r | |
1509 | StartBit,\r | |
1510 | EndBit,\r | |
1511 | AndData\r | |
1512 | );\r | |
1513 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r | |
1514 | SetInterruptState (InterruptState);\r | |
1515 | return Result;\r | |
e1f414b6 | 1516 | }\r |
1517 | \r | |
1518 | /**\r | |
1519 | Reads a bit field in a 32-bit port, performs a bitwise AND followed by a\r | |
62991af2 | 1520 | bitwise OR, and writes the result back to the bit field in the\r |
e1f414b6 | 1521 | 32-bit port.\r |
1522 | \r | |
1523 | Reads the 32-bit PCI configuration register specified by Address, performs a\r | |
62991af2 | 1524 | bitwise AND followed by a bitwise OR between the read result and\r |
e1f414b6 | 1525 | the value specified by AndData, and writes the result to the 32-bit PCI\r |
1526 | configuration register specified by Address. The value written to the PCI\r | |
1527 | configuration register is returned. This function must guarantee that all PCI\r | |
1528 | read and write operations are serialized. Extra left bits in both AndData and\r | |
1529 | OrData are stripped.\r | |
1530 | \r | |
1531 | If Address > 0x0FFFFFFF, then ASSERT().\r | |
1532 | If Address is not aligned on a 32-bit boundary, then ASSERT().\r | |
1533 | If the register specified by Address >= 0x100, then ASSERT().\r | |
1534 | If StartBit is greater than 31, then ASSERT().\r | |
1535 | If EndBit is greater than 31, then ASSERT().\r | |
1536 | If EndBit is less than StartBit, then ASSERT().\r | |
94952554 LG |
1537 | If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().\r |
1538 | If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().\r | |
e1f414b6 | 1539 | \r |
2fc59a00 | 1540 | @param Address The PCI configuration register to write.\r |
e1f414b6 | 1541 | @param StartBit The ordinal of the least significant bit in the bit field.\r |
1542 | Range 0..31.\r | |
1543 | @param EndBit The ordinal of the most significant bit in the bit field.\r | |
1544 | Range 0..31.\r | |
1545 | @param AndData The value to AND with the PCI configuration register.\r | |
1546 | @param OrData The value to OR with the result of the AND operation.\r | |
1547 | \r | |
1548 | @return The value written back to the PCI configuration register.\r | |
1549 | \r | |
1550 | **/\r | |
1551 | UINT32\r | |
1552 | EFIAPI\r | |
2f88bd3a MK |
1553 | PciCf8BitFieldAndThenOr32 (\r |
1554 | IN UINTN Address,\r | |
1555 | IN UINTN StartBit,\r | |
1556 | IN UINTN EndBit,\r | |
1557 | IN UINT32 AndData,\r | |
1558 | IN UINT32 OrData\r | |
e1f414b6 | 1559 | )\r |
1560 | {\r | |
96dd57ee | 1561 | BOOLEAN InterruptState;\r |
1562 | UINT32 AddressPort;\r | |
1563 | UINT32 Result;\r | |
9095d37b | 1564 | \r |
e1f414b6 | 1565 | ASSERT_INVALID_PCI_ADDRESS (Address, 3);\r |
96dd57ee | 1566 | InterruptState = SaveAndDisableInterrupts ();\r |
2f88bd3a | 1567 | AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT);\r |
e1f414b6 | 1568 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address));\r |
96dd57ee | 1569 | Result = IoBitFieldAndThenOr32 (\r |
2f88bd3a MK |
1570 | PCI_CONFIGURATION_DATA_PORT,\r |
1571 | StartBit,\r | |
1572 | EndBit,\r | |
1573 | AndData,\r | |
1574 | OrData\r | |
1575 | );\r | |
96dd57ee | 1576 | IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort);\r |
1577 | SetInterruptState (InterruptState);\r | |
1578 | return Result;\r | |
e1f414b6 | 1579 | }\r |
1580 | \r | |
1581 | /**\r | |
1582 | Reads a range of PCI configuration registers into a caller supplied buffer.\r | |
1583 | \r | |
1584 | Reads the range of PCI configuration registers specified by StartAddress and\r | |
1585 | Size into the buffer specified by Buffer. This function only allows the PCI\r | |
1586 | configuration registers from a single PCI function to be read. Size is\r | |
1587 | returned. When possible 32-bit PCI configuration read cycles are used to read\r | |
1588 | from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit\r | |
1589 | and 16-bit PCI configuration read cycles may be used at the beginning and the\r | |
1590 | end of the range.\r | |
1591 | \r | |
1592 | If StartAddress > 0x0FFFFFFF, then ASSERT().\r | |
1593 | If the register specified by StartAddress >= 0x100, then ASSERT().\r | |
1594 | If ((StartAddress & 0xFFF) + Size) > 0x100, then ASSERT().\r | |
1595 | If Size > 0 and Buffer is NULL, then ASSERT().\r | |
1596 | \r | |
2fc59a00 | 1597 | @param StartAddress The starting address that encodes the PCI Bus, Device,\r |
e1f414b6 | 1598 | Function and Register.\r |
2fc59a00 | 1599 | @param Size The size in bytes of the transfer.\r |
1600 | @param Buffer The pointer to a buffer receiving the data read.\r | |
e1f414b6 | 1601 | \r |
9638ba6d | 1602 | @return Size read from StartAddress.\r |
e1f414b6 | 1603 | \r |
1604 | **/\r | |
1605 | UINTN\r | |
1606 | EFIAPI\r | |
1607 | PciCf8ReadBuffer (\r | |
2f88bd3a MK |
1608 | IN UINTN StartAddress,\r |
1609 | IN UINTN Size,\r | |
1610 | OUT VOID *Buffer\r | |
e1f414b6 | 1611 | )\r |
1612 | {\r | |
2f88bd3a | 1613 | UINTN ReturnValue;\r |
e1f414b6 | 1614 | \r |
1615 | ASSERT_INVALID_PCI_ADDRESS (StartAddress, 0);\r | |
1616 | ASSERT (((StartAddress & 0xFFF) + Size) <= 0x100);\r | |
1617 | \r | |
1618 | if (Size == 0) {\r | |
1619 | return Size;\r | |
1620 | }\r | |
1621 | \r | |
1622 | ASSERT (Buffer != NULL);\r | |
1623 | \r | |
1624 | //\r | |
1625 | // Save Size for return\r | |
1626 | //\r | |
1627 | ReturnValue = Size;\r | |
1628 | \r | |
1629 | if ((StartAddress & 1) != 0) {\r | |
1630 | //\r | |
1631 | // Read a byte if StartAddress is byte aligned\r | |
1632 | //\r | |
1633 | *(volatile UINT8 *)Buffer = PciCf8Read8 (StartAddress);\r | |
2f88bd3a MK |
1634 | StartAddress += sizeof (UINT8);\r |
1635 | Size -= sizeof (UINT8);\r | |
1636 | Buffer = (UINT8 *)Buffer + 1;\r | |
e1f414b6 | 1637 | }\r |
1638 | \r | |
2f88bd3a | 1639 | if ((Size >= sizeof (UINT16)) && ((StartAddress & 2) != 0)) {\r |
e1f414b6 | 1640 | //\r |
1641 | // Read a word if StartAddress is word aligned\r | |
1642 | //\r | |
2f88bd3a | 1643 | WriteUnaligned16 ((UINT16 *)Buffer, (UINT16)PciCf8Read16 (StartAddress));\r |
0c62737d | 1644 | \r |
e1f414b6 | 1645 | StartAddress += sizeof (UINT16);\r |
2f88bd3a MK |
1646 | Size -= sizeof (UINT16);\r |
1647 | Buffer = (UINT16 *)Buffer + 1;\r | |
e1f414b6 | 1648 | }\r |
1649 | \r | |
1650 | while (Size >= sizeof (UINT32)) {\r | |
1651 | //\r | |
1652 | // Read as many double words as possible\r | |
1653 | //\r | |
2f88bd3a | 1654 | WriteUnaligned32 ((UINT32 *)Buffer, (UINT32)PciCf8Read32 (StartAddress));\r |
e1f414b6 | 1655 | StartAddress += sizeof (UINT32);\r |
2f88bd3a MK |
1656 | Size -= sizeof (UINT32);\r |
1657 | Buffer = (UINT32 *)Buffer + 1;\r | |
e1f414b6 | 1658 | }\r |
1659 | \r | |
1660 | if (Size >= sizeof (UINT16)) {\r | |
1661 | //\r | |
1662 | // Read the last remaining word if exist\r | |
1663 | //\r | |
2f88bd3a | 1664 | WriteUnaligned16 ((UINT16 *)Buffer, (UINT16)PciCf8Read16 (StartAddress));\r |
e1f414b6 | 1665 | StartAddress += sizeof (UINT16);\r |
2f88bd3a MK |
1666 | Size -= sizeof (UINT16);\r |
1667 | Buffer = (UINT16 *)Buffer + 1;\r | |
e1f414b6 | 1668 | }\r |
1669 | \r | |
1670 | if (Size >= sizeof (UINT8)) {\r | |
1671 | //\r | |
1672 | // Read the last remaining byte if exist\r | |
1673 | //\r | |
1674 | *(volatile UINT8 *)Buffer = PciCf8Read8 (StartAddress);\r | |
1675 | }\r | |
1676 | \r | |
1677 | return ReturnValue;\r | |
1678 | }\r | |
1679 | \r | |
1680 | /**\r | |
1681 | Copies the data in a caller supplied buffer to a specified range of PCI\r | |
1682 | configuration space.\r | |
1683 | \r | |
1684 | Writes the range of PCI configuration registers specified by StartAddress and\r | |
1685 | Size from the buffer specified by Buffer. This function only allows the PCI\r | |
1686 | configuration registers from a single PCI function to be written. Size is\r | |
1687 | returned. When possible 32-bit PCI configuration write cycles are used to\r | |
1688 | write from StartAdress to StartAddress + Size. Due to alignment restrictions,\r | |
1689 | 8-bit and 16-bit PCI configuration write cycles may be used at the beginning\r | |
1690 | and the end of the range.\r | |
1691 | \r | |
1692 | If StartAddress > 0x0FFFFFFF, then ASSERT().\r | |
1693 | If the register specified by StartAddress >= 0x100, then ASSERT().\r | |
1694 | If ((StartAddress & 0xFFF) + Size) > 0x100, then ASSERT().\r | |
1695 | If Size > 0 and Buffer is NULL, then ASSERT().\r | |
1696 | \r | |
2fc59a00 | 1697 | @param StartAddress The starting address that encodes the PCI Bus, Device,\r |
e1f414b6 | 1698 | Function and Register.\r |
2fc59a00 | 1699 | @param Size The size in bytes of the transfer.\r |
1700 | @param Buffer The pointer to a buffer containing the data to write.\r | |
e1f414b6 | 1701 | \r |
9638ba6d | 1702 | @return Size written to StartAddress.\r |
e1f414b6 | 1703 | \r |
1704 | **/\r | |
1705 | UINTN\r | |
1706 | EFIAPI\r | |
1707 | PciCf8WriteBuffer (\r | |
2f88bd3a MK |
1708 | IN UINTN StartAddress,\r |
1709 | IN UINTN Size,\r | |
1710 | IN VOID *Buffer\r | |
e1f414b6 | 1711 | )\r |
1712 | {\r | |
2f88bd3a | 1713 | UINTN ReturnValue;\r |
e1f414b6 | 1714 | \r |
1715 | ASSERT_INVALID_PCI_ADDRESS (StartAddress, 0);\r | |
1716 | ASSERT (((StartAddress & 0xFFF) + Size) <= 0x100);\r | |
1717 | \r | |
1718 | if (Size == 0) {\r | |
1719 | return 0;\r | |
1720 | }\r | |
1721 | \r | |
1722 | ASSERT (Buffer != NULL);\r | |
1723 | \r | |
1724 | //\r | |
1725 | // Save Size for return\r | |
1726 | //\r | |
1727 | ReturnValue = Size;\r | |
1728 | \r | |
1729 | if ((StartAddress & 1) != 0) {\r | |
1730 | //\r | |
1731 | // Write a byte if StartAddress is byte aligned\r | |
1732 | //\r | |
2f88bd3a | 1733 | PciCf8Write8 (StartAddress, *(UINT8 *)Buffer);\r |
e1f414b6 | 1734 | StartAddress += sizeof (UINT8);\r |
2f88bd3a MK |
1735 | Size -= sizeof (UINT8);\r |
1736 | Buffer = (UINT8 *)Buffer + 1;\r | |
e1f414b6 | 1737 | }\r |
1738 | \r | |
2f88bd3a | 1739 | if ((Size >= sizeof (UINT16)) && ((StartAddress & 2) != 0)) {\r |
e1f414b6 | 1740 | //\r |
1741 | // Write a word if StartAddress is word aligned\r | |
1742 | //\r | |
2f88bd3a | 1743 | PciCf8Write16 (StartAddress, ReadUnaligned16 ((UINT16 *)Buffer));\r |
e1f414b6 | 1744 | StartAddress += sizeof (UINT16);\r |
2f88bd3a MK |
1745 | Size -= sizeof (UINT16);\r |
1746 | Buffer = (UINT16 *)Buffer + 1;\r | |
e1f414b6 | 1747 | }\r |
1748 | \r | |
1749 | while (Size >= sizeof (UINT32)) {\r | |
1750 | //\r | |
1751 | // Write as many double words as possible\r | |
1752 | //\r | |
2f88bd3a | 1753 | PciCf8Write32 (StartAddress, ReadUnaligned32 ((UINT32 *)Buffer));\r |
e1f414b6 | 1754 | StartAddress += sizeof (UINT32);\r |
2f88bd3a MK |
1755 | Size -= sizeof (UINT32);\r |
1756 | Buffer = (UINT32 *)Buffer + 1;\r | |
e1f414b6 | 1757 | }\r |
1758 | \r | |
1759 | if (Size >= sizeof (UINT16)) {\r | |
1760 | //\r | |
1761 | // Write the last remaining word if exist\r | |
1762 | //\r | |
2f88bd3a | 1763 | PciCf8Write16 (StartAddress, ReadUnaligned16 ((UINT16 *)Buffer));\r |
e1f414b6 | 1764 | StartAddress += sizeof (UINT16);\r |
2f88bd3a MK |
1765 | Size -= sizeof (UINT16);\r |
1766 | Buffer = (UINT16 *)Buffer + 1;\r | |
e1f414b6 | 1767 | }\r |
1768 | \r | |
1769 | if (Size >= sizeof (UINT8)) {\r | |
1770 | //\r | |
1771 | // Write the last remaining byte if exist\r | |
1772 | //\r | |
2f88bd3a | 1773 | PciCf8Write8 (StartAddress, *(UINT8 *)Buffer);\r |
e1f414b6 | 1774 | }\r |
1775 | \r | |
1776 | return ReturnValue;\r | |
1777 | }\r |