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

📄 dispatch.cpp

📁 使用DDK编写的PCI9054芯片的驱动程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/******************************************************************************
 * * File Name:
 * *      Dispatch.cpp
 * * Description:
 * *      This file routes incoming I/O Request packets.
 * *		该文件是处理IRP的。
 * * Revision History:
 * *      03-3-02 : PDC4000 v1.00
 *******************************************************************************/

#include "PDC4000.h"
#include "Ioctl.h"

/******************************************************************************
 *
 * Function   :  DispatchCreate
 *
 * Description:  Handle IRP_MJ_CREATE, which allows applications to open handles
 *               to our device, 相应的是函数CreateFile().
 *
 ******************************************************************************/
NTSTATUS DispatchCreate(IN PDEVICE_OBJECT fdo,
						IN PIRP pIrp)
{											//DispatchCreate
    KdPrint((DBG_NAME "CreateFile.\n"));
	//可以在此,做一些初始化工作
    return CompleteRequestInfo(pIrp, STATUS_SUCCESS,0);
}											//DispatchCreate
/******************************************************************************
 *
 * Function   :  DispatchCleanup
 *
 * Description:  Handle the IRP_MJ_CLEANUP IRP.
 *				 在驱动程序被暂停或卸载的时候,需要将IRP栈内所有的IRP清除掉。
 ******************************************************************************/
NTSTATUS DispatchCleanup(IN PDEVICE_OBJECT fdo,
						 IN PIRP  pIrp)
{											//DispatchCleanup
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
	KIRQL OldIrql;

	KdPrint((DBG_NAME "DispatchCleanup Start.\n"));

	IoAcquireCancelSpinLock(&OldIrql);

	// Cancel all IRPs in the I/O Manager maintained queue in device object
	PKDEVICE_QUEUE_ENTRY QueueEntry;
	//清除所有的IRP
	while( (QueueEntry=KeRemoveDeviceQueue(&fdo->DeviceQueue)) != NULL)
	{
		PIRP CancelIrp = CONTAINING_RECORD( QueueEntry, IRP, Tail.Overlay.DeviceQueueEntry);
		CancelIrp->Cancel = TRUE;
		CancelIrp->CancelIrql = OldIrql;
		CancelIrp->CancelRoutine = NULL;

		IoReleaseCancelSpinLock(OldIrql);
		KdPrint((DBG_NAME "WdmIoDispatchCleanup: Cancelling %x %I\n", CancelIrp, CancelIrp));
		UnlockDevice(pdx);

		CancelIrp->IoStatus.Status = STATUS_CANCELLED;
		CancelIrp->IoStatus.Information = 0;
		IoCompleteRequest(CancelIrp,IO_NO_INCREMENT);

		IoAcquireCancelSpinLock(&OldIrql);
	}
	IoReleaseCancelSpinLock(OldIrql);

    return CompleteRequestInfo(pIrp,STATUS_SUCCESS,0);
}											//DispatchCleanup

/************************************************************************
 *
 * Function   :  DispatchClose
 *
 * Description:  Handle IRP_MJ_CLOSE, which allows applications to close handles
 *               to our device,相应的是函数CloseHandle().
 *
 ******************************************************************************/
NTSTATUS DispatchClose(IN PDEVICE_OBJECT fdo,
					   IN PIRP  pIrp)
{												//DispatchClose
	KdPrint((DBG_NAME "CloseFile.\n"));
	//进行处理
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
	pdx->pWaitEvent = NULL;
	pdx->bSetWaitEvent = NULL;

    return CompleteRequestInfo(pIrp,STATUS_SUCCESS,0);
}												//DispatchClose

/******************************************************************************
 *
 * Function   :  DispatchRead
 *
 * Description:  Handle IRP_MJ_READ, which is not implemented by this driver
 *					ReadFile
 ******************************************************************************/
NTSTATUS DispatchRead(IN PDEVICE_OBJECT fdo,
					  IN PIRP pIrp)
{													//DispatchRead
	KdPrint((DBG_NAME "Read Device Start.\n"));
	
	ULONG ReturnedValue;

	NTSTATUS status = STATUS_SUCCESS;

//	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
	
//	ReturnedValue = 0;
	
	//将从硬件采集到的数据送给应用程序, 如果不能很快处理,将IRP进行串行化,交给StartIo处理。
	//Transfer data from local mem by using SGL DMA.
	IoMarkIrpPending(pIrp);
	IoStartPacket(fdo, pIrp, NULL, CancelIrp);
		
	KdPrint((DBG_NAME "Read Device End.\n"));
    return STATUS_PENDING;
	// Just complete the request
 //	return CompleteRequestInfo(pIrp,status,ReturnedValue);
}													//DispatchRead

/******************************************************************************
 *
 * Function   :  DispatchWrite
 *
 * Description:  Handle the IRP_MJ_WRITE, which is not implemented by this driver
 *					WriteFile
 ******************************************************************************/
NTSTATUS DispatchWrite(IN PDEVICE_OBJECT fdo,
					   IN PIRP pIrp)
{												//DispatchWrite
	KdPrint((DBG_NAME "Write File Start.\n"));
	
//	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;


	//将应用程序的数据送到硬件, 将IRP串行化,交给StartIo处理
	//Transfer the data to local mem by using SGL DMA.
	IoMarkIrpPending(pIrp);
	IoStartPacket(fdo, pIrp, NULL, CancelIrp);
	
	KdPrint((DBG_NAME "Write File End.\n"));
	return STATUS_PENDING;
}												//DispatchWrite
 
/******************************************************************************
 *
 * Function   :  DispatchSystemControl
 *
 * Description:  The dispatch routine for WMI IRPs.  It does nothing except
 *               forward the IRP to the next device in the stack.
 *
 ******************************************************************************/
NTSTATUS DispatchSystemControl(IN PDEVICE_OBJECT fdo,
							   IN PIRP pIrp)
{												//DispatchSystemControl
	KdPrint((DBG_NAME "SystemControl.\n"));

    IoSkipCurrentIrpStackLocation(pIrp);

    return IoCallDriver(((DEVICE_EXTENSION *)fdo->DeviceExtension)->pLowerDeviceObject,
						pIrp);
}												//DispatchSystemControl

/******************************************************************************
 *
 * Function   :  DispatchIoControl
 *
 * Description:  Processes the IOCTL IRPs sent to this device.
 *
 * Note       :  The Fast Mutex used in this routine is left here because
 *               some multi-CPU systems hang if it is removed.  As of this time
 *               the cause for this is unknown.  Once the cause is determined,
 *               the Fast Mutex will most likely be removed in a future release.
 *               Performance may improve slightly once it is removed since the
 *               DPC_LEVEL won't continuously need to go between PASSIVE and APC.
 *
 ******************************************************************************/
NTSTATUS DispatchIoControl(IN PDEVICE_OBJECT fdo,
						   IN PIRP pIrp)
{										//DispatchIoControl
    ULONG					i;
    NTSTATUS				status;
    PDEVICE_EXTENSION		pdx;
    PIO_STACK_LOCATION		pIrpStack;
	ULONG					lReturnedValue;
	ULONG					lPdcAddress;		//The base address of PDC4000
	RETURN_CODE				rc;
	ULONG					lDmaMode;
	DMA_CHANNEL_DESCRIPTION dcd;
	DMA_TRANSFER_ELEMENT	dte;

    pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

    pIrpStack = IoGetCurrentIrpStackLocation(pIrp);


    // Assume a successful return status
    status = STATUS_SUCCESS;

    // Lock device to record usage
	LockDevice(pdx);

	KdPrint((DBG_NAME "DeviceIoControl Start.\n"));

    // Handle the PDC4000 specific message
	//处理DeviceIoControl。
    switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode)
    {		//PDC4000 
	case IOCTL_PDC4000_REGISTER_EVENT:		//注册Event变量
		status = ObReferenceObjectByHandle(*(PHANDLE)pIrp->AssociatedIrp.SystemBuffer, 
					EVENT_MODIFY_STATE, *ExEventObjectType,
					pIrp->RequestorMode, (PVOID*)&pdx->pWaitEvent, NULL);
		if (!NT_SUCCESS(status))
		{
			pdx->bSetWaitEvent = FALSE;
			KdPrint((DBG_NAME "WARNNING - ObReferenceObjectByHandle failed\n"));
		}
		else 
		{
			pdx->bSetWaitEvent = TRUE;
			KdPrint((DBG_NAME "OK - ObReferenceObjectByHandle succeed\n"));
		}
		lReturnedValue = 0;
		break;
	case IOCTL_PDC4000_UNREGISTER_EVENT:	//反注册Event变量
		pdx->pWaitEvent = NULL;
		pdx->bSetWaitEvent = FALSE;
		lReturnedValue = 0;
		break;
	case IOCTL_PDC4000_READ_DATA:	
		ULONG Num, Buffer;
		
		lPdcAddress = (ULONG)pdx->PdcMemBase0;

		RtlCopyMemory(&Num, pIrp->AssociatedIrp.SystemBuffer, sizeof(ULONG));
		KdPrint((DBG_NAME "Input Value is %x.", Num));
		Buffer = READ_REGISTER_UCHAR((unsigned char *)(lPdcAddress + Num));
		KdPrint((DBG_NAME "Read Data Value is %x.\n", Buffer));
		RtlCopyMemory( pIrp->AssociatedIrp.SystemBuffer, &Buffer, sizeof(ULONG));
		lReturnedValue = sizeof(ULONG);
		break;
	case IOCTL_PDC4000_WRITE_DATA:
		ULONG dwWriteBuffer[2];
		
		lPdcAddress = (ULONG)pdx->PdcMemBase0;

		RtlCopyMemory(dwWriteBuffer, pIrp->AssociatedIrp.SystemBuffer, 2 * sizeof(ULONG));

		WRITE_REGISTER_UCHAR((unsigned char *)(lPdcAddress + dwWriteBuffer[0]), (CHAR)dwWriteBuffer[1]);
		KdPrint((DBG_NAME "Write Data Value is %x.\n", dwWriteBuffer[1]));

		lReturnedValue = 0;
		break;
	case IOCTL_PDC4000_BLOCK_DMA_PCI_TO_LOCAL:	
		ULONG lDMAPciToLocalTransferSize;
		
		lDMAPciToLocalTransferSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;//0x10;

		//Copy the data to the Common buffer.
		RtlCopyMemory(pdx->DmaInfo[0].vaCommonBuffer, pIrp->AssociatedIrp.SystemBuffer, lDMAPciToLocalTransferSize);

		KdPrint((DBG_NAME "The vaCommonBuffer is %X.\n", *(unsigned char *)(pdx->DmaInfo[0].vaCommonBuffer)));
	
		lPdcAddress = (ULONG)pdx-> ;
/*
	//自己操作Block DMA
		lDmaMode = 0x20540;
		WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_MODE), lDmaMode);
		//PCI Address
		WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_PCI_ADDR), pdx->DmaInfo[0].paCommonBuffer.LowPart);
		//Local Address
		WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_LOCAL_ADDR), 0);
		//Transfer Size
		WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_COUNT),  lDMAPciToLocalTransferSize);
		//DMA Descriptor Pointer
		WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_DESC_PTR), 0x0);
			
		//Initiate DMA Transfer
		WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA_COMMAND_STAT), 0x3);
	
*/		
		dcd.BTERMInputEnable	= 0;
		dcd.DACChainLoad		= 0;
		dcd.DemandMode			= 0;
		dcd.DmaChannelPriority	= Rotational;
		dcd.DmaEOTPinEnable		= 0;
		dcd.DoneInterrputEnable = 1;
		dcd.EnableTransferCountClear = 0;	//For sgl DMA
		dcd.FastSlowTerminateModeSelect = 0;
		dcd.InternalWaitStates	= 0;
		dcd.InterrputSelect		= 1;
		dcd.LocalAddressingMode = 0;
		dcd.LocalBurstEnable	= 1;
		dcd.LocalBusWidth		= 0;
		dcd.MemoryWriteAndInvalidateMode = 0;
		dcd.ReadyInputEnable	= 1;
		dcd.ScatterGatherMODE	= 0;
		//DMA threshold
		dcd.LocalToPciAlmostEmpty	= 0;
		dcd.LocalToPciAlmostFull	= 0;
		dcd.PciToLocalAlmostEmpty	= 0;
		dcd.PciToLocalAlmostFull	= 0;
		pdx->DmaInfo[0].bWriteToLocal = TRUE;
		rc = DmaOpenBlockChannel(pdx, 0, &dcd);
		if (rc != RC_SUCCESS)
		{
			KdPrint((DBG_NAME "Can't DmaOpenBlockChannel.\n"));
			lReturnedValue = 0;
			UnlockDevice(pdx);
			return CompleteRequestInfo(pIrp, status, lReturnedValue);
		}
		KdPrint((DBG_NAME "Had Open DMA Channel.\n"));
		//Set Address and Transfer Size.
		dte.lLocalAddress = 0;
		dte.lPciAddress = pdx->DmaInfo[0].paCommonBuffer.LowPart;
		dte.lPciDualAddress = 0;
		dte.lTransferSize = lDMAPciToLocalTransferSize;	//

		dte.DescriptorLocation = 0;
		dte.DirectionOfTransfer = 0;
		dte.EndOfChain = 0;
		dte.InterruptAfterTerminalCount = 0;
		dte.NextDescriptorAddress = 0;
		
		KdPrint((DBG_NAME "The lDMAPciToLocalTransferSize is 0x%X.\n", lDMAPciToLocalTransferSize));
	
		
		rc = DmaBlockTransfer(pdx, 0, &dte);
		if (rc != RC_SUCCESS)
		{DmaBlockTransfer
			KdPrint((DBG_NAME "Can't DmaBlockTransfer.\n"));
		}

		KdPrint((DBG_NAME "IOCTL_PDC4000_BLOCK_DMA_PCI_TO_LOCAL End.\n"));
		break;
	case IOCTL_PDC4000_BLOCK_DMA_LOCAL_TO_PCI:

		IoMarkIrpPending(pIrp);
		IoStartPacket(fdo, pIrp, NULL, CancelIrp);

	/*	//直接操作Block Dma
		lDmaMode = 0x40540;
		WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_MODE), lDmaMode);
		//PCI Address
		WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_PCI_ADDR), pdx->DmaInfo[0].paCommonBuffer.LowPart);
		//Local Address
		WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_LOCAL_ADDR), 0);
		//Transfer Size
		WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_COUNT),  lDMALocalToPciTransferSize);
		//DMA Descriptor Pointer
		WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_DESC_PTR), 0x8);
			
		//Initiate DMA Transfer
		WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA_COMMAND_STAT), 0x3);

		KdPrint((DBG_NAME "The vaCommonBuffer is %X.\n", *(unsigned char *)(pdx->DmaInfo[0].vaCommonBuffer)));
		//Copy the data to the Common buffer.
		RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer, pdx->DmaInfo[0].vaCommonBuffer, lDMALocalToPciTransferSize);
	*/
	/*	//通过函数调用
		ULONG lDMALocalToPciTransferSize;
		lDMALocalToPciTransferSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;//0x100;
		
		lPdcAddress = (ULONG)pdx->LocalRegisterMemBase;
		dcd.BTERMInputEnable	= 0;
		dcd.DACChainLoad		= 0;
		dcd.DemandMode			= 0;
		dcd.DmaChannelPriority	= Rotational;
		dcd.DmaEOTPinEnable		= 0;
		dcd.DoneInterrputEnable = 1;
		dcd.EnableTransferCountClear = 0;	//For sgl DMA
		dcd.FastSlowTerminateModeSelect = 0;
		dcd.InternalWaitStates	= 0;
		dcd.InterrputSelect		= 1;
		dcd.LocalAddressingMode = 0;
		dcd.LocalBurstEnable	= 1;
		dcd.LocalBusWidth		= 0;
		dcd.MemoryWriteAndInvalidateMode = 0;
		dcd.ReadyInputEnable	= 1;
		dcd.ScatterGatherMODE	= 0;
		//DMA threshold
		dcd.LocalToPciAlmostEmpty	= 0;
		dcd.LocalToPciAlmostFull	= 0;
		dcd.PciToLocalAlmostEmpty	= 0;
		dcd.PciToLocalAlmostFull	= 0;
		pdx->DmaInfo[0].bWriteToLocal = FALSE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -