diff --git a/ihdad/src/HDA/cmdbuff.rs b/ihdad/src/HDA/cmdbuff.rs deleted file mode 100644 index 17efa8cdf7..0000000000 --- a/ihdad/src/HDA/cmdbuff.rs +++ /dev/null @@ -1,469 +0,0 @@ -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 deleted file mode 100644 index 67a35350a0..0000000000 --- a/ihdad/src/HDA/common.rs +++ /dev/null @@ -1,193 +0,0 @@ - - -use std::{mem, thread, ptr, fmt}; -use std::mem::transmute; -pub type HDANodeAddr = 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)] -pub enum HDAWidgetType{ - AudioOutput = 0x0, - AudioInput = 0x1, - AudioMixer = 0x2, - AudioSelector = 0x3, - PinComplex = 0x4, - Power = 0x5, - VolumeKnob = 0x6, - BeepGenerator = 0x7, - - - VendorDefined = 0xf, -} - -impl fmt::Display for HDAWidgetType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self) - } -} - - -#[derive(Debug, PartialEq)] -#[repr(u8)] -pub enum DefaultDevice { - LineOut = 0x0, - Speaker = 0x1, - HPOut = 0x2, - CD = 0x3, - SPDIF = 0x4, - DigitalOtherOut = 0x5, - ModemLineSide = 0x6, - ModemHandsetSide = 0x7, - LineIn = 0x8, - AUX = 0x9, - MicIn = 0xA, - Telephony = 0xB, - SPDIFIn = 0xC, - DigitalOtherIn = 0xD, - Reserved = 0xE, - 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/cmdbuff.rs b/ihdad/src/hda/cmdbuff.rs new file mode 100644 index 0000000000..730ae1518c --- /dev/null +++ b/ihdad/src/hda/cmdbuff.rs @@ -0,0 +1,430 @@ +use syscall::io::{Io, Mmio}; + +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 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 read_pos: u16 = (self.rirb_rp + 1) % self.rirb_count as u16; + + let 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 new file mode 100644 index 0000000000..c2d5215e94 --- /dev/null +++ b/ihdad/src/hda/common.rs @@ -0,0 +1,195 @@ +use std::fmt; +use std::mem::transmute; + +pub type HDANodeAddr = 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)] +pub enum HDAWidgetType { + AudioOutput = 0x0, + AudioInput = 0x1, + AudioMixer = 0x2, + AudioSelector = 0x3, + PinComplex = 0x4, + Power = 0x5, + VolumeKnob = 0x6, + BeepGenerator = 0x7, + + VendorDefined = 0xf, +} + +impl fmt::Display for HDAWidgetType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self) + } +} + +#[derive(Debug, PartialEq)] +#[repr(u8)] +pub enum DefaultDevice { + LineOut = 0x0, + Speaker = 0x1, + HPOut = 0x2, + CD = 0x3, + SPDIF = 0x4, + DigitalOtherOut = 0x5, + ModemLineSide = 0x6, + ModemHandsetSide = 0x7, + LineIn = 0x8, + AUX = 0x9, + MicIn = 0xA, + Telephony = 0xB, + SPDIFIn = 0xC, + DigitalOtherIn = 0xD, + Reserved = 0xE, + 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() + ) + } +} diff --git a/ihdad/src/HDA/device.rs b/ihdad/src/hda/device.rs similarity index 86% rename from ihdad/src/HDA/device.rs rename to ihdad/src/hda/device.rs index f17c79f08c..7a832d1670 100755 --- a/ihdad/src/HDA/device.rs +++ b/ihdad/src/hda/device.rs @@ -1,24 +1,16 @@ #![allow(dead_code)] -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 syscall::PHYSMAP_WRITE; use syscall::error::{Error, EACCES, EBADF, Result, EINVAL}; use syscall::flag::{SEEK_SET, SEEK_CUR, SEEK_END}; use syscall::io::{Mmio, Io}; -use syscall::scheme::SchemeMut; +use syscall::scheme::SchemeBlockMut; use spin::Mutex; @@ -58,24 +50,20 @@ const RIRBDMAEN: u8 = 1 << 1; // 1 bit const ICB: u16 = 1 << 0; const IRV: u16 = 1 << 1; - // CORB and RIRB offset const COMMAND_BUFFER_OFFSET: usize = 0x40; - const NUM_SUB_BUFFS: usize = 2; -const SUB_BUFF_SIZE: usize = 0x4000; - +const SUB_BUFF_SIZE: usize = 2048; enum Handle { + Todo, 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 { @@ -125,26 +113,20 @@ struct Regs { dplbase: Mmio, // 0x70 dpubase: Mmio, // 0x74 - } pub struct IntelHDA { - vend_prod: u32, base: usize, regs: &'static mut Regs, - //corb_rirb_base_phys: usize, - cmd: CommandBuffer, codecs: Vec, - - outputs: Vec, inputs: Vec, @@ -152,14 +134,12 @@ pub struct IntelHDA { output_pins: Vec, input_pins: Vec, - + beep_addr: WidgetAddr, - buff_desc: &'static mut [BufferDescriptorListEntry; 256], buff_desc_phys: usize, - - + output_streams: Vec, buffs: Vec>, @@ -169,38 +149,29 @@ pub struct IntelHDA { next_id: AtomicUsize, } - impl IntelHDA { 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.") }; - - let buff_desc_virt = unsafe { + let buff_desc_virt = unsafe { syscall::physmap(buff_desc_phys, 0x1000, PHYSMAP_WRITE) - .expect("ihdad: failed to map address for buffer descriptor list.") + .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 cmd_buff_address = unsafe { syscall::physalloc(0x1000) .expect("Could not allocate physical memory for CORB and RIRB.") }; - let cmd_buff_virt = unsafe { syscall::physmap(cmd_buff_address, 0x1000, PHYSMAP_WRITE).expect("ihdad: failed to map address for CORB/RIRB buff") }; print!("Virt: {:016X}, Phys: {:016X}\n", cmd_buff_virt, cmd_buff_address); @@ -208,16 +179,15 @@ impl IntelHDA { vend_prod: vend_prod, base: base, regs: regs, - + cmd: CommandBuffer::new(base + COMMAND_BUFFER_OFFSET, cmd_buff_address, cmd_buff_virt), beep_addr: (0,0), - + widget_map: HashMap::::new(), - codecs: Vec::::new(), - + outputs: Vec::::new(), inputs: Vec::::new(), @@ -227,24 +197,20 @@ impl IntelHDA { buff_desc: buff_desc, buff_desc_phys: buff_desc_phys, - - output_streams: Vec::::new(), - buffs: Vec::>::new(), - int_counter: 0, handles: Mutex::new(BTreeMap::new()), - next_id: AtomicUsize::new(0), + next_id: AtomicUsize::new(0), }; - + module.init(); - + // module.info(); module.enumerate(); - + module.configure(); print!("IHDA: Initialization finished.\n"); Ok(module) @@ -255,14 +221,14 @@ impl IntelHDA { self.reset_controller(); let use_immediate_command_interface = match self.vend_prod { - + 0x8086_2668 => false, _ => true, - }; + }; - self.cmd.init(use_immediate_command_interface); + self.cmd.init(use_immediate_command_interface); self.init_interrupts(); - + true } @@ -274,15 +240,10 @@ impl IntelHDA { self.regs.intctl.write((1 << 31) | /* (1 << 30) |*/ (1 << 4)); } - - - - pub fn irq(&mut self) -> bool { + pub fn irq(&mut self) -> bool { self.int_counter += 1; - - self.handle_interrupts(); - true + self.handle_interrupts() } pub fn int_count(&self) -> usize { @@ -294,12 +255,12 @@ impl IntelHDA { let mut temp:u64; node.addr = addr; - + temp = self.cmd.cmd12( addr, 0xF00, 0x04); node.subnode_count = (temp & 0xff) as u16; node.subnode_start = ((temp >> 16) & 0xff) as u16; - + if addr == (0,0) { return node; } @@ -316,41 +277,39 @@ impl IntelHDA { node.conn_list_len = (temp & 0xFF) as u8; node.connections = self.node_get_connection_list(&node); - + node.config_default = self.cmd.cmd12(addr, 0xF1C, 0x00) as u32; node - } 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 - + let count:u8 = len_field & 0x7F; let use_long_addr: bool = (len_field >> 7) & 0x1 == 1; - + let mut current: u8 = 0; - + let mut list = Vec::::new(); while current < count { - + let response: u32 = (self.cmd.cmd12(node.addr, 0xF02, current) & 0xFFFFFFFF) as u32; - + if use_long_addr { for i in 0..2 { let addr_field = ((response >> (16 * i)) & 0xFFFF) as u16; - let addr = (addr_field & 0x7FFF); + let addr = addr_field & 0x7FFF; if addr == 0 { break; } - + if (addr_field >> 15) & 0x1 == 0x1 { - for i in (list.pop().unwrap().1 .. (addr + 1)) { + for i in list.pop().unwrap().1 .. (addr + 1) { list.push((node.addr.0, i)); } } else { @@ -359,56 +318,50 @@ impl IntelHDA { } } else { - for i in 0..4 { let addr_field = ((response >> (8 * i)) & 0xff) as u16; - let addr = (addr_field & 0x7F); - - if addr == 0 { break; } + let addr = addr_field & 0x7F; + + if addr == 0 { break; } if (addr_field >> 7) & 0x1 == 0x1 { - for i in (list.pop().unwrap().1 .. (addr + 1)) { + for i in list.pop().unwrap().1 .. (addr + 1) { list.push((node.addr.0, i)); } } else { list.push((node.addr.0, addr)); } } - } - + current = list.len() as u8; - } + list - } + pub fn enumerate(&mut self) { - - self.output_pins.clear(); self.input_pins.clear(); - let codec:u8 = 0; - + let root = self.read_node((codec,0)); - + // print!("{}\n", root); let root_count = root.subnode_count; let root_start = root.subnode_start; - //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 { + for i in 0..root_count { let afg = self.read_node((codec, root_start + i)); // print!("{}\n", afg); let afg_count = afg.subnode_count; let afg_start = afg.subnode_start; - + for j in 0..afg_count { - + let mut widget = self.read_node((codec, afg_start + j)); widget.is_widget = true; match widget.widget_type() { @@ -419,26 +372,22 @@ impl IntelHDA { let config = widget.configuration_default(); if config.is_output() { self.output_pins.push(widget.addr); - } else if (config.is_input()) { + } 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.widget_map.insert(widget.addr(), widget); - } + } } } - - - pub fn find_best_output_pin(&self) -> Option{ let outs = &self.output_pins; if outs.len() == 0 { @@ -448,10 +397,10 @@ impl IntelHDA { } 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); @@ -462,8 +411,6 @@ impl IntelHDA { } } - - pub fn find_path_to_dac(&self, addr: WidgetAddr) -> Option>{ let widget = self.widget_map.get(&addr).unwrap(); if widget.widget_type() == HDAWidgetType::AudioOutput { @@ -474,7 +421,7 @@ impl IntelHDA { }else{ // TODO: do more than just first widget - let mut res = self.find_path_to_dac(widget.connections[0]); + let res = self.find_path_to_dac(widget.connections[0]); match res { Some(p) => { let mut ret = p.clone(); @@ -486,11 +433,8 @@ impl IntelHDA { } } - } + } - - - /* Here we update the buffers and split them into 128 byte sub chunks because each BufferDescriptorList needs to be 128 byte aligned, @@ -503,7 +447,7 @@ impl IntelHDA { Fixed? */ - + pub fn update_sound_buffers(&mut self) { /* for i in 0..self.buffs.len(){ @@ -516,31 +460,22 @@ impl IntelHDA { let r = self.get_output_stream_descriptor(0).unwrap(); - - self.output_streams.push(OutputStream::new(2, 0x4000, r)); + self.output_streams.push(OutputStream::new(NUM_SUB_BUFFS, SUB_BUFF_SIZE, 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[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); - - } - - - 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(); @@ -552,7 +487,6 @@ impl IntelHDA { // Pin enable self.cmd.cmd12(pin, 0x707, 0x40); - // EAPD enable self.cmd.cmd12(pin, 0x70C, 2); @@ -561,16 +495,12 @@ impl IntelHDA { self.update_sound_buffers(); - //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_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 @@ -581,8 +511,8 @@ impl IntelHDA { 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 @@ -590,14 +520,14 @@ impl IntelHDA { 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(); @@ -605,7 +535,7 @@ impl IntelHDA { // Pin enable self.cmd.cmd12((0,0xC), 0x707, 0x40); - + // EAPD enable self.cmd.cmd12((0,0xC), 0x70C, 2); @@ -619,11 +549,11 @@ impl IntelHDA { 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); + output.set_cyclic_buffer_length(0x8000); output.set_stream_number(1); output.set_last_valid_index(1); output.set_interrupt_on_completion(true); @@ -631,8 +561,8 @@ impl IntelHDA { 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.cmd.cmd12((0,0x3), 0xA00, 0); // Unmute and set gain for pin complex and DAC @@ -642,35 +572,29 @@ impl IntelHDA { output.run(); self.beep(1); - + } - + */ // BEEP!! pub fn beep(&mut self, div:u8) { let addr = self.beep_addr; if addr != (0,0) { - let _ = self.cmd.cmd12(addr, 0xF0A, div); - } - } - + pub fn read_beep(&mut self) -> u8 { let addr = self.beep_addr; if addr != (0,0) { - self.cmd.cmd12(addr, 0x70A, 0) as u8 }else{ 0 } - } pub fn reset_controller(&mut self) -> bool { - self.regs.statests.write(0xFFFF); // 3.3.7 @@ -700,17 +624,17 @@ impl IntelHDA { for i in 0..15 { if (statests >> i) & 0x1 == 1 { self.codecs.push(i as CodecAddr); - } + } } true } - + pub fn num_output_streams(&self) -> usize{ let gcap = self.regs.gcap.read(); ((gcap >> 12) & 0xF) as usize } - + pub fn num_input_streams(&self) -> usize{ let gcap = self.regs.gcap.read(); ((gcap >> 8) & 0xF) as usize @@ -735,8 +659,6 @@ impl IntelHDA { print!("IHDA: 64-Bit: {}\n", self.regs.gcap.read() & 1 == 1); } - - fn get_input_stream_descriptor(&self, index: usize) -> Option<&'static mut StreamDescriptorRegs> { unsafe { if index < self.num_input_streams() { @@ -750,7 +672,7 @@ impl IntelHDA { fn get_output_stream_descriptor(&self, index: usize) -> Option<&'static mut StreamDescriptorRegs> { unsafe { if index < self.num_output_streams() { - Some(&mut *((self.base + 0x80 + + Some(&mut *((self.base + 0x80 + self.num_input_streams() * 0x20 + index * 0x20) as *mut StreamDescriptorRegs)) }else{ @@ -763,7 +685,7 @@ impl IntelHDA { fn get_bidirectional_stream_descriptor(&self, index: usize) -> Option<&'static mut StreamDescriptorRegs> { unsafe { if index < self.num_bidirectional_streams() { - Some(&mut *((self.base + 0x80 + + Some(&mut *((self.base + 0x80 + self.num_input_streams() * 0x20 + self.num_output_streams() * 0x20 + index * 0x20) as *mut StreamDescriptorRegs)) @@ -802,38 +724,29 @@ impl IntelHDA { self.cmd.cmd4(addr, 0x2, fmt); } - - 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; - - if output { payload |= (1 << 15); } - if input { payload |= (1 << 14); } - if left { payload |= (1 << 13); } - if right { payload |= (1 << 12); } - if mute { payload |= (1 << 7); } + + if output { payload |= 1 << 15; } + if input { payload |= 1 << 14; } + if left { payload |= 1 << 13; } + if right { payload |= 1 << 12; } + if mute { payload |= 1 << 7; } payload |= ((index as u16) & 0x0F) << 8; - payload |= ((gain as u16) & 0x7F); + payload |= (gain as u16) & 0x7F; self.cmd.cmd4(addr, 0x3, payload); - + } - pub fn write_to_output(&mut self, index:u8, buf: &[u8]) -> Result { + pub fn write_to_output(&mut self, index:u8, buf: &[u8]) -> Result> { + let output = self.get_output_stream_descriptor(index as usize).unwrap(); + let os = self.output_streams.get_mut(index as usize).unwrap(); - 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 sample_size:usize = output.sample_size(); + //let sample_size:usize = output.sample_size(); let mut open_block = (output.link_position() as usize) / os.block_size(); - - - if open_block == 0 { open_block = 1; } else { @@ -841,43 +754,33 @@ impl IntelHDA { } //print!("Status: {:02X} Pos: {:08X} Output CTL: {:06X}\n", output.status(), output.link_position(), output.control()); - while open_block == os.current_block() { - open_block = (output.link_position() as usize) / os.block_size(); - - if open_block == 0 { - open_block = os.block_count() - 1; - } else { - open_block = open_block - 1; - } - - - thread::yield_now(); + if open_block == os.current_block() { + Ok(None) + } else { + os.write_block(buf).map(|count| Some(count)) } - - let len = min(os.block_size(), buf.len()); - - os.write_block(buf) } - pub fn handle_interrupts(&mut self) { - + pub fn handle_interrupts(&mut self) -> bool { let intsts = self.regs.intsts.read(); - let sis = intsts & 0x3FFFFFFF; - // print!("IHDA INTSTS: {:08X}\n", intsts); + let sis = intsts & 0x3FFFFFFF; + //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(); - } + } if sis != 0 { self.handle_stream_interrupts(sis); } } + + intsts != 0 } pub fn handle_controller_interrupt(&mut self) { - + } pub fn handle_stream_interrupts(&mut self, sis: u32) { @@ -887,78 +790,76 @@ impl IntelHDA { for i in 0..iss { if ((sis >> i) & 1 ) == 1 { - let mut input = self.get_input_stream_descriptor(i).unwrap(); + 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(); + let mut output = self.get_output_stream_descriptor(i).unwrap(); 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(); + let mut bid = self.get_bidirectional_stream_descriptor(i).unwrap(); bid.clear_interrupts(); } } } - - fn validate_path(&mut self, path: &Vec<&str>) -> bool { + 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") => { + 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#") => { + 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)); + 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") => { + 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") => { + 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, + _ => false, } - } + } } @@ -969,44 +870,43 @@ impl Drop for IntelHDA { } } - -impl SchemeMut for IntelHDA { - - - - fn open(&mut self, _path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { - let path: Vec<&str>; +impl SchemeBlockMut for IntelHDA { + 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(0) + let id = self.next_id.fetch_add(1, Ordering::SeqCst); + self.handles.lock().insert(id, Handle::Todo); + Ok(Some(id)) } else { Err(Error::new(EACCES)) } } - fn write(&mut self, _id: usize, buf: &[u8]) -> Result { - - //print!("Int count: {}\n", self.int_counter); - + fn write(&mut self, id: usize, buf: &[u8]) -> Result> { + let index = { + let mut handles = self.handles.lock(); + let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; + 0 + }; - self.write_to_output(0, buf) + //print!("Int count: {}\n", self.int_counter); + + self.write_to_output(index, buf) } - fn seek(&mut self, id: usize, pos: usize, whence: usize) -> Result { + 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) => { @@ -1017,29 +917,28 @@ impl SchemeMut for IntelHDA { 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) + Ok(Some(*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)) - } - - fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result { - //let mut handles = self.handles.lock(); - //let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; + fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result> { + let mut handles = self.handles.lock(); + let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; let mut i = 0; - let scheme_path = b"audio:"; + let scheme_path = b"hda:"; while i < buf.len() && i < scheme_path.len() { buf[i] = scheme_path[i]; i += 1; } - Ok(i) + Ok(Some(i)) } + + fn close(&mut self, id: usize) -> Result> { + let mut handles = self.handles.lock(); + handles.remove(&id).ok_or(Error::new(EBADF)).and(Ok(Some(0))) + } } diff --git a/ihdad/src/HDA/mod.rs b/ihdad/src/hda/mod.rs similarity index 99% rename from ihdad/src/HDA/mod.rs rename to ihdad/src/hda/mod.rs index 90330ee8d6..36b40d3fa3 100644 --- a/ihdad/src/HDA/mod.rs +++ b/ihdad/src/hda/mod.rs @@ -15,6 +15,3 @@ pub use self::stream::BufferDescriptorListEntry; pub use self::stream::BitsPerSample; pub use self::stream::StreamBuffer; pub use self::device::IntelHDA; - - - diff --git a/ihdad/src/HDA/node.rs b/ihdad/src/hda/node.rs similarity index 68% rename from ihdad/src/HDA/node.rs rename to ihdad/src/hda/node.rs index edbb3727e0..69e6c7e137 100644 --- a/ihdad/src/HDA/node.rs +++ b/ihdad/src/hda/node.rs @@ -1,50 +1,43 @@ - -use std::{mem, thread, ptr, fmt}; +use std::{mem, fmt}; use super::common::*; #[derive(Clone)] pub struct HDANode { pub addr: WidgetAddr, - - // 0x4 pub subnode_count: u16, pub subnode_start: u16, - + // 0x5 pub function_group_type: u8, - // 0x9 pub capabilities: u32, // 0xC pub pin_caps: u32, - + // 0xD pub in_amp: u32, - + // 0xE pub conn_list_len: u8, - // 0x12 pub out_amp: u32, // 0x13 pub vol_knob: u8, - + pub connections: Vec, - + pub is_widget: bool, pub config_default: u32, } - impl HDANode { - pub fn new() -> HDANode { HDANode { addr: (0,0), @@ -76,7 +69,7 @@ impl HDANode { Some(unsafe { mem::transmute( ((self.config_default >> 20) & 0xF) as u8 )} ) } } - + pub fn configuration_default(&self) -> ConfigurationDefault { ConfigurationDefault::from_u32(self.config_default) } @@ -89,29 +82,23 @@ impl HDANode { impl fmt::Display for HDANode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 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}:{:02X}, Type: {:?}: {:?}, Inputs: {:X}: {:?}.", - self.addr.0, - self.addr.1, - self.widget_type(), - self.device_default().unwrap(), - 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) }, - + 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}:{:02X}, Type: {:?}: {:?}, Inputs: {:X}: {:?}.", + self.addr.0, + self.addr.1, + self.widget_type(), + self.device_default().unwrap(), + 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}:{:02X}, AFG: {}, Widget count {}.", self.addr.0, self.addr.1, self.function_group_type, self.subnode_count) } - } else { - 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 similarity index 93% rename from ihdad/src/HDA/stream.rs rename to ihdad/src/hda/stream.rs index b905f8d24c..9d630fbb1f 100644 --- a/ihdad/src/HDA/stream.rs +++ b/ihdad/src/hda/stream.rs @@ -1,17 +1,10 @@ - - - use syscall::PHYSMAP_WRITE; -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 syscall::error::{Error, EIO, Result}; +use syscall::io::{Mmio, Io}; use std::result; -use std::cmp::{max, min}; +use std::cmp::min; use std::ptr::copy_nonoverlapping; -use std::{mem, thread, ptr, fmt}; +use std::ptr; extern crate syscall; @@ -177,7 +170,7 @@ impl StreamDescriptorRegs { pub fn set_interrupt_on_completion(&mut self, enable:bool) { let mut ctrl = self.control(); if enable { - ctrl |= (1 << 2); + ctrl |= 1 << 2; } else { ctrl &= !(1 << 2); } @@ -286,8 +279,6 @@ impl BufferDescriptorListEntry { } } - - pub struct StreamBuffer { phys: usize, addr: usize, @@ -365,7 +356,7 @@ impl StreamBuffer { 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); + //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); } @@ -381,8 +372,9 @@ impl Drop for StreamBuffer { fn drop(&mut self) { unsafe { print!("IHDA: Deallocating buffer.\n"); - syscall::physunmap(self.addr); - syscall::physfree(self.phys, self.block_len * self.block_cnt); + if syscall::physunmap(self.addr).is_ok() { + let _ = syscall::physfree(self.phys, self.block_len * self.block_cnt); + } } } } diff --git a/ihdad/src/main.rs b/ihdad/src/main.rs index 87374bb66a..b970ecbad5 100755 --- a/ihdad/src/main.rs +++ b/ihdad/src/main.rs @@ -6,22 +6,17 @@ extern crate spin; extern crate syscall; extern crate event; -use std::{env, usize, u16, thread}; +use std::{env, usize}; use std::fs::File; use std::io::{Read, Write, Result}; -use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; -use syscall::{EVENT_READ, PHYSMAP_WRITE, Event, Packet, Scheme, SchemeMut}; +use std::os::unix::io::{AsRawFd, FromRawFd}; +use syscall::{PHYSMAP_WRITE, Packet, SchemeBlockMut}; use std::cell::RefCell; use std::sync::Arc; - use event::EventQueue; -use syscall::error::EWOULDBLOCK; - -pub mod HDA; - -use HDA::IntelHDA; +pub mod hda; /* VEND:PROD @@ -58,8 +53,8 @@ fn main() { let vend_prod:u32 = ((vend as u32) << 16) | (prod as u32); - 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 device = Arc::new(RefCell::new(unsafe { hda::IntelHDA::new(address, vend_prod).expect("ihdad: failed to allocate device") })); + let socket_fd = syscall::open(":hda", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("IHDA: failed to create hda scheme"); let socket = Arc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd) })); let mut event_queue = EventQueue::::new().expect("IHDA: Could not create event queue."); @@ -71,35 +66,32 @@ fn main() { let todo_irq = todo.clone(); let device_irq = device.clone(); let socket_irq = socket.clone(); - let device_loop = device.clone(); event_queue.add(irq_file.as_raw_fd(), move |_event| -> Result> { let mut irq = [0; 8]; irq_file.read(&mut irq)?; - let _irq = unsafe { device_irq.borrow_mut().irq()}; - - if _irq { + if unsafe { device_irq.borrow_mut().irq() } { irq_file.write(&mut irq)?; let mut todo = todo_irq.borrow_mut(); let mut i = 0; while i < todo.len() { - let a = todo[i].a; - device_irq.borrow_mut().handle(&mut todo[i]); - if todo[i].a == (-EWOULDBLOCK) as usize { - todo[i].a = a; - i += 1; - } else { - socket_irq.borrow_mut().write(&mut todo[i])?; - todo.remove(i); + if let Some(a) = device_irq.borrow_mut().handle(&mut todo[i]) { + let mut packet = todo.remove(i); + packet.a = a; + socket_irq.borrow_mut().write(&packet)?; + } else { + i += 1; } } + /* let next_read = device_irq.next_read(); if next_read > 0 { return Ok(Some(next_read)); - }*/ + } + */ } Ok(Some(0)) }).expect("IHDA: failed to catch events on IRQ file"); @@ -112,22 +104,20 @@ fn main() { break; } - let a = packet.a; - device.borrow_mut().handle(&mut packet); - if packet.a == (-EWOULDBLOCK) as usize { + if let Some(a) = device.borrow_mut().handle(&mut packet) { packet.a = a; - todo.borrow_mut().push(packet); + socket_packet.borrow_mut().write(&packet)?; } else { - socket_packet.borrow_mut().write(&mut packet)?; + todo.borrow_mut().push(packet); } } - /* let next_read = device.borrow().next_read(); if next_read > 0 { return Ok(Some(next_read)); - }*/ + } + */ Ok(None) }).expect("IHDA: failed to catch events on IRQ file");