Home | History | Annotate | Download | only in BaseIoApicLib
      1 /** @file
      2   I/O APIC library.
      3 
      4   I/O APIC library assumes I/O APIC is enabled. It does not
      5   handles cases where I/O APIC is disabled.
      6 
      7   Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
      8   This program and the accompanying materials
      9   are licensed and made available under the terms and conditions of the BSD License
     10   which accompanies this distribution.  The full text of the license may be found at
     11   http://opensource.org/licenses/bsd-license.php
     12 
     13   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     14   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     15 
     16 **/
     17 
     18 #include <Base.h>
     19 
     20 #include <Library/IoApicLib.h>
     21 
     22 #include <Library/DebugLib.h>
     23 #include <Library/PcdLib.h>
     24 #include <Library/IoLib.h>
     25 #include <Library/LocalApicLib.h>
     26 
     27 #include <Register/IoApic.h>
     28 
     29 /**
     30   Read a 32-bit I/O APIC register.
     31 
     32   If Index is >= 0x100, then ASSERT().
     33 
     34   @param  Index  Specifies the I/O APIC register to read.
     35 
     36   @return  The 32-bit value read from the I/O APIC register specified by Index.
     37 **/
     38 UINT32
     39 EFIAPI
     40 IoApicRead (
     41   IN UINTN  Index
     42   )
     43 {
     44   ASSERT (Index < 0x100);
     45   MmioWrite8 (PcdGet32 (PcdIoApicBaseAddress) + IOAPIC_INDEX_OFFSET, (UINT8)Index);
     46   return MmioRead32 (PcdGet32 (PcdIoApicBaseAddress) + IOAPIC_DATA_OFFSET);
     47 }
     48 
     49 /**
     50   Write a 32-bit I/O APIC register.
     51 
     52   If Index is >= 0x100, then ASSERT().
     53 
     54   @param  Index  Specifies the I/O APIC register to write.
     55   @param  Value  Specifies the value to write to the I/O APIC register specified by Index.
     56 
     57   @return  The 32-bit value written to I/O APIC register specified by Index.
     58 **/
     59 UINT32
     60 EFIAPI
     61 IoApicWrite (
     62   IN UINTN   Index,
     63   IN UINT32  Value
     64   )
     65 {
     66   ASSERT (Index < 0x100);
     67   MmioWrite8 (PcdGet32 (PcdIoApicBaseAddress) + IOAPIC_INDEX_OFFSET, (UINT8)Index);
     68   return MmioWrite32 (PcdGet32 (PcdIoApicBaseAddress) + IOAPIC_DATA_OFFSET, Value);
     69 }
     70 
     71 /**
     72   Set the interrupt mask of an I/O APIC interrupt.
     73 
     74   If Irq is larger than the maximum number I/O APIC redirection entries, then ASSERT().
     75 
     76   @param  Irq     Specifies the I/O APIC interrupt to enable or disable.
     77   @param  Enable  If TRUE, then enable the I/O APIC interrupt specified by Irq.
     78                   If FALSE, then disable the I/O APIC interrupt specified by Irq.
     79 **/
     80 VOID
     81 EFIAPI
     82 IoApicEnableInterrupt (
     83   IN UINTN    Irq,
     84   IN BOOLEAN  Enable
     85   )
     86 {
     87   IO_APIC_VERSION_REGISTER         Version;
     88   IO_APIC_REDIRECTION_TABLE_ENTRY  Entry;
     89 
     90   Version.Uint32 = IoApicRead (IO_APIC_VERSION_REGISTER_INDEX);
     91   ASSERT (Version.Bits.MaximumRedirectionEntry < 0xF0);
     92   ASSERT (Irq <= Version.Bits.MaximumRedirectionEntry);
     93 
     94   Entry.Uint32.Low = IoApicRead (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2);
     95   Entry.Bits.Mask = Enable ? 0 : 1;
     96   IoApicWrite (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2, Entry.Uint32.Low);
     97 }
     98 
     99 /**
    100   Configures an I/O APIC interrupt.
    101 
    102   Configure an I/O APIC Redirection Table Entry to deliver an interrupt in physical
    103   mode to the Local APIC of the currntly executing CPU.  The default state of the
    104   entry is for the interrupt to be disabled (masked).  IoApicEnableInterrupts() must
    105   be used to enable(unmask) the I/O APIC Interrupt.
    106 
    107   If Irq is larger than the maximum number I/O APIC redirection entries, then ASSERT().
    108   If Vector >= 0x100, then ASSERT().
    109   If DeliveryMode is not supported, then ASSERT().
    110 
    111   @param  Irq             Specifies the I/O APIC interrupt to initialize.
    112   @param  Vector          The 8-bit interrupt vector associated with the I/O APIC
    113                           Interrupt.  Must be in the range 0x10..0xFE.
    114   @param  DeliveryMode    A 3-bit value that specifies how the recept of the I/O APIC
    115                           interrupt is handled.  The only supported values are:
    116                             0: IO_APIC_DELIVERY_MODE_FIXED
    117                             1: IO_APIC_DELIVERY_MODE_LOWEST_PRIORITY
    118                             2: IO_APIC_DELIVERY_MODE_SMI
    119                             4: IO_APIC_DELIVERY_MODE_NMI
    120                             5: IO_APIC_DELIVERY_MODE_INIT
    121                             7: IO_APIC_DELIVERY_MODE_EXTINT
    122   @param  LevelTriggered  TRUE specifies a level triggered interrupt.
    123                           FALSE specifies an edge triggered interrupt.
    124   @param  AssertionLevel  TRUE specified an active high interrupt.
    125                           FALSE specifies an active low interrupt.
    126 **/
    127 VOID
    128 EFIAPI
    129 IoApicConfigureInterrupt (
    130   IN UINTN    Irq,
    131   IN UINTN    Vector,
    132   IN UINTN    DeliveryMode,
    133   IN BOOLEAN  LevelTriggered,
    134   IN BOOLEAN  AssertionLevel
    135   )
    136 {
    137   IO_APIC_VERSION_REGISTER         Version;
    138   IO_APIC_REDIRECTION_TABLE_ENTRY  Entry;
    139 
    140   Version.Uint32 = IoApicRead (IO_APIC_VERSION_REGISTER_INDEX);
    141   ASSERT (Version.Bits.MaximumRedirectionEntry < 0xF0);
    142   ASSERT (Irq <= Version.Bits.MaximumRedirectionEntry);
    143   ASSERT (Vector <= 0xFF);
    144   ASSERT (DeliveryMode < 8 && DeliveryMode != 6 && DeliveryMode != 3);
    145 
    146   Entry.Uint32.Low = IoApicRead (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2);
    147   Entry.Bits.Vector          = (UINT8)Vector;
    148   Entry.Bits.DeliveryMode    = (UINT32)DeliveryMode;
    149   Entry.Bits.DestinationMode = 0;
    150   Entry.Bits.Polarity        = AssertionLevel ? 0 : 1;
    151   Entry.Bits.TriggerMode     = LevelTriggered ? 1 : 0;
    152   Entry.Bits.Mask            = 1;
    153   IoApicWrite (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2, Entry.Uint32.Low);
    154 
    155   Entry.Uint32.High = IoApicRead (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2 + 1);
    156   Entry.Bits.DestinationID = GetApicId ();
    157   IoApicWrite (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2 + 1, Entry.Uint32.High);
    158 }
    159