2 This contains the installation function for the driver.
4 Copyright (c) 2005 - 2008, Intel Corporation
5 All rights reserved. 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
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.
18 // Global for the Legacy 8259 Protocol that is prodiced by this driver
20 EFI_LEGACY_8259_PROTOCOL m8259
= {
21 Interrupt8259SetVectorBase
,
25 Interrupt8259GetVector
,
26 Interrupt8259EnableIrq
,
27 Interrupt8259DisableIrq
,
28 Interrupt8259GetInterruptLine
,
29 Interrupt8259EndOfInterrupt
33 // Global for the handle that the Legacy 8259 Protocol is installed
35 EFI_HANDLE m8259Handle
= NULL
;
37 UINT8 mMasterBase
= 0xff;
38 UINT8 mSlaveBase
= 0xff;
39 EFI_8259_MODE mMode
= Efi8259ProtectedMode
;
40 UINT16 mProtectedModeMask
= 0xffff;
41 UINT16 mLegacyModeMask
= 0x06b8;
42 UINT16 mProtectedModeEdgeLevel
= 0x0000;
43 UINT16 mLegacyModeEdgeLevel
= 0x0000;
49 Interrupt8259WriteMask (
56 Sets the 8250 mask to the valud specified by Mask
59 Mask - A 16 bit valute that represents the master and slave mask values
65 // TODO: EdgeLevel - add argument and description to function comment
67 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER
, (UINT8
) Mask
);
68 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE
, (UINT8
) (Mask
>> 8));
69 IoWrite8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER
, (UINT8
) EdgeLevel
);
70 IoWrite8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE
, (UINT8
) (EdgeLevel
>> 8));
74 Interrupt8259ReadMask (
81 Sets the 8250 mask to the valud specified by Mask
84 Mask - A 16 bit valute that represents the master and slave mask values
90 // TODO: EdgeLevel - add argument and description to function comment
96 MasterValue
= IoRead8 (LEGACY_8259_MASK_REGISTER_MASTER
);
97 SlaveValue
= IoRead8 (LEGACY_8259_MASK_REGISTER_SLAVE
);
99 *Mask
= (UINT16
) (MasterValue
| (SlaveValue
<< 8));
102 if (EdgeLevel
!= NULL
) {
103 MasterValue
= IoRead8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER
);
104 SlaveValue
= IoRead8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE
);
106 *EdgeLevel
= (UINT16
) (MasterValue
| (SlaveValue
<< 8));
110 // Legacy 8259 Protocol Interface Function
114 Interrupt8259SetVectorBase (
115 IN EFI_LEGACY_8259_PROTOCOL
*This
,
122 Sets the base vector for the 8250 Master and Slave interrupt controllers
125 This - Protocol instance pointer.
126 MasterBase - Base vector of the 8259 Master
127 SlaveBase - Base vector of the 8259 Slave
130 EFI_SUCCESS - 8259 programmed
136 if (SlaveBase
!= mSlaveBase
) {
137 mSlaveBase
= SlaveBase
;
140 // Initialize Slave interrupt controller.
142 Mask
= IoRead8 (LEGACY_8259_MASK_REGISTER_SLAVE
);
143 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE
, 0x11);
144 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE
, mSlaveBase
);
145 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE
, 0x02);
146 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE
, 0x01);
147 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE
, Mask
);
150 if (MasterBase
!= mMasterBase
) {
151 mMasterBase
= MasterBase
;
154 // Initialize Master interrupt controller.
156 Mask
= IoRead8 (LEGACY_8259_MASK_REGISTER_MASTER
);
157 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER
, 0x11);
158 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER
, mMasterBase
);
159 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER
, 0x04);
160 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER
, 0x01);
161 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER
, Mask
);
164 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE
, 0x20);
165 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER
, 0x20);
172 Interrupt8259GetMask (
173 IN EFI_LEGACY_8259_PROTOCOL
* This
,
174 OUT UINT16
*LegacyMask
, OPTIONAL
175 OUT UINT16
*LegacyEdgeLevel
, OPTIONAL
176 OUT UINT16
*ProtectedMask
, OPTIONAL
177 OUT UINT16
*ProtectedEdgeLevel OPTIONAL
182 Get the 8259 master and slave address that maps IRQ to processor interrupt
183 vector number. Get the Context of the device including the state of the
187 This - Protocol instance pointer.
190 EFI_SUCCESS - 8259 programmed
191 EFI_DEVICE_ERROR - Error writting to 8259
194 // TODO: LegacyMask - add argument and description to function comment
195 // TODO: LegacyEdgeLevel - add argument and description to function comment
196 // TODO: ProtectedMask - add argument and description to function comment
197 // TODO: ProtectedEdgeLevel - add argument and description to function comment
199 if (LegacyMask
!= NULL
) {
200 *LegacyMask
= mLegacyModeMask
;
203 if (LegacyEdgeLevel
!= NULL
) {
204 *LegacyEdgeLevel
= mLegacyModeEdgeLevel
;
207 if (ProtectedMask
!= NULL
) {
208 *ProtectedMask
= mProtectedModeMask
;
211 if (ProtectedEdgeLevel
!= NULL
) {
212 *ProtectedEdgeLevel
= mProtectedModeEdgeLevel
;
220 Interrupt8259SetMask (
221 IN EFI_LEGACY_8259_PROTOCOL
* This
,
222 IN UINT16
*LegacyMask
, OPTIONAL
223 IN UINT16
*LegacyEdgeLevel
, OPTIONAL
224 IN UINT16
*ProtectedMask
, OPTIONAL
225 IN UINT16
*ProtectedEdgeLevel OPTIONAL
230 Set the 8259 interrupt and edge/level masks for legacy and/or protected
231 mode operation. This routine does not touch the hardware but only the
232 RAM copies of the masks.
235 This - Protocol instance pointer.
238 EFI_SUCCESS - 8259 masks updated
241 // TODO: LegacyMask - add argument and description to function comment
242 // TODO: LegacyEdgeLevel - add argument and description to function comment
243 // TODO: ProtectedMask - add argument and description to function comment
244 // TODO: ProtectedEdgeLevel - add argument and description to function comment
246 if (LegacyMask
!= NULL
) {
247 mLegacyModeMask
= *LegacyMask
;
250 if (LegacyEdgeLevel
!= NULL
) {
251 mLegacyModeEdgeLevel
= *LegacyEdgeLevel
;
254 if (ProtectedMask
!= NULL
) {
255 mProtectedModeMask
= *ProtectedMask
;
258 if (ProtectedEdgeLevel
!= NULL
) {
259 mProtectedModeEdgeLevel
= *ProtectedEdgeLevel
;
267 Interrupt8259SetMode (
268 IN EFI_LEGACY_8259_PROTOCOL
* This
,
269 IN EFI_8259_MODE Mode
,
270 IN UINT16
*Mask
, OPTIONAL
271 IN UINT16
*EdgeLevel OPTIONAL
276 Set the 8259 master and slave address that maps IRQ to processor interrupt
277 vector number. Restore the Context of the device, so that the interrupt
278 mask is put back in it's previous mode.
281 This - Protocol instance pointer.
286 EFI_SUCCESS - 8259 programmed
287 EFI_DEVICE_ERROR - Error writting to 8259
290 // TODO: EdgeLevel - add argument and description to function comment
291 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
297 if (Mode
== Efi8259LegacyMode
) {
299 // Save the protected mode mask
301 Interrupt8259ReadMask (&mProtectedModeMask
, &mProtectedModeEdgeLevel
);
305 // Update the Mask for the new mode
307 mLegacyModeMask
= *Mask
;
310 if (EdgeLevel
!= NULL
) {
312 // Update the Edge/Level triggered mask for the new mode
314 mLegacyModeEdgeLevel
= *EdgeLevel
;
320 // Set 8259 Vector Base
323 Interrupt8259SetVectorBase (This
, LEGACY_MODE_BASE_VECTOR_MASTER
, LEGACY_MODE_BASE_VECTOR_SLAVE
);
328 Interrupt8259WriteMask (mLegacyModeMask
, mLegacyModeEdgeLevel
);
333 if (Mode
== Efi8259ProtectedMode
) {
335 // Save the legacy mode mask
337 Interrupt8259ReadMask (&mLegacyModeMask
, &mLegacyModeEdgeLevel
);
339 // Always force Timer to be enabled after return from 16-bit code.
340 // This always insures that on next entry, timer is counting.
342 mLegacyModeMask
&= 0xFFFE;
346 // Update the Mask for the new mode
348 mProtectedModeMask
= *Mask
;
351 if (EdgeLevel
!= NULL
) {
353 // Update the Edge/Level triggered mask for the new mode
355 mProtectedModeEdgeLevel
= *EdgeLevel
;
361 // Set 8259 Vector Base
364 Interrupt8259SetVectorBase (This
, PROTECTED_MODE_BASE_VECTOR_MASTER
, PROTECTED_MODE_BASE_VECTOR_SLAVE
);
369 Interrupt8259WriteMask (mProtectedModeMask
, mProtectedModeEdgeLevel
);
374 return EFI_INVALID_PARAMETER
;
379 Interrupt8259GetVector (
380 IN EFI_LEGACY_8259_PROTOCOL
*This
,
387 Convert from IRQ to processor interrupt vector number.
390 This - Protocol instance pointer.
391 Irq - 8259 IRQ0 - IRQ15
392 Vector - Processor vector number that matches Irq
395 EFI_SUCCESS - The Vector matching Irq is returned
396 EFI_INVALID_PARAMETER - Irq not valid
400 if (Irq
< Efi8259Irq0
|| Irq
> Efi8259Irq15
) {
401 return EFI_INVALID_PARAMETER
;
404 if (Irq
<= Efi8259Irq7
) {
405 *Vector
= (UINT8
) (mMasterBase
+ Irq
);
407 *Vector
= (UINT8
) (mSlaveBase
+ (Irq
- Efi8259Irq8
));
415 Interrupt8259EnableIrq (
416 IN EFI_LEGACY_8259_PROTOCOL
*This
,
418 IN BOOLEAN LevelTriggered
423 Enable Irq by unmasking interrupt in 8259
426 This - Protocol instance pointer.
427 Irq - 8259 IRQ0 - IRQ15
430 EFI_SUCCESS - Irq enabled on 8259
431 EFI_INVALID_PARAMETER - Irq not valid
434 // TODO: LevelTriggered - add argument and description to function comment
436 if (Irq
< Efi8259Irq0
|| Irq
> Efi8259Irq15
) {
437 return EFI_INVALID_PARAMETER
;
440 mProtectedModeMask
= (UINT16
) (mProtectedModeMask
& ~(1 << Irq
));
441 if (LevelTriggered
) {
442 mProtectedModeEdgeLevel
= (UINT16
) (mProtectedModeEdgeLevel
| (1 << Irq
));
444 mProtectedModeEdgeLevel
= (UINT16
) (mProtectedModeEdgeLevel
& ~(1 << Irq
));
447 Interrupt8259WriteMask (mProtectedModeMask
, mProtectedModeEdgeLevel
);
454 Interrupt8259DisableIrq (
455 IN EFI_LEGACY_8259_PROTOCOL
*This
,
461 Disable Irq by masking interrupt in 8259
464 This - Protocol instance pointer.
465 Irq - 8259 IRQ0 - IRQ15
468 EFI_SUCCESS - Irq disabled on 8259
469 EFI_INVALID_PARAMETER - Irq not valid
473 if (Irq
< Efi8259Irq0
|| Irq
> Efi8259Irq15
) {
474 return EFI_INVALID_PARAMETER
;
477 mProtectedModeMask
= (UINT16
) (mProtectedModeMask
| (1 << Irq
));
478 mProtectedModeEdgeLevel
= (UINT16
) (mProtectedModeEdgeLevel
& ~(1 << Irq
));
480 Interrupt8259WriteMask (mProtectedModeMask
, mProtectedModeEdgeLevel
);
487 Interrupt8259GetInterruptLine (
488 IN EFI_LEGACY_8259_PROTOCOL
*This
,
489 IN EFI_HANDLE PciHandle
,
495 PciHandle represents a PCI config space of a PCI function. Vector
496 represents Interrupt Pin (from PCI config space) and it is the data
497 that is programmed into the Interrupt Line (from the PCI config space)
501 This - Protocol instance pointer.
502 PciHandle - PCI function to return vector for
503 Vector - Vector for fucntion that matches
506 EFI_SUCCESS - A valid Vector is returned
507 EFI_INVALID_PARAMETER - PciHandle not valid
511 return EFI_UNSUPPORTED
;
516 Interrupt8259EndOfInterrupt (
517 IN EFI_LEGACY_8259_PROTOCOL
*This
,
526 This - Protocol instance pointer.
527 Irq - 8259 IRQ0 - IRQ15
530 EFI_SUCCESS - EOI successfully sent to 8259
531 EFI_INVALID_PARAMETER - Irq not valid
535 if (Irq
< Efi8259Irq0
|| Irq
> Efi8259Irq15
) {
536 return EFI_INVALID_PARAMETER
;
539 if (Irq
>= Efi8259Irq8
) {
540 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE
, LEGACY_8259_EOI
);
543 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER
, LEGACY_8259_EOI
);
549 // Legacy 8259 Driver Entry Point
554 IN EFI_HANDLE ImageHandle
,
555 IN EFI_SYSTEM_TABLE
*SystemTable
564 (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
568 EFI_SUCCESS - Legacy 8259 Protocol Installed
571 // TODO: ImageHandle - add argument and description to function comment
572 // TODO: SystemTable - add argument and description to function comment
578 // Clear all pending interrupt
580 for (Irq
= Efi8259Irq0
; Irq
<= Efi8259Irq15
; Irq
++) {
581 Interrupt8259EndOfInterrupt (&m8259
, Irq
);
585 // Set the 8259 Master base to 0x68 and the 8259 Slave base to 0x70
587 Status
= Interrupt8259SetVectorBase (&m8259
, PROTECTED_MODE_BASE_VECTOR_MASTER
, PROTECTED_MODE_BASE_VECTOR_SLAVE
);
590 // Set all 8259 interrupts to edge triggered and disabled
592 Interrupt8259WriteMask (mProtectedModeMask
, mProtectedModeEdgeLevel
);
595 // Install 8259 Protocol onto a new handle
597 Status
= gBS
->InstallProtocolInterface (
599 &gEfiLegacy8259ProtocolGuid
,
600 EFI_NATIVE_INTERFACE
,