diff --git a/src/backplane.rs b/src/backplane.rs index 1137c37..5f1baac 100644 --- a/src/backplane.rs +++ b/src/backplane.rs @@ -148,51 +148,43 @@ impl Backplane { } pub fn read_word(&self, address: u32) -> Result { - if let Some(mmu) = self.mmu { - self.cards[mmu] - .borrow_mut() - .try_as_mmu() - .unwrap() - .read_word(address, self) - } else { - self.read_word_phys(address) - } + self.mem_helper( + address, + |mut card| card.read_word(address), + |mut card| card.read_word_io(address as u8), + false, + false, + ) } pub fn read_byte(&self, address: u32) -> Result { - if let Some(mmu) = self.mmu { - self.cards[mmu] - .borrow_mut() - .try_as_mmu() - .unwrap() - .read_byte(address, self) - } else { - self.read_byte_phys(address) - } + self.mem_helper( + address, + |mut card| card.read_byte(address), + |mut card| card.read_byte_io(address as u8), + false, + false, + ) } pub fn write_word(&self, address: u32, data: u16) -> Result<(), BusError> { - if let Some(mmu) = self.mmu { - self.cards[mmu] - .borrow_mut() - .try_as_mmu() - .unwrap() - .write_word(address, data, self) - } else { - self.write_word_phys(address, data) - } + self.mem_helper( + address, + |mut card| card.write_word(address, data), + |mut card| card.write_word_io(address as u8, data), + false, + true, + ) } pub fn write_byte(&self, address: u32, data: u8) -> Result<(), BusError> { - if let Some(mmu) = self.mmu { - self.cards[mmu] - .borrow_mut() - .try_as_mmu() - .unwrap() - .write_byte(address, data, self) - } else { - self.write_byte_phys(address, data) - } + self.mem_helper( + address, + |mut card| card.write_byte(address, data), + |mut card| card.write_byte_io(address as u8, data), + false, + true, + ) } pub fn read_word_phys(&self, address: u32) -> Result { @@ -200,30 +192,41 @@ impl Backplane { address, |mut card| card.read_word(address), |mut card| card.read_word_io(address as u8), + true, + false, ) } + #[allow(dead_code)] pub fn read_byte_phys(&self, address: u32) -> Result { self.mem_helper( address, |mut card| card.read_byte(address), |mut card| card.read_byte_io(address as u8), + true, + false, ) } + #[allow(dead_code)] pub fn write_word_phys(&self, address: u32, data: u16) -> Result<(), BusError> { self.mem_helper( address, |mut card| card.write_word(address, data), |mut card| card.write_word_io(address as u8, data), + true, + true, ) } + #[allow(dead_code)] pub fn write_byte_phys(&self, address: u32, data: u8) -> Result<(), BusError> { self.mem_helper( address, |mut card| card.write_byte(address, data), |mut card| card.write_byte_io(address as u8, data), + true, + true, ) } @@ -232,11 +235,29 @@ impl Backplane { address: u32, mut mem_func: M, mut io_func: I, + bypass_mmu: bool, + write: bool, ) -> Result where M: FnMut(RefMut<'_, dyn Card>) -> NullableResult, I: FnMut(RefMut<'_, dyn Card>) -> NullableResult, { + let address = if bypass_mmu { + address + } else if let Some(card_no) = self.mmu { + match self.cards[card_no] + .borrow_mut() + .try_as_mmu() + .unwrap() + .translate_address(self, address, write) + { + NullableResult::Ok(address) => address, + NullableResult::Err(e) => return Err(e), + NullableResult::Null => return Err(BusError), + } + } else { + address + }; let res = match address { (0..=0x00fe_ffff) | (0x0100_0000..=0xffff_ffff) => self .cards diff --git a/src/card.rs b/src/card.rs index cc25027..d58b100 100644 --- a/src/card.rs +++ b/src/card.rs @@ -141,20 +141,15 @@ pub trait Card: Debug + Display + mopa::Any { mopafy!(Card); pub trait Mmu: Debug { - fn read_word(&mut self, address: u32, backplane: &Backplane) -> Result; - fn read_byte(&mut self, address: u32, backplane: &Backplane) -> Result; - - fn write_word( + fn translate_address( &mut self, - address: u32, - data: u16, backplane: &Backplane, - ) -> Result<(), BusError>; - - fn write_byte(&mut self, address: u32, data: u8, backplane: &Backplane) - -> Result<(), BusError>; + address: u32, + write: bool, + ) -> NullableResult; } + #[allow(dead_code)] pub const fn u64_set_be_byte(val: u64, idx: u8, byte: u8) -> u64 { let mut bytes = val.to_be_bytes(); diff --git a/src/mmu.rs b/src/mmu.rs index efb7227..1cb4e30 100644 --- a/src/mmu.rs +++ b/src/mmu.rs @@ -173,13 +173,13 @@ impl Display for MmuCard { } } -impl MmuCard { +impl Mmu for MmuCard { fn translate_address( &mut self, - address: u32, backplane: &Backplane, + address: u32, write: bool, - ) -> Result { + ) -> NullableResult { let print_debug = self.print_debug; if self.enabled { let page = address >> 12; @@ -197,7 +197,7 @@ impl MmuCard { if print_debug { println!("No mapping frame for this quarter"); } - return Err(BusError); + return NullableResult::Null; } let map_frame = self.map_frames[(page >> 10) as usize]; let entry_address = (map_frame) | ((page & 0x3FF) << 2); @@ -218,7 +218,7 @@ impl MmuCard { if print_debug { println!("Entry not writable"); } - return Err(BusError); + return NullableResult::Err(BusError); } if print_debug { println!( @@ -226,49 +226,17 @@ impl MmuCard { (entry.frame << 12) | offset ); } - Ok((entry.frame << 12) | offset) + NullableResult::Ok((entry.frame << 12) | offset) } else { if print_debug { println!("Entry not present"); } - Err(BusError) + NullableResult::Null } } else { - Ok(address) + NullableResult::Ok(address) } } } -impl Mmu for MmuCard { - fn read_word(&mut self, address: u32, backplane: &Backplane) -> Result { - let address = self.translate_address(address, backplane, false)?; - backplane.read_word_phys(address) - } - - fn read_byte(&mut self, address: u32, backplane: &Backplane) -> Result { - let address = self.translate_address(address, backplane, false)?; - backplane.read_byte_phys(address) - } - - fn write_word( - &mut self, - address: u32, - data: u16, - backplane: &Backplane, - ) -> Result<(), BusError> { - let address = self.translate_address(address, backplane, true)?; - backplane.write_word_phys(address, data) - } - - fn write_byte( - &mut self, - address: u32, - data: u8, - backplane: &Backplane, - ) -> Result<(), BusError> { - let address = self.translate_address(address, backplane, true)?; - backplane.write_byte_phys(address, data) - } -} - register!(MmuCard, "mmu");