?? isrdpc.c
字號(hào):
/*++
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,
NULL
);
//
// Indicate that this adapter was interrupting.
//
return TRUE;
} // PciDmaISR
VOID
PciDmaDpc(
IN PKDPC Dpc,
IN PDEVICE_OBJECT DeviceObject,
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
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -