我是根据PCI9054的例子写了这样一个驱动程序。
在READ例程中调用下面的代码,实现数据传输。m_DmaTransfer = new(NonPagedPool) KDmaTransfer(this, &m_Dma);
if ( m_DmaTransfer == NULL )
{
status = STATUS_INSUFFICIENT_RESOURCES;
I.Information() = 0;
I.Status() = status;
ReadQueue.PnpNextIrp(I);
}
status = m_DmaTransfer->Initiate(this, &m_Dma, I.Mdl(),
(I.MajorFunction() == IRP_MJ_READ) ? FromDeviceToMemory : FromMemoryToDevice,LinkTo(Onm_DmaReady), &m_DmaBuffer);//LinkTo(Onm_DmaReady)
if ( ! NT_SUCCESS(status) )
{
delete m_DmaTransfer;
m_DmaTransfer = NULL;
I.Information() = 0;
I.Status() = status;
ReadQueue.PnpNextIrp(I);
}Onm_DmaReady为DMA回调函数。void PCI8030Device::Onm_DmaReady(KDmaTransfer* pTransfer, KIrp I)
{
// TODO: Perform the following:
// Obtain IRP pointer from IRP Queue
// Check pTransfer->BytesRemaining() for additional data to xfer
// Start next segment of DMA transfer
// Terminate the transfer if done
// Complete IRP if done
if (pTransfer->BytesRemaining() == 0)
{ //DMA结束时
pTransfer->Terminate();
I.Information() = I.ReadSize(CURRENT);
I.Status() = STATUS_SUCCESS;
PnpNextIrp(I);
m_DmaTransfer = NULL;
delete pTransfer;
return;
}
//ixx++;
PTRANSFER_DESCRIPTOR ptd; //DMA启动时
while (pTransfer->SequenceTransferDescriptors(&ptd)){}
if ((ULONG) pTransfer->BytesRemaining() == I.ReadSize())
{
StartDMA(ptd->td_PhysAddr.LowPart,ptd->td_Length);
//jxx=4;
}
}
VOID PCI8030Device::StartDMA(ULONG PAddress,ULONG NBytes)
{
unsigned int data=0;
//PAddress=0x95ab000;
//data=data|((NBytes/4)&0xff)|(0xE<<8);//0x1110表示写与0x0110表示读
data=(NBytes/4)&0xff;//0x1110表示写与0x0110表示读
//写入内存地址;DMA开始标志等信息,
m_MemRes.outd(0x52,PAddress); //DMA通道0 的PCI地址
Sleep(5);
m_MemRes.outd(0x48,data); //写传输长度与标志
Sleep(5);
m_IoRes.outb(0,0xFC);//通知PCI写入数据
Sleep(5);
}问题:
在回调函数里面的
if ((ULONG) pTransfer->BytesRemaining() == I.ReadSize())
{
StartDMA(ptd->td_PhysAddr.LowPart,ptd->td_Length);
//jxx=4;
}
这个判断条件回导致PC重启。如果去掉判断条件,保留startDMA的调用,不会重启。如果判断条件内不写任何代码,不会重启。只是写入一个赋值语句也会导致重启。我对此感觉不能理解。这是怎么一回事呢