terrace
驱动牛犊
驱动牛犊
  • 注册日期2004-02-11
  • 最后登录2005-12-04
  • 粉丝0
  • 关注0
  • 积分15分
  • 威望3点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1422回复:0

请问OnDmaReady究竟何时被调用?

楼主#
更多 发布于:2004-07-20 14:14
对于NT下DriverWorks开发驱动程序,我对LinkTo()始终很模糊,不知道被LINK的函数究竟被谁调用,何时调用。如写一个执行DMA的驱动,常要创建一个KDmaAdapter、KDmaTransfer派生的类。然后执行以下操作:

void DMASampleDevice::SerialRead(KIrp I)
{
    NTSTATUS status        = STATUS_SUCCESS;

    m_CurrentTransfer = new(NonPagedPool) KDmaTransfer(this, &m_Dma);

    if ( m_CurrentTransfer == NULL )
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        DbgPrint("unable to allocate transfer object: %x\n", status);

        I.Information() = 0;
        I.Status() = status;
        PnpNextIrp(I);
    }

    status = m_CurrentTransfer->Initiate(
        this,
        &m_Dma,
        I.Mdl(),
        (I.MajorFunction() == IRP_MJ_READ) ? FromDeviceToMemory : FromMemoryToDevice,
        LinkTo(OnDmaReady),
        &m_Buffer
        );
    // If the transfer cannot be initiated, complete it with an error status.
    if ( ! NT_SUCCESS(status) )
    {
        DbgPrint("unable to initiate transfer: %x\n", status);

        delete m_CurrentTransfer;
        m_CurrentTransfer = NULL;

        I.Information() = 0;
        I.Status() = status;
        PnpNextIrp(I);
    }
}

VOID DMASampleDevice::OnDmaReady(KDmaTransfer* pXfer, KIrp I)
{
    t << "Entering OnDmaReady\n";

    // All KDmaTransfer callbacks must first check to see if there are any bytes
    // left to transfer.
    if (pXfer->BytesRemaining() == 0)
    {
        // If there are no bytes left to transfer, the callback must call
        // Terminate(). Then it completes the IRP with STATUS_SUCCESS.
        t << "terminating transfer\n";
        pXfer->Terminate();
    
        I.Information() = I.ReadSize(CURRENT);
        I.Status() = STATUS_SUCCESS;
        PnpNextIrp(I);

        m_CurrentTransfer = NULL;
        delete pXfer;
        return;
    }

    // We must get the descriptor for the physical memory location for
    // the DMA transfer.

    PTRANSFER_DESCRIPTOR ptd;

    while (pXfer->SequenceTransferDescriptors(&ptd)) {
        // program the h/w using  ppTD
        t << "Physical address 0x" << ptd->td_PhysAddr.LowPart << ". Length is 0x"
            << ptd->td_Length << "." << EOL;
    }

    // If this is the first time through, then start the DMA going.
    // We only want to do this ONCE for a given Read transfer.  That
    // way, our data will be collected smoothly, without interruptions
    // or dropouts.
    if ((ULONG) pXfer->BytesRemaining() == I.ReadSize())
        StartDMA(ptd->td_PhysAddr.LowPart,ptd->td_Length);
}

对于上述代码,OnDmaReady究竟在什么情况下被调用?如果硬件支持分散/集中DMA,而且只有当所有的数据(可能不止一个数据块)传输完毕时才产生中断,传完一个数据块也不需驱动去设置硬件的地址或长度寄存器(硬件自己会执行此操作),还会调用它么?

游客

返回顶部