📄 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:
*
* 01-01-07 : PLX SDK v5.00
*
******************************************************************************/
#include "PlxChipFn.h"
#include "PlxInterrupt.h"
#include "SupportFunc.h"
/******************************************************************************
*
* Function : OnInterrupt
*
* Description: The Interrupt Service Routine for the PLX device
*
******************************************************************************/
BOOLEAN
OnInterrupt(
PKINTERRUPT pInterrupt,
PVOID ServiceContext
)
{
U32 RegPciInt;
U32 InterruptSource;
DEVICE_EXTENSION *pdx;
// Get the device extension
pdx = (DEVICE_EXTENSION *)ServiceContext;
// Read interrupt status register
RegPciInt =
PLX_9000_REG_READ(
pdx,
PCI9030_INT_CTRL_STAT
);
/****************************************************
* If the chip is in a low power state, then local
* register reads are disabled and will always return
* 0xFFFFFFFF. If the PLX chip's interrupt is shared
* with another PCI device, the PXL ISR may continue
* to be called. This case is handled to avoid
* erroneous reporting of an active interrupt.
***************************************************/
if (RegPciInt == 0xFFFFFFFF)
return FALSE;
// Check for master PCI interrupt enable
if ((RegPciInt & (1 << 6)) == 0)
return FALSE;
// Verify that an interrupt is truly active
// Clear the interrupt type flag
InterruptSource = INTR_TYPE_NONE;
// Check if Local Interrupt 1 is active and not masked
if ((RegPciInt & (1 << 2)) && (RegPciInt & (1 << 0)))
{
InterruptSource |= INTR_TYPE_LOCAL_1;
}
// Check if Local Interrupt 2 is active and not masked
if ((RegPciInt & (1 << 5)) && (RegPciInt & (1 << 3)))
{
InterruptSource |= INTR_TYPE_LOCAL_2;
}
// Software Interrupt
if (RegPciInt & (1 << 7))
{
InterruptSource |= INTR_TYPE_SOFTWARE;
}
// Return if no interrupts are active
if (InterruptSource == INTR_TYPE_NONE)
return FALSE;
// At this point, the device interrupt is verified
// Mask the PCI Interrupt
PLX_9000_REG_WRITE(
pdx,
PCI9030_INT_CTRL_STAT,
RegPciInt & ~(1 << 6)
);
//
// Schedule deferred procedure (DPC) to complete interrupt processing
//
KeInsertQueueDpc(
&(pdx->DpcForIsr),
(VOID *)(PLX_UINT_PTR)InterruptSource,
NULL
);
return TRUE;
}
/******************************************************************************
*
* Function : DpcForIsr
*
* Description: This routine will be triggered by the ISR to service an interrupt
*
******************************************************************************/
VOID
DpcForIsr(
PKDPC pDpc,
PVOID pContext,
PVOID pArg1,
PVOID pArg2
)
{
U32 RegValue;
PLX_REG_DATA RegData;
DEVICE_EXTENSION *pdx;
PLX_INTERRUPT_DATA IntData;
// Get the device extension
pdx = (DEVICE_EXTENSION *)pContext;
// Get interrupt source
IntData.Source_Ints = PtrToUlong(pArg1);
IntData.Source_Doorbell = 0;
KeAcquireSpinLockAtDpcLevel(
&(pdx->Lock_HwAccess)
);
// Local Interrupt 1
if (IntData.Source_Ints & INTR_TYPE_LOCAL_1)
{
// Setup to synchronize access to Interrupt Control/Status Register
RegData.pdx = pdx;
RegData.offset = PCI9030_INT_CTRL_STAT;
RegData.BitsToSet = 0;
RegData.BitsToClear = 0;
// Check if this is an edge-triggered interrupt
RegValue =
PLX_9000_REG_READ(
pdx,
PCI9030_INT_CTRL_STAT
);
if ((RegValue & (1 << 1)) && (RegValue & (1 << 8)))
{
// Clear edge-triggered interrupt
RegData.BitsToSet = (1 << 10);
KeSynchronizeExecution(
pdx->pInterruptObject,
PlxSynchronizedRegisterModify,
(VOID *)&RegData
);
}
else
{
// Mask Local Interrupt 1
RegData.BitsToClear = (1 << 0);
KeSynchronizeExecution(
pdx->pInterruptObject,
PlxSynchronizedRegisterModify,
(VOID *)&RegData
);
}
}
// Local Interrupt 2
if (IntData.Source_Ints & INTR_TYPE_LOCAL_2)
{
// Setup to synchronize access to Interrupt Control/Status Register
RegData.pdx = pdx;
RegData.offset = PCI9030_INT_CTRL_STAT;
RegData.BitsToSet = 0;
RegData.BitsToClear = 0;
// Check if this is an edge-triggered interrupt
RegValue =
PLX_9000_REG_READ(
pdx,
PCI9030_INT_CTRL_STAT
);
if ((RegValue & (1 << 4)) && (RegValue & (1 << 9)))
{
// Clear edge-triggered interrupt
RegData.BitsToSet = (1 << 11);
KeSynchronizeExecution(
pdx->pInterruptObject,
PlxSynchronizedRegisterModify,
(VOID *)&RegData
);
}
else
{
// Mask Local Interrupt 2
RegData.BitsToClear = (1 << 3);
KeSynchronizeExecution(
pdx->pInterruptObject,
PlxSynchronizedRegisterModify,
(VOID *)&RegData
);
}
}
// Software Interrupt
if (IntData.Source_Ints & INTR_TYPE_SOFTWARE)
{
// Setup to synchronize access to Interrupt Control/Status Register
RegData.pdx = pdx;
RegData.offset = PCI9030_INT_CTRL_STAT;
RegData.BitsToSet = 0;
// Clear the software interrupt
RegData.BitsToClear = (1 << 7);
KeSynchronizeExecution(
pdx->pInterruptObject,
PlxSynchronizedRegisterModify,
(VOID *)&RegData
);
}
KeReleaseSpinLockFromDpcLevel(
&(pdx->Lock_HwAccess)
);
// Signal any objects waiting for notification
PlxSignalNotifications(
pdx,
&IntData
);
// Re-enable interrupts
KeSynchronizeExecution(
pdx->pInterruptObject,
PlxChipInterruptsEnable,
pdx
);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -