📄 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
)
{
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 + -