Home | History | Annotate | Download | only in 8259InterruptControllerDxe
      1 /** @file
      2   This contains the installation function for the driver.
      3 
      4 Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
      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 "8259.h"
     16 
     17 //
     18 // Global for the Legacy 8259 Protocol that is produced by this driver
     19 //
     20 EFI_LEGACY_8259_PROTOCOL  mInterrupt8259 = {
     21   Interrupt8259SetVectorBase,
     22   Interrupt8259GetMask,
     23   Interrupt8259SetMask,
     24   Interrupt8259SetMode,
     25   Interrupt8259GetVector,
     26   Interrupt8259EnableIrq,
     27   Interrupt8259DisableIrq,
     28   Interrupt8259GetInterruptLine,
     29   Interrupt8259EndOfInterrupt
     30 };
     31 
     32 //
     33 // Global for the handle that the Legacy 8259 Protocol is installed
     34 //
     35 EFI_HANDLE                m8259Handle             = NULL;
     36 
     37 UINT8                     mMasterBase             = 0xff;
     38 UINT8                     mSlaveBase              = 0xff;
     39 EFI_8259_MODE             mMode                   = Efi8259ProtectedMode;
     40 UINT16                    mProtectedModeMask      = 0xffff;
     41 UINT16                    mLegacyModeMask;
     42 UINT16                    mProtectedModeEdgeLevel = 0x0000;
     43 UINT16                    mLegacyModeEdgeLevel;
     44 
     45 //
     46 // Worker Functions
     47 //
     48 
     49 /**
     50   Write to mask and edge/level triggered registers of master and slave PICs.
     51 
     52   @param[in]  Mask       low byte for master PIC mask register,
     53                          high byte for slave PIC mask register.
     54   @param[in]  EdgeLevel  low byte for master PIC edge/level triggered register,
     55                          high byte for slave PIC edge/level triggered register.
     56 
     57 **/
     58 VOID
     59 Interrupt8259WriteMask (
     60   IN UINT16  Mask,
     61   IN UINT16  EdgeLevel
     62   )
     63 {
     64   IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, (UINT8) Mask);
     65   IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, (UINT8) (Mask >> 8));
     66   IoWrite8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER, (UINT8) EdgeLevel);
     67   IoWrite8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE, (UINT8) (EdgeLevel >> 8));
     68 }
     69 
     70 /**
     71   Read from mask and edge/level triggered registers of master and slave PICs.
     72 
     73   @param[out]  Mask       low byte for master PIC mask register,
     74                           high byte for slave PIC mask register.
     75   @param[out]  EdgeLevel  low byte for master PIC edge/level triggered register,
     76                           high byte for slave PIC edge/level triggered register.
     77 
     78 **/
     79 VOID
     80 Interrupt8259ReadMask (
     81   OUT UINT16  *Mask,
     82   OUT UINT16  *EdgeLevel
     83   )
     84 {
     85   UINT16  MasterValue;
     86   UINT16  SlaveValue;
     87 
     88   if (Mask != NULL) {
     89     MasterValue = IoRead8 (LEGACY_8259_MASK_REGISTER_MASTER);
     90     SlaveValue  = IoRead8 (LEGACY_8259_MASK_REGISTER_SLAVE);
     91 
     92     *Mask = (UINT16) (MasterValue | (SlaveValue << 8));
     93   }
     94 
     95   if (EdgeLevel != NULL) {
     96     MasterValue = IoRead8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER);
     97     SlaveValue  = IoRead8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE);
     98 
     99     *EdgeLevel = (UINT16) (MasterValue | (SlaveValue << 8));
    100   }
    101 }
    102 
    103 //
    104 // Legacy 8259 Protocol Interface Functions
    105 //
    106 
    107 /**
    108   Sets the base address for the 8259 master and slave PICs.
    109 
    110   @param[in]  This        Indicates the EFI_LEGACY_8259_PROTOCOL instance.
    111   @param[in]  MasterBase  Interrupt vectors for IRQ0-IRQ7.
    112   @param[in]  SlaveBase   Interrupt vectors for IRQ8-IRQ15.
    113 
    114   @retval  EFI_SUCCESS       The 8259 PIC was programmed successfully.
    115   @retval  EFI_DEVICE_ERROR  There was an error while writing to the 8259 PIC.
    116 
    117 **/
    118 EFI_STATUS
    119 EFIAPI
    120 Interrupt8259SetVectorBase (
    121   IN EFI_LEGACY_8259_PROTOCOL  *This,
    122   IN UINT8                     MasterBase,
    123   IN UINT8                     SlaveBase
    124   )
    125 {
    126   UINT8   Mask;
    127   EFI_TPL OriginalTpl;
    128 
    129   OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
    130   //
    131   // Set vector base for slave PIC
    132   //
    133   if (SlaveBase != mSlaveBase) {
    134     mSlaveBase = SlaveBase;
    135 
    136     //
    137     // Initialization sequence is needed for setting vector base.
    138     //
    139 
    140     //
    141     // Preserve interrtup mask register before initialization sequence
    142     // because it will be cleared during intialization
    143     //
    144     Mask = IoRead8 (LEGACY_8259_MASK_REGISTER_SLAVE);
    145 
    146     //
    147     // ICW1: cascade mode, ICW4 write required
    148     //
    149     IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, 0x11);
    150 
    151     //
    152     // ICW2: new vector base (must be multiple of 8)
    153     //
    154     IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, mSlaveBase);
    155 
    156     //
    157     // ICW3: slave indentification code must be 2
    158     //
    159     IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0x02);
    160 
    161     //
    162     // ICW4: fully nested mode, non-buffered mode, normal EOI, IA processor
    163     //
    164     IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0x01);
    165 
    166     //
    167     // Restore interrupt mask register
    168     //
    169     IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, Mask);
    170   }
    171 
    172   //
    173   // Set vector base for master PIC
    174   //
    175   if (MasterBase != mMasterBase) {
    176     mMasterBase = MasterBase;
    177 
    178     //
    179     // Initialization sequence is needed for setting vector base.
    180     //
    181 
    182     //
    183     // Preserve interrtup mask register before initialization sequence
    184     // because it will be cleared during intialization
    185     //
    186     Mask = IoRead8 (LEGACY_8259_MASK_REGISTER_MASTER);
    187 
    188     //
    189     // ICW1: cascade mode, ICW4 write required
    190     //
    191     IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER, 0x11);
    192 
    193     //
    194     // ICW2: new vector base (must be multiple of 8)
    195     //
    196     IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, mMasterBase);
    197 
    198     //
    199     // ICW3: slave PIC is cascaded on IRQ2
    200     //
    201     IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0x04);
    202 
    203     //
    204     // ICW4: fully nested mode, non-buffered mode, normal EOI, IA processor
    205     //
    206     IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0x01);
    207 
    208     //
    209     // Restore interrupt mask register
    210     //
    211     IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, Mask);
    212   }
    213 
    214   IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, LEGACY_8259_EOI);
    215   IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER, LEGACY_8259_EOI);
    216 
    217   gBS->RestoreTPL (OriginalTpl);
    218 
    219   return EFI_SUCCESS;
    220 }
    221 
    222 /**
    223   Gets the current 16-bit real mode and 32-bit protected-mode IRQ masks.
    224 
    225   @param[in]   This                Indicates the EFI_LEGACY_8259_PROTOCOL instance.
    226   @param[out]  LegacyMask          16-bit mode interrupt mask for IRQ0-IRQ15.
    227   @param[out]  LegacyEdgeLevel     16-bit mode edge/level mask for IRQ-IRQ15.
    228   @param[out]  ProtectedMask       32-bit mode interrupt mask for IRQ0-IRQ15.
    229   @param[out]  ProtectedEdgeLevel  32-bit mode edge/level mask for IRQ0-IRQ15.
    230 
    231   @retval  EFI_SUCCESS       The 8259 PIC was programmed successfully.
    232   @retval  EFI_DEVICE_ERROR  There was an error while reading the 8259 PIC.
    233 
    234 **/
    235 EFI_STATUS
    236 EFIAPI
    237 Interrupt8259GetMask (
    238   IN  EFI_LEGACY_8259_PROTOCOL  *This,
    239   OUT UINT16                    *LegacyMask, OPTIONAL
    240   OUT UINT16                    *LegacyEdgeLevel, OPTIONAL
    241   OUT UINT16                    *ProtectedMask, OPTIONAL
    242   OUT UINT16                    *ProtectedEdgeLevel OPTIONAL
    243   )
    244 {
    245   if (LegacyMask != NULL) {
    246     *LegacyMask = mLegacyModeMask;
    247   }
    248 
    249   if (LegacyEdgeLevel != NULL) {
    250     *LegacyEdgeLevel = mLegacyModeEdgeLevel;
    251   }
    252 
    253   if (ProtectedMask != NULL) {
    254     *ProtectedMask = mProtectedModeMask;
    255   }
    256 
    257   if (ProtectedEdgeLevel != NULL) {
    258     *ProtectedEdgeLevel = mProtectedModeEdgeLevel;
    259   }
    260 
    261   return EFI_SUCCESS;
    262 }
    263 
    264 /**
    265   Sets the current 16-bit real mode and 32-bit protected-mode IRQ masks.
    266 
    267   @param[in]  This                Indicates the EFI_LEGACY_8259_PROTOCOL instance.
    268   @param[in]  LegacyMask          16-bit mode interrupt mask for IRQ0-IRQ15.
    269   @param[in]  LegacyEdgeLevel     16-bit mode edge/level mask for IRQ-IRQ15.
    270   @param[in]  ProtectedMask       32-bit mode interrupt mask for IRQ0-IRQ15.
    271   @param[in]  ProtectedEdgeLevel  32-bit mode edge/level mask for IRQ0-IRQ15.
    272 
    273   @retval  EFI_SUCCESS       The 8259 PIC was programmed successfully.
    274   @retval  EFI_DEVICE_ERROR  There was an error while writing the 8259 PIC.
    275 
    276 **/
    277 EFI_STATUS
    278 EFIAPI
    279 Interrupt8259SetMask (
    280   IN EFI_LEGACY_8259_PROTOCOL  *This,
    281   IN UINT16                    *LegacyMask, OPTIONAL
    282   IN UINT16                    *LegacyEdgeLevel, OPTIONAL
    283   IN UINT16                    *ProtectedMask, OPTIONAL
    284   IN UINT16                    *ProtectedEdgeLevel OPTIONAL
    285   )
    286 {
    287   if (LegacyMask != NULL) {
    288     mLegacyModeMask = *LegacyMask;
    289   }
    290 
    291   if (LegacyEdgeLevel != NULL) {
    292     mLegacyModeEdgeLevel = *LegacyEdgeLevel;
    293   }
    294 
    295   if (ProtectedMask != NULL) {
    296     mProtectedModeMask = *ProtectedMask;
    297   }
    298 
    299   if (ProtectedEdgeLevel != NULL) {
    300     mProtectedModeEdgeLevel = *ProtectedEdgeLevel;
    301   }
    302 
    303   return EFI_SUCCESS;
    304 }
    305 
    306 /**
    307   Sets the mode of the PICs.
    308 
    309   @param[in]  This       Indicates the EFI_LEGACY_8259_PROTOCOL instance.
    310   @param[in]  Mode       16-bit real or 32-bit protected mode.
    311   @param[in]  Mask       The value with which to set the interrupt mask.
    312   @param[in]  EdgeLevel  The value with which to set the edge/level mask.
    313 
    314   @retval  EFI_SUCCESS            The mode was set successfully.
    315   @retval  EFI_INVALID_PARAMETER  The mode was not set.
    316 
    317 **/
    318 EFI_STATUS
    319 EFIAPI
    320 Interrupt8259SetMode (
    321   IN EFI_LEGACY_8259_PROTOCOL  *This,
    322   IN EFI_8259_MODE             Mode,
    323   IN UINT16                    *Mask, OPTIONAL
    324   IN UINT16                    *EdgeLevel OPTIONAL
    325   )
    326 {
    327   if (Mode == mMode) {
    328     return EFI_SUCCESS;
    329   }
    330 
    331   if (Mode == Efi8259LegacyMode) {
    332     //
    333     // In Efi8259ProtectedMode, mask and edge/level trigger registers should
    334     // be changed through this protocol, so we can track them in the
    335     // corresponding module variables.
    336     //
    337     Interrupt8259ReadMask (&mProtectedModeMask, &mProtectedModeEdgeLevel);
    338 
    339     if (Mask != NULL) {
    340       //
    341       // Update the Mask for the new mode
    342       //
    343       mLegacyModeMask = *Mask;
    344     }
    345 
    346     if (EdgeLevel != NULL) {
    347       //
    348       // Update the Edge/Level triggered mask for the new mode
    349       //
    350       mLegacyModeEdgeLevel = *EdgeLevel;
    351     }
    352 
    353     mMode = Mode;
    354 
    355     //
    356     // Write new legacy mode mask/trigger level
    357     //
    358     Interrupt8259WriteMask (mLegacyModeMask, mLegacyModeEdgeLevel);
    359 
    360     return EFI_SUCCESS;
    361   }
    362 
    363   if (Mode == Efi8259ProtectedMode) {
    364     //
    365     // Save the legacy mode mask/trigger level
    366     //
    367     Interrupt8259ReadMask (&mLegacyModeMask, &mLegacyModeEdgeLevel);
    368     //
    369     // Always force Timer to be enabled after return from 16-bit code.
    370     // This always insures that on next entry, timer is counting.
    371     //
    372     mLegacyModeMask &= 0xFFFE;
    373 
    374     if (Mask != NULL) {
    375       //
    376       // Update the Mask for the new mode
    377       //
    378       mProtectedModeMask = *Mask;
    379     }
    380 
    381     if (EdgeLevel != NULL) {
    382       //
    383       // Update the Edge/Level triggered mask for the new mode
    384       //
    385       mProtectedModeEdgeLevel = *EdgeLevel;
    386     }
    387 
    388     mMode = Mode;
    389 
    390     //
    391     // Write new protected mode mask/trigger level
    392     //
    393     Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel);
    394 
    395     return EFI_SUCCESS;
    396   }
    397 
    398   return EFI_INVALID_PARAMETER;
    399 }
    400 
    401 /**
    402   Translates the IRQ into a vector.
    403 
    404   @param[in]   This    Indicates the EFI_LEGACY_8259_PROTOCOL instance.
    405   @param[in]   Irq     IRQ0-IRQ15.
    406   @param[out]  Vector  The vector that is assigned to the IRQ.
    407 
    408   @retval  EFI_SUCCESS            The Vector that matches Irq was returned.
    409   @retval  EFI_INVALID_PARAMETER  Irq is not valid.
    410 
    411 **/
    412 EFI_STATUS
    413 EFIAPI
    414 Interrupt8259GetVector (
    415   IN  EFI_LEGACY_8259_PROTOCOL  *This,
    416   IN  EFI_8259_IRQ              Irq,
    417   OUT UINT8                     *Vector
    418   )
    419 {
    420   if ((UINT32)Irq > Efi8259Irq15) {
    421     return EFI_INVALID_PARAMETER;
    422   }
    423 
    424   if (Irq <= Efi8259Irq7) {
    425     *Vector = (UINT8) (mMasterBase + Irq);
    426   } else {
    427     *Vector = (UINT8) (mSlaveBase + (Irq - Efi8259Irq8));
    428   }
    429 
    430   return EFI_SUCCESS;
    431 }
    432 
    433 /**
    434   Enables the specified IRQ.
    435 
    436   @param[in]  This            Indicates the EFI_LEGACY_8259_PROTOCOL instance.
    437   @param[in]  Irq             IRQ0-IRQ15.
    438   @param[in]  LevelTriggered  0 = Edge triggered; 1 = Level triggered.
    439 
    440   @retval  EFI_SUCCESS            The Irq was enabled on the 8259 PIC.
    441   @retval  EFI_INVALID_PARAMETER  The Irq is not valid.
    442 
    443 **/
    444 EFI_STATUS
    445 EFIAPI
    446 Interrupt8259EnableIrq (
    447   IN EFI_LEGACY_8259_PROTOCOL  *This,
    448   IN EFI_8259_IRQ              Irq,
    449   IN BOOLEAN                   LevelTriggered
    450   )
    451 {
    452   if ((UINT32)Irq > Efi8259Irq15) {
    453     return EFI_INVALID_PARAMETER;
    454   }
    455 
    456   mProtectedModeMask = (UINT16) (mProtectedModeMask & ~(1 << Irq));
    457   if (LevelTriggered) {
    458     mProtectedModeEdgeLevel = (UINT16) (mProtectedModeEdgeLevel | (1 << Irq));
    459   } else {
    460     mProtectedModeEdgeLevel = (UINT16) (mProtectedModeEdgeLevel & ~(1 << Irq));
    461   }
    462 
    463   Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel);
    464 
    465   return EFI_SUCCESS;
    466 }
    467 
    468 /**
    469   Disables the specified IRQ.
    470 
    471   @param[in]  This  Indicates the EFI_LEGACY_8259_PROTOCOL instance.
    472   @param[in]  Irq   IRQ0-IRQ15.
    473 
    474   @retval  EFI_SUCCESS            The Irq was disabled on the 8259 PIC.
    475   @retval  EFI_INVALID_PARAMETER  The Irq is not valid.
    476 
    477 **/
    478 EFI_STATUS
    479 EFIAPI
    480 Interrupt8259DisableIrq (
    481   IN EFI_LEGACY_8259_PROTOCOL  *This,
    482   IN EFI_8259_IRQ              Irq
    483   )
    484 {
    485   if ((UINT32)Irq > Efi8259Irq15) {
    486     return EFI_INVALID_PARAMETER;
    487   }
    488 
    489   mProtectedModeMask = (UINT16) (mProtectedModeMask | (1 << Irq));
    490 
    491   mProtectedModeEdgeLevel = (UINT16) (mProtectedModeEdgeLevel & ~(1 << Irq));
    492 
    493   Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel);
    494 
    495   return EFI_SUCCESS;
    496 }
    497 
    498 /**
    499   Reads the PCI configuration space to get the interrupt number that is assigned to the card.
    500 
    501   @param[in]   This       Indicates the EFI_LEGACY_8259_PROTOCOL instance.
    502   @param[in]   PciHandle  PCI function for which to return the vector.
    503   @param[out]  Vector     IRQ number that corresponds to the interrupt line.
    504 
    505   @retval  EFI_SUCCESS  The interrupt line value was read successfully.
    506 
    507 **/
    508 EFI_STATUS
    509 EFIAPI
    510 Interrupt8259GetInterruptLine (
    511   IN  EFI_LEGACY_8259_PROTOCOL  *This,
    512   IN  EFI_HANDLE                PciHandle,
    513   OUT UINT8                     *Vector
    514   )
    515 {
    516   EFI_PCI_IO_PROTOCOL *PciIo;
    517   UINT8               InterruptLine;
    518   EFI_STATUS          Status;
    519 
    520   Status = gBS->HandleProtocol (
    521                   PciHandle,
    522                   &gEfiPciIoProtocolGuid,
    523                   (VOID **) &PciIo
    524                   );
    525   if (EFI_ERROR (Status)) {
    526     return EFI_INVALID_PARAMETER;
    527   }
    528 
    529   PciIo->Pci.Read (
    530                PciIo,
    531                EfiPciIoWidthUint8,
    532                PCI_INT_LINE_OFFSET,
    533                1,
    534                &InterruptLine
    535                );
    536   //
    537   // Interrupt line is same location for standard PCI cards, standard
    538   // bridge and CardBus bridge.
    539   //
    540   *Vector = InterruptLine;
    541 
    542   return EFI_SUCCESS;
    543 }
    544 
    545 /**
    546   Issues the End of Interrupt (EOI) commands to PICs.
    547 
    548   @param[in]  This  Indicates the EFI_LEGACY_8259_PROTOCOL instance.
    549   @param[in]  Irq   The interrupt for which to issue the EOI command.
    550 
    551   @retval  EFI_SUCCESS            The EOI command was issued.
    552   @retval  EFI_INVALID_PARAMETER  The Irq is not valid.
    553 
    554 **/
    555 EFI_STATUS
    556 EFIAPI
    557 Interrupt8259EndOfInterrupt (
    558   IN EFI_LEGACY_8259_PROTOCOL  *This,
    559   IN EFI_8259_IRQ              Irq
    560   )
    561 {
    562   if ((UINT32)Irq > Efi8259Irq15) {
    563     return EFI_INVALID_PARAMETER;
    564   }
    565 
    566   if (Irq >= Efi8259Irq8) {
    567     IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, LEGACY_8259_EOI);
    568   }
    569 
    570   IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER, LEGACY_8259_EOI);
    571 
    572   return EFI_SUCCESS;
    573 }
    574 
    575 /**
    576   Driver Entry point.
    577 
    578   @param[in]  ImageHandle  ImageHandle of the loaded driver.
    579   @param[in]  SystemTable  Pointer to the EFI System Table.
    580 
    581   @retval  EFI_SUCCESS  One or more of the drivers returned a success code.
    582   @retval  !EFI_SUCCESS  Error installing Legacy 8259 Protocol.
    583 
    584 **/
    585 EFI_STATUS
    586 EFIAPI
    587 Install8259 (
    588   IN EFI_HANDLE        ImageHandle,
    589   IN EFI_SYSTEM_TABLE  *SystemTable
    590   )
    591 {
    592   EFI_STATUS   Status;
    593   EFI_8259_IRQ Irq;
    594 
    595   //
    596   // Initialze mask values from PCDs
    597   //
    598   mLegacyModeMask      = PcdGet16 (Pcd8259LegacyModeMask);
    599   mLegacyModeEdgeLevel = PcdGet16 (Pcd8259LegacyModeEdgeLevel);
    600 
    601   //
    602   // Clear all pending interrupt
    603   //
    604   for (Irq = Efi8259Irq0; Irq <= Efi8259Irq15; Irq++) {
    605     Interrupt8259EndOfInterrupt (&mInterrupt8259, Irq);
    606   }
    607 
    608   //
    609   // Set the 8259 Master base to 0x68 and the 8259 Slave base to 0x70
    610   //
    611   Status = Interrupt8259SetVectorBase (&mInterrupt8259, PROTECTED_MODE_BASE_VECTOR_MASTER, PROTECTED_MODE_BASE_VECTOR_SLAVE);
    612 
    613   //
    614   // Set all 8259 interrupts to edge triggered and disabled
    615   //
    616   Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel);
    617 
    618   //
    619   // Install 8259 Protocol onto a new handle
    620   //
    621   Status = gBS->InstallProtocolInterface (
    622                   &m8259Handle,
    623                   &gEfiLegacy8259ProtocolGuid,
    624                   EFI_NATIVE_INTERFACE,
    625                   &mInterrupt8259
    626                   );
    627   return Status;
    628 }
    629