162 lines
3.8 KiB
C
162 lines
3.8 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
isr.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains code for the interrupt service routine
|
|||
|
for the Jazz Sound device driver.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Robin Speed (robinsp) 20-March-1992
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
Sameer Dekate (sameer@mips.com) 19-Aug-1992
|
|||
|
- Changes to support the MIPS sound board
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "sound.h"
|
|||
|
|
|||
|
//
|
|||
|
// Driver ISR
|
|||
|
//
|
|||
|
// When we get here, we acknowledge the interrupt from the
|
|||
|
// MIPSSND and simply let the defered processing routine take over
|
|||
|
// to complete the task.
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
SoundISR(
|
|||
|
IN PKINTERRUPT pInterrupt,
|
|||
|
IN PVOID Context
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Interrupt service routine for the MIPS sound card.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pInterrupt - our interrupt
|
|||
|
Contest - Pointer to our global device info
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if we handled the interrupt
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PGLOBAL_DEVICE_INFO pGDI;
|
|||
|
UCHAR configval, endianval, regval ;
|
|||
|
PSOUND_REGISTERS pSoundRegisters;
|
|||
|
|
|||
|
pGDI = (PGLOBAL_DEVICE_INFO)Context;
|
|||
|
ASSERT(pGDI->Key == GDI_KEY);
|
|||
|
|
|||
|
//
|
|||
|
// Save current Sound state, and then clear the interrupt(s) by writing
|
|||
|
// back the saved value. This works and is safe because the Interrupt bits
|
|||
|
// are "write zero to clear", the enable bit can't be set if DeviceInterrupt
|
|||
|
// bit is set, and the Channel bit can't be changed unless interrupts and
|
|||
|
// the enable bit are clear.
|
|||
|
//
|
|||
|
|
|||
|
pSoundRegisters = pGDI->SoundHardware.SoundVirtualBase;
|
|||
|
|
|||
|
// Clear the terminal count interrupt, disable interrupts
|
|||
|
endianval = READAUDIO_ENDIAN(&pSoundRegisters);
|
|||
|
WRITEAUDIO_ENDIAN(&pSoundRegisters,
|
|||
|
(endianval & ~(DMA_TCINTR | DMA_TCINTR_ENABLE)));
|
|||
|
|
|||
|
// Turn of Overflow and Underflow interrupts
|
|||
|
regval = READAUDIO_DMACNTRL(&pSoundRegisters);
|
|||
|
configval = READAUDIO_CONFIG(&pSoundRegisters);
|
|||
|
WRITEAUDIO_CONFIG(&pSoundRegisters,
|
|||
|
(configval & ~(REC_OVF_INTR | PLAY_UND_INTR)));
|
|||
|
|
|||
|
|
|||
|
dprintf5("SoundISR:d=0x%x c=0x%x e=0x%x",regval,configval,endianval);
|
|||
|
|
|||
|
if (configval & PLAY_UND_INTR) {
|
|||
|
|
|||
|
dprintf4("U");
|
|||
|
pGDI->GotUnderFlow = 1;
|
|||
|
|
|||
|
// Make sure we stop playing immediately
|
|||
|
WRITEAUDIO_DMACNTRL(&pSoundRegisters, (regval & ~PLAY_ENABLE));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If a terminal count interrupt has occured (TcInterrupt), then decrement
|
|||
|
// the pending interrupt count and schedule a Dpc to complete the transfer.
|
|||
|
//
|
|||
|
|
|||
|
if ((endianval & DMA_TCINTR) || (configval & PLAY_UND_INTR)) {
|
|||
|
|
|||
|
if ((configval & PLAY_UND_INTR) == 0)
|
|||
|
pGDI->SoundHardware.TcInterruptsPending -= 1;
|
|||
|
|
|||
|
switch (pGDI->Usage) {
|
|||
|
case SoundInterruptUsageWaveIn:
|
|||
|
dprintf5("i");
|
|||
|
IoRequestDpc(pGDI->pWaveInDevObj,
|
|||
|
pGDI->pWaveInDevObj->CurrentIrp,
|
|||
|
NULL);
|
|||
|
break;
|
|||
|
|
|||
|
case SoundInterruptUsageWaveOut:
|
|||
|
dprintf5("o");
|
|||
|
IoRequestDpc(pGDI->pWaveOutDevObj,
|
|||
|
pGDI->pWaveOutDevObj->CurrentIrp,
|
|||
|
NULL);
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If DeviceInterrupt (data overflow or underflow), and there are still
|
|||
|
// terminal count interrupts pending, restart controller, else set
|
|||
|
// DeviceBusy flag to false.
|
|||
|
//
|
|||
|
|
|||
|
// if (configval & REC_INTR) {
|
|||
|
// if (pGDI->SoundHardware.TcInterruptsPending != 0) {
|
|||
|
// WRITEAUDIO_DMACNTRL(&pSoundRegisters, (regval | REC_ENABLE));
|
|||
|
// }
|
|||
|
// }
|
|||
|
|
|||
|
//
|
|||
|
// Re-Enable the interrupts
|
|||
|
//
|
|||
|
|
|||
|
WRITEAUDIO_ENDIAN(&pSoundRegisters,
|
|||
|
(endianval & (~DMA_TCINTR | DMA_TCINTR_ENABLE)));
|
|||
|
|
|||
|
//
|
|||
|
// Execution continues in the Deferred Procedure Call when it is scheduled
|
|||
|
// Runs SoundInDeferred() or SoundOutDeferred() depending on REC or PLAY
|
|||
|
//
|
|||
|
|
|||
|
return TRUE;
|
|||
|
|
|||
|
DBG_UNREFERENCED_PARAMETER(pInterrupt);
|
|||
|
}
|
|||
|
|