Vishal Bhoj | 82c8071 | 2015-12-15 21:13:33 +0530 | [diff] [blame^] | 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 | }
|