1270 lines
34 KiB
C
1270 lines
34 KiB
C
/* share/src/drv/drvDvx.c
|
||
* share/src/drv $Id$
|
||
*
|
||
* subroutines which are used to interface with the analogic 2502
|
||
* A/D scanner cards
|
||
*
|
||
* Author: Matthew Stettler
|
||
* Date: 5-23-90
|
||
*
|
||
* AT-8 hardware design
|
||
*
|
||
* Modules:
|
||
*
|
||
* dvx_driver_init Finds and initializes all 2502 cards
|
||
* dvx_dma_init Initializes Am9516 DMA controller
|
||
* dvx_driver Reads data from 2502
|
||
* dvx_int Interrupt service routine
|
||
*
|
||
* Test Routines:
|
||
*
|
||
* dvx_dump dumps RAM buffer
|
||
* dvx_dread command line interface to dvx_driver
|
||
* dvx_fempty clears fifo from command line
|
||
* dvx_dma_stat displays DMA channel status
|
||
*
|
||
* Experimental Physics and Industrial Control System (EPICS)
|
||
*
|
||
* Copyright 1991, the Regents of the University of California,
|
||
* and the University of Chicago Board of Governors.
|
||
*
|
||
* This software was produced under U.S. Government contracts:
|
||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||
*
|
||
* Initial development by:
|
||
* The Controls and Automation Group (AT-8)
|
||
* Ground Test Accelerator
|
||
* Accelerator Technology Division
|
||
* Los Alamos National Laboratory
|
||
*
|
||
* Co-developed with
|
||
* The Controls and Computing Group
|
||
* Accelerator Systems Division
|
||
* Advanced Photon Source
|
||
* Argonne National Laboratory
|
||
*
|
||
* Modification Log:
|
||
* -----------------
|
||
* MS 6/22/90 Modifications to aid in debugging interface to Mizar timing
|
||
* system. Interrupt service routine now counts words when clearing
|
||
* fifo, dvx_dump provides fifo status, and dvx_fempty added to
|
||
* clear fifo from command line.
|
||
*
|
||
* MS 7/9/90 Modifications to speed up interrupt service routine.
|
||
*
|
||
* MS 7/23/90 Added DMA control logic.
|
||
*
|
||
* MS 8/20/90 Added support for interrupt scanned records.
|
||
*
|
||
* MS 9/20/90 Changed data conversion to offset binary
|
||
* (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
|
||
*
|
||
* JH 11/14/91 removed sysBCLSet enabling STD non priv and super
|
||
* access since this is already enabled if we are
|
||
* processor 0
|
||
* JH 11/14/91 changed DVX_INTLEV from a mask to a level
|
||
* to support use of sysIntEnable() which
|
||
* is architecture independent
|
||
* BG 4/22/92 added sysBusToLocalAddr() for both short and standard
|
||
* addresses for this module. Moved DVX_ADDR0 to
|
||
* ai_addrs[DVX2502]in module_types.h. Also moved DVX_IVECO
|
||
* to module_types.h.
|
||
* BG 6/23/92 combined dvx_driver.c and drvDvx.c
|
||
* BG 06/26/92 added level to dvx_io_report in drvDvx structure.
|
||
* JH 06/29/92 moved the rest of the dvx io_report here
|
||
* BG 7/2/92 removed the semaphores from dvx_io_report
|
||
* JH 08/03/92 Removed hkv2f dependent base addr
|
||
* 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
|
||
* 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$";
|
||
|
||
|
||
#include <vxWorks.h>
|
||
#include <stdioLib.h>
|
||
#include <vme.h>
|
||
#include <dbDefs.h>
|
||
#include <drvSup.h>
|
||
#include <module_types.h>
|
||
#ifdef V5_vxWorks
|
||
#include <iv.h>
|
||
#else
|
||
#include <iv68k.h>
|
||
#endif
|
||
#ifndef EPICS_V2
|
||
#include <dbScan.h>
|
||
#endif
|
||
|
||
/* general constants */
|
||
#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 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 (words) */
|
||
#define DVX_NBUF 1 /* default # of input buffers */
|
||
|
||
/* modes of operation */
|
||
#define INIT_MODE 0 /* initialization mode */
|
||
#define RUN_MODE 1 /* aquisition mode */
|
||
|
||
/* self test constants */
|
||
#define TST_RATE 0x3ED /* self test scan rate */
|
||
#define TST_THRESH 0xD00 /* mux card test threshold reg value */
|
||
|
||
/* csr command bits */
|
||
#define CSR_RESET 0x01 /* software reset */
|
||
#define CSR_M_START 0x10 /* internal scan start */
|
||
#define CSR_M_ETRIG 0x40 /* external trigger enable */
|
||
#define CSR_M_ESTART 0x20 /* external start enable */
|
||
#define CSR_M_SYSFINH 0x02 /* system fail inhibit */
|
||
#define CSR_M_A24 0x8000 /* enable sequence RAM */
|
||
#define CSR_M_INT 0x80 /* interrupt enable */
|
||
#define CSR_M_MXTST 0x3A /* mux card test bits */
|
||
|
||
/* csr status bits */
|
||
#define S_NEPTY 0x02 /* fifo not empty when = 1 */
|
||
|
||
/* Sequence Program control codes */
|
||
#define GAIN_CHANNEL 0x80
|
||
#define ADVANCE_TRACK 0x40
|
||
#define ADVANCE_HOLD 0xC0
|
||
#define RESTART 0x00
|
||
|
||
/* 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 */
|
||
};
|
||
|
||
/* input buffer */
|
||
struct dvx_inbuf
|
||
{
|
||
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 */
|
||
|
||
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 *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.
|
||
*/
|
||
#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 */
|
||
#define DMA_CARAL 0x08 /* current address reg A low #2 */
|
||
#define DMA_CARBH 0x10 /* current address reg B high #2 */
|
||
#define DMA_CARBL 0x00 /* current address reg B low #2 */
|
||
#define DMA_BARAH 0x1C /* base address reg A high #2 */
|
||
#define DMA_BARAL 0x0C /* base address reg A low #2 */
|
||
#define DMA_BARBH 0x14 /* base address reg B high #2 */
|
||
#define DMA_BARBL 0x04 /* base address reg B low #2 */
|
||
#define DMA_COC 0x30 /* current operation count #2 */
|
||
#define DMA_BOC 0x34 /* base operation count #2 */
|
||
#define DMA_ISR 0x28 /* interrupt save register #2 */
|
||
#define DMA_IVR 0x58 /* interrupt vector register #2 */
|
||
#define DMA_CMRH 0x54 /* channel mode register #2 */
|
||
#define DMA_CMRL 0x50 /* channel mode register #2 */
|
||
#define DMA_CARH 0x24 /* chain address reg high #2 */
|
||
#define DMA_CARL 0x20 /* chain address reg low #2 */
|
||
#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.
|
||
*/
|
||
#define MMR_ENABLE 0x0D /* chip enable value */
|
||
#define CMR_RESET 0x0 /* reset all channels */
|
||
#define CMR_START 0xA0 /* start channel #1 */
|
||
#define CMR_SSR 0x42 /* set software request #1 */
|
||
#define CMR_CSR 0x40 /* clear software request #1 */
|
||
#define CMR_SHM 0x82 /* set hardware mask #1 */
|
||
#define CMR_CHM 0x80 /* clear hardware mask #1 */
|
||
#define CMR_SC 0x22 /* set CIE/IP #1 */
|
||
#define CMR_CC 0x20 /* clear CIE/IP #1 */
|
||
#define CMR_SFB 0x62 /* set flip bit #1 */
|
||
#define CMR_CFB 0x60 /* clear flip bit #1 */
|
||
#define M_CIE 0x10 /* int enable bit mask (SC/CC cmd) */
|
||
#define M_IP 0x4 /* int pending bit mask (SC/CC cmd) */
|
||
#define M_CH2 0x1 /* mask for channel #2 commands */
|
||
|
||
/* am9516 chain reload constants */
|
||
#define R_CAR 0x1 /* chain address */
|
||
#define R_CMR 0x2 /* channel mode */
|
||
#define R_IVR 0x4 /* interrupt vector */
|
||
#define R_PMR 0x8 /* pattern and mask */
|
||
#define R_BOC 0x10 /* base operation count */
|
||
#define R_BAB 0x20 /* base address register B */
|
||
#define R_BAA 0x40 /* base address register A */
|
||
#define R_COC 0x80 /* current operation count */
|
||
#define R_CAB 0x100 /* current address register B */
|
||
#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(int level);
|
||
long dvx_driver_init(void);
|
||
|
||
struct {
|
||
long number;
|
||
DRVSUPFUN report;
|
||
DRVSUPFUN init;
|
||
} drvDvx={
|
||
2,
|
||
dvx_io_report,
|
||
dvx_driver_init};
|
||
|
||
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
|
||
}
|
||
};
|
||
|
||
static int DVX_INTLEV=5; /* allow this to be user setable */
|
||
static int dvxOnline = 0; /* 1 after init invoked */
|
||
|
||
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);
|
||
|
||
|
||
int dvxDebug = 0;
|
||
|
||
|
||
/*
|
||
* dvx_int
|
||
*
|
||
* interrupt service routine
|
||
*
|
||
*/
|
||
LOCAL void
|
||
dvx_int(struct dvx_rec *dvxptr)
|
||
{
|
||
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:
|
||
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 */
|
||
#else
|
||
scanIoRequest(*(dvxptr->pioscanpvt));
|
||
#endif
|
||
break;
|
||
}
|
||
cptr->csr = dvxptr->csr_shadow;
|
||
}
|
||
|
||
|
||
/*
|
||
* dvx_driver_init
|
||
*
|
||
* initialization for 2502 cards
|
||
*
|
||
*/
|
||
LOCAL long dvx_driver_init(void)
|
||
{
|
||
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);
|
||
|
||
dvxOnline = 1; /* do not allow any more user config modifications */
|
||
|
||
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;
|
||
}
|
||
|
||
|
||
/*
|
||
* 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
|
||
if ((dvx[i].pioscanpvt = (IOSCANPVT *) malloc(sizeof(IOSCANPVT))) == NULL)
|
||
return(-1);
|
||
#endif
|
||
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
|
||
*
|
||
* test multiplexer cards
|
||
* I suspect this test does nothing more than light the pass LED on all
|
||
* the 2601 multiplexer cards.
|
||
*
|
||
*/
|
||
LOCAL int muxtst(int card)
|
||
{
|
||
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(sysClkRateGet()); /* let test run */
|
||
dvx[card].pdvx2502->csr = dvx[card].csr_shadow;
|
||
dvx[card].pdvx2502->thresh = 0; /* restore threshold */
|
||
}
|
||
|
||
/*
|
||
* 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.
|
||
*
|
||
* 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.
|
||
*/
|
||
int
|
||
dvx_program(int card, int board, unsigned long mask, int dmaSize)
|
||
{
|
||
int i;
|
||
unsigned long maskCheck;
|
||
int numSamp;
|
||
static int firstTime = 1;
|
||
|
||
if (dvxOnline)
|
||
{
|
||
printf("DVX cards are already on line, no modifications allowed\n");
|
||
return(-1);
|
||
}
|
||
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
|
||
*
|
||
*/
|
||
int dvx_driver(
|
||
int card,
|
||
int chan,
|
||
short *pval
|
||
)
|
||
{
|
||
short ival;
|
||
|
||
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
|
||
*
|
||
*/
|
||
int dvx_dread(int card,int chan)
|
||
{
|
||
short stat;
|
||
short unsigned data;
|
||
float 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
|
||
*
|
||
*/
|
||
int dvx_dump(int card,int firstchan,int lastchan)
|
||
{
|
||
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)
|
||
{
|
||
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;
|
||
}
|
||
|
||
#ifndef EPICS_V2
|
||
dvx_getioscanpvt(int card, IOSCANPVT *scanpvt)
|
||
{
|
||
if ((card >= ai_num_cards[DVX2502]) || (card < 0))return(0);
|
||
if (dvx[card].pdvx2502 == 0) return(0);
|
||
*scanpvt = *(dvx[card].pioscanpvt);
|
||
return(0);
|
||
}
|
||
#endif
|
||
|
||
/*
|
||
*
|
||
* dvx_io_report
|
||
*
|
||
*
|
||
*/
|
||
long dvx_io_report(int level)
|
||
{
|
||
short int i;
|
||
unsigned short card_id;
|
||
|
||
for (i = 0; i < ai_num_cards[DVX2502]; i++){
|
||
if (!dvx[i].pdvx2502)
|
||
continue;
|
||
|
||
/* If detected card is a 2502 print out its number. */
|
||
printf("AI: DVX2505:\tcard %d\n",i);
|
||
|
||
if(level > 0 ){
|
||
int firstchan;
|
||
int 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;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* dvx_fempty
|
||
*
|
||
* empty fifo
|
||
*
|
||
*/
|
||
LOCAL int dvx_fempty(int card)
|
||
{
|
||
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;
|
||
}
|
||
|
||
|
||
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
|
||
*/
|
||
LOCAL dvx_dma_init(struct dvx_rec *ptr)
|
||
{
|
||
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 */
|
||
|
||
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
|
||
*
|
||
*/
|
||
int dvx_dma_stat(int card, int chan)
|
||
{
|
||
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;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
*
|
||
* dvx_reset
|
||
* joh 072591
|
||
*
|
||
* (JRW this should run thru the chain ok init'd boards, not do a probe)
|
||
*
|
||
*/
|
||
LOCAL void
|
||
dvx_reset(void)
|
||
{
|
||
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++, 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 (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
|
||
*
|
||
* 1 sec
|
||
*/
|
||
if(card_found){
|
||
printf("Waiting for DVX 2502 DMA to complete...");
|
||
taskDelay(sysClkRateGet());
|
||
printf("done\n");
|
||
}
|
||
}
|
||
|