1 // Copyright 2018 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use std::os::unix::io::RawFd; 6 7 use audio_streams::StreamSource; 8 use resources::{Alloc, SystemAllocator}; 9 use sys_util::{error, EventFd, GuestMemory}; 10 11 use crate::pci::ac97_bus_master::Ac97BusMaster; 12 use crate::pci::ac97_mixer::Ac97Mixer; 13 use crate::pci::ac97_regs::*; 14 use crate::pci::pci_configuration::{ 15 PciBarConfiguration, PciClassCode, PciConfiguration, PciHeaderType, PciMultimediaSubclass, 16 }; 17 use crate::pci::pci_device::{self, PciDevice, Result}; 18 use crate::pci::PciInterruptPin; 19 20 // Use 82801AA because it's what qemu does. 21 const PCI_DEVICE_ID_INTEL_82801AA_5: u16 = 0x2415; 22 23 /// AC97 audio device emulation. 24 /// Provides the PCI interface for the internal Ac97 emulation. 25 /// Internally the `Ac97BusMaster` and `Ac97Mixer` structs are used to emulated the bus master and 26 /// mixer registers respectively. `Ac97BusMaster` handles moving smaples between guest memory and 27 /// the audio backend. 28 pub struct Ac97Dev { 29 config_regs: PciConfiguration, 30 pci_bus_dev: Option<(u8, u8)>, 31 // The irq events are temporarily saved here. They need to be passed to the device after the 32 // jail forks. This happens when the bus is first written. 33 irq_evt: Option<EventFd>, 34 irq_resample_evt: Option<EventFd>, 35 bus_master: Ac97BusMaster, 36 mixer: Ac97Mixer, 37 } 38 39 impl Ac97Dev { 40 /// Creates an 'Ac97Dev' that uses the given `GuestMemory` and starts with all registers at 41 /// default values. new(mem: GuestMemory, audio_server: Box<dyn StreamSource>) -> Self42 pub fn new(mem: GuestMemory, audio_server: Box<dyn StreamSource>) -> Self { 43 let config_regs = PciConfiguration::new( 44 0x8086, 45 PCI_DEVICE_ID_INTEL_82801AA_5, 46 PciClassCode::MultimediaController, 47 &PciMultimediaSubclass::AudioDevice, 48 None, // No Programming interface. 49 PciHeaderType::Device, 50 0x8086, // Subsystem Vendor ID 51 0x1, // Subsystem ID. 52 ); 53 54 Ac97Dev { 55 config_regs, 56 pci_bus_dev: None, 57 irq_evt: None, 58 irq_resample_evt: None, 59 bus_master: Ac97BusMaster::new(mem, audio_server), 60 mixer: Ac97Mixer::new(), 61 } 62 } 63 read_mixer(&mut self, offset: u64, data: &mut [u8])64 fn read_mixer(&mut self, offset: u64, data: &mut [u8]) { 65 match data.len() { 66 // The mixer is only accessed with 16-bit words. 67 2 => { 68 let val: u16 = self.mixer.readw(offset); 69 data[0] = val as u8; 70 data[1] = (val >> 8) as u8; 71 } 72 l => error!("mixer read length of {}", l), 73 } 74 } 75 write_mixer(&mut self, offset: u64, data: &[u8])76 fn write_mixer(&mut self, offset: u64, data: &[u8]) { 77 match data.len() { 78 // The mixer is only accessed with 16-bit words. 79 2 => self 80 .mixer 81 .writew(offset, u16::from(data[0]) | u16::from(data[1]) << 8), 82 l => error!("mixer write length of {}", l), 83 } 84 // Apply the new mixer settings to the bus master. 85 self.bus_master.update_mixer_settings(&self.mixer); 86 } 87 read_bus_master(&mut self, offset: u64, data: &mut [u8])88 fn read_bus_master(&mut self, offset: u64, data: &mut [u8]) { 89 match data.len() { 90 1 => data[0] = self.bus_master.readb(offset), 91 2 => { 92 let val: u16 = self.bus_master.readw(offset); 93 data[0] = val as u8; 94 data[1] = (val >> 8) as u8; 95 } 96 4 => { 97 let val: u32 = self.bus_master.readl(offset); 98 data[0] = val as u8; 99 data[1] = (val >> 8) as u8; 100 data[2] = (val >> 16) as u8; 101 data[3] = (val >> 24) as u8; 102 } 103 l => error!("read length of {}", l), 104 } 105 } 106 write_bus_master(&mut self, offset: u64, data: &[u8])107 fn write_bus_master(&mut self, offset: u64, data: &[u8]) { 108 match data.len() { 109 1 => self.bus_master.writeb(offset, data[0], &self.mixer), 110 2 => self 111 .bus_master 112 .writew(offset, u16::from(data[0]) | u16::from(data[1]) << 8), 113 4 => self.bus_master.writel( 114 offset, 115 (u32::from(data[0])) 116 | (u32::from(data[1]) << 8) 117 | (u32::from(data[2]) << 16) 118 | (u32::from(data[3]) << 24), 119 ), 120 l => error!("write length of {}", l), 121 } 122 } 123 } 124 125 impl PciDevice for Ac97Dev { debug_label(&self) -> String126 fn debug_label(&self) -> String { 127 "AC97".to_owned() 128 } 129 assign_bus_dev(&mut self, bus: u8, device: u8)130 fn assign_bus_dev(&mut self, bus: u8, device: u8) { 131 self.pci_bus_dev = Some((bus, device)); 132 } 133 assign_irq( &mut self, irq_evt: EventFd, irq_resample_evt: EventFd, irq_num: u32, irq_pin: PciInterruptPin, )134 fn assign_irq( 135 &mut self, 136 irq_evt: EventFd, 137 irq_resample_evt: EventFd, 138 irq_num: u32, 139 irq_pin: PciInterruptPin, 140 ) { 141 self.config_regs.set_irq(irq_num as u8, irq_pin); 142 self.irq_evt = Some(irq_evt); 143 self.irq_resample_evt = Some(irq_resample_evt); 144 } 145 allocate_io_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<(u64, u64)>>146 fn allocate_io_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<(u64, u64)>> { 147 let (bus, dev) = self 148 .pci_bus_dev 149 .expect("assign_bus_dev must be called prior to allocate_io_bars"); 150 let mut ranges = Vec::new(); 151 let mixer_regs_addr = resources 152 .mmio_allocator() 153 .allocate( 154 MIXER_REGS_SIZE, 155 Alloc::PciBar { bus, dev, bar: 0 }, 156 "ac97-mixer_regs".to_string(), 157 ) 158 .map_err(|e| pci_device::Error::IoAllocationFailed(MIXER_REGS_SIZE, e))?; 159 let mixer_config = PciBarConfiguration::default() 160 .set_register_index(0) 161 .set_address(mixer_regs_addr) 162 .set_size(MIXER_REGS_SIZE); 163 self.config_regs 164 .add_pci_bar(&mixer_config) 165 .map_err(|e| pci_device::Error::IoRegistrationFailed(mixer_regs_addr, e))?; 166 ranges.push((mixer_regs_addr, MIXER_REGS_SIZE)); 167 168 let master_regs_addr = resources 169 .mmio_allocator() 170 .allocate( 171 MASTER_REGS_SIZE, 172 Alloc::PciBar { bus, dev, bar: 1 }, 173 "ac97-master_regs".to_string(), 174 ) 175 .map_err(|e| pci_device::Error::IoAllocationFailed(MASTER_REGS_SIZE, e))?; 176 let master_config = PciBarConfiguration::default() 177 .set_register_index(1) 178 .set_address(master_regs_addr) 179 .set_size(MASTER_REGS_SIZE); 180 self.config_regs 181 .add_pci_bar(&master_config) 182 .map_err(|e| pci_device::Error::IoRegistrationFailed(master_regs_addr, e))?; 183 ranges.push((master_regs_addr, MASTER_REGS_SIZE)); 184 Ok(ranges) 185 } 186 config_registers(&self) -> &PciConfiguration187 fn config_registers(&self) -> &PciConfiguration { 188 &self.config_regs 189 } 190 config_registers_mut(&mut self) -> &mut PciConfiguration191 fn config_registers_mut(&mut self) -> &mut PciConfiguration { 192 &mut self.config_regs 193 } 194 keep_fds(&self) -> Vec<RawFd>195 fn keep_fds(&self) -> Vec<RawFd> { 196 if let Some(server_fds) = self.bus_master.keep_fds() { 197 server_fds 198 } else { 199 Vec::new() 200 } 201 } 202 read_bar(&mut self, addr: u64, data: &mut [u8])203 fn read_bar(&mut self, addr: u64, data: &mut [u8]) { 204 let bar0 = u64::from(self.config_regs.get_bar_addr(0)); 205 let bar1 = u64::from(self.config_regs.get_bar_addr(1)); 206 match addr { 207 a if a >= bar0 && a < bar0 + MIXER_REGS_SIZE => self.read_mixer(addr - bar0, data), 208 a if a >= bar1 && a < bar1 + MASTER_REGS_SIZE => { 209 self.read_bus_master(addr - bar1, data) 210 } 211 _ => (), 212 } 213 } 214 write_bar(&mut self, addr: u64, data: &[u8])215 fn write_bar(&mut self, addr: u64, data: &[u8]) { 216 let bar0 = u64::from(self.config_regs.get_bar_addr(0)); 217 let bar1 = u64::from(self.config_regs.get_bar_addr(1)); 218 match addr { 219 a if a >= bar0 && a < bar0 + MIXER_REGS_SIZE => self.write_mixer(addr - bar0, data), 220 a if a >= bar1 && a < bar1 + MASTER_REGS_SIZE => { 221 // Check if the irq needs to be passed to the device. 222 if let (Some(irq_evt), Some(irq_resample_evt)) = 223 (self.irq_evt.take(), self.irq_resample_evt.take()) 224 { 225 self.bus_master.set_irq_event_fd(irq_evt, irq_resample_evt); 226 } 227 self.write_bus_master(addr - bar1, data) 228 } 229 _ => (), 230 } 231 } 232 } 233 234 #[cfg(test)] 235 mod tests { 236 use super::*; 237 use audio_streams::DummyStreamSource; 238 use sys_util::GuestAddress; 239 240 #[test] create()241 fn create() { 242 let mem = GuestMemory::new(&[(GuestAddress(0u64), 4 * 1024 * 1024)]).unwrap(); 243 let mut ac97_dev = Ac97Dev::new(mem, Box::new(DummyStreamSource::new())); 244 let mut allocator = SystemAllocator::builder() 245 .add_io_addresses(0x1000_0000, 0x1000_0000) 246 .add_mmio_addresses(0x2000_0000, 0x1000_0000) 247 .add_device_addresses(0x3000_0000, 0x1000_0000) 248 .create_allocator(5, false) 249 .unwrap(); 250 ac97_dev.assign_bus_dev(0, 0); 251 assert!(ac97_dev.allocate_io_bars(&mut allocator).is_ok()); 252 } 253 } 254