DevIchAc97.cpp revision 5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7
/* $Id$ */
/** @file
* DevIchAc97 - VBox ICH AC97 Audio Controller.
*/
/*
* Copyright (C) 2006-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_DEV_AUDIO
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
#endif
#include "VBoxDD.h"
#ifndef VBOX_WITH_PDM_AUDIO_DRIVER
extern "C" {
#include "audio.h"
}
#endif
/*******************************************************************************
* Defined Constants And Macros *
*******************************************************************************/
#ifndef VBOX
//#define USE_MIXER
#else
# define USE_MIXER
#endif
#define AC97_SSM_VERSION 1
#ifndef VBOX
# define SOFT_VOLUME
#else
#endif
#define GS_RO_MASK (GS_B3S12 | \
GS_B2S12 | \
GS_B1S12 | \
GS_S1CR | \
GS_S0CR | \
GS_MINT | \
GS_POINT | \
GS_PIINT | \
GS_RSRVD | \
GS_MOINT | \
/** @name Buffer Descriptor
* @{ */
/** @} */
#define EACS_VRA 1
#define EACS_VRM 8
#define VOL_MASK 0x1f
#define MUTE_SHIFT 15
#define REC_MASK 7
enum
{
REC_MIC = 0,
};
enum
{
AC97_Reset = 0x00,
AC97_Master_Volume_Mute = 0x02,
AC97_Headphone_Volume_Mute = 0x04,
AC97_Master_Volume_Mono_Mute = 0x06,
AC97_Master_Tone_RL = 0x08,
AC97_PC_BEEP_Volume_Mute = 0x0A,
AC97_Phone_Volume_Mute = 0x0C,
AC97_Mic_Volume_Mute = 0x0E,
AC97_Line_In_Volume_Mute = 0x10,
AC97_CD_Volume_Mute = 0x12,
AC97_Video_Volume_Mute = 0x14,
AC97_Aux_Volume_Mute = 0x16,
AC97_PCM_Out_Volume_Mute = 0x18,
AC97_Record_Select = 0x1A,
AC97_Record_Gain_Mute = 0x1C,
AC97_Record_Gain_Mic_Mute = 0x1E,
AC97_General_Purpose = 0x20,
AC97_3D_Control = 0x22,
AC97_AC_97_RESERVED = 0x24,
AC97_Powerdown_Ctrl_Stat = 0x26,
AC97_Extended_Audio_ID = 0x28,
AC97_Extended_Audio_Ctrl_Stat = 0x2A,
AC97_PCM_Front_DAC_Rate = 0x2C,
AC97_PCM_Surround_DAC_Rate = 0x2E,
AC97_PCM_LFE_DAC_Rate = 0x30,
AC97_PCM_LR_ADC_Rate = 0x32,
AC97_MIC_ADC_Rate = 0x34,
AC97_6Ch_Vol_C_LFE_Mute = 0x36,
AC97_6Ch_Vol_L_R_Surround_Mute = 0x38,
AC97_Vendor_Reserved = 0x58,
AC97_Vendor_ID1 = 0x7c,
AC97_Vendor_ID2 = 0x7e
};
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
typedef struct BD
{
} BD;
typedef struct AC97BusMasterRegs
{
int bd_valid; /**< initialized? */
/** Pointer to a AC97 bus master register. */
typedef AC97BusMasterRegs *PAC97BMREG;
typedef struct AC97STATE
{
/** The PCI device state. */
/** Audio stuff. */
#ifndef VBOX_WITH_PDM_AUDIO_DRIVER
#endif
/** Global Control (Bus Master Control Register) */
/** Global Status (Bus Master Control Register) */
/** Codec Access Semaphore Register (Bus Master Control Register) */
/** Bus Master Control Registers for PCM in, PCM out, and Mic in */
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
/** PCM in */
/** PCM out */
/** Mic in */
#else
/** PCM in */
/** PCM out */
/** Mic in */
#endif
int bup_flag;
/** Pointer to the device instance. */
/** Pointer to the connector of the attached audio driver. */
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
#else
#endif
/** Pointer to the attached audio driver. */
/** The base interface for LUN\#0. */
/** Base port of the I/O space region. */
} AC97STATE;
/** Pointer to the AC97 device state. */
typedef AC97STATE *PAC97STATE;
enum
{
};
enum { \
}
enum
{
PI_INDEX = 0, /* PCM in */
PO_INDEX, /* PCM out */
MC_INDEX, /* Mic in */
};
enum
{
GLOB_CNT = 0x2c,
GLOB_STA = 0x30,
CAS = 0x34
};
{
}
{
}
/** Fetch Buffer Descriptor at _CIV */
{
uint8_t b[8];
#if !defined(RT_ARCH_X86) && !defined(RT_ARCH_AMD64)
#else
#endif
Log(("ac97: bd %2d addr=%#x ctl=%#06x len=%#x(%d bytes)\n",
}
/**
* Update the BM status register
*/
{
int event = 0;
int level = 0;
{
/** @todo is IRQ deasserted when only one of status bits is cleared? */
if (!new_mask)
{
event = 1;
level = 0;
}
{
event = 1;
level = 1;
}
{
event = 1;
level = 1;
}
}
Log(("ac97: IOC%d LVB%d sr=%#x event=%d level=%d\n",
if (event)
{
if (level)
else
}
}
{
switch (bm_index)
{
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
case PI_INDEX:
break;
case PO_INDEX:
break;
case MC_INDEX:
break;
#else
#endif
default: AssertFailed (); break;
}
}
{
Log(("ac97: reset_bm_regs\n"));
/** @todo do we need to do that? */
}
{
{
return;
}
}
{
{
val = 0xffff;
}
else
return val;
}
{
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
int rc;
#endif
if (freq)
{
#ifndef VBOX_WITH_PDM_AUDIO_DRIVER
as.endianness = 0;
#endif
switch (index)
{
case PI_INDEX: /* PCM in */
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
#else
#endif
#ifdef LOG_VOICES
#endif
break;
case PO_INDEX: /* PCM out */
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
{
}
#else
#endif
#ifdef LOG_VOICES
#endif
break;
case MC_INDEX: /* Mic in */
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
#else
#endif
#ifdef LOG_VOICES
#endif
break;
}
}
else
{
switch (index)
{
case PI_INDEX:
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
{
}
#else
#endif
#ifdef LOG_VOICES
LogRel(("AC97: Closing PCM IN\n"));
#endif
break;
case PO_INDEX:
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
{
}
#else
#endif
#ifdef LOG_VOICES
LogRel(("AC97: Closing PCM OUT\n"));
#endif
break;
case MC_INDEX:
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
{
}
#else
#endif
#ifdef LOG_VOICES
LogRel(("AC97: Closing MIC IN\n"));
#endif
break;
}
}
}
{
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
#else
#endif
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
#else
#endif
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
#else
#endif
}
#ifdef USE_MIXER
{
# ifdef SOFT_VOLUME
if (index == AC97_Master_Volume_Mute)
{
# ifdef VBOX_WITH_PDM_AUDIO_DRIVER
# else
# endif
}
else
{
# ifdef VBOX_WITH_PDM_AUDIO_DRIVER
/* @tod0 in SetVolume no passing audmixerctl_in as its not used in DrvAudio.c */
# else
# endif
}
# else
# ifdef VBOX_WITH_PDM_AUDIO_DRIVER
# else
# endif
# endif
/*
* From AC'97 SoundMax Codec AD1981A: "Because AC '97 defines 6-bit volume registers, to
* maintain compatibility whenever the D5 or D13 bits are set to `1,' their respective
* lower five volume bits are automatically set to `1' by the Codec logic. On readback,
* all lower 5 bits will read ones whenever these bits are set to `1.'"
*
* Linux ALSA depends on this behavior.
*/
}
{
switch (i)
{
case REC_MIC: return AUD_REC_MIC;
case REC_CD: return AUD_REC_CD;
case REC_VIDEO: return AUD_REC_VIDEO;
case REC_AUX: return AUD_REC_AUX;
case REC_LINE_IN: return AUD_REC_LINE_IN;
case REC_PHONE: return AUD_REC_PHONE;
default:
Log(("ac97: Unknown record source %d, using MIC\n", i));
return AUD_REC_MIC;
}
}
{
switch (rs)
{
case AUD_REC_MIC: return REC_MIC;
case AUD_REC_CD: return REC_CD;
case AUD_REC_VIDEO: return REC_VIDEO;
case AUD_REC_AUX: return REC_AUX;
case AUD_REC_LINE_IN: return REC_LINE_IN;
case AUD_REC_PHONE: return REC_PHONE;
default:
return REC_MIC;
}
}
{
//AUD_set_record_source(&als, &ars);
}
#endif /* USE_MIXER */
{
Log(("ac97: mixer_reset\n"));
/*
* Sigmatel 9700 (STAC9700)
*/
#ifdef USE_MIXER
record_select(pThis, 0);
#else
#endif
}
{
int to_copy = 0;
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
/* count of bytes left in buf to read = samples left in buffer (each of 16 bit) to read denoted by picb * 2) */
int lun = 0;
#endif
if (!temp)
{
*stop = 1;
return 0;
}
while (temp)
{
int copied;
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
/* save a copy of the audio samples read */
{
/* call pfnwrite with the same data that has been read from the guest physical memory */
}
#else
#endif
if (!copied)
{
*stop = 1;
break;
}
}
if (!temp)
{
if (to_copy < 4)
{
Log(("ac97: whoops\n"));
}
else
}
return written;
}
{
int written = 0;
Log(("ac97: write_bup\n"));
{
{
unsigned int i;
}
else
}
while (elapsed)
{
int copied;
while (temp)
{
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
{
}
#else
#endif
if (!copied)
return;
}
}
}
{
int to_copy = 0;
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
uint32_t cSamplesMixed = 0;
uint32_t cSamplesRead = 0;
void * rate[2];
#else
#endif
if (!temp)
{
*stop = 1;
return 0;
}
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
//rate[1] = pThis->pDrv[1]->pfnPrepareAudioConversion(pThis->pDrv[1], 22100, 22100);
{
if (!temp)
{
*stop = 1;
return 0;
}
offRead = 0;
offWrite = 0;
cSamplesMixed = 0;
nread = 0;
while (temp)
{
int acquired;
while (cSamplesRead)
{
if (!isamp)
{
LogFlow(("DevichAC97: No Input samples \n"));
break;
}
cSamplesRead -= isamp;
cSamplesMixed += isamp;
}
if (!acquired)
{
*stop = 1;
break;
}
//addr += acquired;
//addr += (ctotalSamplexMixed << voice->Props.cShift);
//nread += (cSamplesMixed << voice->Props.cShift);
}
}
if (cTotalSamplesMixed)
#else
while (temp)
{
int acquired;
if (!acquired)
{
*stop = 1;
break;
}
}
#endif
return nread;
}
{
int written = 0;
int stop = 0;
{
{
switch (index)
{
case PO_INDEX:
break;
}
}
return;
}
{
int temp;
{
Log(("ac97: invalid bd\n"));
}
{
Log(("ac97: fresh bd %d is empty %#x %#x, skipping\n", pReg->civ, pReg->bd.addr, pReg->bd.ctl_len));
{
break;
}
continue;
}
switch (index)
{
case PO_INDEX:
break;
case PI_INDEX:
case MC_INDEX:
break;
}
{
{
}
{
stop = 1;
}
else
{
}
}
}
}
{
}
{
}
{
}
/**
* @callback_method_impl{FNIOMIOPORTIN}
*/
static DECLCALLBACK(int) ichac97IOPortNABMRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
{
switch (cb)
{
case 1:
{
*pu32 = ~0U;
switch (index)
{
case CAS:
/* Codec Access Semaphore Register */
break;
case PI_CIV:
case PO_CIV:
case MC_CIV:
/* Current Index Value Register */
break;
case PI_LVI:
case PO_LVI:
case MC_LVI:
/* Last Valid Index Register */
break;
case PI_PIV:
case PO_PIV:
case MC_PIV:
/* Prefetched Index Value Register */
break;
case PI_CR:
case PO_CR:
case MC_CR:
/* Control Register */
break;
case PI_SR:
case PO_SR:
case MC_SR:
/* Status Register (lower part) */
break;
default:
break;
}
break;
}
case 2:
{
*pu32 = ~0U;
switch (index)
{
case PI_SR:
case PO_SR:
case MC_SR:
/* Status Register */
break;
case PI_PICB:
case PO_PICB:
case MC_PICB:
/* Position in Current Buffer Register */
break;
default:
break;
}
break;
}
case 4:
{
*pu32 = ~0U;
switch (index)
{
case PI_BDBAR:
case PO_BDBAR:
case MC_BDBAR:
/* Buffer Descriptor Base Address Register */
break;
case PI_CIV:
case PO_CIV:
case MC_CIV:
/* 32-bit access: Current Index Value Register +
* Last Valid Index Register +
* Status Register */
break;
case PI_PICB:
case PO_PICB:
case MC_PICB:
/* 32-bit access: Position in Current Buffer Register +
* Prefetched Index Value Register +
* Control Register */
Log(("ac97: PICB PIV CR[%d] -> %#x %#x %#x %#x\n", GET_BM(index), *pu32, pReg->picb, pReg->piv, pReg->cr));
break;
case GLOB_CNT:
/* Global Control */
break;
case GLOB_STA:
/* Global Status */
break;
default:
break;
}
break;
}
default:
return VERR_IOM_IOPORT_UNUSED;
}
return VINF_SUCCESS;
}
/**
* @callback_method_impl{FNIOMIOPORTOUT}
*/
static DECLCALLBACK(int) ichac97IOPortNABMWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
{
switch (cb)
{
case 1:
{
switch (index)
{
case PI_LVI:
case PO_LVI:
case MC_LVI:
/* Last Valid Index */
{
}
break;
case PI_CR:
case PO_CR:
case MC_CR:
/* Control Register */
else
{
{
}
else
{
}
}
break;
case PI_SR:
case PO_SR:
case MC_SR:
/* Status Register */
break;
default:
break;
}
break;
}
case 2:
{
switch (index)
{
case PI_SR:
case PO_SR:
case MC_SR:
/* Status Register */
break;
default:
break;
}
break;
}
case 4:
{
switch (index)
{
case PI_BDBAR:
case PO_BDBAR:
case MC_BDBAR:
/* Buffer Descriptor list Base Address Register */
break;
case GLOB_CNT:
/* Global Control */
break;
case GLOB_STA:
/* Global Status */
break;
default:
break;
}
break;
}
default:
break;
}
return VINF_SUCCESS;
}
/**
* @callback_method_impl{FNIOMIOPORTIN}
*/
static DECLCALLBACK(int) ichac97IOPortNAMRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
{
switch (cb)
{
case 1:
{
*pu32 = ~0U;
break;
}
case 2:
{
*pu32 = ~0U;
switch (index)
{
default:
break;
}
break;
}
case 4:
{
*pu32 = ~0U;
break;
}
default:
return VERR_IOM_IOPORT_UNUSED;
}
return VINF_SUCCESS;
}
/**
* @callback_method_impl{FNIOMIOPORTOUT}
*/
static DECLCALLBACK(int) ichac97IOPortNAMWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
{
switch (cb)
{
case 1:
{
break;
}
case 2:
{
switch (index)
{
case AC97_Reset:
break;
case AC97_Powerdown_Ctrl_Stat:
u32 &= ~0xf;
break;
#ifdef USE_MIXER
case AC97_Master_Volume_Mute:
break;
case AC97_PCM_Out_Volume_Mute:
break;
case AC97_Line_In_Volume_Mute:
break;
case AC97_Record_Select:
break;
#else /* !USE_MIXER */
case AC97_Master_Volume_Mute:
case AC97_PCM_Out_Volume_Mute:
case AC97_Line_In_Volume_Mute:
case AC97_Record_Select:
break;
#endif /* !USE_MIXER */
case AC97_Vendor_ID1:
case AC97_Vendor_ID2:
break;
case AC97_Extended_Audio_ID:
break;
{
}
{
}
break;
case AC97_PCM_Front_DAC_Rate:
{
}
else
break;
case AC97_MIC_ADC_Rate:
{
}
else
break;
case AC97_PCM_LR_ADC_Rate:
{
}
else
break;
default:
break;
}
break;
}
case 4:
{
break;
}
default:
break;
}
return VINF_SUCCESS;
}
/**
* @callback_method_impl{FNPCIIOREGIONMAP}
*/
static DECLCALLBACK(int) ichac97IOPortMap(PPCIDEVICE pPciDev, int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb,
{
int rc;
if (iRegion == 0)
else
if (RT_FAILURE(rc))
return rc;
return VINF_SUCCESS;
}
/**
* @callback_method_impl{FNSSMDEVSAVEEXEC}
*/
{
{
}
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
/* writing only host backend values here and ignoring for webm and VRDE */
#else
#endif
return VINF_SUCCESS;
}
/**
* @callback_method_impl{FNSSMDEVLOADEXEC}
*/
static DECLCALLBACK(int) ichac97LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
{
AssertMsgReturn (uVersion == AC97_SSM_VERSION, ("%d\n", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
{
}
#ifdef USE_MIXER
#endif /* USE_MIXER */
return VINF_SUCCESS;
}
/**
* @interface_method_impl{PDMIBASE,pfnQueryInterface}
*/
{
return NULL;
}
/**
* @interface_method_impl{PDMDEVREG,pfnReset}
*
* @remarks The original sources didn't install a reset handler, but it seems to
* make sense to me so we'll do it.
*/
{
/*
* Reset the device state (will need pDrv later).
*/
/*
* Reset the mixer too. The Windows XP driver seems to rely on
* this. At least it wants to read the vendor id before it resets
* the codec manually.
*/
}
/**
* @interface_method_impl{PDMDEVREG,pfnConstruct}
*/
{
int rc;
/*
* Validations.
*/
N_("Invalid configuration for the AC97 device"));
/*
* Initialize data (most of it anyway).
*/
/* IBase */
/* PCI Device (the assertions will be removed later) */
PCIDevSetVendorId (&pThis->PciDev, 0x8086); /* 00 ro - intel. */ Assert(pThis->PciDev.config[0x00] == 0x86); Assert(pThis->PciDev.config[0x01] == 0x80);
PCIDevSetDeviceId (&pThis->PciDev, 0x2415); /* 02 ro - 82801 / 82801aa(?). */ Assert(pThis->PciDev.config[0x02] == 0x15); Assert(pThis->PciDev.config[0x03] == 0x24);
PCIDevSetCommand (&pThis->PciDev, 0x0000); /* 04 rw,ro - pcicmd. */ Assert(pThis->PciDev.config[0x04] == 0x00); Assert(pThis->PciDev.config[0x05] == 0x00);
PCIDevSetStatus (&pThis->PciDev, VBOX_PCI_STATUS_DEVSEL_MEDIUM | VBOX_PCI_STATUS_FAST_BACK); /* 06 rwc?,ro? - pcists. */ Assert(pThis->PciDev.config[0x06] == 0x80); Assert(pThis->PciDev.config[0x07] == 0x02);
PCIDevSetRevisionId (&pThis->PciDev, 0x01); /* 08 ro - rid. */ Assert(pThis->PciDev.config[0x08] == 0x01);
PCIDevSetClassProg (&pThis->PciDev, 0x00); /* 09 ro - pi. */ Assert(pThis->PciDev.config[0x09] == 0x00);
PCIDevSetClassSub (&pThis->PciDev, 0x01); /* 0a ro - scc; 01 == Audio. */ Assert(pThis->PciDev.config[0x0a] == 0x01);
PCIDevSetClassBase (&pThis->PciDev, 0x04); /* 0b ro - bcc; 04 == multimedia. */ Assert(pThis->PciDev.config[0x0b] == 0x04);
PCIDevSetHeaderType (&pThis->PciDev, 0x00); /* 0e ro - headtyp. */ Assert(pThis->PciDev.config[0x0e] == 0x00);
true /* fIoSpace */, false /* fPrefetchable */, false /* f64Bit */, 0x00000000); Assert(pThis->PciDev.config[0x10] == 0x01); Assert(pThis->PciDev.config[0x11] == 0x00); Assert(pThis->PciDev.config[0x12] == 0x00); Assert(pThis->PciDev.config[0x13] == 0x00);
true /* fIoSpace */, false /* fPrefetchable */, false /* f64Bit */, 0x00000000); Assert(pThis->PciDev.config[0x14] == 0x01); Assert(pThis->PciDev.config[0x15] == 0x00); Assert(pThis->PciDev.config[0x16] == 0x00); Assert(pThis->PciDev.config[0x17] == 0x00);
PCIDevSetSubSystemVendorId(&pThis->PciDev, 0x8086); /* 2c ro - intel.) */ Assert(pThis->PciDev.config[0x2c] == 0x86); Assert(pThis->PciDev.config[0x2d] == 0x80);
PCIDevSetSubSystemId (&pThis->PciDev, 0x0000); /* 2e ro. */ Assert(pThis->PciDev.config[0x2e] == 0x00); Assert(pThis->PciDev.config[0x2f] == 0x00);
PCIDevSetInterruptLine (&pThis->PciDev, 0x00); /* 3c rw. */ Assert(pThis->PciDev.config[0x3c] == 0x00);
PCIDevSetInterruptPin (&pThis->PciDev, 0x01); /* 3d ro - INTA#. */ Assert(pThis->PciDev.config[0x3d] == 0x01);
/*
* Register the PCI device, it's I/O regions, the timer and the
* saved state item.
*/
if (RT_FAILURE (rc))
return rc;
if (RT_FAILURE (rc))
return rc;
if (RT_FAILURE (rc))
return rc;
rc = PDMDevHlpSSMRegister(pDevIns, AC97_SSM_VERSION, sizeof(*pThis), ichac97SaveExec, ichac97LoadExec);
if (RT_FAILURE (rc))
return rc;
/*
* Attach driver.
*/
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
{
if (RT_SUCCESS(rc))
{
("Configuration error: instance %d has no host audio interface!\n", iInstance),
}
else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
Log(("ac97: No attached driver!\n"));
else if (RT_FAILURE(rc))
{
return rc;
}
}
#else
if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
Log(("ac97: No attached driver!\n"));
else if (RT_FAILURE(rc))
{
return rc;
}
#endif
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
#else
#endif
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
{
LogRel(("AC97: WARNING: Unable to open PCM IN!\n"));
LogRel(("AC97: WARNING: Unable to open PCM MC!\n"));
LogRel(("AC97: WARNING: Unable to open PCM OUT!\n"));
}
#else
LogRel(("AC97: WARNING: Unable to open PCM IN!\n"));
LogRel(("AC97: WARNING: Unable to open PCM MC!\n"));
LogRel(("AC97: WARNING: Unable to open PCM OUT!\n"));
#endif
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
{
{
/* Was not able initialize *any* voice. Select the NULL audio driver instead */
N_("No audio devices could be opened. Selecting the NULL audio backend "
"with the consequence that no sound is audible"));
}
{
char szMissingVoices[128];
len += RTStrPrintf(szMissingVoices + len, sizeof(szMissingVoices) - len, len ? ", PCM_out" : "PCM_out");
len += RTStrPrintf(szMissingVoices + len, sizeof(szMissingVoices) - len, len ? ", PCM_mic" : "PCM_mic");
N_("Some audio devices (%s) could not be opened. Guest applications generating audio "
"output or depending on audio input may hang. Make sure your host audio device "
"is working properly. Check the logfile for error messages of the audio "
"subsystem"), szMissingVoices);
}
}
#else
{
N_("No audio devices could be opened. Selecting the NULL audio backend "
"with the consequence that no sound is audible"));
}
{
char szMissingVoices[128];
len += RTStrPrintf(szMissingVoices + len, sizeof(szMissingVoices) - len, len ? ", PCM_out" : "PCM_out");
len += RTStrPrintf(szMissingVoices + len, sizeof(szMissingVoices) - len, len ? ", PCM_mic" : "PCM_mic");
N_("Some audio devices (%s) could not be opened. Guest applications generating audio "
"output or depending on audio input may hang. Make sure your host audio device "
"is working properly. Check the logfile for error messages of the audio "
"subsystem"), szMissingVoices);
}
#endif
return VINF_SUCCESS;
}
/**
* The device registration structure.
*/
const PDMDEVREG g_DeviceICHAC97 =
{
/* u32Version */
/* szName */
"ichac97",
/* szRCMod */
"",
/* szR0Mod */
"",
/* pszDescription */
"ICH AC'97 Audio Controller",
/* fFlags */
/* fClass */
/* cMaxInstances */
1,
/* cbInstance */
sizeof(AC97STATE),
/* pfnConstruct */
/* pfnDestruct */
NULL,
/* pfnRelocate */
NULL,
/* pfnMemSetup */
NULL,
/* pfnPowerOn */
NULL,
/* pfnReset */
/* pfnSuspend */
NULL,
/* pfnResume */
NULL,
/* pfnAttach */
NULL,
/* pfnDetach */
NULL,
/* pfnQueryInterface. */
NULL,
/* pfnInitComplete */
NULL,
/* pfnPowerOff */
NULL,
/* pfnSoftReset */
NULL,
/* u32VersionEnd */
};