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