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