ChainedPics

Struct ChainedPics 

Source
pub struct ChainedPics {
    pub master: Pic,
    pub slave: Pic,
    /* private fields */
}
Expand description

A x86 setup of Chained PICs.

In most PCs there are one master and one slave PIC configuration, each having 8 inputs servicing 16 interrupts. This structure allows to easily initialize and control the x86 configuration of PICs and configure all 16 interrupts for further handling.

Provides a minimal set of functions required to properly handle interrupts based on the currently used mode for each PIC.

Fields§

§master: Pic§slave: Pic

Implementations§

Source§

impl ChainedPics

Source

pub const fn new(master_offset: u8, slave_offset: u8) -> Self

Creates a new instance of Chained Pics.

The master offset and slave offset are two offsets that are pointing to the first interrupt vector of each 8259 chip.

§Panics

This function will panic if the provided offsets will overlap with each other or collide with CPU exceptions.

Source

pub const fn new_contiguous(primary_offset: u8) -> Self

Creates a new instance of a Chained Pics.

The offset must point to the the chosen 16 entries from the IDT that will be used for the software interrupts.

This is a convenience function that maps the PIC1 and PIC2 to a contiguous set of interrupts. This function is equivalent to Self::new(primary_offset, primary_offset + 8).

§Panics

This function will panic if the provided offset will overlap with cpu exceptions. It will always prevent the overlapping between master and slave chips though

Source

pub fn is_initialized(&self) -> bool

Returns true if initialized at least once.

Source

pub fn initialize(&mut self)

Initializes the PICs.

This performs an initialization that is compatible with most x86 PC devices. Some archaic devices may use only one PIC. For such possibilities a manual initialization of PIC structure must be performed.

Source

pub fn operation_mode_change(&mut self, new_op_mode: PicOperationMode)

Changes the operation mode for both master and slave PICs.

This sends the OCW2 command and configures the current operation mode of the PIC logic. Refer to PicOperationMode enum for more details. This function only checks the mode of the master PIC, assuming that slave was not changed manually to something else.

§Note

The IRQ mask must be changed after switching from PicOperationMode::PolledMode.

Source

pub unsafe fn is_spurious(&mut self, vec_id: u8) -> bool

Checks if the provided interrupt vector was caused by PIC properly.

When an IRQ occurs, the PIC chip tells the CPU (via. the PIC’s INTR line) that there’s an interrupt, and the CPU acknowledges this and waits for the PIC to send the interrupt vector. This creates a race condition: if the IRQ disappears after the PIC has told the CPU there’s an interrupt but before the PIC has sent the interrupt vector to the CPU, then the CPU will be waiting for the PIC to tell it which interrupt vector but the PIC won’t have a valid interrupt vector to tell the CPU.

Here we read if the interrupt is written within the ISR register, to be sure that we are dealing with real interrupt. If a spurious interrupt was also sent from the slave PIC, the master shall clear this flag, because he also thinks that it was a legit IRQ.

§Important

This is also the reason why sometimes an unimplemented handler functions are causing general protection faults. PIC will cause an interrupt on the lowest priority IRQ, and the interrupt service routine for something like hard disk controller is most likely not implemented in the stage of configuring PICs.

§Note (Fully Nested Mode)

Spurious interrupts can only happen when the lowest priority IRQ are called. The fake interrupt number is the lowest priority interrupt number for the corresponding PIC chip (IRQ 7 for the master PIC, and IRQ 15 for the slave PIC).

Basically this means that you shall only check for spurious IRQs when it is a parallel port interrupt (IRQ7) or secondary ATA channel interrupt (IRQ15)

§Note (Rotations)

When modes with rotations are used: PicOperationMode::AutomaticRotation, PicOperationMode::SpecialMask, the spurious interrupt can still only be found on IRQ7 for the master PIC or IRQ15 for the slave PIC.

§Note (Polled Mode)

Makes no sense in polled mode. Note also that in polled mode the ISR is always zero, so this function will always mark proper IRQs as spurious.

§Unsafe

This function is unsafe only because it shall be used within the interrupt handler function at the very start, to make sure that we are not handling a spurious interrupt. It is completely forbidden to send an end of interrupt after this function.

Source

pub unsafe fn notify_end_of_interrupt(&mut self, vec_id: u8)

Notify a proper PIC chip that the interrupt was successfully handled and shall be cleared within the ISR register.

§Important

To prevent spurious interrupts on lowest priority IRQs, use ChainedPics::is_spurious and jump to the end of interrupt handler function if it returns true. If some interrupt was caused by a hardware|software error, it should not be handled.

PIC must not receive a EOI command, when it is a spurious interrupts. It can clear other interrupt’s flag, which is a bigger trouble.

Lower priority interrupts vary based on the current mode. The function mentioned above handles all logic required for each.

§Unsafe

This command must be used at the end of every interrupt that was issued by any of two PICs. Make sure that this is a last command withon the interrupt service routine.

Source

pub fn disable(&mut self)

Disable both PICs interrupts.

§Note

This must be used when switching to APIC controller for handling interrupts.

Source

pub fn enable(&mut self)

Enables both PICs interrupts.

They are enabled by default after the initialization.

§Warn

This is not the initialization. Please see ChainedPics::initialize

Source

pub fn disable_slave(&mut self)

Disables the slave PIC fully, i.e IRQ8 … IRQ15.

Source

pub fn enable_slave(&mut self)

Enables the slave PIC, i.e IRQ8 … IRQ15.

Source

pub fn get_mask(&mut self) -> IrqMask

Gets the current IRQ mask.

Source

pub unsafe fn write_mask(&mut self, mask: IrqMask)

Masks the IRQ lines of chained PICs.

§Unsafe

Even though masking just disabled some interrupt lines, this function is marked as unsafe due to undefined behavior that might happen when the OCW1 command is not right.

Source

pub fn with_master<F>(&mut self, f: F)
where F: FnOnce(&mut Pic),

Perform something on the master PIC.

Source

pub fn with_slave<F>(&mut self, f: F)
where F: FnOnce(&mut Pic),

Perform something on the slave PIC.

Source

pub const unsafe fn new_unchecked(master_offset: u8, slave_offset: u8) -> Self

Creates a new instance of PIC controller.

The master offset and slave offset are two offsets that are pointing to the first interrupt vector of each 8259 chip.

§Unsafe

This function will not check if the chosen offsets overlap with each other or do they overlap with CPU exceptions.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.