📄 dispatch.cpp
字号:
/******************************************************************************
* * File Name:
* * Dispatch.cpp
* * Description:
* * This file routes incoming I/O Request packets.
* * 该文件是处理IRP的。
* * Revision History:
* * 03-3-02 : PDC1000 v1.00
*******************************************************************************/
#include "PDC1000.h"
#include "Ioctl.h"
/******************************************************************************
*
* Function : DispatchCreate
*
* Description: Handle IRP_MJ_CREATE, which allows applications to open handles
* to our device, 相应的是函数CreateFile().
*
******************************************************************************/
NTSTATUS DispatchCreate(IN PDEVICE_OBJECT fdo,
IN PIRP pIrp)
{ //DispatchCreate
DebugPrint("PDC1000: CreateFile.");
//可以在此,做一些初始化工作
return CompleteRequestInfo(pIrp, STATUS_SUCCESS,0);
} //DispatchCreate
/******************************************************************************
*
* Function : DispatchCleanup
*
* Description: Handle the IRP_MJ_CLEANUP IRP.
* 在驱动程序被暂停或卸载的时候,需要将IRP栈内所有的IRP清除掉。
******************************************************************************/
NTSTATUS DispatchCleanup(IN PDEVICE_OBJECT fdo,
IN PIRP pIrp)
{ //DispatchCleanup
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
KIRQL OldIrql;
DebugPrintMsg("DispatchCleanup Start.");
IoAcquireCancelSpinLock(&OldIrql);
// Cancel all IRPs in the I/O Manager maintained queue in device object
PKDEVICE_QUEUE_ENTRY QueueEntry;
//清除所有的IRP
while( (QueueEntry=KeRemoveDeviceQueue(&fdo->DeviceQueue)) != NULL)
{
PIRP CancelIrp = CONTAINING_RECORD( QueueEntry, IRP, Tail.Overlay.DeviceQueueEntry);
CancelIrp->Cancel = TRUE;
CancelIrp->CancelIrql = OldIrql;
CancelIrp->CancelRoutine = NULL;
IoReleaseCancelSpinLock(OldIrql);
DebugPrint("WdmIoDispatchCleanup: Cancelling %x %I",CancelIrp,CancelIrp);
UnlockDevice(pdx);
CancelIrp->IoStatus.Status = STATUS_CANCELLED;
CancelIrp->IoStatus.Information = 0;
IoCompleteRequest(CancelIrp,IO_NO_INCREMENT);
IoAcquireCancelSpinLock(&OldIrql);
}
IoReleaseCancelSpinLock(OldIrql);
return CompleteRequestInfo(pIrp,STATUS_SUCCESS,0);
} //DispatchCleanup
/************************************************************************
*
* Function : DispatchClose
*
* Description: Handle IRP_MJ_CLOSE, which allows applications to close handles
* to our device,相应的是函数CloseHandle().
*
******************************************************************************/
NTSTATUS DispatchClose(IN PDEVICE_OBJECT fdo,
IN PIRP pIrp)
{ //DispatchClose
DebugPrint("PDC1000: CloseFile.");
//进行处理
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
pdx->pWaitEvent = NULL;
pdx->bSetWaitEvent = NULL;
return CompleteRequestInfo(pIrp,STATUS_SUCCESS,0);
} //DispatchClose
/******************************************************************************
*
* Function : DispatchRead
*
* Description: Handle IRP_MJ_READ, which is not implemented by this driver
* ReadFile
******************************************************************************/
NTSTATUS DispatchRead(IN PDEVICE_OBJECT fdo,
IN PIRP pIrp)
{ //DispatchRead
DebugPrint("Read Device Start.");
ULONG ReturnedValue;
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
ReturnedValue = 0; //sizeof(CAN_DATA_PACKET);
//将从硬件采集到的数据送给应用程序
//如果不能很快处理,将IRP进行串行化,交给StartIo处理。
DebugPrint("Read Device End.");
// Just complete the request
return CompleteRequestInfo(pIrp,status,ReturnedValue);
} //DispatchRead
/******************************************************************************
*
* Function : DispatchWrite
*
* Description: Handle the IRP_MJ_WRITE, which is not implemented by this driver
* WriteFile
******************************************************************************/
NTSTATUS DispatchWrite(IN PDEVICE_OBJECT fdo,
IN PIRP pIrp)
{ //DispatchWrite
DebugPrint("Write File Start.");
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
//将应用程序的数据送到硬件
//如果不能一次完成或者需要中断协助,将IRP串行化,交给StartIo处理
// IoMarkIrpPending(pIrp);
// IoStartPacket(fdo, pIrp, NULL, CancelIrp);
DebugPrint("Write File End.");
return STATUS_PENDING;
} //DispatchWrite
/******************************************************************************
*
* Function : DispatchSystemControl
*
* Description: The dispatch routine for WMI IRPs. It does nothing except
* forward the IRP to the next device in the stack.
*
******************************************************************************/
NTSTATUS DispatchSystemControl(IN PDEVICE_OBJECT fdo,
IN PIRP pIrp)
{ //DispatchSystemControl
DebugPrint("PDC1000: SystemControl.");
IoSkipCurrentIrpStackLocation(pIrp);
return IoCallDriver(((DEVICE_EXTENSION *)fdo->DeviceExtension)->pLowerDeviceObject,
pIrp);
} //DispatchSystemControl
/******************************************************************************
*
* Function : DispatchIoControl
*
* Description: Processes the IOCTL IRPs sent to this device.
*
* Note : The Fast Mutex used in this routine is left here because
* some multi-CPU systems hang if it is removed. As of this time
* the cause for this is unknown. Once the cause is determined,
* the Fast Mutex will most likely be removed in a future release.
* Performance may improve slightly once it is removed since the
* DPC_LEVEL won't continuously need to go between PASSIVE and APC.
*
******************************************************************************/
NTSTATUS DispatchIoControl(IN PDEVICE_OBJECT fdo,
IN PIRP pIrp)
{ //DispatchIoControl
ULONG i;
NTSTATUS status;
PDEVICE_EXTENSION pdx;
PIO_STACK_LOCATION pIrpStack;
ULONG ReturnedValue;
ULONG PdcAddress; //The base address of PDC1000
pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
// Assume a successful return status
status = STATUS_SUCCESS;
// Lock device to record usage
LockDevice(pdx);
DebugPrint("DeviceIoControl Start.");
// Handle the PDC1000 specific message
//处理DeviceIoControl。
switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode)
{ //PDC1000
case IOCTL_PDC1000_REGISTER_EVENT: //注册Event变量
status = ObReferenceObjectByHandle(*(PHANDLE)pIrp->AssociatedIrp.SystemBuffer,
EVENT_MODIFY_STATE, *ExEventObjectType,
pIrp->RequestorMode, (PVOID*)&pdx->pWaitEvent, NULL);
if (!NT_SUCCESS(status))
{
pdx->bSetWaitEvent = FALSE;
DebugPrint("WARNNING - ObReferenceObjectByHandle failed");
}
else
{
pdx->bSetWaitEvent = TRUE;
DebugPrint("OK - ObReferenceObjectByHandle succeed");
}
ReturnedValue = 0;
break;
case IOCTL_PDC1000_UNREGISTER_EVENT: //反注册Event变量
pdx->pWaitEvent = NULL;
pdx->bSetWaitEvent = FALSE;
ReturnedValue = 0;
break;
case IOCTL_PDC1000_READ_DATA:
unsigned char Num,Buffer;
PdcAddress = (ULONG)pdx->PdcMemBase;
RtlCopyMemory(&Num, pIrp->AssociatedIrp.SystemBuffer, 1);
DebugPrint("Input Value is %x.",Num);
Buffer = READ_REGISTER_UCHAR((unsigned char *)(PdcAddress + Num));
DebugPrint("Read Data Value is %x.",Buffer);
RtlCopyMemory( pIrp->AssociatedIrp.SystemBuffer,&Buffer,1);
ReturnedValue = 1;
break;
case IOCTL_PDC1000_WRITE_DATA:
unsigned char WriteBuffer[2];
PdcAddress = (ULONG)pdx->PdcMemBase;
RtlCopyMemory(WriteBuffer, pIrp->AssociatedIrp.SystemBuffer, 2);
WRITE_REGISTER_UCHAR((unsigned char *)(PdcAddress + WriteBuffer[0]), WriteBuffer[1]);
DebugPrint("Write Data Value is %x.", WriteBuffer[1]);
ReturnedValue = 0;
break;
case IOCTL_PDC1000_SELECT_8155MIO:
//通过PCI9052的User0,进行选择
unsigned char Selected;
ULONG Address;
ULONG TempData;
Address = (ULONG)((PDEVICE_EXTENSION)pdx)->MemBase;
RtlCopyMemory(&Selected, pIrp->AssociatedIrp.SystemBuffer, 1);
TempData = READ_REGISTER_ULONG((ULONG *)(Address + 0x50));
if (Selected == 0x00)
{
TempData &= 0xfffffffa;
}
else if(Selected == 0x01)
{
TempData |= 0x00000006;
}
WRITE_REGISTER_ULONG((ULONG *)(Address + 0x50), TempData);
ReturnedValue = 0;
break;
default:
break;
}
UnlockDevice(pdx);
DebugPrint("DeviceIoControl End.");
if (status == STATUS_PENDING)
return STATUS_PENDING;
return CompleteRequestInfo(pIrp,status,ReturnedValue);
} //DispatchIoControl
/******************************************************************************
*
* Function : StartIo
*
* Description: The StartIo Service Routine for PDC1000.
*
******************************************************************************/
VOID StartIo(IN PDEVICE_OBJECT fdo,
IN PIRP pIrp)
{ //StartIo
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
DebugPrint("StartIo Start.");
NTSTATUS status = STATUS_SUCCESS;
if (!LockDevice(pdx))
{
CompleteRequest(pIrp, STATUS_DELETE_PENDING);
}
// Switch on the IRP major function code
switch(pIrpStack->MajorFunction)
{
case IRP_MJ_WRITE:
pdx->TransmitIrpStatus = STATUS_SUCCESS;
break;
default:
status = STATUS_NOT_SUPPORTED;
break;
}
// Complete this IRP
if(pIrp->Cancel)
status = STATUS_CANCELLED;
// Remove cancel routine
KIRQL OldIrql;
IoAcquireCancelSpinLock( &OldIrql);
IoSetCancelRoutine(pIrp, NULL);
IoReleaseCancelSpinLock(OldIrql);
// Unlock device, complete IRP and start next
UnlockDevice(pdx);
DebugPrint("StartIo End.");
CompleteRequestInfo(pIrp, status, 10);
IoStartNextPacket(fdo, TRUE);
} //StartIo
/******************************************************************************
*
* Function : CancelIrp
*
* Description: The CancelIrp Service Routine for PDC1000.
*
******************************************************************************/
VOID CancelIrp(IN PDEVICE_OBJECT fdo,
IN PIRP pIrp)
{ //CancelIrp
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
DebugPrint("WdmIoCancelIrp: Cancelling %x %I",pIrp,pIrp);
if (pIrp == fdo->CurrentIrp)
{
DebugPrintMsg("CancelIrp: IRP running in StartIo");
// IRP is being processed by IoStartIo.
// Irp->Cancel flag already set.
// IoStartIo will detect Cancel flag and cancel IRP in due course
IoReleaseCancelSpinLock(pIrp->CancelIrql);
}
else
{
DebugPrintMsg("CancelIrp: IRP in StartIo queue");
// IRP is still in StartIo device queue.
// Just dequeue and cancel it. No need to start next IRP.
BOOLEAN dequeued = KeRemoveEntryDeviceQueue(
&fdo->DeviceQueue,
&pIrp->Tail.Overlay.DeviceQueueEntry);
IoReleaseCancelSpinLock(pIrp->CancelIrql);
if (dequeued)
{
UnlockDevice(pdx);
CompleteRequest(pIrp, STATUS_CANCELLED);
}
}
} //CancelIrp
/******************************************************************************
*
* Function : OnInterrupt
*
* Description: The Interrupt Service Routine for the PLX device.
* //中断处理函数
* 注意:中断处理函数工作在很高地级别,需要慎重处理
******************************************************************************/
BOOLEAN OnInterrupt(IN PKINTERRUPT pInterrupt,
IN PDEVICE_EXTENSION pdx)//IN PVOID pdx)
{ //OnInterrupt
ULONG RegisterValue;
ULONG Address,CanAddress;
UCHAR cInterrupt;
UCHAR cCommand;
Address = (ULONG)((PDEVICE_EXTENSION)pdx)->MemBase;
// Read interrupt status register
RegisterValue = READ_REGISTER_ULONG((ULONG *)(Address + 0x4c));
// Check for master PCI interrupt enable
if ((RegisterValue & 0x40) == 0)
{
return FALSE; //如果不是该设备的中断,必须返回FALSE,否则系统会出问题。
}
// Check to see if an interrupt is active
if (RegisterValue & ((0x4) | (0x20))) //Only LINTi1 is used.
{
if (pdx->pWaitEvent != NULL)
KeSetEvent(pdx->pWaitEvent, 0, FALSE); //通知应用程序,中断的到来
//在此,处理中断
//如果不能很快处理,则交给Dpc处理,如下:
/* PDEVICE_OBJECT fdo = ((PDEVICE_EXTENSION)pdx)->pDeviceObject;
if (fdo != NULL)
{
PIRP pIrp = fdo->CurrentIrp;
if (pIrp != NULL)
{
IoRequestDpc(fdo, pIrp, (PVOID)pdx);
}
}
*/
return TRUE; //如果是该设备的中断,必须返回TRUE。
}
// If we reach here, then the interrupt is not ours
return FALSE;
} //OnInterrupt
/******************************************************************************
*
* Function : DpcForIsr
*
* Description: This routine will be triggered by the ISR to service an interrupt.
*
* Note : The 9052 supports Edge-triggerable interrupts as well as level
* triggered interrupts. The 9050 only supports level triggered
* interrupts. The interrupt masking code below handles both cases.
* If the chip is a 9050, the same code is used but should work
* ok since edge triggerable interrupts will always be disabled.
*
******************************************************************************/
VOID DpcForIsr(IN PKDPC pDpc,
IN PDEVICE_OBJECT fdo,
IN PIRP pIrp,
IN PDEVICE_EXTENSION pdx)
{ //OnInterrupt DpcForIsr
DebugPrintMsg("DpcForIsr Start.");
if (pIrp->Cancel)
pdx->TransmitIrpStatus = STATUS_CANCELLED;
KIRQL OldIrql;
PIRP Irp = fdo->CurrentIrp;
//Remove Cancel Routine.
IoAcquireCancelSpinLock(&OldIrql);
IoSetCancelRoutine(pIrp,NULL);
IoReleaseCancelSpinLock(OldIrql);
UnlockDevice(pdx);
DebugPrintMsg("DpcForIsr End.");
IoStartNextPacket(fdo, FALSE);
} //OnInterrupt DpcForIsr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -