From 402b46561b3f5e4351ab45c599cee8acfb2c2b39 Mon Sep 17 00:00:00 2001 From: TheSchemm Date: Sat, 17 Jun 2017 17:07:19 -0500 Subject: [PATCH] Refactored ihdad and added Qemu support. --- ihdad/src/HDA/CommandBuffer.rs | 146 ----- ihdad/src/HDA/cmdbuff.rs | 469 ++++++++++++++ ihdad/src/HDA/common.rs | 150 ++++- ihdad/src/HDA/device.rs | 1052 +++++++++++++------------------- ihdad/src/HDA/mod.rs | 5 +- ihdad/src/HDA/node.rs | 31 +- ihdad/src/HDA/stream.rs | 117 +++- ihdad/src/main.rs | 34 +- 8 files changed, 1179 insertions(+), 825 deletions(-) delete mode 100644 ihdad/src/HDA/CommandBuffer.rs create mode 100644 ihdad/src/HDA/cmdbuff.rs diff --git a/ihdad/src/HDA/CommandBuffer.rs b/ihdad/src/HDA/CommandBuffer.rs deleted file mode 100644 index 7d55f80e34..0000000000 --- a/ihdad/src/HDA/CommandBuffer.rs +++ /dev/null @@ -1,146 +0,0 @@ -use std::{mem, thread, ptr, fmt}; -use syscall::io::{Dma, Mmio, Io, ReadOnly}; - - -// CORBCTL -const CMEIE: u8 = 1 << 0; // 1 bit -const CORBRUN: u8 = 1 << 1; // 1 bit - -// CORBSIZE -const CORBSZCAP: (u8,u8) = (4, 4); -const CORBSIZE: (u8,u8) = (0, 2); - -// CORBRP -const CORBRPRST: u16 = 1 << 15; - -// RIRBWP -const RIRBWPRST: u16 = 1 << 15; - -// RIRBCTL -const RINTCTL: u8 = 1 << 0; // 1 bit -const RIRBDMAEN: u8 = 1 << 1; // 1 bit - - -const CORB_OFFSET: usize = 0x00; -const RIRB_OFFSET: usize = 0x10; - - -const CORB_BUFF_MAX_SIZE: usize = 1024; - -struct CommandBufferRegs { - corblbase: Mmio, - corbubase: Mmio, - corbwp: Mmio, - corbrp: Mmio, - corbctl: Mmio, - corbsts: Mmio, - corbsize: Mmio, - rsvd5: Mmio, - - rirblbase: Mmio, - rirbubase: Mmio, - rirbwp: Mmio, - rintcnt: Mmio, - rirbctl: Mmio, - rirbsts: Mmio, - rirbsize: Mmio, - rsvd6: Mmio, -} - - -struct CorbRegs { - corblbase: Mmio, - corbubase: Mmio, - corbwp: Mmio, - corbrp: Mmio, - corbctl: Mmio, - corbsts: Mmio, - corbsize: Mmio, - rsvd5: Mmio, -} - -struct Corb { - regs: &'static mut CorbRegs, - corb_base: *mut u32, - corb_base_phys: usize, -} - -impl Corb { - - pub fn new(regs_addr:usize, corb_buff_phys:usize, corb_buff_virt:usize) -> Corb { - - - Corb { - regs: &mut *(regs_addr as *mut CorbRegs); - corb_base: (corb_buff_virt) as *mut u64, - - } - } - -} - -struct RirbRegs { - rirblbase: Mmio, - rirbubase: Mmio, - rirbwp: Mmio, - rintcnt: Mmio, - rirbctl: Mmio, - rirbsts: Mmio, - rirbsize: Mmio, - rsvd6: Mmio, -} - -struct Rirb { - regs: &'static mut RirbRegs, - rirb_base: *mut u64, - rirb_base_phys: usize, - rirb_rp: usize, -} - -impl Rirb { - - pub fn new(regs_addr:usize, rirb_buff_phys:usize, rirb_buff_virt:usize) -> Rirb { - - - Rirb { - regs: &mut *(regs_addr as *mut RirbRegs); - rirb_base: (rirb_buff_virt) as *mut u64, - rirb_rp: 0, - rirb_base_phys: rirb_buff_phys, - } - } - -} - - -struct CommandBuffer { - - // regs: &'static mut CommandBufferRegs, - - corb: Corb, - rirb: Rirb, - - - corb_rirb_base_phys: usize, - - - -} - -impl CommandBuffer { - pub fn new(regs_addr:usize, cmd_buff_frame_phys:usize, cmd_buff_frame:usize ) -> CommandBuffer { - - let corb = Corb::new(regs_addr + CORB_OFFSET, cmd_buff_frame_phys, cmd_buff_frame); - let rirb = Rirb::new(regs_addr + RIRB_OFFSET, - cmd_buff_frame_phys + CORB_BUFF_MAX_SIZE, - cmd_buff_frame + CORB_BUFF_MAX_SIZE); - - CommandBuffer { - corb: corb, - rirb: rirb, - corb_rirb_base_phys: cmd_buff_frame_phys, - } - } - -} - diff --git a/ihdad/src/HDA/cmdbuff.rs b/ihdad/src/HDA/cmdbuff.rs new file mode 100644 index 0000000000..17efa8cdf7 --- /dev/null +++ b/ihdad/src/HDA/cmdbuff.rs @@ -0,0 +1,469 @@ +use std::{mem, thread, ptr, fmt}; +use syscall::io::{Dma, Mmio, Io, ReadOnly}; + +use super::common::*; + +// CORBCTL +const CMEIE: u8 = 1 << 0; // 1 bit +const CORBRUN: u8 = 1 << 1; // 1 bit + +// CORBSIZE +const CORBSZCAP: (u8,u8) = (4, 4); +const CORBSIZE: (u8,u8) = (0, 2); + +// CORBRP +const CORBRPRST: u16 = 1 << 15; + +// RIRBWP +const RIRBWPRST: u16 = 1 << 15; + +// RIRBCTL +const RINTCTL: u8 = 1 << 0; // 1 bit +const RIRBDMAEN: u8 = 1 << 1; // 1 bit + + +const CORB_OFFSET: usize = 0x00; +const RIRB_OFFSET: usize = 0x10; +const ICMD_OFFSET: usize = 0x20; + +// ICS +const ICB: u16 = 1 << 0; +const IRV: u16 = 1 << 1; + + +// CORB and RIRB offset + +const COMMAND_BUFFER_OFFSET: usize = 0x40; +const CORB_BUFF_MAX_SIZE: usize = 1024; + +struct CommandBufferRegs { + corblbase: Mmio, + corbubase: Mmio, + corbwp: Mmio, + corbrp: Mmio, + corbctl: Mmio, + corbsts: Mmio, + corbsize: Mmio, + rsvd5: Mmio, + + rirblbase: Mmio, + rirbubase: Mmio, + rirbwp: Mmio, + rintcnt: Mmio, + rirbctl: Mmio, + rirbsts: Mmio, + rirbsize: Mmio, + rsvd6: Mmio, +} + + +struct CorbRegs { + corblbase: Mmio, + corbubase: Mmio, + corbwp: Mmio, + corbrp: Mmio, + corbctl: Mmio, + corbsts: Mmio, + corbsize: Mmio, + rsvd5: Mmio, +} + +struct Corb { + regs: &'static mut CorbRegs, + corb_base: *mut u32, + corb_base_phys: usize, + corb_count: usize, +} + +impl Corb { + + pub fn new(regs_addr:usize, corb_buff_phys:usize, corb_buff_virt:usize) -> Corb { + + unsafe { + Corb { + regs: &mut *(regs_addr as *mut CorbRegs), + corb_base: (corb_buff_virt) as *mut u32, + corb_base_phys: corb_buff_phys, + corb_count: 0, + } + } + } + //Intel 4.4.1.3 + pub fn init(&mut self) { + self.stop(); + //Determine CORB and RIRB size and allocate buffer + + + //3.3.24 + let corbsize_reg = self.regs.corbsize.read(); + let corbszcap = (corbsize_reg >> 4) & 0xF; + + let mut corbsize_bytes: usize = 0; + let mut corbsize: u8 = 0; + + if (corbszcap & 4) == 4 { + corbsize = 2; + corbsize_bytes = 1024; + + self.corb_count = 256; + } else if (corbszcap & 2) == 2 { + corbsize = 1; + corbsize_bytes = 64; + + self.corb_count = 16; + } else if (corbszcap & 1) == 1 { + corbsize = 0; + corbsize_bytes = 8; + + self.corb_count = 2; + } + + assert!(self.corb_count != 0); + let addr = self.corb_base_phys; + self.set_address(addr); + self.regs.corbwp.write(0); + self.reset_read_pointer(); + + } + + + pub fn start(&mut self) { + self.regs.corbctl.writef(CORBRUN,true); + } + + + pub fn stop(&mut self) { + while self.regs.corbctl.readf(CORBRUN) { self.regs.corbctl.write(0); } + } + + pub fn set_address(&mut self, addr: usize) { + self.regs.corblbase.write((addr & 0xFFFFFFFF) as u32); + self.regs.corbubase.write((addr >> 32) as u32); + } + + pub fn reset_read_pointer(&mut self){ + + + /* + * FIRST ISSUE/PATCH + * This will loop forever in virtualbox + * So maybe just resetting the read pointer + * and leaving for the specific model? + */ + if true { + self.regs.corbrp.writef(CORBRPRST, true); + + } + else + { + // 3.3.21 + + self.stop(); + // Set CORBRPRST to 1 + print!("CORBRP {:X}\n",self.regs.corbrp.read()); + self.regs.corbrp.writef(CORBRPRST, true); + print!("CORBRP {:X}\n",self.regs.corbrp.read()); + print!("Here!\n"); + + // Wait for it to become 1 + while ! self.regs.corbrp.readf(CORBRPRST) { + self.regs.corbrp.writef(CORBRPRST, true); + } + print!("Here!!\n"); + // Clear the bit again + self.regs.corbrp.write(0); + + // Read back the bit until zero to verify that it is cleared. + + loop { + + if !self.regs.corbrp.readf(CORBRPRST) { + break; + } + self.regs.corbrp.write(0); + } + print!("Here!!!\n"); + } + } + + + fn send_command(&mut self, cmd: u32) { + + // wait for the commands to finish + while (self.regs.corbwp.read() & 0xff) != (self.regs.corbrp.read() & 0xff) {} + let mut write_pos: usize = ( (self.regs.corbwp.read() as usize & 0xFF) + 1) % self.corb_count; + unsafe { + *self.corb_base.offset(write_pos as isize) = cmd; + } + + self.regs.corbwp.write(write_pos as u16); + + print!("Corb: {:08X}\n", cmd); + } +} + +struct RirbRegs { + rirblbase: Mmio, + rirbubase: Mmio, + rirbwp: Mmio, + rintcnt: Mmio, + rirbctl: Mmio, + rirbsts: Mmio, + rirbsize: Mmio, + rsvd6: Mmio, +} + +struct Rirb { + regs: &'static mut RirbRegs, + rirb_base: *mut u64, + rirb_base_phys: usize, + rirb_rp: u16, + rirb_count: usize, +} + +impl Rirb { + + pub fn new(regs_addr:usize, rirb_buff_phys:usize, rirb_buff_virt:usize) -> Rirb { + + unsafe { + Rirb { + regs: &mut *(regs_addr as *mut RirbRegs), + rirb_base: (rirb_buff_virt) as *mut u64, + rirb_rp: 0, + rirb_base_phys: rirb_buff_phys, + rirb_count: 0, + } + } + } + //Intel 4.4.1.3 + pub fn init(&mut self) { + self.stop(); + + + let rirbsize_reg = self.regs.rirbsize.read(); + let rirbszcap = (rirbsize_reg >> 4) & 0xF; + + let mut rirbsize_bytes: usize = 0; + let mut rirbsize: u8 = 0; + + if (rirbszcap & 4) == 4 { + rirbsize = 2; + rirbsize_bytes = 2048; + + self.rirb_count = 256; + } else if (rirbszcap & 2) == 2 { + rirbsize = 1; + rirbsize_bytes = 128; + + self.rirb_count = 8; + } else if (rirbszcap & 1) == 1 { + rirbsize = 0; + rirbsize_bytes = 16; + + self.rirb_count = 2; + } + + assert!(self.rirb_count != 0); + + let addr = self.rirb_base_phys; + self.set_address(addr); + + self.reset_write_pointer(); + self.rirb_rp = 0; + + self.regs.rintcnt.write(1); + + } + + pub fn start(&mut self) { + self.regs.rirbctl.writef(RIRBDMAEN | RINTCTL,true); + } + + pub fn stop(&mut self) { + let mut val = self.regs.rirbctl.read(); + val &= !(RIRBDMAEN); + self.regs.rirbctl.write(val); + } + + + pub fn set_address(&mut self, addr: usize) { + self.regs.rirblbase.write((addr & 0xFFFFFFFF) as u32); + self.regs.rirbubase.write((addr >> 32) as u32); + } + + pub fn reset_write_pointer(&mut self) { + self.regs.rirbwp.writef(RIRBWPRST, true); + } + + fn read_response(&mut self) -> u64 { + // wait for response + while (self.regs.rirbwp.read() & 0xff) == (self.rirb_rp & 0xff) {} + let mut read_pos: u16 = (self.rirb_rp + 1) % self.rirb_count as u16; + + let mut res: u64; + unsafe { + res = *self.rirb_base.offset(read_pos as isize); + } + self.rirb_rp = read_pos; + print!("Rirb: {:08X}\n", res); + res + + } + +} + + +struct ImmediateCommandRegs { + icoi: Mmio, + irii: Mmio, + ics: Mmio, + rsvd7: [Mmio; 6], +} + +pub struct ImmediateCommand { + regs: &'static mut ImmediateCommandRegs, + +} + +impl ImmediateCommand { + + pub fn new(regs_addr:usize) -> ImmediateCommand { + + unsafe { + ImmediateCommand { + regs: &mut *(regs_addr as *mut ImmediateCommandRegs), + } + } + } + + pub fn cmd(&mut self, cmd:u32) -> u64 { + + // wait for ready + while self.regs.ics.readf(ICB) {} + + // write command + self.regs.icoi.write(cmd); + + + // set ICB bit to send command + self.regs.ics.writef(ICB, true); + + + // wait for IRV bit to be set to indicate a response is latched + while !self.regs.ics.readf(IRV) {} + + // read the result register twice, total of 8 bytes + // highest 4 will most likely be zeros (so I've heard) + let mut res:u64 = self.regs.irii.read() as u64; + res |= (self.regs.irii.read() as u64) << 32; + + + // clear the bit so we know when the next response comes + self.regs.ics.writef(IRV, false); + + res + + + } + +} + +pub struct CommandBuffer { + + // regs: &'static mut CommandBufferRegs, + + corb: Corb, + rirb: Rirb, + icmd: ImmediateCommand, + + corb_rirb_base_phys: usize, + + use_immediate_cmd: bool, +} + + + + +impl CommandBuffer { + pub fn new(regs_addr:usize, cmd_buff_frame_phys:usize, cmd_buff_frame:usize ) -> CommandBuffer { + + let corb = Corb::new(regs_addr + CORB_OFFSET, cmd_buff_frame_phys, cmd_buff_frame); + let rirb = Rirb::new(regs_addr + RIRB_OFFSET, + cmd_buff_frame_phys + CORB_BUFF_MAX_SIZE, + cmd_buff_frame + CORB_BUFF_MAX_SIZE); + + let icmd = ImmediateCommand::new(regs_addr + ICMD_OFFSET); + + let cmdbuff = CommandBuffer { + corb: corb, + rirb: rirb, + icmd: icmd, + + corb_rirb_base_phys: cmd_buff_frame_phys, + + use_immediate_cmd: false, + }; + + cmdbuff + } + + pub fn init(&mut self, use_imm_cmds: bool) { + self.corb.init(); + self.rirb.init(); + self.set_use_imm_cmds(use_imm_cmds); + + } + + pub fn cmd12(&mut self, addr: WidgetAddr, command: u32, data: u8) -> u64 { + let mut ncmd: u32 = 0; + + ncmd |= (addr.0 as u32 & 0x00F) << 28; + ncmd |= (addr.1 as u32 & 0x0FF) << 20; + ncmd |= (command & 0xFFF) << 8; + ncmd |= (data as u32 & 0x0FF) << 0; + self.cmd(ncmd) + + } + pub fn cmd4(&mut self, addr: WidgetAddr, command: u32, data: u16) -> u64 { + let mut ncmd: u32 = 0; + + ncmd |= (addr.0 as u32 & 0x000F) << 28; + ncmd |= (addr.1 as u32 & 0x00FF) << 20; + ncmd |= (command & 0x000F) << 16; + ncmd |= (data as u32 & 0xFFFF) << 0; + self.cmd(ncmd) + } + + pub fn cmd(&mut self, cmd:u32) -> u64 { + if self.use_immediate_cmd { + self.cmd_imm(cmd) + } else { + self.cmd_buff(cmd) + } + } + + pub fn cmd_imm(&mut self, cmd:u32) -> u64{ + self.icmd.cmd(cmd) + } + + pub fn cmd_buff(&mut self, cmd:u32) -> u64{ + self.corb.send_command(cmd); + self.rirb.read_response() + } + + pub fn set_use_imm_cmds(&mut self, use_imm: bool) { + self.use_immediate_cmd = use_imm; + + if self.use_immediate_cmd { + self.corb.stop(); + self.rirb.stop(); + } else { + self.corb.start(); + self.rirb.start(); + } + + } + + +} + diff --git a/ihdad/src/HDA/common.rs b/ihdad/src/HDA/common.rs index 7a28902dfa..67a35350a0 100644 --- a/ihdad/src/HDA/common.rs +++ b/ihdad/src/HDA/common.rs @@ -1,9 +1,20 @@ use std::{mem, thread, ptr, fmt}; - +use std::mem::transmute; pub type HDANodeAddr = u16; -pub type HDACodecAddr = u16; +pub type HDACodecAddr = u8; + +pub type NodeAddr = u16; +pub type CodecAddr = u8; + +pub type WidgetAddr = (CodecAddr, NodeAddr); +/* +impl fmt::Display for WidgetAddr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:01X}:{:02X}\n", self.0, self.1) + } +}*/ #[derive(Debug, PartialEq)] #[repr(u8)] @@ -28,9 +39,9 @@ impl fmt::Display for HDAWidgetType { } -#[derive(Debug)] +#[derive(Debug, PartialEq)] #[repr(u8)] -pub enum HDADefaultDevice { +pub enum DefaultDevice { LineOut = 0x0, Speaker = 0x1, HPOut = 0x2, @@ -49,3 +60,134 @@ pub enum HDADefaultDevice { Other = 0xF, } +#[derive(Debug)] +#[repr(u8)] +pub enum PortConnectivity { + ConnectedToJack = 0x0, + NoPhysicalConnection = 0x1, + FixedFunction = 0x2, + JackAndInternal = 0x3, +} + +#[derive(Debug)] +#[repr(u8)] +pub enum GrossLocation { + ExternalOnPrimary = 0x0, + Internal = 0x1, + SeperateChasis = 0x2, + Other = 0x3, +} + +#[derive(Debug)] +#[repr(u8)] +pub enum GeometricLocation { + NA = 0x0, + Rear = 0x1, + Front = 0x2, + Left = 0x3, + Right = 0x4, + Top = 0x5, + Bottom = 0x6, + Special1 = 0x7, + Special2 = 0x8, + Special3 = 0x9, + Resvd1 = 0xA, + Resvd2 = 0xB, + Resvd3 = 0xC, + Resvd4 = 0xD, + Resvd5 = 0xE, + Resvd6 = 0xF, +} + +#[derive(Debug)] +#[repr(u8)] +pub enum Color{ + Unknown = 0x0, + Black = 0x1, + Grey = 0x2, + Blue = 0x3, + Green = 0x4, + Red = 0x5, + Orange = 0x6, + Yellow = 0x7, + Purple = 0x8, + Pink = 0x9, + Resvd1 = 0xA, + Resvd2 = 0xB, + Resvd3 = 0xC, + Resvd4 = 0xD, + White = 0xE, + Other = 0xF, +} + +pub struct ConfigurationDefault { + value: u32, +} + +impl ConfigurationDefault { + pub fn from_u32(value:u32) -> ConfigurationDefault { + ConfigurationDefault { + value: value, + } + } + + pub fn color(&self) -> Color { + unsafe {transmute(((self.value >> 12) & 0xF) as u8)} + } + + pub fn default_device(&self) -> DefaultDevice { + unsafe {transmute(((self.value >> 20) & 0xF) as u8)} + } + + pub fn port_connectivity(&self) -> PortConnectivity { + unsafe {transmute(((self.value >> 30) & 0x3) as u8)} + } + + pub fn gross_location(&self) -> GrossLocation { + unsafe {transmute(((self.value >> 28) & 0x3) as u8)} + } + + pub fn geometric_location(&self) -> GeometricLocation { + unsafe {transmute(((self.value >> 24) & 0x7) as u8)} + } + + pub fn is_output(&self) -> bool { + match self.default_device() { + DefaultDevice::LineOut | + DefaultDevice::Speaker | + DefaultDevice::HPOut | + DefaultDevice::CD | + DefaultDevice::SPDIF | + DefaultDevice::DigitalOtherOut | + DefaultDevice::ModemLineSide => true, + _ => false, + } + } + + pub fn is_input(&self) -> bool { + match self.default_device() { + DefaultDevice::ModemHandsetSide | + DefaultDevice::LineIn | + DefaultDevice::AUX | + DefaultDevice::MicIn | + DefaultDevice::Telephony | + DefaultDevice::SPDIFIn | + DefaultDevice::DigitalOtherIn => true, + _ => false, + } + } + + pub fn sequence(&self) -> u8 { + (self.value & 0xF) as u8 + } + + pub fn default_association(&self) -> u8 { + ((self.value >> 4) & 0xF) as u8 + } +} + +impl fmt::Display for ConfigurationDefault { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?} {:?} {:?} {:?}", self.default_device(), self.color(), self.gross_location(), self.geometric_location()) + } +} \ No newline at end of file diff --git a/ihdad/src/HDA/device.rs b/ihdad/src/HDA/device.rs index f136e91b1e..3a35d0ff70 100755 --- a/ihdad/src/HDA/device.rs +++ b/ihdad/src/HDA/device.rs @@ -1,27 +1,34 @@ -use std::{mem, thread, ptr, fmt}; -use std::cmp::{max, min}; +#![allow(dead_code)] -use syscall::MAP_WRITE; -use syscall::error::{Error, EACCES, EWOULDBLOCK, Result}; -use syscall::flag::O_NONBLOCK; -use syscall::io::{Dma, Mmio, Io, ReadOnly}; -use syscall::scheme::SchemeMut; +use std::{mem, thread, ptr, fmt}; +use std::cmp; +use std::cmp::{max, min}; +use std::ptr::copy_nonoverlapping; use std::sync::Arc; use std::cell::RefCell; - +use std::collections::HashMap; +use std::str; +use std::string::String; +use std::collections::BTreeMap; +use std::sync::atomic::{AtomicUsize, Ordering}; extern crate syscall; -use std::ptr::copy_nonoverlapping; +use syscall::MAP_WRITE; +use syscall::error::{Error, EACCES, EBADF, Result, EINVAL}; +use syscall::io::{ Mmio, Io}; +use syscall::scheme::SchemeMut; + +use spin::Mutex; use super::BufferDescriptorListEntry; use super::common::*; use super::StreamDescriptorRegs; use super::StreamBuffer; use super::BitsPerSample; - +use super::CommandBuffer; use super::HDANode; - +use super::OutputStream; // GCTL - Global Control const CRST: u32 = 1 << 0; // 1 bit @@ -60,8 +67,16 @@ const NUM_SUB_BUFFS: usize = 2; const SUB_BUFF_SIZE: usize = 0x4000; +enum Handle { + Pcmout(usize, usize, usize), // Card, index, block_ptr + Pcmin(usize, usize, usize), // Card, index, block_ptr + StrBuf(Vec,usize), +} + + #[repr(packed)] +#[allow(dead_code)] struct Regs { gcap: Mmio, vmin: Mmio, @@ -113,53 +128,54 @@ struct Regs { } pub struct IntelHDA { + + vend_prod: u32, + base: usize, regs: &'static mut Regs, - corb_rirb_base_phys: usize, + //corb_rirb_base_phys: usize, - corb_base: *mut u32, - rirb_base: *mut u64, + + cmd: CommandBuffer, - corb_count: usize, - rirb_count: usize, + codecs: Vec, - rirb_rp: u16, - - codecs: Vec, - - nodes: Vec, - output_pins: Vec, + outputs: Vec, + inputs: Vec, - input_pins: Vec, + widget_map: HashMap, - beep_addr: HDANodeAddr, + output_pins: Vec, + input_pins: Vec, + + beep_addr: WidgetAddr, buff_desc: &'static mut [BufferDescriptorListEntry; 256], buff_desc_phys: usize, - output_buff: usize, - output_buff_phys: usize, - output_buff_length: usize, - output_buff_wp: usize, - output_current_block: usize, + output_streams: Vec, buffs: Vec>, int_counter: usize, + handles: Mutex>, + next_id: AtomicUsize, } impl IntelHDA { - pub unsafe fn new(base: usize) -> Result { + pub unsafe fn new(base: usize, vend_prod:u32) -> Result { let regs = &mut *(base as *mut Regs); + + let buff_desc_phys = unsafe { syscall::physalloc(0x1000) .expect("Could not allocate physical memory for buffer descriptor list.") @@ -170,79 +186,83 @@ impl IntelHDA { syscall::physmap(buff_desc_phys, 0x1000, MAP_WRITE) .expect("ihdad: failed to map address for buffer descriptor list.") }; + + print!("Virt: {:016X}, Phys: {:016X}\n", buff_desc_virt, buff_desc_phys); let buff_desc = &mut *(buff_desc_virt as *mut [BufferDescriptorListEntry;256]); - let output_length = 0x8000; - let output_phys = unsafe { - syscall::physalloc(output_length) - .expect("Could not allocate physical memory for buffer descriptor list.") + let cmd_buff_address = unsafe { + syscall::physalloc(0x1000) + .expect("Could not allocate physical memory for CORB and RIRB.") }; - let output_virt = unsafe { - syscall::physmap(output_phys, output_length, MAP_WRITE) - .expect("ihdad: failed to map address for buffer descriptor list.") - }; + let cmd_buff_virt = unsafe { syscall::physmap(cmd_buff_address, 0x1000, MAP_WRITE).expect("ihdad: failed to map address for CORB/RIRB buff") }; - + print!("Virt: {:016X}, Phys: {:016X}\n", cmd_buff_virt, cmd_buff_address); let mut module = IntelHDA { + vend_prod: vend_prod, base: base, regs: regs, - corb_base: ptr::null_mut(), - rirb_base: ptr::null_mut(), - corb_rirb_base_phys: 0, - - corb_count: 0, - rirb_count: 0, - rirb_rp: 0, - - beep_addr: 0, - codecs: Vec::::new(), - nodes: Vec::::new(), + cmd: CommandBuffer::new(base + COMMAND_BUFFER_OFFSET, cmd_buff_address, cmd_buff_virt), + + beep_addr: (0,0), - output_pins: Vec::::new(), - input_pins: Vec::::new(), + widget_map: HashMap::::new(), + + + codecs: Vec::::new(), + + outputs: Vec::::new(), + inputs: Vec::::new(), + + output_pins: Vec::::new(), + input_pins: Vec::::new(), buff_desc: buff_desc, buff_desc_phys: buff_desc_phys, - output_buff: output_virt, - output_buff_phys: output_phys, - output_buff_length: output_length, - output_buff_wp: 0, - output_current_block: 0, + + + output_streams: Vec::::new(), + buffs: Vec::>::new(), int_counter: 0, + handles: Mutex::new(BTreeMap::new()), + next_id: AtomicUsize::new(0), }; + module.init(); - //module.info(); + + // module.info(); module.enumerate(); - module.vbox_speaker_test(); + + module.configure(); print!("IHDA: Initialization finished.\n"); Ok(module) } pub fn init(&mut self) -> bool { - self.reset_controller(); - self.init_corb_and_rirb(); + let use_immediate_command_interface = match self.vend_prod { + + 0x8086_2668 => false, + _ => true, + }; + + self.cmd.init(use_immediate_command_interface); self.init_interrupts(); - //print!("Command 0xF0000: {:016X}\n", self.read_response()); - //print!("Command 0xF0004: {:016X}\n", self.send_immediate_command(0xF0004)); - true - } pub fn init_interrupts(&mut self) { @@ -250,10 +270,7 @@ impl IntelHDA { // This just enables the first output stream interupt and the global interrupt // TODO: No magic numbers! Bad Schemm. - self.regs.intctl.write((1 << 31) | (1 << 30) | (1 << 4)); - - - + self.regs.intctl.write((1 << 31) | /* (1 << 30) |*/ (1 << 4)); } @@ -271,52 +288,44 @@ impl IntelHDA { self.int_counter } - pub fn read_node(&mut self, addr: HDANodeAddr) -> HDANode { + pub fn read_node(&mut self, addr: WidgetAddr) -> HDANode { let mut node = HDANode::new(); let mut temp:u64; node.addr = addr; - - self.send_command(Self::node_command(0x00, addr, 0xF00, 0x04)); - temp = self.read_response(); + + temp = self.cmd.cmd12( addr, 0xF00, 0x04); node.subnode_count = (temp & 0xff) as u16; node.subnode_start = ((temp >> 16) & 0xff) as u16; - self.send_command(Self::node_command(0x00, addr, 0xF00, 0x05)); - temp = self.read_response(); + if addr == (0,0) { + return node; + } + temp = self.cmd.cmd12(addr, 0xF00, 0x04); node.function_group_type = (temp & 0xff) as u8; - self.send_command(Self::node_command(0x00, addr, 0xF00, 0x09)); - temp = self.read_response(); - + temp = self.cmd.cmd12(addr, 0xF00, 0x09); node.capabilities = temp as u32; - self.send_command(Self::node_command(0x00, addr, 0xF00, 0x09)); - temp = self.read_response(); + temp = self.cmd.cmd12(addr, 0xF00, 0x0E); - node.capabilities = temp as u32; - - self.send_command(Self::node_command(0x00, addr, 0xF00, 0x0E)); - temp = self.read_response(); - node.conn_list_len = (temp & 0xFF) as u8; node.connections = self.node_get_connection_list(&node); - - self.send_command(Self::node_command(0x00, addr, 0xF1C, 0x00)); - node.config_default = self.read_response() as u32; + + node.config_default = self.cmd.cmd12(addr, 0xF1C, 0x00) as u32; + node } - pub fn node_get_connection_list(&mut self, node: &HDANode) -> Vec { - // get list length - self.send_command(Self::node_command(0x00, node.addr, 0xF00, 0x0E)); - let len_field: u8 = (self.read_response() & 0xFF) as u8; + pub fn node_get_connection_list(&mut self, node: &HDANode) -> Vec { + + let len_field: u8 = (self.cmd.cmd12(node.addr, 0xF00, 0x0E) & 0xFF) as u8; // Highest bit is if addresses are represented in longer notation // lower 7 is actual count @@ -326,11 +335,11 @@ impl IntelHDA { let mut current: u8 = 0; - let mut list = Vec::::new(); + let mut list = Vec::::new(); while current < count { - self.send_command(Self::node_command(0x00, node.addr, 0xF02, current as u32)); - let response: u32 = (self.read_response() & 0xFFFFFFFF) as u32; + + let response: u32 = (self.cmd.cmd12(node.addr, 0xF02, current) & 0xFFFFFFFF) as u32; if use_long_addr { for i in 0..2 { @@ -340,11 +349,11 @@ impl IntelHDA { if addr == 0 { break; } if (addr_field >> 15) & 0x1 == 0x1 { - for i in (list.pop().unwrap() .. (addr + 1)) { - list.push(i); + for i in (list.pop().unwrap().1 .. (addr + 1)) { + list.push((node.addr.0, i)); } } else { - list.push(addr); + list.push((node.addr.0, addr)); } } @@ -357,11 +366,11 @@ impl IntelHDA { if addr == 0 { break; } if (addr_field >> 7) & 0x1 == 0x1 { - for i in (list.pop().unwrap() .. (addr + 1)) { - list.push(i); + for i in (list.pop().unwrap().1 .. (addr + 1)) { + list.push((node.addr.0, i)); } } else { - list.push(addr); + list.push((node.addr.0, addr)); } } @@ -375,75 +384,112 @@ impl IntelHDA { } pub fn enumerate(&mut self) { - self.nodes.clear(); + self.output_pins.clear(); self.input_pins.clear(); + + let codec:u8 = 0; - let root = self.read_node(0); + let root = self.read_node((codec,0)); // print!("{}\n", root); let root_count = root.subnode_count; let root_start = root.subnode_start; - self.nodes.push(root); //FIXME: So basically the way this is set up is to only support one codec and hopes the first one is an audio for i in 0..root_count { - let afg = self.read_node((root_start + i) as HDANodeAddr); + let afg = self.read_node((codec, root_start + i)); // print!("{}\n", afg); let afg_count = afg.subnode_count; let afg_start = afg.subnode_start; - self.nodes.push(afg); for j in 0..afg_count { - let mut widget = self.read_node((afg_start + j) as HDANodeAddr); + + let mut widget = self.read_node((codec, afg_start + j)); widget.is_widget = true; match widget.widget_type() { - HDAWidgetType::AudioOutput => {self.output_pins.push(widget.addr)}, - HDAWidgetType::AudioInput => {self.input_pins.push(widget.addr)}, + HDAWidgetType::AudioOutput => {self.outputs.push(widget.addr)}, + HDAWidgetType::AudioInput => {self.inputs.push(widget.addr)}, HDAWidgetType::BeepGenerator => {self.beep_addr = widget.addr }, + HDAWidgetType::PinComplex => { + let config = widget.configuration_default(); + if config.is_output() { + self.output_pins.push(widget.addr); + } else if (config.is_input()) { + self.input_pins.push(widget.addr); + } + + + print!("{:02X}{:02X} {}\n", widget.addr().0, widget.addr().1, config); + + }, _ => {}, } - // print!("{}\n", widget); - self.nodes.push(widget); + + print!("{}\n", widget); + self.widget_map.insert(widget.addr(), widget); } } } - pub fn get_node(&self, addr: HDANodeAddr) -> Option<&HDANode> { - - for ref node in &self.nodes { - if node.addr == addr { - return Some(node); + + + + pub fn find_best_output_pin(&self) -> Option{ + let outs = &self.output_pins; + if outs.len() == 0 { + None + } else if outs.len() == 1 { + Some(outs[0]) + } else { + // TODO: Somehow find the best. + // Slightly okay is find the speaker with the lowest sequence number. + + for &out in outs { + let widget = self.widget_map.get(&out).unwrap(); + + let cd = widget.configuration_default(); + if cd.sequence() == 0 && cd.default_device() == DefaultDevice::Speaker { + return Some(out); + } } - + + None } - None } - pub fn find_shortest_path_to_speaker(&mut self) -> Vec { - let mut path = Vec::::new(); - - for addr in &self.output_pins { - //let node = self.get_node().unwrap(); - + + + + pub fn find_path_to_dac(&self, addr: WidgetAddr) -> Option>{ + let widget = self.widget_map.get(&addr).unwrap(); + if widget.widget_type() == HDAWidgetType::AudioOutput { + return Some(vec![addr]); + }else{ + if widget.connections.len() == 0 { + return None; + }else{ + // TODO: do more than just first widget + + let mut res = self.find_path_to_dac(widget.connections[0]); + match res { + Some(p) => { + let mut ret = p.clone(); + ret.insert(0, addr); + Some(ret) + }, + None => {None}, + } + } } - - path - } + } - pub fn create_sound_buffers(&mut self) { - - self.buffs.push(Vec::::new()); - // self.buffs[0].push(StreamBuffer::new(0x4000).unwrap()); - // self.buffs[0].push(StreamBuffer::new(0x4000).unwrap()); - - - } - + + /* Here we update the buffers and split them into 128 byte sub chunks because each BufferDescriptorList needs to be 128 byte aligned, @@ -452,7 +498,11 @@ impl IntelHDA { /* Vec of a Vec was doing something weird and causing the driver to hang. So now we have a set of variables instead. + + + Fixed? */ + pub fn update_sound_buffers(&mut self) { /* for i in 0..self.buffs.len(){ @@ -462,144 +512,162 @@ impl IntelHDA { self.buff_desc[i * 128/16 + j].set_interrupt_on_complete(true); } }*/ - - self.buff_desc[0].set_address(self.output_buff_phys); - self.buff_desc[0].set_length((self.output_buff_length/2) as u32); - self.buff_desc[0].set_interrupt_on_complete(true); - self.buff_desc[1].set_address(self.output_buff_phys + self.output_buff_length/2); - self.buff_desc[1].set_length((self.output_buff_length/2) as u32); + let r = self.get_output_stream_descriptor(0).unwrap(); + + + self.output_streams.push(OutputStream::new(2, 0x4000, r)); + + let o = self.output_streams.get_mut(0).unwrap(); + + + self.buff_desc[0].set_address(o.phys()); + self.buff_desc[0].set_length(o.block_size() as u32); + self.buff_desc[0].set_interrupt_on_complete(true); + + + self.buff_desc[1].set_address(o.phys() + o.block_size()); + self.buff_desc[1].set_length(o.block_size() as u32); self.buff_desc[1].set_interrupt_on_complete(true); - } - /* - For testing in VBOX: - Create Ramp wave of 400hz to test the output of - the speakers to see sound can be played - */ - - pub fn test_buff_fill(&mut self) { - let n_samples = self.output_buff_length / (2 * 2); - let buf_ptr = unsafe { self.output_buff as * mut u16}; - - let freq:u16 = 440; - - let period:u16 = 44100 / 440; - - let step:u16 = 65535 / period; - - let mut j:u16 = 0; - let mut val:u16 = 0; - - for i in 0..n_samples { - unsafe { - *buf_ptr.offset((2*i) as isize) = val; - *buf_ptr.offset((2*i+1) as isize) = val; - } - val += step; - j += 1; - - if j >= period { - j = 0; - val = 0; - } - - } - print!("IHDA: Test buffer created.\n"); - } - pub fn vbox_speaker_test(&mut self) { - + pub fn configure(&mut self) { + let outpin = self.find_best_output_pin().expect("IHDA: No output pins?!"); + + //print!("Best pin: {:01X}:{:02X}\n", outpin.0, outpin.1); + let path = self.find_path_to_dac(outpin).unwrap(); + + let dac = *path.last().unwrap(); + let pin = *path.first().unwrap(); + + //print!("Path to DAC: {:?}\n", path); // Pin enable - self.send_command(Self::node_command(0x00, 0xC, 0x707, 0x40)); - let mut response: u32 = (self.read_response() & 0xFFFFFFFF) as u32; - + self.cmd.cmd12(pin, 0x707, 0x40); + // EAPD enable - self.send_command(Self::node_command(0x00, 0xC, 0x70C, 2)); - response = (self.read_response() & 0xFFFFFFFF) as u32; + self.cmd.cmd12(pin, 0x70C, 2); + self.set_stream_channel(dac, 1, 0); - self.set_stream_channel(0x3, 1, 0); - - // self.create_sound_buffers(); self.update_sound_buffers(); - print!("Supported Formats: {:08X}\n", self.get_supported_formats(0x1)); - print!("Capabilities: {:08X}\n", self.get_capabilities(0x3)); + //print!("Supported Formats: {:08X}\n", self.get_supported_formats((0,0x1))); + //print!("Capabilities: {:08X}\n", self.get_capabilities(path[0])); + + let output = self.get_output_stream_descriptor(0).unwrap(); + + + + output.set_address(self.buff_desc_phys); + + + output.set_pcm_format(&super::SR_44_1, BitsPerSample::Bits16, 2); + output.set_cyclic_buffer_length(0x8000); // number of bytes + output.set_stream_number(1); + output.set_last_valid_index(1); + output.set_interrupt_on_completion(true); + + + self.set_power_state(dac, 0); // Power state 0 is fully on + self.set_converter_format(dac, &super::SR_44_1, BitsPerSample::Bits16, 2); + + + self.cmd.cmd12(dac, 0xA00, 0); + + // Unmute and set gain for pin complex and DAC + self.set_amplifier_gain_mute(dac, true, true, true, true, 0, false, 0x7f); + self.set_amplifier_gain_mute(pin, true, true, true, true, 0, false, 0x7f); + + output.run(); + + } + /* + + pub fn configure_vbox(&mut self) { + + let outpin = self.find_best_output_pin().expect("IHDA: No output pins?!"); + + print!("Best pin: {:01X}:{:02X}\n", outpin.0, outpin.1); + + let path = self.find_path_to_dac(outpin).unwrap(); + print!("Path to DAC: {:?}\n", path); + + // Pin enable + self.cmd.cmd12((0,0xC), 0x707, 0x40); + + + // EAPD enable + self.cmd.cmd12((0,0xC), 0x70C, 2); + + self.set_stream_channel((0,0x3), 1, 0); + + self.update_sound_buffers(); + + + print!("Supported Formats: {:08X}\n", self.get_supported_formats((0,0x1))); + print!("Capabilities: {:08X}\n", self.get_capabilities((0,0x1))); let output = self.get_output_stream_descriptor(0).unwrap(); output.set_address(self.buff_desc_phys); output.set_pcm_format(&super::SR_44_1, BitsPerSample::Bits16, 2); - output.set_cyclic_buffer_length(0x8000); // number of samples + output.set_cyclic_buffer_length(0x8000); output.set_stream_number(1); output.set_last_valid_index(1); output.set_interrupt_on_completion(true); - self.set_power_state(0x3, 0); // Power state 0 is fully on - self.set_converter_format(0x3, &super::SR_44_1, BitsPerSample::Bits16, 2); + self.set_power_state((0,0x3), 0); // Power state 0 is fully on + self.set_converter_format((0,0x3), &super::SR_44_1, BitsPerSample::Bits16, 2); - self.send_command(Self::node_command(0x00, 0x3, 0xA00, 0)); - response = (self.read_response() & 0xFFFFFFFF) as u32; - print!("Format: {:04X}\n",response); + self.cmd.cmd12((0,0x3), 0xA00, 0); // Unmute and set gain for pin complex and DAC - self.set_amplifier_gain_mute(0x3, true, true, true, true, 0, false, 0x7f); - self.set_amplifier_gain_mute(0xC, true, true, true, true, 0, false, 0x7f); - - - - - // self.test_buff_fill(); + self.set_amplifier_gain_mute((0,0x3), true, true, true, true, 0, false, 0x7f); + self.set_amplifier_gain_mute((0,0xC), true, true, true, true, 0, false, 0x7f); output.run(); - print!("IHDA: Beep? \n"); self.beep(1); } - + + */ // BEEP!! pub fn beep(&mut self, div:u8) { let addr = self.beep_addr; - if addr != 0 { + if addr != (0,0) { + + let _ = self.cmd.cmd12(addr, 0xF0A, div); - self.send_command(Self::node_command(0x00, addr, 0xF0A, div as u32)); - let response = (self.read_response() & 0xFFFFFFFF) as u32; } } pub fn read_beep(&mut self) -> u8 { let addr = self.beep_addr; - if addr != 0 { - self.send_command(Self::node_command(0x00, addr, 0x70A, 0)); - (self.read_response() & 0xFF) as u8 + if addr != (0,0) { + + self.cmd.cmd12(addr, 0x70A, 0) as u8 }else{ 0 } } - pub fn enable_pin(&self, node: &HDANode) { - - - } - pub fn reset_controller(&mut self) -> bool { self.regs.statests.write(0xFFFF); @@ -626,11 +694,11 @@ impl IntelHDA { } let statests = self.regs.statests.read(); - + print!("Statests: {:04X}\n", statests); for i in 0..15 { if (statests >> i) & 0x1 == 1 { - self.codecs.push(i as HDANodeAddr); + self.codecs.push(i as CodecAddr); } } true @@ -666,289 +734,9 @@ impl IntelHDA { print!("IHDA: 64-Bit: {}\n", self.regs.gcap.read() & 1 == 1); } - pub fn node_command(codec_address: u32, node_index: HDANodeAddr, command: u32, data: u32) -> u32{ - let mut ncmd: u32 = 0; - let node_addr = node_index as u32; - - ncmd |= (codec_address & 0x00F) << 28; - ncmd |= (node_addr & 0x0FF) << 20; - ncmd |= (command & 0xFFF) << 8; - ncmd |= (data & 0x0FF) << 0; - ncmd - } - - - pub fn corb_start(&mut self) { - self.regs.corbctl.writef(CORBRUN,true); - } - - pub fn rirb_start(&mut self) { - self.regs.rirbctl.writef(RIRBDMAEN | RINTCTL,true); - } - - pub fn corb_stop(&mut self) { - - while self.regs.corbctl.readf(CORBRUN) { self.regs.corbctl.write(0); } - } - - pub fn rirb_stop(&mut self) { - let mut val = self.regs.rirbctl.read(); - val &= !(RIRBDMAEN); - self.regs.rirbctl.write(val); - } - - //Intel 4.4.1.3 - - pub fn init_corb_and_rirb(&mut self) -> Result<()> { - - - self.corb_stop(); - self.rirb_stop(); - - - //Determine CORB and RIRB size and allocate buffer - - - //3.3.24 - let corbsize_reg = self.regs.corbsize.read(); - let corbszcap = (corbsize_reg >> 4) & 0xF; - - let mut corbsize_bytes: usize = 0; - let mut corbsize: u8 = 0; - - if (corbszcap & 4) == 4 { - corbsize = 2; - corbsize_bytes = 1024; - - self.corb_count = 256; - } else if (corbszcap & 2) == 2 { - corbsize = 1; - corbsize_bytes = 64; - - self.corb_count = 16; - } else if (corbszcap & 1) == 1 { - corbsize = 0; - corbsize_bytes = 8; - - self.corb_count = 2; - } else { - //TODO: Error! - } - - //3.3.31 - - let rirbsize_reg = self.regs.rirbsize.read(); - let rirbszcap = (rirbsize_reg >> 4) & 0xF; - - let mut rirbsize_bytes: usize = 0; - let mut rirbsize: u8 = 0; - - if (rirbszcap & 4) == 4 { - rirbsize = 2; - rirbsize_bytes = 2048; - - self.rirb_count = 256; - } else if (rirbszcap & 2) == 2 { - rirbsize = 1; - rirbsize_bytes = 128; - - self.rirb_count = 8; - } else if (rirbszcap & 1) == 1 { - rirbsize = 0; - rirbsize_bytes = 16; - - self.rirb_count = 2; - } else { - //TODO: Error! - } - - //print!("CORB size: {} RIRB size: {}\n", corbsize_bytes, rirbsize_bytes); - - - // Allocate the physical memory, keeping in mind - // that the buffers need to be 128-byte aligned - - let buff_address = unsafe { - syscall::physalloc(max(rirbsize_bytes, 128) + max(corbsize_bytes, 128)) - .expect("Could not allocate physical memory for CORB and RIRB.") - }; - - - let virt_address = unsafe { syscall::physmap(buff_address, 0x1000, MAP_WRITE).expect("ihdad: failed to map address for CORB/RIRB buff") }; - - - self.corb_rirb_base_phys = buff_address; - - // Set the sizes and addresses of the buffers - self.regs.corbsize.write(corbsize); - - self.corb_set_address(buff_address); - - // make sure that the RIRB buffer is at least aligned to 128 bytes. - self.regs.rirbsize.write(rirbsize); - self.rirb_set_address(buff_address + max(128, corbsize_bytes)); - - - // set virtual addresses for the buffer so we can access it - - self.corb_base = (virt_address) as *mut u32; - self.rirb_base = (virt_address + max(128, corbsize_bytes)) as *mut u64; - - - //print!("IHDA State: {:04X}\n",self.regs.statests.read()); - self.regs.corbwp.write(0); - self.corb_reset_read_pointer(); - self.rirb_reset_write_pointer(); - self.rirb_rp = 0; - - self.regs.rintcnt.write(1); - - - self.corb_start(); - self.rirb_start(); - - Ok(()) - } - - fn corb_set_address(&mut self, addr: usize) { - - - - self.regs.corblbase.write((addr & 0xFFFFFFFF) as u32); - self.regs.corbubase.write((addr >> 32) as u32); - } - - fn rirb_set_address(&mut self, addr: usize) { - self.regs.rirblbase.write((addr & 0xFFFFFFFF) as u32); - self.regs.rirbubase.write((addr >> 32) as u32); - } - - fn rirb_reset_write_pointer(&mut self) { - self.regs.rirbwp.writef(RIRBWPRST, true); - - - } - - fn corb_reset_read_pointer(&mut self){ - - - /* - * FIRST ISSUE/PATCH - * This will loop forever in virtualbox - * So maybe just resetting the read pointer - * and leaving for the specific model? - */ - if true { - self.regs.corbrp.writef(CORBRPRST, true); - - } - else - { - // 3.3.21 - - self.corb_stop(); - // Set CORBRPRST to 1 - print!("CORBRP {:X}\n",self.regs.corbrp.read()); - self.regs.corbrp.writef(CORBRPRST, true); - print!("CORBRP {:X}\n",self.regs.corbrp.read()); - print!("Here!\n"); - - // Wait for it to become 1 - while ! self.regs.corbrp.readf(CORBRPRST) { - self.regs.corbrp.writef(CORBRPRST, true); - } - print!("Here!!\n"); - // Clear the bit again - self.regs.corbrp.write(0); - - // Read back the bit until zero to verify that it is cleared. - - loop { - - if !self.regs.corbrp.readf(CORBRPRST) { - break; - } - self.regs.corbrp.write(0); - } - } - } - - - fn send_command(&mut self, cmd: u32) { - - // wait for the commands to finish - while (self.regs.corbwp.read() & 0xff) != (self.regs.corbrp.read() & 0xff) {} - - let mut write_pos: usize = ( (self.regs.corbwp.read() as usize & 0xFF) + 1) % self.corb_count; - - unsafe { - *self.corb_base.offset(write_pos as isize) = cmd; - } - - self.regs.corbwp.write(write_pos as u16); - - - - } - - fn read_response(&mut self) -> u64 { - - // wait for response - while (self.regs.rirbwp.read() & 0xff) == (self.rirb_rp & 0xff) {} - - let mut read_pos: u16 = (self.rirb_rp + 1) % self.rirb_count as u16; - - let mut res: u64; - unsafe { - res = *self.rirb_base.offset(read_pos as isize); - } - - self.rirb_rp = read_pos; - - res - - } - - - // FIXME: Apparently vbox is picky about sending immediate commands. - // Hopefully this can be disregarded if the DMA works. - - - - fn send_immediate_command(&mut self, cmd: u32) -> u64 { - print!("Status: {:04X}\n",self.regs.ics.read()); - - // wait for ready - while self.regs.ics.readf(ICB) {} - - // write command - self.regs.icoi.write(cmd); - - - // set ICB bit to send command - self.regs.ics.writef(ICB, true); - - print!("Status: {:04X}\n",self.regs.ics.read()); - - // wait for IRV bit to be set to indicate a response is latched - while !self.regs.ics.readf(IRV) {} - - // read the result register twice, total of 8 bytes - // highest 4 will most likely be zeros (so I've heard) - let mut res:u64 = self.regs.irii.read() as u64; - res |= (self.regs.irii.read() as u64) << 32; - - - // clear the bit so we know when the next response comes - self.regs.ics.writef(IRV, false); - - res - - } - - fn get_input_descriptor(&self, index: usize) -> Option<&'static mut StreamDescriptorRegs> { + fn get_input_stream_descriptor(&self, index: usize) -> Option<&'static mut StreamDescriptorRegs> { unsafe { if index < self.num_input_streams() { Some(&mut *((self.base + 0x80 + index * 0x20) as *mut StreamDescriptorRegs)) @@ -991,38 +779,31 @@ impl IntelHDA { } - fn set_stream_channel(&mut self, addr: HDANodeAddr, stream: u8, channel:u8) { + fn set_stream_channel(&mut self, addr: WidgetAddr, stream: u8, channel:u8) { let val = ((stream & 0xF) << 4) | (channel & 0xF); - self.send_command(Self::node_command(0x00, addr, 0x706, val as u32)); - let temp = self.read_response(); + self.cmd.cmd12(addr, 0x706, val); } - fn set_power_state(&mut self, addr:HDANodeAddr, state:u8) { - self.send_command(Self::node_command(0x00, addr, 0x705, state as u32 & 0xF)); - let temp = self.read_response(); + fn set_power_state(&mut self, addr:WidgetAddr, state:u8) { + self.cmd.cmd12(addr, 0x705, state & 0xF) as u32; } - fn get_supported_formats(&mut self, addr: HDANodeAddr) -> u32 { - self.send_command(Self::node_command(0x00, addr, 0xF00, 0x0A)); - self.read_response() as u32 + fn get_supported_formats(&mut self, addr: WidgetAddr) -> u32 { + self.cmd.cmd12(addr, 0xF00, 0x0A) as u32 } - fn get_capabilities(&mut self, addr: HDANodeAddr) -> u32 { - self.send_command(Self::node_command(0x00, addr, 0xF00, 0x09)); - self.read_response() as u32 + fn get_capabilities(&mut self, addr: WidgetAddr) -> u32 { + self.cmd.cmd12(addr, 0xF00, 0x09) as u32 } - fn set_converter_format(&mut self, addr:HDANodeAddr, sr: &super::SampleRate, bps: BitsPerSample, channels:u8) { + fn set_converter_format(&mut self, addr:WidgetAddr, sr: &super::SampleRate, bps: BitsPerSample, channels:u8) { let fmt = super::format_to_u16(sr, bps, channels); - let fmt_hi = (fmt >> 8) as u32; - let fmt_lo = (fmt & 0xFF) as u32; - print!("Format: {:04X}\n",fmt); - self.send_command(Self::node_command(0x00, addr, 0x200 | fmt_hi, fmt_lo)); - let temp = self.read_response(); - + self.cmd.cmd4(addr, 0x2, fmt); } - fn set_amplifier_gain_mute(&mut self, addr:HDANodeAddr, output:bool, input:bool, left:bool, right:bool, index:u8, mute:bool, gain: u8) { + + + fn set_amplifier_gain_mute(&mut self, addr: WidgetAddr, output:bool, input:bool, left:bool, right:bool, index:u8, mute:bool, gain: u8) { let mut payload: u16 = 0; @@ -1033,83 +814,24 @@ impl IntelHDA { if mute { payload |= (1 << 7); } payload |= ((index as u16) & 0x0F) << 8; payload |= ((gain as u16) & 0x7F); - - let payload_hi = (payload >> 8); - let payload_lo = (payload & 0xFF) as u8; - self.send_command(Self::node_command(0x00, addr, 0x300 | payload_hi as u32, payload_lo as u32)); - let temp = self.read_response(); - } + self.cmd.cmd4(addr, 0x3, payload); - fn write_to_output(&mut self, out_index: usize, buf: &[u8]) -> Result { - - - // TODO: Better way of writing than just writing from the write pointer to the link position in buffer - - - - - let mut output = self.get_output_stream_descriptor(0).unwrap(); - - let sample_size:usize = output.sample_size(); - let sample_count:usize = buf.len() / sample_size; - let buff_len = output.cyclic_buffer_length() as usize; - - let mut samples_copied: usize = 0; - while samples_copied < sample_count { - - let samples_left = sample_count - samples_copied; - - // modular arithmetic to get the number of samples that we can write to - - let mut can_write = (output.link_position() as usize + buff_len) - self.output_buff_wp; - - if can_write >= buff_len { - can_write -= buff_len; - } - - let samples_to_write = min(can_write, samples_left); - let samples_until_end = buff_len - self.output_buff_wp; - - if samples_to_write > 0 { - - if samples_until_end >= samples_to_write { - unsafe { - copy_nonoverlapping(buf.as_ptr(), (self.output_buff + self.output_buff_wp * sample_size) as * mut u8, samples_to_write * sample_size); - } - - } else { - unsafe { - copy_nonoverlapping(buf.as_ptr(), (self.output_buff + self.output_buff_wp * sample_size) as * mut u8, samples_until_end * sample_size); - copy_nonoverlapping((buf.as_ptr() as usize + (samples_to_write * sample_size)) as * const u8, - (self.output_buff + self.output_buff_wp * sample_size) as * mut u8, - (samples_to_write - samples_until_end) * sample_size); - } - } - - self.output_buff_wp += samples_to_write; - if self.output_buff_wp >= buff_len { - self.output_buff_wp -= buff_len; - } - - samples_copied += samples_to_write; - } - thread::yield_now(); - } - - Ok(samples_copied * sample_size) - } + pub fn write_to_output(&mut self, index:u8, buf: &[u8]) -> Result { - - pub fn write_to_output2(&mut self, index:u8, buf: &[u8]) -> Result { + let mut output = self.get_output_stream_descriptor(index as usize).unwrap(); + let mut os = self.output_streams.get_mut(index as usize).unwrap(); + - let mut output = self.get_output_stream_descriptor(0).unwrap(); let sample_size:usize = output.sample_size(); - let mut open_block = (output.link_position() as usize) / 0x4000; + let mut open_block = (output.link_position() as usize) / os.block_size(); + + + if open_block == 0 { open_block = 1; @@ -1117,35 +839,31 @@ impl IntelHDA { open_block = open_block - 1; } + //print!("Status: {:02X} Pos: {:08X} Output CTL: {:06X}\n", output.status(), output.link_position(), output.control()); + while open_block == os.current_block() { - while open_block == self.output_current_block { - - open_block = (output.link_position() as usize) / 0x4000; + open_block = (output.link_position() as usize) / os.block_size(); if open_block == 0 { - open_block = 1; + open_block = os.block_count() - 1; } else { open_block = open_block - 1; } - + + thread::yield_now(); } - self.output_current_block = open_block; - let len = min(0x4000, buf.len()); - - unsafe { - copy_nonoverlapping(buf.as_ptr(), (self.output_buff + self.output_current_block * 0x4000) as * mut u8, len); - } + let len = min(os.block_size(), buf.len()); - Ok(len) + os.write_block(buf) } pub fn handle_interrupts(&mut self) { let intsts = self.regs.intsts.read(); let sis = intsts & 0x3FFFFFFF; - print!("IHDA INTSTS: {:08X}\n", intsts); + // print!("IHDA INTSTS: {:08X}\n", intsts); if ((intsts >> 31) & 1) == 1 { // Global Interrupt Status if ((intsts >> 30) & 1) == 1 { // Controller Interrupt Status self.handle_controller_interrupt(); @@ -1158,73 +876,120 @@ impl IntelHDA { } pub fn handle_controller_interrupt(&mut self) { - + } pub fn handle_stream_interrupts(&mut self, sis: u32) { let oss = self.num_output_streams(); let iss = self.num_input_streams(); let bss = self.num_bidirectional_streams(); - - - let sample_size = 4; // TODO: create method to get sample size for i in 0..iss { if ((sis >> i) & 1 ) == 1 { - - + let mut input = self.get_input_stream_descriptor(i).unwrap(); + input.clear_interrupts(); } } for i in 0..oss { if ((sis >> (i + iss)) & 1 ) == 1 { - let mut output = self.get_output_stream_descriptor(i).unwrap(); - // TODO: No magic numbers! - let mut temp = output.link_position() as usize / 0x4000; - - if temp == 0 { - temp = self.output_buff_length - 0x4000; - } else { - temp = temp - 0x4000; - } - self.output_current_block = temp; output.clear_interrupts(); } } for i in 0..bss { if ((sis >> (i + iss + oss)) & 1 ) == 1 { - - + let mut bid = self.get_bidirectional_stream_descriptor(i).unwrap(); + bid.clear_interrupts(); } } } + fn validate_path(&mut self, path: &Vec<&str>) -> bool { + + print!("Path: {:?}\n", path); + let mut it = path.iter(); + match it.next() { + Some(card_str) if (*card_str).starts_with("card") => { + match usize::from_str_radix(&(*card_str)[4..], 10) { + Ok(card_num) => { + print!("Card# {}\n", card_num); + match it.next() { + Some(codec_str) if (*codec_str).starts_with("codec#") => { + match usize::from_str_radix(&(*codec_str)[6..], 10) { + Ok(codec_num) => { + + let id = self.next_id.fetch_add(1, Ordering::SeqCst); + //self.handles.lock().insert(id, Handle::Disk(disk.clone(), 0)); + true + + }, + _ => false, + } + }, + Some(pcmout_str) if (*pcmout_str).starts_with("pcmout") => { + match usize::from_str_radix(&(*pcmout_str)[6..], 10) { + Ok(pcmout_num) => { + print!("pcmout {}\n", pcmout_num); + true + }, + _ => false, + } + }, + Some(pcmin_str) if (*pcmin_str).starts_with("pcmin") => { + match usize::from_str_radix(&(*pcmin_str)[6..], 10) { + Ok(pcmin_num) => { + print!("pcmin {}\n", pcmin_num); + true + }, + _ => false, + } + }, + _ => false, + } + }, + _ => false, + } + }, + Some(cards_str) if *cards_str == "cards" => { + true + }, + _ => false, + } + } } impl Drop for IntelHDA { fn drop(&mut self) { - let _ = unsafe {syscall::physfree(self.buff_desc_phys, 0x1000)}; - if self.output_buff_phys != 0 { - unsafe { - let _ = syscall::physfree(self.output_buff_phys, self.output_buff_length); - } - } print!("IHDA: Deallocating IHDA driver.\n"); } - - } impl SchemeMut for IntelHDA { - fn open(&mut self, _path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { - - // TODO: + + + fn open(&mut self, _path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { + let path: Vec<&str>; + /* + match str::from_utf8(_path) { + Ok(p) => { + path = p.split("/").collect(); + if !self.validate_path(&path) { + return Err(Error::new(EINVAL)); + + }, + Err(_) => {return Err(Error::new(EINVAL));}, + }*/ + + + + + // TODO: if uid == 0 { Ok(flags) } else { @@ -1237,12 +1002,31 @@ impl SchemeMut for IntelHDA { //print!("Int count: {}\n", self.int_counter); - self.write_to_output2(0, buf) + self.write_to_output(0, buf) } - fn close(&mut self, _id: usize) -> Result { - // TODO: - Ok(0) + fn seek(&mut self, id: usize, pos: usize, whence: usize) -> Result { + let mut handles = self.handles.lock(); + match *handles.get_mut(&id).ok_or(Error::new(EBADF))? { + Handle::StrBuf(ref mut strbuf, ref mut size) => { + let len = strbuf.len() as usize; + *size = match whence { + SEEK_SET => cmp::min(len, pos), + SEEK_CUR => cmp::max(0, cmp::min(len as isize, *size as isize + pos as isize)) as usize, + SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize, + _ => return Err(Error::new(EINVAL)) + }; + Ok(*size) + }, + + _ => Err(Error::new(EINVAL)), + } } -} + + fn close(&mut self, _id: usize) -> Result { + let mut handles = self.handles.lock(); + handles.remove(&_id).ok_or(Error::new(EBADF)).and(Ok(0)) + } + +} \ No newline at end of file diff --git a/ihdad/src/HDA/mod.rs b/ihdad/src/HDA/mod.rs index f3c06f06d0..90330ee8d6 100644 --- a/ihdad/src/HDA/mod.rs +++ b/ihdad/src/HDA/mod.rs @@ -1,14 +1,15 @@ - +#![allow(dead_code)] pub mod device; pub mod stream; pub mod common; pub mod node; - +pub mod cmdbuff; pub use self::stream::*; pub use self::node::*; +pub use self::cmdbuff::*; pub use self::stream::StreamDescriptorRegs; pub use self::stream::BufferDescriptorListEntry; pub use self::stream::BitsPerSample; diff --git a/ihdad/src/HDA/node.rs b/ihdad/src/HDA/node.rs index 86e79eaa58..edbb3727e0 100644 --- a/ihdad/src/HDA/node.rs +++ b/ihdad/src/HDA/node.rs @@ -4,7 +4,7 @@ use super::common::*; #[derive(Clone)] pub struct HDANode { - pub addr: HDANodeAddr, + pub addr: WidgetAddr, @@ -35,7 +35,7 @@ pub struct HDANode { // 0x13 pub vol_knob: u8, - pub connections: Vec, + pub connections: Vec, pub is_widget: bool, @@ -47,7 +47,7 @@ impl HDANode { pub fn new() -> HDANode { HDANode { - addr: 0, + addr: (0,0), subnode_count: 0, subnode_start: 0, function_group_type: 0, @@ -60,7 +60,7 @@ impl HDANode { config_default: 0, is_widget: false, - connections: Vec::::new(), + connections: Vec::::new(), } } @@ -69,7 +69,7 @@ impl HDANode { } - pub fn getDeviceDefault(&self) -> Option { + pub fn device_default(&self) -> Option { if self.widget_type() != HDAWidgetType::PinComplex { None } else { @@ -77,32 +77,37 @@ impl HDANode { } } - pub fn addr(&self) -> HDANodeAddr { + pub fn configuration_default(&self) -> ConfigurationDefault { + ConfigurationDefault::from_u32(self.config_default) + } + + pub fn addr(&self) -> WidgetAddr { self.addr } } impl fmt::Display for HDANode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.addr == 0 { - write!(f, "Addr: {:02X}, Root Node.", self.addr) + if self.addr == (0,0) { + write!(f, "Addr: {:02X}:{:02X}, Root Node.", self.addr.0, self.addr.1) } else if self.is_widget { match self.widget_type() { HDAWidgetType::PinComplex => { - write!(f, "Addr: {:02X}, Type: {:?}: {:?}, Inputs: {:X}: {:?}.", - self.addr, + write!(f, "Addr: {:02X}:{:02X}, Type: {:?}: {:?}, Inputs: {:X}: {:?}.", + self.addr.0, + self.addr.1, self.widget_type(), - self.getDeviceDefault().unwrap(), + self.device_default().unwrap(), self.conn_list_len, self.connections) }, - _ => { write!(f, "Addr: {:02X}, Type: {:?}, Inputs: {:X}: {:?}.", self.addr, self.widget_type(), self.conn_list_len, self.connections) }, + _ => { write!(f, "Addr: {:02X}:{:02X}, Type: {:?}, Inputs: {:X}: {:?}.", self.addr.0, self.addr.1, self.widget_type(), self.conn_list_len, self.connections) }, } } else { - write!(f, "Addr: {:02X}, AFG: {}, Widget count {}.", self.addr, self.function_group_type, self.subnode_count) + write!(f, "Addr: {:02X}:{:02X}, AFG: {}, Widget count {}.", self.addr.0, self.addr.1, self.function_group_type, self.subnode_count) } } } diff --git a/ihdad/src/HDA/stream.rs b/ihdad/src/HDA/stream.rs index 75034be732..c87faf8690 100644 --- a/ihdad/src/HDA/stream.rs +++ b/ihdad/src/HDA/stream.rs @@ -1,15 +1,17 @@ -use std::{mem, thread, ptr, fmt}; -use std::cmp::max; + + use syscall::MAP_WRITE; -use syscall::error::{Error, EACCES, EWOULDBLOCK, Result}; +use syscall::error::{Error, EACCES, EWOULDBLOCK, EIO, Result}; use syscall::flag::O_NONBLOCK; use syscall::io::{Dma, Mmio, Io, ReadOnly}; use syscall::scheme::SchemeMut; use std::sync::Arc; use std::cell::RefCell; use std::result; - +use std::cmp::{max, min}; +use std::ptr::copy_nonoverlapping; +use std::{mem, thread, ptr, fmt}; extern crate syscall; @@ -201,18 +203,56 @@ impl StreamDescriptorRegs { _ => 4 * (chan + 1), } } + + } -pub struct Stream { - buff: usize, - buff_phys: usize, - buff_length: usize, - output_current_block: usize, - block_length: usize, - block_count: usize, +pub struct OutputStream { + buff: StreamBuffer, + + desc_regs: &'static mut StreamDescriptorRegs, } +impl OutputStream { + pub fn new(block_count: usize, block_length: usize, regs: &'static mut StreamDescriptorRegs) -> OutputStream { + unsafe { + OutputStream { + buff: StreamBuffer::new(block_length, block_count).unwrap(), + + desc_regs: regs, + } + } + } + + pub fn write_block(&mut self, buf: &[u8]) -> Result { + self.buff.write_block(buf) + } + + pub fn block_size(&self) -> usize { + self.buff.block_size() + } + + pub fn block_count(&self) -> usize { + self.buff.block_count() + } + + pub fn current_block(&self) -> usize { + self.buff.current_block() + } + + pub fn addr(&self) -> usize { + self.buff.addr() + } + + pub fn phys(&self) -> usize { + self.buff.phys() + } +} + + + + #[repr(packed)] pub struct BufferDescriptorListEntry { addr: Mmio, @@ -252,13 +292,16 @@ pub struct StreamBuffer { phys: usize, addr: usize, - len: usize, + block_cnt: usize, + block_len: usize, + + cur_pos: usize, } impl StreamBuffer { - pub fn new(length: usize) -> result::Result { + pub fn new(block_length: usize, block_count: usize) -> result::Result { let phys = unsafe { - syscall::physalloc(length) + syscall::physalloc(block_length * block_count) }; if !phys.is_ok() { return Err("Could not allocate physical memory for buffer."); @@ -267,24 +310,25 @@ impl StreamBuffer { let phys_addr = phys.unwrap(); let addr = unsafe { - syscall::physmap(phys_addr, length, MAP_WRITE) + syscall::physmap(phys_addr, block_length * block_count, MAP_WRITE) }; if !addr.is_ok() { + unsafe {syscall::physfree(phys_addr, block_length * block_count);} return Err("Could not map physical memory for buffer."); - } else { - unsafe {syscall::physfree(phys_addr, length);} } Ok(StreamBuffer { phys: phys_addr, addr: addr.unwrap(), - len: length, + block_len: block_length, + block_cnt: block_count, + cur_pos: 0, }) } pub fn length(&self) -> usize { - self.len + self.block_len * self.block_cnt } pub fn addr(&self) -> usize { @@ -295,14 +339,43 @@ impl StreamBuffer { self.phys } + pub fn block_size(&self) -> usize { + self.block_len + } + + pub fn block_count(&self) -> usize { + self.block_cnt + } + + pub fn current_block(&self) -> usize { + self.cur_pos + } + + pub fn write_block(&mut self, buf: &[u8]) -> Result { + if buf.len() != self.block_size() { + return Err(Error::new(EIO)) + } + let len = min(self.block_size(), buf.len()); + + + print!("Phys: {:X} Virt: {:X} Offset: {:X} Len: {:X}\n", self.phys(), self.addr(), self.current_block() * self.block_size(), len); + unsafe { + copy_nonoverlapping(buf.as_ptr(), (self.addr() + self.current_block() * self.block_size()) as * mut u8, len); + } + + self.cur_pos += 1; + self.cur_pos %= self.block_count(); + + Ok(len) + + } } -/* impl Drop for StreamBuffer { fn drop(&mut self) { unsafe { print!("IHDA: Deallocating buffer.\n"); syscall::physunmap(self.addr); - syscall::physfree(self.phys, self.len); + syscall::physfree(self.phys, self.block_len * self.block_cnt); } } -}*/ +} diff --git a/ihdad/src/main.rs b/ihdad/src/main.rs index 5825ad7cd7..e914783d00 100755 --- a/ihdad/src/main.rs +++ b/ihdad/src/main.rs @@ -6,7 +6,7 @@ extern crate spin; extern crate syscall; extern crate event; -use std::{env, usize, thread}; +use std::{env, usize, u16, thread}; use std::fs::File; use std::io::{Read, Write, Result}; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; @@ -14,14 +14,27 @@ use syscall::{EVENT_READ, MAP_WRITE, Event, Packet, Scheme, SchemeMut}; use std::cell::RefCell; use std::sync::Arc; + use event::EventQueue; use syscall::error::EWOULDBLOCK; + pub mod HDA; - use HDA::IntelHDA; + + + + + +/* + VEND:PROD + Virtualbox 8086:2668 + QEMU ICH9 8086:293E + 82801H ICH8 8086:284B +*/ + fn main() { let mut args = env::args().skip(1); @@ -34,8 +47,17 @@ fn main() { let irq_str = args.next().expect("ihda: no irq provided"); let irq = irq_str.parse::().expect("ihda: failed to parse irq"); + + let vend_str = args.next().expect("ihda: no vendor id provided"); + let vend = usize::from_str_radix(&vend_str, 16).expect("ihda: failed to parse vendor id"); + + + let prod_str = args.next().expect("ihda: no product id provided"); + let prod = usize::from_str_radix(&prod_str, 16).expect("ihda: failed to parse product id"); + print!("{}", format!(" + ihda {} on: {:X} IRQ: {}\n", name, bar, irq)); + // Daemonize if unsafe { syscall::clone(0).unwrap() } == 0 { @@ -45,8 +67,10 @@ fn main() { let mut irq_file = File::open(format!("irq:{}", irq)).expect("IHDA: failed to open IRQ file"); + let vend_prod:u32 = ((vend as u32) << 16) | (prod as u32); - let device = Arc::new(RefCell::new(unsafe { HDA::IntelHDA::new(address).expect("ihdad: failed to allocate device") })); + + let device = Arc::new(RefCell::new(unsafe { HDA::IntelHDA::new(address, vend_prod).expect("ihdad: failed to allocate device") })); let socket_fd = syscall::open(":audio", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("IHDA: failed to create audio scheme"); let socket = Arc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd) })); @@ -95,7 +119,6 @@ fn main() { } Ok(Some(0)) }).expect("IHDA: failed to catch events on IRQ file"); - let socket_fd = socket.borrow().as_raw_fd(); let socket_packet = socket.clone(); event_queue.add(socket_fd, move |_count: usize| -> Result> { @@ -114,6 +137,8 @@ fn main() { socket_packet.borrow_mut().write(&mut packet)?; } } + + /* let next_read = device.borrow().next_read(); if next_read > 0 { @@ -138,6 +163,7 @@ fn main() { + loop { { //device_loop.borrow_mut().handle_interrupts();