From 7aef09ba4aca34e59f4dd19d85028c6c387f7f8e Mon Sep 17 00:00:00 2001 From: John Winans Date: Fri, 29 Jan 1993 11:52:04 +0000 Subject: [PATCH] major rewrite of init code. Added programming options --- src/drv/drvDvx.c | 1398 ++++++++++++++++++++++++++++++---------------- 1 file changed, 905 insertions(+), 493 deletions(-) diff --git a/src/drv/drvDvx.c b/src/drv/drvDvx.c index 0bb311d66..5182d1d5a 100644 --- a/src/drv/drvDvx.c +++ b/src/drv/drvDvx.c @@ -1,4 +1,4 @@ -/* +/* share/src/drv/drvDvx.c * share/src/drv $Id$ * * subroutines which are used to interface with the analogic 2502 @@ -61,7 +61,7 @@ * (only test routines affected) * * JH 07/25/91 added dvx_reset() and dvx_reset() on control X reboot - + * * JH 11/14/91 changed a sysBCLSet to sysIntEnable so ioc_core * will load into the nat inst cpu030 * @@ -83,10 +83,39 @@ * JH 08/03/92 moved interrupt vector base to module_types.h * JH 08/05/92 dvx driver init is called from drvDvx now * JH 08/10/92 merged dvx private include file into this source - * MRK 08/26/92 Added support for new I/O event scanning - */ + * JH 09/09/92 ran through UNIX C beautifier and converted to ANSI C + * JH 09/09/92 check to see if A24 is open prior to mapping + * the seq ram. + * JH 09/14/92 Made taskDelays() CPU tick rate independent + * tick rate + * JH 09/15/92 made interrupt vector CPU independent + * MRK 09/16/92 Added support for new I/O event scanning + * JH 09/16/92 dont write wordcnt every time the fifo is unloaded + * JH 09/16/92 Use sysLocalToBusAdrs() to translate from an internal + * to a VME A24 address in case the internal base for A24 + * addressed local memory is not on a 16MB boundary. + * sysLocalToBusAdrs() is called for each malloc'ed + * pointer used by the DVX to verify that each one is + * within the portion of local memory mapped to A24. + * JH 09/17/92 one more sysLocalToBusAdrs() address translation + * needed + * JRW 01/18/92 Replaced init code to allow user to select the interrupt + * level value and to select the ports that are to be read. + * + * + * NOTE (JRW 11-18-92): + * In a phone conversation with Analogic, Tech support said that when the start + * signal is de-asserted (when using external start/stop mode), the DMAC is + * told to start transferring more data. This is in case the sampling + * completes with less than 512 bytes in the fifo. + * + * BUGS: + * The driver should inspect the VXI make and model codes and use a data type + * for the DMA buffer that is appropriate. + */ + +static char *SccsId = "$Id$"; -static char *SccsId = "$Id$\t$Date$"; #include #include @@ -94,6 +123,11 @@ static char *SccsId = "$Id$\t$Date$"; #include #include #include +#ifdef V5_vxWorks +#include +#else +#include +#endif #ifndef EPICS_V2 #include #endif @@ -102,11 +136,9 @@ static char *SccsId = "$Id$\t$Date$"; #define DVX_ID 0xCFF5 /* analogic ID code */ #define MAX_DVX_CARDS 5 /* max # of 2502 cards per IOC */ #define MAX_PORTS 3 /* max # of 2601 cards per 2502 */ -#define MAX_CHAN 127 /* max chan when 2601 muxes are used */ #define DVX_DRATE 0xFFEC /* default scan rate of 184 KHz */ #define DVX_SRATE 0xF201 /* slow scan used for run away mode */ -#define DVX_RAMSIZE 2048 /* sequence RAM size */ -#define DVX_INTLEV 5 /* interrupt level 5 */ +#define DVX_RAMSIZE 2048 /* sequence RAM size (words) */ #define DVX_NBUF 1 /* default # of input buffers */ /* modes of operation */ @@ -138,53 +170,59 @@ static char *SccsId = "$Id$\t$Date$"; /* analogic 2502 memory structure */ struct dvx_2502 - { - unsigned short dev_id; /* device id code (CFF5) */ - unsigned short dev_type; /* type code (B100) */ - unsigned short csr; /* control and status register */ - unsigned short seq_offst; /* sequence RAM offset register */ - unsigned short mem_attr; /* memory attribute register */ - unsigned short samp_rate; /* sample rate register */ - unsigned short dma_point; /* DMA pointer register */ - unsigned short dma_data; /* DMA data register */ - unsigned short thresh; /* threshold register */ - unsigned short fifo; /* input fifo */ - unsigned short end_pad[54]; /* pad to 64 byte boundary */ - }; +{ + unsigned short dev_id; /* device id code (CFF5) */ + unsigned short dev_type; /* type code (B100) */ + unsigned short csr; /* control and status register */ + unsigned short seq_offst; /* sequence RAM offset register */ + unsigned short mem_attr; /* memory attribute register */ + unsigned short samp_rate; /* sample rate register */ + unsigned short dma_point; /* DMA pointer register */ + unsigned short dma_data; /* DMA data register */ + unsigned short thresh; /* threshold register */ + unsigned short fifo; /* input fifo */ + unsigned short end_pad[54]; /* pad to 64 byte boundary */ +}; /* input buffer */ struct dvx_inbuf - { - struct dvx_inbuf *link; /* link to next buffer */ - int wordcnt; /* # of words read to clear fifo */ - short data[512]; /* data buffer */ - }; +{ + struct dvx_inbuf *link; /* link to next buffer */ + int wordcnt; /* # of words read to clear fifo */ + short *data; /* data buffer */ +}; /* analogic 2502 control structure */ struct dvx_rec - { - struct dvx_2502 *pdvx2502; /* pointer to device registers */ - short *sr_ptr; /* pointer to sequence RAM */ - struct dvx_inbuf *inbuf; /* pointer to current buffer */ - short unsigned csr_shadow; /* csr shadow register */ - short mode; /* operation mode (init or run) */ - int int_vector; /* interrupt vector */ - int intcnt; /* interrupt count # */ - int cnum; /* card number */ +{ + struct dvx_2502 *pdvx2502; /* pointer to device registers */ + short *sr_ptr; /* pointer to sequence RAM */ + struct dvx_inbuf *inbuf; /* pointer to current buffer */ + short unsigned csr_shadow; /* csr shadow register */ + short mode; /* operation mode (init or run) */ + int int_vector; /* interrupt vector */ + int intcnt; /* interrupt count # */ + int cnum; /* card number */ + + int dmaSize; /* samples to read before IRQ */ + unsigned int numChan; /* total number of ports to read */ + unsigned long pgmMask[8]; /* ports to be read by seq-program */ + #ifndef EPICS_V2 - IOSCANPVT ioscanpvt; + IOSCANPVT *pioscanpvt; #endif - }; +}; /* dma chain table size */ #define DVX_CTBL 34 /* max size of chain table */ /* am9516 register select constants. - The DMA control registers are accessed through the dvx2502 registers - dma_point and dma_data. The constants below are the addresses which must - be loaded into the pointer register to access the named register through - the data register. All dual registers are commented as #2. To access channel - #1, OR the value M_CH1 with the channel #2 address. */ + * The DMA control registers are accessed through the dvx2502 registers + * dma_point and dma_data. The constants below are the addresses which must + * be loaded into the pointer register to access the named register through + * the data register. All dual registers are commented as #2. To access channel + * #1, OR the value M_CH1 with the channel #2 address. + */ #define DMA_MMR 0x38 /* master mode register */ #define DMA_CSR 0x2C /* command/status register #2 */ #define DMA_CARAH 0x18 /* current address reg A high #2 */ @@ -206,8 +244,9 @@ struct dvx_rec #define M_CH1 0x2 /* mask for chan 1 reg addresses */ /* am9516 command constants - All dual commands are commented as #1. To command channel #2, OR the - valur M_CH2 with the channel #1 command. */ + * All dual commands are commented as #1. To command channel #2, OR the + * valur M_CH2 with the channel #1 command. + */ #define MMR_ENABLE 0x0D /* chip enable value */ #define CMR_RESET 0x0 /* reset all channels */ #define CMR_START 0xA0 /* start channel #1 */ @@ -236,8 +275,8 @@ struct dvx_rec #define R_CAA 0x200 /* current address register A */ /* If any of the following does not exist replace it with #define <> NULL */ -long dvx_io_report(); -long dvx_driver_init(); +long dvx_io_report(int level); +long dvx_driver_init(void); struct { long number; @@ -248,183 +287,310 @@ struct { dvx_io_report, dvx_driver_init}; -struct dvx_rec dvx[MAX_DVX_CARDS]; -static char *dvx_shortaddr; -static char *dvx_stdaddr; +static struct dvx_rec dvx[MAX_DVX_CARDS] = { +{ NULL, NULL, NULL, -1, -1, -1, -1, -1, 128, 0, {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff} +#ifndef EPICS_V2 +, NULL +#endif +}, +{ NULL, NULL, NULL, -1, -1, -1, -1, -1, 128, 0, {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff} +#ifndef EPICS_V2 +, NULL +#endif +}, +{ NULL, NULL, NULL, -1, -1, -1, -1, -1, 128, 0, {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff} +#ifndef EPICS_V2 +, NULL +#endif +}, +{ NULL, NULL, NULL, -1, -1, -1, -1, -1, 128, 0, {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff} +#ifndef EPICS_V2 +, NULL +#endif +} +}; -/* variable used in io_report to report which cards have been found. */ +static int DVX_INTLEV=5; /* allow this to be user setable */ +static int dvxOnline = 0; /* 1 after init invoked */ -short dvx_cards_found[MAX_DVX_CARDS]; +int lclToA24(void *pLocal, void **ppA24); +void dvx_reset(void); +void dvx_int(struct dvx_rec *dvxptr); +int muxtst(int card); +int sramld(int card); +int dvx_driver( int card, int chan, short *pval); +int dvx_dread(int card,int chan); +int dvx_dump(int card,int firstchan,int lastchan); +int dvx_chan_print(int dvx_card, int firstchan, int lastchan); +int dvx_fempty(int card); +int dvx_dma_init(struct dvx_rec *ptr); +int dvx_dma_reset(struct dvx_rec *ptr); +int dvx_dma_stat(int card, int chan); -void dvx_reset(); -void dvx_int(); +int dvxDebug = 0; + + /* * dvx_int * * interrupt service routine * */ -void -dvx_int(dvxptr) - struct dvx_rec *dvxptr; +LOCAL void +dvx_int(struct dvx_rec *dvxptr) { - static short i, junk; - register struct dvx_2502 *cptr; - static unsigned int tick, t, intlev; + static short i, junk; + register struct dvx_2502 *cptr; + static unsigned int tick, t, intlev; - cptr = dvxptr->pdvx2502; - cptr->dma_point = DMA_CSR; - cptr->dma_data = CMR_CC | M_IP | M_CH2; /* clear dma int channel #2 */ - cptr->csr = dvxptr->csr_shadow & 0xff5f; /* disable fifo interrupts */ - switch (dvxptr->mode) - { - /* - interrupt recieved during initialization - - empty fifo and throw away data - */ - case INIT_MODE: - dvxptr->intcnt = 0; /* initialize interrupt count */ - for (i = 0; cptr->csr & 0x2; i++) - junk = cptr->fifo; - break; - /* - interrupt recieved during data aquisition - - empty fifo into next input buffer, then make it current - */ - case RUN_MODE: - dvxptr->intcnt++; /* incriment interrupt count */ - dvxptr->inbuf = dvxptr->inbuf->link; /* update current data buffer */ - for (i = 0; cptr->csr & S_NEPTY; i++, junk = cptr->fifo) - dvxptr->inbuf->wordcnt = i; /* record # of words to clear fifo */ - /* enable DMA opeations */ - cptr->dma_point = DMA_CSR; - cptr->dma_data = CMR_SC | M_CIE | M_CH2; /* enable int channel #2 */ - cptr->dma_data = CMR_START | M_CH2; /* start channel #2 */ + cptr = dvxptr->pdvx2502; + cptr->dma_point = DMA_CSR; + cptr->dma_data = CMR_CC | M_IP | M_CH2; /* clear dma int channel #2 */ + cptr->csr = dvxptr->csr_shadow & 0xff5f; /* disable fifo interrupts */ + switch (dvxptr->mode) + { + /* + * interrupt recieved during initialization + * - empty fifo and throw away data + */ + case INIT_MODE: + if(dvxDebug) + logMsg("dvx_int: INIT_MODE\n"); + dvxptr->intcnt = 0; /* initialize interrupt count */ + for (i = 0; cptr->csr & 0x2; i++) + junk = cptr->fifo; + break; + /* + * interrupt recieved during data aquisition + * - empty fifo into next input buffer, then make it current + */ + case RUN_MODE: + if(dvxDebug) + logMsg("dvx_int: RUN_MODE\n"); + dvxptr->intcnt++; /* incriment interrupt count */ + + dvxptr->inbuf = dvxptr->inbuf->link; /* update current data buffer */ + + for (i = 0; cptr->csr & S_NEPTY; i++, junk = cptr->fifo); + + dvxptr->inbuf->wordcnt = i; /* record # of words to clear fifo */ + + /* enable DMA opeations */ + cptr->dma_point = DMA_CSR; + cptr->dma_data = CMR_SC | M_CIE | M_CH2; /* enable int channel #2 */ + cptr->dma_data = CMR_START | M_CH2; /* start channel #2 */ #ifdef EPICS_V2 - io_scanner_wakeup(IO_AI,DVX2502,dvxptr->cnum); /*update database records */ + io_scanner_wakeup(IO_AI,DVX2502,dvxptr->cnum); /*update database records */ #else - scanIoRequest(dvxptr->ioscanpvt); + scanIoRequest(*(dvxptr->pioscanpvt)); #endif - break; - } - cptr->csr = dvxptr->csr_shadow; + break; + } + cptr->csr = dvxptr->csr_shadow; } + + /* * dvx_driver_init * * initialization for 2502 cards * */ -long dvx_driver_init() +LOCAL long dvx_driver_init(void) { - int card_id, i, j, status; - short *ramptr; - struct dvx_inbuf *ibptr, *ibptra; - int intvec = DVX_IVEC0; - struct dvx_2502 *ptr; - short *sptr; - /* - * dont continue DMA while vxWorks is control X - * rebooting (and changing bus arbitration mode) - * joh 072591 - */ - rebootHookAdd(dvx_reset); + int i; + int j; + int status; + unsigned short card_id; + short *ramptr; + struct dvx_inbuf *ibptr; + struct dvx_inbuf *ibptra; + int intvec = DVX_IVEC0; + struct dvx_2502 *pDvxA16; + short *pDvxA24; + short *pDvxA24Bus; + /* + * dont continue DMA while vxWorks is control X + * rebooting (and changing bus arbitration mode) + * joh 072591 + */ + rebootHookAdd(dvx_reset); - if ((status = sysBusToLocalAdrs(VME_AM_SUP_SHORT_IO,ai_addrs[DVX2502],&dvx_shortaddr)) != OK){ - printf("A16 base addr problems DVX 2502\n"); - return ERROR; - } + dvxOnline = 1; /* do not allow any more user config modifications */ - if ((status = sysBusToLocalAdrs(VME_AM_STD_SUP_DATA,ai_memaddrs[DVX2502],&dvx_stdaddr)) != OK){ - printf("A24 base addr problems DVX 2502\n"); - return ERROR; - } - - ptr = (struct dvx_2502 *)dvx_shortaddr; - sptr = (short int *)dvx_stdaddr; - for (i = 0; i < ai_num_cards[DVX2502]; i++, ptr++) /* search for cards */ - if (vxMemProbe (ptr,READ,2,&card_id) == OK) - if (ptr->dev_id == DVX_ID) /* see if detected card is a 2502 */ - { - /* - record card address and allocate input buffers - */ - dvx[i].pdvx2502 = ptr; /* record card address */ - dvx[i].cnum = i; /* record card number */ - ptr->csr = CSR_RESET; /* software reset */ - dvx[i].mode = INIT_MODE; /* initialization mode */ - /* create linked list of input buffers */ - for (j = 0, ibptra = 0; j < DVX_NBUF; j++, ibptra = ibptr) - { - if ((ibptr = (struct dvx_inbuf *)malloc(sizeof (struct dvx_inbuf))) - == NULL) /* abort if buffer allocation */ - return -1; /* unsuccessfull */ - - /* - * test for local/external addr dont match - * as the author assumed - */ - if(lclToA24(ibptr)!=ibptr){ - logMsg("%s: A24 address map failure\n"); + status = sysBusToLocalAdrs( + VME_AM_SUP_SHORT_IO, + ai_addrs[DVX2502], + &pDvxA16); + if (status != OK){ + logMsg( "%s: A16 base addr problems DVX 2502\n", + __FILE__); return ERROR; - } + } - if (j == 0) - dvx[i].inbuf = ibptr; /* initialize if first */ - ibptr->link = ibptra; /* link to last buffer */ - } - dvx[i].inbuf->link = ibptr; /* close list */ - /* - locate and enable sequence RAM - */ - dvx[i].sr_ptr = sptr; /* record seq RAM address */ - ptr->seq_offst = (int)sptr>>8; /* locate sequence RAM */ - dvx[i].csr_shadow = CSR_M_A24; /* enable sequence RAM (shadow csr) */ - ptr->csr = dvx[i].csr_shadow; /* enable sequence RAM */ - sptr += DVX_RAMSIZE; /* point to next seq RAM block */ - /* - set up interrupt handler - */ - dvx[i].csr_shadow |= (intvec<<8); /* load int vector (shadow csr) */ - ptr->csr = dvx[i].csr_shadow; /* load int vector */ - dvx[i].int_vector = intvec; /* save interrupt vector # */ - if (intConnect((intvec<<2),dvx_int,&dvx[i]) != OK) - return -2; /* abort if can't connect */ - sysIntEnable(DVX_INTLEV); /* enable interrupt level */ - dvx[i].csr_shadow |= CSR_M_INT; /* enable fifo int (shadow csr) */ - ptr->csr = dvx[i].csr_shadow; /* enable fifo interrupts */ - intvec++; /* advance to next vector # */ - - /* - test mux cards and load sequence RAM - */ - muxtst(i); /* test mux cards */ - sramld(i); /* load scan program */ - /* - initialize DMA - */ - dvx_dma_init(&dvx[i]); /* initialize DMA controller */ - dvx[i].csr_shadow ^= CSR_M_INT; /* disable fifo int (shadow csr) */ - ptr->csr = dvx[i].csr_shadow; /* disable fifo interrupts */ - /* - set scan rate and enable external start - */ - ptr->samp_rate = DVX_DRATE; /* scan rate of 184 KHz */ - dvx[i].csr_shadow |= CSR_M_ESTART; /* enable ext start (shadow csr) */ - ptr->csr = dvx[i].csr_shadow; /* enable external start */ - dvx[i].mode = RUN_MODE; /* ready to aquire data */ + + /* + * search for DVX cards + */ + for ( i = 0, pDvxA24Bus = (short *)ai_memaddrs[DVX2502]; + i < ai_num_cards[DVX2502]; + i++, pDvxA16++, pDvxA24Bus += DVX_RAMSIZE) + { +# ifdef DEBUG + logMsg("Probing for DVX at %x\n", pDvxA16); +# endif + + dvx[i].pdvx2502 = NULL; + status = vxMemProbe ( + &pDvxA16->dev_id, + READ, + sizeof(card_id), + &card_id); + if (status <0){ + continue; + } + if (card_id != DVX_ID){ /* see if detected card is a 2502 */ + logMsg("%s: Card installed at addr=0X%x is not a dvx2502\n", + __FILE__, + pDvxA16); + continue; + } + + /* Card found! Finish the init for it. */ + + dvx[i].cnum = i; /* record card number */ + pDvxA16->csr = CSR_RESET; /* software reset */ + + status = sysBusToLocalAdrs( + VME_AM_STD_SUP_DATA, + pDvxA24Bus, + &pDvxA24); + if (status != OK){ + logMsg( "%s: A24 base addr problems DVX 2502 A24=%x\n", + __FILE__, + pDvxA24Bus); + continue; + } + + /* + * check for incorrectly addressed card in A24 + */ + status = vxMemProbe (pDvxA24, READ, sizeof(card_id), &card_id); + if (status == OK){ + logMsg( "%s: A24 responding where DVX should be addr=%x\n", + __FILE__, + pDvxA24); + logMsg( "%s: DVX card=%d ignored\n", + __FILE__, + i); + continue; + } + + #ifndef EPICS_V2 - scanIoInit(&dvx[i].ioscanpvt); + if ((dvx[i].pioscanpvt = (IOSCANPVT *) malloc(sizeof(IOSCANPVT))) == NULL) + return(-1); #endif - } - else - dvx[i].pdvx2502 = 0; - else - dvx[i].pdvx2502 = 0; - return 0; /* return 0 to database */ + if (dvx[i].dmaSize == 0) + { + logMsg("%s: No channels selected on card %d, init aborted\n", i); + continue; + } + + dvx[i].mode = INIT_MODE; /* initialization mode */ + /* create linked list of input buffers */ + for ( j = 0, ibptra = NULL; + j < DVX_NBUF; + j++, ibptra = ibptr) + { + + ibptr = (struct dvx_inbuf *)malloc(sizeof (struct dvx_inbuf)); + /* + * exit with error if buffer allocation fails + */ + if (ibptr == NULL) + return -1; /* unsuccessfull */ + + if ((ibptr->data = (short *) malloc(dvx[i].dmaSize * sizeof(short))) == NULL) + return(-1); + + if (j == 0){ + dvx[i].inbuf = ibptr; /* initialize if first */ + } + + ibptr->wordcnt = 0; + ibptr->link = ibptra; /* LINK TO last buffer */ + } + dvx[i].inbuf->link = ibptr; /* close list */ + + /* + * locate sequence RAM in an unassigned portion of VME A24 + * + * Use the A24 bus address since the processor may not have placed + * A24 on a 16 MB boundary + */ + pDvxA16->seq_offst = (int)pDvxA24Bus>>8; + dvx[i].csr_shadow = CSR_M_A24; /* enable sequence RAM (shadow csr) */ + pDvxA16->csr = dvx[i].csr_shadow; /* enable sequence RAM */ + + /* + * record card address and allocate input buffers + */ + dvx[i].pdvx2502 = pDvxA16; /* record card address */ + + /* + * locate and enable sequence RAM + */ + dvx[i].sr_ptr = pDvxA24; /* record seq RAM address */ + + /* + * set up interrupt handler + */ + dvx[i].csr_shadow |= (intvec<<8); /* load int vector (shadow csr) */ + pDvxA16->csr = dvx[i].csr_shadow; /* load int vector */ + dvx[i].int_vector = intvec; /* save interrupt vector # */ + status = intConnect(INUM_TO_IVEC(intvec),dvx_int,&dvx[i]); + if (status != OK) + return -2; /* abort if can't connect */ + sysIntEnable(DVX_INTLEV); /* enable interrupt level */ + + /* make sure the DMA chip is fully disabled */ + dvx_dma_reset(dvx[i].pdvx2502); + + dvx[i].csr_shadow |= CSR_M_INT; /* enable fifo int (shadow csr) */ + pDvxA16->csr = dvx[i].csr_shadow; /* enable fifo interrupts */ + intvec++; /* advance to next vector # */ + + /* + * test mux cards and load sequence RAM + */ + muxtst(i); /* test mux cards */ + sramld(i); /* load scan program */ + + dvx[i].csr_shadow ^= CSR_M_INT; /* disable fifo int (shadow csr) */ + pDvxA16->csr = dvx[i].csr_shadow; /* disable fifo interrupts */ + /* + * initialize DMA + */ + dvx_dma_init(&dvx[i]); /* initialize DMA controller */ + /* + * set scan rate and enable external start + */ + pDvxA16->samp_rate = DVX_DRATE; /* scan rate of 184 KHz */ + dvx[i].csr_shadow |= CSR_M_ESTART; /* enable ext start (shadow csr) */ + pDvxA16->csr = dvx[i].csr_shadow; /* enable external start */ + dvx[i].mode = RUN_MODE; /* ready to aquire data */ +#ifndef EPICS_V2 + scanIoInit(dvx[i].pioscanpvt); +#endif + } + + return 0; /* return 0 to database */ } + + /* * muxtst * @@ -433,170 +599,372 @@ long dvx_driver_init() * the 2601 multiplexer cards. * */ -muxtst(card) - int card; - +LOCAL int muxtst(int card) { - int i; - short *ramptr; + int i; + short *ramptr; - /* - inhibit sys fail and load test setup parameters - */ - dvx[card].pdvx2502->csr = dvx[card].csr_shadow | CSR_M_SYSFINH; - ramptr = dvx[card].sr_ptr; /* pointer to sequence RAM */ - dvx[card].pdvx2502->thresh = TST_THRESH; /* load test threshold */ - dvx[card].pdvx2502->samp_rate = TST_RATE; /* test sample rate */ - /* - load test program into sequence RAM - */ - for (i = 0; i < MAX_PORTS; i++) - { - *ramptr++ = GAIN_CHANNEL; /* first sequence RAM value */ - *ramptr++ = ADVANCE_HOLD | i; /* mux card select */ - } - *ramptr++ = RESTART; /* end of scan */ - *ramptr = RESTART; - /* - run test and restore csr - */ - dvx[card].pdvx2502->csr = dvx[card].csr_shadow | CSR_M_MXTST; - taskDelay(1); /* let test run */ - dvx[card].pdvx2502->csr = dvx[card].csr_shadow; - dvx[card].pdvx2502->thresh = 0; /* restore threshold */ + /* + * inhibit sys fail and load test setup parameters + */ + dvx[card].pdvx2502->csr = dvx[card].csr_shadow | CSR_M_SYSFINH; + ramptr = dvx[card].sr_ptr; /* pointer to sequence RAM */ + dvx[card].pdvx2502->thresh = TST_THRESH; /* load test threshold */ + dvx[card].pdvx2502->samp_rate = TST_RATE; /* test sample rate */ + /* + * load test program into sequence RAM + */ + for (i = 0; i < MAX_PORTS; i++) + { + *ramptr++ = GAIN_CHANNEL; /* first sequence RAM value */ + *ramptr++ = ADVANCE_HOLD | i; /* mux card select */ + } + *ramptr++ = RESTART; /* end of scan */ + *ramptr = RESTART; + /* + * run test and restore csr + */ + dvx[card].pdvx2502->csr = dvx[card].csr_shadow | CSR_M_MXTST; + taskDelay(sysClkRateGet()); /* let test run */ + dvx[card].pdvx2502->csr = dvx[card].csr_shadow; + dvx[card].pdvx2502->thresh = 0; /* restore threshold */ } + /* - * sramld + * dvx_program() is used to define what ports on what boards to scan + * when taking a sample. Each time a start pulse is supplied to the DVX + * board, it will read from the ports in the specified by the user. When + * dmaSize samples have been taken (possibly after many start pulses) the DMA + * controller will terminate transferring data and generate a completion event. + * After this event, the whole process starts over again with the next start + * pulse. * - * load sequence RAM with 128 channel scan + * The dvx_program() parms are simply a bit mask of what ports to read from + * each board. There may be up to 8 boards on one DVX master. The bit masks + * are 32 bit unsigned numbers that should be assigned during the startup + * script when booting the IOC. * + * To program a DVX card (card 0) to read all ports from 2 S/H muxes (boards 2 + * and 6) and 1 mux (board 1). You may do the following. + * + * dvx_program(0, 2, 0x0000ffff, 0) -- 16 ports from board 2 + * dvx_program(0, 6, 0x0000ffff, 0) -- 16 ports from board 6 + * dvx_program(0, 1, 0xffffffff, 64) -- 32 ports from board 1 + * + * The 64 on the last line specified that we want to read 64 samples before the + * DMA is considered complete. The last dvx_program() value for the dma size + * is the only one that is used, all previous are discarded. + * + * If so desired, the above example could have used 128 for the DMA size value. + * in this case, the dvx 'system' would not consider the sample complete until + * all the ports were read twice. + * + * NOTE: Each card has its own notion of DMA size. Each card also has its + * own notion of default values. If no programming is done for a + * specific card number, its default values will be used. + * + * The ports are read from the lowest board number and lowest port number first. */ -sramld(card) - int card; - +int +dvx_program(int card, int board, unsigned long mask, int dmaSize) { - short *ramptr; - int i, j, temp; + int i; + unsigned long maskCheck; + int numSamp; + static int firstTime = 1; - /* - load 128 channel scan sequence in groups of 16 (1 mux at a time) - */ - ramptr = dvx[card].sr_ptr; /* point to sequence RAM */ - for (i = 0; i < ai_num_channels[DVX2502]; i += 16) - { /* load a single 16-1 mux */ - temp = i; /* load last due to pipeline delay */ - for (j = 1; j < 16; j++) - { /* load channels 1 to 15 */ - *ramptr++ = GAIN_CHANNEL | (((i+j)>>3) & 1); - *ramptr++ = ADVANCE_HOLD | ((((i+j) & 7)<<3) | (((i+j) & 0x70)>>4)); - } /* when done load channel 0 */ - *ramptr++ = GAIN_CHANNEL | ((temp>>3) & 1); - *ramptr++ = ADVANCE_HOLD | (((temp & 7)<<3) | ((temp & 0x70)>>4)); - } - /* - load remaining sequence RAM locations with prescan - prescan consists of channel 0 from each 16-1 mux (a total of 8 values) - */ - for (j = 0, i = i<<1; i < DVX_RAMSIZE; i += 2, j &= 0x7f) + if (dvxOnline) { - *ramptr++ = GAIN_CHANNEL | ((j>>3) & 1); - *ramptr++ = ADVANCE_HOLD | (((j & 7)<<3) | ((j & 0x70)>>4)); - j += 16; + printf("DVX cards are already on line, no modifications allowed\n"); + return(-1); } - /* - set scan rate and run scan - */ - dvx[card].pdvx2502->samp_rate = DVX_DRATE; - dvx[card].pdvx2502->csr = dvx[card].csr_shadow | CSR_M_START; - taskDelay(1); /* let scan run */ - dvx[card].pdvx2502->csr = dvx[card].csr_shadow; /* restore csr */ + if ((card < 0) || (card > ai_num_cards[DVX2502])) + { + printf("dvx_program(%d, %d, 0x%08.8X): invalid card number specified\n", card, board, mask); + return(1); + } + if ((board < 0) || (board > 7)) + { + printf("dvx_program(%d, %d, 0x%08.8X): invalid board number specified\n", card, board, mask); + return(2); + } + if (firstTime) + { /* Clear out the default port numbers, this is the first dvx_program call */ + int i; + + firstTime=0; + for (i=0; i<8; i++) + dvx[card].pgmMask[i] = 0; + } + + dvx[card].pgmMask[board] = mask; + dvx[card].dmaSize = dmaSize; + + return(0); } + +/* + * Allow the user to specify the interrupt level number + * + * It returns the 'old' IRQ level value. + */ +int dvx_setIrqLevel(int level) +{ + int i; + + if (dvxOnline) + { + printf("DVX card(s) already initialized at level %d, new IRQ level ignored\n", DVX_INTLEV); + return(DVX_INTLEV); + } + i = DVX_INTLEV; + DVX_INTLEV = level; + return(i); +} + +/* + * This can be called by a user program to get information about how + * the dvx card is programmed. + */ +int dvx_getProgram(int card, int *dmaSize, int *numChan) +{ + *dmaSize = dvx[card].dmaSize; + *numChan = dvx[card].numChan; + + if (dvxDebug) + printf("total DMA samples=%d, total number of physical channels=%d\n", *dmaSize, *numChan); + + return(-1); +} + +/* + * This version of the sequence program loader allows the number of channels + * to be programmable. It is assumed that the programmable constants will + * be fetched from the user. + * + */ +LOCAL +int sramld(int card) +{ + short *ramptr; + int i, port, firstPort; + unsigned long mask; + + /* load sequence program */ + ramptr = dvx[card].sr_ptr; /* point to sequence RAM */ + dvx[card].numChan = 0; + + for (i=0; i<8; i++) + { + mask = 1; + port = 0; + firstPort = -1; + + while(port < 32) + { + if (mask & dvx[card].pgmMask[i]) + { /* I need to read a sample from this port */ + if (firstPort == -1) + { /* save this one for prescan */ + firstPort = port; + } + else + { + *ramptr++ = GAIN_CHANNEL | ((port >> 3) & 3); + *ramptr++ = ADVANCE_HOLD | ((port & 0x07) << 3) | i; + dvx[card].numChan++; + if (dvxDebug) + printf("board %d, port %d\n", i, port); + } + } + mask <<= 1; + port++; + } + if (firstPort != -1) + { /* Put the first port number to read on each board, last in scan list. */ + *ramptr++ = GAIN_CHANNEL | ((firstPort >> 3) & 3); + *ramptr++ = ADVANCE_HOLD | ((firstPort & 0x07) << 3) | i; + dvx[card].numChan++; + if (dvxDebug) + printf("board %d, port %d\n", i, firstPort); + } + } + if (dvxDebug) + printf("Total channels read in %d\n", dvx[card].numChan); + +#if 0 /* Force the user to reference board 7 on their own */ + /* Make the extender system reset by referencing board 7 (No sample taken) */ + *ramptr++ = GAIN_CHANNEL | ((0xF0 >> 3) & 3); + *ramptr++ = (((0xF0 & 7) << 3) | ((0xF0 & 0xE0) >> 5)); +#endif + + *ramptr++ = 0; /* mark the end of the sequence program */ + *ramptr++ = 0; + + /* set scan rate and run it once */ + dvx[card].pdvx2502->samp_rate = DVX_DRATE; + dvx[card].pdvx2502->csr = dvx[card].csr_shadow | CSR_M_START; + taskDelay(sysClkRateGet()); /* let scan run */ + dvx[card].pdvx2502->csr = dvx[card].csr_shadow; /* restore csr */ +} + /* * dvx_driver * * interface to analog input buffer * */ -dvx_driver(card,chan,pval) -register short card; -short chan; -short *pval; +int dvx_driver( +int card, +int chan, +short *pval +) { - short ival; + short ival; - if ((card >= ai_num_cards[DVX2502]) || (card < 0)) /* make sure hardware exists */ - return -1; - else if (dvx[card].pdvx2502 == 0) - return -2; - *pval = dvx[card].inbuf->data[chan & 0x7f]; /* read buffer (128 elements) */ - return 0; + if ((card >= ai_num_cards[DVX2502]) || (card < 0)) /* make sure hardware exists */ + return -1; + else if (dvx[card].pdvx2502 == NULL) + return -2; + else if (chan > dvx[card].dmaSize) + return -2; + + *pval = dvx[card].inbuf->data[chan]; + return 0; } + +/* + * dvxReadWf + * + * Allows a waveform record to read all samples from the dvx buffer as a + * waveform. + */ +int dvxReadWf(int card, int start, int num, short *pwf, unsigned long *numRead) +{ + int dataIndex; + + if(dvxDebug) + printf("dvxReadWf(%d, %d, %d, 0x%08.8X, 0x%08.8X)\n", card, start, num, pwf, numRead); + + *numRead = 0; /* in case we have an error condition */ + + /* make sure hardware exists */ + if ((card >= ai_num_cards[DVX2502]) || (card < 0)) + return(-1); + else if ((dvx[card].pdvx2502 == NULL)||(start > dvx[card].dmaSize)|| + (start < 0)||(num < 1)) + return(-2); + + /* if user asked for too many, chop off the length to that available */ + if (start+num > dvx[card].dmaSize) + num -= (start+num) - dvx[card].dmaSize; + + dataIndex = start+num; + *numRead = num; + + if (dvxDebug) + printf("dvxReadWf(): Actual elements read: %d\n", num); + + while(num) + { + num--; + dataIndex--; + pwf[num] = dvx[card].inbuf->data[dataIndex]; + } + return(0); +} + + /* * dvx_dread * * stand alone interface to dvx_driver * */ -dvx_dread(card,chan) - int card, chan; +int dvx_dread(int card,int chan) { - short stat; - short unsigned data; - float volts; + short stat; + short unsigned data; + float volts; - stat = dvx_driver(card,chan,&data); - volts = data * 10./32767. - 10; - printf("channel # %d\tdata = %x\tvolts = %f\n" - ,chan,data,volts); + stat = dvx_driver(card,chan,(short *)&data); + volts = data * 10./32767. - 10; + printf("channel # %d\tdata = %x\tvolts = %f\n" + ,chan,data,volts); } + + /* * dvx_dump * * dump RAM buffer * */ -dvx_dump(card,firstchan,lastchan) - int card, firstchan, lastchan; +int dvx_dump(int card,int firstchan,int lastchan) { - int i; - short unsigned data; - float volts; - printf("Entering dvx_dump with card = %d,firstchan = %d,lastchan = %d\n",card,firstchan, - lastchan); - if ((card >= ai_num_cards[DVX2502]) || (card < 0)) - return -1; - else if (dvx[card].pdvx2502 == 0) - return -2; - printf("buffer address = %x word count = %d interrupt count = %d\n", - dvx[card].inbuf,dvx[card].inbuf->wordcnt,dvx[card].intcnt); - if (dvx[card].pdvx2502->csr & 0x2) - printf("fifo status = not empty"); - else - printf("fifo status = empty"); - printf(" current input channel = %x\n", - (dvx[card].pdvx2502->csr & 0x3fc0)>>6); - for (i = firstchan; i <= lastchan; i++) + int i, port, ix, printing, tmp; + short unsigned data; + unsigned long mask; + float volts; + + printf("Entering dvx_dump with card = %d,firstchan = %d,lastchan = %d\n",card,firstchan, + lastchan); + if ((card >= ai_num_cards[DVX2502]) || (card < 0)) + return -1; + else if (dvx[card].pdvx2502 == 0) + return -2; + printf("buffer address = %x word count = %d interrupt count = %d\n", + dvx[card].inbuf,dvx[card].inbuf->wordcnt,dvx[card].intcnt); + if (dvx[card].pdvx2502->csr & 0x2) + printf("fifo status = not empty,"); + else + printf("fifo status = empty,"); + printf(" current input channel = %x\n", + (dvx[card].pdvx2502->csr & 0x3fc0)>>6); + + ix = 0; + printing= 1; + while ((ix < dvx[card].dmaSize) && (ix < lastchan) && printing) { - data = dvx[card].inbuf->data[i]; - volts = data * 10./32767. - 10; - printf("channel # %d\tdata = %x\tvolts = %f\n" - ,i,data,volts); + printing = 0; + for (i=0; i<8; i++) + { + mask = 1; + port = 0; + while(port < 32) + { + if (mask & dvx[card].pgmMask[i]) + { + if (ix >= firstchan) + { + tmp = dvx[card].inbuf->data[ix]; + tmp &= 0x0000ffff; + + volts = tmp * 10./32767.; + printf("signal %2d, board %d, port %2d, data 0x%04.4X, voltage %f\n", ix, i, port, tmp, volts); + } + + ix++; + printing = 1; + } + mask <<= 1; + port++; + } + } } - printf("end of list\n"); - return(0); + + printf("end of list\n"); + + return 0; } #ifndef EPICS_V2 -dvx_getioscanpvt(card,scanpvt) -short card; -IOSCANPVT *scanpvt; +dvx_getioscanpvt(int card, IOSCANPVT *scanpvt) { - if ((card >= ai_num_cards[DVX2502]) || (card < 0)) /* make sure hardware exists */ - return(0); - if (dvx[card].pdvx2502 == 0) - return(0); - *scanpvt = dvx[card].ioscanpvt; - return(0); + if ((card >= ai_num_cards[DVX2502]) || (card < 0))return(0); + if (dvx[card].pdvx2502 == 0) return(0); + *scanpvt = *(dvx[card].pioscanpvt); + return(0); } #endif @@ -606,183 +974,232 @@ IOSCANPVT *scanpvt; * * */ -long dvx_io_report(level) - short int level; - { - short int i, j, card_id; - struct dvx_2502 *ptr; - int status; - int num_cards = 0; +long dvx_io_report(int level) +{ + short int i; + unsigned short card_id; - /* zero array for keeping track of which cards have - been found. */ - - for (i = 0; i < ai_num_cards[DVX2502]; i++){ - dvx_cards_found[i] = 0; - } - ptr = (struct dvx_2502 *)dvx_shortaddr; - for (i = 0; i < ai_num_cards[DVX2502]; i++, ptr++){ - status = vxMemProbe (ptr,READ,sizeof(card_id),&card_id); - if (status != OK) + for (i = 0; i < ai_num_cards[DVX2502]; i++){ + if (!dvx[i].pdvx2502) continue; - if (ptr->dev_id == DVX_ID){ /* If detected card is a 2502 - print out its number. */ - num_cards++; - dvx_cards_found[i] = 1; - printf("DVX2505: card %d\n",i); - } - - } - if((level > 0 ) && (num_cards >0)){ - for(j = 0; j < ai_num_cards[DVX2502];j++){ - int dvx_card; + /* If detected card is a 2502 print out its number. */ + printf("AI: DVX2505:\tcard %d\n",i); + + if(level > 0 ){ int firstchan; int lastchan; - - dvx_card = j; - if(dvx_cards_found[dvx_card] >0){ - printf("Enter number of the first channel you wish to read:\n"); - scanf("%d",&firstchan); - printf("First channel is %d\n",firstchan); - printf("Enter number of the last channel you wish to read:\n"); - scanf("%d",&lastchan); - printf("Last channel is %d\n",lastchan); - dvx_chan_print(dvx_card,firstchan,lastchan); - } + + printf("Enter number of the first channel you wish to read:\n"); + scanf("%d",&firstchan); + printf("First channel is %d\n",firstchan); + printf("Enter number of the last channel you wish to read:\n"); + scanf("%d",&lastchan); + printf("Last channel is %d\n",lastchan); + dvx_dump(i,firstchan,lastchan); } } - return OK; - } + return OK; +} - int dvx_chan_print(dvx_card,firstchan,lastchan) - short int dvx_card,firstchan,lastchan; - { - dvx_dump(dvx_card,firstchan,lastchan); - } + + /* * dvx_fempty * * empty fifo * */ -dvx_fempty(card) - int card; - +LOCAL int dvx_fempty(int card) { - int i, junk; + int i, junk; - if ((card>= ai_num_cards[DVX2502]) || (card < 0)) - return -1; - else if (dvx[card].pdvx2502 == 0) - return -2; - for (i = 0; dvx[card].pdvx2502->csr & 0x2; i++) - junk = dvx[card].pdvx2502->fifo; - printf("%d words read from fifo\n",i); - return 0; + if ((card>= ai_num_cards[DVX2502]) || (card < 0)) + return -1; + else if (dvx[card].pdvx2502 == 0) + return -2; + for (i = 0; dvx[card].pdvx2502->csr & 0x2; i++) + junk = dvx[card].pdvx2502->fifo; + printf("%d words read from fifo\n",i); + return 0; } + + +LOCAL dvx_dma_reset(struct dvx_2502 *dev) +{ + dev->dma_point = DMA_CSR; + dev->dma_data = CMR_RESET; /* reset the thing */ + return(0); +} + /* * dvx_dma_init * * am9516 DMA controller initialization * + * local to A24 bus addr conversions below are necessary on processors + * that dont place the local base for A24 on an even 16 MB boundary */ -dvx_dma_init(ptr) - struct dvx_rec *ptr; +LOCAL dvx_dma_init(struct dvx_rec *ptr) { - int i, j; - short *cptr, *cptra, *cptr0; - struct dvx_2502 *dev; - struct dvx_inbuf *bpnt; + int i, j; + int status; + short *cptr, *cptra, *cptr0, *pext; + short *BusPtr; + struct dvx_2502 *dev; + struct dvx_inbuf *bpnt; - dev = ptr->pdvx2502; /* point to hardware */ - dev->dma_point = DMA_CSR; /* reset chip */ - dev->dma_data = CMR_RESET; - /* build chain table */ - if ((cptr = cptr0 = (short *)malloc(DVX_CTBL)) == NULL) - return -1; - dev->dma_point = DMA_MMR; /* enable chip */ - dev->dma_data = MMR_ENABLE; - dev->dma_point = DMA_CARH; /* load init chain address */ - dev->dma_data = (int)cptr>>8 & 0xff00; - dev->dma_point = DMA_CARL; - dev->dma_data = (int)cptr & 0xffff; - for (i = 0, bpnt = ptr->inbuf->link; i < DVX_NBUF; - i++, cptr = cptra, bpnt = bpnt->link) - { /* create chain for each input buffer */ - if ((i + 1) == DVX_NBUF) - cptra = cptr0; /* close list */ - else - if ((cptra = (short *)malloc(DVX_CTBL)) == NULL) - return -1; /* allocate next chain */ - *cptr++ = R_CAA | R_CAB | R_COC | R_CMR | R_CAR; /* load mask */ - *cptr++ = 0xd0; - *cptr++ = (int)&dev->fifo & 0xffff; /* address reg A (src) */ - *cptr++ = (((int)bpnt->data>>8) & 0xff00) | 0xc0; - *cptr++ = (int)bpnt->data & 0xffff; /* address reg B (dest) */ - *cptr++ = 512; /* operation count */ - *cptr++ = 0x4; - *cptr++ = 0x0252; /* dma mode control */ - *cptr++ = (int)cptra>>8 & 0xff00; - *cptr = (int)cptra & 0xffff; /* next chain address */ - } - /* enable DMA opeations */ - dev->dma_point = DMA_CSR; - dev->dma_data = CMR_SC | M_CIE | M_CH2; /* enable int channel #2 */ - dev->dma_data = CMR_START | M_CH2; /* start channel #2 */ - return 0; + dev = ptr->pdvx2502; /* point to hardware */ + + dvx_dma_reset(dev); /* reset the DMA chip */ + + /* build chain table */ + if ((cptr = cptr0 = (short *)malloc(DVX_CTBL)) == NULL) + return -1; + dev->dma_point = DMA_MMR; /* enable chip */ + dev->dma_data = MMR_ENABLE; + + /* + * The 2502 uses A24 priv data VME addr mods + * for its DMAchain operations + */ + status = sysLocalToBusAdrs( + VME_AM_STD_SUP_DATA, + cptr, + &BusPtr); + if(status < 0){ + logMsg( "%s:Local chain addr 0x%X does not map to A24 bus addr\n", + __FILE__, + cptr); + return -1; + } + dev->dma_point = DMA_CARH; /* load init chain address */ + dev->dma_data = (int) BusPtr>>8 & 0xff00; + dev->dma_point = DMA_CARL; + dev->dma_data = (int) BusPtr & 0xffff; + + for ( i = 0, bpnt = ptr->inbuf->link; + i < DVX_NBUF; + i++, cptr = cptra, bpnt = bpnt->link) + { /* create chain for each input buffer */ + if ((i + 1) == DVX_NBUF) + cptra = cptr0; /* close list */ + else + if ((cptra = (short *)malloc(DVX_CTBL)) == NULL) + return -1; /* allocate next chain */ + + /* Set the reload word */ + *cptr++ = R_CAA | R_CAB | R_COC | R_CMR | R_CAR; /* load mask */ + + /* + * + * source options: + * 1) data (not chain) operation + * 2) hold (dont auto incr or decr) the src address + * + * The src addr here is ignored by the dvx2502 hardware + * and is therefore set to zero. The source is always + * the dvx 2502 fifo. + */ + *cptr++ = 0xd0; + *cptr++ = 0; /* address reg A (src) */ + + /* + * The 2502 uses A24 non-priv data VME addr mods + * for its DMA data transfers + */ + status = sysLocalToBusAdrs( + VME_AM_STD_USR_DATA, + bpnt->data, + &BusPtr); + if(status < 0){ + logMsg( "%s: Local dest addr 0x%X does not map to A24 addr\n", + __FILE__, + bpnt->data); + return -1; + } + *cptr++ = (((int)BusPtr>>8) & 0xff00) | 0xc0; + *cptr++ = (int) BusPtr & 0xffff; /* address reg B (dest) */ + + *cptr++ = ptr->dmaSize; /* operation count */ + *cptr++ = 0x4; + *cptr++ = 0x0252; /* dma mode control */ + + /* + * The 2502 uses A24 priv data VME addr mods + * for its DMA chain operations + */ + status = sysLocalToBusAdrs( + VME_AM_STD_SUP_DATA, + cptra, + &BusPtr); + if(status < 0){ + logMsg( "%s:Local addr 0x%X does not map to A24 addr\n", + __FILE__, + cptra); + return -1; + } + *cptr++ = (int)BusPtr>>8 & 0xff00; + *cptr = (int)BusPtr& 0xffff; /* next chain address */ + } + /* enable DMA opeations */ + dev->dma_point = DMA_CSR; + dev->dma_data = CMR_SC | M_CIE | M_CH2; /* enable int channel #2 */ + dev->dma_data = CMR_START | M_CH2; /* start channel #2 */ + return 0; } + + /* * dvx_dma_stat * * reads status of dma channel * */ -dvx_dma_stat(card,chan) - short card,chan; +int dvx_dma_stat(int card, int chan) { - struct dvx_2502 *ptr; - short unsigned temp; + struct dvx_2502 *ptr; + short unsigned temp; - if ((card < 0) || (card > ai_num_cards[DVX2502])) - return -1; - else if (dvx[card].pdvx2502 == 0) - return -2; - else - { - ptr = dvx[card].pdvx2502; - temp = (chan & 0x1)<<1; - ptr->dma_point = DMA_CSR | temp; - printf("dma status = %x\n",ptr->dma_data); - ptr->dma_point = DMA_MMR; - printf("master mode register = %x\n",ptr->dma_data); - ptr->dma_point = DMA_CARH | temp; - printf("chain address high = %x\n",ptr->dma_data); - ptr->dma_point = DMA_CARL | temp; - printf("chain address low = %x\n",ptr->dma_data); - ptr->dma_point = DMA_CARAH | temp; - printf("current address register A high = %x\n",ptr->dma_data); - ptr->dma_point = DMA_CARAL | temp; - printf("current address register A low = %x\n",ptr->dma_data); - ptr->dma_point = DMA_CARBH | temp; - printf("current address register B high = %x\n",ptr->dma_data); - ptr->dma_point = DMA_CARBL | temp; - printf("current address register B low = %x\n",ptr->dma_data); - ptr->dma_point = DMA_BARAH | temp; - printf("base address register A high = %x\n",ptr->dma_data); - ptr->dma_point = DMA_BARAL | temp; - printf("base address register A low = %x\n",ptr->dma_data); - ptr->dma_point = DMA_BARBH | temp; - printf("base address register B high = %x\n",ptr->dma_data); - ptr->dma_point = DMA_BARBL | temp; - printf("base address register B low = %x\n",ptr->dma_data); - ptr->dma_point = DMA_COC | temp; - printf("current operation count = %x\n",ptr->dma_data); - ptr->dma_point = DMA_BOC | temp; - printf("base operation count = %x\n",ptr->dma_data); - } - return 0; + if ((card < 0) || (card > ai_num_cards[DVX2502])) + return -1; + else if (dvx[card].pdvx2502 == 0) + return -2; + else + { + ptr = dvx[card].pdvx2502; + temp = (chan & 0x1)<<1; + ptr->dma_point = DMA_CSR | temp; + printf("dma status = %x\n",ptr->dma_data); + ptr->dma_point = DMA_MMR; + printf("master mode register = %x\n",ptr->dma_data); + ptr->dma_point = DMA_CARH | temp; + printf("chain address high = %x\n",ptr->dma_data); + ptr->dma_point = DMA_CARL | temp; + printf("chain address low = %x\n",ptr->dma_data); + ptr->dma_point = DMA_CARAH | temp; + printf("current address register A high = %x\n",ptr->dma_data); + ptr->dma_point = DMA_CARAL | temp; + printf("current address register A low = %x\n",ptr->dma_data); + ptr->dma_point = DMA_CARBH | temp; + printf("current address register B high = %x\n",ptr->dma_data); + ptr->dma_point = DMA_CARBL | temp; + printf("current address register B low = %x\n",ptr->dma_data); + ptr->dma_point = DMA_BARAH | temp; + printf("base address register A high = %x\n",ptr->dma_data); + ptr->dma_point = DMA_BARAL | temp; + printf("base address register A low = %x\n",ptr->dma_data); + ptr->dma_point = DMA_BARBH | temp; + printf("base address register B high = %x\n",ptr->dma_data); + ptr->dma_point = DMA_BARBL | temp; + printf("base address register B low = %x\n",ptr->dma_data); + ptr->dma_point = DMA_COC | temp; + printf("current operation count = %x\n",ptr->dma_data); + ptr->dma_point = DMA_BOC | temp; + printf("base operation count = %x\n",ptr->dma_data); + } + return 0; } @@ -792,32 +1209,51 @@ dvx_dma_stat(card,chan) * dvx_reset * joh 072591 * + * (JRW this should run thru the chain ok init'd boards, not do a probe) + * */ -void -dvx_reset() +LOCAL void +dvx_reset(void) { - struct dvx_2502 *ptr = (struct dvx_2502 *)dvx_shortaddr; - short card_id; - int i; - int status; + struct dvx_2502 *pDvxA16; + unsigned short card_id; + int i; + int status; int card_found = FALSE; + status = sysBusToLocalAdrs( + VME_AM_SUP_SHORT_IO, + ai_addrs[DVX2502], + &pDvxA16); + if (status != OK){ + logMsg( "%s: A16 base addr problems DVX 2502\n", + __FILE__); + return; + } + /* * search for cards */ - for (i = 0; i < ai_num_cards[DVX2502]; i++, ptr++){ - status = vxMemProbe (ptr,READ,sizeof(card_id),&card_id); - if (status != OK) + for (i = 0; i < ai_num_cards[DVX2502]; i++, pDvxA16++){ + status = vxMemProbe ( + &pDvxA16->dev_id, + READ, + sizeof(card_id), + &card_id); + if (status != OK) continue; /* * see if detected card is a 2502 * and reset if so */ - if (ptr->dev_id == DVX_ID){ - ptr->csr = CSR_RESET; + if (card_id == DVX_ID){ + /* reset the DMA controller */ + dvx_dma_reset(pDvxA16); + + pDvxA16->csr = CSR_RESET; card_found = TRUE; } - } + } /* * wait long enough for the current DMA to end @@ -825,33 +1261,9 @@ dvx_reset() * 1 sec */ if(card_found){ + printf("Waiting for DVX 2502 DMA to complete..."); taskDelay(sysClkRateGet()); + printf("done\n"); } } - - -/* - * - * lclToA24() - * - * - */ -LOCAL -void *lclToA24(void *pLocal) -{ - int status; - void *pA24; - - status = sysLocalToBusAdrs( - VME_AM_STD_SUP_DATA, - pLocal, - &pA24); - if(status<0){ - logMsg( "%s:Local addr 0x%X does not map to A24 addr\n", - __FILE__, - pLocal); - return NULL; - } - return pA24; -}