1mod keyboard;
17mod display;
18mod timer;
19
20use super::IO_START;
21pub use keyboard::BufferedKeyboard;
22pub use display::BufferedDisplay;
23pub use timer::TimerDevice;
24
25const KBSR: u16 = 0xFE00;
26const KBDR: u16 = 0xFE02;
27const DSR: u16 = 0xFE04;
28const DDR: u16 = 0xFE06;
29const KB_INTV: u8 = 0x80;
30const KB_INTP: u8 = 0b100;
31const DEVICE_SLOTS: usize = IO_START.wrapping_neg() as usize;
32
33pub trait ExternalDevice: Send + Sync + 'static {
35 fn io_read(&mut self, addr: u16, effectful: bool) -> Option<u16>;
40
41 fn io_write(&mut self, addr: u16, data: u16) -> bool;
45
46 fn io_reset(&mut self);
48
49 fn poll_interrupt(&mut self) -> Option<Interrupt>;
55
56 #[doc(hidden)]
61 fn _to_sim_device(self, _: internals::ToSimDeviceToken) -> internals::SimDevice
62 where Self: Sized
63 {
64 internals::SimDevice::Custom(Box::new(self))
65 }
66}
67
68fn _get_dev_id(ports: &[u16], port: u16) -> Option<u16> {
69 ports.get(port.checked_sub(IO_START)? as usize).copied()
70}
71
72#[derive(Debug)]
74pub struct DeviceHandler {
75 devices: Vec<internals::SimDevice>,
76 io_ports: Box<[u16; DEVICE_SLOTS]>
77}
78
79impl DeviceHandler {
80 const NULL_DEV: u16 = 0;
81 const KB_DEV: u16 = 1;
82 const DS_DEV: u16 = 2;
83 const FIXED_DEVS: &'static [u16] = &[Self::NULL_DEV, Self::KB_DEV, Self::DS_DEV];
84
85 pub fn new() -> Self {
87 use internals::SimDevice::Null;
88
89 let mut handler = Self {
90 devices: vec![Null, Null, Null],
91 io_ports: vec![0; DEVICE_SLOTS]
92 .try_into()
93 .expect("array should have the correct number of elements")
94 };
95
96 handler.set_port(KBSR, Self::KB_DEV);
97 handler.set_port(KBDR, Self::KB_DEV);
98 handler.set_port(DSR, Self::DS_DEV);
99 handler.set_port(DDR, Self::DS_DEV);
100
101 handler
102 }
103
104 fn get_dev_id(&self, port: u16) -> Option<u16> {
106 _get_dev_id(&*self.io_ports, port)
107 }
108 fn set_port(&mut self, port: u16, dev_id: u16) -> bool {
110 fn get_dev_id_mut(ports: &mut [u16], port: u16) -> Option<&mut u16> {
111 ports.get_mut(port.checked_sub(IO_START)? as usize)
112 }
113
114 let dev_len = self.devices.len();
115
116 if let Some(d @ 0) = get_dev_id_mut(&mut *self.io_ports, port) {
117 if (dev_id as usize) < dev_len {
118 *d = dev_id;
119 }
120 }
121
122 false
123 }
124
125 pub fn set_keyboard(&mut self, kb: impl ExternalDevice) {
127 self.devices[Self::KB_DEV as usize] = kb._to_sim_device(internals::ToSimDeviceToken(()));
128 }
129 pub fn set_display(&mut self, ds: impl ExternalDevice) {
131 self.devices[Self::DS_DEV as usize] = ds._to_sim_device(internals::ToSimDeviceToken(()));
132 }
133 pub fn add_device<D: ExternalDevice>(&mut self, dev: D, addrs: &[u16]) -> Result<u16, D> {
145 let Ok(dev_id) = u16::try_from(self.devices.len()) else { return Err(dev) };
147 let all_valid_ports = addrs.iter()
149 .copied()
150 .map(|p| self.get_dev_id(p))
151 .all(|m_dev_id| m_dev_id.is_some_and(|d| d == 0));
152 if !all_valid_ports { return Err(dev) };
153
154 self.devices.push(dev._to_sim_device(internals::ToSimDeviceToken(())));
156
157 for &p in addrs {
158 self.set_port(p, dev_id);
159 }
160
161 Ok(dev_id)
162 }
163 pub fn remove_device(&mut self, dev_id: u16) {
165 if let Some(dev_ref) = self.devices.get_mut(dev_id as usize) {
166 std::mem::take(dev_ref);
167
168 if !Self::FIXED_DEVS.contains(&dev_id) {
170 self.io_ports.iter_mut()
171 .filter(|p| **p == dev_id)
172 .for_each(|p| *p = Self::NULL_DEV);
173 }
174 }
175 }
176}
177impl Default for DeviceHandler {
178 fn default() -> Self {
179 Self::new()
180 }
181}
182impl ExternalDevice for DeviceHandler {
183 fn io_read(&mut self, addr: u16, effectful: bool) -> Option<u16> {
185 let dev_id = self.get_dev_id(addr)?;
186 self.devices[dev_id as usize].io_read(addr, effectful)
187 }
188
189 fn io_write(&mut self, addr: u16, data: u16) -> bool {
191 let Some(dev_id) = self.get_dev_id(addr) else { return false };
192 self.devices[dev_id as usize].io_write(addr, data)
193 }
194
195 fn io_reset(&mut self) {
197 self.devices.iter_mut().for_each(ExternalDevice::io_reset)
198 }
199
200 fn poll_interrupt(&mut self) -> Option<Interrupt> {
202 self.devices.iter_mut()
203 .filter_map(|s| s.poll_interrupt())
204 .max_by_key(|i| i.priority().unwrap_or(0b1000))
205 }
206}
207
208#[derive(Debug)]
212pub struct Interrupt {
213 pub(super) kind: InterruptKind
214}
215
216#[derive(Debug)]
217pub(super) enum InterruptKind {
218 Vectored {
220 vect: u8,
222 priority: u8
224 },
225
226 External(ExternalInterrupt)
228}
229impl Interrupt {
230 pub fn vectored(vect: u8, priority: u8) -> Self {
234 Self { kind: InterruptKind::Vectored { vect, priority: priority.clamp(0, 7) } }
235 }
236 pub fn external(e: impl std::error::Error + Send + Sync + 'static) -> Self {
249 Self { kind: InterruptKind::External(ExternalInterrupt::new(e)) }
250 }
251
252 pub fn priority(&self) -> Option<u8> {
257 match self.kind {
258 InterruptKind::Vectored { vect: _, priority } => Some(priority & 0b111),
259 InterruptKind::External(_) => None,
260 }
261 }
262}
263
264#[derive(Debug)]
268pub struct ExternalInterrupt(Box<dyn std::error::Error + Send + Sync + 'static>);
269impl ExternalInterrupt {
270 fn new(e: impl std::error::Error + Send + Sync + 'static) -> Self {
272 ExternalInterrupt(Box::new(e))
273 }
274
275 pub fn into_inner(self) -> Box<dyn std::error::Error + Send + Sync + 'static> {
279 self.0
280 }
281}
282impl std::fmt::Display for ExternalInterrupt {
283 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
284 self.0.fmt(f)
285 }
286}
287impl std::error::Error for ExternalInterrupt {}
288
289
290#[repr(transparent)]
295struct DevWrapper<D, T: ?Sized>(D, std::marker::PhantomData<T>);
296impl<D, T: ?Sized> DevWrapper<D, T> {
297 pub fn wrap(d: &mut D) -> &mut DevWrapper<D, T> {
298 unsafe { &mut *(d as *mut D).cast::<DevWrapper<D, T>>() }
300 }
301}
302impl<D, T: ?Sized> std::ops::Deref for DevWrapper<D, T> {
303 type Target = D;
304
305 fn deref(&self) -> &Self::Target {
306 &self.0
307 }
308}
309impl<D, T: ?Sized> std::ops::DerefMut for DevWrapper<D, T> {
310 fn deref_mut(&mut self) -> &mut Self::Target {
311 &mut self.0
312 }
313}
314mod internals {
317 use super::{BufferedDisplay, BufferedKeyboard, ExternalDevice, NullDevice};
318
319 #[derive(Default)]
320 pub enum SimDevice {
321 #[default]
322 Null,
323 Keyboard(BufferedKeyboard),
324 Display(BufferedDisplay),
325 Custom(Box<dyn ExternalDevice + Send + Sync + 'static>)
326 }
327
328 impl ExternalDevice for SimDevice {
329 fn io_read(&mut self, addr: u16, effectful: bool) -> Option<u16> {
330 match self {
331 SimDevice::Null => NullDevice.io_read(addr, effectful),
332 SimDevice::Keyboard(dev) => dev.io_read(addr, effectful),
333 SimDevice::Display(dev) => dev.io_read(addr, effectful),
334 SimDevice::Custom(dev) => dev.io_read(addr, effectful),
335 }
336 }
337
338 fn io_write(&mut self, addr: u16, data: u16) -> bool {
339 match self {
340 SimDevice::Null => NullDevice.io_write(addr, data),
341 SimDevice::Keyboard(dev) => dev.io_write(addr, data),
342 SimDevice::Display(dev) => dev.io_write(addr, data),
343 SimDevice::Custom(dev) => dev.io_write(addr, data),
344 }
345 }
346
347 fn io_reset(&mut self) {
348 match self {
349 SimDevice::Null => NullDevice.io_reset(),
350 SimDevice::Keyboard(dev) => dev.io_reset(),
351 SimDevice::Display(dev) => dev.io_reset(),
352 SimDevice::Custom(dev) => dev.io_reset(),
353 }
354 }
355
356 fn poll_interrupt(&mut self) -> Option<super::Interrupt> {
357 match self {
358 SimDevice::Null => NullDevice.poll_interrupt(),
359 SimDevice::Keyboard(dev) => dev.poll_interrupt(),
360 SimDevice::Display(dev) => dev.poll_interrupt(),
361 SimDevice::Custom(dev) => dev.poll_interrupt(),
362 }
363 }
364 }
365 impl std::fmt::Debug for SimDevice {
366 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
367 match self {
368 Self::Null => write!(f, "Null"),
369 Self::Keyboard(_) => f.debug_struct("Keyboard").finish_non_exhaustive(),
370 Self::Display(_) => f.debug_struct("Display").finish_non_exhaustive(),
371 Self::Custom(_) => f.debug_struct("Custom").finish_non_exhaustive(),
372 }
373 }
374 }
375
376 pub struct ToSimDeviceToken(pub ());
378}
379
380#[derive(Default, Clone, Copy, PartialEq, Eq)]
386pub struct NullDevice;
387impl ExternalDevice for NullDevice {
388 fn io_read(&mut self, _addr: u16, _effectful: bool) -> Option<u16> {
389 None
390 }
391
392 fn io_write(&mut self, _addr: u16, _data: u16) -> bool {
393 false
394 }
395
396 fn io_reset(&mut self) {}
397
398 fn poll_interrupt(&mut self) -> Option<Interrupt> {
399 None
400 }
401
402 fn _to_sim_device(self, _: internals::ToSimDeviceToken) -> internals::SimDevice
403 where Self: Sized
404 {
405 internals::SimDevice::Null
406 }
407}
408
409#[allow(clippy::type_complexity)]
411pub struct InterruptFromFn(Box<dyn FnMut() -> Option<Interrupt> + Send + Sync + 'static>);
412impl InterruptFromFn {
413 pub fn new(f: impl FnMut() -> Option<Interrupt> + Send + Sync + 'static) -> Self {
415 Self(Box::new(f))
416 }
417}
418impl std::fmt::Debug for InterruptFromFn {
419 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
420 f.debug_struct("InterruptFromFn").finish_non_exhaustive()
421 }
422}
423impl ExternalDevice for InterruptFromFn {
424 fn io_read(&mut self, _addr: u16, _effectful: bool) -> Option<u16> {
425 None
426 }
427
428 fn io_write(&mut self, _addr: u16, _data: u16) -> bool {
429 false
430 }
431
432 fn io_reset(&mut self) {}
433
434 fn poll_interrupt(&mut self) -> Option<Interrupt> {
435 (self.0)()
436 }
437}
438
439fn resolve_lock<G>(e: std::sync::TryLockResult<G>) -> Option<G> {
440 use std::sync::TryLockError;
441
442 match e {
443 Ok(guard) => Some(guard),
444 Err(TryLockError::WouldBlock) => None,
445 Err(TryLockError::Poisoned(e)) => Some(e.into_inner())
446 }
447}
448impl<D: ExternalDevice> ExternalDevice for std::sync::Arc<std::sync::RwLock<D>> {
449 fn io_read(&mut self, addr: u16, effectful: bool) -> Option<u16> {
450 resolve_lock(self.try_write())?
451 .io_read(addr, effectful)
452 }
453
454 fn io_write(&mut self, addr: u16, data: u16) -> bool {
455 resolve_lock(self.try_write())
456 .is_some_and(|mut g| g.io_write(addr, data))
457 }
458
459 fn io_reset(&mut self) {
460 if let Some(mut guard) = resolve_lock(self.try_write()) {
461 guard.io_reset();
462 }
463 }
464
465 fn poll_interrupt(&mut self) -> Option<Interrupt> {
466 resolve_lock(self.try_write())
467 .and_then(|mut g| g.poll_interrupt())
468 }
469}
470impl<D: ExternalDevice> ExternalDevice for std::sync::Arc<std::sync::Mutex<D>> {
471 fn io_read(&mut self, addr: u16, effectful: bool) -> Option<u16> {
472 resolve_lock(self.try_lock())?
473 .io_read(addr, effectful)
474 }
475
476 fn io_write(&mut self, addr: u16, data: u16) -> bool {
477 resolve_lock(self.try_lock())
478 .is_some_and(|mut g| g.io_write(addr, data))
479 }
480
481 fn io_reset(&mut self) {
482 if let Some(mut guard) = resolve_lock(self.try_lock()) {
483 guard.io_reset();
484 }
485 }
486
487 fn poll_interrupt(&mut self) -> Option<Interrupt> {
488 resolve_lock(self.try_lock())
489 .and_then(|mut g| g.poll_interrupt())
490 }
491}