/****************************************************************************** * * Title : hostUtility.c * Version * * Description: Host supporting routines * *. * Author: Lukas Tomasek, tomasekl@fzu.cz * ******************************************************************************/ /****************************************************************************** * Header files * ******************************************************************************/ #include #include #include #include #include "hostUtility.h" #include "vmeHpiUtility.h" #include "errorHandler.h" #include "threadUtility.h" #include "uirUtility.h" #include "mainUir.h" //dpsf: #include "memoryPartitions.h" #include "primFunctionInit.h" #include "comRegDfns.h" #include "RWlists.h" /****************************************************************************** * Global functions * ******************************************************************************/ /*============================================================================= * checkSum() *============================================================================= * * Calculates checksum on 32b wide word array. * * Input: -> sourceAddress[] - pointer to array, * -> wordCount - array length in 32bit wide words. * Return: checksum value. */ UINT32 checkSum(UINT32 sourceAddress[], UINT32 wordCount) { UINT32 i, result=0; for(i=0; i vmeCommandReg - pointer to vmeCommandReg struct, * -> bitNumber - bit number to set (from 0 to 31 - def.in comRegsDfns.h). */ ERROR_ID setVmeCommandRegBit(UINT8 slotNumber, UINT32 *vmeCommandReg, unsigned int bitNumber){ ERROR_ID errorId=SUCCESS; char errorMessage[200]; SET_BIT(*vmeCommandReg, bitNumber); errorId=RWmaster(WRITE, slotNumber, COMMAND_REG_0, vmeCommandReg, 1, NO_HPIA_AUTOINCREMENT, 0); ERROR_CHECK(errorId, "RWmaster(WRITE VmeCommandReg)"); return(errorId); } /*============================================================================= * clearVmeCommandRegBit() *============================================================================= * * Clears VmeCommandRegBit. * * Input: -> vmeCommandReg - pointer to vmeCommandReg struct, * -> bitNumber - bit number to clear (from 0 to 31 - def.in comRegsDfns.h). */ ERROR_ID clearVmeCommandRegBit(UINT8 slotNumber, UINT32 *vmeCommandReg, unsigned int bitNumber){ ERROR_ID errorId=SUCCESS; char errorMessage[200]; CLEAR_BIT(*vmeCommandReg, bitNumber); errorId=RWmaster(WRITE, slotNumber, COMMAND_REG_0, vmeCommandReg, 1, NO_HPIA_AUTOINCREMENT, 0); ERROR_CHECK(errorId, "RWmaster(WRITE VmeCommandReg)"); return(errorId); } /*============================================================================= * readRodStatusRegs() *============================================================================= * * Reads RodStatusRegs. * * Input: -> rodStatusRegs - pointer to first rodStatusReg struct you wish to read; * -> numberOfRegisters - number(from 1 to 3) of 32 bit registers to read, * starting. * Output: -> rodStatusRegs pointer returns the register value */ ERROR_ID readRodStatusRegs(UINT8 slotNumber, UINT32 rodStatusRegs[NUMBER_OF_ROD_STAT_REGS]){ ERROR_ID errorId=SUCCESS; unsigned int i; //dpsf: This ought to be defined via the ROD memory map. errorId=RWmaster(READ, slotNumber, STATUS_REG_0, &rodStatusRegs[0], 1, HPIA_AUTOINCREMENT, 0); errorId=RWmaster(READ, slotNumber, STATUS_REG_1, &rodStatusRegs[1], 1, HPIA_AUTOINCREMENT, 0); errorId=RWmaster(READ, slotNumber, STATUS_REG_2, &rodStatusRegs[2], 1, HPIA_AUTOINCREMENT, 0); ERROR_CHECK(errorId, RWmaster(READ rodStatusRegs)); return(errorId); } /*============================================================================= * executePrimList() *============================================================================= * * executePrimList. * */ ERROR_ID executePrimList(struct HOST *host, struct LIST_TABLE *newPrimList, unsigned int repetitions, int repeatBuildNotExec, int insideCmdList){ ERROR_ID errorId; int status; if(host->option.rodEnabled==0) return(SUCCESS); if(((host->cmdListExecState!=CMDLISTEXEC_IDLE)&(!insideCmdList))||(host->primListReady)){ HOST_ERROR_CHECK(PROGRAM_ERROR, host, Cannot execute PrimList - CmdListExecution is busy!!); return(PROGRAM_ERROR); } /* copy new prim list */ host->listTable=*newPrimList; host->option.repeatExecNotBuild=!repeatBuildNotExec; SetCtrlVal(host->panel.parent, ROD_REPEAT_BUILD_EXEC, !repeatBuildNotExec); host->option.primListRepetitions=repetitions; SetCtrlVal(host->panel.parent, ROD_NUMBER_OF_LIST_REP, repetitions); host->primListReady=1; displayCmdListExecBusy(host); return(SUCCESS); } /*============================================================================= * executeCmdListFile() *============================================================================= * * * */ ERROR_ID executePrimListFile(unsigned char slotNumber, char primListFile[PATHNAME_LENGTH], unsigned int repetitions, int repeatBuildNotExec, int insideCmdList){ ERROR_ID errorId; int status; struct LIST_TABLE newPrimList; UINT8 hostIndex; struct HOST *host; char text[300]; if(primListFile[0]==0) { return(SUCCESS); } errorId=readPrimListFile(primListFile, &newPrimList); ERROR_CHECK(errorId, readPrimListFile()); if(errorId!=SUCCESS) return(errorId); if(slotNumber==ALL_RODS) hostIndex=0; //all rods else hostIndex=HOST_INDEX(slotNumber); //only one rod for( ; hostIndexoption.rodEnabled==0) return(SUCCESS); if((host->cmdListExecState!=CMDLISTEXEC_IDLE)||(host->primListReady)){ HOST_ERROR_CHECK(PROGRAM_ERROR, host, Cannot execute CommandList - CmdListExecution is busy!!); return(PROGRAM_ERROR); } /* copy new command list to host */ host->commandList=*newCommandList; host->option.commandListRepetitions=repetitions; SetCtrlVal(host->panel.commandListStatus, CLISTP_NUM_OF_LIST_REP, repetitions); SetCtrlVal(host->panel.commandListStatus, CLISTP_IF_ERROR, ifError); /* start control thread */ host->cmdListExecState=CMDLISTEXEC_BUSY; displayCmdListExecBusy(host); errorId=resumeThread(host->cmdListExecThread.handle); HOST_ERROR_CHECK(errorId, host, resumeThread()); return(errorId); } /*============================================================================= * executeCmdListFile() *============================================================================= * * * */ ERROR_ID executeCommandListFile(unsigned char slotNumber, char cmdListFile[PATHNAME_LENGTH], unsigned int repetitions, CMDLIST_ERROR_OPTION ifError){ ERROR_ID errorId; int status; struct COMMAND_LIST newCommandList; UINT8 hostIndex; struct HOST *host; char text[300]; if(cmdListFile[0]==0) { return(SUCCESS); } errorId=readCmdListFile(cmdListFile, &newCommandList); ERROR_CHECK(errorId, readCmdListFile()); if(errorId!=SUCCESS){ return(errorId); } if(slotNumber==ALL_RODS) hostIndex=0; //all rods else hostIndex=HOST_INDEX(slotNumber); //only one rod for( ; hostIndexcListFile, cmdListFile); errorId=executeCommandList(host, &newCommandList, repetitions, ifError); ERROR_CHECK(errorId, addTestToControlThread()); if(slotNumber!=0) break; //only one rod } return(errorId); } /*============================================================================= * executeTimCommandList() *============================================================================= * * Executes TIM specific commandList directly from the main thread (there is no * control thread for TIM). * Only RW_VME and COMPARE_FILES commands are valid for TIM command list!! * */ ERROR_ID executeTimCommandList(struct COMMAND_LIST *commandList){ int commandIndex, commandRepCount; struct COMMAND *command; ERROR_ID errorId; for(commandIndex=0; commandIndexcommandCount; ++commandIndex){ command=&commandList->command[commandIndex]; /* pass only commands valid for TIM, ie. RW_VME and COMPARE_FILES */ switch(command->id){ case RW_VME_COMMAND_ID: break; case COMPARE_FILES_COMMAND_ID: break; default: /* wrong command for TIM */ ERROR_CHECK(COMMAND_LIST_ERROR, Invalid command in TIM command list!!); return(COMMAND_LIST_ERROR); } for(commandRepCount=0; commandRepCount<=command->numRepetitions; ++commandRepCount){ errorId=(*global.commandFunction[command->id])(COMMAND_EXECUTION, command, TIM_SLOT_NUMBER, 0); ERROR_CHECK(errorId, commandFunction()); if(errorId!=SUCCESS){ return(COMMAND_ERROR); /* don't continue */ } } } return(SUCCESS); } /*============================================================================= * stopCommunicationLoop() *============================================================================= * * Stops communication loop * */ #define STOP_COMMLOOP_TIMEOUT 10 /* seconds */ ERROR_ID stopCommunicationLoop(struct GLOBAL_VARIABLES *global){ int i; ERROR_ID errorId; global->option.stopCommLoop=TRUE; /* set stop commThread flag */ /* wait until it really stops */ for(i=0; i<(STOP_COMMLOOP_TIMEOUT*10); ++i){ if(global->option.commLoopRunning==FALSE){ return(SUCCESS); } Sleep(50); } /* if didn't stop within the time limit - timeout error */ errorId=PROGRAM_WARNING; ERROR_CHECK(errorId, "StopCommunicationLoop timeout."); return(errorId); } /*============================================================================= * resumeCommunicationLoop() *============================================================================= * * Resumes the communication loop * */ ERROR_ID resumeCommunicationLoop(struct GLOBAL_VARIABLES *global){ ERROR_ID errorId; global->option.stopCommLoop=FALSE; errorId=resumeThread(global->communLoopThread.handle); ERROR_CHECK(errorId,resumeThread(communLoopThread)); return(errorId); } /*============================================================================= * resetRod() *============================================================================= * * Resets the Rod. * */ ERROR_ID resetRod(struct HOST *host){ void *buffer; int status; int commLoopRunningSave; ERROR_ID errorId; UINT32 value=0; host->option.rodEnabled=FALSE; SetCtrlVal(host->panel.parent, ROD_HOST_RUNNING, host->option.rodEnabled); host->rodInitialized=FALSE; host->commandReady=0; host->primListReady=0; host->rodInitialized=0; /* stop CommunicationLoop */ commLoopRunningSave=global.option.commLoopRunning; if(commLoopRunningSave){ errorId=stopCommunicationLoop(&global); ERROR_CHECK(errorId, stopCommunicationLoop()); } /* reset list handler */ host->listHandlerState=LIST_HANDL_IDLE; // OVERIT!! /* reset control thread */ if(host->cmdListExecState!=CMDLISTEXEC_IDLE){ errorId=setEvent(host->commandDone_event); ERROR_CHECK(errorId, waitForEvent()); } host->cmdListExecState=CMDLISTEXEC_IDLE; displayCmdListExecBusy(host); SetCtrlVal(host->panel.commandListStatus, CLISTP_STOPPED, 0); errorId=resumeThread(host->cmdListExecThread.handle); HOST_ERROR_CHECK(errorId, host, resumeThread()); /* clear local copies of registers */ host->rodStatusReg[0]=0; host->rodStatusReg[1]=0; displayRodStatusReg0(host); SetCtrlVal(host->panel.parent, ROD_ROD_STAT_REG1, host->rodStatusReg[1]); host->vmeCommandReg[0]=0; displayVmeCommandReg0(host); SetCtrlVal(host->panel.parent, ROD_RESUME_BUTTON, 0); SetCtrlVal(host->panel.parent, ROD_ABORT_BUTTON, 0); SetCtrlVal(host->panel.parent, ROD_PAUSE_BUTTON, 0); SetCtrlVal(host->panel.parent, ROD_DMA_REQ_BUTTON, 0); /* reset board */ value=0; SET_BIT(value, 6); errorId=vmeWriteElement(value, BASE_ADDRESS(host->slotNumber)+FPGA_CONTROL_2_REL_ADDR, sizeof(UINT32)); ERROR_CHECK(errorId, vmeWriteElement()); // turn OFF slave DSP LED's SetCtrlVal(host->panel.parent, ROD_SLAVE0, 0); SetCtrlVal(host->panel.parent, ROD_SLAVE1, 0); SetCtrlVal(host->panel.parent, ROD_SLAVE2, 0); SetCtrlVal(host->panel.parent, ROD_SLAVE3, 0); SetCtrlAttribute (host->panel.parent, ROD_SLAVE0,ATTR_OFF_COLOR, VAL_PANEL_GRAY); SetCtrlAttribute (host->panel.parent, ROD_SLAVE1,ATTR_OFF_COLOR, VAL_PANEL_GRAY); SetCtrlAttribute (host->panel.parent, ROD_SLAVE2,ATTR_OFF_COLOR, VAL_PANEL_GRAY); SetCtrlAttribute (host->panel.parent, ROD_SLAVE3,ATTR_OFF_COLOR, VAL_PANEL_GRAY); /* return communicationLoop to original state */ if(commLoopRunningSave){ errorId=resumeCommunicationLoop(&global); ERROR_CHECK(errorId, resumeCommunicationLoop()); } return(SUCCESS); /* change - return error */ } /*============================================================================= * dmaAccessSwitch() *============================================================================= * * * */ ERROR_ID dmaAccessSwitch(UINT8 slotNumber, int on, double timeoutInSeconds){ ERROR_ID errorId; char errorMessage[200]; double timeStart; struct HOST *host; UINT32 *rodStatusPtr; UINT32 *vmeCmdPtr; UINT32 regValue=0; host=global.host[slotNumber-FIRST_ROD_VME_SLOT]; if(host!=0){ rodStatusPtr=&host->rodStatusReg[0]; vmeCmdPtr=&host->vmeCommandReg[0]; }else{ rodStatusPtr=®Value; vmeCmdPtr=®Value; } if(on){ /* make sure that MDSP SR_DMA_ACCESS_ACK is 0 !! */ timeStart=Timer(); while(1){ /* read Status Reg. 0 */ errorId=RWmaster(READ, slotNumber, STATUS_REG_0, rodStatusPtr, 1, NO_HPIA_AUTOINCREMENT, 0); ERROR_CHECK(errorId, RWmaster(READ rodStatusReg0)); if(READ_BIT(*rodStatusPtr, SR_DMA_ACCESS_ACK)==0) break; /* timeout error */ if((Timer() - timeStart)>timeoutInSeconds) { ERROR_CHECK(TIMEOUT_ERROR, Poll SR_DMA_ACCESS_ACK timeout.); regValue=0; errorId=clearVmeCommandRegBit(slotNumber, vmeCmdPtr, CR_DMA_ACCESS_REQ); HOST_ERROR_CHECK(errorId, host, clearVmeCommandRegBit(vmeCommandReg[0], CR_DMA_ACCESS_REQ)); return(TIMEOUT_ERROR); } } regValue=0; errorId=setVmeCommandRegBit(slotNumber, vmeCmdPtr, CR_DMA_ACCESS_REQ); HOST_ERROR_CHECK(errorId, host, setVmeCommandRegBit(vmeCommandReg[0], CR_DMA_ACCESS_REQ)); if((host!=0)&&(global.option.displayRefresh==REFRESH_RUNTIME)){ displayRodStatusReg0(host); displayVmeCommandReg0(host); } timeStart=Timer(); /* wait until ready for DMA */ while(1){ /* read Status Reg. 0 */ errorId=RWmaster(READ, slotNumber, STATUS_REG_0, rodStatusPtr, 1, NO_HPIA_AUTOINCREMENT, 0); ERROR_CHECK(errorId, RWmaster(READ rodStatusReg0)); /* Master DSP error */ if(READ_BIT(*rodStatusPtr, SR_DMA_ACCESS_ERR)==1){ ERROR_CHECK(TIMEOUT_ERROR, SR_DMA_ACCESS_ERR error.); regValue=0; errorId=clearVmeCommandRegBit(slotNumber, vmeCmdPtr, CR_DMA_ACCESS_REQ); HOST_ERROR_CHECK(errorId, host, clearVmeCommandRegBit(vmeCommandReg[0], CR_DMA_ACCESS_REQ)); return(TIMEOUT_ERROR); } if(READ_BIT(*rodStatusPtr, SR_DMA_ACCESS_ACK)==1) break; /* Master to Slave communication is stopped */ /* timeout error */ if((Timer() - timeStart)>timeoutInSeconds) { ERROR_CHECK(TIMEOUT_ERROR, Poll SR_DMA_ACCESS_ACK timeout.); regValue=0; errorId=clearVmeCommandRegBit(slotNumber, vmeCmdPtr, CR_DMA_ACCESS_REQ); HOST_ERROR_CHECK(errorId, host, clearVmeCommandRegBit(vmeCommandReg[0], CR_DMA_ACCESS_REQ)); return(TIMEOUT_ERROR); } } if((host!=0)&&(global.option.displayRefresh==REFRESH_RUNTIME)){ displayRodStatusReg0(host); displayVmeCommandReg0(host); } }else{ regValue=0; errorId=clearVmeCommandRegBit(slotNumber, vmeCmdPtr, CR_DMA_ACCESS_REQ); HOST_ERROR_CHECK(errorId, host, clearVmeCommandRegBit(vmeCommandReg[0], CR_DMA_ACCESS_REQ)); if((host!=0)&&(global.option.displayRefresh==REFRESH_RUNTIME)){ displayRodStatusReg0(host); displayVmeCommandReg0(host); } } return(errorId); } /*============================================================================= * FEoccupancy() *============================================================================= * * * */ ERROR_ID FEoccupancy(struct HOST *host){ ERROR_ID errorId; int status; UINT32 *dataBuffer; int i, j; UINT32 value; UINT32 address; UINT8 byte; unsigned int samples; int FEOccNotFifoWC; unsigned int link; char fileName[300]; char string[300]; double timeStart; const int panel=host->panel.parent; const int graphPanel=global.panel.distributionPlot; int overflow; int graphColor[8]={ /* 8 links */ VAL_GREEN, VAL_CYAN, VAL_MAGENTA, VAL_YELLOW, VAL_RED, VAL_BLUE, VAL_DK_CYAN, VAL_DK_MAGENTA }; double feOccDistribution[8][0x10]; /* 4 bit value, 8 channels */ double outFifoWCDistribution[0x100]; /* 8 bit value, 1 channel */ int saveData; FILE *fileHandle; GetCtrlVal(panel, ROD_SAMPLES, &samples); GetCtrlVal(panel, ROD_LINK, &link); GetCtrlVal(panel, ROD_FEOCC_NOT_FIFOWC, &FEOccNotFifoWC); dataBuffer=calloc(samples, sizeof(UINT32)); if(dataBuffer==NULL){ ERROR_CHECK(PROGRAM_ERROR, calloc()); return(PROGRAM_ERROR); } /* find address */ if(FEOccNotFifoWC){ /* read FEoccCnt */ address=0x00404500+4*((int)(link/8)); }else{ /* read OutFifoWC */ address=0x00400040+0x400*((int)(link/12))+0x4*((int)(link%12)); } /* time stamp start */ timeStart=Timer(); /* read */ errorId=RWmaster(READ, host->slotNumber, address, dataBuffer, samples, NO_HPIA_AUTOINCREMENT, 0); ERROR_CHECK(errorId, RWmaster()); if(errorId!=SUCCESS){ free(dataBuffer); /* !!!! */ return(PROGRAM_ERROR); } /* sampling time */ SetCtrlVal(panel, ROD_SAMPLING_TIME, (Timer() - timeStart)); overflow=1; while(1){ /* read DebugMode Status Reg. until bits 7:6 are set */ errorId=RWmaster(READ, host->slotNumber, DEBUG_MODE_STAT_REG_ADDR, &value, 1, NO_HPIA_AUTOINCREMENT, 0); ERROR_CHECK(errorId, RWmaster()); if(errorId!=SUCCESS){ free(dataBuffer); /* !!!! */ return(PROGRAM_ERROR); } /* stop data taking conditions */ if(((value&0xC0)==0xC0)||((value&0xC0)==0)){ /* overflow ? */ SetCtrlVal(panel, ROD_OVERFLOW, overflow); break; } overflow=0; GetCtrlVal(panel, ROD_CAPTURE, &value); if(value==0) break; } /* total time */ SetCtrlVal(panel, ROD_TOTAL_TIME, (Timer() - timeStart)); SetCtrlVal(panel, ROD_CAPTURE, 0); /* turn capture to OFF */ GetCtrlVal(panel, ROD_SAVE_DATA, &saveData); /* save to files */ strcpy(fileName, host->dataDir); if(FEOccNotFifoWC){ /* FE Occ Cnt */ /* clear distribution array */ for(i=0; i<0x10; ++i){ for(j=0; j<8; ++j) feOccDistribution[j][i]=0.0; } /* get distribution */ for(i=0; i>4)&0xF])+=1; } } /* normalize distribution */ for(i=0; i<0x10; ++i){ for(j=0; j<8; ++j) feOccDistribution[j][i]/=samples; } /* plot distribution */ DeleteGraphPlot (graphPanel, GRAPHP_GRAPH, -1, 1); SetAxisScalingMode (graphPanel, GRAPHP_GRAPH, VAL_XAXIS, VAL_MANUAL, 0.0, 0x10); for(j=0; j<8; ++j){ PlotY (graphPanel, GRAPHP_GRAPH, &feOccDistribution[j][0], 0x10, VAL_DOUBLE, VAL_CONNECTED_POINTS, VAL_EMPTY_SQUARE, VAL_SOLID, 1, graphColor[j]); } status=DisplayPanel(graphPanel); UIR_STATUS_CHECK(status, DisplayPanel()); value=(int)(link/8)*8; sprintf(string, "FEOccCnt_Link%dto%d", value, value+7); strcat(fileName, string); strcpy(string, fileName); strcat(fileName, ".bin"); if(saveData){ /* save raw data */ errorId=writeToBinFile(fileName, 0, dataBuffer, samples*4); ERROR_CHECK(errorId, writeToBinFile()); } /* save occupancy plot */ strcat(string, ".txt"); fileHandle = fopen (string, "w"); fprintf(fileHandle, "FEOccCnt Occupancy(link +0,1,2,3,4,5,6,7) [Samples: 0x%X]", samples); /* header */ for(i=0; i<0x10; ++i){ fprintf(fileHandle, "\n0x%2.2X ", i); for(j=0; j<8; ++j) fprintf(fileHandle, " %2.3f", feOccDistribution[j][i]); } fclose(fileHandle); }else{ /* Output Fifo WC */ /* clear distribution array */ for(i=0; i<0x100; ++i){ outFifoWCDistribution[i]=0.0; } /* compress data, get distribution */ for(i=0; i