VirtualBox

Changeset 67899 in vbox


Ignore:
Timestamp:
Jul 11, 2017 11:03:53 AM (7 years ago)
Author:
vboxsync
Message:

Audio/DevHDA.cpp: Modularized code more by also factoring out the HDA stream functions into an own file. No actual code changes.

Location:
trunk/src/VBox/Devices
Files:
3 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DevHDA.cpp

    r67855 r67899  
    11/* $Id$ */
    22/** @file
    3  * DevHDA - VBox Intel HD Audio Controller.
     3 * DevHDA.cpp - VBox Intel HD Audio Controller.
    44 *
    55 * Implemented against the specifications found in "High Definition Audio
     
    4747#include "AudioMixBuffer.h"
    4848#include "AudioMixer.h"
     49
     50#include "DevHDA.h"
     51#include "DevHDACommon.h"
     52
    4953#include "HDACodec.h"
     54#include "HDAStream.h"
    5055# if defined(VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT) || defined(VBOX_WITH_AUDIO_HDA_51_SURROUND)
    5156#  include "HDAStreamChannel.h"
     
    5358#include "HDAStreamMap.h"
    5459#include "HDAStreamPeriod.h"
    55 #include "DevHDACommon.h"
     60
    5661#include "DrvAudio.h"
    5762
     
    107112#endif
    108113
    109 /** Default timer frequency (in Hz).
    110  *
    111  *  Note: Keep in mind that the Hz rate has nothing to do with samples rates
    112  *        or DMA / interrupt timing -- it's purely needed in order to drive
    113  *        the data flow at a constant (and sufficient) rate.
    114  *
    115  *        Lowering this value can ask for trouble, as backends then can run
    116  *        into data underruns. */
    117 #define HDA_TIMER_HZ            200
    118 
    119 /** HDA's (fixed) audio frame size in bytes.
    120  *  We only support 16-bit stereo frames at the moment. */
    121 #define HDA_FRAME_SIZE          4
    122 
    123 /**
    124  * At the moment we support 4 input + 4 output streams max, which is 8 in total.
    125  * Bidirectional streams are currently *not* supported.
    126  *
    127  * Note: When changing any of those values, be prepared for some saved state
    128  *       fixups / trouble!
    129  */
    130 #define HDA_MAX_SDI             4
    131 #define HDA_MAX_SDO             4
    132 #define HDA_MAX_STREAMS         (HDA_MAX_SDI + HDA_MAX_SDO)
    133 AssertCompile(HDA_MAX_SDI <= HDA_MAX_SDO);
    134 
    135 /** Number of general registers. */
    136 #define HDA_NUM_GENERAL_REGS    34
    137 /** Number of total registers in the HDA's register map. */
    138 #define HDA_NUM_REGS            (HDA_NUM_GENERAL_REGS + (HDA_MAX_STREAMS * 10 /* Each stream descriptor has 10 registers */))
    139 /** Total number of stream tags (channels). Index 0 is reserved / invalid. */
    140 #define HDA_MAX_TAGS            16
    141 
    142 /**
    143  * NB: Register values stored in memory (au32Regs[]) are indexed through
    144  * the HDA_RMX_xxx macros (also HDA_MEM_IND_NAME()). On the other hand, the
    145  * register descriptors in g_aHdaRegMap[] are indexed through the
    146  * HDA_REG_xxx macros (also HDA_REG_IND_NAME()).
    147  *
    148  * The au32Regs[] layout is kept unchanged for saved state
    149  * compatibility.
    150  */
    151 
    152 /* Registers */
    153 #define HDA_REG_IND_NAME(x)                 HDA_REG_##x
    154 #define HDA_MEM_IND_NAME(x)                 HDA_RMX_##x
    155 #define HDA_REG_IND(pThis, x)               ((pThis)->au32Regs[g_aHdaRegMap[x].mem_idx])
    156 #define HDA_REG(pThis, x)                   (HDA_REG_IND((pThis), HDA_REG_IND_NAME(x)))
    157 
    158 
    159 #define HDA_REG_GCAP                0 /* range 0x00-0x01*/
    160 #define HDA_RMX_GCAP                0
    161 /* GCAP HDASpec 3.3.2 This macro encodes the following information about HDA in a compact manner:
    162  * oss (15:12) - number of output streams supported
    163  * iss (11:8)  - number of input streams supported
    164  * bss (7:3)   - number of bidirectional streams supported
    165  * bds (2:1)   - number of serial data out (SDO) signals supported
    166  * b64sup (0)  - 64 bit addressing supported.
    167  */
    168 #define HDA_MAKE_GCAP(oss, iss, bss, bds, b64sup) \
    169     (  (((oss)   & 0xF)  << 12) \
    170      | (((iss)   & 0xF)  << 8)  \
    171      | (((bss)   & 0x1F) << 3)  \
    172      | (((bds)   & 0x3)  << 2)  \
    173      | ((b64sup) & 1))
    174 
    175 #define HDA_REG_VMIN                1 /* 0x02 */
    176 #define HDA_RMX_VMIN                1
    177 
    178 #define HDA_REG_VMAJ                2 /* 0x03 */
    179 #define HDA_RMX_VMAJ                2
    180 
    181 #define HDA_REG_OUTPAY              3 /* 0x04-0x05 */
    182 #define HDA_RMX_OUTPAY              3
    183 
    184 #define HDA_REG_INPAY               4 /* 0x06-0x07 */
    185 #define HDA_RMX_INPAY               4
    186 
    187 #define HDA_REG_GCTL                5 /* 0x08-0x0B */
    188 #define HDA_RMX_GCTL                5
    189 #define HDA_GCTL_UNSOL              RT_BIT(8)   /* Accept Unsolicited Response Enable */
    190 #define HDA_GCTL_FCNTRL             RT_BIT(1)   /* Flush Control */
    191 #define HDA_GCTL_CRST               RT_BIT(0)   /* Controller Reset */
    192 
    193 #define HDA_REG_WAKEEN              6 /* 0x0C */
    194 #define HDA_RMX_WAKEEN              6
    195 
    196 #define HDA_REG_STATESTS            7 /* 0x0E */
    197 #define HDA_RMX_STATESTS            7
    198 #define HDA_STATESTS_SCSF_MASK      0x7 /* State Change Status Flags (6.2.8). */
    199 
    200 #define HDA_REG_GSTS                8 /* 0x10-0x11*/
    201 #define HDA_RMX_GSTS                8
    202 #define HDA_GSTS_FSTS               RT_BIT(1)   /* Flush Status */
    203 
    204 #define HDA_REG_OUTSTRMPAY          9  /* 0x18 */
    205 #define HDA_RMX_OUTSTRMPAY          112
    206 
    207 #define HDA_REG_INSTRMPAY           10 /* 0x1a */
    208 #define HDA_RMX_INSTRMPAY           113
    209 
    210 #define HDA_REG_INTCTL              11 /* 0x20 */
    211 #define HDA_RMX_INTCTL              9
    212 #define HDA_INTCTL_GIE              RT_BIT(31)  /* Global Interrupt Enable */
    213 #define HDA_INTCTL_CIE              RT_BIT(30)  /* Controller Interrupt Enable */
    214 /* Bits 0-29 correspond to streams 0-29. */
    215 #define HDA_STRMINT_MASK            0xFF        /* Streams 0-7 implemented. Applies to INTCTL and INTSTS. */
    216 
    217 #define HDA_REG_INTSTS              12 /* 0x24 */
    218 #define HDA_RMX_INTSTS              10
    219 #define HDA_INTSTS_GIS              RT_BIT(31)  /* Global Interrupt Status */
    220 #define HDA_INTSTS_CIS              RT_BIT(30)  /* Controller Interrupt Status */
    221 /* Bits 0-29 correspond to streams 0-29. */
    222 
    223 #define HDA_REG_WALCLK              13 /* 0x30 */
    224 /* NB: HDA_RMX_WALCLK is not defined because the register is not stored in memory. */
    225 
    226 /* Note: The HDA specification defines a SSYNC register at offset 0x38. The
    227  * ICH6/ICH9 datahseet defines SSYNC at offset 0x34. The Linux HDA driver matches
    228  * the datasheet.
    229  */
    230 #define HDA_REG_SSYNC               14 /* 0x34 */
    231 #define HDA_RMX_SSYNC               12
    232 
    233 #define HDA_REG_CORBLBASE           15 /* 0x40 */
    234 #define HDA_RMX_CORBLBASE           13
    235 
    236 #define HDA_REG_CORBUBASE           16 /* 0x44 */
    237 #define HDA_RMX_CORBUBASE           14
    238 
    239 #define HDA_REG_CORBWP              17 /* 0x48 */
    240 #define HDA_RMX_CORBWP              15
    241 
    242 #define HDA_REG_CORBRP              18 /* 0x4A */
    243 #define HDA_RMX_CORBRP              16
    244 #define HDA_CORBRP_RST              RT_BIT(15)  /* CORB Read Pointer Reset */
    245 
    246 #define HDA_REG_CORBCTL             19 /* 0x4C */
    247 #define HDA_RMX_CORBCTL             17
    248 #define HDA_CORBCTL_DMA             RT_BIT(1)   /* Enable CORB DMA Engine */
    249 #define HDA_CORBCTL_CMEIE           RT_BIT(0)   /* CORB Memory Error Interrupt Enable */
    250 
    251 #define HDA_REG_CORBSTS             20 /* 0x4D */
    252 #define HDA_RMX_CORBSTS             18
    253 
    254 #define HDA_REG_CORBSIZE            21 /* 0x4E */
    255 #define HDA_RMX_CORBSIZE            19
    256 /* NB: Up to and including ICH 10, sizes of CORB and RIRB are fixed at 256 entries. */
    257 
    258 #define HDA_REG_RIRBLBASE           22 /* 0x50 */
    259 #define HDA_RMX_RIRBLBASE           20
    260 
    261 #define HDA_REG_RIRBUBASE           23 /* 0x54 */
    262 #define HDA_RMX_RIRBUBASE           21
    263 
    264 #define HDA_REG_RIRBWP              24 /* 0x58 */
    265 #define HDA_RMX_RIRBWP              22
    266 #define HDA_RIRBWP_RST              RT_BIT(15)  /* RIRB Write Pointer Reset */
    267 
    268 #define HDA_REG_RINTCNT             25 /* 0x5A */
    269 #define HDA_RMX_RINTCNT             23
    270 #define RINTCNT_N(pThis)            (HDA_REG(pThis, RINTCNT) & 0xff)
    271 
    272 #define HDA_REG_RIRBCTL             26 /* 0x5C */
    273 #define HDA_RMX_RIRBCTL             24
    274 #define HDA_RIRBCTL_ROIC            RT_BIT(2)   /* Response Overrun Interrupt Control */
    275 #define HDA_RIRBCTL_RDMAEN          RT_BIT(1)   /* RIRB DMA Enable */
    276 #define HDA_RIRBCTL_RINTCTL         RT_BIT(0)   /* Response Interrupt Control */
    277 
    278 #define HDA_REG_RIRBSTS             27 /* 0x5D */
    279 #define HDA_RMX_RIRBSTS             25
    280 #define HDA_RIRBSTS_RIRBOIS         RT_BIT(2)   /* Response Overrun Interrupt Status */
    281 #define HDA_RIRBSTS_RINTFL          RT_BIT(0)   /* Response Interrupt Flag */
    282 
    283 #define HDA_REG_RIRBSIZE            28 /* 0x5E */
    284 #define HDA_RMX_RIRBSIZE            26
    285 
    286 #define HDA_REG_IC                  29 /* 0x60 */
    287 #define HDA_RMX_IC                  27
    288 
    289 #define HDA_REG_IR                  30 /* 0x64 */
    290 #define HDA_RMX_IR                  28
    291 
    292 #define HDA_REG_IRS                 31 /* 0x68 */
    293 #define HDA_RMX_IRS                 29
    294 #define HDA_IRS_IRV                 RT_BIT(1)   /* Immediate Result Valid */
    295 #define HDA_IRS_ICB                 RT_BIT(0)   /* Immediate Command Busy */
    296 
    297 #define HDA_REG_DPLBASE             32 /* 0x70 */
    298 #define HDA_RMX_DPLBASE             30
    299 
    300 #define HDA_REG_DPUBASE             33 /* 0x74 */
    301 #define HDA_RMX_DPUBASE             31
    302 
    303 #define DPBASE_ADDR_MASK            (~(uint64_t)0x7f)
    304 
    305 #define HDA_STREAM_REG_DEF(name, num)           (HDA_REG_SD##num##name)
    306 #define HDA_STREAM_RMX_DEF(name, num)           (HDA_RMX_SD##num##name)
    307 /* Note: sdnum here _MUST_ be stream reg number [0,7]. */
    308 #define HDA_STREAM_REG(pThis, name, sdnum)      (HDA_REG_IND((pThis), HDA_REG_SD0##name + (sdnum) * 10))
    309 
    310 #define HDA_SD_NUM_FROM_REG(pThis, func, reg)   ((reg - HDA_STREAM_REG_DEF(func, 0)) / 10)
    311 
    312 /** @todo Condense marcos! */
    313 
    314 #define HDA_REG_SD0CTL              HDA_NUM_GENERAL_REGS /* 0x80; other streams offset by 0x20 */
    315 #define HDA_RMX_SD0CTL              32
    316 #define HDA_RMX_SD1CTL              (HDA_STREAM_RMX_DEF(CTL, 0) + 10)
    317 #define HDA_RMX_SD2CTL              (HDA_STREAM_RMX_DEF(CTL, 0) + 20)
    318 #define HDA_RMX_SD3CTL              (HDA_STREAM_RMX_DEF(CTL, 0) + 30)
    319 #define HDA_RMX_SD4CTL              (HDA_STREAM_RMX_DEF(CTL, 0) + 40)
    320 #define HDA_RMX_SD5CTL              (HDA_STREAM_RMX_DEF(CTL, 0) + 50)
    321 #define HDA_RMX_SD6CTL              (HDA_STREAM_RMX_DEF(CTL, 0) + 60)
    322 #define HDA_RMX_SD7CTL              (HDA_STREAM_RMX_DEF(CTL, 0) + 70)
    323 
    324 #define HDA_SDCTL_NUM_MASK          0xF
    325 #define HDA_SDCTL_NUM_SHIFT         20
    326 #define HDA_SDCTL_DIR               RT_BIT(19)  /* Direction (Bidirectional streams only!) */
    327 #define HDA_SDCTL_TP                RT_BIT(18)  /* Traffic Priority (PCI Express) */
    328 #define HDA_SDCTL_STRIPE_MASK       0x3
    329 #define HDA_SDCTL_STRIPE_SHIFT      16
    330 #define HDA_SDCTL_DEIE              RT_BIT(4)   /* Descriptor Error Interrupt Enable */
    331 #define HDA_SDCTL_FEIE              RT_BIT(3)   /* FIFO Error Interrupt Enable */
    332 #define HDA_SDCTL_IOCE              RT_BIT(2)   /* Interrupt On Completion Enable */
    333 #define HDA_SDCTL_RUN               RT_BIT(1)   /* Stream Run */
    334 #define HDA_SDCTL_SRST              RT_BIT(0)   /* Stream Reset */
    335 
    336 #define HDA_REG_SD0STS              35 /* 0x83; other streams offset by 0x20 */
    337 #define HDA_RMX_SD0STS              33
    338 #define HDA_RMX_SD1STS              (HDA_STREAM_RMX_DEF(STS, 0) + 10)
    339 #define HDA_RMX_SD2STS              (HDA_STREAM_RMX_DEF(STS, 0) + 20)
    340 #define HDA_RMX_SD3STS              (HDA_STREAM_RMX_DEF(STS, 0) + 30)
    341 #define HDA_RMX_SD4STS              (HDA_STREAM_RMX_DEF(STS, 0) + 40)
    342 #define HDA_RMX_SD5STS              (HDA_STREAM_RMX_DEF(STS, 0) + 50)
    343 #define HDA_RMX_SD6STS              (HDA_STREAM_RMX_DEF(STS, 0) + 60)
    344 #define HDA_RMX_SD7STS              (HDA_STREAM_RMX_DEF(STS, 0) + 70)
    345 
    346 #define HDA_SDSTS_FIFORDY           RT_BIT(5)   /* FIFO Ready */
    347 #define HDA_SDSTS_DESE              RT_BIT(4)   /* Descriptor Error */
    348 #define HDA_SDSTS_FIFOE             RT_BIT(3)   /* FIFO Error */
    349 #define HDA_SDSTS_BCIS              RT_BIT(2)   /* Buffer Completion Interrupt Status */
    350 
    351 #define HDA_REG_SD0LPIB             36 /* 0x84; other streams offset by 0x20 */
    352 #define HDA_REG_SD1LPIB             (HDA_STREAM_REG_DEF(LPIB, 0) + 10) /* 0xA4 */
    353 #define HDA_REG_SD2LPIB             (HDA_STREAM_REG_DEF(LPIB, 0) + 20) /* 0xC4 */
    354 #define HDA_REG_SD3LPIB             (HDA_STREAM_REG_DEF(LPIB, 0) + 30) /* 0xE4 */
    355 #define HDA_REG_SD4LPIB             (HDA_STREAM_REG_DEF(LPIB, 0) + 40) /* 0x104 */
    356 #define HDA_REG_SD5LPIB             (HDA_STREAM_REG_DEF(LPIB, 0) + 50) /* 0x124 */
    357 #define HDA_REG_SD6LPIB             (HDA_STREAM_REG_DEF(LPIB, 0) + 60) /* 0x144 */
    358 #define HDA_REG_SD7LPIB             (HDA_STREAM_REG_DEF(LPIB, 0) + 70) /* 0x164 */
    359 #define HDA_RMX_SD0LPIB             34
    360 #define HDA_RMX_SD1LPIB             (HDA_STREAM_RMX_DEF(LPIB, 0) + 10)
    361 #define HDA_RMX_SD2LPIB             (HDA_STREAM_RMX_DEF(LPIB, 0) + 20)
    362 #define HDA_RMX_SD3LPIB             (HDA_STREAM_RMX_DEF(LPIB, 0) + 30)
    363 #define HDA_RMX_SD4LPIB             (HDA_STREAM_RMX_DEF(LPIB, 0) + 40)
    364 #define HDA_RMX_SD5LPIB             (HDA_STREAM_RMX_DEF(LPIB, 0) + 50)
    365 #define HDA_RMX_SD6LPIB             (HDA_STREAM_RMX_DEF(LPIB, 0) + 60)
    366 #define HDA_RMX_SD7LPIB             (HDA_STREAM_RMX_DEF(LPIB, 0) + 70)
    367 
    368 #define HDA_REG_SD0CBL              37 /* 0x88; other streams offset by 0x20 */
    369 #define HDA_RMX_SD0CBL              35
    370 #define HDA_RMX_SD1CBL              (HDA_STREAM_RMX_DEF(CBL, 0) + 10)
    371 #define HDA_RMX_SD2CBL              (HDA_STREAM_RMX_DEF(CBL, 0) + 20)
    372 #define HDA_RMX_SD3CBL              (HDA_STREAM_RMX_DEF(CBL, 0) + 30)
    373 #define HDA_RMX_SD4CBL              (HDA_STREAM_RMX_DEF(CBL, 0) + 40)
    374 #define HDA_RMX_SD5CBL              (HDA_STREAM_RMX_DEF(CBL, 0) + 50)
    375 #define HDA_RMX_SD6CBL              (HDA_STREAM_RMX_DEF(CBL, 0) + 60)
    376 #define HDA_RMX_SD7CBL              (HDA_STREAM_RMX_DEF(CBL, 0) + 70)
    377 
    378 #define HDA_REG_SD0LVI              38 /* 0x8C; other streams offset by 0x20 */
    379 #define HDA_RMX_SD0LVI              36
    380 #define HDA_RMX_SD1LVI              (HDA_STREAM_RMX_DEF(LVI, 0) + 10)
    381 #define HDA_RMX_SD2LVI              (HDA_STREAM_RMX_DEF(LVI, 0) + 20)
    382 #define HDA_RMX_SD3LVI              (HDA_STREAM_RMX_DEF(LVI, 0) + 30)
    383 #define HDA_RMX_SD4LVI              (HDA_STREAM_RMX_DEF(LVI, 0) + 40)
    384 #define HDA_RMX_SD5LVI              (HDA_STREAM_RMX_DEF(LVI, 0) + 50)
    385 #define HDA_RMX_SD6LVI              (HDA_STREAM_RMX_DEF(LVI, 0) + 60)
    386 #define HDA_RMX_SD7LVI              (HDA_STREAM_RMX_DEF(LVI, 0) + 70)
    387 
    388 #define HDA_REG_SD0FIFOW            39 /* 0x8E; other streams offset by 0x20 */
    389 #define HDA_RMX_SD0FIFOW            37
    390 #define HDA_RMX_SD1FIFOW            (HDA_STREAM_RMX_DEF(FIFOW, 0) + 10)
    391 #define HDA_RMX_SD2FIFOW            (HDA_STREAM_RMX_DEF(FIFOW, 0) + 20)
    392 #define HDA_RMX_SD3FIFOW            (HDA_STREAM_RMX_DEF(FIFOW, 0) + 30)
    393 #define HDA_RMX_SD4FIFOW            (HDA_STREAM_RMX_DEF(FIFOW, 0) + 40)
    394 #define HDA_RMX_SD5FIFOW            (HDA_STREAM_RMX_DEF(FIFOW, 0) + 50)
    395 #define HDA_RMX_SD6FIFOW            (HDA_STREAM_RMX_DEF(FIFOW, 0) + 60)
    396 #define HDA_RMX_SD7FIFOW            (HDA_STREAM_RMX_DEF(FIFOW, 0) + 70)
    397 
    398 /*
    399  * ICH6 datasheet defined limits for FIFOW values (18.2.38).
    400  */
    401 #define HDA_SDFIFOW_8B              0x2
    402 #define HDA_SDFIFOW_16B             0x3
    403 #define HDA_SDFIFOW_32B             0x4
    404 
    405 #define HDA_REG_SD0FIFOS            40 /* 0x90; other streams offset by 0x20 */
    406 #define HDA_RMX_SD0FIFOS            38
    407 #define HDA_RMX_SD1FIFOS            (HDA_STREAM_RMX_DEF(FIFOS, 0) + 10)
    408 #define HDA_RMX_SD2FIFOS            (HDA_STREAM_RMX_DEF(FIFOS, 0) + 20)
    409 #define HDA_RMX_SD3FIFOS            (HDA_STREAM_RMX_DEF(FIFOS, 0) + 30)
    410 #define HDA_RMX_SD4FIFOS            (HDA_STREAM_RMX_DEF(FIFOS, 0) + 40)
    411 #define HDA_RMX_SD5FIFOS            (HDA_STREAM_RMX_DEF(FIFOS, 0) + 50)
    412 #define HDA_RMX_SD6FIFOS            (HDA_STREAM_RMX_DEF(FIFOS, 0) + 60)
    413 #define HDA_RMX_SD7FIFOS            (HDA_STREAM_RMX_DEF(FIFOS, 0) + 70)
    414 
    415 /*
    416  * ICH6 datasheet defines limits for FIFOS registers (18.2.39)
    417  * formula: size - 1
    418  * Other values not listed are not supported.
    419  */
    420 /** Maximum FIFO size (in bytes). */
    421 #define HDA_FIFO_MAX                256
    422 
    423 #define HDA_SDIFIFO_120B            0x77 /* 8-, 16-, 20-, 24-, 32-bit Input Streams */
    424 #define HDA_SDIFIFO_160B            0x9F /* 20-, 24-bit Input Streams Streams */
    425 
    426 #define HDA_SDOFIFO_16B             0x0F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
    427 #define HDA_SDOFIFO_32B             0x1F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
    428 #define HDA_SDOFIFO_64B             0x3F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
    429 #define HDA_SDOFIFO_128B            0x7F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
    430 #define HDA_SDOFIFO_192B            0xBF /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
    431 #define HDA_SDOFIFO_256B            0xFF /* 20-, 24-bit Output Streams */
    432 
    433 #define HDA_REG_SD0FMT              41 /* 0x92; other streams offset by 0x20 */
    434 #define HDA_RMX_SD0FMT              39
    435 #define HDA_RMX_SD1FMT              (HDA_STREAM_RMX_DEF(FMT, 0) + 10)
    436 #define HDA_RMX_SD2FMT              (HDA_STREAM_RMX_DEF(FMT, 0) + 20)
    437 #define HDA_RMX_SD3FMT              (HDA_STREAM_RMX_DEF(FMT, 0) + 30)
    438 #define HDA_RMX_SD4FMT              (HDA_STREAM_RMX_DEF(FMT, 0) + 40)
    439 #define HDA_RMX_SD5FMT              (HDA_STREAM_RMX_DEF(FMT, 0) + 50)
    440 #define HDA_RMX_SD6FMT              (HDA_STREAM_RMX_DEF(FMT, 0) + 60)
    441 #define HDA_RMX_SD7FMT              (HDA_STREAM_RMX_DEF(FMT, 0) + 70)
    442 
    443 #define HDA_REG_SD0BDPL             42 /* 0x98; other streams offset by 0x20 */
    444 #define HDA_RMX_SD0BDPL             40
    445 #define HDA_RMX_SD1BDPL             (HDA_STREAM_RMX_DEF(BDPL, 0) + 10)
    446 #define HDA_RMX_SD2BDPL             (HDA_STREAM_RMX_DEF(BDPL, 0) + 20)
    447 #define HDA_RMX_SD3BDPL             (HDA_STREAM_RMX_DEF(BDPL, 0) + 30)
    448 #define HDA_RMX_SD4BDPL             (HDA_STREAM_RMX_DEF(BDPL, 0) + 40)
    449 #define HDA_RMX_SD5BDPL             (HDA_STREAM_RMX_DEF(BDPL, 0) + 50)
    450 #define HDA_RMX_SD6BDPL             (HDA_STREAM_RMX_DEF(BDPL, 0) + 60)
    451 #define HDA_RMX_SD7BDPL             (HDA_STREAM_RMX_DEF(BDPL, 0) + 70)
    452 
    453 #define HDA_REG_SD0BDPU             43 /* 0x9C; other streams offset by 0x20 */
    454 #define HDA_RMX_SD0BDPU             41
    455 #define HDA_RMX_SD1BDPU             (HDA_STREAM_RMX_DEF(BDPU, 0) + 10)
    456 #define HDA_RMX_SD2BDPU             (HDA_STREAM_RMX_DEF(BDPU, 0) + 20)
    457 #define HDA_RMX_SD3BDPU             (HDA_STREAM_RMX_DEF(BDPU, 0) + 30)
    458 #define HDA_RMX_SD4BDPU             (HDA_STREAM_RMX_DEF(BDPU, 0) + 40)
    459 #define HDA_RMX_SD5BDPU             (HDA_STREAM_RMX_DEF(BDPU, 0) + 50)
    460 #define HDA_RMX_SD6BDPU             (HDA_STREAM_RMX_DEF(BDPU, 0) + 60)
    461 #define HDA_RMX_SD7BDPU             (HDA_STREAM_RMX_DEF(BDPU, 0) + 70)
    462 
    463 #define HDA_BDLE_FLAG_IOC           RT_BIT(0) /* Interrupt on completion (IOC). */
    464 
    465 #define HDA_CODEC_CAD_SHIFT         28
    466 /* Encodes the (required) LUN into a codec command. */
    467 #define HDA_CODEC_CMD(cmd, lun)     ((cmd) | (lun << HDA_CODEC_CAD_SHIFT))
    468 
    469 
    470114
    471115/*********************************************************************************************************************************
    472116*   Structures and Typedefs                                                                                                      *
    473117*********************************************************************************************************************************/
    474 
    475 /**
    476  * Internal state of a Buffer Descriptor List Entry (BDLE),
    477  * needed to keep track of the data needed for the actual device
    478  * emulation.
    479  */
    480 typedef struct HDABDLESTATE
    481 {
    482     /** Own index within the BDL (Buffer Descriptor List). */
    483     uint32_t     u32BDLIndex;
    484     /** Number of bytes below the stream's FIFO watermark (SDFIFOW).
    485      *  Used to check if we need fill up the FIFO again. */
    486     uint32_t     cbBelowFIFOW;
    487     /** Current offset in DMA buffer (in bytes).*/
    488     uint32_t     u32BufOff;
    489     uint32_t     Padding;
    490 } HDABDLESTATE, *PHDABDLESTATE;
    491 
    492 /**
    493  * BDL description structure.
    494  * Do not touch this, as this must match to the HDA specs.
    495  */
    496 typedef struct HDABDLEDESC
    497 {
    498     /** Starting address of the actual buffer. Must be 128-bit aligned. */
    499     uint64_t     u64BufAdr;
    500     /** Size of the actual buffer (in bytes). */
    501     uint32_t     u32BufSize;
    502     /** Bit 0: Interrupt on completion; the controller will generate
    503      *  an interrupt when the last byte of the buffer has been
    504      *  fetched by the DMA engine.
    505      *
    506      *  Rest is reserved for further use and must be 0. */
    507     uint32_t     fFlags;
    508 } HDABDLEDESC, *PHDABDLEDESC;
    509 AssertCompileSize(HDABDLEDESC, 16); /* Always 16 byte. Also must be aligned on 128-byte boundary. */
    510 
    511 /**
    512  * Buffer Descriptor List Entry (BDLE) (3.6.3).
    513  */
    514 typedef struct HDABDLE
    515 {
    516     /** The actual BDL description. */
    517     HDABDLEDESC  Desc;
    518     /** Internal state of this BDLE.
    519      *  Not part of the actual BDLE registers. */
    520     HDABDLESTATE State;
    521 } HDABDLE, *PHDABDLE;
    522 
    523 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    524 /**
    525  * Structure keeping the HDA stream's state for asynchronous I/O.
    526  */
    527 typedef struct HDASTREAMSTATEAIO
    528 {
    529     /** Thread handle for the actual I/O thread. */
    530     RTTHREAD              Thread;
    531     /** Event for letting the thread know there is some data to process. */
    532     RTSEMEVENT            Event;
    533     /** Critical section for synchronizing access. */
    534     RTCRITSECT            CritSect;
    535     /** Started indicator. */
    536     volatile bool         fStarted;
    537     /** Shutdown indicator. */
    538     volatile bool         fShutdown;
    539     /** Whether the thread should do any data processing or not. */
    540     volatile bool         fEnabled;
    541     uint32_t              Padding1;
    542 } HDASTREAMSTATEAIO, *PHDASTREAMSTATEAIO;
    543 #endif
    544 
    545 /**
    546  * Internal state of a HDA stream.
    547  */
    548 typedef struct HDASTREAMSTATE
    549 {
    550     /** Current BDLE to use. Wraps around to 0 if
    551      *  maximum (cBDLE) is reached. */
    552     uint16_t                uCurBDLE;
    553     /** Flag indicating whether this stream currently is
    554      *  in reset mode and therefore not acccessible by the guest. */
    555     volatile bool           fInReset;
    556     /** Unused, padding. */
    557     uint32_t                Padding0;
    558     /** Critical section to serialize access. */
    559     RTCRITSECT              CritSect;
    560 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    561     /** Asynchronous I/O state members. */
    562     HDASTREAMSTATEAIO       AIO;
    563 #endif
    564     /** This stream's data mapping. */
    565     HDASTREAMMAPPING        Mapping;
    566     /** Current BDLE (Buffer Descriptor List Entry). */
    567     HDABDLE                 BDLE;
    568     /** Circular buffer (FIFO) for holding DMA'ed data. */
    569     R3PTRTYPE(PRTCIRCBUF)   pCircBuf;
    570     /** Timestamp of the last success DMA data transfer.
    571      *  Used to calculate the time actually elapsed between two transfers. */
    572     uint64_t                uTimerTS;
    573     /** The stream's period. Need for timing. */
    574     HDASTREAMPERIOD         Period;
    575     /** The stream's current configuration.
    576      *  Should match SDFMT. */
    577     PDMAUDIOSTREAMCFG       strmCfg;
    578 #ifdef HDA_USE_DMA_ACCESS_HANDLER
    579     /** List of DMA handlers. */
    580     RTLISTANCHORR3          lstDMAHandlers;
    581 #endif
    582     /** Unused, padding. */
    583     uint8_t                 Padding1[3];
    584 } HDASTREAMSTATE, *PHDASTREAMSTATE;
    585 
    586 /**
    587  * Structure defining an HDA mixer sink.
    588  * Its purpose is to know which audio mixer sink is bound to
    589  * which SDn (SDI/SDO) device stream.
    590  *
    591  * This is needed in order to handle interleaved streams
    592  * (that is, multiple channels in one stream) or non-interleaved
    593  * streams (each channel has a dedicated stream).
    594  *
    595  * This is only known to the actual device emulation level.
    596  */
    597 typedef struct HDAMIXERSINK
    598 {
    599     /** SDn ID this sink is assigned to. 0 if not assigned. */
    600     uint8_t                uSD;
    601     /** Channel ID of SDn ID. Only valid if SDn ID is valid. */
    602     uint8_t                uChannel;
    603     uint8_t                Padding[3];
    604     /** Pointer to the actual audio mixer sink. */
    605     R3PTRTYPE(PAUDMIXSINK) pMixSink;
    606 } HDAMIXERSINK, *PHDAMIXERSINK;
    607 
    608 #if defined (DEBUG) || defined(HDA_USE_DMA_ACCESS_HANDLER)
    609 typedef struct HDASTREAMDBGINFO
    610 {
    611     /** Critical section to serialize access if needed. */
    612     RTCRITSECT              CritSect;
    613     uint32_t                Padding1[2];
    614     /** Number of total read accesses. */
    615     uint64_t                cReadsTotal;
    616     /** Number of total DMA bytes read. */
    617     uint64_t                cbReadTotal;
    618     /** Timestamp (in ns) of last read access. */
    619     uint64_t                tsLastReadNs;
    620     /** Number of total write accesses. */
    621     uint64_t                cWritesTotal;
    622     /** Number of total DMA bytes written. */
    623     uint64_t                cbWrittenTotal;
    624     /** Number of total write accesses since last iteration (Hz). */
    625     uint64_t                cWritesHz;
    626     /** Number of total DMA bytes written since last iteration (Hz). */
    627     uint64_t                cbWrittenHz;
    628     /** Timestamp (in ns) of beginning a new write slot. */
    629     uint64_t                tsWriteSlotBegin;
    630     /** Number of current silence samples in a (consecutive) row. */
    631     uint64_t                csSilence;
    632     /** Number of silent samples in a row to consider an audio block as audio gap (silence). */
    633     uint64_t                cSilenceThreshold;
    634     /** How many bytes to skip in an audio stream before detecting silence.
    635      *  (useful for intros and silence at the beginning of a song). */
    636     uint64_t                cbSilenceReadMin;
    637 } HDASTREAMDBGINFO ,*PHDASTREAMDBGINFO;
    638 #endif /* defined (DEBUG) || defined(HDA_USE_DMA_ACCESS_HANDLER) */
    639 
    640 /**
    641  * Structure for keeping a HDA stream (SDI / SDO).
    642  *
    643  * Note: This HDA stream has nothing to do with a regular audio stream handled
    644  * by the audio connector or the audio mixer. This HDA stream is a serial data in/out
    645  * stream (SDI/SDO) defined in hardware and can contain multiple audio streams
    646  * in one single SDI/SDO (interleaving streams).
    647  *
    648  * How a specific SDI/SDO is mapped to our internal audio streams relies on the
    649  * stream channel mappings.
    650  *
    651  * Contains only register values which do *not* change until a
    652  * stream reset occurs.
    653  */
    654 typedef struct HDASTREAM
    655 {
    656     /** Stream descriptor number (SDn). */
    657     uint8_t                  u8SD;
    658     uint8_t                  Padding0[7];
    659     /** DMA base address (SDnBDPU - SDnBDPL). */
    660     uint64_t                 u64BDLBase;
    661     /** Cyclic Buffer Length (SDnCBL).
    662      *  Represents the size of the ring buffer. */
    663     uint32_t                 u32CBL;
    664     /** Format (SDnFMT). */
    665     uint16_t                 u16FMT;
    666     /** FIFO Size (FIFOS).
    667      *  Maximum number of bytes that may have been DMA'd into
    668      *  memory but not yet transmitted on the link. */
    669     uint16_t                 u16FIFOS;
    670     /** FIFO Watermark. */
    671     uint16_t                 u16FIFOW;
    672     /** Last Valid Index (SDnLVI). */
    673     uint16_t                 u16LVI;
    674     uint16_t                 Padding1[2];
    675     /** Pointer to the HDA state this stream is attached to. */
    676     R3PTRTYPE(PHDASTATE)     pHDAState;
    677     /** Pointer to HDA sink this stream is attached to. */
    678     R3PTRTYPE(PHDAMIXERSINK) pMixSink;
    679     /** Internal state of this stream. */
    680     HDASTREAMSTATE           State;
    681 #ifdef DEBUG
    682     /** Debug information. */
    683     HDASTREAMDBGINFO         Dbg;
    684 #endif
    685 } HDASTREAM, *PHDASTREAM;
    686 
    687 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    688 /**
    689  * Structure for keeping a HDA stream thread context.
    690  */
    691 typedef struct HDASTREAMTHREADCTX
    692 {
    693     PHDASTATE  pThis;
    694     PHDASTREAM pStream;
    695 } HDASTREAMTHREADCTX, *PHDASTREAMTHREADCTX;
    696 #endif
    697 
    698 /**
    699  * Structure for mapping a stream tag to an HDA stream.
    700  */
    701 typedef struct HDATAG
    702 {
    703     /** Own stream tag. */
    704     uint8_t               uTag;
    705     uint8_t               Padding[7];
    706     /** Pointer to associated stream. */
    707     R3PTRTYPE(PHDASTREAM) pStream;
    708 } HDATAG, *PHDATAG;
    709118
    710119/**
     
    792201} HDADRIVER;
    793202
    794 #ifdef DEBUG
    795 /** @todo Make STAM values out of this? */
    796 typedef struct HDASTATEDBGINFO
    797 {
    798     /** Timestamp (in ns) of the last timer callback (hdaTimer).
    799      * Used to calculate the time actually elapsed between two timer callbacks. */
    800     uint64_t                           tsTimerLastCalledNs;
    801     /** IRQ debugging information. */
    802     struct
    803     {
    804         /** Timestamp (in ns) of last processed (asserted / deasserted) IRQ. */
    805         uint64_t                       tsProcessedLastNs;
    806         /** Timestamp (in ns) of last asserted IRQ. */
    807         uint64_t                       tsAssertedNs;
    808         /** How many IRQs have been asserted already. */
    809         uint64_t                       cAsserted;
    810         /** Accumulated elapsed time (in ns) of all IRQ being asserted. */
    811         uint64_t                       tsAssertedTotalNs;
    812         /** Timestamp (in ns) of last deasserted IRQ. */
    813         uint64_t                       tsDeassertedNs;
    814         /** How many IRQs have been deasserted already. */
    815         uint64_t                       cDeasserted;
    816         /** Accumulated elapsed time (in ns) of all IRQ being deasserted. */
    817         uint64_t                       tsDeassertedTotalNs;
    818     } IRQ;
    819 } HDASTATEDBGINFO, *PHDASTATEDBGINFO;
    820 #endif
    821 
    822 /**
    823  * ICH Intel HD Audio Controller state.
    824  */
    825 typedef struct HDASTATE
    826 {
    827     /** The PCI device structure. */
    828     PDMPCIDEV                          PciDev;
    829     /** R3 Pointer to the device instance. */
    830     PPDMDEVINSR3                       pDevInsR3;
    831     /** R0 Pointer to the device instance. */
    832     PPDMDEVINSR0                       pDevInsR0;
    833     /** R0 Pointer to the device instance. */
    834     PPDMDEVINSRC                       pDevInsRC;
    835     /** Padding for alignment. */
    836     uint32_t                           u32Padding;
    837     /** The base interface for LUN\#0. */
    838     PDMIBASE                           IBase;
    839     RTGCPHYS                           MMIOBaseAddr;
    840     /** The HDA's register set. */
    841     uint32_t                           au32Regs[HDA_NUM_REGS];
    842     /** Internal stream states. */
    843     HDASTREAM                          aStreams[HDA_MAX_STREAMS];
    844     /** Mapping table between stream tags and stream states. */
    845     HDATAG                             aTags[HDA_MAX_TAGS];
    846     /** CORB buffer base address. */
    847     uint64_t                           u64CORBBase;
    848     /** RIRB buffer base address. */
    849     uint64_t                           u64RIRBBase;
    850     /** DMA base address.
    851      *  Made out of DPLBASE + DPUBASE (3.3.32 + 3.3.33). */
    852     uint64_t                           u64DPBase;
    853     /** Pointer to CORB buffer. */
    854     R3PTRTYPE(uint32_t *)              pu32CorbBuf;
    855     /** Size in bytes of CORB buffer. */
    856     uint32_t                           cbCorbBuf;
    857     /** Padding for alignment. */
    858     uint32_t                           u32Padding1;
    859     /** Pointer to RIRB buffer. */
    860     R3PTRTYPE(uint64_t *)              pu64RirbBuf;
    861     /** Size in bytes of RIRB buffer. */
    862     uint32_t                           cbRirbBuf;
    863     /** DMA position buffer enable bit. */
    864     bool                               fDMAPosition;
    865     /** Flag whether the R0 part is enabled. */
    866     bool                               fR0Enabled;
    867     /** Flag whether the RC part is enabled. */
    868     bool                               fRCEnabled;
    869     /** Number of active (running) SDn streams. */
    870     uint8_t                            cStreamsActive;
    871 #ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
    872     /** The timer for pumping data thru the attached LUN drivers. */
    873     PTMTIMERR3                         pTimer;
    874     /** Flag indicating whether the timer is active or not. */
    875     bool                               fTimerActive;
    876     uint8_t                            u8Padding1[7];
    877     /** Timer ticks per Hz. */
    878     uint64_t                           cTimerTicks;
    879     /** The current timer expire time (in timer ticks). */
    880     uint64_t                           tsTimerExpire;
    881 #endif
    882 #ifdef VBOX_WITH_STATISTICS
    883 # ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
    884     STAMPROFILE                        StatTimer;
    885 # endif
    886     STAMPROFILE                        StatIn;
    887     STAMPROFILE                        StatOut;
    888     STAMCOUNTER                        StatBytesRead;
    889     STAMCOUNTER                        StatBytesWritten;
    890 #endif
    891     /** Pointer to HDA codec to use. */
    892     R3PTRTYPE(PHDACODEC)               pCodec;
    893     /** List of associated LUN drivers (HDADRIVER). */
    894     RTLISTANCHORR3                     lstDrv;
    895     /** The device' software mixer. */
    896     R3PTRTYPE(PAUDIOMIXER)             pMixer;
    897     /** HDA sink for (front) output. */
    898     HDAMIXERSINK                       SinkFront;
    899 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    900     /** HDA sink for center / LFE output. */
    901     HDAMIXERSINK                       SinkCenterLFE;
    902     /** HDA sink for rear output. */
    903     HDAMIXERSINK                       SinkRear;
    904 #endif
    905     /** HDA mixer sink for line input. */
    906     HDAMIXERSINK                       SinkLineIn;
    907 #ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
    908     /** Audio mixer sink for microphone input. */
    909     HDAMIXERSINK                       SinkMicIn;
    910 #endif
    911     /** Last updated WALCLK counter. */
    912     uint64_t                           u64WalClk;
    913     /** Response Interrupt Count (RINTCNT). */
    914     uint8_t                            u8RespIntCnt;
    915     /** Current IRQ level. */
    916     uint8_t                            u8IRQL;
    917     /** Padding for alignment. */
    918     uint8_t                            au8Padding2[6];
    919 #ifdef DEBUG
    920     HDASTATEDBGINFO                    Dbg;
    921 #endif
    922 } HDASTATE;
    923 /** Pointer to the ICH Intel HD Audio Controller state. */
    924 typedef HDASTATE *PHDASTATE;
    925 
    926 #ifdef VBOX_WITH_AUDIO_HDA_CALLBACKS
    927 typedef struct HDACALLBACKCTX
    928 {
    929     PHDASTATE  pThis;
    930     PHDADRIVER pDriver;
    931 } HDACALLBACKCTX, *PHDACALLBACKCTX;
    932 #endif
    933 
    934203
    935204/*********************************************************************************************************************************
     
    980249/** @} */
    981250
    982 /** @name {IOB}SDn utility functions.
    983  * @{
    984  */
    985 #ifdef IN_RING3
    986 static int hdaSDFMTToPCMProps(uint32_t u32SDFMT, PPDMAUDIOPCMPROPS pProps);
    987 #endif
    988 /** @} */
    989 
    990251/** @name Generic register read/write functions.
    991252 * @{
     
    1001262static int hdaRegReadU8(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
    1002263static int hdaRegWriteU8(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    1003 /** @} */
    1004 
    1005 /** @name Stream functions.
    1006  * @{
    1007  */
    1008 #ifdef IN_RING3
    1009 static void          hdaStreamDestroy(PHDASTREAM pStream);
    1010 static int           hdaStreamEnable(PHDASTREAM pStream, bool fEnable);
    1011 static uint32_t      hdaStreamGetUsed(PHDASTREAM pStream);
    1012 static uint32_t      hdaStreamGetFree(PHDASTREAM pStream);
    1013 static int           hdaStreamTransfer(PHDASTREAM pStream, uint32_t cbToProcessMax);
    1014 DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTREAM pStream, uint32_t u32LPIB);
    1015 static void          hdaStreamLock(PHDASTREAM pStream);
    1016 static void          hdaStreamUnlock(PHDASTREAM pStream);
    1017 static int           hdaStreamRead(PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead);
    1018 static int           hdaStreamWrite(PHDASTREAM pStream, uint32_t cbToWrite, uint32_t *pcbWritten);
    1019 static void          hdaStreamUpdate(PHDASTREAM pStream, bool fAsync);
    1020 # ifdef HDA_USE_DMA_ACCESS_HANDLER
    1021 static bool          hdaStreamRegisterDMAHandlers(PHDASTREAM pStream);
    1022 static void          hdaStreamUnregisterDMAHandlers(PHDASTREAM pStream);
    1023 # endif
    1024 #endif /* IN_RING3 */
    1025 /** @} */
    1026 
    1027 /** @name Async I/O stream functions.
    1028  * @{
    1029  */
    1030 #ifdef IN_RING3
    1031 # ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    1032 static DECLCALLBACK(int) hdaStreamAsyncIOThread(RTTHREAD hThreadSelf, void *pvUser);
    1033 static int               hdaStreamAsyncIOCreate(PHDASTREAM pStream);
    1034 static int               hdaStreamAsyncIODestroy(PHDASTREAM pStream);
    1035 static int               hdaStreamAsyncIONotify(PHDASTREAM pStream);
    1036 static void              hdaStreamAsyncIOLock(PHDASTREAM pStream);
    1037 static void              hdaStreamAsyncIOUnlock(PHDASTREAM pStream);
    1038 static void              hdaStreamAsyncIOEnable(PHDASTREAM pStream, bool fEnable);
    1039 # endif
    1040 #endif
    1041264/** @} */
    1042265
     
    1052275/** @} */
    1053276
    1054 /** @name BDLE (Buffer Descriptor List Entry) functions.
    1055  * @{
    1056  */
    1057 #ifdef IN_RING3
    1058 static int           hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry);
    1059 # ifdef LOG_ENABLED
    1060 static void          hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BaseDMA, uint16_t cBDLE);
    1061 # endif
    1062 #endif /* IN_RING3 */
    1063 /** @} */
    1064 
    1065277/** @name Timer functions.
    1066278 * @{
     
    1073285/** @} */
    1074286
    1075 /** @name Wall clock (WALCLK) functions.
    1076  * @{
    1077  */
    1078 uint64_t          hdaWalClkGetCurrent(PHDASTATE pThis);
    1079 #ifdef IN_RING3
    1080 bool              hdaWalClkSet(PHDASTATE pThis, uint64_t u64WalClk, bool fForce);
    1081 #endif
    1082 /** @} */
    1083287
    1084288/*********************************************************************************************************************************
    1085289*   Global Variables                                                                                                             *
    1086290*********************************************************************************************************************************/
    1087 
    1088 /** Offset of the SD0 register map. */
    1089 #define HDA_REG_DESC_SD0_BASE 0x80
    1090 
    1091 /** Turn a short global register name into an memory index and a stringized name. */
    1092 #define HDA_REG_IDX(abbrev)         HDA_MEM_IND_NAME(abbrev), #abbrev
    1093 
    1094 /** Turns a short stream register name into an memory index and a stringized name. */
    1095 #define HDA_REG_IDX_STRM(reg, suff) HDA_MEM_IND_NAME(reg ## suff), #reg #suff
    1096 
    1097 /** Same as above for a register *not* stored in memory. */
    1098 #define HDA_REG_IDX_NOMEM(abbrev)   0, #abbrev
    1099291
    1100292/** No register description (RD) flags defined. */
     
    1134326
    1135327/* See 302349 p 6.2. */
    1136 static const struct HDAREGDESC
    1137 {
    1138     /** Register offset in the register space. */
    1139     uint32_t    offset;
    1140     /** Size in bytes. Registers of size > 4 are in fact tables. */
    1141     uint32_t    size;
    1142     /** Readable bits. */
    1143     uint32_t    readable;
    1144     /** Writable bits. */
    1145     uint32_t    writable;
    1146     /** Register descriptor (RD) flags of type HDA_RD_FLAG_.
    1147      *  These are used to specify the handling (read/write)
    1148      *  policy of the register. */
    1149     uint32_t    fFlags;
    1150     /** Read callback. */
    1151     int       (*pfnRead)(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
    1152     /** Write callback. */
    1153     int       (*pfnWrite)(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    1154     /** Index into the register storage array. */
    1155     uint32_t    mem_idx;
    1156     /** Abbreviated name. */
    1157     const char *abbrev;
    1158     /** Descripton. */
    1159     const char *desc;
    1160 } g_aHdaRegMap[HDA_NUM_REGS] =
    1161 
     328const HDAREGDESC g_aHdaRegMap[HDA_NUM_REGS] =
    1162329{
    1163330    /* offset  size     read mask   write mask  flags             read callback     write callback       index + abbrev              */
     
    1209376};
    1210377
    1211 /**
    1212  * HDA register aliases (HDA spec 3.3.45).
    1213  * @remarks Sorted by offReg.
    1214  */
    1215 static const struct
    1216 {
    1217     /** The alias register offset. */
    1218     uint32_t    offReg;
    1219     /** The register index. */
    1220     int         idxAlias;
    1221 } g_aHdaRegAliases[] =
     378const HDAREGALIAS g_aHdaRegAliases[] =
    1222379{
    1223380    { 0x2084, HDA_REG_SD0LPIB },
     
    1228385    { 0x2124, HDA_REG_SD5LPIB },
    1229386    { 0x2144, HDA_REG_SD6LPIB },
    1230     { 0x2164, HDA_REG_SD7LPIB },
     387    { 0x2164, HDA_REG_SD7LPIB }
    1231388};
    1232389
     
    1321478}
    1322479
    1323 /**
    1324  * Updates an HDA stream's current read or write buffer position (depending on the stream type) by
    1325  * updating its associated LPIB register and DMA position buffer (if enabled).
    1326  *
    1327  * @returns Set LPIB value.
    1328  * @param   pStream             HDA stream to update read / write position for.
    1329  * @param   u32LPIB             New LPIB (position) value to set.
    1330  */
    1331 DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTREAM pStream, uint32_t u32LPIB)
    1332 {
    1333     AssertPtrReturn(pStream, 0);
    1334 
    1335     AssertMsg(u32LPIB <= pStream->u32CBL,
    1336               ("[SD%RU8] New LPIB (%RU32) exceeds CBL (%RU32)\n", pStream->u8SD, u32LPIB, pStream->u32CBL));
    1337 
    1338     const PHDASTATE pThis = pStream->pHDAState;
    1339 
    1340     u32LPIB = RT_MIN(u32LPIB, pStream->u32CBL);
    1341 
    1342     LogFlowFunc(("[SD%RU8]: LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n",
    1343                  pStream->u8SD, u32LPIB, pThis->fDMAPosition));
    1344 
    1345     /* Update LPIB in any case. */
    1346     HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) = u32LPIB;
    1347 
    1348     /* Do we need to tell the current DMA position? */
    1349     if (pThis->fDMAPosition)
    1350     {
    1351         int rc2 = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),
    1352                                         pThis->u64DPBase + (pStream->u8SD * 2 * sizeof(uint32_t)),
    1353                                         (void *)&u32LPIB, sizeof(uint32_t));
    1354         AssertRC(rc2);
    1355     }
    1356 
    1357     return u32LPIB;
    1358 }
    1359 
    1360 
    1361 /**
    1362  * Locks an HDA stream for serialized access.
    1363  *
    1364  * @returns IPRT status code.
    1365  * @param   pStream             HDA stream to lock.
    1366  */
    1367 static void hdaStreamLock(PHDASTREAM pStream)
    1368 {
    1369     AssertPtrReturnVoid(pStream);
    1370     int rc2 = RTCritSectEnter(&pStream->State.CritSect);
    1371     AssertRC(rc2);
    1372 }
    1373 
    1374 
    1375 /**
    1376  * Unlocks a formerly locked HDA stream.
    1377  *
    1378  * @returns IPRT status code.
    1379  * @param   pStream             HDA stream to unlock.
    1380  */
    1381 static void hdaStreamUnlock(PHDASTREAM pStream)
    1382 {
    1383     AssertPtrReturnVoid(pStream);
    1384     int rc2 = RTCritSectLeave(&pStream->State.CritSect);
    1385     AssertRC(rc2);
    1386 }
    1387 
    1388 
    1389 /**
    1390  * Returns the HDA stream of specified stream descriptor number.
    1391  *
    1392  * @return  Pointer to HDA stream, or NULL if none found.
    1393  */
    1394 DECLINLINE(PHDASTREAM) hdaStreamGetFromSD(PHDASTATE pThis, uint8_t uSD)
    1395 {
    1396     AssertPtrReturn(pThis, NULL);
    1397     AssertReturn(uSD < HDA_MAX_STREAMS, NULL);
    1398 
    1399     if (uSD >= HDA_MAX_STREAMS)
    1400     {
    1401         AssertMsgFailed(("Invalid / non-handled SD%RU8\n", uSD));
    1402         return NULL;
    1403     }
    1404 
    1405     return &pThis->aStreams[uSD];
    1406 }
    1407 
    1408 
    1409 /**
    1410  * Returns the HDA stream of specified HDA sink.
    1411  *
    1412  * @return  Pointer to HDA stream, or NULL if none found.
    1413  */
    1414 DECLINLINE(PHDASTREAM) hdaSinkGetStream(PHDASTATE pThis, PHDAMIXERSINK pSink)
    1415 {
    1416     AssertPtrReturn(pThis, NULL);
    1417     AssertPtrReturn(pSink, NULL);
    1418 
    1419     /** @todo Do something with the channel mapping here? */
    1420     return hdaStreamGetFromSD(pThis, pSink->uSD);
    1421 }
    1422 
    1423 
    1424 /**
    1425  * Returns the audio direction of a specified stream descriptor.
    1426  *
    1427  * The register layout specifies that input streams (SDI) come first,
    1428  * followed by the output streams (SDO). So every stream ID below HDA_MAX_SDI
    1429  * is an input stream, whereas everything >= HDA_MAX_SDI is an output stream.
    1430  *
    1431  * Note: SDnFMT register does not provide that information, so we have to judge
    1432  *       for ourselves.
    1433  *
    1434  * @return  Audio direction.
    1435  */
    1436 DECLINLINE(PDMAUDIODIR) hdaGetDirFromSD(uint8_t uSD)
    1437 {
    1438     AssertReturn(uSD < HDA_MAX_STREAMS, PDMAUDIODIR_UNKNOWN);
    1439 
    1440     if (uSD < HDA_MAX_SDI)
    1441         return PDMAUDIODIR_IN;
    1442 
    1443     return PDMAUDIODIR_OUT;
    1444 }
    1445 #endif /* IN_RING3 */
    1446 
    1447 static uint32_t hdaGetINTSTS(PHDASTATE pThis)
    1448 {
    1449     uint32_t intSts = 0;
    1450 
    1451     /* Check controller interrupts (RIRB, STATEST). */
    1452     if (   (HDA_REG(pThis, RIRBSTS) & HDA_REG(pThis, RIRBCTL) & (HDA_RIRBCTL_ROIC | HDA_RIRBCTL_RINTCTL))
    1453         /* SDIN State Change Status Flags (SCSF). */
    1454         || (HDA_REG(pThis, STATESTS) & HDA_STATESTS_SCSF_MASK))
    1455     {
    1456         intSts |= HDA_INTSTS_CIS; /* Set the Controller Interrupt Status (CIS). */
    1457     }
    1458 
    1459     if (HDA_REG(pThis, STATESTS) & HDA_REG(pThis, WAKEEN))
    1460     {
    1461         intSts |= HDA_INTSTS_CIS; /* Touch Controller Interrupt Status (CIS). */
    1462     }
    1463 
    1464     /* For each stream, check if any interrupt status bit is set and enabled. */
    1465     for (uint8_t iStrm = 0; iStrm < HDA_MAX_STREAMS; ++iStrm)
    1466     {
    1467         if (HDA_STREAM_REG(pThis, STS, iStrm) & HDA_STREAM_REG(pThis, CTL, iStrm) & (HDA_SDCTL_DEIE | HDA_SDCTL_FEIE  | HDA_SDCTL_IOCE))
    1468         {
    1469             Log3Func(("[SD%d] interrupt status set\n", iStrm));
    1470             intSts |= RT_BIT(iStrm);
    1471         }
    1472     }
    1473 
    1474     if (intSts)
    1475         intSts |= HDA_INTSTS_GIS; /* Set the Global Interrupt Status (GIS). */
    1476 
    1477     Log3Func(("-> 0x%x\n", intSts));
    1478 
    1479     return intSts;
    1480 }
    1481 
    1482 #ifndef DEBUG
    1483 /**
    1484  * Processes (de/asserts) the interrupt according to the HDA's current state.
    1485  *
    1486  * @returns IPRT status code.
    1487  * @param   pThis               HDA state.
    1488  */
    1489 static int hdaProcessInterrupt(PHDASTATE pThis)
    1490 #else
    1491 /**
    1492  * Processes (de/asserts) the interrupt according to the HDA's current state.
    1493  * Debug version.
    1494  *
    1495  * @returns IPRT status code.
    1496  * @param   pThis               HDA state.
    1497  * @param   pszSource           Caller information.
    1498  */
    1499 static int hdaProcessInterrupt(PHDASTATE pThis, const char *pszSource)
    1500 #endif
    1501 {
    1502     HDA_REG(pThis, INTSTS) = hdaGetINTSTS(pThis);
    1503 
    1504     Log3Func(("IRQL=%RU8\n", pThis->u8IRQL));
    1505 
    1506     /* NB: It is possible to have GIS set even when CIE/SIEn are all zero; the GIS bit does
    1507      * not control the interrupt signal. See Figure 4 on page 54 of the HDA 1.0a spec.
    1508      */
    1509 
    1510     /* If global interrupt enable (GIE) is set, check if any enabled interrupts are set. */
    1511     if (   (HDA_REG(pThis, INTCTL) & HDA_INTCTL_GIE)
    1512         && (HDA_REG(pThis, INTSTS) & HDA_REG(pThis, INTCTL) & (HDA_INTCTL_CIE | HDA_STRMINT_MASK)))
    1513     {
    1514         if (!pThis->u8IRQL)
    1515         {
    1516 #ifdef DEBUG
    1517             if (!pThis->Dbg.IRQ.tsProcessedLastNs)
    1518                 pThis->Dbg.IRQ.tsProcessedLastNs = RTTimeNanoTS();
    1519 
    1520             const uint64_t tsLastElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsProcessedLastNs;
    1521 
    1522             if (!pThis->Dbg.IRQ.tsAssertedNs)
    1523                 pThis->Dbg.IRQ.tsAssertedNs = RTTimeNanoTS();
    1524 
    1525             const uint64_t tsAssertedElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsAssertedNs;
    1526 
    1527             pThis->Dbg.IRQ.cAsserted++;
    1528             pThis->Dbg.IRQ.tsAssertedTotalNs += tsAssertedElapsedNs;
    1529 
    1530             const uint64_t avgAssertedUs = (pThis->Dbg.IRQ.tsAssertedTotalNs / pThis->Dbg.IRQ.cAsserted) / 1000;
    1531 
    1532             if (avgAssertedUs > (1000 / HDA_TIMER_HZ) /* ms */ * 1000) /* Exceeds time slot? */
    1533                 Log3Func(("Asserted (%s): %zuus elapsed (%zuus on average) -- %zuus alternation delay\n",
    1534                           pszSource, tsAssertedElapsedNs / 1000,
    1535                           avgAssertedUs,
    1536                           (pThis->Dbg.IRQ.tsDeassertedNs - pThis->Dbg.IRQ.tsAssertedNs) / 1000));
    1537 #endif
    1538             Log3Func(("Asserted (%s): %RU64us between alternation (WALCLK=%RU64)\n",
    1539                       pszSource, tsLastElapsedNs / 1000, pThis->u64WalClk));
    1540 
    1541             PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, 1 /* Assert */);
    1542             pThis->u8IRQL = 1;
    1543 
    1544 #ifdef DEBUG
    1545             pThis->Dbg.IRQ.tsAssertedNs = RTTimeNanoTS();
    1546             pThis->Dbg.IRQ.tsProcessedLastNs = pThis->Dbg.IRQ.tsAssertedNs;
    1547 #endif
    1548         }
    1549     }
    1550     else
    1551     {
    1552         if (pThis->u8IRQL)
    1553         {
    1554 #ifdef DEBUG
    1555             if (!pThis->Dbg.IRQ.tsProcessedLastNs)
    1556                 pThis->Dbg.IRQ.tsProcessedLastNs = RTTimeNanoTS();
    1557 
    1558             const uint64_t tsLastElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsProcessedLastNs;
    1559 
    1560             if (!pThis->Dbg.IRQ.tsDeassertedNs)
    1561                 pThis->Dbg.IRQ.tsDeassertedNs = RTTimeNanoTS();
    1562 
    1563             const uint64_t tsDeassertedElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsDeassertedNs;
    1564 
    1565             pThis->Dbg.IRQ.cDeasserted++;
    1566             pThis->Dbg.IRQ.tsDeassertedTotalNs += tsDeassertedElapsedNs;
    1567 
    1568             const uint64_t avgDeassertedUs = (pThis->Dbg.IRQ.tsDeassertedTotalNs / pThis->Dbg.IRQ.cDeasserted) / 1000;
    1569 
    1570             if (avgDeassertedUs > (1000 / HDA_TIMER_HZ) /* ms */ * 1000) /* Exceeds time slot? */
    1571                 Log3Func(("Deasserted (%s): %zuus elapsed (%zuus on average)\n",
    1572                           pszSource, tsDeassertedElapsedNs / 1000, avgDeassertedUs));
    1573 
    1574             Log3Func(("Deasserted (%s): %RU64us between alternation (WALCLK=%RU64)\n",
    1575                       pszSource, tsLastElapsedNs / 1000, pThis->u64WalClk));
    1576 #endif
    1577             PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, 0 /* Deassert */);
    1578             pThis->u8IRQL = 0;
    1579 
    1580 #ifdef DEBUG
    1581             pThis->Dbg.IRQ.tsDeassertedNs    = RTTimeNanoTS();
    1582             pThis->Dbg.IRQ.tsProcessedLastNs = pThis->Dbg.IRQ.tsDeassertedNs;
    1583 #endif
    1584         }
    1585     }
    1586 
    1587     return VINF_SUCCESS;
    1588 }
    1589 
    1590 #ifdef IN_RING3
    1591480/**
    1592481 * Reschedules pending interrupts for all audio streams which have complete
     
    1878767    return rc;
    1879768}
    1880 
    1881 /**
    1882  * Creates an HDA stream.
    1883  *
    1884  * @returns IPRT status code.
    1885  * @param   pStream             HDA stream to create.
    1886  * @param   pThis               HDA state to assign the HDA stream to.
    1887  */
    1888 static int hdaStreamCreate(PHDASTREAM pStream, PHDASTATE pThis)
    1889 {
    1890     RT_NOREF(pThis);
    1891     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    1892 
    1893     pStream->u8SD           = UINT8_MAX;
    1894     pStream->pMixSink       = NULL;
    1895     pStream->pHDAState      = pThis;
    1896 
    1897     pStream->State.fInReset = false;
    1898 #ifdef HDA_USE_DMA_ACCESS_HANDLER
    1899     RTListInit(&pStream->State.lstDMAHandlers);
    1900 #endif
    1901 
    1902     int rc = RTCircBufCreate(&pStream->State.pCircBuf, _64K); /** @todo Make this configurable. */
    1903     if (RT_SUCCESS(rc))
    1904     {
    1905         rc = hdaStreamPeriodCreate(&pStream->State.Period);
    1906         if (RT_SUCCESS(rc))
    1907             rc = RTCritSectInit(&pStream->State.CritSect);
    1908     }
    1909 
    1910 #ifdef DEBUG
    1911     int rc2 = RTCritSectInit(&pStream->Dbg.CritSect);
    1912     AssertRC(rc2);
    1913 #endif
    1914 
    1915     return rc;
    1916 }
    1917 
    1918 /**
    1919  * Destroys an HDA stream.
    1920  *
    1921  * @param   pStream             HDA stream to destroy.
    1922  */
    1923 static void hdaStreamDestroy(PHDASTREAM pStream)
    1924 {
    1925     AssertPtrReturnVoid(pStream);
    1926 
    1927     LogFlowFunc(("[SD%RU8]: Destroying ...\n", pStream->u8SD));
    1928 
    1929     hdaStreamMapDestroy(&pStream->State.Mapping);
    1930 
    1931     int rc2;
    1932 
    1933 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    1934     rc2 = hdaStreamAsyncIODestroy(pStream);
    1935     AssertRC(rc2);
    1936 #else
    1937     RT_NOREF(pThis);
    1938 #endif
    1939 
    1940     rc2 = RTCritSectDelete(&pStream->State.CritSect);
    1941     AssertRC(rc2);
    1942 
    1943     if (pStream->State.pCircBuf)
    1944     {
    1945         RTCircBufDestroy(pStream->State.pCircBuf);
    1946         pStream->State.pCircBuf = NULL;
    1947     }
    1948 
    1949     hdaStreamPeriodDestroy(&pStream->State.Period);
    1950 
    1951 #ifdef DEBUG
    1952     rc2 = RTCritSectDelete(&pStream->Dbg.CritSect);
    1953     AssertRC(rc2);
    1954 #endif
    1955 
    1956     LogFlowFuncLeave();
    1957 }
    1958 
    1959 /**
    1960  * Initializes an HDA stream.
    1961  *
    1962  * @returns IPRT status code.
    1963  * @param   pStream             HDA stream to initialize.
    1964  * @param   uSD                 SD (stream descriptor) number to assign the HDA stream to.
    1965  */
    1966 static int hdaStreamInit(PHDASTREAM pStream, uint8_t uSD)
    1967 {
    1968     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    1969 
    1970     PHDASTATE pThis = pStream->pHDAState;
    1971     AssertPtr(pThis);
    1972 
    1973     pStream->u8SD       = uSD;
    1974     pStream->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStream->u8SD),
    1975                                       HDA_STREAM_REG(pThis, BDPU, pStream->u8SD));
    1976     pStream->u16LVI     = HDA_STREAM_REG(pThis, LVI, pStream->u8SD);
    1977     pStream->u32CBL     = HDA_STREAM_REG(pThis, CBL, pStream->u8SD);
    1978     pStream->u16FIFOS   = HDA_STREAM_REG(pThis, FIFOS, pStream->u8SD) + 1;
    1979 
    1980     /* Make sure to also update the stream's DMA counter (based on its current LPIB value). */
    1981     hdaStreamUpdateLPIB(pStream, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD));
    1982 
    1983     PPDMAUDIOSTREAMCFG pCfg = &pStream->State.strmCfg;
    1984 
    1985     int rc = hdaSDFMTToPCMProps(HDA_STREAM_REG(pThis, FMT, uSD), &pCfg->Props);
    1986     if (RT_FAILURE(rc))
    1987     {
    1988         LogRel(("HDA: Warning: Format 0x%x for stream #%RU8 not supported\n", HDA_STREAM_REG(pThis, FMT, uSD), uSD));
    1989         return rc;
    1990     }
    1991 
    1992     /* Set the stream's direction. */
    1993     pCfg->enmDir = hdaGetDirFromSD(pStream->u8SD);
    1994 
    1995     /* The the stream's name, based on the direction. */
    1996     switch (pCfg->enmDir)
    1997     {
    1998         case PDMAUDIODIR_IN:
    1999 # ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
    2000 #  error "Implement me!"
    2001 # else
    2002             pCfg->DestSource.Source = PDMAUDIORECSOURCE_LINE;
    2003             pCfg->enmLayout         = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;
    2004             RTStrCopy(pCfg->szName, sizeof(pCfg->szName), "Line In");
    2005 # endif
    2006             break;
    2007 
    2008         case PDMAUDIODIR_OUT:
    2009             /* Destination(s) will be set in hdaAddStreamOut(),
    2010              * based on the channels / stream layout. */
    2011             break;
    2012 
    2013         default:
    2014             rc = VERR_NOT_SUPPORTED;
    2015             break;
    2016     }
    2017 
    2018     /*
    2019      * Initialize the stream mapping in any case, regardless if
    2020      * we support surround audio or not. This is needed to handle
    2021      * the supported channels within a single audio stream, e.g. mono/stereo.
    2022      *
    2023      * In other words, the stream mapping *always* knows the real
    2024      * number of channels in a single audio stream.
    2025      */
    2026     rc = hdaStreamMapInit(&pStream->State.Mapping, &pCfg->Props);
    2027     AssertRCReturn(rc, rc);
    2028 
    2029     LogFunc(("[SD%RU8] DMA @ 0x%x (%RU32 bytes), LVI=%RU16, FIFOS=%RU16, rc=%Rrc\n",
    2030              pStream->u8SD, pStream->u64BDLBase, pStream->u32CBL, pStream->u16LVI, pStream->u16FIFOS, rc));
    2031 
    2032     return rc;
    2033 }
    2034 
    2035 /**
    2036  * Resets an HDA stream.
    2037  *
    2038  * @param   pThis               HDA state.
    2039  * @param   pStream             HDA stream to reset.
    2040  * @param   uSD                 Stream descriptor (SD) number to use for this stream.
    2041  */
    2042 static void hdaStreamReset(PHDASTATE pThis, PHDASTREAM pStream, uint8_t uSD)
    2043 {
    2044     AssertPtrReturnVoid(pThis);
    2045     AssertPtrReturnVoid(pStream);
    2046     AssertReturnVoid(uSD < HDA_MAX_STREAMS);
    2047 
    2048 # ifdef VBOX_STRICT
    2049     AssertReleaseMsg(!RT_BOOL(HDA_STREAM_REG(pThis, CTL, uSD) & HDA_SDCTL_RUN),
    2050                      ("[SD%RU8] Cannot reset stream while in running state\n", uSD));
    2051 # endif
    2052 
    2053     LogFunc(("[SD%RU8]: Reset\n", uSD));
    2054 
    2055     /*
    2056      * Set reset state.
    2057      */
    2058     Assert(ASMAtomicReadBool(&pStream->State.fInReset) == false); /* No nested calls. */
    2059     ASMAtomicXchgBool(&pStream->State.fInReset, true);
    2060 
    2061     /*
    2062      * Second, initialize the registers.
    2063      */
    2064     HDA_STREAM_REG(pThis, STS,   uSD) = HDA_SDSTS_FIFORDY;
    2065     /* According to the ICH6 datasheet, 0x40000 is the default value for stream descriptor register 23:20
    2066      * bits are reserved for stream number 18.2.33, resets SDnCTL except SRST bit. */
    2067     HDA_STREAM_REG(pThis, CTL,   uSD) = 0x40000 | (HDA_STREAM_REG(pThis, CTL, uSD) & HDA_SDCTL_SRST);
    2068     /* ICH6 defines default values (120 bytes for input and 192 bytes for output descriptors) of FIFO size. 18.2.39. */
    2069     HDA_STREAM_REG(pThis, FIFOS, uSD) = hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN ? HDA_SDIFIFO_120B : HDA_SDOFIFO_192B;
    2070     /* See 18.2.38: Always defaults to 0x4 (32 bytes). */
    2071     HDA_STREAM_REG(pThis, FIFOW, uSD) = HDA_SDFIFOW_32B;
    2072     HDA_STREAM_REG(pThis, LPIB,  uSD) = 0;
    2073     HDA_STREAM_REG(pThis, CBL,   uSD) = 0;
    2074     HDA_STREAM_REG(pThis, LVI,   uSD) = 0;
    2075     HDA_STREAM_REG(pThis, FMT,   uSD) = 0;
    2076     HDA_STREAM_REG(pThis, BDPU,  uSD) = 0;
    2077     HDA_STREAM_REG(pThis, BDPL,  uSD) = 0;
    2078 
    2079 #ifdef HDA_USE_DMA_ACCESS_HANDLER
    2080     hdaStreamUnregisterDMAHandlers(pThis, pStream);
    2081 #endif
    2082 
    2083     RT_ZERO(pStream->State.BDLE);
    2084     pStream->State.uCurBDLE = 0;
    2085 
    2086     if (pStream->State.pCircBuf)
    2087         RTCircBufReset(pStream->State.pCircBuf);
    2088 
    2089     /* Reset stream map. */
    2090     hdaStreamMapReset(&pStream->State.Mapping);
    2091 
    2092     /* (Re-)initialize the stream with current values. */
    2093     int rc2 = hdaStreamInit(pStream, uSD);
    2094     AssertRC(rc2);
    2095 
    2096     /* Reset the stream's period. */
    2097     hdaStreamPeriodReset(&pStream->State.Period);
    2098 
    2099 #ifdef DEBUG
    2100     pStream->Dbg.cReadsTotal      = 0;
    2101     pStream->Dbg.cbReadTotal      = 0;
    2102     pStream->Dbg.tsLastReadNs     = 0;
    2103     pStream->Dbg.cWritesTotal     = 0;
    2104     pStream->Dbg.cbWrittenTotal   = 0;
    2105     pStream->Dbg.cWritesHz        = 0;
    2106     pStream->Dbg.cbWrittenHz      = 0;
    2107     pStream->Dbg.tsWriteSlotBegin = 0;
    2108 #endif
    2109 
    2110     /* Report that we're done resetting this stream. */
    2111     HDA_STREAM_REG(pThis, CTL,   uSD) = 0;
    2112 
    2113     LogFunc(("[SD%RU8] Reset\n", uSD));
    2114 
    2115     /* Exit reset mode. */
    2116     ASMAtomicXchgBool(&pStream->State.fInReset, false);
    2117 }
    2118 
    2119 /**
    2120  * Enables or disables an HDA audio stream.
    2121  *
    2122  * @returns IPRT status code.
    2123  * @param   pStream             HDA stream to enable or disable.
    2124  * @param   fEnable             Whether to enable or disble the stream.
    2125  */
    2126 static int hdaStreamEnable(PHDASTREAM pStream, bool fEnable)
    2127 {
    2128     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    2129 
    2130     LogFunc(("[SD%RU8]: fEnable=%RTbool, pMixSink=%p\n", pStream->u8SD, fEnable, pStream->pMixSink));
    2131 
    2132     int rc = VINF_SUCCESS;
    2133 
    2134     if (pStream->pMixSink) /* Stream attached to a sink? */
    2135     {
    2136         AUDMIXSINKCMD enmCmd = fEnable
    2137                              ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE;
    2138 
    2139         /* First, enable or disable the stream and the stream's sink, if any. */
    2140         if (pStream->pMixSink->pMixSink)
    2141             rc = AudioMixerSinkCtl(pStream->pMixSink->pMixSink, enmCmd);
    2142     }
    2143 
    2144     LogFunc(("[SD%RU8] rc=%Rrc\n", pStream->u8SD, rc));
    2145     return rc;
    2146 }
    2147769#endif /* IN_RING3 */
    2148770
     
    2278900    *pu32Value = u32LPIB;
    2279901    return VINF_SUCCESS;
    2280 }
    2281 
    2282 /**
    2283  * Retrieves the currently set value for the wall clock.
    2284  *
    2285  * @return  IPRT status code.
    2286  * @return  Currently set wall clock value.
    2287  * @param   pThis               HDA state.
    2288  *
    2289  * @remark  Operation is atomic.
    2290  */
    2291 uint64_t hdaWalClkGetCurrent(PHDASTATE pThis)
    2292 {
    2293     return ASMAtomicReadU64(&pThis->u64WalClk);
    2294902}
    2295903
     
    2329937
    2330938    return u64WalClkNew;
    2331 }
    2332 
    2333 /**
    2334  * Sets the actual WALCLK register to the specified wall clock value.
    2335  * The specified wall clock value only will be set (unless fForce is set to true) if all
    2336  * handled HDA streams have passed (in time) that value. This guarantees that the WALCLK
    2337  * register stays in sync with all handled HDA streams.
    2338  *
    2339  * @return  true if the WALCLK register has been updated, false if not.
    2340  * @param   pThis               HDA state.
    2341  * @param   u64WalClk           Wall clock value to set WALCLK register to.
    2342  * @param   fForce              Whether to force setting the wall clock value or not.
    2343  */
    2344 bool hdaWalClkSet(PHDASTATE pThis, uint64_t u64WalClk, bool fForce)
    2345 {
    2346     const bool     fFrontPassed       = hdaStreamPeriodHasPassedAbsWalClk (&hdaSinkGetStream(pThis, &pThis->SinkFront)->State.Period,
    2347                                                                            u64WalClk);
    2348     const uint64_t u64FrontAbsWalClk  = hdaStreamPeriodGetAbsElapsedWalClk(&hdaSinkGetStream(pThis, &pThis->SinkFront)->State.Period);
    2349 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    2350 # error "Implement me!"
    2351 #endif
    2352 
    2353     const bool     fLineInPassed      = hdaStreamPeriodHasPassedAbsWalClk (&hdaSinkGetStream(pThis, &pThis->SinkLineIn)->State.Period, u64WalClk);
    2354     const uint64_t u64LineInAbsWalClk = hdaStreamPeriodGetAbsElapsedWalClk(&hdaSinkGetStream(pThis, &pThis->SinkLineIn)->State.Period);
    2355 #ifdef VBOX_WITH_HDA_MIC_IN
    2356     const bool     fMicInPassed       = hdaStreamPeriodHasPassedAbsWalClk (&hdaSinkGetStream(pThis, &pThis->SinkMicIn)->State.Period,  u64WalClk);
    2357     const uint64_t u64MicInAbsWalClk  = hdaStreamPeriodGetAbsElapsedWalClk(&hdaSinkGetStream(pThis, &pThis->SinkMicIn)->State.Period);
    2358 #endif
    2359 
    2360 #ifdef VBOX_STRICT
    2361     const uint64_t u64WalClkCur = ASMAtomicReadU64(&pThis->u64WalClk);
    2362 #endif
    2363           uint64_t u64WalClkSet = u64WalClk;
    2364 
    2365     /* Only drive the WALCLK register forward if all (active) stream periods have passed
    2366      * the specified point in time given by u64WalClk. */
    2367     if (  (   fFrontPassed
    2368 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    2369 # error "Implement me!"
    2370 #endif
    2371            && fLineInPassed
    2372 #ifdef VBOX_WITH_HDA_MIC_IN
    2373            && fMicInPassed
    2374 #endif
    2375           )
    2376        || fForce)
    2377     {
    2378         if (!fForce)
    2379         {
    2380             /* Get the maximum value of all periods we need to handle.
    2381              * Not the most elegant solution, but works for now ... */
    2382             u64WalClk = RT_MAX(u64WalClkSet, u64FrontAbsWalClk);
    2383 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    2384 # error "Implement me!"
    2385 #endif
    2386             u64WalClk = RT_MAX(u64WalClkSet, u64LineInAbsWalClk);
    2387 #ifdef VBOX_WITH_HDA_MIC_IN
    2388             u64WalClk = RT_MAX(u64WalClkSet, u64MicInAbsWalClk);
    2389 #endif
    2390             AssertMsg(u64WalClkSet > u64WalClkCur,
    2391                       ("Setting WALCLK to a stale or backward value (%RU64 -> %RU64) isn't a good idea really. "
    2392                        "Good luck with stuck audio stuff.\n", u64WalClkCur, u64WalClkSet));
    2393         }
    2394 
    2395         /* Set the new WALCLK value. */
    2396         ASMAtomicWriteU64(&pThis->u64WalClk, u64WalClkSet);
    2397     }
    2398 
    2399     const uint64_t u64WalClkNew = hdaWalClkGetCurrent(pThis);
    2400 
    2401     Log3Func(("Cur: %RU64, New: %RU64 (force %RTbool) -> %RU64 %s\n",
    2402               u64WalClkCur, u64WalClk, fForce,
    2403               u64WalClkNew, u64WalClkNew == u64WalClk ? "[OK]" : "[DELAYED]"));
    2404 
    2405     return (u64WalClkNew == u64WalClk);
    2406939}
    2407940#endif /* IN_RING3 */
     
    28591392
    28601393#ifdef IN_RING3
    2861 /**
    2862  * Converts an HDA stream's SDFMT register into a given PCM properties structure.
    2863  *
    2864  * @return  IPRT status code.
    2865  * @param   u32SDFMT            The HDA stream's SDFMT value to convert.
    2866  * @param   pProps              PCM properties structure to hold converted result on success.
    2867  */
    2868 static int hdaSDFMTToPCMProps(uint32_t u32SDFMT, PPDMAUDIOPCMPROPS pProps)
    2869 {
    2870     AssertPtrReturn(pProps, VERR_INVALID_POINTER);
    2871 
    2872 # define EXTRACT_VALUE(v, mask, shift) ((v & ((mask) << (shift))) >> (shift))
    2873 
    2874     int rc = VINF_SUCCESS;
    2875 
    2876     uint32_t u32Hz     = EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_BASE_RATE_MASK, HDA_SDFMT_BASE_RATE_SHIFT)
    2877                        ? 44100 : 48000;
    2878     uint32_t u32HzMult = 1;
    2879     uint32_t u32HzDiv  = 1;
    2880 
    2881     switch (EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_MULT_MASK, HDA_SDFMT_MULT_SHIFT))
    2882     {
    2883         case 0: u32HzMult = 1; break;
    2884         case 1: u32HzMult = 2; break;
    2885         case 2: u32HzMult = 3; break;
    2886         case 3: u32HzMult = 4; break;
    2887         default:
    2888             LogFunc(("Unsupported multiplier %x\n",
    2889                      EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_MULT_MASK, HDA_SDFMT_MULT_SHIFT)));
    2890             rc = VERR_NOT_SUPPORTED;
    2891             break;
    2892     }
    2893     switch (EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_DIV_MASK, HDA_SDFMT_DIV_SHIFT))
    2894     {
    2895         case 0: u32HzDiv = 1; break;
    2896         case 1: u32HzDiv = 2; break;
    2897         case 2: u32HzDiv = 3; break;
    2898         case 3: u32HzDiv = 4; break;
    2899         case 4: u32HzDiv = 5; break;
    2900         case 5: u32HzDiv = 6; break;
    2901         case 6: u32HzDiv = 7; break;
    2902         case 7: u32HzDiv = 8; break;
    2903         default:
    2904             LogFunc(("Unsupported divisor %x\n",
    2905                      EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_DIV_MASK, HDA_SDFMT_DIV_SHIFT)));
    2906             rc = VERR_NOT_SUPPORTED;
    2907             break;
    2908     }
    2909 
    2910     uint8_t cBits = 0;
    2911     switch (EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_BITS_MASK, HDA_SDFMT_BITS_SHIFT))
    2912     {
    2913         case 0:
    2914             cBits = 8;
    2915             break;
    2916         case 1:
    2917             cBits = 16;
    2918             break;
    2919         case 4:
    2920             cBits = 32;
    2921             break;
    2922         default:
    2923             AssertMsgFailed(("Unsupported bits per sample %x\n",
    2924                              EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_BITS_MASK, HDA_SDFMT_BITS_SHIFT)));
    2925             rc = VERR_NOT_SUPPORTED;
    2926             break;
    2927     }
    2928 
    2929     if (RT_SUCCESS(rc))
    2930     {
    2931         RT_BZERO(pProps, sizeof(PDMAUDIOPCMPROPS));
    2932 
    2933         pProps->cBits     = cBits;
    2934         pProps->fSigned   = true;
    2935         pProps->cChannels = (u32SDFMT & 0xf) + 1;
    2936         pProps->uHz       = u32Hz * u32HzMult / u32HzDiv;
    2937         pProps->cShift    = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pProps->cBits, pProps->cChannels);
    2938     }
    2939 
    2940 # undef EXTRACT_VALUE
    2941     return rc;
    2942 }
    2943 
    29441394/**
    29451395 * Adds an audio output stream to the device setup using the given configuration.
     
    33951845#ifdef IN_RING3
    33961846
    3397 # ifdef HDA_USE_DMA_ACCESS_HANDLER
    3398 /**
    3399  * Registers access handlers for a stream's BDLE DMA accesses.
    3400  *
    3401  * @returns true if registration was successful, false if not.
    3402  * @param   pStream             HDA stream to register BDLE access handlers for.
    3403  */
    3404 static bool hdaStreamRegisterDMAHandlers(PHDASTREAM pStream)
    3405 {
    3406     /* At least LVI and the BDL base must be set. */
    3407     if (   !pStream->u16LVI
    3408         || !pStream->u64BDLBase)
    3409     {
    3410         return false;
    3411     }
    3412 
    3413     hdaStreamUnregisterDMAHandlers(pStream);
    3414 
    3415     LogFunc(("Registering ...\n"));
    3416 
    3417     int rc = VINF_SUCCESS;
    3418 
    3419     /*
    3420      * Create BDLE ranges.
    3421      */
    3422 
    3423     struct BDLERANGE
    3424     {
    3425         RTGCPHYS uAddr;
    3426         uint32_t uSize;
    3427     } arrRanges[16]; /** @todo Use a define. */
    3428 
    3429     size_t cRanges = 0;
    3430 
    3431     for (uint16_t i = 0; i < pStream->u16LVI + 1; i++)
    3432     {
    3433         HDABDLE BDLE;
    3434         rc = hdaBDLEFetch(pThis, &BDLE, pStream->u64BDLBase, i /* Index */);
    3435         if (RT_FAILURE(rc))
    3436             break;
    3437 
    3438         bool fAddRange = true;
    3439         BDLERANGE *pRange;
    3440 
    3441         if (cRanges)
    3442         {
    3443             pRange = &arrRanges[cRanges - 1];
    3444 
    3445             /* Is the current range a direct neighbor of the current BLDE? */
    3446             if ((pRange->uAddr + pRange->uSize) == BDLE.Desc.u64BufAdr)
    3447             {
    3448                 /* Expand the current range by the current BDLE's size. */
    3449                 pRange->uSize += BDLE.Desc.u32BufSize;
    3450 
    3451                 /* Adding a new range in this case is not needed anymore. */
    3452                 fAddRange = false;
    3453 
    3454                 LogFunc(("Expanding range %zu by %RU32 (%RU32 total now)\n", cRanges - 1, BDLE.Desc.u32BufSize, pRange->uSize));
    3455             }
    3456         }
    3457 
    3458         /* Do we need to add a new range? */
    3459         if (   fAddRange
    3460             && cRanges < RT_ELEMENTS(arrRanges))
    3461         {
    3462             pRange = &arrRanges[cRanges];
    3463 
    3464             pRange->uAddr = BDLE.Desc.u64BufAdr;
    3465             pRange->uSize = BDLE.Desc.u32BufSize;
    3466 
    3467             LogFunc(("Adding range %zu - 0x%x (%RU32)\n", cRanges, pRange->uAddr, pRange->uSize));
    3468 
    3469             cRanges++;
    3470         }
    3471     }
    3472 
    3473     LogFunc(("%zu ranges total\n", cRanges));
    3474 
    3475     /*
    3476      * Register all ranges as DMA access handlers.
    3477      */
    3478 
    3479     for (size_t i = 0; i < cRanges; i++)
    3480     {
    3481         BDLERANGE *pRange = &arrRanges[i];
    3482 
    3483         PHDADMAACCESSHANDLER pHandler = (PHDADMAACCESSHANDLER)RTMemAllocZ(sizeof(HDADMAACCESSHANDLER));
    3484         if (!pHandler)
    3485         {
    3486             rc = VERR_NO_MEMORY;
    3487             break;
    3488         }
    3489 
    3490         RTListAppend(&pStream->State.lstDMAHandlers, &pHandler->Node);
    3491 
    3492         pHandler->pStream = pStream; /* Save a back reference to the owner. */
    3493 
    3494         char szDesc[32];
    3495         RTStrPrintf(szDesc, sizeof(szDesc), "HDA[SD%RU8 - RANGE%02zu]", pStream->u8SD, i);
    3496 
    3497         int rc2 = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pStream->pHDAState->pDevInsR3), PGMPHYSHANDLERKIND_WRITE,
    3498                                                    hdaDMAAccessHandler,
    3499                                                    NULL, NULL, NULL,
    3500                                                    NULL, NULL, NULL,
    3501                                                    szDesc, &pHandler->hAccessHandlerType);
    3502         AssertRCBreak(rc2);
    3503 
    3504         pHandler->BDLEAddr  = pRange->uAddr;
    3505         pHandler->BDLESize  = pRange->uSize;
    3506 
    3507         /* Get first and last pages of the BDLE range. */
    3508         RTGCPHYS pgFirst = pRange->uAddr & ~PAGE_OFFSET_MASK;
    3509         RTGCPHYS pgLast  = RT_ALIGN(pgFirst + pRange->uSize, PAGE_SIZE);
    3510 
    3511         /* Calculate the region size (in pages). */
    3512         RTGCPHYS regionSize = RT_ALIGN(pgLast - pgFirst, PAGE_SIZE);
    3513 
    3514         pHandler->GCPhysFirst = pgFirst;
    3515         pHandler->GCPhysLast  = pHandler->GCPhysFirst + (regionSize - 1);
    3516 
    3517         LogFunc(("\tRegistering region '%s': 0x%x - 0x%x (region size: %zu)\n",
    3518                  szDesc, pHandler->GCPhysFirst, pHandler->GCPhysLast, regionSize));
    3519         LogFunc(("\tBDLE @ 0x%x - 0x%x (%RU32)\n",
    3520                  pHandler->BDLEAddr, pHandler->BDLEAddr + pHandler->BDLESize, pHandler->BDLESize));
    3521 
    3522         rc2 = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pStream->pHDAState->pDevInsR3),
    3523                                          pHandler->GCPhysFirst, pHandler->GCPhysLast,
    3524                                          pHandler->hAccessHandlerType, pHandler, NIL_RTR0PTR, NIL_RTRCPTR,
    3525                                          szDesc);
    3526         AssertRCBreak(rc2);
    3527 
    3528         pHandler->fRegistered = true;
    3529     }
    3530 
    3531     LogFunc(("Registration ended with rc=%Rrc\n", rc));
    3532 
    3533     return RT_SUCCESS(rc);
    3534 }
    3535 
    3536 /**
    3537  * Unregisters access handlers of a stream's BDLEs.
    3538  *
    3539  * @param   pStream             HDA stream to unregister BDLE access handlers for.
    3540  */
    3541 static void hdaStreamUnregisterDMAHandlers(PHDASTREAM pStream)
    3542 {
    3543     LogFunc(("\n"));
    3544 
    3545     PHDADMAACCESSHANDLER pHandler, pHandlerNext;
    3546     RTListForEachSafe(&pStream->State.lstDMAHandlers, pHandler, pHandlerNext, HDADMAACCESSHANDLER, Node)
    3547     {
    3548         if (!pHandler->fRegistered) /* Handler not registered? Skip. */
    3549             continue;
    3550 
    3551         LogFunc(("Unregistering 0x%x - 0x%x (%zu)\n",
    3552                  pHandler->GCPhysFirst, pHandler->GCPhysLast, pHandler->GCPhysLast - pHandler->GCPhysFirst));
    3553 
    3554         int rc2 = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pStream->pHDAState->pDevInsR3),
    3555                                                pHandler->GCPhysFirst);
    3556         AssertRC(rc2);
    3557 
    3558         RTListNodeRemove(&pHandler->Node);
    3559 
    3560         RTMemFree(pHandler);
    3561         pHandler = NULL;
    3562     }
    3563 
    3564     Assert(RTListIsEmpty(&pStream->State.lstDMAHandlers));
    3565 }
    3566 # endif /* HDA_USE_DMA_ACCESS_HANDLER */
    3567 
    35681847#ifdef LOG_ENABLED
    35691848static void hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BDLBase, uint16_t cBDLE)
     
    36021881}
    36031882#endif /* LOG_ENABLED */
    3604 
    3605 /**
    3606  * Fetches a Bundle Descriptor List Entry (BDLE) from the DMA engine.
    3607  *
    3608  * @param   pThis                   Pointer to HDA state.
    3609  * @param   pBDLE                   Where to store the fetched result.
    3610  * @param   u64BaseDMA              Address base of DMA engine to use.
    3611  * @param   u16Entry                BDLE entry to fetch.
    3612  */
    3613 static int hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry)
    3614 {
    3615     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    3616     AssertPtrReturn(pBDLE,   VERR_INVALID_POINTER);
    3617     AssertReturn(u64BaseDMA, VERR_INVALID_PARAMETER);
    3618 
    3619     if (!u64BaseDMA)
    3620     {
    3621         LogRel2(("HDA: Unable to fetch BDLE #%RU16 - no base DMA address set (yet)\n", u16Entry));
    3622         return VERR_NOT_FOUND;
    3623     }
    3624     /** @todo Compare u16Entry with LVI. */
    3625 
    3626     int rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BaseDMA + (u16Entry * sizeof(HDABDLEDESC)),
    3627                                &pBDLE->Desc, sizeof(pBDLE->Desc));
    3628 
    3629     if (RT_SUCCESS(rc))
    3630     {
    3631         /* Reset internal state. */
    3632         RT_ZERO(pBDLE->State);
    3633         pBDLE->State.u32BDLIndex = u16Entry;
    3634     }
    3635 
    3636     Log3Func(("Entry #%d @ 0x%x: %R[bdle], rc=%Rrc\n", u16Entry, u64BaseDMA + (u16Entry * sizeof(HDABDLEDESC)), pBDLE, rc));
    3637 
    3638 
    3639     return VINF_SUCCESS;
    3640 }
    3641 
    3642 /**
    3643  * Returns the number of outstanding stream data bytes which need to be processed
    3644  * by the DMA engine assigned to this stream.
    3645  *
    3646  * @return Number of bytes for the DMA engine to process.
    3647  */
    3648 DECLINLINE(uint32_t) hdaStreamGetTransferSize(PHDASTATE pThis, PHDASTREAM pStream)
    3649 {
    3650     AssertPtrReturn(pThis, 0);
    3651     AssertPtrReturn(pStream, 0);
    3652 
    3653     if (!RT_BOOL(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_SDCTL_RUN))
    3654     {
    3655         AssertFailed(); /* Should never happen. */
    3656         return 0;
    3657     }
    3658 
    3659     /* Determine how much for the current BDL entry we have left to transfer. */
    3660     PHDABDLE pBDLE  = &pStream->State.BDLE;
    3661     const uint32_t cbBDLE = RT_MIN(pBDLE->Desc.u32BufSize, pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);
    3662 
    3663     /* Determine how much we (still) can stuff in the stream's internal FIFO.  */
    3664     const uint32_t cbCircBuf   = (uint32_t)RTCircBufFree(pStream->State.pCircBuf);
    3665 
    3666     uint32_t cbToTransfer = cbBDLE;
    3667 
    3668     /* Make sure that we don't transfer more than our FIFO can hold at the moment.
    3669      * As the host sets the overall pace it needs to process some of the FIFO data first before
    3670      * we can issue a new DMA data transfer. */
    3671     if (cbToTransfer > cbCircBuf)
    3672         cbToTransfer = cbCircBuf;
    3673 
    3674     Log3Func(("[SD%RU8] LPIB=%RU32 CBL=%RU32 cbCircBuf=%RU32, -> cbToTransfer=%RU32 %R[bdle]\n", pStream->u8SD,
    3675               HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), pStream->u32CBL, cbCircBuf, cbToTransfer, pBDLE));
    3676     return cbToTransfer;
    3677 }
    3678 
    3679 /**
    3680  * Increases the amount of transferred (audio) data of an HDA stream and
    3681  * reports this as needed to the guest.
    3682  *
    3683  * @param  pStream              HDA stream to increase amount for.
    3684  * @param  cbInc                Amount (in bytes) to increase.
    3685  */
    3686 DECLINLINE(void) hdaStreamTransferInc(PHDASTREAM pStream, uint32_t cbInc)
    3687 {
    3688     AssertPtrReturnVoid(pStream);
    3689 
    3690     if (!cbInc)
    3691         return;
    3692 
    3693     const PHDASTATE pThis  = pStream->pHDAState;
    3694 
    3695     const uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD);
    3696 
    3697     Log3Func(("[SD%RU8] %RU32 + %RU32 -> %RU32, CBL=%RU32\n",
    3698               pStream->u8SD, u32LPIB, cbInc, u32LPIB + cbInc, pStream->u32CBL));
    3699 
    3700     hdaStreamUpdateLPIB(pStream, u32LPIB + cbInc);
    3701 }
    37021883
    37031884/**
     
    43342515}
    43352516#endif /* HDA_USE_DMA_ACCESS_HANDLER */
    4336 
    4337 /**
    4338  * Reads DMA data from a given HDA output stream into its associated FIFO buffer.
    4339  *
    4340  * @return  IPRT status code.
    4341  * @param   pThis               HDA state.
    4342  * @param   pStream             HDA output stream to read DMA data from.
    4343  * @param   cbToRead            How much (in bytes) to read from DMA.
    4344  * @param   pcbRead             Returns read bytes from DMA. Optional.
    4345  */
    4346 static int hdaDMARead(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead)
    4347 {
    4348     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    4349     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    4350     /* pcbRead is optional. */
    4351 
    4352     int rc = VINF_SUCCESS;
    4353 
    4354     uint32_t cbReadTotal = 0;
    4355 
    4356     PHDABDLE   pBDLE     = &pStream->State.BDLE;
    4357     PRTCIRCBUF pCircBuf  = pStream->State.pCircBuf;
    4358     AssertPtr(pCircBuf);
    4359 
    4360 #ifdef HDA_DEBUG_SILENCE
    4361     uint64_t   csSilence = 0;
    4362 
    4363     pStream->Dbg.cSilenceThreshold = 100;
    4364     pStream->Dbg.cbSilenceReadMin  = _1M;
    4365 #endif
    4366 
    4367     while (cbToRead)
    4368     {
    4369         /* Make sure we only copy as much as the stream's FIFO can hold (SDFIFOS, 18.2.39). */
    4370         void *pvBuf;
    4371         size_t cbBuf;
    4372         RTCircBufAcquireWriteBlock(pCircBuf, RT_MIN(cbToRead, pStream->u16FIFOS), &pvBuf, &cbBuf);
    4373 
    4374         if (cbBuf)
    4375         {
    4376             /*
    4377              * Read from the current BDLE's DMA buffer.
    4378              */
    4379             int rc2 = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),
    4380                                         pBDLE->Desc.u64BufAdr + pBDLE->State.u32BufOff + cbReadTotal, pvBuf, cbBuf);
    4381             AssertRC(rc2);
    4382 
    4383 #ifdef HDA_DEBUG_SILENCE
    4384             uint16_t *pu16Buf = (uint16_t *)pvBuf;
    4385             for (size_t i = 0; i < cbBuf / sizeof(uint16_t); i++)
    4386             {
    4387                 if (*pu16Buf == 0)
    4388                 {
    4389                     csSilence++;
    4390                 }
    4391                 else
    4392                     break;
    4393                 pu16Buf++;
    4394             }
    4395 #endif
    4396 
    4397 #ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
    4398             if (cbBuf)
    4399             {
    4400                 RTFILE fh;
    4401                 rc2 = RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMARead.pcm",
    4402                                  RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
    4403                 if (RT_SUCCESS(rc2))
    4404                 {
    4405                     RTFileWrite(fh, pvBuf, cbBuf, NULL);
    4406                     RTFileClose(fh);
    4407                 }
    4408                 else
    4409                     AssertRC(rc2);
    4410             }
    4411 #endif
    4412 
    4413 #if 0
    4414             pStream->Dbg.cbReadTotal += cbBuf;
    4415             const uint64_t cbWritten = ASMAtomicReadU64(&pStream->Dbg.cbWrittenTotal);
    4416             Log3Func(("cbRead=%RU64, cbWritten=%RU64 -> %RU64 bytes %s\n",
    4417                       pStream->Dbg.cbReadTotal, cbWritten,
    4418                       pStream->Dbg.cbReadTotal >= cbWritten ? pStream->Dbg.cbReadTotal - cbWritten : cbWritten - pStream->Dbg.cbReadTotal,
    4419                       pStream->Dbg.cbReadTotal > cbWritten ? "too much" : "too little"));
    4420 #endif
    4421 
    4422 #ifdef VBOX_WITH_STATISTICS
    4423             STAM_COUNTER_ADD(&pThis->StatBytesRead, cbBuf);
    4424 #endif
    4425         }
    4426 
    4427         RTCircBufReleaseWriteBlock(pCircBuf, cbBuf);
    4428 
    4429         if (!cbBuf)
    4430         {
    4431             rc = VERR_BUFFER_OVERFLOW;
    4432             break;
    4433         }
    4434 
    4435         cbReadTotal += (uint32_t)cbBuf;
    4436         Assert(pBDLE->State.u32BufOff + cbReadTotal <= pBDLE->Desc.u32BufSize);
    4437 
    4438         Assert(cbToRead >= cbBuf);
    4439         cbToRead    -= (uint32_t)cbBuf;
    4440     }
    4441 
    4442 #ifdef HDA_DEBUG_SILENCE
    4443 
    4444     if (csSilence)
    4445         pStream->Dbg.csSilence += csSilence;
    4446 
    4447     if (   csSilence == 0
    4448         && pStream->Dbg.csSilence   >  pStream->Dbg.cSilenceThreshold
    4449         && pStream->Dbg.cbReadTotal >= pStream->Dbg.cbSilenceReadMin)
    4450     {
    4451         LogFunc(("Silent block detected: %RU64 audio samples\n", pStream->Dbg.csSilence));
    4452         pStream->Dbg.csSilence = 0;
    4453     }
    4454 #endif
    4455 
    4456     if (RT_SUCCESS(rc))
    4457     {
    4458         if (pcbRead)
    4459             *pcbRead = cbReadTotal;
    4460     }
    4461 
    4462     return rc;
    4463 }
    4464 
    4465 /**
    4466  * Tells whether a given BDLE is complete or not.
    4467  *
    4468  * @return  true if BDLE is complete, false if not.
    4469  * @param   pBDLE               BDLE to retrieve status for.
    4470  */
    4471 static bool hdaBDLEIsComplete(PHDABDLE pBDLE)
    4472 {
    4473     bool fIsComplete = false;
    4474 
    4475     if (   !pBDLE->Desc.u32BufSize /* There can be BDLEs with 0 size. */
    4476         || (pBDLE->State.u32BufOff >= pBDLE->Desc.u32BufSize))
    4477     {
    4478         Assert(pBDLE->State.u32BufOff == pBDLE->Desc.u32BufSize);
    4479         fIsComplete = true;
    4480     }
    4481 
    4482     Log3Func(("%R[bdle] => %s\n", pBDLE, fIsComplete ? "COMPLETE" : "INCOMPLETE"));
    4483 
    4484     return fIsComplete;
    4485 }
    4486 
    4487 
    4488 /**
    4489  * Tells whether a given BDLE needs an interrupt or not.
    4490  *
    4491  * @return  true if BDLE needs an interrupt, false if not.
    4492  * @param   pBDLE               BDLE to retrieve status for.
    4493  */
    4494 static bool hdaBDLENeedsInterrupt(PHDABDLE pBDLE)
    4495 {
    4496     return (pBDLE->Desc.fFlags & HDA_BDLE_FLAG_IOC);
    4497 }
    4498 
    4499 /**
    4500  * Writes audio data from an HDA input stream's FIFO to its associated DMA area.
    4501  *
    4502  * @return  IPRT status code.
    4503  * @param   pThis               HDA state.
    4504  * @param   pStream             HDA input stream to write audio data to.
    4505  * @param   cbToWrite           How much (in bytes) to write.
    4506  * @param   pcbWritten          Returns written bytes on success. Optional.
    4507  */
    4508 static int hdaDMAWrite(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToWrite, uint32_t *pcbWritten)
    4509 {
    4510     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    4511     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    4512     /* pcbWritten is optional. */
    4513 
    4514     PHDABDLE   pBDLE    = &pStream->State.BDLE;
    4515     PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
    4516     AssertPtr(pCircBuf);
    4517 
    4518     int rc = VINF_SUCCESS;
    4519 
    4520     uint32_t cbWrittenTotal = 0;
    4521 
    4522     void *pvBuf  = NULL;
    4523     size_t cbBuf = 0;
    4524 
    4525     uint8_t abSilence[HDA_FIFO_MAX + 1] = { 0 };
    4526 
    4527     while (cbToWrite)
    4528     {
    4529         size_t cbChunk = RT_MIN(cbToWrite, pStream->u16FIFOS);
    4530 
    4531         size_t cbBlock = 0;
    4532         RTCircBufAcquireReadBlock(pCircBuf, cbChunk, &pvBuf, &cbBlock);
    4533 
    4534         if (cbBlock)
    4535         {
    4536             cbBuf = cbBlock;
    4537         }
    4538         else /* No audio data available? Send silence. */
    4539         {
    4540             pvBuf = &abSilence;
    4541             cbBuf = cbChunk;
    4542         }
    4543 
    4544         /* Sanity checks. */
    4545         Assert(cbBuf <= pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);
    4546         Assert(cbBuf % HDA_FRAME_SIZE == 0);
    4547         Assert((cbBuf >> 1) >= 1);
    4548 
    4549 #ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
    4550         RTFILE fh;
    4551         RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMAWrite.pcm",
    4552                    RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
    4553         RTFileWrite(fh, pvBuf, cbBuf, NULL);
    4554         RTFileClose(fh);
    4555 #endif
    4556         int rc2 = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),
    4557                                         pBDLE->Desc.u64BufAdr + pBDLE->State.u32BufOff + cbWrittenTotal,
    4558                                         pvBuf, cbBuf);
    4559         AssertRC(rc2);
    4560 
    4561 #ifdef VBOX_WITH_STATISTICS
    4562         STAM_COUNTER_ADD(&pThis->StatBytesWritten, cbBuf);
    4563 #endif
    4564         if (cbBlock)
    4565             RTCircBufReleaseReadBlock(pCircBuf, cbBlock);
    4566 
    4567         Assert(cbToWrite >= cbBuf);
    4568         cbToWrite -= (uint32_t)cbBuf;
    4569 
    4570         cbWrittenTotal += (uint32_t)cbBuf;
    4571     }
    4572 
    4573     if (RT_SUCCESS(rc))
    4574     {
    4575         if (pcbWritten)
    4576             *pcbWritten = cbWrittenTotal;
    4577     }
    4578     else
    4579         LogFunc(("Failed with %Rrc\n", rc));
    4580 
    4581     return rc;
    4582 }
    45832517
    45842518/**
     
    47892723#endif
    47902724
    4791 /**
    4792  * Retrieves the available size of (buffered) audio data (in bytes) of a given HDA stream.
    4793  *
    4794  * @returns Available data (in bytes).
    4795  * @param   pStream             HDA stream to retrieve size for.
    4796  */
    4797 static uint32_t hdaStreamGetUsed(PHDASTREAM pStream)
    4798 {
    4799     AssertPtrReturn(pStream, 0);
    4800 
    4801     if (!pStream->State.pCircBuf)
    4802         return 0;
    4803 
    4804     return (uint32_t)RTCircBufUsed(pStream->State.pCircBuf);
    4805 }
    4806 
    4807 /**
    4808  * Retrieves the free size of audio data (in bytes) of a given HDA stream.
    4809  *
    4810  * @returns Free data (in bytes).
    4811  * @param   pStream             HDA stream to retrieve size for.
    4812  */
    4813 static uint32_t hdaStreamGetFree(PHDASTREAM pStream)
    4814 {
    4815     AssertPtrReturn(pStream, 0);
    4816 
    4817     if (!pStream->State.pCircBuf)
    4818         return 0;
    4819 
    4820     return (uint32_t)RTCircBufFree(pStream->State.pCircBuf);
    4821 }
    4822 
    4823 
    4824 /**
    4825  * Writes audio data from a mixer sink into an HDA stream's DMA buffer.
    4826  *
    4827  * @returns IPRT status code.
    4828  * @param   pStream             HDA stream to write to.
    4829  * @param   cbToWrite           Number of bytes to write.
    4830  * @param   pcbWritten          Number of bytes written. Optional.
    4831  */
    4832 static int hdaStreamWrite(PHDASTREAM pStream, uint32_t cbToWrite, uint32_t *pcbWritten)
    4833 {
    4834     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    4835     AssertReturn(cbToWrite,  VERR_INVALID_PARAMETER);
    4836     /* pcbWritten is optional. */
    4837 
    4838     PHDAMIXERSINK pSink = pStream->pMixSink;
    4839     if (!pSink)
    4840     {
    4841         AssertMsgFailed(("[SD%RU8]: Can't write to a stream with no sink attached\n", pStream->u8SD));
    4842 
    4843         if (pcbWritten)
    4844             *pcbWritten = 0;
    4845         return VINF_SUCCESS;
    4846     }
    4847 
    4848     PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
    4849     AssertPtr(pCircBuf);
    4850 
    4851     int rc = VINF_SUCCESS;
    4852 
    4853     uint32_t cbWrittenTotal = 0;
    4854     uint32_t cbLeft         = RT_MIN(cbToWrite, (uint32_t)RTCircBufFree(pCircBuf));
    4855 
    4856     while (cbLeft)
    4857     {
    4858         void *pvDst;
    4859         size_t cbDst;
    4860 
    4861         uint32_t cbRead = 0;
    4862 
    4863         RTCircBufAcquireWriteBlock(pCircBuf, cbToWrite, &pvDst, &cbDst);
    4864 
    4865         if (cbDst)
    4866         {
    4867             rc = AudioMixerSinkRead(pSink->pMixSink, AUDMIXOP_COPY, pvDst, (uint32_t)cbDst, &cbRead);
    4868             AssertRC(rc);
    4869 
    4870             Assert(cbDst >= cbRead);
    4871             Log2Func(("[SD%RU8]: %zu/%zu bytes read\n", pStream->u8SD, cbRead, cbDst));
    4872 
    4873 #ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
    4874             RTFILE fh;
    4875             RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaStreamWrite.pcm",
    4876                        RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
    4877             RTFileWrite(fh, pvDst, cbRead, NULL);
    4878             RTFileClose(fh);
    4879 #endif
    4880         }
    4881 
    4882         RTCircBufReleaseWriteBlock(pCircBuf, cbRead);
    4883 
    4884         if (RT_FAILURE(rc))
    4885             break;
    4886 
    4887         Assert(cbLeft  >= cbRead);
    4888         cbLeft         -= cbRead;
    4889 
    4890         cbWrittenTotal += cbRead;
    4891     }
    4892 
    4893     if (pcbWritten)
    4894         *pcbWritten = cbWrittenTotal;
    4895 
    4896     return rc;
    4897 }
    4898 
    4899 
    4900 /**
    4901  * Reads audio data from an HDA stream's DMA buffer and writes into a specified mixer sink.
    4902  *
    4903  * @returns IPRT status code.
    4904  * @param   pStream             HDA stream to read audio data from.
    4905  * @param   cbToRead            Number of bytes to read.
    4906  * @param   pcbRead             Number of bytes read. Optional.
    4907  */
    4908 static int hdaStreamRead(PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead)
    4909 {
    4910     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    4911     AssertReturn(cbToRead,   VERR_INVALID_PARAMETER);
    4912     /* pcbWritten is optional. */
    4913 
    4914     PHDAMIXERSINK pSink = pStream->pMixSink;
    4915     if (!pSink)
    4916     {
    4917         AssertMsgFailed(("[SD%RU8]: Can't read from a stream with no sink attached\n", pStream->u8SD));
    4918 
    4919         if (pcbRead)
    4920             *pcbRead = 0;
    4921         return VINF_SUCCESS;
    4922     }
    4923 
    4924     PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
    4925     AssertPtr(pCircBuf);
    4926 
    4927     int rc = VINF_SUCCESS;
    4928 
    4929     uint32_t cbReadTotal = 0;
    4930     uint32_t cbLeft      = RT_MIN(cbToRead, (uint32_t)RTCircBufUsed(pCircBuf));
    4931 
    4932     while (cbLeft)
    4933     {
    4934         void *pvSrc;
    4935         size_t cbSrc;
    4936 
    4937         uint32_t cbWritten = 0;
    4938 
    4939         RTCircBufAcquireReadBlock(pCircBuf, cbLeft, &pvSrc, &cbSrc);
    4940 
    4941         if (cbSrc)
    4942         {
    4943 #ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
    4944             RTFILE fh;
    4945             RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaStreamRead.pcm",
    4946                        RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
    4947             RTFileWrite(fh, pvSrc, cbSrc, NULL);
    4948             RTFileClose(fh);
    4949 #endif
    4950             rc = AudioMixerSinkWrite(pSink->pMixSink, AUDMIXOP_COPY, pvSrc, (uint32_t)cbSrc, &cbWritten);
    4951             AssertRC(rc);
    4952 
    4953             Assert(cbSrc >= cbWritten);
    4954             Log2Func(("[SD%RU8]: %zu/%zu bytes read\n", pStream->u8SD, cbWritten, cbSrc));
    4955         }
    4956 
    4957         RTCircBufReleaseReadBlock(pCircBuf, cbWritten);
    4958 
    4959         if (RT_FAILURE(rc))
    4960             break;
    4961 
    4962         Assert(cbLeft  >= cbWritten);
    4963         cbLeft         -= cbWritten;
    4964 
    4965         cbReadTotal    += cbWritten;
    4966     }
    4967 
    4968     if (pcbRead)
    4969         *pcbRead = cbReadTotal;
    4970 
    4971     return rc;
    4972 }
    4973 
    4974 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    4975 /**
    4976  * Asynchronous I/O thread for a HDA stream.
    4977  * This will do the heavy lifting work for us as soon as it's getting notified by another thread.
    4978  *
    4979  * @returns IPRT status code.
    4980  * @param   hThreadSelf         Thread handle.
    4981  * @param   pvUser              User argument. Must be of type PHDASTREAMTHREADCTX.
    4982  */
    4983 static DECLCALLBACK(int) hdaStreamAsyncIOThread(RTTHREAD hThreadSelf, void *pvUser)
    4984 {
    4985     PHDASTREAMTHREADCTX pCtx = (PHDASTREAMTHREADCTX)pvUser;
    4986     AssertPtr(pCtx);
    4987 
    4988     PHDASTREAM pStream = pCtx->pStream;
    4989     AssertPtr(pStream);
    4990 
    4991     PHDASTREAMSTATEAIO pAIO = &pCtx->pStream->State.AIO;
    4992 
    4993     ASMAtomicXchgBool(&pAIO->fStarted, true);
    4994 
    4995     RTThreadUserSignal(hThreadSelf);
    4996 
    4997     LogFunc(("[SD%RU8]: Started\n", pStream->u8SD));
    4998 
    4999     for (;;)
    5000     {
    5001         int rc2 = RTSemEventWait(pAIO->Event, RT_INDEFINITE_WAIT);
    5002         if (RT_FAILURE(rc2))
    5003             break;
    5004 
    5005         if (ASMAtomicReadBool(&pAIO->fShutdown))
    5006             break;
    5007 
    5008         rc2 = RTCritSectEnter(&pAIO->CritSect);
    5009         if (RT_SUCCESS(rc2))
    5010         {
    5011             if (!pAIO->fEnabled)
    5012             {
    5013                 RTCritSectLeave(&pAIO->CritSect);
    5014                 continue;
    5015             }
    5016 
    5017             hdaStreamUpdate(pStream, false /* fInTimer */);
    5018 
    5019             int rc3 = RTCritSectLeave(&pAIO->CritSect);
    5020             AssertRC(rc3);
    5021         }
    5022 
    5023         AssertRC(rc2);
    5024     }
    5025 
    5026     LogFunc(("[SD%RU8]: Ended\n", pStream->u8SD));
    5027 
    5028     ASMAtomicXchgBool(&pAIO->fStarted, false);
    5029 
    5030     return VINF_SUCCESS;
    5031 }
    5032 
    5033 /**
    5034  * Creates the async I/O thread for a specific HDA audio stream.
    5035  *
    5036  * @returns IPRT status code.
    5037  * @param   pStream             HDA audio stream to create the async I/O thread for.
    5038  */
    5039 static int hdaStreamAsyncIOCreate(PHDASTREAM pStream)
    5040 {
    5041     PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
    5042 
    5043     int rc;
    5044 
    5045     if (!ASMAtomicReadBool(&pAIO->fStarted))
    5046     {
    5047         pAIO->fShutdown = false;
    5048 
    5049         rc = RTSemEventCreate(&pAIO->Event);
    5050         if (RT_SUCCESS(rc))
    5051         {
    5052             rc = RTCritSectInit(&pAIO->CritSect);
    5053             if (RT_SUCCESS(rc))
    5054             {
    5055                 HDASTREAMTHREADCTX Ctx = { pStream->pHDAState, pStream };
    5056 
    5057                 char szThreadName[64];
    5058                 RTStrPrintf2(szThreadName, sizeof(szThreadName), "hdaAIO%RU8", pStream->u8SD);
    5059 
    5060                 rc = RTThreadCreate(&pAIO->Thread, hdaStreamAsyncIOThread, &Ctx,
    5061                                     0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, szThreadName);
    5062                 if (RT_SUCCESS(rc))
    5063                     rc = RTThreadUserWait(pAIO->Thread, 10 * 1000 /* 10s timeout */);
    5064             }
    5065         }
    5066     }
    5067     else
    5068         rc = VINF_SUCCESS;
    5069 
    5070     LogFunc(("[SD%RU8]: Returning %Rrc\n", pStream->u8SD, rc));
    5071     return rc;
    5072 }
    5073 
    5074 /**
    5075  * Destroys the async I/O thread of a specific HDA audio stream.
    5076  *
    5077  * @returns IPRT status code.
    5078  * @param   pStream             HDA audio stream to destroy the async I/O thread for.
    5079  */
    5080 static int hdaStreamAsyncIODestroy(PHDASTREAM pStream)
    5081 {
    5082     PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
    5083 
    5084     if (!ASMAtomicReadBool(&pAIO->fStarted))
    5085         return VINF_SUCCESS;
    5086 
    5087     ASMAtomicWriteBool(&pAIO->fShutdown, true);
    5088 
    5089     int rc = hdaStreamAsyncIONotify(pStream);
    5090     AssertRC(rc);
    5091 
    5092     int rcThread;
    5093     rc = RTThreadWait(pAIO->Thread, 30 * 1000 /* 30s timeout */, &rcThread);
    5094     LogFunc(("Async I/O thread ended with %Rrc (%Rrc)\n", rc, rcThread));
    5095 
    5096     if (RT_SUCCESS(rc))
    5097     {
    5098         rc = RTCritSectDelete(&pAIO->CritSect);
    5099         AssertRC(rc);
    5100 
    5101         rc = RTSemEventDestroy(pAIO->Event);
    5102         AssertRC(rc);
    5103 
    5104         pAIO->fStarted  = false;
    5105         pAIO->fShutdown = false;
    5106         pAIO->fEnabled  = false;
    5107     }
    5108 
    5109     LogFunc(("[SD%RU8]: Returning %Rrc\n", pStream->u8SD, rc));
    5110     return rc;
    5111 }
    5112 
    5113 /**
    5114  * Lets the stream's async I/O thread know that there is some data to process.
    5115  *
    5116  * @returns IPRT status code.
    5117  * @param   pStream             HDA stream to notify async I/O thread for.
    5118  */
    5119 static int hdaStreamAsyncIONotify(PHDASTREAM pStream)
    5120 {
    5121     return RTSemEventSignal(pStream->State.AIO.Event);
    5122 }
    5123 
    5124 /**
    5125  * Locks the async I/O thread of a specific HDA audio stream.
    5126  *
    5127  * @param   pStream             HDA stream to lock async I/O thread for.
    5128  */
    5129 static void hdaStreamAsyncIOLock(PHDASTREAM pStream)
    5130 {
    5131     PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
    5132 
    5133     if (!ASMAtomicReadBool(&pAIO->fStarted))
    5134         return;
    5135 
    5136     int rc2 = RTCritSectEnter(&pAIO->CritSect);
    5137     AssertRC(rc2);
    5138 }
    5139 
    5140 /**
    5141  * Unlocks the async I/O thread of a specific HDA audio stream.
    5142  *
    5143  * @param   pStream             HDA stream to unlock async I/O thread for.
    5144  */
    5145 static void hdaStreamAsyncIOUnlock(PHDASTREAM pStream)
    5146 {
    5147     PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
    5148 
    5149     if (!ASMAtomicReadBool(&pAIO->fStarted))
    5150         return;
    5151 
    5152     int rc2 = RTCritSectLeave(&pAIO->CritSect);
    5153     AssertRC(rc2);
    5154 }
    5155 
    5156 /**
    5157  * Enables (resumes) or disables (pauses) the async I/O thread.
    5158  *
    5159  * @param   pStream             HDA stream to enable/disable async I/O thread for.
    5160  * @param   fEnable             Whether to enable or disable the I/O thread.
    5161  *
    5162  * @remarks Does not do locking.
    5163  */
    5164 static void hdaStreamAsyncIOEnable(PHDASTREAM pStream, bool fEnable)
    5165 {
    5166     PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
    5167     ASMAtomicXchgBool(&pAIO->fEnabled, fEnable);
    5168 }
    5169 #endif /* VBOX_WITH_AUDIO_HDA_ASYNC_IO */
    5170 
    5171 static uint32_t hdaStreamTransferGetElapsed(PHDASTREAM pStream)
    5172 {
    5173     AssertPtr(pStream->pHDAState->pTimer);
    5174     const uint64_t cTicksNow     = TMTimerGet(pStream->pHDAState->pTimer);
    5175     const uint64_t cTicksPerSec  = TMTimerGetFreq(pStream->pHDAState->pTimer);
    5176 
    5177     const uint64_t cTicksElapsed = cTicksNow - pStream->State.uTimerTS;
    5178 #ifdef DEBUG
    5179     const uint64_t cMsElapsed    = cTicksElapsed / (cTicksPerSec / 1000);
    5180 #endif
    5181 
    5182     AssertPtr(pStream->pHDAState->pCodec);
    5183 
    5184     PPDMAUDIOSTREAMCFG pCfg = &pStream->State.strmCfg;
    5185 
    5186     /* A stream *always* runs with 48 kHz device-wise, regardless of the actual stream input/output format (Hz) being set. */
    5187     uint32_t csPerPeriod = (int)((pCfg->Props.cChannels * cTicksElapsed * 48000 /* Hz */ + cTicksPerSec) / cTicksPerSec / 2);
    5188     uint32_t cbPerPeriod = csPerPeriod << pCfg->Props.cShift;
    5189 
    5190     Log3Func(("[SD%RU8] %RU64ms (%zu samples, %zu bytes) elapsed\n", pStream->u8SD, cMsElapsed, csPerPeriod, cbPerPeriod));
    5191 
    5192     return cbPerPeriod;
    5193 }
    5194 
    5195 /**
    5196  * Transfers data of an HDA stream according to its usage (input / output).
    5197  *
    5198  * For an SDO (output) stream this means reading DMA data from the device to
    5199  * the HDA stream's internal FIFO buffer.
    5200  *
    5201  * For an SDI (input) stream this is reading audio data from the HDA stream's
    5202  * internal FIFO buffer and writing it as DMA data to the device.
    5203  *
    5204  * @returns IPRT status code.
    5205  * @param   pStream             HDA stream to update.
    5206  * @param   cbToProcessMax      Maximum of data (in bytes) to process.
    5207  */
    5208 static int hdaStreamTransfer(PHDASTREAM pStream, uint32_t cbToProcessMax)
    5209 {
    5210     AssertPtrReturn(pStream,        VERR_INVALID_POINTER);
    5211     AssertReturn(cbToProcessMax,    VERR_INVALID_PARAMETER);
    5212 
    5213     hdaStreamLock(pStream);
    5214 
    5215     PHDASTATE pThis = pStream->pHDAState;
    5216     AssertPtr(pThis);
    5217 
    5218     PHDASTREAMPERIOD pPeriod = &pStream->State.Period;
    5219     int rc = hdaStreamPeriodLock(pPeriod);
    5220     AssertRC(rc);
    5221 
    5222     bool fProceed = true;
    5223 
    5224     /* Stream not running? */
    5225     if (!(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_SDCTL_RUN))
    5226     {
    5227         Log3Func(("[SD%RU8] RUN bit not set\n", pStream->u8SD));
    5228         fProceed = false;
    5229     }
    5230     /* Period complete? */
    5231     else if (hdaStreamPeriodIsComplete(pPeriod))
    5232     {
    5233         Log3Func(("[SD%RU8] Period is complete, nothing to do\n", pStream->u8SD));
    5234         fProceed = false;
    5235     }
    5236 
    5237     if (!fProceed)
    5238     {
    5239         hdaStreamPeriodUnlock(pPeriod);
    5240         hdaStreamUnlock(pStream);
    5241         return VINF_SUCCESS;
    5242     }
    5243 
    5244     /* Sanity checks. */
    5245     Assert(pStream->u8SD < HDA_MAX_STREAMS);
    5246     Assert(pStream->u64BDLBase);
    5247     Assert(pStream->u32CBL);
    5248 
    5249     /* State sanity checks. */
    5250     Assert(ASMAtomicReadBool(&pStream->State.fInReset) == false);
    5251 
    5252     /* Fetch first / next BDL entry. */
    5253     PHDABDLE pBDLE = &pStream->State.BDLE;
    5254     if (hdaBDLEIsComplete(pBDLE))
    5255     {
    5256         rc = hdaBDLEFetch(pThis, pBDLE, pStream->u64BDLBase, pStream->State.uCurBDLE);
    5257         AssertRC(rc);
    5258     }
    5259 
    5260     const uint32_t cbPeriodRemaining = hdaStreamPeriodGetRemainingFrames(pPeriod) * HDA_FRAME_SIZE;
    5261     Assert(cbPeriodRemaining); /* Paranoia. */
    5262 
    5263     const uint32_t cbElapsed         = hdaStreamTransferGetElapsed(pStream);
    5264     Assert(cbElapsed);         /* Paranoia. */
    5265 
    5266     /* Limit the data to read, as this routine could be delayed and therefore
    5267      * report wrong (e.g. too much) cbElapsed bytes. */
    5268     uint32_t cbLeft                  = RT_MIN(RT_MIN(cbPeriodRemaining, cbElapsed), cbToProcessMax);
    5269 
    5270     Log3Func(("[SD%RU8] cbPeriodRemaining=%RU32, cbElapsed=%RU32, cbToProcessMax=%RU32 -> cbLeft=%RU32\n",
    5271               pStream->u8SD, cbPeriodRemaining, cbElapsed, cbToProcessMax, cbLeft));
    5272 
    5273     Assert(cbLeft % HDA_FRAME_SIZE == 0); /* Paranoia. */
    5274 
    5275     while (cbLeft)
    5276     {
    5277         uint32_t cbChunk = RT_MIN(hdaStreamGetTransferSize(pThis, pStream), cbLeft);
    5278         if (!cbChunk)
    5279             break;
    5280 
    5281         uint32_t cbDMA   = 0;
    5282 
    5283         if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */
    5284         {
    5285             STAM_PROFILE_START(&pThis->StatOut, a);
    5286 
    5287             rc = hdaDMARead(pThis, pStream, cbChunk, &cbDMA /* pcbRead */);
    5288             if (RT_FAILURE(rc))
    5289                 LogRel(("HDA: Reading from stream #%RU8 DMA failed with %Rrc\n", pStream->u8SD, rc));
    5290 
    5291             STAM_PROFILE_STOP(&pThis->StatOut, a);
    5292         }
    5293         else if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN) /* Input (SDI). */
    5294         {
    5295             STAM_PROFILE_START(&pThis->StatIn, a);
    5296 
    5297             rc = hdaDMAWrite(pThis, pStream, cbChunk, &cbDMA /* pcbWritten */);
    5298             if (RT_FAILURE(rc))
    5299                 LogRel(("HDA: Writing to stream #%RU8 DMA failed with %Rrc\n", pStream->u8SD, rc));
    5300 
    5301             STAM_PROFILE_STOP(&pThis->StatIn, a);
    5302         }
    5303         else /** @todo Handle duplex streams? */
    5304             AssertFailed();
    5305 
    5306         if (cbDMA)
    5307         {
    5308             Assert(cbDMA % HDA_FRAME_SIZE == 0);
    5309 
    5310             /* We always increment the position of DMA buffer counter because we're always reading
    5311              * into an intermediate buffer. */
    5312             pBDLE->State.u32BufOff += (uint32_t)cbDMA;
    5313             Assert(pBDLE->State.u32BufOff <= pBDLE->Desc.u32BufSize);
    5314 
    5315             hdaStreamTransferInc(pStream, cbDMA);
    5316 
    5317             uint32_t framesDMA = cbDMA / HDA_FRAME_SIZE;
    5318 
    5319             /* Add the transferred frames to the period. */
    5320             hdaStreamPeriodInc(pPeriod, framesDMA);
    5321 
    5322             /* Save the timestamp of when the last successful DMA transfer has been for this stream. */
    5323             pStream->State.uTimerTS = TMTimerGet(pThis->pTimer);
    5324 
    5325             Assert(cbLeft >= cbDMA);
    5326             cbLeft        -= cbDMA;
    5327         }
    5328 
    5329         if (hdaBDLEIsComplete(pBDLE))
    5330         {
    5331             Log3Func(("[SD%RU8] Complete: %R[bdle]\n", pStream->u8SD, pBDLE));
    5332 
    5333             if (hdaBDLENeedsInterrupt(pBDLE))
    5334             {
    5335                 /* If the IOCE ("Interrupt On Completion Enable") bit of the SDCTL register is set
    5336                  * we need to generate an interrupt.
    5337                  */
    5338                 if (HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_SDCTL_IOCE)
    5339                     hdaStreamPeriodAcquireInterrupt(pPeriod);
    5340             }
    5341 
    5342             if (pStream->State.uCurBDLE == pStream->u16LVI)
    5343             {
    5344                 Assert(pStream->u32CBL == HDA_STREAM_REG(pThis, LPIB, pStream->u8SD));
    5345 
    5346                 pStream->State.uCurBDLE = 0;
    5347                 hdaStreamUpdateLPIB(pStream, 0 /* LPIB */);
    5348             }
    5349             else
    5350                 pStream->State.uCurBDLE++;
    5351 
    5352             hdaBDLEFetch(pThis, pBDLE, pStream->u64BDLBase, pStream->State.uCurBDLE);
    5353 
    5354             Log3Func(("[SD%RU8] Fetching: %R[bdle]\n", pStream->u8SD, pBDLE));
    5355         }
    5356 
    5357         if (RT_FAILURE(rc))
    5358             break;
    5359     }
    5360 
    5361     if (hdaStreamPeriodIsComplete(pPeriod))
    5362     {
    5363         Log3Func(("[SD%RU8] Period complete -- Current: %R[bdle]\n", pStream->u8SD, &pStream->State.BDLE));
    5364 
    5365         /* Set the stream's BCIS bit.
    5366          *
    5367          * Note: This only must be done if the whole period is complete, and not if only
    5368          * one specific BDL entry is complete (if it has the IOC bit set).
    5369          *
    5370          * This will otherwise confuses the guest when it 1) deasserts the interrupt,
    5371          * 2) reads SDSTS (with BCIS set) and then 3) too early reads a (wrong) WALCLK value.
    5372          *
    5373          * snd_hda_intel on Linux will tell. */
    5374         HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_SDSTS_BCIS;
    5375 
    5376         /* Try updating the wall clock. */
    5377         const uint64_t u64WalClk  = hdaStreamPeriodGetAbsElapsedWalClk(pPeriod);
    5378         const bool     fWalClkSet = hdaWalClkSet(pThis, u64WalClk, false /* fForce */);
    5379 
    5380         /* Does the period have any interrupts outstanding? */
    5381         if (hdaStreamPeriodNeedsInterrupt(pPeriod))
    5382         {
    5383             if (fWalClkSet)
    5384             {
    5385                 Log3Func(("[SD%RU8] Set WALCLK to %RU64, triggering interrupt\n", pStream->u8SD, u64WalClk));
    5386 
    5387                 /* Trigger an interrupt first and let hdaRegWriteSDSTS() deal with
    5388                  * ending / beginning a period. */
    5389 #ifndef DEBUG
    5390                 hdaProcessInterrupt(pThis);
    5391 #else
    5392                 hdaProcessInterrupt(pThis, __FUNCTION__);
    5393 #endif
    5394             }
    5395         }
    5396         else
    5397         {
    5398             /* End the period first ... */
    5399             hdaStreamPeriodEnd(pPeriod);
    5400 
    5401             /* ... and immediately begin the next one. */
    5402             hdaStreamPeriodBegin(pPeriod, hdaWalClkGetCurrent(pThis));
    5403         }
    5404     }
    5405 
    5406     hdaStreamPeriodUnlock(pPeriod);
    5407 
    5408     Log3Func(("[SD%RU8] Returning %Rrc ==========================================\n", pStream->u8SD, rc));
    5409 
    5410     if (RT_FAILURE(rc))
    5411         LogFunc(("[SD%RU8] Failed with rc=%Rrcc\n", pStream->u8SD, rc));
    5412 
    5413     hdaStreamUnlock(pStream);
    5414 
    5415     return VINF_SUCCESS;
    5416 }
    5417 
    5418 /**
    5419  * Updates a HDA stream by doing its required data transfers.
    5420  * The host sink(s) set the overall pace.
    5421  *
    5422  * This routine is called by both, the synchronous and the asynchronous, implementations.
    5423  *
    5424  * @param   pStream             HDA stream to update.
    5425  * @param   fInTimer            Whether to this function was called from the timer
    5426  *                              context or an asynchronous I/O stream thread (if supported).
    5427  */
    5428 static void hdaStreamUpdate(PHDASTREAM pStream, bool fInTimer)
    5429 {
    5430     PAUDMIXSINK pSink = NULL;
    5431     if (   pStream->pMixSink
    5432         && pStream->pMixSink->pMixSink)
    5433     {
    5434         pSink = pStream->pMixSink->pMixSink;
    5435     }
    5436 
    5437     if (!AudioMixerSinkIsActive(pSink)) /* No sink available? Bail out. */
    5438         return;
    5439 
    5440     int rc2;
    5441 
    5442     if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */
    5443     {
    5444         /* Is the HDA stream ready to be written (guest output data) to? If so, by how much? */
    5445         const uint32_t cbFree = hdaStreamGetFree(pStream);
    5446 
    5447         if (   fInTimer
    5448             && cbFree)
    5449         {
    5450             Log3Func(("[SD%RU8] cbFree=%RU32\n", pStream->u8SD, cbFree));
    5451 
    5452             /* Do the DMA transfer. */
    5453             rc2 = hdaStreamTransfer(pStream, cbFree);
    5454             AssertRC(rc2);
    5455         }
    5456 
    5457         /* How much (guest output) data is available at the moment for the HDA stream? */
    5458         uint32_t cbUsed = hdaStreamGetUsed(pStream);
    5459 
    5460 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    5461         if (   fInTimer
    5462             && cbUsed)
    5463         {
    5464             rc2 = hdaStreamAsyncIONotify(pStream);
    5465             AssertRC(rc2);
    5466         }
    5467         else
    5468         {
    5469 #endif
    5470             const uint32_t cbSinkWritable = AudioMixerSinkGetWritable(pSink);
    5471 
    5472             /* Do not write more than the sink can hold at the moment.
    5473              * The host sets the overall pace. */
    5474             if (cbUsed > cbSinkWritable)
    5475                 cbUsed = cbSinkWritable;
    5476 
    5477             if (cbUsed)
    5478             {
    5479                 /* Read (guest output) data and write it to the stream's sink. */
    5480                 rc2 = hdaStreamRead(pStream, cbUsed, NULL /* pcbRead */);
    5481                 AssertRC(rc2);
    5482             }
    5483 
    5484             /* When running synchronously, update the associated sink here.
    5485              * Otherwise this will be done in the device timer. */
    5486             rc2 = AudioMixerSinkUpdate(pSink);
    5487             AssertRC(rc2);
    5488 
    5489 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    5490         }
    5491 #endif
    5492     }
    5493     else /* Input (SDI). */
    5494     {
    5495 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    5496         if (fInTimer)
    5497         {
    5498             rc2 = hdaStreamAsyncIONotify(pStream);
    5499             AssertRC(rc2);
    5500         }
    5501         else
    5502         {
    5503 #endif
    5504             rc2 = AudioMixerSinkUpdate(pSink);
    5505             AssertRC(rc2);
    5506 
    5507             /* Is the sink ready to be read (host input data) from? If so, by how much? */
    5508             const uint32_t cbReadable = AudioMixerSinkGetReadable(pSink);
    5509 
    5510             /* How much (guest input) data is free at the moment? */
    5511             uint32_t cbFree = hdaStreamGetFree(pStream);
    5512 
    5513             Log3Func(("[SD%RU8] cbReadable=%RU32, cbFree=%RU32\n", pStream->u8SD, cbReadable, cbFree));
    5514 
    5515             /* Do not read more than the sink can provide at the moment.
    5516              * The host sets the overall pace. */
    5517             if (cbFree > cbReadable)
    5518                 cbFree = cbReadable;
    5519 
    5520             if (cbFree)
    5521             {
    5522                 /* Write (guest input) data to the stream which was read from stream's sink before. */
    5523                 rc2 = hdaStreamWrite(pStream, cbFree, NULL /* pcbWritten */);
    5524                 AssertRC(rc2);
    5525             }
    5526 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    5527         }
    5528 #endif
    5529 
    5530 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    5531         if (fInTimer)
    5532         {
    5533 #endif
    5534             const uint32_t cbToTransfer = hdaStreamGetUsed(pStream);
    5535             if (cbToTransfer)
    5536             {
    5537                 /* When running synchronously, do the DMA data transfers here.
    5538                  * Otherwise this will be done in the stream's async I/O thread. */
    5539                 rc2 = hdaStreamTransfer(pStream, cbToTransfer);
    5540                 AssertRC(rc2);
    5541             }
    5542 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    5543         }
    5544 #endif
    5545     }
    5546 }
    55472725#endif /* IN_RING3 */
    55482726
  • trunk/src/VBox/Devices/Audio/DevHDACommon.h

    r64351 r67899  
    11/* $Id$ */
    22/** @file
    3  * DevHDACommon.h - Shared defines / functions between HDA controller and codec.
     3 * DevHDACommon.h - Shared HDA device defines / functions.
    44 */
    55
    66/*
    7  * Copyright (C) 2016 Oracle Corporation
     7 * Copyright (C) 2016-2017 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1818#ifndef DEV_HDA_COMMON_H
    1919#define DEV_HDA_COMMON_H
     20
     21#include "AudioMixer.h"
     22
     23/** See 302349 p 6.2. */
     24typedef struct HDAREGDESC
     25{
     26    /** Register offset in the register space. */
     27    uint32_t    offset;
     28    /** Size in bytes. Registers of size > 4 are in fact tables. */
     29    uint32_t    size;
     30    /** Readable bits. */
     31    uint32_t    readable;
     32    /** Writable bits. */
     33    uint32_t    writable;
     34    /** Register descriptor (RD) flags of type HDA_RD_FLAG_.
     35     *  These are used to specify the handling (read/write)
     36     *  policy of the register. */
     37    uint32_t    fFlags;
     38    /** Read callback. */
     39    int       (*pfnRead)(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
     40    /** Write callback. */
     41    int       (*pfnWrite)(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
     42    /** Index into the register storage array. */
     43    uint32_t    mem_idx;
     44    /** Abbreviated name. */
     45    const char *abbrev;
     46    /** Descripton. */
     47    const char *desc;
     48} HDAREGDESC, *PHDAREGDESC;
     49
     50/**
     51 * HDA register aliases (HDA spec 3.3.45).
     52 * @remarks Sorted by offReg.
     53 */
     54typedef struct HDAREGALIAS
     55{
     56    /** The alias register offset. */
     57    uint32_t    offReg;
     58    /** The register index. */
     59    int         idxAlias;
     60} HDAREGALIAS, *PHDAREGALIAS;
     61
     62/**
     63 * At the moment we support 4 input + 4 output streams max, which is 8 in total.
     64 * Bidirectional streams are currently *not* supported.
     65 *
     66 * Note: When changing any of those values, be prepared for some saved state
     67 *       fixups / trouble!
     68 */
     69#define HDA_MAX_SDI                 4
     70#define HDA_MAX_SDO                 4
     71#define HDA_MAX_STREAMS             (HDA_MAX_SDI + HDA_MAX_SDO)
     72
     73/** Number of general registers. */
     74#define HDA_NUM_GENERAL_REGS        34
     75/** Number of total registers in the HDA's register map. */
     76#define HDA_NUM_REGS                                       (HDA_NUM_GENERAL_REGS + (HDA_MAX_STREAMS * 10 /* Each stream descriptor has 10 registers */))
     77/** Total number of stream tags (channels). Index 0 is reserved / invalid. */
     78#define HDA_MAX_TAGS                16
     79
     80/*
     81 * ICH6 datasheet defines limits for FIFOS registers (18.2.39)
     82 * formula: size - 1
     83 * Other values not listed are not supported.
     84 */
     85/** Maximum FIFO size (in bytes). */
     86#define HDA_FIFO_MAX                256
     87
     88/** Default timer frequency (in Hz).
     89 *
     90 *  Note: Keep in mind that the Hz rate has nothing to do with samples rates
     91 *        or DMA / interrupt timing -- it's purely needed in order to drive
     92 *        the data flow at a constant (and sufficient) rate.
     93 *
     94 *        Lowering this value can ask for trouble, as backends then can run
     95 *        into data underruns. */
     96#define HDA_TIMER_HZ                200
     97
     98/** HDA's (fixed) audio frame size in bytes.
     99 *  We only support 16-bit stereo frames at the moment. */
     100#define HDA_FRAME_SIZE              4
     101
     102/** Offset of the SD0 register map. */
     103#define HDA_REG_DESC_SD0_BASE       0x80
     104
     105/** Turn a short global register name into an memory index and a stringized name. */
     106#define HDA_REG_IDX(abbrev)         HDA_MEM_IND_NAME(abbrev), #abbrev
     107
     108/** Turns a short stream register name into an memory index and a stringized name. */
     109#define HDA_REG_IDX_STRM(reg, suff) HDA_MEM_IND_NAME(reg ## suff), #reg #suff
     110
     111/** Same as above for a register *not* stored in memory. */
     112#define HDA_REG_IDX_NOMEM(abbrev)   0, #abbrev
     113
     114extern const HDAREGDESC g_aHdaRegMap[HDA_NUM_REGS];
     115
     116/**
     117 * NB: Register values stored in memory (au32Regs[]) are indexed through
     118 * the HDA_RMX_xxx macros (also HDA_MEM_IND_NAME()). On the other hand, the
     119 * register descriptors in g_aHdaRegMap[] are indexed through the
     120 * HDA_REG_xxx macros (also HDA_REG_IND_NAME()).
     121 *
     122 * The au32Regs[] layout is kept unchanged for saved state
     123 * compatibility.
     124 */
     125
     126/* Registers */
     127#define HDA_REG_IND_NAME(x)         HDA_REG_##x
     128#define HDA_MEM_IND_NAME(x)         HDA_RMX_##x
     129#define HDA_REG_IND(pThis, x)       ((pThis)->au32Regs[g_aHdaRegMap[x].mem_idx])
     130#define HDA_REG(pThis, x)           (HDA_REG_IND((pThis), HDA_REG_IND_NAME(x)))
     131
     132
     133#define HDA_REG_GCAP                0 /* range 0x00-0x01*/
     134#define HDA_RMX_GCAP                0
     135/* GCAP HDASpec 3.3.2 This macro encodes the following information about HDA in a compact manner:
     136 * oss (15:12) - number of output streams supported
     137 * iss (11:8)  - number of input streams supported
     138 * bss (7:3)   - number of bidirectional streams supported
     139 * bds (2:1)   - number of serial data out (SDO) signals supported
     140 * b64sup (0)  - 64 bit addressing supported.
     141 */
     142#define HDA_MAKE_GCAP(oss, iss, bss, bds, b64sup) \
     143    (  (((oss)   & 0xF)  << 12) \
     144     | (((iss)   & 0xF)  << 8)  \
     145     | (((bss)   & 0x1F) << 3)  \
     146     | (((bds)   & 0x3)  << 2)  \
     147     | ((b64sup) & 1))
     148
     149#define HDA_REG_VMIN                1 /* 0x02 */
     150#define HDA_RMX_VMIN                1
     151
     152#define HDA_REG_VMAJ                2 /* 0x03 */
     153#define HDA_RMX_VMAJ                2
     154
     155#define HDA_REG_OUTPAY              3 /* 0x04-0x05 */
     156#define HDA_RMX_OUTPAY              3
     157
     158#define HDA_REG_INPAY               4 /* 0x06-0x07 */
     159#define HDA_RMX_INPAY               4
     160
     161#define HDA_REG_GCTL                5 /* 0x08-0x0B */
     162#define HDA_RMX_GCTL                5
     163#define HDA_GCTL_UNSOL              RT_BIT(8)   /* Accept Unsolicited Response Enable */
     164#define HDA_GCTL_FCNTRL             RT_BIT(1)   /* Flush Control */
     165#define HDA_GCTL_CRST               RT_BIT(0)   /* Controller Reset */
     166
     167#define HDA_REG_WAKEEN              6 /* 0x0C */
     168#define HDA_RMX_WAKEEN              6
     169
     170#define HDA_REG_STATESTS            7 /* 0x0E */
     171#define HDA_RMX_STATESTS            7
     172#define HDA_STATESTS_SCSF_MASK      0x7 /* State Change Status Flags (6.2.8). */
     173
     174#define HDA_REG_GSTS                8 /* 0x10-0x11*/
     175#define HDA_RMX_GSTS                8
     176#define HDA_GSTS_FSTS               RT_BIT(1)   /* Flush Status */
     177
     178#define HDA_REG_OUTSTRMPAY          9  /* 0x18 */
     179#define HDA_RMX_OUTSTRMPAY          112
     180
     181#define HDA_REG_INSTRMPAY           10 /* 0x1a */
     182#define HDA_RMX_INSTRMPAY           113
     183
     184#define HDA_REG_INTCTL              11 /* 0x20 */
     185#define HDA_RMX_INTCTL              9
     186#define HDA_INTCTL_GIE              RT_BIT(31)  /* Global Interrupt Enable */
     187#define HDA_INTCTL_CIE              RT_BIT(30)  /* Controller Interrupt Enable */
     188/* Bits 0-29 correspond to streams 0-29. */
     189#define HDA_STRMINT_MASK            0xFF        /* Streams 0-7 implemented. Applies to INTCTL and INTSTS. */
     190
     191#define HDA_REG_INTSTS              12 /* 0x24 */
     192#define HDA_RMX_INTSTS              10
     193#define HDA_INTSTS_GIS              RT_BIT(31)  /* Global Interrupt Status */
     194#define HDA_INTSTS_CIS              RT_BIT(30)  /* Controller Interrupt Status */
     195/* Bits 0-29 correspond to streams 0-29. */
     196
     197#define HDA_REG_WALCLK              13 /* 0x30 */
     198/* NB: HDA_RMX_WALCLK is not defined because the register is not stored in memory. */
     199
     200/* Note: The HDA specification defines a SSYNC register at offset 0x38. The
     201 * ICH6/ICH9 datahseet defines SSYNC at offset 0x34. The Linux HDA driver matches
     202 * the datasheet.
     203 */
     204#define HDA_REG_SSYNC               14 /* 0x34 */
     205#define HDA_RMX_SSYNC               12
     206
     207#define HDA_REG_CORBLBASE           15 /* 0x40 */
     208#define HDA_RMX_CORBLBASE           13
     209
     210#define HDA_REG_CORBUBASE           16 /* 0x44 */
     211#define HDA_RMX_CORBUBASE           14
     212
     213#define HDA_REG_CORBWP              17 /* 0x48 */
     214#define HDA_RMX_CORBWP              15
     215
     216#define HDA_REG_CORBRP              18 /* 0x4A */
     217#define HDA_RMX_CORBRP              16
     218#define HDA_CORBRP_RST              RT_BIT(15)  /* CORB Read Pointer Reset */
     219
     220#define HDA_REG_CORBCTL             19 /* 0x4C */
     221#define HDA_RMX_CORBCTL             17
     222#define HDA_CORBCTL_DMA             RT_BIT(1)   /* Enable CORB DMA Engine */
     223#define HDA_CORBCTL_CMEIE           RT_BIT(0)   /* CORB Memory Error Interrupt Enable */
     224
     225#define HDA_REG_CORBSTS             20 /* 0x4D */
     226#define HDA_RMX_CORBSTS             18
     227
     228#define HDA_REG_CORBSIZE            21 /* 0x4E */
     229#define HDA_RMX_CORBSIZE            19
     230/* NB: Up to and including ICH 10, sizes of CORB and RIRB are fixed at 256 entries. */
     231
     232#define HDA_REG_RIRBLBASE           22 /* 0x50 */
     233#define HDA_RMX_RIRBLBASE           20
     234
     235#define HDA_REG_RIRBUBASE           23 /* 0x54 */
     236#define HDA_RMX_RIRBUBASE           21
     237
     238#define HDA_REG_RIRBWP              24 /* 0x58 */
     239#define HDA_RMX_RIRBWP              22
     240#define HDA_RIRBWP_RST              RT_BIT(15)  /* RIRB Write Pointer Reset */
     241
     242#define HDA_REG_RINTCNT             25 /* 0x5A */
     243#define HDA_RMX_RINTCNT             23
     244#define RINTCNT_N(pThis)            (HDA_REG(pThis, RINTCNT) & 0xff)
     245
     246#define HDA_REG_RIRBCTL             26 /* 0x5C */
     247#define HDA_RMX_RIRBCTL             24
     248#define HDA_RIRBCTL_ROIC            RT_BIT(2)   /* Response Overrun Interrupt Control */
     249#define HDA_RIRBCTL_RDMAEN          RT_BIT(1)   /* RIRB DMA Enable */
     250#define HDA_RIRBCTL_RINTCTL         RT_BIT(0)   /* Response Interrupt Control */
     251
     252#define HDA_REG_RIRBSTS             27 /* 0x5D */
     253#define HDA_RMX_RIRBSTS             25
     254#define HDA_RIRBSTS_RIRBOIS         RT_BIT(2)   /* Response Overrun Interrupt Status */
     255#define HDA_RIRBSTS_RINTFL          RT_BIT(0)   /* Response Interrupt Flag */
     256
     257#define HDA_REG_RIRBSIZE            28 /* 0x5E */
     258#define HDA_RMX_RIRBSIZE            26
     259
     260#define HDA_REG_IC                  29 /* 0x60 */
     261#define HDA_RMX_IC                  27
     262
     263#define HDA_REG_IR                  30 /* 0x64 */
     264#define HDA_RMX_IR                  28
     265
     266#define HDA_REG_IRS                 31 /* 0x68 */
     267#define HDA_RMX_IRS                 29
     268#define HDA_IRS_IRV                 RT_BIT(1)   /* Immediate Result Valid */
     269#define HDA_IRS_ICB                 RT_BIT(0)   /* Immediate Command Busy */
     270
     271#define HDA_REG_DPLBASE             32 /* 0x70 */
     272#define HDA_RMX_DPLBASE             30
     273
     274#define HDA_REG_DPUBASE             33 /* 0x74 */
     275#define HDA_RMX_DPUBASE             31
     276
     277#define DPBASE_ADDR_MASK            (~(uint64_t)0x7f)
     278
     279#define HDA_STREAM_REG_DEF(name, num)           (HDA_REG_SD##num##name)
     280#define HDA_STREAM_RMX_DEF(name, num)           (HDA_RMX_SD##num##name)
     281/* Note: sdnum here _MUST_ be stream reg number [0,7]. */
     282#define HDA_STREAM_REG(pThis, name, sdnum)      (HDA_REG_IND((pThis), HDA_REG_SD0##name + (sdnum) * 10))
     283
     284#define HDA_SD_NUM_FROM_REG(pThis, func, reg)   ((reg - HDA_STREAM_REG_DEF(func, 0)) / 10)
     285
     286/** @todo Condense marcos! */
     287
     288#define HDA_REG_SD0CTL              HDA_NUM_GENERAL_REGS /* 0x80; other streams offset by 0x20 */
     289#define HDA_RMX_SD0CTL              32
     290#define HDA_RMX_SD1CTL              (HDA_STREAM_RMX_DEF(CTL, 0) + 10)
     291#define HDA_RMX_SD2CTL              (HDA_STREAM_RMX_DEF(CTL, 0) + 20)
     292#define HDA_RMX_SD3CTL              (HDA_STREAM_RMX_DEF(CTL, 0) + 30)
     293#define HDA_RMX_SD4CTL              (HDA_STREAM_RMX_DEF(CTL, 0) + 40)
     294#define HDA_RMX_SD5CTL              (HDA_STREAM_RMX_DEF(CTL, 0) + 50)
     295#define HDA_RMX_SD6CTL              (HDA_STREAM_RMX_DEF(CTL, 0) + 60)
     296#define HDA_RMX_SD7CTL              (HDA_STREAM_RMX_DEF(CTL, 0) + 70)
     297
     298#define HDA_SDCTL_NUM_MASK          0xF
     299#define HDA_SDCTL_NUM_SHIFT         20
     300#define HDA_SDCTL_DIR               RT_BIT(19)  /* Direction (Bidirectional streams only!) */
     301#define HDA_SDCTL_TP                RT_BIT(18)  /* Traffic Priority (PCI Express) */
     302#define HDA_SDCTL_STRIPE_MASK       0x3
     303#define HDA_SDCTL_STRIPE_SHIFT      16
     304#define HDA_SDCTL_DEIE              RT_BIT(4)   /* Descriptor Error Interrupt Enable */
     305#define HDA_SDCTL_FEIE              RT_BIT(3)   /* FIFO Error Interrupt Enable */
     306#define HDA_SDCTL_IOCE              RT_BIT(2)   /* Interrupt On Completion Enable */
     307#define HDA_SDCTL_RUN               RT_BIT(1)   /* Stream Run */
     308#define HDA_SDCTL_SRST              RT_BIT(0)   /* Stream Reset */
     309
     310#define HDA_REG_SD0STS              35 /* 0x83; other streams offset by 0x20 */
     311#define HDA_RMX_SD0STS              33
     312#define HDA_RMX_SD1STS              (HDA_STREAM_RMX_DEF(STS, 0) + 10)
     313#define HDA_RMX_SD2STS              (HDA_STREAM_RMX_DEF(STS, 0) + 20)
     314#define HDA_RMX_SD3STS              (HDA_STREAM_RMX_DEF(STS, 0) + 30)
     315#define HDA_RMX_SD4STS              (HDA_STREAM_RMX_DEF(STS, 0) + 40)
     316#define HDA_RMX_SD5STS              (HDA_STREAM_RMX_DEF(STS, 0) + 50)
     317#define HDA_RMX_SD6STS              (HDA_STREAM_RMX_DEF(STS, 0) + 60)
     318#define HDA_RMX_SD7STS              (HDA_STREAM_RMX_DEF(STS, 0) + 70)
     319
     320#define HDA_SDSTS_FIFORDY           RT_BIT(5)   /* FIFO Ready */
     321#define HDA_SDSTS_DESE              RT_BIT(4)   /* Descriptor Error */
     322#define HDA_SDSTS_FIFOE             RT_BIT(3)   /* FIFO Error */
     323#define HDA_SDSTS_BCIS              RT_BIT(2)   /* Buffer Completion Interrupt Status */
     324
     325#define HDA_REG_SD0LPIB             36 /* 0x84; other streams offset by 0x20 */
     326#define HDA_REG_SD1LPIB             (HDA_STREAM_REG_DEF(LPIB, 0) + 10) /* 0xA4 */
     327#define HDA_REG_SD2LPIB             (HDA_STREAM_REG_DEF(LPIB, 0) + 20) /* 0xC4 */
     328#define HDA_REG_SD3LPIB             (HDA_STREAM_REG_DEF(LPIB, 0) + 30) /* 0xE4 */
     329#define HDA_REG_SD4LPIB             (HDA_STREAM_REG_DEF(LPIB, 0) + 40) /* 0x104 */
     330#define HDA_REG_SD5LPIB             (HDA_STREAM_REG_DEF(LPIB, 0) + 50) /* 0x124 */
     331#define HDA_REG_SD6LPIB             (HDA_STREAM_REG_DEF(LPIB, 0) + 60) /* 0x144 */
     332#define HDA_REG_SD7LPIB             (HDA_STREAM_REG_DEF(LPIB, 0) + 70) /* 0x164 */
     333#define HDA_RMX_SD0LPIB             34
     334#define HDA_RMX_SD1LPIB             (HDA_STREAM_RMX_DEF(LPIB, 0) + 10)
     335#define HDA_RMX_SD2LPIB             (HDA_STREAM_RMX_DEF(LPIB, 0) + 20)
     336#define HDA_RMX_SD3LPIB             (HDA_STREAM_RMX_DEF(LPIB, 0) + 30)
     337#define HDA_RMX_SD4LPIB             (HDA_STREAM_RMX_DEF(LPIB, 0) + 40)
     338#define HDA_RMX_SD5LPIB             (HDA_STREAM_RMX_DEF(LPIB, 0) + 50)
     339#define HDA_RMX_SD6LPIB             (HDA_STREAM_RMX_DEF(LPIB, 0) + 60)
     340#define HDA_RMX_SD7LPIB             (HDA_STREAM_RMX_DEF(LPIB, 0) + 70)
     341
     342#define HDA_REG_SD0CBL              37 /* 0x88; other streams offset by 0x20 */
     343#define HDA_RMX_SD0CBL              35
     344#define HDA_RMX_SD1CBL              (HDA_STREAM_RMX_DEF(CBL, 0) + 10)
     345#define HDA_RMX_SD2CBL              (HDA_STREAM_RMX_DEF(CBL, 0) + 20)
     346#define HDA_RMX_SD3CBL              (HDA_STREAM_RMX_DEF(CBL, 0) + 30)
     347#define HDA_RMX_SD4CBL              (HDA_STREAM_RMX_DEF(CBL, 0) + 40)
     348#define HDA_RMX_SD5CBL              (HDA_STREAM_RMX_DEF(CBL, 0) + 50)
     349#define HDA_RMX_SD6CBL              (HDA_STREAM_RMX_DEF(CBL, 0) + 60)
     350#define HDA_RMX_SD7CBL              (HDA_STREAM_RMX_DEF(CBL, 0) + 70)
     351
     352#define HDA_REG_SD0LVI              38 /* 0x8C; other streams offset by 0x20 */
     353#define HDA_RMX_SD0LVI              36
     354#define HDA_RMX_SD1LVI              (HDA_STREAM_RMX_DEF(LVI, 0) + 10)
     355#define HDA_RMX_SD2LVI              (HDA_STREAM_RMX_DEF(LVI, 0) + 20)
     356#define HDA_RMX_SD3LVI              (HDA_STREAM_RMX_DEF(LVI, 0) + 30)
     357#define HDA_RMX_SD4LVI              (HDA_STREAM_RMX_DEF(LVI, 0) + 40)
     358#define HDA_RMX_SD5LVI              (HDA_STREAM_RMX_DEF(LVI, 0) + 50)
     359#define HDA_RMX_SD6LVI              (HDA_STREAM_RMX_DEF(LVI, 0) + 60)
     360#define HDA_RMX_SD7LVI              (HDA_STREAM_RMX_DEF(LVI, 0) + 70)
     361
     362#define HDA_REG_SD0FIFOW            39 /* 0x8E; other streams offset by 0x20 */
     363#define HDA_RMX_SD0FIFOW            37
     364#define HDA_RMX_SD1FIFOW            (HDA_STREAM_RMX_DEF(FIFOW, 0) + 10)
     365#define HDA_RMX_SD2FIFOW            (HDA_STREAM_RMX_DEF(FIFOW, 0) + 20)
     366#define HDA_RMX_SD3FIFOW            (HDA_STREAM_RMX_DEF(FIFOW, 0) + 30)
     367#define HDA_RMX_SD4FIFOW            (HDA_STREAM_RMX_DEF(FIFOW, 0) + 40)
     368#define HDA_RMX_SD5FIFOW            (HDA_STREAM_RMX_DEF(FIFOW, 0) + 50)
     369#define HDA_RMX_SD6FIFOW            (HDA_STREAM_RMX_DEF(FIFOW, 0) + 60)
     370#define HDA_RMX_SD7FIFOW            (HDA_STREAM_RMX_DEF(FIFOW, 0) + 70)
     371
     372/*
     373 * ICH6 datasheet defined limits for FIFOW values (18.2.38).
     374 */
     375#define HDA_SDFIFOW_8B              0x2
     376#define HDA_SDFIFOW_16B             0x3
     377#define HDA_SDFIFOW_32B             0x4
     378
     379#define HDA_REG_SD0FIFOS            40 /* 0x90; other streams offset by 0x20 */
     380#define HDA_RMX_SD0FIFOS            38
     381#define HDA_RMX_SD1FIFOS            (HDA_STREAM_RMX_DEF(FIFOS, 0) + 10)
     382#define HDA_RMX_SD2FIFOS            (HDA_STREAM_RMX_DEF(FIFOS, 0) + 20)
     383#define HDA_RMX_SD3FIFOS            (HDA_STREAM_RMX_DEF(FIFOS, 0) + 30)
     384#define HDA_RMX_SD4FIFOS            (HDA_STREAM_RMX_DEF(FIFOS, 0) + 40)
     385#define HDA_RMX_SD5FIFOS            (HDA_STREAM_RMX_DEF(FIFOS, 0) + 50)
     386#define HDA_RMX_SD6FIFOS            (HDA_STREAM_RMX_DEF(FIFOS, 0) + 60)
     387#define HDA_RMX_SD7FIFOS            (HDA_STREAM_RMX_DEF(FIFOS, 0) + 70)
     388
     389#define HDA_SDIFIFO_120B            0x77 /* 8-, 16-, 20-, 24-, 32-bit Input Streams */
     390#define HDA_SDIFIFO_160B            0x9F /* 20-, 24-bit Input Streams Streams */
     391
     392#define HDA_SDOFIFO_16B             0x0F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
     393#define HDA_SDOFIFO_32B             0x1F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
     394#define HDA_SDOFIFO_64B             0x3F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
     395#define HDA_SDOFIFO_128B            0x7F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
     396#define HDA_SDOFIFO_192B            0xBF /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
     397#define HDA_SDOFIFO_256B            0xFF /* 20-, 24-bit Output Streams */
     398
     399#define HDA_REG_SD0FMT              41 /* 0x92; other streams offset by 0x20 */
     400#define HDA_RMX_SD0FMT              39
     401#define HDA_RMX_SD1FMT              (HDA_STREAM_RMX_DEF(FMT, 0) + 10)
     402#define HDA_RMX_SD2FMT              (HDA_STREAM_RMX_DEF(FMT, 0) + 20)
     403#define HDA_RMX_SD3FMT              (HDA_STREAM_RMX_DEF(FMT, 0) + 30)
     404#define HDA_RMX_SD4FMT              (HDA_STREAM_RMX_DEF(FMT, 0) + 40)
     405#define HDA_RMX_SD5FMT              (HDA_STREAM_RMX_DEF(FMT, 0) + 50)
     406#define HDA_RMX_SD6FMT              (HDA_STREAM_RMX_DEF(FMT, 0) + 60)
     407#define HDA_RMX_SD7FMT              (HDA_STREAM_RMX_DEF(FMT, 0) + 70)
     408
     409#define HDA_REG_SD0BDPL             42 /* 0x98; other streams offset by 0x20 */
     410#define HDA_RMX_SD0BDPL             40
     411#define HDA_RMX_SD1BDPL             (HDA_STREAM_RMX_DEF(BDPL, 0) + 10)
     412#define HDA_RMX_SD2BDPL             (HDA_STREAM_RMX_DEF(BDPL, 0) + 20)
     413#define HDA_RMX_SD3BDPL             (HDA_STREAM_RMX_DEF(BDPL, 0) + 30)
     414#define HDA_RMX_SD4BDPL             (HDA_STREAM_RMX_DEF(BDPL, 0) + 40)
     415#define HDA_RMX_SD5BDPL             (HDA_STREAM_RMX_DEF(BDPL, 0) + 50)
     416#define HDA_RMX_SD6BDPL             (HDA_STREAM_RMX_DEF(BDPL, 0) + 60)
     417#define HDA_RMX_SD7BDPL             (HDA_STREAM_RMX_DEF(BDPL, 0) + 70)
     418
     419#define HDA_REG_SD0BDPU             43 /* 0x9C; other streams offset by 0x20 */
     420#define HDA_RMX_SD0BDPU             41
     421#define HDA_RMX_SD1BDPU             (HDA_STREAM_RMX_DEF(BDPU, 0) + 10)
     422#define HDA_RMX_SD2BDPU             (HDA_STREAM_RMX_DEF(BDPU, 0) + 20)
     423#define HDA_RMX_SD3BDPU             (HDA_STREAM_RMX_DEF(BDPU, 0) + 30)
     424#define HDA_RMX_SD4BDPU             (HDA_STREAM_RMX_DEF(BDPU, 0) + 40)
     425#define HDA_RMX_SD5BDPU             (HDA_STREAM_RMX_DEF(BDPU, 0) + 50)
     426#define HDA_RMX_SD6BDPU             (HDA_STREAM_RMX_DEF(BDPU, 0) + 60)
     427#define HDA_RMX_SD7BDPU             (HDA_STREAM_RMX_DEF(BDPU, 0) + 70)
     428
     429#define HDA_CODEC_CAD_SHIFT         28
     430/* Encodes the (required) LUN into a codec command. */
     431#define HDA_CODEC_CMD(cmd, lun)     ((cmd) | (lun << HDA_CODEC_CAD_SHIFT))
    20432
    21433#define HDA_SDFMT_NON_PCM_SHIFT                            15
     
    72484     | ( (_aChan)     & HDA_SDFMT_CHANNELS_MASK))
    73485
    74 #endif /* DEV_HDA_COMMON_H */
    75 
     486/** Interrupt on completion (IOC) flag. */
     487#define HDA_BDLE_FLAG_IOC           RT_BIT(0)
     488
     489/*********************************************************************************************************************************
     490*   Prototypes                                                                                                                 *
     491*********************************************************************************************************************************/
     492
     493/** The HDA controller. */
     494typedef struct HDASTATE *PHDASTATE;
     495/** The HDA stream. */
     496typedef struct HDASTREAM *PHDASTREAM;
     497
     498typedef struct HDAMIXERSINK *PHDAMIXERSINK;
     499
     500
     501/**
     502 * Internal state of a Buffer Descriptor List Entry (BDLE),
     503 * needed to keep track of the data needed for the actual device
     504 * emulation.
     505 */
     506typedef struct HDABDLESTATE
     507{
     508    /** Own index within the BDL (Buffer Descriptor List). */
     509    uint32_t     u32BDLIndex;
     510    /** Number of bytes below the stream's FIFO watermark (SDFIFOW).
     511     *  Used to check if we need fill up the FIFO again. */
     512    uint32_t     cbBelowFIFOW;
     513    /** Current offset in DMA buffer (in bytes).*/
     514    uint32_t     u32BufOff;
     515    uint32_t     Padding;
     516} HDABDLESTATE, *PHDABDLESTATE;
     517
     518/**
     519 * BDL description structure.
     520 * Do not touch this, as this must match to the HDA specs.
     521 */
     522typedef struct HDABDLEDESC
     523{
     524    /** Starting address of the actual buffer. Must be 128-bit aligned. */
     525    uint64_t     u64BufAdr;
     526    /** Size of the actual buffer (in bytes). */
     527    uint32_t     u32BufSize;
     528    /** Bit 0: Interrupt on completion; the controller will generate
     529     *  an interrupt when the last byte of the buffer has been
     530     *  fetched by the DMA engine.
     531     *
     532     *  Rest is reserved for further use and must be 0. */
     533    uint32_t     fFlags;
     534} HDABDLEDESC, *PHDABDLEDESC;
     535
     536/**
     537 * Buffer Descriptor List Entry (BDLE) (3.6.3).
     538 */
     539typedef struct HDABDLE
     540{
     541    /** The actual BDL description. */
     542    HDABDLEDESC  Desc;
     543    /** Internal state of this BDLE.
     544     *  Not part of the actual BDLE registers. */
     545    HDABDLESTATE State;
     546} HDABDLE, *PHDABDLE;
     547
     548/** @name Object lookup functions.
     549 * @{
     550 */
     551PDMAUDIODIR   hdaGetDirFromSD(uint8_t uSD);
     552PHDASTREAM    hdaStreamGetFromSD(PHDASTATE pThis, uint8_t uSD);
     553PHDASTREAM    hdaSinkGetStream(PHDASTATE pThis, PHDAMIXERSINK pSink);
     554/** @} */
     555
     556/** @name Interrupt functions.
     557 * @{
     558 */
     559#ifdef DEBUG
     560int           hdaProcessInterrupt(PHDASTATE pThis, const char *pszSource);
     561#else
     562int           hdaProcessInterrupt(PHDASTATE pThis);
     563#endif
     564/** @} */
     565
     566/** @name Wall clock (WALCLK) functions.
     567 * @{
     568 */
     569uint64_t      hdaWalClkGetCurrent(PHDASTATE pThis);
     570#ifdef IN_RING3
     571bool          hdaWalClkSet(PHDASTATE pThis, uint64_t u64WalClk, bool fForce);
     572#endif
     573/** @} */
     574
     575/** @name DMA utility functions.
     576 * @{
     577 */
     578int           hdaDMARead(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead);
     579int           hdaDMAWrite(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToWrite, uint32_t *pcbWritten);
     580/** @} */
     581
     582/** @name Register functions.
     583 * @{
     584 */
     585uint32_t      hdaGetINTSTS(PHDASTATE pThis);
     586#ifdef IN_RING3
     587int           hdaSDFMTToPCMProps(uint32_t u32SDFMT, PPDMAUDIOPCMPROPS pProps);
     588#endif /* IN_RING3 */
     589/** @} */
     590
     591/** @name BDLE (Buffer Descriptor List Entry) functions.
     592 * @{
     593 */
     594#ifdef IN_RING3
     595int           hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry);
     596bool          hdaBDLEIsComplete(PHDABDLE pBDLE);
     597bool          hdaBDLENeedsInterrupt(PHDABDLE pBDLE);
     598#endif /* IN_RING3 */
     599/** @} */
     600
     601#endif /* DEV_HDA_H_COMMON */
     602
  • trunk/src/VBox/Devices/Audio/HDACodec.h

    r67534 r67899  
    1818#ifndef DEV_HDA_CODEC_H
    1919#define DEV_HDA_CODEC_H
     20
     21#include <iprt/list.h>
     22
     23#include "AudioMixer.h"
    2024
    2125/** The ICH HDA (Intel) controller. */
  • trunk/src/VBox/Devices/Makefile.kmk

    r67699 r67899  
    596596        Audio/DevSB16.cpp \
    597597        Audio/DevHDA.cpp \
     598        Audio/DevHDACommon.cpp \
    598599        Audio/HDACodec.cpp \
     600        Audio/HDAStream.cpp \
    599601        Audio/HDAStreamChannel.cpp \
    600602        Audio/HDAStreamMap.cpp \
Note: See TracChangeset for help on using the changeset viewer.

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