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

📄 dispatch.cpp

📁 使用DDK编写的PCI9054芯片的驱动程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		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);
		}
		//Set Address and Transfer Size.
		dte.lLocalAddress = 0;
		dte.lPciAddress = pdx->DmaInfo[0].paCommonBuffer.LowPart;
		dte.lPciDualAddress = 0;
		dte.lTransferSize = lDMALocalToPciTransferSize;	//

		dte.DescriptorLocation = 0;
		dte.DirectionOfTransfer = 1;
		dte.EndOfChain = 0;
		dte.InterruptAfterTerminalCount = 0;
		dte.NextDescriptorAddress = 0;
		
		pdx->DmaInfo[0].lTransferedBytes = lDMALocalToPciTransferSize;

		rc = DmaBlockTransfer(pdx, 0, &dte);
		if (rc != RC_SUCCESS)
		{
			KdPrint((DBG_NAME "Can't DmaBlockTransfer.\n"));
		}
		lReturnedValue = lDMALocalToPciTransferSize;
	*/	
		status = STATUS_PENDING;
		break;
	case IOCTL_PDC4000_READ_REG_DATA:	
		unsigned long lNumReg, lBufferReg;
		
		lPdcAddress = (ULONG)pdx->LocalRegisterMemBase;
	//	KdPrint((DBG_NAME "The LocalRegisterMemBase is %x.\n", lPdcAddress));
		RtlCopyMemory(&lNumReg, pIrp->AssociatedIrp.SystemBuffer, sizeof(ULONG));
		KdPrint((DBG_NAME "Input Value is %x.\n", lNumReg));
		lBufferReg = READ_REGISTER_ULONG((unsigned long *)(lPdcAddress + lNumReg));
		KdPrint((DBG_NAME "Read Reg Data Value is %x.\n", lBufferReg));
		RtlCopyMemory( pIrp->AssociatedIrp.SystemBuffer, &lBufferReg, sizeof(ULONG));
		lReturnedValue = sizeof(ULONG);
		break;
	case IOCTL_PDC4000_WRITE_REG_DATA:
		unsigned long lWriteBufferReg[2];
		
		lPdcAddress = (ULONG)pdx->LocalRegisterMemBase;

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

		WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + lWriteBufferReg[0]), lWriteBufferReg[1]);
		KdPrint((DBG_NAME "Write Reg Data Value is %x.\n", lWriteBufferReg[1]));

		lReturnedValue = 0;
		break;
	case IOCTL_PDC4000_BURST_READ_DATA:
		unsigned char cNumBurst, cBufferBurst[16];
		
		lPdcAddress = (ULONG)pdx->PdcMemBase0;

		RtlCopyMemory(&cNumBurst, pIrp->AssociatedIrp.SystemBuffer, 1);
		KdPrint((DBG_NAME "Input Value is %x.\n", cNumBurst));
		READ_REGISTER_BUFFER_UCHAR((unsigned char *)(lPdcAddress + cNumBurst), cBufferBurst, 16);
		KdPrint((DBG_NAME "Read Data Value is: \n"));
		for (i = 0; i < 16; i ++)
		{
			KdPrint((DBG_NAME "[%d]: %X.\n", i, cBufferBurst[i]));
		}
		RtlCopyMemory( pIrp->AssociatedIrp.SystemBuffer, cBufferBurst, 16);
		lReturnedValue = 16;
		break;
	case IOCTL_PDC4000_BURST_WRITE_DATA:
		unsigned char cWriteBufferBurst[17];
		
		lPdcAddress = (ULONG)pdx->PdcMemBase0;
	//	KdPrint((DBG_NAME "The PdcMemBase0 is %x.\n", lPdcAddress));

		RtlCopyMemory(cWriteBufferBurst, pIrp->AssociatedIrp.SystemBuffer, 17);

		WRITE_REGISTER_BUFFER_UCHAR((unsigned char *)(lPdcAddress + cWriteBufferBurst[0]), &cWriteBufferBurst[1], 16);
		KdPrint((DBG_NAME "Write Data Value is %x.\n", cWriteBufferBurst[1]));

		lReturnedValue = 0;
		break;
	default:
        break;
    }

    UnlockDevice(pdx);

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

    if (status == STATUS_PENDING)
        return STATUS_PENDING;

    return CompleteRequestInfo(pIrp, status, lReturnedValue);
}												//DispatchIoControl
/******************************************************************************
 *
 * Function   :  StartIo
 *
 * Description:  The StartIo Service Routine for PDC4000.
 *
 ******************************************************************************/
VOID StartIo(IN PDEVICE_OBJECT fdo,
			 IN PIRP pIrp)
{												//StartIo
	PDEVICE_EXTENSION pdx			= (PDEVICE_EXTENSION)fdo->DeviceExtension;
	PIO_STACK_LOCATION pIrpStack	= IoGetCurrentIrpStackLocation(pIrp);

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

	NTSTATUS status = STATUS_SUCCESS;
	
	BOOLEAN bResult;

	RETURN_CODE rc;

	PMDL pMdl;
	DMA_CHANNEL_DESCRIPTION dcd;

/*	if (!LockDevice(pdx))
	{
		CompleteRequest(pIrp, STATUS_DELETE_PENDING);
	}
*/

	
	// Switch on the IRP major function code
	switch(pIrpStack->MajorFunction)
	{
	case IRP_MJ_WRITE:
		//Open Dma Channl0
		
		dcd.BTERMInputEnable	= 0;
		dcd.DACChainLoad		= 0;
		dcd.DemandMode			= 0;
		dcd.DmaChannelPriority	= Rotational;
		dcd.DmaEOTPinEnable		= 0;
		dcd.DoneInterrputEnable = 1;
		dcd.EnableTransferCountClear = 1;	//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	= 1;
		//DMA threshold
		dcd.LocalToPciAlmostEmpty	= 0;
		dcd.LocalToPciAlmostFull	= 0;
		dcd.PciToLocalAlmostEmpty	= 0;
		dcd.PciToLocalAlmostFull	= 0;
		
		rc = DmaOpenSglChannel(pdx, 0, &dcd);
		if (rc != RC_SUCCESS)
		{
			CompleteRequestInfo(pIrp, status, 0);
			IoStartNextPacket(fdo, TRUE);
			KdPrint((DBG_NAME "Can't DmaOpenBlockChannel.\n"));
		}
		//DMA Transfer Data
		pdx->DmaInfo[0].bWriteToLocal = TRUE;
		pMdl = pIrp->MdlAddress;	
		KeFlushIoBuffers(pMdl, FALSE, TRUE);	//For Dma Transfer

		status = (*pdx->DmaInfo[0].pDmaAdapterObject->DmaOperations->AllocateAdapterChannel)(
								pdx->DmaInfo[0].pDmaAdapterObject, 
								fdo, 
								pdx->DmaInfo[0].lNumberOfMapRegisters,
								(PDRIVER_CONTROL) AdapterControl,		//ExecutionRoutine 
								pdx);	//Context
		if (!NT_SUCCESS(status))
		{
			CompleteRequestInfo(pIrp, status, 0);
			IoStartNextPacket(fdo, TRUE);
		}
		return;	//退出StartIo;
		break;
	case IRP_MJ_READ:
		//Open Dma Channl0

		
			
		dcd.BTERMInputEnable	= 0;
		dcd.DACChainLoad		= 0;
		dcd.DemandMode			= 0;
		dcd.DmaChannelPriority	= Rotational;
		dcd.DmaEOTPinEnable		= 0;
		dcd.DoneInterrputEnable = 1;
		dcd.EnableTransferCountClear = 1;	//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	= 1;
		//DMA threshold
		dcd.LocalToPciAlmostEmpty	= 0;
		dcd.LocalToPciAlmostFull	= 0;
		dcd.PciToLocalAlmostEmpty	= 0;
		dcd.PciToLocalAlmostFull	= 0;

		rc = DmaOpenSglChannel(pdx, 0, &dcd);
		if (rc != RC_SUCCESS)
		{
			CompleteRequestInfo(pIrp, status, 0);
			IoStartNextPacket(fdo, TRUE);
			KdPrint((DBG_NAME "Can't DmaOpenBlockChannel.\n"));
		}
		//DMA Transfer Data
		pdx->DmaInfo[0].bWriteToLocal = FALSE;
		pMdl = pIrp->MdlAddress;	
		KeFlushIoBuffers(pMdl, FALSE, TRUE);	//For Dma Transfer

		status = (*pdx->DmaInfo[0].pDmaAdapterObject->DmaOperations->AllocateAdapterChannel)(
								pdx->DmaInfo[0].pDmaAdapterObject, 
								fdo, 
								pdx->DmaInfo[0].lNumberOfMapRegisters,
								(PDRIVER_CONTROL) AdapterControl,		//ExecutionRoutine 
								pdx);	//Context
		if (!NT_SUCCESS(status))
		{
			CompleteRequestInfo(pIrp, status, 0);
			IoStartNextPacket(fdo, TRUE);
		}
		return;
		break;
	case IRP_MJ_DEVICE_CONTROL:
		ULONG lDMALocalToPciTransferSize;
		ULONG lPdcAddress;		//The base address of PDC4000
	//	ULONG lReturnedValue;
		lDMALocalToPciTransferSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;//0x100;
		
		lPdcAddress = (ULONG)pdx->LocalRegisterMemBase;

	/*	//直接操作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);
	*/
		//通过函数调用
		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;
		rc = DmaOpenBlockChannel(pdx, 0, &dcd);
		if (rc != RC_SUCCESS)
		{
			KdPrint((DBG_NAME "Can't DmaOpenBlockChannel.\n"));
		}
		//Set Address and Transfer Size.
		DMA_TRANSFER_ELEMENT dte;
		dte.lLocalAddress = 0;
		dte.lPciAddress = pdx->DmaInfo[0].paCommonBuffer.LowPart;
		dte.lPciDualAddress = 0;
		dte.lTransferSize = lDMALocalToPciTransferSize;	//

		dte.DescriptorLocation = 0;
		dte.DirectionOfTransfer = 1;
		dte.EndOfChain = 0;
		dte.InterruptAfterTerminalCount = 0;
		dte.NextDescriptorAddress = 0;
		
		pdx->DmaInfo[0].lTransferedBytes = lDMALocalToPciTransferSize;

		rc = DmaBlockTransfer(pdx, 0, &dte);
		if (rc != RC_SUCCESS)
		{
			KdPrint((DBG_NAME "Can't DmaBlockTransfer.\n"));
		}
		return;
		break;

	default:
		status = STATUS_NOT_SUPPORTED;
		break;
	}

	// Complete this IRP
	if(pIrp->Cancel) 
		status = STATUS_CANCELLED;

	// Remove cancel routine
	KIRQL OldIrql;
	IoAcquireCancelSpinLock( &OldIrql);
	IoSetCancelRoutine(pIrp, NULL);
	IoReleaseCancelSpinLock(OldIrql);

	// Unlock device, complete IRP and start next
//	UnlockDevice(pdx);

	KdPrint((DBG_NAME "StartIo End.\n"));

	CompleteRequestInfo(pIrp, STATUS_SUCCESS, 0);
	IoStartNextPacket(fdo, TRUE);

}												//StartIo

/******************************************************************************
 *
 * Function   :  CancelIrp
 *
 * Description:  The CancelIrp Service Routine for PDC4000.
 *
 ******************************************************************************/
VOID CancelIrp(IN PDEVICE_OBJECT fdo,
			   IN PIRP pIrp)
{												//CancelIrp
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
	KdPrint((DBG_NAME "WdmIoCancelIrp: Cancelling %x %I", pIrp, pIrp));

	if (pIrp == fdo->CurrentIrp)
	{
		KdPrint((DBG_NAME "CancelIrp: IRP running in StartIo\n"));
		// IRP is being processed by IoStartIo.
		// Irp->Cancel flag already set.
		// IoStartIo will detect Cancel flag and cancel IRP in due course
		IoReleaseCancelSpinLock(pIrp->CancelIrql);
	}
	else
	{
		KdPrint((DBG_NAME "CancelIrp: IRP in StartIo queue.\n"));
		// IRP is still in StartIo device queue.
		// Just dequeue and cancel it.  No need to start next IRP.
		BOOLEAN dequeued = KeRemoveEntryDeviceQueue(
								&fdo->DeviceQueue,
								&pIrp->Tail.Overlay.DeviceQueueEntry);

		IoReleaseCancelSpinLock(pIrp->CancelIrql);

		if (dequeued)
		{
			UnlockDevice(pdx);
			CompleteRequest(pIrp, STATUS_CANCELLED);
		}
	}
}												//CancelIrp
 /******************************************************************************
 *
 * Function   :  OnInterrupt
 *
 * Description:  The Interrupt Service Routine for the PLX device.
 *					//中断处理函数
 *	注意:中断处理函数工作在很高地级别,需要慎重处理
 ******************************************************************************/
BOOLEAN OnInterrupt(IN PKINTERRUPT pInterrupt,
					IN PDEVICE_EXTENSION pdx)//IN PVOID pdx)	
{												//OnInterrupt
    ULONG	lRegisterValue;

⌨️ 快捷键说明

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