/************************************************************************************ * listManager.c * * synopsis: This file contains routines which handle incoming primitive lists and * outgoing reply lists * * in this file: initPrimListStructs, resetPrimListStructs, initPrimParams, * readListWrapper, getNewListInfo, getPrimIndex, execPrim, * checkPrimHeader, addListWrapper, updateListBfr, replyAvailable, * addMessage, addReplyData, addPrimData, getReplyMsg, loadSlaveList, * storeReplyParams, getReplyDest, copySlvReply * * related files: * smHostListProc.c: state machine for reading and executing primitive lists and * sending reply lists * msgBuff.c: Contains some routines involved in reading a primitive list. * msgBuff.h: Contains prototypes of routines which are in msgBuff.c. Contains the * structure tags which describe the primitive list buffer. * primFuncts.c: Contains primitive execution functions and the function which * initializes the array of pointers to the primitive execution * functions. * primFuncts.h: Declares the structure tag which communicates necessary information * to primitive functions. * primParams.h: Defines primitive ids which are used to index the array of pointers * to primitive functions, structure tags for primitive data and reply * data, and prototypes of primitive functions. * 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 #include #include #include #include "resources.h" #ifdef I_AM_MASTER_DSP #include "rodMemoryMap.h" #endif #include "primFuncts.h" #include "listProc.h" #include "msgBuff.h" #define LIST_DONE(x,y) (msgList[x][y].msgCounter == msgList[x][y].head.numMsgs) #define BFR_OFFSET(x,y) (msgList[x][y].rwPtr - msgList[x][y].base) extern char genStr[]; extern TIMER_Handle timer1; /* general purpose timer, started in main() */ #pragma CODE_SECTION(initPrimListStructs, "xcode"); #pragma CODE_SECTION(resetPrimListStructs, "xcode"); #pragma CODE_SECTION(initPrimParams, "xcode"); #pragma CODE_SECTION(readListWrapper, "xcode"); #pragma CODE_SECTION(getNewListInfo, "xcode"); #pragma CODE_SECTION(getPrimIndex, "xcode"); #pragma CODE_SECTION(execPrim, "xcode"); #pragma CODE_SECTION(checkPrimHeader, "xcode"); #pragma CODE_SECTION(addListWrapper, "xcode"); #pragma CODE_SECTION(updateListBfr, "xcode"); #pragma CODE_SECTION(replyAvailable, "xcode"); #pragma CODE_SECTION(addMessage, "xcode"); #pragma CODE_SECTION(addReplyData, "xcode"); #pragma CODE_SECTION(getReplyMsg, "xcode"); #ifdef I_AM_MASTER_DSP #pragma CODE_SECTION(loadSlaveList, "xcode"); #pragma CODE_SECTION(storeReplyParams, "xcode"); #pragma CODE_SECTION(getReplyDest, "xcode"); #pragma CODE_SECTION(copySlvReply, "xcode"); #endif /* file scope variables: */ /* primParameters is an array of structures of type PRIM_PARAMETERS. There is an * array element for each available primitive ID. PRIM_PARAMETERS has 2 elements: * - primParameters[ID].primFunction: pointer to primitive function of primitive ID * - primParameters[ID].primRevision: revision of primitive structures of primitive ID * * The primitive functions are of type INT32 and take a single argument of type * 'PrimData *'. All primitive routines must conform to this prototype. * * execPrim() branches to the routine primParameters[ID].primFunction(). * The address of primFunction for each ID is assigned to the location of the * appropriate function in initializePrimParameters. * primIDList is a lookup table; translating the primitive IDs into indices in * the primParameters structure array. */ struct PRIM_PARAMETERS primParameters[NUM_PRIMITIVES]; UINT32 primIDList[NUM_PRIMITIVES]; /* msgList describes the primtive and reply buffers */ #ifndef COMPACT #define N_MSG_BFRS 3 #else #define N_MSG_BFRS 1 #endif struct MSG_LIST msgList[N_MSG_BFRS][2]; /* header of current primitive being executed */ struct MSG_HEAD primHead; /* Current revision number of primParams.h */ UINT32 listRevision; /* The following arrays are used to store the parameters of a sendSlaveList primitive * so that they can be used to generate the slave reply list header if required. */ #ifdef I_AM_MASTER_DSP struct MSG_HEAD primHeadStore[N_SDSP]; UINT32 *slaveReplyAdr[N_SDSP]; #endif /* file scope function prototypes: */ INT32 checkPrimHeader(UINT32 buffNum); INT32 updateListBfr(UINT32 buffNum, UINT32 buffIdx, struct MSG_HEAD listHead); /************************************************************************************ * initPrimListStructs * * synopsis: Initializes the primitive and reply list structures. * The structure elements are: * *base: fixed to base address of primitive list partition * buffSize: size of buffer in words * *rwPtr: init to start of 1st primitive * msgCounter: init to 0, counts primitives executed * checksumWC: init to check all, num of words in checksum * checksum: locally calculated checksum * head.length: read from list head, length in words of list * head.index: read from list head, primitive list index * head.numMsgs: read from list head, number of prims in list * head.primListRevision: read from list head, revision of available primitives * tail.length: read from list tail, should match head.length * tail.checksum: read from list tail * * 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 initPrimListStructs() { UINT32 bfrNum, bfrIdx; /* initialize buffer structures for primitive lists from the host */ #if defined(I_AM_MASTER_DSP) msgList[HOST_LIST][PRM].base = (UINT32 *)(MDSP_PRM_BFR_BASE); msgList[HOST_LIST][PRM].buffSize = (MDSP_PRM_BFR_SZ) / 4; msgList[HOST_LIST][REP].base = (UINT32 *)(MDSP_REP_BFR_BASE); msgList[HOST_LIST][REP].buffSize = (MDSP_REP_BFR_SZ) / 4; #elif defined(I_AM_SLAVE_DSP) msgList[HOST_LIST][PRM].base = (UINT32 *)(SDSP_PRM_BFR_BASE); msgList[HOST_LIST][PRM].buffSize = (SDSP_PRM_BFR_SZ) / 4; msgList[HOST_LIST][REP].base = (UINT32 *)(SDSP_REP_BFR_BASE); msgList[HOST_LIST][REP].buffSize = (SDSP_REP_BFR_SZ) / 4; #endif #ifndef COMPACT /* initialize buffer structures for primitive lists from another DSP */ msgList[INTR_DSP_LIST_PRC][PRM].base = (UINT32 *)(INTR_DSP_PRM_BFR_BASE_PRC); msgList[INTR_DSP_LIST_PRC][PRM].buffSize = (INTR_DSP_PRM_BFR_SZ) / 4; msgList[INTR_DSP_LIST_PRC][REP].base = (UINT32 *)(INTR_DSP_REP_BFR_BASE_PRC); msgList[INTR_DSP_LIST_PRC][REP].buffSize = (INTR_DSP_REP_BFR_SZ) / 4; /* initialize buffer structures for primitive lists to another DSP */ msgList[INTR_DSP_LIST_SND][PRM].base = (UINT32 *)(INTR_DSP_PRM_BFR_BASE_SND); msgList[INTR_DSP_LIST_SND][PRM].buffSize = (INTR_DSP_PRM_BFR_SZ) / 4; msgList[INTR_DSP_LIST_SND][REP].base = (UINT32 *)(INTR_DSP_REP_BFR_BASE_SND); msgList[INTR_DSP_LIST_SND][REP].buffSize = (INTR_DSP_REP_BFR_SZ) / 4; #endif for (bfrNum = 0; bfrNum < N_MSG_BFRS; ++bfrNum) { for (bfrIdx = 0; bfrIdx < 2; ++bfrIdx) { msgList[bfrNum][bfrIdx].rwPtr = msgList[bfrNum][bfrIdx].base + SIZEOF(struct MSG_LIST_HEAD); msgList[bfrNum][bfrIdx].msgCounter = 0; msgList[bfrNum][bfrIdx].checksumWC = 0xFFFFFFFF; } } return; } /************************************************************************************ * resetPrimListStructs * * synopisis: resets some of the msgList structure elements after * primitive list execution is completed. ************************************************************************************/ void resetPrimListStructs(UINT32 buffNum) { UINT32 bfrIdx; for (bfrIdx = 0; bfrIdx < 2; ++bfrIdx) { msgList[buffNum][bfrIdx].rwPtr = msgList[buffNum][bfrIdx].base + SIZEOF(struct MSG_LIST_HEAD); msgList[buffNum][bfrIdx].msgCounter = 0; } return; } /************************************************************************************ * initPrimParams * * synopsis: This routine is called from the master initialization routine on start * up. It in turn calls initializePrimParams which initializes the * primParameters array of structures which has primitive version number and * pointer to primitive function as elements. ************************************************************************************/ void initPrimParams(void) { initializePrimParams(primIDList, primParameters, &listRevision); return; } /************************************************************************************ * readListWrapper * * synopsis: Called when a new primitive list has been written to the prim list buff. * Calls the general routine for extracting the list info (index, length, * numPrims, checksum and primitive data revision.) * Performs error checks on the list (length, checksum, etc) * * arguments: * IN: buffNum = which primitive list buffer has a new primitive list to execute * In the slave DSPs there is only one primitive list buffer, the one * which is written to by the master DSP. In the master DSP there * are several, a large one which is written to by the host and one * smaller buffer for each slave DSP to send instruction lists. * * OUT: index = the primitive list index ************************************************************************************/ INT32 readListWrapper(UINT32 buffNum, UINT32 buffIdx, UINT32 *index) { INT32 error, returnCode; returnCode = SUCCESS; error = getNewListInfo(&msgList[buffNum][buffIdx]); *index = msgList[buffNum][buffIdx].head.index; if (error < 0) { addError(&returnCode, error, "readListWrapper", "getNewListInfo", __FILE__, __LINE__); if (FATAL(returnCode)) { return returnCode; } } /* check that the sender and receiver have same version of the list structure */ if (listRevision != msgList[buffNum][buffIdx].head.primListRevision) { newError(&returnCode, PRIM_LIST_REV_MISMATCH, FATAL_ERR, "readListWrapper", "primitive list version mismatch, compile with current primParams.h", __FILE__, __LINE__); return returnCode; } return returnCode; } /************************************************************************************ * getNewListInfo * * synopsis: Copies the header and trailer of an incoming message list into the head * and tail structures of the structures which describe message buffer. * Performs error checks on the list (length, checksum, etc) * * arguments: * IN/OUT: listPtr: pointer to MSG_LIST structure which describes the message buffer * OUT: index: the message list index ************************************************************************************/ INT32 getNewListInfo(struct MSG_LIST *listPtr) { INT32 returnCode = SUCCESS; UINT32 *tailPtr; INT32 checksumWC; UINT32 *baseAddress; /* read the list header information */ *(&listPtr->head) = *((struct MSG_LIST_HEAD *)listPtr->base); /* Check that list length is within bounds */ if (listPtr->head.length > listPtr->buffSize) { newError(&returnCode, MSG_LIST_TOO_LONG, FATAL_ERR, "getNewListInfo", "message list too long, possible memory overwrite!\0", __FILE__,__LINE__); return returnCode; } /* Read the list trailer information */ tailPtr = listPtr->base + listPtr->head.length - SIZEOF(struct MSG_LIST_TAIL); *(&listPtr->tail) = *((struct MSG_LIST_TAIL *)tailPtr); /* Check that the length parameter in the head and the tail are the same */ if (listPtr->head.length != listPtr->tail.length) { newError(&returnCode, MSG_LIST_LENGTH_MISMATCH, FATAL_ERR, "getNewListInfo", "header and trailer list lengths don't match\0", __FILE__, __LINE__); return returnCode; } /* If checksumWC != 0 calculate the checksum and verify that it matches the * transmitted checksum from the list trailer. */ if (listPtr->checksumWC != 0) { MINI(listPtr->checksumWC, *(listPtr->base)-1, checksumWC); baseAddress = listPtr->base; listPtr->checksum = calculateChecksum(baseAddress, checksumWC); if (listPtr->checksum != listPtr->tail.checksum) { sprintf(genStr, "checksum error: list= 0x%08x, calc= 0x%08x.\n", listPtr->tail.checksum, listPtr->checksum); newError(&returnCode, CHECKSUM_ERROR, FATAL_ERR, "getNewListInfo", genStr, __FILE__,__LINE__); return returnCode; } } return returnCode; } /************************************************************************************ * getPrimIndex * * synopsis: Reads the header of the next primitive and returns the index of the * primitive. * * arguments * IN: buffNum = Identifies current primitive list buffer. * OUT: index is the primitive index ************************************************************************************/ void getPrimIndex(UINT32 buffNum, UINT32 *index) { primHead = *((struct MSG_HEAD *)msgList[buffNum][PRM].rwPtr); *index = primHead.index; return; } /************************************************************************************ * execPrim * * synopsis: Executes a single primitive. * * arguments * IN: buffNum = Identifies current primitive list buffer. * OUT: listDone indicates to the calling routine that the last primitive has been * executed * * modifications/bugs * - The primitive IDs have been decoupled from the list structure, so that * primitive lists on the vme host do not have to be re-written with each * insertion of a primitive (alternative was to always tack onto the end, * which eventually will lead to confusion). This demands a new array which * stores the IDs. 16.04.02 dpsf ************************************************************************************/ INT32 execPrim(UINT32 buffNum, UINT32 *listDone) { INT32 status, returnCode = SUCCESS, idx, idMatch; PrimData primData; struct MSG_HEAD repHead; primHead = *((struct MSG_HEAD *)msgList[buffNum][PRM].rwPtr); status = checkPrimHeader(buffNum); if (status < 0) { addError(&returnCode, status, "execPrim", "checkPrimHeader",__FILE__, __LINE__); if (FATAL(returnCode)) { return returnCode; } } /* if all ok, load the primData struct */ primData.priBodyLength= primHead.length -(SIZEOF(struct MSG_HEAD)); primData.priBodyPtr = msgList[buffNum][PRM].rwPtr +(SIZEOF(struct MSG_HEAD)); primData.repBodyLength= 0; primData.repBodyPtr = msgList[buffNum][REP].rwPtr +(SIZEOF(struct MSG_HEAD)); primData.repBuffEnd = msgList[buffNum][REP].base +msgList[buffNum][REP].buffSize; /* Now call the primitive function */ for (idMatch= 0xffff, idx= 0; idx < NUM_PRIMITIVES; ++idx) { if (primIDList[idx]== primHead.id) {idMatch= idx;} } status= primParameters[idMatch].fxnValidate(primHead.primRevision, &primData); if (status != SUCCESS) { addError(&returnCode, status, "execPrim", "validate prim", __FILE__, __LINE__); return returnCode; } /* invalid primitive IDs were already guarded against in checkPrimHeader */ status = primParameters[idMatch].primFunction(&primData); if (status < 0) { addError(&returnCode, status, "execPrim", "primParameters[].primFunction\0", __FILE__, __LINE__); } /* If the primitive did not return REPEAT_PRIMITIVE process reply, etc... */ if (status != REPEAT_PRIMITIVE) { if (primData.repBodyLength != 0) { repHead = primHead; repHead.length = primData.repBodyLength + SIZEOF(struct MSG_HEAD); *(struct MSG_HEAD *)msgList[buffNum][REP].rwPtr = repHead; status = updateListBfr(buffNum, REP, repHead); if (status < 0) { addError(&returnCode, status, "execPrim", "updateListBfr", __FILE__,__LINE__); } } /* increment the primitive counter and the read pointer */ status = updateListBfr(buffNum, PRM, primHead); if (status < 0) { addError(&returnCode, status, "execPrim","updateListBfr",__FILE__,__LINE__); } /* in case of fatal error or last primtive, set listDone return argument */ if (LIST_DONE(buffNum, PRM) || (FATAL(returnCode))) { *listDone = 1; } /* if entire list was processed check read ptr is consistent with listLength*/ if (LIST_DONE(buffNum, PRM)) { if (BFR_OFFSET(buffNum, PRM) + SIZEOF(struct MSG_LIST_TAIL) != msgList[buffNum][PRM].head.length) { newError(&returnCode, END_OF_LIST_ADDR_ERR, ERROR_1, "execPrim", "primitive list length != header list length", __FILE__, __LINE__); } } } /* not repeating primitive */ return returnCode; } /************************************************************************************ * checkPrimHeader * * synopsis: Checks the parameters in the primitive header. * * modifications/bugs * - The primitive IDs have been decoupled from the list structure, so that * primitive lists on the vme host do not have to be re-written with each * insertion of a primitive (alternative was to always tack onto the end, * which eventually will lead to confusion). This demands a new array which * stores the IDs. 16.04.02 dpsf ************************************************************************************/ INT32 checkPrimHeader(UINT32 buffNum) { INT32 returnCode = SUCCESS, idx, idMatch; /* check that this primitive does not exceed list bounds */ if ( BFR_OFFSET(buffNum, PRM) + primHead.length + (SIZEOF(struct MSG_LIST_TAIL)) > msgList[buffNum][PRM].head.length ) { newError(&returnCode, MSG_EXCEEDS_LIST_BOUND, FATAL_ERR, "checkPrimHeader", "primitive exceeds list bound", __FILE__, __LINE__); return returnCode; } /* check that the primitive id is valid */ for (idMatch= 0xffff, idx= 0; idx < NUM_PRIMITIVES; ++idx) { if (primIDList[idx]== primHead.id) {idMatch= idx;} } if (idMatch==0xffff) { sprintf(genStr, "Invalid primitive ID (0x%x).\n", primHead.id); newError(&returnCode, ILLEGAL_PRIM_ID, FATAL_ERR, "checkPrimHeader", genStr, __FILE__, __LINE__); return returnCode; } /* check that the primitive revision number has been set */ if (primParameters[idMatch].primRevision == UNINITIALIZED_PRIM) { sprintf(genStr, "%s 0x%x, %s", "Version has not been set for ID", primHead.id, "check initializePrimParams().\n"); newError(&returnCode, PRIM_REV_NOT_SET, FATAL_ERR, "checkPrimHeader", genStr, __FILE__, __LINE__); return returnCode; } /* check that the sender and receiver have same version of this primitive */ if (primParameters[idMatch].primRevision != primHead.primRevision) { sprintf(genStr, "%s 0x%x %s %d %d %s", "Version mismatch for ID", primHead.id, "(Vers. DSP & list:", primParameters[idMatch].primRevision, primHead.primRevision, ") => compile with current primParams.h\n"); newError(&returnCode, PRIM_REV_MISMATCH, FATAL_ERR, "checkPrimHeader", genStr, __FILE__, __LINE__); return returnCode; } return returnCode; } /************************************************************************************ * addListWrapper * * synopsis: Adds the head and tail to a msgList ************************************************************************************/ void addListWrapper(UINT32 buffNum, UINT32 buffIdx, UINT32 index) { UINT32 *tailPtr; UINT32 *baseAddress; INT32 checksumWC; msgList[buffNum][buffIdx].head.index = index; msgList[buffNum][buffIdx].head.primListRevision = listRevision; msgList[buffNum][buffIdx].head.numMsgs = msgList[buffNum][buffIdx].msgCounter; msgList[buffNum][buffIdx].head.length = BFR_OFFSET(buffNum, buffIdx) + SIZEOF(struct MSG_LIST_TAIL); msgList[buffNum][buffIdx].tail.length = msgList[buffNum][buffIdx].head.length; /* write header to the buffer */ *((struct MSG_LIST_HEAD *)msgList[buffNum][buffIdx].base) = msgList[buffNum][buffIdx].head; /* write the reply list trailer, not checksum yet */ tailPtr = msgList[buffNum][buffIdx].base + msgList[buffNum][buffIdx].head.length - SIZEOF(struct MSG_LIST_TAIL); *((struct MSG_LIST_TAIL *)tailPtr) = msgList[buffNum][buffIdx].tail; /* calculate the checksum */ if (msgList[buffNum][buffIdx].checksumWC != 0) { MINI(msgList[buffNum][buffIdx].checksumWC, *(msgList[buffNum][buffIdx].base)-1, checksumWC); baseAddress = msgList[buffNum][buffIdx].base; msgList[buffNum][buffIdx].tail.checksum = calculateChecksum(baseAddress, checksumWC); } /* rewrite the list tail with the correct checksum */ *((struct MSG_LIST_TAIL *)tailPtr) = msgList[buffNum][buffIdx].tail; return; } /************************************************************************************ * updateListBfr * * synopsis: Adds the header to a reply message associated with a primitive. In the * event that the reply message is in the reply buffer, the reply buffer * message counter and read/write pointer are incremented. * * IN: *listPtr - Pointer to the listPtr structure being updated. In COMPACT mode * all DSPs have 1 primitive list and 1 reply list buffer. In * normal operation, they have 3 of each. * listHead - The list header of the buffer being updated. ************************************************************************************/ INT32 updateListBfr(UINT32 bfrNum, UINT32 bfrIdx, struct MSG_HEAD msgHead) { INT32 returnCode = SUCCESS; /* increment message counter and rw pointer */ ++msgList[bfrNum][bfrIdx].msgCounter; msgList[bfrNum][bfrIdx].rwPtr += msgHead.length; /* check for overwrite of reply buffer */ if (BFR_OFFSET(bfrNum, bfrIdx) + SIZEOF(struct MSG_LIST_TAIL) > msgList[bfrNum][bfrIdx].buffSize) { newError(&returnCode, MSG_EXCEEDS_LIST_BOUND, FATAL_ERR, "updateListBfr", "message list too long, possible memory overwrite!\0", __FILE__,__LINE__); } return returnCode; } /************************************************************************************ * replyAvailable * * synopsis: Returns 1 if there is reply data available to primitive list buffNum. ************************************************************************************/ UINT32 replyAvailable(UINT32 buffNum) { return (msgList[buffNum][REP].msgCounter != 0); } /*#ifndef COMPACT */ /************************************************************************************ * The following routines are used to build primitive lists to send to another DSP. * For example, the master should send configuration commands to the slaves so that * slave configurations are consistent with data path FPGA configurations. Slaves * will need to send run time error instructions to the master DSP. ************************************************************************************/ /************************************************************************************ * addMessage * * synopsis: Adds a message to a message buffer. ************************************************************************************/ INT32 addMessage(UINT32 buffNum, UINT32 buffIdx, UINT32 msgId, UINT32 msgRevision, UINT32 msgBodyLength, UINT32 *msgBodyPtr) { UINT32 prmBodyIndx; struct MSG_HEAD msgHead; INT32 error, returnCode = SUCCESS; /* determine the length of this primitive; set other header parameters */ msgHead.length = SIZEOF(struct MSG_HEAD) + msgBodyLength; msgHead.index = 0; msgHead.id = msgId; msgHead.primRevision = msgRevision; /* write primitive header and data to the buffer */ *((struct MSG_HEAD *)msgList[buffNum][buffIdx].rwPtr) = msgHead; for (prmBodyIndx = 0; prmBodyIndx < msgBodyLength; ++prmBodyIndx) { *(msgList[buffNum][buffIdx].rwPtr + SIZEOF(struct MSG_HEAD) + prmBodyIndx) = *(msgBodyPtr + prmBodyIndx); } /* increment the primitive counter and the buffer rw pointer */ error = updateListBfr(buffNum, buffIdx, msgHead); if (error < 0) { addError(&returnCode, error, "execPrim", "updateListBfr", __FILE__,__LINE__); } return returnCode; } /************************************************************************************ * addReplyData * * synopsis: Adds data to a reply primitive's body, testing beforehand to see if * it will fit in the list. ************************************************************************************/ INT32 addReplyData(PrimData *primData, void *ptr, UINT32 nWords) { INT32 returnCode= SUCCESS; UINT32 allowed; allowed= primData->repBuffEnd -primData->repBodyPtr -2; //-2 => list trailer if (nWords <= allowed) { copyMem(ptr, (primData->repBodyPtr +primData->repBodyLength), nWords); primData->repBodyLength+= nWords; } else { primData->repBodyLength= 0; newError(&returnCode, DATA_EXCEEDS_BUFFER, FATAL_ERR, "addPrimData", "If added, the reply message body would exceed the list size limit", __FILE__, __LINE__); } return returnCode; } /************************************************************************************ * getReplyMsg * * synopsis: Returns a pointer to the next message in the requested reply buffer, * the length of the message, and a flag indicating whether it was the * last message in the buffer. ************************************************************************************/ void getReplyMsg(UINT32 bfrNum, UINT32 *msgBodyPtr, UINT32 *msgBodyLength, UINT32 *listDone) { struct MSG_HEAD *msgHead; msgHead = (struct MSG_HEAD *)msgList[bfrNum][REP].rwPtr; *msgBodyPtr = (UINT32)msgList[bfrNum][REP].rwPtr + (SIZEOF(struct MSG_HEAD)); *msgBodyLength = msgHead->length - SIZEOF(struct MSG_HEAD); ++msgList[bfrNum][REP].msgCounter; msgList[bfrNum][REP].rwPtr += msgHead->length; *listDone = 0; if (LIST_DONE(bfrNum, REP)) *listDone = 1; return; } /************************************************************************************ * The following routines are used by the master to manage a slave which is executing * a primitive list from the host. The state machine for this is smHostListToSlave. ************************************************************************************/ #ifdef I_AM_MASTER_DSP /************************************************************************************ * loadSlaveList * * synopsis: Loads a block of data located at slavePrimList into the primitive list * buffer of the identified 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 * - The function now calls writeSlvBlock to accomplish its work. 06.08.03 dpsf ************************************************************************************/ void loadSlaveList(UINT32 slv, UINT32 listLength, UINT32 *slavePrimList) { UINT32 *slvPtr; if (getRodRev() == 0xe) slvPtr= (UINT32 *) 0xa0062000; else slvPtr= (UINT32 *) 0x02062000; writeSlvBlock(slv, slvPtr, slavePrimList, listLength); } /************************************************************************************ * storeReplyParams * * synopsis: Called from SEND_SLAVE_LIST. Stores some parameters which are needed * to build the reply message to the subsequant START_SLAVE_LIST primitive * in the event that the slave reply data is requested. ************************************************************************************/ void storeReplyParams(UINT32 slaveNumber, UINT32 *slaveRepData) { primHeadStore[slaveNumber].index = primHead.index; primHeadStore[slaveNumber].id = primHead.id; primHeadStore[slaveNumber].primRevision = primHead.primRevision; slaveReplyAdr[slaveNumber] = slaveRepData; return; } /************************************************************************************ * getReplyDest * * synopsis: Returns the destination address for the reply data to the primtive list. ************************************************************************************/ UINT32 *getReplyDest(UINT32 slaveNumber) { return slaveReplyAdr[slaveNumber]; } /************************************************************************************ * copySlvReply * * synopsis: Copies a slave reply list to a specified location in the master DSP * memory map. The special value DEFAULT indicates that the slave reply * list should be inserted into the masterDSP reply list. Calls * updateListBfr to add the header and update the reply buffer structure * if necessary. * * 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 copySlvReply(UINT32 sdsp) { UINT32 replyLength; UINT32 *replyAddress, *slvPtr; struct MSG_HEAD repHead; /* read list length from slave reply buffer */ /* CAUTION: depends on length being 1st element of list */ if (getRodRev() == 0xe) slvPtr= (UINT32 *) 0xa0082000; else slvPtr= (UINT32 *) 0x02082000; writeSlvHPIA(sdsp, (UINT32) slvPtr); replyLength = readSlvHPID(sdsp); /* recall the header of the sendSlaveList primitive associated with this reply list * and copy it to the reply message header; update the length to that of reply * message (this is the slave reply list length + the size of the message header * the master will add to it) */ repHead= primHeadStore[sdsp]; repHead.length= replyLength + SIZEOF(struct MSG_HEAD); /* copy list to designated address (stored earlier in storeReplyParams); * leave room to add the reply message header */ if (slaveReplyAdr[sdsp] == (UINT32 *) DEFAULT) { replyAddress= msgList[HOST_LIST][REP].rwPtr; updateListBfr(HOST_LIST, REP, repHead); } else { replyAddress= slaveReplyAdr[sdsp]; } /* Add header to reply list, and then concatenate the SDSP reply list. */ *(struct MSG_HEAD *) replyAddress= repHead; replyAddress+= SIZEOF(struct MSG_HEAD); readSlvBlock(sdsp, slvPtr, replyAddress, replyLength); return; } #endif /* #ifdef I_AM_MASTER_DSP */