blob: a9ccef5e1c9a1dde987b9ed8112f34b210606bf7 [file] [log] [blame]
Vishal Bhoj82c80712015-12-15 21:13:33 +05301/*++
2
3Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>
4
5This program and the accompanying materials
6are licensed and made available under the terms and conditions of the BSD License
7which accompanies this distribution. The full text of the license may be found at
8http://opensource.org/licenses/bsd-license.php
9
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13--*/
14
15#include "ArmGicDxe.h"
16
17VOID
18EFIAPI
19IrqInterruptHandler (
20 IN EFI_EXCEPTION_TYPE InterruptType,
21 IN EFI_SYSTEM_CONTEXT SystemContext
22 );
23
24VOID
25EFIAPI
26ExitBootServicesEvent (
27 IN EFI_EVENT Event,
28 IN VOID *Context
29 );
30
31//
32// Making this global saves a few bytes in image size
33//
34EFI_HANDLE gHardwareInterruptHandle = NULL;
35
36//
37// Notifications
38//
39EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
40
41// Maximum Number of Interrupts
42UINTN mGicNumInterrupts = 0;
43
44HARDWARE_INTERRUPT_HANDLER *gRegisteredInterruptHandlers = NULL;
45
46/**
47 Register Handler for the specified interrupt source.
48
49 @param This Instance pointer for this protocol
50 @param Source Hardware source of the interrupt
51 @param Handler Callback for interrupt. NULL to unregister
52
53 @retval EFI_SUCCESS Source was updated to support Handler.
54 @retval EFI_DEVICE_ERROR Hardware could not be programmed.
55
56**/
57EFI_STATUS
58EFIAPI
59RegisterInterruptSource (
60 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
61 IN HARDWARE_INTERRUPT_SOURCE Source,
62 IN HARDWARE_INTERRUPT_HANDLER Handler
63 )
64{
65 if (Source > mGicNumInterrupts) {
66 ASSERT(FALSE);
67 return EFI_UNSUPPORTED;
68 }
69
70 if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {
71 return EFI_INVALID_PARAMETER;
72 }
73
74 if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {
75 return EFI_ALREADY_STARTED;
76 }
77
78 gRegisteredInterruptHandlers[Source] = Handler;
79
80 // If the interrupt handler is unregistered then disable the interrupt
81 if (NULL == Handler){
82 return This->DisableInterruptSource (This, Source);
83 } else {
84 return This->EnableInterruptSource (This, Source);
85 }
86}
87
88EFI_STATUS
89InstallAndRegisterInterruptService (
90 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *InterruptProtocol,
91 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler,
92 IN EFI_EVENT_NOTIFY ExitBootServicesEvent
93 )
94{
95 EFI_STATUS Status;
96 EFI_CPU_ARCH_PROTOCOL *Cpu;
97
98 // Initialize the array for the Interrupt Handlers
99 gRegisteredInterruptHandlers = (HARDWARE_INTERRUPT_HANDLER*)AllocateZeroPool (sizeof(HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts);
100 if (gRegisteredInterruptHandlers == NULL) {
101 return EFI_OUT_OF_RESOURCES;
102 }
103
104 Status = gBS->InstallMultipleProtocolInterfaces (
105 &gHardwareInterruptHandle,
106 &gHardwareInterruptProtocolGuid, InterruptProtocol,
107 NULL
108 );
109 if (EFI_ERROR (Status)) {
110 return Status;
111 }
112
113 //
114 // Get the CPU protocol that this driver requires.
115 //
116 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
117 if (EFI_ERROR (Status)) {
118 return Status;
119 }
120
121 //
122 // Unregister the default exception handler.
123 //
124 Status = Cpu->RegisterInterruptHandler (Cpu, ARM_ARCH_EXCEPTION_IRQ, NULL);
125 if (EFI_ERROR (Status)) {
126 return Status;
127 }
128
129 //
130 // Register to receive interrupts
131 //
132 Status = Cpu->RegisterInterruptHandler (Cpu, ARM_ARCH_EXCEPTION_IRQ, InterruptHandler);
133 if (EFI_ERROR (Status)) {
134 return Status;
135 }
136
137 // Register for an ExitBootServicesEvent
138 Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
139
140 return Status;
141}