Compare commits

..

No commits in common. "9956962089374b1a747980155d952ee2d26f3eed" and "b5409f3590de76750db9fa8b72ef9376168c1d3c" have entirely different histories.

2 changed files with 12 additions and 72 deletions

View File

@ -1,6 +1,5 @@
use std::fmt::Debug; use std::fmt::Debug;
use std::fmt::Display; use std::fmt::Display;
use std::marker::PhantomData;
use anyhow::anyhow; use anyhow::anyhow;
use itertools::Itertools; use itertools::Itertools;
@ -15,41 +14,23 @@ use crate::{
}; };
pub trait DMAHandler: Debug { pub trait DMAHandler: Debug {
fn handle<'a>(&mut self, backplane: &'a Backplane, card_accessor: DMACardAccessorBuilder<'a>); fn handle<'a>(&mut self, backplane: &'a Backplane, card_accessor: DMACardAccessor<'a>);
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
#[allow(dead_code)] #[allow(dead_code)]
pub struct DMACardAccessorBuilder<'a> { pub struct DMACardAccessor<'a> {
backplane: &'a Backplane, backplane: &'a Backplane,
card_no: usize, card_no: usize,
} }
impl<'a> DMACardAccessorBuilder<'a> { impl DMACardAccessor<'_> {
#[allow(dead_code)] #[allow(dead_code)]
pub fn build<T: Card>(self) -> DMACardAccessor<'a, T> { pub fn get<T: Card>(&self) -> Option<MappedMutexGuard<T>> {
DMACardAccessor { MutexGuard::try_map(self.backplane.cards.lock(), |cards| {
backplane: self.backplane, cards[self.card_no].downcast_mut::<T>()
card_no: self.card_no,
card_type: PhantomData,
}
}
}
#[derive(Copy, Clone, Debug)]
#[allow(dead_code)]
pub struct DMACardAccessor<'a, T> {
backplane: &'a Backplane,
card_no: usize,
card_type: PhantomData<T>,
}
impl<T: Card> DMACardAccessor<'_, T> {
#[allow(dead_code)]
pub fn get(&self) -> MappedMutexGuard<T> {
MutexGuard::map(self.backplane.cards.lock(), |cards| {
cards[self.card_no].downcast_mut::<T>().unwrap()
}) })
.ok()
} }
} }
@ -195,7 +176,7 @@ impl Backplane {
for handler in self.dma_handlers.lock().iter_mut() { for handler in self.dma_handlers.lock().iter_mut() {
handler.1.handle( handler.1.handle(
self, self,
DMACardAccessorBuilder { DMACardAccessor {
backplane: self, backplane: self,
card_no: handler.0, card_no: handler.0,
}, },

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
backplane::{Backplane, DMACardAccessorBuilder, DMAHandler}, backplane::DMAHandler,
card::{u16_get_be_byte, u32_get_be_byte, u32_set_be_byte, Card}, card::{u16_get_be_byte, u32_get_be_byte, u32_set_be_byte, Card},
m68k::BusError, m68k::BusError,
register, register,
@ -34,12 +34,10 @@ bitflags! {
#[derive(Debug)] #[derive(Debug)]
pub struct Storage { pub struct Storage {
file: Option<(File, String)>, file: Option<(File, String)>,
transfer: bool, read_data: VecDeque<u8>,
sector: u32, sector: u32,
count: u32, count: u32,
status: Status, status: Status,
read_data: VecDeque<u8>,
start_addresss: u32,
} }
// Registers // Registers
@ -47,7 +45,6 @@ pub struct Storage {
// 0x4-0x8: Sector count // 0x4-0x8: Sector count
// 0x8-0xA: Command (W) / Status(R) // 0x8-0xA: Command (W) / Status(R)
// 0xA-0xC: Data // 0xA-0xC: Data
// 0xC-0x11: Start address for DMA
impl Card for Storage { impl Card for Storage {
fn new(data: Value) -> anyhow::Result<(Self, Option<Box<dyn DMAHandler>>)> { fn new(data: Value) -> anyhow::Result<(Self, Option<Box<dyn DMAHandler>>)> {
@ -63,14 +60,12 @@ impl Card for Storage {
Ok(( Ok((
Self { Self {
file: file.zip(file_name), file: file.zip(file_name),
transfer: false, read_data: VecDeque::new(),
sector: 0, sector: 0,
count: 0, count: 0,
status: Status::empty(), status: Status::empty(),
read_data: VecDeque::new(),
start_addresss: 0,
}, },
Some(Box::new(Dma)), None,
)) ))
} }
@ -85,7 +80,6 @@ impl Card for Storage {
} }
NullableResult::Ok(self.read_data.pop_front().unwrap_or(0)) NullableResult::Ok(self.read_data.pop_front().unwrap_or(0))
} }
0xC..=0x10 => NullableResult::Ok(u32_get_be_byte(self.start_addresss, address - 0xD)),
0xFF => NullableResult::Ok(4), 0xFF => NullableResult::Ok(4),
_ => NullableResult::Null, _ => NullableResult::Null,
} }
@ -113,23 +107,8 @@ impl Card for Storage {
self.status.set(Status::DATA_READY, true); self.status.set(Status::DATA_READY, true);
} }
} }
0x1 => {
if let Some((file, _)) = &mut self.file {
file.seek(SeekFrom::Start(self.sector as u64 * SECTOR_SIZE))
.unwrap();
let mut buf = Vec::new();
buf.resize(self.count as usize * SECTOR_SIZE as usize, 0);
file.read_exact(&mut buf).unwrap();
self.read_data.extend(buf);
self.status.set(Status::BUSY, true);
self.transfer = true;
}
}
_ => (), _ => (),
}, },
0xC..=0x10 => {
self.start_addresss = u32_set_be_byte(self.start_addresss, address - 0xC, data);
}
_ => (), _ => (),
} }
NullableResult::Ok(()) NullableResult::Ok(())
@ -162,23 +141,3 @@ impl Display for Storage {
} }
register!(Storage, "storage"); register!(Storage, "storage");
#[derive(Debug)]
struct Dma;
impl DMAHandler for Dma {
fn handle<'a>(&mut self, backplane: &'a Backplane, card_accessor: DMACardAccessorBuilder<'a>) {
let card_accessor = card_accessor.build::<Storage>();
if card_accessor.get().transfer {
let mut address = card_accessor.get().start_addresss;
#[allow(clippy::redundant_closure_call)]
// Closure is used to drop the mutex guard between pop calls to prevent deadlock
while let Some(data) = (|| card_accessor.get().read_data.pop_front())() {
backplane.write_byte(address, data).unwrap();
address += 1;
}
card_accessor.get().transfer = false;
card_accessor.get().status.set(Status::BUSY, false);
}
}
}