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