1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
/** @file
I/O APIC library.
I/O APIC library assumes I/O APIC is enabled. It does not
handles cases where I/O APIC is disabled.
Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Base.h>
#include <Library/IoApicLib.h>
#include <Library/DebugLib.h>
#include <Library/PcdLib.h>
#include <Library/IoLib.h>
#include <Library/LocalApicLib.h>
#include <Register/IoApic.h>
/**
Read a 32-bit I/O APIC register.
If Index is >= 0x100, then ASSERT().
@param Index Specifies the I/O APIC register to read.
@return The 32-bit value read from the I/O APIC register specified by Index.
**/
UINT32
EFIAPI
IoApicRead (
IN UINTN Index
)
{
ASSERT (Index < 0x100);
MmioWrite8 (PcdGet32 (PcdIoApicBaseAddress) + IOAPIC_INDEX_OFFSET, (UINT8)Index);
return MmioRead32 (PcdGet32 (PcdIoApicBaseAddress) + IOAPIC_DATA_OFFSET);
}
/**
Write a 32-bit I/O APIC register.
If Index is >= 0x100, then ASSERT().
@param Index Specifies the I/O APIC register to write.
@param Value Specifies the value to write to the I/O APIC register specified by Index.
@return The 32-bit value written to I/O APIC register specified by Index.
**/
UINT32
EFIAPI
IoApicWrite (
IN UINTN Index,
IN UINT32 Value
)
{
ASSERT (Index < 0x100);
MmioWrite8 (PcdGet32 (PcdIoApicBaseAddress) + IOAPIC_INDEX_OFFSET, (UINT8)Index);
return MmioWrite32 (PcdGet32 (PcdIoApicBaseAddress) + IOAPIC_DATA_OFFSET, Value);
}
/**
Set the interrupt mask of an I/O APIC interrupt.
If Irq is larger than the maximum number I/O APIC redirection entries, then ASSERT().
@param Irq Specifies the I/O APIC interrupt to enable or disable.
@param Enable If TRUE, then enable the I/O APIC interrupt specified by Irq.
If FALSE, then disable the I/O APIC interrupt specified by Irq.
**/
VOID
EFIAPI
IoApicEnableInterrupt (
IN UINTN Irq,
IN BOOLEAN Enable
)
{
IO_APIC_VERSION_REGISTER Version;
IO_APIC_REDIRECTION_TABLE_ENTRY Entry;
Version.Uint32 = IoApicRead (IO_APIC_VERSION_REGISTER_INDEX);
ASSERT (Version.Bits.MaximumRedirectionEntry < 0xF0);
ASSERT (Irq <= Version.Bits.MaximumRedirectionEntry);
Entry.Uint32.Low = IoApicRead (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2);
Entry.Bits.Mask = Enable ? 0 : 1;
IoApicWrite (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2, Entry.Uint32.Low);
}
/**
Configures an I/O APIC interrupt.
Configure an I/O APIC Redirection Table Entry to deliver an interrupt in physical
mode to the Local APIC of the currently executing CPU. The default state of the
entry is for the interrupt to be disabled (masked). IoApicEnableInterrupts() must
be used to enable(unmask) the I/O APIC Interrupt.
If Irq is larger than the maximum number I/O APIC redirection entries, then ASSERT().
If Vector >= 0x100, then ASSERT().
If DeliveryMode is not supported, then ASSERT().
@param Irq Specifies the I/O APIC interrupt to initialize.
@param Vector The 8-bit interrupt vector associated with the I/O APIC
Interrupt. Must be in the range 0x10..0xFE.
@param DeliveryMode A 3-bit value that specifies how the recept of the I/O APIC
interrupt is handled. The only supported values are:
0: IO_APIC_DELIVERY_MODE_FIXED
1: IO_APIC_DELIVERY_MODE_LOWEST_PRIORITY
2: IO_APIC_DELIVERY_MODE_SMI
4: IO_APIC_DELIVERY_MODE_NMI
5: IO_APIC_DELIVERY_MODE_INIT
7: IO_APIC_DELIVERY_MODE_EXTINT
@param LevelTriggered TRUE specifies a level triggered interrupt.
FALSE specifies an edge triggered interrupt.
@param AssertionLevel TRUE specified an active high interrupt.
FALSE specifies an active low interrupt.
**/
VOID
EFIAPI
IoApicConfigureInterrupt (
IN UINTN Irq,
IN UINTN Vector,
IN UINTN DeliveryMode,
IN BOOLEAN LevelTriggered,
IN BOOLEAN AssertionLevel
)
{
IO_APIC_VERSION_REGISTER Version;
IO_APIC_REDIRECTION_TABLE_ENTRY Entry;
Version.Uint32 = IoApicRead (IO_APIC_VERSION_REGISTER_INDEX);
ASSERT (Version.Bits.MaximumRedirectionEntry < 0xF0);
ASSERT (Irq <= Version.Bits.MaximumRedirectionEntry);
ASSERT (Vector <= 0xFF);
ASSERT (DeliveryMode < 8 && DeliveryMode != 6 && DeliveryMode != 3);
Entry.Uint32.Low = IoApicRead (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2);
Entry.Bits.Vector = (UINT8)Vector;
Entry.Bits.DeliveryMode = (UINT32)DeliveryMode;
Entry.Bits.DestinationMode = 0;
Entry.Bits.Polarity = AssertionLevel ? 0 : 1;
Entry.Bits.TriggerMode = LevelTriggered ? 1 : 0;
Entry.Bits.Mask = 1;
IoApicWrite (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2, Entry.Uint32.Low);
Entry.Uint32.High = IoApicRead (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2 + 1);
Entry.Bits.DestinationID = GetApicId ();
IoApicWrite (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2 + 1, Entry.Uint32.High);
}
|