📄 dispatch.cpp
字号:
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);
}
//Set Address and Transfer Size.
dte.lLocalAddress = 0;
dte.lPciAddress = pdx->DmaInfo[0].paCommonBuffer.LowPart;
dte.lPciDualAddress = 0;
dte.lTransferSize = lDMALocalToPciTransferSize; //
dte.DescriptorLocation = 0;
dte.DirectionOfTransfer = 1;
dte.EndOfChain = 0;
dte.InterruptAfterTerminalCount = 0;
dte.NextDescriptorAddress = 0;
pdx->DmaInfo[0].lTransferedBytes = lDMALocalToPciTransferSize;
rc = DmaBlockTransfer(pdx, 0, &dte);
if (rc != RC_SUCCESS)
{
KdPrint((DBG_NAME "Can't DmaBlockTransfer.\n"));
}
lReturnedValue = lDMALocalToPciTransferSize;
*/
status = STATUS_PENDING;
break;
case IOCTL_PDC4000_READ_REG_DATA:
unsigned long lNumReg, lBufferReg;
lPdcAddress = (ULONG)pdx->LocalRegisterMemBase;
// KdPrint((DBG_NAME "The LocalRegisterMemBase is %x.\n", lPdcAddress));
RtlCopyMemory(&lNumReg, pIrp->AssociatedIrp.SystemBuffer, sizeof(ULONG));
KdPrint((DBG_NAME "Input Value is %x.\n", lNumReg));
lBufferReg = READ_REGISTER_ULONG((unsigned long *)(lPdcAddress + lNumReg));
KdPrint((DBG_NAME "Read Reg Data Value is %x.\n", lBufferReg));
RtlCopyMemory( pIrp->AssociatedIrp.SystemBuffer, &lBufferReg, sizeof(ULONG));
lReturnedValue = sizeof(ULONG);
break;
case IOCTL_PDC4000_WRITE_REG_DATA:
unsigned long lWriteBufferReg[2];
lPdcAddress = (ULONG)pdx->LocalRegisterMemBase;
RtlCopyMemory(lWriteBufferReg, pIrp->AssociatedIrp.SystemBuffer, sizeof(ULONG) * 2);
WRITE_REGISTER_ULONG((unsigned long *)(lPdcAddress + lWriteBufferReg[0]), lWriteBufferReg[1]);
KdPrint((DBG_NAME "Write Reg Data Value is %x.\n", lWriteBufferReg[1]));
lReturnedValue = 0;
break;
case IOCTL_PDC4000_BURST_READ_DATA:
unsigned char cNumBurst, cBufferBurst[16];
lPdcAddress = (ULONG)pdx->PdcMemBase0;
RtlCopyMemory(&cNumBurst, pIrp->AssociatedIrp.SystemBuffer, 1);
KdPrint((DBG_NAME "Input Value is %x.\n", cNumBurst));
READ_REGISTER_BUFFER_UCHAR((unsigned char *)(lPdcAddress + cNumBurst), cBufferBurst, 16);
KdPrint((DBG_NAME "Read Data Value is: \n"));
for (i = 0; i < 16; i ++)
{
KdPrint((DBG_NAME "[%d]: %X.\n", i, cBufferBurst[i]));
}
RtlCopyMemory( pIrp->AssociatedIrp.SystemBuffer, cBufferBurst, 16);
lReturnedValue = 16;
break;
case IOCTL_PDC4000_BURST_WRITE_DATA:
unsigned char cWriteBufferBurst[17];
lPdcAddress = (ULONG)pdx->PdcMemBase0;
// KdPrint((DBG_NAME "The PdcMemBase0 is %x.\n", lPdcAddress));
RtlCopyMemory(cWriteBufferBurst, pIrp->AssociatedIrp.SystemBuffer, 17);
WRITE_REGISTER_BUFFER_UCHAR((unsigned char *)(lPdcAddress + cWriteBufferBurst[0]), &cWriteBufferBurst[1], 16);
KdPrint((DBG_NAME "Write Data Value is %x.\n", cWriteBufferBurst[1]));
lReturnedValue = 0;
break;
default:
break;
}
UnlockDevice(pdx);
KdPrint((DBG_NAME "DeviceIoControl End.\n"));
if (status == STATUS_PENDING)
return STATUS_PENDING;
return CompleteRequestInfo(pIrp, status, lReturnedValue);
} //DispatchIoControl
/******************************************************************************
*
* Function : StartIo
*
* Description: The StartIo Service Routine for PDC4000.
*
******************************************************************************/
VOID StartIo(IN PDEVICE_OBJECT fdo,
IN PIRP pIrp)
{ //StartIo
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
KdPrint((DBG_NAME "StartIo Start.\n"));
NTSTATUS status = STATUS_SUCCESS;
BOOLEAN bResult;
RETURN_CODE rc;
PMDL pMdl;
DMA_CHANNEL_DESCRIPTION dcd;
/* if (!LockDevice(pdx))
{
CompleteRequest(pIrp, STATUS_DELETE_PENDING);
}
*/
// Switch on the IRP major function code
switch(pIrpStack->MajorFunction)
{
case IRP_MJ_WRITE:
//Open Dma Channl0
dcd.BTERMInputEnable = 0;
dcd.DACChainLoad = 0;
dcd.DemandMode = 0;
dcd.DmaChannelPriority = Rotational;
dcd.DmaEOTPinEnable = 0;
dcd.DoneInterrputEnable = 1;
dcd.EnableTransferCountClear = 1; //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 = 1;
//DMA threshold
dcd.LocalToPciAlmostEmpty = 0;
dcd.LocalToPciAlmostFull = 0;
dcd.PciToLocalAlmostEmpty = 0;
dcd.PciToLocalAlmostFull = 0;
rc = DmaOpenSglChannel(pdx, 0, &dcd);
if (rc != RC_SUCCESS)
{
CompleteRequestInfo(pIrp, status, 0);
IoStartNextPacket(fdo, TRUE);
KdPrint((DBG_NAME "Can't DmaOpenBlockChannel.\n"));
}
//DMA Transfer Data
pdx->DmaInfo[0].bWriteToLocal = TRUE;
pMdl = pIrp->MdlAddress;
KeFlushIoBuffers(pMdl, FALSE, TRUE); //For Dma Transfer
status = (*pdx->DmaInfo[0].pDmaAdapterObject->DmaOperations->AllocateAdapterChannel)(
pdx->DmaInfo[0].pDmaAdapterObject,
fdo,
pdx->DmaInfo[0].lNumberOfMapRegisters,
(PDRIVER_CONTROL) AdapterControl, //ExecutionRoutine
pdx); //Context
if (!NT_SUCCESS(status))
{
CompleteRequestInfo(pIrp, status, 0);
IoStartNextPacket(fdo, TRUE);
}
return; //退出StartIo;
break;
case IRP_MJ_READ:
//Open Dma Channl0
dcd.BTERMInputEnable = 0;
dcd.DACChainLoad = 0;
dcd.DemandMode = 0;
dcd.DmaChannelPriority = Rotational;
dcd.DmaEOTPinEnable = 0;
dcd.DoneInterrputEnable = 1;
dcd.EnableTransferCountClear = 1; //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 = 1;
//DMA threshold
dcd.LocalToPciAlmostEmpty = 0;
dcd.LocalToPciAlmostFull = 0;
dcd.PciToLocalAlmostEmpty = 0;
dcd.PciToLocalAlmostFull = 0;
rc = DmaOpenSglChannel(pdx, 0, &dcd);
if (rc != RC_SUCCESS)
{
CompleteRequestInfo(pIrp, status, 0);
IoStartNextPacket(fdo, TRUE);
KdPrint((DBG_NAME "Can't DmaOpenBlockChannel.\n"));
}
//DMA Transfer Data
pdx->DmaInfo[0].bWriteToLocal = FALSE;
pMdl = pIrp->MdlAddress;
KeFlushIoBuffers(pMdl, FALSE, TRUE); //For Dma Transfer
status = (*pdx->DmaInfo[0].pDmaAdapterObject->DmaOperations->AllocateAdapterChannel)(
pdx->DmaInfo[0].pDmaAdapterObject,
fdo,
pdx->DmaInfo[0].lNumberOfMapRegisters,
(PDRIVER_CONTROL) AdapterControl, //ExecutionRoutine
pdx); //Context
if (!NT_SUCCESS(status))
{
CompleteRequestInfo(pIrp, status, 0);
IoStartNextPacket(fdo, TRUE);
}
return;
break;
case IRP_MJ_DEVICE_CONTROL:
ULONG lDMALocalToPciTransferSize;
ULONG lPdcAddress; //The base address of PDC4000
// ULONG lReturnedValue;
lDMALocalToPciTransferSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;//0x100;
lPdcAddress = (ULONG)pdx->LocalRegisterMemBase;
/* //直接操作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);
*/
//通过函数调用
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;
rc = DmaOpenBlockChannel(pdx, 0, &dcd);
if (rc != RC_SUCCESS)
{
KdPrint((DBG_NAME "Can't DmaOpenBlockChannel.\n"));
}
//Set Address and Transfer Size.
DMA_TRANSFER_ELEMENT dte;
dte.lLocalAddress = 0;
dte.lPciAddress = pdx->DmaInfo[0].paCommonBuffer.LowPart;
dte.lPciDualAddress = 0;
dte.lTransferSize = lDMALocalToPciTransferSize; //
dte.DescriptorLocation = 0;
dte.DirectionOfTransfer = 1;
dte.EndOfChain = 0;
dte.InterruptAfterTerminalCount = 0;
dte.NextDescriptorAddress = 0;
pdx->DmaInfo[0].lTransferedBytes = lDMALocalToPciTransferSize;
rc = DmaBlockTransfer(pdx, 0, &dte);
if (rc != RC_SUCCESS)
{
KdPrint((DBG_NAME "Can't DmaBlockTransfer.\n"));
}
return;
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);
KdPrint((DBG_NAME "StartIo End.\n"));
CompleteRequestInfo(pIrp, STATUS_SUCCESS, 0);
IoStartNextPacket(fdo, TRUE);
} //StartIo
/******************************************************************************
*
* Function : CancelIrp
*
* Description: The CancelIrp Service Routine for PDC4000.
*
******************************************************************************/
VOID CancelIrp(IN PDEVICE_OBJECT fdo,
IN PIRP pIrp)
{ //CancelIrp
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
KdPrint((DBG_NAME "WdmIoCancelIrp: Cancelling %x %I", pIrp, pIrp));
if (pIrp == fdo->CurrentIrp)
{
KdPrint((DBG_NAME "CancelIrp: IRP running in StartIo\n"));
// 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
{
KdPrint((DBG_NAME "CancelIrp: IRP in StartIo queue.\n"));
// 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 lRegisterValue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -