1 /*++ 2 3 Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR> 4 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 9 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. 12 13 --*/ 14 15 #include "ArmGicDxe.h" 16 17 VOID 18 EFIAPI 19 IrqInterruptHandler ( 20 IN EFI_EXCEPTION_TYPE InterruptType, 21 IN EFI_SYSTEM_CONTEXT SystemContext 22 ); 23 24 VOID 25 EFIAPI 26 ExitBootServicesEvent ( 27 IN EFI_EVENT Event, 28 IN VOID *Context 29 ); 30 31 // 32 // Making this global saves a few bytes in image size 33 // 34 EFI_HANDLE gHardwareInterruptHandle = NULL; 35 36 // 37 // Notifications 38 // 39 EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL; 40 41 // Maximum Number of Interrupts 42 UINTN mGicNumInterrupts = 0; 43 44 HARDWARE_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 **/ 57 EFI_STATUS 58 EFIAPI 59 RegisterInterruptSource ( 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 88 EFI_STATUS 89 InstallAndRegisterInterruptService ( 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 } 142