diff --git a/src/backplane.rs b/src/backplane.rs index b23416d..46cfba2 100644 --- a/src/backplane.rs +++ b/src/backplane.rs @@ -3,6 +3,7 @@ use std::cell::{Cell, RefCell, RefMut}; use std::fmt::{Debug, Display}; use std::marker::PhantomData; use std::rc::Rc; +use std::sync::atomic::{AtomicBool, Ordering}; use anyhow::anyhow; use itertools::Itertools; @@ -67,6 +68,7 @@ pub struct Backplane { cards: Vec>>, mmu: Option, in_dma: Cell, + io_at_top_16mb: AtomicBool, } impl Display for Backplane { @@ -130,6 +132,7 @@ impl Backplane { cards, mmu, in_dma: Cell::new(false), + io_at_top_16mb: AtomicBool::new(true), }) } @@ -274,17 +277,35 @@ impl Backplane { .iter() .try_find_map(|card| mem_func(address, card.borrow_mut())) .result(BusError), - (0x00ff_0000..=0x00ff_00ff) | (0xffff_0000..=0xffff_00ff) => backplane_io_func(address) - .optional_result() - .unwrap_or(Ok(T::default())), - (0x00ff_0100..=0x00ff_ffff) | (0xffff_0100..=0xffff_ffff) => self - .cards - .get(((address >> 8) as u8 - 1) as usize) - .map_or(Ok(T::default()), |card| { - io_func(address, card.borrow_mut()) + (0x00ff_0000..=0x00ff_00ff) | (0xffff_0000..=0xffff_00ff) => { + if address < 0x0100_0000 && !self.io_at_top_16mb.load(Ordering::Relaxed) { + self.cards + .iter() + .try_find_map(|card| mem_func(address, card.borrow_mut())) + .result(BusError) + } else { + backplane_io_func(address) .optional_result() .unwrap_or(Ok(T::default())) - }), + } + } + (0x00ff_0100..=0x00ff_ffff) | (0xffff_0100..=0xffff_ffff) => { + if address < 0x0100_0000 && !self.io_at_top_16mb.load(Ordering::Relaxed) { + self.cards + .iter() + .try_find_map(|card| mem_func(address, card.borrow_mut())) + .result(BusError) + } else { + self.cards.get(((address >> 8) as u8 - 1) as usize).map_or( + Ok(T::default()), + |card| { + io_func(address, card.borrow_mut()) + .optional_result() + .unwrap_or(Ok(T::default())) + }, + ) + } + } }; let val = res?; self.handle_dma(); @@ -303,11 +324,22 @@ impl Backplane { } } - fn read_byte_io(&self, _address: u8) -> NullableResult { - NullableResult::Null + fn read_byte_io(&self, address: u8) -> NullableResult { + #[allow(clippy::single_match)] + match address { + 0x1 => NullableResult::Ok(self.io_at_top_16mb.load(Ordering::Relaxed) as u8), + _ => NullableResult::Ok(0), + } } - fn write_byte_io(&self, _address: u8, _data: u8) -> NullableResult<(), BusError> { + fn write_byte_io(&self, address: u8, data: u8) -> NullableResult<(), BusError> { + #[allow(clippy::single_match)] + match address { + 0x1 => self + .io_at_top_16mb + .store((data & 0x1) > 0, Ordering::Relaxed), + _ => (), + } NullableResult::Ok(()) }