Changeset 55009 in vbox for trunk/src/VBox
- Timestamp:
- Mar 30, 2015 3:33:15 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevSB16.cpp
r55005 r55009 3 3 * DevSB16 - VBox SB16 Audio Controller. 4 4 * 5 * (r3917 sb16.c)6 *7 5 * @todo hiccups on NT4 and Win98. 8 6 */ 9 7 10 8 /* 9 * Copyright (C) 2015 Oracle Corporation 10 * 11 * This file is part of VirtualBox Open Source Edition (OSE), as 12 * available from http://www.virtualbox.org. This file is free software; 13 * you can redistribute it and/or modify it under the terms of the GNU 14 * General Public License (GPL) as published by the Free Software 15 * Foundation, in version 2 as it comes in the "COPYING" file of the 16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 18 * -------------------------------------------------------------------- 19 * 20 * This code is based on: sb16.c from QEMU AUDIO subsystem (r3917). 11 21 * QEMU Soundblaster 16 emulation 12 22 * … … 32 42 */ 33 43 34 #define LOG_GROUP LOG_GROUP_DEV_AUDIO 44 #include <iprt/assert.h> 45 #ifdef IN_RING3 46 # include <iprt/mem.h> 47 # include <iprt/string.h> 48 # include <iprt/uuid.h> 49 #endif 50 35 51 #include <VBox/vmm/pdmdev.h> 36 52 #include <VBox/vmm/pdmaudioifs.h> 37 #include <iprt/assert.h> 38 #include <iprt/string.h> 39 #include <iprt/uuid.h> 53 40 54 #include "vl_vbox.h" 55 56 #ifdef LOG_GROUP 57 #undef LOG_GROUP 58 #endif 59 #define LOG_GROUP LOG_GROUP_DEV_AUDIO 60 #include <VBox/log.h> 41 61 42 62 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER … … 169 189 int use_hdma; 170 190 int highspeed; 171 int can_write; 191 int can_write; /** @Todo Value never gets 0? */ 172 192 173 193 int v2x6; … … 196 216 197 217 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 198 R3PTRTYPE(PPDMAUDIOGSTSTRMOUT) pGstStrmOut;199 /** List of associated LUN drivers. */200 218 RTLISTANCHOR lstDrv; 201 219 /** The device' software mixer. */ … … 203 221 /** Audio sink for PCM output. */ 204 222 R3PTRTYPE(PAUDMIXSINK) pSinkOutput; 223 /** The emulation timer for handling I/O of the attached LUN drivers. */ 224 PTMTIMERR3 pTimerIO; 225 /** Timer ticks for handling the LUN drivers. */ 226 uint64_t uTicksIO; 205 227 #else 206 228 SWVoiceOut *voice; 207 229 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 208 230 209 PTMTIMER pTimer ;231 PTMTIMER pTimerIRQ; 210 232 PPDMIBASE pDrvBase; 211 233 /** LUN\#0: Base interface. */ … … 218 240 219 241 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 242 static int sb16OpenOut(PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg); 243 #endif 244 245 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 246 /** 247 * Attach command. 248 * 249 * This is called to let the device attach to a driver for a specified LUN 250 * during runtime. This is not called during VM construction, the device 251 * constructor have to attach to all the available drivers. 252 * 253 * @returns VBox status code. 254 * @param pDevIns The device instance. 255 * @param uLUN The logical unit which is being detached. 256 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines. 257 */ 258 static DECLCALLBACK(int) sb16Attach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags) 259 { 260 PSB16STATE pThis = PDMINS_2_DATA(pDevIns, PSB16STATE); 261 262 AssertMsgReturn(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG, 263 ("AC'97 device does not support hotplugging\n"), 264 VERR_INVALID_PARAMETER); 265 266 /* 267 * Attach driver. 268 */ 269 char *pszDesc = NULL; 270 if (RTStrAPrintf(&pszDesc, "Audio driver port (SB16) for LUN #%u", uLUN) <= 0) 271 AssertMsgReturn(pszDesc, 272 ("Not enough memory for SB16 driver port description of LUN #%u\n", uLUN), 273 VERR_NO_MEMORY); 274 275 int rc = PDMDevHlpDriverAttach(pDevIns, uLUN, 276 &pThis->IBase, &pThis->pDrvBase, pszDesc); 277 if (RT_SUCCESS(rc)) 278 { 279 PSB16DRIVER pDrv = (PSB16DRIVER)RTMemAllocZ(sizeof(SB16DRIVER)); 280 if (pDrv) 281 { 282 pDrv->pConnector = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIAUDIOCONNECTOR); 283 AssertMsg(pDrv->pConnector != NULL, 284 ("Configuration error: LUN #%u has no host audio interface, rc=%Rrc\n", 285 uLUN, rc)); 286 pDrv->pSB16State = pThis; 287 pDrv->uLUN = uLUN; 288 289 /* 290 * For now we always set the driver at LUN 0 as our primary 291 * host backend. This might change in the future. 292 */ 293 if (pDrv->uLUN == 0) 294 pDrv->Flags |= PDMAUDIODRVFLAG_PRIMARY; 295 296 LogFunc(("LUN#%RU8: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->Flags)); 297 298 /* Attach to driver list. */ 299 RTListAppend(&pThis->lstDrv, &pDrv->Node); 300 } 301 else 302 rc = VERR_NO_MEMORY; 303 } 304 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER) 305 { 306 LogFunc(("No attached driver for LUN #%u\n", uLUN)); 307 } 308 else if (RT_FAILURE(rc)) 309 AssertMsgFailed(("Failed to attach SB16 LUN #%u (\"%s\"), rc=%Rrc\n", 310 uLUN, pszDesc, rc)); 311 312 RTStrFree(pszDesc); 313 314 LogFunc(("iLUN=%u, fFlags=0x%x, rc=%Rrc\n", uLUN, fFlags, rc)); 315 return rc; 316 } 317 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 318 319 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 220 320 static void sb16AudioCallback(void *pvContext, uint32_t cbFree); 221 321 #else … … 225 325 static int magic_of_irq (int irq) 226 326 { 227 switch (irq) { 228 case 5: 229 return 2; 230 case 7: 231 return 4; 232 case 9: 233 return 1; 234 case 10: 235 return 8; 236 default: 237 LogFlowFunc(("bad irq %d\n", irq)); 238 return 2; 239 } 327 switch (irq) 328 { 329 case 5: 330 return 2; 331 case 7: 332 return 4; 333 case 9: 334 return 1; 335 case 10: 336 return 8; 337 default: 338 break; 339 } 340 341 LogFlowFunc(("bad irq %d\n", irq)); 342 return 2; 240 343 } 241 344 242 345 static int irq_of_magic (int magic) 243 346 { 244 switch (magic) { 245 case 1: 246 return 9; 247 case 2: 248 return 5; 249 case 4: 250 return 7; 251 case 8: 252 return 10; 253 default: 254 LogFlowFunc(("bad irq magic %d\n", magic)); 255 return -1; 256 } 347 switch (magic) 348 { 349 case 1: 350 return 9; 351 case 2: 352 return 5; 353 case 4: 354 return 7; 355 case 8: 356 return 10; 357 default: 358 break; 359 } 360 361 LogFlowFunc(("bad irq magic %d\n", magic)); 362 return -1; 257 363 } 258 364 259 365 #if 0 260 static void log_dsp ( SB16State *dsp)366 static void log_dsp (PSB16STATE dsp) 261 367 { 262 368 ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n", … … 272 378 #endif 273 379 274 static void s peaker(PSB16STATE pThis, int on)380 static void sb16SpeakerControl(PSB16STATE pThis, int on) 275 381 { 276 382 pThis->speaker = on; … … 278 384 } 279 385 280 static void control(PSB16STATE pThis, int hold)386 static void sb16Control(PSB16STATE pThis, int hold) 281 387 { 282 388 int dma = pThis->use_hdma ? pThis->hdma : pThis->dma; … … 295 401 } 296 402 #else /* VBOX */ 403 # ifdef VBOX_WITH_PDM_AUDIO_DRIVER 404 PSB16DRIVER pDrv; 405 # endif 297 406 if (hold) 298 407 { 299 408 PDMDevHlpDMASetDREQ (pThis->pDevIns, dma, 1); 300 409 PDMDevHlpDMASchedule (pThis->pDevIns); 301 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 302 pThis->pDrv->pfnEnableOut(pThis->pDrv, pThis->pGstStrmOut, true /* fEnable */); 303 #else 410 # ifdef VBOX_WITH_PDM_AUDIO_DRIVER 411 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 412 pDrv->pConnector->pfnEnableOut(pDrv->pConnector, 413 pDrv->Out.pStrmOut, true /* fEnable */); 414 # else 304 415 AUD_set_active_out (pThis->voice, 1); 305 # endif416 # endif 306 417 } 307 418 else 308 419 { 309 420 PDMDevHlpDMASetDREQ (pThis->pDevIns, dma, 0); 310 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 311 pThis->pDrv->pfnEnableOut(pThis->pDrv, pThis->pGstStrmOut, false /* fEnable */); 312 #else 421 # ifdef VBOX_WITH_PDM_AUDIO_DRIVER 422 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 423 pDrv->pConnector->pfnEnableOut(pDrv->pConnector, 424 pDrv->Out.pStrmOut, false /* fEnable */); 425 # else 313 426 AUD_set_active_out (pThis->voice, 0); 314 # endif427 # endif 315 428 } 316 429 #endif /* VBOX */ … … 325 438 } 326 439 #else /* VBOX */ 327 static DECLCALLBACK(void) sb16Timer (PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvThis)328 { 329 PSB16STATE pThis = ( SB16STATE *)pvThis;440 static DECLCALLBACK(void) sb16TimerIRQ(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvThis) 441 { 442 PSB16STATE pThis = (PSB16STATE)pvThis; 330 443 pThis->can_write = 1; 331 444 PDMDevHlpISASetIrq(pThis->pDevIns, pThis->irq, 1); … … 336 449 #define DMA8_HIGH 2 337 450 338 static void continue_dma8 451 static void continue_dma8(PSB16STATE pThis) 339 452 { 340 453 if (pThis->freq > 0) … … 343 456 344 457 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 345 PDMAUDIOSTREAMCFG as;346 as.uHz = pThis->freq;347 as.cChannels = 1 << pThis->fmt_stereo;348 as.enmFormat = pThis->fmt;349 as.enmEndianness = PDMAUDIOHOSTENDIANESS;350 351 int rc = pThis->pDrv->pfnOpenOut(pThis->pDrv, "sb16.out", &as, &pThis->pGstStrmOut);458 PDMAUDIOSTREAMCFG streamCfg; 459 streamCfg.uHz = pThis->freq; 460 streamCfg.cChannels = 1 << pThis->fmt_stereo; 461 streamCfg.enmFormat = pThis->fmt; 462 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANESS; 463 464 int rc = sb16OpenOut(pThis, &streamCfg); 352 465 AssertRC(rc); 353 466 #else 354 audsettings_t as;355 as.freq = pThis->freq;356 as.nchannels = 1 << pThis->fmt_stereo;357 as.fmt = pThis->fmt;358 as.endianness = 0;467 audsettings_t streamCfg; 468 streamCfg.freq = pThis->freq; 469 streamCfg.nchannels = 1 << pThis->fmt_stereo; 470 streamCfg.fmt = pThis->fmt; 471 streamCfg.endianness = 0; 359 472 pThis->voice = AUD_open_out ( 360 473 &pThis->card, … … 363 476 pThis, 364 477 sb16AudioCallback, 365 & as478 &streamCfg 366 479 ); 367 480 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 368 481 } 369 482 370 control(pThis, 1);371 } 372 373 static void dma_cmd8 374 { 375 pThis->fmt = AUD_FMT_U8;376 pThis->use_hdma = 0;377 pThis->fmt_bits = 8;483 sb16Control(pThis, 1); 484 } 485 486 static void dma_cmd8(PSB16STATE pThis, int mask, int dma_len) 487 { 488 pThis->fmt = AUD_FMT_U8; 489 pThis->use_hdma = 0; 490 pThis->fmt_bits = 8; 378 491 pThis->fmt_signed = 0; 379 492 pThis->fmt_stereo = (pThis->mixer_regs[0x0e] & 2) != 0; 380 if (-1 == pThis->time_const) { 493 494 if (-1 == pThis->time_const) 495 { 381 496 if (pThis->freq <= 0) 382 497 pThis->freq = 11025; 383 498 } 384 else { 499 else 500 { 385 501 int tmp = (256 - pThis->time_const); 386 502 pThis->freq = (1000000 + (tmp / 2)) / tmp; 387 503 } 388 504 389 if (dma_len != -1) { 505 if (dma_len != -1) 506 { 390 507 pThis->block_size = dma_len << pThis->fmt_stereo; 391 508 } 392 else { 509 else 510 { 393 511 /* This is apparently the only way to make both Act1/PL 394 512 and SecondReality/FC work … … 421 539 422 540 continue_dma8 (pThis); 423 s peaker(pThis, 1);541 sb16SpeakerControl(pThis, 1); 424 542 } 425 543 426 544 static void dma_cmd (PSB16STATE pThis, uint8_t cmd, uint8_t d0, int dma_len) 427 545 { 428 pThis->use_hdma = cmd < 0xc0;429 pThis->fifo = (cmd >> 1) & 1;430 pThis->dma_auto = (cmd >> 2) & 1;546 pThis->use_hdma = cmd < 0xc0; 547 pThis->fifo = (cmd >> 1) & 1; 548 pThis->dma_auto = (cmd >> 2) & 1; 431 549 pThis->fmt_signed = (d0 >> 4) & 1; 432 550 pThis->fmt_stereo = (d0 >> 5) & 1; 433 551 434 switch (cmd >> 4) { 435 case 11: 436 pThis->fmt_bits = 16; 437 break; 438 439 case 12: 440 pThis->fmt_bits = 8; 441 break; 442 } 443 444 if (-1 != pThis->time_const) { 552 switch (cmd >> 4) 553 { 554 case 11: 555 pThis->fmt_bits = 16; 556 break; 557 558 case 12: 559 pThis->fmt_bits = 8; 560 break; 561 } 562 563 if (-1 != pThis->time_const) 564 { 445 565 #if 1 446 566 int tmp = 256 - pThis->time_const; … … 455 575 pThis->block_size = dma_len + 1; 456 576 pThis->block_size <<= ((pThis->fmt_bits == 16) ? 1 : 0); 457 if (!pThis->dma_auto) { 577 if (!pThis->dma_auto) 578 { 458 579 /* It is clear that for DOOM and auto-init this value 459 580 shouldn't take stereo into account, while Miles Sound Systems … … 463 584 } 464 585 465 LogFlowFunc(("freq %d, stereo %d, sign %d, bits %d, " 466 "dma %d, auto %d, fifo %d, high %d\n", 467 pThis->freq, pThis->fmt_stereo, pThis->fmt_signed, pThis->fmt_bits, 468 pThis->block_size, pThis->dma_auto, pThis->fifo, pThis->highspeed)); 469 470 if (16 == pThis->fmt_bits) { 471 if (pThis->fmt_signed) { 472 pThis->fmt = AUD_FMT_S16; 473 } 474 else { 475 pThis->fmt = AUD_FMT_U16; 476 } 477 } 478 else { 479 if (pThis->fmt_signed) { 480 pThis->fmt = AUD_FMT_S8; 481 } 482 else { 483 pThis->fmt = AUD_FMT_U8; 484 } 485 } 586 LogFlowFunc(("freq %d, stereo %d, sign %d, bits %d, dma %d, auto %d, fifo %d, high %d\n", 587 pThis->freq, pThis->fmt_stereo, pThis->fmt_signed, pThis->fmt_bits, 588 pThis->block_size, pThis->dma_auto, pThis->fifo, pThis->highspeed)); 589 590 if (16 == pThis->fmt_bits) 591 pThis->fmt = pThis->fmt_signed ? AUD_FMT_S16 : AUD_FMT_U16; 592 else 593 pThis->fmt = pThis->fmt_signed ? AUD_FMT_S8 : AUD_FMT_U8; 486 594 487 595 pThis->left_till_irq = pThis->block_size; … … 490 598 pThis->highspeed = 0; 491 599 pThis->align = (1 << (pThis->fmt_stereo + (pThis->fmt_bits == 16))) - 1; 492 if (pThis->block_size & pThis->align) { 600 if (pThis->block_size & pThis->align) 601 { 493 602 LogFlowFunc(("warning: misaligned block size %d, alignment %d\n", 494 pThis->block_size, pThis->align + 1));603 pThis->block_size, pThis->align + 1)); 495 604 } 496 605 … … 500 609 501 610 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 502 PDMAUDIOSTREAMCFG as;503 as.uHz = pThis->freq;504 as.cChannels = 1 << pThis->fmt_stereo;505 as.enmFormat = pThis->fmt;506 as.enmEndianness = PDMAUDIOHOSTENDIANESS;507 508 int rc = pThis->pDrv->pfnOpenOut(pThis->pDrv, "sb16.out", &as, &pThis->pGstStrmOut);611 PDMAUDIOSTREAMCFG streamCfg; 612 streamCfg.uHz = pThis->freq; 613 streamCfg.cChannels = 1 << pThis->fmt_stereo; 614 streamCfg.enmFormat = pThis->fmt; 615 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANESS; 616 617 int rc = sb16OpenOut(pThis, &streamCfg); 509 618 AssertRC(rc); 510 619 #else 511 audsettings_t as;512 as.freq = pThis->freq;513 as.nchannels = 1 << pThis->fmt_stereo;514 as.fmt = pThis->fmt;515 as.endianness = 0;620 audsettings_t streamCfg; 621 streamCfg.freq = pThis->freq; 622 streamCfg.nchannels = 1 << pThis->fmt_stereo; 623 streamCfg.fmt = pThis->fmt; 624 streamCfg.endianness = 0; 516 625 pThis->voice = AUD_open_out ( 517 626 &pThis->card, … … 520 629 pThis, 521 630 sb16AudioCallback, 522 & as631 &streamCfg 523 632 ); 524 633 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 525 634 } 526 635 527 control(pThis, 1);528 s peaker(pThis, 1);636 sb16Control(pThis, 1); 637 sb16SpeakerControl(pThis, 1); 529 638 } 530 639 … … 684 793 case 0x90: 685 794 case 0x91: 686 dma_cmd8 795 dma_cmd8(pThis, (((cmd & 1) == 0) ? 1 : 0) | DMA8_HIGH, -1); 687 796 break; 688 797 689 798 case 0xd0: /* halt DMA operation. 8bit */ 690 control(pThis, 0);799 sb16Control(pThis, 0); 691 800 break; 692 801 693 802 case 0xd1: /* speaker on */ 694 s peaker(pThis, 1);803 sb16SpeakerControl(pThis, 1); 695 804 break; 696 805 697 806 case 0xd3: /* speaker off */ 698 s peaker(pThis, 0);807 sb16SpeakerControl(pThis, 0); 699 808 break; 700 809 … … 706 815 707 816 case 0xd5: /* halt DMA operation. 16bit */ 708 control(pThis, 0);817 sb16Control(pThis, 0); 709 818 break; 710 819 711 820 case 0xd6: /* continue DMA operation. 16bit */ 712 control(pThis, 1);821 sb16Control(pThis, 1); 713 822 break; 714 823 … … 891 1000 892 1001 case 0x14: 893 dma_cmd8 1002 dma_cmd8(pThis, 0, dsp_get_lohi (pThis) + 1); 894 1003 break; 895 1004 … … 943 1052 LogFlowFunc(("mix silence %d %d %" PRId64 "\n", samples, bytes, ticks)); 944 1053 #else /* VBOX */ 945 ticks = (bytes * TMTimerGetFreq(pThis->pTimer )) / freq;946 if (ticks < TMTimerGetFreq(pThis->pTimer ) / 1024)1054 ticks = (bytes * TMTimerGetFreq(pThis->pTimerIRQ)) / freq; 1055 if (ticks < TMTimerGetFreq(pThis->pTimerIRQ) / 1024) 947 1056 PDMDevHlpISASetIrq(pThis->pDevIns, pThis->irq, 1); 948 1057 else 949 TMTimerSet(pThis->pTimer , TMTimerGet(pThis->pTimer) + ticks);1058 TMTimerSet(pThis->pTimerIRQ, TMTimerGet(pThis->pTimerIRQ) + ticks); 950 1059 LogFlowFunc(("mix silence %d %d % %RU64\n", samples, bytes, ticks)); 951 1060 #endif /* VBOX */ … … 1002 1111 } 1003 1112 1004 static void legacy_reset 1005 { 1006 pThis->freq = 11025;1113 static void legacy_reset(PSB16STATE pThis) 1114 { 1115 pThis->freq = 11025; 1007 1116 pThis->fmt_signed = 0; 1008 pThis->fmt_bits = 8;1117 pThis->fmt_bits = 8; 1009 1118 pThis->fmt_stereo = 0; 1010 1119 1011 1120 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1012 PDMAUDIOSTREAMCFG as;1013 as.uHz = pThis->freq;1014 as.cChannels = 1;1015 as.enmFormat = AUD_FMT_U8;1016 as.enmEndianness = PDMAUDIOHOSTENDIANESS;1017 1018 int rc = pThis->pDrv->pfnOpenOut(pThis->pDrv, "sb16.out", &as, &pThis->pGstStrmOut);1121 PDMAUDIOSTREAMCFG streamCfg; 1122 streamCfg.uHz = pThis->freq; 1123 streamCfg.cChannels = 1; /* Mono */ 1124 streamCfg.enmFormat = AUD_FMT_U8; 1125 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANESS; 1126 1127 int rc = sb16OpenOut(pThis, &streamCfg); 1019 1128 AssertRC(rc); 1020 1129 #else 1021 audsettings_t as;1022 as.freq = pThis->freq;1023 as.nchannels = 1;1024 as.fmt = AUD_FMT_U8;1025 as.endianness = 0;1130 audsettings_t streamCfg; 1131 streamCfg.freq = pThis->freq; 1132 streamCfg.nchannels = 1; 1133 streamCfg.fmt = AUD_FMT_U8; 1134 streamCfg.endianness = 0; 1026 1135 pThis->voice = AUD_open_out ( 1027 1136 &pThis->card, … … 1030 1139 pThis, 1031 1140 sb16AudioCallback, 1032 & as1141 &streamCfg 1033 1142 ); 1034 1143 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ … … 1067 1176 1068 1177 dsp_out_data(pThis, 0xaa); 1069 s peaker(pThis, 0);1070 control(pThis, 0);1178 sb16SpeakerControl(pThis, 0); 1179 sb16Control(pThis, 0); 1071 1180 legacy_reset (pThis); 1072 1181 } … … 1090 1199 PDMDevHlpISASetIrq(pThis->pDevIns, pThis->irq, 0); 1091 1200 #endif 1092 control(pThis, 0);1201 sb16Control(pThis, 0); 1093 1202 } 1094 1203 else { … … 1174 1283 #endif 1175 1284 1176 switch (iport) { 1177 case 0x06: /* reset */ 1178 retval = 0xff; 1179 break; 1180 1181 case 0x0a: /* read data */ 1182 if (pThis->out_data_len) { 1183 retval = pThis->out_data[--pThis->out_data_len]; 1184 pThis->last_read_byte = retval; 1185 } 1186 else { 1187 if (pThis->cmd != -1) { 1188 LogFlowFunc(("empty output buffer for command %#x\n", 1189 pThis->cmd)); 1285 switch (iport) 1286 { 1287 case 0x06: /* reset */ 1288 retval = 0xff; 1289 break; 1290 1291 case 0x0a: /* read data */ 1292 if (pThis->out_data_len) 1293 { 1294 retval = pThis->out_data[--pThis->out_data_len]; 1295 pThis->last_read_byte = retval; 1190 1296 } 1191 retval = pThis->last_read_byte; 1192 /* goto error; */ 1193 } 1194 break; 1195 1196 case 0x0c: /* 0 can write */ 1197 retval = pThis->can_write ? 0 : 0x80; 1198 break; 1199 1200 case 0x0d: /* timer interrupt clear */ 1201 /* LogFlowFunc(("timer interrupt clear\n")); */ 1202 retval = 0; 1203 break; 1204 1205 case 0x0e: /* data available status | irq 8 ack */ 1206 retval = (!pThis->out_data_len || pThis->highspeed) ? 0 : 0x80; 1207 if (pThis->mixer_regs[0x82] & 1) { 1208 ack = 1; 1209 pThis->mixer_regs[0x82] &= ~1; 1297 else 1298 { 1299 if (pThis->cmd != -1) 1300 LogFlowFunc(("empty output buffer for command %#x\n", pThis->cmd)); 1301 retval = pThis->last_read_byte; 1302 /* goto error; */ 1303 } 1304 break; 1305 1306 case 0x0c: /* 0 can write */ 1307 retval = pThis->can_write ? 0 : 0x80; 1308 break; 1309 1310 case 0x0d: /* timer interrupt clear */ 1311 /* LogFlowFunc(("timer interrupt clear\n")); */ 1312 retval = 0; 1313 break; 1314 1315 case 0x0e: /* data available status | irq 8 ack */ 1316 retval = (!pThis->out_data_len || pThis->highspeed) ? 0 : 0x80; 1317 if (pThis->mixer_regs[0x82] & 1) 1318 { 1319 ack = 1; 1320 pThis->mixer_regs[0x82] &= ~1; 1210 1321 #ifndef VBOX 1211 qemu_irq_lower (pThis->pic[pThis->irq]); 1212 #else 1213 PDMDevHlpISASetIrq(pThis->pDevIns, pThis->irq, 0); 1214 #endif 1215 } 1216 break; 1217 1218 case 0x0f: /* irq 16 ack */ 1219 retval = 0xff; 1220 if (pThis->mixer_regs[0x82] & 2) { 1221 ack = 1; 1222 pThis->mixer_regs[0x82] &= ~2; 1322 qemu_irq_lower (pThis->pic[pThis->irq]); 1323 #else 1324 PDMDevHlpISASetIrq(pThis->pDevIns, pThis->irq, 0); 1325 #endif 1326 } 1327 break; 1328 1329 case 0x0f: /* irq 16 ack */ 1330 retval = 0xff; 1331 if (pThis->mixer_regs[0x82] & 2) 1332 { 1333 ack = 1; 1334 pThis->mixer_regs[0x82] &= ~2; 1223 1335 #ifndef VBOX 1224 qemu_irq_lower (pThis->pic[pThis->irq]);1225 #else 1226 PDMDevHlpISASetIrq(pThis->pDevIns, pThis->irq, 0);1227 #endif 1228 }1229 break;1230 1231 default:1232 goto error;1233 } 1234 1235 if (!ack) {1336 qemu_irq_lower (pThis->pic[pThis->irq]); 1337 #else 1338 PDMDevHlpISASetIrq(pThis->pDevIns, pThis->irq, 0); 1339 #endif 1340 } 1341 break; 1342 1343 default: 1344 goto error; 1345 } 1346 1347 if (!ack) 1236 1348 LogFlowFunc(("read %#x -> %#x\n", nport, retval)); 1237 }1238 1349 1239 1350 #ifndef VBOX … … 1253 1364 } 1254 1365 1255 static void reset_mixer (PSB16STATE pThis) 1256 { 1257 int i; 1366 static void sb16MixerReset(PSB16STATE pThis) 1367 { 1368 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1369 PSB16DRIVER pDrv; 1370 1371 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 1372 pDrv->Out.phStrmOut = NULL; 1373 1374 pThis->pSinkOutput = NULL; 1375 1376 if (pThis->pMixer) 1377 { 1378 audioMixerDestroy(pThis->pMixer); 1379 pThis->pMixer = NULL; 1380 } 1381 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 1258 1382 1259 1383 memset (pThis->mixer_regs, 0xff, 0x7f); … … 1278 1402 pThis->mixer_regs[0x26] = (4 << 5) | (4 << 1); 1279 1403 1280 for (i = 0x30; i < 0x48; i++) {1404 for (int i = 0x30; i < 0x48; i++) 1281 1405 pThis->mixer_regs[i] = 0x20; 1282 } 1406 1407 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1408 int rc2 = audioMixerCreate("SB16 Mixer", 0 /* uFlags */, &pThis->pMixer); 1409 if (RT_SUCCESS(rc2)) 1410 { 1411 /* Set a default audio format for our mixer. */ 1412 PDMAUDIOSTREAMCFG streamCfg; 1413 streamCfg.uHz = 41000; 1414 streamCfg.cChannels = 2; 1415 streamCfg.enmFormat = AUD_FMT_S16; 1416 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANESS; 1417 1418 rc2 = audioMixerSetDeviceFormat(pThis->pMixer, &streamCfg); 1419 AssertRC(rc2); 1420 1421 /* Add all required audio sinks. */ 1422 rc2 = audioMixerAddSink(pThis->pMixer, "[Playback] PCM Output", 1423 AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOutput); 1424 AssertRC(rc2); 1425 } 1426 #endif 1283 1427 } 1284 1428 … … 1323 1467 { 1324 1468 case 0x00: 1325 reset_mixer(pThis);1469 sb16MixerReset(pThis); 1326 1470 /* And update the actual volume, too. */ 1327 1471 fUpdateMaster = true; … … 1498 1642 } 1499 1643 1500 static int write_audio (PSB16STATE pThis, int nchan, int dma_pos, 1501 int dma_len, int len) 1502 { 1503 int temp, net; 1504 uint8_t tmpbuf[_4K]; 1505 1506 temp = len; 1507 net = 0; 1508 1509 while (temp) 1510 { 1511 int left = dma_len - dma_pos; 1644 static int sb16WriteAudio(PSB16STATE pThis, int nchan, int dma_pos, 1645 int dma_len, int len) 1646 { 1647 uint8_t tmpbuf[_4K]; /** @todo Have a buffer on the heap. */ 1648 1649 int cbToWrite = len; 1650 int cbWrittenTotal = 0; 1651 1652 while (cbToWrite) 1653 { 1512 1654 #ifndef VBOX 1513 size_t to_copy;1514 int c opied;1515 #else 1516 size_t to_copy;1517 uint32_t copied;1518 #endif 1519 1520 to_copy = RT_MIN(temp, left);1521 if ( to_copy> sizeof(tmpbuf))1522 to_copy= sizeof(tmpbuf);1655 size_t cbToRead; 1656 int cbRead; 1657 #else 1658 uint32_t cbWrittenMin = UINT32_MAX; 1659 size_t cbToRead; 1660 uint32_t cbRead; 1661 #endif 1662 cbToRead = RT_MIN(dma_len - dma_pos, cbToWrite); 1663 if (cbToRead > sizeof(tmpbuf)) 1664 cbToRead = sizeof(tmpbuf); 1523 1665 1524 1666 #ifndef VBOX 1525 copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy); 1526 #else 1527 int rc = PDMDevHlpDMAReadMemory(pThis->pDevIns, nchan, tmpbuf, dma_pos, 1528 to_copy, &copied); 1667 cbRead = DMA_read_memory (nchan, tmpbuf, dma_pos, cbToRead); 1668 #else 1669 int rc = PDMDevHlpDMAReadMemory(pThis->pDevIns, nchan, tmpbuf, dma_pos, cbToRead, &cbRead); 1529 1670 AssertMsgRC (rc, ("DMAReadMemory -> %Rrc\n", rc)); 1530 1671 #endif 1531 1672 1532 1673 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1533 rc = pThis->pDrv->pfnWrite(pThis->pDrv, pThis->pGstStrmOut, tmpbuf, to_copy, &copied); 1534 if (RT_FAILURE(rc)) 1535 break; 1536 #else 1537 copied = AUD_write (pThis->voice, tmpbuf, copied); 1674 uint32_t cbWritten; 1675 1676 /* Just multiplex the output to the connected backends. 1677 * No need to utilize the virtual mixer here (yet). */ 1678 PSB16DRIVER pDrv; 1679 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 1680 { 1681 int rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut, 1682 tmpbuf, cbToRead, &cbWritten); 1683 AssertRCBreak(rc); 1684 if (RT_FAILURE(rc2)) 1685 continue; 1686 1687 cbWrittenMin = RT_MIN(cbWrittenMin, cbWritten); 1688 LogFlowFunc(("\tLUN#%RU8: cbWritten=%RU32, cWrittenMin=%RU32\n", pDrv->uLUN, cbWritten, cbWrittenMin)); 1689 } 1690 #else 1691 cbWrittenMin = AUD_write (pThis->voice, tmpbuf, cbToRead); 1538 1692 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 1539 1693 1540 temp -= copied;1541 dma_pos = (dma_pos + copied) % dma_len;1542 net += copied;1543 1544 if (!c opied)1545 break; 1546 } 1547 1548 return net;1694 cbToWrite -= cbWrittenMin; 1695 dma_pos = (dma_pos + cbWrittenMin) % dma_len; 1696 cbWrittenTotal += cbWrittenMin; 1697 1698 if (!cbRead) 1699 break; 1700 } 1701 1702 return cbWrittenTotal; 1549 1703 } 1550 1704 1551 1705 #ifndef VBOX 1552 static int SB_read_DMA(void *opaque, int nchan, int dma_pos, int dma_len)1553 #else 1554 static DECLCALLBACK(uint32_t) SB_read_DMA(PPDMDEVINS pDevIns, void *opaque, unsigned nchan, uint32_t dma_pos, uint32_t dma_len)1555 #endif 1556 { 1557 PSB16STATE pThis = ( SB16STATE*)opaque;1706 static int sb16DMARead(void *opaque, int nchan, int dma_pos, int dma_len) 1707 #else 1708 static DECLCALLBACK(uint32_t) sb16DMARead(PPDMDEVINS pDevIns, void *opaque, unsigned nchan, uint32_t dma_pos, uint32_t dma_len) 1709 #endif 1710 { 1711 PSB16STATE pThis = (PSB16STATE)opaque; 1558 1712 int till, copy, written, free; 1559 1713 1560 if (pThis->block_size <= 0) { 1714 if (pThis->block_size <= 0) 1715 { 1561 1716 LogFlowFunc(("invalid block size=%d nchan=%d dma_pos=%d dma_len=%d\n", 1562 1717 pThis->block_size, nchan, dma_pos, dma_len)); … … 1564 1719 } 1565 1720 1566 if (pThis->left_till_irq < 0) {1721 if (pThis->left_till_irq < 0) 1567 1722 pThis->left_till_irq = pThis->block_size; 1568 }1569 1723 1570 1724 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1571 if (pThis->pGstStrmOut) { 1572 #else 1573 if (pThis->voice) { 1725 PSB16DRIVER pDrv; 1726 1727 uint32_t cbOutMin = UINT32_MAX; 1728 uint32_t cbOut; 1729 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 1730 { 1731 int rc2 = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector, 1732 NULL /* pcbIn */, &cbOut, NULL /* pcSamplesLive */); 1733 if (RT_SUCCESS(rc2)) 1734 cbOutMin = RT_MIN(cbOutMin, cbOut); 1735 } 1736 1737 LogFlowFunc(("cbOutMin=%RU32\n", cbOutMin)); 1738 if (cbOutMin == UINT32_MAX) 1739 { 1740 free = dma_len; 1741 } 1742 else 1743 { 1744 free = cbOutMin & ~pThis->align; /** @todo int vs. uint32. */ 1745 if ((free <= 0) || !dma_len) 1746 return dma_pos; 1747 } 1748 #else 1749 if (pThis->voice) 1750 { 1751 free = pThis->audio_free & ~pThis->align; 1752 if ((free <= 0) || !dma_len) 1753 return dma_pos; 1754 } 1755 else 1756 free = dma_len; 1574 1757 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 1575 free = pThis->audio_free & ~pThis->align;1576 if ((free <= 0) || !dma_len) {1577 return dma_pos;1578 }1579 }1580 else {1581 free = dma_len;1582 }1583 1758 1584 1759 copy = free; … … 1586 1761 1587 1762 #ifdef DEBUG_SB16_MOST 1588 LogFlowFunc(("pos:%06d %d till:%d len:%d\n", 1589 dma_pos, free, till, dma_len)); 1590 #endif 1591 1592 if (copy >= till) { 1593 if (0 == pThis->dma_auto) { 1763 LogFlowFunc(("pos:%06d %d till:%d len:%d\n", dma_pos, free, till, dma_len)); 1764 #endif 1765 1766 if (copy >= till) 1767 { 1768 if (0 == pThis->dma_auto) 1769 { 1594 1770 copy = till; 1595 } else {1596 if( copy >= till + pThis->block_size ) {1597 copy = till; /* Make sure we won't skip IRQs. */1598 }1599 1771 } 1600 } 1601 1602 written = write_audio (pThis, nchan, dma_pos, dma_len, copy); 1772 else 1773 { 1774 if (copy >= till + pThis->block_size) 1775 copy = till; /* Make sure we won't skip IRQs. */ 1776 } 1777 } 1778 1779 written = sb16WriteAudio(pThis, nchan, dma_pos, dma_len, copy); 1603 1780 dma_pos = (dma_pos + written) % dma_len; 1781 Assert(pThis->left_till_irq >= written); 1604 1782 pThis->left_till_irq -= written; 1605 1783 1606 if (pThis->left_till_irq <= 0) { 1784 if (pThis->left_till_irq <= 0) 1785 { 1607 1786 pThis->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1; 1608 1787 #ifndef VBOX … … 1611 1790 PDMDevHlpISASetIrq(pThis->pDevIns, pThis->irq, 1); 1612 1791 #endif 1613 if (0 == pThis->dma_auto) { 1614 control (pThis, 0); 1615 speaker (pThis, 0); 1792 if (0 == pThis->dma_auto) 1793 { 1794 sb16Control(pThis, 0); 1795 sb16SpeakerControl(pThis, 0); 1616 1796 } 1617 1797 } … … 1619 1799 #ifdef DEBUG_SB16_MOST 1620 1800 LogFlowFunc(("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n", 1621 dma_pos, free, dma_len, pThis->left_till_irq, copy, written, 1622 pThis->block_size)); 1623 #endif 1624 1625 while (pThis->left_till_irq <= 0) { 1626 pThis->left_till_irq = pThis->block_size + pThis->left_till_irq; 1627 } 1801 dma_pos, free, dma_len, pThis->left_till_irq, copy, written, 1802 pThis->block_size)); 1803 #endif 1804 1805 while (pThis->left_till_irq <= 0) 1806 pThis->left_till_irq += pThis->block_size; 1628 1807 1629 1808 return dma_pos; 1630 1809 } 1631 1810 1632 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1633 static void sb16AudioCallback(void *pvContext, uint32_t cbFree) 1634 #else 1811 #ifndef VBOX_WITH_PDM_AUDIO_DRIVER 1635 1812 static void sb16AudioCallback(void *pvContext, int cbFree) 1636 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 1637 { 1638 SB16STATE *pState = (SB16STATE*)pvContext; 1813 { 1814 PSB16STATE pState = (PSB16STATE)pvContext; 1639 1815 AssertPtrReturnVoid(pState); 1640 1816 pState->audio_free = cbFree; … … 1644 1820 #endif 1645 1821 } 1822 #else 1823 static DECLCALLBACK(void) sb16TimerIO(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 1824 { 1825 PSB16STATE pThis = PDMINS_2_DATA(pDevIns, PSB16STATE); 1826 AssertPtrReturnVoid(pThis); 1827 1828 int rc = VINF_SUCCESS; 1829 1830 uint32_t cbInMax = 0; 1831 uint32_t cbOutMin = UINT32_MAX; 1832 1833 PSB16DRIVER pDrv; 1834 1835 uint32_t cbIn, cbOut, cSamplesLive; 1836 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 1837 { 1838 rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector, 1839 &cbIn, &cbOut, &cSamplesLive); 1840 if (RT_SUCCESS(rc)) 1841 { 1842 LogFlowFunc(("\tLUN#%RU8: [1] cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, cbIn, cbOut)); 1843 1844 if (cSamplesLive) 1845 { 1846 uint32_t cSamplesPlayed; 1847 int rc2 = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, &cSamplesPlayed); 1848 if (RT_SUCCESS(rc2)) 1849 LogFlowFunc(("LUN#%RU8: cSamplesLive=%RU32, cSamplesPlayed=%RU32\n", 1850 pDrv->uLUN, cSamplesLive, cSamplesPlayed)); 1851 1852 if (cSamplesPlayed) 1853 { 1854 rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector, 1855 &cbIn, &cbOut, &cSamplesLive); 1856 if (RT_SUCCESS(rc)) 1857 LogFlowFunc(("\tLUN#%RU8: [2] cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, cbIn, cbOut)); 1858 } 1859 } 1860 1861 cbInMax = RT_MAX(cbInMax, cbIn); 1862 cbOutMin = RT_MIN(cbOutMin, cbOut); 1863 } 1864 } 1865 1866 LogFlowFunc(("cbInMax=%RU32, cbOutMin=%RU32\n", cbInMax, cbOutMin)); 1867 1868 if (cbOutMin == UINT32_MAX) 1869 cbOutMin = 0; 1870 1871 /* 1872 * Playback. 1873 */ 1874 if (cbOutMin) 1875 { 1876 Assert(cbOutMin != UINT32_MAX); 1877 1878 /* New space available, see if we can transfer more. */ 1879 PDMDevHlpDMASchedule(pThis->pDevIns); 1880 } 1881 1882 /* 1883 * Recording. 1884 */ 1885 /** @todo Implement recording. */ 1886 1887 TMTimerSet(pThis->pTimerIO, TMTimerGet(pThis->pTimerIO) + pThis->uTicksIO); 1888 } 1889 #endif /* !VBOX_WITH_PDM_AUDIO_DRIVER */ 1646 1890 1647 1891 static void SB_save (QEMUFile *f, void *opaque) … … 1650 1894 PSB16STATE pThis = opaque; 1651 1895 #else 1652 PSB16STATE pThis = ( SB16STATE *)opaque;1896 PSB16STATE pThis = (PSB16STATE)opaque; 1653 1897 #endif 1654 1898 … … 1711 1955 } 1712 1956 #else 1713 PSB16STATE pThis = ( SB16STATE *)opaque;1957 PSB16STATE pThis = (PSB16STATE)opaque; 1714 1958 #endif 1715 1959 … … 1763 2007 1764 2008 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1765 if (pThis->pGstStrmOut) 1766 { 1767 pThis->pDrv->pfnCloseOut(pThis->pDrv, pThis->pGstStrmOut); 1768 pThis->pGstStrmOut = NULL; 2009 PSB16DRIVER pDrv; 2010 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 2011 { 2012 if (pDrv->Out.pStrmOut) 2013 { 2014 pDrv->pConnector->pfnCloseOut(pThis->pDrv, pDrv->Out.pStrmOut); 2015 pDrv->Out.pStrmOut = NULL; 2016 } 1769 2017 } 1770 2018 #else … … 1786 2034 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANESS; 1787 2035 1788 int rc = pThis->pDrv->pfnOpenOut(pThis->pDrv, "sb16.out", &streamCfg, &pThis->pGstStrmOut);2036 int rc = sb16OpenOut(pThis, &streamCfg); 1789 2037 AssertRC(rc); 1790 2038 #else … … 1805 2053 } 1806 2054 1807 control(pThis, 1);1808 s peaker(pThis, pThis->speaker);2055 sb16Control(pThis, 1); 2056 sb16SpeakerControl(pThis, pThis->speaker); 1809 2057 } 1810 2058 … … 1849 2097 pThis->csp_regs[9] = 0xf8; 1850 2098 1851 reset_mixer(pThis);2099 sb16MixerReset (pThis); 1852 2100 pThis->aux_ts = qemu_new_timer (vm_clock, aux_timer, s); 1853 2101 if (!pThis->aux_ts) { … … 1868 2116 register_ioport_write (pThis->port + 0x5, 1, 1, mixer_write_datab, s); 1869 2117 1870 DMA_register_channel (pThis->hdma, SB_read_DMA, s);1871 DMA_register_channel (pThis->dma, SB_read_DMA, s);2118 DMA_register_channel (pThis->hdma, sb16DMARead, s); 2119 DMA_register_channel (pThis->dma, sb16DMARead, s); 1872 2120 pThis->can_write = 1; 1873 2121 … … 1879 2127 #else /* VBOX */ 1880 2128 1881 1882 static DECLCALLBACK(int) sb16LiveExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass) 2129 static DECLCALLBACK(int) sb16LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass) 1883 2130 { 1884 2131 PSB16STATE pThis = PDMINS_2_DATA (pDevIns, PSB16STATE); … … 1892 2139 } 1893 2140 1894 static DECLCALLBACK(int) sb16SaveExec 2141 static DECLCALLBACK(int) sb16SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 1895 2142 { 1896 2143 PSB16STATE pThis = PDMINS_2_DATA (pDevIns, PSB16STATE); … … 1901 2148 } 1902 2149 1903 static DECLCALLBACK(int) sb16LoadExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSM, 1904 uint32_t uVersion, uint32_t uPass) 2150 static DECLCALLBACK(int) sb16LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) 1905 2151 { 1906 2152 PSB16STATE pThis = PDMINS_2_DATA (pDevIns, PSB16STATE); … … 1944 2190 } 1945 2191 2192 static int sb16OpenOut(PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg) 2193 { 2194 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 2195 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 2196 2197 int rc = VINF_SUCCESS; 2198 2199 PSB16DRIVER pDrv; 2200 uint8_t uLUN = 0; 2201 char *pszDesc; 2202 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 2203 { 2204 if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] sb16.po", uLUN) <= 0) 2205 { 2206 rc = VERR_NO_MEMORY; 2207 break; 2208 } 2209 2210 int rc2 = pDrv->pConnector->pfnOpenOut(pDrv->pConnector, pszDesc, pCfg, &pDrv->Out.pStrmOut); 2211 LogFlowFunc(("LUN#%RU8: Opened output with rc=%Rrc\n", uLUN, rc)); 2212 if (rc2 == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */ 2213 { 2214 audioMixerRemoveStream(pThis->pSinkOutput, pDrv->Out.phStrmOut); 2215 rc = audioMixerAddStreamOut(pThis->pSinkOutput, 2216 pDrv->pConnector, pDrv->Out.pStrmOut, 2217 0 /* uFlags */, 2218 &pDrv->Out.phStrmOut); 2219 } 2220 2221 RTStrFree(pszDesc); 2222 2223 if (RT_FAILURE(rc2)) 2224 { 2225 if (RT_SUCCESS(rc)) 2226 rc = rc2; 2227 break; 2228 } 2229 2230 uLUN++; 2231 } 2232 2233 return rc; 2234 } 2235 1946 2236 /** 1947 2237 * @interface_method_impl{PDMIBASE,pfnQueryInterface} 1948 2238 */ 1949 static DECLCALLBACK(void *) sb16QueryInterface (struct PDMIBASE *pInterface, 1950 const char *pszIID) 2239 static DECLCALLBACK(void *) sb16QueryInterface(struct PDMIBASE *pInterface, const char *pszIID) 1951 2240 { 1952 2241 PSB16STATE pThis = RT_FROM_MEMBER(pInterface, SB16STATE, IBase); … … 1982 2271 } 1983 2272 1984 static DECLCALLBACK(int) sb16Construct 2273 static DECLCALLBACK(int) sb16Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle) 1985 2274 { 1986 2275 PSB16STATE pThis = PDMINS_2_DATA(pDevIns, PSB16STATE); … … 2052 2341 pThis->csp_regs[9] = 0xf8; 2053 2342 2054 reset_mixer(pThis);2343 sb16MixerReset(pThis); 2055 2344 2056 2345 /* 2057 * Create timer , register & attach stuff.2346 * Create timer(s), register & attach stuff. 2058 2347 */ 2059 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, sb16Timer , pThis,2060 TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "SB16 timer", &pThis->pTimer);2348 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, sb16TimerIRQ, pThis, 2349 TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "SB16 IRQ timer", &pThis->pTimerIRQ); 2061 2350 if (RT_FAILURE(rc)) 2062 AssertMsgFailedReturn(("pfnTMTimerCreate -> %Rrc\n", rc), rc); 2351 AssertMsgFailedReturn(("Error creating IRQ timer, rc=%Rrc\n", rc), rc); 2352 2353 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2354 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, sb16TimerIO, pThis, 2355 TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "SB16 IO timer", &pThis->pTimerIO); 2356 if (RT_FAILURE(rc)) 2357 AssertMsgFailedReturn(("Error creating I/O timer, rc=%Rrc\n", rc), rc); 2358 else 2359 { 2360 pThis->uTicksIO = PDMDevHlpTMTimeVirtGetFreq(pDevIns) / 200; /** Hz. @todo Make this configurable! */ 2361 if (pThis->uTicksIO < 100) 2362 pThis->uTicksIO = 100; 2363 LogFunc(("I/O timer ticks=%RU64\n", pThis->uTicksIO)); 2364 2365 /* Fire off timer. */ 2366 TMTimerSet(pThis->pTimerIO, TMTimerGet(pThis->pTimerIO) + pThis->uTicksIO); 2367 } 2368 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 2063 2369 2064 2370 rc = PDMDevHlpIOPortRegister(pDevIns, pThis->port + 0x04, 2, pThis, … … 2071 2377 return rc; 2072 2378 2073 rc = PDMDevHlpDMARegister(pDevIns, pThis->hdma, SB_read_DMA, pThis);2379 rc = PDMDevHlpDMARegister(pDevIns, pThis->hdma, sb16DMARead, pThis); 2074 2380 if (RT_FAILURE(rc)) 2075 2381 return rc; 2076 rc = PDMDevHlpDMARegister(pDevIns, pThis->dma, SB_read_DMA, pThis);2382 rc = PDMDevHlpDMARegister(pDevIns, pThis->dma, sb16DMARead, pThis); 2077 2383 if (RT_FAILURE(rc)) 2078 2384 return rc; … … 2084 2390 return rc; 2085 2391 2392 /* 2393 * Attach driver. 2394 */ 2395 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2396 RTListInit(&pThis->lstDrv); 2397 2398 uint8_t uLUN; 2399 for (uLUN = 0; uLUN < UINT8_MAX; uLUN) 2400 { 2401 LogFunc(("Trying to attach driver for LUN #%RU8 ...\n", uLUN)); 2402 rc = sb16Attach(pDevIns, uLUN, PDM_TACH_FLAGS_NOT_HOT_PLUG); 2403 if (RT_FAILURE(rc)) 2404 { 2405 if (rc == VERR_PDM_NO_ATTACHED_DRIVER) 2406 rc = VINF_SUCCESS; 2407 break; 2408 } 2409 2410 uLUN++; 2411 } 2412 2413 LogFunc(("cLUNs=%RU8, rc=%Rrc\n", uLUN, rc)); 2414 #else 2086 2415 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase, "Audio Driver Port"); 2087 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER2088 if(RT_SUCCESS(rc))2089 {2090 pThis->pDrv = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIAUDIOCONNECTOR);2091 AssertMsgReturn(pThis->pDrv,2092 ("Configuration error: instance %d has no host audio interface!\n", iInstance),2093 VERR_PDM_MISSING_INTERFACE);2094 }2095 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)2096 #else2097 2416 if (rc == VERR_PDM_NO_ATTACHED_DRIVER) 2098 #endif 2099 LogFunc(("No attached driver!\n")); 2417 LogFunc(("ac97: No attached driver!\n")); 2100 2418 else if (RT_FAILURE(rc)) 2101 2419 { … … 2103 2421 return rc; 2104 2422 } 2423 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 2105 2424 2106 2425 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2107 2426 legacy_reset(pThis); 2108 2427 2109 if (!pThis->pDrv->pfnIsOutputOK(pThis->pDrv,pThis->pGstStrmOut)) 2110 { 2111 LogRel(("SB16: WARNING: Unable to open PCM OUT!\n")); 2112 pThis->pDrv->pfnCloseOut(pThis->pDrv, pThis->pGstStrmOut ); 2113 pThis->pGstStrmOut = NULL; 2114 2115 pThis->pDrv->pfnInitNull(pThis->pDrv); 2116 2117 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding", 2118 N_("No audio devices could be opened. Selecting the NULL audio backend " 2119 "with the consequence that no sound is audible")); 2428 PSB16DRIVER pDrv; 2429 uLUN = 0; 2430 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 2431 { 2432 /* 2433 * Only primary drivers are critical for the VM to run. Everything else 2434 * might not worth showing an own error message box in the GUI. 2435 */ 2436 if (!(pDrv->Flags & PDMAUDIODRVFLAG_PRIMARY)) 2437 continue; 2438 2439 PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector; 2440 AssertPtr(pCon); 2441 if (!pCon->pfnIsOutputOK(pCon, pDrv->Out.pStrmOut)) 2442 { 2443 LogRel(("SB16: WARNING: Unable to open PCM OUT!\n")); 2444 2445 pCon->pfnCloseOut(pCon, pDrv->Out.pStrmOut); 2446 pDrv->Out.pStrmOut = NULL; 2447 2448 pThis->pDrv->pfnInitNull(pThis->pDrv); 2449 2450 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding", 2451 N_("No audio devices could be opened. Selecting the NULL audio backend " 2452 "with the consequence that no sound is audible")); 2453 } 2120 2454 } 2121 2455 #else … … 2191 2525 PDM_DEVREG_VERSION 2192 2526 }; 2193 2194 2527 #endif /* VBOX */ 2195 2528
Note:
See TracChangeset
for help on using the changeset viewer.