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

📄 phantomeppsrlapi.c

📁 用Ardence RTX SDK开发的EPP并口驱动程序.
💻 C
📖 第 1 页 / 共 3 页
字号:
		pIrp->dwStatus     = STATUS_SUCCESS;
		//IoCompleteRequest( pIrp, IO_NO_INCREMENT ); 
		goto FINISH;
	}

	if (IOCTL_WRITE_STATUS_REGISTER == currentIoControlCode)
	{
		UCHAR                       statusRegister;
		//RtPrintf("PHANTOMEPP:IOCTL_WRITE_STATUS_REGISTER\n");
		statusRegister = pIoBuffer[0];
		WriteStatus(nPortBase, statusRegister);
		pIrp->dwBytesReturned = 0; /* Output Buffer Size */
		pIrp->dwStatus      = STATUS_SUCCESS;
		//IoCompleteRequest( pIrp, IO_NO_INCREMENT );
		goto FINISH;
	}

	if (IOCTL_READ_CONTROL_REGISTER == currentIoControlCode)
	{
		UCHAR                       controlRegister;
		//RtPrintf("PHANTOMEPP:IOCTL_READ_STATUS_REGISTER\n");
		controlRegister = ReadControl(nPortBase);
		pIoBuffer[0]    = controlRegister;
		pIrp->dwBytesReturned = 1; /* Output Buffer Size */
		pIrp->dwStatus     = STATUS_SUCCESS;
		//IoCompleteRequest( pIrp, IO_NO_INCREMENT );
		goto FINISH;
	}

	if (IOCTL_WRITE_CONTROL_REGISTER == currentIoControlCode)
	{
		UCHAR                       controlRegister;
		//RtPrintf("PHANTOMEPP:IOCTL_WRITE_CONTROL_REGISTER\n");
		controlRegister = pIoBuffer[0];
		WriteControl(nPortBase,controlRegister);
		pIrp->dwBytesReturned = 0; /* Output Buffer Size */
		pIrp->dwStatus       = STATUS_SUCCESS;
		//IoCompleteRequest( pIrp, IO_NO_INCREMENT );
		goto FINISH;
	}

	if (IOCTL_READ_BYTE == currentIoControlCode)
	{
		UCHAR                       dataAddress;
		UCHAR                       dataValue;
		//RtPrintf("PHANTOMEPP:IOCTL_READ_BYTE\n");

		dataAddress = pIoBuffer[0];

		// Note that IOCTL_WRITE_BYTE only works for the first channel.
		// The pass-thru facility only works when performing a burst
		// read/write.
		if (dataAddress >= 0 && dataAddress < INPUT_LENGTH)
		{
			WriteAddress(nPortBase, dataAddress);
			dataValue = ReadByte(nPortBase);

			pIoBuffer[0] = dataAddress;
			pIoBuffer[1] = dataValue;

			pIrp->dwBytesReturned = 2; /* Output Buffer Size */
			pIrp->dwStatus = STATUS_SUCCESS;
		}
		else
		{
			pIrp->dwBytesReturned = 0; /* Output Buffer Size */
			pIrp->dwStatus = STATUS_UNSUCCESSFUL;
		}

		//IoCompleteRequest( pIrp, IO_NO_INCREMENT );
		goto FINISH;
	}

	if (IOCTL_WRITE_BYTE == currentIoControlCode)
	{
		UCHAR                       dataAddress;
		UCHAR                       dataValue;
		//RtPrintf("PHANTOMEPP:IOCTL_WRITE_BYTE\n");

		dataAddress     = pIoBuffer[0];
		dataValue       = pIoBuffer[1];

		// Note that IOCTL_WRITE_BYTE only works for the first channel.
		// The pass-thru facility only works when performing a burst
		// read/write.
		if (dataAddress >= INPUT_LENGTH && 
			dataAddress < (INPUT_LENGTH + OUTPUT_LENGTH))
		{
			ULONG nIndex;

			WriteAddress(nPortBase, dataAddress);
			WriteByte(nPortBase, dataValue);

			// Also update the WriteBuffers cache. 
			nIndex = dataAddress - INPUT_LENGTH;
			ucb.m_WriteBuffers[0][nIndex] = dataValue;

			status = STATUS_SUCCESS;
		}
		else
		{
			// Invalid address
			status = STATUS_UNSUCCESSFUL;
		}

		pIrp->dwBytesReturned = 0; /* Output Buffer Size */
		pIrp->dwStatus = status;
		//IoCompleteRequest( pIrp, IO_NO_INCREMENT );
		goto FINISH;
	}

	if (IOCTL_READ_ECR_REGISTER == currentIoControlCode)
	{
		UCHAR                       dataAddress;
		UCHAR                       dataValue;
		//RtPrintf("PHANTOMEPP:IOCTL_READ_ECR\n");

		dataAddress     = pIoBuffer[0];
		WriteAddress(nPortBase, dataAddress);
		dataValue       = ReadECR(nPortBase);
		pIoBuffer[0]    = dataAddress;
		pIoBuffer[1]    = dataValue;
		pIrp->dwBytesReturned = 2; /* Output Buffer Size */
		pIrp->dwStatus  = STATUS_SUCCESS;
		//IoCompleteRequest( pIrp, IO_NO_INCREMENT );
		goto FINISH;
	}

	if (IOCTL_WRITE_ECR_REGISTER == currentIoControlCode)
	{
		UCHAR                       dataAddress;
		UCHAR                       dataValue;
		//RtPrintf("PHANTOMEPP:IOCTL_WRITE_ECR\n");

		dataAddress     = pIoBuffer[0];
		dataValue       = pIoBuffer[1];
		WriteAddress(nPortBase, dataAddress);
		WriteECR(nPortBase,   dataValue);
		pIrp->dwBytesReturned = 0; /* Output Buffer Size */
		pIrp->dwStatus      = STATUS_SUCCESS;
		//IoCompleteRequest( pIrp, IO_NO_INCREMENT );
		goto FINISH;
	}

	if (IOCTL_PING_DEVICE == currentIoControlCode)
	{
		//RtPrintf("PHANTOMEPP:IOCTL_PING_DEVICE\n");
		status = PingDevice();
		pIrp->dwBytesReturned = 0; /* Output Buffer Size */
		pIrp->dwStatus = STATUS_SUCCESS;
		//IoCompleteRequest( pIrp, IO_NO_INCREMENT );
		goto FINISH;
	}     

	if (IOCTL_ENABLE_TIMER_EVENT == currentIoControlCode)
	{
		RtPrintf("PHANTOMEPP:IOCTL_ENABLE_TIMER_EVENT\n");

		if (inBufferLength == sizeof(PHANTOM_ENABLE_TIMER_EVENT))
		{   
			PPHANTOM_ENABLE_TIMER_EVENT pEventData = (PHANTOM_ENABLE_TIMER_EVENT*)pIoBuffer;

			if (pEventData->UseSoftwareTimer)
			{
				pEventData->EventHandle = RtdDriverGetEvent(hDriver);
				status = EnableSoftwareTimerEvent(
					pEventData->EventHandle,
					pEventData->SoftwareTimerPeriodMs);
			}
			else
			{
				status = EnableInterrupts();

				if (status == STATUS_SUCCESS)
				{
					status = EnableTimerEvent(
						pEventData->EventHandle);
				}
			}
		}
		else
		{
			status = STATUS_UNSUCCESSFUL;
		}

		pIrp->dwBytesReturned = 0; 
		pIrp->dwStatus = status;
		//IoCompleteRequest( pIrp, IO_NO_INCREMENT );
		goto FINISH;
	}

	if (IOCTL_DISABLE_TIMER_EVENT == currentIoControlCode)
	{
		RtPrintf("PHANTOMEPP:IOCTL_DISABLE_TIMER_EVENT\n");

		if (ucb.m_SoftwareTimerEnabled)
		{
			status = DisableSoftwareTimerEvent();
		}
		else
		{
			status = DisableTimerEvent();

			if (status == STATUS_SUCCESS)
			{
				status = DisableInterrupts();
			}
		}

		pIrp->dwBytesReturned = 0; 
		pIrp->dwStatus = status;
		//IoCompleteRequest( pIrp, IO_NO_INCREMENT );
		goto FINISH;
	}

	if (IOCTL_READ_EVENT_COUNT == currentIoControlCode)
	{
		if (outBufferLength == sizeof(ULONG))
		{
			ULONG *outputBuffer = (ULONG*)pIoBuffer; 
			outputBuffer[0] = ucb.m_SignalEventCount;            

			pIrp->dwBytesReturned = outBufferLength; /* Output Buffer Size */
			pIrp->dwStatus = STATUS_SUCCESS;
		}
		else
		{
			pIrp->dwBytesReturned = 0;
			pIrp->dwStatus = STATUS_UNSUCCESSFUL;
		}

		//IoCompleteRequest( pIrp, IO_NO_INCREMENT );
		goto FINISH;
	}

	RtPrintf("PHANTOMEPP:Unsupported IOCTL Call\n");

	status = STATUS_UNSUCCESSFUL;
	pIrp->dwStatus = status;
	pIrp->dwBytesReturned = 0;
	//IoCompleteRequest(pIrp, IO_NO_INCREMENT);
FINISH:
	return status;
}


//
// Copies data to be written into persistent write buffer
//
VOID PreReadWritePhantom(PHANTOM_READ_WRITE_BLOCK   *pBlockData)
{
	ULONG   i;
	UCHAR   uMask;

	// Make sure this routine is multiprocessor safe
	//KeAcquireSpinLock(&ucb.m_SpinLock, &restoreIrql);

	ucb.m_ChannelMask = pBlockData->ChannelMask;

	ucb.m_EnableSoftwareWatchdog = pBlockData->EnableSoftwareWatchdog;

	for (i = 0; i < PHANTOM_MAX_CHANNELS; i++)
	{
		uMask = 1 << i;        

		// Copy the data to write from the PHANTOM_READ_WRITE_BLOCK struct
		// Maintain this data for refreshing the device later
		if ((pBlockData->ChannelMask & uMask) != 0)
		{
			RtCopyMemory(ucb.m_WriteBuffers[i],pBlockData->Values[i],pBlockData->WriteCount[i]);
		}
	}

	//KeReleaseSpinLock(&ucb.m_SpinLock, restoreIrql);
}


//
// Copies previously read data into a PHANTOM_READ_WRITE_BLOCK to be
// buffered to usermode
//
VOID PostReadWritePhantom(PHANTOM_READ_WRITE_BLOCK   *pBlockData)
{
	ULONG   i;
	UCHAR   uMask;

	// Make sure this routine is multiprocessor safe
	//KeAcquireSpinLock(&ucb.m_SpinLock, &restoreIrql);

	for (i = 0; i < PHANTOM_MAX_CHANNELS; i++)
	{
		uMask = 1 << i;        

		// Copy the data read into the PHANTOM_READ_WRITE_BLOCK struct
		// to be buffered back to usermode
		if ((pBlockData->ChannelMask & uMask) != 0)
		{
			RtCopyMemory(pBlockData->Values[i],ucb.m_ReadBuffers[i],pBlockData->ReadCount[i]);
		}
	}

	//KeReleaseSpinLock(&ucb.m_SpinLock, restoreIrql);
}


DWORD ReadWritePhantom()
{
	ULONG    i;
	UCHAR    uNextChannels;
	DWORD status = STATUS_UNSUCCESSFUL;

	// Make sure this routine is multiprocessor safe
	//KeAcquireSpinLock(&ucb.m_SpinLock, &restoreIrql);

	// Validate that the port is operable
	if (!CheckStatus(ucb.baseAddress))
	{
		goto FINISH;
	}

	// Reset the address and allow the device to internally increment it
	// as well as pass-thru read/write data to chained devices. Unfortunately,
	// the PhantomEPP firmware does not behave as documented in the
	// "Phantom EPP System Specification Rev 9". We are not able to perform
	// burst read/write with the pass-thru Phantom without first performing
	// a burst read/write with the initial Phantom. This prevents us from
	// supporting a more general block transfer API 
	WriteAddress(ucb.baseAddress, 0x00);    

	for (i = 0; i < PHANTOM_MAX_CHANNELS; i++)
	{
		// Read a block of data from the EPP board
		ReadBlock(ucb.baseAddress,
			ucb.m_ReadBuffers[i], 
			INPUT_LENGTH);            

		// Update the watchdog counter and validate the echo register
		if (!ManageWatchDog(ucb.m_ReadBuffers[i],
			ucb.m_WriteBuffers[i],
			&ucb.m_PrevWatchdogOut[i],
			&ucb.m_WatchdogErrorCount[i]))
		{
			goto FINISH;
		}

		// Write a block of data to the EPP board
		WriteBlock(ucb.baseAddress,
			ucb.m_WriteBuffers[i],
			OUTPUT_LENGTH);

		// Break early if there are no other channels to be serviced
		uNextChannels = ucb.m_ChannelMask >> (i + 1);
		if (uNextChannels == 0)
			break;
	}

	// Make sure that the ACK line of the status register has been supressed
	if (!HandleInterrupt())
	{
		goto FINISH;
	}

	status = STATUS_SUCCESS;

FINISH:

	//KeReleaseSpinLock(&ucb.m_SpinLock, restoreIrql);

	return status;
}



VOID SetWatchdogTimeout()
{
	LARGE_INTEGER DueTime;

	DueTime.QuadPart = SOFTWARE_WATCHDOG_TIMEOUT;

	//KeAcquireSpinLock(&ucb.m_SpinLock, &restoreIrql);

	RtSetTimerRelative(ucb.m_TimeoutTimer, &DueTime,NULL);

	// Mark a flag that the timer has been set
	ucb.m_TimeoutCount += 1;

	//KeReleaseSpinLock(&ucb.m_SpinLock, restoreIrql);
}


BOOLEAN ManageWatchDog(PUCHAR   pReadBuffer,
					   PUCHAR   pWriteBuffer,
					   PUCHAR   pPrevWatchdogOut,
					   PUCHAR   pWatchdogErrorCount)
{
	PPORT_INPUT pRegsIn = (PPORT_INPUT)pReadBuffer;
	PPORT_OUTPUT pRegsOut = (PPORT_OUTPUT)pWriteBuffer;

	if ((pRegsIn->ucMiscIn & WDOG_IS_OK) == 0)
	{
		//RtPrintf("PHANTOMEPP:Watchdog Not OK\n");
	}	    

	// Validate the consistency of the watchdog echo register
	if (pRegsIn->ucWatchdogCntrIn == *pPrevWatchdogOut)
	{
		// Reset the watchdog error count as long as we're getting
		// correct input/output echoing
		*pWatchdogErrorCount = 0;
	}
	else
	{
		// The watchdog value was not echoed so record an error
		*pWatchdogErrorCount += 1;

		// Bail if we've deteced 3 or more errors
		if (*pWatchdogErrorCount >= 3)
		{
			*pWatchdogErrorCount = 0;
			return FALSE;
		}
	}

	// Increment the watchdog counter
	*pPrevWatchdogOut += 1;

	pRegsOut->ucWatchdogCntrOut = *pPrevWatchdogOut;

	return TRUE;
}

DWORD ClearWatchdogTimeout(BOOLEAN bWaitForCancel)
{
	DWORD status = STATUS_SUCCESS;
	LARGE_INTEGER TimeRemaining;
	DWORD Timeout;
	BOOLEAN  bTimerCancelled;

	//KeAcquireSpinLock(&pDeviceExtension->m_SpinLock, &restoreIrql);

	// Cancel the pending watchdog timeout
	bTimerCancelled = RtCancelTimer(&ucb.m_TimeoutTimer,&TimeRemaining);

	// Optionally wait for the DPC routine to finish in the case where
	// the timer had been set, signaled and we are waiting for the DPC to finish
	if (!bTimerCancelled && ucb.m_TimeoutCount && bWaitForCancel)
	{
		Timeout = SOFTWARE_WATCHDOG_TIMEOUT;

		status = RtWaitForSingleObject(ucb.m_TimeoutEvent,Timeout);
	}

	// Timer has been cleared so reset the timeout count
	ucb.m_TimeoutCount = 0;

	//KeReleaseSpinLock(&pDeviceExtension->m_SpinLock, restoreIrql);

	return status;
}


DWORD EnableSoftwareTimerEvent(HANDLE hEvent,ULONG SoftwareTimerPeriodMs)
{
	DWORD status = STATUS_SUCCESS; 

	// First setup the timer event as usual
	status = EnableTimerEvent(hEvent);
	if (status != STATUS_SUCCESS)
		return status;

	// Now we can raise IRQL and manage the assignment
	//KeAcquireSpinLock(&pDeviceExtension->m_SpinLock, &restoreIrql);

	// Mark the timer enabled flag

⌨️ 快捷键说明

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