1 use crate::ManagedSlice; 2 use core::alloc::Allocator; 3 4 #[derive(Debug)] 5 pub struct IoApic { 6 pub id: u8, 7 /// The physical address at which to access this I/O APIC. 8 pub address: u32, 9 /// The global system interrupt number where this I/O APIC's inputs start. 10 pub global_system_interrupt_base: u32, 11 } 12 13 #[derive(Debug)] 14 pub struct NmiLine { 15 pub processor: NmiProcessor, 16 pub line: LocalInterruptLine, 17 } 18 19 /// Indicates which local interrupt line will be utilized by an external interrupt. Specifically, 20 /// these lines directly correspond to their requisite LVT entries in a processor's APIC. 21 #[derive(Debug, Clone, Copy, PartialEq, Eq)] 22 pub enum LocalInterruptLine { 23 Lint0, 24 Lint1, 25 } 26 27 #[derive(Debug, Clone, Copy, PartialEq, Eq)] 28 pub enum NmiProcessor { 29 All, 30 ProcessorUid(u32), 31 } 32 33 /// Polarity indicates what signal mode the interrupt line needs to be in to be considered 'active'. 34 #[derive(Debug, Clone, Copy, PartialEq, Eq)] 35 pub enum Polarity { 36 SameAsBus, 37 ActiveHigh, 38 ActiveLow, 39 } 40 41 /// Trigger mode of an interrupt, describing how the interrupt is triggered. 42 /// 43 /// When an interrupt is `Edge` triggered, it is triggered exactly once, when the interrupt 44 /// signal goes from its opposite polarity to its active polarity. 45 /// 46 /// For `Level` triggered interrupts, a continuous signal is emitted so long as the interrupt 47 /// is in its active polarity. 48 /// 49 /// `SameAsBus`-triggered interrupts will utilize the same interrupt triggering as the system bus 50 /// they communicate across. 51 #[derive(Debug, Clone, Copy, PartialEq, Eq)] 52 pub enum TriggerMode { 53 SameAsBus, 54 Edge, 55 Level, 56 } 57 58 /// Describes a difference in the mapping of an ISA interrupt to how it's mapped in other interrupt 59 /// models. For example, if a device is connected to ISA IRQ 0 and IOAPIC input 2, an override will 60 /// appear mapping source 0 to GSI 2. Currently these will only be created for ISA interrupt 61 /// sources. 62 #[derive(Debug)] 63 pub struct InterruptSourceOverride { 64 pub isa_source: u8, 65 pub global_system_interrupt: u32, 66 pub polarity: Polarity, 67 pub trigger_mode: TriggerMode, 68 } 69 70 /// Describes a Global System Interrupt that should be enabled as non-maskable. Any source that is 71 /// non-maskable can not be used by devices. 72 #[derive(Debug)] 73 pub struct NmiSource { 74 pub global_system_interrupt: u32, 75 pub polarity: Polarity, 76 pub trigger_mode: TriggerMode, 77 } 78 79 #[derive(Debug)] 80 pub struct Apic<'a, A> 81 where 82 A: Allocator, 83 { 84 pub local_apic_address: u64, 85 pub io_apics: ManagedSlice<'a, IoApic, A>, 86 pub local_apic_nmi_lines: ManagedSlice<'a, NmiLine, A>, 87 pub interrupt_source_overrides: ManagedSlice<'a, InterruptSourceOverride, A>, 88 pub nmi_sources: ManagedSlice<'a, NmiSource, A>, 89 90 /// If this field is set, you must remap and mask all the lines of the legacy PIC, even if 91 /// you choose to use the APIC. It's recommended that you do this even if ACPI does not 92 /// require you to. 93 pub also_has_legacy_pics: bool, 94 } 95 96 impl<'a, A> Apic<'a, A> 97 where 98 A: Allocator, 99 { new( local_apic_address: u64, io_apics: ManagedSlice<'a, IoApic, A>, local_apic_nmi_lines: ManagedSlice<'a, NmiLine, A>, interrupt_source_overrides: ManagedSlice<'a, InterruptSourceOverride, A>, nmi_sources: ManagedSlice<'a, NmiSource, A>, also_has_legacy_pics: bool, ) -> Self100 pub(crate) fn new( 101 local_apic_address: u64, 102 io_apics: ManagedSlice<'a, IoApic, A>, 103 local_apic_nmi_lines: ManagedSlice<'a, NmiLine, A>, 104 interrupt_source_overrides: ManagedSlice<'a, InterruptSourceOverride, A>, 105 nmi_sources: ManagedSlice<'a, NmiSource, A>, 106 also_has_legacy_pics: bool, 107 ) -> Self { 108 Self { 109 local_apic_address, 110 io_apics, 111 local_apic_nmi_lines, 112 interrupt_source_overrides, 113 nmi_sources, 114 also_has_legacy_pics, 115 } 116 } 117 } 118 119 #[derive(Debug)] 120 #[non_exhaustive] 121 pub enum InterruptModel<'a, A> 122 where 123 A: Allocator, 124 { 125 /// This model is only chosen when the MADT does not describe another interrupt model. On `x86_64` platforms, 126 /// this probably means only the legacy i8259 PIC is present. 127 Unknown, 128 129 /// Describes an interrupt controller based around the Advanced Programmable Interrupt Controller (any of APIC, 130 /// XAPIC, or X2APIC). These are likely to be found on x86 and x86_64 systems and are made up of a Local APIC 131 /// for each core and one or more I/O APICs to handle external interrupts. 132 Apic(Apic<'a, A>), 133 } 134