Files
2026-07-30 11:19:44 +05:30

171 lines
6.6 KiB
C

/****************************************************************************
* sec2isr.c -- The Interrupt Service code for SEC2 Driver
****************************************************************************
* Copyright (c) Certicom Corp. 1996-2002. All rights reserved
* Copyright (c) 2003, 2004 Freescale Semiconductor
* All Rights Reserved. Proprietary and Confidential.
*
* NOTICE: The information contained in this file is proprietary
* to Freescale Semiconductor, and is being made available to
* Freescale's customers under strict license agreements.
* Use or disclosure of this information is permissible only
* under the terms of the existing license agreement.
****************************************************************************/
/*
* Revision History:
* 1.0 Aug 24,2003 dgs - adapted from the final version of mpc18x
* May 12,2004 sec - turned on some windview events for debug
* Jun 06,2004 sec - corrected channel reset logic
* Jun 10,2004 sec - remove superfluous I/O calls
* Jul 22,2004 sec - added double CHA reset to handle errata
* 1.1.0 Nov 16,2004 sec - updated for linux change merge from prior revs
* 1.1.1 Dec 16,2004 sec - cleanup, remove unused diagnostics
* 1.2 Jan 27,2005
*/
#include "Sec2Driver.h"
/* Interpeak begin */
#undef NUM_CHANNELS
#define NUM_CHANNELS (num_channels)
extern int num_channels;
/* Interpeak end */
/**************************************************************************
* Function Name: InterruptServiceRoutine
* Purpose: To handle all interrupt generated by Channel or CHA (Done or Error)
* indicated by the Interrupt Status Register
* If Error, clean the InterruptStatusRegister by writing InterruptClearRegister
* If Done, call ProcessRequestDone routine
* Input: Interrupt - PKINTERRUPT
* Context - PVOID the request Context
*
*************************************************************************/
#ifdef __KERNEL__
DEVICE_REGS pRegs_queue[PREGS_QUEUE_DEPTH];
unsigned PQ_head = 0;
unsigned PQ_tail = 0;
unsigned PQ_entries = 0;
extern void ProcessingComplete(unsigned long not_used);
DECLARE_TASKLET(isr_tasklet,ProcessingComplete,0);
void InterruptServiceRoutine(int irq, void *dev_id, struct pt_regs *pt_regs)
#else
void InterruptServiceRoutine(void)
#endif
{
register int cha, cha_res;
register int channel;
unsigned long temp[2];
unsigned long intStatus0, intStatus1;
DEVICE_REGS *pRegs;
static DEVICE_REGS regs;
/* save interrupt status register for the ProcessingComplete */
intStatus0 = *(InterruptStatusRegister);
intStatus1 = *(InterruptStatusRegister + 1);
pRegs = &regs;
pRegs->IntStatus[0] = intStatus0;
pRegs->IntStatus[1] = intStatus1;
/* check for error interrupts, was there any error? */
if ((intStatus0 & ALL_INT_ERRORS_MASK_LOW) ||
(intStatus1 & ALL_INT_ERRORS_MASK_HIGH))
{
/* save assigment statii for background servicing to use */
pRegs->ChaAssignmentStatus[0] = *(ChaAssignmentStatusRegister);
pRegs->ChaAssignmentStatus[1] = *(ChaAssignmentStatusRegister + 1);
/* service CHA error interrupts first */
for (cha_res = 0; cha_res < NUM_CHAS; cha_res++)
{
/* save the channel this CHA is assigned to if any */
if (cha_res < 4)
channel = (pRegs->ChaAssignmentStatus[0] >> (cha_res * 8)) & 0xF;
else
channel = (pRegs->ChaAssignmentStatus[1] >> ((cha_res - 4) * 8)) & 0xF;
cha = cha_idx[cha_res];
if ((intStatus1 & ChaErrorInterruptMasks[cha]) ||
(channel > 0 && channel < (NUM_CHANNELS+1) &&
(intStatus0 & ChannelErrorInterruptMasks[channel-1])))
{
/* found a CHA error interrupt, read the CHA status register */
pRegs->ChaError[cha][0] = *(unsigned long *)(ChaInterruptStatusRegister[cha]);
pRegs->ChaError[cha][1] = *(unsigned long *)(ChaInterruptStatusRegister[cha] + 1);
/* ensure that the associated channel is reset */
if (channel > 0 && channel < (NUM_CHANNELS+1))
intStatus0 |= ChannelErrorInterruptMasks[channel-1];
pRegs->ChannelError[channel][0] = *(unsigned long *)(ChannelPointerStatusRegister[channel-1]);
pRegs->ChannelError[channel][1] = *(unsigned long *)(ChannelPointerStatusRegister[channel-1] + 1);
/* Done extracting info, reset the CHA */
/* This will be done twice to work around an errata that has to do with CHA */
/* reset hold time */
*(ChaResetControlRegister[cha]) = CHA_SOFTWARE_RESET;
*(ChaResetControlRegister[cha] + 1) = 0;
*(ChaResetControlRegister[cha]) = CHA_SOFTWARE_RESET;
*(ChaResetControlRegister[cha] + 1) = 0;
if (cha == CHA_DES) /* is this cha des? */
{
*(ChaInterruptControlRegister[cha]) = CHA_DESA_KEY_PARITY_ERROR_DISABLE;
*(ChaInterruptControlRegister[cha] + 1) = 0;
}
if (cha == CHA_PKHA) /* is this cha the pkha? */
{
*(ChaInterruptControlRegister[cha]) = CHA_PKHA_ILLEGAL_ADDR_ERROR_DISABLE;
*(ChaInterruptControlRegister[cha] + 1) = 0;
}
} /* if (cha causes error) */
} /* for (all chas) */
/* look at the channel error interrupts next */
for (channel=0; channel<NUM_CHANNELS; channel++)
{
if (intStatus0 & ChannelErrorInterruptMasks[channel])
{
/* fetch a copy of the CPSR for out-of-ISR processing */
pRegs->ChannelError[channel][0] = *(unsigned long *)(ChannelPointerStatusRegister[channel]);
pRegs->ChannelError[channel][1] = *(unsigned long *)(ChannelPointerStatusRegister[channel] + 1);
/* reset the channel */
*(ChannelConfigRegister[channel]) = (unsigned long)CHANNEL_RESET;
*(ChannelConfigRegister[channel] + 1) = (unsigned long)0;
/* give the hardware a chance to clock... */
temp[0] = *(unsigned long *)(ChannelConfigRegister[channel]);
/* re-enable channel interrupts */
*(ChannelConfigRegister[channel]) = (unsigned long)0;
*(ChannelConfigRegister[channel] + 1) = (unsigned long)CHANNEL_INTEN | CHANNEL_BURST128;
} /* if (channel error) */
} /* for (all channels) */
} /* if (any error interrupt) */
/* clear latched interrupts at the control register level */
*(InterruptClearRegister) = intStatus0;
*(InterruptClearRegister + 1) = intStatus1;
/* schedule process complete function */
#ifdef __KERNEL__
(void)QmsgSend();
#else
(void)msgQSend(IsrMsgQId, (char*)pRegs, sizeof(DEVICE_REGS), NO_WAIT, MSG_PRI_NORMAL);
#endif
} /* end of SEC2InterruptService */