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

📄 blockdmadevice.cpp

📁 pci9054的驱动
💻 CPP
📖 第 1 页 / 共 3 页
字号:
			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);
	}
}

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

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

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

	HANDLE hEvent=*(HANDLE*)I.IoctlBuffer();
	if(m_pEventToSignal) 
	{
		delete m_pEventToSignal;
		m_pEventToSignal=NULL;
	}
	m_pEventToSignal=new(NonPagedPool)KEvent(hEvent,OBJECT_TYPE_ALL_ACCESS);
	if(m_pEventToSignal==NULL)
	{
		status=STATUS_INSUFFICIENT_RESOURCES;
	}
	else
	{
		status=STATUS_SUCCESS;
//		m_pEventToSignal->Initialize(SynchronizationEvent ,FALSE);
	}

// TODO:	Handle the the BlockDMA_IOCTL_800 request, or 
//			defer the processing of the IRP (i.e. by queuing) and set
//			status to STATUS_PENDING.

// TODO:	Assuming that the request was handled here. Set I.Information
//			to indicate how much data to copy back to the user.
	I.Information() = sizeof(ULONG);

	return status;
}

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

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

//	t << "Entering BlockDMADevice::BlockDMA_IOCTL_801_Handler, " << I << EOL;
// TODO:	Verify that the input parameters are correct
//			If not, return STATUS_INVALID_PARAMETER

// TODO:	Handle the the BlockDMA_IOCTL_801 request, or 
//			defer the processing of the IRP (i.e. by queuing) and set
//			status to STATUS_PENDING.

// TODO:	Assuming that the request was handled here. Set I.Information
//			to indicate how much data to copy back to the user.
//	I.Information() = 0;

/**	NTSTATUS status		= STATUS_SUCCESS;

	//下面创建类实例m_CurrentTransfer,并初始化

	// Create a new DMA transfer object for this IRP
	m_CurrentTransfer = new(NonPagedPool) KDmaTransfer(this, &m_Dma);

	if ( m_CurrentTransfer == NULL )
	{
		status = STATUS_INSUFFICIENT_RESOURCES;
		DbgPrint("unable to allocate transfer object: %x\n", status);

		I.Information() = 0;
//		I.Status() = status;
//		PnpNextIrp(I);
	}

	//下面采用应用程序的数据缓冲区作为DMA数据区
/*	status = m_CurrentTransfer->Initiate(
		I.Mdl(),
		(I.MajorFunction() == IRP_MJ_READ) ? FromDeviceToMemory : FromMemoryToDevice,
		LinkTo(OnDmaReady)
		);	//此操作将使系统调用OnDmaReady例程*/
//	下面采用公用缓冲区作为DMA数据区,这两种方法都可以
/**	m_LocalAddress = *((PULONG)I.IoctlBuffer());  //读取应用程序中函数DeviceIoControl的输出缓冲区(应用程序传递给驱动的参数)数据
	status = m_CurrentTransfer->Initiate(
		this,
		&m_Dma,
		I.Mdl(),
		FromDeviceToMemory ,//: FromMemoryToDevice,
		LinkTo(OnDmaReady),
		&m_Buffer
		); 	//此操作将使系统调用OnDmaReady例程

	// If the transfer cannot be initiated, complete it with an error status.
	if ( ! NT_SUCCESS(status) )
	{
		DbgPrint("unable to initiate transfer: %x\n", status);

		delete m_CurrentTransfer;
		delete &m_LocalAddress;
		m_CurrentTransfer = NULL;

		I.Information() = 0;
//		I.Status() = status;
//		PnpNextIrp(I);
	}

	return status;
/*	for(ULONG j=0;j<0xFFFFFF;j++)
	{
	m_IoPortRange2.outd(0xAA,0x0);
	}
	I.Information() = sizeof(ULONG);*/
/*	KMemory Mem(I.Mdl());

	ULONG reg;
	ULONG *pBuf;
	pBuf=(ULONG *)Mem.MapToSystemSpace();
//	reg=m_IoPortRange1.ind(0x04);
	reg=m_Bytes;
    *pBuf=reg;
*/


	/*初始化并启动DMA*/
	ULONG Reg68 = 0;//Interrupt Control & Status Register
	ULONG Reg80 = 0;//DMA Channel 0 Mode Register
	ULONG Reg84 = 0;//DMA Channel 0 PCI Adress Register
	ULONG Reg88 = 0;//DMA Channel 0 Local Adress Register
	ULONG Reg8C = 0;//DMA Channel 0 Transfer Size(Bytes) Register
	ULONG Reg90 = 0;//DMA Channel 0 Descriptor Pointer Register
	UCHAR RegA8 = 0;//DMA Channel 0 Command/Status Register

	Reg68 = 0x00040180;
	m_IoPortRange1.outd(0x68,Reg68);//Enable Dma Channel0 INT



//	m_IoPortRange1.outd(MBRAR,0x280000);        //dma通道优先级设置

	Reg80 = 0x000205C3;  //BTERM=1,BURST=1
	m_IoPortRange1.outd(0x80 , Reg80);


	/*在不使用commonbuffer的情况下*/
//	PTRANSFER_DESCRIPTOR ptd;

//	while(m_CurrentTransfer->SequenceTransferDescriptors(&ptd))  
//	{
//	}
//	Reg84=(ULONG)ptd->td_PhysAddr.LowPart;
	/*在不使用commonbuffer的情况下*/

//	KMemory Mem(I.Mdl());
//	ULONG  ptd=(ULONG )Mem.MapToSystemSpace();
	m_IoPortRange1.outd(0x84 , Reg84);

	Reg88 = 0xed000000;
	m_IoPortRange1.outd(0x88 , Reg88);

	Reg8C = 0x400000;//16384 * 4;0x7FFFFF
	m_IoPortRange1.outd(0x8c , Reg8C);// set dma count(bytes)

	Reg90 = 0x8;
	m_IoPortRange1.outd(0x90 , Reg90);

	RegA8 = 0x03;
	m_IoPortRange1.outb(0xA8 , RegA8);

//	I.Information() = 0;
	return STATUS_SUCCESS;
}

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

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

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

	ULONG *pp=(ULONG *)I.IoctlBuffer();
	if(pp!=NULL)
	{
		ULONG index=*(ULONG *)pp;
		ULONG Regvalue=m_IoPortRange3.ind(index);
        KMemory Mem(I.Mdl());
		ULONG *ret=(ULONG *)Mem.MapToSystemSpace();
		*ret=Regvalue;
		I.Information()=sizeof(ULONG);          
		status=STATUS_SUCCESS;                 //缓冲区方式
	}
	else
	{
		status=STATUS_UNSUCCESSFUL;
	}

	return status;
}

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

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

	t << "Entering BlockDMADevice::BlockDMA_IOCTL_803_Handler, " << I << EOL;
// TODO:	Verify that the input parameters are correct
//			If not, return STATUS_INVALID_PARAMETER

// TODO:	Handle the the BlockDMA_IOCTL_803 request, or 
//			defer the processing of the IRP (i.e. by queuing) and set
//			status to STATUS_PENDING.

// TODO:	Assuming that the request was handled here. Set I.Information
//			to indicate how much data to copy back to the user.
//	I.Information() = 0;

	//测试是否可以复位9054
    long m_reset;
	m_reset=m_IoPortRange1.ind(0X6C); 
	t<<"输出当前CNTRL寄存器的值"<<m_reset<<EOL;

	m_reset=0X4180F767;  //复位9054
    m_IoPortRange1.outd(0X6C,m_reset) ;
	t<<"向CNTRL寄存器写入"<<m_reset<<EOL;    

	m_reset=m_IoPortRange1.ind(0X6C); 
	t<<"向CNTRL寄存器写入复位信息后再次读出的值是"<<m_reset<<EOL;


    m_IoPortRange1.outd(0X6C,0X200F767E) ;
	t<<"清除复位标志,重新加载EEPROM的信息到9054"<<m_reset<<EOL;  

	m_reset=m_IoPortRange1.ind(0X6C); 
	t<<"察看复位标志位是否被清除,以及EEPROM加载标志是否有效"<<m_reset<<EOL;
    
    m_IoPortRange1.outd(0X6C,0X000F767E) ;
	t<<"加载EEPROM结束"<<EOL;  


	I.Information()=sizeof(ULONG);
	return status;
}

NTSTATUS BlockDMADevice::BLOCKDMA_IOCTL_804_Handler(KIrp I)
{
	NTSTATUS status=STATUS_SUCCESS;
	ULONG *pp=(ULONG *)I.IoctlBuffer();
	if(pp!=NULL)
	{
		ULONG index=*(ULONG *)pp;
		ULONG Regvalue=*(ULONG *)(pp+1);
		m_IoPortRange3.outd(index,Regvalue);
        t<<"Enter 804 address = "<<index<<"  "<<Regvalue<<EOL;
		I.Information()=sizeof(ULONG);          
		status=STATUS_SUCCESS;                 //缓冲区方式
	}
	else
	{
		status=STATUS_UNSUCCESSFUL;
	}
	return status;
}

////////////////////////////////////////////////////////////////////////
//  BlockDMADevice::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 BlockDMADevice::DpcFor_Irq(PVOID Arg1, PVOID Arg2)
{
    t<<"延时过程调用  "<<EOL;

	m_CurrentTransfer->Continue(UseTransferSize);

}

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

BOOLEAN BlockDMADevice::Isr_Irq(void)
{
    
	//第3 步 DMA 传输结束 中断服务子程序 
	t<<"第3 步 DMA 传输结束 ,中断服务子程序 "<<EOL;
	ULONG status;

	status=	m_IoPortRange1.ind(INTCSR);

	if ((status & 0x200000)==0)
	{	
		return FALSE;	
	}

	//清除中断
	m_IoPortRange1.outd(DMAMODE0,0x201C3);	
	m_IoPortRange1.outb(DMACSR0,0x18);	
	
	if(!m_DpcFor_Irq.Request(NULL,NULL)){}	

	return TRUE;

//	m_pEventToSignal->Set();
	//m_IoPortRange1.outd(0x84 , m_PAddr);
	//	    m_IoPortRange1.outd(0x80 , 0x000205C3);
	//	    m_IoPortRange1.outb(0xA8 , 0x03);    
	//	    m_Bytes=m_Bytes+0x100000;
	

}

VOID BlockDMADevice::StartDMA(ULONG PAddress,ULONG NBytes)
{
	
	//Channel0 interrupt to the PCI Bus interrupt,Done Interrupt Enable,FIFO;   
	/*初始化并启动DMA*/
	t<<"The StartDma function  Called"<<EOL;

	ULONG Reg68 = 0x00040180;
	m_IoPortRange1.outd(0x68,Reg68);//Enable Dma Channel0 INT

	ULONG Reg80 = 0x000205C3;  //BTERM=1,BURST=1
	m_IoPortRange1.outd(0x80 , Reg80);//DMA Channel 0 Mode 

	ULONG Reg84 = PAddress;
	m_IoPortRange1.outd(0x84 , Reg84);//DMA Channel 0 PCI Adress Register

	ULONG Reg88 = 0xed000000;
	m_IoPortRange1.outd(0x88 , Reg88); //DMA Channel 0 Local Adress Register

	ULONG Reg8C = NBytes;
	m_IoPortRange1.outd(0x8c , Reg8C);// DMA Channel 0 set dma count(bytes)

	ULONG Reg90 = 0x8;

    if(m_ReadWrite==2) Reg90 = 0x0;

	m_IoPortRange1.outd(0x90 , Reg90);//DMA Channel 0 Descriptor Pointer Register

	UCHAR RegA8 = 0x03;
	m_IoPortRange1.outb(0xA8 , RegA8);//DMA Channel 0 Command/Status Register
}

VOID BlockDMADevice::OnDmaReady(KDmaTransfer* pXfer, KIrp I)
{
	// All KDmaTransfer callbacks must first check to see if there are any bytes
	// left to transfer.
    if(m_ReadWrite==1){
	LONG Bytes=pXfer->BytesRemaining();
	if (Bytes == 0)
	{	//第四步,DMA结束,完成IRP
		// If there are no bytes left to transfer, the callback must call
		// Terminate(). Then it completes the IRP with STATUS_SUCCESS.
		pXfer->Terminate();
	    t<<"第4步 DMA传输结束 ,完成IRP"<<EOL;       
		I.Information() = I.ReadSize(CURRENT);
		I.Status() = STATUS_SUCCESS;
		PnpNextIrp(I);
		m_CurrentTransfer = NULL;
		delete pXfer;
      
	    m_pEventToSignal->Set();
		return;
	}

//	else if(Bytes==I.ReadSize(CURRENT))
	
	//下面是第二步,获取要传输的物理内存的地址和字节数,调用StartDMA例程

	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.  ptd->td_Length

     	if ((ULONG) pXfer->BytesRemaining() == I.ReadSize()){
	           t<<"第2步 启动 StartDMA"<<EOL;			 
	           StartDMA(ptd->td_PhysAddr.LowPart,ptd->td_Length);
		}
	
	}else if(m_ReadWrite==2){

	     LONG Bytes=pXfer->BytesRemaining();
         if (Bytes == 0)
		 {	//第四步,DMA结束,完成IRP
		   // If there are no bytes left to transfer, the callback must call
		   // Terminate(). Then it completes the IRP with STATUS_SUCCESS.
		   pXfer->Terminate();
	       t<<"第4步 DMA传输结束 ,完成IRP"<<EOL;       
	       I.Information() = I.WriteSize(CURRENT);
		   I.Status() = STATUS_SUCCESS;
		   PnpNextIrp(I);
		   m_CurrentTransfer = NULL;
		   delete pXfer;
      
	  
		   return;
		 }


	
	      //下面是第二步,获取要传输的物理内存的地址和字节数,调用StartDMA例程

        	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.  ptd->td_Length

	    if ((ULONG) pXfer->BytesRemaining() == I.WriteSize()){
	           t<<"第2步 启动 StartDMA"<<EOL; 
	           StartDMA(ptd->td_PhysAddr.LowPart,ptd->td_Length);
		}
	}
	
}

⌨️ 快捷键说明

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