📄 genport.c
字号:
Return Value:
STATUS_SUCCESS if the IRP was processed successfully, otherwise an error
indicating the reason for failure.
--*/
{
PLOCAL_DEVICE_INFO pLDI;
PIO_STACK_LOCATION pIrpStack;
NTSTATUS Status;
PAGED_CODE();
pIrp->IoStatus.Information = 0;
pLDI = (PLOCAL_DEVICE_INFO)pDO->DeviceExtension; // Get local info struct
// DebugPrint (("Entered GpdDispatch\n"));
Status = IoAcquireRemoveLock (&pLDI->RemoveLock, pIrp);//在处理IRP请求之前,先上锁,以免被其他程序将该请求删除,引起冲突
//与其对应的解锁操作是IoReleaseRemoveLock(&pLDI->RemoveLock, pIrp);
if (!NT_SUCCESS (Status)) {
DebugPrint ((">>> IoAcquireRemoveLock Failed! %X\n",Status));
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = Status;
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
return Status;
}
if (!pLDI->Started) {//如果所指定的设备还没有被“start”,将报“STATUS_DEVICE_NOT_READY”状态错误
//
// We fail all the IRPs that arrive before the device is started.
//
pIrp->IoStatus.Status = Status = STATUS_DEVICE_NOT_READY;
IoCompleteRequest(pIrp, IO_NO_INCREMENT );
IoReleaseRemoveLock(&pLDI->RemoveLock, pIrp);
DebugPrint ((">>> !pLDI->Started ! STATUS_DEVICE_NOT_READY\n"));
return Status;
}
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);//从IRP栈内取一个包,准备处理
// Dispatch based on major fcn code.
switch (pIrpStack->MajorFunction)
{
case IRP_MJ_CREATE:
DebugPrint ((">>> IRP_MJ_CREATE\n"));
Status = STATUS_SUCCESS;
break;
case IRP_MJ_CLOSE:
// We don't need any special processing on open/close so we'll
// just return success.
DebugPrint ((">>> IRP_MJ_CLOSE\n"));
Status = STATUS_SUCCESS;
break;
case IRP_MJ_DEVICE_CONTROL:
// Dispatch on IOCTL
switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode)//pIrpStack->MajorFunction 如果是 IRP_MJ_DEVICE_CONTROL
//则需要查看 pIrpStack->Parameters.DeviceIoControl.IoControlCode 的代码的值,再分别进行处理
{
case IOCTL_GPD_READ_PORT_UCHAR:
case IOCTL_GPD_READ_PORT_USHORT:
case IOCTL_GPD_READ_PORT_ULONG:
// DebugPrint ((">>> IOCTL_GPD_READ_PORT_UCHAR\n"));
Status = GpdIoctlReadPort(
pLDI,
pIrp,
pIrpStack,
pIrpStack->Parameters.DeviceIoControl.IoControlCode
);
break;
case IOCTL_GPD_WRITE_PORT_UCHAR:
case IOCTL_GPD_WRITE_PORT_USHORT:
case IOCTL_GPD_WRITE_PORT_ULONG:
// DebugPrint ((">>> IOCTL_GPD_WRITE_PORT_UCHAR TestIsr = %d\n",pLDI->TestIsr));
Status = GpdIoctlWritePort(
pLDI,
pIrp,
pIrpStack,
pIrpStack->Parameters.DeviceIoControl.IoControlCode
);
break;
case IOCTL_RESET://设置串口波特率,和工作方式
// DebugPrint ((">>> IOCTL_RESET \n"));
Status = SerialReset(pDO,pIrp,pIrpStack);
break;
case IOCTL_SET_BAUD_MODE://设置串口波特率,和工作方式
// DebugPrint ((">>> IOCTL_SET_BAUD_MODE \n"));
Status = SerialSetBaud(pDO,pIrp,pIrpStack);
break;
case IOCTL_READ_DATA_0://读串口0的数据
// DebugPrint ((">>> IOCTL_READ_DATA \n"));
Status = SerialReadData(pDO,pIrp,pIrpStack,0);
break;
case IOCTL_WRITE_DATA_0://写串口0的数据
// DebugPrint ((">>> IOCTL_WRITE_DATA \n"));
Status = SerialWriteData(pDO,pIrp,pIrpStack,0);
break;
case IOCTL_READ_DATA_1://读串口1的数据
// DebugPrint ((">>> IOCTL_READ_DATA_1 \n"));
Status = SerialReadData(pDO,pIrp,pIrpStack,1);
break;
case IOCTL_WRITE_DATA_1://写串口1的数据
// DebugPrint ((">>> IOCTL_WRITE_DATA_1 \n"));
Status = SerialWriteData(pDO,pIrp,pIrpStack,1);
break;
////////////////////////////////
case IOCTL_READ_DATA_2://读串口2的数据
// DebugPrint ((">>> IOCTL_READ_DATA_2 \n"));
Status = SerialReadData(pDO,pIrp,pIrpStack,2);
break;
case IOCTL_WRITE_DATA_2://写串口2的数据
// DebugPrint ((">>> IOCTL_WRITE_DATA_2 \n"));
Status = SerialWriteData(pDO,pIrp,pIrpStack,2);
break;
case IOCTL_READ_DATA_3://读串口3的数据
// DebugPrint ((">>> IOCTL_READ_DATA_3 \n"));
Status = SerialReadData(pDO,pIrp,pIrpStack,3);
break;
case IOCTL_WRITE_DATA_3://写串口3的数据
// DebugPrint ((">>> IOCTL_WRITE_DATA_3 \n"));
Status = SerialWriteData(pDO,pIrp,pIrpStack,3);
//njh20080118
case IOCTL_WRITE_SWITCH://开关量输出
DebugPrint ((">>> enter IOCTL_WRITE_SWITCH branch \n"));
Status = WriteSwitch(pDO,pIrp,pIrpStack);
break;
default:
Status = STATUS_INVALID_PARAMETER;
}
break;
default:
Status = STATUS_NOT_IMPLEMENTED;
break;
}
// We're done with I/O request. Record the status of the I/O action.
pIrp->IoStatus.Status = Status;
// Don't boost priority when returning since this took little time.
IoCompleteRequest(pIrp, IO_NO_INCREMENT );
IoReleaseRemoveLock(&pLDI->RemoveLock, pIrp);
return Status;
}
//
BOOLEAN
GpdInterruptService(
IN PKINTERRUPT Interrupt,
IN PVOID Extension
)
/*++
Routine Description:
This routine services the interrupt for the parallel port.
This routine will call out to all of the interrupt routines
that connected with this device via
IOCTL_INTERNAL_PARALLEL_CONNECT_INTERRUPT in order until
one of them returns TRUE.
Arguments:
Interrupt - Supplies the interrupt object.
Extension - Supplies the device extension.
Return Value:
FALSE - The interrupt was not handled.
TRUE - The interrupt was handled.
--*/
{
((PLOCAL_DEVICE_INFO)Extension)->TestIsr++;
return(TRUE);
}
//
NTSTATUS
GpdIoctlReadPort(
IN PLOCAL_DEVICE_INFO pLDI,
IN PIRP pIrp,
IN PIO_STACK_LOCATION IrpStack,
IN ULONG IoctlCode )
/*++
Routine Description:
This routine processes the IOCTLs which read from the ports.
Arguments:
pLDI - our local device data
pIrp - IO request packet
IrpStack - The current stack location
IoctlCode - The ioctl code from the IRP
Return Value:
STATUS_SUCCESS -- OK
STATUS_INVALID_PARAMETER -- The buffer sent to the driver
was too small to contain the
port, or the buffer which
would be sent back to the driver
was not a multiple of the data size.
STATUS_ACCESS_VIOLATION -- An illegal port number was given.
--*/
{
// NOTE: Use METHOD_BUFFERED ioctls.
PULONG pIOBuffer; // Pointer to transfer buffer
// (treated as an array of longs).
ULONG InBufferSize; // Amount of data avail. from caller.
ULONG OutBufferSize; // Max data that caller can accept.
ULONG nPort; // Port number to read
ULONG DataBufferSize;
// PAGED_CODE();
// Size of buffer containing data from application
InBufferSize = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
// Size of buffer for data to be sent to application
OutBufferSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
// NT copies inbuf here before entry and copies this to outbuf after
// return, for METHOD_BUFFERED IOCTL's.
pIOBuffer = (PULONG)pIrp->AssociatedIrp.SystemBuffer;
// Check to ensure input buffer is big enough to hold a port number and
// the output buffer is at least as big as the port data width.
//
// DebugPrint ((">>> GpdIoctlReadPort 1\n"));
switch (IoctlCode)
{
case IOCTL_GPD_READ_PORT_UCHAR:
DataBufferSize = sizeof(UCHAR);
break;
case IOCTL_GPD_READ_PORT_USHORT:
DataBufferSize = sizeof(USHORT);
break;
case IOCTL_GPD_READ_PORT_ULONG:
DataBufferSize = sizeof(ULONG);
break;
default:
return STATUS_INVALID_PARAMETER;
}
// DebugPrint ((">>> GpdIoctlReadPort 2\n"));
if ( InBufferSize != sizeof(ULONG) || OutBufferSize < DataBufferSize )
{
return STATUS_INVALID_PARAMETER;
}
// Buffers are big enough.
nPort = *pIOBuffer; // Get the I/O port number from the buffer.
/* if (nPort >= pLDI->PortCount ||
(nPort + DataBufferSize) > pLDI->PortCount ||
(((ULONG_PTR)pLDI->PortBase + nPort) & (DataBufferSize - 1)) != 0)
{
return STATUS_ACCESS_VIOLATION; // It was not legal.
}*/
// DebugPrint ((">>> GpdIoctlReadPort 3\n"));
if (pLDI->PortMemoryType == 1)
{
// Address is in I/O space
switch (IoctlCode)
{
case IOCTL_GPD_READ_PORT_UCHAR:
*(PUCHAR)pIOBuffer = READ_PORT_UCHAR(
(PUCHAR)((ULONG_PTR)pLDI->PortBase + nPort) );
DebugPrint ((">>> ReadPort Port=0x%X Value=0x%X\n",
(PUCHAR)((ULONG_PTR)pLDI->PortBase + nPort),
*(PUCHAR)pIOBuffer));
break;
case IOCTL_GPD_READ_PORT_USHORT:
*(PUSHORT)pIOBuffer = READ_PORT_USHORT(
(PUSHORT)((ULONG_PTR)pLDI->PortBase + nPort) );
break;
case IOCTL_GPD_READ_PORT_ULONG:
*(PULONG)pIOBuffer = READ_PORT_ULONG(
(PULONG)((ULONG_PTR)pLDI->PortBase + nPort) );
break;
default:
return STATUS_INVALID_PARAMETER;
}
}
else if (pLDI->PortMemoryType == 0)
{
// Address is in Memory space
switch (IoctlCode)
{
case IOCTL_GPD_READ_PORT_UCHAR:
*(PUCHAR)pIOBuffer = READ_REGISTER_UCHAR(
(PUCHAR)((ULONG_PTR)pLDI->PortBase + nPort) );
DebugPrint ((">>> ReadMem Mem=0x%X Value=0x%X\n",
(PUCHAR)((ULONG_PTR)pLDI->PortBase + nPort),
*(PUCHAR)pIOBuffer));
break;
case IOCTL_GPD_READ_PORT_USHORT:
*(PUSHORT)pIOBuffer = READ_REGISTER_USHORT(
(PUSHORT)((ULONG_PTR)pLDI->PortBase + nPort) );
break;
case IOCTL_GPD_READ_PORT_ULONG:
*(PULONG)pIOBuffer = READ_REGISTER_ULONG(
(PULONG)((ULONG_PTR)pLDI->PortBase + nPort) );
break;
default:
return STATUS_INVALID_PARAMETER;
}
}
else
{
return STATUS_UNSUCCESSFUL;
}
//
// Indicate # of bytes read
//
pIrp->IoStatus.Information = DataBufferSize;
return STATUS_SUCCESS;
}
NTSTATUS
GpdIoctlWritePort(
IN PLOCAL_DEVICE_INFO pLDI,
IN PIRP pIrp,
IN PIO_STACK_LOCATION IrpStack,
IN ULONG IoctlCode
)
/*++
Routine Description:
This routine processes the IOCTLs which write to the ports.
Arguments:
pLDI - our local device data
pIrp - IO request packet
IrpStack - The current stack location
IoctlCode - The ioctl code from the IRP
Return Value:
STATUS_SUCCESS -- OK
STATUS_INVALID_PARAMETER -- The buffer sent to the driver
was too small to contain the
port, or the buffer which
would be sent back to the driver
was not a multiple of the data size.
STATUS_ACCESS_VIOLATION -- An illegal port number was given.
--*/
{
// NOTE: Use METHOD_BUFFERED ioctls.
PULONG pIOBuffer; // Pointer to transfer buffer
// (treated as array of longs).
ULONG InBufferSize ; // Amount of data avail. from caller.
ULONG nPort; // Port number to read or write.
ULONG Dat
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -