2020-09-30 17:12:29 +02:00

162 lines
3.8 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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);
}