diff --git a/src/cpus/m68k/state.rs b/src/cpus/m68k/state.rs index 8cb64bf..9bc7388 100644 --- a/src/cpus/m68k/state.rs +++ b/src/cpus/m68k/state.rs @@ -7,21 +7,19 @@ use super::decode::M68kDecoder; use super::debugger::M68kDebugger; +#[allow(dead_code)] #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum M68kType { - #[allow(dead_code)] MC68000, - #[allow(dead_code)] MC68010, - #[allow(dead_code)] MC68020, - #[allow(dead_code)] MC68030, } const FLAGS_ON_RESET: u16 = 0x2700; #[repr(u16)] +#[allow(dead_code)] #[derive(Copy, Clone, Debug, PartialEq)] pub enum Flags { Carry = 0x0001, @@ -36,6 +34,7 @@ pub enum Flags { } #[repr(u8)] +#[allow(dead_code)] #[derive(Copy, Clone, Debug, PartialEq)] pub enum Exceptions { BusError = 2, diff --git a/src/main.rs b/src/main.rs index ae25777..8f7036f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ mod error; mod memory; mod timers; mod devices; +mod ttys; mod interrupts; mod cpus; mod peripherals; diff --git a/src/peripherals/mc68681.rs b/src/peripherals/mc68681.rs index 6bd5ceb..aa2ef84 100644 --- a/src/peripherals/mc68681.rs +++ b/src/peripherals/mc68681.rs @@ -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::system::System; use crate::devices::{Clock, Steppable}; use crate::memory::{Address, Addressable, MAX_READ}; +use crate::ttys::{SimplePty, SharedSimplePty}; const REG_MR1A_MR2A: Address = 0x01; @@ -77,7 +71,7 @@ const ISR_CH_A_TX_READY: u8 = 0x01; const DEV_NAME: &'static str = "mc68681"; pub struct MC68681Port { - pub tty: Option, + pub tty: Option, pub status: u8, pub tx_enabled: bool, @@ -100,21 +94,15 @@ impl MC68681Port { } pub fn open(&mut self) -> Result { - let master = pty::posix_openpt(OFlag::O_RDWR).and_then(|master| { - pty::grantpt(&master)?; - 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"))? }; + let pty = SimplePty::open()?; + let name = pty.lock().unwrap().name.clone(); println!("{}: opening pts {}", DEV_NAME, name); - self.tty = Some(master); + self.tty = Some(pty); Ok(name) } 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); } @@ -134,18 +122,15 @@ impl MC68681Port { pub fn check_rx(&mut self) -> Result { 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(); - match tty.read(&mut buf) { - Ok(count) => { - self.input = buf[0]; + let result = tty.lock().unwrap().read(); + match result { + Some(input) => { + self.input = input; self.set_rx_status(true); return Ok(true); }, - Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => { }, - Err(err) => { - println!("ERROR: {:?}", err); - } + None => { }, } } Ok(false) diff --git a/src/ttys.rs b/src/ttys.rs new file mode 100644 index 0000000..7b0b382 --- /dev/null +++ b/src/ttys.rs @@ -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, + output: Vec, +} + +pub type SharedSimplePty = Arc>; + +impl SimplePty { + pub fn new_shared(name: String) -> SharedSimplePty { + Arc::new(Mutex::new(SimplePty { + name, + input: None, + output: vec![], + })) + } + + pub fn open() -> Result { + 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 { + 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)); + } + }); + } +} +