diff --git a/src/dev/devVxiTDM.c b/src/dev/devVxiTDM.c index aa352ec16..f06be1e19 100644 --- a/src/dev/devVxiTDM.c +++ b/src/dev/devVxiTDM.c @@ -30,8 +30,7 @@ * Modification Log: * ----------------- * .01 08-20-92 jbk Initial Implementation - * .02 02-16-92 joh vxi incl name change & cpu - * independent int vector include + * .02 09-18-92 jbk frame/slot addressing added * ... */ @@ -83,7 +82,7 @@ #include #include #include -#include +#include #include #include #include @@ -98,6 +97,7 @@ static long init(); static long init_pd(); static long get_ioint_info(); static long write_pd(); +static long get_enum(); typedef struct { long number; @@ -106,11 +106,12 @@ typedef struct { DEVSUPFUN init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN write; + DEVSUPFUN get_enum; } TDM_DSET; /*It doesnt matter who honors report or init thus let 1st devSup do it*/ -TDM_DSET devPdVxiTDM = { 5, report, init, init_pd, NULL, write_pd }; +TDM_DSET devPdVxiTDM = { 6, report, init, init_pd, NULL, write_pd, get_enum }; volatile int VxiTDMDebug=0; @@ -119,9 +120,6 @@ volatile int VxiTDMDebug=0; /* definitions related to fields of records*/ /* defs for gtyp and ctyp fields */ -#define INTERNAL 0 -#define EXTERNAL 1 -#define SOFTWARE 1 #define ACTIVE 1 #define INACTIVE 0 @@ -135,15 +133,9 @@ volatile int VxiTDMDebug=0; #define TRGS3 0x0200 #define TRGS4 0x0300 -/* vxi register offsets */ -#define ID_REG_OFFSET 0x0000 -#define DEV_TYPE_REG_OFFSET 0x0002 -#define STAT_CTRL_REG_OFFSET 0x0004 -#define OFFSET_REG_OFFSET 0x0006 - #define TRIG_ENABLE(reg) (reg|0x0400) #define TRIG_DISABLE(reg) (reg&(~0x400)) -#define TRIG_VALUE(reg) (reg&0x0400) +#define TRIG_VALUE(reg) ((reg&0x0400)?1:0) #define DELAY_CLEAR(reg) (reg&0xff00) #define DELAY_SET(delay,reg) (DELAY_CLEAR(reg)|delay) @@ -151,24 +143,24 @@ volatile int VxiTDMDebug=0; #define TRIG_DETECT(reg) (0x0800®) -#define VXI_BASE 0xc000 -#define CARD_SIZE 0x0040 #define REG_OFFSET 0x0020 -#define MAXCARDS 31 +/* EPICS_VXI_LA_COUNT is a global variable that must be present in the IOC */ +#define MAXCARDS EPICS_VXI_LA_COUNT #define MAXSIG 9 #define MAX_NANOSEC 1275e1 #define MAX_DELAY 255e1 #define TIME_FACT MAX_DELAY/MAX_NANOSEC #define TIME_FACT_TO MAX_NANOSEC/MAX_DELAY -#define CARD(la) (char *)shortaddr+CARD_SIZE*la -#define SIGNAL(la,signal) CARD(la)+REG_OFFSET+signal*2 +#define VXI_MAKE_TDM 0xee4 /* official is 3812 */ +#define VXI_MODEL_TDM 0xf01 /* test one 0xf01 */ -#define VXI_MAKE_TDM 0xf00 -#define VXI_MODEL_TDM 0xf00 +unsigned long VxiTDM_make = VXI_MAKE_TDM; +unsigned long VxiTDM_model = VXI_MODEL_TDM; static unsigned long tdmDriverID; +/* config area for each card */ /* for stat-> bit per channel 1=used/valid, 0=unused/invalid, bit-0=channel-0 */ struct tdm_config { @@ -187,6 +179,10 @@ static void tdm_stat(); static void tdm_report(); +/***************************************************************/ +/* + report for device - just uses the vxi report +*/ static long report(int interest) { @@ -198,19 +194,27 @@ epvxiDeviceSearchPattern dsp; printf("Report for Vxi Time Delay Module\n"); dsp.flags=VXI_DSP_make|VXI_DSP_model; - dsp.make=VXI_MAKE_TDM; - dsp.model=VXI_MODEL_TDM; + dsp.make=VxiTDM_make; /* VXI_MAKE_TDM; */ + dsp.model=VxiTDM_model; /* VXI_MODEL_TDM; */ if( epvxiLookupLA(&dsp,tdm_report,(void *)&interest)<0 ) return ERROR; - return (OK); + + return OK; } static void tdm_report(unsigned la,void *interest) { tdm_stat(la,(int)*(int *)interest); + + return; } +/***************************************************************/ +/* + Initialize all the TDM cards +*/ + static long init(int after) { epvxiDeviceSearchPattern dsp; @@ -220,29 +224,39 @@ epvxiDeviceSearchPattern dsp; tdmDriverID=epvxiUniqueDriverID(); dsp.flags=VXI_DSP_make|VXI_DSP_model; - dsp.make=VXI_MAKE_TDM; - dsp.model=VXI_MODEL_TDM; + dsp.make=VxiTDM_make; /* VXI_MAKE_TDM; */ + dsp.model=VxiTDM_model; /* VXI_MODEL_TDM; */ if( epvxiLookupLA(&dsp,tdmInitLA,(void *)NULL) <0) + { + logMsg("No ANL Time Delay Modules found\n"); return ERROR; + } - if(epvxiRegisterMakeName(VXI_MAKE_TDM,"ANL")<0) + if(epvxiRegisterMakeName(VxiTDM_make,"ANL")<0) /* VXI_MAKE_TDM */ logMsg("%s: unable to register MAKE\n",__FILE__); - if(epvxiRegisterModelName(VXI_MAKE_TDM,VXI_MODEL_TDM, - "Time Delay Module")<0) + if(epvxiRegisterModelName(VxiTDM_make,VxiTDM_model, + "Time Delay Module")<0) /* VXI_MAKE_TDM VXI_MODEL_TDM */ logMsg("%s: unable to register MODEL\n",__FILE__); return OK; } +/***************************************************************/ +/* + Initialize one TDM card +*/ + static void tdmInitLA(unsigned la) { int status; struct vxi_csr *pcsr; struct tdm_config *tc; + Debug("tdmInitLA() la=%d \n",la); + status=epvxiOpen(la,tdmDriverID,sizeof(struct tdm_config),tdm_stat); if(status<0) @@ -269,12 +283,18 @@ struct tdm_config *tc; } +/***************************************************************/ +/* + Initialize a pulse delay record channel (signal) +*/ + static long init_pd(struct pulseDelayRecord *pd) { struct vxiio *pvxiio = (struct vxiio *)&(pd->out.value); int dummy; short la,signal; unsigned short *channel_reg; +static unsigned epvxiGetLa(); struct vxi_csr *pcsr; struct tdm_config *tc; @@ -285,6 +305,7 @@ struct tdm_config *tc; case (VXI_IO): break; + default : recGblRecordError(S_dev_badBus,(void *)pd, "devVxiTDM (init_record) Illegal OUT Bus Type"); return(S_dev_badBus); @@ -292,7 +313,13 @@ struct tdm_config *tc; /* initialize to null indicating no address found */ - la = pvxiio->la; + if((la=epvxiGetLa(pvxiio))<0) + { + recGblRecordError(S_dev_badSignal,(void *)pd, + "devVxiTDM (init_record) Illegal frame/slot"); + return(S_dev_badSignal); + } + Debug("got la = %d\n",la); if(isdigit(pvxiio->parm[0])) signal=pvxiio->parm[0]-'0'; @@ -310,7 +337,7 @@ struct tdm_config *tc; Debug("signal = %d \n",signal); Debug("parm = (%s) \n",pvxiio->parm); - if(la>MAXCARDS) + if(la>=MAXCARDS) { recGblRecordError(S_dev_badCard,(void *)pd, "devVxiTDM (init_record) exceeded maximum supported cards"); @@ -327,11 +354,20 @@ struct tdm_config *tc; /* get the address of the register for this la and signal */ tc=epvxiPConfig(la,tdmDriverID,struct tdm_config *); + + if(!tc) + { + recGblRecordError(S_dev_badSignal,(void *)pd, + "devVxiTDM (init_record) No card at address"); + return(S_dev_badSignal); + } + pcsr=VXIBASE(la); (char *)channel_reg=(char *)pcsr+REG_OFFSET; Debug("channel_reg = %08.8X \n",channel_reg); + Debug("tc->stat = %x \n",tc->stat); if( tc->stat&(1<pfld) + /* only lower 2 bytes used in pfld - kludge to be removed later */ + + if(!(pr->pfld&0x00ff)) { channel_read=channel_reg[signal]; @@ -428,6 +471,7 @@ struct tdm_config *tc; else pr->val=INACTIVE; + pr->udf=FALSE; pr->dly=(double)DELAY_VALUE(channel_read)*TIME_FACT_TO; pr->hts=TRGS_VALUE(channel_read); pr->gate=TRIG_VALUE(channel_read); @@ -446,7 +490,14 @@ struct tdm_config *tc; Debug("delay time = %d\n",delay_time); Debug("units = %d \n",pr->unit); - if(delay_time > 255) delay_time=255; + if(delay_time > 255) + { + recGblSetSevr(pr,WRITE_ALARM,INVALID_ALARM); + recGblRecordError(S_db_badField,(void *)pr, + "invalid delay value - set to max"); + + delay_time=255; + } channel_value=DELAY_SET(delay_time,channel_value); @@ -466,7 +517,8 @@ struct tdm_config *tc; if(pr->hts > 3) { recGblSetSevr(pr,WRITE_ALARM,INVALID_ALARM); - recGblRecordError(S_db_badField,(void *)pr,"invalid trigger value"); + recGblRecordError(S_db_badField,(void *)pr, + "invalid trigger value"); return(0); } @@ -476,6 +528,7 @@ struct tdm_config *tc; channel_reg[signal]=channel_value; Debug("Ending channel value = %04.4X\n",channel_value); + } FASTUNLOCK(&tc->lock); @@ -484,6 +537,11 @@ struct tdm_config *tc; } +/***************************************************************/ +/* + report for vxi routines +*/ + static void tdm_stat(unsigned la,int level) { struct tdm_config *tc; @@ -502,3 +560,83 @@ int i; printf("\n"); } + +/***************************************************************/ +/* + Routines to fill vxiio stucture - + always returns la + calculates la from frame/slot or figures out frame/slot + from la +*/ + +#define MAX_VXI_SLOTS 12 +#define MAX_VXI_FRAMES 255 + +static void epvxiGetLA_one(unsigned la,void *pvxiio) +{ +struct vxiio *pvxi=(struct vxiio *)pvxiio; + + Debug("epvxiGetLA_one() la = %x \n",la); + pvxi->la=(short)la; + + return; +} + +static unsigned epvxiGetLa(struct vxiio *pvxiio,unsigned long vxiDriverID) +{ +epvxiDeviceSearchPattern dsp; + + if(pvxiio->flag==0) /* frame */ + { + dsp.flags=VXI_DSP_slot|VXI_DSP_slot_zero_la; + + if(pvxiio->slot > MAX_VXI_SLOTS || pvxiio->slot < 0 || + pvxiio->frame > MAX_VXI_FRAMES || pvxiio->frame < 0) + return ERROR; + + dsp.slot=(unsigned char)pvxiio->slot; + dsp.slot_zero_la=(unsigned char)pvxiio->frame; + + Debug("epvxiGetLa() dsp.slot=%d\n",dsp.slot); + Debug("epvxiGetLa() dsp.slotzero_la=%d\n",dsp.slot_zero_la); + + if( epvxiLookupLA(&dsp,epvxiGetLA_one,(void *)pvxiio) <0) + return ERROR; + } + else /* SA - static address (la) */ + { + pvxiio->frame=PVXIDI(pvxiio->la)->slot_zero_la; + pvxiio->slot=PVXIDI(pvxiio->la)->slot; + } + + return(pvxiio->la); +} + +#define LOW_HTS 0 +#define HIGH_HTS 3 + +static long get_enum(struct dbAddr *paddr,struct dbr_enumStrs *p) +{ + struct pulseDelayRecord *ppd=(struct pulseDelayRecord *)paddr->precord; + int i,j; + + Debug("Getting values for hts\n",0); + + if(paddr->pfield==(void *)&ppd->hts) + { + for(j=0,i=LOW_HTS;i<=HIGH_HTS&&jstrs[j],"%d",i); + } + + p->no_str=j; + } + else + { + p->no_str=0; + } + + return(0); +} +