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