1dfaaa5a5eda92aafec7e4d14894c41541d4788fcydong/** @file
21166d06825aca8d7e172776bd1297d6bcd3ad47cklu  This contains the installation function for the driver.
347ca9c95885ec58c3c49efb2593692693748a2f1darylm
43d78c020d22023d35d27b48817d73ff31a361ac7rsunCopyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
547ca9c95885ec58c3c49efb2593692693748a2f1darylmThis program and the accompanying materials
647ca9c95885ec58c3c49efb2593692693748a2f1darylmare licensed and made available under the terms and conditions of the BSD License
747ca9c95885ec58c3c49efb2593692693748a2f1darylmwhich accompanies this distribution.  The full text of the license may be found at
847ca9c95885ec58c3c49efb2593692693748a2f1darylmhttp://opensource.org/licenses/bsd-license.php
947ca9c95885ec58c3c49efb2593692693748a2f1darylm
1047ca9c95885ec58c3c49efb2593692693748a2f1darylmTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
1147ca9c95885ec58c3c49efb2593692693748a2f1darylmWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
121166d06825aca8d7e172776bd1297d6bcd3ad47cklu
131166d06825aca8d7e172776bd1297d6bcd3ad47cklu**/
141166d06825aca8d7e172776bd1297d6bcd3ad47cklu
151166d06825aca8d7e172776bd1297d6bcd3ad47cklu#include "8259.h"
161166d06825aca8d7e172776bd1297d6bcd3ad47cklu
171166d06825aca8d7e172776bd1297d6bcd3ad47cklu//
1890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten// Global for the Legacy 8259 Protocol that is produced by this driver
191166d06825aca8d7e172776bd1297d6bcd3ad47cklu//
2024115e44926b33c763f81026690f20efd913daf2ydongEFI_LEGACY_8259_PROTOCOL  mInterrupt8259 = {
211166d06825aca8d7e172776bd1297d6bcd3ad47cklu  Interrupt8259SetVectorBase,
221166d06825aca8d7e172776bd1297d6bcd3ad47cklu  Interrupt8259GetMask,
231166d06825aca8d7e172776bd1297d6bcd3ad47cklu  Interrupt8259SetMask,
241166d06825aca8d7e172776bd1297d6bcd3ad47cklu  Interrupt8259SetMode,
251166d06825aca8d7e172776bd1297d6bcd3ad47cklu  Interrupt8259GetVector,
261166d06825aca8d7e172776bd1297d6bcd3ad47cklu  Interrupt8259EnableIrq,
271166d06825aca8d7e172776bd1297d6bcd3ad47cklu  Interrupt8259DisableIrq,
281166d06825aca8d7e172776bd1297d6bcd3ad47cklu  Interrupt8259GetInterruptLine,
291166d06825aca8d7e172776bd1297d6bcd3ad47cklu  Interrupt8259EndOfInterrupt
301166d06825aca8d7e172776bd1297d6bcd3ad47cklu};
311166d06825aca8d7e172776bd1297d6bcd3ad47cklu
321166d06825aca8d7e172776bd1297d6bcd3ad47cklu//
331166d06825aca8d7e172776bd1297d6bcd3ad47cklu// Global for the handle that the Legacy 8259 Protocol is installed
341166d06825aca8d7e172776bd1297d6bcd3ad47cklu//
351166d06825aca8d7e172776bd1297d6bcd3ad47ckluEFI_HANDLE                m8259Handle             = NULL;
361166d06825aca8d7e172776bd1297d6bcd3ad47cklu
371166d06825aca8d7e172776bd1297d6bcd3ad47ckluUINT8                     mMasterBase             = 0xff;
381166d06825aca8d7e172776bd1297d6bcd3ad47ckluUINT8                     mSlaveBase              = 0xff;
391166d06825aca8d7e172776bd1297d6bcd3ad47ckluEFI_8259_MODE             mMode                   = Efi8259ProtectedMode;
401166d06825aca8d7e172776bd1297d6bcd3ad47ckluUINT16                    mProtectedModeMask      = 0xffff;
41856f592ccf397bd55a242375fc1854a190c776e1mdkinneyUINT16                    mLegacyModeMask;
421166d06825aca8d7e172776bd1297d6bcd3ad47ckluUINT16                    mProtectedModeEdgeLevel = 0x0000;
43856f592ccf397bd55a242375fc1854a190c776e1mdkinneyUINT16                    mLegacyModeEdgeLevel;
441166d06825aca8d7e172776bd1297d6bcd3ad47cklu
451166d06825aca8d7e172776bd1297d6bcd3ad47cklu//
461166d06825aca8d7e172776bd1297d6bcd3ad47cklu// Worker Functions
471166d06825aca8d7e172776bd1297d6bcd3ad47cklu//
4890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
4990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten/**
5090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  Write to mask and edge/level triggered registers of master and slave PICs.
5190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
5290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  Mask       low byte for master PIC mask register,
5390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten                         high byte for slave PIC mask register.
5490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  EdgeLevel  low byte for master PIC edge/level triggered register,
5590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten                         high byte for slave PIC edge/level triggered register.
5690b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
5790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten**/
581166d06825aca8d7e172776bd1297d6bcd3ad47ckluVOID
591166d06825aca8d7e172776bd1297d6bcd3ad47ckluInterrupt8259WriteMask (
601166d06825aca8d7e172776bd1297d6bcd3ad47cklu  IN UINT16  Mask,
611166d06825aca8d7e172776bd1297d6bcd3ad47cklu  IN UINT16  EdgeLevel
621166d06825aca8d7e172776bd1297d6bcd3ad47cklu  )
631166d06825aca8d7e172776bd1297d6bcd3ad47cklu{
641166d06825aca8d7e172776bd1297d6bcd3ad47cklu  IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, (UINT8) Mask);
651166d06825aca8d7e172776bd1297d6bcd3ad47cklu  IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, (UINT8) (Mask >> 8));
661166d06825aca8d7e172776bd1297d6bcd3ad47cklu  IoWrite8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER, (UINT8) EdgeLevel);
671166d06825aca8d7e172776bd1297d6bcd3ad47cklu  IoWrite8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE, (UINT8) (EdgeLevel >> 8));
681166d06825aca8d7e172776bd1297d6bcd3ad47cklu}
691166d06825aca8d7e172776bd1297d6bcd3ad47cklu
701166d06825aca8d7e172776bd1297d6bcd3ad47cklu/**
7190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  Read from mask and edge/level triggered registers of master and slave PICs.
721166d06825aca8d7e172776bd1297d6bcd3ad47cklu
7390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[out]  Mask       low byte for master PIC mask register,
7490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten                          high byte for slave PIC mask register.
7590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[out]  EdgeLevel  low byte for master PIC edge/level triggered register,
7690b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten                          high byte for slave PIC edge/level triggered register.
771166d06825aca8d7e172776bd1297d6bcd3ad47cklu
781166d06825aca8d7e172776bd1297d6bcd3ad47cklu**/
7990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenVOID
8090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenInterrupt8259ReadMask (
8190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  OUT UINT16  *Mask,
8290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  OUT UINT16  *EdgeLevel
8390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  )
841166d06825aca8d7e172776bd1297d6bcd3ad47cklu{
85a694b670e1a14b3a4da306463d9760176a73bef3xli  UINT16  MasterValue;
86a694b670e1a14b3a4da306463d9760176a73bef3xli  UINT16  SlaveValue;
87a694b670e1a14b3a4da306463d9760176a73bef3xli
881166d06825aca8d7e172776bd1297d6bcd3ad47cklu  if (Mask != NULL) {
89a694b670e1a14b3a4da306463d9760176a73bef3xli    MasterValue = IoRead8 (LEGACY_8259_MASK_REGISTER_MASTER);
90a694b670e1a14b3a4da306463d9760176a73bef3xli    SlaveValue  = IoRead8 (LEGACY_8259_MASK_REGISTER_SLAVE);
91a694b670e1a14b3a4da306463d9760176a73bef3xli
92a694b670e1a14b3a4da306463d9760176a73bef3xli    *Mask = (UINT16) (MasterValue | (SlaveValue << 8));
931166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
941166d06825aca8d7e172776bd1297d6bcd3ad47cklu
951166d06825aca8d7e172776bd1297d6bcd3ad47cklu  if (EdgeLevel != NULL) {
96a694b670e1a14b3a4da306463d9760176a73bef3xli    MasterValue = IoRead8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER);
97a694b670e1a14b3a4da306463d9760176a73bef3xli    SlaveValue  = IoRead8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE);
98a694b670e1a14b3a4da306463d9760176a73bef3xli
99a694b670e1a14b3a4da306463d9760176a73bef3xli    *EdgeLevel = (UINT16) (MasterValue | (SlaveValue << 8));
1001166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
1011166d06825aca8d7e172776bd1297d6bcd3ad47cklu}
10290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
1031166d06825aca8d7e172776bd1297d6bcd3ad47cklu//
10490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten// Legacy 8259 Protocol Interface Functions
1051166d06825aca8d7e172776bd1297d6bcd3ad47cklu//
1061166d06825aca8d7e172776bd1297d6bcd3ad47cklu
10790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten/**
10890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  Sets the base address for the 8259 master and slave PICs.
1091166d06825aca8d7e172776bd1297d6bcd3ad47cklu
11090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  This        Indicates the EFI_LEGACY_8259_PROTOCOL instance.
11190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  MasterBase  Interrupt vectors for IRQ0-IRQ7.
11290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  SlaveBase   Interrupt vectors for IRQ8-IRQ15.
1131166d06825aca8d7e172776bd1297d6bcd3ad47cklu
11490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  EFI_SUCCESS       The 8259 PIC was programmed successfully.
11590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  EFI_DEVICE_ERROR  There was an error while writing to the 8259 PIC.
1161166d06825aca8d7e172776bd1297d6bcd3ad47cklu
1171166d06825aca8d7e172776bd1297d6bcd3ad47cklu**/
11890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenEFI_STATUS
11990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenEFIAPI
12090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenInterrupt8259SetVectorBase (
12190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN EFI_LEGACY_8259_PROTOCOL  *This,
12290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN UINT8                     MasterBase,
12390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN UINT8                     SlaveBase
12490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  )
1251166d06825aca8d7e172776bd1297d6bcd3ad47cklu{
1264fde0f15aae4489bd3973fb4698e6333c98c2b06li-elvin  UINT8   Mask;
1274fde0f15aae4489bd3973fb4698e6333c98c2b06li-elvin  EFI_TPL OriginalTpl;
1281166d06825aca8d7e172776bd1297d6bcd3ad47cklu
1294fde0f15aae4489bd3973fb4698e6333c98c2b06li-elvin  OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
13090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  //
13190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  // Set vector base for slave PIC
13290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  //
1331166d06825aca8d7e172776bd1297d6bcd3ad47cklu  if (SlaveBase != mSlaveBase) {
1341166d06825aca8d7e172776bd1297d6bcd3ad47cklu    mSlaveBase = SlaveBase;
1351166d06825aca8d7e172776bd1297d6bcd3ad47cklu
1361166d06825aca8d7e172776bd1297d6bcd3ad47cklu    //
13790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // Initialization sequence is needed for setting vector base.
13890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
13990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
14090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
14190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // Preserve interrtup mask register before initialization sequence
14290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // because it will be cleared during intialization
1431166d06825aca8d7e172776bd1297d6bcd3ad47cklu    //
1441166d06825aca8d7e172776bd1297d6bcd3ad47cklu    Mask = IoRead8 (LEGACY_8259_MASK_REGISTER_SLAVE);
14590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
14690b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
14790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // ICW1: cascade mode, ICW4 write required
14890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
1491166d06825aca8d7e172776bd1297d6bcd3ad47cklu    IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, 0x11);
15090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
15190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
15290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // ICW2: new vector base (must be multiple of 8)
15390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
1541166d06825aca8d7e172776bd1297d6bcd3ad47cklu    IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, mSlaveBase);
15590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
15690b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
15790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // ICW3: slave indentification code must be 2
15890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
1591166d06825aca8d7e172776bd1297d6bcd3ad47cklu    IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0x02);
16090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
16190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
16290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // ICW4: fully nested mode, non-buffered mode, normal EOI, IA processor
16390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
1641166d06825aca8d7e172776bd1297d6bcd3ad47cklu    IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0x01);
16590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
16690b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
16790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // Restore interrupt mask register
16890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
1691166d06825aca8d7e172776bd1297d6bcd3ad47cklu    IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, Mask);
1701166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
1711166d06825aca8d7e172776bd1297d6bcd3ad47cklu
17290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  //
17390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  // Set vector base for master PIC
17490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  //
1751166d06825aca8d7e172776bd1297d6bcd3ad47cklu  if (MasterBase != mMasterBase) {
1761166d06825aca8d7e172776bd1297d6bcd3ad47cklu    mMasterBase = MasterBase;
1771166d06825aca8d7e172776bd1297d6bcd3ad47cklu
1781166d06825aca8d7e172776bd1297d6bcd3ad47cklu    //
17990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // Initialization sequence is needed for setting vector base.
18090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
18190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
18290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
18390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // Preserve interrtup mask register before initialization sequence
18490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // because it will be cleared during intialization
1851166d06825aca8d7e172776bd1297d6bcd3ad47cklu    //
1861166d06825aca8d7e172776bd1297d6bcd3ad47cklu    Mask = IoRead8 (LEGACY_8259_MASK_REGISTER_MASTER);
18790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
18890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
18990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // ICW1: cascade mode, ICW4 write required
19090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
1911166d06825aca8d7e172776bd1297d6bcd3ad47cklu    IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER, 0x11);
19290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
19390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
19490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // ICW2: new vector base (must be multiple of 8)
19590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
1961166d06825aca8d7e172776bd1297d6bcd3ad47cklu    IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, mMasterBase);
19790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
19890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
19990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // ICW3: slave PIC is cascaded on IRQ2
20090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
2011166d06825aca8d7e172776bd1297d6bcd3ad47cklu    IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0x04);
20290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
20390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
20490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // ICW4: fully nested mode, non-buffered mode, normal EOI, IA processor
20590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
2061166d06825aca8d7e172776bd1297d6bcd3ad47cklu    IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0x01);
20790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
20890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
20990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // Restore interrupt mask register
21090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    //
2111166d06825aca8d7e172776bd1297d6bcd3ad47cklu    IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, Mask);
2121166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
2131166d06825aca8d7e172776bd1297d6bcd3ad47cklu
214ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff  IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, LEGACY_8259_EOI);
215ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff  IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER, LEGACY_8259_EOI);
2164fde0f15aae4489bd3973fb4698e6333c98c2b06li-elvin
2174fde0f15aae4489bd3973fb4698e6333c98c2b06li-elvin  gBS->RestoreTPL (OriginalTpl);
2181166d06825aca8d7e172776bd1297d6bcd3ad47cklu
2191166d06825aca8d7e172776bd1297d6bcd3ad47cklu  return EFI_SUCCESS;
2201166d06825aca8d7e172776bd1297d6bcd3ad47cklu}
2211166d06825aca8d7e172776bd1297d6bcd3ad47cklu
22290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten/**
22390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  Gets the current 16-bit real mode and 32-bit protected-mode IRQ masks.
22490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
22590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]   This                Indicates the EFI_LEGACY_8259_PROTOCOL instance.
22690b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[out]  LegacyMask          16-bit mode interrupt mask for IRQ0-IRQ15.
22790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[out]  LegacyEdgeLevel     16-bit mode edge/level mask for IRQ-IRQ15.
22890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[out]  ProtectedMask       32-bit mode interrupt mask for IRQ0-IRQ15.
22990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[out]  ProtectedEdgeLevel  32-bit mode edge/level mask for IRQ0-IRQ15.
23090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
23190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  EFI_SUCCESS       The 8259 PIC was programmed successfully.
23290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  EFI_DEVICE_ERROR  There was an error while reading the 8259 PIC.
23390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
23490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten**/
2351166d06825aca8d7e172776bd1297d6bcd3ad47ckluEFI_STATUS
2361166d06825aca8d7e172776bd1297d6bcd3ad47ckluEFIAPI
2371166d06825aca8d7e172776bd1297d6bcd3ad47ckluInterrupt8259GetMask (
23890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN  EFI_LEGACY_8259_PROTOCOL  *This,
2391166d06825aca8d7e172776bd1297d6bcd3ad47cklu  OUT UINT16                    *LegacyMask, OPTIONAL
2401166d06825aca8d7e172776bd1297d6bcd3ad47cklu  OUT UINT16                    *LegacyEdgeLevel, OPTIONAL
2411166d06825aca8d7e172776bd1297d6bcd3ad47cklu  OUT UINT16                    *ProtectedMask, OPTIONAL
2421166d06825aca8d7e172776bd1297d6bcd3ad47cklu  OUT UINT16                    *ProtectedEdgeLevel OPTIONAL
2431166d06825aca8d7e172776bd1297d6bcd3ad47cklu  )
2441166d06825aca8d7e172776bd1297d6bcd3ad47cklu{
2451166d06825aca8d7e172776bd1297d6bcd3ad47cklu  if (LegacyMask != NULL) {
2461166d06825aca8d7e172776bd1297d6bcd3ad47cklu    *LegacyMask = mLegacyModeMask;
2471166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
2481166d06825aca8d7e172776bd1297d6bcd3ad47cklu
2491166d06825aca8d7e172776bd1297d6bcd3ad47cklu  if (LegacyEdgeLevel != NULL) {
2501166d06825aca8d7e172776bd1297d6bcd3ad47cklu    *LegacyEdgeLevel = mLegacyModeEdgeLevel;
2511166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
2521166d06825aca8d7e172776bd1297d6bcd3ad47cklu
2531166d06825aca8d7e172776bd1297d6bcd3ad47cklu  if (ProtectedMask != NULL) {
2541166d06825aca8d7e172776bd1297d6bcd3ad47cklu    *ProtectedMask = mProtectedModeMask;
2551166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
2561166d06825aca8d7e172776bd1297d6bcd3ad47cklu
2571166d06825aca8d7e172776bd1297d6bcd3ad47cklu  if (ProtectedEdgeLevel != NULL) {
2581166d06825aca8d7e172776bd1297d6bcd3ad47cklu    *ProtectedEdgeLevel = mProtectedModeEdgeLevel;
2591166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
2601166d06825aca8d7e172776bd1297d6bcd3ad47cklu
2611166d06825aca8d7e172776bd1297d6bcd3ad47cklu  return EFI_SUCCESS;
2621166d06825aca8d7e172776bd1297d6bcd3ad47cklu}
2631166d06825aca8d7e172776bd1297d6bcd3ad47cklu
2641166d06825aca8d7e172776bd1297d6bcd3ad47cklu/**
26590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  Sets the current 16-bit real mode and 32-bit protected-mode IRQ masks.
2661166d06825aca8d7e172776bd1297d6bcd3ad47cklu
26790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  This                Indicates the EFI_LEGACY_8259_PROTOCOL instance.
26890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  LegacyMask          16-bit mode interrupt mask for IRQ0-IRQ15.
26990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  LegacyEdgeLevel     16-bit mode edge/level mask for IRQ-IRQ15.
27090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  ProtectedMask       32-bit mode interrupt mask for IRQ0-IRQ15.
27190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  ProtectedEdgeLevel  32-bit mode edge/level mask for IRQ0-IRQ15.
2721166d06825aca8d7e172776bd1297d6bcd3ad47cklu
27390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  EFI_SUCCESS       The 8259 PIC was programmed successfully.
27490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  EFI_DEVICE_ERROR  There was an error while writing the 8259 PIC.
2751166d06825aca8d7e172776bd1297d6bcd3ad47cklu
2761166d06825aca8d7e172776bd1297d6bcd3ad47cklu**/
27790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenEFI_STATUS
27890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenEFIAPI
27990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenInterrupt8259SetMask (
28090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN EFI_LEGACY_8259_PROTOCOL  *This,
28190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN UINT16                    *LegacyMask, OPTIONAL
28290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN UINT16                    *LegacyEdgeLevel, OPTIONAL
28390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN UINT16                    *ProtectedMask, OPTIONAL
28490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN UINT16                    *ProtectedEdgeLevel OPTIONAL
28590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  )
2861166d06825aca8d7e172776bd1297d6bcd3ad47cklu{
2871166d06825aca8d7e172776bd1297d6bcd3ad47cklu  if (LegacyMask != NULL) {
2881166d06825aca8d7e172776bd1297d6bcd3ad47cklu    mLegacyModeMask = *LegacyMask;
2891166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
2901166d06825aca8d7e172776bd1297d6bcd3ad47cklu
2911166d06825aca8d7e172776bd1297d6bcd3ad47cklu  if (LegacyEdgeLevel != NULL) {
2921166d06825aca8d7e172776bd1297d6bcd3ad47cklu    mLegacyModeEdgeLevel = *LegacyEdgeLevel;
2931166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
2941166d06825aca8d7e172776bd1297d6bcd3ad47cklu
2951166d06825aca8d7e172776bd1297d6bcd3ad47cklu  if (ProtectedMask != NULL) {
2961166d06825aca8d7e172776bd1297d6bcd3ad47cklu    mProtectedModeMask = *ProtectedMask;
2971166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
2981166d06825aca8d7e172776bd1297d6bcd3ad47cklu
2991166d06825aca8d7e172776bd1297d6bcd3ad47cklu  if (ProtectedEdgeLevel != NULL) {
3001166d06825aca8d7e172776bd1297d6bcd3ad47cklu    mProtectedModeEdgeLevel = *ProtectedEdgeLevel;
3011166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
3021166d06825aca8d7e172776bd1297d6bcd3ad47cklu
3031166d06825aca8d7e172776bd1297d6bcd3ad47cklu  return EFI_SUCCESS;
3041166d06825aca8d7e172776bd1297d6bcd3ad47cklu}
3051166d06825aca8d7e172776bd1297d6bcd3ad47cklu
3061166d06825aca8d7e172776bd1297d6bcd3ad47cklu/**
30790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  Sets the mode of the PICs.
3081166d06825aca8d7e172776bd1297d6bcd3ad47cklu
30990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  This       Indicates the EFI_LEGACY_8259_PROTOCOL instance.
31090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  Mode       16-bit real or 32-bit protected mode.
31190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  Mask       The value with which to set the interrupt mask.
31290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  EdgeLevel  The value with which to set the edge/level mask.
3131166d06825aca8d7e172776bd1297d6bcd3ad47cklu
31490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  EFI_SUCCESS            The mode was set successfully.
31590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  EFI_INVALID_PARAMETER  The mode was not set.
3161166d06825aca8d7e172776bd1297d6bcd3ad47cklu
3171166d06825aca8d7e172776bd1297d6bcd3ad47cklu**/
31890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenEFI_STATUS
31990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenEFIAPI
32090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenInterrupt8259SetMode (
32190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN EFI_LEGACY_8259_PROTOCOL  *This,
32290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN EFI_8259_MODE             Mode,
32390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN UINT16                    *Mask, OPTIONAL
32490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN UINT16                    *EdgeLevel OPTIONAL
32590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  )
3261166d06825aca8d7e172776bd1297d6bcd3ad47cklu{
3271166d06825aca8d7e172776bd1297d6bcd3ad47cklu  if (Mode == mMode) {
3281166d06825aca8d7e172776bd1297d6bcd3ad47cklu    return EFI_SUCCESS;
3291166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
3301166d06825aca8d7e172776bd1297d6bcd3ad47cklu
3311166d06825aca8d7e172776bd1297d6bcd3ad47cklu  if (Mode == Efi8259LegacyMode) {
3321166d06825aca8d7e172776bd1297d6bcd3ad47cklu    //
33390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // In Efi8259ProtectedMode, mask and edge/level trigger registers should
33490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // be changed through this protocol, so we can track them in the
33590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // corresponding module variables.
3361166d06825aca8d7e172776bd1297d6bcd3ad47cklu    //
3371166d06825aca8d7e172776bd1297d6bcd3ad47cklu    Interrupt8259ReadMask (&mProtectedModeMask, &mProtectedModeEdgeLevel);
3381166d06825aca8d7e172776bd1297d6bcd3ad47cklu
3391166d06825aca8d7e172776bd1297d6bcd3ad47cklu    if (Mask != NULL) {
3401166d06825aca8d7e172776bd1297d6bcd3ad47cklu      //
3411166d06825aca8d7e172776bd1297d6bcd3ad47cklu      // Update the Mask for the new mode
3421166d06825aca8d7e172776bd1297d6bcd3ad47cklu      //
3431166d06825aca8d7e172776bd1297d6bcd3ad47cklu      mLegacyModeMask = *Mask;
3441166d06825aca8d7e172776bd1297d6bcd3ad47cklu    }
3451166d06825aca8d7e172776bd1297d6bcd3ad47cklu
3461166d06825aca8d7e172776bd1297d6bcd3ad47cklu    if (EdgeLevel != NULL) {
3471166d06825aca8d7e172776bd1297d6bcd3ad47cklu      //
3481166d06825aca8d7e172776bd1297d6bcd3ad47cklu      // Update the Edge/Level triggered mask for the new mode
3491166d06825aca8d7e172776bd1297d6bcd3ad47cklu      //
3501166d06825aca8d7e172776bd1297d6bcd3ad47cklu      mLegacyModeEdgeLevel = *EdgeLevel;
3511166d06825aca8d7e172776bd1297d6bcd3ad47cklu    }
3521166d06825aca8d7e172776bd1297d6bcd3ad47cklu
3531166d06825aca8d7e172776bd1297d6bcd3ad47cklu    mMode = Mode;
3541166d06825aca8d7e172776bd1297d6bcd3ad47cklu
3551166d06825aca8d7e172776bd1297d6bcd3ad47cklu    //
35690b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // Write new legacy mode mask/trigger level
3571166d06825aca8d7e172776bd1297d6bcd3ad47cklu    //
3581166d06825aca8d7e172776bd1297d6bcd3ad47cklu    Interrupt8259WriteMask (mLegacyModeMask, mLegacyModeEdgeLevel);
3591166d06825aca8d7e172776bd1297d6bcd3ad47cklu
3601166d06825aca8d7e172776bd1297d6bcd3ad47cklu    return EFI_SUCCESS;
3611166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
3621166d06825aca8d7e172776bd1297d6bcd3ad47cklu
3631166d06825aca8d7e172776bd1297d6bcd3ad47cklu  if (Mode == Efi8259ProtectedMode) {
3641166d06825aca8d7e172776bd1297d6bcd3ad47cklu    //
36590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // Save the legacy mode mask/trigger level
3661166d06825aca8d7e172776bd1297d6bcd3ad47cklu    //
3671166d06825aca8d7e172776bd1297d6bcd3ad47cklu    Interrupt8259ReadMask (&mLegacyModeMask, &mLegacyModeEdgeLevel);
3681166d06825aca8d7e172776bd1297d6bcd3ad47cklu    //
3691166d06825aca8d7e172776bd1297d6bcd3ad47cklu    // Always force Timer to be enabled after return from 16-bit code.
3701166d06825aca8d7e172776bd1297d6bcd3ad47cklu    // This always insures that on next entry, timer is counting.
3711166d06825aca8d7e172776bd1297d6bcd3ad47cklu    //
3721166d06825aca8d7e172776bd1297d6bcd3ad47cklu    mLegacyModeMask &= 0xFFFE;
3731166d06825aca8d7e172776bd1297d6bcd3ad47cklu
3741166d06825aca8d7e172776bd1297d6bcd3ad47cklu    if (Mask != NULL) {
3751166d06825aca8d7e172776bd1297d6bcd3ad47cklu      //
3761166d06825aca8d7e172776bd1297d6bcd3ad47cklu      // Update the Mask for the new mode
3771166d06825aca8d7e172776bd1297d6bcd3ad47cklu      //
3781166d06825aca8d7e172776bd1297d6bcd3ad47cklu      mProtectedModeMask = *Mask;
3791166d06825aca8d7e172776bd1297d6bcd3ad47cklu    }
3801166d06825aca8d7e172776bd1297d6bcd3ad47cklu
3811166d06825aca8d7e172776bd1297d6bcd3ad47cklu    if (EdgeLevel != NULL) {
3821166d06825aca8d7e172776bd1297d6bcd3ad47cklu      //
3831166d06825aca8d7e172776bd1297d6bcd3ad47cklu      // Update the Edge/Level triggered mask for the new mode
3841166d06825aca8d7e172776bd1297d6bcd3ad47cklu      //
3851166d06825aca8d7e172776bd1297d6bcd3ad47cklu      mProtectedModeEdgeLevel = *EdgeLevel;
3861166d06825aca8d7e172776bd1297d6bcd3ad47cklu    }
3871166d06825aca8d7e172776bd1297d6bcd3ad47cklu
3881166d06825aca8d7e172776bd1297d6bcd3ad47cklu    mMode = Mode;
3891166d06825aca8d7e172776bd1297d6bcd3ad47cklu
3901166d06825aca8d7e172776bd1297d6bcd3ad47cklu    //
39190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten    // Write new protected mode mask/trigger level
3921166d06825aca8d7e172776bd1297d6bcd3ad47cklu    //
3931166d06825aca8d7e172776bd1297d6bcd3ad47cklu    Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel);
3941166d06825aca8d7e172776bd1297d6bcd3ad47cklu
3951166d06825aca8d7e172776bd1297d6bcd3ad47cklu    return EFI_SUCCESS;
3961166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
3971166d06825aca8d7e172776bd1297d6bcd3ad47cklu
3981166d06825aca8d7e172776bd1297d6bcd3ad47cklu  return EFI_INVALID_PARAMETER;
3991166d06825aca8d7e172776bd1297d6bcd3ad47cklu}
4001166d06825aca8d7e172776bd1297d6bcd3ad47cklu
40190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten/**
40290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  Translates the IRQ into a vector.
40390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
40490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]   This    Indicates the EFI_LEGACY_8259_PROTOCOL instance.
40590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]   Irq     IRQ0-IRQ15.
40690b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[out]  Vector  The vector that is assigned to the IRQ.
40790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
40890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  EFI_SUCCESS            The Vector that matches Irq was returned.
40990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  EFI_INVALID_PARAMETER  Irq is not valid.
41090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
41190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten**/
4121166d06825aca8d7e172776bd1297d6bcd3ad47ckluEFI_STATUS
4131166d06825aca8d7e172776bd1297d6bcd3ad47ckluEFIAPI
4141166d06825aca8d7e172776bd1297d6bcd3ad47ckluInterrupt8259GetVector (
4151166d06825aca8d7e172776bd1297d6bcd3ad47cklu  IN  EFI_LEGACY_8259_PROTOCOL  *This,
4161166d06825aca8d7e172776bd1297d6bcd3ad47cklu  IN  EFI_8259_IRQ              Irq,
4171166d06825aca8d7e172776bd1297d6bcd3ad47cklu  OUT UINT8                     *Vector
4181166d06825aca8d7e172776bd1297d6bcd3ad47cklu  )
4191166d06825aca8d7e172776bd1297d6bcd3ad47cklu{
4203d78c020d22023d35d27b48817d73ff31a361ac7rsun  if ((UINT32)Irq > Efi8259Irq15) {
4211166d06825aca8d7e172776bd1297d6bcd3ad47cklu    return EFI_INVALID_PARAMETER;
4221166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
4231166d06825aca8d7e172776bd1297d6bcd3ad47cklu
4241166d06825aca8d7e172776bd1297d6bcd3ad47cklu  if (Irq <= Efi8259Irq7) {
4251166d06825aca8d7e172776bd1297d6bcd3ad47cklu    *Vector = (UINT8) (mMasterBase + Irq);
4261166d06825aca8d7e172776bd1297d6bcd3ad47cklu  } else {
4271166d06825aca8d7e172776bd1297d6bcd3ad47cklu    *Vector = (UINT8) (mSlaveBase + (Irq - Efi8259Irq8));
4281166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
4291166d06825aca8d7e172776bd1297d6bcd3ad47cklu
4301166d06825aca8d7e172776bd1297d6bcd3ad47cklu  return EFI_SUCCESS;
4311166d06825aca8d7e172776bd1297d6bcd3ad47cklu}
4321166d06825aca8d7e172776bd1297d6bcd3ad47cklu
4331166d06825aca8d7e172776bd1297d6bcd3ad47cklu/**
43490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  Enables the specified IRQ.
4351166d06825aca8d7e172776bd1297d6bcd3ad47cklu
43690b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  This            Indicates the EFI_LEGACY_8259_PROTOCOL instance.
43790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  Irq             IRQ0-IRQ15.
43890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  LevelTriggered  0 = Edge triggered; 1 = Level triggered.
4391166d06825aca8d7e172776bd1297d6bcd3ad47cklu
44090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  EFI_SUCCESS            The Irq was enabled on the 8259 PIC.
44190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  EFI_INVALID_PARAMETER  The Irq is not valid.
4421166d06825aca8d7e172776bd1297d6bcd3ad47cklu
4431166d06825aca8d7e172776bd1297d6bcd3ad47cklu**/
44490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenEFI_STATUS
44590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenEFIAPI
44690b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenInterrupt8259EnableIrq (
44790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN EFI_LEGACY_8259_PROTOCOL  *This,
44890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN EFI_8259_IRQ              Irq,
44990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN BOOLEAN                   LevelTriggered
45090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  )
4511166d06825aca8d7e172776bd1297d6bcd3ad47cklu{
4523d78c020d22023d35d27b48817d73ff31a361ac7rsun  if ((UINT32)Irq > Efi8259Irq15) {
4531166d06825aca8d7e172776bd1297d6bcd3ad47cklu    return EFI_INVALID_PARAMETER;
4541166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
4551166d06825aca8d7e172776bd1297d6bcd3ad47cklu
456a694b670e1a14b3a4da306463d9760176a73bef3xli  mProtectedModeMask = (UINT16) (mProtectedModeMask & ~(1 << Irq));
4571166d06825aca8d7e172776bd1297d6bcd3ad47cklu  if (LevelTriggered) {
458a694b670e1a14b3a4da306463d9760176a73bef3xli    mProtectedModeEdgeLevel = (UINT16) (mProtectedModeEdgeLevel | (1 << Irq));
4591166d06825aca8d7e172776bd1297d6bcd3ad47cklu  } else {
460a694b670e1a14b3a4da306463d9760176a73bef3xli    mProtectedModeEdgeLevel = (UINT16) (mProtectedModeEdgeLevel & ~(1 << Irq));
4611166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
4621166d06825aca8d7e172776bd1297d6bcd3ad47cklu
4631166d06825aca8d7e172776bd1297d6bcd3ad47cklu  Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel);
4641166d06825aca8d7e172776bd1297d6bcd3ad47cklu
4651166d06825aca8d7e172776bd1297d6bcd3ad47cklu  return EFI_SUCCESS;
4661166d06825aca8d7e172776bd1297d6bcd3ad47cklu}
4671166d06825aca8d7e172776bd1297d6bcd3ad47cklu
4681166d06825aca8d7e172776bd1297d6bcd3ad47cklu/**
46990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  Disables the specified IRQ.
4701166d06825aca8d7e172776bd1297d6bcd3ad47cklu
47190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  This  Indicates the EFI_LEGACY_8259_PROTOCOL instance.
47290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  Irq   IRQ0-IRQ15.
4731166d06825aca8d7e172776bd1297d6bcd3ad47cklu
47490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  EFI_SUCCESS            The Irq was disabled on the 8259 PIC.
47590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  EFI_INVALID_PARAMETER  The Irq is not valid.
4761166d06825aca8d7e172776bd1297d6bcd3ad47cklu
4771166d06825aca8d7e172776bd1297d6bcd3ad47cklu**/
47890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenEFI_STATUS
47990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenEFIAPI
48090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenInterrupt8259DisableIrq (
48190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN EFI_LEGACY_8259_PROTOCOL  *This,
48290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN EFI_8259_IRQ              Irq
48390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  )
4841166d06825aca8d7e172776bd1297d6bcd3ad47cklu{
4853d78c020d22023d35d27b48817d73ff31a361ac7rsun  if ((UINT32)Irq > Efi8259Irq15) {
4861166d06825aca8d7e172776bd1297d6bcd3ad47cklu    return EFI_INVALID_PARAMETER;
4871166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
4881166d06825aca8d7e172776bd1297d6bcd3ad47cklu
48990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  mProtectedModeMask = (UINT16) (mProtectedModeMask | (1 << Irq));
49090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
491a694b670e1a14b3a4da306463d9760176a73bef3xli  mProtectedModeEdgeLevel = (UINT16) (mProtectedModeEdgeLevel & ~(1 << Irq));
4921166d06825aca8d7e172776bd1297d6bcd3ad47cklu
4931166d06825aca8d7e172776bd1297d6bcd3ad47cklu  Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel);
4941166d06825aca8d7e172776bd1297d6bcd3ad47cklu
4951166d06825aca8d7e172776bd1297d6bcd3ad47cklu  return EFI_SUCCESS;
4961166d06825aca8d7e172776bd1297d6bcd3ad47cklu}
4971166d06825aca8d7e172776bd1297d6bcd3ad47cklu
49890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten/**
49990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  Reads the PCI configuration space to get the interrupt number that is assigned to the card.
50090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
50190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]   This       Indicates the EFI_LEGACY_8259_PROTOCOL instance.
50290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]   PciHandle  PCI function for which to return the vector.
50390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[out]  Vector     IRQ number that corresponds to the interrupt line.
50490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
50590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  EFI_SUCCESS  The interrupt line value was read successfully.
50690b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
50790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten**/
5081166d06825aca8d7e172776bd1297d6bcd3ad47ckluEFI_STATUS
5091166d06825aca8d7e172776bd1297d6bcd3ad47ckluEFIAPI
5101166d06825aca8d7e172776bd1297d6bcd3ad47ckluInterrupt8259GetInterruptLine (
5111166d06825aca8d7e172776bd1297d6bcd3ad47cklu  IN  EFI_LEGACY_8259_PROTOCOL  *This,
5121166d06825aca8d7e172776bd1297d6bcd3ad47cklu  IN  EFI_HANDLE                PciHandle,
5131166d06825aca8d7e172776bd1297d6bcd3ad47cklu  OUT UINT8                     *Vector
5141166d06825aca8d7e172776bd1297d6bcd3ad47cklu  )
5151166d06825aca8d7e172776bd1297d6bcd3ad47cklu{
516ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff  EFI_PCI_IO_PROTOCOL *PciIo;
517ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff  UINT8               InterruptLine;
518ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff  EFI_STATUS          Status;
519ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff
520ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff  Status = gBS->HandleProtocol (
521ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff                  PciHandle,
522ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff                  &gEfiPciIoProtocolGuid,
523ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff                  (VOID **) &PciIo
524ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff                  );
525ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff  if (EFI_ERROR (Status)) {
526ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff    return EFI_INVALID_PARAMETER;
527ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff  }
528ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff
529ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff  PciIo->Pci.Read (
530ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff               PciIo,
531ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff               EfiPciIoWidthUint8,
532ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff               PCI_INT_LINE_OFFSET,
533ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff               1,
534ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff               &InterruptLine
535ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff               );
536ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff  //
537ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff  // Interrupt line is same location for standard PCI cards, standard
538ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff  // bridge and CardBus bridge.
539ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff  //
540ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff  *Vector = InterruptLine;
541ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff
542ae6a37f06bce9e1f6218409bc1087c6b34b63ed8vanjeff  return EFI_SUCCESS;
5431166d06825aca8d7e172776bd1297d6bcd3ad47cklu}
5441166d06825aca8d7e172776bd1297d6bcd3ad47cklu
5451166d06825aca8d7e172776bd1297d6bcd3ad47cklu/**
54690b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  Issues the End of Interrupt (EOI) commands to PICs.
5471166d06825aca8d7e172776bd1297d6bcd3ad47cklu
54890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  This  Indicates the EFI_LEGACY_8259_PROTOCOL instance.
54990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  Irq   The interrupt for which to issue the EOI command.
5501166d06825aca8d7e172776bd1297d6bcd3ad47cklu
55190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  EFI_SUCCESS            The EOI command was issued.
55290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  EFI_INVALID_PARAMETER  The Irq is not valid.
5531166d06825aca8d7e172776bd1297d6bcd3ad47cklu
5541166d06825aca8d7e172776bd1297d6bcd3ad47cklu**/
55590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenEFI_STATUS
55690b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenEFIAPI
55790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljustenInterrupt8259EndOfInterrupt (
55890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN EFI_LEGACY_8259_PROTOCOL  *This,
55990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  IN EFI_8259_IRQ              Irq
56090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  )
5611166d06825aca8d7e172776bd1297d6bcd3ad47cklu{
5623d78c020d22023d35d27b48817d73ff31a361ac7rsun  if ((UINT32)Irq > Efi8259Irq15) {
5631166d06825aca8d7e172776bd1297d6bcd3ad47cklu    return EFI_INVALID_PARAMETER;
5641166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
5651166d06825aca8d7e172776bd1297d6bcd3ad47cklu
5661166d06825aca8d7e172776bd1297d6bcd3ad47cklu  if (Irq >= Efi8259Irq8) {
5671166d06825aca8d7e172776bd1297d6bcd3ad47cklu    IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, LEGACY_8259_EOI);
5681166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
5691166d06825aca8d7e172776bd1297d6bcd3ad47cklu
5701166d06825aca8d7e172776bd1297d6bcd3ad47cklu  IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER, LEGACY_8259_EOI);
5711166d06825aca8d7e172776bd1297d6bcd3ad47cklu
5721166d06825aca8d7e172776bd1297d6bcd3ad47cklu  return EFI_SUCCESS;
5731166d06825aca8d7e172776bd1297d6bcd3ad47cklu}
5741166d06825aca8d7e172776bd1297d6bcd3ad47cklu
57590b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten/**
57690b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  Driver Entry point.
57790b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
57890b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  ImageHandle  ImageHandle of the loaded driver.
57990b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @param[in]  SystemTable  Pointer to the EFI System Table.
58090b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
58190b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  EFI_SUCCESS  One or more of the drivers returned a success code.
58290b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten  @retval  !EFI_SUCCESS  Error installing Legacy 8259 Protocol.
58390b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten
58490b8b0ecf56e7282c2a39e1efe4745b74c6fc9d5jljusten**/
5851166d06825aca8d7e172776bd1297d6bcd3ad47ckluEFI_STATUS
5861166d06825aca8d7e172776bd1297d6bcd3ad47ckluEFIAPI
5871166d06825aca8d7e172776bd1297d6bcd3ad47ckluInstall8259 (
5881166d06825aca8d7e172776bd1297d6bcd3ad47cklu  IN EFI_HANDLE        ImageHandle,
5891166d06825aca8d7e172776bd1297d6bcd3ad47cklu  IN EFI_SYSTEM_TABLE  *SystemTable
5901166d06825aca8d7e172776bd1297d6bcd3ad47cklu  )
5911166d06825aca8d7e172776bd1297d6bcd3ad47cklu{
5921166d06825aca8d7e172776bd1297d6bcd3ad47cklu  EFI_STATUS   Status;
5931166d06825aca8d7e172776bd1297d6bcd3ad47cklu  EFI_8259_IRQ Irq;
5941166d06825aca8d7e172776bd1297d6bcd3ad47cklu
5951166d06825aca8d7e172776bd1297d6bcd3ad47cklu  //
596856f592ccf397bd55a242375fc1854a190c776e1mdkinney  // Initialze mask values from PCDs
597856f592ccf397bd55a242375fc1854a190c776e1mdkinney  //
598856f592ccf397bd55a242375fc1854a190c776e1mdkinney  mLegacyModeMask      = PcdGet16 (Pcd8259LegacyModeMask);
599856f592ccf397bd55a242375fc1854a190c776e1mdkinney  mLegacyModeEdgeLevel = PcdGet16 (Pcd8259LegacyModeEdgeLevel);
600856f592ccf397bd55a242375fc1854a190c776e1mdkinney
601856f592ccf397bd55a242375fc1854a190c776e1mdkinney  //
6021166d06825aca8d7e172776bd1297d6bcd3ad47cklu  // Clear all pending interrupt
6031166d06825aca8d7e172776bd1297d6bcd3ad47cklu  //
6041166d06825aca8d7e172776bd1297d6bcd3ad47cklu  for (Irq = Efi8259Irq0; Irq <= Efi8259Irq15; Irq++) {
60524115e44926b33c763f81026690f20efd913daf2ydong    Interrupt8259EndOfInterrupt (&mInterrupt8259, Irq);
6061166d06825aca8d7e172776bd1297d6bcd3ad47cklu  }
6071166d06825aca8d7e172776bd1297d6bcd3ad47cklu
6081166d06825aca8d7e172776bd1297d6bcd3ad47cklu  //
6091166d06825aca8d7e172776bd1297d6bcd3ad47cklu  // Set the 8259 Master base to 0x68 and the 8259 Slave base to 0x70
6101166d06825aca8d7e172776bd1297d6bcd3ad47cklu  //
61124115e44926b33c763f81026690f20efd913daf2ydong  Status = Interrupt8259SetVectorBase (&mInterrupt8259, PROTECTED_MODE_BASE_VECTOR_MASTER, PROTECTED_MODE_BASE_VECTOR_SLAVE);
6121166d06825aca8d7e172776bd1297d6bcd3ad47cklu
6131166d06825aca8d7e172776bd1297d6bcd3ad47cklu  //
6141166d06825aca8d7e172776bd1297d6bcd3ad47cklu  // Set all 8259 interrupts to edge triggered and disabled
6151166d06825aca8d7e172776bd1297d6bcd3ad47cklu  //
6161166d06825aca8d7e172776bd1297d6bcd3ad47cklu  Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel);
6171166d06825aca8d7e172776bd1297d6bcd3ad47cklu
6181166d06825aca8d7e172776bd1297d6bcd3ad47cklu  //
6191166d06825aca8d7e172776bd1297d6bcd3ad47cklu  // Install 8259 Protocol onto a new handle
6201166d06825aca8d7e172776bd1297d6bcd3ad47cklu  //
6211166d06825aca8d7e172776bd1297d6bcd3ad47cklu  Status = gBS->InstallProtocolInterface (
6221166d06825aca8d7e172776bd1297d6bcd3ad47cklu                  &m8259Handle,
6231166d06825aca8d7e172776bd1297d6bcd3ad47cklu                  &gEfiLegacy8259ProtocolGuid,
6241166d06825aca8d7e172776bd1297d6bcd3ad47cklu                  EFI_NATIVE_INTERFACE,
62524115e44926b33c763f81026690f20efd913daf2ydong                  &mInterrupt8259
6261166d06825aca8d7e172776bd1297d6bcd3ad47cklu                  );
6271166d06825aca8d7e172776bd1297d6bcd3ad47cklu  return Status;
6281166d06825aca8d7e172776bd1297d6bcd3ad47cklu}
629