www.pudn.com > PlxSdk.rar > PlxInterrupt.c
/******************************************************************************* * Copyright (c) 2007 PLX Technology, Inc. * * PLX Technology Inc. licenses this software under specific terms and * conditions. Use of any of the software or derviatives thereof in any * product without a PLX Technology chip is strictly prohibited. * * PLX Technology, Inc. provides this software AS IS, WITHOUT ANY WARRANTY, * EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. PLX makes no guarantee * or representations regarding the use of, or the results of the use of, * the software and documentation in terms of correctness, accuracy, * reliability, currentness, or otherwise; and you rely on the software, * documentation and results solely at your own risk. * * IN NO EVENT SHALL PLX BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS, * LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES * OF ANY KIND. IN NO EVENT SHALL PLX'S TOTAL LIABILITY EXCEED THE SUM * PAID TO PLX FOR THE PRODUCT LICENSED HEREUNDER. * ******************************************************************************/ /****************************************************************************** * * File Name: * * PlxInterrupt.c * * Description: * * This file handles interrupts for the PLX device * * Revision History: * * 04-01-07 : PLX SDK v5.00 * ******************************************************************************/ #include#include #include #include #include #include #include // Note: interrupt.h must be last to avoid compiler // errors with some 2.4 kernel headers #include "DriverDefs.h" #include "PciSupport.h" #include "PlxInterrupt.h" #include "SupportFunc.h" /****************************************************************************** * * Function : OnInterrupt * * Description: The Interrupt Service Routine for the PLX device * ******************************************************************************/ irqreturn_t OnInterrupt( int irq, void *dev_id #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) , struct pt_regs *regs #endif ) { U32 RegMask; U32 RegStatus; U32 Offset_Mask; U32 Offset_StatClear; DEVICE_EXTENSION *pdx; // Get the device extension pdx = (DEVICE_EXTENSION *)dev_id; // Set proper reg offset if (pdx->bFromLinkSide) { Offset_Mask = 0x11000 + 0xa8; // Link side interrupt registers Offset_StatClear = 0x11000 + 0xa4; } else { Offset_Mask = 0x10000 + 0x98; // Virtual side interrupt registers Offset_StatClear = 0x10000 + 0x94; } // Get interrupt mask RegMask = PLX_8000_REG_READ( pdx, Offset_Mask ); // Invert mask to make it an 'enable' RegMask = ~RegMask; // Get interrupt status RegStatus = PLX_8000_REG_READ( pdx, Offset_StatClear ); // Clear unused bits RegMask &= 0xFFFF; RegStatus &= 0xFFFF; // Determine active interrupts RegStatus = RegMask & RegStatus; // Return if no interrupt active if (RegStatus == 0) { return FALSE; } // At this point, the device interrupt is verified // Store the doorbell value pdx->Source_Doorbell |= RegStatus; // Clear active interrupts PLX_8000_REG_WRITE( pdx, Offset_StatClear, RegStatus ); // // Schedule deferred procedure (DPC) to complete interrupt processing // #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) // Reset task structure pdx->Task_DpcForIsr.sync = 0; // Add task to system immediate queue queue_task( &(pdx->Task_DpcForIsr), &tq_immediate ); // Mark queue for Bottom-half processing mark_bh( IMMEDIATE_BH ); #else // Add task to system work queue schedule_work( &(pdx->Task_DpcForIsr) ); #endif return PLX_IRQ_RETVAL(IRQ_HANDLED); } /****************************************************************************** * * Function : DpcForIsr * * Description: This routine will be triggered by the ISR to service an interrupt * ******************************************************************************/ VOID DpcForIsr( PLX_DPC_PARAM *pArg1 ) { DEVICE_EXTENSION *pdx; PLX_INTERRUPT_DATA IntData; // Get the device extension pdx = container_of( pArg1, DEVICE_EXTENSION, Task_DpcForIsr ); // Setup for synchonized access to interrupt source IntData.pdx = pdx; // Get current pending interrupt sources PlxSynchronizedGetInterruptSource( &IntData ); // Signal any objects waiting for notification PlxSignalNotifications( pdx, &IntData ); }