hal_x86_64/interrupt/
pic.rs1use super::IsaInterrupt;
2use crate::cpu;
3use hal_core::interrupt::{Handlers, RegistrationError};
4
5#[derive(Debug)]
6pub(crate) struct Pic {
7 address: u8,
8 command: cpu::Port,
9 data: cpu::Port,
10}
11
12impl Pic {
13 const fn new(address: u8, command: u16, data: u16) -> Self {
14 Self {
15 address,
16 command: cpu::Port::at(command),
17 data: cpu::Port::at(data),
18 }
19 }
20
21 unsafe fn mask(&mut self, num: u8) {
23 debug_assert!(num < 8);
24 let imr = self.data.readb();
26 self.data.writeb(imr | (1 << num));
28 }
29
30 unsafe fn unmask(&mut self, num: u8) {
32 debug_assert!(num < 8);
33 let imr = self.data.readb();
35 self.data.writeb(imr & !(1 << num));
37 }
38}
39
40#[derive(Debug)]
41pub struct CascadedPic {
42 sisters: PicSisters,
43}
44
45#[derive(Debug)]
48struct PicSisters {
49 big: Pic,
50 little: Pic,
51}
52
53impl PicSisters {
54 pub(crate) const fn new() -> Self {
55 Self {
56 big: Pic::new(0, 0x20, 0x21),
60 little: Pic::new(8, 0xa0, 0xa1),
61 }
62 }
63}
64
65impl CascadedPic {
66 pub(crate) const fn new() -> Self {
67 Self {
68 sisters: PicSisters::new(),
69 }
70 }
71
72 pub(crate) fn mask(&mut self, irq: IsaInterrupt) {
73 let (pic, num) = self.pic_for_irq(irq);
74 unsafe {
75 pic.mask(num);
76 }
77 }
78
79 pub(crate) fn unmask(&mut self, irq: IsaInterrupt) {
80 let (pic, num) = self.pic_for_irq(irq);
81 unsafe {
82 pic.unmask(num);
83 }
84 }
85
86 fn pic_for_irq(&mut self, irq: IsaInterrupt) -> (&mut Pic, u8) {
87 let num = irq as u8;
88 if num >= 8 {
89 (&mut self.sisters.little, num - 8)
90 } else {
91 (&mut self.sisters.big, num)
92 }
93 }
94
95 pub(crate) fn end_interrupt(&mut self, irq: IsaInterrupt) {
96 const END_INTERRUPT: u8 = 0x20; let num = irq as u8;
98 if num >= 8 {
99 unsafe {
100 self.sisters.little.command.writeb(END_INTERRUPT);
101 }
102 }
103
104 unsafe {
105 self.sisters.big.command.writeb(END_INTERRUPT);
106 }
107 }
108}
109
110impl hal_core::interrupt::Control for CascadedPic {
111 type Registers = super::Registers;
112 fn register_handlers<H>(&mut self) -> Result<(), hal_core::interrupt::RegistrationError>
113 where
114 H: Handlers<super::Registers>,
115 {
116 Err(RegistrationError::other(
117 "x86_64 handlers must be registered via the IDT, not to the PIC interrupt component",
118 ))
119 }
120
121 unsafe fn disable(&mut self) {
122 self.sisters.big.data.writeb(0xff);
123 self.sisters.little.data.writeb(0xff);
124 }
125
126 unsafe fn enable(&mut self) {
127 self.sisters.big.data.writeb(0x00);
130 self.sisters.little.data.writeb(0x00);
131 }
132
133 fn is_enabled(&self) -> bool {
134 unimplemented!("ixi do this one!!!")
135 }
136}
137
138impl CascadedPic {
139 pub(crate) unsafe fn set_irq_address(&mut self, primary_start: u8, secondary_start: u8) {
140 let iowait = || cpu::Port::at(0x80).writeb(0);
145
146 let primary_mask = self.sisters.big.data.readb();
147 let secondary_mask = self.sisters.little.data.readb();
148
149 const EXTENDED_CONFIG: u8 = 0x01; const PIC_INIT: u8 = 0x10; self.sisters.big.command.writeb(PIC_INIT | EXTENDED_CONFIG);
153 iowait();
154 self.sisters
155 .little
156 .command
157 .writeb(PIC_INIT | EXTENDED_CONFIG);
158 iowait();
159 self.sisters.big.data.writeb(primary_start);
160 iowait();
161 self.sisters.little.data.writeb(secondary_start);
162 iowait();
163 self.sisters.big.data.writeb(4);
182 iowait();
183 self.sisters.little.data.writeb(2);
186 iowait();
187 self.sisters.big.data.writeb(1); iowait();
189 self.sisters.little.data.writeb(1); iowait();
191
192 self.sisters.big.data.writeb(primary_mask);
193 iowait();
194 self.sisters.little.data.writeb(secondary_mask);
195 iowait();
196 self.sisters.big.address = primary_start;
197 self.sisters.little.address = secondary_start;
198 }
199}