📄 dispatch.cpp
字号:
/******************************************************************************
* * File Name:
* * Dispatch.cpp
* * Description:
* * This file routes incoming I/O Request packets.
* * 该文件是处理IRP的。
* * Revision History:
* * 03-3-02 : PDC4000 v1.00
*******************************************************************************/
#include "PDC4000.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
KdPrint((DBG_NAME "CreateFile.\n"));
//可以在此,做一些初始化工作
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;
KdPrint((DBG_NAME "DispatchCleanup Start.\n"));
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);
KdPrint((DBG_NAME "WdmIoDispatchCleanup: Cancelling %x %I\n", 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
KdPrint((DBG_NAME "CloseFile.\n"));
//进行处理
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
KdPrint((DBG_NAME "Read Device Start.\n"));
ULONG ReturnedValue;
NTSTATUS status = STATUS_SUCCESS;
// PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
// ReturnedValue = 0;
//将从硬件采集到的数据送给应用程序, 如果不能很快处理,将IRP进行串行化,交给StartIo处理。
//Transfer data from local mem by using SGL DMA.
IoMarkIrpPending(pIrp);
IoStartPacket(fdo, pIrp, NULL, CancelIrp);
KdPrint((DBG_NAME "Read Device End.\n"));
return STATUS_PENDING;
// 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
KdPrint((DBG_NAME "Write File Start.\n"));
// PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
//将应用程序的数据送到硬件, 将IRP串行化,交给StartIo处理
//Transfer the data to local mem by using SGL DMA.
IoMarkIrpPending(pIrp);
IoStartPacket(fdo, pIrp, NULL, CancelIrp);
KdPrint((DBG_NAME "Write File End.\n"));
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
KdPrint((DBG_NAME "SystemControl.\n"));
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 lReturnedValue;
ULONG lPdcAddress; //The base address of PDC4000
RETURN_CODE rc;
ULONG lDmaMode;
DMA_CHANNEL_DESCRIPTION dcd;
DMA_TRANSFER_ELEMENT dte;
pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
// Assume a successful return status
status = STATUS_SUCCESS;
// Lock device to record usage
LockDevice(pdx);
KdPrint((DBG_NAME "DeviceIoControl Start.\n"));
// Handle the PDC4000 specific message
//处理DeviceIoControl。
switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode)
{ //PDC4000
case IOCTL_PDC4000_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;
KdPrint((DBG_NAME "WARNNING - ObReferenceObjectByHandle failed\n"));
}
else
{
pdx->bSetWaitEvent = TRUE;
KdPrint((DBG_NAME "OK - ObReferenceObjectByHandle succeed\n"));
}
lReturnedValue = 0;
break;
case IOCTL_PDC4000_UNREGISTER_EVENT: //反注册Event变量
pdx->pWaitEvent = NULL;
pdx->bSetWaitEvent = FALSE;
lReturnedValue = 0;
break;
case IOCTL_PDC4000_READ_DATA:
ULONG Num, Buffer;
lPdcAddress = (ULONG)pdx->PdcMemBase0;
RtlCopyMemory(&Num, pIrp->AssociatedIrp.SystemBuffer, sizeof(ULONG));
KdPrint((DBG_NAME "Input Value is %x.", Num));
Buffer = READ_REGISTER_UCHAR((unsigned char *)(lPdcAddress + Num));
KdPrint((DBG_NAME "Read Data Value is %x.\n", Buffer));
RtlCopyMemory( pIrp->AssociatedIrp.SystemBuffer, &Buffer, sizeof(ULONG));
lReturnedValue = sizeof(ULONG);
break;
case IOCTL_PDC4000_WRITE_DATA:
ULONG dwWriteBuffer[2];
lPdcAddress = (ULONG)pdx->PdcMemBase0;
RtlCopyMemory(dwWriteBuffer, pIrp->AssociatedIrp.SystemBuffer, 2 * sizeof(ULONG));
WRITE_REGISTER_UCHAR((unsigned char *)(lPdcAddress + dwWriteBuffer[0]), (CHAR)dwWriteBuffer[1]);
KdPrint((DBG_NAME "Write Data Value is %x.\n", dwWriteBuffer[1]));
lReturnedValue = 0;
break;
case IOCTL_PDC4000_BLOCK_DMA_PCI_TO_LOCAL:
ULONG lDMAPciToLocalTransferSize;
lDMAPciToLocalTransferSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;//0x10;
//Copy the data to the Common buffer.
RtlCopyMemory(pdx->DmaInfo[0].vaCommonBuffer, pIrp->AssociatedIrp.SystemBuffer, lDMAPciToLocalTransferSize);
KdPrint((DBG_NAME "The vaCommonBuffer is %X.\n", *(unsigned char *)(pdx->DmaInfo[0].vaCommonBuffer)));
lPdcAddress = (ULONG)pdx-> ;
/*
//自己操作Block DMA
lDmaMode = 0x20540;
WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_MODE), lDmaMode);
//PCI Address
WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_PCI_ADDR), pdx->DmaInfo[0].paCommonBuffer.LowPart);
//Local Address
WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_LOCAL_ADDR), 0);
//Transfer Size
WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_COUNT), lDMAPciToLocalTransferSize);
//DMA Descriptor Pointer
WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_DESC_PTR), 0x0);
//Initiate DMA Transfer
WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA_COMMAND_STAT), 0x3);
*/
dcd.BTERMInputEnable = 0;
dcd.DACChainLoad = 0;
dcd.DemandMode = 0;
dcd.DmaChannelPriority = Rotational;
dcd.DmaEOTPinEnable = 0;
dcd.DoneInterrputEnable = 1;
dcd.EnableTransferCountClear = 0; //For sgl DMA
dcd.FastSlowTerminateModeSelect = 0;
dcd.InternalWaitStates = 0;
dcd.InterrputSelect = 1;
dcd.LocalAddressingMode = 0;
dcd.LocalBurstEnable = 1;
dcd.LocalBusWidth = 0;
dcd.MemoryWriteAndInvalidateMode = 0;
dcd.ReadyInputEnable = 1;
dcd.ScatterGatherMODE = 0;
//DMA threshold
dcd.LocalToPciAlmostEmpty = 0;
dcd.LocalToPciAlmostFull = 0;
dcd.PciToLocalAlmostEmpty = 0;
dcd.PciToLocalAlmostFull = 0;
pdx->DmaInfo[0].bWriteToLocal = TRUE;
rc = DmaOpenBlockChannel(pdx, 0, &dcd);
if (rc != RC_SUCCESS)
{
KdPrint((DBG_NAME "Can't DmaOpenBlockChannel.\n"));
lReturnedValue = 0;
UnlockDevice(pdx);
return CompleteRequestInfo(pIrp, status, lReturnedValue);
}
KdPrint((DBG_NAME "Had Open DMA Channel.\n"));
//Set Address and Transfer Size.
dte.lLocalAddress = 0;
dte.lPciAddress = pdx->DmaInfo[0].paCommonBuffer.LowPart;
dte.lPciDualAddress = 0;
dte.lTransferSize = lDMAPciToLocalTransferSize; //
dte.DescriptorLocation = 0;
dte.DirectionOfTransfer = 0;
dte.EndOfChain = 0;
dte.InterruptAfterTerminalCount = 0;
dte.NextDescriptorAddress = 0;
KdPrint((DBG_NAME "The lDMAPciToLocalTransferSize is 0x%X.\n", lDMAPciToLocalTransferSize));
rc = DmaBlockTransfer(pdx, 0, &dte);
if (rc != RC_SUCCESS)
{DmaBlockTransfer
KdPrint((DBG_NAME "Can't DmaBlockTransfer.\n"));
}
KdPrint((DBG_NAME "IOCTL_PDC4000_BLOCK_DMA_PCI_TO_LOCAL End.\n"));
break;
case IOCTL_PDC4000_BLOCK_DMA_LOCAL_TO_PCI:
IoMarkIrpPending(pIrp);
IoStartPacket(fdo, pIrp, NULL, CancelIrp);
/* //直接操作Block Dma
lDmaMode = 0x40540;
WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_MODE), lDmaMode);
//PCI Address
WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_PCI_ADDR), pdx->DmaInfo[0].paCommonBuffer.LowPart);
//Local Address
WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_LOCAL_ADDR), 0);
//Transfer Size
WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_COUNT), lDMALocalToPciTransferSize);
//DMA Descriptor Pointer
WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA0_DESC_PTR), 0x8);
//Initiate DMA Transfer
WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + PCI9054_DMA_COMMAND_STAT), 0x3);
KdPrint((DBG_NAME "The vaCommonBuffer is %X.\n", *(unsigned char *)(pdx->DmaInfo[0].vaCommonBuffer)));
//Copy the data to the Common buffer.
RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer, pdx->DmaInfo[0].vaCommonBuffer, lDMALocalToPciTransferSize);
*/
/* //通过函数调用
ULONG lDMALocalToPciTransferSize;
lDMALocalToPciTransferSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;//0x100;
lPdcAddress = (ULONG)pdx->LocalRegisterMemBase;
dcd.BTERMInputEnable = 0;
dcd.DACChainLoad = 0;
dcd.DemandMode = 0;
dcd.DmaChannelPriority = Rotational;
dcd.DmaEOTPinEnable = 0;
dcd.DoneInterrputEnable = 1;
dcd.EnableTransferCountClear = 0; //For sgl DMA
dcd.FastSlowTerminateModeSelect = 0;
dcd.InternalWaitStates = 0;
dcd.InterrputSelect = 1;
dcd.LocalAddressingMode = 0;
dcd.LocalBurstEnable = 1;
dcd.LocalBusWidth = 0;
dcd.MemoryWriteAndInvalidateMode = 0;
dcd.ReadyInputEnable = 1;
dcd.ScatterGatherMODE = 0;
//DMA threshold
dcd.LocalToPciAlmostEmpty = 0;
dcd.LocalToPciAlmostFull = 0;
dcd.PciToLocalAlmostEmpty = 0;
dcd.PciToLocalAlmostFull = 0;
pdx->DmaInfo[0].bWriteToLocal = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -