📄 wavepdd.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*++
$Workfile: WAVEPDD.C $
$Date: 2/03/04 10:11a $
Abstract:
The PDD (Platform Dependent Driver) is responsible for
communicating with the audio circuit to start and stop playback
and/or recording and initialize and deinitialize the circuits. The
API between the PDD and the MDD is called the DDSI (see "Key Routines"
for more info).
Warning:
This driver is specifically written for the UCB 1400 Audio Codec. It is
not a general AC 97 CODEC device driver.
Key Routines:
PDD_AudioGetInterruptType -- This routine is part of the Interrupt Service Thread managed
by the wave MDD. Here interrupts are processed and DMA buffers are returned to the driver.
That is, the DMA buffers are protected to keep the DMAC from reading or writing the buffers
while the driver is processing them. If the DMAC attempts to work on a buffer that is has
not been posted by the driver an Interrupt will occur indicating write overflow or read
under flow. The DMAC engine will stall until the buffer is ready. The status of reads or
writes is returned to the MDD.
private_WaveInStart, private_WaveOutStart -- These routines setup the DMAC for receive or
transmit. They copy data from application buffers (sent from or to the OS) to DMA buffers.
The inital DMA buffers are then "posted" or setup for the DMAC engine to read or write.
private_WaveInContinue, private_WaveOutContinue -- These routines continue processing
input or output by moving data from or to application buffers from or to the DMAC buffers.
Buffers are "posted" (marked for handling) by these routines. If the DMAC engine attempts
to read a buffer before it is posted, it will generate an interrupt and stall. If the DMAC
has stalled this routine will restart DMA. (See also PDD_AudioGetInterruptType,
private_AudioFillBuffer, and private_AudioGetBuffer).
private_AudioFillBuffer,private_AudioGetBuffer -- These routines perform the actual copy and
formatting of application sound data. They copy the data from or to the DMAC buffers from
or to the application buffers. The data is also converted from the format of the audio
Codec (stereo 16 bit) to the format requested by the application (such as monoral 8 bit).
private_WaveInStop, private_WaveOutStop -- These routines stop the processing of audio buffers
by indicating that no more data is available and setting the DMAC registers to stop xmit or
recv of application data.
PDD_WaveProc -- This routine actually processes the messages of the Device Driver Service
Interface (DDSI). The MDD sends these messages to the PDD for handling.
PDD_AudioMessage -- This routine exposes a private interface to applications.
Key Structures:
Function Hierarchy:
PDD_AudioGetInterruptType xx
PDD_AudioMessage xx
PDD_AudioInitialize xx
AudioPowerOn() xx
AudioOutMute(); xx
PDD_AudioDeinitialize xx
PddpAudioDeallocateVm(); xx
PDD_AudioPowerHandler xx
PDD_WaveProc xx
WPDM_OPEN, xx
private_WaveOpen xx
WPDM_CLOSE xx
WPDM_START xx
private_WaveInStart xx
private_AudioGetBuffer xx
private_WaveOutStart xx
private_AudioFillBuffer !!
WPDM_RESTART xx
private_WaveOutRestart xx
WPDM_STOP xx
private_WaveInStop xx
private_WaveOutStop xx
WPDM_CONTINUE xx
private_WaveInContinue xx
private_WaveOutContinue xx
WPDM_ENDOFDATA xx
private_WaveOutEndOfData xx
WPDM_STANDBY xx
private_WaveStandby --
WPDM_PAUSE xx
private_WaveOutPause xx
WPDM_GETDEVCAPS xx
private_WaveGetDevCaps xx
WPDM_GETVOLUME
WPDM_SETVOLUME
Notes:
--*/
static const char __copyright[]= "Copyright 2000 Intel Corp."; //only for C/CPP files
/*++
** Copyright 2000-2001 Intel Corporation. All Rights Reserved.
**
** Portions of the source code contained or described herein and all documents
** related to such source code (Material) are owned by Intel Corporation
** or its suppliers or licensors and is licensed by Microsoft Corporation for distribution.
** Title to the Material remains with Intel Corporation or its suppliers and licensors.
** Use of the Materials is subject to the terms of the Microsoft license agreement which accompanied the Materials.
** No other license under any patent, copyright, trade secret or other intellectual
** property right is granted to or conferred upon you by disclosure or
** delivery of the Materials, either expressly, by implication, inducement,
** estoppel or otherwise
** Some portion of the Materials may be copyrighted by Microsoft Corporation.
--*/
//-----------------------------------------------------------------
// INCLUDE FILES
//-----------------------------------------------------------------
#include <windows.h>
#include <types.h>
#include <memory.h>
#include <excpt.h>
#include <wavepdd.h>
#include <waveddsi.h>
#include <wavedbg.h>
#include <nkintr.h>
#include <ceddk.h>
#include <devload.h>
#include <bulverde.h>
#include "mmsystem.h"
#include <wavedbg.h>
#include "aclink.h"
#include "dmac.h"
#include "AC97.H"
#include "WAVE162.H"
//-----------------------------------------------------------------
// MACROS
//-----------------------------------------------------------------
#define BITS_8_TO_16(x) (short) ( ( (LONG) ( (UINT8)(x) - 128) ) << 8 )
#define BITS_16_TO_8(x) ( (UINT8) (( (x) >> 8 ) +128))
//-----------------------------------------------------------------
// DEFINES
//-----------------------------------------------------------------
#define NUM_DMA_AUDIO_BUFFERS 4
#define LOOPBACK_MASK 0x40
#define RESET_CODEC_MASK 0x04 //bit 2 0 origin
#define MHZ11_980 11980000
#define KHZ08_000 8000
#define KHZ11_025 11025
#define KHZ12_000 12000
#define KHZ16_000 16000
#define KHZ22_050 22050
#define KHZ24_000 24000
#define KHZ32_000 32000
#define KHZ44_100 44100
#define KHZ48_000 48000
#define TIMERTICK 4 // 1 microsecond is 3.7 clock ticks
#define BULVERDE_REG_SYSINTR_VAL_NAME TEXT("Sysintr")
#define BULVERDE_REG_SYSINTR_VAL_LEN sizeof( DWORD )
// TODO
#define DEV_TOUCH 1
#define DEV_AUDIO 2
#define DEV_BATTERY 3
//-----------------------------------------------------------------
// INTERNAL FUNCTIONS
//-----------------------------------------------------------------
// Local
static BOOL MapDMADescriptors(void);
static BOOL MapDeviceRegisters(void);
static void FillDescriptors(void);
BOOL AC97_SetVolume(ULONG uVolume);
short int AC97SetSampleRate(unsigned short int SampleRate, WAPI_INOUT apidir );
BOOL audio_out_buffer(ULONG);
BOOL AudioInMute( BOOL mute );
BOOL AudioOutMute( BOOL mute );
void AudioPowerOff();
BOOL AudioPowerOn();
void ClearDmac( void );
void dumpInterrupt(void);
BOOL InitDMAC(int);
BOOL IsMuted(BYTE Offset);
void PowerDownUnit(unsigned short int Unit,BOOL ShutDown);
void private_WaveStandby(WAPI_INOUT apidir);
short int ShadowReadAC97(BYTE Offset, unsigned short int *Data, BYTE DevId);
short int ShadowWriteAC97(BYTE Offset, unsigned short int Data, BYTE DevId);
BOOL StopDmac(int);
BOOL UnMapVirtual(void * v_pMapSpace);
VOID private_WaveOutStop();
unsigned short int LastSampleRateIn=KHZ48_000;
unsigned short int LastSampleRateOut=KHZ48_000;
//-----------------------------------------------------------------
// EXTERNAL FUNCTIONS
//-----------------------------------------------------------------
extern PVOID VirtualAllocCopy(unsigned size,char *str,PVOID pVirtualAddress);
//-----------------------------------------------------------------
// CONSTANTS AND VARIABLES
//-----------------------------------------------------------------
unsigned long Ac97ShadowRegisters[64]; //shadow writes to the AC97 Codec
static unsigned int ResetCaps; //HACK: If 0x2a0 it's rev 2a, if its 0x2a then its rev 1b
static unsigned int CodecType=GENERIC_AC97;
static BOOL PlayWave = 0;
static unsigned int i_buffer = 0; // Rcv buffer index
static unsigned int o_buffer = 0; // Xmt buffer index
static BOOL Expect_RcvRup_A; // TRUE ==> Done_A interrupt expected; FALSE ==> Done_B
static BOOL Expect_XmtRup_A; // TRUE ==> Done_A interrupt expected; FALSE ==> Done_B
InputSourceType gInputSrc=Line; //Track the input source (microphone or line in)
const ULONG g_dma_buffer_size = AUDIO_BUFFER_SIZE;
DWORD g_capture_buffer_size;
const g_capture_latency = 20; // capture buffers will hold this much data (in milliseconds)
// This lets us know if we're in our power handler routine, so we know
// not to make any system calls (debug messages, etc).
BOOL g_fInPowerHandler;
// however, 44.1 will be about 1.1% off
static int sample_rate_out = KHZ44_100; //define sample rate globally
static int sample_rate_in = KHZ44_100; //define sample rate globally
VOID (*g_pfnFillBuffer) (PINT16 pDstBuffer, PBYTE pSrcBuffer, DWORD dwSamples);
VOID (*g_pfnGetBuffer) (PBYTE pDstBuffer, PINT16 pSrcBuffer, DWORD dwSamples);
//point to the AC97 read/write functions based on
//the needs for the power handler
BOOL (*g_pfnReadAc97) (BYTE Offset, UINT16 * Data, BYTE DevId);
BOOL (*g_pfnWriteAc97) (BYTE Offset, UINT16 Data, BYTE DevId);
VOID FillBufferM08 (PINT16 pDstBuffer, PBYTE pSrcBuffer, DWORD dwSamples);
VOID FillBufferS08 (PINT16 pDstBuffer, PBYTE pSrcBuffer, DWORD dwSamples);
VOID FillBufferM16 (PINT16 pDstBuffer, PBYTE pSrcBuffer, DWORD dwSamples);
VOID FillBufferS16 (PINT16 pDstBuffer, PBYTE pSrcBuffer, DWORD dwSamples);
VOID GetBufferM08 (PBYTE pDstBuffer, PINT16 pSrcBuffer, DWORD dwSamples);
VOID GetBufferS08 (PBYTE pDstBuffer, PINT16 pSrcBuffer, DWORD dwSamples);
VOID GetBufferM16 (PBYTE pDstBuffer, PINT16 pSrcBuffer, DWORD dwSamples);
VOID GetBufferS16 (PBYTE pDstBuffer, PINT16 pSrcBuffer, DWORD dwSamples);
static int in_counter;
static UINT16 g_VolMatrix[0x64];
volatile PBYTE dma_page[NUM_DMA_AUDIO_BUFFERS];
volatile PBYTE dma_page_physical[NUM_DMA_AUDIO_BUFFERS];
ULONG v_nVolume=0xeeeeeeee; //default to volume
static int max_sample;
static int in_counter;
DWORD gIntrAudio = SYSINTR_UNDEFINED;
//
// These variables may be accessed by different processes or the hardware and
// are likely to change in a time critical fashion. Optimization may cause
// errors if not declared volatile.
//
volatile BOOL v_fMoreData[2];
// DMA descriptor buffers.
volatile DMADescriptorChannelType *v_pAudioRcvA_Virtual = NULL; // VA: Audio receive buffer A 128 bits (16 byte aligned)
volatile DMADescriptorChannelType *v_pAudioRcvA_Physical = NULL; // PA: Audio receive buffer A 128 bits (16 byte aligned)
volatile DMADescriptorChannelType *v_pAudioRcvB_Virtual = NULL; // VA: Audio receive buffer B 128 bits (16 byte aligned)
volatile DMADescriptorChannelType *v_pAudioRcvB_Physical = NULL; // PA: Audio receive buffer B 128 bits (16 byte aligned)
volatile DMADescriptorChannelType *v_pAudioXmitA_Virtual = NULL; // VA: Audio transmit buffer A 128 bits (16 byte aligned)
volatile DMADescriptorChannelType *v_pAudioXmitA_Physical = NULL; // PA: Audio transmit buffer A 128 bits (16 byte aligned)
volatile DMADescriptorChannelType *v_pAudioXmitB_Virtual = NULL; // VA: Audio transmit buffer B 128 bits (16 byte aligned)
volatile DMADescriptorChannelType *v_pAudioXmitB_Physical = NULL; // PA: Audio transmit buffer B 128 bits (16 byte aligned)
volatile DMADescriptorChannelType *v_pAudioMicA_Virtual = NULL; // VA: Audio Microphone buffer A 128 bits (16 byte aligned)
volatile DMADescriptorChannelType *v_pAudioMicA_Physical = NULL; // PA: Audio Microphone buffer A 128 bits (16 byte aligned)
volatile DMADescriptorChannelType *v_pAudioMicB_Virtual = NULL; // VA: Audio Microphone buffer B 128 bits (16 byte aligned)
volatile DMADescriptorChannelType *v_pAudioMicB_Physical = NULL; // PA: Audio Microphone buffer B 128 bits (16 byte aligned)
volatile BULVERDE_DMA_REG *v_pDMARegs = NULL;
volatile BULVERDE_AC97_REG *v_pAC97Regs = NULL;
#define NUM_API_DIRS 2
BOOL g_fInUse[NUM_API_DIRS]; // is apidir in use? if so, fail Open calls
DWORD g_sample_size[NUM_API_DIRS];
void ResetAC97Controller(void)
{
//reset the AC97 to workaround issue in sighting 46676
ULONG ulTemp;
// set GCR.ACOFF - turn controller off to flush FIFOs
ulTemp = v_pAC97Regs->gcr;
ulTemp |= 8;
v_pAC97Regs->gcr = ulTemp; // do it.
// wait for the ACOFFD (acoff "done") bit to assert.
while(1)
{
ulTemp = v_pAC97Regs->gsr;
if( ulTemp & 0x8 )
break;
}
// clear GCR.ACOFF - turn controller back on
ulTemp = v_pAC97Regs->gcr;
ulTemp &= ~8;
v_pAC97Regs->gcr = ulTemp;
}
//-----------------------------------------------------------------
// IMPLEMENTATIONS
//-----------------------------------------------------------------
void DumpDmacRegs()
{
int i;
DEBUGMSG(ZONE_ERROR, (TEXT( "%x, %x, %x, %x, %x\r\n" ),
v_pAC97Regs->gsr,
v_pAC97Regs->posr,
v_pAC97Regs->pocr,
v_pAC97Regs->pisr,
v_pAC97Regs->picr
) );
for (i=0; i< 16; i++)
DEBUGMSG(ZONE_ERROR, (TEXT( "v_pDMARegs->dcsr[%d] %x \r\n" ),i,v_pDMARegs->dcsr[i] ) );
//skip rsvd section rsvd0[44];
DEBUGMSG(ZONE_ERROR, (TEXT( "v_pDMARegs->dint %x \r\n" ),v_pDMARegs->dint ) );
//skip rsvd seciton rsvd1[3];
for (i=0; i< 39; i++)
DEBUGMSG(ZONE_ERROR, (TEXT( "v_pDMARegs->drcmr[%d] %x \r\n" ),i,v_pDMARegs->drcmr[i] ) );
for (i=0; i<16; i++)
{
DEBUGMSG(ZONE_ERROR, (TEXT( "v_pDMARegs->ddg[%d].ddadr %x \r\n" ),i,v_pDMARegs->ddg[i].ddadr ) );
DEBUGMSG(ZONE_ERROR, (TEXT( "v_pDMARegs->ddg[%d].dsadr %x \r\n" ),i,v_pDMARegs->ddg[i].dsadr ) );
DEBUGMSG(ZONE_ERROR, (TEXT( "v_pDMARegs->ddg[%d].dtadr %x \r\n" ),i,v_pDMARegs->ddg[i].dtadr ) );
DEBUGMSG(ZONE_ERROR, (TEXT( "v_pDMARegs->ddg[%d].dcmd %x \r\n" ),i,v_pDMARegs->ddg[i].dcmd ) );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -