1 // Copyright 2018 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 mod sys;
6
7 use std::sync::atomic::AtomicBool;
8 use std::sync::atomic::Ordering;
9 use std::sync::Arc;
10 use std::thread;
11 use std::time::Instant;
12
13 use audio_streams::StreamControl;
14 use base::error;
15 use base::warn;
16 use remain::sorted;
17 use sync::Condvar;
18 use sync::Mutex;
19 use thiserror::Error;
20 use vm_memory::GuestAddress;
21 use vm_memory::GuestMemory;
22
23 use crate::pci::ac97::sys::AudioStreamSource;
24 use crate::pci::ac97_bus_master::sys::Ac97BusMasterSys;
25 pub(crate) use crate::pci::ac97_bus_master::sys::AudioError;
26 use crate::pci::ac97_mixer::Ac97Mixer;
27 use crate::pci::ac97_regs::*;
28 use crate::IrqLevelEvent;
29
30 const INPUT_SAMPLE_RATE: u32 = 48000;
31 const DEVICE_INPUT_CHANNEL_COUNT: usize = 2;
32
33 // Bus Master registers. Keeps the state of the bus master register values. Used to share the state
34 // between the main and audio threads.
35 struct Ac97BusMasterRegs {
36 pi_regs: Ac97FunctionRegs, // Input
37 po_regs: Ac97FunctionRegs, // Output
38 po_pointer_update_time: Instant, // Time the picb and civ regs were last updated.
39 mc_regs: Ac97FunctionRegs, // Microphone
40 glob_cnt: u32,
41 glob_sta: u32,
42
43 // IRQ event - driven by the glob_sta register.
44 irq_evt: Option<IrqLevelEvent>,
45 }
46
47 impl Ac97BusMasterRegs {
new() -> Ac97BusMasterRegs48 fn new() -> Ac97BusMasterRegs {
49 Ac97BusMasterRegs {
50 pi_regs: Ac97FunctionRegs::new(),
51 po_regs: Ac97FunctionRegs::new(),
52 po_pointer_update_time: Instant::now(),
53 mc_regs: Ac97FunctionRegs::new(),
54 glob_cnt: 0,
55 glob_sta: GLOB_STA_RESET_VAL,
56 irq_evt: None,
57 }
58 }
59
func_regs(&self, func: Ac97Function) -> &Ac97FunctionRegs60 fn func_regs(&self, func: Ac97Function) -> &Ac97FunctionRegs {
61 match func {
62 Ac97Function::Input => &self.pi_regs,
63 Ac97Function::Output => &self.po_regs,
64 Ac97Function::Microphone => &self.mc_regs,
65 }
66 }
67
func_regs_mut(&mut self, func: Ac97Function) -> &mut Ac97FunctionRegs68 fn func_regs_mut(&mut self, func: Ac97Function) -> &mut Ac97FunctionRegs {
69 match func {
70 Ac97Function::Input => &mut self.pi_regs,
71 Ac97Function::Output => &mut self.po_regs,
72 Ac97Function::Microphone => &mut self.mc_regs,
73 }
74 }
75
tube_count(&self, func: Ac97Function) -> usize76 fn tube_count(&self, func: Ac97Function) -> usize {
77 fn output_tube_count(glob_cnt: u32) -> usize {
78 let val = (glob_cnt & GLOB_CNT_PCM_246_MASK) >> 20;
79 match val {
80 0 => 2,
81 1 => 4,
82 2 => 6,
83 _ => {
84 warn!("unknown tube_count: 0x{:x}", val);
85 2
86 }
87 }
88 }
89
90 match func {
91 Ac97Function::Output => output_tube_count(self.glob_cnt),
92 _ => DEVICE_INPUT_CHANNEL_COUNT,
93 }
94 }
95
96 /// Returns whether the irq is set for any one of the bus master function registers.
has_irq(&self) -> bool97 pub fn has_irq(&self) -> bool {
98 self.pi_regs.has_irq() || self.po_regs.has_irq() || self.mc_regs.has_irq()
99 }
100 }
101
102 // Internal error type used for reporting errors from guest memory reading.
103 #[sorted]
104 #[derive(Error, Debug)]
105 pub(crate) enum GuestMemoryError {
106 // Failure getting the address of the audio buffer.
107 #[error("Failed to get the address of the audio buffer: {0}.")]
108 ReadingGuestBufferAddress(vm_memory::GuestMemoryError),
109 }
110
111 impl From<GuestMemoryError> for AudioError {
from(err: GuestMemoryError) -> Self112 fn from(err: GuestMemoryError) -> Self {
113 AudioError::ReadingGuestError(err)
114 }
115 }
116
117 type GuestMemoryResult<T> = std::result::Result<T, GuestMemoryError>;
118
119 type AudioResult<T> = std::result::Result<T, AudioError>;
120
121 // Audio thread book-keeping data
122 struct AudioThreadInfo {
123 thread: Option<thread::JoinHandle<()>>,
124 thread_run: Arc<AtomicBool>,
125 thread_semaphore: Arc<Condvar>,
126 stream_control: Option<Box<dyn StreamControl>>,
127 }
128
129 impl AudioThreadInfo {
new() -> Self130 fn new() -> Self {
131 Self {
132 thread: None,
133 thread_run: Arc::new(AtomicBool::new(false)),
134 thread_semaphore: Arc::new(Condvar::new()),
135 stream_control: None,
136 }
137 }
138
is_running(&self) -> bool139 fn is_running(&self) -> bool {
140 self.thread_run.load(Ordering::Relaxed)
141 }
142
stop(&mut self)143 fn stop(&mut self) {
144 self.thread_run.store(false, Ordering::Relaxed);
145 self.thread_semaphore.notify_one();
146 if let Some(thread) = self.thread.take() {
147 if let Err(e) = thread.join() {
148 error!("Failed to join thread: {:?}.", e);
149 }
150 }
151 }
152 }
153
154 /// `Ac97BusMaster` emulates the bus master portion of AC97. It exposes a register read/write
155 /// interface compliant with the ICH bus master.
156 pub struct Ac97BusMaster {
157 // Keep guest memory as each function will use it for buffer descriptors.
158 mem: GuestMemory,
159 regs: Arc<Mutex<Ac97BusMasterRegs>>,
160 acc_sema: u8,
161
162 // Bookkeeping info for playback and capture stream.
163 po_info: AudioThreadInfo,
164 pi_info: AudioThreadInfo,
165 pmic_info: AudioThreadInfo,
166
167 // Audio server used to create playback or capture streams.
168 audio_server: AudioStreamSource,
169
170 // Thread for hadlind IRQ resample events from the guest.
171 irq_resample_thread: Option<thread::JoinHandle<()>>,
172 #[cfg_attr(unix, allow(dead_code))]
173 sys: Ac97BusMasterSys,
174 }
175
176 impl Ac97BusMaster {
177 /// Provides the events needed to raise interrupts in the guest.
set_irq_event(&mut self, irq_evt: IrqLevelEvent)178 pub fn set_irq_event(&mut self, irq_evt: IrqLevelEvent) {
179 let thread_regs = self.regs.clone();
180 self.regs.lock().irq_evt = Some(irq_evt.try_clone().expect("cloning irq_evt failed"));
181 self.irq_resample_thread = Some(thread::spawn(move || {
182 loop {
183 if let Err(e) = irq_evt.get_resample().wait() {
184 error!(
185 "Failed to read the irq event from the resample thread: {}.",
186 e,
187 );
188 break;
189 }
190 {
191 // Scope for the lock on thread_regs.
192 let regs = thread_regs.lock();
193 if regs.has_irq() {
194 if let Err(e) = irq_evt.trigger() {
195 error!("Failed to set the irq from the resample thread: {}.", e);
196 break;
197 }
198 }
199 }
200 }
201 }));
202 }
203
204 /// Called when `mixer` has been changed and the new values should be applied to currently
205 /// active streams.
update_mixer_settings(&mut self, mixer: &Ac97Mixer)206 pub fn update_mixer_settings(&mut self, mixer: &Ac97Mixer) {
207 if let Some(control) = self.po_info.stream_control.as_mut() {
208 // The audio server only supports one volume, not separate left and right.
209 let (muted, left_volume, _right_volume) = mixer.get_master_volume();
210 control.set_volume(left_volume);
211 control.set_mute(muted);
212 }
213 }
214
215 /// Checks if the bus master is in the cold reset state.
is_cold_reset(&self) -> bool216 pub fn is_cold_reset(&self) -> bool {
217 self.regs.lock().glob_cnt & GLOB_CNT_COLD_RESET == 0
218 }
219
220 /// Reads a byte from the given `offset`.
readb(&mut self, offset: u64) -> u8221 pub fn readb(&mut self, offset: u64) -> u8 {
222 fn readb_func_regs(func_regs: &Ac97FunctionRegs, offset: u64) -> u8 {
223 match offset {
224 CIV_OFFSET => func_regs.civ,
225 LVI_OFFSET => func_regs.lvi,
226 SR_OFFSET => func_regs.sr as u8,
227 PIV_OFFSET => func_regs.piv,
228 CR_OFFSET => func_regs.cr,
229 _ => 0,
230 }
231 }
232
233 let regs = self.regs.lock();
234 match offset {
235 PI_BASE_00..=PI_CR_0B => readb_func_regs(®s.pi_regs, offset - PI_BASE_00),
236 PO_BASE_10..=PO_CR_1B => readb_func_regs(®s.po_regs, offset - PO_BASE_10),
237 MC_BASE_20..=MC_CR_2B => readb_func_regs(®s.mc_regs, offset - MC_BASE_20),
238 ACC_SEMA_34 => self.acc_sema,
239 _ => 0,
240 }
241 }
242
243 /// Reads a word from the given `offset`.
readw(&mut self, offset: u64, mixer: &Ac97Mixer) -> u16244 pub fn readw(&mut self, offset: u64, mixer: &Ac97Mixer) -> u16 {
245 let regs = self.regs.lock();
246 match offset {
247 PI_SR_06 => regs.pi_regs.sr,
248 PI_PICB_08 => regs.pi_regs.picb,
249 PO_SR_16 => regs.po_regs.sr,
250 PO_PICB_18 => {
251 // PO PICB
252 if !self.thread_info(Ac97Function::Output).is_running() {
253 // Not running, no need to estimate what has been consumed.
254 regs.po_regs.picb
255 } else {
256 // Estimate how many samples have been played since the last audio callback.
257 let num_channels = regs.tube_count(Ac97Function::Output) as u64;
258 let micros = regs.po_pointer_update_time.elapsed().subsec_micros();
259 // Round down to the next 10 millisecond boundary. The linux driver often
260 // assumes that two rapid reads from picb will return the same value.
261 let millis = micros / 1000 / 10 * 10;
262 let sample_rate = self.current_sample_rate(Ac97Function::Output, mixer);
263 let frames_consumed = sample_rate as u64 * u64::from(millis) / 1000;
264
265 regs.po_regs
266 .picb
267 .saturating_sub((num_channels * frames_consumed) as u16)
268 }
269 }
270 MC_SR_26 => regs.mc_regs.sr,
271 MC_PICB_28 => regs.mc_regs.picb,
272 _ => 0,
273 }
274 }
275
276 /// Reads a 32-bit word from the given `offset`.
readl(&mut self, offset: u64) -> u32277 pub fn readl(&mut self, offset: u64) -> u32 {
278 let regs = self.regs.lock();
279 match offset {
280 PI_BDBAR_00 => regs.pi_regs.bdbar,
281 PI_CIV_04 => regs.pi_regs.atomic_status_regs(),
282 PO_BDBAR_10 => regs.po_regs.bdbar,
283 PO_CIV_14 => regs.po_regs.atomic_status_regs(),
284 MC_BDBAR_20 => regs.mc_regs.bdbar,
285 MC_CIV_24 => regs.mc_regs.atomic_status_regs(),
286 GLOB_CNT_2C => regs.glob_cnt,
287 GLOB_STA_30 => regs.glob_sta,
288 _ => 0,
289 }
290 }
291
292 /// Writes the byte `val` to the register specified by `offset`.
writeb(&mut self, offset: u64, val: u8, mixer: &Ac97Mixer)293 pub fn writeb(&mut self, offset: u64, val: u8, mixer: &Ac97Mixer) {
294 // Only process writes to the control register when cold reset is set.
295 if self.is_cold_reset() {
296 return;
297 }
298
299 match offset {
300 PI_CIV_04 => (), // RO
301 PI_LVI_05 => self.set_lvi(Ac97Function::Input, val),
302 PI_SR_06 => self.set_sr(Ac97Function::Input, u16::from(val)),
303 PI_PIV_0A => (), // RO
304 PI_CR_0B => self.set_cr(Ac97Function::Input, val, mixer),
305 PO_CIV_14 => (), // RO
306 PO_LVI_15 => self.set_lvi(Ac97Function::Output, val),
307 PO_SR_16 => self.set_sr(Ac97Function::Output, u16::from(val)),
308 PO_PIV_1A => (), // RO
309 PO_CR_1B => self.set_cr(Ac97Function::Output, val, mixer),
310 MC_CIV_24 => (), // RO
311 MC_LVI_25 => self.set_lvi(Ac97Function::Microphone, val),
312 MC_SR_26 => self.set_sr(Ac97Function::Microphone, u16::from(val)),
313 MC_PIV_2A => (), // RO
314 MC_CR_2B => self.set_cr(Ac97Function::Microphone, val, mixer),
315 ACC_SEMA_34 => self.acc_sema = val,
316 o => warn!("write byte to 0x{:x}", o),
317 }
318 }
319
320 /// Writes the word `val` to the register specified by `offset`.
writew(&mut self, offset: u64, val: u16)321 pub fn writew(&mut self, offset: u64, val: u16) {
322 // Only process writes to the control register when cold reset is set.
323 if self.is_cold_reset() {
324 return;
325 }
326 match offset {
327 PI_SR_06 => self.set_sr(Ac97Function::Input, val),
328 PI_PICB_08 => (), // RO
329 PO_SR_16 => self.set_sr(Ac97Function::Output, val),
330 PO_PICB_18 => (), // RO
331 MC_SR_26 => self.set_sr(Ac97Function::Microphone, val),
332 MC_PICB_28 => (), // RO
333 o => warn!("write word to 0x{:x}", o),
334 }
335 }
336
337 /// Writes the 32-bit `val` to the register specified by `offset`.
writel(&mut self, offset: u64, val: u32, mixer: &mut Ac97Mixer)338 pub fn writel(&mut self, offset: u64, val: u32, mixer: &mut Ac97Mixer) {
339 // Only process writes to the control register when cold reset is set.
340 if self.is_cold_reset() && offset != 0x2c {
341 return;
342 }
343 match offset {
344 PI_BDBAR_00 => self.set_bdbar(Ac97Function::Input, val),
345 PO_BDBAR_10 => self.set_bdbar(Ac97Function::Output, val),
346 MC_BDBAR_20 => self.set_bdbar(Ac97Function::Microphone, val),
347 GLOB_CNT_2C => self.set_glob_cnt(val, mixer),
348 GLOB_STA_30 => (), // RO
349 o => warn!("write long to 0x{:x}", o),
350 }
351 }
352
set_bdbar(&mut self, func: Ac97Function, val: u32)353 fn set_bdbar(&mut self, func: Ac97Function, val: u32) {
354 self.regs.lock().func_regs_mut(func).bdbar = val & !0x07;
355 }
356
set_lvi(&mut self, func: Ac97Function, val: u8)357 fn set_lvi(&mut self, func: Ac97Function, val: u8) {
358 let mut regs = self.regs.lock();
359 let func_regs = regs.func_regs_mut(func);
360 func_regs.lvi = val % 32; // LVI wraps at 32.
361
362 // If running and stalled waiting for more valid buffers, restart by clearing the "DMA
363 // stopped" bit.
364 if func_regs.cr & CR_RPBM == CR_RPBM
365 && func_regs.sr & SR_DCH == SR_DCH
366 && func_regs.civ != func_regs.lvi
367 {
368 #[cfg(unix)]
369 Ac97BusMaster::check_and_move_to_next_buffer(func_regs);
370
371 func_regs.sr &= !(SR_DCH | SR_CELV);
372
373 #[cfg(unix)]
374 self.thread_semaphore_notify(func);
375 }
376 }
377
set_sr(&mut self, func: Ac97Function, val: u16)378 fn set_sr(&mut self, func: Ac97Function, val: u16) {
379 let mut sr = self.regs.lock().func_regs(func).sr;
380 if val & SR_FIFOE != 0 {
381 sr &= !SR_FIFOE;
382 }
383 if val & SR_LVBCI != 0 {
384 sr &= !SR_LVBCI;
385 }
386 if val & SR_BCIS != 0 {
387 sr &= !SR_BCIS;
388 }
389 update_sr(&mut self.regs.lock(), func, sr);
390 }
391
set_cr(&mut self, func: Ac97Function, val: u8, mixer: &Ac97Mixer)392 fn set_cr(&mut self, func: Ac97Function, val: u8, mixer: &Ac97Mixer) {
393 if val & CR_RR != 0 {
394 let mut regs = self.regs.lock();
395 Self::reset_func_regs(&mut regs, func);
396 } else {
397 let cr = self.regs.lock().func_regs(func).cr;
398 if val & CR_RPBM == 0 {
399 // Run/Pause set to pause.
400 self.thread_info_mut(func).stop();
401 let mut regs = self.regs.lock();
402 regs.func_regs_mut(func).sr |= SR_DCH;
403 } else if cr & CR_RPBM == 0 {
404 // Not already running.
405 // Run/Pause set to run.
406 {
407 let mut regs = self.regs.lock();
408 let func_regs = regs.func_regs_mut(func);
409 func_regs.piv = 1;
410 func_regs.civ = 0;
411 func_regs.sr &= !SR_DCH;
412 }
413 if let Err(e) = self.start_audio(func, mixer) {
414 warn!("Failed to start audio: {}", e);
415 }
416 }
417 let mut regs = self.regs.lock();
418 regs.func_regs_mut(func).cr = val & CR_VALID_MASK;
419 }
420 }
421
set_glob_cnt(&mut self, new_glob_cnt: u32, mixer: &mut Ac97Mixer)422 fn set_glob_cnt(&mut self, new_glob_cnt: u32, mixer: &mut Ac97Mixer) {
423 // Only the reset bits are emulated, the GPI and PCM formatting are not supported.
424 if new_glob_cnt & GLOB_CNT_COLD_RESET == 0 {
425 self.reset_audio_regs();
426 mixer.reset();
427 let mut regs = self.regs.lock();
428 regs.glob_cnt = new_glob_cnt & GLOB_CNT_STABLE_BITS;
429 self.acc_sema = 0;
430 return;
431 }
432 if new_glob_cnt & GLOB_CNT_WARM_RESET != 0 {
433 // Check if running and if so, ignore. Warm reset is specified to no-op when the device
434 // is playing or recording audio.
435 if !self.is_audio_running() {
436 self.stop_all_audio();
437 let mut regs = self.regs.lock();
438 regs.glob_cnt = new_glob_cnt & !GLOB_CNT_WARM_RESET; // Auto-cleared reset bit.
439 return;
440 }
441 }
442 self.regs.lock().glob_cnt = new_glob_cnt;
443 }
444
current_sample_rate(&self, func: Ac97Function, mixer: &Ac97Mixer) -> u32445 fn current_sample_rate(&self, func: Ac97Function, mixer: &Ac97Mixer) -> u32 {
446 match func {
447 Ac97Function::Output => mixer.get_sample_rate().into(),
448 _ => INPUT_SAMPLE_RATE,
449 }
450 }
451
thread_info(&self, func: Ac97Function) -> &AudioThreadInfo452 fn thread_info(&self, func: Ac97Function) -> &AudioThreadInfo {
453 match func {
454 Ac97Function::Microphone => &self.pmic_info,
455 Ac97Function::Input => &self.pi_info,
456 Ac97Function::Output => &self.po_info,
457 }
458 }
459
thread_info_mut(&mut self, func: Ac97Function) -> &mut AudioThreadInfo460 fn thread_info_mut(&mut self, func: Ac97Function) -> &mut AudioThreadInfo {
461 match func {
462 Ac97Function::Microphone => &mut self.pmic_info,
463 Ac97Function::Input => &mut self.pi_info,
464 Ac97Function::Output => &mut self.po_info,
465 }
466 }
467
is_audio_running(&self) -> bool468 fn is_audio_running(&self) -> bool {
469 self.thread_info(Ac97Function::Output).is_running()
470 || self.thread_info(Ac97Function::Input).is_running()
471 || self.thread_info(Ac97Function::Microphone).is_running()
472 }
473
stop_all_audio(&mut self)474 fn stop_all_audio(&mut self) {
475 self.thread_info_mut(Ac97Function::Input).stop();
476 self.thread_info_mut(Ac97Function::Output).stop();
477 self.thread_info_mut(Ac97Function::Microphone).stop();
478 }
479
480 // Helper function for resetting function registers.
reset_func_regs(regs: &mut Ac97BusMasterRegs, func: Ac97Function)481 fn reset_func_regs(regs: &mut Ac97BusMasterRegs, func: Ac97Function) {
482 regs.func_regs_mut(func).do_reset();
483 update_sr(regs, func, SR_DCH);
484 }
485
reset_audio_regs(&mut self)486 fn reset_audio_regs(&mut self) {
487 self.stop_all_audio();
488 let mut regs = self.regs.lock();
489 Self::reset_func_regs(&mut regs, Ac97Function::Input);
490 Self::reset_func_regs(&mut regs, Ac97Function::Output);
491 Self::reset_func_regs(&mut regs, Ac97Function::Microphone);
492 }
493 }
494
get_buffer_samples( func_regs: &Ac97FunctionRegs, mem: &GuestMemory, index: u8, ) -> GuestMemoryResult<usize>495 fn get_buffer_samples(
496 func_regs: &Ac97FunctionRegs,
497 mem: &GuestMemory,
498 index: u8,
499 ) -> GuestMemoryResult<usize> {
500 let descriptor_addr = func_regs.bdbar + u32::from(index) * DESCRIPTOR_LENGTH as u32;
501 let control_reg: u32 = mem
502 .read_obj_from_addr(GuestAddress(u64::from(descriptor_addr) + 4))
503 .map_err(GuestMemoryError::ReadingGuestBufferAddress)?;
504 let buffer_samples = control_reg as usize & 0x0000_ffff;
505 Ok(buffer_samples)
506 }
507
508 // Marks the current buffer completed and moves to the next buffer for the given
509 // function and registers.
buffer_completed( regs: &mut Ac97BusMasterRegs, mem: &GuestMemory, func: Ac97Function, ) -> AudioResult<()>510 fn buffer_completed(
511 regs: &mut Ac97BusMasterRegs,
512 mem: &GuestMemory,
513 func: Ac97Function,
514 ) -> AudioResult<()> {
515 // check if the completed descriptor wanted an interrupt on completion.
516 let civ = regs.func_regs(func).civ;
517 let descriptor_addr = regs.func_regs(func).bdbar + u32::from(civ) * DESCRIPTOR_LENGTH as u32;
518 let control_reg: u32 = mem
519 .read_obj_from_addr(GuestAddress(u64::from(descriptor_addr) + 4))
520 .map_err(GuestMemoryError::ReadingGuestBufferAddress)?;
521
522 let mut new_sr = regs.func_regs(func).sr & !SR_CELV;
523 if control_reg & BD_IOC != 0 {
524 new_sr |= SR_BCIS;
525 }
526
527 let lvi = regs.func_regs(func).lvi;
528 // if the current buffer was the last valid buffer, then update the status register to
529 // indicate that the end of audio was hit and possibly raise an interrupt.
530 if civ == lvi {
531 new_sr |= SR_DCH | SR_CELV | SR_LVBCI;
532 } else {
533 regs.func_regs_mut(func).move_to_next_buffer();
534 }
535
536 update_sr(regs, func, new_sr);
537
538 regs.func_regs_mut(func).picb = current_buffer_size(regs.func_regs(func), mem)? as u16;
539 if func == Ac97Function::Output {
540 regs.po_pointer_update_time = Instant::now();
541 }
542
543 Ok(())
544 }
545
546 // Update the status register and if any interrupts need to fire, raise them.
update_sr(regs: &mut Ac97BusMasterRegs, func: Ac97Function, val: u16)547 fn update_sr(regs: &mut Ac97BusMasterRegs, func: Ac97Function, val: u16) {
548 let int_mask = match func {
549 Ac97Function::Input => GS_PIINT,
550 Ac97Function::Output => GS_POINT,
551 Ac97Function::Microphone => GS_MINT,
552 };
553
554 let mut interrupt_high = false;
555
556 {
557 let func_regs = regs.func_regs_mut(func);
558 let old_sr = func_regs.sr;
559 func_regs.sr = val;
560 if (old_sr ^ val) & SR_INT_MASK != 0 {
561 if (val & SR_LVBCI) != 0 && (func_regs.cr & CR_LVBIE) != 0 {
562 interrupt_high = true;
563 }
564 if (val & SR_BCIS) != 0 && (func_regs.cr & CR_IOCE) != 0 {
565 interrupt_high = true;
566 }
567 } else {
568 return;
569 }
570 }
571
572 if interrupt_high {
573 regs.glob_sta |= int_mask;
574 if let Some(ref irq_evt) = regs.irq_evt {
575 // Ignore write failure, nothing can be done about it from here.
576 let _ = irq_evt.trigger();
577 }
578 } else {
579 regs.glob_sta &= !int_mask;
580 }
581 }
582
583 // Returns the size in samples of the buffer pointed to by the CIV register.
current_buffer_size( func_regs: &Ac97FunctionRegs, mem: &GuestMemory, ) -> GuestMemoryResult<usize>584 fn current_buffer_size(
585 func_regs: &Ac97FunctionRegs,
586 mem: &GuestMemory,
587 ) -> GuestMemoryResult<usize> {
588 let civ = func_regs.civ;
589 get_buffer_samples(func_regs, mem, civ)
590 }
591
592 #[cfg(test)]
593 mod tests {
594
595 use super::*;
596
597 #[cfg(unix)]
new_mock_ac97_bus_master() -> Ac97BusMaster598 fn new_mock_ac97_bus_master() -> Ac97BusMaster {
599 Ac97BusMaster::new(
600 GuestMemory::new(&[]).expect("Creating guest memory failed."),
601 Box::new(audio_streams::shm_streams::MockShmStreamSource::new()),
602 )
603 }
604
605 #[cfg(windows)]
new_mock_ac97_bus_master() -> Ac97BusMaster606 fn new_mock_ac97_bus_master() -> Ac97BusMaster {
607 let memory_start_addr = GuestAddress(0x0);
608 Ac97BusMaster::new(
609 GuestMemory::new(&[(memory_start_addr, 0x1000)])
610 .expect("Creating guest memory failed."),
611 Arc::new(Mutex::new(audio_streams::NoopStreamSource::new())),
612 None,
613 )
614 }
615
616 #[test]
bm_bdbar()617 fn bm_bdbar() {
618 let mut bm = new_mock_ac97_bus_master();
619 let mut mixer = Ac97Mixer::new();
620
621 let bdbars = [0x00u64, 0x10, 0x20];
622
623 // Make sure writes have no affect during cold reset.
624 bm.writel(0x00, 0x5555_555f, &mut mixer);
625 assert_eq!(bm.readl(0x00), 0x0000_0000);
626
627 // Relesase cold reset.
628 bm.writel(GLOB_CNT_2C, 0x0000_0002, &mut mixer);
629
630 // Tests that the base address is writable and that the bottom three bits are read only.
631 for bdbar in &bdbars {
632 assert_eq!(bm.readl(*bdbar), 0x0000_0000);
633 bm.writel(*bdbar, 0x5555_555f, &mut mixer);
634 assert_eq!(bm.readl(*bdbar), 0x5555_5558);
635 }
636 }
637
638 #[test]
bm_status_reg()639 fn bm_status_reg() {
640 let mut bm = new_mock_ac97_bus_master();
641 let mixer = Ac97Mixer::new();
642
643 let sr_addrs = [0x06u64, 0x16, 0x26];
644
645 for sr in &sr_addrs {
646 assert_eq!(bm.readw(*sr, &mixer), 0x0001);
647 bm.writew(*sr, 0xffff);
648 assert_eq!(bm.readw(*sr, &mixer), 0x0001);
649 }
650 }
651
652 #[test]
bm_global_control()653 fn bm_global_control() {
654 let mut bm = new_mock_ac97_bus_master();
655 let mut mixer = Ac97Mixer::new();
656
657 assert_eq!(bm.readl(GLOB_CNT_2C), 0x0000_0000);
658
659 // Relesase cold reset.
660 bm.writel(GLOB_CNT_2C, 0x0000_0002, &mut mixer);
661
662 // Check interrupt enable bits are writable.
663 bm.writel(GLOB_CNT_2C, 0x0000_0072, &mut mixer);
664 assert_eq!(bm.readl(GLOB_CNT_2C), 0x0000_0072);
665
666 // A Warm reset should doesn't affect register state and is auto cleared.
667 bm.writel(0x00, 0x5555_5558, &mut mixer);
668 bm.writel(GLOB_CNT_2C, 0x0000_0076, &mut mixer);
669 assert_eq!(bm.readl(GLOB_CNT_2C), 0x0000_0072);
670 assert_eq!(bm.readl(0x00), 0x5555_5558);
671 // Check that a cold reset works, but setting bdbar and checking it is zeroed.
672 bm.writel(0x00, 0x5555_555f, &mut mixer);
673 bm.writel(GLOB_CNT_2C, 0x000_0070, &mut mixer);
674 assert_eq!(bm.readl(GLOB_CNT_2C), 0x0000_0070);
675 assert_eq!(bm.readl(0x00), 0x0000_0000);
676 }
677
playback_release_cold_reset_and_setup_ping_pong_buffers( bdbar: u64, mixer: &mut Ac97Mixer, bm: &mut Ac97BusMaster, mem: &GuestMemory, num_buffers: usize, guest_addr_base: u32, fragment_size: usize, lvi_mask: u8, ioc_mask: u32, )678 pub(super) fn playback_release_cold_reset_and_setup_ping_pong_buffers(
679 bdbar: u64,
680 mixer: &mut Ac97Mixer,
681 bm: &mut Ac97BusMaster,
682 mem: &GuestMemory,
683 num_buffers: usize,
684 guest_addr_base: u32,
685 fragment_size: usize,
686 lvi_mask: u8,
687 ioc_mask: u32,
688 ) {
689 // Release cold reset.
690 bm.writel(GLOB_CNT_2C, 0x0000_0002, mixer);
691 // Setup ping-pong buffers. A and B repeating for every possible index.
692 bm.writel(bdbar, guest_addr_base, mixer);
693 for i in 0..num_buffers {
694 let pointer_addr = GuestAddress(guest_addr_base as u64 + i as u64 * 8);
695 let control_addr = GuestAddress(guest_addr_base as u64 + i as u64 * 8 + 4);
696 if i % 2 == 0 {
697 mem.write_obj_at_addr(guest_addr_base, pointer_addr)
698 .expect("Writing guest memory failed.");
699 } else {
700 mem.write_obj_at_addr(guest_addr_base + fragment_size as u32, pointer_addr)
701 .expect("Writing guest memory failed.");
702 };
703 mem.write_obj_at_addr(ioc_mask | ((fragment_size as u32) / 2), control_addr)
704 .expect("Writing guest memory failed.");
705 }
706 bm.writeb(bdbar + LVI_OFFSET, lvi_mask, mixer);
707 }
708
capture_release_cold_reset_and_setup_ping_pong_buffers( base: u64, mixer: &mut Ac97Mixer, bm: &mut Ac97BusMaster, mem: &GuestMemory, num_buffers: usize, guest_addr_base: u32, fragment_size: usize, lvi_mask: u8, ioc_mask: u32, )709 pub(super) fn capture_release_cold_reset_and_setup_ping_pong_buffers(
710 base: u64,
711 mixer: &mut Ac97Mixer,
712 bm: &mut Ac97BusMaster,
713 mem: &GuestMemory,
714 num_buffers: usize,
715 guest_addr_base: u32,
716 fragment_size: usize,
717 lvi_mask: u8,
718 ioc_mask: u32,
719 ) {
720 // Release cold reset.
721 bm.writel(GLOB_CNT_2C, 0x0000_0002, mixer);
722
723 // Setup ping-pong buffers.
724 bm.writel(base, guest_addr_base, mixer);
725 for i in 0..num_buffers {
726 let pointer_addr = GuestAddress(guest_addr_base as u64 + i as u64 * 8);
727 let control_addr = GuestAddress(guest_addr_base as u64 + i as u64 * 8 + 4);
728 mem.write_obj_at_addr(guest_addr_base + fragment_size as u32, pointer_addr)
729 .expect("Writing guest memory failed.");
730 mem.write_obj_at_addr(ioc_mask | ((fragment_size as u32) / 2), control_addr)
731 .expect("Writing guest memory failed.");
732 }
733
734 bm.writeb(base + LVI_OFFSET, lvi_mask, mixer);
735 }
736
check_buffer_set_and_clear_bcis( base: u64, mixer: &Ac97Mixer, bm: &mut Ac97BusMaster, )737 pub(super) fn check_buffer_set_and_clear_bcis(
738 base: u64,
739 mixer: &Ac97Mixer,
740 bm: &mut Ac97BusMaster,
741 ) {
742 // Buffer complete should be set as the IOC bit was set in the descriptor.
743 assert!(bm.readw(base + SR_OFFSET, mixer) & SR_BCIS != 0);
744 // Clear the BCIS bit
745 bm.writew(base + SR_OFFSET, SR_BCIS);
746 assert!(bm.readw(base + SR_OFFSET, mixer) & SR_BCIS == 0);
747 }
748
clear_lvb_and_reset_lvi( base: u64, mixer: &Ac97Mixer, bm: &mut Ac97BusMaster, lvi_mask: u8, )749 pub(super) fn clear_lvb_and_reset_lvi(
750 base: u64,
751 mixer: &Ac97Mixer,
752 bm: &mut Ac97BusMaster,
753 lvi_mask: u8,
754 ) {
755 // Clear the LVB bit
756 bm.writeb(base + SR_OFFSET, SR_LVBCI as u8, mixer);
757 assert!(bm.readw(base + SR_OFFSET, mixer) & SR_LVBCI == 0);
758 // Reset the LVI to the last buffer and check that playback resumes
759 bm.writeb(base + LVI_OFFSET, lvi_mask, mixer);
760 assert!(bm.readw(base + SR_OFFSET, mixer) & SR_DCH == 0); // DMA restarts.
761 assert_eq!(bm.readw(base + SR_OFFSET, mixer) & SR_CELV, 0);
762 }
763
stop(base: u64, int_mask: u32, mixer: &Ac97Mixer, bm: &mut Ac97BusMaster)764 pub(super) fn stop(base: u64, int_mask: u32, mixer: &Ac97Mixer, bm: &mut Ac97BusMaster) {
765 // Stop.
766 bm.writeb(base + CR_OFFSET, 0, mixer);
767 assert!(bm.readw(base + SR_OFFSET, mixer) & 0x01 != 0); // DMA is not running.
768 bm.writeb(base + CR_OFFSET, CR_RR, mixer);
769 assert!(
770 bm.readl(GLOB_STA_30) & int_mask == 0,
771 "POINT bit should be disabled."
772 );
773 }
774 }
775