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