/************************************************************************************ * smIntrDspListSend.c * * synopsis: This state machine controls sending a primitive list to another DSP to * execute, i.e. the master DSP builds and sends a list to a slave DSP or * a slave DSP builds and sends a list to the master DSP. * * in this file: smIntrDspListSend, intrDspListSendIdle, replyDataAvail, * initiateListSendSM, setIntrDspInLisdtRdy, rstIntrDspInListRdy, * getIntrDspAck, getIntrDspOutListRdy * * 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 "rodConfiguration.h" #include "memoryPartitions.h" #include "comRegDfns.h" #include "listProc.h" /* states */ #define LIST_IDLE 0 #define LIST_SENT 1 #define LIST_DEACTIVATE 2 extern TIMER_Handle timer1; /* general purpose timer, started in main() */ /* file level variables */ UINT32 intrDspListSendState= LIST_IDLE; UINT32 listReady= FALSE; UINT32 replyAvail; #ifdef I_AM_MASTER_DSP UINT32 slaveNumber; #endif #pragma CODE_SECTION(smIntrDspListSend, "xcode"); #pragma CODE_SECTION(intrDspListSendIdle, "icode"); #pragma CODE_SECTION(replyDataAvail, "xcode"); #pragma CODE_SECTION(initiateListSendSM, "xcode"); #pragma CODE_SECTION(setIntrDspInListRdy, "xcode"); #pragma CODE_SECTION(rstIntrDspInListRdy, "xcode"); #pragma CODE_SECTION(getIntrDspAck, "xcode"); #pragma CODE_SECTION(getIntrDspOutListRdy, "xcode"); /* file function prototypes */ void setIntrDspInListRdy(void); void rstIntrDspInListRdy(void); UINT32 getIntrDspAck(void); UINT32 getIntrDspOutListRdy(void); /************************************************************************************ * smIntrDspListSend * * synopsis: State machine to control sending a primitive list to another DSP to * execute. * * modifications/bugs * - Added a new state to the SM: deactivate. A bit in the status register is * raised by initiateListSendSM; this then allows the inter-DSP list send state * machine to be called inside the main polling loop (to decrease overhead, * all the subroutines in the main loop are not called unless needed). The * inter-DSP list processing register bit is also raised on the other processor. * (For slaves: the master DSP polls the slave's status registers & sets its own * status register bit according to the state of the slave register bits. For * master: the appropriate slave's command register bit is set. Thus there are * actually different inter-DSP list processing bits for master and slave DSPs * in the status and command registers respectively, due to the differences in * the way they communicate). The inter-DSP lists for both processors are turned * off after the end of the handshake by the deactivate state. 14.10.02 dpsf ************************************************************************************/ INT32 smIntrDspListSend() { #ifdef I_AM_MASTER_DSP UINT32 *localBfr, *slvPtr; #endif UINT32 listLength; INT32 returnCode= SUCCESS; switch (intrDspListSendState) { case LIST_IDLE: /* currently no sent lists are active */ if (listReady) { /* Check if there is a list ready to send. */ listReady= replyAvail= FALSE; /* read and check the list length. NOTE: This depends on listLength * being the first entry in the buffer. */ listLength= *((UINT32 *) (INTR_DSP_PRM_BFR_BASE_SND)); if (listLength > INTR_DSP_PRM_BFR_SZ) { newError(&returnCode, MSG_LIST_TOO_LONG, FATAL_ERR, "smIntrDspListSend","Outgoing intrDspPrimList too long\0", __FILE__, __LINE__); return returnCode; } /* Master DSP only: Copy the list to the slave buffer for execution. */ #ifdef I_AM_MASTER_DSP if (getRodRev() == 0xe) slvPtr= (UINT32 *) 0xa0061000; else slvPtr= (UINT32 *) 0x02061000; localBfr= (UINT32 *) INTR_DSP_PRM_BFR_BASE_SND; writeSlvBlock(slaveNumber, slvPtr, localBfr, listLength); #endif /* set inListRdy and go to LIST_SENT */ setIntrDspInListRdy(); intrDspListSendState= LIST_SENT; } break; case LIST_SENT: /* waiting for acknowledge from the DSP executing the list */ /* check if the destination DSP has finished executing the list */ if (getIntrDspAck()) { /* check if there is reply data, if so... maybe do something with it */ if (getIntrDspOutListRdy()) { replyAvail= TRUE; /* if master copy the slave reply to the local buffer. NOTE: this * depends on listLength being the first entry in the buffer */ #ifdef I_AM_MASTER_DSP localBfr = (UINT32 *)INTR_DSP_REP_BFR_BASE_SND; if (getRodRev() == 0xe) slvPtr= (UINT32 *) 0xa0061800; else slvPtr= (UINT32 *) 0x02061800; writeSlvHPIA(slaveNumber, (UINT32) slvPtr); listLength= readSlvHPID(slaveNumber); readSlvBlock(slaveNumber, slvPtr, localBfr, listLength); #endif } /* finish the handshake, reset buffer structures and go back * to LIST_IDLE */ rstIntrDspInListRdy(); resetPrimListStructs(INTR_DSP_LIST_SND); intrDspListSendState= LIST_DEACTIVATE; } break; case LIST_DEACTIVATE: /* turn off the bits in the cmd & stat registers. */ if (!getIntrDspAck()) { RST_RBIT(STATUS_REG_0, SR_IDLS_ACTIVE); #ifdef I_AM_MASTER_DSP rstSlvRegBit(slaveNumber, COMMAND_REG_0, CR_IDLP_ACTIVE); #endif intrDspListSendState= LIST_IDLE; } break; default: break; } /* end of SM state switch */ return returnCode; } /************************************************************************************ * intrDspListSendIdle() * * synopsis: Returns 1/0 if the state machine is idle/notIdle ************************************************************************************/ UINT32 intrDspListSendIdle() { return ((intrDspListSendState == (LIST_IDLE)) && !listReady); } /************************************************************************************ * replyDataAvail() * * synopsis: Returns 1/0 if there is a reply to the primitive list ************************************************************************************/ UINT32 replyDataAvail() { return replyAvail; } /************************************************************************************ * initiateListSendSM * * synopsis: starts the state machine by setting the listReady flag * * arguments: * IN: slaveNumber - Master dsp only this is the slave number. * * modifications/bugs * - Activate the routines by setting a bit in the status register (and for the * master DSP, in the slave's command register); see the comment for * smIntrDspListSend. 15.02.02 dpsf ************************************************************************************/ #if defined(I_AM_MASTER_DSP) void initiateListSendSM(UINT32 sdsp) { slaveNumber= sdsp; listReady= TRUE; SET_RBIT(STATUS_REG_0, SR_IDLS_ACTIVE); setSlvRegBit(slaveNumber, COMMAND_REG_0, CR_IDLP_ACTIVE); return; } #elif defined(I_AM_SLAVE_DSP) void initiateListSendSM(UINT32 dummy) { listReady= TRUE; SET_RBIT(STATUS_REG_0, SR_IDLS_ACTIVE); /* master will discover slave's IDLS_ACTIVE bit is set during polling, and set its own IDLP_ACTIVE bit. */ return; } #endif /************************************************************************************ * Utility routines to access the bits in the INTR_DSP_HSHK_WR and INTR_DSP_HSHK_RD ************************************************************************************/ #if defined(I_AM_MASTER_DSP) void setIntrDspInListRdy() { setSlvRegBit(slaveNumber, INTR_DSP_HSHK_WR,INTR_DSP_IN_LIST_RDY); return; } void rstIntrDspInListRdy() { rstSlvRegBit(slaveNumber, INTR_DSP_HSHK_WR, INTR_DSP_IN_LIST_RDY); return; } /* ----------- */ UINT32 getIntrDspAck() { return getSlvRegBit(slaveNumber, INTR_DSP_HSHK_RD, INTR_DSP_ACK); } /* ----------- */ UINT32 getIntrDspOutListRdy() { return getSlvRegBit(slaveNumber, INTR_DSP_HSHK_RD, INTR_DSP_OUT_LIST_RDY); } #elif defined(I_AM_SLAVE_DSP) void setIntrDspInListRdy() { SET_RBIT(INTR_DSP_HSHK_WR, INTR_DSP_IN_LIST_RDY); return; } void rstIntrDspInListRdy() { RST_RBIT(INTR_DSP_HSHK_WR, INTR_DSP_IN_LIST_RDY); return; } /* ----------- */ UINT32 getIntrDspAck() { return GET_RBIT(INTR_DSP_HSHK_RD, INTR_DSP_ACK); } /* ----------- */ UINT32 getIntrDspOutListRdy() { return GET_RBIT(INTR_DSP_HSHK_RD, INTR_DSP_OUT_LIST_RDY); } #endif