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

📄 pciscc_drv.c

📁 高速同步串口芯片PEB20534的驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:

#include <ntddk.h>
#include "pciscc_drv.h"
#include "pciscc_ioctl.h"
#include "pciscc_flex.h"

#define	CHIP_TIMEOUT	1000000		/* chip command timeout */
#define	XTAL_FREQ		19660000	/* on board crystal freq. */
#define	MIN_FLAGS		32			/* minimum delay/tail bits */

NTSTATUS DriverEntry(
	IN PDRIVER_OBJECT  DriverObject,
	IN PUNICODE_STRING RegistryPath
	)
{
	PLOCAL_DEVICE_INFO pLDI;
	PDEVICE_OBJECT DeviceObject;
	UNICODE_STRING NtDeviceName;
	UNICODE_STRING Win32DeviceName;
	NTSTATUS Status;

	// Initialize the driver object dispatch table.
	// NT sends requests to these routines.
	DriverObject->MajorFunction[IRP_MJ_CREATE]			= pciscc_create;
	DriverObject->MajorFunction[IRP_MJ_CLOSE]			= pciscc_close;
	DriverObject->MajorFunction[IRP_MJ_READ]			= pciscc_read;
	DriverObject->MajorFunction[IRP_MJ_WRITE]			= pciscc_write;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]	= pciscc_ioctl;
	DriverObject->DriverUnload							= pciscc_unload;

	/* Get UNICODE name for device.*/
	RtlInitUnicodeString(&NtDeviceName, PCISCC_NT_NAME);
	RtlInitUnicodeString(&Win32DeviceName, PCISCC_W32_NAME);

	/* Create our device. */
	Status = IoCreateDevice(
					DriverObject,
					sizeof(LOCAL_DEVICE_INFO),
					&NtDeviceName,
					FILE_DEVICE_UNKNOWN,
					0,
					FALSE,
					&DeviceObject
					);

	if (!NT_SUCCESS(Status))
		return Status;

	/* Initialize the local driver info */
	pLDI = (PLOCAL_DEVICE_INFO)DeviceObject->DeviceExtension;

	/* Clear local device info memory */
	RtlZeroMemory(pLDI, sizeof(LOCAL_DEVICE_INFO));

	DeviceObject->Flags |= DO_BUFFERED_IO;
	DeviceObject->AlignmentRequirement = FILE_BYTE_ALIGNMENT;
	
	InitializeListHead(&pLDI->RxQueue);
	InitializeListHead(&pLDI->RxPending);
	KeInitializeSpinLock(&pLDI->Lock);

	KeInitializeDpc(&pLDI->TxResetDpc, pciscc_dpc_txreset, DeviceObject);
	KeInitializeDpc(&pLDI->IsrDpc, pciscc_dpc_isr, DeviceObject);

	/* Create symbolic device link */
	Status = IoCreateSymbolicLink( &Win32DeviceName, &NtDeviceName );
	if (!NT_SUCCESS(Status))
	{
		IoDeleteDevice(DeviceObject);
		return Status;
	}

	/* PCISCC hardware probe */
	Status = pciscc_nt_config(DriverObject,RegistryPath,pLDI);
	if (NT_SUCCESS(Status))
		Status = pciscc_chip_open(pLDI);

	if (!NT_SUCCESS(Status))
	{
		IoDeleteSymbolicLink(&Win32DeviceName);
		IoDeleteDevice(DeviceObject);
		return Status;
	}

	return Status;
}

NTSTATUS pciscc_create(
	IN PDEVICE_OBJECT pDO,
	IN PIRP pIrp             
	)
{
	PLOCAL_DEVICE_INFO pLDI = pDO->DeviceExtension;

	pLDI->OpenCnt++;
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}

NTSTATUS pciscc_close(
	IN PDEVICE_OBJECT pDO,
	IN PIRP pIrp             
	)
{
	PLOCAL_DEVICE_INFO pLDI = pDO->DeviceExtension;
	KIRQL OldIrql;
	ULONG chan;

	pLDI->OpenCnt--;
	if (!pLDI->OpenCnt) {
		KeAcquireSpinLock(&pLDI->Lock,&OldIrql);
		for (chan = 0; chan < 4; chan++)
			pciscc_channel_close(pLDI,chan);
		KeReleaseSpinLock(&pLDI->Lock,OldIrql);
	}
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}

NTSTATUS pciscc_read(
	IN PDEVICE_OBJECT pDO,
	IN PIRP pIrp
	)
{
	PLOCAL_DEVICE_INFO pLDI = pDO->DeviceExtension;
	PIO_STACK_LOCATION pIrpStack;
	PLIST_ENTRY pEntry;
	L1FRAME *rx_frame;
	KIRQL OldIrql;
	ULONG Count;
	ULONG Result = 0;

	/* Get read buffer length */
	pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
	Count = pIrpStack->Parameters.Read.Length;
	if (Count > sizeof(L1FRAME))
		Count = sizeof(L1FRAME);

	KeAcquireSpinLock(&pLDI->Lock,&OldIrql);
	/* RX frame list empty ? */
	if (!IsListEmpty(&pLDI->RxQueue)) {
		pEntry = RemoveHeadList(&pLDI->RxQueue);
		rx_frame = CONTAINING_RECORD(pEntry, L1FRAME, list_entry);
		RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer, rx_frame, Count);
		pciscc_free(rx_frame);
		Result = Count;
	}
	if ((pLDI->ReadMode == 1) && (Result == 0)) {
		pIrp->IoStatus.Status = STATUS_PENDING;
		IoMarkIrpPending(pIrp);
		IoSetCancelRoutine(pIrp, pciscc_cancel);
		InsertTailList(&pLDI->RxPending, &pIrp->Tail.Overlay.ListEntry);
		KeReleaseSpinLock(&pLDI->Lock,OldIrql);

		return STATUS_PENDING;
	}
	KeReleaseSpinLock(&pLDI->Lock,OldIrql);

	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}

NTSTATUS pciscc_write(
	IN PDEVICE_OBJECT pDO,
	IN PIRP pIrp
	)
{
	PLOCAL_DEVICE_INFO pLDI = pDO->DeviceExtension;
	PIO_STACK_LOCATION pIrpStack;
	XMIT_SYNC_INFO TxData;
	KIRQL OldIrql;
	ULONG Count;
	ULONG Result = 0;

	/* Get write buffer length */
	pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
	Count = pIrpStack->Parameters.Write.Length;
	if (Count > sizeof(L1FRAME))
		Count = sizeof(L1FRAME);

	KeAcquireSpinLock(&pLDI->Lock,&OldIrql);
	/* TX frame allocated ? */
	if (TxData.tx_frame = pciscc_alloc(sizeof(L1FRAME))) {
		RtlCopyMemory(TxData.tx_frame, pIrp->AssociatedIrp.SystemBuffer, Count);
		TxData.pLDI = pLDI;
		if (KeSynchronizeExecution(pLDI->IrqObject,pciscc_xmit_sync,&TxData))
			Result = Count;
		else
			pciscc_free(TxData.tx_frame);
	}
	KeReleaseSpinLock(&pLDI->Lock,OldIrql);

	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = Result;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	
	return STATUS_SUCCESS;
}

NTSTATUS pciscc_ioctl(
	IN PDEVICE_OBJECT pDO,
	IN PIRP pIrp
	)
{
	PLOCAL_DEVICE_INFO pLDI = pDO->DeviceExtension;
	PIO_STACK_LOCATION pIrpStack;
	CALIB_SYNC_INFO CalibInfo;
	NTSTATUS Status;
	KIRQL OldIrql;
	PULONG pIOBuffer;
	ULONG RdCnt, WrCnt;
	ULONG Result = 0;

	/* Get buffer length */
	pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
	pIOBuffer = (PULONG) pIrp->AssociatedIrp.SystemBuffer;

	/* Get output buffer size */
	RdCnt = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
	WrCnt = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;

	/* Set default return status */
	Status = STATUS_INVALID_BUFFER_SIZE;

	KeAcquireSpinLock(&pLDI->Lock,&OldIrql);
	switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode)
	{
		case PCISCC_SET_PARAM_0:
			if (WrCnt < 2 * sizeof(ULONG))
				break;
			Status = pciscc_channel_open(pLDI,0,pIOBuffer[0],pIOBuffer[1]);
			break;

		case PCISCC_SET_PARAM_1:
			if (WrCnt < 2 * sizeof(ULONG))
				break;
			Status = pciscc_channel_open(pLDI,1,pIOBuffer[0],pIOBuffer[1]);
			break;

		case PCISCC_SET_PARAM_2:
			if (WrCnt < 2 * sizeof(ULONG))
				break;
			Status = pciscc_channel_open(pLDI,2,pIOBuffer[0],pIOBuffer[1]);
			break;

		case PCISCC_SET_PARAM_3:
			if (WrCnt < 2 * sizeof(ULONG))
				break;
			Status = pciscc_channel_open(pLDI,3,pIOBuffer[0],pIOBuffer[1]);
			break;

		case PCISCC_SET_CALIB_0:
			if (WrCnt < sizeof(ULONG))
				break;
			CalibInfo.pLDI = pLDI;
			CalibInfo.chan = 0;
			CalibInfo.time = pIOBuffer[0];
			KeSynchronizeExecution(pLDI->IrqObject,pciscc_calib_sync,&CalibInfo);
			Status = STATUS_SUCCESS;
			break;

		case PCISCC_SET_CALIB_1:
			if (WrCnt < sizeof(ULONG))
				break;
			CalibInfo.pLDI = pLDI;
			CalibInfo.chan = 1;
			CalibInfo.time = pIOBuffer[0];
			KeSynchronizeExecution(pLDI->IrqObject,pciscc_calib_sync,&CalibInfo);
			Status = STATUS_SUCCESS;
			break;

		case PCISCC_SET_CALIB_2:
			if (WrCnt < sizeof(ULONG))
				break;
			CalibInfo.pLDI = pLDI;
			CalibInfo.chan = 2;
			CalibInfo.time = pIOBuffer[0];
			KeSynchronizeExecution(pLDI->IrqObject,pciscc_calib_sync,&CalibInfo);
			Status = STATUS_SUCCESS;
			break;

		case PCISCC_SET_CALIB_3:
			if (WrCnt < sizeof(ULONG))
				break;
			CalibInfo.pLDI = pLDI;
			CalibInfo.chan = 3;
			CalibInfo.time = pIOBuffer[0];
			KeSynchronizeExecution(pLDI->IrqObject,pciscc_calib_sync,&CalibInfo);
			Status = STATUS_SUCCESS;
			break;

		case PCISCC_GET_STATE_0:
			if (RdCnt < sizeof(ULONG))
				break;
			pIOBuffer[0] = pciscc_state(pLDI,0);
			Result = sizeof(ULONG);
			Status = STATUS_SUCCESS;
			break;

		case PCISCC_GET_STATE_1:
			if (RdCnt < sizeof(ULONG))
				break;
			pIOBuffer[0] = pciscc_state(pLDI,1);
			Result = sizeof(ULONG);
			Status = STATUS_SUCCESS;
			break;

		case PCISCC_GET_STATE_2:
			if (RdCnt < sizeof(ULONG))
				break;
			pIOBuffer[0] = pciscc_state(pLDI,2);
			Result = sizeof(ULONG);
			Status = STATUS_SUCCESS;
			break;

		case PCISCC_GET_STATE_3:
			if (RdCnt < sizeof(ULONG))
				break;
			pIOBuffer[0] = pciscc_state(pLDI,3);
			Result = sizeof(ULONG);
			Status = STATUS_SUCCESS;
			break;

		case PCISCC_GET_INFO_0:
			if (RdCnt > sizeof(L1_STATISTICS))
				RdCnt = sizeof(L1_STATISTICS);
			RtlCopyMemory(pIOBuffer, &pLDI->Channel[0].stats, RdCnt);
			Result = RdCnt;
			Status = STATUS_SUCCESS;
			break;

		case PCISCC_GET_INFO_1:
			if (RdCnt < sizeof(L1_STATISTICS))
				RdCnt = sizeof(L1_STATISTICS);
			RtlCopyMemory(pIOBuffer, &pLDI->Channel[1].stats, RdCnt);
			Result = RdCnt;
			Status = STATUS_SUCCESS;
			break;

		case PCISCC_GET_INFO_2:
			if (RdCnt < sizeof(L1_STATISTICS))
				RdCnt = sizeof(L1_STATISTICS);
			RtlCopyMemory(pIOBuffer, &pLDI->Channel[2].stats, RdCnt);
			Result = RdCnt;
			Status = STATUS_SUCCESS;
			break;

		case PCISCC_GET_INFO_3:
			if (RdCnt < sizeof(L1_STATISTICS))
				RdCnt = sizeof(L1_STATISTICS);
			RtlCopyMemory(pIOBuffer, &pLDI->Channel[3].stats, RdCnt);
			Result = RdCnt;
			Status = STATUS_SUCCESS;
			break;

		case PCISCC_NONBLOCK_READ:
			pLDI->ReadMode = 0;
			pciscc_clear_rxpending(pLDI);
			Status = STATUS_SUCCESS;
			break;

		case PCISCC_BLOCK_READ:
			pLDI->ReadMode = 1;
			Status = STATUS_SUCCESS;
			break;

		default:
			Status = STATUS_NOT_IMPLEMENTED;
			break;
	}
	KeReleaseSpinLock(&pLDI->Lock,OldIrql);

	pIrp->IoStatus.Status = Status;
	pIrp->IoStatus.Information = Result;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return Status;
}

/* unload driver */
VOID pciscc_unload(
	IN PDRIVER_OBJECT DriverObject
	)
{
	PLOCAL_DEVICE_INFO pLDI;
	UNICODE_STRING Win32DeviceName;

	/* Find our global data */
	pLDI = (PLOCAL_DEVICE_INFO)DriverObject->DeviceObject->DeviceExtension;

	/* Stop chip activity */
	pciscc_chip_close(pLDI);

	/* Release hardware resources */
	pciscc_free_resources(DriverObject);

	/* Assume all handles are closed down. */
	RtlInitUnicodeString(&Win32DeviceName, PCISCC_W32_NAME);
	IoDeleteSymbolicLink(&Win32DeviceName);
	IoDeleteDevice(DriverObject->DeviceObject);
}

/* pending IRP cancel routine */
VOID pciscc_cancel(
	IN PDEVICE_OBJECT pDO,
	IN PIRP pIrp
	)
{
	PLOCAL_DEVICE_INFO pLDI = (PLOCAL_DEVICE_INFO)pDO->DeviceExtension;
	KIRQL OldIrql;

	IoReleaseCancelSpinLock(pIrp->CancelIrql);

	KeAcquireSpinLock(&pLDI->Lock,&OldIrql);
    if (!IsListEmpty(&pIrp->Tail.Overlay.ListEntry))
	{
		RemoveEntryList(&pIrp->Tail.Overlay.ListEntry);
		pIrp->IoStatus.Information = 0;
		pIrp->IoStatus.Status = STATUS_CANCELLED;
		IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	}
	KeReleaseSpinLock(&pLDI->Lock,OldIrql);
}

⌨️ 快捷键说明

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