2 This contains the installation function for the driver.
4 Copyright (c) 2005 - 2007, 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 CPU I/O Protocol that is consumed by this driver
20 EFI_CPU_IO_PROTOCOL
*mCpuIo
;
23 // Global for the Legacy 8259 Protocol that is prodiced by this driver
25 EFI_LEGACY_8259_PROTOCOL m8259
= {
26 Interrupt8259SetVectorBase
,
30 Interrupt8259GetVector
,
31 Interrupt8259EnableIrq
,
32 Interrupt8259DisableIrq
,
33 Interrupt8259GetInterruptLine
,
34 Interrupt8259EndOfInterrupt
38 // Global for the handle that the Legacy 8259 Protocol is installed
40 EFI_HANDLE m8259Handle
= NULL
;
42 UINT8 mMasterBase
= 0xff;
43 UINT8 mSlaveBase
= 0xff;
44 EFI_8259_MODE mMode
= Efi8259ProtectedMode
;
45 UINT16 mProtectedModeMask
= 0xffff;
46 UINT16 mLegacyModeMask
= 0x06b8;
47 UINT16 mProtectedModeEdgeLevel
= 0x0000;
48 UINT16 mLegacyModeEdgeLevel
= 0x0000;
61 Writes an I/O port using the CPU I/O Protocol
64 Register - I/O Port to write
65 Value - The 8 bit value to write to Port
72 mCpuIo
->Io
.Write (mCpuIo
, EfiCpuIoWidthUint8
, Port
, 1, &Value
);
82 Writes an I/O port using the CPU I/O Protocol
85 Register - I/O Port to write
86 Value - The 8 bit value to write to Port
95 mCpuIo
->Io
.Read (mCpuIo
, EfiCpuIoWidthUint8
, Port
, 1, &Value
);
100 Interrupt8259WriteMask (
107 Sets the 8250 mask to the valud specified by Mask
110 Mask - A 16 bit valute that represents the master and slave mask values
116 // TODO: EdgeLevel - add argument and description to function comment
118 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER
, (UINT8
) Mask
);
119 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE
, (UINT8
) (Mask
>> 8));
120 IoWrite8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER
, (UINT8
) EdgeLevel
);
121 IoWrite8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE
, (UINT8
) (EdgeLevel
>> 8));
125 Interrupt8259ReadMask (
132 Sets the 8250 mask to the valud specified by Mask
135 Mask - A 16 bit valute that represents the master and slave mask values
141 // TODO: EdgeLevel - add argument and description to function comment
144 *Mask
= (UINT16
) (IoRead8 (LEGACY_8259_MASK_REGISTER_MASTER
) | (IoRead8 (LEGACY_8259_MASK_REGISTER_SLAVE
) << 8));
147 if (EdgeLevel
!= NULL
) {
148 *EdgeLevel
= (UINT16
)
150 IoRead8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER
) |
151 (IoRead8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE
) << 8)
156 // Legacy 8259 Protocol Interface Function
160 Interrupt8259SetVectorBase (
161 IN EFI_LEGACY_8259_PROTOCOL
*This
,
168 Sets the base vector for the 8250 Master and Slave interrupt controllers
171 This - Protocol instance pointer.
172 MasterBase - Base vector of the 8259 Master
173 SlaveBase - Base vector of the 8259 Slave
176 EFI_SUCCESS - 8259 programmed
182 if (SlaveBase
!= mSlaveBase
) {
183 mSlaveBase
= SlaveBase
;
186 // Initialize Slave interrupt controller.
188 Mask
= IoRead8 (LEGACY_8259_MASK_REGISTER_SLAVE
);
189 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE
, 0x11);
190 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE
, mSlaveBase
);
191 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE
, 0x02);
192 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE
, 0x01);
193 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE
, Mask
);
196 if (MasterBase
!= mMasterBase
) {
197 mMasterBase
= MasterBase
;
200 // Initialize Master interrupt controller.
202 Mask
= IoRead8 (LEGACY_8259_MASK_REGISTER_MASTER
);
203 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER
, 0x11);
204 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER
, mMasterBase
);
205 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER
, 0x04);
206 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER
, 0x01);
207 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER
, Mask
);
210 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE
, 0x20);
211 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER
, 0x20);
218 Interrupt8259GetMask (
219 IN EFI_LEGACY_8259_PROTOCOL
* This
,
220 OUT UINT16
*LegacyMask
, OPTIONAL
221 OUT UINT16
*LegacyEdgeLevel
, OPTIONAL
222 OUT UINT16
*ProtectedMask
, OPTIONAL
223 OUT UINT16
*ProtectedEdgeLevel OPTIONAL
228 Get the 8259 master and slave address that maps IRQ to processor interrupt
229 vector number. Get the Context of the device including the state of the
233 This - Protocol instance pointer.
236 EFI_SUCCESS - 8259 programmed
237 EFI_DEVICE_ERROR - Error writting to 8259
240 // TODO: LegacyMask - add argument and description to function comment
241 // TODO: LegacyEdgeLevel - add argument and description to function comment
242 // TODO: ProtectedMask - add argument and description to function comment
243 // TODO: ProtectedEdgeLevel - add argument and description to function comment
245 if (LegacyMask
!= NULL
) {
246 *LegacyMask
= mLegacyModeMask
;
249 if (LegacyEdgeLevel
!= NULL
) {
250 *LegacyEdgeLevel
= mLegacyModeEdgeLevel
;
253 if (ProtectedMask
!= NULL
) {
254 *ProtectedMask
= mProtectedModeMask
;
257 if (ProtectedEdgeLevel
!= NULL
) {
258 *ProtectedEdgeLevel
= mProtectedModeEdgeLevel
;
266 Interrupt8259SetMask (
267 IN EFI_LEGACY_8259_PROTOCOL
* This
,
268 IN UINT16
*LegacyMask
, OPTIONAL
269 IN UINT16
*LegacyEdgeLevel
, OPTIONAL
270 IN UINT16
*ProtectedMask
, OPTIONAL
271 IN UINT16
*ProtectedEdgeLevel OPTIONAL
276 Set the 8259 interrupt and edge/level masks for legacy and/or protected
277 mode operation. This routine does not touch the hardware but only the
278 RAM copies of the masks.
281 This - Protocol instance pointer.
284 EFI_SUCCESS - 8259 masks updated
287 // TODO: LegacyMask - add argument and description to function comment
288 // TODO: LegacyEdgeLevel - add argument and description to function comment
289 // TODO: ProtectedMask - add argument and description to function comment
290 // TODO: ProtectedEdgeLevel - add argument and description to function comment
292 if (LegacyMask
!= NULL
) {
293 mLegacyModeMask
= *LegacyMask
;
296 if (LegacyEdgeLevel
!= NULL
) {
297 mLegacyModeEdgeLevel
= *LegacyEdgeLevel
;
300 if (ProtectedMask
!= NULL
) {
301 mProtectedModeMask
= *ProtectedMask
;
304 if (ProtectedEdgeLevel
!= NULL
) {
305 mProtectedModeEdgeLevel
= *ProtectedEdgeLevel
;
313 Interrupt8259SetMode (
314 IN EFI_LEGACY_8259_PROTOCOL
* This
,
315 IN EFI_8259_MODE Mode
,
316 IN UINT16
*Mask
, OPTIONAL
317 IN UINT16
*EdgeLevel OPTIONAL
322 Set the 8259 master and slave address that maps IRQ to processor interrupt
323 vector number. Restore the Context of the device, so that the interrupt
324 mask is put back in it's previous mode.
327 This - Protocol instance pointer.
332 EFI_SUCCESS - 8259 programmed
333 EFI_DEVICE_ERROR - Error writting to 8259
336 // TODO: EdgeLevel - add argument and description to function comment
337 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
343 if (Mode
== Efi8259LegacyMode
) {
345 // Save the protected mode mask
347 Interrupt8259ReadMask (&mProtectedModeMask
, &mProtectedModeEdgeLevel
);
351 // Update the Mask for the new mode
353 mLegacyModeMask
= *Mask
;
356 if (EdgeLevel
!= NULL
) {
358 // Update the Edge/Level triggered mask for the new mode
360 mLegacyModeEdgeLevel
= *EdgeLevel
;
366 // Set 8259 Vector Base
369 Interrupt8259SetVectorBase (This
, LEGACY_MODE_BASE_VECTOR_MASTER
, LEGACY_MODE_BASE_VECTOR_SLAVE
);
374 Interrupt8259WriteMask (mLegacyModeMask
, mLegacyModeEdgeLevel
);
379 if (Mode
== Efi8259ProtectedMode
) {
381 // Save the legacy mode mask
383 Interrupt8259ReadMask (&mLegacyModeMask
, &mLegacyModeEdgeLevel
);
385 // Always force Timer to be enabled after return from 16-bit code.
386 // This always insures that on next entry, timer is counting.
388 mLegacyModeMask
&= 0xFFFE;
392 // Update the Mask for the new mode
394 mProtectedModeMask
= *Mask
;
397 if (EdgeLevel
!= NULL
) {
399 // Update the Edge/Level triggered mask for the new mode
401 mProtectedModeEdgeLevel
= *EdgeLevel
;
407 // Set 8259 Vector Base
410 Interrupt8259SetVectorBase (This
, PROTECTED_MODE_BASE_VECTOR_MASTER
, PROTECTED_MODE_BASE_VECTOR_SLAVE
);
415 Interrupt8259WriteMask (mProtectedModeMask
, mProtectedModeEdgeLevel
);
420 return EFI_INVALID_PARAMETER
;
425 Interrupt8259GetVector (
426 IN EFI_LEGACY_8259_PROTOCOL
*This
,
433 Convert from IRQ to processor interrupt vector number.
436 This - Protocol instance pointer.
437 Irq - 8259 IRQ0 - IRQ15
438 Vector - Processor vector number that matches Irq
441 EFI_SUCCESS - The Vector matching Irq is returned
442 EFI_INVALID_PARAMETER - Irq not valid
446 if (Irq
< Efi8259Irq0
|| Irq
> Efi8259Irq15
) {
447 return EFI_INVALID_PARAMETER
;
450 if (Irq
<= Efi8259Irq7
) {
451 *Vector
= (UINT8
) (mMasterBase
+ Irq
);
453 *Vector
= (UINT8
) (mSlaveBase
+ (Irq
- Efi8259Irq8
));
461 Interrupt8259EnableIrq (
462 IN EFI_LEGACY_8259_PROTOCOL
*This
,
464 IN BOOLEAN LevelTriggered
469 Enable Irq by unmasking interrupt in 8259
472 This - Protocol instance pointer.
473 Irq - 8259 IRQ0 - IRQ15
476 EFI_SUCCESS - Irq enabled on 8259
477 EFI_INVALID_PARAMETER - Irq not valid
480 // TODO: LevelTriggered - add argument and description to function comment
482 if (Irq
< Efi8259Irq0
|| Irq
> Efi8259Irq15
) {
483 return EFI_INVALID_PARAMETER
;
486 mProtectedModeMask
&= ~(1 << Irq
);
487 if (LevelTriggered
) {
488 mProtectedModeEdgeLevel
|= (1 << Irq
);
490 mProtectedModeEdgeLevel
&= ~(1 << Irq
);
493 Interrupt8259WriteMask (mProtectedModeMask
, mProtectedModeEdgeLevel
);
500 Interrupt8259DisableIrq (
501 IN EFI_LEGACY_8259_PROTOCOL
*This
,
507 Disable Irq by masking interrupt in 8259
510 This - Protocol instance pointer.
511 Irq - 8259 IRQ0 - IRQ15
514 EFI_SUCCESS - Irq disabled on 8259
515 EFI_INVALID_PARAMETER - Irq not valid
519 if (Irq
< Efi8259Irq0
|| Irq
> Efi8259Irq15
) {
520 return EFI_INVALID_PARAMETER
;
523 mProtectedModeMask
|= (1 << Irq
);
524 mProtectedModeEdgeLevel
&= ~(1 << Irq
);
526 Interrupt8259WriteMask (mProtectedModeMask
, mProtectedModeEdgeLevel
);
533 Interrupt8259GetInterruptLine (
534 IN EFI_LEGACY_8259_PROTOCOL
*This
,
535 IN EFI_HANDLE PciHandle
,
541 PciHandle represents a PCI config space of a PCI function. Vector
542 represents Interrupt Pin (from PCI config space) and it is the data
543 that is programmed into the Interrupt Line (from the PCI config space)
547 This - Protocol instance pointer.
548 PciHandle - PCI function to return vector for
549 Vector - Vector for fucntion that matches
552 EFI_SUCCESS - A valid Vector is returned
553 EFI_INVALID_PARAMETER - PciHandle not valid
557 return EFI_UNSUPPORTED
;
562 Interrupt8259EndOfInterrupt (
563 IN EFI_LEGACY_8259_PROTOCOL
*This
,
572 This - Protocol instance pointer.
573 Irq - 8259 IRQ0 - IRQ15
576 EFI_SUCCESS - EOI successfully sent to 8259
577 EFI_INVALID_PARAMETER - Irq not valid
581 if (Irq
< Efi8259Irq0
|| Irq
> Efi8259Irq15
) {
582 return EFI_INVALID_PARAMETER
;
585 if (Irq
>= Efi8259Irq8
) {
586 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE
, LEGACY_8259_EOI
);
589 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER
, LEGACY_8259_EOI
);
595 // Legacy 8259 Driver Entry Point
600 IN EFI_HANDLE ImageHandle
,
601 IN EFI_SYSTEM_TABLE
*SystemTable
610 (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
614 EFI_SUCCESS - Legacy 8259 Protocol Installed
617 // TODO: ImageHandle - add argument and description to function comment
618 // TODO: SystemTable - add argument and description to function comment
624 // Find the CPU I/O Protocol
626 Status
= gBS
->LocateProtocol (&gEfiCpuIoProtocolGuid
, NULL
, (VOID
**) &mCpuIo
);
627 ASSERT_EFI_ERROR (Status
);
630 // Clear all pending interrupt
632 for (Irq
= Efi8259Irq0
; Irq
<= Efi8259Irq15
; Irq
++) {
633 Interrupt8259EndOfInterrupt (&m8259
, Irq
);
637 // Set the 8259 Master base to 0x68 and the 8259 Slave base to 0x70
639 Status
= Interrupt8259SetVectorBase (&m8259
, PROTECTED_MODE_BASE_VECTOR_MASTER
, PROTECTED_MODE_BASE_VECTOR_SLAVE
);
642 // Set all 8259 interrupts to edge triggered and disabled
644 Interrupt8259WriteMask (mProtectedModeMask
, mProtectedModeEdgeLevel
);
647 // Install 8259 Protocol onto a new handle
649 Status
= gBS
->InstallProtocolInterface (
651 &gEfiLegacy8259ProtocolGuid
,
652 EFI_NATIVE_INTERFACE
,