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);
|
||
}
|
||
|