Changeset 88797 in vbox for trunk/src/VBox/Devices/Audio/DevSB16.cpp
- Timestamp:
- Apr 30, 2021 12:39:40 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevSB16.cpp
r88773 r88797 69 69 * Defined Constants And Macros * 70 70 *********************************************************************************************************************************/ 71 /** Default timer frequency (in Hz). */ 72 #define SB16_TIMER_HZ_DEFAULT 100 71 73 /** The maximum number of separate streams we currently implement. 72 74 * Currently we only support one stream only, namely the output stream. */ … … 196 198 } SB16STREAMDEBUG; 197 199 200 typedef struct SB16STREAMHWCFG 201 { 202 uint8_t uIrq; 203 uint8_t uDmaChanLow; 204 uint8_t uDmaChanHigh; 205 RTIOPORT uPort; 206 uint16_t uVer; 207 } SB16STREAMHWCFG; 208 198 209 /** 199 210 * Structure for a SB16 stream. … … 203 214 /** The stream's own index in \a aStreams of SB16STATE. 204 215 * Set to UINT8_MAX if not set (yet). */ 205 uint8_t uIdx; 216 uint8_t uIdx; 217 uint16_t uTimerHz; 206 218 /** The timer for pumping data thru the attached LUN drivers. */ 207 TMTIMERHANDLE 219 TMTIMERHANDLE hTimerIO; 208 220 /** The timer interval for pumping data thru the LUN drivers in timer ticks. */ 209 uint64_t 221 uint64_t cTicksTimerIOInterval; 210 222 /** Timestamp of the last timer callback (sb16TimerIO). 211 * Used to calculate the 223 * Used to calculate thetime actually elapsed between two timer callbacks. 212 224 * This currently ASSMUMES that we only have one single (output) stream. */ 213 uint64_t tsTimerIO; /** @todo Make this a per-stream value. */ 214 /** The stream's current configuration. */ 215 PDMAUDIOSTREAMCFG Cfg; 225 uint64_t tsTimerIO; /** @todo Make this a per-stream value. */ 226 /** The stream's currentconfiguration. */ 227 PDMAUDIOSTREAMCFG Cfg; 228 /** The stream's defaulthardware configuration, mostly done by jumper settings back then. */ 229 SB16STREAMHWCFG HwCfgDefault; 230 /** The stream's hardware configuration set at runtime. 231 * Might differ from the default configuration above and is needed for live migration. */ 232 SB16STREAMHWCFG HwCfgRuntime; 233 234 int fifo; 235 int dma_auto; 236 /** Whether to use the high (\c true) or the low (\c false) DMA channel. */ 237 int fDmaUseHigh; 238 int can_write; /** @todo r=andy BUGBUG Value never gets set to 0! */ 239 int time_const; 240 /** The DMA transfer (block)size in bytes. */ 241 int32_t cbDmaBlockSize; 242 int32_t cbDmaLeft; /** Note: Can be < 0. Needs to 32-bit for backwards compatibility. */ 216 243 /** Internal state of this stream. */ 217 SB16STREAMSTATE 244 SB16STREAMSTATE State; 218 245 /** Debug stuff. */ 219 SB16STREAMDEBUG 246 SB16STREAMDEBUG Dbg; 220 247 } SB16STREAM; 221 248 /** Pointer to a SB16 stream */ … … 255 282 typedef struct SB16STATE 256 283 { 257 #ifdef VBOX258 284 /** Pointer to the device instance. */ 259 PPDMDEVINSR3 pDevInsR3;285 PPDMDEVINSR3 pDevInsR3; 260 286 /** Pointer to the connector of the attached audio driver. */ 261 PPDMIAUDIOCONNECTOR pDrv; 262 int irqCfg; 263 int dmaCfg; 264 int hdmaCfg; 265 int portCfg; 266 int verCfg; 267 #endif 268 int irq; 269 int dma; 270 int hdma; 271 int port; 272 int ver; 273 274 int dsp_in_idx; 275 int dsp_out_data_len; 276 int fmt_stereo; 277 int fmt_signed; 278 int fmt_bits; 279 PDMAUDIOFMT fmt; 280 int dma_auto; 281 int block_size; 282 int fifo; 283 int freq; 284 int time_const; 285 int speaker; 286 int dsp_in_needed_bytes; 287 int cmd; 288 int use_hdma; 289 int highspeed; 290 int can_write; /** @todo r=andy BUGBUG Value never gets set to 0! */ 291 292 int v2x6; 293 294 uint8_t csp_param; 295 uint8_t csp_value; 296 uint8_t csp_mode; 297 uint8_t csp_index; 298 uint8_t csp_regs[256]; 299 uint8_t csp_reg83[4]; 300 int csp_reg83r; 301 int csp_reg83w; 302 303 uint8_t dsp_in_data[10]; 304 uint8_t dsp_out_data[50]; 305 uint8_t test_reg; 306 uint8_t last_read_byte; 307 int nzero; 308 309 int left_till_irq; /** Note: Can be < 0. */ 310 311 int dma_running; 312 int bytes_per_second; 313 int align; 314 315 RTLISTANCHOR lstDrv; 287 PPDMIAUDIOCONNECTOR pDrv; 288 289 int dsp_in_idx; 290 int dsp_out_data_len; 291 int dsp_in_needed_bytes; 292 int cmd; 293 int highspeed; 294 295 int v2x6; 296 297 uint8_t csp_param; 298 uint8_t csp_value; 299 uint8_t csp_mode; 300 uint8_t csp_index; 301 uint8_t csp_regs[256]; 302 uint8_t csp_reg83[4]; 303 int csp_reg83r; 304 int csp_reg83w; 305 306 uint8_t dsp_in_data[10]; 307 uint8_t dsp_out_data[50]; 308 uint8_t test_reg; 309 uint8_t last_read_byte; 310 int nzero; 311 312 RTLISTANCHOR lstDrv; 316 313 /** IRQ timer */ 317 TMTIMERHANDLE hTimerIRQ;314 TMTIMERHANDLE hTimerIRQ; 318 315 /** The base interface for LUN\#0. */ 319 PDMIBASE IBase;316 PDMIBASE IBase; 320 317 321 318 /** Array of all SB16 hardware audio stream. */ … … 327 324 328 325 /** The two mixer I/O ports (port + 4). */ 329 IOMIOPORTHANDLE hIoPortsMixer;326 IOMIOPORTHANDLE hIoPortsMixer; 330 327 /** The 10 DSP I/O ports (port + 6). */ 331 IOMIOPORTHANDLE hIoPortsDsp;328 IOMIOPORTHANDLE hIoPortsDsp; 332 329 333 330 /** Debug settings. */ 334 SB16STATEDEBUG 331 SB16STATEDEBUG Dbg; 335 332 336 333 /* mixer state */ 337 uint8_t mixer_nreg;338 uint8_t mixer_regs[256];334 uint8_t mixer_nreg; 335 uint8_t mixer_regs[256]; 339 336 340 337 #ifdef VBOX_WITH_STATISTICS 341 STAMPROFILE 342 STAMCOUNTER 338 STAMPROFILE StatTimerIO; 339 STAMCOUNTER StatBytesRead; 343 340 #endif 344 341 } SB16STATE; … … 369 366 #endif /* VBOX_WITH_AUDIO_SB16_ASYNC_IO */ 370 367 371 static void sb16SpeakerControl(PSB16STATE pThis, int on);368 static void sb16SpeakerControl(PSB16STATE pThis, bool fOn); 372 369 static void sb16UpdateVolume(PSB16STATE pThis); 373 370 374 #if 0 // unused // def DEBUG375 DECLINLINE(void) log_dsp(PSB16STATE pThis)376 {377 LogFlowFunc(("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",378 pThis->fmt_stereo ? "Stereo" : "Mono",379 pThis->fmt_signed ? "Signed" : "Unsigned",380 pThis->fmt_bits,381 pThis->dma_auto ? "Auto" : "Single",382 pThis->block_size,383 pThis->freq,384 pThis->time_const,385 pThis->speaker));386 }387 #endif388 371 389 372 #ifdef VBOX_WITH_AUDIO_SB16_ASYNC_IO … … 545 528 #endif /* VBOX_WITH_AUDIO_SB16_ASYNC_IO */ 546 529 547 static void sb16SpeakerControl(PSB16STATE pThis, int on) 548 { 549 pThis->speaker = on; 550 } 551 552 static void sb16Control(PPDMDEVINS pDevIns, PSB16STATE pThis, int hold) 553 { 554 int dma = pThis->use_hdma ? pThis->hdma : pThis->dma; 555 pThis->dma_running = hold; 556 557 LogFlowFunc(("hold %d high %d dma %d\n", hold, pThis->use_hdma, dma)); 558 559 PDMDevHlpDMASetDREQ(pThis->pDevInsR3, dma, hold); 560 561 /* We only support one output stream at the moment, so keep things simple here for now. */ 562 PSB16STREAM pStream = &pThis->aStreams[SB16_IDX_OUT]; 563 564 if (hold) 565 { 566 int rc = VINF_SUCCESS; 567 568 if (pThis->freq > 0) 530 static void sb16SpeakerControl(PSB16STATE pThis, bool fOn) 531 { 532 RT_NOREF(pThis, fOn); 533 534 /** @todo This currently does nothing. */ 535 } 536 537 static void sb16StreamControl(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream, bool fRun) 538 { 539 unsigned uDmaChan = pStream->fDmaUseHigh ? pStream->HwCfgRuntime.uDmaChanHigh : pStream->HwCfgRuntime.uDmaChanLow; 540 541 LogFunc(("fRun=%RTbool, fDmaUseHigh=%RTbool, uDmaChan=%u\n", fRun, pStream->fDmaUseHigh, uDmaChan)); 542 543 PDMDevHlpDMASetDREQ(pThis->pDevInsR3, uDmaChan, fRun ? 1 : 0); 544 545 if (fRun != pStream->State.fEnabled) 546 { 547 if (fRun) 569 548 { 570 rc = sb16StreamOpen(pDevIns, pThis, pStream); 571 if (RT_SUCCESS(rc)) 572 sb16UpdateVolume(pThis); 573 } 574 575 if (RT_SUCCESS(rc)) 576 { 577 rc = sb16StreamEnable(pThis, pStream, true /* fEnable */, false /* fForce */); 549 int rc = VINF_SUCCESS; 550 551 if (pStream->Cfg.Props.uHz > 0) 552 { 553 rc = sb16StreamOpen(pDevIns, pThis, pStream); 554 if (RT_SUCCESS(rc)) 555 sb16UpdateVolume(pThis); 556 } 557 else 558 AssertFailed(); /** @todo Buggy code? */ 559 578 560 if (RT_SUCCESS(rc)) 579 561 { 580 sb16TimerSet(pDevIns, pStream, pStream->cTicksTimerIOInterval); 581 582 PDMDevHlpDMASchedule(pThis->pDevInsR3); 562 rc = sb16StreamEnable(pThis, pStream, true /* fEnable */, false /* fForce */); 563 if (RT_SUCCESS(rc)) 564 { 565 sb16TimerSet(pDevIns, pStream, pStream->cTicksTimerIOInterval); 566 567 PDMDevHlpDMASchedule(pThis->pDevInsR3); 568 } 583 569 } 584 570 } 585 }586 else587 {588 sb16StreamEnable(pThis, pStream, false /* fEnable */, false /* fForce */);571 else 572 { 573 sb16StreamEnable(pThis, pStream, false /* fEnable */, false /* fForce */); 574 } 589 575 } 590 576 } … … 593 579 #define DMA8_HIGH 2 594 580 595 static void continue_dma8(PPDMDEVINS pDevIns, PSB16STATE pThis) 596 { 597 sb16Control(pDevIns, pThis, 1); 598 } 599 600 static void dma_cmd8(PPDMDEVINS pDevIns, PSB16STATE pThis, int mask, int dma_len) 601 { 602 pThis->fmt = PDMAUDIOFMT_U8; 603 pThis->use_hdma = 0; 604 pThis->fmt_bits = 8; 605 pThis->fmt_signed = 0; 606 pThis->fmt_stereo = (pThis->mixer_regs[0x0e] & 2) != 0; 607 608 if (-1 == pThis->time_const) 609 { 610 if (pThis->freq <= 0) 611 pThis->freq = 11025; 581 static void sb16DmaCmdContinue8(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream) 582 { 583 sb16StreamControl(pDevIns, pThis, pStream, true /* fRun */); 584 } 585 586 static void sb16DmaCmd8(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream, 587 int mask, int dma_len) 588 { 589 pStream->fDmaUseHigh = 0; 590 591 if (-1 == pStream->time_const) 592 { 593 if (pStream->Cfg.Props.uHz == 0) 594 pStream->Cfg.Props.uHz = 11025; 612 595 } 613 596 else 614 597 { 615 int tmp = (256 - pThis->time_const); 616 pThis->freq = (1000000 + (tmp / 2)) / tmp; 617 } 598 int tmp = (256 - pStream->time_const); 599 pStream->Cfg.Props.uHz = (1000000 + (tmp / 2)) / tmp; 600 } 601 602 unsigned cShiftChannels = pStream->Cfg.Props.cChannelsX >= 2 ? 1 : 0; 618 603 619 604 if (dma_len != -1) 620 605 { 621 p This->block_size = dma_len << pThis->fmt_stereo;606 pStream->cbDmaBlockSize = dma_len << cShiftChannels; 622 607 } 623 608 else … … 632 617 Both use stereo, and Creatives own documentation states that 633 618 0x48 sets block size in bytes less one.. go figure */ 634 pThis->block_size &= ~pThis->fmt_stereo; 635 } 636 637 pThis->freq >>= pThis->fmt_stereo; 638 pThis->left_till_irq = pThis->block_size; 639 pThis->bytes_per_second = (pThis->freq << pThis->fmt_stereo); 619 pStream->cbDmaBlockSize &= ~cShiftChannels; 620 } 621 622 pStream->Cfg.Props.uHz >>= cShiftChannels; 623 pStream->cbDmaLeft = pStream->cbDmaBlockSize; 640 624 /* pThis->highspeed = (mask & DMA8_HIGH) != 0; */ 641 pThis->dma_auto = (mask & DMA8_AUTO) != 0; 642 pThis->align = (1 << pThis->fmt_stereo) - 1; 643 644 if (pThis->block_size & pThis->align) 645 LogFlowFunc(("warning: misaligned block size %d, alignment %d\n", pThis->block_size, pThis->align + 1)); 646 647 LogFlowFunc(("freq %d, stereo %d, sign %d, bits %d, dma %d, auto %d, fifo %d, high %d\n", 648 pThis->freq, pThis->fmt_stereo, pThis->fmt_signed, pThis->fmt_bits, 649 pThis->block_size, pThis->dma_auto, pThis->fifo, pThis->highspeed)); 650 651 continue_dma8(pDevIns, pThis); 625 pStream->dma_auto = (mask & DMA8_AUTO) != 0; 626 627 PDMAudioPropsInit(&pStream->Cfg.Props, 1 /* 8-bit */, 628 false /* fSigned */, 629 (pThis->mixer_regs[0x0e] & 2) == 0 ? 1 : 2 /* Mono/Stereo */, 630 pStream->Cfg.Props.uHz); 631 632 /** @todo Check if stream's DMA block size is properly aligned to the set PCM props. */ 633 634 sb16DmaCmdContinue8(pDevIns, pThis, pStream); 652 635 sb16SpeakerControl(pThis, 1); 653 636 } 654 637 655 static void dma_cmd(PPDMDEVINS pDevIns, PSB16STATE pThis, uint8_t cmd, uint8_t d0, int dma_len) 656 { 657 pThis->use_hdma = cmd < 0xc0; 658 pThis->fifo = (cmd >> 1) & 1; 659 pThis->dma_auto = (cmd >> 2) & 1; 660 pThis->fmt_signed = (d0 >> 4) & 1; 661 pThis->fmt_stereo = (d0 >> 5) & 1; 638 static void sb16DmaCmd(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream, 639 uint8_t cmd, uint8_t d0, int dma_len) 640 { 641 pStream->fDmaUseHigh = cmd < 0xc0; 642 pStream->fifo = (cmd >> 1) & 1; 643 pStream->dma_auto = (cmd >> 2) & 1; 644 645 pStream->Cfg.Props.fSigned = RT_BOOL((d0 >> 4) & 1); /** @todo Use RT_BIT? */ 646 pStream->Cfg.Props.cChannelsX = (d0 >> 5) & 1 ? 2 : 1; 662 647 663 648 switch (cmd >> 4) 664 649 { 665 650 case 11: 666 p This->fmt_bits = 16;651 pStream->Cfg.Props.cbSampleX = 2 /* 16 bit */; 667 652 break; 668 653 669 654 case 12: 670 pThis->fmt_bits = 8; 671 break; 672 } 673 674 if (-1 != pThis->time_const) 655 pStream->Cfg.Props.cbSampleX = 1 /* 8 bit */; 656 break; 657 658 default: 659 AssertFailed(); 660 break; 661 } 662 663 if (-1 != pStream->time_const) 675 664 { 676 665 #if 1 677 int tmp = 256 - p This->time_const;678 p This->freq= (1000000 + (tmp / 2)) / tmp;666 int tmp = 256 - pStream->time_const; 667 pStream->Cfg.Props.uHz = (1000000 + (tmp / 2)) / tmp; 679 668 #else 680 /* pThis->freq = 1000000 / ((255 - p This->time_const) << pThis->fmt_stereo); */681 pThis->freq = 1000000 / ((255 - p This->time_const));669 /* pThis->freq = 1000000 / ((255 - pStream->time_const) << pThis->fmt_stereo); */ 670 pThis->freq = 1000000 / ((255 - pStream->time_const)); 682 671 #endif 683 p This->time_const = -1;684 } 685 686 p This->block_size = dma_len + 1;687 p This->block_size <<= ((pThis->fmt_bits == 16) ? 1 : 0);688 if (!p This->dma_auto)672 pStream->time_const = -1; 673 } 674 675 pStream->cbDmaBlockSize = dma_len + 1; 676 pStream->cbDmaBlockSize <<= ((pStream->Cfg.Props.cbSampleX == 2) ? 1 : 0); 677 if (!pStream->dma_auto) 689 678 { 690 679 /* … … 694 683 * wonders of SB16 yet again. 695 684 */ 696 pThis->block_size <<= pThis->fmt_stereo; 697 } 698 699 LogFlowFunc(("freq %d, stereo %d, sign %d, bits %d, dma %d, auto %d, fifo %d, high %d\n", 700 pThis->freq, pThis->fmt_stereo, pThis->fmt_signed, pThis->fmt_bits, 701 pThis->block_size, pThis->dma_auto, pThis->fifo, pThis->highspeed)); 702 703 if (16 == pThis->fmt_bits) 704 pThis->fmt = pThis->fmt_signed ? PDMAUDIOFMT_S16 : PDMAUDIOFMT_U16; 705 else 706 pThis->fmt = pThis->fmt_signed ? PDMAUDIOFMT_S8 : PDMAUDIOFMT_U8; 707 708 pThis->left_till_irq = pThis->block_size; 709 710 pThis->bytes_per_second = (pThis->freq << pThis->fmt_stereo) << ((pThis->fmt_bits == 16) ? 1 : 0); 685 pStream->cbDmaBlockSize <<= pStream->Cfg.Props.cChannelsX == 2 ? 1 : 0; 686 } 687 688 pStream->cbDmaLeft = pStream->cbDmaBlockSize; 689 711 690 pThis->highspeed = 0; 712 pThis->align = (1 << (pThis->fmt_stereo + (pThis->fmt_bits == 16))) - 1; 713 if (pThis->block_size & pThis->align) 714 { 715 LogFlowFunc(("warning: misaligned block size %d, alignment %d\n", 716 pThis->block_size, pThis->align + 1)); 717 } 718 719 sb16Control(pDevIns, pThis, 1); 691 692 /** @todo Check if stream's DMA block size is properly aligned to the set PCM props. */ 693 694 sb16StreamControl(pDevIns, pThis, pStream, true /* fRun */); 720 695 sb16SpeakerControl(pThis, 1); 721 696 } 722 697 723 static inline void dsp_set_data(PSB16STATE pThis, uint8_t val)698 static inline void sb16DspSeData(PSB16STATE pThis, uint8_t val) 724 699 { 725 700 LogFlowFunc(("%#x\n", val)); … … 728 703 } 729 704 730 static inline uint8_t dsp_get_data(PSB16STATE pThis)705 static inline uint8_t sb16DspGetData(PSB16STATE pThis) 731 706 { 732 707 if (pThis->dsp_in_idx) … … 736 711 } 737 712 738 static void sb16 HandleCommand(PPDMDEVINS pDevIns, PSB16STATE pThis, uint8_t cmd)713 static void sb16DspCmdLookup(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream, uint8_t cmd) 739 714 { 740 715 LogFlowFunc(("command %#x\n", cmd)); … … 760 735 pThis->dsp_in_needed_bytes = 0; 761 736 737 /** @todo Use a mapping table with 738 * - a command verb (binary search) 739 * - required bytes 740 * - function callback handler 741 */ 742 762 743 switch (cmd) 763 744 { 764 case 0x03: 765 dsp_set_data(pThis, 0x10); /* pThis->csp_param); */745 case 0x03: /* ASP Status */ 746 sb16DspSeData(pThis, 0x10); /* pThis->csp_param); */ 766 747 goto warn; 767 748 768 case 0x04: 749 case 0x04: /* DSP Status (Obsolete) / ASP ??? */ 769 750 pThis->dsp_in_needed_bytes = 1; 770 751 goto warn; 771 752 772 case 0x05: 753 case 0x05: /* ASP ??? */ 773 754 pThis->dsp_in_needed_bytes = 2; 774 755 goto warn; 775 756 776 case 0x08: 757 case 0x08: /* ??? */ 777 758 /* __asm__ ("int3"); */ 778 759 goto warn; 779 760 780 case 0x0e: 761 case 0x09: /* ??? */ 762 sb16DspSeData(pThis, 0xf8); 763 goto warn; 764 765 case 0x0e: /* ??? */ 781 766 pThis->dsp_in_needed_bytes = 2; 782 767 goto warn; 783 768 784 case 0x09: 785 dsp_set_data(pThis, 0xf8); 786 goto warn; 787 788 case 0x0f: 769 case 0x0f: /* ??? */ 789 770 pThis->dsp_in_needed_bytes = 1; 790 771 goto warn; 791 772 792 case 0x10: 773 case 0x10: /* Direct mode DAC */ 793 774 pThis->dsp_in_needed_bytes = 1; 794 775 goto warn; 795 776 796 case 0x14: 777 case 0x14: /* DAC DMA, 8-bit, uncompressed */ 797 778 pThis->dsp_in_needed_bytes = 2; 798 p This->block_size = 0;779 pStream->cbDmaBlockSize = 0; 799 780 break; 800 781 801 782 case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */ 802 dma_cmd8(pDevIns, pThis, DMA8_AUTO, -1);783 sb16DmaCmd8(pDevIns, pThis, pStream, DMA8_AUTO, -1); 803 784 break; 804 785 805 786 case 0x20: /* Direct ADC, Juice/PL */ 806 dsp_set_data(pThis, 0xff);787 sb16DspSeData(pThis, 0xff); 807 788 goto warn; 808 789 809 case 0x35: 810 LogFlowFunc(("0x35 - MIDI command not implemented\n")); 811 break; 812 813 case 0x40: 814 pThis->freq = -1; 815 pThis->time_const = -1; 790 case 0x35: /* MIDI Read Interrupt + Write Poll (UART) */ 791 LogRelMax2(32, ("SB16: MIDI support not implemented yet\n")); 792 break; 793 794 case 0x40: /* Set Time Constant */ 795 pStream->time_const = -1; 816 796 pThis->dsp_in_needed_bytes = 1; 817 797 break; 818 798 819 case 0x41: 820 p This->freq = -1;821 p This->time_const = -1;799 case 0x41: /* Set sample rate for input */ 800 pStream->Cfg.Props.uHz = 0; /** @todo r=andy Why do we reset output stuff here? */ 801 pStream->time_const = -1; 822 802 pThis->dsp_in_needed_bytes = 2; 823 803 break; 824 804 825 case 0x42: 826 p This->freq = -1;827 p This->time_const = -1;805 case 0x42: /* Set sample rate for output */ 806 pStream->Cfg.Props.uHz = 0; 807 pStream->time_const = -1; 828 808 pThis->dsp_in_needed_bytes = 2; 829 809 goto warn; 830 810 831 case 0x45: 832 dsp_set_data(pThis, 0xaa);811 case 0x45: /* Continue Auto-Initialize DMA, 8-bit */ 812 sb16DspSeData(pThis, 0xaa); 833 813 goto warn; 834 814 835 case 0x47: /* Continue Auto-Initialize DMA 16bit */836 break; 837 838 case 0x48: 815 case 0x47: /* Continue Auto-Initialize DMA, 16-bit */ 816 break; 817 818 case 0x48: /* Set DMA Block Size */ 839 819 pThis->dsp_in_needed_bytes = 2; 840 820 break; 841 821 842 case 0x74: 843 pThis->dsp_in_needed_bytes = 2; /* DMA DAC, 4-bit ADPCM */844 LogFlowFunc((" 0x75 - DMA DAC, 4-bit ADPCM not implemented\n"));822 case 0x74: /* DMA DAC, 4-bit ADPCM */ 823 pThis->dsp_in_needed_bytes = 2; 824 LogFlowFunc(("4-bit ADPCM not implemented yet\n")); 845 825 break; 846 826 847 827 case 0x75: /* DMA DAC, 4-bit ADPCM Reference */ 848 828 pThis->dsp_in_needed_bytes = 2; 849 LogFlowFunc((" 0x74 -DMA DAC, 4-bit ADPCM Reference not implemented\n"));829 LogFlowFunc(("DMA DAC, 4-bit ADPCM Reference not implemented\n")); 850 830 break; 851 831 852 832 case 0x76: /* DMA DAC, 2.6-bit ADPCM */ 853 833 pThis->dsp_in_needed_bytes = 2; 854 LogFlowFunc((" 0x74 - DMA DAC, 2.6-bit ADPCM not implemented\n"));834 LogFlowFunc(("DMA DAC, 2.6-bit ADPCM not implemented yet\n")); 855 835 break; 856 836 857 837 case 0x77: /* DMA DAC, 2.6-bit ADPCM Reference */ 858 838 pThis->dsp_in_needed_bytes = 2; 859 LogFlowFunc(("0x74 - DMA DAC, 2.6-bit ADPCM Reference not implemented\n")); 860 break; 861 862 case 0x7d: 863 LogFlowFunc(("0x7d - Autio-Initialize DMA DAC, 4-bit ADPCM Reference\n")); 864 LogFlowFunc(("not implemented\n")); 865 break; 866 867 case 0x7f: 868 LogFlowFunc(("0x7d - Autio-Initialize DMA DAC, 2.6-bit ADPCM Reference\n")); 869 LogFlowFunc(("not implemented\n")); 870 break; 871 872 case 0x80: 839 LogFlowFunc(("ADPCM reference not implemented yet\n")); 840 break; 841 842 case 0x7d: /* Auto-Initialize DMA DAC, 4-bit ADPCM Reference */ 843 LogFlowFunc(("Autio-Initialize DMA DAC, 4-bit ADPCM reference not implemented yet\n")); 844 break; 845 846 case 0x7f: /* Auto-Initialize DMA DAC, 16-bit ADPCM Reference */ 847 LogFlowFunc(("Autio-Initialize DMA DAC, 2.6-bit ADPCM Reference not implemented yet\n")); 848 break; 849 850 case 0x80: /* Silence DAC */ 873 851 pThis->dsp_in_needed_bytes = 2; 874 852 break; 875 853 876 case 0x90: 877 case 0x91: 878 dma_cmd8(pDevIns, pThis, (((cmd & 1) == 0) ? 1 : 0) | DMA8_HIGH, -1); 879 break; 880 881 case 0xd0: /* halt DMA operation. 8bit */ 882 sb16Control(pDevIns, pThis, 0); 883 break; 884 885 case 0xd1: /* speaker on */ 886 sb16SpeakerControl(pThis, 1); 887 break; 888 889 case 0xd3: /* speaker off */ 890 sb16SpeakerControl(pThis, 0); 891 break; 892 893 case 0xd4: /* continue DMA operation. 8bit */ 854 case 0x90: /* Auto-Initialize DMA DAC, 8-bit (High Speed) */ 855 RT_FALL_THROUGH(); 856 case 0x91: /* Normal DMA DAC, 8-bit (High Speed) */ 857 sb16DmaCmd8(pDevIns, pThis, pStream, (((cmd & 1) == 0) ? 1 : 0) | DMA8_HIGH, -1); 858 break; 859 860 case 0xd0: /* Halt DMA operation. 8bit */ 861 sb16StreamControl(pDevIns, pThis, pStream, false /* fRun */); 862 break; 863 864 case 0xd1: /* Speaker on */ 865 sb16SpeakerControl(pThis, true /* fOn */); 866 break; 867 868 case 0xd3: /* Speaker off */ 869 sb16SpeakerControl(pThis, false /* fOn */); 870 break; 871 872 case 0xd4: /* Continue DMA operation, 8-bit */ 894 873 /* KQ6 (or maybe Sierras audblst.drv in general) resets 895 874 the frequency between halt/continue */ 896 continue_dma8(pDevIns, pThis);897 break; 898 899 case 0xd5: /* halt DMA operation. 16bit */900 sb16 Control(pDevIns, pThis, 0);901 break; 902 903 case 0xd6: /* continue DMA operation. 16bit */904 sb16 Control(pDevIns, pThis, 1);905 break; 906 907 case 0xd9: /* exit auto-init DMA after this block. 16bit */908 p This->dma_auto = 0;909 break; 910 911 case 0xda: /* exit auto-init DMA after this block. 8bit */912 p This->dma_auto = 0;875 sb16DmaCmdContinue8(pDevIns, pThis, pStream); 876 break; 877 878 case 0xd5: /* Halt DMA operation, 16-bit */ 879 sb16StreamControl(pDevIns, pThis, pStream, false /* fRun */); 880 break; 881 882 case 0xd6: /* Continue DMA operation, 16-bit */ 883 sb16StreamControl(pDevIns, pThis, pStream, true /* fRun */); 884 break; 885 886 case 0xd9: /* Exit auto-init DMA after this block, 16-bit */ 887 pStream->dma_auto = 0; 888 break; 889 890 case 0xda: /* Exit auto-init DMA after this block, 8-bit */ 891 pStream->dma_auto = 0; 913 892 break; 914 893 … … 917 896 break; 918 897 919 case 0xe1: 920 dsp_set_data(pThis, pThis->ver & 0xff);921 dsp_set_data(pThis, pThis->ver >> 8);922 break; 923 924 case 0xe2: 898 case 0xe1: /* DSP version */ 899 sb16DspSeData(pThis, RT_LO_U8(pStream->HwCfgRuntime.uVer)); 900 sb16DspSeData(pThis, RT_HI_U8(pStream->HwCfgRuntime.uVer)); 901 break; 902 903 case 0xe2: /* ??? */ 925 904 pThis->dsp_in_needed_bytes = 1; 926 905 goto warn; 927 906 928 case 0xe3: 907 case 0xe3: /* DSP copyright */ 929 908 { 930 for (int i = sizeof (e3) - 1; i >= 0; --i) 931 dsp_set_data(pThis, e3[i]); 932 909 for (int i = sizeof(e3) - 1; i >= 0; --i) 910 sb16DspSeData(pThis, e3[i]); 933 911 break; 934 912 } 935 913 936 case 0xe4: /* write test reg*/914 case 0xe4: /* Write test register */ 937 915 pThis->dsp_in_needed_bytes = 1; 938 916 break; 939 917 940 case 0xe7: 918 case 0xe7: /* ??? */ 941 919 LogFlowFunc(("Attempt to probe for ESS (0xe7)?\n")); 942 920 break; 943 921 944 case 0xe8: /* read test reg */ 945 dsp_set_data(pThis, pThis->test_reg); 946 break; 947 948 case 0xf2: 949 case 0xf3: 950 dsp_set_data(pThis, 0xaa); 922 case 0xe8: /* Read test register */ 923 sb16DspSeData(pThis, pThis->test_reg); 924 break; 925 926 case 0xf2: /* IRQ Request, 8-bit */ 927 RT_FALL_THROUGH(); 928 case 0xf3: /* IRQ Request, 16-bit */ 929 { 930 sb16DspSeData(pThis, 0xaa); 951 931 pThis->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2; 952 PDMDevHlpISASetIrq(pThis->pDevInsR3, p This->irq, 1);953 break; 954 955 case 0xf8: 956 /* Undocumented, used by old Creative diagnostic programs.*/957 dsp_set_data(pThis, 0);932 PDMDevHlpISASetIrq(pThis->pDevInsR3, pStream->HwCfgRuntime.uIrq, 1); 933 break; 934 } 935 936 case 0xf8: /* Undocumented, used by old Creative diagnostic programs */ 937 sb16DspSeData(pThis, 0); 958 938 goto warn; 959 939 960 case 0xf9: 940 case 0xf9: /* ??? */ 961 941 pThis->dsp_in_needed_bytes = 1; 962 942 goto warn; 963 943 964 case 0xfa: 965 dsp_set_data(pThis, 0);944 case 0xfa: /* ??? */ 945 sb16DspSeData(pThis, 0); 966 946 goto warn; 967 947 968 case 0xfc: /* FIXME*/969 dsp_set_data(pThis, 0);948 case 0xfc: /* ??? */ 949 sb16DspSeData(pThis, 0); 970 950 goto warn; 971 951 972 952 default: 973 LogF lowFunc(("Unrecognized command %#x\n", cmd));953 LogFunc(("Unrecognized DSP command %#x, ignored\n", cmd)); 974 954 break; 975 955 } 976 956 } 977 978 if (!pThis->dsp_in_needed_bytes)979 LogFlow(("\n"));980 957 981 958 exit: … … 989 966 990 967 warn: 991 LogF lowFunc(("warning: command %#x,%d is not truly understood yet\n", cmd, pThis->dsp_in_needed_bytes));968 LogFunc(("warning: command %#x,%d is not truly understood yet\n", cmd, pThis->dsp_in_needed_bytes)); 992 969 goto exit; 993 970 } 994 971 995 DECLINLINE(uint16_t) dsp_get_lohi(PSB16STATE pThis)996 { 997 const uint8_t hi = dsp_get_data(pThis);998 const uint8_t lo = dsp_get_data(pThis);972 DECLINLINE(uint16_t) sb16DspGetLoHi(PSB16STATE pThis) 973 { 974 const uint8_t hi = sb16DspGetData(pThis); 975 const uint8_t lo = sb16DspGetData(pThis); 999 976 return RT_MAKE_U16(lo, hi); 1000 977 } 1001 978 1002 DECLINLINE(uint16_t) dsp_get_hilo(PSB16STATE pThis)1003 { 1004 const uint8_t lo = dsp_get_data(pThis);1005 const uint8_t hi = dsp_get_data(pThis);979 DECLINLINE(uint16_t) sb16DspGetHiLo(PSB16STATE pThis) 980 { 981 const uint8_t lo = sb16DspGetData(pThis); 982 const uint8_t hi = sb16DspGetData(pThis); 1006 983 return RT_MAKE_U16(lo, hi); 1007 984 } 1008 985 1009 static void dsp_cmd_complete(PPDMDEVINS pDevIns, PSB16STATE pThis)986 static void sb16DspCmdComplete(PPDMDEVINS pDevIns, PSB16STATE pThis) 1010 987 { 1011 988 LogFlowFunc(("Command %#x, in_index %d, needed_bytes %d\n", pThis->cmd, pThis->dsp_in_idx, pThis->dsp_in_needed_bytes)); … … 1017 994 if (pThis->cmd > 0xaf && pThis->cmd < 0xd0) 1018 995 { 1019 v2 = dsp_get_data(pThis);1020 v1 = dsp_get_data(pThis);1021 v0 = dsp_get_data(pThis);996 v2 = sb16DspGetData(pThis); 997 v1 = sb16DspGetData(pThis); 998 v0 = sb16DspGetData(pThis); 1022 999 1023 1000 if (pThis->cmd & 8) … … 1026 1003 { 1027 1004 LogFlowFunc(("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n", pThis->cmd, v0, v1, v2)); 1028 dma_cmd(pDevIns, pThis, pThis->cmd, v0, v1 + (v2 << 8));1005 sb16DmaCmd(pDevIns, pThis, pStream, pThis->cmd, v0, v1 + (v2 << 8)); 1029 1006 } 1030 1007 } … … 1035 1012 case 0x04: 1036 1013 { 1037 pThis->csp_mode = dsp_get_data(pThis);1014 pThis->csp_mode = sb16DspGetData(pThis); 1038 1015 pThis->csp_reg83r = 0; 1039 1016 pThis->csp_reg83w = 0; … … 1044 1021 case 0x05: 1045 1022 { 1046 pThis->csp_param = dsp_get_data(pThis);1047 pThis->csp_value = dsp_get_data(pThis);1023 pThis->csp_param = sb16DspGetData(pThis); 1024 pThis->csp_value = sb16DspGetData(pThis); 1048 1025 LogFlowFunc(("CSP command 0x05: param=%#x value=%#x\n", pThis->csp_param, pThis->csp_value)); 1049 1026 break; … … 1052 1029 case 0x0e: 1053 1030 { 1054 v0 = dsp_get_data(pThis);1055 v1 = dsp_get_data(pThis);1031 v0 = sb16DspGetData(pThis); 1032 v1 = sb16DspGetData(pThis); 1056 1033 LogFlowFunc(("write CSP register %d <- %#x\n", v1, v0)); 1057 1034 if (v1 == 0x83) … … 1068 1045 case 0x0f: 1069 1046 { 1070 v0 = dsp_get_data(pThis);1047 v0 = sb16DspGetData(pThis); 1071 1048 LogFlowFunc(("read CSP register %#x -> %#x, mode=%#x\n", v0, pThis->csp_regs[v0], pThis->csp_mode)); 1072 1049 if (v0 == 0x83) 1073 1050 { 1074 1051 LogFlowFunc(("0x83[%d] -> %#x\n", pThis->csp_reg83w, pThis->csp_reg83[pThis->csp_reg83w % 4])); 1075 dsp_set_data(pThis, pThis->csp_reg83[pThis->csp_reg83w % 4]);1052 sb16DspSeData(pThis, pThis->csp_reg83[pThis->csp_reg83w % 4]); 1076 1053 pThis->csp_reg83w += 1; 1077 1054 } 1078 1055 else 1079 dsp_set_data(pThis, pThis->csp_regs[v0]);1056 sb16DspSeData(pThis, pThis->csp_regs[v0]); 1080 1057 break; 1081 1058 } 1082 1059 1083 1060 case 0x10: 1084 v0 = dsp_get_data(pThis);1061 v0 = sb16DspGetData(pThis); 1085 1062 LogFlowFunc(("cmd 0x10 d0=%#x\n", v0)); 1086 1063 break; 1087 1064 1088 1065 case 0x14: 1089 dma_cmd8(pDevIns, pThis, 0, dsp_get_lohi(pThis) + 1);1066 sb16DmaCmd8(pDevIns, pThis, pStream, 0, sb16DspGetLoHi(pThis) + 1); 1090 1067 break; 1091 1068 … … 1095 1072 1096 1073 case 0x40: /* Sets the timer constant; SB16 is able to use sample rates via 0x41 instead. */ 1097 p This->time_const = dsp_get_data(pThis);1098 LogFlowFunc(("set time const %d\n", p This->time_const));1074 pStream->time_const = sb16DspGetData(pThis); 1075 LogFlowFunc(("set time const %d\n", pStream->time_const)); 1099 1076 break; 1100 1077 … … 1107 1084 case 0x41: /* Sets the output rate (in Hz). */ 1108 1085 { 1109 p This->freq = dsp_get_hilo(pThis);1110 LogFlowFunc(("set freq %d\n", pThis->freq));1086 pStream->Cfg.Props.uHz = sb16DspGetHiLo(pThis); 1087 LogFlowFunc(("set freq to %RU16Hz\n", pStream->Cfg.Props.uHz)); 1111 1088 break; 1112 1089 } … … 1114 1091 case 0x48: 1115 1092 { 1116 p This->block_size = dsp_get_lohi(pThis) + 1;1117 LogFlowFunc(("set dma block len %d\n", p This->block_size));1093 pStream->cbDmaBlockSize = sb16DspGetLoHi(pThis) + 1; 1094 LogFlowFunc(("set dma block len %d\n", pStream->cbDmaBlockSize)); 1118 1095 break; 1119 1096 } … … 1131 1108 case 0x80: /* Sets the IRQ. */ 1132 1109 { 1133 sb16StreamTransferScheduleNext(pThis, pStream, dsp_get_lohi(pThis) + 1);1110 sb16StreamTransferScheduleNext(pThis, pStream, sb16DspGetLoHi(pThis) + 1); 1134 1111 break; 1135 1112 } … … 1137 1114 case 0xe0: 1138 1115 { 1139 v0 = dsp_get_data(pThis);1116 v0 = sb16DspGetData(pThis); 1140 1117 pThis->dsp_out_data_len = 0; 1141 1118 LogFlowFunc(("E0=%#x\n", v0)); 1142 dsp_set_data(pThis, ~v0);1119 sb16DspSeData(pThis, ~v0); 1143 1120 break; 1144 1121 } … … 1146 1123 case 0xe2: 1147 1124 { 1148 v0 = dsp_get_data(pThis);1125 v0 = sb16DspGetData(pThis); 1149 1126 LogFlowFunc(("E2=%#x\n", v0)); 1150 1127 break; … … 1152 1129 1153 1130 case 0xe4: 1154 pThis->test_reg = dsp_get_data(pThis);1131 pThis->test_reg = sb16DspGetData(pThis); 1155 1132 break; 1156 1133 1157 1134 case 0xf9: 1158 v0 = dsp_get_data(pThis);1135 v0 = sb16DspGetData(pThis); 1159 1136 switch (v0) 1160 1137 { 1161 1138 case 0x0e: 1162 dsp_set_data(pThis, 0xff);1139 sb16DspSeData(pThis, 0xff); 1163 1140 break; 1164 1141 1165 1142 case 0x0f: 1166 dsp_set_data(pThis, 0x07);1143 sb16DspSeData(pThis, 0x07); 1167 1144 break; 1168 1145 1169 1146 case 0x37: 1170 dsp_set_data(pThis, 0x38);1147 sb16DspSeData(pThis, 0x38); 1171 1148 break; 1172 1149 1173 1150 default: 1174 dsp_set_data(pThis, 0x00);1151 sb16DspSeData(pThis, 0x00); 1175 1152 break; 1176 1153 } … … 1187 1164 } 1188 1165 1189 static void sb16 CmdResetLegacy(PSB16STATE pThis)1166 static void sb16DspCmdResetLegacy(PSB16STATE pThis) 1190 1167 { 1191 1168 LogFlowFuncEnter(); 1192 1169 1193 pThis->freq = 11025; 1194 pThis->fmt_signed = 0; 1195 pThis->fmt_bits = 8; 1196 pThis->fmt_stereo = 0; 1170 /* Disable speaker(s). */ 1171 sb16SpeakerControl(pThis, false /* fOn */); 1197 1172 1198 1173 /* … … 1200 1175 */ 1201 1176 for (unsigned i = 0; i < SB16_MAX_STREAMS; i++) 1202 {1203 sb16StreamEnable(pThis, &pThis->aStreams[i], false /* fEnable */, false /* fForce */);1204 1177 sb16StreamReset(pThis, &pThis->aStreams[i]); 1205 } 1206 } 1207 1208 static void sb16CmdReset(PPDMDEVINS pDevIns, PSB16STATE pThis) 1209 { 1210 PDMDevHlpISASetIrq(pDevIns, pThis->irq, 0); 1211 if (pThis->dma_auto) 1212 { 1213 PDMDevHlpISASetIrq(pDevIns, pThis->irq, 1); 1214 PDMDevHlpISASetIrq(pDevIns, pThis->irq, 0); 1215 } 1216 1178 } 1179 1180 static void sb16DspCmdReset(PSB16STATE pThis) 1181 { 1217 1182 pThis->mixer_regs[0x82] = 0; 1218 pThis->dma_auto = 0;1219 1183 pThis->dsp_in_idx = 0; 1220 1184 pThis->dsp_out_data_len = 0; 1221 pThis->left_till_irq = 0;1222 1185 pThis->dsp_in_needed_bytes = 0; 1223 pThis->block_size = -1;1224 1186 pThis->nzero = 0; 1225 1187 pThis->highspeed = 0; … … 1227 1189 pThis->cmd = -1; 1228 1190 1229 dsp_set_data(pThis, 0xaa); 1230 sb16SpeakerControl(pThis, 0); 1231 1232 sb16Control(pDevIns, pThis, 0); 1233 sb16CmdResetLegacy(pThis); 1191 sb16DspSeData(pThis, 0xaa); 1192 1193 sb16DspCmdResetLegacy(pThis); 1234 1194 } 1235 1195 … … 1241 1201 PSB16STATE pThis = PDMDEVINS_2_DATA(pDevIns, PSB16STATE); 1242 1202 RT_NOREF(pvUser, cb); 1203 1204 /** @todo Figure out how we can distinguish between streams. DSP port #, e.g. 0x220? */ 1205 PSB16STREAM pStream = &pThis->aStreams[SB16_IDX_OUT]; 1243 1206 1244 1207 LogFlowFunc(("write %#x <- %#x\n", offPort, u32)); … … 1255 1218 { 1256 1219 pThis->highspeed = 0; 1257 PDMDevHlpISASetIrq(pThis->pDevInsR3, p This->irq, 0);1258 sb16 Control(pDevIns, pThis, 0);1220 PDMDevHlpISASetIrq(pThis->pDevInsR3, pStream->HwCfgRuntime.uIrq, 0); 1221 sb16StreamControl(pDevIns, pThis, pStream, false /* fRun */); 1259 1222 } 1260 1223 else 1261 sb16 CmdReset(pDevIns,pThis);1224 sb16DspCmdReset(pThis); 1262 1225 } 1263 1226 pThis->v2x6 = 0; … … 1275 1238 1276 1239 case 0xb8: /* Panic */ 1277 sb16 CmdReset(pDevIns,pThis);1240 sb16DspCmdReset(pThis); 1278 1241 break; 1279 1242 1280 1243 case 0x39: 1281 dsp_set_data(pThis, 0x38);1282 sb16 CmdReset(pDevIns,pThis);1244 sb16DspSeData(pThis, 0x38); 1245 sb16DspCmdReset(pThis); 1283 1246 pThis->v2x6 = 0x39; 1284 1247 break; … … 1297 1260 if (0 == pThis->dsp_in_needed_bytes) 1298 1261 { 1299 sb16HandleCommand(pDevIns, pThis, u32); 1300 #if 0 1301 if (0 == pThis->needed_bytes) { 1302 log_dsp (pThis); 1303 } 1304 #endif 1262 sb16DspCmdLookup(pDevIns, pThis, pStream, u32); 1305 1263 } 1306 1264 else … … 1316 1274 { 1317 1275 pThis->dsp_in_needed_bytes = 0; 1318 dsp_cmd_complete(pDevIns, pThis); 1319 #if 0 1320 log_dsp (pThis); 1321 #endif 1276 sb16DspCmdComplete(pDevIns, pThis); 1322 1277 } 1323 1278 } … … 1339 1294 static DECLCALLBACK(VBOXSTRICTRC) sb16IoPortDspRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) 1340 1295 { 1296 RT_NOREF(pvUser, cb); 1297 1341 1298 PSB16STATE pThis = PDMDEVINS_2_DATA(pDevIns, PSB16STATE); 1299 1342 1300 uint32_t retval; 1343 1301 int ack = 0; 1344 RT_NOREF(pvUser, cb); 1345 1302 1303 /** @todo Figure out how we can distinguish between streams. */ 1304 PSB16STREAM pStream = &pThis->aStreams[SB16_IDX_OUT]; 1346 1305 1347 1306 /** @todo reject non-byte access? … … 1370 1329 1371 1330 case 6: /* 0 can write */ 1372 retval = p This->can_write ? 0 : 0x80;1331 retval = pStream->can_write ? 0 : 0x80; 1373 1332 break; 1374 1333 … … 1384 1343 ack = 1; 1385 1344 pThis->mixer_regs[0x82] &= ~1; 1386 PDMDevHlpISASetIrq(pThis->pDevInsR3, p This->irq, 0);1345 PDMDevHlpISASetIrq(pThis->pDevInsR3, pStream->HwCfgRuntime.uIrq, 0); 1387 1346 } 1388 1347 break; … … 1394 1353 ack = 1; 1395 1354 pThis->mixer_regs[0x82] &= ~2; 1396 PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 0);1355 PDMDevHlpISASetIrq(pThis->pDevInsR3, pStream->HwCfgRuntime.uIrq, 0); 1397 1356 } 1398 1357 break; … … 1570 1529 } 1571 1530 1572 static int mixer_write_indexb(PSB16STATE pThis, uint8_t val) 1573 { 1531 static int sb16MixerWriteIndex(PSB16STATE pThis, PSB16STREAM pStream, uint8_t val) 1532 { 1533 RT_NOREF(pStream); 1574 1534 pThis->mixer_nreg = val; 1575 1535 return VINF_SUCCESS; … … 1621 1581 1622 1582 1623 static int mixer_write_datab(PSB16STATE pThis, uint8_t val)1583 static int sb16MixerWriteData(PSB16STATE pThis, PSB16STREAM pStream, uint8_t val) 1624 1584 { 1625 1585 bool fUpdateMaster = false; 1626 1586 bool fUpdateStream = false; 1627 1587 1628 LogFlowFunc((" sb16IoPortMixerWrite[%#x] <- %#x\n", pThis->mixer_nreg, val));1588 LogFlowFunc(("[%#x] <- %#x\n", pThis->mixer_nreg, val)); 1629 1589 1630 1590 switch (pThis->mixer_nreg) … … 1706 1666 { 1707 1667 int irq = irq_of_magic(val); 1708 Log FlowFunc(("setting irq to %d (val=%#x)\n", irq, val));1668 LogRelMax2(64, ("SB16: Setting IRQ to %d\n", irq)); 1709 1669 if (irq > 0) 1710 p This->irq = irq;1670 pStream->HwCfgRuntime.uIrq = irq; 1711 1671 break; 1712 1672 } … … 1714 1674 case 0x81: 1715 1675 { 1716 int dma, hdma; 1717 1718 dma = lsbindex (val & 0xf); 1719 hdma = lsbindex (val & 0xf0); 1720 if (dma != pThis->dma || hdma != pThis->hdma) 1721 LogFlow(("SB16: attempt to change DMA 8bit %d(%d), 16bit %d(%d) (val=%#x)\n", 1722 dma, pThis->dma, hdma, pThis->hdma, val)); 1676 int dma = lsbindex(val & 0xf); 1677 int hdma = lsbindex(val & 0xf0); 1678 if ( dma != pStream->HwCfgRuntime.uDmaChanLow 1679 || hdma != pStream->HwCfgRuntime.uDmaChanHigh) 1680 { 1681 LogRelMax2(64, ("SB16: Attempt to change DMA 8bit %d(%d), 16bit %d(%d)\n", 1682 dma, pStream->HwCfgRuntime.uDmaChanLow, hdma, pStream->HwCfgRuntime.uDmaChanHigh)); 1683 } 1723 1684 #if 0 1724 p This->dma = dma;1725 p This->hdma = hdma;1685 pStream->dma = dma; 1686 pStream->hdma = hdma; 1726 1687 #endif 1727 1688 break; … … 1729 1690 1730 1691 case 0x82: 1731 Log FlowFunc(("attempt to write into IRQ status register (val=%#x)\n", val));1692 LogRelMax2(64, ("SB16: Attempt to write into IRQ status register to %#x\n", val)); 1732 1693 return VINF_SUCCESS; 1733 1694 … … 1757 1718 PSB16STATE pThis = PDMDEVINS_2_DATA(pDevIns, PSB16STATE); 1758 1719 RT_NOREF(pvUser); 1720 1721 /** @todo Figure out how we can distinguish between streams. */ 1722 PSB16STREAM pStream = &pThis->aStreams[SB16_IDX_OUT]; 1759 1723 1760 1724 switch (cb) … … 1764 1728 { 1765 1729 case 0: 1766 mixer_write_indexb(pThis, u32);1730 sb16MixerWriteIndex(pThis, pStream, u32); 1767 1731 break; 1768 1732 case 1: 1769 mixer_write_datab(pThis, u32);1733 sb16MixerWriteData(pThis, pStream, u32); 1770 1734 break; 1771 1735 default: … … 1774 1738 break; 1775 1739 case 2: 1776 mixer_write_indexb(pThis, u32 & 0xff);1777 mixer_write_datab(pThis, (u32 >> 8) & 0xff);1740 sb16MixerWriteIndex(pThis, pStream, u32 & 0xff); 1741 sb16MixerWriteData(pThis, pStream, (u32 >> 8) & 0xff); 1778 1742 break; 1779 1743 default: … … 1825 1789 int till, copy, free; 1826 1790 1827 if (p This->block_size <= 0)1828 { 1829 LogFlowFunc(("invalid block size=%d uChannel=%d off=%d cb=%d\n", p This->block_size, uChannel, off, cb));1791 if (pStream->cbDmaBlockSize <= 0) 1792 { 1793 LogFlowFunc(("invalid block size=%d uChannel=%d off=%d cb=%d\n", pStream->cbDmaBlockSize, uChannel, off, cb)); 1830 1794 return off; 1831 1795 } 1832 1796 1833 if (p This->left_till_irq< 0)1834 p This->left_till_irq = pThis->block_size;1797 if (pStream->cbDmaLeft < 0) 1798 pStream->cbDmaLeft = pStream->cbDmaBlockSize; 1835 1799 1836 1800 free = cb; 1837 1801 1838 1802 copy = free; 1839 till = p This->left_till_irq;1803 till = pStream->cbDmaLeft; 1840 1804 1841 1805 Log4Func(("pos=%d %d, till=%d, len=%d\n", off, free, till, cb)); … … 1843 1807 if (copy >= till) 1844 1808 { 1845 if (0 == p This->dma_auto)1809 if (0 == pStream->dma_auto) 1846 1810 { 1847 1811 copy = till; … … 1849 1813 else 1850 1814 { 1851 if (copy >= till + p This->block_size)1815 if (copy >= till + pStream->cbDmaBlockSize) 1852 1816 copy = till; /* Make sure we won't skip IRQs. */ 1853 1817 } … … 1862 1826 /** @todo Convert the rest to uin32_t / size_t. */ 1863 1827 off = (off + (int)written) % cb; 1864 p This->left_till_irq-= (int)written; /** @todo r=andy left_till_irq can be < 0. Correct? Revisit this. */1828 pStream->cbDmaLeft -= (int)written; /** @todo r=andy left_till_irq can be < 0. Correct? Revisit this. */ 1865 1829 1866 1830 Log3Func(("pos %d/%d, free=%d, till=%d, copy=%d, written=%RU32, block_size=%d\n", 1867 off, cb, free, p This->left_till_irq, copy, copy, pThis->block_size));1868 1869 if (p This->left_till_irq<= 0)1831 off, cb, free, pStream->cbDmaLeft, copy, copy, pStream->cbDmaBlockSize)); 1832 1833 if (pStream->cbDmaLeft <= 0) 1870 1834 { 1871 1835 pThis->mixer_regs[0x82] |= (uChannel & 4) ? 2 : 1; 1872 1836 1873 PDMDevHlpISASetIrq(pThis->pDevInsR3, p This->irq, 1);1874 1875 if (0 == p This->dma_auto) /** @todo r=andy BUGBUG Why do we first assert the IRQ if dma_auto is 0? Revisit this. */1837 PDMDevHlpISASetIrq(pThis->pDevInsR3, pStream->HwCfgRuntime.uIrq, 1); 1838 1839 if (0 == pStream->dma_auto) /** @todo r=andy BUGBUG Why do we first assert the IRQ if dma_auto is 0? Revisit this. */ 1876 1840 { 1877 sb16 Control(pDevIns, pThis, 0);1841 sb16StreamControl(pDevIns, pThis, pStream, false /* fRun */); 1878 1842 sb16SpeakerControl(pThis, 0); 1879 1843 } 1880 1844 } 1881 1845 1882 while (p This->left_till_irq<= 0)1883 p This->left_till_irq += pThis->block_size;1846 while (pStream->cbDmaLeft <= 0) 1847 pStream->cbDmaLeft += pStream->cbDmaBlockSize; 1884 1848 1885 1849 return off; … … 1897 1861 { 1898 1862 PSB16STATE pThis = PDMDEVINS_2_DATA(pDevIns, PSB16STATE); 1899 RT_NOREF(pvUser, hTimer); 1863 RT_NOREF(hTimer, pThis); 1864 1865 PSB16STREAM pStream = (PSB16STREAM)pvUser; 1866 AssertPtrReturnVoid(pStream); 1900 1867 1901 1868 LogFlowFuncEnter(); 1902 1869 1903 p This->can_write = 1;1904 PDMDevHlpISASetIrq(pDevIns, p This->irq, 1);1870 pStream->can_write = 1; 1871 PDMDevHlpISASetIrq(pDevIns, pStream->HwCfgRuntime.uIrq, 1); 1905 1872 } 1906 1873 … … 1923 1890 static DECLCALLBACK(void) sb16TimerIO(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, void *pvUser) 1924 1891 { 1892 PSB16STATE pThis = PDMDEVINS_2_DATA(pDevIns, PSB16STATE); 1893 STAM_PROFILE_START(&pThis->StatTimerIO, a); 1894 1925 1895 PSB16STREAM pStream = (PSB16STREAM)pvUser; 1926 1896 AssertPtrReturnVoid(pStream); 1927 1928 PSB16STATE pThis = PDMDEVINS_2_DATA(pDevIns, PSB16STATE);1929 STAM_PROFILE_START(&pThis->StatTimerIO, a);1930 1897 AssertReturnVoid(hTimer == pStream->hTimerIO); 1931 1898 … … 2400 2367 LogFlowFuncEnter(); 2401 2368 2369 PDMDevHlpISASetIrq(pThis->pDevInsR3, pStream->HwCfgRuntime.uIrq, 0); 2370 if (pStream->dma_auto) 2371 { 2372 PDMDevHlpISASetIrq(pThis->pDevInsR3, pStream->HwCfgRuntime.uIrq, 1); 2373 PDMDevHlpISASetIrq(pThis->pDevInsR3, pStream->HwCfgRuntime.uIrq, 0); 2374 2375 pStream->dma_auto = 0; 2376 } 2377 2378 sb16StreamControl(pThis->pDevInsR3, pThis, pStream, false /* fRun */); 2379 sb16StreamEnable(pThis, pStream, false /* fEnable */, false /* fForce */); 2380 2402 2381 switch (pStream->uIdx) 2403 2382 { … … 2408 2387 pStream->Cfg.enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED; 2409 2388 2410 PDMAudioPropsInit(&pStream->Cfg.Props, 1 /* 8-bit */, false /* fSigned */, 1 /* Mono */, pThis->freq);2389 PDMAudioPropsInit(&pStream->Cfg.Props, 1 /* 8-bit */, false /* fSigned */, 1 /* Mono */, 11025 /* uHz */); 2411 2390 RTStrCopy(pStream->Cfg.szName, sizeof(pStream->Cfg.szName), "Output"); 2412 2391 … … 2418 2397 break; 2419 2398 } 2399 2400 pStream->cbDmaLeft = 0; 2401 pStream->cbDmaBlockSize = 0; 2402 pStream->can_write = 1; /** @ŧodo r=andy BUGBUG Figure out why we (still) need this. */ 2420 2403 2421 2404 /** @todo Also reset corresponding DSP values here? */ … … 2436 2419 LogFlowFuncEnter(); 2437 2420 2438 PDMAUDIOSTREAMCFG Cfg; 2439 RT_ZERO(Cfg); 2440 2441 /** @todo Implement mixer sink selection (and it's in/out + destination mapping) here once we add more streams. */ 2442 PDMAudioPropsInit(&Cfg.Props, pThis->fmt_bits / 8, pThis->fmt_signed != 0, 1 << pThis->fmt_stereo, pThis->freq); 2443 2444 /* Bail out early if the PCM properties did not change. */ 2445 if (PDMAudioPropsAreEqual(&Cfg.Props, &pStream->Cfg.Props)) 2446 return VINF_SUCCESS; 2421 PDMAudioPropsInit(&pStream->Cfg.Props, 2422 pStream->Cfg.Props.cbSampleX, 2423 pStream->Cfg.Props.fSigned, 2424 pStream->Cfg.Props.cChannelsX, 2425 pStream->Cfg.Props.uHz); 2426 2427 AssertReturn(PDMAudioPropsAreValid(&pStream->Cfg.Props), VERR_INVALID_PARAMETER); 2447 2428 2448 2429 PDMAUDIODSTSRCUNION dstSrc; … … 2453 2434 case SB16_IDX_OUT: 2454 2435 { 2455 Cfg.enmDir = PDMAUDIODIR_OUT;2456 Cfg.u.enmDst = PDMAUDIOPLAYBACKDST_FRONT;2457 Cfg.enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;2458 2459 RTStrCopy( Cfg.szName, sizeof(Cfg.szName), "Output");2436 pStream->Cfg.enmDir = PDMAUDIODIR_OUT; 2437 pStream->Cfg.u.enmDst = PDMAUDIOPLAYBACKDST_FRONT; 2438 pStream->Cfg.enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED; 2439 2440 RTStrCopy(pStream->Cfg.szName, sizeof(pStream->Cfg.szName), "Output"); 2460 2441 2461 2442 dstSrc.enmDst = PDMAUDIOPLAYBACKDST_FRONT; … … 2469 2450 } 2470 2451 2471 LogRel2(("SB16: (Re-)Opening stream '%s' (%RU32Hz, %RU8 channels, %s%RU8)\n", Cfg.szName, Cfg.Props.uHz, 2472 PDMAudioPropsChannels(&Cfg.Props), Cfg.Props.fSigned ? "S" : "U", PDMAudioPropsSampleBits(&Cfg.Props))); 2473 2474 int rc = PDMAudioStrmCfgCopy(&pStream->Cfg, &Cfg); 2475 if (RT_FAILURE(rc)) 2476 return rc; 2452 LogRel2(("SB16: (Re-)Opening stream '%s' (%RU32Hz, %RU8 channels, %s%RU8)\n", pStream->Cfg.szName, pStream->Cfg.Props.uHz, 2453 PDMAudioPropsChannels(&pStream->Cfg.Props), pStream->Cfg.Props.fSigned ? "S" : "U", 2454 PDMAudioPropsSampleBits(&pStream->Cfg.Props))); 2477 2455 2478 2456 /* (Re-)create the stream's internal ring buffer. */ … … 2483 2461 } 2484 2462 2485 const uint32_t cbCircBuf = PDMAudioPropsMilliToBytes(&pStream->Cfg.Props, 2 * 10 /* ms */); 2486 2487 rc = RTCircBufCreate(&pStream->State.pCircBuf, cbCircBuf); 2463 const uint32_t cbCircBuf 2464 = PDMAudioPropsMilliToBytes(&pStream->Cfg.Props, (RT_MS_1SEC / pStream->uTimerHz) * 2 /* Use double buffering here */); 2465 2466 int rc = RTCircBufCreate(&pStream->State.pCircBuf, cbCircBuf); 2488 2467 AssertRCReturn(rc, rc); 2489 2468 2490 2469 /* Set scheduling hint (if available). */ 2491 2470 if (pStream->cTicksTimerIOInterval) 2492 pStream->Cfg.Device.cMsSchedulingHint = 1000 /* ms */ 2493 / ( PDMDevHlpTimerGetFreq(pDevIns, pStream->hTimerIO) 2494 / RT_MIN(pStream->cTicksTimerIOInterval, 1)); 2471 pStream->Cfg.Device.cMsSchedulingHint = RT_MS_1SEC / pStream->uTimerHz; 2495 2472 2496 2473 PAUDMIXSINK pMixerSink = sb16StreamIndexToSink(pThis, pStream->uIdx); … … 2545 2522 RT_NOREF(pStream); 2546 2523 2547 #if 02548 uint32_t const freq = pThis->freq > 0 ? pThis->freq : 11025;2549 uint32_t const bytes = cSamples << pThis->fmt_stereo << (pThis->fmt_bits == 16 ? 1 : 0);2550 uint64_t const uTimerHz = PDMDevHlpTimerGetFreq(pThis->pDevInsR3, pThis->hTimerIRQ);2551 uint64_t const cTicks = (bytes * uTimerHz) / freq;2552 #endif2553 2554 2524 uint64_t const uTimerHz = PDMDevHlpTimerGetFreq(pThis->pDevInsR3, pThis->hTimerIRQ); 2555 2525 … … 2562 2532 { 2563 2533 LogFlowFunc(("IRQ\n")); 2564 PDMDevHlpISASetIrq(pThis->pDevInsR3, p This->irq, 1);2534 PDMDevHlpISASetIrq(pThis->pDevInsR3, pStream->HwCfgRuntime.uIrq, 1); 2565 2535 } 2566 2536 else … … 2629 2599 static DECLCALLBACK(int) sb16LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass) 2630 2600 { 2601 RT_NOREF(uPass); 2602 2631 2603 PSB16STATE pThis = PDMDEVINS_2_DATA(pDevIns, PSB16STATE); 2632 2604 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; 2633 RT_NOREF(uPass); 2634 2635 pHlp->pfnSSMPutS32(pSSM, pThis->irqCfg); 2636 pHlp->pfnSSMPutS32(pSSM, pThis->dmaCfg); 2637 pHlp->pfnSSMPutS32(pSSM, pThis->hdmaCfg); 2638 pHlp->pfnSSMPutS32(pSSM, pThis->portCfg); 2639 pHlp->pfnSSMPutS32(pSSM, pThis->verCfg); 2605 2606 /** Currently the saved state only contains the one-and-only output stream. */ 2607 PSB16STREAM pStream = &pThis->aStreams[SB16_IDX_OUT]; 2608 2609 pHlp->pfnSSMPutS32(pSSM, pStream->HwCfgDefault.uIrq); 2610 pHlp->pfnSSMPutS32(pSSM, pStream->HwCfgDefault.uDmaChanLow); 2611 pHlp->pfnSSMPutS32(pSSM, pStream->HwCfgDefault.uDmaChanHigh); 2612 pHlp->pfnSSMPutS32(pSSM, pStream->HwCfgDefault.uPort); 2613 pHlp->pfnSSMPutS32(pSSM, pStream->HwCfgDefault.uVer); 2640 2614 return VINF_SSM_DONT_CALL_AGAIN; 2641 2615 } … … 2646 2620 static int sb16Save(PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM, PSB16STATE pThis) 2647 2621 { 2648 pHlp->pfnSSMPutS32(pSSM, pThis->irq); 2649 pHlp->pfnSSMPutS32(pSSM, pThis->dma); 2650 pHlp->pfnSSMPutS32(pSSM, pThis->hdma); 2651 pHlp->pfnSSMPutS32(pSSM, pThis->port); 2652 pHlp->pfnSSMPutS32(pSSM, pThis->ver); 2622 /** Currently the saved state only contains the one-and-only output stream. */ 2623 PSB16STREAM pStream = &pThis->aStreams[SB16_IDX_OUT]; 2624 2625 pHlp->pfnSSMPutS32(pSSM, pStream->HwCfgRuntime.uIrq); 2626 pHlp->pfnSSMPutS32(pSSM, pStream->HwCfgRuntime.uDmaChanLow); 2627 pHlp->pfnSSMPutS32(pSSM, pStream->HwCfgRuntime.uDmaChanHigh); 2628 pHlp->pfnSSMPutS32(pSSM, pStream->HwCfgRuntime.uPort); 2629 pHlp->pfnSSMPutS32(pSSM, pStream->HwCfgRuntime.uVer); 2653 2630 pHlp->pfnSSMPutS32(pSSM, pThis->dsp_in_idx); 2654 2631 pHlp->pfnSSMPutS32(pSSM, pThis->dsp_out_data_len); 2655 pHlp->pfnSSMPutS32(pSSM, pThis->fmt_stereo); 2656 pHlp->pfnSSMPutS32(pSSM, pThis->fmt_signed); 2657 pHlp->pfnSSMPutS32(pSSM, pThis->fmt_bits); 2658 2659 pHlp->pfnSSMPutU32(pSSM, pThis->fmt); 2660 2661 pHlp->pfnSSMPutS32(pSSM, pThis->dma_auto); 2662 pHlp->pfnSSMPutS32(pSSM, pThis->block_size); 2663 pHlp->pfnSSMPutS32(pSSM, pThis->fifo); 2664 pHlp->pfnSSMPutS32(pSSM, pThis->freq); 2665 pHlp->pfnSSMPutS32(pSSM, pThis->time_const); 2666 pHlp->pfnSSMPutS32(pSSM, pThis->speaker); 2632 2633 /** Currently the saved state only contains the one-and-only output stream. */ 2634 pHlp->pfnSSMPutS32(pSSM, pStream->Cfg.Props.cChannelsX >= 2 ? 1 : 0); 2635 pHlp->pfnSSMPutS32(pSSM, pStream->Cfg.Props.fSigned ? 1 : 0); 2636 pHlp->pfnSSMPutS32(pSSM, pStream->Cfg.Props.cbSampleX * 8 /* Convert bytes to bits */); 2637 pHlp->pfnSSMPutU32(pSSM, 0); /* Legacy; was PDMAUDIOFMT, unused now. */ 2638 2639 pHlp->pfnSSMPutS32(pSSM, pStream->dma_auto); 2640 pHlp->pfnSSMPutS32(pSSM, pStream->cbDmaBlockSize); 2641 pHlp->pfnSSMPutS32(pSSM, pStream->fifo); 2642 pHlp->pfnSSMPutS32(pSSM, pStream->Cfg.Props.uHz); 2643 pHlp->pfnSSMPutS32(pSSM, pStream->time_const); 2644 pHlp->pfnSSMPutS32(pSSM, 0); /* Legacy; was speaker control (on/off) for output stream. */ 2667 2645 pHlp->pfnSSMPutS32(pSSM, pThis->dsp_in_needed_bytes); 2668 2646 pHlp->pfnSSMPutS32(pSSM, pThis->cmd); 2669 pHlp->pfnSSMPutS32(pSSM, p This->use_hdma);2647 pHlp->pfnSSMPutS32(pSSM, pStream->fDmaUseHigh); 2670 2648 pHlp->pfnSSMPutS32(pSSM, pThis->highspeed); 2671 pHlp->pfnSSMPutS32(pSSM, p This->can_write);2649 pHlp->pfnSSMPutS32(pSSM, pStream->can_write); 2672 2650 pHlp->pfnSSMPutS32(pSSM, pThis->v2x6); 2673 2651 … … 2688 2666 2689 2667 pHlp->pfnSSMPutS32(pSSM, pThis->nzero); 2690 pHlp->pfnSSMPutS32(pSSM, pThis->left_till_irq); 2691 pHlp->pfnSSMPutS32(pSSM, pThis->dma_running); 2692 pHlp->pfnSSMPutS32(pSSM, pThis->bytes_per_second); 2693 pHlp->pfnSSMPutS32(pSSM, pThis->align); 2668 pHlp->pfnSSMPutS32(pSSM, pStream->cbDmaLeft); 2669 pHlp->pfnSSMPutS32(pSSM, pStream->State.fEnabled ? 1 : 0); 2670 /* The stream's bitrate. Needed for backwards (legacy) compatibility. */ 2671 pHlp->pfnSSMPutS32(pSSM, AudioHlpCalcBitrate(pThis->aStreams[SB16_IDX_OUT].Cfg.Props.cbSampleX * 8, 2672 pThis->aStreams[SB16_IDX_OUT].Cfg.Props.uHz, 2673 pThis->aStreams[SB16_IDX_OUT].Cfg.Props.cChannelsX)); 2674 /* Block size alignment, superfluous and thus not saved anymore. Needed for backwards (legacy) compatibility. */ 2675 pHlp->pfnSSMPutS32(pSSM, 0); 2694 2676 2695 2677 pHlp->pfnSSMPutS32(pSSM, pThis->mixer_nreg); … … 2716 2698 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; 2717 2699 2718 pHlp->pfnSSMGetS32(pSSM, &pThis->irq); 2719 pHlp->pfnSSMGetS32(pSSM, &pThis->dma); 2720 pHlp->pfnSSMGetS32(pSSM, &pThis->hdma); 2721 pHlp->pfnSSMGetS32(pSSM, &pThis->port); 2722 pHlp->pfnSSMGetS32(pSSM, &pThis->ver); 2700 /** Currently the saved state only contains the one-and-only output stream. */ 2701 PSB16STREAM pStream = &pThis->aStreams[SB16_IDX_OUT]; 2702 2703 int32_t s32Tmp; 2704 pHlp->pfnSSMGetS32(pSSM, &s32Tmp); 2705 pStream->HwCfgRuntime.uIrq = s32Tmp; 2706 pHlp->pfnSSMGetS32(pSSM, &s32Tmp); 2707 pStream->HwCfgRuntime.uDmaChanLow = s32Tmp; 2708 pHlp->pfnSSMGetS32(pSSM, &s32Tmp); 2709 pStream->HwCfgRuntime.uDmaChanHigh = s32Tmp; 2710 pHlp->pfnSSMGetS32(pSSM, &s32Tmp); /* Port */ 2711 pStream->HwCfgRuntime.uPort = s32Tmp; 2712 pHlp->pfnSSMGetS32(pSSM, &s32Tmp); /* Ver */ 2713 pStream->HwCfgRuntime.uVer = s32Tmp; 2723 2714 pHlp->pfnSSMGetS32(pSSM, &pThis->dsp_in_idx); 2724 2715 pHlp->pfnSSMGetS32(pSSM, &pThis->dsp_out_data_len); 2725 pHlp->pfnSSMGetS32(pSSM, &pThis->fmt_stereo); 2726 pHlp->pfnSSMGetS32(pSSM, &pThis->fmt_signed); 2727 pHlp->pfnSSMGetS32(pSSM, &pThis->fmt_bits); 2728 2729 PDMDEVHLP_SSM_GET_ENUM32_RET(pHlp, pSSM, pThis->fmt, PDMAUDIOFMT); 2730 2731 pHlp->pfnSSMGetS32(pSSM, &pThis->dma_auto); 2732 pHlp->pfnSSMGetS32(pSSM, &pThis->block_size); 2733 pHlp->pfnSSMGetS32(pSSM, &pThis->fifo); 2734 pHlp->pfnSSMGetS32(pSSM, &pThis->freq); 2735 pHlp->pfnSSMGetS32(pSSM, &pThis->time_const); 2736 pHlp->pfnSSMGetS32(pSSM, &pThis->speaker); 2716 pHlp->pfnSSMGetS32(pSSM, &s32Tmp); /* Channels */ 2717 pStream->Cfg.Props.cChannelsX = (uint8_t)s32Tmp; 2718 pHlp->pfnSSMGetS32(pSSM, &s32Tmp); /* Signed */ 2719 pStream->Cfg.Props.fSigned = s32Tmp == 0 ? false : true; 2720 pHlp->pfnSSMGetS32(pSSM, &s32Tmp); 2721 pStream->Cfg.Props.cbSampleX = s32Tmp / 8; /* Convert bits to bytes. */ 2722 pHlp->pfnSSMSkip (pSSM, sizeof(int32_t)); /* Legacy; was PDMAUDIOFMT, unused now. */ 2723 pHlp->pfnSSMGetS32(pSSM, &pStream->dma_auto); 2724 pHlp->pfnSSMGetS32(pSSM, &pThis->aStreams[SB16_IDX_OUT].cbDmaBlockSize); 2725 pHlp->pfnSSMGetS32(pSSM, &pStream->fifo); 2726 pHlp->pfnSSMGetS32(pSSM, &s32Tmp); pStream->Cfg.Props.uHz = s32Tmp; 2727 pHlp->pfnSSMGetS32(pSSM, &pStream->time_const); 2728 pHlp->pfnSSMSkip (pSSM, sizeof(int32_t)); /* Legacy; was speaker (on / off) for output stream. */ 2737 2729 pHlp->pfnSSMGetS32(pSSM, &pThis->dsp_in_needed_bytes); 2738 2730 pHlp->pfnSSMGetS32(pSSM, &pThis->cmd); 2739 pHlp->pfnSSMGetS32(pSSM, &p This->use_hdma);2731 pHlp->pfnSSMGetS32(pSSM, &pStream->fDmaUseHigh); 2740 2732 pHlp->pfnSSMGetS32(pSSM, &pThis->highspeed); 2741 pHlp->pfnSSMGetS32(pSSM, &p This->can_write);2733 pHlp->pfnSSMGetS32(pSSM, &pStream->can_write); 2742 2734 pHlp->pfnSSMGetS32(pSSM, &pThis->v2x6); 2743 2735 … … 2758 2750 2759 2751 pHlp->pfnSSMGetS32(pSSM, &pThis->nzero); 2760 pHlp->pfnSSMGetS32(pSSM, &pThis->left_till_irq); 2761 pHlp->pfnSSMGetS32(pSSM, &pThis->dma_running); 2762 pHlp->pfnSSMGetS32(pSSM, &pThis->bytes_per_second); 2763 pHlp->pfnSSMGetS32(pSSM, &pThis->align); 2752 pHlp->pfnSSMGetS32(pSSM, &pStream->cbDmaLeft); 2753 pHlp->pfnSSMGetS32(pSSM, &s32Tmp); 2754 pStream->State.fEnabled = s32Tmp == 0 ? false: true; 2755 pHlp->pfnSSMSkip (pSSM, sizeof(int32_t)); /* Legacy; was the output stream's current bitrate (in bytes). */ 2756 pHlp->pfnSSMSkip (pSSM, sizeof(int32_t)); /* Legacy; was the output stream's DMA block alignment. */ 2764 2757 2765 2758 int32_t mixer_nreg = 0; … … 2770 2763 AssertRCReturn(rc, rc); 2771 2764 2772 if (pThis->dma_running) 2773 { 2774 sb16Control(pDevIns, pThis, 1); 2775 sb16SpeakerControl(pThis, pThis->speaker); 2776 } 2765 if (pStream->State.fEnabled) 2766 sb16StreamControl(pDevIns, pThis, pStream, true /* fRun */); 2777 2767 2778 2768 /* Update the master (mixer) and PCM out volumes. */ … … 2796 2786 if (uVersion > SB16_SAVE_STATE_VERSION_VBOX_30) 2797 2787 { 2788 /** Currently the saved state only contains the one-and-only output stream. */ 2789 PSB16STREAM pStream = &pThis->aStreams[SB16_IDX_OUT]; 2790 2798 2791 int32_t irq; 2799 2792 pHlp->pfnSSMGetS32(pSSM, &irq); … … 2808 2801 AssertRCReturn (rc, rc); 2809 2802 2810 if ( irq != p This->irqCfg2811 || dma != p This->dmaCfg2812 || hdma != p This->hdmaCfg2813 || port != p This->portCfg2814 || ver != p This->verCfg)2803 if ( irq != pStream->HwCfgDefault.uIrq 2804 || dma != pStream->HwCfgDefault.uDmaChanLow 2805 || hdma != pStream->HwCfgDefault.uDmaChanHigh 2806 || port != pStream->HwCfgDefault.uPort 2807 || ver != pStream->HwCfgDefault.uVer) 2815 2808 { 2816 2809 return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS, 2817 2810 N_("config changed: irq=%x/%x dma=%x/%x hdma=%x/%x port=%x/%x ver=%x/%x (saved/config)"), 2818 irq, p This->irqCfg,2819 dma, p This->dmaCfg,2820 hdma, p This->hdmaCfg,2821 port, p This->portCfg,2822 ver, p This->verCfg);2811 irq, pStream->HwCfgDefault.uIrq, 2812 dma, pStream->HwCfgDefault.uDmaChanLow, 2813 hdma, pStream->HwCfgDefault.uDmaChanHigh, 2814 port, pStream->HwCfgDefault.uPort, 2815 ver, pStream->HwCfgDefault.uVer); 2823 2816 } 2824 2817 } … … 3017 3010 LogRel2(("SB16: Reset\n")); 3018 3011 3019 /* Bring back the device to initial state, and especially make3020 * sure there's no interrupt or DMA activity.3021 */3022 PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 0);3023 3024 3012 pThis->mixer_regs[0x82] = 0; 3025 3013 pThis->csp_regs[5] = 1; 3026 3014 pThis->csp_regs[9] = 0xf8; 3027 3015 3028 pThis->dma_auto = 0;3029 3016 pThis->dsp_in_idx = 0; 3030 3017 pThis->dsp_out_data_len = 0; 3031 pThis->left_till_irq = 0;3032 3018 pThis->dsp_in_needed_bytes = 0; 3033 pThis->block_size = -1;3034 3019 pThis->nzero = 0; 3035 3020 pThis->highspeed = 0; … … 3039 3024 sb16MixerReset(pThis); 3040 3025 sb16SpeakerControl(pThis, 0); 3041 sb16Control(pDevIns, pThis, 0); 3042 sb16CmdResetLegacy(pThis); 3026 sb16DspCmdResetLegacy(pThis); 3043 3027 } 3044 3028 … … 3131 3115 * Validate and read config data. 3132 3116 */ 3117 /* Note: For now we only support the one-and-only output stream. */ 3118 PSB16STREAM pStream = &pThis->aStreams[SB16_IDX_OUT]; 3119 3133 3120 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "IRQ|DMA|DMA16|Port|Version|TimerHz|DebugEnabled|DebugPathOut", ""); 3134 int rc = pHlp->pfnCFGMQuery SIntDef(pCfg, "IRQ", &pThis->irq, 5);3121 int rc = pHlp->pfnCFGMQueryU8Def(pCfg, "IRQ", &pStream->HwCfgDefault.uIrq, 5); 3135 3122 if (RT_FAILURE(rc)) 3136 3123 return PDMDEV_SET_ERROR(pDevIns, rc, N_("SB16 configuration error: Failed to get the \"IRQ\" value")); 3137 p This->irqCfg = pThis->irq;3138 3139 rc = pHlp->pfnCFGMQuery SIntDef(pCfg, "DMA", &pThis->dma, 1);3124 pStream->HwCfgRuntime.uIrq = pStream->HwCfgDefault.uIrq; 3125 3126 rc = pHlp->pfnCFGMQueryU8Def(pCfg, "DMA", &pStream->HwCfgDefault.uDmaChanLow, 1); 3140 3127 if (RT_FAILURE(rc)) 3141 3128 return PDMDEV_SET_ERROR(pDevIns, rc, N_("SB16 configuration error: Failed to get the \"DMA\" value")); 3142 p This->dmaCfg = pThis->dma;3143 3144 rc = pHlp->pfnCFGMQuery SIntDef(pCfg, "DMA16", &pThis->hdma, 5);3129 pStream->HwCfgRuntime.uDmaChanLow = pStream->HwCfgDefault.uDmaChanLow; 3130 3131 rc = pHlp->pfnCFGMQueryU8Def(pCfg, "DMA16", &pStream->HwCfgDefault.uDmaChanHigh, 5); 3145 3132 if (RT_FAILURE(rc)) 3146 3133 return PDMDEV_SET_ERROR(pDevIns, rc, N_("SB16 configuration error: Failed to get the \"DMA16\" value")); 3147 pThis->hdmaCfg = pThis->hdma; 3148 3149 RTIOPORT Port; 3150 rc = pHlp->pfnCFGMQueryPortDef(pCfg, "Port", &Port, 0x220); 3134 pStream->HwCfgRuntime.uDmaChanHigh = pStream->HwCfgDefault.uDmaChanHigh; 3135 3136 rc = pHlp->pfnCFGMQueryPortDef(pCfg, "Port", &pStream->HwCfgDefault.uPort, 0x220); 3151 3137 if (RT_FAILURE(rc)) 3152 3138 return PDMDEV_SET_ERROR(pDevIns, rc, N_("SB16 configuration error: Failed to get the \"Port\" value")); 3153 pThis->port = Port; 3154 pThis->portCfg = Port; 3155 3156 uint16_t u16Version; 3157 rc = pHlp->pfnCFGMQueryU16Def(pCfg, "Version", &u16Version, 0x0405); 3139 pStream->HwCfgRuntime.uPort = pStream->HwCfgDefault.uPort; 3140 3141 rc = pHlp->pfnCFGMQueryU16Def(pCfg, "Version", &pStream->HwCfgDefault.uVer, 0x0405); 3158 3142 if (RT_FAILURE(rc)) 3159 3143 return PDMDEV_SET_ERROR(pDevIns, rc, N_("SB16 configuration error: Failed to get the \"Version\" value")); 3160 pThis->ver = u16Version; 3161 pThis->verCfg = u16Version; 3162 3163 uint16_t uTimerHz; 3164 rc = pHlp->pfnCFGMQueryU16Def(pCfg, "TimerHz", &uTimerHz, 100 /* Hz */); 3144 pStream->HwCfgRuntime.uVer = pStream->HwCfgDefault.uVer; 3145 3146 rc = pHlp->pfnCFGMQueryU16Def(pCfg, "TimerHz", &pStream->uTimerHz, SB16_TIMER_HZ_DEFAULT); 3165 3147 if (RT_FAILURE(rc)) 3166 return PDMDEV_SET_ERROR(pDevIns, rc, N_("SB16 configuration error: failed to read Hertz (Hz)rate as unsigned integer"));3167 if ( uTimerHz == 0)3168 return PDMDEV_SET_ERROR(pDevIns, rc, N_("SB16 configuration error: TimerHz is zero"));3169 if ( uTimerHz > 2048)3170 return PDMDEV_SET_ERROR(pDevIns, rc, N_("SB16 configuration error: Max TimerHz value is 2048."));3148 return PDMDEV_SET_ERROR(pDevIns, rc, N_("SB16 configuration error: failed to read Hertz rate as unsigned integer")); 3149 if (pStream->uTimerHz == 0) 3150 return PDMDEV_SET_ERROR(pDevIns, rc, N_("SB16 configuration error: Hertz rate is invalid")); 3151 if (pStream->uTimerHz > 2048) 3152 return PDMDEV_SET_ERROR(pDevIns, rc, N_("SB16 configuration error: Maximum Hertz rate is 2048")); 3171 3153 3172 3154 rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "DebugEnabled", &pThis->Dbg.fEnabled, false); … … 3209 3191 * Setup the mixer now that we've got the irq and dma channel numbers. 3210 3192 */ 3211 pThis->mixer_regs[0x80] = magic_of_irq(p This->irq);3212 pThis->mixer_regs[0x81] = (1 << p This->dma) | (1 << pThis->hdma);3193 pThis->mixer_regs[0x80] = magic_of_irq(pStream->HwCfgRuntime.uIrq); 3194 pThis->mixer_regs[0x81] = (1 << pStream->HwCfgRuntime.uDmaChanLow) | (1 << pStream->HwCfgRuntime.uDmaChanHigh); 3213 3195 pThis->mixer_regs[0x82] = 2 << 5; 3214 3196 … … 3230 3212 AssertRCReturn(rc, rc); 3231 3213 3232 pThis->aStreams[i].cTicksTimerIOInterval = PDMDevHlpTimerGetFreq(pDevIns, pThis->aStreams[i].hTimerIO) / uTimerHz; 3214 pThis->aStreams[i].cTicksTimerIOInterval = PDMDevHlpTimerGetFreq(pDevIns, pThis->aStreams[i].hTimerIO) 3215 / pThis->aStreams[i].uTimerHz; 3233 3216 pThis->aStreams[i].tsTimerIO = PDMDevHlpTimerGet(pDevIns, pThis->aStreams[i].hTimerIO); 3234 3217 } … … 3262 3245 }; 3263 3246 3264 rc = PDMDevHlpIoPortCreateAndMap(pDevIns, p This->port + 0x04 /*uPort*/, 2 /*cPorts*/,3247 rc = PDMDevHlpIoPortCreateAndMap(pDevIns, pStream->HwCfgRuntime.uPort + 0x04 /*uPort*/, 2 /*cPorts*/, 3265 3248 sb16IoPortMixerWrite, sb16IoPortMixerRead, 3266 3249 "SB16 - Mixer", &s_aAllDescs[4], &pThis->hIoPortsMixer); 3267 3250 AssertRCReturn(rc, rc); 3268 rc = PDMDevHlpIoPortCreateAndMap(pDevIns, p This->port + 0x06 /*uPort*/, 10 /*cPorts*/,3251 rc = PDMDevHlpIoPortCreateAndMap(pDevIns, pStream->HwCfgRuntime.uPort + 0x06 /*uPort*/, 10 /*cPorts*/, 3269 3252 sb16IoPortDspWrite, sb16IoPortDspRead, 3270 3253 "SB16 - DSP", &s_aAllDescs[6], &pThis->hIoPortsDsp); 3271 3254 AssertRCReturn(rc, rc); 3272 3255 3273 rc = PDMDevHlpDMARegister(pDevIns, p This->hdma, sb16DMARead, &pThis->aStreams[SB16_IDX_OUT] /* pvUser */);3256 rc = PDMDevHlpDMARegister(pDevIns, pStream->HwCfgRuntime.uDmaChanHigh, sb16DMARead, &pThis->aStreams[SB16_IDX_OUT] /* pvUser */); 3274 3257 AssertRCReturn(rc, rc); 3275 rc = PDMDevHlpDMARegister(pDevIns, p This->dma, sb16DMARead, &pThis->aStreams[SB16_IDX_OUT] /* pvUser */);3258 rc = PDMDevHlpDMARegister(pDevIns, pStream->HwCfgRuntime.uDmaChanLow, sb16DMARead, &pThis->aStreams[SB16_IDX_OUT] /* pvUser */); 3276 3259 AssertRCReturn(rc, rc); 3277 3278 pThis->can_write = 1;3279 3260 3280 3261 /* … … 3287 3268 LogRel(("SB16: Asynchronous I/O enabled\n")); 3288 3269 # endif 3270 LogRel2(("SB16: Using port %#x, DMA%RU8, IRQ%RU8\n", 3271 pStream->HwCfgRuntime.uPort, pStream->HwCfgRuntime.uDmaChanLow, pStream->HwCfgRuntime.uIrq)); 3289 3272 3290 3273 /* … … 3305 3288 } 3306 3289 3307 sb16 CmdResetLegacy(pThis);3290 sb16DspCmdResetLegacy(pThis); 3308 3291 3309 3292 #ifdef VBOX_WITH_AUDIO_SB16_ONETIME_INIT … … 3326 3309 LogRel(("SB16: Falling back to NULL backend (no sound audible)\n")); 3327 3310 3328 sb16 CmdResetLegacy(pThis);3311 sb16DspCmdResetLegacy(pThis); 3329 3312 sb16ReconfigLunWithNullAudio(pThis, pDrv->uLUN); 3330 3313 pDrv = NULL; /* no longer valid */
Note:
See TracChangeset
for help on using the changeset viewer.