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

📄 bpskdevice.cpp

📁 PCI9054驱动
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//		I - Current IRP
//
//	Return Value:
//		NTSTATUS - Result code
//
//	Comments:
//		This routine handles write requests.
//
//		The KPnpDevice class handles restricting IRP flow
//		if the device is stopping or being removed.
//

NTSTATUS BPSKDevice::Write(KIrp I) 
{
	t << "Entering BPSKDevice::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 (I.WriteSize() == 0)
	{
		I.Information() = 0;
		return I.PnpComplete(this, STATUS_SUCCESS);
	}

	return QueueIrp(I, LinkTo(CancelQueuedIrp));
/*	原来的框架
	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);
	}
	NTSTATUS status		= STATUS_SUCCESS;

	KMemory Mem(I.Mdl());						// Declare a memory object
	// Use the memory object to create a pointer to the caller's buffer
	PUCHAR	pBuffer		= (PUCHAR) Mem.VirtualAddress();

	ULONG   dwTotalSize = I.WriteSize(CURRENT);
	ULONG   dwBytesSent = 0;

// 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() = dwBytesSent;

	return I.PnpComplete(this, status);
*/
}


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

NTSTATUS BPSKDevice::CONFIG_SYMBOL_RATE_Handler(KIrp I)
{
	NTSTATUS status = STATUS_SUCCESS;

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

// TODO:	Handle the the CONFIG_SYMBOL_RATE 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.

	SYMBOL_RATE_STRUCT *SymbolRate= (SYMBOL_RATE_STRUCT *)(I.IoctlBuffer());
	for(DWORD i = 0;i < SymbolRate->BytesCount;i++)
	{
		t<< "Control Word is:  "<<SymbolRate->ControlWord[i]<<EOL;
		m_IoPortRange1.outb(0xc0,SymbolRate->ControlWord[i]);
	}
	BYTE TEMP=m_IoPortRange1.inb(0xf0);//0xf0:Range for PCI-to-Local Address Space 1
	I.Information() = 0;

	return status;
}

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

NTSTATUS BPSKDevice::MODULATE_MODE_Handler(KIrp I)
{
	NTSTATUS status = STATUS_SUCCESS;

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

// TODO:	Handle the the MODULATE_MODE 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.
	BYTE *ModulMode=(BYTE *)(I.IoctlBuffer());
	BYTE TEMP=*ModulMode;
	m_IoPortRange1.outb(0x30,*ModulMode);//0x30:PCI Base Address for Local Expansion ROM
	I.Information() = 0;

	return status;
}

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

NTSTATUS BPSKDevice::SET_IF_FRE_Handler(KIrp I)
{
	NTSTATUS status = STATUS_SUCCESS;

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

// TODO:	Handle the the SET_IF_FRE 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.
	IF_FRE_STRUCT *IF_FRE= (IF_FRE_STRUCT *)(I.IoctlBuffer());
	for(DWORD i = 0;i < IF_FRE->BytesCount;i++)
	{
		t<< "Control Word is:  "<<IF_FRE->ControlWord[i]<<EOL;
		m_IoPortRange1.outb(0x30,IF_FRE->ControlWord[i]);
	}
	m_IoPortRange1.inb(0x60);//0x60:PCI-to-Local Doorbell Register
	I.Information() = 0;

	return status;
}

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

NTSTATUS BPSKDevice::CTRL_AD9851_INIT_Handler(KIrp I)
{
	NTSTATUS status = STATUS_SUCCESS;

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

// TODO:	Handle the the CTRL_AD9851_INIT 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.
	m_IoPortRange1.inb(0x90);
	AD9851_CONTROL_STRUCT *AD9851_ctrl = (AD9851_CONTROL_STRUCT *)(I.IoctlBuffer());
	for(DWORD i = 0;i < AD9851_ctrl->BytesCount;i++)
	{
		t<< "Control Word is:  "<<AD9851_ctrl->ControlWord[i]<<EOL;
		m_IoPortRange1.outb(0x30,AD9851_ctrl->ControlWord[i]);
	}
	m_IoPortRange1.inb(0x60);//0x60:PCI-to-Local Doorbell Register
	I.Information() = 0;

	return status;
}

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

NTSTATUS BPSKDevice::IOCTL_SET_NOTIFICATION_EVENT_Handler(KIrp I)
{
	t << "Entering BPSKDevice::IOCTL_SET_NOTIFICATION_EVENT_Handler, " << I << EOL;

	HANDLE hEvent;
	NTSTATUS status;
	hEvent=*(HANDLE*)I.IoctlBuffer();
/*	KMemory Mem(I.Mdl());
	// Use the memory object to create a pointer to the caller's buffer
	hEvent=*(HANDLE*) Mem.MapToSystemSpaceAddress();
*/
	m_pEvent=new(NonPagedPool)KEvent(hEvent,OBJECT_TYPE_ALL_ACCESS);
	status=(m_pEvent!=NULL)?STATUS_SUCCESS:STATUS_INSUFFICIENT_RESOURCES;
	I.Information()=0;
	return status;
}

////////////////////////////////////////////////////////////////////////
//  BPSKDevice::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 BPSKDevice::DpcFor_Irq(PVOID Arg1, PVOID Arg2)
{
	t<<"Entering Dpc"<<EOL;

	if(LocInt==0)
	{	
		m_CurrentTransfer->Continue(UseTransferSize);
		t<<"继续DMA传输"<<EOL;
	}
	else if(LocInt==1)
	{
		t<<"本地传输"<<EOL;
	BOOLEAN Notify;
	BOOLEAN SynchStatus;
	if(m_pEvent)
	{
		SynchStatus=SynchronizeInterrupt(&m_Irq,LinkTo(TestAndClearNotifyApp),&Notify);
		if(SynchStatus)//是否已获得中断自旋锁
		{
			t<<"DPC,App notify="<<ULONG(Notify)<<"\n";
			m_pEvent->Set();
		}
		else
			t<<"DPC error synchronizing\n";
	}
	}
	UNREFERENCED_PARAMETER(Arg1);
	UNREFERENCED_PARAMETER(Arg2);
	
}
BOOLEAN BPSKDevice::TestAndClearNotifyApp(PVOID p)
{
	t<<"Entering BPSKDevice::TestAndClearNotifyApp, "<< EOL;
	*(BOOLEAN*)p=m_bNotifyApp;
	m_bNotifyApp=FALSE;
	return TRUE;
}
////////////////////////////////////////////////////////////////////////
//  BPSKDevice::Isr_Irq
//
//	Routine Description:
//		Interrupt Service Routine (ISR) for IRQ Irq
//
//	Parameters:
//		None
// 
//	Return Value:
//		BOOLEAN		True if this is our interrupt
//
//	Comments:
//

BOOLEAN BPSKDevice::Isr_Irq(void)
{
	t<<"Entering Isr_Irq."<<EOL;
	ULONG status;
	status=	m_IoPortRange0.ind(INTCSR);
	t<<"INTCSR的内容"<<status<<EOL;
	if((status&0x8000)!=0)
	{
		LocInt=1;//local中断
		t<<"Local Interrupt"<<EOL;
		m_IoPortRange0.outd(INTCSR,0x40100);
		m_DpcFor_Irq.Request(NULL, NULL);
		return TRUE;
	}
	else if ((status & 0x200000)!=0)
	{
		LocInt=0;
		m_IoPortRange0.outd(DMAMODE0,0x20801);//禁止中断
		m_IoPortRange0.outb(DMACSR0,0x8);//Clear Interrupt
		t<<"DMA Interrupt."<<EOL;
		m_DpcFor_Irq.Request(NULL, NULL);
		return TRUE;
	}
/*	if (!m_DpcFor_Irq.Request(NULL, NULL))
	{
// TODO:	Request is already in the queue
//			You may want to set flags or perform
//			other actions in this case
	}

	// Return TRUE to indicate that our device caused the interrupt
	return TRUE;
*/
	else	
		t<<"Interrupt didn't happen."<<EOL;
		return FALSE;
}
VOID BPSKDevice::StartDMA(ULONG PAddress,ULONG NBytes)
{
	//下面几条语句设置DMA通道0寄存器,启动块传输方式,从FIFO读数据
	t<<"Entering StartDMA"<<EOL;
	ULONG TEMP1,TEMP2;
	TEMP1=PAddress;
	TEMP2=NBytes;
	//Channel0 interrupt to the PCI Bus interrupt,Done Interrupt Enable,FIFO
	m_IoPortRange0.outd(DMAMODE0,0x20dc1);//16位
	//DMA Channel0 PCI Address
	m_IoPortRange0.outd(DMAPADR0,PAddress);
	//DMA Channel0 Local Address,自己设计的FIFO地址0X14
//	m_IoPortRange0.outd(DMALADR0,0x8);//内部fifo,08x:DMA仲裁
	m_IoPortRange0.outd(DMALADR0,0xe0);//0xe0
	//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
	m_IoPortRange0.outb(DMACSR0,0x3);
}

VOID BPSKDevice::OnDmaReady(KDmaTransfer* pXfer, KIrp I)
{
	// All KDmaTransfer callbacks must first check to see if there are any bytes
	// left to transfer.
	LONG TEMP=pXfer->BytesRemaining();
	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.
		pXfer->Terminate();
		I.Information() = I.ReadSize(CURRENT);
		I.Status() = STATUS_SUCCESS;
		PnpNextIrp(I);
		m_CurrentTransfer = NULL;
//		t<<"一次DMA传输结束,通知应用程序取数据"<<EOL;
//		m_pEvent1->Set();
		delete pXfer;
		m_IoPortRange0.outd(INTCSR,0x40900);//允许本地中断
		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.
	TEMP=I.ReadSize();
	if ((ULONG) pXfer->BytesRemaining() == I.ReadSize())
		StartDMA(ptd->td_PhysAddr.LowPart,ptd->td_Length);
}



NTSTATUS BPSKDevice::START_COLLECT_Handler(KIrp I)
{
	NTSTATUS status = STATUS_SUCCESS;
	ULONG test2;
	t << "Entering BPSKDevice::START_COLLECT_Handler, " << I << EOL;

//	m_IoPortRange1.inb(0x90);
	m_IoPortRange1.inb(0x10);//0x10
	// TODO:允许PCI中断和DMA通道0中断
	m_IoPortRange0.outd(INTCSR,0x40900);
	test2=m_IoPortRange0.ind(INTCSR);
	I.Information() = 0;

	return status;
}

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

NTSTATUS BPSKDevice::STOP_COLLECT_Handler(KIrp I)
{
	NTSTATUS status = STATUS_SUCCESS;

	t << "Entering BPSKDevice::STOP_COLLECT_Handler, " << I << EOL;
	m_IoPortRange1.inb(0x20);//0x20:Local Base Address for PCI Initiator-to-PCI Memory
	I.Information() = 0;

	return status;
}

⌨️ 快捷键说明

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