reactos/drivers/multimedia/audio/sb16_nt4.old/control.c

223 lines
4.4 KiB
C

#include <sndblst.h>
/*
TODO: MmMapIoSpace()
*/
/*
This checks the read or write status port of the device.
*/
BOOLEAN
WaitForReady(
PSOUND_BLASTER_PARAMETERS SBDevice,
UCHAR Port)
{
ULONG timeout = SB_TIMEOUT;
BOOL ready = FALSE;
while ( ( ! ready ) && ( timeout > 0 ) )
{
if ( SbRead(SBDevice, Port) & 0x80 )
return TRUE;
timeout --;
}
return FALSE;
}
BOOLEAN
SbWriteData(
PSOUND_BLASTER_PARAMETERS SBDevice,
UCHAR Data)
{
if ( ! WaitToWrite(SBDevice) )
return FALSE;
DPRINT("Writing 0x%x to Sound Blaster card (data)\n", Data);
SbWrite(SBDevice, SB_WRITE_DATA_PORT, Data);
return TRUE;
}
BOOLEAN
SbReadData(
PSOUND_BLASTER_PARAMETERS SBDevice,
PUCHAR Data)
{
if ( ! WaitToWrite(SBDevice) )
return FALSE;
*Data = SbRead(SBDevice, SB_READ_DATA_PORT);
DPRINT("Read 0x%x from Sound Blaster card (data)\n", *Data);
return TRUE;
}
BOOLEAN
ResetSoundBlaster(
PSOUND_BLASTER_PARAMETERS SBDevice)
{
BOOLEAN acked = FALSE;
ULONG timeout;
SbWriteReset(SBDevice, 0x01);
for (timeout = 0; timeout < 30000; timeout ++ );
SbWriteReset(SBDevice, 0x00);
DPRINT("Waiting for SB to acknowledge our reset request\n");
if ( ! WaitToRead(SBDevice) )
{
DPRINT("Didn't get an ACK :(\n");
return FALSE;
}
timeout = 0;
while ( ( ! acked ) && ( timeout < SB_TIMEOUT ) )
{
acked = ( SbReadDataWithoutWait(SBDevice) == SB_DSP_READY );
timeout ++;
}
if ( ! acked )
{
DPRINT("Didn't get an ACK :(\n");
return FALSE;
}
return TRUE;
}
ULONG
GetSoundBlasterModel(
PSOUND_BLASTER_PARAMETERS SBDevice)
{
UCHAR MajorVer, MinorVer;
DPRINT("Querying DSP version\n");
if ( ! SbWriteData(SBDevice, SbGetDspVersion) )
return NotDetected;
if ( ! WaitToRead(SBDevice) )
return NotDetected;
if ( SbReadData(SBDevice, &MajorVer) )
{
if ( SbReadData(SBDevice, &MinorVer) )
{
DPRINT("Version %d.%d\n", MajorVer, MinorVer);
SBDevice->dsp_version = (MajorVer * 256) + MinorVer;
if ( SBDevice->dsp_version < 0x0200 )
return SoundBlaster;
else if ( ( SBDevice->dsp_version & 0xFF00 ) == 0x0200 )
return SoundBlaster2;
else if ( ( SBDevice->dsp_version & 0xFF00 ) == 0x0300 )
return SoundBlasterPro;
else if ( SBDevice->dsp_version >= 0x0400 )
return SoundBlaster16;
return NotDetected;
}
}
return NotDetected;
}
BOOLEAN
IsSampleRateCompatible(
PSOUND_BLASTER_PARAMETERS SBDevice,
ULONG SampleRate)
{
/* TODO */
return TRUE;
}
BOOLEAN
SetOutputSampleRate(
PSOUND_BLASTER_PARAMETERS SBDevice,
ULONG SampleRate)
{
/* Only works for DSP v4.xx */
DPRINT("Setting sample rate\n");
SbWriteData(SBDevice, SbSetOutputRate);
SbWriteData(SBDevice, SampleRate / 256);
SbWriteData(SBDevice, SampleRate % 256);
return TRUE;
}
BOOLEAN
EnableSpeaker(
PSOUND_BLASTER_PARAMETERS SBDevice)
{
DPRINT("Enabling speaker\n");
return SbWriteData(SBDevice, SbEnableSpeaker);
}
BOOLEAN
DisableSpeaker(
PSOUND_BLASTER_PARAMETERS SBDevice)
{
DPRINT("Disabling speaker\n");
return SbWriteData(SBDevice, SbDisableSpeaker);
}
BOOLEAN
StartSoundOutput(
PSOUND_BLASTER_PARAMETERS SBDevice,
ULONG BitDepth,
ULONG Channels,
ULONG BlockSize)
{
DPRINT("Initializing output with %d channels at %d bits/sample\n", Channels, BitDepth);
UCHAR command = 0xc6, mode = 0x00;
if ( ( Channels < 1 ) || ( Channels > 2 ) )
return FALSE;
if ( ( BitDepth != 8 ) && ( BitDepth != 16 ) )
return FALSE;
switch ( BitDepth )
{
case 8 : command = 0xc6; break;
case 16 : command = 0xb6; break;
};
switch ( Channels )
{
case 1 : mode = 0x00; break;
case 2 : mode = 0x20; break;
}
#if 0
first_byte = (BitDepth == 16) ? 0xb6 : 0xc6;
second_byte = (Channels == 1) ? 0x20 : 0x00;
#endif
if ( SBDevice->dsp_version < 0x0400 )
{
/* TODO: Additional programming required */
}
/* Send freq */
SbWriteData(SBDevice, command);
SbWriteData(SBDevice, mode);
SbWriteData(SBDevice, BlockSize % 256);
SbWriteData(SBDevice, BlockSize / 256);
DPRINT("Finished programming the DSP\n");
return TRUE;
}