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