mirror of https://github.com/acidanthera/audk.git
Improve Local APIC library class. Add new library APIs: GetApicVersion(), SendFixedIpi(), SendFixedIpiAllExcludingSelf(), GetApicTimerState(). Remove GetApicTimerDivisor (), its functionality can be covered by GetApicTimerState().
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10824 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
2ca7eca448
commit
ae40aef1fb
|
@ -75,6 +75,45 @@ GetApicId (
|
||||||
VOID
|
VOID
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the value of the local APIC version register.
|
||||||
|
|
||||||
|
@return the value of the local APIC version register.
|
||||||
|
**/
|
||||||
|
UINT32
|
||||||
|
EFIAPI
|
||||||
|
GetApicVersion (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Send a Fixed IPI to a specified target processor.
|
||||||
|
|
||||||
|
This function returns after the IPI has been accepted by the target processor.
|
||||||
|
|
||||||
|
@param ApicId The local APIC ID of the target processor.
|
||||||
|
@param Vector The vector number of the interrupt being sent.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
SendFixedIpi (
|
||||||
|
IN UINT32 ApicId,
|
||||||
|
IN UINT8 Vector
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Send a Fixed IPI to all processors excluding self.
|
||||||
|
|
||||||
|
This function returns after the IPI has been accepted by the target processors.
|
||||||
|
|
||||||
|
@param Vector The vector number of the interrupt being sent.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
SendFixedIpiAllExcludingSelf (
|
||||||
|
IN UINT8 Vector
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Send a SMI IPI to a specified target processor.
|
Send a SMI IPI to a specified target processor.
|
||||||
|
|
||||||
|
@ -173,18 +212,6 @@ ProgramVirtualWireMode (
|
||||||
VOID
|
VOID
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
Get the divide value from the DCR (Divide Configuration Register) by which
|
|
||||||
the processor's bus clock is divided to form the time base for the APIC timer.
|
|
||||||
|
|
||||||
@return The divide value is one of 1,2,4,8,16,32,64,128.
|
|
||||||
**/
|
|
||||||
UINTN
|
|
||||||
EFIAPI
|
|
||||||
GetApicTimerDivisor (
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Read the initial count value from the init-count register.
|
Read the initial count value from the init-count register.
|
||||||
|
|
||||||
|
@ -227,6 +254,21 @@ InitializeApicTimer (
|
||||||
IN UINT8 Vector
|
IN UINT8 Vector
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the state of the local APIC timer.
|
||||||
|
|
||||||
|
@param DivideValue Return the divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.
|
||||||
|
@param PeriodicMode Return the timer mode. If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.
|
||||||
|
@param Vector Return the timer interrupt vector number.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
GetApicTimerState (
|
||||||
|
OUT UINTN *DivideValue OPTIONAL,
|
||||||
|
OUT BOOLEAN *PeriodicMode OPTIONAL,
|
||||||
|
OUT UINT8 *Vector OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Enable the local APIC timer interrupt.
|
Enable the local APIC timer interrupt.
|
||||||
**/
|
**/
|
||||||
|
|
|
@ -30,15 +30,16 @@
|
||||||
//
|
//
|
||||||
// Definition for Local APIC registers and related values
|
// Definition for Local APIC registers and related values
|
||||||
//
|
//
|
||||||
#define XAPIC_ID_OFFSET 0x0
|
#define XAPIC_ID_OFFSET 0x20
|
||||||
|
#define XAPIC_VERSION_OFFSET 0x30
|
||||||
#define XAPIC_EOI_OFFSET 0x0b0
|
#define XAPIC_EOI_OFFSET 0x0b0
|
||||||
#define XAPIC_ICR_DFR_OFFSET 0x0e0
|
#define XAPIC_ICR_DFR_OFFSET 0x0e0
|
||||||
#define XAPIC_SPURIOUS_VECTOR_OFFSET 0x0f0
|
#define XAPIC_SPURIOUS_VECTOR_OFFSET 0x0f0
|
||||||
#define XAPIC_ICR_LOW_OFFSET 0x300
|
#define XAPIC_ICR_LOW_OFFSET 0x300
|
||||||
#define XAPIC_ICR_HIGH_OFFSET 0x310
|
#define XAPIC_ICR_HIGH_OFFSET 0x310
|
||||||
#define XAPIC_LVT_TIMER_OFFSET 0x320
|
#define XAPIC_LVT_TIMER_OFFSET 0x320
|
||||||
#define XAPIC_LINT0_VECTOR_OFFSET 0x350
|
#define XAPIC_LVT_LINT0_OFFSET 0x350
|
||||||
#define XAPIC_LINT1_VECTOR_OFFSET 0x360
|
#define XAPIC_LVT_LINT1_OFFSET 0x360
|
||||||
#define XAPIC_TIMER_INIT_COUNT_OFFSET 0x380
|
#define XAPIC_TIMER_INIT_COUNT_OFFSET 0x380
|
||||||
#define XAPIC_TIMER_CURRENT_COUNT_OFFSET 0x390
|
#define XAPIC_TIMER_CURRENT_COUNT_OFFSET 0x390
|
||||||
#define XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET 0x3E0
|
#define XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET 0x3E0
|
||||||
|
@ -71,6 +72,20 @@ typedef union {
|
||||||
UINT64 Uint64;
|
UINT64 Uint64;
|
||||||
} MSR_IA32_APIC_BASE;
|
} MSR_IA32_APIC_BASE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Local APIC Version Register.
|
||||||
|
//
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
UINT32 Version:8; ///< The version numbers of the local APIC.
|
||||||
|
UINT32 Reserved0:8; ///< Reserved.
|
||||||
|
UINT32 MaxLvtEntry:8; ///< Number of LVT entries minus 1.
|
||||||
|
UINT32 EoiBroadcastSuppression:1; ///< 1 if EOI-broadcast suppression supported.
|
||||||
|
UINT32 Reserved1:7; ///< Reserved.
|
||||||
|
} Bits;
|
||||||
|
UINT32 Uint32;
|
||||||
|
} LOCAL_APIC_VERSION;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Low half of Interrupt Command Register (ICR).
|
// Low half of Interrupt Command Register (ICR).
|
||||||
//
|
//
|
||||||
|
|
|
@ -202,6 +202,67 @@ GetApicId (
|
||||||
return ApicId;
|
return ApicId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the value of the local APIC version register.
|
||||||
|
|
||||||
|
@return the value of the local APIC version register.
|
||||||
|
**/
|
||||||
|
UINT32
|
||||||
|
EFIAPI
|
||||||
|
GetApicVersion (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return ReadLocalApicReg (XAPIC_VERSION_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Send a Fixed IPI to a specified target processor.
|
||||||
|
|
||||||
|
This function returns after the IPI has been accepted by the target processor.
|
||||||
|
|
||||||
|
@param ApicId The local APIC ID of the target processor.
|
||||||
|
@param Vector The vector number of the interrupt being sent.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
SendFixedIpi (
|
||||||
|
IN UINT32 ApicId,
|
||||||
|
IN UINT8 Vector
|
||||||
|
)
|
||||||
|
{
|
||||||
|
LOCAL_APIC_ICR_LOW IcrLow;
|
||||||
|
|
||||||
|
IcrLow.Uint32 = 0;
|
||||||
|
IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_FIXED;
|
||||||
|
IcrLow.Bits.Level = 1;
|
||||||
|
IcrLow.Bits.Vector = Vector;
|
||||||
|
SendIpi (IcrLow.Uint32, ApicId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Send a Fixed IPI to all processors excluding self.
|
||||||
|
|
||||||
|
This function returns after the IPI has been accepted by the target processors.
|
||||||
|
|
||||||
|
@param Vector The vector number of the interrupt being sent.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
SendFixedIpiAllExcludingSelf (
|
||||||
|
IN UINT8 Vector
|
||||||
|
)
|
||||||
|
{
|
||||||
|
LOCAL_APIC_ICR_LOW IcrLow;
|
||||||
|
|
||||||
|
IcrLow.Uint32 = 0;
|
||||||
|
IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_FIXED;
|
||||||
|
IcrLow.Bits.Level = 1;
|
||||||
|
IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
|
||||||
|
IcrLow.Bits.Vector = Vector;
|
||||||
|
SendIpi (IcrLow.Uint32, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Send a SMI IPI to a specified target processor.
|
Send a SMI IPI to a specified target processor.
|
||||||
|
|
||||||
|
@ -381,43 +442,22 @@ ProgramVirtualWireMode (
|
||||||
//
|
//
|
||||||
// Program the LINT0 vector entry as ExtInt. Not masked, edge, active high.
|
// Program the LINT0 vector entry as ExtInt. Not masked, edge, active high.
|
||||||
//
|
//
|
||||||
Lint.Uint32 = ReadLocalApicReg (XAPIC_LINT0_VECTOR_OFFSET);
|
Lint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET);
|
||||||
Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_EXTINT;
|
Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_EXTINT;
|
||||||
Lint.Bits.InputPinPolarity = 0;
|
Lint.Bits.InputPinPolarity = 0;
|
||||||
Lint.Bits.TriggerMode = 0;
|
Lint.Bits.TriggerMode = 0;
|
||||||
Lint.Bits.Mask = 0;
|
Lint.Bits.Mask = 0;
|
||||||
WriteLocalApicReg (XAPIC_LINT0_VECTOR_OFFSET, Lint.Uint32);
|
WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET, Lint.Uint32);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Program the LINT0 vector entry as NMI. Not masked, edge, active high.
|
// Program the LINT0 vector entry as NMI. Not masked, edge, active high.
|
||||||
//
|
//
|
||||||
Lint.Uint32 = ReadLocalApicReg (XAPIC_LINT1_VECTOR_OFFSET);
|
Lint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET);
|
||||||
Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_NMI;
|
Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_NMI;
|
||||||
Lint.Bits.InputPinPolarity = 0;
|
Lint.Bits.InputPinPolarity = 0;
|
||||||
Lint.Bits.TriggerMode = 0;
|
Lint.Bits.TriggerMode = 0;
|
||||||
Lint.Bits.Mask = 0;
|
Lint.Bits.Mask = 0;
|
||||||
WriteLocalApicReg (XAPIC_LINT1_VECTOR_OFFSET, Lint.Uint32);
|
WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET, Lint.Uint32);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Get the divide value from the DCR (Divide Configuration Register) by which
|
|
||||||
the processor's bus clock is divided to form the time base for the APIC timer.
|
|
||||||
|
|
||||||
@return The divide value is one of 1,2,4,8,16,32,64,128.
|
|
||||||
**/
|
|
||||||
UINTN
|
|
||||||
EFIAPI
|
|
||||||
GetApicTimerDivisor (
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
UINT32 DivideValue;
|
|
||||||
LOCAL_APIC_DCR Dcr;
|
|
||||||
|
|
||||||
Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET);
|
|
||||||
DivideValue = Dcr.Bits.DivideValue1 | (Dcr.Bits.DivideValue2 << 2);
|
|
||||||
DivideValue = (DivideValue + 1) & 0x7;
|
|
||||||
return ((UINTN)1) << DivideValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -510,6 +550,47 @@ InitializeApicTimer (
|
||||||
WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);
|
WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the state of the local APIC timer.
|
||||||
|
|
||||||
|
@param DivideValue Return the divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.
|
||||||
|
@param PeriodicMode Return the timer mode. If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.
|
||||||
|
@param Vector Return the timer interrupt vector number.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
GetApicTimerState (
|
||||||
|
OUT UINTN *DivideValue OPTIONAL,
|
||||||
|
OUT BOOLEAN *PeriodicMode OPTIONAL,
|
||||||
|
OUT UINT8 *Vector OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT32 Divisor;
|
||||||
|
LOCAL_APIC_DCR Dcr;
|
||||||
|
LOCAL_APIC_LVT_TIMER LvtTimer;
|
||||||
|
|
||||||
|
if (DivideValue != NULL) {
|
||||||
|
Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET);
|
||||||
|
Divisor = Dcr.Bits.DivideValue1 | (Dcr.Bits.DivideValue2 << 2);
|
||||||
|
Divisor = (Divisor + 1) & 0x7;
|
||||||
|
*DivideValue = ((UINTN)1) << Divisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PeriodicMode != NULL || Vector != NULL) {
|
||||||
|
LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
|
||||||
|
if (PeriodicMode != NULL) {
|
||||||
|
if (LvtTimer.Bits.TimerMode == 1) {
|
||||||
|
*PeriodicMode = TRUE;
|
||||||
|
} else {
|
||||||
|
*PeriodicMode = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Vector != NULL) {
|
||||||
|
*Vector = (UINT8) LvtTimer.Bits.Vector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Enable the local APIC timer interrupt.
|
Enable the local APIC timer interrupt.
|
||||||
**/
|
**/
|
||||||
|
|
|
@ -285,6 +285,67 @@ GetApicId (
|
||||||
return ApicId;
|
return ApicId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the value of the local APIC version register.
|
||||||
|
|
||||||
|
@return the value of the local APIC version register.
|
||||||
|
**/
|
||||||
|
UINT32
|
||||||
|
EFIAPI
|
||||||
|
GetApicVersion (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return ReadLocalApicReg (XAPIC_VERSION_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Send a Fixed IPI to a specified target processor.
|
||||||
|
|
||||||
|
This function returns after the IPI has been accepted by the target processor.
|
||||||
|
|
||||||
|
@param ApicId The local APIC ID of the target processor.
|
||||||
|
@param Vector The vector number of the interrupt being sent.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
SendFixedIpi (
|
||||||
|
IN UINT32 ApicId,
|
||||||
|
IN UINT8 Vector
|
||||||
|
)
|
||||||
|
{
|
||||||
|
LOCAL_APIC_ICR_LOW IcrLow;
|
||||||
|
|
||||||
|
IcrLow.Uint32 = 0;
|
||||||
|
IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_FIXED;
|
||||||
|
IcrLow.Bits.Level = 1;
|
||||||
|
IcrLow.Bits.Vector = Vector;
|
||||||
|
SendIpi (IcrLow.Uint32, ApicId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Send a Fixed IPI to all processors excluding self.
|
||||||
|
|
||||||
|
This function returns after the IPI has been accepted by the target processors.
|
||||||
|
|
||||||
|
@param Vector The vector number of the interrupt being sent.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
SendFixedIpiAllExcludingSelf (
|
||||||
|
IN UINT8 Vector
|
||||||
|
)
|
||||||
|
{
|
||||||
|
LOCAL_APIC_ICR_LOW IcrLow;
|
||||||
|
|
||||||
|
IcrLow.Uint32 = 0;
|
||||||
|
IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_FIXED;
|
||||||
|
IcrLow.Bits.Level = 1;
|
||||||
|
IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
|
||||||
|
IcrLow.Bits.Vector = Vector;
|
||||||
|
SendIpi (IcrLow.Uint32, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Send a SMI IPI to a specified target processor.
|
Send a SMI IPI to a specified target processor.
|
||||||
|
|
||||||
|
@ -464,43 +525,22 @@ ProgramVirtualWireMode (
|
||||||
//
|
//
|
||||||
// Program the LINT0 vector entry as ExtInt. Not masked, edge, active high.
|
// Program the LINT0 vector entry as ExtInt. Not masked, edge, active high.
|
||||||
//
|
//
|
||||||
Lint.Uint32 = ReadLocalApicReg (XAPIC_LINT0_VECTOR_OFFSET);
|
Lint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET);
|
||||||
Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_EXTINT;
|
Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_EXTINT;
|
||||||
Lint.Bits.InputPinPolarity = 0;
|
Lint.Bits.InputPinPolarity = 0;
|
||||||
Lint.Bits.TriggerMode = 0;
|
Lint.Bits.TriggerMode = 0;
|
||||||
Lint.Bits.Mask = 0;
|
Lint.Bits.Mask = 0;
|
||||||
WriteLocalApicReg (XAPIC_LINT0_VECTOR_OFFSET, Lint.Uint32);
|
WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET, Lint.Uint32);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Program the LINT0 vector entry as NMI. Not masked, edge, active high.
|
// Program the LINT0 vector entry as NMI. Not masked, edge, active high.
|
||||||
//
|
//
|
||||||
Lint.Uint32 = ReadLocalApicReg (XAPIC_LINT1_VECTOR_OFFSET);
|
Lint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET);
|
||||||
Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_NMI;
|
Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_NMI;
|
||||||
Lint.Bits.InputPinPolarity = 0;
|
Lint.Bits.InputPinPolarity = 0;
|
||||||
Lint.Bits.TriggerMode = 0;
|
Lint.Bits.TriggerMode = 0;
|
||||||
Lint.Bits.Mask = 0;
|
Lint.Bits.Mask = 0;
|
||||||
WriteLocalApicReg (XAPIC_LINT1_VECTOR_OFFSET, Lint.Uint32);
|
WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET, Lint.Uint32);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Get the divide value from the DCR (Divide Configuration Register) by which
|
|
||||||
the processor's bus clock is divided to form the time base for the APIC timer.
|
|
||||||
|
|
||||||
@return The divide value is one of 1,2,4,8,16,32,64,128.
|
|
||||||
**/
|
|
||||||
UINTN
|
|
||||||
EFIAPI
|
|
||||||
GetApicTimerDivisor (
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
UINT32 DivideValue;
|
|
||||||
LOCAL_APIC_DCR Dcr;
|
|
||||||
|
|
||||||
Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET);
|
|
||||||
DivideValue = Dcr.Bits.DivideValue1 | (Dcr.Bits.DivideValue2 << 2);
|
|
||||||
DivideValue = (DivideValue + 1) & 0x7;
|
|
||||||
return ((UINTN)1) << DivideValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -593,6 +633,47 @@ InitializeApicTimer (
|
||||||
WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);
|
WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the state of the local APIC timer.
|
||||||
|
|
||||||
|
@param DivideValue Return the divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.
|
||||||
|
@param PeriodicMode Return the timer mode. If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.
|
||||||
|
@param Vector Return the timer interrupt vector number.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
GetApicTimerState (
|
||||||
|
OUT UINTN *DivideValue OPTIONAL,
|
||||||
|
OUT BOOLEAN *PeriodicMode OPTIONAL,
|
||||||
|
OUT UINT8 *Vector OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT32 Divisor;
|
||||||
|
LOCAL_APIC_DCR Dcr;
|
||||||
|
LOCAL_APIC_LVT_TIMER LvtTimer;
|
||||||
|
|
||||||
|
if (DivideValue != NULL) {
|
||||||
|
Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET);
|
||||||
|
Divisor = Dcr.Bits.DivideValue1 | (Dcr.Bits.DivideValue2 << 2);
|
||||||
|
Divisor = (Divisor + 1) & 0x7;
|
||||||
|
*DivideValue = ((UINTN)1) << Divisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PeriodicMode != NULL || Vector != NULL) {
|
||||||
|
LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
|
||||||
|
if (PeriodicMode != NULL) {
|
||||||
|
if (LvtTimer.Bits.TimerMode == 1) {
|
||||||
|
*PeriodicMode = TRUE;
|
||||||
|
} else {
|
||||||
|
*PeriodicMode = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Vector != NULL) {
|
||||||
|
*Vector = (UINT8) LvtTimer.Bits.Vector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Enable the local APIC timer interrupt.
|
Enable the local APIC timer interrupt.
|
||||||
**/
|
**/
|
||||||
|
|
Loading…
Reference in New Issue