3 Copyright (c) 2013-2017, ARM Ltd. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "ArmGicDxe.h"
20 IN EFI_EXCEPTION_TYPE InterruptType
,
21 IN EFI_SYSTEM_CONTEXT SystemContext
26 ExitBootServicesEvent (
31 // Making this global saves a few bytes in image size
32 EFI_HANDLE gHardwareInterruptHandle
= NULL
;
35 EFI_EVENT EfiExitBootServicesEvent
= (EFI_EVENT
)NULL
;
37 // Maximum Number of Interrupts
38 UINTN mGicNumInterrupts
= 0;
40 HARDWARE_INTERRUPT_HANDLER
*gRegisteredInterruptHandlers
= NULL
;
44 Calculate GICD_ICFGRn base address and corresponding bit
45 field Int_config[1] of the GIC distributor register.
47 @param Source Hardware source of the interrupt.
48 @param RegAddress Corresponding GICD_ICFGRn base address.
49 @param Config1Bit Bit number of F Int_config[1] bit in the register.
51 @retval EFI_SUCCESS Source interrupt supported.
52 @retval EFI_UNSUPPORTED Source interrupt is not supported.
55 GicGetDistributorIcfgBaseAndBit (
56 IN HARDWARE_INTERRUPT_SOURCE Source
,
57 OUT UINTN
*RegAddress
,
64 if (Source
>= mGicNumInterrupts
) {
65 ASSERT(Source
< mGicNumInterrupts
);
66 return EFI_UNSUPPORTED
;
69 RegIndex
= Source
/ ARM_GIC_ICDICFR_F_STRIDE
; // NOTE: truncation is significant
70 Field
= Source
% ARM_GIC_ICDICFR_F_STRIDE
;
71 *RegAddress
= PcdGet64 (PcdGicDistributorBase
)
73 + (ARM_GIC_ICDICFR_BYTES
* RegIndex
);
74 *Config1Bit
= ((Field
* ARM_GIC_ICDICFR_F_WIDTH
)
75 + ARM_GIC_ICDICFR_F_CONFIG1_BIT
);
83 Register Handler for the specified interrupt source.
85 @param This Instance pointer for this protocol
86 @param Source Hardware source of the interrupt
87 @param Handler Callback for interrupt. NULL to unregister
89 @retval EFI_SUCCESS Source was updated to support Handler.
90 @retval EFI_DEVICE_ERROR Hardware could not be programmed.
95 RegisterInterruptSource (
96 IN EFI_HARDWARE_INTERRUPT_PROTOCOL
*This
,
97 IN HARDWARE_INTERRUPT_SOURCE Source
,
98 IN HARDWARE_INTERRUPT_HANDLER Handler
101 if (Source
>= mGicNumInterrupts
) {
103 return EFI_UNSUPPORTED
;
106 if ((Handler
== NULL
) && (gRegisteredInterruptHandlers
[Source
] == NULL
)) {
107 return EFI_INVALID_PARAMETER
;
110 if ((Handler
!= NULL
) && (gRegisteredInterruptHandlers
[Source
] != NULL
)) {
111 return EFI_ALREADY_STARTED
;
114 gRegisteredInterruptHandlers
[Source
] = Handler
;
116 // If the interrupt handler is unregistered then disable the interrupt
117 if (NULL
== Handler
){
118 return This
->DisableInterruptSource (This
, Source
);
120 return This
->EnableInterruptSource (This
, Source
);
124 STATIC VOID
*mCpuArchProtocolNotifyEventRegistration
;
129 CpuArchEventProtocolNotify (
134 EFI_CPU_ARCH_PROTOCOL
*Cpu
;
137 // Get the CPU protocol that this driver requires.
138 Status
= gBS
->LocateProtocol (&gEfiCpuArchProtocolGuid
, NULL
, (VOID
**)&Cpu
);
139 if (EFI_ERROR (Status
)) {
143 // Unregister the default exception handler.
144 Status
= Cpu
->RegisterInterruptHandler (Cpu
, ARM_ARCH_EXCEPTION_IRQ
, NULL
);
145 if (EFI_ERROR (Status
)) {
146 DEBUG ((DEBUG_ERROR
, "%a: Cpu->RegisterInterruptHandler() - %r\n",
147 __FUNCTION__
, Status
));
151 // Register to receive interrupts
152 Status
= Cpu
->RegisterInterruptHandler (Cpu
, ARM_ARCH_EXCEPTION_IRQ
,
154 if (EFI_ERROR (Status
)) {
155 DEBUG ((DEBUG_ERROR
, "%a: Cpu->RegisterInterruptHandler() - %r\n",
156 __FUNCTION__
, Status
));
159 gBS
->CloseEvent (Event
);
163 InstallAndRegisterInterruptService (
164 IN EFI_HARDWARE_INTERRUPT_PROTOCOL
*InterruptProtocol
,
165 IN EFI_HARDWARE_INTERRUPT2_PROTOCOL
*Interrupt2Protocol
,
166 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
,
167 IN EFI_EVENT_NOTIFY ExitBootServicesEvent
171 CONST UINTN RihArraySize
=
172 (sizeof(HARDWARE_INTERRUPT_HANDLER
) * mGicNumInterrupts
);
174 // Initialize the array for the Interrupt Handlers
175 gRegisteredInterruptHandlers
= AllocateZeroPool (RihArraySize
);
176 if (gRegisteredInterruptHandlers
== NULL
) {
177 return EFI_OUT_OF_RESOURCES
;
180 Status
= gBS
->InstallMultipleProtocolInterfaces (
181 &gHardwareInterruptHandle
,
182 &gHardwareInterruptProtocolGuid
,
184 &gHardwareInterrupt2ProtocolGuid
,
188 if (EFI_ERROR (Status
)) {
193 // Install the interrupt handler as soon as the CPU arch protocol appears.
195 EfiCreateProtocolNotifyEvent (
196 &gEfiCpuArchProtocolGuid
,
198 CpuArchEventProtocolNotify
,
200 &mCpuArchProtocolNotifyEventRegistration
);
202 // Register for an ExitBootServicesEvent
203 Status
= gBS
->CreateEvent (
204 EVT_SIGNAL_EXIT_BOOT_SERVICES
,
206 ExitBootServicesEvent
,
208 &EfiExitBootServicesEvent