⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 channel2.c

📁 driver wdk
💻 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 + -