mirror of
https://github.com/transistorfet/moa.git
synced 2024-08-18 18:29:29 +00:00
Moved I/O to a separate thread
but I'm not happy with it, and will likely change it in future, possibly to use two threads and two sets of channels to pass chars back and forth
This commit is contained in:
parent
853626584e
commit
93c9307829
@ -7,21 +7,19 @@ use super::decode::M68kDecoder;
|
|||||||
use super::debugger::M68kDebugger;
|
use super::debugger::M68kDebugger;
|
||||||
|
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum M68kType {
|
pub enum M68kType {
|
||||||
#[allow(dead_code)]
|
|
||||||
MC68000,
|
MC68000,
|
||||||
#[allow(dead_code)]
|
|
||||||
MC68010,
|
MC68010,
|
||||||
#[allow(dead_code)]
|
|
||||||
MC68020,
|
MC68020,
|
||||||
#[allow(dead_code)]
|
|
||||||
MC68030,
|
MC68030,
|
||||||
}
|
}
|
||||||
|
|
||||||
const FLAGS_ON_RESET: u16 = 0x2700;
|
const FLAGS_ON_RESET: u16 = 0x2700;
|
||||||
|
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub enum Flags {
|
pub enum Flags {
|
||||||
Carry = 0x0001,
|
Carry = 0x0001,
|
||||||
@ -36,6 +34,7 @@ pub enum Flags {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub enum Exceptions {
|
pub enum Exceptions {
|
||||||
BusError = 2,
|
BusError = 2,
|
||||||
|
@ -4,6 +4,7 @@ mod error;
|
|||||||
mod memory;
|
mod memory;
|
||||||
mod timers;
|
mod timers;
|
||||||
mod devices;
|
mod devices;
|
||||||
|
mod ttys;
|
||||||
mod interrupts;
|
mod interrupts;
|
||||||
mod cpus;
|
mod cpus;
|
||||||
mod peripherals;
|
mod peripherals;
|
||||||
|
@ -1,15 +1,9 @@
|
|||||||
|
|
||||||
use std::io::{Read, Write};
|
|
||||||
use std::os::unix::io::AsRawFd;
|
|
||||||
|
|
||||||
use nix::fcntl::OFlag;
|
|
||||||
use nix::pty::{self, PtyMaster};
|
|
||||||
use nix::fcntl::{fcntl, FcntlArg};
|
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::system::System;
|
use crate::system::System;
|
||||||
use crate::devices::{Clock, Steppable};
|
use crate::devices::{Clock, Steppable};
|
||||||
use crate::memory::{Address, Addressable, MAX_READ};
|
use crate::memory::{Address, Addressable, MAX_READ};
|
||||||
|
use crate::ttys::{SimplePty, SharedSimplePty};
|
||||||
|
|
||||||
|
|
||||||
const REG_MR1A_MR2A: Address = 0x01;
|
const REG_MR1A_MR2A: Address = 0x01;
|
||||||
@ -77,7 +71,7 @@ const ISR_CH_A_TX_READY: u8 = 0x01;
|
|||||||
const DEV_NAME: &'static str = "mc68681";
|
const DEV_NAME: &'static str = "mc68681";
|
||||||
|
|
||||||
pub struct MC68681Port {
|
pub struct MC68681Port {
|
||||||
pub tty: Option<PtyMaster>,
|
pub tty: Option<SharedSimplePty>,
|
||||||
pub status: u8,
|
pub status: u8,
|
||||||
|
|
||||||
pub tx_enabled: bool,
|
pub tx_enabled: bool,
|
||||||
@ -100,21 +94,15 @@ impl MC68681Port {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn open(&mut self) -> Result<String, Error> {
|
pub fn open(&mut self) -> Result<String, Error> {
|
||||||
let master = pty::posix_openpt(OFlag::O_RDWR).and_then(|master| {
|
let pty = SimplePty::open()?;
|
||||||
pty::grantpt(&master)?;
|
let name = pty.lock().unwrap().name.clone();
|
||||||
pty::unlockpt(&master)?;
|
|
||||||
fcntl(master.as_raw_fd(), FcntlArg::F_SETFL(OFlag::O_NONBLOCK))?;
|
|
||||||
Ok(master)
|
|
||||||
}).map_err(|_| Error::new("Error opening new pseudoterminal"))?;
|
|
||||||
|
|
||||||
let name = unsafe { pty::ptsname(&master).map_err(|_| Error::new("Unable to get pty name"))? };
|
|
||||||
println!("{}: opening pts {}", DEV_NAME, name);
|
println!("{}: opening pts {}", DEV_NAME, name);
|
||||||
self.tty = Some(master);
|
self.tty = Some(pty);
|
||||||
Ok(name)
|
Ok(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_byte(&mut self, data: u8) {
|
pub fn send_byte(&mut self, data: u8) {
|
||||||
self.tty.as_mut().map(|tty| tty.write_all(&[data]));
|
self.tty.as_mut().map(|tty| tty.lock().unwrap().write(data));
|
||||||
self.set_tx_status(false);
|
self.set_tx_status(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,18 +122,15 @@ impl MC68681Port {
|
|||||||
|
|
||||||
pub fn check_rx(&mut self) -> Result<bool, Error> {
|
pub fn check_rx(&mut self) -> Result<bool, Error> {
|
||||||
if self.rx_enabled && (self.status & SR_RX_READY) == 0 && self.tty.is_some() {
|
if self.rx_enabled && (self.status & SR_RX_READY) == 0 && self.tty.is_some() {
|
||||||
let mut buf = [0; 1];
|
|
||||||
let tty = self.tty.as_mut().unwrap();
|
let tty = self.tty.as_mut().unwrap();
|
||||||
match tty.read(&mut buf) {
|
let result = tty.lock().unwrap().read();
|
||||||
Ok(count) => {
|
match result {
|
||||||
self.input = buf[0];
|
Some(input) => {
|
||||||
|
self.input = input;
|
||||||
self.set_rx_status(true);
|
self.set_rx_status(true);
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
},
|
},
|
||||||
Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => { },
|
None => { },
|
||||||
Err(err) => {
|
|
||||||
println!("ERROR: {:?}", err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(false)
|
Ok(false)
|
||||||
|
95
src/ttys.rs
Normal file
95
src/ttys.rs
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
|
||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::os::unix::io::AsRawFd;
|
||||||
|
|
||||||
|
use nix::fcntl::OFlag;
|
||||||
|
use nix::pty::{self, PtyMaster};
|
||||||
|
use nix::fcntl::{fcntl, FcntlArg};
|
||||||
|
|
||||||
|
use crate::error::Error;
|
||||||
|
|
||||||
|
|
||||||
|
pub struct SimplePty {
|
||||||
|
pub name: String,
|
||||||
|
input: Option<u8>,
|
||||||
|
output: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type SharedSimplePty = Arc<Mutex<SimplePty>>;
|
||||||
|
|
||||||
|
impl SimplePty {
|
||||||
|
pub fn new_shared(name: String) -> SharedSimplePty {
|
||||||
|
Arc::new(Mutex::new(SimplePty {
|
||||||
|
name,
|
||||||
|
input: None,
|
||||||
|
output: vec![],
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn open() -> Result<SharedSimplePty, Error> {
|
||||||
|
let pty = pty::posix_openpt(OFlag::O_RDWR).and_then(|pty| {
|
||||||
|
pty::grantpt(&pty)?;
|
||||||
|
pty::unlockpt(&pty)?;
|
||||||
|
fcntl(pty.as_raw_fd(), FcntlArg::F_SETFL(OFlag::O_NONBLOCK))?;
|
||||||
|
Ok(pty)
|
||||||
|
}).map_err(|_| Error::new("Error opening new pseudoterminal"))?;
|
||||||
|
|
||||||
|
let name = unsafe { pty::ptsname(&pty).map_err(|_| Error::new("Unable to get pty name"))? };
|
||||||
|
let shared = SimplePty::new_shared(name);
|
||||||
|
SimplePty::spawn_poller(pty, shared.clone());
|
||||||
|
Ok(shared)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(&mut self) -> Option<u8> {
|
||||||
|
if self.input.is_some() {
|
||||||
|
let input = self.input;
|
||||||
|
self.input = None;
|
||||||
|
input
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&mut self, output: u8) -> bool {
|
||||||
|
self.output.push(output);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spawn_poller(mut pty: PtyMaster, shared: SharedSimplePty) {
|
||||||
|
thread::spawn(move || {
|
||||||
|
println!("pty: spawned reader for {}", shared.lock().unwrap().name);
|
||||||
|
|
||||||
|
let mut buf = [0; 1];
|
||||||
|
loop {
|
||||||
|
{
|
||||||
|
let mut value = shared.lock().unwrap();
|
||||||
|
if value.input.is_none() {
|
||||||
|
match pty.read(&mut buf) {
|
||||||
|
Ok(_) => {
|
||||||
|
(*value).input = Some(buf[0]);
|
||||||
|
},
|
||||||
|
Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => { },
|
||||||
|
Err(err) => {
|
||||||
|
println!("ERROR: {:?}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !value.output.is_empty() {
|
||||||
|
match pty.write_all(value.output.as_slice()) {
|
||||||
|
Ok(()) => { },
|
||||||
|
_ => panic!(""),
|
||||||
|
}
|
||||||
|
(*value).output.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
thread::sleep(Duration::from_millis(10));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user