⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isrdpc.c

📁 dma驱动开发程序
💻 C
字号:
/*++

Copyright (c) 1997-1998  Microsoft Corporation

Module Name:

    isrdpc.c

Abstract:

    This file contains the Interrupt Service Routine (ISR) and Deferred
    Procedure Call (DPC) routines and any associated support routines.

Author:

    Steve Dziok (SteveDz)

Environment:

    Kernel mode

Revision History:


--*/

#include "pcidma.h"


BOOLEAN
PciDmaISR(
    IN PKINTERRUPT Interrupt,
    IN PVOID ServiceContext
    )
/*++

Routine Description:

    This routine assumes that only a single I/O can be completed at a
    time on the hardware (i.e. at most one I/O completed per interrupt).

Arguments:

    Interrupt - Pointer to the driver's interrupt object.

    Context - Pointer to context information as specified in the call to
              IoConnectInterrupt.

Return Value:

    TRUE - Interrupt belongs to this device.
    
--*/
{
    PDEVICE_OBJECT      deviceObject = (PDEVICE_OBJECT)ServiceContext;
    PDEVICE_EXTENSION   deviceExtension = deviceObject->DeviceExtension;

    UCHAR   intStatus;
    UCHAR   intStat0;
    UCHAR   intStat1;
    
    DebugPrint((3, "PciDmaISR \n"));

    //
    // Check if adapter is interrupting.  If not, return FALSE.  It is 
    // critical to check whether this adapter is interrupting as soon as 
    // possible so the operating system can call the next ISR when shared
    // interrupts are used.
    //

    //
    // First, check if device configuration was complete.  If not, return to 
    // caller.  The device should not yet be interrupting.  Also, if 
    // configuration was not complete, we have no safe way to insure the 
    // device registers have been mapped, nor are we sure the device 
    // components have been safely set up.
    //
    // If the system uses shared interrupts, and this ISR is being called
    // for another devices interrupt, we can safely read the ready flag in
    // the device extension.  Don't need to use the interlocked routines to
    // read this flag.
    //
    
    if (!deviceExtension->DeviceConfigured) {
        
        DebugPrint((3, "Device not configured but ISR called \n"));
        
        return FALSE;
    }

///////////////////////////////////////////////////////////////
//
// VENDOR_UNIQUE  -- Vendor unique code -- START 
//
///////////////////////////////////////////////////////////////
#ifdef VENDORID_1000_DEVICEID_0004

    //
    // Check if the adapter is interrupting.  If not, indicate this fact.
    //

    intStatus = READ_UCHAR(INT_STATUS);
    
    if (!intStatus) {

        //
        // This adapter was not interrupting.
        //

        return FALSE;
    }

    ASSERT(intStatus == 0x02);
    
    //
    // Clear the interrupt.  This sample throws away all the interrupt 
    // information.  Of course a real driver would use this information.
    //

    intStat0 = READ_UCHAR(INT_STAT0);
    intStat1 = READ_UCHAR(INT_STAT1);

    WRITE_UCHAR(TIMER1, 0x00);        

#endif
///////////////////////////////////////////////////////////////
//
// VENDOR_UNIQUE  -- Vendor unique code -- END
//
///////////////////////////////////////////////////////////////
    
    //
    // Check if there is a current IRP.  If not, then this interrupt cannot
    // do anything.  This driver design requires an I/O to be pending in order
    // to queue the DPC.  If there is no I/O current, then there is no need
    // to have a DPC queued.  This driver also assumes one I/O per interrupt.
    //
    // IMPORTANT: Before returning TRUE, the interrupt must have been cleared
    // on the device or the system will hang trying to service this level 
    // sensitive interrupt.
    //
    
    if (!deviceObject->CurrentIrp) {
        
        DebugPrint((3, "Hardware generated interrupt with no IRP pending \n"));
        
        //
        // Clear the interrupt on the device before returning TRUE.
        //
        
        return TRUE;
    }
    
///////////////////////////////////////////////////////////////
//
// VENDOR_UNIQUE  -- Vendor unique code -- START 
//
///////////////////////////////////////////////////////////////
#ifdef VENDORID_1000_DEVICEID_0004

    //
    // Interrupt came from this adapter.  Save only as much information as
    // necessary,  clear the interrupt on the adapter, request a DPC and
    // return TRUE.
    //

    //
    // Save information for the DPC.
    //

    //
    // Clear the interrupt from this adapter.
    //

#endif
///////////////////////////////////////////////////////////////
//
// VENDOR_UNIQUE  -- Vendor unique code -- END
//
///////////////////////////////////////////////////////////////

    //
    // Request the DPC to complete the transfer.
    //

    IoRequestDpc(deviceObject,
                 deviceObject->CurrentIrp,
                 NULL
                 );

    //
    // Indicate that this adapter was interrupting.
    //

    return TRUE;

}   // PciDmaISR


VOID
PciDmaDpc(
    IN PKDPC Dpc,
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Context
    )
/*++

Routine Description:

    The DPC routine does most of the work of servicing the interrupt.  If
    the original I/O transfer was too large for the adapter and split into
    multiple transfers, the remaining partial transfers must be completed.  
    If the original transfer is completed, the IRP must be completed, and 
    the next packet started.

    This routine assumes that only a single I/O can be completed at a
    time on the hardware (i.e. at most one I/O completed per interrupt).

    Remember that if this routine needs to access hardware registers or data
    shared with the ISR, it must use a SynchCritSection routine (i.e. use
    KeSynchronizeExecution).

Arguments:

    Dpc - Pointer to kernel DPC object.
    
    DeviceObject - Object representing a particular adapter.

    Irp - Current IRP for the specified device.
    
    Context - Driver determined context information.  For this driver,
              the context is not used.
    
Return Value:

    None
    
--*/
{
    PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;
    
    PTRANSFER_INFO      transferInfo = deviceExtension->TransferInfo;
    
    PIO_STACK_LOCATION  irpStack = IoGetCurrentIrpStackLocation(Irp);


    DebugPrint((3, "PciDmaDpc \n"));

///////////////////////////////////////////////////////////////
//
// VENDOR_UNIQUE  -- Vendor unique code -- START 
//
///////////////////////////////////////////////////////////////
#ifdef VENDORID_1000_DEVICEID_0004

    //
    // Check if the I/O failed.  If so, the I/O can be retried or completed 
    // with an error status at this point.  Also, we may want to write 
    // information to the event log about the error.  Don't forget to start 
    // the next I/O on failure.
    //

#endif
///////////////////////////////////////////////////////////////
//
// VENDOR_UNIQUE  -- Vendor unique code -- END
//
///////////////////////////////////////////////////////////////

    //
    // Given the current IRP, find the correct transfer info.  Since this 
    // driver handles only one IRP on the device at a time, the transfer 
    // info is the only one in the device extension.
    //

    ASSERT(Irp == transferInfo->Irp);
        
    //
    // On success, flush the adapter buffers.
    //

    IoFlushAdapterBuffers(deviceExtension->AdapterObject,
                          Irp->MdlAddress,
                          deviceExtension->MapRegisterBase,
                          transferInfo->CurrentVA,
                          transferInfo->ByteCount,
                          transferInfo->WriteToDevice
                          );
    
    //
    // Free the map registers.
    //
    
    IoFreeMapRegisters(deviceExtension->AdapterObject,
                       transferInfo->MapRegisterBase,
                       transferInfo->NumberOfMapRegisters
                       );                      
    
    //
    // For this sample, indicate success and set the transfer length to the 
    // length requested.  A real driver would set the length according to the
    // length of data actually transferred.
    //

    DebugPrint((2,
                "Completing IRP %8x \n",
                Irp
                ));
    
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = transferInfo->ByteCount;

    //
    // Clear out the transfer info.
    //
    
    RtlZeroMemory(transferInfo, sizeof(TRANSFER_INFO));
    
    //
    // Try to start the next I/O packet, if any.
    //

    IoStartNextPacket(DeviceObject, FALSE);

    //
    // Choose an appropriate priority increment for IoCompleteRequest.  See
    // NTDDK.H for details.
    //

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

}   // PciDmaDpc


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -