/************************************************************************************ * smGetSlvTxtBuff.c * * synopsis: This is the state machine which coordinates copying slave text buffer * contents to the transfer buffer of the master DSP. * * in this file: initGetSlvTxtBuffSM, readSlvTxtBuffAddr, getSlvTxtBuffs, * smGetSlvTxtBuffs * * related files: * txtBuffer.h: tag for the TXTBUFFER structure and related constants * xferTxtBuffSM.h: defines the available text buffers ************************************************************************************/ #include "resources.h" #include "memoryPartitions.h" #include "rodConfiguration.h" #include "txtBuffer.h" #pragma CODE_SECTION(initGetSlvTxtBuffSM, "xcode"); #pragma CODE_SECTION(readSlvTxtBuffAddr, "xcode"); #pragma CODE_SECTION(getSlvTxtBuffs, "xcode"); #pragma CODE_SECTION(smGetSlvTxtBuff, "xcode"); /* states of a slave text buffer processing state machine */ #define IDLE 0 /* check if txtBuffer is occupied */ #define WAITING 1 /* buffer was occupied, waiting for permission to read */ /* slvTxtBuffAdd[m][n] is the address of the text buffer structure n for slave m. * getSlvTxtBuffState[m][n] is the current transfer state of text buffer n of slave m. */ UINT32 slvTxtBuffAdd[N_SDSP][N_TXT_BUFFS]; UINT32 getSlvTxtBuffState[N_SDSP][N_TXT_BUFFS]; /* local function prototypes */ INT32 smGetSlvTxtBuff(UINT32 slaveDsp, UINT32 buffer); /************************************************************************************ * initGetSlvTxtBuffSM * * synopsis: Initialize master DSP state machines which control readout of the slave * DSP text buffers. * * NOTE: The caller is responsible to make sure the the slave number is valid. The * code is protected to avoid a segmentation fault. The symptom of an illegal * slave number is that the slave will not be configured. ************************************************************************************/ void initGetSlvTxtBuffSM(UINT32 slvDspNum) { UINT32 txtBuffIdx; if (slvDspNum < N_SDSP) { for (txtBuffIdx = 0; txtBuffIdx < N_TXT_BUFFS; ++txtBuffIdx) { getSlvTxtBuffState[slvDspNum][txtBuffIdx]= IDLE; } } return; } /************************************************************************************ * readSlvTxtBuffAddr * * synopsis: Each slave DSP writes the addresses of its txtBuffer structures to its * reply buffer when it self-initializes after booting. When the * initialization procedure is done, it sets the RUNNING bit in the * STATUS_REG. This tells the master DSP to read the txtBuffer structure * addresses from the reply buffer. (This same protocol is used between * the master and host processor when the master is booted.) * * NOTE: The caller is responsible to make sure the the slave number is valid. The * code is protected to avoid a segmentation fault. The symptom of an illegal * slave number is that all slave text buffer addresses will not be set to the * last legal word address of IPRAM. * * arguments: * IN: slvDsp = number of the slave DSP * * modifications/bugs * - Master & slave DSPs now have different size primitive & reply buffers. The * compilation constants HOST_(PRM/REP)_BFR_(BASE/SZ) in memoryPartitions.h have * been replaced with different sets for the two DSP types. 10.12.02 dpsf ************************************************************************************/ void readSlvTxtBuffAddr(UINT32 slvDspNum) { UINT32 bufferIdx, sdspAddr; if (slvDspNum < (N_SDSP)) { if (getRodRev() == 0xe) sdspAddr= 0xa0082000; else sdspAddr= 0x02082000; writeSlvHPIA(slvDspNum, sdspAddr); for (bufferIdx= 0; bufferIdx < (N_TXT_BUFFS -1); ++bufferIdx) { slvTxtBuffAdd[slvDspNum][bufferIdx] = readSlvHPID_I(slvDspNum); } slvTxtBuffAdd[slvDspNum][bufferIdx] = readSlvHPID(slvDspNum); } else { for (slvDspNum= 0; slvDspNum < N_SDSP; ++slvDspNum) { for (bufferIdx= 0; bufferIdx < N_TXT_BUFFS; ++bufferIdx) { slvTxtBuffAdd[slvDspNum][bufferIdx] = (UINT32)(IPRAM_BASE +IPRAM_SZ -4); } } } return; } /************************************************************************************ * getSlvTxtBuffs * * synopsis: Calls smGetSlvTxtBuff for each text buffer of a slave DSP. * * arguments: * IN: slvDsp = number of the slave DSP ************************************************************************************/ INT32 getSlvTxtBuffs(UINT32 slaveNumber) { INT32 returnCode= SUCCESS, error; UINT32 bufferIdx; for (bufferIdx = 0; bufferIdx < N_TXT_BUFFS; ++bufferIdx) { error= smGetSlvTxtBuff(slaveNumber, bufferIdx); if (error < 0) { addError(&returnCode, error, "getSlvTxtBuffs", "smGetSlvTxtBuff", __FILE__, __LINE__); if (FATAL(returnCode)) { return returnCode; } } } return returnCode; } /************************************************************************************ * smGetSlvTxtBuff * * synopsis: State machine for copying a slave text buffer into the transfer buffer. * * arguments: * IN: slvDsp = number of the slave DSP * buffer = number of the text buffer, defined in smSendTxtBuff.h * * modifications/bugs * - Mark the buffer as occupied in the status register (to speed * up the main polling loop; it does not have to make a call). 07.11.02 dpsf ************************************************************************************/ INT32 smGetSlvTxtBuff(UINT32 slvDsp, UINT32 buffer){ INT32 returnCode= SUCCESS; UINT32 nDataWords, *slvPtr, *xferPtr; char *mstrXferBfrDataPtr; extern struct TXTBUFFER xferBuffer; switch (getSlvTxtBuffState[slvDsp][buffer]){ /* IDLE: If the slave text buffer is Not Empty, request permission to read it, * by setting the Read Request bit. */ case IDLE: if (getSlvTxtBuffNE(slvDsp, buffer)) { setSlvTxtBuffRR(slvDsp, buffer); getSlvTxtBuffState[slvDsp][buffer] = WAITING; } break; /* WAITING: Have indicated to the slave that you are ready to read this buffer, * waiting for the OK, indicated by the slave resetting the Not Empty * bit. When this happens, copy this slave text buffer into the * transfer buffer on the master DSP. */ case WAITING: /* First check that the master DSP xfer buffer is not occupied. */ if (xferBuffer.state == BUFFER_EMPTY) { if (!getSlvTxtBuffNE(slvDsp, buffer)) { /* Copy slave text buffer structure into the xfer buffer struct */ /* 1st store the address of the master DSP xferBuffer data */ mstrXferBfrDataPtr= xferBuffer.data; /* Copy the slave text buffer struct into the master xfer buffer struct. * NOTE: This does not copy the buffer, just the structure which describes * the current state of the buffer. */ readSlvBlock(slvDsp, (UINT32 *) slvTxtBuffAdd[slvDsp][buffer], (UINT32 *) &xferBuffer, SIZEOF(struct TXTBUFFER)); /* Store the address of the slave text buffer data area in readBase. */ slvPtr= (UINT32 *) xferBuffer.data; /* Restore the address of the master xfer buffer in the xfer buffer struct * The host needs this to read the master xfer buffer, just as the master * needs the location of the slave text buffer in order to read it. */ xferBuffer.data= mstrXferBfrDataPtr; xferBuffer.id= XFER_BUFF; /* Just to be safe, restore id too. dpsf */ /* Get the offset from the buffer base of the last word written (txtBuffer * write routines word pad messages). "writeIndx" is the offset of the next * available byte, so the last word written is offset by (writeIndx - 4). * writeIndx == 0 is a special case. This means that the last word written * was the last available word in the buffer, which is offset by dataEnd. * In that case, the offset of the last word is (dataEnd - 3). */ if (xferBuffer.writeIndx == 0) { newError(&returnCode, TEXT_OVERFLOW_ERROR, FATAL_ERR, "smGetSlvTxtBuff", "The transfer buffer is full!", __FILE__, __LINE__); return returnCode; } else { nDataWords= (xferBuffer.writeIndx -xferBuffer.readIndx)>>2; } /* Now read the buffer. xferBuffer.data points to the base of the buffer * data, a char array. If the readIndx (beginning of data to be read) is * less than the index of the last word written, read from readIndx to * lastWordIndx. */ if (xferBuffer.readIndx <= (xferBuffer.writeIndx -4) ) { xferPtr= (UINT32 *) xferBuffer.data; if (xferBuffer.readIndx != 0) { newError(&returnCode, PARAM_ERROR, FATAL_ERR, "smGetSlvTxtBuff", "readindex != 0?", __FILE__, __LINE__); return returnCode; } readSlvBlock(slvDsp, slvPtr, xferPtr, nDataWords); } /* If the readIndx is greater than the index of the last word written, * there has been a wrap-around. Read from readIndx to the buffer end and * then from the buffer start to lastWordIndx. */ else { newError(&returnCode, TEXT_OVERFLOW_ERROR, FATAL_ERR, "smGetSlvTxtBuff", "Whoa- the transfer buffer wrapped!", __FILE__, __LINE__); return returnCode; } /* Finish off the handshake, e.g. clear the read request bit. * Go to IDLE */ rstSlvTxtBuffRR(slvDsp, buffer); getSlvTxtBuffState[slvDsp][buffer]= IDLE; setTxtBuffProc(xferBuffer.id); /* Indicate to host know that there is data */ } /* slave's buffer has data */ } /* master's xfer buffer is empty; ready for more data */ break; default: break; } /* end of switch */ return returnCode; }