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

📄 dispatch.cpp

📁 在vxworks下
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		dcd.DACChainLoad		= 0;//
		dcd.DemandMode			= 0;
		dcd.DmaChannelPriority	= Channel0Highest;
		
		//DMA threshold
		dcd.LocalToPciAlmostEmpty	= 0;
		dcd.LocalToPciAlmostFull	= 0;
		dcd.PciToLocalAlmostEmpty	= 0;
		dcd.PciToLocalAlmostFull	= 0;
		

		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);
		}

		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;

	case IOCTL_PDC4000_RTLCPY_VABUFFER:
		ULONG lDMALocalToPciTransferSize2;
		lDMALocalToPciTransferSize2 = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
        RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer, pdx->DmaInfo[0].vaCommonBuffer, lDMALocalToPciTransferSize2);
	    lReturnedValue = lDMALocalToPciTransferSize2;
       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;
	
	PMDL pMdl;

/*	if (!LockDevice(pdx))
	{
		CompleteRequest(pIrp, STATUS_DELETE_PENDING);
	}
*/
	//Open Dma Channl0
	DMA_CHANNEL_DESCRIPTION dcd;
		
	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		= 3;
	dcd.MemoryWriteAndInvalidateMode = 0;
	dcd.ReadyInputEnable	= 1;
	dcd.ScatterGatherMODE	= 0;
	//DMA threshold
	dcd.LocalToPciAlmostEmpty	= 0;
	dcd.LocalToPciAlmostFull	= 0;
	dcd.PciToLocalAlmostEmpty	= 0;
	dcd.PciToLocalAlmostFull	= 0;
	
	BOOLEAN bResult;

	RETURN_CODE rc = DmaOpenSglChannel(pdx, 0, &dcd);
	if (rc != RC_SUCCESS)
	{
		CompleteRequestInfo(pIrp, status, 0);
		IoStartNextPacket(fdo, TRUE);
		KdPrint((DBG_NAME "Can't DmaOpenBlockChannel.\n"));
	}
	
	// Switch on the IRP major function code
	switch(pIrpStack->MajorFunction)
	{
	case IRP_MJ_WRITE:
		//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:
				//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;
	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.
 *					
 * Note		  :  中断处理函数工作在很高地级别,需要慎重处理
 ******************************************************************************/
BOOLEAN OnInterrupt(IN PKINTERRUPT pInterrupt,
					IN PDEVICE_EXTENSION pdx)//IN PVOID pdx)	
{												//OnInterrupt
    ULONG	lRegisterValue;
	ULONG	lAddress;
	UCHAR	cInterrupt;
	UCHAR	cCommand;

	lAddress = (ULONG)((PDEVICE_EXTENSION)pdx)->LocalRegisterMemBase;

    // Read interrupt status register.
	lRegisterValue = READ_REGISTER_ULONG((ULONG *)(lAddress + PCI9054_INT_CTRL_STAT));

    // Check for master PCI interrupt enable.
	if ((lRegisterValue & 0x100) == 0)	//Interupt Control/Status Register: 8
	{
		return FALSE;		//如果不是该设备的中断,必须返回FALSE,否则系统会出问题。
	}

	KdPrint((DBG_NAME "On Interrupt!!!\n"));
	KdPrint((DBG_NAME "ICS Register is 0x%X.\n", lRegisterValue));
	// Check to see if an interrupt is active. 
	if ((lRegisterValue & 0x00200000)==0x00200000)//有DMA中断就通知应用程序
	{
		lRegisterValue &= (~0x100);//禁止所有的pci的中断
		WRITE_REGISTER_ULONG((ULONG *)(lAddress + PCI9054_INT_CTRL_STAT), lRegisterValue);
		KdPrint((DBG_NAME "Operate the Interrupt.\n"));

		if (pdx->pWaitEvent != NULL)
			KeSetEvent(pdx->pWaitEvent, 0, FALSE);	//通知应用程序,中断的到来
	
		if (pdx->DmaInfo[0].State == DMA_STATE_BLOCK)
		{
			KdPrint((DBG_NAME "Block DMA Interrupt!!!\n"));
		    WRITE_REGISTER_ULONG((ULONG *)(lAddress + PCI9054_DMA_COMMAND_STAT), 0x9);//把DMA通道0的中断标志清0
			DmaCloseBlockChannel(pdx, 0, FALSE);
		}

	    //打开中断
		lRegisterValue |= 0x100;
		WRITE_REGISTER_ULONG((ULONG *)(lAddress + PCI9054_INT_CTRL_STAT), lRegisterValue);
		KdPrint((DBG_NAME "open the Interrupt.\n"));
           
        	
		return TRUE;	//如果是该设备的中断,必须返回TRUE。
    }

	
	return FALSE;
}												//OnInterrupt

/******************************************************************************
 *
 * Function   :  DpcForIsr
 *
 * Description:  This routine will be triggered by the ISR to service an interrupt.
 *
 * Note       :  The 9052 supports Edge-triggerable interrupts as well as level
 *               triggered interrupts.  The 9050 only supports level triggered
 *               interrupts.  The interrupt masking code below handles both cases.
 *               If the chip is a 9050, the same code is used but should work
 *               ok since edge triggerable interrupts will always be disabled.
 *
 ******************************************************************************/
VOID DpcForIsr(IN PKDPC pDpc,
			   IN PDEVICE_OBJECT fdo,
			   IN PIRP pIrp, 
			   IN PDEVICE_EXTENSION pdx)
{												//OnInterrupt DpcForIsr
	KdPrint((DBG_NAME "DpcForIsr Start.\n"));
	
	if (pIrp->Cancel)
		pdx->TransmitIrpStatus = STATUS_CANCELLED;

	KIRQL OldIrql;

	//Remove Cancel Routine.
	IoAcquireCancelSpinLock(&OldIrql);
	IoSetCancelRoutine(pIrp,NULL);
	IoReleaseCancelSpinLock(OldIrql);
	

	if (!LockDevice(pdx))
	{
		CompleteRequest(pIrp, STATUS_DELETE_PENDING);
	}
	
	KIRQL	OriginalIrqL;
	KeAcquireSpinLock(&(pdx->HardwareAccessLock), &OriginalIrqL);

	ULONG lRegAddress = (ULONG)pdx->LocalRegisterMemBase;
    // Read interrupt status register
    ULONG lRegValue = READ_REGISTER_ULONG((ULONG *)(lRegAddress + PCI9054_INT_CTRL_STAT));

	REG_DATA	RegData;
	ULONG		lValue;

    // Local Interrupt 
    if (lRegValue & (1 << 15))
    {
		// Setup to synchronize access to Interrupt Control/Status Register
		RegData.lRegAddress	= lRegAddress + PCI9054_INT_CTRL_STAT;
		RegData.lBitsToSet	= 0;
		RegData.lBitsToClear = (1 << 11);

		// Mask Local Interrupt 1
        KeSynchronizeExecution(pdx->pInterruptObject, 
								(PKSYNCHRONIZE_ROUTINE)SynchronizedModifyRegister, 
								(VOID *)&RegData);
    //	if (pdx->pWaitEvent != NULL)
	//		KeSetEvent(pdx->pWaitEvent, 0, FALSE);
	
	}

   

 
	KeReleaseSpinLock(&(pdx->HardwareAccessLock), OriginalIrqL);

    // Re-enable PCI interrupts

	KeSynchronizeExecution(pdx->pInterruptObject, 
								(PKSYNCHRONIZE_ROUTINE)EnablePciInterrupt, 

⌨️ 快捷键说明

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