/************************************************************************************ * smIntrDspListProc.c * * synopsis: This state machine controls the receipt and execution of primitive * lists received by the master DSP from a slave DSP or by a slave DSP * from the master DSP. * * in this file: smIntrDspListProc, setIntrDspAck, rstIntrDspAck, * assignIntrDspOutListRdy, getIntrDspInListRdy, getIntrDspAbort * * related files: * listManager.c: Routines which process the primitive list. * listProc.h: Defines states of the primitive list processing state machines and * the indicies of the primitive and reply list buffer structures. * * Damon Fasching, UW Madison fasching@wisconsin.cern.ch ************************************************************************************/ #include "resources.h" #include "memoryPartitions.h" #include "comRegDfns.h" #include "listProc.h" extern char genStr[]; extern TIMER_Handle timer1; /* general purpose timer, started in main() */ /* file level variables */ UINT32 intrDspListProcState= IDLE; #ifdef I_AM_MASTER_DSP UINT32 slvDspNum= 0; UINT32 findNextSlave= TRUE; #endif #pragma CODE_SECTION(smIntrDspListProc, "xcode"); #pragma CODE_SECTION(setIntrDspAck, "xcode"); #pragma CODE_SECTION(rstIntrDspAck, "xcode"); #pragma CODE_SECTION(assignIntrDspOutListRdy, "xcode"); #pragma CODE_SECTION(getIntrDspInListRdy, "icode"); #pragma CODE_SECTION(getIntrDspAbort, "xcode"); /* file function prototypes */ void setIntrDspAck(void); void rstIntrDspAck(void); void assignIntrDspOutListRdy(UINT32 outputData); UINT32 getIntrDspInListRdy(void); UINT32 getIntrDspAbort(void); /************************************************************************************ * smIntrDspListProc * * synopsis: State machine for handling primitive lists received from another DSP. * On the master it handles lists sent by the slaves. On the slaves it * handles lists sent by the master. The master DSP can only process a * list from 1 slave at a time. * * modifications/bugs * - inlined the small function goToAck-- the state machine's state is now only * modified from within smIntrDspListProc. 16.10.02 dpsf ************************************************************************************/ INT32 smIntrDspListProc() { #ifdef I_AM_MASTER_DSP UINT32 *localBfr, *slvPtr; #endif static UINT32 listIndx; UINT32 outputData= FALSE, listDone= FALSE; UINT32 listLength; INT32 status, returnCode= SUCCESS; switch (intrDspListProcState) { /* IDLE: not currently processing a primitive list */ case IDLE: /* NOTE: May want to protect this against infinite loop. In principle, * this routine should never be entered if all the slaves have their * communication with the master DSP shut off. An infinite loop here * indicates a problem somewhere else which needs attention. dpf */ #ifdef I_AM_MASTER_DSP while (findNextSlave) { ++slvDspNum; if (slvDspNum == numSlaves()) slvDspNum= 0; if (slaveIsOn(slvDspNum)) findNextSlave= FALSE; } #endif /* Check if a slave has a primitive list for the master to execute. If so, * copy the list from the slave buffer to the local buffer on the master * and begin processing. */ if (getIntrDspInListRdy()) { /* Master DSP only: Copy the list from the slave buffer for execution. * NOTE: Depends on listLength being the first entry in the buffer. */ #ifdef I_AM_MASTER_DSP if (getRodRev() == 0xe) slvPtr= (UINT32 *) 0xa0060000; else slvPtr= (UINT32 *) 0x02060000; writeSlvHPIA(slvDspNum, (UINT32) slvPtr); listLength= readSlvHPID(slvDspNum); localBfr= (UINT32 *)INTR_DSP_PRM_BFR_BASE_PRC; readSlvBlock(slvDspNum, slvPtr, localBfr, listLength); #endif /* read list header and trailer */ status= readListWrapper(INTR_DSP_LIST_PRC, PRM, &listIndx); if (status != SUCCESS) { addError(&returnCode, status, "smIntrDspListProc","readListWrapper", __FILE__, __LINE__); if (FATAL(returnCode)) { /* was: goToAck(outputData); dpsf */ assignIntrDspOutListRdy(outputData); setIntrDspAck(); intrDspListProcState= ACKNOWLEDGED; return returnCode; } } intrDspListProcState = EXECUTING; } break; /* EXECUTING: processing a primitive list */ case EXECUTING: /* execute the entire primitive list, exit cleanly if fatal error */ while ( ! (listDone || (FATAL(returnCode)) || getIntrDspAbort())) { status= execPrim(INTR_DSP_LIST_PRC, &listDone); if (status != SUCCESS) { addError(&returnCode, status, "smIntrDspListProc", "execPrim", __FILE__, __LINE__); } } /* If reply is available, add msgList wrapper, check length and on the * master copy it from the slave to the local buffer. */ outputData = replyAvailable(INTR_DSP_LIST_PRC); if (outputData) { addListWrapper(INTR_DSP_LIST_PRC, REP, listIndx); /* If list is too long, just truncate it. Receiver will have errors * processing the reply, but at least will get something. * NOTE: depends on listLength being the first entry in the buffer */ listLength= *(UINT32 *) (INTR_DSP_REP_BFR_BASE_PRC); if (listLength > INTR_DSP_REP_BFR_SZ) { newError(&returnCode, MSG_LIST_TOO_LONG, ERROR_1, "smIntrDspListProc", "Inter DSP reply list too long.\0", __FILE__, __LINE__); *(UINT32 *)(INTR_DSP_REP_BFR_BASE_PRC) = INTR_DSP_REP_BFR_SZ; listLength= *(UINT32 *)(INTR_DSP_REP_BFR_BASE_PRC); } #ifdef I_AM_MASTER_DSP if (getRodRev() == 0xe) slvPtr= (UINT32 *) 0xa0060800; else slvPtr= (UINT32 *) 0x02060800; localBfr = (UINT32 *)INTR_DSP_REP_BFR_BASE_PRC; writeSlvBlock(slvDspNum, slvPtr, localBfr, listLength); #endif } /* reinitialize list structures and finish handshake on this side */ resetPrimListStructs(INTR_DSP_LIST_PRC); /* was: goToAck(outputData); dpsf */ assignIntrDspOutListRdy(outputData); setIntrDspAck(); intrDspListProcState= ACKNOWLEDGED; break; /* ACKNOWLEDGED: list processing done and acknowledged, wait for inListRdy= 0 */ case ACKNOWLEDGED: if ( ! getIntrDspInListRdy()) { rstIntrDspAck(); #ifdef I_AM_MASTER_DSP findNextSlave= TRUE; #endif intrDspListProcState= IDLE; } break; default: break; } /* end of SM state switch */ return returnCode; } /************************************************************************************ * Utility routines to access the bits in the INTR_DSP_HSHK_WR and INTR_DSP_HSHK_RD ************************************************************************************/ #if defined(I_AM_MASTER_DSP) void setIntrDspAck() { setSlvRegBit(slvDspNum, INTR_DSP_HSHK_WR, INTR_DSP_ACK); return; } void rstIntrDspAck() { rstSlvRegBit(slvDspNum, INTR_DSP_HSHK_WR, INTR_DSP_ACK); return; } /* ----------- */ void assignIntrDspOutListRdy(UINT32 outputData) { if (outputData == FALSE) { rstSlvRegBit(slvDspNum, INTR_DSP_HSHK_WR, INTR_DSP_OUT_LIST_RDY); } else { setSlvRegBit(slvDspNum, INTR_DSP_HSHK_WR, INTR_DSP_OUT_LIST_RDY); } return; } /* ----------- */ UINT32 getIntrDspInListRdy() { return getSlvRegBit(slvDspNum, INTR_DSP_HSHK_RD, INTR_DSP_IN_LIST_RDY); } /* ----------- */ UINT32 getIntrDspAbort() { return getSlvRegBit(slvDspNum, INTR_DSP_HSHK_RD, INTR_DSP_ABORT); } #elif defined(I_AM_SLAVE_DSP) void setIntrDspAck() { SET_RBIT(INTR_DSP_HSHK_WR, INTR_DSP_ACK); return; } void rstIntrDspAck() { RST_RBIT(INTR_DSP_HSHK_WR, INTR_DSP_ACK); return; } /* ----------- */ void assignIntrDspOutListRdy(UINT32 outputData) { if (outputData == FALSE) { RST_RBIT(INTR_DSP_HSHK_WR, INTR_DSP_OUT_LIST_RDY); } else { SET_RBIT(INTR_DSP_HSHK_WR, INTR_DSP_OUT_LIST_RDY); } return; } /* ----------- */ UINT32 getIntrDspInListRdy() { return GET_RBIT(INTR_DSP_HSHK_RD, INTR_DSP_IN_LIST_RDY); } /* ----------- */ UINT32 getIntrDspAbort() { return GET_RBIT(INTR_DSP_HSHK_RD, INTR_DSP_ABORT); } #endif