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

📄 blockdmadevice.cpp

📁 pci9054的驱动
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//			Restore any context to the hardware device that
//			was saved during the handling of a power down request.
//			See the OnDeviceSleep function.
//			Do NOT complete this IRP.
//
	return status;

	// The following macro simply allows compilation at Warning Level 4
	// If you reference this parameter in the function simply remove the macro.
	UNREFERENCED_PARAMETER(I);
}

////////////////////////////////////////////////////////////////////////
//  BlockDMADevice::OnDeviceSleep
//
//	Routine Description:
//		Handler for IRP_MJ_POWER with minor function IRP_MN_SET_POWER
//		for a request to go to a low power state from a high power state
//
//	Parameters:
//		I - IRP containing POWER request
//
//	Return Value:
//		NTSTATUS - Status code indicating success or failure
//
//	Comments:
//		This routine implements the OnDeviceSleep function.
//		This function was called by the framework from the IRP_MJ_POWER 
//		dispatch handler in KPnpDevice prior to forwarding to the PDO.
//		The hardware has yet to be powered down and this driver can now
//		access the hardware device.  
//		This routine runs at passive level.
//	

NTSTATUS BlockDMADevice::OnDeviceSleep(KIrp I)
{
	NTSTATUS status = STATUS_SUCCESS;

	t << "Entering BlockDMADevice::OnDeviceSleep\n";

// TODO:	Service the device.
//			Save any context to the hardware device that will be required 
//			during a power up request. See the OnDevicePowerUp function.
//			Do NOT complete this IRP.  The base class handles forwarding
//			this IRP to the PDO.
//
	return status;

	// The following macro simply allows compilation at Warning Level 4
	// If you reference this parameter in the function simply remove the macro.
	UNREFERENCED_PARAMETER(I);
}

////////////////////////////////////////////////////////////////////////
//  BlockDMADevice::CancelQueuedIrp
//
//	Routine Description:
//		This routine is called when an IRP is canceled while queued.
//
//	Parameters:
//		I - IRP being canceled
//
//	Return Value:
//		None
//
//	Comments:
//
// TODO:	You may want to write additional cancel routines
//			to use during different stages of IRP processing.

VOID BlockDMADevice::CancelQueuedIrp(KIrp I)
{
	KDeviceQueue dq(DeviceQueue());

	// Test if the IRP is the current IRP.
	if ( (PIRP)I == CurrentIrp() )
	{

		// If so, NULL it out, release the global cancel spinlock, then
		// complete it as canceled and start the next IRP.  Note that
		// if we got here, the IRP was still in a cancelable state when
		// it was canceled, and most likely is just about to start being
		// processed on the device.
		CurrentIrp() = NULL;
		CancelSpinLock::Release(I.CancelIrql());
		t << "IRP canceled " << I << EOL;
	    I.Information() = 0;
		I.Status() = STATUS_CANCELLED;
		PnpNextIrp(I);
	}
	// See if the IRP can be removed from the device queue.
	else if (dq.RemoveSpecificEntry(I))
	{

		// If so, release the global cancel spinlock and complete it
		// as canceled.
		CancelSpinLock::Release(I.CancelIrql());
		t << "IRP canceled " << I << EOL;
	    I.Information() = 0;
		I.PnpComplete(this, STATUS_CANCELLED);
	}
	else
	{

		// If we got here the IRP wasn't the current IRP, and wasn't in the
		// device queue.  This could happen if the IRP was removed by the
		// device queue's cleanup routine, just as it was being canceled.
		// In this case we have no work to do, since the cleanup routine
		// will cancel the IRP.  Simply release the global cancel spinlock.
		CancelSpinLock::Release(I.CancelIrql());
	}
}

////////////////////////////////////////////////////////////////////////
//  BlockDMADevice::StartIo
//
//	Routine Description:
//		StartIo is called when an IRP is taken off the device queue
//		used by the	system for serializing I/O.  StartIo is called at
//		dispatch level.
//
//	Parameters:
//		I - IRP removed from queue
//
//	Return Value:
//		None
//
//	Comments:
//

VOID BlockDMADevice::StartIo(KIrp I)
{
	t << "Entering StartIo, " << I << EOL;

	// Before processing the Irp, we need to check to see if it has been
	// canceled.  We also want to set the Irp into an non-cancelable state
	// (cancel routine set to NULL) so we can process it. You may want to set
	// a different cancel routine here, or at other points within this function.
	// When performing these operations, it is necessary to hold the global
	// cancel spin lock and take special precautions to ensure the Irp is still
	// valid.  This is accomplished using the routine KIrp::TestAndSetCancelRoutine().
	if ( !I.TestAndSetCancelRoutine(
		LinkTo(CancelQueuedIrp),
		NULL,
		CurrentIrp()) )
	{
		
		// The Irp has been canceled we stop processing and exit.  Since
		// it was in a cancelable state previously, it will be completed by
		// the cancel routine that had been set on it.
		return;
	}

	// Start processing request.

	// Switch on the IRP's function:
	switch (I.MajorFunction())
	{
		case IRP_MJ_READ:
			SerialRead(I);
			break;
		case IRP_MJ_WRITE:
			SerialWrite(I);
			break;
		case IRP_MJ_DEVICE_CONTROL:
			switch (I.IoctlCode())
			{
				default:
					// We queued a request that shouldn't have been queued
					// (should never get here)
					ASSERT(FALSE);
					break;
			}
			break;
		default:
			// The driver queued an Irp that isn't handled
			// by StartIo.  This shouldn't happen.
			ASSERT(FALSE);
			PnpNextIrp(I);
			break;
	}
}

////////////////////////////////////////////////////////////////////////
//  BlockDMADevice::Create
//
//	Routine Description:
//		Handler for IRP_MJ_CREATE
//
//	Parameters:
//		I - Current IRP
//
//	Return Value:
//		NTSTATUS - Result code
//
//	Comments:
//

NTSTATUS BlockDMADevice::Create(KIrp I)
{
	NTSTATUS status;

	t << "Entering BlockDMADevice::Create, " << I << EOL;

// TODO: Add driver specific create handling code here

	// Generally a create IRP is targeted at our FDO, so we don't need
	// to pass it down to the PDO.  We have found for some devices, the
	// PDO is not expecting this Irp and returns an error code.
	// The default wizard code, therefore completes the Irp here using
	// PnpComplete().  The following commented code could be used instead
	// of PnpComplete() to pass the Irp to the PDO, which would complete it.
	//
//	I.ForceReuseOfCurrentStackLocationInCalldown();
//	status = m_Lower.PnpCall(this, I);

	status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT);

	t << "BlockDMADevice::Create Status " << (ULONG)status << EOL;

	return status;
}


////////////////////////////////////////////////////////////////////////
//  BlockDMADevice::Close
//
//	Routine Description:
//		Handler for IRP_MJ_CLOSE
//
//	Parameters:
//		I - Current IRP
//
//	Return Value:
//		NTSTATUS - Result code
//
//	Comments:
//

NTSTATUS BlockDMADevice::Close(KIrp I)
{
	NTSTATUS status;

	t << "Entering BlockDMADevice::Close, " << I << EOL;

// TODO: Add driver specific close handling code here

	// Generally a close IRP is targeted at our FDO, so we don't need
	// to pass it down to the PDO.  We have found for some devices, the
	// PDO is not expecting this Irp and returns an error code.
	// The default wizard code, therefore completes the Irp here using
	// PnpComplete().  The following commented code could be used instead
	// of PnpComplete() to pass the Irp to the PDO, which would complete it.
	//
//	I.ForceReuseOfCurrentStackLocationInCalldown();
//	status = m_Lower.PnpCall(this, I);

	status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT);

	t << "BlockDMADevice::Close Status " << (ULONG)status << EOL;

    return status;
}

////////////////////////////////////////////////////////////////////////
//  BlockDMADevice::Cleanup
//
//	Routine Description:
//		Handler for IRP_MJ_CLEANUP	
//
//	Parameters:
//		I - Current IRP
//
//	Return Value:
//		NTSTATUS - Result code
//
//	Comments:
//

NTSTATUS BlockDMADevice::CleanUp(KIrp I)
{
	t << "Entering CleanUp, " << I << EOL;

// TODO:	Insert your code to respond to the CLEANUP message.
//			This code cleans up the single Wizard created queue.  If you
//			have created additional queues,	or have any outstanding Irps
//			stored in some other fashion in your driver, you should clean
//			these up as well for the file object specified in the cleanup Irp.

    KDeviceQueue dq(DeviceQueue());
	dq.PnpCleanUp(this, I.FileObject());
	return I.PnpComplete(this, STATUS_SUCCESS);
}

////////////////////////////////////////////////////////////////////////
//  BlockDMADevice::SerialRead
//	
//	Routine Description:
//		Handler for serialized READ
//
//	Parameters:
//		I - Current IRP
//
//	Return Value:
//		None
//
//	Comments:
//		This routine is called when the IRP is removed from the
//		STARTIO queue.  This guarantees that multiple requests are
//		never processed simultaneously.
//
//		This routine is called at dispatch level.
//

void BlockDMADevice::SerialRead(KIrp I)
{
	//第一步 启动DMA 读传输
	t<<"第1步 启动DMA 读传输 Serial Read begin "<<EOL;
	NTSTATUS status = STATUS_SUCCESS;
    m_ReadWrite=1;
	m_CurrentTransfer= new (NonPagedPool) KDmaTransfer(this,&m_Dma);

	if(	m_CurrentTransfer == NULL) {
		status = STATUS_INSUFFICIENT_RESOURCES;

		I.Information()=0;
		I.Status()=status;
		PnpNextIrp(I);
	}
    
	//第一次启动OnDmaReady 
//	status = m_CurrentTransfer->Initiate(I.Mdl(),(I.MajorFunction()==IRP_MJ_READ)
//		?FromDeviceToMemory:FromMemoryToDevice , LinkTo(OnDmaReady));
status = m_CurrentTransfer->Initiate(this,&m_Dma,I.Mdl(),(I.MajorFunction()==IRP_MJ_READ)
		?FromDeviceToMemory:FromMemoryToDevice , LinkTo(OnDmaReady),&m_Buffer);
	if(!NT_SUCCESS(status)){
		delete m_CurrentTransfer;
		m_CurrentTransfer=NULL;
		I.Information()=0;
		I.Status()=status;
		PnpNextIrp(I);
	}
}


////////////////////////////////////////////////////////////////////////
//  BlockDMADevice::Read
//
//	Routine Description:
//		Handler for IRP_MJ_READ
//
//	Parameters:
//		I			Current IRP
//
//	Return Value:
//		NTSTATUS	Result code
//
//	Comments:
//		This routine handles read 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 BlockDMADevice::Read(KIrp I) 
{
	t << "Entering BlockDMADevice::Read, " << 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)		// If (Request is invalid)
	{
		// Invalid parameter in the Read request
		I.Information() = 0;
		return I.PnpComplete(this, STATUS_INVALID_PARAMETER);
	}

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

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

////////////////////////////////////////////////////////////////////////
//  BlockDMADevice::SerialWrite
//	
//	Routine Description:
//		Handler for serialized WRITE
//
//	Parameters:
//		I - Current IRP
//
//	Return Value:
//		None
//
//	Comments:
//		This routine is called when the IRP is removed from the
//		STARTIO queue.  This guarantees that multiple requests are
//		never processed simultaneously.
//

void BlockDMADevice::SerialWrite(KIrp I)
{

	//第一步 启动DMA 写传输

	t<<"第1步 启动DMA 写传输 Serial Write begin "<<EOL;
	NTSTATUS status = STATUS_SUCCESS;
	m_ReadWrite=2;
	m_CurrentTransfer= new (NonPagedPool) KDmaTransfer(this,&m_Dma);

	if(	m_CurrentTransfer == NULL) {
		status = STATUS_INSUFFICIENT_RESOURCES;

		I.Information()=0;
		I.Status()=status;
		PnpNextIrp(I);
	}
    
	//第一次启动OnDmaReady 
status = m_CurrentTransfer->Initiate(this,&m_Dma,I.Mdl(),(I.MajorFunction()==IRP_MJ_READ)
		?FromDeviceToMemory:FromMemoryToDevice , LinkTo(OnDmaReady),&m_Buffer);
	if(!NT_SUCCESS(status)){
		delete m_CurrentTransfer;
		m_CurrentTransfer=NULL;
		I.Information()=0;
		I.Status()=status;
		PnpNextIrp(I);
	}


}


////////////////////////////////////////////////////////////////////////
//  BlockDMADevice::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 BlockDMADevice::Write(KIrp I) 
{
	t << "Entering BlockDMADevice::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));
}

////////////////////////////////////////////////////////////////////////
//  BlockDMADevice::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 BlockDMADevice::DeviceControl(KIrp I) 
{
	NTSTATUS status;

	t << "Entering BlockDMADevice::Device Control, " << I << EOL;
	switch (I.IoctlCode())
	{
		case BLOCKDMA_IOCTL_800:
			status = BLOCKDMA_IOCTL_800_Handler(I);
			break;

		case BLOCKDMA_IOCTL_801:
			status = BLOCKDMA_IOCTL_801_Handler(I);
			break;

		case BLOCKDMA_IOCTL_802:
			status = BLOCKDMA_IOCTL_802_Handler(I);
			break;

		case BLOCKDMA_IOCTL_803:
			status = BLOCKDMA_IOCTL_803_Handler(I);
			break;

		case BLOCKDMA_IOCTL_804:
			status = BLOCKDMA_IOCTL_804_Handler(I);

⌨️ 快捷键说明

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