381 lines
7.7 KiB
C
381 lines
7.7 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
openclse.c
|
||
|
||
Abstract:
|
||
|
||
This module contains code for the device open/create and
|
||
close functions.
|
||
|
||
Author:
|
||
|
||
Nigel Thompson (nigelt) 25-Apr-1991
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
Revision History:
|
||
|
||
Robin Speed (RobinSp) 29-Jan-1992
|
||
- Large additions and change
|
||
|
||
Sameer Dekate (sameer@mips.com) 19-Aug-1992
|
||
- Changes to support the MIPS sound board
|
||
|
||
--*/
|
||
|
||
#include "sound.h"
|
||
|
||
|
||
NTSTATUS
|
||
sndCreate(
|
||
IN OUT PLOCAL_DEVICE_INFO pLDI
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Create call (for FILE_WRITE_DATA access). Read access is granted to
|
||
anyone in dispatch.c.
|
||
|
||
Arguments:
|
||
|
||
pLDI - our local device into
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS if OK or
|
||
STATUS_BUSY if someone else has the device
|
||
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
PGLOBAL_DEVICE_INFO pGDI;
|
||
|
||
pGDI = (PGLOBAL_DEVICE_INFO)pLDI->pGlobalInfo;
|
||
//
|
||
// Acquire the spin lock
|
||
//
|
||
|
||
GlobalEnter(pLDI->pGlobalInfo)
|
||
|
||
if (pLDI->DeviceType == WAVE_IN || pLDI->DeviceType == WAVE_OUT) {
|
||
|
||
//
|
||
// The other 3 devices share the interrupt
|
||
//
|
||
|
||
if (pLDI->pGlobalInfo->Usage != SoundInterruptUsageIdle) {
|
||
|
||
dprintf1("Attempt to open device while busy");
|
||
Status = STATUS_DEVICE_BUSY;
|
||
|
||
} else {
|
||
|
||
ASSERT(pLDI->pGlobalInfo->pIrpPause == NULL &&
|
||
pLDI->State == 0 &&
|
||
IsListEmpty(&pLDI->QueueHead));
|
||
|
||
|
||
pLDI->pGlobalInfo->DMABuffer[0].nBytes = 0;
|
||
pLDI->pGlobalInfo->DMABuffer[1].nBytes = 0;
|
||
pLDI->SampleNumber = 0;
|
||
|
||
//
|
||
// Initialize state data and interrupt usage for
|
||
// the chosen device type
|
||
//
|
||
|
||
switch (pLDI->DeviceType) {
|
||
case WAVE_IN:
|
||
|
||
pLDI->pGlobalInfo->Usage = SoundInterruptUsageWaveIn;
|
||
pLDI->pGlobalInfo->SamplesPerSec = WAVE_INPUT_DEFAULT_RATE;
|
||
pLDI->State = WAVE_DD_STOPPED;
|
||
|
||
//
|
||
// Set the input source
|
||
//
|
||
|
||
sndSetInputVolume(pGDI);
|
||
dprintf3("Opened for wave input");
|
||
|
||
Status = STATUS_SUCCESS;
|
||
break;
|
||
|
||
case WAVE_OUT:
|
||
|
||
ASSERT(IsListEmpty(&pLDI->TransitQueue) &&
|
||
IsListEmpty(&pLDI->DeadQueue));
|
||
|
||
pLDI->pGlobalInfo->Usage = SoundInterruptUsageWaveOut;
|
||
pLDI->pGlobalInfo->SamplesPerSec = WAVE_OUTPUT_DEFAULT_RATE;
|
||
pLDI->State = WAVE_DD_PLAYING;
|
||
|
||
dprintf3("Opened for wave output");
|
||
|
||
Status = STATUS_SUCCESS;
|
||
break;
|
||
|
||
default:
|
||
|
||
Status = STATUS_INTERNAL_ERROR;
|
||
break;
|
||
}
|
||
|
||
if (Status == STATUS_SUCCESS) {
|
||
ASSERT(!pLDI->DeviceBusy);
|
||
pLDI->DeviceBusy = TRUE;
|
||
}
|
||
}
|
||
} else {
|
||
Status = STATUS_INTERNAL_ERROR;
|
||
}
|
||
|
||
//
|
||
// Release the spin lock
|
||
//
|
||
GlobalLeave(pLDI->pGlobalInfo)
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
|
||
NTSTATUS
|
||
sndCleanUp(
|
||
IN OUT PLOCAL_DEVICE_INFO pLDI
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Clean up the requested device
|
||
|
||
Arguments:
|
||
|
||
pLDI - pointer to our local device info
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS if OK otherwise
|
||
STATUS_INTERNAL_ERROR
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
PGLOBAL_DEVICE_INFO pGDI;
|
||
|
||
pGDI = pLDI->pGlobalInfo;
|
||
|
||
//
|
||
// Acquire the spin lock
|
||
//
|
||
|
||
GlobalEnter(pGDI)
|
||
|
||
if (pLDI->DeviceType == WAVE_IN || pLDI->DeviceType == WAVE_OUT) {
|
||
|
||
//
|
||
// Check this is valid call
|
||
//
|
||
|
||
ASSERT(pLDI->DeviceBusy == TRUE);
|
||
|
||
//
|
||
// Call the device reset function to complete any
|
||
// pending i/o requests and terminate any current
|
||
// requests in progress
|
||
//
|
||
|
||
switch (pLDI->DeviceType) {
|
||
|
||
case WAVE_IN:
|
||
|
||
sndStopWaveInput(pLDI);
|
||
|
||
//
|
||
// Reset position to start and free any pending Irps.
|
||
//
|
||
sndFreeQ(pLDI, &pLDI->QueueHead, STATUS_CANCELLED);
|
||
pLDI->SampleNumber = 0;
|
||
|
||
break;
|
||
|
||
case WAVE_OUT:
|
||
|
||
//
|
||
// If anything is in the queue then free it.
|
||
// beware that the final block of a request may still be
|
||
// being dma'd when we get this call. We now kill this as well
|
||
// because we've changed such that the if the application thinks
|
||
// all the requests are complete then they are complete.
|
||
//
|
||
|
||
if (pGDI->DMABusy) {
|
||
|
||
#ifdef MIPSSND_TAIL_BUG
|
||
|
||
//
|
||
// Turn off the headphone and Lineout to avoid end clicks
|
||
//
|
||
sndMute(pGDI);
|
||
|
||
// We could also mute by turning of the headphone
|
||
// But mute using volume "sounds" better.
|
||
// sndHeadphoneControl(pGDI, OFF);
|
||
// sndLineoutControl(pGDI, OFF);
|
||
|
||
#endif // MIPSSND_TAIL_BUG
|
||
|
||
sndStopDMA(pGDI);
|
||
}
|
||
|
||
sndResetOutput(pLDI);
|
||
|
||
if (pGDI->pIrpPause) {
|
||
pGDI->pIrpPause->IoStatus.Status = STATUS_SUCCESS;
|
||
IoCompleteRequest(pGDI->pIrpPause, IO_SOUND_INCREMENT);
|
||
pGDI->pIrpPause = NULL;
|
||
}
|
||
|
||
break;
|
||
}
|
||
//
|
||
// return the device to it's idle state
|
||
//
|
||
|
||
if (Status == STATUS_SUCCESS) {
|
||
pLDI->State = 0;
|
||
pLDI->DeviceBusy = 2;
|
||
dprintf3("Device closing");
|
||
}
|
||
}
|
||
|
||
if ( pLDI->DeviceType != WAVE_IN && pLDI->DeviceType != WAVE_OUT ){
|
||
dprintf1("Bogus device type for cleanup request");
|
||
Status = STATUS_INTERNAL_ERROR;
|
||
}
|
||
|
||
|
||
#ifdef MIPSSND_TAIL_BUG
|
||
|
||
// Since the Device is now closed we can set the Output Volume
|
||
// just in case someone wants to play CDs or listen to Linein
|
||
|
||
sndSetOutputVolume( pGDI );
|
||
|
||
#endif // MIPSSND_TAIL_BUG
|
||
|
||
//
|
||
// Release the spin lock
|
||
//
|
||
|
||
GlobalLeave(pGDI);
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
sndClose(
|
||
IN OUT PLOCAL_DEVICE_INFO pLDI
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Close the requested device
|
||
|
||
Note - we close immediately, there is no waiting for the device.
|
||
|
||
Arguments:
|
||
|
||
pLDI - pointer to our local device info
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS if OK otherwise
|
||
STATUS_INTERNAL_ERROR
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
PGLOBAL_DEVICE_INFO pGDI;
|
||
|
||
pGDI = pLDI->pGlobalInfo;
|
||
|
||
//
|
||
// Acquire the spin lock
|
||
//
|
||
|
||
GlobalEnter(pGDI)
|
||
|
||
|
||
//
|
||
// Call the device reset function to complete any
|
||
// pending i/o requests and terminate any current
|
||
// requests in progress
|
||
//
|
||
|
||
switch (pLDI->DeviceType) {
|
||
case WAVE_IN:
|
||
case WAVE_OUT:
|
||
|
||
//
|
||
// Check this is valid call
|
||
//
|
||
ASSERT(pLDI->DeviceBusy == 2);
|
||
|
||
pGDI->Usage = SoundInterruptUsageIdle;
|
||
if (pLDI->DeviceType) {
|
||
|
||
//
|
||
// Restore the line in input if necessary
|
||
//
|
||
|
||
sndSetInputVolume(pGDI);
|
||
}
|
||
break;
|
||
|
||
default:
|
||
dprintf1("Bogus device type for close request");
|
||
Status = STATUS_INTERNAL_ERROR;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// return the device to it's idle state
|
||
//
|
||
|
||
if (Status == STATUS_SUCCESS) {
|
||
pLDI->DeviceBusy = FALSE;
|
||
dprintf3("Device closed");
|
||
}
|
||
|
||
#ifdef MIPSSND_TAIL_BUG
|
||
|
||
// Since the Device is now closed we can set the Output Volume
|
||
// just in case someone wants to play CDs or listen to Linein
|
||
|
||
sndSetOutputVolume( pGDI );
|
||
|
||
#endif // MIPSSND_TAIL_BUG
|
||
|
||
//
|
||
// Release the spin lock
|
||
//
|
||
|
||
GlobalLeave(pGDI);
|
||
|
||
return Status;
|
||
}
|
||
|
||
|