VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/HDAStream.h@ 88137

Last change on this file since 88137 was 88137, checked in by vboxsync, 4 years ago

DevHDA: Made the DMA timer scheduling heuristics more flexible and ditched the alternative approaches. Changed the DMA engine to load the whole BDL and not reload BDLEs as we work thru them. Ditched the HDABDLE structure and some other DMA related stuff (FIFO buffer is on the todo list). bugref:9890

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.8 KB
Line 
1/* $Id: HDAStream.h 88137 2021-03-16 12:22:05Z vboxsync $ */
2/** @file
3 * HDAStream.h - Streams for HD Audio.
4 */
5
6/*
7 * Copyright (C) 2017-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef VBOX_INCLUDED_SRC_Audio_HDAStream_h
19#define VBOX_INCLUDED_SRC_Audio_HDAStream_h
20#ifndef RT_WITHOUT_PRAGMA_ONCE
21# pragma once
22#endif
23
24#include "DevHDACommon.h"
25#include "HDAStreamMap.h"
26#include "HDAStreamPeriod.h"
27
28
29#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
30/**
31 * HDA stream's state for asynchronous I/O.
32 */
33typedef struct HDASTREAMSTATEAIO
34{
35 /** Thread handle for the actual I/O thread. */
36 RTTHREAD hThread;
37 /** Event for letting the thread know there is some data to process. */
38 RTSEMEVENT hEvent;
39 /** Critical section for synchronizing access. */
40 RTCRITSECT CritSect;
41 /** Started indicator. */
42 volatile bool fStarted;
43 /** Shutdown indicator. */
44 volatile bool fShutdown;
45 /** Whether the thread should do any data processing or not. */
46 volatile bool fEnabled;
47 bool afPadding[1+4];
48} HDASTREAMSTATEAIO;
49/** Pointer to a HDA stream's asynchronous I/O state. */
50typedef HDASTREAMSTATEAIO *PHDASTREAMSTATEAIO;
51#endif
52
53/**
54 * Structure containing HDA stream debug stuff, configurable at runtime.
55 */
56typedef struct HDASTREAMDEBUGRT
57{
58 /** Whether debugging is enabled or not. */
59 bool fEnabled;
60 uint8_t Padding[7];
61 /** File for dumping stream reads / writes.
62 * For input streams, this dumps data being written to the device FIFO,
63 * whereas for output streams this dumps data being read from the device FIFO. */
64 R3PTRTYPE(PPDMAUDIOFILE) pFileStream;
65 /** File for dumping raw DMA reads / writes.
66 * For input streams, this dumps data being written to the device DMA,
67 * whereas for output streams this dumps data being read from the device DMA. */
68 R3PTRTYPE(PPDMAUDIOFILE) pFileDMARaw;
69 /** File for dumping mapped (that is, extracted) DMA reads / writes. */
70 R3PTRTYPE(PPDMAUDIOFILE) pFileDMAMapped;
71} HDASTREAMDEBUGRT;
72
73/**
74 * Structure containing HDA stream debug information.
75 */
76typedef struct HDASTREAMDEBUG
77{
78#ifdef DEBUG
79 /** Critical section to serialize access if needed. */
80 RTCRITSECT CritSect;
81 uint32_t Padding0[2];
82 /** Number of total read accesses. */
83 uint64_t cReadsTotal;
84 /** Number of total DMA bytes read. */
85 uint64_t cbReadTotal;
86 /** Timestamp (in ns) of last read access. */
87 uint64_t tsLastReadNs;
88 /** Number of total write accesses. */
89 uint64_t cWritesTotal;
90 /** Number of total DMA bytes written. */
91 uint64_t cbWrittenTotal;
92 /** Number of total write accesses since last iteration (Hz). */
93 uint64_t cWritesHz;
94 /** Number of total DMA bytes written since last iteration (Hz). */
95 uint64_t cbWrittenHz;
96 /** Timestamp (in ns) of beginning a new write slot. */
97 uint64_t tsWriteSlotBegin;
98 /** Number of current silence samples in a (consecutive) row. */
99 uint64_t csSilence;
100 /** Number of silent samples in a row to consider an audio block as audio gap (silence). */
101 uint64_t cSilenceThreshold;
102 /** How many bytes to skip in an audio stream before detecting silence.
103 * (useful for intros and silence at the beginning of a song). */
104 uint64_t cbSilenceReadMin;
105#endif
106 /** Runtime debug info. */
107 HDASTREAMDEBUGRT Runtime;
108} HDASTREAMDEBUG;
109typedef HDASTREAMDEBUG *PHDASTREAMDEBUG;
110
111/**
112 * Internal state of a HDA stream.
113 */
114typedef struct HDASTREAMSTATE
115{
116 /** Flag indicating whether this stream currently is
117 * in reset mode and therefore not acccessible by the guest. */
118 volatile bool fInReset;
119 /** Flag indicating if the stream is in running state or not. */
120 volatile bool fRunning;
121 /** The stream's I/O timer Hz rate. */
122 uint16_t uTimerIoHz;
123 /** How many interrupts are pending due to
124 * BDLE interrupt-on-completion (IOC) bits set. */
125 uint8_t cTransferPendingInterrupts;
126 /** Unused, padding. */
127 uint8_t abPadding1[3];
128 /** Timestamp (absolute, in timer ticks) of the last DMA data transfer. */
129 uint64_t tsTransferLast;
130 /** Timestamp (absolute, in timer ticks) of the next DMA data transfer.
131 * Next for determining the next scheduling window.
132 * Can be 0 if no next transfer is scheduled. */
133 uint64_t tsTransferNext;
134 /** Total transfer size (in bytes) of a transfer period.
135 * @note This is in host side frames, in case we're doing any mapping. */
136 uint32_t cbTransferSize;
137 /** The size of an average transfer. */
138 uint32_t cbAvgTransfer;
139 /** The stream's period. Need for timing. */
140 HDASTREAMPERIOD Period;
141 /** The stream's current host side configuration.
142 * This should match the SDnFMT in all respects but maybe the channel count as
143 * we may need to expand mono or into/from into stereo. The unmodified SDnFMT
144 * properties can be found in HDASTREAMR3::Mapping::PCMProps. */
145 PDMAUDIOSTREAMCFG Cfg;
146 /** Timestamp (real time, in ns) of last DMA transfer. */
147 uint64_t tsLastTransferNs;
148 /** Timestamp (real time, in ns) of last stream read (to backends).
149 * When running in async I/O mode, this differs from \a tsLastTransferNs,
150 * because reading / processing will be done in a separate stream. */
151 uint64_t tsLastReadNs;
152
153 /** This is set to the timer clock time when the msInitialDelay period is over.
154 * Once reached, this is set to zero to avoid unnecessary time queries. */
155 uint64_t tsAioDelayEnd;
156 /** The start time for the playback (on the timer clock). */
157 uint64_t tsStart;
158
159 /** @name DMA engine
160 * @{ */
161 /** The offset into the current BDLE. */
162 uint32_t offCurBdle;
163 /** LVI + 1 */
164 uint16_t cBdles;
165 /** The index of the current BDLE.
166 * This is the entry which period is currently "running" on the DMA timer. */
167 uint8_t idxCurBdle;
168 /** The number of prologue scheduling steps.
169 * This is used when the tail BDLEs doesn't have IOC set. */
170 uint8_t cSchedulePrologue;
171 /** Number of scheduling steps. */
172 uint16_t cSchedule;
173 /** Current scheduling step. */
174 uint16_t idxSchedule;
175 /** Current loop number within the current scheduling step. */
176 uint32_t idxScheduleLoop;
177
178 /** Buffer descriptors and additional timer scheduling state.
179 * (Same as HDABDLEDESC, with more sensible naming.) */
180 struct
181 {
182 /** The buffer address. */
183 uint64_t GCPhys;
184 /** The buffer size (guest bytes). */
185 uint32_t cb;
186 /** The flags (only bit 0 is defined). */
187 uint32_t fFlags;
188 } aBdl[256];
189 /** Scheduling steps. */
190 struct
191 {
192 /** Number of timer ticks per period.
193 * ASSUMES that we don't need a full second and that the timer resolution
194 * isn't much higher than nanoseconds. */
195 uint32_t cPeriodTicks;
196 /** The period length in host bytes. */
197 uint32_t cbPeriod;
198 /** Number of times to repeat the period. */
199 uint32_t cLoops;
200 /** The BDL index of the first entry. */
201 uint8_t idxFirst;
202 /** The number of BDL entries. */
203 uint8_t cEntries;
204 uint8_t abPadding[2];
205 } aSchedule[512+8];
206 /** @} */
207} HDASTREAMSTATE;
208AssertCompileSizeAlignment(HDASTREAMSTATE, 8);
209AssertCompileMemberAlignment(HDASTREAMSTATE, aBdl, 16);
210AssertCompileMemberAlignment(HDASTREAMSTATE, aSchedule, 16);
211
212/**
213 * An HDA stream (SDI / SDO) - shared.
214 *
215 * @note This HDA stream has nothing to do with a regular audio stream handled
216 * by the audio connector or the audio mixer. This HDA stream is a serial
217 * data in/out stream (SDI/SDO) defined in hardware and can contain
218 * multiple audio streams in one single SDI/SDO (interleaving streams).
219 *
220 * How a specific SDI/SDO is mapped to our internal audio streams relies on the
221 * stream channel mappings.
222 *
223 * Contains only register values which do *not* change until a stream reset
224 * occurs.
225 */
226typedef struct HDASTREAM
227{
228 /** Stream descriptor number (SDn). */
229 uint8_t u8SD;
230 /** Current channel index.
231 * For a stereo stream, this is u8Channel + 1. */
232 uint8_t u8Channel;
233 uint8_t abPadding0[6];
234#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
235 /** The stream's shared r0/r3 critical section to serialize access between the async I/O
236 * thread and (basically) the guest. */
237 PDMCRITSECT CritSect;
238#endif
239 /** DMA base address (SDnBDPU - SDnBDPL).
240 * Will be updated in hdaR3StreamInit(). */
241 uint64_t u64BDLBase;
242 /** Cyclic Buffer Length (SDnCBL).
243 * Represents the size of the ring buffer.
244 * Will be updated in hdaR3StreamInit(). */
245 uint32_t u32CBL;
246 /** Format (SDnFMT).
247 * Will be updated in hdaR3StreamInit(). */
248 uint16_t u16FMT;
249 /** FIFO Size (checked + translated in bytes, FIFOS).
250 * Maximum number of bytes that may have been DMA'd into
251 * memory but not yet transmitted on the link.
252 *
253 * Will be updated in hdaR3StreamInit(). */
254 uint8_t u8FIFOS;
255 /** FIFO Watermark (checked + translated in bytes, FIFOW). */
256 uint8_t u8FIFOW;
257 uint8_t abPadding1[2];
258 /** FIFO scratch buffer, to avoid intermediate (re-)allocations. */
259 uint8_t abFIFO[HDA_FIFO_MAX + 1];
260 /** Last Valid Index (SDnLVI).
261 * Will be updated in hdaR3StreamInit(). */
262 uint16_t u16LVI;
263 /** The timer for pumping data thru the attached LUN drivers. */
264 TMTIMERHANDLE hTimer;
265 /** Internal state of this stream. */
266 HDASTREAMSTATE State;
267} HDASTREAM;
268/** Pointer to an HDA stream (SDI / SDO). */
269typedef HDASTREAM *PHDASTREAM;
270
271
272/**
273 * An HDA stream (SDI / SDO) - ring-3 bits.
274 */
275typedef struct HDASTREAMR3
276{
277 /** Stream descriptor number (SDn). */
278 uint8_t u8SD;
279 uint8_t abPadding[7];
280 /** The shared state for the parent HDA device. */
281 R3PTRTYPE(PHDASTATE) pHDAStateShared;
282 /** The ring-3 state for the parent HDA device. */
283 R3PTRTYPE(PHDASTATER3) pHDAStateR3;
284 /** Pointer to HDA sink this stream is attached to. */
285 R3PTRTYPE(PHDAMIXERSINK) pMixSink;
286 /** Internal state of this stream. */
287 struct
288 {
289 /** This stream's data mapping. */
290 HDASTREAMMAP Mapping;
291 /** Circular buffer (FIFO) for holding DMA'ed data. */
292 R3PTRTYPE(PRTCIRCBUF) pCircBuf;
293 /** Current circular buffer read offset (for tracing & logging). */
294 uint64_t offRead;
295 /** Current circular buffer write offset (for tracing & logging). */
296 uint64_t offWrite;
297#ifdef HDA_USE_DMA_ACCESS_HANDLER
298 /** List of DMA handlers. */
299 RTLISTANCHORR3 lstDMAHandlers;
300#endif
301#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
302 /** Asynchronous I/O state members. */
303 HDASTREAMSTATEAIO AIO;
304#endif
305 /** Counter for all under/overflows problems. */
306 STAMCOUNTER StatDmaFlowProblems;
307 /** Counter for unresovled under/overflows problems. */
308 STAMCOUNTER StatDmaFlowErrors;
309 } State;
310 /** Debug bits. */
311 HDASTREAMDEBUG Dbg;
312} HDASTREAMR3;
313/** Pointer to an HDA stream (SDI / SDO). */
314typedef HDASTREAMR3 *PHDASTREAMR3;
315
316/** @name Stream functions (shared).
317 * @{
318 */
319void hdaStreamLock(PHDASTREAM pStreamShared);
320void hdaStreamUnlock(PHDASTREAM pStreamShared);
321/** @} */
322
323#ifdef IN_RING3
324
325/** @name Stream functions (ring-3).
326 * @{
327 */
328int hdaR3StreamConstruct(PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3, PHDASTATE pThis,
329 PHDASTATER3 pThisCC, uint8_t uSD);
330void hdaR3StreamDestroy(PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3);
331int hdaR3StreamSetUp(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShared,
332 PHDASTREAMR3 pStreamR3, uint8_t uSD);
333void hdaR3StreamReset(PHDASTATE pThis, PHDASTATER3 pThisCC,
334 PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3, uint8_t uSD);
335int hdaR3StreamEnable(PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3, bool fEnable);
336void hdaR3StreamMarkStarted(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShared, uint64_t tsNow);
337void hdaR3StreamMarkStopped(PHDASTREAM pStreamShared);
338
339void hdaR3StreamSetPositionAdd(PHDASTREAM pStreamShared, PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t uToAdd);
340uint64_t hdaR3StreamTimerMain(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC,
341 PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3);
342void hdaR3StreamUpdate(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC,
343 PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3, bool fInTimer);
344PHDASTREAM hdaR3StreamR3ToShared(PHDASTREAMR3 pStreamCC);
345# ifdef HDA_USE_DMA_ACCESS_HANDLER
346bool hdaR3StreamRegisterDMAHandlers(PHDASTREAM pStream);
347void hdaR3StreamUnregisterDMAHandlers(PHDASTREAM pStream);
348# endif
349/** @} */
350
351/** @name Async I/O stream functions (ring-3).
352 * @{
353 */
354# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
355int hdaR3StreamAsyncIOCreate(PHDASTREAMR3 pStreamR3);
356void hdaR3StreamAsyncIOLock(PHDASTREAMR3 pStreamR3);
357void hdaR3StreamAsyncIOUnlock(PHDASTREAMR3 pStreamR3);
358void hdaR3StreamAsyncIOEnable(PHDASTREAMR3 pStreamR3, bool fEnable);
359# endif /* VBOX_WITH_AUDIO_HDA_ASYNC_IO */
360/** @} */
361
362#endif /* IN_RING3 */
363#endif /* !VBOX_INCLUDED_SRC_Audio_HDAStream_h */
364
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette