Changeset 70435 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Jan 2, 2018 4:21:53 PM (7 years ago)
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevHDA.cpp
r70433 r70435 1560 1560 pStream->State.tsTransferNext = tsNow + cTicksToNext; 1561 1561 1562 Assert(pStream->State.cTransferPendingInterrupts);1563 1562 if (pStream->State.cTransferPendingInterrupts) 1564 1563 pStream->State.cTransferPendingInterrupts--; -
trunk/src/VBox/Devices/Audio/HDAStream.cpp
r70321 r70435 243 243 pThis->u16TimerHz, pStream->State.Cfg.Props.uHz)); 244 244 245 /* Figure out how many transfer fragments we're going to use for this stream. */ 245 246 /** @todo Use a more dynamic fragment size? */ 246 247 Assert(pStream->u16LVI <= UINT8_MAX - 1); … … 249 250 cFragments = 2; /* At least two fragments (BDLEs) must be present. */ 250 251 251 /* Calculate the fragment size the guest OS expects interrupt delivery at. */252 pStream->State.cbTransferSize = pStream->u32CBL / cFragments;253 Assert(pStream->State.cbTransferSize);254 Assert(pStream->State.cbTransferSize % pStream->State.cbFrameSize == 0);255 256 /* Calculate the bytes we need to transfer to / from the stream's DMA per iteration.257 * This is bound to the device's Hz rate and thus to the (virtual) timing the device expects. */258 pStream->State.cbTransferChunk = (pStream->State.Cfg.Props.uHz / pThis->u16TimerHz) * pStream->State.cbFrameSize;259 Assert(pStream->State.cbTransferChunk);260 Assert(pStream->State.cbTransferChunk % pStream->State.cbFrameSize == 0);261 262 /* Make sure that the transfer chunk does not exceed the overall transfer size. */263 if (pStream->State.cbTransferChunk > pStream->State.cbTransferSize)264 pStream->State.cbTransferChunk = pStream->State.cbTransferSize;265 266 pStream->State.cbTransferProcessed = 0;267 pStream->State.cTransferPendingInterrupts = 0;268 269 const uint64_t cTicksPerHz = TMTimerGetFreq(pThis->pTimer) / pThis->u16TimerHz;270 271 /* Calculate the timer ticks per byte for this stream. */272 pStream->State.cTicksPerByte = cTicksPerHz / pStream->State.cbTransferChunk;273 Assert(pStream->State.cTicksPerByte);274 275 /* Calculate timer ticks per transfer. */276 pStream->State.cTransferTicks = pStream->State.cbTransferChunk * pStream->State.cTicksPerByte;277 278 /* Initialize the transfer timestamps. */279 pStream->State.tsTransferLast = 0;280 pStream->State.tsTransferNext = 0;281 282 LogFunc(("[SD%RU8] Timer %uHz (%RU64 ticks per Hz), cTicksPerByte=%RU64, cbTransferChunk=%RU32, cTransferTicks=%RU64, " \283 "cbTransferSize=%RU32\n",284 pStream->u8SD, pThis->u16TimerHz, cTicksPerHz, pStream->State.cTicksPerByte,285 pStream->State.cbTransferChunk, pStream->State.cTransferTicks, pStream->State.cbTransferSize));286 252 /* 287 253 * Handle the stream's position adjustment. … … 289 255 uint32_t cfPosAdjust = 0; 290 256 257 LogFunc(("[SD%RU8] fPosAdjustEnabled=%RTbool, cPosAdjustFrames=%RU16\n", 258 pStream->u8SD, pThis->fPosAdjustEnabled, pThis->cPosAdjustFrames)); 259 291 260 if (pThis->fPosAdjustEnabled) /* Is the position adjustment enabled at all? */ 292 261 { 262 HDABDLE BDLE; 263 RT_ZERO(BDLE); 264 265 Assert(pStream->u64BDLBase); 266 267 int rc2 = hdaBDLEFetch(pThis, &BDLE, pStream->u64BDLBase, 0 /* Entry */); 268 AssertRC(rc2); 269 270 Assert(BDLE.Desc.u32BufSize % pStream->State.cbFrameSize == 0); 271 293 272 /* If no custom set position adjustment is set, apply some 294 273 * simple heuristics to detect the appropriate position adjustment. */ 295 if ( pStream->u64BDLBase 296 && !pThis->cPosAdjustFrames) 274 if ( !pThis->cPosAdjustFrames 275 /* Position adjustmenet buffer *must* have the IOC bit set! */ 276 && hdaBDLENeedsInterrupt(&BDLE)) 297 277 { 298 HDABDLE BDLE;299 int rc2 = hdaBDLEFetch(pThis, &BDLE, pStream->u64BDLBase, 0 /* Entry */);300 AssertRC(rc2);301 302 278 /** @todo Implement / use a (dynamic) table once this gets more complicated. */ 303 304 279 #ifdef VBOX_WITH_INTEL_HDA 305 280 /* Intel ICH / PCH: 1 frame. */ … … 313 288 cfPosAdjust = 32; 314 289 } 315 else316 290 #endif 317 cfPosAdjust = pThis->cPosAdjustFrames;318 291 } 319 292 else /* Go with the set default. */ … … 322 295 if (cfPosAdjust) 323 296 { 297 /* Also adjust the number of fragments, as the position adjustment buffer 298 * does not count as an own fragment as such. 299 * 300 * This e.g. can happen on (newer) Ubuntu guests which use 301 * 4 (IOC) + 4408 (IOC) + 4408 (IOC) + 4408 (IOC) + 4404 (= 17632) bytes, 302 * where the first buffer (4) is used as position adjustment. 303 * 304 * Only skip a fragment if the whole buffer fragment is used for 305 * position adjustment. 306 */ 307 if ( (cfPosAdjust * pStream->State.cbFrameSize) == BDLE.Desc.u32BufSize 308 && cFragments) 309 { 310 cFragments--; 311 } 312 324 313 /* Initialize position adjustment counter. */ 325 314 pStream->State.cPosAdjustFramesLeft = cfPosAdjust; … … 328 317 } 329 318 330 LogFunc(("[SD%RU8] cfPosAdjust=%RU32\n", pStream->u8SD, cfPosAdjust)); 319 LogFunc(("[SD%RU8] cfPosAdjust=%RU32, cFragments=%RU8\n", pStream->u8SD, cfPosAdjust, cFragments)); 320 321 /* 322 * Set up data transfer transfer stuff. 323 */ 324 325 /* Calculate the fragment size the guest OS expects interrupt delivery at. */ 326 pStream->State.cbTransferSize = pStream->u32CBL / cFragments; 327 Assert(pStream->State.cbTransferSize); 328 Assert(pStream->State.cbTransferSize % pStream->State.cbFrameSize == 0); 329 330 /* Calculate the bytes we need to transfer to / from the stream's DMA per iteration. 331 * This is bound to the device's Hz rate and thus to the (virtual) timing the device expects. */ 332 pStream->State.cbTransferChunk = (pStream->State.Cfg.Props.uHz / pThis->u16TimerHz) * pStream->State.cbFrameSize; 333 Assert(pStream->State.cbTransferChunk); 334 Assert(pStream->State.cbTransferChunk % pStream->State.cbFrameSize == 0); 335 336 /* Make sure that the transfer chunk does not exceed the overall transfer size. */ 337 if (pStream->State.cbTransferChunk > pStream->State.cbTransferSize) 338 pStream->State.cbTransferChunk = pStream->State.cbTransferSize; 339 340 pStream->State.cbTransferProcessed = 0; 341 pStream->State.cTransferPendingInterrupts = 0; 342 343 const uint64_t cTicksPerHz = TMTimerGetFreq(pThis->pTimer) / pThis->u16TimerHz; 344 345 /* Calculate the timer ticks per byte for this stream. */ 346 pStream->State.cTicksPerByte = cTicksPerHz / pStream->State.cbTransferChunk; 347 Assert(pStream->State.cTicksPerByte); 348 349 /* Calculate timer ticks per transfer. */ 350 pStream->State.cTransferTicks = pStream->State.cbTransferChunk * pStream->State.cTicksPerByte; 351 352 /* Initialize the transfer timestamps. */ 353 pStream->State.tsTransferLast = 0; 354 pStream->State.tsTransferNext = 0; 355 356 LogFunc(("[SD%RU8] Timer %uHz (%RU64 ticks per Hz), cTicksPerByte=%RU64, cbTransferChunk=%RU32, cTransferTicks=%RU64, " \ 357 "cbTransferSize=%RU32\n", 358 pStream->u8SD, pThis->u16TimerHz, cTicksPerHz, pStream->State.cTicksPerByte, 359 pStream->State.cbTransferChunk, pStream->State.cTransferTicks, pStream->State.cbTransferSize)); 331 360 332 361 /* Make sure to also update the stream's DMA counter (based on its current LPIB value). */
Note:
See TracChangeset
for help on using the changeset viewer.