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

📄 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
	)
{
	UNICODE_STRING NtDeviceName;
	UNICODE_STRING Win32DeviceName;

	// 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->MajorFunction[IRP_MJ_PNP]				= pciscc_pnp;
    DriverObject->MajorFunction[IRP_MJ_POWER]			= pciscc_power;
    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL]	= pciscc_sysctl;
	DriverObject->DriverUnload							= pciscc_unload;
    DriverObject->DriverExtension->AddDevice			= pciscc_add_device;

    return STATUS_SUCCESS;
}

NTSTATUS pciscc_add_device(
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT PhysicalDeviceObject
    )
{
	NTSTATUS Status;
	PDEVICE_OBJECT DeviceObject;
	PLOCAL_DEVICE_INFO pLDI;
	UNICODE_STRING NtDeviceName;
	UNICODE_STRING Win32DeviceName;
	
	/* 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);
	IoInitializeRemoveLock(&pLDI->RemoveLock,PCISCC_TAG,1,5);

	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;
	}

	/* Interface to lower driver */
	pLDI->NextLowerDrv = IoAttachDeviceToDeviceStack(	DeviceObject,
														PhysicalDeviceObject);
	if (pLDI->NextLowerDrv == NULL) {
		IoDeleteSymbolicLink(&Win32DeviceName);
		IoDeleteDevice(DeviceObject);
		Status = STATUS_NO_SUCH_DEVICE;
	}

	/* Device init complete */
	DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
	return Status;
}

NTSTATUS pciscc_pnp(
    IN PDEVICE_OBJECT pDO,
    IN PIRP pIrp
    )
{
    PIO_STACK_LOCATION	pIrpStack;
	UNICODE_STRING		Win32DeviceName;
    KEVENT				Event;
    PLOCAL_DEVICE_INFO	pLDI;
	NTSTATUS			Status = STATUS_SUCCESS;

	/* get control parameter */
	pLDI = (PLOCAL_DEVICE_INFO)pDO->DeviceExtension;
	pIrpStack = IoGetCurrentIrpStackLocation(pIrp);

	/* acquire remove lock*/
	Status = IoAcquireRemoveLock (&pLDI->RemoveLock, pIrp);
	if (!NT_SUCCESS (Status)) {
		pIrp->IoStatus.Status = Status;
		IoCompleteRequest(pIrp, IO_NO_INCREMENT);
		return Status;
	}

	switch (pIrpStack->MinorFunction) {
	case IRP_MN_START_DEVICE:
		/* The device is starting */
		IoCopyCurrentIrpStackLocationToNext(pIrp);
		KeInitializeEvent(&Event,NotificationEvent,FALSE);

		IoSetCompletionRoutine(pIrp,(PIO_COMPLETION_ROUTINE) pciscc_complete, 
                               &Event,TRUE,TRUE,TRUE);

		Status = IoCallDriver(pLDI->NextLowerDrv, pIrp);
		if (Status == STATUS_PENDING)
			KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
		if (NT_SUCCESS(Status) && NT_SUCCESS(pIrp->IoStatus.Status))
		{
			Status = pciscc_2k_config(pDO, pIrp);
			if (NT_SUCCESS (Status))
				Status = pciscc_chip_open(pLDI);
        }
		pIrp->IoStatus.Status = Status;
		IoCompleteRequest(pIrp, IO_NO_INCREMENT);
        break;

    case IRP_MN_QUERY_STOP_DEVICE:
    case IRP_MN_STOP_DEVICE:
		pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
		IoCompleteRequest(pIrp, IO_NO_INCREMENT);
		break;

    case IRP_MN_QUERY_REMOVE_DEVICE:
    case IRP_MN_CANCEL_REMOVE_DEVICE: 
	case IRP_MN_CANCEL_STOP_DEVICE:
		pIrp->IoStatus.Status = STATUS_SUCCESS;
		IoSkipCurrentIrpStackLocation(pIrp);
		Status = IoCallDriver(pLDI->NextLowerDrv, pIrp);
		break;

    case IRP_MN_SURPRISE_REMOVAL:
		/* Stop chip activity */
		pciscc_chip_close(pLDI);

		pIrp->IoStatus.Status = STATUS_SUCCESS;
		IoSkipCurrentIrpStackLocation(pIrp);
		Status = IoCallDriver(pLDI->NextLowerDrv, pIrp);
		break;
        
    case IRP_MN_REMOVE_DEVICE:
		/* Stop chip activity */
		pciscc_chip_close(pLDI);

		RtlInitUnicodeString(&Win32DeviceName, PCISCC_W32_NAME);
		IoDeleteSymbolicLink(&Win32DeviceName);
		IoReleaseRemoveLockAndWait(&pLDI->RemoveLock, pIrp);

		pIrp->IoStatus.Status = STATUS_SUCCESS;
		IoSkipCurrentIrpStackLocation(pIrp);
		Status = IoCallDriver(pLDI->NextLowerDrv, pIrp);

		IoDetachDevice(pLDI->NextLowerDrv);
		IoDeleteDevice(pDO);
		return Status;
                
    default:
        //
        // Please see PnP documentation for use of these IRPs.
        //
        IoSkipCurrentIrpStackLocation (pIrp);
        Status = IoCallDriver(pLDI->NextLowerDrv, pIrp);
        break;
    }

    IoReleaseRemoveLock(&pLDI->RemoveLock, pIrp);       
    return Status;
}

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

	PoStartNextPowerIrp(pIrp);
	IoSkipCurrentIrpStackLocation(pIrp);
	return PoCallDriver(pLDI->NextLowerDrv, pIrp);
}

NTSTATUS pciscc_sysctl(
	IN PDEVICE_OBJECT pDO,
	IN PIRP pIrp
	)
{
	PLOCAL_DEVICE_INFO pLDI;

	pLDI = (PLOCAL_DEVICE_INFO)pDO->DeviceExtension;
	IoSkipCurrentIrpStackLocation(pIrp);
	return IoCallDriver(pLDI->NextLowerDrv,pIrp);
}

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);

⌨️ 快捷键说明

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