diff --git a/slsvme.c b/slsvme.c new file mode 100644 index 0000000..2c1bb1f --- /dev/null +++ b/slsvme.c @@ -0,0 +1,805 @@ + /*-------------------------------------------------------------------------- + S L S V M E + + This file contains the driver for the PSI-DSP magnet controller as + aquired from SLS. + + This version is for the new interface provided by the vmemaggi server + program running on embedded linux on a computer in the VME crate which + talks directly to the IP communication mudules on the VME bus. + + Copyright: see file COPYRIGHT + + Mark Koennecke, April 2008 +----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "evdriver.h" +#include +#include +#include "vmemaggi.h" +#include + +#define ABS(x) (x < 0 ? -(x) : (x)) +extern char *trim(char *txt); + +#define DEVERR -2001 +#define BADHIGHLIM -2002 +#define BADLOWLIM -2003 +/*-----------------------------------------------------------------------*/ + typedef struct { + prs232 controller; + int iNum; + int iError; + int iDevError; + char errorText[80]; + } SLSDriv, *pSLSDriv; +/*-------------------------------------------------------------------------*/ +static int communicateSLS(pSLSDriv self, char *command, + char *reply, int replyLen) +{ + long lVal = 0; + int iRet, i, address, status; + char *pPtr; + char text[80]; + + if(!self->controller){ + self->iError = NOTCONNECTED; + strcpy(self->errorText,"Not Connected"); + return -1; + } + self->iDevError = 0; + + memset(reply,0,replyLen); + iRet = transactRS232(self->controller, command, strlen(command), + reply, replyLen); + if(iRet < 0){ + return iRet; + } + if(strstr(reply, "ERROR") != NULL){ + pPtr = reply; + /* jump over error */ + pPtr = stptok(pPtr,"text",80,":"); + /* read error number */ + pPtr = stptok(pPtr,"text",80,":"); + self->iError = atoi(trim(text)); + /* read error description */ + pPtr = stptok(pPtr,"text",80,":"); + strncpy(self->errorText, text, 80); + return DEVERR; + } + return 1; +} +/*--------------------------------------------------------------------------*/ +static void locateValue(char *rawReply, char *value, int valLen){ + char *pPtr; + + pPtr = rawReply; + pPtr = stptok(pPtr,value, valLen," "); + pPtr = stptok(pPtr,value, valLen," "); + stptok(pPtr,value, valLen," "); +} + /*---------------------------------------------------------------------*/ +static void slsdspCodeToText(int code, char *text, int textlen){ + switch(code){ + case 0x0: + strncpy(text,"NO",textlen); + break; + case 0x1: + strncpy(text,"DEVICE_STATE_ERROR",textlen); + break; + case 0x2: + strncpy(text,"DEVICE_SUPERVISOR_DISABLED",textlen); + break; + case 0x3: + strncpy(text,"COMMAND_ABORT",textlen); + break; + case 0x4: + strncpy(text,"DATA_NOT_STORED",textlen); + break; + case 0x5: + strncpy(text,"ERROR_ERASING_FLASH",textlen); + break; + case 0x6: + strncpy(text,"COMMUNICATION_BREAK",textlen); + break; + case 0x7: + strncpy(text,"INTERNAL_COMMUNICATION_ERROR",textlen); + break; + case 0x8: + strncpy(text,"MASTER_CARD_ERROR",textlen); + break; + case 0x9: + strncpy(text,"INTERNAL_BUFFER_FULL",textlen); + break; + case 0xa: + strncpy(text,"WRONG_SECTOR",textlen); + break; + case 0xb: + strncpy(text,"DATA_NOT_COPIED",textlen); + break; + case 0xc: + strncpy(text,"WRONG_DOWNLOAD_PARAMETERS",textlen); + break; + case 0xd: + strncpy(text,"DEVICE_PARAMETRIZATION_ERROR",textlen); + break; + case 0x10: + strncpy(text,"TIMEOUT_DC_LINK_VOLTAGE",textlen); + break; + case 0x11: + strncpy(text,"TIMEOUT_AUXILIARY_RELAY_ON",textlen); + break; + case 0x12: + strncpy(text,"TIMEOUT_AUXILIARY_RELAY_OFF",textlen); + break; + case 0x13: + strncpy(text,"TIMEOUT_MAIN_RELAY_ON",textlen); + break; + case 0x14: + strncpy(text,"TIMEOUT_MAIN_RELAY_OFF",textlen); + break; + case 0x15: + strncpy(text,"TIMEOUT_DATA_DOWNLOAD",textlen); + break; + case 0x20: + strncpy(text,"INTERLOCK",textlen); + break; + case 0x21: + strncpy(text,"MASTER_SWITCH",textlen); + break; + case 0x22: + strncpy(text,"MAGNET_INTERLOCK",textlen); + break; + case 0x23: + strncpy(text,"TEMPERATURE_TRANSFORMER",textlen); + break; + case 0x24: + strncpy(text,"TEMPERATURE_RECTIFIER",textlen); + break; + case 0x25: + strncpy(text,"TEMPERATURE_CONVERTER",textlen); + break; + case 0x26: + strncpy(text,"CURRENT_TRANSDUCER",textlen); + break; + case 0x27: + strncpy(text,"TEMPERATURE_POLARITY_SWITCH",textlen); + break; + case 0x28: + strncpy(text,"POWER_SEMICONDUCTOR",textlen); + break; + case 0x29: + strncpy(text,"MAIN_RELAY",textlen); + break; + case 0x2a: + strncpy(text,"AD_CONVERTER_CARD",textlen); + break; + case 0x2b: + strncpy(text,"POLARITY_SWITCH",textlen); + break; + case 0x2c: + strncpy(text,"AUXILIARY_RELAY",textlen); + break; + case 0x2d: + strncpy(text,"MASTER_SWITCH_T1",textlen); + break; + case 0x2e: + strncpy(text,"MASTER_SWITCH_T2",textlen); + break; + case 0x2f: + strncpy(text,"TEMPERATURE_MAGNET",textlen); + break; + case 0x30: + strncpy(text,"WATER_MAGNET",textlen); + break; + case 0x31: + strncpy(text,"WATER_RACK",textlen); + break; + case 0x40: + strncpy(text,"LOAD_CURRENT_TOO_HIGH",textlen); + break; + case 0x41: + strncpy(text,"DC_LINK_VOLTAGE_TOO_LOW",textlen); + break; + case 0x42: + strncpy(text,"DC_LINK_VOLTAGE_TOO_HIGH",textlen); + break; + case 0x43: + strncpy(text,"LOAD_VOLTAGE_TOO_HIGH",textlen); + break; + case 0x44: + strncpy(text,"LOAD_CURRENT_RIPPLE_TOO_HIGH",textlen); + break; + case 0x45: + strncpy(text,"DC_LINK_ISOLATION_NOT_OK",textlen); + break; + case 0x46: + strncpy(text,"LOAD_ISOLATION_NOT_OK",textlen); + break; + case 0x47: + strncpy(text,"LOAD_IMPEDANCE_OUT_OF_RANGE",textlen); + break; + case 0x48: + strncpy(text,"SHUT_OFF_CURRENT_TOO_HIGH",textlen); + break; + case 0x49: + strncpy(text,"LOAD_DC_CURRENT_TOO_HIGH",textlen); + break; + case 0x4a: + strncpy(text,"CURRENT_I1A1_TOO_HIGH",textlen); + break; + case 0x4b: + strncpy(text,"CURRENT_I1B1_TOO_HIGH",textlen); + break; + case 0x4c: + strncpy(text,"CURRENT_I1A2_TOO_HIGH",textlen); + break; + case 0x4d: + strncpy(text,"CURRENT_I1B2_TOO_HIGH",textlen); + break; + case 0x4e: + strncpy(text,"CURRENT_I2A1_TOO_HIGH",textlen); + break; + case 0x4f: + strncpy(text,"CURRENT_I2B1_TOO_HIGH",textlen); + break; + case 0x50: + strncpy(text,"CURRENT_I2A2_TOO_HIGH",textlen); + break; + case 0x51: + strncpy(text,"CURRENT_I2B2_TOO_HIGH",textlen); + break; + case 0x52: + strncpy(text,"CURRENT_I3P_TOO_HIGH",textlen); + break; + case 0x53: + strncpy(text,"CURRENT_I3N_TOO_HIGH",textlen); + break; + case 0x54: + strncpy(text,"CURRENT_IE_TOO_HIGH",textlen); + break; + case 0x55: + strncpy(text,"VOLTAGE_U1A_TOO_LOW",textlen); + break; + case 0x56: + strncpy(text,"VOLTAGE_U1B_TOO_LOW",textlen); + break; + case 0x57: + strncpy(text,"DIFF_CURRENT_I1A1_I1A2_TOO_HIGH",textlen); + break; + case 0x58: + strncpy(text,"DIFF_CURRENT_I1B1_I1B2_TOO_HIGH",textlen); + break; + case 0x59: + strncpy(text,"DIFF_CURRENT_I2A1_I2A2_TOO_HIGH",textlen); + break; + case 0x5a: + strncpy(text,"DIFF_CURRENT_I2B1_I2B2_TOO_HIGH",textlen); + break; + case 0x5b: + strncpy(text,"DIFF_CURRENT_I3P_I3N_TOO_HIGH",textlen); + break; + case 0x5c: + strncpy(text,"CURRENT_I1A_TOO_HIGH",textlen); + break; + case 0x5d: + strncpy(text,"CURRENT_I1B_TOO_HIGH",textlen); + break; + case 0x5e: + strncpy(text,"CURRENT_I3A1_TOO_HIGH",textlen); + break; + case 0x5f: + strncpy(text,"CURRENT_I3B1_TOO_HIGH",textlen); + break; + case 0x60: + strncpy(text,"CURRENT_I3A2_TOO_HIGH",textlen); + break; + case 0x61: + strncpy(text,"CURRENT_I3B2_TOO_HIGH",textlen); + break; + case 0x62: + strncpy(text,"CURRENT_I4_TOO_HIGH",textlen); + break; + case 0x63: + strncpy(text,"CURRENT_I5_TOO_HIGH",textlen); + break; + case 0x64: + strncpy(text,"DIFF_CURRENT_I3A1_I3A2_TOO_HIGH",textlen); + break; + case 0x65: + strncpy(text,"DIFF_CURRENT_I3B1_I3B2_TOO_HIGH",textlen); + break; + case 0x66: + strncpy(text,"DIFF_CURRENT_I4_I5_TOO_HIGH",textlen); + break; + case 0x67: + strncpy(text,"VOLTAGE_U3A_TOO_LOW",textlen); + break; + case 0x68: + strncpy(text,"VOLTAGE_U3B_TOO_LOW",textlen); + break; + case 0x69: + strncpy(text,"VOLTAGE_U1_TOO_LOW",textlen); + break; + case 0x6a: + strncpy(text,"VOLTAGE_U3A_TOO_HIGH",textlen); + break; + case 0x6b: + strncpy(text,"VOLTAGE_U3B_TOO_HIGH",textlen); + break; + case 0x6c: + strncpy(text,"SPEED_ERROR_TOO_HIGH",textlen); + break; + case 0x70: + strncpy(text,"MAIN_RELAY_A",textlen); + break; + case 0x71: + strncpy(text,"MAIN_RELAY_B",textlen); + break; + case 0x72: + strncpy(text,"POWER_SWITCH_A",textlen); + break; + case 0x73: + strncpy(text,"POWER_SWITCH_B",textlen); + break; + case 0x74: + strncpy(text,"MONITOR_TRAFO_A",textlen); + break; + case 0x75: + strncpy(text,"MONITOR_TRAFO_B",textlen); + break; + case 0x76: + strncpy(text,"TEMPERATURE_RECTIFIER_A",textlen); + break; + case 0x77: + strncpy(text,"TEMPERATURE_RECTIFIER_B",textlen); + break; + case 0x78: + strncpy(text,"TEMPERATURE_CONVERTER_A",textlen); + break; + case 0x79: + strncpy(text,"TEMPERATURE_CONVERTER_B",textlen); + break; + case 0x7a: + strncpy(text,"TEMPERATURE_CONVERTER_A1",textlen); + break; + case 0x7b: + strncpy(text,"TEMPERATURE_CONVERTER_B1",textlen); + break; + case 0x7c: + strncpy(text,"TEMPERATURE_CONVERTER_A2",textlen); + break; + case 0x7d: + strncpy(text,"TEMPERATURE_CONVERTER_B2",textlen); + break; + case 0x7e: + strncpy(text,"TEMPERATURE_TRANSFORMER_A",textlen); + break; + case 0x7f: + strncpy(text,"TEMPERATURE_TRANSFORMER_B",textlen); + break; + case 0x80: + strncpy(text,"WATER_RECTIFIER_A",textlen); + break; + case 0x81: + strncpy(text,"WATER_RECTIFIER_B",textlen); + break; + case 0x82: + strncpy(text,"WATER_CONVERTER_A",textlen); + break; + case 0x83: + strncpy(text,"WATER_CONVERTER_B",textlen); + break; + case 0x84: + strncpy(text,"WATER_CONVERTER_A1",textlen); + break; + case 0x85: + strncpy(text,"WATER_CONVERTER_B1",textlen); + break; + case 0x86: + strncpy(text,"WATER_CONVERTER_A2",textlen); + break; + case 0x87: + strncpy(text,"WATER_CONVERTER_B2",textlen); + break; + case 0x88: + strncpy(text,"WATER_TRANSFORMER_A",textlen); + break; + case 0x89: + strncpy(text,"WATER_TRANSFORMER_B",textlen); + break; + case 0x8a: + strncpy(text,"DOOR_A",textlen); + break; + case 0x8b: + strncpy(text,"DOOR_B",textlen); + break; + case 0x8c: + strncpy(text,"DOOR_C",textlen); + break; + case 0x8d: + strncpy(text,"POWER_SEMICONDUCTOR_CONVERTER_A",textlen); + break; + case 0x8e: + strncpy(text,"POWER_SEMICONDUCTOR_CONVERTER_B",textlen); + break; + case 0x8f: + strncpy(text,"POWER_SEMICONDUCTOR_CONVERTER_A1",textlen); + break; + case 0x90: + strncpy(text,"POWER_SEMICONDUCTOR_CONVERTER_B1",textlen); + break; + case 0x91: + strncpy(text,"POWER_SEMICONDUCTOR_CONVERTER_A2",textlen); + break; + case 0x92: + strncpy(text,"POWER_SEMICONDUCTOR_CONVERTER_B2",textlen); + break; + case 0x93: + strncpy(text,"CURRENT_TRANSDUCER_I3P",textlen); + break; + case 0x94: + strncpy(text,"CURRENT_TRANSDUCER_I3N",textlen); + break; + case 0x95: + strncpy(text,"MAGNET_INTERLOCK_1",textlen); + break; + case 0x96: + strncpy(text,"MAGNET_INTERLOCK_2",textlen); + break; + case 0x97: + strncpy(text,"VENTILATOR",textlen); + break; + case 0x98: + strncpy(text,"EMERGENCY_SWITCH",textlen); + break; + case 0x99: + strncpy(text,"CAPACITOR_DISCHARGE_A_ON",textlen); + break; + case 0x9a: + strncpy(text,"CAPACITOR_DISCHARGE_B_ON",textlen); + break; + case 0x9b: + strncpy(text,"CURRENT_TRANSDUCER_I4",textlen); + break; + case 0x9c: + strncpy(text,"CURRENT_TRANSDUCER_I5",textlen); + break; + case 0xb0: + strncpy(text,"TIMEOUT_DC_LINK_VOLTAGE_PART_A",textlen); + break; + case 0xb1: + strncpy(text,"TIMEOUT_DC_LINK_VOLTAGE_PART_B",textlen); + break; + case 0xb2: + strncpy(text,"TIMEOUT_AUXILIARY_RELAY_A_ON",textlen); + break; + case 0xb3: + strncpy(text,"TIMEOUT_AUXILIARY_RELAY_B_ON",textlen); + break; + case 0xb4: + strncpy(text,"TIMEOUT_AUXILIARY_RELAY_A_OFF",textlen); + break; + case 0xb5: + strncpy(text,"TIMEOUT_AUXILIARY_RELAY_B_OFF",textlen); + break; + case 0xb6: + strncpy(text,"TIMEOUT_MAIN_RELAY_A_ON",textlen); + break; + case 0xb7: + strncpy(text,"TIMEOUT_MAIN_RELAY_B_ON",textlen); + break; + case 0xb8: + strncpy(text,"TIMEOUT_MAIN_RELAY_A_OFF",textlen); + break; + case 0xb9: + strncpy(text,"TIMEOUT_MAIN_RELAY_B_OFF",textlen); + break; + } +} +/*---------------------------------------------------------------------------*/ + static int GetSLSPos(pEVDriver self, float *fPos) + { + pSLSDriv pMe = NULL; + char command[40], reply[132], value[40]; + int iRet; + + assert(self); + pMe = (pSLSDriv)self->pPrivate; + assert(pMe); + + /* + * first try to read the error code + */ + snprintf(command,40,"r %d err\n", pMe->iNum); + iRet = communicateSLS(pMe, command, reply, 132); + if(iRet < 0){ + return 0; + } + locateValue(reply, value,40); + sscanf(value,"%x", &iRet); + if(iRet != 0){ + slsdspCodeToText(iRet, pMe->errorText, 80); + pMe->iError = DEVERROR; + pMe->iDevError = iRet; + return 0; + } + + /* + * really read the current + */ + snprintf(command,40,"r %d cur\n", pMe->iNum); + iRet = communicateSLS(pMe, command, reply, 132); + if(iRet < 0){ + return 0; + } + locateValue(reply, value,40); + sscanf(value,"%f", fPos); + + return 1; + } +/*----------------------------------------------------------------------------*/ + static int SLSRun(pEVDriver self, float fVal) + { + pSLSDriv pMe = NULL; + int iRet; + char command[40], reply[132], value[40]; + + assert(self); + pMe = (pSLSDriv )self->pPrivate; + assert(pMe); + + /* + * first check if this on + */ + snprintf(command,40,"r %d onoff\n", pMe->iNum); + iRet = communicateSLS(pMe, command, reply, 132); + if(iRet < 0){ + return 0; + } + locateValue(reply,value,40); + if(strstr(value,"1") == NULL){ + /* + * switch on + */ + snprintf(command,40,"w %d on\n", pMe->iNum); + iRet = communicateSLS(pMe, command, reply, 132); + if(iRet < 0){ + return 0; + } + } + + /* + * set a new value + */ + snprintf(command,40,"w %d cur %f\n", pMe->iNum, fVal); + iRet = communicateSLS(pMe, command, reply, 132); + if(iRet < 0){ + return 0; + } + return 1; + } + +/*--------------------------------------------------------------------------*/ + static int SLSError(pEVDriver self, int *iCode, char *error, int iErrLen) + { + pSLSDriv pMe = NULL; + char *pPtr = NULL; + int i1, i2; + char pBueffel[132]; + + assert(self); + pMe = (pSLSDriv)self->pPrivate; + assert(pMe); + + *iCode = pMe->iError; + + if(pMe->iError == DEVERROR){ + strncpy(error,pMe->errorText, iErrLen); + return 1; + } + if(pMe->iError < -2000 || (pMe->iError >= 70 && pMe->iError < 83)){ + strncpy(error,pMe->errorText, iErrLen); + return 1; + } + + getRS232Error(*iCode,error,iErrLen); + + return 1; + } +/*-------------------------------------------------------------------------*/ + static int SLSSend(pEVDriver self, char *pCommand, char *pReply, int iLen) + { + pSLSDriv pMe = NULL; + int iRet, ival; + char command[40]; + + assert(self); + pMe = (pSLSDriv )self->pPrivate; + assert(pMe); + + if(strcmp(pCommand,"off") == 0){ + snprintf(command,40,"w %d off\n", pMe->iNum); + } else if(strcmp(pCommand,"on") == 0){ + snprintf(command,40,"w %d on\n", pMe->iNum); + } else { + strncpy(command,pCommand,40); + } + iRet = communicateSLS(pMe, command, pReply, iLen); + if(iRet < 0){ + return 0; + } + return 1; + } +/*--------------------------------------------------------------------------*/ + static int SLSInit(pEVDriver self) + { + pSLSDriv pMe = NULL; + int iRet, ival, i; + char msg[40], reply[40]; + + assert(self); + pMe = (pSLSDriv )self->pPrivate; + assert(pMe); + + iRet = initRS232(pMe->controller); + if(iRet < 0) + { + return 0; + } + setRS232SendTerminator(pMe->controller, "\n"); + setRS232ReplyTerminator(pMe->controller, "\n"); + setRS232Timeout(pMe->controller, 1000); + + snprintf(msg,40,"w %d on\n", pMe->iNum); + iRet = communicateSLS(pMe, msg, reply, 40); + if(iRet < 0){ + return 0; + } + + return 1; + } +/*--------------------------------------------------------------------------*/ + static int SLSClose(pEVDriver self) + { + pSLSDriv pMe = NULL; + int iRet, ival; + char msg[6], reply[6]; + + assert(self); + pMe = (pSLSDriv )self->pPrivate; + assert(pMe); + + closeRS232(pMe->controller); + + return 1; + } +/*---------------------------------------------------------------------------*/ + static int SLSFix(pEVDriver self, int iError) + { + pSLSDriv pMe = NULL; + int iRet, i, dataLen; + char buffer[80]; + char msg[6], reply[6]; + float fVal = .0; + + assert(self); + pMe = (pSLSDriv )self->pPrivate; + assert(pMe); + + switch(iError) + { + case BADHIGHLIM: + case BADLOWLIM: + case BADSLOT: + case BADMAP: + case DSPSTOP: + case LINKDWN: + case MISPS: + case PSRNG: + case NOPAR: + case NOVAL: + case BADPAR: + case SETRNG: + case DEVERROR: + return DEVFAULT; + break; + case SOFTTIM: + case FPGATIM: + case ADDRMIS: + return DEVREDO; + break; + case TIMEOUT: + for(i = 0; i < 10; i++){ + iRet = availableRS232(pMe->controller); + dataLen = 70; + if(iRet == 1){ + readRS232(pMe->controller, buffer,&dataLen); + } + } + return DEVREDO; + break; + default: + SLSClose(self); + iRet = SLSInit(self); + if(iRet) + { + return DEVREDO; + } + else + { + return DEVFAULT; + } + break; + } + } + +/*--------------------------------------------------------------------------*/ + static int SLSHalt(pEVDriver *self) + { + assert(self); + + return 1; + } +/*------------------------------------------------------------------------*/ + static void KillSLS(void *pData) + { + pSLSDriv pMe = NULL; + + pMe = (pSLSDriv)pData; + assert(pMe); + + free(pMe); + } +/*------------------------------------------------------------------------*/ + pEVDriver CreateSLSVMEDriv(int argc, char *argv[]) + { + pEVDriver pNew = NULL; + pSLSDriv pSim = NULL; + + /* check for arguments */ + if(argc < 2) + { + return NULL; + } + + pNew = CreateEVDriver(argc,argv); + pSim = (pSLSDriv)malloc(sizeof(SLSDriv)); + memset(pSim,0,sizeof(SLSDriv)); + if(!pNew || !pSim) + { + return NULL; + } + pNew->pPrivate = pSim; + pNew->KillPrivate = KillSLS; + + pSim->controller = FindCommandData(pServ->pSics, argv[0],"RS232 Controller"); + if(pSim->controller == NULL){ + return NULL; + } + pSim->iNum = atoi(argv[1]); + + /* initialise function pointers */ + pNew->SetValue = SLSRun; + pNew->GetValue = GetSLSPos; + pNew->Send = SLSSend; + pNew->GetError = SLSError; + pNew->TryFixIt = SLSFix; + pNew->Init = SLSInit; + pNew->Close = SLSClose; + + return pNew; + } + + + diff --git a/vmemaggi.h b/vmemaggi.h new file mode 100644 index 0000000..cb5d826 --- /dev/null +++ b/vmemaggi.h @@ -0,0 +1,62 @@ +/** + * This file contaisn some data structure definitions and constants + * for the VME-MAGII program. For more information see vmemaggi.c + * + * copyright: GPL + * + * Mark Koennecke, March 2008 + */ +#ifndef VMEMAGGI +#define VMEMAGGI + +#define SLOTBASE 0x1000 /* change when Hitec in different VME slot */ +#define MAPREG 0x424 +/** + * VME has several completely different address ranges: + * one 16 bit wide accessed through device node vme4l_a16d16 + * one 24 bit wide accessed through device node vme4l_a24d16 + * The sharc lives in the address range of the 24 bit bus. + */ +#define VMEDEV "/dev/vme4l_a16d16" +#define MODSIZE 0x100 + +typedef volatile unsigned char REG8BIT; +typedef volatile unsigned short REG16BIT; + +struct PSCreg { + REG16BIT stat_and_addr; + REG16BIT data_hi; + REG16BIT data_lo; + REG16BIT not_used; +} ; + +/* Bits of return status of the stat_and_addr word */ +#define PSC_REPLY_ERROR 0x20000 +#define PSC_STATUS_REPLY_READFLAG 0x8000 +#define PSC_STATUS_REPLY_FLAG_MISMATCH 0x4000 +#define PSC_STATUS_REPLY_BUFFERFULL 0x2000 +#define PSC_STATUS_REPLY_DSP_STOPPED 0x1000 /* disabled */ +#define PSC_STATUS_REPLY_PS_LOCAL 0x0800 +#define PSC_STATUS_REPLY_LINK_DOWN 0x0400 +#define PSC_STATUS_REPLY_ADDR_MISMATCH 0x0080 +#define PSC_STATUS_REPLY_DATA_MISMATCH 0x0040 +#define PSC_STATUS_REPLY_SOFTTIMEOUT 0x0020 +#define PSC_STATUS_REPLY_FPGATIMEOUT 0x0010 +#define PSC_STATUS_REPLY_STRLEN 256 + +/* error codes */ +#define BADSLOT 70 +#define BADMAP 71 +#define DSPSTOP 72 +#define LINKDWN 73 +#define SOFTTIM 74 +#define FPGATIM 75 +#define ADDRMIS 76 +#define MISPS 77 +#define PSRNG 78 +#define NOPAR 79 +#define NOVAL 80 +#define BADPAR 81 +#define SETRNG 82 + +#endif