📄 channel2.c
字号:
//++
// File Name:
// channel2.c
//
// Contents:
// Routines to manage channel 2
//--
#include "ave2k.h"
#include "ave2kregs.h"
#include "channel2.h"
//++
// Function:
// Ave2kChannel2StartPacket
//
// Description:
// This function is responsible for doing any
// function-code specific pre-processing and
// then starting the actual data transfer.
//
// Arguments:
// Pointer to the Device object
// Pointer to the IRP for this request
//
// Return Value:
// (None)
//
// Synchronization:
// This routine is called at PASSIVE_LEVEL IRQL,
// but it pops up to DISPATCH_LEVEL.
//
//--
VOID
Ave2kChannel2StartPacket(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PDRIVER_CANCEL CancelFunction
)
{
KIRQL OldIrql;
PDEVICE_EXTENSION pDE =
DeviceObject->DeviceExtension;
IoAcquireCancelSpinLock( &OldIrql );
IoSetCancelRoutine( Irp, CancelFunction );
if( KeInsertDeviceQueue(
&pDE->AlternateIrpQueue,
&Irp->Tail.Overlay.DeviceQueueEntry ))
{
IoReleaseCancelSpinLock( OldIrql );
}
else
{
pDE->CurrentAlternateIrp = Irp;
IoReleaseCancelSpinLock( OldIrql );
KeRaiseIrql( DISPATCH_LEVEL, &OldIrql );
Ave2kChannel2StartIo( DeviceObject, Irp );
KeLowerIrql( OldIrql );
}
}
//++
// Function:
// Ave2kChannel2StartNextPacket
//
// Description:
// This function is responsible for doing any
// function-code specific pre-processing and
// then starting the actual data transfer.
//
// Arguments:
// Pointer to the Device object
// BOOLEAN indicating whether
// to grab Cancel spin lock
//
// Return Value:
// (None)
//
// Synchronization:
// This routine *MUST* be called at
// DISPATCH_LEVEL IRQL.
//
//--
VOID
Ave2kChannel2StartNextPacket(
IN PDEVICE_OBJECT DeviceObject,
IN BOOLEAN Cancelable
)
{
PDEVICE_EXTENSION pDE =
DeviceObject->DeviceExtension;
PKDEVICE_QUEUE_ENTRY QueueEntry;
PIRP Irp;
KIRQL OldIrql;
if( Cancelable )
IoAcquireCancelSpinLock( &OldIrql );
QueueEntry =
KeRemoveDeviceQueue(
&pDE->AlternateIrpQueue );
if( QueueEntry != NULL )
{
Irp = CONTAINING_RECORD(
QueueEntry,
IRP,
Tail.Overlay.DeviceQueueEntry );
pDE->CurrentAlternateIrp = Irp;
if( Cancelable )
IoReleaseCancelSpinLock( OldIrql );
Ave2kChannel2StartIo( DeviceObject, Irp );
}
else
{
pDE->CurrentAlternateIrp = NULL;
if( Cancelable )
IoReleaseCancelSpinLock( OldIrql );
}
}
//++
// Function:
// Ave2kChannel2StartIo
//
// Description:
// This function is responsible for doing any
// function-code specific pre-processing and
// then starting the actual data transfer.
//
// Arguments:
// Pointer to the Device object
// Pointer to the IRP for this request
//
// Return Value:
// (None)
//--
VOID
Ave2kChannel2StartIo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
KIRQL OldIrql;
PIO_STACK_LOCATION IrpStack =
IoGetCurrentIrpStackLocation( Irp );
PDEVICE_EXTENSION pDE =
DeviceObject->DeviceExtension;
//
// Before starting the operation, see if the
// Cancel routine has run between the time
// the IRP was removed from the Device Queue
// and now. Start by grabbing the Cancel spin
// lock.
//
IoAcquireCancelSpinLock( &OldIrql );
//
// Check the state of the Cancel flag. If
// it's set, release the spin lock and return
// immediately. The IRP has already been
// processed by the Cancel routine.
//
if( Irp->Cancel )
{
IoReleaseCancelSpinLock( OldIrql );
return;
}
//
// If the Cancel flag is clear, remove the
// IRP from the cancelable state and start
// processing it.
//
else
{
IoSetCancelRoutine( Irp, NULL);//Ave2kCancelChannel2Irp);
IoReleaseCancelSpinLock( OldIrql );
}
/*
//
// Set up counts and byte pointer
//
KeAcquireSpinLock(&pDE->ReadLock2, &OldIrql);
#ifdef USING_DIRECT_IO
pDE->CurrentAlternateIrpBuffer=
MmGetSystemAddressForMdl(Irp->MdlAddress);
#else
pDE->CurrentAlternateIrpBuffer=
Irp->AssociatedIrp.SystemBuffer; //Using buffered I/O
#endif
KeReleaseSpinLock(&pDE->ReadLock2, OldIrql);
Ave2kDpcForChannel2(
NULL,
pDE->DeviceObject,
NULL,
NULL
);
// KeInsertQueueDpc(
// &pDE->AlternateDpc,
// NULL,
// NULL
// );
*/
/*
//
// Try to start receiving data frame.
if(KeSynchronizeExecution(
pDE->pInterrupt,
SyncChannel2Read,
pDE ))
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = IrpStack->Parameters.Read.Length //sizeof(AUDIOSTREAMSECTOR);
Ave2kChannel2StartNextPacket(DeviceObject,TRUE);
IoCompleteRequest(Irp,IO_NO_INCREMENT);
pDE->CurrentAlternateIrpBuffer=NULL;
}
KeReleaseSpinLock(&pDE->ReadLock2, OldIrql);
ErrorRecover(pDE, 1);
*/
}
//++
// Function:
// Ave2kDpcForChannel2
//
// Description:
// This function is responsible for doing any
// function-code specific post-processing a IRP after
// interrupt happens.
//
// Arguments:
// Pointer to the KDPC
// Pointer to the context past by caller
// Pointer to the SystemArgument1 and SystemArgument2.
//
// Return Value:
// (None)
//--
VOID
Ave2kDpcForChannel2
(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
)
{
PIO_STACK_LOCATION IrpStack;
PDEVICE_OBJECT DeviceObject = DeferredContext;
PDEVICE_EXTENSION pDE = DeviceObject->DeviceExtension;
PIRP Irp = pDE->CurrentAlternateIrp;
KIRQL OldIrql;
ULONG BufLen;
KeAcquireSpinLock(&pDE->ReadLock2,&OldIrql);
//KeSynchronizeExecution(
// pDE->pInterrupt,
// SyncChannel2Write,
// (PVOID)pDE);
SyncChannel2Write((PVOID)pDE);
KeReleaseSpinLock(&pDE->ReadLock2,OldIrql);
if(Irp == NULL)
return ;
IoAcquireCancelSpinLock( &OldIrql );
//
// Check the state of the Cancel flag. If
// it's set, release the spin lock and return
// immediately. The IRP has already been
// processed by the Cancel routine.
//
if( Irp->Cancel )
{
IoReleaseCancelSpinLock( OldIrql );
return;
}
IoReleaseCancelSpinLock( OldIrql );
KeAcquireSpinLock(&pDE->ReadLock2,&OldIrql);
if(pDE->CurrentAlternateIrpBuffer==NULL){
KeReleaseSpinLock(&pDE->ReadLock2,OldIrql);
return;
}
Irp = pDE->CurrentAlternateIrp;
ASSERT(Irp!=NULL);
IrpStack =IoGetCurrentIrpStackLocation( Irp );
ASSERT(IrpStack!=NULL);
BufLen=IrpStack->Parameters.Read.Length;
//if(KeSynchronizeExecution(
// pDE->pInterrupt,
// SyncChannel2Read,
// (PVOID)pDE))
if(AudioDespListRead(pDE, BufLen, 1))
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = IrpStack->Parameters.Read.Length; /*sizeof(AUDIOSTREAMSECTOR)*/;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
pDE->CurrentAlternateIrpBuffer=NULL;
Ave2kChannel2StartNextPacket(DeviceObject,TRUE);
}
KeReleaseSpinLock(&pDE->ReadLock2,OldIrql);
ErrorRecover(pDE, 1);
}
//++
// Function:
// SyncChannel2Read
//
// Description:
// This function is responsible for reading data from channel2's DMA
// buffer to current alternate IRP.
//
// Arguments:
// Pointer to the SynchronizeContext, caller should pass PDEVICE_EXTENSION.
//
// Return Value:
// TRUE if one frame is read successfully.
//--
BOOLEAN
SyncChannel2Read(
PVOID SynchronizeContext)
{
PDEVICE_EXTENSION pDE;
PDEVICE_OBJECT pDeviceObject;
PIRP pIrp;
ULONG BufLen;
PIO_STACK_LOCATION IrpStack;
pDE=(PDEVICE_EXTENSION)SynchronizeContext;
pDeviceObject = pDE->DeviceObject;
pIrp=pDE->CurrentAlternateIrp;
if(pIrp == NULL)
return FALSE;
IrpStack=IoGetCurrentIrpStackLocation( pIrp );
BufLen=IrpStack->Parameters.Read.Length;
//if(pDE->DataReceiving[1]==TRUE){
// if(!(Ave2kReadRegister(pDE, MC1)&0x01))
// KdPrint(("Ch2: Detected DMA off\n"));
// if(Ave2kReadRegister(pDE, RPS_ADDR0)!=pDE->RPS[0].PhysicalAddress+9*sizeof(ULONG))
// KdPrint(("Ch2: Detected active RPS\n"));
//}
return AudioDespListRead(pDE, BufLen, 1);
//&pDE->AudioBufferList2,
// pDE->CurrentAlternateIrpBuffer, BufLen, pDE->DataFilter[1]);
}
//++
// Function:
// SyncChannel2Write
//
// Description:
// This function is responsible for updating data structure that
// describes status of DMA buffer.
//
// Arguments:
// Pointer to the SynchronizeContext, caller should pass PDEVICE_EXTENSION.
//
// Return Value:
// TRUE if successful.
//--
BOOLEAN
SyncChannel2Write(
PVOID SynchronizeContext
)
{
PDEVICE_EXTENSION pDE;
PUCHAR DMAPointer; //Virtual address of current DMA pointer
ULONG CurOffset;
ULONG Distance; //distance between write pointer and current DMA pointer
PUCHAR LimitPointer;
PAUDIODESPLIST pDespList;
pDE=(PDEVICE_EXTENSION)SynchronizeContext;
pDespList = &pDE->AudioBufferList2;
CurOffset=Ave2kReadRegister(pDE, PCI_ADP2) -
pDE->DataCommonBuffer2.DMAAddress;
LimitPointer = pDE->DataCommonBuffer2.BaseAddress +
pDE->DataCommonBuffer2.Length;
DMAPointer= pDE->DataCommonBuffer2.BaseAddress + CurOffset;
if(DMAPointer >= pDespList->pWritePointer->pData)
Distance = DMAPointer - pDespList->pWritePointer->pData;
else
Distance = CurOffset + LimitPointer - pDespList->pWritePointer->pData;
while(Distance >= sizeof(AUDIOSTREAMSECTOR)){
if(pDespList->pWritePointer->Flags.ownbit == 1){
//the buffer ring is full, discard old data frame
ASSERT(pDespList->pWritePointer ==pDespList->pReadPointer);
pDE->Stat[1].PacketLost++;
pDespList->pReadPointer =
pDespList->pReadPointer->pNext;
}
pDespList->pWritePointer->Flags.ownbit = 1;
pDespList->pWritePointer->Flags.datalen = sizeof(AUDIOSTREAMSECTOR);
pDespList->pWritePointer =
pDespList->pWritePointer->pNext;
Distance-=sizeof(AUDIOSTREAMSECTOR);
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -