📄 pciscc_drv.c
字号:
#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 + -