/************************************************************************************ * smSendTxtBuff.c * * synopsis: This is the state machine which handles text buffer state transitions * and communication with the host for readout of the text buffers. * * in this file: initSendTxtBuffSM, sendTxtBuffs, smSendTxtBuff, txtBuffSMIdle, * newInformation, addInformation, newDiagnostic, addDiagnostic, * newXfer, addXfer, newError, addError, setErrMask, getErrMask. * * related files: * smSendTxtBuff.h: Contains prototypes for routines in this file and definitions of * the states. * txtBuffer.c: Contains routines which write to and manage the text buffers. * txtBuffer.h: Contains the tag for the TXTBUFFER structure and related constants, * and prototypes for the functions in txtBuffer.c which are visible * from outside txtBuffer.c * * Damon Fasching, UW Madison fasching@wisconsin.cern.ch * Douglas Ferguson, UW Madison (510) 486-5230 dpferguson@lbl.gov * * - removed the two error macros (ADD_SEVERITY and MERGE_ERROR) and put them * inside errorCodes.h so that other routines can use them. 22.03.02 dpsf * - added 2 routines to add messages to the transfer buffer. 08.06.02 dpsf ************************************************************************************/ #include #include #include #include "resources.h" #include "memoryPartitions.h" #include "txtBuffer.h" #pragma CODE_SECTION(initSendTxtBuffSM, "xcode"); #pragma CODE_SECTION(sendTxtBuffs, "xcode"); #pragma CODE_SECTION(smSendTxtBuff, "xcode"); #pragma CODE_SECTION(txtBuffSMIdle, "xcode"); #pragma CODE_SECTION(addErrorInfo, "xcode"); #pragma CODE_SECTION(newInformation, "xcode"); #pragma CODE_SECTION(addInformation, "xcode"); #pragma CODE_SECTION(newDiagnostic, "xcode"); #pragma CODE_SECTION(addDiagnostic, "xcode"); #ifdef I_AM_MASTER_DSP #pragma CODE_SECTION(newXfer, "xcode"); #pragma CODE_SECTION(addXfer, "xcode"); #endif #pragma CODE_SECTION(newError, "xcode"); #pragma CODE_SECTION(addError, "xcode"); #pragma CODE_SECTION(setErrMask, "xcode"); #pragma CODE_SECTION(getErrMask, "xcode"); /* states of a message list processing state machine */ #define TXT_INACTIVE 0 // State machine is turned off #define TXT_IDLE 1 // Not processing, waiting for txtBuffer->occupied = true. #define TXT_WAITING 2 // Buffer occupied, notEmpty bit set, waiting for readRequest #define TXT_FROZEN 3 /* read by upstrm processor has been oked, buffer frozen until after read */ //dpsf: not true. /* instantiations of the text buffers */ struct TXTBUFFER errBuffer = { /* all error messages, fatal and nonfatal */ TXT_BFR_SZ - 1, /* dataEnd, fixed to last index of data array */ 0, /* readIndx, index of next element to read */ 0, /* writeIndx, index of next element to write */ LINBUFF, /* mode, after read, LINBUFF(RINGBUFF)=>set Indxs=0 (set writeIndx=readIndx) */ NOOVERWRITE, /* overwrite, OVERWRITE(NOOVERWRITE)=>overwrite old (throw away new) data if full */ TXT_BFR_NOOVERFLOW, /* overflow, flag indicating that the buffer is in overflow */ NOWRAPAROUND, /* wrap, flag indicating the buffer has wrapped around */ BUFFER_EMPTY, /* occupied, indicates whether there is data in the buffer */ ERR_BUFF, /* id of buffer */ (char *) ERR_BFR_BASE /* *data, pointer to the character data */ }; struct TXTBUFFER infoBuffer = { /* info buffer: general info , e.g. data avail, etc. */ TXT_BFR_SZ - 1, 0, 0, LINBUFF, NOOVERWRITE, TXT_BFR_NOOVERFLOW, NOWRAPAROUND, BUFFER_EMPTY, INFO_BUFF, (char *) INFO_BFR_BASE }; struct TXTBUFFER diagBuffer = { /* diagnostic buffer: acts like print during debug */ TXT_BFR_SZ - 1, 0, 0, RINGBUFF, OVERWRITE, TXT_BFR_NOOVERFLOW, NOWRAPAROUND, BUFFER_EMPTY, DIAG_BUFF, (char *) DIAG_BFR_BASE }; struct TXTBUFFER xferBuffer = { /* slave transfer buffer: slave txt buffer -> host */ TXT_BFR_SZ - 1, 0, 0, LINBUFF, NOOVERWRITE, TXT_BFR_NOOVERFLOW, NOWRAPAROUND, BUFFER_EMPTY, XFER_BUFF, (char *) XFER_BFR_BASE }; extern TIMER_Handle timer1; /* general purpose timer, started in main() */ /* file scope variables */ /* txtBuffer[n] is the address of text buffer n. * txtBuffState[n] is the current state of text buffer n. * errMsgMask selects, based on severity, which errors get written to text buffers */ struct TXTBUFFER *txtBuffer[N_TXT_BUFFS]; UINT32 txtBuffState[N_TXT_BUFFS]; UINT32 errMsgMask = 0; /* file scope routines */ INT32 smSendTxtBuff(UINT32 buffer); /************************************************************************************ * initSendTxtBuffSM * * synopsis: The addresses of the txtBuffer structures are written to the reply * buffer at initialization. After it is booted and the initialization * functions are completed, the DSP sets the RUNNING bit in its * STATUS_REGISTER. In the case of the master DSP, when the host sees this * bit, it reads these structure addresses from the reply buffer. In the * case of a slave DSP, when the master DSP sees this bit, it reads these * structure addresses from that slave's reply buffer. * * 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 initSendTxtBuffSM(void) { /* Initialize the state machines; slaves do not use the transfer buffer */ txtBuffState[ERR_BUFF]= TXT_IDLE; txtBuffState[INFO_BUFF]= TXT_IDLE; txtBuffState[DIAG_BUFF]= TXT_IDLE; #if defined(I_AM_MASTER_DSP) txtBuffState[XFER_BUFF]= TXT_IDLE; #else txtBuffState[XFER_BUFF]= TXT_INACTIVE; #endif /* get the addresses of the buffer descriptor structures */ txtBuffer[ERR_BUFF]= &errBuffer; txtBuffer[INFO_BUFF]= &infoBuffer; txtBuffer[DIAG_BUFF]= &diagBuffer; txtBuffer[XFER_BUFF]= &xferBuffer; /* Write the addresses of the buffer descriptor structures to the reply * buffer. The host will read these from the reply buffer of the MDSP after * booting. Temporary until the test-stand is modified to use the new * memory struct. dpsf. */ #if defined(I_AM_MASTER_DSP) *((UINT32 *) MDSP_REP_BFR_BASE +(ERR_BUFF))= (UINT32) txtBuffer[ERR_BUFF]; *((UINT32 *) MDSP_REP_BFR_BASE +(INFO_BUFF))= (UINT32) txtBuffer[INFO_BUFF]; *((UINT32 *) MDSP_REP_BFR_BASE +(DIAG_BUFF))= (UINT32) txtBuffer[DIAG_BUFF]; *((UINT32 *) MDSP_REP_BFR_BASE +(XFER_BUFF))= (UINT32) txtBuffer[XFER_BUFF]; #elif defined(I_AM_SLAVE_DSP) *((UINT32 *) SDSP_REP_BFR_BASE +(ERR_BUFF))= (UINT32) txtBuffer[ERR_BUFF]; *((UINT32 *) SDSP_REP_BFR_BASE +(INFO_BUFF))= (UINT32) txtBuffer[INFO_BUFF]; *((UINT32 *) SDSP_REP_BFR_BASE +(DIAG_BUFF))= (UINT32) txtBuffer[DIAG_BUFF]; *((UINT32 *) SDSP_REP_BFR_BASE +(XFER_BUFF))= (UINT32) txtBuffer[XFER_BUFF]; #endif return; } /************************************************************************************ * sendTxtBuffs * * synopsis: Calls readTxtBuffSM for each text buffer. * * arguments: * IN: slvDsp = number of the slave DSP ************************************************************************************/ INT32 sendTxtBuffs(void) { INT32 returnCode= SUCCESS, status; UINT32 idx; for (idx=0; idxstate == BUFFER_OCCUPIED) { setTxtBuffNE(buffer); txtBuffState[buffer] = TXT_WAITING; } break; case TXT_WAITING: /* has data and is waiting for a request to be read */ /* check the read request bit in the command register */ readRqst = getTxtBuffRR(buffer); /* If readRqst is set, reset the not-empty bit which indicates it is ok * to read; freeze the buffer until it is read. */ if (readRqst) { rstTxtBuffNE(buffer); txtBuffState[buffer] = TXT_FROZEN; } break; case TXT_FROZEN: /* Text buffer is frozen; waiting for the host to read it. */ /* Check read request bit, which will be reset after buffer has been read. * If read request has been cleared, thaw the buffer and go back to idle */ readRqst = getTxtBuffRR(buffer); if (!readRqst) { txtBuffState[buffer] = TXT_IDLE; txtMarkBufferRead(txtBuffer[buffer]); rstTxtBuffProc(buffer); } break; default: break; } /* end of switch on txtBuffState[buffer] */ return returnCode; } /************************************************************************************ * txtBuffSMIdle: return true the text buffer state machine for that buffer is * currently in TXT_IDLE, empty (ie. no pending requests, and * safe to write). * * 18.04.02 dpsf ************************************************************************************/ INT32 txtBuffSMIdle(UINT32 buffer) { if ( (txtBuffState[buffer] == TXT_IDLE) && (txtBuffer[buffer]->state == BUFFER_EMPTY)) return 1; else return 0; } /************************************************************************************ * newInformation, addInformation, newDiagnostic, addDiagnostic, newXfer, addXfer, * newError, addError * * synopsis: Interface routines to txtBuffer.c package for writing to the buffers. * * modifications/bugs * - Added addErrorInfo to function like addInformation, but place the text * into the error buffer. This allows us to give extra details on a * previously reported error, without any other extra information (addError * is for reporting the calling path of the error). 13.03.04 dpsf ************************************************************************************/ void addErrorInfo(char file[], INT32 line, char message[]) { txtAddBufferEntry(&errBuffer, file, line, message); return; } void newInformation(char file[], INT32 line, char message[]) { txtNewBufferEntry(&infoBuffer, file, line, message); return; } void addInformation(char file[], INT32 line, char message[]) { txtAddBufferEntry(&infoBuffer, file, line, message); return; } void newDiagnostic(char file[], INT32 line, char message[]) { txtNewBufferEntry(&diagBuffer, file, line, message); return; } void addDiagnostic(char file[], INT32 line, char message[]) { txtAddBufferEntry(&diagBuffer, file, line, message); return; } #ifdef I_AM_MASTER_DSP void newXfer(char file[], INT32 line, char message[]) { txtNewBufferEntry(&xferBuffer, file, line, message); return; } void addXfer(char file[], INT32 line, char message[]) { txtAddBufferEntry(&xferBuffer, file, line, message); return; } #endif /************************************************************************************ * newError * * synopsis: Error handler function called for the first message of an error stack. * Builds the error code and calls txtNewBufferEntry. * * arguments * IN: error = error code for the error which has just occurred * severity = severity level of the error * routine = name of the routine in which the error occurred * errorText = text describing the error * file = __FILE__ macro (file in which "routine" resides) * line = __LINE__ macro (line in "file" from which newError was called) * INOUT: *runningError = the error code with severity ************************************************************************************/ void newError(INT32 *runningError, INT32 error, INT32 severity, char routine[], char errorText[], char file[], INT32 line) { char errString[200]; if ((1 << severity) & ~errMsgMask) { sprintf(errString, " Error %#x occurred in %s with severity %x. %s.\n", abs(error), routine, severity-(ERROR_0), errorText); txtNewBufferEntry(&errBuffer, file, line, errString); } /* If the severity level is illegal, add an error message and set level to FATAL */ if (severity > FATAL_ERR) { txtAddBufferEntry(&errBuffer, __FILE__, __LINE__, " Illegal error severity, setting severity to FATAL\n"); severity = FATAL_ERR; } /* Add the severity bit to the error code and return in runningError. */ ADD_SEVERITY(*runningError, error, severity); return; } /************************************************************************************ * addError * * synopsis: Error handler routine called for all messages in an error stack except * the first. * Adds pre-existing severity bits to the error code and calls * txtAddBufferEntry. * NOTE: Writing of FATAL errros to the buffer can not be disabled. * * arguments * IN: error = error code which was returned by the subroutine * routine = name of the calling routine * branch = name of the routine in which the error occurred * file = file in which 'routine' resides * line = line number in 'file' from which addError was called * INOUT: *runningError = input: pre-existing stored error code * output: 'error' with the severity bits of input * 'runningError' added on ************************************************************************************/ void addError(INT32 *runningError, INT32 error, char routine[], char branch[], char file[], INT32 line) { char errString[100]; if ((error & SEVERITY_BITS) & ~errMsgMask) { sprintf(errString, " %s returned -%x to %s.\n", branch, abs(error), routine); txtAddBufferEntry(&errBuffer, file, line, errString); } /* Add the severity bits of runningError to error; return result in runningError */ MERGE_ERROR(*runningError, error); return; } /************************************************************************************ * Access routines for errMsgMask ************************************************************************************/ void setErrMask(UINT32 errMask) { UINT32 nonFatalMask = 0x7FFFFFFF & (~(FATAL_BIT)); /*Don't mask sign & FATAL bits*/ errMsgMask = errMask & nonFatalMask; return; } UINT32 getErrMask() { return errMsgMask; }