1 /** @file
2 This driver is responsible for the registration of child drivers
3 and the abstraction of the PCH SMI sources.
4
5 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9 #include "PchSmmHelpers.h"
10
11 //
12 // Help handle porting bit shifts to IA-64.
13 //
14 #define BIT_ZERO 0x00000001
15
16 /**
17 Publish SMI Dispatch protocols.
18
19
20 **/
21 VOID
PchSmmPublishDispatchProtocols(VOID)22 PchSmmPublishDispatchProtocols (
23 VOID
24 )
25 {
26 EFI_STATUS Status = EFI_SUCCESS;
27 UINTN Index;
28 //
29 // Install protocol interfaces.
30 //
31 for (Index = 0; Index < PCH_SMM_PROTOCOL_TYPE_MAX; Index++) {
32 Status = gSmst->SmmInstallProtocolInterface (
33 &mPrivateData.InstallMultProtHandle,
34 mPrivateData.Protocols[Index].Guid,
35 EFI_NATIVE_INTERFACE,
36 &mPrivateData.Protocols[Index].Protocols.Generic
37 );
38 }
39 ASSERT_EFI_ERROR (Status);
40 }
41
42 /**
43 Initialize bits that aren't necessarily related to an SMI source.
44
45
46 @retval EFI_SUCCESS SMI source initialization completed.
47 @retval Asserts Global Smi Bit is not enabled successfully.
48 **/
49 EFI_STATUS
PchSmmInitHardware(VOID)50 PchSmmInitHardware (
51 VOID
52 )
53 {
54 EFI_STATUS Status;
55
56 ///
57 /// Clear all SMIs
58 ///
59 PchSmmClearSmi ();
60
61 Status = PchSmmEnableGlobalSmiBit ();
62 ASSERT_EFI_ERROR (Status);
63
64 ///
65 /// Be *really* sure to clear all SMIs
66 ///
67 PchSmmClearSmi ();
68
69 return EFI_SUCCESS;
70 }
71
72 /**
73 Enables the PCH to generate SMIs. Note that no SMIs will be generated
74 if no SMI sources are enabled. Conversely, no enabled SMI source will
75 generate SMIs if SMIs are not globally enabled. This is the main
76 switchbox for SMI generation.
77
78
79 @retval EFI_SUCCESS Enable Global Smi Bit completed
80 **/
81 EFI_STATUS
PchSmmEnableGlobalSmiBit(VOID)82 PchSmmEnableGlobalSmiBit (
83 VOID
84 )
85 {
86 UINT32 SmiEn;
87
88 SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN));
89
90 ///
91 /// Set the "global smi enable" bit
92 ///
93 SmiEn |= B_PCH_SMI_EN_GBL_SMI;
94
95 IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN), SmiEn);
96
97 return EFI_SUCCESS;
98 }
99
100 /**
101 Clears the SMI after all SMI source have been processed.
102 Note that this function will not work correctly (as it is
103 written) unless all SMI sources have been processed.
104 A revision of this function could manually clear all SMI
105 status bits to guarantee success.
106
107
108 @retval EFI_SUCCESS Clears the SMIs completed
109 @retval Asserts EOS was not set to a 1
110 **/
111 EFI_STATUS
PchSmmClearSmi(VOID)112 PchSmmClearSmi (
113 VOID
114 )
115 {
116 BOOLEAN EosSet;
117 BOOLEAN SciEn;
118 UINT32 Pm1Cnt;
119 UINT16 Pm1Sts;
120 UINT32 Gpe0Sts;
121 UINT32 SmiSts;
122 UINT16 DevActSts;
123 UINT16 Tco1Sts;
124
125 Gpe0Sts = 0;
126 ///
127 /// Determine whether an ACPI OS is present (via the SCI_EN bit)
128 ///
129 Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
130 SciEn = (BOOLEAN) ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SCI_EN) == B_PCH_ACPI_PM1_CNT_SCI_EN);
131 if (!SciEn) {
132 ///
133 /// Clear any SMIs that double as SCIs (when SCI_EN==0)
134 ///
135 Pm1Sts = IoRead16 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS));
136 Gpe0Sts = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_GPE0_STS_127_96));
137
138 Pm1Sts |=
139 (
140 B_PCH_ACPI_PM1_STS_WAK |
141 B_PCH_ACPI_PM1_STS_PRBTNOR |
142 B_PCH_ACPI_PM1_STS_RTC |
143 B_PCH_ACPI_PM1_STS_PWRBTN |
144 B_PCH_ACPI_PM1_STS_GBL |
145 B_PCH_ACPI_PM1_STS_TMROF
146 );
147
148 Gpe0Sts |=
149 (
150 B_PCH_ACPI_GPE0_STS_127_96_PME_B0 |
151 B_PCH_ACPI_GPE0_STS_127_96_PME |
152 B_PCH_ACPI_GPE0_STS_127_96_BATLOW |
153 B_PCH_ACPI_GPE0_STS_127_96_PCI_EXP |
154 B_PCH_ACPI_GPE0_STS_127_96_RI |
155 B_PCH_ACPI_GPE0_STS_127_96_SMB_WAK |
156 B_PCH_ACPI_GPE0_STS_127_96_TC0SCI |
157 B_PCH_ACPI_GPE0_STS_127_96_HOT_PLUG |
158 B_PCH_ACPI_GPE0_STS_127_96_BATLOW |
159 B_PCH_ACPI_GPE0_STS_127_96_LAN_WAKE
160 );
161
162 IoWrite16 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS), (UINT16) Pm1Sts);
163 IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_GPE0_STS_127_96), (UINT32) Gpe0Sts);
164 }
165 ///
166 /// Clear all SMIs that are unaffected by SCI_EN
167 ///
168 SmiSts = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_STS));
169 DevActSts = IoRead16 ((UINTN) (mAcpiBaseAddr + R_PCH_DEVACT_STS));
170 Tco1Sts = IoRead16 ((UINTN) (mTcoBaseAddr + R_PCH_TCO1_STS));
171
172 SmiSts |=
173 (
174 B_PCH_SMI_STS_SMBUS |
175 B_PCH_SMI_STS_PERIODIC |
176 B_PCH_SMI_STS_TCO |
177 B_PCH_SMI_STS_MCSMI |
178 B_PCH_SMI_STS_SWSMI_TMR |
179 B_PCH_SMI_STS_APM |
180 B_PCH_SMI_STS_ON_SLP_EN |
181 B_PCH_SMI_STS_BIOS
182 );
183 DevActSts |=
184 (
185 B_PCH_DEVACT_STS_KBC |
186 B_PCH_DEVACT_STS_PIRQDH |
187 B_PCH_DEVACT_STS_PIRQCG |
188 B_PCH_DEVACT_STS_PIRQBF |
189 B_PCH_DEVACT_STS_PIRQAE
190 );
191 Tco1Sts |=
192 (
193 B_PCH_TCO1_STS_DMISERR |
194 B_PCH_TCO1_STS_DMISMI |
195 B_PCH_TCO1_STS_DMISCI |
196 B_PCH_TCO1_STS_BIOSWR |
197 B_PCH_TCO1_STS_NEWCENTURY |
198 B_PCH_TCO1_STS_TIMEOUT |
199 B_PCH_TCO1_STS_TCO_INT |
200 B_PCH_TCO1_STS_SW_TCO_SMI
201 );
202
203 GpioClearAllGpiSmiSts ();
204
205 //
206 // If NewCentury Sts is set here, it must clear the NewCentury Sts separately.
207 //
208 PchTcoClearNewCenturySts (NULL);
209
210 IoWrite16 ((UINTN) (mTcoBaseAddr + R_PCH_TCO1_STS), Tco1Sts);
211
212 //
213 // We do not want to write 1 to clear INTRD_DET bit.
214 //
215 IoWrite16 ((UINTN) (mTcoBaseAddr + R_PCH_TCO2_STS), (UINT16) ~B_PCH_TCO2_STS_INTRD_DET);
216
217 IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_STS), SmiSts);
218
219 IoWrite16 ((UINTN) (mAcpiBaseAddr + R_PCH_DEVACT_STS), DevActSts);
220
221 ///
222 /// Try to clear the EOS bit. ASSERT on an error
223 ///
224 EosSet = PchSmmSetAndCheckEos ();
225 ASSERT (EosSet);
226
227 return EFI_SUCCESS;
228 }
229
230 /**
231 Set the SMI EOS bit after all SMI source have been processed.
232
233
234 @retval FALSE EOS was not set to a 1; this is an error
235 @retval TRUE EOS was correctly set to a 1
236 **/
237 BOOLEAN
PchSmmSetAndCheckEos(VOID)238 PchSmmSetAndCheckEos (
239 VOID
240 )
241 {
242 UINT32 SmiEn;
243
244 SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN));
245
246 ///
247 /// Reset the PCH to generate subsequent SMIs
248 ///
249 SmiEn |= B_PCH_SMI_EN_EOS;
250
251 IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN), SmiEn);
252
253 ///
254 /// Double check that the assert worked
255 ///
256 SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN));
257
258 ///
259 /// Return TRUE if EOS is set correctly
260 ///
261 if ((SmiEn & B_PCH_SMI_EN_EOS) == 0) {
262 ///
263 /// EOS was not set to a 1; this is an error
264 ///
265 return FALSE;
266 } else {
267 ///
268 /// EOS was correctly set to a 1
269 ///
270 return TRUE;
271 }
272 }
273
274 /**
275 Determine whether an ACPI OS is present (via the SCI_EN bit)
276
277
278 @retval TRUE ACPI OS is present
279 @retval FALSE ACPI OS is not present
280 **/
281 BOOLEAN
PchSmmGetSciEn(VOID)282 PchSmmGetSciEn (
283 VOID
284 )
285 {
286 BOOLEAN SciEn;
287 UINT32 Pm1Cnt;
288
289 ///
290 /// Determine whether an ACPI OS is present (via the SCI_EN bit)
291 ///
292 Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
293 SciEn = (BOOLEAN) ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SCI_EN) == B_PCH_ACPI_PM1_CNT_SCI_EN);
294
295 return SciEn;
296 }
297
298 /**
299 Read a specifying bit with the register
300 These may or may not need to change w/ the PCH version; they're highly IA-32 dependent, though.
301
302 @param[in] BitDesc The struct that includes register address, size in byte and bit number
303
304 @retval TRUE The bit is enabled
305 @retval FALSE The bit is disabled
306 **/
307 BOOLEAN
ReadBitDesc(CONST PCH_SMM_BIT_DESC * BitDesc)308 ReadBitDesc (
309 CONST PCH_SMM_BIT_DESC *BitDesc
310 )
311 {
312 EFI_STATUS Status;
313 UINT64 Register;
314 UINT32 PciBus;
315 UINT32 PciDev;
316 UINT32 PciFun;
317 UINT32 PciReg;
318 UINTN RegSize;
319 BOOLEAN BitWasOne;
320 UINTN ShiftCount;
321 UINTN RegisterOffset;
322 UINT32 BaseAddr;
323 UINTN PciBaseAddress;
324
325 ASSERT (BitDesc != NULL);
326 ASSERT (!IS_BIT_DESC_NULL (*BitDesc));
327
328 RegSize = 0;
329 Register = 0;
330 ShiftCount = 0;
331 BitWasOne = FALSE;
332
333 switch (BitDesc->Reg.Type) {
334
335 case ACPI_ADDR_TYPE:
336 case TCO_ADDR_TYPE:
337 if (BitDesc->Reg.Type == ACPI_ADDR_TYPE) {
338 RegisterOffset = BitDesc->Reg.Data.acpi;
339 BaseAddr = mAcpiBaseAddr;
340 } else {
341 RegisterOffset = BitDesc->Reg.Data.tco;
342 BaseAddr = mTcoBaseAddr;
343 }
344 switch (BitDesc->SizeInBytes) {
345
346 case 0:
347 ///
348 /// Chances are that this field didn't get initialized.
349 /// Check your assignments to bit descriptions.
350 ///
351 ASSERT (FALSE);
352 break;
353
354 case 1:
355 RegSize = SMM_IO_UINT8;
356 break;
357
358 case 2:
359 RegSize = SMM_IO_UINT16;
360 break;
361
362 case 4:
363 RegSize = SMM_IO_UINT32;
364 break;
365
366 case 8:
367 RegSize = SMM_IO_UINT64;
368 break;
369
370 default:
371 ///
372 /// Unsupported or invalid register size
373 ///
374 ASSERT (FALSE);
375 break;
376 }
377 ///
378 /// Double check that we correctly read in the acpi base address
379 ///
380 ASSERT ((BaseAddr != 0x0) && ((BaseAddr & 0x1) != 0x1));
381
382 ShiftCount = BitDesc->Bit;
383 ///
384 /// As current CPU Smm Io can only support at most
385 /// 32-bit read/write,if Operation is 64 bit,
386 /// we do a 32 bit operation according to BitDesc->Bit
387 ///
388 if (RegSize == SMM_IO_UINT64) {
389 RegSize = SMM_IO_UINT32;
390 ///
391 /// If the operation is for high 32 bits
392 ///
393 if (BitDesc->Bit >= 32) {
394 RegisterOffset += 4;
395 ShiftCount -= 32;
396 }
397 }
398
399 Status = gSmst->SmmIo.Io.Read (
400 &gSmst->SmmIo,
401 RegSize,
402 BaseAddr + RegisterOffset,
403 1,
404 &Register
405 );
406 ASSERT_EFI_ERROR (Status);
407
408 if ((Register & (LShiftU64 (BIT_ZERO, ShiftCount))) != 0) {
409 BitWasOne = TRUE;
410 } else {
411 BitWasOne = FALSE;
412 }
413 break;
414
415 case GPIO_ADDR_TYPE:
416 case MEMORY_MAPPED_IO_ADDRESS_TYPE:
417 ///
418 /// Read the register, and it with the bit to read
419 ///
420 switch (BitDesc->SizeInBytes) {
421 case 1:
422 Register = (UINT64) MmioRead8 ((UINTN) BitDesc->Reg.Data.Mmio);
423 break;
424
425 case 2:
426 Register = (UINT64) MmioRead16 ((UINTN) BitDesc->Reg.Data.Mmio);
427 break;
428
429 case 4:
430 Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
431 break;
432
433 case 8:
434 Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
435 *((UINT32 *) (&Register) + 1) = MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio + 4);
436 break;
437
438 default:
439 ///
440 /// Unsupported or invalid register size
441 ///
442 ASSERT (FALSE);
443 break;
444 }
445
446 Register = Register & (LShiftU64 (BIT0, BitDesc->Bit));
447 if (Register) {
448 BitWasOne = TRUE;
449 } else {
450 BitWasOne = FALSE;
451 }
452 break;
453
454 case PCIE_ADDR_TYPE:
455 PciBus = BitDesc->Reg.Data.pcie.Fields.Bus;
456 PciDev = BitDesc->Reg.Data.pcie.Fields.Dev;
457 PciFun = BitDesc->Reg.Data.pcie.Fields.Fnc;
458 PciReg = BitDesc->Reg.Data.pcie.Fields.Reg;
459 PciBaseAddress = MmPciBase (PciBus, PciDev, PciFun);
460 switch (BitDesc->SizeInBytes) {
461
462 case 0:
463 ///
464 /// Chances are that this field didn't get initialized.
465 /// Check your assignments to bit descriptions.
466 ///
467 ASSERT (FALSE);
468 break;
469
470 case 1:
471 Register = (UINT64) MmioRead8 (PciBaseAddress + PciReg);
472 break;
473
474 case 2:
475 Register = (UINT64) MmioRead16 (PciBaseAddress + PciReg);
476 break;
477
478 case 4:
479 Register = (UINT64) MmioRead32 (PciBaseAddress + PciReg);
480 break;
481
482 default:
483 ///
484 /// Unsupported or invalid register size
485 ///
486 ASSERT (FALSE);
487 break;
488 }
489
490 if ((Register & (LShiftU64 (BIT_ZERO, BitDesc->Bit))) != 0) {
491 BitWasOne = TRUE;
492 } else {
493 BitWasOne = FALSE;
494 }
495 break;
496
497 case PCR_ADDR_TYPE:
498 ///
499 /// Read the register, and it with the bit to read
500 ///
501 switch (BitDesc->SizeInBytes) {
502 case 1:
503 PchPcrRead8 (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT8*) &Register);
504 break;
505
506 case 2:
507 PchPcrRead16 (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT16*) &Register);
508 break;
509
510 case 4:
511 PchPcrRead32 (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT32*) &Register);
512 break;
513
514 default:
515 ///
516 /// Unsupported or invalid register size
517 ///
518 ASSERT (FALSE);
519 break;
520 }
521
522 Register = Register & (LShiftU64 (BIT0, BitDesc->Bit));
523 if (Register) {
524 BitWasOne = TRUE;
525 } else {
526 BitWasOne = FALSE;
527 }
528 break;
529
530 default:
531 ///
532 /// This address type is not yet implemented
533 ///
534 ASSERT (FALSE);
535 break;
536 }
537
538 return BitWasOne;
539 }
540
541 /**
542 Write a specifying bit with the register
543
544 @param[in] BitDesc The struct that includes register address, size in byte and bit number
545 @param[in] ValueToWrite The value to be wrote
546 @param[in] WriteClear If the rest bits of the register is write clear
547
548 **/
549 VOID
WriteBitDesc(CONST PCH_SMM_BIT_DESC * BitDesc,CONST BOOLEAN ValueToWrite,CONST BOOLEAN WriteClear)550 WriteBitDesc (
551 CONST PCH_SMM_BIT_DESC *BitDesc,
552 CONST BOOLEAN ValueToWrite,
553 CONST BOOLEAN WriteClear
554 )
555 {
556 EFI_STATUS Status;
557 UINT64 Register;
558 UINT64 AndVal;
559 UINT64 OrVal;
560 UINT32 RegSize;
561 UINT32 PciBus;
562 UINT32 PciDev;
563 UINT32 PciFun;
564 UINT32 PciReg;
565 UINTN RegisterOffset;
566 UINT32 BaseAddr;
567 UINTN PciBaseAddress;
568
569 ASSERT (BitDesc != NULL);
570 ASSERT (!IS_BIT_DESC_NULL (*BitDesc));
571
572 RegSize = 0;
573 Register = 0;
574
575 if (WriteClear) {
576 AndVal = LShiftU64 (BIT_ZERO, BitDesc->Bit);
577 } else {
578 AndVal = ~(LShiftU64 (BIT_ZERO, BitDesc->Bit));
579 }
580
581 OrVal = (LShiftU64 ((UINT32) ValueToWrite, BitDesc->Bit));
582
583 switch (BitDesc->Reg.Type) {
584
585 case ACPI_ADDR_TYPE:
586 case TCO_ADDR_TYPE:
587 if (BitDesc->Reg.Type == ACPI_ADDR_TYPE) {
588 RegisterOffset = BitDesc->Reg.Data.acpi;
589 BaseAddr = mAcpiBaseAddr;
590 } else {
591 RegisterOffset = BitDesc->Reg.Data.tco;
592 BaseAddr = mTcoBaseAddr;
593 }
594
595 switch (BitDesc->SizeInBytes) {
596
597 case 0:
598 ///
599 /// Chances are that this field didn't get initialized.
600 /// Check your assignments to bit descriptions.
601 ///
602 ASSERT (FALSE);
603 break;
604
605 case 1:
606 RegSize = SMM_IO_UINT8;
607 break;
608
609 case 2:
610 RegSize = SMM_IO_UINT16;
611 break;
612
613 case 4:
614 RegSize = SMM_IO_UINT32;
615 break;
616
617 case 8:
618 RegSize = SMM_IO_UINT64;
619 break;
620
621 default:
622 ///
623 /// Unsupported or invalid register size
624 ///
625 ASSERT (FALSE);
626 break;
627 }
628 ///
629 /// Double check that we correctly read in the acpi base address
630 ///
631 ASSERT ((BaseAddr != 0x0) && ((BaseAddr & 0x1) != 0x1));
632
633 ///
634 /// As current CPU Smm Io can only support at most
635 /// 32-bit read/write,if Operation is 64 bit,
636 /// we do a 32 bit operation according to BitDesc->Bit
637 ///
638 if (RegSize == SMM_IO_UINT64) {
639 RegSize = SMM_IO_UINT32;
640 ///
641 /// If the operation is for high 32 bits
642 ///
643 if (BitDesc->Bit >= 32) {
644 RegisterOffset += 4;
645
646 if (WriteClear) {
647 AndVal = LShiftU64 (BIT_ZERO, BitDesc->Bit - 32);
648 } else {
649 AndVal = ~(LShiftU64 (BIT_ZERO, BitDesc->Bit - 32));
650 }
651
652 OrVal = LShiftU64 ((UINT32) ValueToWrite, BitDesc->Bit - 32);
653 }
654 }
655
656 Status = gSmst->SmmIo.Io.Read (
657 &gSmst->SmmIo,
658 RegSize,
659 BaseAddr + RegisterOffset,
660 1,
661 &Register
662 );
663 ASSERT_EFI_ERROR (Status);
664
665 Register &= AndVal;
666 Register |= OrVal;
667
668 Status = gSmst->SmmIo.Io.Write (
669 &gSmst->SmmIo,
670 RegSize,
671 BaseAddr + RegisterOffset,
672 1,
673 &Register
674 );
675 ASSERT_EFI_ERROR (Status);
676 break;
677
678 case GPIO_ADDR_TYPE:
679 case MEMORY_MAPPED_IO_ADDRESS_TYPE:
680 ///
681 /// Read the register, or it with the bit to set, then write it back.
682 ///
683 switch (BitDesc->SizeInBytes) {
684 case 1:
685 MmioAndThenOr8 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT8) AndVal, (UINT8) OrVal);
686 break;
687
688 case 2:
689 MmioAndThenOr16 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT16) AndVal, (UINT16) OrVal);
690 break;
691
692 case 4:
693 MmioAndThenOr32 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT32) AndVal, (UINT32) OrVal);
694 break;
695
696 case 8:
697 Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
698 *((UINT32 *) (&Register) + 1) = MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio + 4);
699 Register &= AndVal;
700 Register |= OrVal;
701 MmioWrite32 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT32) Register);
702 MmioWrite32 ((UINTN) BitDesc->Reg.Data.Mmio + 4, *((UINT32 *) (&Register) + 1));
703 break;
704
705 default:
706 ///
707 /// Unsupported or invalid register size
708 ///
709 ASSERT (FALSE);
710 break;
711 }
712 break;
713
714 case PCIE_ADDR_TYPE:
715 PciBus = BitDesc->Reg.Data.pcie.Fields.Bus;
716 PciDev = BitDesc->Reg.Data.pcie.Fields.Dev;
717 PciFun = BitDesc->Reg.Data.pcie.Fields.Fnc;
718 PciReg = BitDesc->Reg.Data.pcie.Fields.Reg;
719 PciBaseAddress = MmPciBase (PciBus, PciDev, PciFun);
720 switch (BitDesc->SizeInBytes) {
721
722 case 0:
723 ///
724 /// Chances are that this field didn't get initialized -- check your assignments
725 /// to bit descriptions.
726 ///
727 ASSERT (FALSE);
728 break;
729
730 case 1:
731 MmioAndThenOr8 (PciBaseAddress + PciReg, (UINT8) AndVal, (UINT8) OrVal);
732 break;
733
734 case 2:
735 MmioAndThenOr16 (PciBaseAddress + PciReg, (UINT16) AndVal, (UINT16) OrVal);
736 break;
737
738 case 4:
739 MmioAndThenOr32 (PciBaseAddress + PciReg, (UINT32) AndVal, (UINT32) OrVal);
740 break;
741
742 default:
743 ///
744 /// Unsupported or invalid register size
745 ///
746 ASSERT (FALSE);
747 break;
748 }
749 break;
750
751 case PCR_ADDR_TYPE:
752 ///
753 /// Read the register, or it with the bit to set, then write it back.
754 ///
755 switch (BitDesc->SizeInBytes) {
756 case 1:
757 PchPcrAndThenOr8 ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT8) AndVal, (UINT8) OrVal);
758 break;
759
760 case 2:
761 PchPcrAndThenOr16 ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT16) AndVal, (UINT16) OrVal);
762 break;
763
764 case 4:
765 PchPcrAndThenOr32 ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT32) AndVal, (UINT32) OrVal);
766 break;
767
768 default:
769 ///
770 /// Unsupported or invalid register size
771 ///
772 ASSERT (FALSE);
773 break;
774 }
775 break;
776
777 default:
778 ///
779 /// This address type is not yet implemented
780 ///
781 ASSERT (FALSE);
782 break;
783 }
784 }
785