1use x86_64::instructions::port::Port;
2
3use crate::{
4 error::ControllerError,
5 flags::{
6 ControllerConfigFlags, ControllerStatusFlags, InputPortFlags, OutputPortFlags,
7 TestPortFlags,
8 },
9 keyboard::Keyboard,
10 mouse::Mouse,
11};
12
13const DATA_REGISTER: u16 = 0x60;
14const COMMAND_REGISTER: u16 = 0x64;
15const DEFAULT_TIMEOUT: usize = 10_000;
16
17type Result<T> = core::result::Result<T, ControllerError>;
18
19#[repr(u8)]
20pub(crate) enum Command {
21 ReadInternalRam = 0x20,
22 WriteInternalRam = 0x60,
23 DisableMouse = 0xa7,
24 EnableMouse = 0xa8,
25 TestMouse = 0xa9,
26 TestController = 0xaa,
27 TestKeyboard = 0xab,
28 DiagnosticDump = 0xac,
29 DisableKeyboard = 0xad,
30 EnableKeyboard = 0xae,
31 ReadControllerInput = 0xc0,
32 WriteLowInputNibbleToStatus = 0xc1,
33 WriteHighInputNibbleToStatus = 0xc2,
34 ReadControllerOutput = 0xd0,
35 WriteControllerOutput = 0xd1,
36 WriteKeyboardBuffer = 0xd2,
37 WriteMouseBuffer = 0xd3,
38 WriteMouse = 0xd4,
39 ReadTestPort = 0xe0,
40 PulseOutput = 0xf0,
41}
42
43#[derive(Debug)]
51pub struct Controller {
52 command_register: Port<u8>,
53 data_register: Port<u8>,
54 timeout: usize,
55}
56
57impl Controller {
58 pub const unsafe fn new() -> Self {
65 Self::with_timeout(DEFAULT_TIMEOUT)
66 }
67
68 pub const unsafe fn with_timeout(timeout: usize) -> Self {
71 Self {
72 command_register: Port::new(COMMAND_REGISTER),
73 data_register: Port::new(DATA_REGISTER),
74 timeout,
75 }
76 }
77
78 pub const fn keyboard(&mut self) -> Keyboard<'_> {
80 Keyboard::new(self)
81 }
82
83 pub const fn mouse(&mut self) -> Mouse<'_> {
85 Mouse::new(self)
86 }
87
88 pub fn read_status(&mut self) -> ControllerStatusFlags {
90 ControllerStatusFlags::from_bits_truncate(unsafe { self.command_register.read() })
91 }
92
93 fn wait_for_read(&mut self) -> Result<()> {
94 let mut cycles = 0;
95 while cycles < self.timeout {
96 if self
97 .read_status()
98 .contains(ControllerStatusFlags::OUTPUT_FULL)
99 {
100 return Ok(());
101 }
102 cycles += 1;
103 }
104 Err(ControllerError::Timeout)
105 }
106
107 fn wait_for_write(&mut self) -> Result<()> {
108 let mut cycles = 0;
109 while cycles < self.timeout {
110 if !self
111 .read_status()
112 .contains(ControllerStatusFlags::INPUT_FULL)
113 {
114 return Ok(());
115 }
116 cycles += 1;
117 }
118 Err(ControllerError::Timeout)
119 }
120
121 pub(crate) fn write_command(&mut self, command: Command) -> Result<()> {
122 self.wait_for_write()?;
123 unsafe { self.command_register.write(command as u8) };
124 Ok(())
125 }
126
127 pub fn read_data(&mut self) -> Result<u8> {
132 self.wait_for_read()?;
133 Ok(unsafe { self.data_register.read() })
134 }
135
136 pub fn write_data(&mut self, data: u8) -> Result<()> {
141 self.wait_for_write()?;
142 unsafe { self.data_register.write(data) };
143 Ok(())
144 }
145
146 pub fn read_internal_ram(&mut self, byte_number: u8) -> Result<u8> {
151 let command = Command::ReadInternalRam as u8 | byte_number & 0x1f;
153 self.wait_for_write()?;
155 unsafe {
156 self.command_register.write(command as u8);
157 }
158 self.read_data()
159 }
160
161 pub fn write_internal_ram(&mut self, byte_number: u8, data: u8) -> Result<()> {
166 let command = Command::WriteInternalRam as u8 | byte_number & 0x1f;
168 self.wait_for_write()?;
170 unsafe {
171 self.command_register.write(command as u8);
172 }
173 self.write_data(data)
174 }
175
176 pub fn read_config(&mut self) -> Result<ControllerConfigFlags> {
179 Ok(ControllerConfigFlags::from_bits_truncate(
180 self.read_internal_ram(0)?,
181 ))
182 }
183
184 pub fn write_config(&mut self, config: ControllerConfigFlags) -> Result<()> {
187 self.write_internal_ram(0, config.bits())
188 }
189
190 pub fn disable_mouse(&mut self) -> Result<()> {
192 self.write_command(Command::DisableMouse)
193 }
194
195 pub fn enable_mouse(&mut self) -> Result<()> {
197 self.write_command(Command::EnableMouse)
198 }
199
200 pub fn test_mouse(&mut self) -> Result<()> {
204 self.write_command(Command::TestMouse)?;
205 match self.read_data()? {
206 0x00 => Ok(()),
207 err => Err(ControllerError::TestFailed { response: err }),
208 }
209 }
210
211 pub fn test_controller(&mut self) -> Result<()> {
215 self.write_command(Command::TestController)?;
216 match self.read_data()? {
217 0x55 => Ok(()),
218 err => Err(ControllerError::TestFailed { response: err }),
219 }
220 }
221
222 pub fn test_keyboard(&mut self) -> Result<()> {
226 self.write_command(Command::TestKeyboard)?;
227 match self.read_data()? {
228 0x00 => Ok(()),
229 err => Err(ControllerError::TestFailed { response: err }),
230 }
231 }
232
233 pub fn diagnostic_dump(&mut self) -> Result<[u8; 32]> {
236 self.write_command(Command::DiagnosticDump)?;
237 let mut result = [0; 32];
238 for byte in result.iter_mut() {
239 *byte = self.read_data()?;
240 }
241 Ok(result)
242 }
243
244 pub fn disable_keyboard(&mut self) -> Result<()> {
248 self.write_command(Command::DisableKeyboard)
249 }
250
251 pub fn enable_keyboard(&mut self) -> Result<()> {
255 self.write_command(Command::EnableKeyboard)
256 }
257
258 pub fn read_input_port(&mut self) -> Result<InputPortFlags> {
260 self.write_command(Command::ReadControllerInput)?;
261 Ok(InputPortFlags::from_bits_truncate(self.read_data()?))
262 }
263
264 pub fn write_input_low_nibble_to_status(&mut self) -> Result<()> {
267 self.write_command(Command::WriteLowInputNibbleToStatus)
268 }
269
270 pub fn write_input_high_nibble_to_status(&mut self) -> Result<()> {
273 self.write_command(Command::WriteHighInputNibbleToStatus)
274 }
275
276 pub fn read_output_port(&mut self) -> Result<OutputPortFlags> {
278 self.write_command(Command::ReadControllerOutput)?;
279 Ok(OutputPortFlags::from_bits_truncate(self.read_data()?))
280 }
281
282 pub fn write_output_port(&mut self, output: OutputPortFlags) -> Result<()> {
284 self.write_command(Command::WriteControllerOutput)?;
285 self.write_data(output.bits())
286 }
287
288 pub fn write_keyboard_buffer(&mut self, data: u8) -> Result<()> {
292 self.write_command(Command::WriteKeyboardBuffer)?;
293 self.write_data(data)
294 }
295
296 pub fn write_mouse_buffer(&mut self, data: u8) -> Result<()> {
300 self.write_command(Command::WriteMouseBuffer)?;
301 self.write_data(data)
302 }
303
304 pub fn write_mouse(&mut self, data: u8) -> Result<()> {
306 self.write_command(Command::WriteMouse)?;
307 self.write_data(data)
308 }
309
310 pub fn read_test_port(&mut self) -> Result<TestPortFlags> {
312 self.write_command(Command::ReadTestPort)?;
313 Ok(TestPortFlags::from_bits_truncate(self.read_data()?))
314 }
315
316 pub fn pulse_output_low_nibble(&mut self, data: u8) -> Result<()> {
318 let command = Command::PulseOutput as u8 | data;
320 self.wait_for_write()?;
322 unsafe {
323 self.command_register.write(command as u8);
324 }
325 Ok(())
326 }
327}