/************************************************************************* $Archive: /PACS/OnBoard/smcs.s $ $Revision: 28 $ $Date: 3/14/06 4:32p $ $Author: Pacs Egse $ $Log: /PACS/OnBoard/smcs.s $ ; ; 28 3/14/06 4:32p Pacs Egse ; Version 6.001 ; Cleaned and commented *************************************************************************/ #include #include "c:\virtuoso\adi21020\inc\macro.h" #define INCLUDE_DEFINE_ONLY #include "d:\prj\pacs\onboard\m_smcsin.h" #include "d:\prj\pacs\onboard\m_smcsge.h" #include "d:\prj\pacs\onboard\l_hwmap.h" #include "d:\prj\pacs\onboard\link1355.h" #define MEMORY_SCRUBBING_BUFFER_SIZE 256 /*if you change it here, change it also in Hk.h*/ .segment /pm seg_pmco; /****************************************************************/ /* EXTERNAL VARIABLES */ /****************************************************************/ .extern _K_ArgsP; /* pointer to argument stack for ISR - Virtuoso convention */ .extern _K_Args; /* argument stack for ISR - Virtuoso convention - not used */ .extern gaEventsSmcsTransmitCompleted; .extern gaEventsSmcsReceiveCompleted; .extern gSemaSMCS; .extern gaLinkTransmitCompleted; .extern gaLinkReceptionCompleted; .extern gLastSmcs2ISR; .extern gLastSmcs2IMR; .extern gSmcs2IsrCount; .extern gSmcs2IsrHandledCount; /**************************************************************** FUNCTIONS DECLARATION ****************************************************************/ .global _smcs1_isr; .global _smcs2_isr; .global _pmpsc_isr; /* ISR : _smcs1_isr AUTHOR : AMazy USE : This is the SMCS 1 interrupt routine SEE ALSO : "link1355.c" */ _smcs1_isr: START_ISR; //save MODE1, ASTAT, r0, r1, r2, r4, r8, r12, i4, i12 /* read ISR register*/ i4 = K_DMADDR_BASE_SMCS1; /* absolutely need to read it this way*/ r0 = dm(0x04, i4); dm(0x7F, i4) = r0; /*dummy write command*/ /* read IMR register*/ i4 = K_DMADDR_BASE_SMCS1; /* absolutely need to read it this way*/ r2 = dm(0x08, i4); dm(0x7F, i4) = r2; /*dummy write command*/ r0 = r0 and r2; i4 = _gaLinkTransmitCompleted; i12 = _gaLinkReceptionCompleted; r4 = 0; /*r4 will be set to 1 if an event needs to be reported to high level software*/ r12 = 1; /*************/ /* CHANNEL 0 */ /*************/ smcs1_test_err0 : btst r0 by K_BPOS_SMCSINT_CH1_PAR_DIS_ERR; if sz jump (smcs1_test_tx0); /* if bit ERR is set*/ dm(_gaLinkParityDisconnectError + 0) = r12; r4 = 1; smcs1_test_tx0 : btst r0 by K_BPOS_SMCSINT_CH1_DATA_TXED; /* test bit TX */ if sz jump (smcs1_test_rx0); dm(_gaLinkTransmitCompleted + 0) = r12; r4 = 1; smcs1_test_rx0 : btst r0 by K_BPOS_SMCSINT_CH1_DATA_RXED; /* test bit RX */ if not sz jump (smcs1_signal_rx0); btst r0 by K_BPOS_SMCSINT_CH1_EOP_RXED; /* test bit EOP RX */ if sz jump (smcs1_test_err1); smcs1_signal_rx0 : dm(_gaLinkReceptionCompleted + 0) = r12; r4 = 1; /*************/ /* CHANNEL 1 */ /*************/ smcs1_test_err1 : btst r0 by K_BPOS_SMCSINT_CH2_PAR_DIS_ERR; if sz jump (smcs1_test_tx1); /* if bit ERR is set*/ dm(_gaLinkParityDisconnectError + 1) = r12; r4 = 1; smcs1_test_tx1 : btst r0 by K_BPOS_SMCSINT_CH2_DATA_TXED; /* test bit TX */ if sz jump (smcs1_test_rx1); dm(_gaLinkTransmitCompleted + 1) = r12; r4 = 1; smcs1_test_rx1 : btst r0 by K_BPOS_SMCSINT_CH2_DATA_RXED; /* test bit RX */ if not sz jump (smcs1_signal_rx1); btst r0 by K_BPOS_SMCSINT_CH2_EOP_RXED; /* test bit EOP RX */ if sz jump (smcs1_test_err2); smcs1_signal_rx1 : dm(_gaLinkReceptionCompleted + 1) = r12; r4 = 1; /*************/ /* CHANNEL 2 */ /*************/ smcs1_test_err2 : btst r0 by K_BPOS_SMCSINT_CH3_PAR_DIS_ERR; if sz jump (smcs1_test_tx2); /* if bit ERR is set*/ dm(_gaLinkParityDisconnectError + 2) = r12; r4 = 1; smcs1_test_tx2 : btst r0 by K_BPOS_SMCSINT_CH3_DATA_TXED; /* test bit TX */ if sz jump (smcs1_test_rx2); dm(_gaLinkTransmitCompleted + 2) = r12; r4 = 1; smcs1_test_rx2 : btst r0 by K_BPOS_SMCSINT_CH3_DATA_RXED; /* test bit RX */ if not sz jump (smcs1_signal_rx2); btst r0 by K_BPOS_SMCSINT_CH3_EOP_RXED; /* test bit EOP RX */ if sz jump (smcs1_end_isr); smcs1_signal_rx2 : dm(_gaLinkReceptionCompleted + 2) = r12; r4 = 1; smcs1_end_isr : btst r4 by 0; if sz jump (smcs1_exit_isr); i4 = dm(_K_ArgsP); r2 = _gSemaSMCS; PRHI_STACK_PSH; smcs1_exit_isr : ENDISR1; /**************************************************************************************** ISR : _smcs2_isr AUTHOR : AMazy USE : This is the SMCS2 interrupt routine. It also handles DMPSC EDAC interrupts that arrives on the same interrupt line SEE ALSO : "link1355.c" ****************************************************************************************/ _smcs2_isr: START_ISR; //save MODE1, ASTAT, r0, r1, r2, r4, r8, r12, i4, i12 /***********************/ /*Handle EDAC interrupt*/ /***********************/ r0 = dm(K_DMADD_DMPSC_INTP); /* read DMPSC interrupt register*/ dm(_gLastSmcs2IMR) = r0; btst r0 by K_BPOS_PSCINT_SF; /* check if it is a single bit failure*/ if sz jump (dmpsc_test_df); /* if not, jumpt to test if it is a double bit failure*/ r1 = dm(K_DMADD_DMPSC_SFADD); /* read the address where the sf has been detected*/ i4 = r1; /* load this address in i4*/ r2 = dm(i4, 0); /* read the content of this address, the content will be corrected by EDAC*/ dm(i4, 0) = r2; /* write the corrected content at this address*/ /* store last sf error */ i4 = dm(_gpMemoryScrubbing); /* load the address of gpMemoryScrubbing into i4 */ r4 = dm(2, i4); /* the index where to store the next SF error address */ r2 = 6; /* the base address of the array containing the last error addresses */ r2 = r2 + r4; /* the offset between gpMemoryScrubbing and the place where to store the error address */ m4 = r2; dm(m4, i4) = r1; /* store the faulty address */ r4 = r4 + 1; r2 = MEMORY_SCRUBBING_BUFFER_SIZE ; comp(r4, r2); if lt jump(dmpsc_test_sf_2); r4 = 0; dmpsc_test_sf_2: dm(2, i4) = r4; r4 = dm(K_DMADD_DMPSC_INTRST); /* reset the interrupt */ r4 = bset r4 by K_BPOS_PSCINT_SF; dm(K_DMADD_DMPSC_INTRST) = r4; dmpsc_test_df: btst r0 by K_BPOS_PSCINT_DF; /* check if it is a double bit failure*/ if sz jump (dmpsc_end_isr); r1 = dm(K_DMADD_DMPSC_DFADD); /* read the address where the sf has been detected*/ /* store last sf error */ i4 = dm(_gpMemoryScrubbing); /* load the address of gpMemoryScrubbing into i4 */ r4 = dm(4, i4); /* the index where to store the next DF error address */ r2 = (2*MEMORY_SCRUBBING_BUFFER_SIZE +6);/* the base address of the array containing the last error addresses */ r2 = r2 + r4; /* the offset between gpMemoryScrubbing and the place where to store the error address */ m4 = r2; dm(m4, i4) = r1; /* store the faulty address */ r4 = r4 + 1; r2 = MEMORY_SCRUBBING_BUFFER_SIZE; comp(r4, r2); if lt jump(dmpsc_test_df_2); r4 = 0; dmpsc_test_df_2: dm(4, i4) = r4; r4 = dm(K_DMADD_DMPSC_INTRST); /* reset the interrupt */ r4 = bset r4 by K_BPOS_PSCINT_SF; r4 = bset r4 by K_BPOS_PSCINT_DF; dm(K_DMADD_DMPSC_INTRST) = r4; dmpsc_end_isr: /***********************/ /*Handle SMCS Interrupt*/ /***********************/ r4 = dm(_gSmcs2IsrCount); r4 = r4 + 1; dm(_gSmcs2IsrCount) = r4; /*reset the SMCS interrupt*/ r4 = dm(K_DMADD_DMPSC_INTRST); r4 = bset r4 by 3; dm(K_DMADD_DMPSC_INTRST) = r4; /* read ISR register*/ i4 = K_DMADDR_BASE_SMCS2; /* absolutely need to read it this way*/ r0 = dm(0x04, i4); dm(0x7F, i4) = r0; /*dummy write command*/ dm(_gLastSmcs2ISR) = r0; /* read IMR register*/ i4 = K_DMADDR_BASE_SMCS2; /* absolutely need to read it this way*/ r2 = dm(0x08, i4); dm(0x7F, i4) = r2; /*dummy write command*/ r0 = r0 and r2; if eq jump smcs2_exit_isr; r4 = 0; /*r4 will be set to 1 if an event needs to be reported to high level software*/ r12 = 1; /*************/ /* CHANNEL 0 */ /*************/ smcs2_test_err0 : btst r0 by K_BPOS_SMCSINT_CH1_PAR_DIS_ERR; if sz jump (smcs2_test_tx0); /* if bit ERR is set*/ dm(_gaLinkParityDisconnectError + 3) = r12; r4 = 1; smcs2_test_tx0 : btst r0 by K_BPOS_SMCSINT_CH1_DATA_TXED; /* test bit TX */ if sz jump (smcs2_test_rx0); dm(_gaLinkTransmitCompleted + 3) = r12; r4 = 1; smcs2_test_rx0 : btst r0 by K_BPOS_SMCSINT_CH1_DATA_RXED; /* test bit RX */ if not sz jump (smcs2_signal_rx0); btst r0 by K_BPOS_SMCSINT_CH1_EOP_RXED; /* test bit EOP RX */ if sz jump (smcs2_test_err1); smcs2_signal_rx0 : dm(_gaLinkReceptionCompleted + 3) = r12; r4 = 1; /*************/ /* CHANNEL 1 */ /*************/ smcs2_test_err1 : btst r0 by K_BPOS_SMCSINT_CH2_PAR_DIS_ERR; if sz jump (smcs2_test_tx1); /* if bit ERR is set*/ dm(_gaLinkParityDisconnectError + 4) = r12; r4 = 1; smcs2_test_tx1 : btst r0 by K_BPOS_SMCSINT_CH2_DATA_TXED; /* test bit TX */ if sz jump (smcs2_test_rx1); dm(_gaLinkTransmitCompleted + 4) = r12; r4 = 1; smcs2_test_rx1 : btst r0 by K_BPOS_SMCSINT_CH2_DATA_RXED; /* test bit RX */ if not sz jump (smcs2_signal_rx1); btst r0 by K_BPOS_SMCSINT_CH2_EOP_RXED; /* test bit EOP RX */ if sz jump (smcs2_test_err2); smcs2_signal_rx1 : dm(_gaLinkReceptionCompleted + 4) = r12; r4 = 1; /*************/ /* CHANNEL 2 */ /*************/ smcs2_test_err2 : btst r0 by K_BPOS_SMCSINT_CH3_PAR_DIS_ERR; if sz jump (smcs2_test_tx2); /* if bit ERR is set*/ dm(_gaLinkParityDisconnectError + 5) = r12; r4 = 1; smcs2_test_tx2 : btst r0 by K_BPOS_SMCSINT_CH3_DATA_TXED; /* test bit TX */ if sz jump (smcs2_test_rx2); dm(_gaLinkTransmitCompleted + 5) = r12; r4 = 1; smcs2_test_rx2 : btst r0 by K_BPOS_SMCSINT_CH3_DATA_RXED; /* test bit RX */ if not sz jump (smcs2_signal_rx2); btst r0 by K_BPOS_SMCSINT_CH3_EOP_RXED; /* test bit EOP RX */ if sz jump (smcs2_end_isr); smcs2_signal_rx2 : dm(_gaLinkReceptionCompleted + 5) = r12; r4 = 1; smcs2_end_isr : btst r4 by 0; if sz jump (smcs2_exit_isr); r4 = dm(_gSmcs2IsrHandledCount); r4 = r4 + 1; dm(_gSmcs2IsrHandledCount) = r4; i4 = dm(_K_ArgsP); r2 = _gSemaSMCS; PRHI_STACK_PSH; smcs2_exit_isr : ENDISR1; /**************************************************************************************** ISR : _pmpsc_isr AUTHOR : AMazy USE : This is the PMPSC EDAC interrupt routine SEE ALSO : "link1355.c" ****************************************************************************************/ _pmpsc_isr: START_ISR; //save MODE1, ASTAT, r0, r1, r2, r4, r8, r12, i4, i12 /***********************/ /*Handle EDAC interrupt*/ /***********************/ r0 = pm(K_PMADD_PMPSC_INTP); /* read PMPSC interrupt register*/ btst r0 by K_BPOS_PSCINT_SF; /* check if it is a single bit failure*/ if sz jump (pmpsc_test_df); /* if not, jumpt to test if it is a double bit failure*/ r1 = pm(K_PMADD_PMPSC_SFADD); /* read the address where the sf has been detected*/ i12 = r1; /* load this address in i12*/ r2 = pm(i12, 0); /* read the content of this address, the content will be corrected by EDAC*/ pm(i12, 0) = r2; /* write the corrected content at this address*/ /* store last sf error */ i4 = dm(_gpMemoryScrubbing); /* load the address of gpMemoryScrubbing into i4 */ r4 = dm(3, i4); /* the index where to store the next SF error address */ r2 = (MEMORY_SCRUBBING_BUFFER_SIZE +6); /* the base address of the array containing the last error addresses */ r2 = r2 + r4; /* the offset between gpMemoryScrubbing and the place where to store the error address */ m4 = r2; dm(m4, i4) = r1; /* store the faulty address */ r4 = r4 + 1; r2 = MEMORY_SCRUBBING_BUFFER_SIZE ; comp(r4, r2); if lt jump(pmpsc_test_sf_2); r4 = 0; pmpsc_test_sf_2: dm(3, i4) = r4; pmpsc_test_df: btst r0 by K_BPOS_PSCINT_DF; /* check if it is a double bit failure*/ if sz jump (exit_pmpsc_isr); r1 = pm(K_PMADD_PMPSC_DFADD); /* read the address where the sf has been detected*/ /* store last sf error */ i4 = dm(_gpMemoryScrubbing); /* load the address of gpMemoryScrubbing into i4 */ r4 = dm(5, i4); /* the index where to store the next DF error address */ r2 = (3*MEMORY_SCRUBBING_BUFFER_SIZE +6);/* the base address of the array containing the last error addresses */ r2 = r2 + r4; /* the offset between gpMemoryScrubbing and the place where to store the error address */ m4 = r2; dm(m4, i4) = r1; /* store the faulty address */ r4 = r4 + 1; r2 = MEMORY_SCRUBBING_BUFFER_SIZE; comp(r4, r2); if lt jump(pmpsc_test_df_2); r4 = 0; pmpsc_test_df_2: dm(5, i4) = r4; /*reset the interrupt. This is done at the end of the routine to avoid infinite triggering of the interrupt in case of permanent error on a memory cell. If there is a permanent error, the interrupt will be raised again when we write again the memory location. Since the interrupt is reset only at the end, we will not catch it.*/ exit_pmpsc_isr: r4 = pm(K_PMADD_PMPSC_INTRST); r4 = bset r4 by K_BPOS_PSCINT_SF; r4 = bset r4 by K_BPOS_PSCINT_DF; pm(K_PMADD_PMPSC_INTRST) = r4; ENDISR1; .endseg;