NT4/private/ntos/dd/sound/necsnd/wave.h

302 lines
9.6 KiB
C
Raw Normal View History

2001-01-01 00:00:00 +01:00
/*++ BUILD Version: 0001 // Increment this if a change has global effects
"@(#) NEC wave.h 1.1 95/03/22 21:23:38"
Copyright (c) 1995 NEC Corporation.
Copyright (c) 1990 Microsoft Corporation
Module Name:
wave.h
Abstract:
This include file defines common structures for wave drivers
Revision History:
--*/
//
// Minimum buffer size for DMA (in case we couldn't get what we asked for).
// 4K
//
#define SOUND_MINIMUM_WAVE_BUFFER_SIZE (4096)
//
// Common DMA buffer for auto-initialize DMA and structures
// for using double-buffered DMA
//
typedef struct {
PADAPTER_OBJECT AdapterObject[2]; // The adapter object(s) -
// We may use 2 channels
ULONG BufferSize; // Size of the buffer
PVOID VirtualAddress; // Address of buffer
PHYSICAL_ADDRESS LogicalAddress; // Where is it really?
PMDL Mdl; // Mdl we are using for the buffer
} SOUND_DMA_BUFFER, *PSOUND_DMA_BUFFER;
typedef struct {
//
// Values for NextHalf field. This is the half of the DMA buffer
// to fill next. If wave data is being played or recorded this is
// also the 'live' part of the buffer (the part DMA is running on)
// and hence the next part to become free.
//
enum {LowerHalf = 0,
UpperHalf}
NextHalf; // Where we are now
ULONG BufferSize; // Size of the buffer
PUCHAR Buf; // Position
ULONG StartOfData; // Start of valid data
ULONG nBytes; // Number of bytes in buffer
UCHAR Pad; // Padding byte to use
} SOUND_DOUBLE_BUFFER, *PSOUND_DOUBLE_BUFFER;
//
// Control processing of device queue
//
typedef struct {
LIST_ENTRY QueueHead; // head of the queue if Irps
// for writing to / reading from
// device.
// Entries are cancellable Irps.
ULONG BytesProcessed; // Bytes put into or copied from buffers
ULONG UserBufferSize; // Size of user buffer
ULONG UserBufferPosition; // Position in buffer and
PUCHAR UserBuffer; // buffer corresponding to next user
PIRP pIrp; // pointer to the current request
//
// Variables for controlling wave output sequencing of Irps
// to ensure that wave output is not signalled as finished until
// the data has actually played
//
LIST_ENTRY ProgressQueue; // Wave output buffers in progress
// Entries on this queue are not
// cancellable
} SOUND_BUFFER_QUEUE, *PSOUND_BUFFER_QUEUE;
//
// Hardware interface routine type for Wave processing
//
struct _WAVE_INFO;
typedef BOOLEAN WAVE_INTERFACE_ROUTINE(struct _WAVE_INFO *);
typedef WAVE_INTERFACE_ROUTINE *PWAVE_INTERFACE_ROUTINE;
typedef NTSTATUS SOUND_QUERY_FORMAT_ROUTINE (PLOCAL_DEVICE_INFO, PPCMWAVEFORMAT);
typedef SOUND_QUERY_FORMAT_ROUTINE *PSOUND_QUERY_FORMAT_ROUTINE;
enum {
SoundNoDMA,
SoundAutoInitDMA, // Use autoinitialize
SoundReprogramOnInterruptDMA, // Reprogram on interrupt
Sound2ChannelDMA // Keep 2 channels going
};
typedef struct _WAVE_INFO
{
ULONG Key; // Debugging
#define WAVE_INFO_KEY (*(ULONG *)"Wave")
PDEVICE_OBJECT DeviceObject; // Current real device (back pointer)
// Information input to this component about our DMA buffer
SOUND_DMA_BUFFER DMABuf;
// Data for manipulation of the buffer, INTERNAL to this component
SOUND_DOUBLE_BUFFER DoubleBuffer;
// Data for maninpulation of input queue of data INTERNAL to this
// component
SOUND_BUFFER_QUEUE BufferQueue;
// Current wave format data - created by this component - INPUT to
// hardware interface routines
ULONG SamplesPerSec;
UCHAR BitsPerSample;
UCHAR Channels;
BOOLEAN FormatChanged; // New format has been set
PWAVEFORMATEX WaveFormat;
BOOLEAN LowPrioritySaved;
PFILE_OBJECT LowPriorityHandle; // File object of device
PLOCAL_DEVICE_INFO
LowPriorityDevice; // Real device
// Low priority mode save area
struct
{
SOUND_BUFFER_QUEUE BufferQueue;
ULONG SamplesPerSec;
UCHAR BitsPerSample;
UCHAR Channels;
PWAVEFORMATEX WaveFormat;
ULONG State;
} LowPriorityModeSave;
PVOID MRB[2]; // Info about adapter for DMA
// Event to wait for Dma channel to be allocated
KEVENT DmaSetupEvent;
// The following events are reset by SoundStopDMA and waited on
// if DpcQueued is set after resetting it. The Dpc routine sets
// this event when it has finished.
KEVENT DpcEvent;
KEVENT TimerDpcEvent;
KSPIN_LOCK DeviceSpinLock; // spin lock for synchrnonizing with
// Dpc routine
#if DBG
BOOLEAN LockHeld; // Get spin locks right
#endif
PKINTERRUPT Interrupt; // interrupt object
BOOLEAN Direction; // TRUE = out, FALSE = in
UCHAR DMAType; // Type of DMA :
// SoundAutoInitDMA
// SoundReprogramOnInterruptDMA
// Sound2DMAChannelDMA
UCHAR InterruptHalf; // Used with SoundReprogramOnInterruptDMA
// as next half to use.
volatile BOOLEAN
DMABusy; // set if dma in progress
// Dpc routine can turn it off
// so make it volatile
volatile BOOLEAN
DpcQueued; // Set by Isr, cleared by Dpc routine
// tested by SoundStopDMA
ULONG Overrun; // Interrupts overran Dpcs
// Managed at DEVICE level
PVOID HwContext; // Context for hardware interface
// routines
// Stuff to call stop DMA on a worker thread because all these DSPs
// are so slow. This also makes it much easier to share the use
// of these devices via a Mutex in the drivers (rather than a spin
// lock).
//
// This can also be called to terminate wave input when our timeout
// expires and we had no interrupt
WORK_QUEUE_ITEM WaveStopWorkItem;
KEVENT WaveReallyComplete;
// Callouts back to device specific code
// This routine returns TRUE if a wave format passed to it can be
// handled by the device.
PSOUND_QUERY_FORMAT_ROUTINE
QueryFormat; // Format query and set routine
PWAVE_INTERFACE_ROUTINE
HwSetupDMA, // Outside spin lock - sets up parms
// for DMA
HwStopDMA, // Outside spin lock - stop device
// gracefully
HwSetWaveFormat; // Set the format to use
KDPC TimerDpc; // Check if the device keeps
KTIMER DeviceCheckTimer; // going
BOOLEAN GotWaveDpc; // This flag is set if we are
// still going
BOOLEAN DeviceBad; // Failed timer test
BOOLEAN TimerActive; // Need to synch timer routine
UCHAR FailureCount; // If we fail 30 times in a row give up
BOOLEAN Calibration; // Auto Calibration
ULONG MapOn; // Next DMA Call
}WAVE_INFO, *PWAVE_INFO;
//
// Macros to assist in safely using our spin lock
//
#if DBG
#define DMAEnter(pWave) \
{ \
KIRQL OldIrql; \
KeAcquireSpinLock(&(pWave)->DeviceSpinLock, &OldIrql);\
ASSERT((pWave)->LockHeld == FALSE); \
(pWave)->LockHeld = TRUE;
#define DMALeave(pWave) \
ASSERT((pWave)->LockHeld == TRUE); \
(pWave)->LockHeld = FALSE; \
KeReleaseSpinLock(&(pWave)->DeviceSpinLock, OldIrql);\
}
#else
#define DMAEnter(pWave) \
{ \
KIRQL OldIrql; \
ASSERT((pWave)->LockHeld == FALSE); \
KeAcquireSpinLock(&(pWave)->DeviceSpinLock, &OldIrql);
#define DMALeave(pWave) \
ASSERT((pWave)->LockHeld == TRUE); \
KeReleaseSpinLock(&(pWave)->DeviceSpinLock, OldIrql);\
}
#endif
//
// Notification codes for wave line changes
//
#define SOUND_LINE_NOTIFY_WAVE 0
#define SOUND_LINE_NOTIFY_VOICE 1
//
// Exported routines
//
VOID
SoundInitializeWaveInfo(
PWAVE_INFO WaveInfo,
UCHAR DMAType,
PSOUND_QUERY_FORMAT_ROUTINE QueryFormat,
PVOID HwContext
);
NTSTATUS
SoundGetCommonBuffer(
IN PDEVICE_DESCRIPTION DeviceDescription,
IN OUT PSOUND_DMA_BUFFER SoundAutoData
);
VOID
SoundFreeCommonBuffer(
IN OUT PSOUND_DMA_BUFFER SoundAutoData
);
BOOLEAN
SoundPeakMeter(
IN PWAVE_INFO WaveInfo,
OUT PLONG Amplitudes
);
ULONG
SoundGetDMABufferSize(
IN PWAVE_INFO WaveInfo
);
int
SoundTestWaveDevice(
IN PDEVICE_OBJECT pDO
);