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
);
125 InstallAndRegisterInterruptService (
126 IN EFI_HARDWARE_INTERRUPT_PROTOCOL
*InterruptProtocol
,
127 IN EFI_HARDWARE_INTERRUPT2_PROTOCOL
*Interrupt2Protocol
,
128 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
,
129 IN EFI_EVENT_NOTIFY ExitBootServicesEvent
133 EFI_CPU_ARCH_PROTOCOL
*Cpu
;
134 CONST UINTN RihArraySize
=
135 (sizeof(HARDWARE_INTERRUPT_HANDLER
) * mGicNumInterrupts
);
137 // Initialize the array for the Interrupt Handlers
138 gRegisteredInterruptHandlers
= AllocateZeroPool (RihArraySize
);
139 if (gRegisteredInterruptHandlers
== NULL
) {
140 return EFI_OUT_OF_RESOURCES
;
143 Status
= gBS
->InstallMultipleProtocolInterfaces (
144 &gHardwareInterruptHandle
,
145 &gHardwareInterruptProtocolGuid
,
147 &gHardwareInterrupt2ProtocolGuid
,
151 if (EFI_ERROR (Status
)) {
155 // Get the CPU protocol that this driver requires.
156 Status
= gBS
->LocateProtocol (&gEfiCpuArchProtocolGuid
, NULL
, (VOID
**)&Cpu
);
157 if (EFI_ERROR (Status
)) {
161 // Unregister the default exception handler.
162 Status
= Cpu
->RegisterInterruptHandler (Cpu
, ARM_ARCH_EXCEPTION_IRQ
, NULL
);
163 if (EFI_ERROR (Status
)) {
167 // Register to receive interrupts
168 Status
= Cpu
->RegisterInterruptHandler (
170 ARM_ARCH_EXCEPTION_IRQ
,
173 if (EFI_ERROR (Status
)) {
177 // Register for an ExitBootServicesEvent
178 Status
= gBS
->CreateEvent (
179 EVT_SIGNAL_EXIT_BOOT_SERVICES
,
181 ExitBootServicesEvent
,
183 &EfiExitBootServicesEvent