ax_driver/
binding_info.rs1use alloc::vec::Vec;
2
3use axklib::irq::{legacy_irq_raw, try_legacy_irq};
4use irq_framework::{AcpiGsiRoute, IrqId, IrqSource};
5use rdrive::DeviceId;
6
7#[derive(Clone, Debug, Default, PartialEq, Eq)]
8pub struct BindingInfo {
9 irq: Option<BindingIrq>,
10}
11
12#[derive(Clone, Debug, Eq, PartialEq)]
13pub enum BindingIrq {
14 Id(IrqId),
15 Source(BindingIrqSource),
16}
17
18#[derive(Clone, Debug, Eq, PartialEq)]
19pub enum BindingIrqSource {
20 AcpiGsi(u32),
21 AcpiGsiRoute(AcpiGsiRoute),
22 FdtInterrupt(FdtIrqSpec),
23}
24
25#[derive(Clone, Debug, Eq, PartialEq)]
27pub struct FdtIrqSpec {
28 pub controller: DeviceId,
29 pub cells: Vec<u32>,
30}
31
32#[derive(Clone, Copy, Debug, Eq, PartialEq)]
33#[cfg(feature = "pci")]
34pub enum PciIrqRequirement {
35 Optional,
36 Required,
37}
38
39impl BindingInfo {
40 pub const fn empty() -> Self {
41 Self { irq: None }
42 }
43
44 pub fn with_irq(irq: Option<usize>) -> Result<Self, irq_framework::IrqError> {
45 Ok(Self {
46 irq: irq.map(BindingIrq::try_legacy).transpose()?,
47 })
48 }
49
50 pub fn with_irq_id(irq: Option<IrqId>) -> Self {
51 Self {
52 irq: irq.map(BindingIrq::id),
53 }
54 }
55
56 pub fn with_binding_irq(irq: Option<BindingIrq>) -> Self {
57 Self { irq }
58 }
59
60 pub fn irq(&self) -> Option<&BindingIrq> {
61 self.irq.as_ref()
62 }
63
64 pub fn irq_cloned(&self) -> Option<BindingIrq> {
65 self.irq.clone()
66 }
67
68 pub fn irq_num(&self) -> Option<usize> {
69 self.irq.as_ref().and_then(BindingIrq::legacy_num)
70 }
71}
72
73impl BindingIrq {
74 pub const fn id(id: IrqId) -> Self {
75 Self::Id(id)
76 }
77
78 pub fn try_legacy(raw: usize) -> Result<Self, irq_framework::IrqError> {
79 Ok(Self::Id(try_legacy_irq(raw)?))
80 }
81
82 pub const fn acpi_gsi(gsi: u32) -> Self {
83 Self::Source(BindingIrqSource::AcpiGsi(gsi))
84 }
85
86 pub const fn acpi_gsi_route(route: AcpiGsiRoute) -> Self {
87 Self::Source(BindingIrqSource::AcpiGsiRoute(route))
88 }
89
90 pub fn fdt_interrupt_with_controller(controller: DeviceId, cells: impl Into<Vec<u32>>) -> Self {
91 Self::Source(BindingIrqSource::fdt_interrupt_with_controller(
92 controller, cells,
93 ))
94 }
95
96 pub const fn irq_id(&self) -> Option<IrqId> {
97 match self {
98 Self::Id(id) => Some(*id),
99 Self::Source(_) => None,
100 }
101 }
102
103 pub fn legacy_num(&self) -> Option<usize> {
104 self.irq_id().and_then(legacy_irq_raw)
105 }
106
107 pub fn as_irq_source(&self) -> Option<IrqSource> {
108 match self {
109 Self::Id(_) => None,
110 Self::Source(source) => source.as_irq_source(),
111 }
112 }
113}
114
115impl BindingIrqSource {
116 pub const fn acpi_gsi(gsi: u32) -> Self {
117 Self::AcpiGsi(gsi)
118 }
119
120 pub const fn acpi_gsi_route(route: AcpiGsiRoute) -> Self {
121 Self::AcpiGsiRoute(route)
122 }
123
124 pub fn fdt_interrupt_with_controller(controller: DeviceId, cells: impl Into<Vec<u32>>) -> Self {
125 Self::FdtInterrupt(FdtIrqSpec {
126 controller,
127 cells: cells.into(),
128 })
129 }
130
131 pub fn as_irq_source(&self) -> Option<IrqSource> {
132 match self {
133 Self::AcpiGsi(gsi) => Some(IrqSource::AcpiGsi(*gsi)),
134 Self::AcpiGsiRoute(route) => Some(IrqSource::AcpiGsiRoute(*route)),
135 Self::FdtInterrupt(_) => None,
136 }
137 }
138}
139
140impl From<rdif_intc::AcpiGsiRoute> for BindingIrq {
141 fn from(route: rdif_intc::AcpiGsiRoute) -> Self {
142 Self::Source(BindingIrqSource::from(route))
143 }
144}
145
146impl From<rdif_intc::AcpiGsiRoute> for BindingIrqSource {
147 fn from(route: rdif_intc::AcpiGsiRoute) -> Self {
148 Self::AcpiGsiRoute(AcpiGsiRoute {
149 gsi: route.gsi,
150 vector: route.vector,
151 controller: match route.controller {
152 rdif_intc::AcpiGsiController::IoApic => irq_framework::AcpiGsiController::IoApic,
153 rdif_intc::AcpiGsiController::PchPic => irq_framework::AcpiGsiController::PchPic,
154 },
155 controller_id: route.controller_id,
156 controller_address: route.controller_address,
157 controller_input: route.controller_input,
158 trigger: match route.trigger {
159 rdif_intc::AcpiIrqTrigger::Edge => irq_framework::AcpiIrqTrigger::Edge,
160 rdif_intc::AcpiIrqTrigger::Level => irq_framework::AcpiIrqTrigger::Level,
161 },
162 polarity: match route.polarity {
163 rdif_intc::AcpiIrqPolarity::ActiveHigh => {
164 irq_framework::AcpiIrqPolarity::ActiveHigh
165 }
166 rdif_intc::AcpiIrqPolarity::ActiveLow => irq_framework::AcpiIrqPolarity::ActiveLow,
167 },
168 })
169 }
170}