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

📄 d9054device.cpp

📁 一个在ddk环境下编的plx9054的驱动程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:

// TODO:	If the write can be satisfied immediately, set the Information
//			and Status fields now, then call NextIrp to complete this IRP
//			and start processing the next IRP in the queue.

// TODO:	If the device cannot accept all of the data yet, initiate a 
//			request to the physical device here, and defer the Information,
//			Status, and NextIrp handling until the hardware indicates that
//			the write is complete.  Typically, this might be handled in a
//			DPC that is called after the hardware finishes transferring
//			the data.

// TODO:	To satisfy the write now, transfer data to the device
//			from caller's buffer at "pBuffer".  Then, indicate how much
//			data was transferred:


	I.Information() = 0;

	I.Status() = status;

	// PnpNextIrp completes this IRP and starts  
	// processing for the next IRP in the queue.
	PnpNextIrp(I);
}


////////////////////////////////////////////////////////////////////////
//  D9054Device::Write
//
//	Routine Description:
//		Handler for IRP_MJ_WRITE
//
//	Parameters:
//		I - Current IRP
//
//	Return Value:
//		NTSTATUS - Result code
//
//	Comments:
//		This routine handles write requests.
//		The requests are queued to the StartIo	
//		queue.  This enforces serialization so that
//		multiple requests are not processed	
//		simultaneously.
//
//		The KPnpDevice class handles restricting IRP flow
//		if the device is stopping or being removed.
//

NTSTATUS D9054Device::Write(KIrp I) 
{
	t << "Entering D9054Device::Write, " << I << EOL;
// TODO:	Check the incoming request.  Replace "FALSE" in the following
//			line with a check that returns TRUE if the request is not valid.
    if (FALSE)
	{
		// Invalid parameter in the Write request
		I.Information() = 0;
		return I.PnpComplete(this, STATUS_INVALID_PARAMETER);
	}

	// Always ok to write 0 elements.
	if (I.WriteSize() == 0)
	{
		I.Information() = 0;
		return I.PnpComplete(this, STATUS_SUCCESS);
	}

	// Queue the IRP for processing in StartIO
	// The write function is performed in SerialWrite
	return QueueIrp(I, LinkTo(CancelQueuedIrp));
}

////////////////////////////////////////////////////////////////////////
//  D9054Device::DeviceControl
//
//	Routine Description:
//		Handler for IRP_MJ_DEVICE_CONTROL
//
//	Parameters:
//		I - Current IRP
// 
//	Return Value:
//		None
//
//	Comments:
//		This routine is the first handler for Device Control requests.
//		Some function codes may be handled immediately, 
//		while others may be serialized through the StartIo routine.
//		
//		The KPnpDevice class handles restricting IRP flow
//		if the device is stopping or being removed.
//

NTSTATUS D9054Device::DeviceControl(KIrp I) 
{
	NTSTATUS status;

	t  << "		Entering DeviceControl "<< I.IoctlCode();

	switch (I.IoctlCode())
	{
		case EVENT_SET:

			{
				t<<"	\nEVENT_SET\n\n";

				t<<"INTCSR ="<<m_IoPortRange0.ind(INTCSR)<<"\n";

				m_IoPortRange0.outd(INTCSR,0x40100);

				HANDLE hEvent = *(HANDLE*)I.IoctlBuffer();

				if (m_pEvent)
				{
					delete m_pEvent;
					m_pEvent = NULL;
				}

				m_pEvent = new (NonPagedPool) KEvent(hEvent);

				status = ( m_pEvent != NULL ) ? STATUS_SUCCESS:STATUS_INSUFFICIENT_RESOURCES ;

				bRec = TRUE ;
				m_pEvent->Set();				

				return I.Complete(status);
				
			}
			
			break;
		case READ_RGS:
			{
				t<<"\n\nREAD_RGS bRec="<<bRec<<"\n\n";
				
				bRec = FALSE ;		

				return STATUS_SUCCESS;
			}


		case EVENT_CANCEL:

			break;

		default:
			// Unrecognized IOCTL request
			status = STATUS_INVALID_PARAMETER;
			break;
	}

	// If the IRP was queued, or its IOCTL handler deferred processing using some
	// driver specific scheme, the status variable is set to STATUS_PENDING.
	// In this case we simply return that status, and the IRP will be completed
	// later.  Otherwise, complete the IRP using the status returned by the
	// IOCTL handler.
	if (status == STATUS_PENDING)
	{
		return status;
	}
	else
	{
		return I.PnpComplete(this, status);
	}
}

////////////////////////////////////////////////////////////////////////
//  D9054Device::EVENT_SET_Handler
//
//	Routine Description:
//		Handler for IO Control Code EVENT_SET
//
//	Parameters:
//		I - IRP containing IOCTL request
//
//	Return Value:
//		NTSTATUS - Status code indicating success or failure
//
//	Comments:
//		This routine implements the EVENT_SET function.
//		This routine runs at passive level.
//

NTSTATUS D9054Device::EVENT_SET_Handler(KIrp I)
{
	NTSTATUS status = STATUS_SUCCESS;

//	t << "Entering D9054Device::EVENT_SET_Handler, " << I << EOL;

	I.Information() = 0;

	return status;
}

////////////////////////////////////////////////////////////////////////
//  D9054Device::EVENT_CANCEL_Handler
//
//	Routine Description:
//		Handler for IO Control Code EVENT_CANCEL
//
//	Parameters:
//		I - IRP containing IOCTL request
//
//	Return Value:
//		NTSTATUS - Status code indicating success or failure
//
//	Comments:
//		This routine implements the EVENT_CANCEL function.
//		This routine runs at passive level.
//

NTSTATUS D9054Device::EVENT_CANCEL_Handler(KIrp I)
{
	NTSTATUS status = STATUS_SUCCESS;

//	t << "Entering D9054Device::EVENT_CANCEL_Handler, " << I << EOL;
	
	/////// 事件取消 //////////




	///////事件取消//////////

	I.Information() = 0;

	return status;
}

////////////////////////////////////////////////////////////////////////
//  D9054Device::DpcFor_Irq
//
//	Routine Description:
//		Deferred Procedure Call (DPC) for Irq
//
//	Parameters:
//		Arg1 - User-defined context variable
//		Arg2 - User-defined context variable
//
//	Return Value:
//		None
//
//	Comments:
//		This function is called for secondary processing of an interrupt.
//		Most code that runs at elevated IRQL should run here rather than
//		in the ISR, so that other interrupt handlers can continue to run.
//

VOID D9054Device::DpcFor_Irq(PVOID Arg1, PVOID Arg2)
{
// TODO:	Typically, the interrupt signals the end of a data transfer
//			operation for a READ or WRITE operation. The following code
//			assumes the driver will handle the completion of the IRP
//			associated with this operation here.  It further assumes that the
//			IRP to be completed is the current IRP on the device queue.  Modify
//			or replace the code here to handle the function of your DPC.

	t<<"\n	Enter DPC !!!!!!! \n";


	m_CurrentTransfer->Continue(UseTransferSize);

	UNREFERENCED_PARAMETER(Arg1);
	UNREFERENCED_PARAMETER(Arg2);
}

////////////////////////////////////////////////////////////////////////
//  D9054Device::Isr_Irq
//
//	Routine Description:
//		Interrupt Service Routine (ISR) for IRQ Irq
//
//	Parameters:
//		None
// 
//	Return Value:
//		BOOLEAN		True if this is our interrupt
//
//	Comments:
//

BOOLEAN D9054Device::Isr_Irq(void)
{
// TODO:	Verify that the interrupt was caused by our device.
//			Replace "TRUE" in next line with actual test.

	t<<"	Enter ISR_IRQ() !!! "<<bRec<<"\n";

	ULONG status;

	status=	m_IoPortRange0.ind(INTCSR); //  读中断状态寄存器

	if( status & 0x8000 )  // pci
	{
		t<<"PCI int "<<bRec<<"\n";

		m_IoPortRange0.outd(INTCSR,0x40100);

		if( m_pEvent )
		{
			m_pEvent->Set();
		}
		else
		{
			t<<"end of rec \n";
		}

		return TRUE;
	}
	else if ((status & 0x200000)==0) // dma
	{
		return FALSE;
	}
	else if(status & 0x200000)
	{
		t<<"DMA int "<<bRec<<"\n";

		if( m_pEvent )
		{
			m_pEvent->Clear();
		}

		m_IoPortRange0.outd(DMAMODE0,0x20800);  // 禁止中断
		m_IoPortRange0.outb(DMACSR0,0x10);//  0x18 ??????  Clear Interrupt

		m_IoPortRange0.outd(INTCSR,0x40900);
		
		if (!m_DpcFor_Irq.Request(NULL, NULL))
		{

		}
	}	

	// Return TRUE to indicate that our device caused the interrupt
	return TRUE;
}

VOID D9054Device::StartDMA(ULONG PAddress,ULONG NBytes)
{

	t<<"	Enter StartDMA !!!\n";

/*	t<<"\nINSTCR-> "<<m_IoPortRange0.ind(INTCSR);
	t<<"\nDMAMODE0-> "<<m_IoPortRange0.ind(DMAMODE0);
	t<<"\nDMAPADR0-> "<<m_IoPortRange0.ind(DMAPADR0);
	t<<"\nDMALADR0-> "<<m_IoPortRange0.ind(DMALADR0);
	t<<"\nDMASIZ0-> "<<m_IoPortRange0.ind(DMASIZ0);
	t<<"\nDMADPR0-> "<<m_IoPortRange0.ind(DMADPR0);
	t<<"\nDMACSR0-> "<<m_IoPortRange0.inb(DMACSR0);
*/

	//下面几条语句设置DMA通道0寄存器,启动块传输方式,从FIFO读数据
	//Channel0 interrupt to the PCI Bus interrupt,Done Interrupt Enable,FIFO
	m_IoPortRange0.outd(DMAMODE0,0x20DC3); //  
	//DMA Channel0 PCI Address
	m_IoPortRange0.outd(DMAPADR0,PAddress);
	//DMA Channel0 Local Address,自己设计的FIFO地址
	m_IoPortRange0.outd(DMALADR0,0x8);
	//DMA Channel0 Transfer Size(Bytes)
	m_IoPortRange0.outd(DMASIZ0,NBytes);
	//from the Local Bus to the PCI Bus
	m_IoPortRange0.outd(DMADPR0,0x8);
	//Channel0 Enable,Start  p284
	m_IoPortRange0.outb(DMACSR0,0x3);

/*	t<<"\nINSTCR-> "<<m_IoPortRange0.ind(INTCSR);
	t<<"\nDMAMODE0-> "<<m_IoPortRange0.ind(DMAMODE0);
	t<<"\nDMAPADR0-> "<<m_IoPortRange0.ind(DMAPADR0);
	t<<"\nDMALADR0-> "<<m_IoPortRange0.ind(DMALADR0);
	t<<"\nDMASIZ0-> "<<m_IoPortRange0.ind(DMASIZ0);
	t<<"\nDMADPR0-> "<<m_IoPortRange0.ind(DMADPR0);
	t<<"\nDMACSR0-> "<<m_IoPortRange0.inb(DMACSR0);
*/


}

VOID D9054Device::OnDmaReady(KDmaTransfer* pXfer, KIrp I)
{
	// All KDmaTransfer callbacks must first check to see if there are any bytes
	// left to transfer.

	t<<"Enter OnDmaReady\n";

	if (pXfer->BytesRemaining() == 0)
	{
		// If there are no bytes left to transfer, the callback must call
		// Terminate(). Then it completes the IRP with STATUS_SUCCESS.

		if( !bRec )
		{
			t<<"\nbRec = FALSE\n";		
		}

		pXfer->Terminate();
	
		I.Information() = I.ReadSize(CURRENT);
		I.Status() = STATUS_SUCCESS;
		PnpNextIrp(I);

		m_CurrentTransfer = NULL;
		delete pXfer;
	

		return;
	}

	// We must get the descriptor for the physical memory location for
	// the DMA transfer.

	PTRANSFER_DESCRIPTOR ptd;

	while (pXfer->SequenceTransferDescriptors(&ptd)) {
		// program the h/w using  ppTD
		t << " Physical address 0x" << ptd->td_PhysAddr.LowPart << ". Length is 0x"
			<< ptd->td_Length << "." << EOL;
	}

	// If this is the first time through, then start the DMA going.
	// We only want to do this ONCE for a given Read transfer.  That
	// way, our data will be collected smoothly, without interruptions
	// or dropouts.
	if ((ULONG) pXfer->BytesRemaining() == I.ReadSize())
		StartDMA(ptd->td_PhysAddr.LowPart,ptd->td_Length);
}

⌨️ 快捷键说明

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