/****************************************************************************** * * Title : listHandler.c * Version 0.0 * * Description: listHandler routines. * * * Author: Lukas Tomasek, tomasekl@fzu.cz * ******************************************************************************/ #include #include "globalDefinitions.h" #include "primListHandler.h" #include "primFunctionInit.h" #include "uirUtility.h" #include "hostUtility.h" #include "comRegDfns.h" #include "vmeHpiUtility.h" #include "threadUtility.h" #include "fileUtility.h" #include "RccExtControl.h" #include "RWlists.h" #ifdef LAB_WINDOWS_CVI #include "mainUir.h" #endif /* LAB_WINDOWS_CVI */ #define I_AM_MASTER_DSP #undef IDREGS_BASE #include "memoryPartitions.h" //dspf: MDSP_PRM_BFR_SZ, MDSP_REP_BFR_SZ => use memory map. #undef I_AM_MASTER_DSP /****************************************************************************** * Definitions * ******************************************************************************/ #define MIN_LIST_LENGTH (SIZEOF(struct MSG_LIST_HEAD)+SIZEOF(struct MSG_LIST_TAIL)) /****************************************************************************** * Static Function Declarations * ******************************************************************************/ static ERROR_ID buildPrimList(struct HOST *host, UINT32 primBuffer[PRIM_BUFF_SIZE/4]); static ERROR_ID processMasterRepList(struct HOST *host, UINT32 replyBuffer[REP_BUFF_SIZE/4]); /****************************************************************************** * Global functions * ******************************************************************************/ /*============================================================================= * listHandler() *============================================================================= * * Host implementation of the ListCommunicationProtocol - passing primLists to * Rod and reading repLists from Rod + handshaking. * * Input: ->host - pointer to host, ->listHandlerState - pointer to state(local * variable in CommunicationLoop), * ->timeoutStart - timeout starting point variable(CommonLoop local var.). * */ ERROR_ID listHandler(struct HOST *host, LIST_HANDLER_STATE *listHandlerState){ char buffFileName[PATHNAME_LENGTH]; char tableFileName[PATHNAME_LENGTH]; char errorMessage[200]; int status; UINT32 readLength; ERROR_ID errorId=SUCCESS; static UINT32 primBuff[PRIM_BUFF_SIZE/4]; /* local primBuffer */ static UINT32 replyBuff[REP_BUFF_SIZE/4]; /* local replyBuffer */ static struct MSG_LIST_HEAD *primListHeader=(struct MSG_LIST_HEAD*)&primBuff; static struct MSG_LIST_HEAD *repListHeader=(struct MSG_LIST_HEAD*)&replyBuff; //struct MSG_LIST_HEAD *repListTableHeader; struct LIST_TABLE *repListTable; static double timeoutStart[MAXRODS]; const UINT8 hostIndex=HOST_INDEX(host->slotNumber); UINT32 uintVar; switch (*listHandlerState){ case LIST_HANDL_IDLE: /* poll until new primList is built- signal from primListBuildingThread, */ if(!host->primListReady) { break; } host->primListRepCounter= 0; if(global.option.displayRefresh==REFRESH_RUNTIME ){ GET_AND_SET_CTRL_VAL(host->panel.parent, ROD_LIST_REPEAT_COUNTER, host->primListRepCounter, &uintVar); } /* no break !! */ case LIST_HANDL_REPEAT_BUILD: if(host->primListReady==RAW_EXTERNAL_LIST){ /* copy raw list from shared memory */ memcpy(primBuff, sharedMemPtr->primBuff, PRIM_BUFF_SIZE); }else{ errorId=buildPrimList(host, primBuff); if(errorId!=SUCCESS){ hostError(__FILE__,__LINE__, errorId, host, "buildPrimList()"); break; /* go to error state */ } } if(primListHeader->length>(PRIM_BUFF_SIZE/4)){ errorId=HOST_ERROR; sprintf(errorMessage,"length(=%d words)>PRIM_BUFF_SIZE/4(=%dB).", primListHeader->length, PRIM_BUFF_SIZE); hostError(__FILE__, __LINE__, errorId, host, errorMessage); break; } if(primListHeader->lengthlength, MIN_LIST_LENGTH); hostError(__FILE__, __LINE__, errorId, host, errorMessage); break; } /* transfer list from local buffer to Rod */ errorId=RWmaster(WRITE, host->slotNumber, PRIM_BUFF_BASE, primBuff, primListHeader->length, HPIA_AUTOINCREMENT, 0); if (errorId!=SUCCESS){ sprintf(errorMessage,"RWmaster(WRITE primList) - ListLength=%dB.", primListHeader->length); hostError(__FILE__, __LINE__, errorId, host, errorMessage); break; } if(global.option.displayRefresh==REFRESH_RUNTIME ){ /* update listIndex on the screen */ SetCtrlVal(host->panel.parent, ROD_LIST_INDEX, primListHeader->index); } *listHandlerState=POLL_DspAck_CLEAR; /* no break!! */ timeoutStart[hostIndex]=Timer(); case POLL_DspAck_CLEAR: /* poll until DspAck bit is 0 and previous repList has been sucessfully processed if non overlap mode*/ if(READ_BIT(host->rodStatusReg[0], SR_DSP_ACK)){ if((Timer() - timeoutStart[hostIndex])>global.dspAckClearTimeout) { errorId=TIMEOUT_ERROR; hostError(__FILE__, __LINE__, errorId, host, "POLL_DspAck_CLEAR timeout"); } break; } /* set inListRdy in CommandReg0 */ errorId=setVmeCommandRegBit(host->slotNumber, &host->vmeCommandReg[0], CR_IN_LIST_RDY); if (errorId!=SUCCESS){ hostError(__FILE__, __LINE__, errorId, host, "setVmeCommandRegBit(vmeCommandReg[0], CR_IN_LIST_RDY)"); break; } if(global.option.displayRefresh==REFRESH_RUNTIME ){ /* update display */ displayVmeCommandReg0(host); } *listHandlerState=POLL_DspAck_SET; timeoutStart[hostIndex]=Timer(); break; case POLL_DspAck_SET: /* poll until DspAck bit is 1 and previous repList has been sucessfully processed if in overlap mode*/ if((READ_BIT(host->rodStatusReg[0], SR_DSP_ACK)==0)){ if(global.option.dspAckSetTimeoutOn&&((Timer() - timeoutStart[hostIndex])>global.dspAckSetTimeout)) { errorId=TIMEOUT_ERROR; hostError(__FILE__, __LINE__, errorId, host, "POLL_DspAck_SET timeout"); } break; } repListTable=&host->listTable; /* clear inList bit */ errorId=clearVmeCommandRegBit(host->slotNumber, &host->vmeCommandReg[0], CR_IN_LIST_RDY); if(errorId!=SUCCESS){ hostError(__FILE__, __LINE__, errorId, host, "setVmeCommandRegBit(clearCommandReg[0], CR_IN_LIST_RDY)"); break; } if(global.option.displayRefresh==REFRESH_RUNTIME){ /* update display */ displayVmeCommandReg0(host); } /* check index */ if((repListTable->inListHeader.index&0xF)!=(host->rodStatusReg[1]&0xF)){ errorId=HOST_ERROR; sprintf(errorMessage,"Index error - rodStatusRegIndex=%x , expectedIndex=%x!!", host->rodStatusReg[1]&0xF,repListTable->inListHeader.index&0xF); hostError(__FILE__,__LINE__, errorId, host, errorMessage); } if(READ_BIT(host->rodStatusReg[0], SR_OUT_LIST_RDY)==0){ /* NO repList ready */ if(repListTable->replyLength>0) { /* repList expected */ errorId=REPLIST_ERROR; sprintf(errorMessage,"RepList error - outListReady==0, repListExpected==1."); hostError(__FILE__, __LINE__, errorId, host, errorMessage); break; } if(host->primListRepCounteroption.primListRepetitions){ ++host->primListRepCounter; if(global.option.displayRefresh==REFRESH_RUNTIME){ GET_AND_SET_CTRL_VAL(host->panel.parent, ROD_LIST_REPEAT_COUNTER, host->primListRepCounter, &uintVar); } if(host->option.repeatExecNotBuild){ timeoutStart[hostIndex]=Timer(); *listHandlerState=POLL_DspAck_CLEAR; }else{ *listHandlerState=LIST_HANDL_REPEAT_BUILD; } } else { *listHandlerState=LIST_HANDL_IDLE; host->primListReady=0; if(host->cmdListExecState==CMDLISTEXEC_BUSY){ host->commandStatus=SUCCESS; errorId=setEvent(host->commandDone_event); HOST_ERROR_CHECK(errorId, host, setEvent()); }else displayCmdListExecBusy(host); } break; /* !!!! */ } /* repList ready */ if(repListTable->replyLength==0) { /* repList NOT expected */ errorId=REPLIST_ERROR; sprintf(errorMessage,"RepList error - outListReady==1, repListExpected==0."); hostError(__FILE__, __LINE__, errorId, host, errorMessage); /* no break - read message anyway */ } /* READ_REP_LIST */ memset(replyBuff, 0, sizeof(struct MSG_LIST_HEAD)); /* clear buffer header for sure */ /* read repListLength - first word */ errorId=RWmaster(READ, host->slotNumber, REP_BUFF_BASE, replyBuff, 1, NO_HPIA_AUTOINCREMENT, 0); if (errorId!=SUCCESS){ sprintf(errorMessage,"RWmaster(READ repListLength)."); hostError(__FILE__, __LINE__, errorId, host, errorMessage); break; } if (repListHeader->length>(REP_BUFF_SIZE/4)){ /* repList length>buffSize */ errorId=REPLIST_ERROR; sprintf(errorMessage,"repListLength(=%d words)>REP_BUFF_SIZE/4(=%d words).", repListHeader->length, REP_BUFF_SIZE/4); hostError(__FILE__, __LINE__, errorId, host, errorMessage); readLength=REP_BUFF_SIZE/4-1; /* read full buffer */ } else { readLength=repListHeader->length-1; } /* read the rest of repList */ errorId=RWmaster(READ, host->slotNumber, REP_BUFF_BASE+4, &replyBuff[1], readLength, HPIA_AUTOINCREMENT, 0); if (errorId!=SUCCESS){ hostError(__FILE__, __LINE__, errorId, host, "RWmaster(READ repList)."); break; } if(host->primListReady==RAW_EXTERNAL_LIST){ /* copy raw reply list to shared memory */ memcpy(sharedMemPtr->replyBuff, replyBuff, PRIM_BUFF_SIZE); }else{ /* repListProcessing */ errorId=processMasterRepList(host, replyBuff); if (errorId!=SUCCESS){ hostError(__FILE__, __LINE__, errorId, host, "processMasterRepList()."); break; } } if(host->primListRepCounteroption.primListRepetitions){ ++host->primListRepCounter; if(global.option.displayRefresh==REFRESH_RUNTIME){ GET_AND_SET_CTRL_VAL(host->panel.parent, ROD_LIST_REPEAT_COUNTER, host->primListRepCounter, &uintVar); } if(host->option.repeatExecNotBuild){ timeoutStart[hostIndex]=Timer(); *listHandlerState=POLL_DspAck_CLEAR; }else{ *listHandlerState=LIST_HANDL_REPEAT_BUILD; } } else { *listHandlerState=LIST_HANDL_IDLE; host->primListReady=0; if(host->cmdListExecState==CMDLISTEXEC_BUSY){ host->commandStatus=SUCCESS; errorId=setEvent(host->commandDone_event); HOST_ERROR_CHECK(errorId, host, setEvent()); }else displayCmdListExecBusy(host); } break; default: errorId=HOST_ERROR; sprintf(errorMessage,"Host error - non known listHandlerState(#%d).",*listHandlerState); hostError(__FILE__, __LINE__, errorId, host, errorMessage); } if(errorId!=SUCCESS) { *listHandlerState=LIST_HANDL_IDLE; host->primListReady=0; if(host->cmdListExecState==CMDLISTEXEC_BUSY){ host->commandStatus=PRIMLIST_ERROR; errorId=setEvent(host->commandDone_event); HOST_ERROR_CHECK(errorId, host, setEvent()); }else displayCmdListExecBusy(host); } return(errorId); } /****************************************************************************** * Static functions * ******************************************************************************/ /*============================================================================= * buildPrimList() *============================================================================= * * Builds prim list in the local copy of PrimBuff from input listTable * */ static ERROR_ID buildPrimList(struct HOST *host, UINT32 primBuffer[PRIM_BUFF_SIZE/4]){ struct MSG_LIST_HEAD *inListHeader=(struct MSG_LIST_HEAD*)primBuffer; struct MSG_LIST_TAIL *inListTrailer; struct MSG_HEAD *inPrimHeader; struct LIST_TABLE *listTable=&host->listTable; struct PRIM_TABLE *primTable; UINT32 primitiveIndex; ERROR_ID errorId=SUCCESS; UINT32 maxLength; UINT32* inListPtr=(UINT32*)((UINT32)inListHeader+sizeof(struct MSG_LIST_HEAD)); UINT32 outListLength=0; UINT32 tablePrimIndex; //unsigned int tableLength; if(global.option.saveLists){ /* save list table to file */ errorId=writePrimListFile(host->primTableFile, listTable); ERROR_CHECK(errorId, writeToBinFile()); } ++host->listIndex; listTable->inListHeader.index=host->listIndex; inListHeader->index=host->listIndex; inListHeader->numMsgs=0; inListHeader->primListRevision=listTable->inListHeader.primListRevision; inListHeader->length=SIZEOF(struct MSG_LIST_HEAD); for(primitiveIndex=0; primitiveIndexinListHeader.numMsgs; ++primitiveIndex){ inPrimHeader=(struct MSG_HEAD*) inListPtr; tablePrimIndex=listTable->masterToTablePrimIndex[primitiveIndex]; primTable=&listTable->primTable[tablePrimIndex]; *inPrimHeader=primTable->inPrimHeader; maxLength= PRIM_BUFF_SIZE/4-inListHeader->length; /* build primitive in primBuffer */ errorId=(*global.primFunction[getPrimArrayId(primTable->inPrimHeader.id)])(PRIM_BUILD, primTable, inPrimHeader, maxLength, host->slotNumber); ERROR_CHECK(errorId, primFunction()); if(errorId!=SUCCESS) return(errorId); /* update list header */ inListHeader->length+=inPrimHeader->length; inListPtr+=inPrimHeader->length; outListLength+=primTable->replyLength; ++inListHeader->numMsgs; } /* update list header */ inListHeader->length+=sizeof(struct MSG_LIST_TAIL)/4; inListTrailer=(struct MSG_LIST_TAIL*)inListPtr; inListTrailer->length=inListHeader->length; listTable->inListHeader.length=inListHeader->length; if(outListLength>0){ outListLength+=SIZEOF(struct MSG_LIST_HEAD)+SIZEOF(struct MSG_LIST_TAIL); } if(outListLength>(REP_BUFF_SIZE/sizeof(UINT32))){ errorId=PRIMLIST_ERROR; ERROR_CHECK(errorId, PrimListBuilding: outListLength>REPLY_BUFFER); } listTable->replyLength=outListLength; /* check sizes again for sure */ if(listTable->inListHeader.length>(PRIM_BUFF_SIZE/sizeof(UINT32))){ errorId=PRIMLIST_ERROR; ERROR_CHECK(errorId, PrimListBuilding: primListLength>REPLY_BUFFER); } if(listTable->replyLength>(REP_BUFF_SIZE/sizeof(UINT32))){ errorId=PRIMLIST_ERROR; ERROR_CHECK(errorId, PrimListBuilding: outListLength>REPLY_BUFFER); } /* calculate checksum */ if(global.option.masterChecksum) { inListTrailer->checksum=checkSum((UINT32*)inListHeader, inListHeader->length-1); } else { inListTrailer->checksum= 0; } if(global.option.saveLists){ errorId=writeToBinFile(host->primListFile, 0, primBuffer, inListHeader->length*4); ERROR_CHECK(errorId, writeToBinFile()); } return(errorId); } /*============================================================================= * processMasterRepList() *============================================================================= * * * */ static ERROR_ID processMasterRepList(struct HOST *host, UINT32 replyBuffer[REP_BUFF_SIZE/4]){ struct MSG_LIST_HEAD* const outListHeader=(struct MSG_LIST_HEAD*)replyBuffer; struct MSG_HEAD *outPrimHeader; struct PRIM_TABLE *primTable; struct LIST_TABLE *listTable=&host->listTable; UINT32 repIndex; ERROR_ID errorId; ERROR_ID returnErrorId=SUCCESS; UINT32 maxLength; UINT32* outListPtr=(UINT32*)((UINT32)outListHeader+sizeof(struct MSG_LIST_HEAD)); UINT32 tablePrimIndex; struct MSG_LIST_TAIL *outListTrailer; char errorMessage[500]; UINT32 checkSumHost; /* check list index */ if(outListHeader->index!=listTable->inListHeader.index) { returnErrorId=REPLIST_ERROR; sprintf(errorMessage,"Index error - RepListIndex=%x , expectedIndex=%x!!",outListHeader->index, listTable->inListHeader.index); hostError(__FILE__,__LINE__, returnErrorId, host, errorMessage); return(returnErrorId); /* don't process */ } #if 0 -- DON'T CHECK LIST_LENGTH !!!!! /* check list length */ if(outListHeader->length!=listTable->outListHeader.length) { returnErrorId=REPLIST_ERROR; sprintf(errorMessage,"Reply list length error - RepListLength=%x , expectedLength=%x!!",outListHeader->length, listTable->outListHeader.length); hostError(__FILE__,__LINE__, returnErrorId, host, errorMessage); /* continue anyway */ } #endif /* check trailer length */ outListTrailer=(struct MSG_LIST_TAIL*)(replyBuffer+outListHeader->length-SIZEOF(struct MSG_LIST_TAIL)); if(outListTrailer->length!=outListHeader->length){ returnErrorId=REPLIST_ERROR; HOST_ERROR_CHECK(returnErrorId, host, outListTrailer->length!=outListHeader->length); return(returnErrorId); /* don't process */ } /* check trailer checksum */ if(global.option.masterChecksum) { if(outListHeader->length<(REP_BUFF_SIZE/4)){ checkSumHost=checkSum(replyBuffer, outListHeader->length); } else{ returnErrorId=REPLIST_ERROR; HOST_ERROR_CHECK(returnErrorId, host, Reply list exceeds buffer boundaries!); return(returnErrorId); /* don't process */ } if(checkSumHost!=0){ returnErrorId=REPLIST_ERROR; sprintf(errorMessage,"RepList checksum(%x)!=0 !",checkSumHost); hostError(__FILE__,__LINE__, returnErrorId, host, errorMessage); return(returnErrorId); /* don't process */ } } if(listTable->replyCount!=outListHeader->numMsgs){ returnErrorId=REPLIST_ERROR; ERROR_CHECK(returnErrorId, numMsgs!=expectedNumMsgs); /* continue anyway */ } for(repIndex=0; repIndex<(outListHeader->numMsgs); ++repIndex){ outPrimHeader=(struct MSG_HEAD*) outListPtr; tablePrimIndex=listTable->masterToTablePrimIndex[outPrimHeader->index]; primTable=&listTable->primTable[tablePrimIndex]; if(outPrimHeader->length!=primTable->replyLength){ switch(primTable->inPrimHeader.id){ /* not error - not known reply data length */ case SEND_DATA: break; case TEST: break; case TASK_OPERATION: break; case RW_MODULE_VARIABLE: break; #ifdef PIXEL_ROD case TEST_GLOBAL_REG: break; #endif /* else length error */ default: returnErrorId=REPLIST_ERROR; sprintf(errorMessage,"RepPrim length(0x%X!=expectedLength(0x%X): ReplyPrimIndex=0x%X, primId=0x%X", outPrimHeader->length, primTable->replyLength, outPrimHeader->index, primTable->inPrimHeader.id); hostError(__FILE__,__LINE__, REPLIST_ERROR, host, errorMessage); outListPtr+= outPrimHeader->length; continue; /* don't process */ } } if(outPrimHeader->id!=primTable->inPrimHeader.id){ returnErrorId=REPLIST_ERROR; sprintf(errorMessage,"Wrong reply prim ID(0x%X): ReplyPrimIndex=0x%X, primId=0x%X(expected).", outPrimHeader->id, outPrimHeader->index, primTable->inPrimHeader.id); hostError(__FILE__,__LINE__, REPLIST_ERROR, host, errorMessage); outListPtr+= outPrimHeader->length; continue; /* don't process */ } /* processing */ errorId=(*global.primFunction[getPrimArrayId(primTable->inPrimHeader.id)])(REP_DATA_PROCESS, primTable, outPrimHeader, MASTER_DSP, host->slotNumber); ERROR_CHECK(errorId, primFunction(REP_DATA_PROCESS)); if(errorId!=SUCCESS){ sprintf(errorMessage,"primFunction(REP_DATA_PROCESS): ReplyPrimIndex=0x%X, primId=0x%X.", outPrimHeader->index, primTable->inPrimHeader.id); hostError(__FILE__,__LINE__, REPLIST_ERROR, host, errorMessage); returnErrorId=REPLIST_ERROR; } outListPtr+= outPrimHeader->length; } return(returnErrorId); } /******************************************************************************/