Compare commits
No commits in common. "9956962089374b1a747980155d952ee2d26f3eed" and "b5409f3590de76750db9fa8b72ef9376168c1d3c" have entirely different histories.
9956962089
...
b5409f3590
@ -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,
|
||||||
},
|
},
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user