Files
pcas/src/dev/devMpc.c
1995-11-29 14:38:52 +00:00

1126 lines
30 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*****************************************************************
*
* Author: John Winans
* Date: 3/95
*
* $Id$
*
*****************************************************************
* COPYRIGHT NOTIFICATION
*****************************************************************
*
* THE FOLLOWING IS A NOTICE OF COPYRIGHT, AVAILABILITY OF THE CODE,
* AND DISCLAIMER WHICH MUST BE INCLUDED IN THE PROLOGUE OF THE CODE
* AND IN ALL SOURCE LISTINGS OF THE CODE.
*
* (C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO
*
* Argonne National Laboratory (ANL), with facilities in the States of
* Illinois and Idaho, is owned by the United States Government, and
* operated by the University of Chicago under provision of a contract
* with the Department of Energy.
*
* Portions of this material resulted from work developed under a U.S.
* Government contract and are subject to the following license: For
* a period of five years from March 30, 1993, the Government is
* granted for itself and others acting on its behalf a paid-up,
* nonexclusive, irrevocable worldwide license in this computer
* software to reproduce, prepare derivative works, and perform
* publicly and display publicly. With the approval of DOE, this
* period may be renewed for two additional five year periods.
* Following the expiration of this period or periods, the Government
* is granted for itself and others acting on its behalf, a paid-up,
* nonexclusive, irrevocable worldwide license in this computer
* software to reproduce, prepare derivative works, distribute copies
* to the public, perform publicly and display publicly, and to permit
* others to do so.
*
*****************************************************************
* DISCLAIMER
*****************************************************************
*
* NEITHER THE UNITED STATES GOVERNMENT NOR ANY AGENCY THEREOF, NOR
* THE UNIVERSITY OF CHICAGO, NOR ANY OF THEIR EMPLOYEES OR OFFICERS,
* MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL
* LIABILITY OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR
* USEFULNESS OF ANY INFORMATION, APPARATUS, PRODUCT, OR PROCESS
* DISCLOSED, OR REPRESENTS THAT ITS USE WOULD NOT INFRINGE PRIVATELY
* OWNED RIGHTS.
*
*****************************************************************
* LICENSING INQUIRIES MAY BE DIRECTED TO THE INDUSTRIAL TECHNOLOGY
* DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000).
*****************************************************************
*
* $Log$
* Revision 1.2 1995/04/05 14:13:43 winans
* Only do a sysIntEnable() for those cards that are found with the probe.
*
* Revision 1.1 1995/03/31 15:03:32 winans
* Machine protection system interface card
*
*
* 00:
* HBI OSC AND3 AND2 AND1 OUT2 OUT1 OUT x x x x T2 T1 RR TEST
*
* HBI = Heartbeat in OK (just the input HB is OK)
* OSC = Onboard OSC OK
* AND3 = AND2 && LB2
* AND2 = AND1 && LB1
* AND1 = HBI
* OUT2 = LB2
* OUT1 = LB1
* OUT = OUT1 && OUT2
* T2 = (output) force LB2 == 0
* T1 = (output) force LB1 == 0
* RR = (output) pulse 0-1-0 to reset LED latches
* TEST = (output) 1 = puts latch logic into test mode, 0 = normal
*
* 02: IRQ mask of
* 7r 7f 6r 6f 5r 5f 4r 4f 3r 3f 2r 2f 1r 1f 0r 0f
*
* 04: IRQ mask of
* 15r 15f 14r 14f 13r 13f 12r 12f 11r 11f 10r 10f 9r 9f 8r 8f
*
* 06: IRQ mask of
* 23r 23f 22r 22f 21r 21f 20r 20f 19r 19f 18r 18f 17r 17f 16r 16f
*
* input [0..19] = Signals 0 thru 19
* input 20 = OR of all inputs, 1=all true
* input 21 = OR of all test signals, 1=all true
* input 22 = AND of both logic blocks, LB1 && LB2
* input 23 = Input heartbeat OK, 1 = OK
* r = rising, f = falling
*
* 08: Latched image of transition
* 7r 7f 6r 6f 5r 5f 4r 4f 3r 3f 2r 2f 1r 1f 0r 0f
*
* 0a: Latched image of transition
* 15r 15f 14r 14f 13r 13f 12r 12f 11r 11f 10r 10f 9r 9f 8r 8f
*
* 0c: Latched image of transition
* 23r 23f 22r 22f 21r 21f 20r 20f 19r 19f 18r 18f 17r 17f 16r 16f
*
* 0e: IRQ settings
* xxxxELLLVVVVVVVV
*
* x = don't care
* E = Enable IRQs
* LLL = IRQ level
* VVVVVVVV = IRQ vector
*
* 10: State of LEDs
* 7c 7l 6c 6l 5c 5l 4c 4l 3c 3l 2c 2l 1c 1l 0c 0l
*
* 12: State of LEDs
* 15c 15l 14c 14c 13l 13c 12l 12c 11l 11c 10c 10l 9c 9l 8c 8l
*
* 14: State of LEDs
* xxx xxx xxx xxx HBI HBO TRP LT 19c 19l 18c 18l 17c 17l 16c 16l
*
* LED[0..19] = Signals 0 thru 19
* LT = ORd result of all LED latch signals, 1=all true
* TRP = ORd result of all trip outputs, 1 = all true
* HBO = Heartbeat out OK = AND3 (HBI && LB1 &&LB2)
* HBI = Heartbeat in OK (just the input HB is OK)
* xxx = don't care
* c = current state, l = latched
*
* 16:
* TRIP[15..0]
*
* 18:
* xxxxxxxx TRIP[20..16]
*
* NOTE: the TRIP outputs are negative-true logic feeding the OR gate
* referenced by byte 06, label 21[rf]
*
****************************************************************************/
#include <vxWorks.h>
#include <sysLib.h>
#include <vme.h>
#include <types.h>
#include <stdioLib.h>
#include <string.h>
#include <semLib.h>
#include <fast_lock.h>
#include <iv.h>
#include <wdLib.h>
#include "alarm.h"
#include "dbDefs.h"
#include "dbAccess.h"
#include "recSup.h"
#include "devSup.h"
#include "link.h"
#include "dbCommon.h"
#include "aiRecord.h"
#include "boRecord.h"
#include "biRecord.h"
#include "mbboRecord.h"
#include "mbbiRecord.h"
#include "dbScan.h"
#include "errMdef.h"
#include "eventRecord.h"
#define MPC_DOG_POLL_RATE 6
#define NUM_LINKS 4 /* Max number of allowed cards */
#define STATIC /* static /* */
int MpcConfig();
STATIC long MpcInit();
STATIC long MpcReport();
STATIC void MpcIsr();
STATIC long MpcInitBoRec();
STATIC long MpcWriteBo();
STATIC long MpcInitBiRec();
STATIC long MpcReadBi();
STATIC long MpcGetIointInfoBi();
#if 0
STATIC long MpcInitMbboRec();
STATIC long MpcInitMbbiRec();
STATIC long MpcWriteMbbo(), MpcReadMbbi();
#endif
int devMpcDebug = 0;
typedef struct ParmTableStruct
{
char *parm_name;
} ParmTableStruct;
#define MPC_PARM_TESTMODE 0
#define MPC_PARM_RESETLATCHES 1
#define MPC_PARM_TESTLB1 2
#define MPC_PARM_TESTLB2 3
#define MPC_PARM_TI 4
#define MPC_PARM_LB1OK 5
#define MPC_PARM_LB2OK 6
#define MPC_PARM_AND1OK 7
#define MPC_PARM_AND2OK 8
#define MPC_PARM_AND3OK 9
#define MPC_PARM_OSCOK 10
#define MPC_PARM_HBIOK 11
#define MPC_PARM_HBOOK 12
#define MPC_PARM_DI 13
#define MPC_PARM_LI 14
#define MPC_PARM_ALLLATCHTRUE 15
#define MPC_PARM_ALLTRIPTRUE 16
static ParmTableStruct ParmTable[] =
{
/* Binary Out (BI allowed for readback) */
{"TestMode"}, /* 1 = place unit in test mode */
{"ResetLatches"}, /* A one-shot that resets the latches */
{"TestLb1"}, /* 1 = force a false from LB1 */
{"TestLb2"}, /* 1 = force a falce from LB2 */
{"Ti"}, /* Trip test input bit values */
/* Binary In */
{"LB1OK"}, /* 1 = LB1 output true */
{"LB2OK"}, /* 1 = LB2 output true */
{"And1OK"}, /* AND1 output true */
{"And2OK"}, /* AND2 output true */
{"And3OK"}, /* AND3 output true */
{"OscOK"}, /* Oscilator OK */
{"HBIOK"}, /* Heart beat input OK */
{"HBOOK"}, /* Heart beat output OK */
{"Di"}, /* Current input values */
{"Li"}, /* Latched input values */
{"AllLatchTrue"}, /* 1 = all latch signals are true */
{"AllTripTrue"}, /* 1 = all test trip signals are true */
};
#define PARM_TABLE_SIZE (sizeof(ParmTable)/sizeof(ParmTable[0]))
typedef struct MpcStruct {
volatile unsigned short Stat;
volatile unsigned short EdgeMask0;
volatile unsigned short EdgeMask1;
volatile unsigned short EdgeMask2;
volatile unsigned short EdgeState0;
volatile unsigned short EdgeState1;
volatile unsigned short EdgeState2;
volatile unsigned short Irq;
volatile unsigned short LatchState0;
volatile unsigned short LatchState1;
volatile unsigned short LatchState2;
volatile unsigned short LatchTest0;
volatile unsigned short LatchTest1;
volatile char fill[6+32];
}MpcStruct;
/*****************************************************************************
*
* Per-record private structure hooked onto dpvt.
*
*****************************************************************************/
typedef struct PvtStruct
{
int index; /* Parameter/operation type */
volatile unsigned short *pReg; /* Pointer to actual register */
unsigned short mask; /* value mask derived from signal number */
} PvtStruct;
/*****************************************************************************
*
* Per-card global variables.
*
*****************************************************************************/
struct ioCard { /* structure maintained for each card */
int CardValid; /* card exists */
unsigned long MpcBaseA16; /* A16 card address */
int VMEintVector; /* IRQ vector used by mpc */
int VMEintLevel; /* IRQ level */
MpcStruct *MpcBase; /* Physical card address */
FAST_LOCK lock; /* semaphore */
IOSCANPVT ioscanpvt; /* Token for I/O intr scanned records */
WDOG_ID Doggie; /* Used to poll the I/O pinz */
unsigned short s0;
unsigned short s1;
unsigned short s2;
};
static struct ioCard cards[NUM_LINKS]; /* card information structure */
typedef struct MpcDsetStruct {
long number;
DEVSUPFUN report; /* used by dbior */
DEVSUPFUN init; /* called 1 time before & after all records */
DEVSUPFUN init_record; /* called 1 time for each record */
DEVSUPFUN get_ioint_info; /* used for COS processing */
DEVSUPFUN read_write; /* output command goes here */
} MpcDsetStruct;
MpcDsetStruct devBoMpc={
5,
NULL,
MpcInit,
MpcInitBoRec,
NULL,
MpcWriteBo
};
/* Create the dset for devBiMpc */
MpcDsetStruct devBiMpc={
5,
MpcReport,
MpcInit,
MpcInitBiRec,
MpcGetIointInfoBi,
MpcReadBi
};
#if 0
/* Create the dset for devMbboMpc */
MpcDsetStruct devMbboMpc={
5,
NULL,
MpcInit,
MpcInitMbboRec,
NULL,
MpcWriteMbbo
};
/* Create the dset for devMbbiMpc */
MpcDsetStruct devMbbiMpc={
5,
NULL,
MpcInit,
MpcInitMbbiRec,
NULL,
MpcReadMbbi
};
#endif
/*****************************************************************************
*
*****************************************************************************/
STATIC long MpcReport(void)
{
int j;
for (j=0; j<NUM_LINKS; j++)
{
if (cards[j].CardValid)
{
printf(" card %d: A16:0x%4.4X VME-IRQ:0x%2.2X IRQ-level:%d\n",
j, cards[j].MpcBaseA16, cards[j].VMEintVector, cards[j].VMEintLevel);
}
}
}
/*****************************************************************************
*
* Called from the shell to configure the attributes of a MPC card.
*
*****************************************************************************/
int MpcConfig(
int Card, /* Which card to set parms for */
unsigned long MpcBaseA16, /* Base address in A16 */
int VMEintVector, /* IRQ vector used by mpc */
int VMEintLevel /* IRQ level */
)
{
if ((Card < 0) || (Card >= NUM_LINKS))
{
printf("ERROR: Invalid card number specified %d\n", Card);
return(0);
}
cards[Card].CardValid = 0;
cards[Card].VMEintVector = 0;
cards[Card].VMEintLevel = 0;
cards[Card].MpcBaseA16 = 0;
if ((VMEintVector < 64) || (VMEintVector > 255))
{
printf("devMpc: ERROR VME IRQ vector out of range\n");
return(0);
}
if (devMpcDebug >= 5)
printf("devMpc: MpcInit VME int vector = 0x%2.2X\n", VMEintVector);
if ((VMEintLevel < 0) || (VMEintLevel > 7))
{
printf("devMpc: ERROR VME IRQ level out of range\n");
return(0);
}
if (devMpcDebug >= 5)
printf("devMpc: MpcInit VME int level = %d\n", VMEintLevel);
if ((MpcBaseA16 > 0x0ffff) || (MpcBaseA16 & 0x003f))
{
printf("devMpc: ERROR Invalid address specified 0x%4.4X\n", MpcBaseA16);
return(0);
}
if (devMpcDebug >= 5)
printf("devMpc: MpcInit VME base address = %p\n", MpcBaseA16);
cards[Card].VMEintVector = VMEintVector;
cards[Card].VMEintLevel = VMEintLevel;
cards[Card].MpcBaseA16 = MpcBaseA16;
cards[Card].CardValid = 1;
return(0);
}
/*****************************************************************************
*
* Used as an alternate to raw IRQ handling because the IRQ rate can exceed
* what vxWorks can handle. Using the MpcDogWatcher will allow I/O Scanned
* records to operate w/o actually using IRQs.
*
*****************************************************************************/
STATIC void MpcDogWatcher(struct ioCard *p)
{
unsigned short junk0;
unsigned short junk1;
unsigned short junk2;
junk0 = p->MpcBase->LatchState0;
junk1 = p->MpcBase->LatchState1;
junk2 = p->MpcBase->LatchState2;
if ((p->s0 != junk0) || (p->s1 != junk1) || (p->s2 != junk2))
{
if (devMpcDebug > 9)
{
logMsg("MpcDogWatcher was %04.4X %04.4X %04.4X\n", p->s0, p->s1, p->s2);
logMsg("MpcDogWatcher is %04.4X %04.4X %04.4X\n", junk0, junk1, junk2);
}
scanIoRequest(p->ioscanpvt);
}
p->s0 = junk0;
p->s1 = junk1;
p->s2 = junk2;
if (devMpcDebug > 10)
logMsg("MpcDogWatcher %04.4X %04.4X %04.4X\n", junk2, junk1, junk0);
wdStart(p->Doggie, MPC_DOG_POLL_RATE, (FUNCPTR)MpcDogWatcher, (int)p);
return;
}
/**************************************************************************
*
* IRQ handler registered in MpcInit(). This routine clears the status
* registers and fires off any IO-scanned records.
*
**************************************************************************/
STATIC void MpcIsr(int Card)
{
unsigned short junk0;
unsigned short junk1;
unsigned short junk2;
junk0 = cards[Card].MpcBase->EdgeState0;
junk1 = cards[Card].MpcBase->EdgeState1;
junk2 = cards[Card].MpcBase->EdgeState2;
if (devMpcDebug >= 10)
logMsg("MpcIsr %04.4X %04.4X %04.4X\n", junk2, junk1, junk0);
scanIoRequest(cards[Card].ioscanpvt);
/* Disable and then reenable the IRQs */
cards[Card].MpcBase->EdgeMask0 = 0;
cards[Card].MpcBase->EdgeMask1 = 0;
cards[Card].MpcBase->EdgeMask2 = 0;
cards[Card].MpcBase->EdgeMask0 = 0xffff;
cards[Card].MpcBase->EdgeMask1 = 0xffff;
cards[Card].MpcBase->EdgeMask2 = 0xffff;
return;
}
/**************************************************************************
*
* Initialization of MPC Binary I/O Card. Called from the DSET init
* entry points.
*
***************************************************************************/
STATIC long MpcInit(int flag)
{
int Card;
unsigned short probeVal;
static int init_flag = 0;
unsigned short junk;
if (init_flag != 0)
return(OK);
init_flag = 1;
/* We end up here 1 time before all records are initialized */
for (Card=0; Card < NUM_LINKS; Card++)
{
if (cards[Card].CardValid != 0)
{
if (devMpcDebug >= 5)
logMsg("devMpc: init link %d\n", Card);
if (sysBusToLocalAdrs(VME_AM_SUP_SHORT_IO, (char *)cards[Card].MpcBaseA16, (char **)&(cards[Card].MpcBase)) == ERROR)
{
if (devMpcDebug >= 5)
logMsg("devMpc: can not find short address space\n");
return(ERROR); /* BUG */
}
if (vxMemProbe((char *)&cards[Card].MpcBase->Stat, READ, sizeof(cards[Card].MpcBase->Stat), (char *)&probeVal) != OK)
{
cards[Card].CardValid = 0; /* No card found */
if (devMpcDebug >= 5)
logMsg("devMpc: init vxMemProbe FAILED\n");
}
else
{
if (devMpcDebug >= 5)
logMsg("devMpc: init vxMemProbe OK\n");
FASTLOCKINIT(&(cards[Card].lock));
if (devMpcDebug >= 5)
logMsg("devMpc: init address\n");
scanIoInit(&cards[Card].ioscanpvt); /* interrupt initialized */
if (devMpcDebug >= 5)
logMsg("devMpc: init ScanIoInit \n");
if (devMpcDebug >= 5)
logMsg("devMpc: init address of MPC Card %8.8x \n", cards[Card].MpcBase);
#ifdef MPC_USE_IRQS
/* Register a reboot handler in here */
/* Read all the stat regs here to clear bogus edges. */
junk = cards[Card].MpcBase->EdgeState0;
junk = cards[Card].MpcBase->EdgeState1;
junk = cards[Card].MpcBase->EdgeState2;
cards[Card].MpcBase->EdgeMask0 = 0xffff;
cards[Card].MpcBase->EdgeMask1 = 0xffff;
cards[Card].MpcBase->EdgeMask2 = 0xffff;
probeVal = cards[Card].VMEintVector;
probeVal |= (cards[Card].VMEintLevel<<8)|0x0800;
cards[Card].MpcBase->Irq = probeVal;
if (devMpcDebug >= 5)
logMsg("devMpc: init Interrupt vector loaded \n");
if(intConnect(INUM_TO_IVEC(cards[Card].VMEintVector),(FUNCPTR)MpcIsr, Card)!=OK)
{
logMsg("devMpc (init) intConnect failed \n");
return(ERROR);
}
/* Read all the stat regs here to clear any bogus edges. */
junk = cards[Card].MpcBase->EdgeState0;
junk = cards[Card].MpcBase->EdgeState1;
junk = cards[Card].MpcBase->EdgeState2;
#else
cards[Card].MpcBase->EdgeMask0 = 0;
cards[Card].MpcBase->EdgeMask1 = 0;
cards[Card].MpcBase->EdgeMask2 = 0;
/* Read all the stat regs here to clear any bogus edges. */
junk = cards[Card].MpcBase->EdgeState0;
junk = cards[Card].MpcBase->EdgeState1;
junk = cards[Card].MpcBase->EdgeState2;
cards[Card].s0 = 0;
cards[Card].s1 = 0;
cards[Card].s2 = 0;
cards[Card].Doggie = wdCreate();
wdStart(cards[Card].Doggie, MPC_DOG_POLL_RATE, (FUNCPTR)MpcDogWatcher, (int)(&cards[Card]));
#endif
#ifdef MPC_USE_IRQS
sysIntEnable(cards[Card].VMEintLevel);
#endif
}
}
}
return(OK);
}
/***************************************************************************
*
* generic init record
*
***************************************************************************/
static long GenericInitRecord(struct dbCommon *pr, DBLINK *link)
{
struct vmeio *pvmeio = (struct vmeio*)&(link->value);
int j;
PvtStruct *pvt;
if (link->type != VME_IO)
{
recGblRecordError(S_dev_badBus,(void *)pr, "devMpc (init_record) Illegal Bus Type");
return(S_dev_badBus);
}
/* makes sure that card is valid */
if ((pvmeio->card > NUM_LINKS) || (pvmeio->card < 0) || (!cards[pvmeio->card].CardValid))
{
if (devMpcDebug >= 10)
{
logMsg("devMpc: Illegal CARD field ->%s, %d<- \n", pr->name, pvmeio->card);
if(!cards[pvmeio->card].CardValid)
logMsg("devMpc: Illegal CARD field card NOT VALID \n\n");
}
recGblRecordError(S_dev_badCard,(void *)pr, "devMpc (init_record) Illegal CARD field");
return(S_dev_badCard);
}
/* verifies that parm field is valid */
for (j = 0; (j < PARM_TABLE_SIZE) && strcmp(ParmTable[j].parm_name, pvmeio->parm); j++ );
if (j >= PARM_TABLE_SIZE)
{
if (devMpcDebug >= 10)
logMsg("devMpc: Illegal parm field ->%s<- \n", pr->name);
recGblRecordError(S_dev_badSignal,(void *)pr, "devMpc (init_record) Illegal parm field");
return(S_dev_badSignal);
}
if (devMpcDebug >= 10)
logMsg("devMpc: %s of record type %d - %s\n", pr->name, j, ParmTable[j].parm_name);
pvt = (PvtStruct *) malloc(sizeof(PvtStruct));
pvt->index = j;
pr->dpvt = pvt;
return(0);
}
/**************************************************************************
*
* BO Initialization (Called one time for each BO MPC card record)
*
**************************************************************************/
STATIC long MpcInitBoRec(struct boRecord *pRec)
{
struct vmeio* pvmeio = (struct vmeio*)&(pRec->out.value);
int status = 0;
PvtStruct *pvt;
status = GenericInitRecord((struct dbCommon *)pRec, &pRec->out);
if(status)
{
pRec->dpvt = NULL;
return(status);
}
pvt = (PvtStruct *)pRec->dpvt;
switch (pvt->index)
{
case MPC_PARM_RESETLATCHES:
break; /* don't need to do anything here */
case MPC_PARM_TESTMODE:
pvt->mask = 0x0001;
pvt->pReg = &(cards[pvmeio->card].MpcBase->Stat);
break;
case MPC_PARM_TESTLB1:
pvt->mask = 0x0004;
pvt->pReg = &(cards[pvmeio->card].MpcBase->Stat);
break;
case MPC_PARM_TESTLB2:
pvt->mask = 0x0008;
pvt->pReg = &(cards[pvmeio->card].MpcBase->Stat);
break;
case MPC_PARM_TI:
if ((pvmeio->signal >= 0)&&(pvmeio->signal <= 15))
{
pvt->mask = 1 << (pvmeio->signal);
pvt->pReg = &(cards[pvmeio->card].MpcBase->LatchTest0);
}
else if ((pvmeio->signal >= 16)&&(pvmeio->signal <= 19))
{
pvt->mask = 1 << ((pvmeio->signal)-16);
pvt->pReg = &(cards[pvmeio->card].MpcBase->LatchTest1);
}
else
{
free(pRec->dpvt);
pRec->dpvt = NULL;
if (devMpcDebug >= 10)
logMsg("devMpc: Illegal signal field ->%d<- \n", pvmeio->signal);
recGblRecordError(S_dev_badSignal,(void *)pRec, "devMpc (init_record) Illegal parm field");
return(S_dev_badSignal);
}
break;
default:
pRec->dpvt = NULL;
if (devMpcDebug >= 10)
logMsg("devMpc: Illegal parm field ->%s<- \n", pvmeio->parm);
recGblRecordError(S_dev_badSignal,(void *)pRec,
"devMpc (init_record) Illegal parm field");
return(S_dev_badSignal);
}
return (0);
}
/**************************************************************************
*
* BI Initialization (Called one time for each BI MPC card record)
*
**************************************************************************/
STATIC long MpcInitBiRec(struct biRecord *pRec)
{
struct vmeio* pvmeio = (struct vmeio*)&(pRec->inp.value);
PvtStruct *pvt;
int status = 0;
int signal;
status = GenericInitRecord((struct dbCommon *)pRec, &pRec->inp);
if(status)
{
pRec->dpvt = NULL;
return(status);
}
pvt = (PvtStruct *)pRec->dpvt;
switch (pvt->index)
{
case MPC_PARM_TESTMODE:
pvt->mask = 0x0001;
pvt->pReg = &(cards[pvmeio->card].MpcBase->Stat);
break;
case MPC_PARM_LB1OK:
pvt->mask = 0x0200;
pvt->pReg = &(cards[pvmeio->card].MpcBase->Stat);
break;
case MPC_PARM_LB2OK:
pvt->mask = 0x0400;
pvt->pReg = &(cards[pvmeio->card].MpcBase->Stat);
break;
case MPC_PARM_AND1OK:
pvt->mask = 0x0800;
pvt->pReg = &(cards[pvmeio->card].MpcBase->Stat);
break;
case MPC_PARM_AND2OK:
pvt->mask = 0x1000;
pvt->pReg = &(cards[pvmeio->card].MpcBase->Stat);
break;
case MPC_PARM_AND3OK:
pvt->mask = 0x2000;
pvt->pReg = &(cards[pvmeio->card].MpcBase->Stat);
break;
case MPC_PARM_OSCOK:
pvt->mask = 0x4000;
pvt->pReg = &(cards[pvmeio->card].MpcBase->Stat);
break;
case MPC_PARM_HBIOK:
pvt->mask = 0x8000;
pvt->pReg = &(cards[pvmeio->card].MpcBase->Stat);
break;
case MPC_PARM_LI:
if ((pvmeio->signal >= 0)&&(pvmeio->signal <= 7))
{
pvt->mask = 2 << ((pvmeio->signal) * 2);
pvt->pReg = &(cards[pvmeio->card].MpcBase->LatchState0);
}
else if ((pvmeio->signal >= 8)&&(pvmeio->signal <= 15))
{
pvt->mask = 2 << ((pvmeio->signal - 8) * 2);
pvt->pReg = &(cards[pvmeio->card].MpcBase->LatchState1);
}
else if ((pvmeio->signal >= 16)&&(pvmeio->signal <= 19))
{
pvt->mask = 2 << ((pvmeio->signal - 16) * 2);
pvt->pReg = &(cards[pvmeio->card].MpcBase->LatchState2);
}
else
{
free(pRec->dpvt);
pRec->dpvt = NULL;
if (devMpcDebug >= 10)
logMsg("devMpc: Illegal signal field ->%d<- \n", pvmeio->signal);
recGblRecordError(S_dev_badSignal,(void *)pRec, "devMpc (init_record) Illegal parm field");
return(S_dev_badSignal);
}
break;
case MPC_PARM_DI:
if ((pvmeio->signal >= 0)&&(pvmeio->signal <= 7))
{
pvt->mask = 1 << ((pvmeio->signal) * 2);
pvt->pReg = &(cards[pvmeio->card].MpcBase->LatchState0);
}
else if ((pvmeio->signal >= 8)&&(pvmeio->signal <= 15))
{
pvt->mask = 1 << ((pvmeio->signal - 8) * 2);
pvt->pReg = &(cards[pvmeio->card].MpcBase->LatchState1);
}
else if ((pvmeio->signal >= 16)&&(pvmeio->signal <= 19))
{
pvt->mask = 1 << ((pvmeio->signal - 16) * 2);
pvt->pReg = &(cards[pvmeio->card].MpcBase->LatchState2);
}
else
{
free(pRec->dpvt);
pRec->dpvt = NULL;
if (devMpcDebug >= 10)
logMsg("devMpc: Illegal signal field ->%d<- \n", pvmeio->signal);
recGblRecordError(S_dev_badSignal,(void *)pRec, "devMpc (init_record) Illegal parm field");
return(S_dev_badSignal);
}
break;
case MPC_PARM_ALLLATCHTRUE:
pvt->mask = 0x0100;
pvt->pReg = &(cards[pvmeio->card].MpcBase->LatchState2);
break;
case MPC_PARM_ALLTRIPTRUE:
pvt->mask = 0x0200;
pvt->pReg = &(cards[pvmeio->card].MpcBase->LatchState2);
break;
case MPC_PARM_TESTLB1:
pvt->mask = 0x0040;
pvt->pReg = &(cards[pvmeio->card].MpcBase->Stat);
break;
case MPC_PARM_TESTLB2:
pvt->mask = 0x0080;
pvt->pReg = &(cards[pvmeio->card].MpcBase->Stat);
break;
case MPC_PARM_TI:
if ((pvmeio->signal >= 0)&&(pvmeio->signal <= 15))
{
pvt->mask = 1 << (pvmeio->signal);
pvt->pReg = &(cards[pvmeio->card].MpcBase->LatchTest0);
}
else if ((pvmeio->signal >= 16)&&(pvmeio->signal <= 19))
{
pvt->mask = 1 << ((pvmeio->signal)-16);
pvt->pReg = &(cards[pvmeio->card].MpcBase->LatchTest1);
}
else
{
free(pRec->dpvt);
pRec->dpvt = NULL;
if (devMpcDebug >= 10)
logMsg("devMpc: Illegal signal field ->%d<- \n", pvmeio->signal);
recGblRecordError(S_dev_badSignal,(void *)pRec, "devMpc (init_record) Illegal parm field");
return(S_dev_badSignal);
}
break;
default:
free(pRec->dpvt);
pRec->dpvt = NULL;
if (devMpcDebug >= 10)
logMsg("devMpc: Illegal parm field ->%s<- \n", pvmeio->parm);
recGblRecordError(S_dev_badSignal,(void *)pRec, "devMpc (init_record) Illegal parm field");
return(S_dev_badSignal);
}
if (devMpcDebug >= 10)
logMsg("devMpc BI record mask = 0x%04.4X reg=0x%08.8X\n", pvt->mask, pvt->pReg);
return (0);
}
/**************************************************************************
*
* MBBO Initialization (Called one time for each MBBO MPC card record)
*
**************************************************************************/
STATIC long MpcInitMbboRec(struct mbboRecord *pmbbo)
{
#if 0
struct vmeio* pvmeio = (struct vmeio*)&(pmbbo->out.value);
PvtStruct *pvt;
int status = 0;
status = GenericInitRecord((struct dbCommon *)pmbbo, &pmbbo->out);
if(status)
{
pmbbo->dpvt = NULL;
return(status);
}
pvt = (PvtStruct *)pmbbo->dpvt;
if (pvt->index != MPC_PARM_DO)
{
pmbbo->dpvt = NULL;
if (devMpcDebug >= 10)
logMsg("devMpc: Illegal parm field ->%s<- \n", pvmeio->parm);
recGblRecordError(S_dev_badSignal,(void *)pmbbo,
"devMpc (init_record) Illegal parm field");
return(S_dev_badSignal);
}
pvt->pReg = &(cards[pvmeio->card].MpcBase->MpcDio);
pmbbo->shft = pvmeio->signal;
pmbbo->mask <<= pmbbo->shft;
#endif
return(0);
}
/**************************************************************************
*
* MBBI Initialization (Called one time for each MBBI MPC card record)
*
**************************************************************************/
STATIC long MpcInitMbbiRec(struct mbbiRecord *pmbbi)
{
#if 0
struct vmeio* pvmeio = (struct vmeio*)&(pmbbi->inp.value);
PvtStruct *pvt;
int status = 0;
status = GenericInitRecord((struct dbCommon *)pmbbi, &pmbbi->inp);
if(status)
{
pmbbi->dpvt = NULL;
return(status);
}
pvt = (PvtStruct *)pmbbi->dpvt;
if ((pvt->index != MPC_PARM_DI) && (pvt->index != MPC_PARM_DO))
{
pmbbi->dpvt = NULL;
if (devMpcDebug >= 10)
logMsg("devMpc: Illegal parm field ->%s<- \n", pvmeio->parm);
recGblRecordError(S_dev_badSignal,(void *)pmbbi,
"devMpc (init_record) Illegal parm field");
return(S_dev_badSignal);
}
pvt->pReg = &(cards[pvmeio->card].MpcBase->MpcDio);
pmbbi->shft = pvmeio->signal;
if (pvt->index == MPC_PARM_DI)
pmbbi->shft += 8;
pmbbi->mask <<= pmbbi->shft;
#endif
return(0);
}
/**************************************************************************
*
* Perform a write operation from a BO record
*
**************************************************************************/
STATIC long MpcWriteBo(struct boRecord *pRec)
{
struct vmeio *pvmeio = (struct vmeio*)&(pRec->out.value);
PvtStruct *pvt = (PvtStruct *)pRec->dpvt;
if (pvt == NULL)
return(0);
FASTLOCK(&cards[pvmeio->card].lock);
switch (pvt->index){
case MPC_PARM_RESETLATCHES:
/* Toggle the reset bit on and off again */
cards[pvmeio->card].MpcBase->Stat |= 0x0002;
cards[pvmeio->card].MpcBase->Stat &= ~0x0002;
break;
default:
if (pRec->val)
*(pvt->pReg) |= pvt->mask;
else
*(pvt->pReg) &= ~pvt->mask;
}
FASTUNLOCK(&cards[pvmeio->card].lock);
return(0);
}
/**************************************************************************
*
* Perform a read operation from a BI record
*
**************************************************************************/
STATIC long MpcReadBi(struct biRecord *pRec)
{
struct vmeio *pvmeio = (struct vmeio*)&(pRec->inp.value);
unsigned short regVal = 0;
PvtStruct *pvt = (PvtStruct *)pRec->dpvt;
if (pvt == NULL)
return(0);
regVal = *(pvt->pReg);
if (devMpcDebug)
logMsg("read 0x%4.4X, masking with 0x%4.4X\n", regVal, pvt->mask);
regVal &= pvt->mask;
if(regVal)
pRec->rval = 1;
else
pRec->rval = 0;
return(0);
}
/**************************************************************************
*
* Perform a write operation from a MBBO record
*
**************************************************************************/
STATIC long MpcWriteMbbo(struct mbboRecord *pmbbo)
{
#if 0
struct vmeio *pvmeio = (struct vmeio*)&(pmbbo->out.value);
unsigned short regVal;
PvtStruct *pvt = (PvtStruct *)pmbbo->dpvt;
if (pvt == NULL)
return(0);
FASTLOCK(&cards[pvmeio->card].lock);
regVal = *(pvt->pReg);
regVal &= ~pmbbo->mask;
regVal |= pmbbo->rval;
*(pvt->pReg) = regVal;
if (devMpcDebug)
printf("MpcReadMbbo masked value %8.8X\n", regVal);
FASTUNLOCK(&cards[pvmeio->card].lock);
#endif
return(0);
}
/**************************************************************************
*
* Perform a read operation from a MBBI record
*
**************************************************************************/
STATIC long MpcReadMbbi(struct mbbiRecord *pmbbi)
{
#if 0
struct vmeio *pvmeio = (struct vmeio*)&(pmbbi->inp.value);
unsigned short regVal;
PvtStruct *pvt = (PvtStruct *)pmbbi->dpvt;
if (pvt == NULL)
return(0);
regVal = ~(*(pvt->pReg)); /* Stupid inputs are inverted */
regVal &= pmbbi->mask;
if (devMpcDebug)
printf("MpcReadMbbi masked value %8.8X\n", regVal);
pmbbi->rval = regVal;
pmbbi->udf = 0;
#endif
return(0);
}
/*****************************************************
*
* record support interrupt routine
*
* cmd = 0 if being added
* cmd = 1 if taken off the I/O Event scanned list
*
****************************************************/
STATIC long MpcGetIointInfoBi(int cmd, struct biRecord *pr, IOSCANPVT *ppvt)
{
struct vmeio *pvmeio = (struct vmeio *)(&pr->inp.value);
int intmask;
if (pr->dpvt == NULL)
return(0);
if(pvmeio->card > NUM_LINKS) {
recGblRecordError(S_dev_badCard,(void *)pr, "devMpc (get_int_info) exceeded maximum supported cards");
return(S_dev_badCard);
}
*ppvt = cards[pvmeio->card].ioscanpvt;
return(0);
}