Modified the read interface yet again

This commit is contained in:
transistor 2021-10-26 17:33:23 -07:00
parent 1ad7ad1807
commit 8bbffbe34c
5 changed files with 34 additions and 27 deletions

View File

@ -39,19 +39,25 @@ pub trait Interruptable {
/// A device that can be addressed to read data from or write data to the device. /// A device that can be addressed to read data from or write data to the device.
pub trait Addressable { pub trait Addressable {
fn len(&self) -> usize; fn len(&self) -> usize;
fn read(&mut self, addr: Address, count: usize) -> Result<[u8; MAX_READ], Error>; fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error>;
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error>; fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error>;
fn read_u8(&mut self, addr: Address) -> Result<u8, Error> { fn read_u8(&mut self, addr: Address) -> Result<u8, Error> {
Ok(self.read(addr, 1)?[0]) let mut data = [0; 1];
self.read(addr, &mut data)?;
Ok(data[0])
} }
fn read_beu16(&mut self, addr: Address) -> Result<u16, Error> { fn read_beu16(&mut self, addr: Address) -> Result<u16, Error> {
Ok(read_beu16(&self.read(addr, 2)?)) let mut data = [0; 2];
self.read(addr, &mut data)?;
Ok(read_beu16(&data))
} }
fn read_beu32(&mut self, addr: Address) -> Result<u32, Error> { fn read_beu32(&mut self, addr: Address) -> Result<u32, Error> {
Ok(read_beu32(&self.read(addr, 4)?)) let mut data = [0; 4];
self.read(addr, &mut data)?;
Ok(read_beu32(&data))
} }
fn write_u8(&mut self, addr: Address, value: u8) -> Result<(), Error> { fn write_u8(&mut self, addr: Address, value: u8) -> Result<(), Error> {

View File

@ -42,13 +42,11 @@ impl Addressable for MemoryBlock {
self.contents.len() self.contents.len()
} }
fn read(&mut self, addr: Address, count: usize) -> Result<[u8; MAX_READ], Error> { fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> {
let mut data = [0; MAX_READ]; for i in 0..data.len() {
//self.contents[(addr as usize) .. (addr as usize + 4)].clone_from_slice(&data);
for i in 0..std::cmp::min(count, MAX_READ) {
data[i] = self.contents[(addr as usize) + i]; data[i] = self.contents[(addr as usize) + i];
} }
Ok(data) Ok(())
} }
fn write(&mut self, mut addr: Address, data: &[u8]) -> Result<(), Error> { fn write(&mut self, mut addr: Address, data: &[u8]) -> Result<(), Error> {
@ -76,21 +74,21 @@ pub struct Block {
pub struct Bus { pub struct Bus {
pub blocks: Vec<Block>, pub blocks: Vec<Block>,
pub mask: Address, pub address_mask: Address,
} }
impl Bus { impl Bus {
pub fn new() -> Bus { pub fn new() -> Bus {
Bus { Bus {
blocks: vec!(), blocks: vec!(),
mask: !0, address_mask: !0,
} }
} }
pub fn address_limit(&mut self, bits: u8) { pub fn set_address_bits(&mut self, bits: u8) {
self.mask = 0; self.address_mask = 0;
for _ in 0..bits { for _ in 0..bits {
self.mask = (self.mask << 1) | 0x01; self.address_mask = (self.address_mask << 1) | 0x01;
} }
} }
@ -106,7 +104,7 @@ impl Bus {
} }
pub fn get_device_at(&self, addr: Address, count: usize) -> Result<(TransmutableBox, Address), Error> { pub fn get_device_at(&self, addr: Address, count: usize) -> Result<(TransmutableBox, Address), Error> {
let addr = addr & self.mask; let addr = addr & self.address_mask;
for block in &self.blocks { for block in &self.blocks {
if addr >= block.base && addr <= (block.base + block.length as Address) { if addr >= block.base && addr <= (block.base + block.length as Address) {
let relative_addr = addr - block.base; let relative_addr = addr - block.base;
@ -146,9 +144,9 @@ impl Addressable for Bus {
(block.base as usize) + block.length (block.base as usize) + block.length
} }
fn read(&mut self, addr: Address, count: usize) -> Result<[u8; MAX_READ], Error> { fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> {
let (dev, relative_addr) = self.get_device_at(addr, count)?; let (dev, relative_addr) = self.get_device_at(addr, data.len())?;
let result = dev.borrow_mut().as_addressable().unwrap().read(relative_addr, count); let result = dev.borrow_mut().as_addressable().unwrap().read(relative_addr, data);
result result
} }
@ -159,4 +157,3 @@ impl Addressable for Bus {
} }
} }

View File

@ -67,9 +67,7 @@ impl Addressable for AtaDevice {
0x30 0x30
} }
fn read(&mut self, addr: Address, _count: usize) -> Result<[u8; MAX_READ], Error> { fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> {
let mut data = [0; MAX_READ];
match addr { match addr {
ATA_REG_DATA_WORD => { ATA_REG_DATA_WORD => {
self.selected_count -= 2; self.selected_count -= 2;
@ -99,7 +97,7 @@ impl Addressable for AtaDevice {
_ => { debug!("{}: reading from {:0x}", DEV_NAME, addr); }, _ => { debug!("{}: reading from {:0x}", DEV_NAME, addr); },
} }
Ok(data) Ok(())
} }
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> { fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {

View File

@ -261,9 +261,7 @@ impl Addressable for MC68681 {
0x30 0x30
} }
fn read(&mut self, addr: Address, _count: usize) -> Result<[u8; MAX_READ], Error> { fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> {
let mut data = [0; MAX_READ];
match addr { match addr {
REG_SRA_RD => { REG_SRA_RD => {
data[0] = self.port_a.status data[0] = self.port_a.status
@ -312,7 +310,7 @@ impl Addressable for MC68681 {
debug!("{}: read from {:0x} of {:0x}", DEV_NAME, addr, data[0]); debug!("{}: read from {:0x} of {:0x}", DEV_NAME, addr, data[0]);
} }
Ok(data) Ok(())
} }
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> { fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {

View File

@ -1,4 +1,12 @@
* each device that can make a bus request should have a BusPort which is used to access the bus. Not sure how it'll be created or passed to the device, since
the offset should be set by the builder or system, and the mask and data size should be sent by the CPU (although I suppose some systems could hook it up differently)
* what about even vs odd accesses? If you access a byte, should the bus port possible turn it into a word access, and return only the byte portion?
this would be more accurate for the 68000 which doesn't have an A0 address pin
* there is clearly an issue with the ROM writing 4 bytes to the data port when the autoincrement is only 2. This might be an issue with the fact that the CPU
is making full long word requests even though the 68000 shouldn't be able to (a long word would be 2 word accesses)
* make devices nameable, using a hashmap to store them * make devices nameable, using a hashmap to store them
* can you eventually make the system connections all configurable via a config file? * can you eventually make the system connections all configurable via a config file?