mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-11-04 06:52:16 +00:00 
			
		
		
		
	mGicNumInterrupts is the total number of interrupts, so the interrupt ID equal to mGicNumInterrupts is also invalid. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Heyi Guo <heyi.guo@linaro.org> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
		
			
				
	
	
		
			142 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
 | 
						|
Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>
 | 
						|
 | 
						|
This program and the accompanying materials
 | 
						|
are licensed and made available under the terms and conditions of the BSD License
 | 
						|
which accompanies this distribution.  The full text of the license may be found at
 | 
						|
http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
#include "ArmGicDxe.h"
 | 
						|
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
IrqInterruptHandler (
 | 
						|
  IN EFI_EXCEPTION_TYPE           InterruptType,
 | 
						|
  IN EFI_SYSTEM_CONTEXT           SystemContext
 | 
						|
  );
 | 
						|
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
ExitBootServicesEvent (
 | 
						|
  IN EFI_EVENT  Event,
 | 
						|
  IN VOID       *Context
 | 
						|
  );
 | 
						|
 | 
						|
//
 | 
						|
// Making this global saves a few bytes in image size
 | 
						|
//
 | 
						|
EFI_HANDLE  gHardwareInterruptHandle = NULL;
 | 
						|
 | 
						|
//
 | 
						|
// Notifications
 | 
						|
//
 | 
						|
EFI_EVENT EfiExitBootServicesEvent      = (EFI_EVENT)NULL;
 | 
						|
 | 
						|
// Maximum Number of Interrupts
 | 
						|
UINTN mGicNumInterrupts                 = 0;
 | 
						|
 | 
						|
HARDWARE_INTERRUPT_HANDLER  *gRegisteredInterruptHandlers = NULL;
 | 
						|
 | 
						|
/**
 | 
						|
  Register Handler for the specified interrupt source.
 | 
						|
 | 
						|
  @param This     Instance pointer for this protocol
 | 
						|
  @param Source   Hardware source of the interrupt
 | 
						|
  @param Handler  Callback for interrupt. NULL to unregister
 | 
						|
 | 
						|
  @retval EFI_SUCCESS Source was updated to support Handler.
 | 
						|
  @retval EFI_DEVICE_ERROR  Hardware could not be programmed.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
RegisterInterruptSource (
 | 
						|
  IN EFI_HARDWARE_INTERRUPT_PROTOCOL    *This,
 | 
						|
  IN HARDWARE_INTERRUPT_SOURCE          Source,
 | 
						|
  IN HARDWARE_INTERRUPT_HANDLER         Handler
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (Source >= mGicNumInterrupts) {
 | 
						|
    ASSERT(FALSE);
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {
 | 
						|
    return EFI_ALREADY_STARTED;
 | 
						|
  }
 | 
						|
 | 
						|
  gRegisteredInterruptHandlers[Source] = Handler;
 | 
						|
 | 
						|
  // If the interrupt handler is unregistered then disable the interrupt
 | 
						|
  if (NULL == Handler){
 | 
						|
    return This->DisableInterruptSource (This, Source);
 | 
						|
  } else {
 | 
						|
    return This->EnableInterruptSource (This, Source);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
InstallAndRegisterInterruptService (
 | 
						|
  IN EFI_HARDWARE_INTERRUPT_PROTOCOL   *InterruptProtocol,
 | 
						|
  IN EFI_CPU_INTERRUPT_HANDLER          InterruptHandler,
 | 
						|
  IN EFI_EVENT_NOTIFY                   ExitBootServicesEvent
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS               Status;
 | 
						|
  EFI_CPU_ARCH_PROTOCOL   *Cpu;
 | 
						|
 | 
						|
  // Initialize the array for the Interrupt Handlers
 | 
						|
  gRegisteredInterruptHandlers = (HARDWARE_INTERRUPT_HANDLER*)AllocateZeroPool (sizeof(HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts);
 | 
						|
  if (gRegisteredInterruptHandlers == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                  &gHardwareInterruptHandle,
 | 
						|
                  &gHardwareInterruptProtocolGuid, InterruptProtocol,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the CPU protocol that this driver requires.
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Unregister the default exception handler.
 | 
						|
  //
 | 
						|
  Status = Cpu->RegisterInterruptHandler (Cpu, ARM_ARCH_EXCEPTION_IRQ, NULL);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Register to receive interrupts
 | 
						|
  //
 | 
						|
  Status = Cpu->RegisterInterruptHandler (Cpu, ARM_ARCH_EXCEPTION_IRQ, InterruptHandler);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Register for an ExitBootServicesEvent
 | 
						|
  Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 |