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

381 lines
7.7 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:
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;
}