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