TianoCore EDK2 master
Loading...
Searching...
No Matches
HpetTimer.c
Go to the documentation of this file.
1
9#include <PiDxe.h>
10
11#include <Protocol/Cpu.h>
12#include <Protocol/Timer.h>
13
14#include <Library/IoLib.h>
15#include <Library/PcdLib.h>
16#include <Library/BaseLib.h>
17#include <Library/DebugLib.h>
20#include <Library/IoApicLib.h>
21
22#include <Register/LocalApic.h>
23#include <Register/IoApic.h>
24#include <Register/Hpet.h>
25
29#define HPET_INVALID_TIMER_INDEX 0xff
30
34
66EFIAPI
70 );
71
100EFIAPI
103 IN UINT64 TimerPeriod
104 );
105
121EFIAPI
124 OUT UINT64 *TimerPeriod
125 );
126
144EFIAPI
147 );
148
153
162};
163
168
173
177UINT64 mTimerPeriod = 0;
178
183
188
192volatile UINT64 mPreviousMainCounter;
193
194volatile UINT64 mPreviousComparator;
195
200
205
211
217
224
230
238UINT64
240 IN UINTN Offset
241 )
242{
243 return MmioRead64 (PcdGet32 (PcdHpetBaseAddress) + Offset);
244}
245
254UINT64
256 IN UINTN Offset,
257 IN UINT64 Value
258 )
259{
260 return MmioWrite64 (PcdGet32 (PcdHpetBaseAddress) + Offset, Value);
261}
262
269VOID
271 IN BOOLEAN Enable
272 )
273{
274 mHpetGeneralConfiguration.Bits.MainCounterEnable = Enable ? 1 : 0;
275 HpetWrite (HPET_GENERAL_CONFIGURATION_OFFSET, mHpetGeneralConfiguration.Uint64);
276}
277
288VOID
289EFIAPI
291 IN EFI_EXCEPTION_TYPE InterruptType,
292 IN EFI_SYSTEM_CONTEXT SystemContext
293 )
294{
295 UINT64 MainCounter;
296 UINT64 Comparator;
297 UINT64 TimerPeriod;
298 UINT64 Delta;
299
300 //
301 // Count number of ticks
302 //
303 DEBUG_CODE (
304 mNumTicks++;
305 );
306
307 //
308 // Clear HPET timer interrupt status
309 //
310 HpetWrite (HPET_GENERAL_INTERRUPT_STATUS_OFFSET, LShiftU64 (1, mTimerIndex));
311
312 //
313 // Local APIC EOI
314 //
315 SendApicEoi ();
316
317 //
318 // Disable HPET timer when adjusting the COMPARATOR value to prevent a missed interrupt
319 //
321
322 //
323 // Capture main counter value
324 //
325 MainCounter = HpetRead (HPET_MAIN_COUNTER_OFFSET);
326
327 //
328 // Get the previous comparator counter
329 //
330 mPreviousComparator = HpetRead (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE);
331
332 //
333 // Set HPET COMPARATOR to the value required for the next timer tick
334 //
335 Comparator = (mPreviousComparator + mTimerCount) & mCounterMask;
336
337 if ((mPreviousMainCounter < MainCounter) && (mPreviousComparator > Comparator)) {
338 //
339 // When comparator overflows
340 //
341 HpetWrite (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, Comparator);
342 } else if ((mPreviousMainCounter > MainCounter) && (mPreviousComparator < Comparator)) {
343 //
344 // When main counter overflows
345 //
346 HpetWrite (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, (MainCounter + mTimerCount) & mCounterMask);
347 } else {
348 //
349 // When both main counter and comparator do not overflow or both do overflow
350 //
351 if (Comparator > MainCounter) {
352 HpetWrite (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, Comparator);
353 } else {
354 HpetWrite (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, (MainCounter + mTimerCount) & mCounterMask);
355 }
356 }
357
358 //
359 // Enable the HPET counter once the new COMPARATOR value has been set.
360 //
362
363 //
364 // Check to see if there is a registered notification function
365 //
366 if (mTimerNotifyFunction != NULL) {
367 //
368 // Compute time since last notification in 100 ns units (10 ^ -7)
369 //
370 if (MainCounter > mPreviousMainCounter) {
371 //
372 // Main counter does not overflow
373 //
374 Delta = MainCounter - mPreviousMainCounter;
375 } else {
376 //
377 // Main counter overflows, first usb, then add
378 //
379 Delta = (mCounterMask - mPreviousMainCounter) + MainCounter;
380 }
381
382 TimerPeriod = DivU64x32 (
383 MultU64x32 (
384 Delta & mCounterMask,
385 mHpetGeneralCapabilities.Bits.CounterClockPeriod
386 ),
387 100000000
388 );
389
390 //
391 // Save main counter value before calling notification function
392 // that may enable interrupts and allow interrupt nesting.
393 //
394 mPreviousMainCounter = MainCounter;
395
396 //
397 // Call registered notification function passing in the time since the last
398 // interrupt in 100 ns units.
399 //
400 mTimerNotifyFunction (TimerPeriod);
401 return;
402 }
403
404 //
405 // Save main counter value
406 //
407 mPreviousMainCounter = MainCounter;
408}
409
441EFIAPI
445 )
446{
447 //
448 // Check for invalid parameters
449 //
450 if ((NotifyFunction == NULL) && (mTimerNotifyFunction == NULL)) {
451 return EFI_INVALID_PARAMETER;
452 }
453
454 if ((NotifyFunction != NULL) && (mTimerNotifyFunction != NULL)) {
455 return EFI_ALREADY_STARTED;
456 }
457
458 //
459 // Cache the registered notification function
460 //
462
463 return EFI_SUCCESS;
464}
465
494EFIAPI
497 IN UINT64 TimerPeriod
498 )
499{
500 EFI_TPL Tpl;
501 UINT64 MainCounter;
502 UINT64 Delta;
503 UINT64 CurrentComparator;
504 HPET_TIMER_MSI_ROUTE_REGISTER HpetTimerMsiRoute;
505
506 //
507 // Disable interrupts
508 //
509 Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
510
511 //
512 // Disable HPET timer when adjusting the timer period
513 //
515
516 if (TimerPeriod == 0) {
517 if (mTimerPeriod != 0) {
518 //
519 // Check if there is possibly a pending interrupt
520 //
521 MainCounter = HpetRead (HPET_MAIN_COUNTER_OFFSET);
522 if (MainCounter < mPreviousMainCounter) {
523 Delta = (mCounterMask - mPreviousMainCounter) + MainCounter;
524 } else {
525 Delta = MainCounter - mPreviousMainCounter;
526 }
527
528 if ((Delta & mCounterMask) >= mTimerCount) {
529 //
530 // Interrupt still happens after disable HPET, wait to be processed
531 // Wait until interrupt is processed and comparator is increased
532 //
533 CurrentComparator = HpetRead (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE);
534 while (CurrentComparator == mPreviousComparator) {
535 CurrentComparator = HpetRead (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE);
536 CpuPause ();
537 }
538 }
539 }
540
541 //
542 // If TimerPeriod is 0, then mask HPET Timer interrupts
543 //
544
545 if ((mTimerConfiguration.Bits.MsiInterruptCapability != 0) && FeaturePcdGet (PcdHpetMsiEnable)) {
546 //
547 // Disable HPET MSI interrupt generation
548 //
549 mTimerConfiguration.Bits.MsiInterruptEnable = 0;
550 } else {
551 //
552 // Disable I/O APIC Interrupt
553 //
555 }
556
557 //
558 // Disable HPET timer interrupt
559 //
560 mTimerConfiguration.Bits.InterruptEnable = 0;
561 HpetWrite (HPET_TIMER_CONFIGURATION_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, mTimerConfiguration.Uint64);
562 } else {
563 //
564 // Convert TimerPeriod to femtoseconds and divide by the number if femtoseconds
565 // per tick of the HPET counter to determine the number of HPET counter ticks
566 // in TimerPeriod 100 ns units.
567 //
569 MultU64x32 (TimerPeriod, 100000000),
570 mHpetGeneralCapabilities.Bits.CounterClockPeriod
571 );
572
573 //
574 // Program the HPET Comparator with the number of ticks till the next interrupt
575 //
576 MainCounter = HpetRead (HPET_MAIN_COUNTER_OFFSET);
577 if (MainCounter > mPreviousMainCounter) {
578 Delta = MainCounter - mPreviousMainCounter;
579 } else {
580 Delta = (mCounterMask - mPreviousMainCounter) + MainCounter;
581 }
582
583 if ((Delta & mCounterMask) >= mTimerCount) {
584 HpetWrite (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, (MainCounter + 1) & mCounterMask);
585 } else {
587 }
588
589 //
590 // Enable HPET Timer interrupt generation
591 //
592 if ((mTimerConfiguration.Bits.MsiInterruptCapability != 0) && FeaturePcdGet (PcdHpetMsiEnable)) {
593 //
594 // Program MSI Address and MSI Data values in the selected HPET Timer
595 // Program HPET register with APIC ID of current BSP in case BSP has been switched
596 //
597 HpetTimerMsiRoute.Bits.Address = GetApicMsiAddress ();
598 HpetTimerMsiRoute.Bits.Value = (UINT32)GetApicMsiValue (PcdGet8 (PcdHpetLocalApicVector), LOCAL_APIC_DELIVERY_MODE_LOWEST_PRIORITY, FALSE, FALSE);
599 HpetWrite (HPET_TIMER_MSI_ROUTE_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, HpetTimerMsiRoute.Uint64);
600 //
601 // Enable HPET MSI Interrupt
602 //
603 mTimerConfiguration.Bits.MsiInterruptEnable = 1;
604 } else {
605 //
606 // Enable timer interrupt through I/O APIC
607 // Program IOAPIC register with APIC ID of current BSP in case BSP has been switched
608 //
609 IoApicConfigureInterrupt (mTimerIrq, PcdGet8 (PcdHpetLocalApicVector), IO_APIC_DELIVERY_MODE_LOWEST_PRIORITY, TRUE, FALSE);
611 }
612
613 //
614 // Enable HPET Interrupt Generation
615 //
616 mTimerConfiguration.Bits.InterruptEnable = 1;
617 HpetWrite (HPET_TIMER_CONFIGURATION_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, mTimerConfiguration.Uint64);
618 }
619
620 //
621 // Save the new timer period
622 //
623 mTimerPeriod = TimerPeriod;
624
625 //
626 // Enable the HPET counter once new timer period has been established
627 // The HPET counter should run even if the HPET Timer interrupts are
628 // disabled. This is used to account for time passed while the interrupt
629 // is disabled.
630 //
632
633 //
634 // Restore interrupts
635 //
636 gBS->RestoreTPL (Tpl);
637
638 return EFI_SUCCESS;
639}
640
656EFIAPI
659 OUT UINT64 *TimerPeriod
660 )
661{
662 if (TimerPeriod == NULL) {
663 return EFI_INVALID_PARAMETER;
664 }
665
666 *TimerPeriod = mTimerPeriod;
667
668 return EFI_SUCCESS;
669}
670
688EFIAPI
691 )
692{
693 UINT64 MainCounter;
694 EFI_TPL Tpl;
695 UINT64 TimerPeriod;
696 UINT64 Delta;
697
698 //
699 // Disable interrupts
700 //
701 Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
702
703 //
704 // Capture main counter value
705 //
706 MainCounter = HpetRead (HPET_MAIN_COUNTER_OFFSET);
707
708 //
709 // Check to see if there is a registered notification function
710 //
711 if (mTimerNotifyFunction != NULL) {
712 //
713 // Compute time since last interrupt in 100 ns units (10 ^ -7)
714 //
715 if (MainCounter > mPreviousMainCounter) {
716 //
717 // Main counter does not overflow
718 //
719 Delta = MainCounter - mPreviousMainCounter;
720 } else {
721 //
722 // Main counter overflows, first usb, then add
723 //
724 Delta = (mCounterMask - mPreviousMainCounter) + MainCounter;
725 }
726
727 TimerPeriod = DivU64x32 (
728 MultU64x32 (
729 Delta & mCounterMask,
730 mHpetGeneralCapabilities.Bits.CounterClockPeriod
731 ),
732 100000000
733 );
734
735 //
736 // Call registered notification function passing in the time since the last
737 // interrupt in 100 ns units.
738 //
739 mTimerNotifyFunction (TimerPeriod);
740 }
741
742 //
743 // Save main counter value
744 //
745 mPreviousMainCounter = MainCounter;
746
747 //
748 // Restore interrupts
749 //
750 gBS->RestoreTPL (Tpl);
751
752 return EFI_SUCCESS;
753}
754
767EFIAPI
769 IN EFI_HANDLE ImageHandle,
770 IN EFI_SYSTEM_TABLE *SystemTable
771 )
772{
773 EFI_STATUS Status;
774 UINTN TimerIndex;
775 UINTN MsiTimerIndex;
776 HPET_TIMER_MSI_ROUTE_REGISTER HpetTimerMsiRoute;
777
778 DEBUG ((DEBUG_INFO, "Init HPET Timer Driver\n"));
779
780 //
781 // Make sure the Timer Architectural Protocol is not already installed in the system
782 //
783 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiTimerArchProtocolGuid);
784
785 //
786 // Find the CPU architectural protocol.
787 //
788 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);
789 ASSERT_EFI_ERROR (Status);
790
791 //
792 // Retrieve HPET Capabilities and Configuration Information
793 //
795 mHpetGeneralConfiguration.Uint64 = HpetRead (HPET_GENERAL_CONFIGURATION_OFFSET);
796
797 //
798 // If Revision is not valid, then ASSERT() and unload the driver because the HPET
799 // device is not present.
800 //
801 ASSERT (mHpetGeneralCapabilities.Uint64 != 0);
802 ASSERT (mHpetGeneralCapabilities.Uint64 != 0xFFFFFFFFFFFFFFFFULL);
803 if ((mHpetGeneralCapabilities.Uint64 == 0) || (mHpetGeneralCapabilities.Uint64 == 0xFFFFFFFFFFFFFFFFULL)) {
804 DEBUG ((DEBUG_ERROR, "HPET device is not present. Unload HPET driver.\n"));
805 return EFI_DEVICE_ERROR;
806 }
807
808 //
809 // Force the HPET timer to be disabled while setting everything up
810 //
812
813 //
814 // Dump HPET Configuration Information
815 //
817 DEBUG ((DEBUG_INFO, "HPET Base Address = 0x%08x\n", PcdGet32 (PcdHpetBaseAddress)));
818 DEBUG ((DEBUG_INFO, " HPET_GENERAL_CAPABILITIES_ID = 0x%016lx\n", mHpetGeneralCapabilities));
819 DEBUG ((DEBUG_INFO, " HPET_GENERAL_CONFIGURATION = 0x%016lx\n", mHpetGeneralConfiguration.Uint64));
820 DEBUG ((DEBUG_INFO, " HPET_GENERAL_INTERRUPT_STATUS = 0x%016lx\n", HpetRead (HPET_GENERAL_INTERRUPT_STATUS_OFFSET)));
821 DEBUG ((DEBUG_INFO, " HPET_MAIN_COUNTER = 0x%016lx\n", HpetRead (HPET_MAIN_COUNTER_OFFSET)));
822 DEBUG ((DEBUG_INFO, " HPET Main Counter Period = %d (fs)\n", mHpetGeneralCapabilities.Bits.CounterClockPeriod));
823 for (TimerIndex = 0; TimerIndex <= mHpetGeneralCapabilities.Bits.NumberOfTimers; TimerIndex++) {
824 DEBUG ((DEBUG_INFO, " HPET_TIMER%d_CONFIGURATION = 0x%016lx\n", TimerIndex, HpetRead (HPET_TIMER_CONFIGURATION_OFFSET + TimerIndex * HPET_TIMER_STRIDE)));
825 DEBUG ((DEBUG_INFO, " HPET_TIMER%d_COMPARATOR = 0x%016lx\n", TimerIndex, HpetRead (HPET_TIMER_COMPARATOR_OFFSET + TimerIndex * HPET_TIMER_STRIDE)));
826 DEBUG ((DEBUG_INFO, " HPET_TIMER%d_MSI_ROUTE = 0x%016lx\n", TimerIndex, HpetRead (HPET_TIMER_MSI_ROUTE_OFFSET + TimerIndex * HPET_TIMER_STRIDE)));
827 }
828
830
831 //
832 // Capture the current HPET main counter value.
833 //
835
836 //
837 // Determine the interrupt mode to use for the HPET Timer.
838 // Look for MSI first, then unused PIC mode interrupt, then I/O APIC mode interrupt
839 //
840 MsiTimerIndex = HPET_INVALID_TIMER_INDEX;
842 for (TimerIndex = 0; TimerIndex <= mHpetGeneralCapabilities.Bits.NumberOfTimers; TimerIndex++) {
843 //
844 // Read the HPET Timer Capabilities and Configuration register
845 //
846 mTimerConfiguration.Uint64 = HpetRead (HPET_TIMER_CONFIGURATION_OFFSET + TimerIndex * HPET_TIMER_STRIDE);
847
848 //
849 // Check to see if this HPET Timer supports MSI
850 //
851 if (mTimerConfiguration.Bits.MsiInterruptCapability != 0) {
852 //
853 // Save the index of the first HPET Timer that supports MSI interrupts
854 //
855 if (MsiTimerIndex == HPET_INVALID_TIMER_INDEX) {
856 MsiTimerIndex = TimerIndex;
857 }
858 }
859
860 //
861 // Check to see if this HPET Timer supports I/O APIC interrupts
862 //
863 if (mTimerConfiguration.Bits.InterruptRouteCapability != 0) {
864 //
865 // Save the index of the first HPET Timer that supports I/O APIC interrupts
866 //
868 mTimerIndex = TimerIndex;
869 mTimerIrq = (UINT32)LowBitSet32 (mTimerConfiguration.Bits.InterruptRouteCapability);
870 }
871 }
872 }
873
874 if (FeaturePcdGet (PcdHpetMsiEnable) && (MsiTimerIndex != HPET_INVALID_TIMER_INDEX)) {
875 //
876 // Use MSI interrupt if supported
877 //
878 mTimerIndex = MsiTimerIndex;
879
880 //
881 // Program MSI Address and MSI Data values in the selected HPET Timer
882 //
883 HpetTimerMsiRoute.Bits.Address = GetApicMsiAddress ();
884 HpetTimerMsiRoute.Bits.Value = (UINT32)GetApicMsiValue (PcdGet8 (PcdHpetLocalApicVector), LOCAL_APIC_DELIVERY_MODE_LOWEST_PRIORITY, FALSE, FALSE);
885 HpetWrite (HPET_TIMER_MSI_ROUTE_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, HpetTimerMsiRoute.Uint64);
886
887 //
888 // Read the HPET Timer Capabilities and Configuration register and initialize for MSI mode
889 // Clear LevelTriggeredInterrupt to use edge triggered interrupts when in MSI mode
890 //
891 mTimerConfiguration.Uint64 = HpetRead (HPET_TIMER_CONFIGURATION_OFFSET + mTimerIndex * HPET_TIMER_STRIDE);
892 mTimerConfiguration.Bits.LevelTriggeredInterrupt = 0;
893 } else {
894 //
895 // If no HPET timers support MSI or I/O APIC modes, then ASSERT() and unload the driver.
896 //
899 DEBUG ((DEBUG_ERROR, "No HPET timers support MSI or I/O APIC mode. Unload HPET driver.\n"));
900 return EFI_DEVICE_ERROR;
901 }
902
903 //
904 // Initialize I/O APIC entry for HPET Timer Interrupt
905 // Fixed Delivery Mode, Level Triggered, Asserted Low
906 //
907 IoApicConfigureInterrupt (mTimerIrq, PcdGet8 (PcdHpetLocalApicVector), IO_APIC_DELIVERY_MODE_LOWEST_PRIORITY, TRUE, FALSE);
908
909 //
910 // Read the HPET Timer Capabilities and Configuration register and initialize for I/O APIC mode
911 // Clear MsiInterruptCapability to force rest of driver to use I/O APIC mode
912 // Set LevelTriggeredInterrupt to use level triggered interrupts when in I/O APIC mode
913 // Set InterruptRoute field based in mTimerIrq
914 //
915 mTimerConfiguration.Uint64 = HpetRead (HPET_TIMER_CONFIGURATION_OFFSET + mTimerIndex * HPET_TIMER_STRIDE);
916 mTimerConfiguration.Bits.LevelTriggeredInterrupt = 1;
917 mTimerConfiguration.Bits.InterruptRoute = mTimerIrq;
918 }
919
920 //
921 // Configure the selected HPET Timer with settings common to both MSI mode and I/O APIC mode
922 // Clear InterruptEnable to keep interrupts disabled until full init is complete
923 // Clear PeriodicInterruptEnable to use one-shot mode
924 // Configure as a 32-bit counter
925 //
926 mTimerConfiguration.Bits.InterruptEnable = 0;
927 mTimerConfiguration.Bits.PeriodicInterruptEnable = 0;
928 mTimerConfiguration.Bits.CounterSizeEnable = 1;
929 HpetWrite (HPET_TIMER_CONFIGURATION_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, mTimerConfiguration.Uint64);
930
931 //
932 // Read the HPET Timer Capabilities and Configuration register back again.
933 // CounterSizeEnable will be read back as a 0 if it is a 32-bit only timer
934 //
935 mTimerConfiguration.Uint64 = HpetRead (HPET_TIMER_CONFIGURATION_OFFSET + mTimerIndex * HPET_TIMER_STRIDE);
936 if ((mTimerConfiguration.Bits.CounterSizeEnable == 1) && (sizeof (UINTN) == sizeof (UINT64))) {
937 DEBUG ((DEBUG_INFO, "Choose 64-bit HPET timer.\n"));
938 //
939 // 64-bit BIOS can use 64-bit HPET timer
940 //
941 mCounterMask = 0xffffffffffffffffULL;
942 //
943 // Set timer back to 64-bit
944 //
945 mTimerConfiguration.Bits.CounterSizeEnable = 0;
946 HpetWrite (HPET_TIMER_CONFIGURATION_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, mTimerConfiguration.Uint64);
947 } else {
948 DEBUG ((DEBUG_INFO, "Choose 32-bit HPET timer.\n"));
949 mCounterMask = 0x00000000ffffffffULL;
950 }
951
952 //
953 // Install interrupt handler for selected HPET Timer
954 //
955 Status = mCpu->RegisterInterruptHandler (mCpu, PcdGet8 (PcdHpetLocalApicVector), TimerInterruptHandler);
956 ASSERT_EFI_ERROR (Status);
957 if (EFI_ERROR (Status)) {
958 DEBUG ((DEBUG_ERROR, "Unable to register HPET interrupt with CPU Arch Protocol. Unload HPET driver.\n"));
959 return EFI_DEVICE_ERROR;
960 }
961
962 //
963 // Force the HPET Timer to be enabled at its default period
964 //
965 Status = TimerDriverSetTimerPeriod (&mTimer, PcdGet64 (PcdHpetDefaultTimerPeriod));
966 ASSERT_EFI_ERROR (Status);
967 if (EFI_ERROR (Status)) {
968 DEBUG ((DEBUG_ERROR, "Unable to set HPET default timer rate. Unload HPET driver.\n"));
969 return EFI_DEVICE_ERROR;
970 }
971
972 //
973 // Show state of enabled HPET timer
974 //
976 if ((mTimerConfiguration.Bits.MsiInterruptCapability != 0) && FeaturePcdGet (PcdHpetMsiEnable)) {
977 DEBUG ((DEBUG_INFO, "HPET Interrupt Mode MSI\n"));
978 } else {
979 DEBUG ((DEBUG_INFO, "HPET Interrupt Mode I/O APIC\n"));
980 DEBUG ((DEBUG_INFO, "HPET I/O APIC IRQ = 0x%02x\n", mTimerIrq));
981 }
982
983 DEBUG ((DEBUG_INFO, "HPET Interrupt Vector = 0x%02x\n", PcdGet8 (PcdHpetLocalApicVector)));
984 DEBUG ((DEBUG_INFO, "HPET Counter Mask = 0x%016lx\n", mCounterMask));
985 DEBUG ((DEBUG_INFO, "HPET Timer Period = %d\n", mTimerPeriod));
986 DEBUG ((DEBUG_INFO, "HPET Timer Count = 0x%016lx\n", mTimerCount));
987 DEBUG ((DEBUG_INFO, "HPET_TIMER%d_CONFIGURATION = 0x%016lx\n", mTimerIndex, HpetRead (HPET_TIMER_CONFIGURATION_OFFSET + mTimerIndex * HPET_TIMER_STRIDE)));
988 DEBUG ((DEBUG_INFO, "HPET_TIMER%d_COMPARATOR = 0x%016lx\n", mTimerIndex, HpetRead (HPET_TIMER_COMPARATOR_OFFSET + mTimerIndex * HPET_TIMER_STRIDE)));
989 DEBUG ((DEBUG_INFO, "HPET_TIMER%d_MSI_ROUTE = 0x%016lx\n", mTimerIndex, HpetRead (HPET_TIMER_MSI_ROUTE_OFFSET + mTimerIndex * HPET_TIMER_STRIDE)));
990
991 //
992 // Wait for a few timer interrupts to fire before continuing
993 //
994 while (mNumTicks < 10) {
995 }
996
998
999 //
1000 // Install the Timer Architectural Protocol onto a new handle
1001 //
1002 Status = gBS->InstallMultipleProtocolInterfaces (
1003 &mTimerHandle,
1004 &gEfiTimerArchProtocolGuid,
1005 &mTimer,
1006 NULL
1007 );
1008 ASSERT_EFI_ERROR (Status);
1009
1010 return Status;
1011}
UINT64 UINTN
INTN EFIAPI LowBitSet32(IN UINT32 Operand)
Definition: LowBitSet32.c:26
UINT64 EFIAPI DivU64x32(IN UINT64 Dividend, IN UINT32 Divisor)
Definition: DivU64x32.c:29
VOID EFIAPI CpuPause(VOID)
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition: MultU64x32.c:27
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
UINT64 HpetWrite(IN UINTN Offset, IN UINT64 Value)
Definition: HpetTimer.c:255
EFI_STATUS EFIAPI TimerDriverInitialize(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: HpetTimer.c:768
HPET_TIMER_CONFIGURATION_REGISTER mTimerConfiguration
Definition: HpetTimer.c:223
UINT64 mTimerCount
Definition: HpetTimer.c:182
UINT64 HpetRead(IN UINTN Offset)
Definition: HpetTimer.c:239
HPET_GENERAL_CAPABILITIES_ID_REGISTER mHpetGeneralCapabilities
Definition: HpetTimer.c:210
EFI_TIMER_NOTIFY mTimerNotifyFunction
Definition: HpetTimer.c:172
VOID HpetEnable(IN BOOLEAN Enable)
Definition: HpetTimer.c:270
EFI_STATUS EFIAPI TimerDriverRegisterHandler(IN EFI_TIMER_ARCH_PROTOCOL *This, IN EFI_TIMER_NOTIFY NotifyFunction)
Definition: HpetTimer.c:442
EFI_HANDLE mTimerHandle
Definition: HpetTimer.c:152
UINT32 mTimerIrq
Definition: HpetTimer.c:204
volatile UINTN mNumTicks
Definition: HpetTimer.c:229
volatile UINT64 mPreviousMainCounter
Definition: HpetTimer.c:192
#define HPET_INVALID_TIMER_INDEX
Definition: HpetTimer.c:29
EFI_STATUS EFIAPI TimerDriverGetTimerPeriod(IN EFI_TIMER_ARCH_PROTOCOL *This, OUT UINT64 *TimerPeriod)
Definition: HpetTimer.c:657
EFI_STATUS EFIAPI TimerDriverSetTimerPeriod(IN EFI_TIMER_ARCH_PROTOCOL *This, IN UINT64 TimerPeriod)
Definition: HpetTimer.c:495
EFI_STATUS EFIAPI TimerDriverGenerateSoftInterrupt(IN EFI_TIMER_ARCH_PROTOCOL *This)
Definition: HpetTimer.c:689
HPET_GENERAL_CONFIGURATION_REGISTER mHpetGeneralConfiguration
Definition: HpetTimer.c:216
UINT64 mTimerPeriod
Definition: HpetTimer.c:177
EFI_TIMER_ARCH_PROTOCOL mTimer
Definition: HpetTimer.c:157
VOID EFIAPI TimerInterruptHandler(IN EFI_EXCEPTION_TYPE InterruptType, IN EFI_SYSTEM_CONTEXT SystemContext)
Definition: HpetTimer.c:290
UINT64 mCounterMask
Definition: HpetTimer.c:187
EFI_CPU_ARCH_PROTOCOL * mCpu
Definition: HpetTimer.c:167
UINTN mTimerIndex
Definition: HpetTimer.c:199
VOID EFIAPI IoApicConfigureInterrupt(IN UINTN Irq, IN UINTN Vector, IN UINTN DeliveryMode, IN BOOLEAN LevelTriggered, IN BOOLEAN AssertionLevel)
Definition: IoApicLib.c:123
VOID EFIAPI IoApicEnableInterrupt(IN UINTN Irq, IN BOOLEAN Enable)
Definition: IoApicLib.c:76
UINT64 EFIAPI MmioWrite64(IN UINTN Address, IN UINT64 Value)
Definition: IoLib.c:400
UINT64 EFIAPI MmioRead64(IN UINTN Address)
Definition: IoLib.c:355
UINT32 EFIAPI GetApicMsiAddress(VOID)
Definition: BaseXApicLib.c:900
UINT64 EFIAPI GetApicMsiValue(IN UINT8 Vector, IN UINTN DeliveryMode, IN BOOLEAN LevelTriggered, IN BOOLEAN AssertionLevel)
Definition: BaseXApicLib.c:946
VOID EFIAPI SendApicEoi(VOID)
Definition: BaseXApicLib.c:885
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG_CODE_BEGIN()
Definition: DebugLib.h:564
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define ASSERT_PROTOCOL_ALREADY_INSTALLED(Handle, Guid)
Definition: DebugLib.h:535
#define DEBUG_CODE_END()
Definition: DebugLib.h:578
#define DEBUG_CODE(Expression)
Definition: DebugLib.h:590
INTN EFI_EXCEPTION_TYPE
Definition: DebugSupport.h:35
VOID(EFIAPI * EFI_TIMER_NOTIFY)(IN UINT64 Time)
Definition: Timer.h:41
#define HPET_MAIN_COUNTER_OFFSET
Definition: Hpet.h:23
#define HPET_TIMER_STRIDE
Definition: Hpet.h:31
#define HPET_GENERAL_CAPABILITIES_ID_OFFSET
Definition: Hpet.h:16
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
#define PcdGet8(TokenName)
Definition: PcdLib.h:336
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define FeaturePcdGet(TokenName)
Definition: PcdLib.h:50
VOID EFIAPI NotifyFunction(IN EFI_EVENT Event, IN VOID *Context)
Definition: ScsiBus.c:1492
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
UINTN EFI_TPL
Definition: UefiBaseType.h:41
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS