diff --git a/src/drv/old/Makefile.Vx b/src/drv/old/Makefile.Vx index 6516a622e..088c3369f 100644 --- a/src/drv/old/Makefile.Vx +++ b/src/drv/old/Makefile.Vx @@ -21,21 +21,10 @@ else USR_CFLAGS = -fshared-data -fvolatile endif -#The following have been unbundled. DONT USE THESE -#INC += drvBB232.h -INC += drvBitBus.h +# These two Bitbus files are needed to build the GPIB support. However the +# bitbus driver source has now been unbundled and removed from Base. INC += drvBitBusErr.h -#INC += drvMsg.h -#drvBitBus and include files APPEARS HERE AND IN UNBUNDLED - BIG PROBLEM INC += drvBitBusInterface.h -#SRCS.c += ../drvBB232.c -SRCS.c += ../drvBitBus.c -#SRCS.c += ../drvMsg.c -#SRCS.c += ../drvTranServ.c - -#The following have not been used -#INC += drvRs232.h -#INC += drvTy232.h INC += drvGpib.h INC += drvGpibErr.h @@ -45,7 +34,6 @@ INC += drvJgvtr1.h INC += drvOms.h INC += steppermotor.h - SRCS.c += ../module_types.c SRCS.c += ../drvBb902.c SRCS.c += ../drvBb910.c @@ -58,7 +46,6 @@ SRCS.c += ../drvGpib.c SRCS.c += ../drvJgvtr1.c SRCS.c += ../drvOms.c SRCS.c += ../drvVmi4100.c -SRCS.c += ../drvXy010.c SRCS.c += ../drvXy210.c SRCS.c += ../drvXy220.c SRCS.c += ../drvXy240.c diff --git a/src/drv/old/drvBitBus.c b/src/drv/old/drvBitBus.c deleted file mode 100644 index 64bbce654..000000000 --- a/src/drv/old/drvBitBus.c +++ /dev/null @@ -1,2908 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* #define XYCOM_DO_RESET_AND_OFFLINE */ -/* #define PEP_DO_RESET_AND_OFFLINE */ - - -/* - changes to UI: - - XYCOM_BB_MAX_OUTSTAND_MSGS -> XycomMaxOutstandMsgs - - - - TODO: - - 1) Synthetic delays after 91s. - 2) Rebuild the link kill stuff so that it does not mess with the WDtask. - 3) Verify race conditions on the slave reset function. - 4) Write a callable bug-syncer that uses the RAC get function ID command. - 5) Merge the watchdog tasks into one. - 6) Try merging the TX and RX tasks. - -*/ - -/* - * Original Author: Ned Arnold - * Author: John Winans - * Date: 09-10-91 - * XVME-402 and PB-bit BitBus driver - * - * NOTES: - * This driver currently needs work on error message generation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* used by device support routines */ -#include -#include -#include -#include -#include -#include - -#include -#include "drvBitBus.h" - -#define STATIC static - -#define BB_DEFAULT_RETIRE_TIME 5 /* Seconds to wait for a response */ - -STATIC long reportBB(void); -STATIC long initBB(void); -STATIC long qBBReq(struct dpvtBitBusHead *pdpvt, int prio); - -STATIC int xvmeReset(int link); -STATIC int xvmeTmoHandler(int link); -STATIC int xvmeRxTask(int link); -STATIC int xvmeTxTask(int link); -STATIC int xvmeWdTask(int link); -STATIC int xvmeIrqRdav(int link); -STATIC int xvmeIrqRcmd(int link); - -STATIC int pepReset(int link); -STATIC int pepTmoHandler(int link); -STATIC int pepRxTask(int link); -STATIC int pepTxTask(int link); -STATIC int pepWdTask(int link); -STATIC int pepIrqRdav(int link); - -STATIC int bbKill(int link); -STATIC void BBrebootFunc(void); - -STATIC int txStuck(int link); -int BBConfig(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); -int __BBConfig(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); - -#ifdef BB_SUPER_DEBUG -int BBHistDump(int link); -STATIC int BBDumpXactHistory(XactHistStruct *pXact); -#endif - -long pulseSysMon(); - - -/***************************************************************************** - * - * Used to limit the TOTAL number of simultaneous messages that can be - * outstanding on a single Xycom/PEP link. (Shell settable.) PEP limit - * of 7 is a magic number. Anything more and PEP board will throw away - * your transaction resulting in a TIMEOUT. Ugh. - * - *****************************************************************************/ -int XycomMaxOutstandMsgs = XYCOM_BB_MAX_OUTSTAND_MSGS; -int PepMaxOutstandMsgs = 7; /* constraint of PEP discovered in 80C152 - source code */ - -/***************************************************************************** - * - * Create an artificial delay to prevent back-to-back message - * loading of the PEP FIFO, since this has proven to induce protocol - * errors. If the global PepLinkDelay variable is non-zero, - * use a software spin loop for the delay. (these values can be set to 0 - * if a "patched PROM" is used on the PB-BIT board). - * - *****************************************************************************/ -int PepLinkLoadDelay = 0; /* set to 450 if a "non-patched" PB-BIT is used */ - -/* On a bitbus error, if link and node match the following global variables, - write to the System Monitor board to generate a trigger */ - -int bbErrorTrigNode = 1; /* Set to -1 for all nodes */ -int bbErrorTrigLink = 0; - -/* Used to keep track of errors per node */ -#define BB_NUM_NODES 100 -unsigned short bbNodeTMO[BB_NUM_LINKS][BB_NUM_NODES]; -unsigned short bbNode91[BB_NUM_LINKS][BB_NUM_NODES]; - -/***************************************************************************** - * - * Debugging flags that may be set from the shell. - * - * bbDebug Used to get status information from the driver's internals. - * May be set with a value from 0 to 40. the higher the number - * the more information. 0 will provide no internal debugging. - * - * bbDebugLink Used to get general status information about a single slave - * bbDebugNode node. - * To disable this feature, set one of them to -1. - * - *****************************************************************************/ -int bbDebug = 1; -int bbDebugLink=-1; -int bbDebugNode=-1; - -#ifdef BB_SUPER_DEBUG -static int BBSetHistEvent(int link, struct dpvtBitBusHead *pXact, int State); -#endif - -/****************************************************************************** - * - * This structure contains a list of the outside-callable functions. - * - ******************************************************************************/ -struct drvBitBusEt drvBitBus = { - 3, - reportBB, - initBB, - qBBReq -}; - -#if 0 -/* JRW --> get rid of this crap */ -STATIC char BitbusInitCalled = 0; /* to insure that init is done first */ -STATIC void *short_base; /* base of short address space */ -#endif - - -STATIC BitbusLinkStruct *pBBLink[BB_NUM_LINKS]; /* NULL if link not config'd */ - /*************************************************************************** - * - * User-callable configuration function. - * - * This function is used to configure the type of link as well as to - * initialize it for operation. - * - *****************************************************************************/ -int BBConfig(unsigned long Link, - unsigned long LinkType, - unsigned long BaseAddr, - unsigned long IrqVector, - unsigned long IrqLevel) -{ - __BBConfig(Link, LinkType, BaseAddr, IrqVector, IrqLevel); - return(0); -} - -int __BBConfig(unsigned long Link, - unsigned long LinkType, - unsigned long BaseAddr, - unsigned long IrqVector, - unsigned long IrqLevel) -{ - void *pVoid; - int j; - static int FirstTime = 1; - char nameTemp[30]; - int taskId; - - if (FirstTime) - { - rebootHookAdd(BBrebootFunc); - FirstTime = 0; - } - if (Link >= BB_NUM_LINKS) - { - logMsg("Error: Invalid link (%d) specified in BBConfig()\n", Link); - return(-1); - } - if ((LinkType != BB_CONF_TYPE_XYCOM) && (LinkType != BB_CONF_TYPE_PEP)) - { - logMsg("Error: Invalid link type (%d) specified in BBConfig()\n", LinkType); - return(-1); - } - if (pBBLink[Link] != NULL) - { - logMsg("Error: BBConfig() Attempt to reconfigure link %d!\n", Link); - return(-1); - } - if (IrqVector%4 != 0) - { - epicsPrintf("Error: BBConfig() IrqVector must be multiple of 4!\n", Link); - return(-1); - } - - if ((pBBLink[Link] = (BitbusLinkStruct *) malloc(sizeof(BitbusLinkStruct))) == NULL) - { - logMsg("Error: BBConfig() cannot malloc\n"); - return(-1); - } - - pBBLink[Link]->LinkType = BB_CONF_HOSED; /* Changed if all goes well */ - pBBLink[Link]->BaseAddr = BaseAddr; - pBBLink[Link]->IrqVector = IrqVector; - pBBLink[Link]->IrqLevel = IrqLevel; - -#ifdef BB_SUPER_DEBUG - /* Init the history FIFO to empty */ - pBBLink[Link]->History.sem = semBCreate(SEM_Q_PRIORITY, SEM_FULL); - pBBLink[Link]->History.Next = 0; - pBBLink[Link]->History.Num = 0; -#endif - - pBBLink[Link]->linkEventSem = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY); - - if (sysBusToLocalAdrs(VME_AM_SUP_SHORT_IO , BaseAddr, &pVoid) != OK) - { - logMsg("Error: BBConfig() can not translate requested A16 address(0x%8.8X\n", BaseAddr); - pBBLink[Link] = NULL; - return(-1); - } - - /* - * Interface specific I/O mapping and registration - */ - - switch (LinkType) - { - case BB_CONF_TYPE_XYCOM: - pBBLink[Link]->l.XycomLink.rxInt = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY); - pBBLink[Link]->l.XycomLink.bbRegs = (XycomBBRegsStruct *)pVoid; - if (devRegisterAddress("Xycom Bitbus", atVMEA16, (void*)BaseAddr, sizeof(XycomBBRegsStruct), NULL) != 0) - { - logMsg("Error: BBConfig() can not register address %8.8X\n", pVoid); - pBBLink[Link] = NULL; - return(-1); /* BUG */ - } - break; - case BB_CONF_TYPE_PEP: - pBBLink[Link]->l.PepLink.rxInt = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY); - pBBLink[Link]->l.PepLink.bbRegs = (PepBBRegsStruct *)pVoid; - if (devRegisterAddress("PEP Bitbus", atVMEA16, (void*)BaseAddr, sizeof(PepBBRegsStruct), NULL) != 0) - { - logMsg("Error: BBConfig() can not register address %8.8X\n", pVoid); - pBBLink[Link] = NULL; - return(-1); /* BUG */ - } - break; - } - - /* - * Common data structure initialization. - */ - - /* Init the prioritized queue lists */ - for (j=0; jqueue[j].head = NULL; - pBBLink[Link]->queue[j].tail = NULL; - pBBLink[Link]->queue[j].sem = semBCreate(SEM_Q_PRIORITY, SEM_FULL); - pBBLink[Link]->queue[j].elements = 0; - } - - /* Init the busy message list */ - pBBLink[Link]->busyList.sem = semBCreate(SEM_Q_PRIORITY, SEM_FULL); - pBBLink[Link]->busyList.head = NULL; - pBBLink[Link]->busyList.tail = NULL; - pBBLink[Link]->busyList.elements = 0; - - for (j=0; jdeviceStatus[j] = BB_IDLE; - pBBLink[Link]->syntheticDelay[j] = 0; - } - pBBLink[Link]->DelayCount = 0; - - pBBLink[Link]->watchDogId = wdCreate(); - pBBLink[Link]->watchDogSem = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY); - - /* Clear the link abort status */ - pBBLink[Link]->abortFlag = 0; - pBBLink[Link]->txAbortAck = 0; - pBBLink[Link]->rxAbortAck = 0; - - /* - * Interface type specific initialization of management tasks. - */ - - if (LinkType == BB_CONF_TYPE_XYCOM) - { - /* BOARD SPECIFIC INIT CODE for XYCOM */ - if (xvmeReset(Link) != 0) - { - pBBLink[Link] = NULL; - return(-1); - } - - pBBLink[Link]->LinkType = LinkType; - - /* attach the interrupt handler routines */ - intConnect(INUM_TO_IVEC(BB_IVEC_BASE + 1 + (Link*4)), xvmeIrqRcmd, Link); - intConnect(INUM_TO_IVEC(BB_IVEC_BASE + 3 + (Link*4)), xvmeIrqRdav, Link); - - /* Start a task to manage the TX link */ - sprintf(nameTemp, "%s%d-xy", BBTXLINK_NAME, Link); - if ((taskId=taskSpawn(nameTemp, BBTXLINK_PRI, BBTXLINK_OPT, BBTXLINK_STACK, xvmeTxTask, Link)) == ERROR) - { - logMsg("BBConfig(): failed to start TX link task for link %d\n", Link); - } - taskwdInsert(taskId,NULL,NULL); - /* Start a task to manage the RX link */ - sprintf(nameTemp, "%s%d-xy", BBRXLINK_NAME, Link); - if ((taskId=taskSpawn(nameTemp, BBRXLINK_PRI, BBRXLINK_OPT, BBRXLINK_STACK, xvmeRxTask, Link)) == ERROR) - { - logMsg("BBConfig(): failed to start RX link task for link %d\n", Link); - } - taskwdInsert(taskId,NULL,NULL); - /* Start a task to keep an eye on the busy list */ - sprintf(nameTemp, "%s%d-xy", BBWDTASK_NAME, Link); - if ((taskId=taskSpawn(nameTemp, BBWDTASK_PRI, BBWDTASK_OPT, BBWDTASK_STACK, xvmeWdTask, Link)) == ERROR) - { - logMsg("BBConfig(): failed to start watchdog task for link %d\n", Link); - } - taskwdInsert(taskId,NULL,NULL); - } - else if (LinkType == BB_CONF_TYPE_PEP) - { - /* PEP specific init code */ - if (pepReset(Link) != 0) - { - pBBLink[Link] = NULL; - return(-1); - } - - pBBLink[Link]->LinkType = LinkType; - - /* attach the interrupt handler routines */ - intConnect(INUM_TO_IVEC(PEP_BB_IVEC_BASE + (Link*2)), pepIrqRdav, Link); - - /* Start a task to manage the TX link */ - sprintf(nameTemp, "%s%d-pep", BBTXLINK_NAME, Link); - if ((taskId=taskSpawn(nameTemp, BBTXLINK_PRI, BBTXLINK_OPT, BBTXLINK_STACK, pepTxTask, Link)) == ERROR) - { - logMsg("BBConfig(): failed to start TX link task for link %d\n", Link); - } - taskwdInsert(taskId,NULL,NULL); - /* Start a task to manage the RX link */ - sprintf(nameTemp, "%s%d-pep", BBRXLINK_NAME, Link); - if ((taskId=taskSpawn(nameTemp, BBRXLINK_PRI, BBRXLINK_OPT, BBRXLINK_STACK, pepRxTask, Link)) == ERROR) - { - logMsg("BBConfig(): failed to start RX link task for link %d\n", Link); - } - taskwdInsert(taskId,NULL,NULL); - /* Start a task to keep an eye on the busy list */ - sprintf(nameTemp, "%s%d-pep", BBWDTASK_NAME, Link); - if ((taskId=taskSpawn(nameTemp, BBWDTASK_PRI, BBWDTASK_OPT, BBWDTASK_STACK, pepWdTask, Link)) == ERROR) - { - logMsg("BBConfig(): failed to start watchdog task for link %d\n", Link); - } - taskwdInsert(taskId,NULL,NULL); - } - sysIntEnable(IrqLevel); - return(0); -} - /****************************************************************** - * - * The EPICS init routine is not needed. - * - ******************************************************************/ -STATIC long initBB(void) -{ - return(0); -} - -/****************************************************************** - * FUNCTION: reportBB() - * PURPOSE : Prints a message indicating the presence of each - * bitbus module found in system. - * ARGS IN : none - * ARGS OUT: none - * GLOBALS: checks pBBLink[i] for NULL - ******************************************************************/ - -STATIC long reportBB(void) -{ - int i; - - if (bbDebug>1) - printf("Bitbus debugging flag is set to %d\n", bbDebug); - - for (i=0; i< BB_NUM_LINKS; i++) - { - if (pBBLink[i] != NULL) - { - if (pBBLink[i]->LinkType == BB_CONF_TYPE_XYCOM) - printf("Bitbus link %d present at %p IV=0x%2.2X IL=%d (XYCOM)\n", i, pBBLink[i]->l.XycomLink.bbRegs, pBBLink[i]->IrqVector, pBBLink[i]->IrqLevel); - else if (pBBLink[i]->LinkType == BB_CONF_TYPE_PEP) - printf("Bitbus link %d present at %p IV=0x%2.2X IL=%d (PEP)\n", i, pBBLink[i]->l.PepLink.bbRegs, pBBLink[i]->IrqVector, pBBLink[i]->IrqLevel); - } - } - return(OK); -} - /****************************************************************** - * FUNCTION: pepReset() - * PURPOSE : Performs firmware reset of PB-BIT module corresponding - * to link. Attempts to empty any data sitting in receive - * FIFO. Interrupts are disabled and Rx task is unblocked. - * ARGS IN : xvmeRegs ptr to register structure of PB-BIT module - * link link number serviced by PB-BIT module - * ARGS OUT: none - * GLOBALS: twiddles board - ******************************************************************/ -STATIC int -pepReset(int link) -{ - char trash; - int j; - int lockKey; - int probeValue; - - if (bbDebug) - printf("pepReset(%d): Resetting pep module\n", link); - - probeValue = 0; - if (vxMemProbe(&(pBBLink[link]->l.PepLink.bbRegs->int_vec), WRITE, 1, &probeValue) < OK) - { /* no BB board present here */ - logMsg("ERROR: PEP Bitbus link %d not present at 0x%8.8X\n", link, pBBLink[link]->l.PepLink.bbRegs); - return(-1); - } - - /* Write firmware reset package (2 bytes) to board */ - pBBLink[link]->l.PepLink.bbRegs->data = 0x83; - pBBLink[link]->l.PepLink.bbRegs->stat_ctl = 0x01; - - taskDelay(20); /* give the 80152 time to self check */ - - if ((pBBLink[link]->l.PepLink.bbRegs->stat_ctl & 0x10) != 0x0) - { - if (bbDebug) - printf("pepReset(%d): PB-BIT firmware reset failed!\n", link); - return(ERROR); - } - - j = 1026; /* 1K deep receive fifo */ - /* flush receive fifo if junk in it */ - while ((pBBLink[link]->l.PepLink.bbRegs->stat_ctl & PEP_BB_RFNE) && --j) - trash = pBBLink[link]->l.PepLink.bbRegs->data; - - if (!j) - { - if (bbDebug) - printf("pepReset(%d): receive fifo will not clear after reset!\n", link); - return(ERROR); - } - - /* Disable interrupts */ - lockKey = intLock(); - pBBLink[link]->l.PepLink.bbRegs->int_vec = 0; - intUnlock(lockKey); - - /* Tell pepRxTask to Re-enable ints */ - semGive(pBBLink[link]->l.PepLink.rxInt); - - return(OK); -} - /**************************************************************************** - * - * Reset an xvme-402 BitBus card by cycling the reset bit in the fifo - * status register. - * - ****************************************************************************/ -STATIC int xvmeReset(int link) -{ - char trash; - int j; - int lockKey; - unsigned char probeValue; - - - if (bbDebug) - printf("xvmeReset(%d): Resetting xvme module\n", link); - - probeValue = XVME_RESET; - if (vxMemProbe(&(pBBLink[link]->l.XycomLink.bbRegs->fifo_stat), WRITE, 1, &probeValue) < OK) - { /* no BB board present here */ - logMsg("ERROR: Xycom Bitbus link %d not present at 0x%8.8X\n", link, pBBLink[link]->l.XycomLink.bbRegs); - return(-1); - } - -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, NULL, XACT_HIST_STATE_RESET); -#endif - - taskDelay(2); - pBBLink[link]->l.XycomLink.bbRegs->fifo_stat = 0; /* clear reset pulse */ - taskDelay(30); /* give the 8044 time to self check */ - - j = 100; /* give up after this */ - while ((pBBLink[link]->l.XycomLink.bbRegs->fifo_stat & XVME_RCMD) && --j) - trash = pBBLink[link]->l.XycomLink.bbRegs->cmnd; /* flush command buffer if junk in it */ - - if (!j) - { - if (bbDebug) - printf("xvmeReset(%d): Command buffer will not clear after reset!\n", link); - return(ERROR); - } - - j = 100; - while ((pBBLink[link]->l.XycomLink.bbRegs->fifo_stat & XVME_RFNE) && --j) - trash = pBBLink[link]->l.XycomLink.bbRegs->data; /* flush data buffer if junk in it */ - - if (!j) - { - if (bbDebug) - printf("xvmeReset(%d): Data buffer will not clear after reset!\n", link); - return(ERROR); - } - - if ((pBBLink[link]->l.XycomLink.bbRegs->fifo_stat & XVME_FSVALID) != XVME_FSIDLE) - { - if (bbDebug) - printf("xvmeReset(%d): XVME board not returning to idle status after reset!\n", link); - return(ERROR); - } - - /* set the interrupt vector */ - lockKey = intLock(); - pBBLink[link]->l.XycomLink.bbRegs->stat_ctl = 0; /* disable all interupts */ - pBBLink[link]->l.XycomLink.bbRegs->int_vec = BB_IVEC_BASE + (link*4);/* set the int vector */ - intUnlock(lockKey); - - semGive(pBBLink[link]->l.XycomLink.rxInt); /* Tell xvmeRxTask to Re-enable interrupts */ - - return(OK); -} - /**************************************************************************** - * - * This function is used to add a node to the HEAD of a list. - * - ****************************************************************************/ -static int -listAddHead(struct bbList *plist, struct dpvtBitBusHead *pnode) -{ - pnode->prev = NULL; - pnode->next = plist->head; - - if (plist->head != NULL) - plist->head->prev = pnode; - - if (plist->tail == NULL) - plist->tail = pnode; - - plist->head = pnode; - - plist->elements++; - - return(0); -} -/****************************************************************************** - * - * This function is used to add a node to the TAIL of a list. - * - ******************************************************************************/ -static int -listAddTail(struct bbList *plist, struct dpvtBitBusHead *pnode) -{ - pnode->next = NULL; /* No next node if this is the TAIL */ - pnode->prev = plist->tail; /* previous node is the 'old' TAIL node */ - - if (plist->tail != NULL) - plist->tail->next = pnode; /* link the 'old' tail to the 'new' tail node */ - - if (plist->head == NULL) - plist->head = pnode; - - plist->tail = pnode; /* this is the 'new' tail node */ - - plist->elements++; - - return(0); -} - /*************************************************************************** - * - * This function is used to delete a node from a list. - * - ***************************************************************************/ -static int -listDel(struct bbList *plist, struct dpvtBitBusHead *pnode) -{ - if (pnode->next != NULL) - pnode->next->prev = pnode->prev; - - if (pnode->prev != NULL) - pnode->prev->next = pnode->next; - - if (plist->head == pnode) - plist->head = pnode->next; - - if (plist->tail == pnode) - plist->tail = pnode->prev; - - plist->elements--; - - return(0); -} - /**************************************************************************** - * - * xycom IRQ handler for receiver data bytes. - * - ****************************************************************************/ -static int -xvmeIrqRdav(int link) -{ - if (bbDebug > 30) - logMsg("bitbus rx IRQ on link %d\n", link); - semGive(pBBLink[link]->l.XycomLink.rxInt); /* deliver the groceries */ - return(0); -} - -/**************************************************************************** - * - * xycom IRQ handler invoked when the BitBus controller has completed the - * transfer of a RECEIVED message. - * - ****************************************************************************/ -static int -xvmeIrqRcmd(int link) -{ - if (bbDebug > 30) - logMsg("bitbus rcmd IRQ on link %d\n", link); - semGive(pBBLink[link]->l.XycomLink.rxInt); /* deliver the groceries */ - return(0); -} - /****************************************************************** - * FUNCTION: pepIrqRdav() - * PURPOSE : Invoked when PB-BIT module has received a complete - * bitbus message (ie. not on a byte-by-byte basis). - * ARGS IN : link link number upon which message has arrived - * ARGS OUT: none - * GLOBALS: unblocks Rx task (if it is not already running) - ******************************************************************/ -STATIC int -pepIrqRdav(int link) -{ - pBBLink[link]->l.PepLink.bbRegs->int_vec = 0; /* disable IRQs */ - - if (bbDebug > 30) - logMsg("PEP bitbus rx IRQ on link %d\n", link); - - semGive(pBBLink[link]->l.PepLink.rxInt); /* unblock it */ - return(0); -} - /****************************************************************** - * FUNCTION: pepTmoHandler() - * PURPOSE : Invoked whenever a watchdog timer times out. Watchdogs - * are running whenever the busyList has any elements on - * it. The idea here is that the watchdog handler scans - * through the busyList, looking for old requests that have - * not been replied to in too long a time. If there are - * any old ones around, they are removed from the list, - * and the associated node is reset and marked offline. - * - * ARGS IN : link - * ARGS OUT: none - * GLOBALS: none - ******************************************************************/ -STATIC int -pepTmoHandler(int link) -{ - if (bbDebug > 25) - logMsg("pepTmoHandler(%d): Watch dog interrupt\n", link); - - semGive(pBBLink[link]->watchDogSem); /* unblock Wd task */ - return(0); -} - -/****************************************************************************** - * - * Watchdogs are running when ever the busy list has any elements in it. - * The idea here is that the watchdog handler scans thru the busy list, - * looking for old requests that have not been replied to in too long - * a time. If there are any old ones around, they are removed from the - * list and marked as un-replied to. - * - ******************************************************************************/ -static int -xvmeTmoHandler(int link) -{ - if (bbDebug > 25) - logMsg("xvmeTmoHandler(%d): Watch dog interrupt\n", link); - - semGive(pBBLink[link]->watchDogSem); - return(0); -} - /**************************************************************************** - * - * Given a link number, make sure it is valid. - * - ****************************************************************************/ -static int -checkLink(int link) -{ - if ((link<0) || (link>BB_NUM_LINKS)) - return(ERROR); /* link number out of range */ - - if (pBBLink[link] == NULL) - return(ERROR); /* link number has no card installed */ - - return(OK); -} - /*************************************************************************** - * - * This function is started as a task during driver init time. It's purpose - * is to read messages that are received from the bitbus link. After a message - * is received, the soliciting message's completion routines are started by - * the use of semaphores and/or a callbackRequest(). - * - ***************************************************************************/ -static int -xvmeRxTask(int link) -{ - int rxState; /* current state of the receiver */ -#define BBRX_HEAD 1 -#define BBRX_DATA 2 -#define BBRX_RCMD 3 -#define BBRX_IGN 4 - - unsigned char rxHead[5]; /* room for header of current rx msg */ - unsigned char *rxMsg; /* where to place next byte (after header) */ - int rxTCount; /* byte counter for data in rxHead */ - unsigned char ch; - struct dpvtBitBusHead *rxDpvtHead; /* for message currently receiving */ - - struct dpvtBitBusHead UselessMsg; /* to hold unsolicited responses */ - unsigned char UselessData[BB_MAX_MSG_LENGTH]; - - int lockKey; /* used for intLock calls */ - - rxMsg = (unsigned char *) NULL; - rxState = BBRX_HEAD; - rxTCount = 0; - rxDpvtHead = (struct dpvtBitBusHead *) NULL; - - /* Dummy up the UselessMsg fields so we can use it */ - UselessMsg.rxMaxLen = BB_MAX_MSG_LENGTH; - UselessMsg.rxMsg.data = UselessData; - UselessMsg.link = link; - UselessMsg.ageLimit = 0; - UselessMsg.retire = 0; - - while (1) - { - /* Wait for RX interrupts, but only if no chars are ready */ - if ((pBBLink[link]->l.XycomLink.bbRegs->fifo_stat & XVME_RFNE) == 0) - { - /* Enable interrupts and check again because xycom blew it */ - lockKey = intLock(); - pBBLink[link]->l.XycomLink.bbRegs->stat_ctl = XVME_ENABLE_INT | XVME_RX_INT; - intUnlock(lockKey); - - while (((pBBLink[link]->l.XycomLink.bbRegs->fifo_stat & XVME_RFNE) == 0) && (pBBLink[link]->abortFlag == 0)) - { - /* Re-enable ints here each time in case board got reset */ - lockKey = intLock(); - pBBLink[link]->l.XycomLink.bbRegs->stat_ctl = XVME_ENABLE_INT | XVME_RX_INT; - intUnlock(lockKey); - - /* Wait for groceries */ - semTake(pBBLink[link]->l.XycomLink.rxInt, WAIT_FOREVER); - } - /* Disable RX Interrupts (prevents unnecessary context switching) */ - lockKey = intLock(); - pBBLink[link]->l.XycomLink.bbRegs->stat_ctl = 0; - intUnlock(lockKey); - } - if (pBBLink[link]->abortFlag == 0) - { - /* check to see if we got a data byte or a command byte */ - if ((pBBLink[link]->l.XycomLink.bbRegs->fifo_stat & XVME_RCMD) == XVME_RCMD) - rxState = BBRX_RCMD; - - switch (rxState) { - case BBRX_HEAD: /* getting the head of a new message */ - rxHead[rxTCount] = pBBLink[link]->l.XycomLink.bbRegs->data; - if (bbDebug>21) - printf("xvmeRxTask(%d): >%2.2X< (Header)\n", link, rxHead[rxTCount]); - - if (++rxTCount == 5) - { /* find the message this is a reply to */ - rxTCount += 2; /* adjust for the link field space */ - - /* Lock the busy list */ - semTake(pBBLink[link]->busyList.sem, WAIT_FOREVER); - - rxDpvtHead = pBBLink[link]->busyList.head; - while (rxDpvtHead != NULL) - { - if (bbDebug>19) - printf("xvmeRxTask(%d): checking reply against %p\n", link, rxDpvtHead); - - /* see if node's match */ - if (rxDpvtHead->txMsg.node == rxHead[2]) - { /* see if the tasks match */ - if (rxDpvtHead->txMsg.tasks == rxHead[3]) - { /* They match, finish putting response into the rxMsg buffer */ - if (bbDebug>4) - printf("xvmeRxTask(%d): reply to %p\n", link, rxDpvtHead); - - /* Delete the node from the list */ - listDel(&(pBBLink[link]->busyList), rxDpvtHead); - - /* If busy list is empty, stop the dog */ - if (pBBLink[link]->busyList.head == NULL) - wdCancel(pBBLink[link]->watchDogId); - - if (rxHead[4] == 0x91) - { /* something bad happened... inject a delay to the */ - /* requested timeout duration. */ - - if ((link == bbErrorTrigLink) && - ((bbErrorTrigNode < 0) || (bbErrorTrigNode == rxHead[2]))) - pulseSysMon(); - - /* keep track of timeouts per node */ - if(rxHead[2] < BB_NUM_NODES) { - bbNode91[link][rxHead[2]]++; - } - - if (bbDebug) - printf("xvmeRxTask(%d): 0x91 from node %d, invoking synthetic delay\n", link, rxHead[2]); - (pBBLink[link]->syntheticDelay[rxDpvtHead->txMsg.node]) = rxDpvtHead->retire; - pBBLink[link]->DelayCount++; - } - else - { /* decrement the number of outstanding messages to the node */ - (pBBLink[link]->deviceStatus[rxDpvtHead->txMsg.node])--; - } - - /* Wake up Link Task in case was waiting on "this" node */ - semGive(pBBLink[link]->linkEventSem); - -#if 0 - semGive(pXvmeLink[link]->pbbLink->busyList.sem); - - rxDpvtHead->rxMsg.length = rxHead[0]; - rxDpvtHead->rxMsg.route = rxHead[1]; - rxDpvtHead->rxMsg.node = rxHead[2]; - rxDpvtHead->rxMsg.tasks = rxHead[3]; - rxDpvtHead->rxMsg.cmd = rxHead[4]; - rxMsg = rxDpvtHead->rxMsg.data; - - rxDpvtHead->status = BB_OK; /* OK, unless BB_LENGTH */ - rxState = BBRX_DATA; /* finish reading till RCMD */ -#endif - break; /* get out of the while() */ - } - } - rxDpvtHead = rxDpvtHead->next; /* Keep looking */ - } - - semGive(pBBLink[link]->busyList.sem); - - /* Couldn't find a match... fake one so can print the bad message */ - if (rxDpvtHead == NULL) - rxDpvtHead = &UselessMsg; - - rxDpvtHead->rxMsg.length = rxHead[0]; - rxDpvtHead->rxMsg.route = rxHead[1]; - rxDpvtHead->rxMsg.node = rxHead[2]; - rxDpvtHead->rxMsg.tasks = rxHead[3]; - rxDpvtHead->rxMsg.cmd = rxHead[4]; - rxMsg = rxDpvtHead->rxMsg.data; - - rxDpvtHead->status = BB_OK; /* OK, unless BB_LENGTH */ - rxState = BBRX_DATA; /* finish reading till RCMD */ - } - break; - - case BBRX_DATA: /* finish reading data portion of message */ - ch = pBBLink[link]->l.XycomLink.bbRegs->data; - if (rxTCount >= rxDpvtHead->rxMaxLen) - { - rxState = BBRX_IGN; /* toss the rest of the data */ - rxDpvtHead->status = BB_LENGTH; /* set driver status */ - if (bbDebug>22) - printf("xvmeRxTask(%d): %2.2X (Ignored)\n", link, ch); - } - else - { - *rxMsg = ch; - if (bbDebug>22) - printf("xvmeRxTask(%d): %2.2X (Data)\n", link, ch); - rxMsg++; - rxTCount++; - } - break; - - case BBRX_IGN: - ch = pBBLink[link]->l.XycomLink.bbRegs->data; - if (bbDebug>22) - printf("xvmeRxTask(%d): %2.2X (Ignored)\n", link, ch); - break; - - case BBRX_RCMD: - if (rxDpvtHead == NULL) - { - ch = pBBLink[link]->l.XycomLink.bbRegs->cmnd; - if (bbDebug) - printf("xvmeRxTask(%d): got unexpected XVME_RCMD\n", link); -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, NULL, XACT_HIST_STATE_RX_URCMD); -#endif - } - else if (rxDpvtHead == &UselessMsg) - { - rxDpvtHead->status = BB_OK; /* XXX -- ??? */ - rxDpvtHead->rxCmd = pBBLink[link]->l.XycomLink.bbRegs->cmnd; - - if (bbDebug) - { - printf("xvmeRxTask(%d): msg from node %d unsolicited:", link, rxDpvtHead->rxMsg.node); - drvBitBusDumpMsg(&(rxDpvtHead->rxMsg)); - } -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, rxDpvtHead, XACT_HIST_STATE_RX_UNSOLICITED); -#endif - } - else - { - rxDpvtHead->status = BB_OK; /* XXX -- ??? */ - rxDpvtHead->rxCmd = pBBLink[link]->l.XycomLink.bbRegs->cmnd; - - if (bbDebug>24) - printf("xvmeRxTask(%d):RX command byte = %2.2X\n", link, rxDpvtHead->rxCmd); - -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, rxDpvtHead, XACT_HIST_STATE_RX); -#endif - if (rxDpvtHead->finishProc != NULL) - { - if (bbDebug>8) - printf("xvmeRxTask(%d): invoking the callbackRequest\n", link); - callbackRequest(rxDpvtHead); /* schedule completion processing */ - } - else - { - /* If there is a semaphore for synchronous I/O, unlock it */ - if (rxDpvtHead->psyncSem != NULL) - semGive(*(rxDpvtHead->psyncSem)); - } - } - /* Reset the state of the RxTask to expect a new message */ - rxMsg = (unsigned char *) NULL; - rxState = BBRX_HEAD; - rxTCount = 0; - rxDpvtHead = (struct dpvtBitBusHead *) NULL; - - break; - } - } - else - { /* Link abort state is active reset receiver link status now */ - if (rxDpvtHead != NULL) - { /* This xact is not on the busy list, put it back on */ - semTake(pBBLink[link]->busyList.sem, WAIT_FOREVER); - (pBBLink[link]->deviceStatus[rxDpvtHead->txMsg.node])++; - listAddTail(&(pBBLink[link]->busyList), rxDpvtHead); - semGive(pBBLink[link]->busyList.sem); - } - -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, rxDpvtHead, XACT_HIST_STATE_RX_ABORT); -#endif - rxMsg = (unsigned char *) NULL; - rxState = BBRX_HEAD; - rxTCount = 0; - rxDpvtHead = (struct dpvtBitBusHead *) NULL; - - /* Tell the watch dog I am ready for the reset (reset in the dog task) */ - pBBLink[link]->rxAbortAck = 1; - - if (bbDebug) - printf("xvmeRxTask(%d): resetting due to abort status\n", link); - - /* wait for link state to become active again */ - while (pBBLink[link]->abortFlag != 0) - taskDelay(RESET_POLL_TIME); - - if (bbDebug) - printf("xvmeRxTask(%d): restarting after abort\n", link); - } - } -} - -/****************************************************************************** - * - * A user callable link resetter. This sets a flag and releases the dog - * task to reset the link. - * - ******************************************************************************/ -int -bbReset(int link) -{ - if (checkLink(link) != ERROR) - { - pBBLink[link]->nukeEm = 1; - semGive(pBBLink[link]->watchDogSem); - } - else - printf("Link %d not installed.\n", link); - - return(0); -} - -/****************************************************************************** - * - * BUG -- this does not do the nuke=2 reset and kill link operations like - * the PEP does. - * - ******************************************************************************/ -static int -xvmeWdTask(int link) -{ - struct dpvtBitBusHead *pnode; - struct dpvtBitBusHead *npnode; - unsigned long now; - -#ifdef XYCOM_DO_RESET_AND_OFFLINE - SEM_ID syncSem; - - struct dpvtBitBusHead resetNode; - unsigned char resetNodeData; /* 1-byte data field for RAC_OFFLINE */ - - /* init the SEM used when sending the reset message */ - syncSem = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY); - - /* - * Hand-craft a RAC_OFFLINE message to use when a message times out. - * NOTE that having only one copy is OK provided that the dog waits for - * a response before sending it again! - */ - resetNode.finishProc = NULL; /* no callback routine used */ - resetNode.psyncSem = &syncSem;/* do a semGive on this SEM when done sending */ - resetNode.link = link; /* which bitbus link to send message out on */ - resetNode.rxMaxLen = 7; /* Chop off the response... we don't care */ - resetNode.ageLimit = sysClkRateGet()*100; /* make sure this never times out */ - - resetNode.txMsg.length = 8; - resetNode.txMsg.route = BB_STANDARD_TX_ROUTE; - resetNode.txMsg.node = 0xff; - resetNode.txMsg.tasks = 0x0; - resetNode.txMsg.cmd = RAC_OFFLINE; - resetNode.txMsg.data = &resetNodeData; -#endif - - pBBLink[link]->nukeEm = 0; /* Make sure the nuke status is clear */ - while(1) - { - semTake(pBBLink[link]->watchDogSem, WAIT_FOREVER); - now = tickGet(); /* what time is it? */ - - if (pBBLink[link]->nukeEm != 0) - printf("Bitbus manual reset being issued on link %d\n", link); - - if (bbDebug>4) - printf("xvmeWdTask(%d): (Watchdog) checking busy list\n", link); - - pBBLink[link]->rxAbortAck = 0; /* In case we need to use them */ - pBBLink[link]->txAbortAck = 0; - - if (pBBLink[link]->nukeEm != 0) - { /* set abort status and wait for the abort acks */ - pBBLink[link]->abortFlag = 1; - - /* wake up the Tx task so it can observe the abort status */ - semGive(pBBLink[link]->linkEventSem); - - /* wake up the Rx task so it can observe the abort ststus */ - semGive(pBBLink[link]->l.XycomLink.rxInt); - - /* sleep until abort ack from Tx & Rx tasks */ - while ((pBBLink[link]->rxAbortAck == 0) && (pBBLink[link]->txAbortAck == 0)) - taskDelay(RESET_POLL_TIME); - -#ifdef BB_SUPER_DEBUG - if (pBBLink[link]->nukeEm < 2) - { /* Do a history dump since this is not supposed to happen */ - BBHistDump(link); - } -#endif - } - /* - * Run thru entire busy list to see if there are any transactions - * that have been waiting on a response for too long a period. - */ - semTake(pBBLink[link]->busyList.sem, WAIT_FOREVER); - pnode = pBBLink[link]->busyList.head; - - while (pnode != NULL) - { - npnode = pnode->next; /* remember where we were in the list */ - - if ((pBBLink[link]->nukeEm != 0) || (pnode->retire <= now)) - { - /* Get rid of the request and set error status etc... */ - listDel(&(pBBLink[link]->busyList), pnode); - - if (bbDebug) - { -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, pnode, XACT_HIST_STATE_WD_TIMEOUT); -#endif - printf("xvmeWdTask(%d): TIMEOUT on bitbus message:\n", link); - drvBitBusDumpMsg(&pnode->txMsg); - } - - if(pnode->txMsg.node < BB_NUM_NODES) { - bbNodeTMO[link][pnode->txMsg.node]++; - } - - - /* BUG -- do this here or defer until RX gets a response? */ - (pBBLink[link]->deviceStatus[pnode->txMsg.node])--; /* fix device status */ - pnode->status = BB_TIMEOUT; - -#ifdef XYCOM_DO_RESET_AND_OFFLINE - /* BUG ----- wait for the response from the last one first? */ - - /* Do now in case we need it later */ - resetNodeData = pnode->txMsg.node; /* mark the node number */ -#endif - - /* Make the callbackRequest if one was spec'd */ - if(pnode->finishProc != NULL) - { - callbackRequest(pnode); /* schedule completion processing */ - } - else - { - /* Release a completion lock if one was spec'd */ - if (pnode->psyncSem != NULL) - semGive(*(pnode->psyncSem)); - } - -#ifdef XYCOM_DO_RESET_AND_OFFLINE - /* If we are not going to reboot the link... */ - if (pBBLink[link]->nukeEm == 0) - { /* Send out a RAC_NODE_OFFLINE to the controller */ - semGive(pBBLink[link]->busyList.sem); - - if (bbDebug) - printf("issuing a node offline for link %d node %d\n", link, resetNodeData); - - semTake(pBBLink[link]->queue[BB_Q_HIGH].sem, WAIT_FOREVER); - listAddHead(&(pBBLink[link]->queue[BB_Q_HIGH]), &resetNode); - semGive(pBBLink[link]->queue[BB_Q_HIGH].sem); - - semGive(pBBLink[link]->linkEventSem); /* Tell TxTask to send the message */ - - if (semTake(syncSem, sysClkRateGet()/4) == ERROR) - { - if (bbDebug) - printf("xvmeWdTask(%d): link dead, trying manual reboot\n", link); - pBBLink[link]->nukeEm = 1; - - pBBLink[link]->abortFlag = 1; /* Start the abort sequence */ - semGive(pBBLink[link]->linkEventSem); /* Let Tx task observe abort status */ - semGive(pBBLink[link]->l.XycomLink.rxInt); /* Let Rx task observe abort ststus */ - - /* sleep until abort ack from Tx & Rx tasks */ - while ((pBBLink[link]->rxAbortAck == 0) && (pBBLink[link]->txAbortAck == 0)) - taskDelay(RESET_POLL_TIME); - } - /* Start over since released the busy list */ - - semTake(pBBLink[link]->busyList.sem, WAIT_FOREVER); - npnode = pBBLink[link]->busyList.head; - } -#else - semGive(pBBLink[link]->linkEventSem); -#endif - } - pnode = npnode; - } - if (pBBLink[link]->busyList.head != NULL) - { /* Restart the dog timer */ - - if (bbDebug>5) - printf("xvmeWdTask(%d): restarting watch dog timer\n", link); - - wdStart(pBBLink[link]->watchDogId, pBBLink[link]->busyList.head->retire - now, xvmeTmoHandler, link); - } - semGive(pBBLink[link]->busyList.sem); - - /* Finish the link reboot if necessary */ - if (pBBLink[link]->nukeEm != 0) - { - xvmeReset(link); - - /* clear the abort_flag */ - pBBLink[link]->abortFlag = 0; - - pBBLink[link]->nukeEm = 0; - } - } -} - -/****************************************************************************** - * - * This function is started as a task during driver init time. It's purpose - * is to keep the link busy. It awaits user-calls to qBbReq() with new work - * as well as wake-up calls from the watchdog timer. - * - * At the time this function is started as its own task, the linked list - * structures will have been created and initialized. - * - ******************************************************************************/ -static int -xvmeTxTask(int link) -{ - struct dpvtBitBusHead *pnode; - int prio; - int working; - int dogStart; - int stuck; - - int txTCount; - int txCCount; - unsigned char *txMsg; - register int x; - unsigned long now; - SEM_ID resetNodeSem; - struct dpvtBitBusHead resetNode; - unsigned char resetNodeData; /* 1-byte data field for RAC_OFFLINE */ - - if (bbDebug) - printf("xvmeTxTask started for link %d\n", link); - - /* hand-craft a RAC_OFFLINE message for use with RAC_RESET_SLAVE commands */ - /* NOTE that having only one copy is OK provided that this message is */ - /* sent immediately following the RAC_RESET_SLAVE message. */ - - resetNodeSem = semBCreate(SEM_Q_PRIORITY, SEM_FULL); - - resetNode.finishProc = NULL; - resetNode.psyncSem = &resetNodeSem; - resetNode.link = link; - resetNode.rxMaxLen = 7; /* Chop it off, we don't care */ - resetNode.ageLimit = sysClkRateGet(); - - resetNode.txMsg.length = 8; - resetNode.txMsg.route = BB_STANDARD_TX_ROUTE; - resetNode.txMsg.node = 0xff; - resetNode.txMsg.tasks = 0x0; - resetNode.txMsg.cmd = RAC_OFFLINE; - resetNode.txMsg.data = &resetNodeData; - - while(1) - { - if (pBBLink[link]->abortFlag != 0) - { - pBBLink[link]->txAbortAck = 1; /* let the dog know we are ready */ -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, NULL, XACT_HIST_STATE_TX_ABORT); -#endif - - if (bbDebug) - printf("xvmeTxTask(%d): resetting due to abort status\n", link); - - while (pBBLink[link]->abortFlag != 0) - taskDelay(RESET_POLL_TIME); /* wait for link to reset */ - - if (bbDebug) - printf("xvmeTxTask(%d): restarting after abort\n", link); - } - else - { - if (pBBLink[link]->DelayCount) - semTake(pBBLink[link]->linkEventSem, 2 * sysClkRateGet()); - else - semTake(pBBLink[link]->linkEventSem, WAIT_FOREVER); - } - - if (bbDebug>5) - printf("xvmeTxTask(%d): got an event\n", link); - - working = 1; - while ((working != 0) && (pBBLink[link]->abortFlag == 0) && (pBBLink[link]->busyList.elements < XycomMaxOutstandMsgs)) - { - working = 0; - - prio = BB_NUM_PRIO-1; - while ((prio >= 0) && (pBBLink[link]->abortFlag == 0)) - { - /* see if the queue has anything in it */ - semTake(pBBLink[link]->queue[prio].sem, WAIT_FOREVER); - - if ((pnode = pBBLink[link]->queue[prio].head) != NULL) - { - now = tickGet(); - while (pBBLink[link]->deviceStatus[pnode->txMsg.node] == BB_BUSY) - { - if ((pBBLink[link]->syntheticDelay[pnode->txMsg.node] != 0) - && (pBBLink[link]->syntheticDelay[pnode->txMsg.node] < now)) - { - if (bbDebug) - printf("xvmeTxTask(%d): terminating synthetic idle on node %d\n", link, pnode->txMsg.node); - (pBBLink[link]->deviceStatus[pnode->txMsg.node])--; - pBBLink[link]->syntheticDelay[pnode->txMsg.node] = 0; - pBBLink[link]-> DelayCount--; - } - else - { - if ((pnode = pnode->next) == NULL) - break; - } - } - } - if (pnode != NULL) - { /* have an xact to start processing */ - working = 1; /* indicate work being done */ - - /* delete the node from the inbound fifo queue */ - listDel(&(pBBLink[link]->queue[prio]), pnode); - - semGive(pBBLink[link]->queue[prio].sem); - -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, pnode, XACT_HIST_STATE_TX); -#endif - if (bbDebug>3) - printf("xvmeTxTask(%d): got xact, pnode=%p\n", link, pnode); - - /* Send the message in polled mode */ - - txTCount = pnode->txMsg.length - 2; - txCCount = 0; - txMsg = &(pnode->txMsg.length); - - while ((txCCount <= txTCount) && (pBBLink[link]->abortFlag == 0)) - { - stuck = 1000; - while (((pBBLink[link]->l.XycomLink.bbRegs->fifo_stat & XVME_TFNF) != XVME_TFNF) && (pBBLink[link]->abortFlag == 0) && --stuck) - for(x=0;x<100;x++); /* wait for TX ready */ - - if (!stuck) - { -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, pnode, XACT_HIST_STATE_TX_STUCK); -#endif - txStuck(link); /* will end up setting abortFlag */ - } - else if (txCCount < txTCount) /* on last time, just wait, no data */ - { - pBBLink[link]->l.XycomLink.bbRegs->data = *txMsg; /* send next byte */ - if (bbDebug>30) - printf("xvmeTxTask(%d): outputting %2.2X\n", link, *txMsg); - - /* On 5th byte, we are dun w/header, set start w/data buffer */ - if (txCCount != 4) - txMsg++; - else - txMsg = pnode->txMsg.data; - } - txCCount++; - } - - if (pBBLink[link]->abortFlag == 0) - { - - /* All data bytes have been sent, put on busy list and release */ - - /* Don't add to busy list if was a RAC_RESET_SLAVE */ - if ((pnode->txMsg.cmd == RAC_RESET_SLAVE) && (pnode->txMsg.tasks == 0)) - { /* Finish the transaction here if was a RAC_RESET_SLAVE */ -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, pnode, XACT_HIST_STATE_TX_RESET); -#endif - if (bbDebug) - printf("xvmeTxTask(%d): RAC_RESET_SLAVE sent, resetting node %d\n", link, pnode->txMsg.node); - - pnode->status = BB_OK; - - if (pnode->finishProc != NULL) - { - if (bbDebug>4) - printf("xvmeTxTask(%d): invoking callbackRequest\n", link); - - callbackRequest(pnode); /* schedule completion processing */ - } - else - { - /* If there is a semaphore for synchronous I/O, unlock it */ - if (pnode->psyncSem != NULL) - semGive(*(pnode->psyncSem)); - } - - /* Wait for last NODE_OFFLINE to finish (if still pending) */ - semTake(resetNodeSem, WAIT_FOREVER); - - /* have to reset the master so it won't wait on a response */ - resetNodeData = pnode->txMsg.node; /* mark the node number */ - semTake(pBBLink[link]->queue[BB_Q_HIGH].sem, WAIT_FOREVER); - listAddHead(&(pBBLink[link]->queue[BB_Q_HIGH]), &resetNode); - semGive(pBBLink[link]->queue[BB_Q_HIGH].sem); - - /* taskDelay(15); */ /* wait while bug is resetting */ - } - else - { - /* Lock the busy list */ - semTake(pBBLink[link]->busyList.sem, WAIT_FOREVER); - - /* set the retire time */ - pnode->retire = tickGet(); - if (pnode->ageLimit) - pnode->retire += pnode->ageLimit; - else - pnode->retire += BB_DEFAULT_RETIRE_TIME * sysClkRateGet(); - - if (pBBLink[link]->busyList.head == NULL) - dogStart = 1; - else - dogStart = 0; - - /* Add pnode to the busy list */ - listAddTail(&(pBBLink[link]->busyList), pnode); - - /* Count the outstanding messages */ - (pBBLink[link]->deviceStatus[pnode->txMsg.node])++; - - semGive(pBBLink[link]->busyList.sem); - - /* If just added something to an empty busy list, start the dog */ - if (dogStart) - { - now = tickGet(); - wdStart(pBBLink[link]->watchDogId, pBBLink[link]->busyList.head->retire - now, xvmeTmoHandler, link); - } - } - - /* Tell the 8044 to fire out the message now */ - pBBLink[link]->l.XycomLink.bbRegs->cmnd = BB_SEND_CMD; /* forward it now */ - } - else - { /* Aborted transmission operation, re-queue the message */ - semTake(pBBLink[link]->queue[BB_Q_HIGH].sem, WAIT_FOREVER); - listAddHead(&(pBBLink[link]->queue[BB_Q_HIGH]), pnode); - semGive(pBBLink[link]->queue[BB_Q_HIGH].sem); -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, pnode, XACT_HIST_STATE_TX_ABORT); -#endif - if (bbDebug) - { - printf("Message in progress when abort issued:\n"); - drvBitBusDumpMsg(&pnode->txMsg); - } - } -/* BUG -- I don't really need this */ - /* break;*/ /* stop checking the fifo queues */ - } - else - { /* we have no xacts that can be processed at this time */ - semGive(pBBLink[link]->queue[prio].sem); - } - prio--; /* look at the next prio queue */ - } - } - } -} - -/****************************************************************************** - * - * This gets called by the transmit task if it gets stuck waiting to send a - * byte to the transmit fifo. - * - ******************************************************************************/ -STATIC int txStuck(int link) -{ - if (bbDebug) - printf("bitbus transmitter task stuck, resetting link %d\n", link); - - bbReset(link); - while (pBBLink[link]->abortFlag == 0) - taskDelay(1); - - return(OK); -} - -/****************************************************************************** - * - * This function is called by user programs to queue an I/O transaction request - * for the BB driver. It is the only user-callable function provided in this - * driver. - * - ******************************************************************************/ -STATIC long qBBReq(struct dpvtBitBusHead *pdpvt, int prio) -{ - static linkErrFlags[BB_NUM_LINKS]; /* Supposedly init'd to zero */ - char message[200]; - - if ((prio < 0) || (prio >= BB_NUM_PRIO)) - { - sprintf(message, "invalid priority requested in call to qbbreq(%p, %d)\n", pdpvt, prio); - errMessage(S_BB_badPrio, message); - return(ERROR); - } - if (checkLink(pdpvt->link) == ERROR) - { - if (pdpvt->link >= BB_NUM_LINKS) - { - sprintf(message, "qbbreq(%p, %d) %d\n", pdpvt, prio, pdpvt->link); - errMessage(S_BB_badlink, message); - } - else if (linkErrFlags[pdpvt->link] == 0) - { /* Anti-message swamping check */ - linkErrFlags[pdpvt->link] = 1; - sprintf(message, "qbbreq(%p, %d) %d... card not present\n", pdpvt, prio, pdpvt->link); - errMessage(S_BB_badlink, message); - } - return(ERROR); - } - -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(pdpvt->link, pdpvt, XACT_HIST_STATE_QUEUE); -#endif - - if (bbDebug>5) - printf("qbbreq(%p, %d): transaction queued\n", pdpvt, prio); - if (bbDebug>6) - drvBitBusDumpMsg(&(pdpvt->txMsg)); - - semTake(pBBLink[pdpvt->link]->queue[prio].sem, WAIT_FOREVER); - - /* Add to the end of the queue of waiting transactions */ - listAddTail(&(pBBLink[pdpvt->link]->queue[prio]), pdpvt); - - semGive(pBBLink[pdpvt->link]->queue[prio].sem); - - semGive(pBBLink[pdpvt->link]->linkEventSem); - - return(OK); -} - - -/****************************************************************** - * - * Reset hook function... takes down ALL the bitbus links and leaves - * them down. - * - ******************************************************************/ -STATIC void BBrebootFunc(void) -{ - int i; - - for (i=0; inukeEm = 2; - semGive(pBBLink[link]->watchDogSem); - } - else - printf("Link %d not installed.\n", link); - - return(0); -} - - - /****************************************************************** - * - * Super debugging facility. - * - ******************************************************************/ -int -drvBitBusDumpMsg(struct bitBusMsg *pbbMsg) -{ - char ascBuf[15]; /* for ascii xlation part of the dump */ - int x; - int y; - int z; - - printf("Link 0x%4.4X, length 0x%2.2X, route 0x%2.2X, node 0x%2.2X, tasks 0x%2.2X, cmd %2.2X\n", pbbMsg->link, pbbMsg->length, pbbMsg->route, pbbMsg->node, pbbMsg->tasks, pbbMsg->cmd); - - x = BB_MSG_HEADER_SIZE; - y = pbbMsg->length; - z = 0; - - while (x < y) - { - printf("%2.2X ", pbbMsg->data[z]); - ascBuf[z] = pbbMsg->data[z]; - - if (!((ascBuf[z] >= 0x20) && (ascBuf[z] <= 0x7e))) - ascBuf[z] = '.'; - - x++; - z++; - } - - while (x < BB_MAX_MSG_LENGTH) - { - printf(" "); - x++; - } - - ascBuf[z] = '\0'; - printf(" *%s*\n", ascBuf); - return(OK); -} - -#ifdef BB_SUPER_DEBUG -/* - * Place an event into the history buffer. - */ -static int BBSetHistEvent(int link, struct dpvtBitBusHead *pXact, int State) -{ - semTake(pBBLink[link]->History.sem, WAIT_FOREVER); - - - pBBLink[link]->History.Num++; - - pBBLink[link]->History.Xact[pBBLink[link]->History.Next].Time = tickGet(); - pBBLink[link]->History.Xact[pBBLink[link]->History.Next].State = State; - if (pXact != NULL) - memcpy (&pBBLink[link]->History.Xact[pBBLink[link]->History.Next].Xact, pXact, sizeof(struct dpvtBitBusHead)); - - if (link==bbDebugLink && pBBLink[link]->History.Xact[pBBLink[link]->History.Next].Xact.txMsg.node==bbDebugNode) - BBDumpXactHistory(&pBBLink[link]->History.Xact[pBBLink[link]->History.Next]); - - if (++pBBLink[link]->History.Next == BB_SUPER_DEBUG_HIST_SIZ) - pBBLink[link]->History.Next = 0; - - semGive(pBBLink[link]->History.sem); - return(0); -} - -int BBHistDump(int link) -{ - int count; - int ix; - - if (checkLink(link) == ERROR) - { - printf(" Link %d is not valid\n", link); - return(-1); - } - printf("Dumping bitbus history for link %d\n", link); - semTake(pBBLink[link]->History.sem, WAIT_FOREVER); - - if (pBBLink[link]->History.Num < BB_SUPER_DEBUG_HIST_SIZ) - { - count = pBBLink[link]->History.Num; - ix = 0; - } - else - { - count = BB_SUPER_DEBUG_HIST_SIZ; - ix = pBBLink[link]->History.Next; - } - - while(count) - { - printf("%8.8d:", pBBLink[link]->History.Xact[ix].Time); - - if (BBDumpXactHistory(&pBBLink[link]->History.Xact[ix]) != 0) - count = 0; - else - --count; - - if (++ix >= BB_SUPER_DEBUG_HIST_SIZ) - ix = 0; - } - - semGive(pBBLink[link]->History.sem); - return(0); -} -STATIC int BBDumpXactHistory(XactHistStruct *pXact) -{ - switch (pXact->State) - { - /* No BB message present */ - case XACT_HIST_STATE_RESET: - printf("Link Reset:\n"); - break; - case XACT_HIST_STATE_RX_ABORT: - printf("Link RX aborted\n"); - break; - case XACT_HIST_STATE_TX_ABORT: - printf("Link TX aborted\n"); - break; - case XACT_HIST_STATE_RX_URCMD: - printf("Link RX got unexpected RCMD\n"); - break; - - /* TX message only */ - case XACT_HIST_STATE_QUEUE: - printf("Message Queued:\n"); - goto do_tx_only; - case XACT_HIST_STATE_TX: - printf("Message Transmitted:\n"); - goto do_tx_only; - case XACT_HIST_STATE_WD_TIMEOUT: - printf("Watchdog Timeout:\n"); - goto do_tx_only; - case XACT_HIST_STATE_TX_STUCK: - printf("Transmitter stuck:\n"); - goto do_tx_only; - case XACT_HIST_STATE_TX_RESET: - printf("TX just sent a RAC RESET:\n"); - - do_tx_only: - drvBitBusDumpMsg(&pXact->Xact.txMsg); - break; - - /* RX message only */ - case XACT_HIST_STATE_RX_UNSOLICITED: - printf("RX unsolicited message:\n"); - drvBitBusDumpMsg(&pXact->Xact.rxMsg); - break; - - /* TX and RX messages present */ - case XACT_HIST_STATE_RX: - printf("RX response... complete transaction:\n"); - drvBitBusDumpMsg(&pXact->Xact.txMsg); - drvBitBusDumpMsg(&pXact->Xact.rxMsg); - break; - - default: - printf("Corrupt bitbus debug state!\n"); - return(-1); - } - return(0); -} -#endif - -/****************************************************************************** - * - * A user callable function that may be used to reset the specified slave - * node. - * - * This routine is NOT reenterant but contains a monitor so that it always - * operates properly. - * - ******************************************************************************/ -int ResetBug(int node, int link) -{ - static int FirstTime = 1; - static SEM_ID monLock; - static SEM_ID syncSem; /* Semaphore to use for completion */ - struct dpvtBitBusHead resetNode; /* actual message to send out */ - unsigned char resetNodeData; /* 1-byte data field for RAC_RESET */ - - if (FirstTime) - { - monLock = semBCreate(SEM_Q_PRIORITY, SEM_FULL); - syncSem = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY); - FirstTime = 0; - } - - semTake(monLock, WAIT_FOREVER); - - resetNode.finishProc = NULL; /* no callback routine used */ - resetNode.psyncSem = &syncSem;/* do a semGive on this SEM when done sending */ - resetNode.link = link; /* which bitbus link to send message out on */ - resetNode.rxMaxLen = 7; /* Chop off the response... we don't care */ - resetNode.ageLimit = sysClkRateGet()*2; - - resetNode.txMsg.length = 8; - resetNode.txMsg.route = BB_STANDARD_TX_ROUTE; - resetNode.txMsg.node = node; - resetNode.txMsg.tasks = 0x0; - resetNode.txMsg.cmd = RAC_RESET_SLAVE; - resetNode.txMsg.data = &resetNodeData; - - qBBReq(&resetNode, 0); - semTake(syncSem, WAIT_FOREVER); - semGive(monLock); - - return(0); -} - /****************************************************************** - * FUNCTION: pepRxTask() - * PURPOSE : This function is started as a task during driver init - * time. It's purpose is to read messages off the receive - * FIFO. After a complete message is read, the soliciting - * message's completion routines are started by the use - * of semaphores and/or a callbackRequest(). - * ARGS IN : link - * ARGS OUT: none - * GLOBALS: none - ******************************************************************/ -STATIC int -pepRxTask(int link) -{ - int rxState; /* current state of the receiver */ -#define BBRX_HEAD 1 -#define BBRX_DATA 2 -#define BBRX_RCMD 3 -#define BBRX_IGN 4 - - unsigned char rxHead[7]; /* room for header of current rx msg */ - unsigned char *rxMsg; /* where to place next byte (after header) */ - int rxTCount; /* byte counter for data in rxHead */ - unsigned char ch; - struct dpvtBitBusHead *rxDpvtHead; /* for message currently receiving */ - - struct dpvtBitBusHead UselessMsg; /* to hold unsolicited responses */ - unsigned char UselessData[BB_MAX_MSG_LENGTH]; - - int lockKey; /* used for intLock calls */ - int packageComplete; /* indicates end of package read */ - - rxMsg = (unsigned char *) NULL; - rxState = BBRX_HEAD; - rxTCount = 0; - rxDpvtHead = (struct dpvtBitBusHead *) NULL; - packageComplete = 0; - - /* Dummy up the UselessMsg fields so we can use it */ - UselessMsg.rxMaxLen = BB_MAX_MSG_LENGTH; - UselessMsg.rxMsg.data = UselessData; - UselessMsg.link = link; - UselessMsg.ageLimit = 0; - UselessMsg.retire = 0; - - while (1) - { - /* Wait for RX interrupts, but only if no chars are ready */ - if ((pBBLink[link]->l.PepLink.bbRegs->stat_ctl & PEP_BB_RFNE) == 0) - { - /* Enable interrupts and check again in case PB-BIT blew it */ - lockKey = intLock(); - pBBLink[link]->l.PepLink.bbRegs->int_vec = PEP_BB_IVEC_BASE +(link*2); - intUnlock(lockKey); - - while (((pBBLink[link]->l.PepLink.bbRegs->stat_ctl & PEP_BB_RFNE) == 0) - && (pBBLink[link]->abortFlag == 0)) - { - /* Re-enable ints here each time in case board got reset */ - lockKey = intLock(); - pBBLink[link]->l.PepLink.bbRegs->int_vec = PEP_BB_IVEC_BASE +(link*2); - intUnlock(lockKey); - - if (bbDebug>35) - printf("pepRxTask(%d): waiting on IRQ\n", link); - - /* wait for data bytes */ - semTake(pBBLink[link]->l.PepLink.rxInt, WAIT_FOREVER); - } - /* Disable RX Interrupts (prevents unnecessary context switching) */ - lockKey = intLock(); - pBBLink[link]->l.PepLink.bbRegs->int_vec = 0; - intUnlock(lockKey); - } - - if (pBBLink[link]->abortFlag == 0) - { - /* READ ONE CHAR FROM RECEIVE FIFO */ - ch = pBBLink[link]->l.PepLink.bbRegs->data; - - /* check to see if we got a data byte or a command byte */ - if ((pBBLink[link]->l.PepLink.bbRegs->stat_ctl & PEP_BB_RCMD) == PEP_BB_RCMD) - packageComplete = 1; - - switch (rxState) { - case BBRX_HEAD: /* getting the head of a new message */ - if (rxTCount > 1) /* Toss the 2 PEP specific header bytes */ - rxHead[rxTCount] = ch; - if (bbDebug>21) - printf("pepRxTask(%d): >%2.2X< (Header)\n", link, ch); - - if (++rxTCount == 7) - { - /* find the message this is a reply to */ - /* rxTCount += 2; PEP header bytes already messed up the count (jrw)*/ - - /* Lock the busy list */ - semTake(pBBLink[link]->busyList.sem, WAIT_FOREVER); - - rxDpvtHead = pBBLink[link]->busyList.head; - while (rxDpvtHead != NULL) { - if (bbDebug>19) - printf("pepRxTask(%d): checking reply against %p\n", - link, rxDpvtHead); - - /* see if node's match */ - if (rxDpvtHead->txMsg.node == rxHead[4]) { - /* see if the tasks match */ - /* if (rxDpvtHead->txMsg.tasks == rxHead[5]) */ - { - /* They match, finish putting response into the rxMsg buffer */ - if (bbDebug>4) - printf("pepRxTask(%d): reply to %p\n", - link, rxDpvtHead); - - /* Delete the node from the list */ - listDel(&(pBBLink[link]->busyList), rxDpvtHead); - - /* If busy list is empty, stop the dog */ - if (pBBLink[link]->busyList.head == NULL) - wdCancel(pBBLink[link]->watchDogId); - - if (rxHead[6] == 0x91) - { /* something bad happened... inject a delay to the */ - /* requested timeout duration. */ - - if ((link == bbErrorTrigLink) && - ((bbErrorTrigNode < 0) || (bbErrorTrigNode == rxHead[2]))) - pulseSysMon(); - - /* keep track of timeouts per node */ - if(rxHead[4] < BB_NUM_NODES) { - bbNode91[link][rxHead[4]]++; - } - - if (bbDebug) - printf("pepRxTask(%d): 0x91 from node %d, invoking synthetic delay\n", link, rxHead[4]); - (pBBLink[link]->syntheticDelay[rxDpvtHead->txMsg.node]) = rxDpvtHead->retire; - pBBLink[link]->DelayCount++; - } - else - { /* decrement the number of outstanding messages to the node */ - (pBBLink[link]->deviceStatus[rxDpvtHead->txMsg.node])--; - } - - /* Wake up Link Task in case was waiting on "this" node */ - semGive(pBBLink[link]->linkEventSem); -#if 0 - semGive(pXvmeLink[link]->pbbLink->busyList.sem); - - rxDpvtHead->rxMsg.length = rxHead[2]; - rxDpvtHead->rxMsg.route = rxHead[3]; - rxDpvtHead->rxMsg.node = rxHead[4]; - rxDpvtHead->rxMsg.tasks = rxHead[5]; - rxDpvtHead->rxMsg.cmd = rxHead[6]; - rxMsg = rxDpvtHead->rxMsg.data; - - rxDpvtHead->status = BB_OK; /* OK, unless BB_LENGTH */ - rxState = BBRX_DATA; /* finish reading till RCMD */ -#endif - break; /* get out of the while() */ - } - } - rxDpvtHead = rxDpvtHead->next; /* Keep looking */ - } - - semGive(pBBLink[link]->busyList.sem); - - /* Couldn't find a match... fake one so can print the bad message */ - if (rxDpvtHead == NULL) - rxDpvtHead = &UselessMsg; - - rxDpvtHead->rxMsg.length = rxHead[2]; - rxDpvtHead->rxMsg.route = rxHead[3]; - rxDpvtHead->rxMsg.node = rxHead[4]; - rxDpvtHead->rxMsg.tasks = rxHead[5]; - rxDpvtHead->rxMsg.cmd = rxHead[6]; - rxMsg = rxDpvtHead->rxMsg.data; - - rxDpvtHead->status = BB_OK; /* OK, unless BB_LENGTH */ - rxState = BBRX_DATA; /* finish reading till RCMD */ - } - break; - - case BBRX_DATA: /* finish reading data portion of message */ - if (rxTCount >= rxDpvtHead->rxMaxLen) { - rxState = BBRX_IGN; /* toss the rest of the data */ - rxDpvtHead->status = BB_LENGTH; /* set driver status */ - if (bbDebug>22) - printf("pepRxTask(%d): %2.2X (Ignored)\n", link, ch); - - } - else { - *rxMsg = ch; - if (bbDebug>22) - printf("pepRxTask(%d): %2.2X (Data)\n", link, ch); - rxMsg++; - rxTCount++; - } - break; - - case BBRX_IGN: - if (bbDebug>22) - printf("pepRxTask(%d): %2.2X (Ignored)\n", link, ch); - break; - } - - if (packageComplete) - { - if (rxDpvtHead == NULL) - { - if (bbDebug > 22) - printf("pepRxTask(%d): got unexpected completion status\n", link); -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, NULL, XACT_HIST_STATE_RX_URCMD); -#endif - } - else if (rxDpvtHead == &UselessMsg) - { - rxDpvtHead->status = BB_OK; - if (bbDebug) - { - printf("pepRxTask(%d): msg from node %d unsolicited:\n", link, rxDpvtHead->rxMsg.node); - drvBitBusDumpMsg(&(rxDpvtHead->rxMsg)); - } -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, rxDpvtHead, XACT_HIST_STATE_RX_UNSOLICITED); -#endif - } - else - { - rxDpvtHead->status = BB_OK; - if (bbDebug>24) - printf("pepRxTask(%d): RX command byte = %2.2X\n", link, ch); - -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, rxDpvtHead, XACT_HIST_STATE_RX); -#endif - - if (rxDpvtHead->finishProc != NULL) - { - if (bbDebug>8) - printf("pepRxTask(%d): invoking the callbackRequest\n", link); - callbackRequest(rxDpvtHead); /* schedule completion processing */ - } - else - { - /* If there is a semaphore for synchronous I/O, unlock it */ - if (rxDpvtHead->psyncSem != NULL) - semGive(*(rxDpvtHead->psyncSem)); - } - } - /* Reset the state of the RxTask to expect a new message */ - rxMsg = (unsigned char *) NULL; - rxState = BBRX_HEAD; - rxTCount = 0; - rxDpvtHead = (struct dpvtBitBusHead *) NULL; - packageComplete = 0; - } - } - else - { - /* Link abort state is active reset receiver link status now */ - if (rxDpvtHead != NULL) - { - /* This xact is not on the busy list, put it back on */ - semTake(pBBLink[link]->busyList.sem, WAIT_FOREVER); - (pBBLink[link]->deviceStatus[rxDpvtHead->txMsg.node])++; - listAddTail(&(pBBLink[link]->busyList), rxDpvtHead); - semGive(pBBLink[link]->busyList.sem); - } -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, rxDpvtHead, XACT_HIST_STATE_RX_ABORT); -#endif - - rxMsg = (unsigned char *) NULL; - rxState = BBRX_HEAD; - rxTCount = 0; - rxDpvtHead = (struct dpvtBitBusHead *) NULL; - - /* Tell the watch dog I am ready for the reset (reset in the dog task) */ - pBBLink[link]->rxAbortAck = 1; - - if (bbDebug) - printf("pepRxTask(%d): resetting due to abort status\n", link); - - /* wait for link state to become active again */ - while (pBBLink[link]->abortFlag != 0) - taskDelay(RESET_POLL_TIME); - - if (bbDebug) - printf("pepRxTask(%d): restarting after abort\n", link); - } - } -} - -/****************************************************************** - * FUNCTION: pepWdTask() - * PURPOSE : - * - * ARGS IN : none - * ARGS OUT: none - * GLOBALS: none - ******************************************************************/ -STATIC int pepWdTask(int link) -{ - struct dpvtBitBusHead *pnode; - struct dpvtBitBusHead *npnode; - unsigned long now; - -#ifdef PEP_DO_RESET_AND_OFFLINE - SEM_ID syncSem; - - struct dpvtBitBusHead resetNode; - unsigned char resetNodeData; /* 1-byte data field for RAC_RESET */ - unsigned char responseData; - - struct dpvtBitBusHead offlnNode; - unsigned char offlnNodeData; /* 1-byte data field for RAC_OFFLN */ - unsigned char response1Data; /* 1-byte response data field */ - - /* init the SEM used when sending the RAC_OFFLNE message */ - syncSem = semBCreate(SEM_Q_PRIORITY,SEM_EMPTY); - - /* - * Hand-craft a RAC_RESET and RAC_OFFLINE message to use when - * a message times out. - * NOTE that having only one copy is OK provided that the dog waits for - * a response before sending it again! - */ - resetNode.finishProc = NULL; /* no callback routine used */ - resetNode.psyncSem = NULL; - resetNode.link = link; /* which bitbus link to send message out on */ - resetNode.rxMaxLen = 10; - resetNode.ageLimit = sysClkRateGet()*100; /* make sure this never times out */ - - resetNode.txMsg.length = 8; - resetNode.txMsg.route = BB_STANDARD_TX_ROUTE; - resetNode.txMsg.tasks = 0x0; - resetNode.txMsg.data = &resetNodeData; - resetNode.rxMsg.data = &responseData; - - offlnNode.finishProc = NULL; /* no callback routine used */ - offlnNode.psyncSem = &syncSem;/* do a semGive on this SEM when responded to*/ - offlnNode.link = link; /* which bitbus link to send message out on */ - offlnNode.rxMaxLen = 10; - offlnNode.ageLimit = sysClkRateGet()*100; /* make sure this never times out */ - - offlnNode.txMsg.length = 8; - offlnNode.txMsg.route = BB_STANDARD_TX_ROUTE; - offlnNode.txMsg.tasks = 0x0; - offlnNode.txMsg.data = &offlnNodeData; - offlnNode.rxMsg.data = &response1Data; -#endif - - pBBLink[link]->nukeEm = 0; /* Make sure the nuke status is clear */ - while(1) { - /* SLEEP UNTIL WATCHDOG TIMER ROUTINE GIVES SEMAPHORE */ - semTake(pBBLink[link]->watchDogSem, WAIT_FOREVER); - now = tickGet(); /* what time is it? */ - - if (pBBLink[link]->nukeEm != 0) - printf("Bitbus manual reset being issued on link %d\n", link); - - if (bbDebug>4) - printf("pepWdTask(%d): (Watchdog) checking busy list\n", link); - - pBBLink[link]->rxAbortAck = 0; - pBBLink[link]->txAbortAck = 0; - - if (pBBLink[link]->nukeEm != 0) { - /* set abort status and wait for the abort acks */ - pBBLink[link]->abortFlag = 1; - - /* wake up the Tx task so it can observe the abort status */ - semGive(pBBLink[link]->linkEventSem); - - /* wake up the Rx task so it can observe the abort status */ - semGive(pBBLink[link]->l.PepLink.rxInt); - - /* sleep until abort ack from Tx & Rx tasks */ - while ((pBBLink[link]->rxAbortAck == 0) && - (pBBLink[link]->txAbortAck == 0)) - taskDelay(RESET_POLL_TIME); - -#ifdef BB_SUPER_DEBUG - if (pBBLink[link]->nukeEm < 2) - { /* Do a history dump since this is not supposed to happen */ - BBHistDump(link); - } -#endif - } - /* - * Run thru entire busy list to see if there are any transactions - * that have been waiting on a response for too long a period. - */ - semTake(pBBLink[link]->busyList.sem, WAIT_FOREVER); - pnode = pBBLink[link]->busyList.head; - - while (pnode != NULL) { - npnode = pnode->next; /* remember where we were in the list */ - - if ((pBBLink[link]->nukeEm != 0) || (pnode->retire <= now)) { - /* Get rid of the request and set error status etc... */ - listDel(&(pBBLink[link]->busyList), pnode); - -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, pnode, XACT_HIST_STATE_WD_TIMEOUT); -#endif - if (bbDebug) - { - printf("pepWdTask(%d): TIMEOUT on bitbus message:\n", link); - drvBitBusDumpMsg(&pnode->txMsg); - } - - if(pnode->txMsg.node < BB_NUM_NODES) { - bbNodeTMO[link][pnode->txMsg.node]++; - } - - /* BUG -- do this here or defer until RX gets a response? */ - (pBBLink[link]->deviceStatus[pnode->txMsg.node])--; /* fix device status */ - pnode->status = BB_TIMEOUT; - -#ifdef PEP_DO_RESET_AND_OFFLINE - /* Gotta do this now in case we need the info after the completion */ - resetNode.txMsg.node = pnode->txMsg.node; - offlnNodeData = pnode->txMsg.node; /* mark the node number */ -#endif - /* Make the callbackRequest if one was spec'd */ - if(pnode->finishProc != NULL) - { - if (bbDebug>2) - { - printf("pepWdTask(%d): invoking the callbackRequest %p %d\n", link, pnode->finishProc, pnode->priority); - } - callbackRequest(pnode); /* schedule completion processing */ - } - else - { - /* Release a completion lock if one was spec'd */ - if (pnode->psyncSem != NULL && pBBLink[link]->nukeEm == 0) - semGive(*(pnode->psyncSem)); - } - -#ifdef PEP_DO_RESET_AND_OFFLINE - /* If we are not going to reboot the link... */ - if ( pBBLink[link]->nukeEm == 0 ) { - /* Send out a RAC_RESET/RAC_OFFLINE pair */ - semGive(pBBLink[link]->busyList.sem); - - /* Configure message for a RAC_RESET */ - resetNode.txMsg.cmd = 0x00; - - /* Configure message for a RAC_OFFLINE */ - offlnNode.txMsg.cmd = RAC_OFFLINE; - offlnNode.txMsg.node = 0xff; - - /* Queue the messages (high priority, reset first) */ - - semTake(pBBLink[link]->queue[BB_Q_HIGH].sem, WAIT_FOREVER); - listAddHead(&(pBBLink[link]->queue[BB_Q_HIGH]), &offlnNode); -/* listAddHead(&(pBBLink[link]->queue[BB_Q_HIGH]), &resetNode); */ - semGive(pBBLink[link]->queue[BB_Q_HIGH].sem); - - semGive(pBBLink[link]->linkEventSem); /* Tell TxTask to send the messages */ - - if (semTake(syncSem, (sysClkRateGet()) ) == ERROR) - { - if (bbDebug) - printf("pepWdTask(%d): link dead, trying manual reboot\n", link); - - pBBLink[link]->nukeEm = 1; - pBBLink[link]->abortFlag = 1; - semGive(pBBLink[link]->linkEventSem); - semGive(pBBLink[link]->rxInt); - - /* sleep until abort ack from Tx & Rx tasks */ - while ((pBBLink[link]->rxAbortAck == 0) && - (pBBLink[link]->txAbortAck == 0)) - taskDelay(RESET_POLL_TIME); - } - - /* Start over since released the busy list */ - semTake(pBBLink[link]->busyList.sem, WAIT_FOREVER); - npnode = pBBLink[link]->busyList.head; - } -#endif - - } - pnode = npnode; - } - - /* Finish the link reboot if necessary */ - if (pBBLink[link]->nukeEm != 0) - { - /* shut down the bitbus card. */ - pepReset(link); - - if (pBBLink[link]->nukeEm == 2) - { - /* - * Stop the watchdog task so the link stays dead. - * Since the busy list is locked and the nukeEm flag is still set, - * this link can not do any more work. - */ - abort(); - } - - /* clear the abort_flag */ - pBBLink[link]->abortFlag = 0; - - pBBLink[link]->nukeEm = 0; - } - - if (pBBLink[link]->busyList.head != NULL) { - /* Restart the dog timer */ - if (bbDebug>5) - printf("pepWdTask(%d): restarting watch dog timer\n", link); - - wdStart(pBBLink[link]->watchDogId, pBBLink[link]->busyList.head->retire - now, - pepTmoHandler, link); - } - - semGive(pBBLink[link]->busyList.sem); - - /* In case the TX is waiting on a node that just timed out */ - semGive(pBBLink[link]->linkEventSem); - } -} - -/****************************************************************** - * FUNCTION: pepTxTask() - * PURPOSE : This function is started as a task during driver init - * time. It's purpose is to keep the link busy with - * outgoing messages. It awaits user-calls to qBBReq() - * (new message to send). It also awaits wake up calls - * from the Wd timer (a timed out message to a node, - * once handled, means Tx is free to send again to that - * node). - * - * ARGS IN : link - * ARGS OUT: none - * GLOBALS: none - ******************************************************************/ -STATIC int pepTxTask(int link) -{ - struct dpvtBitBusHead *pnode; - int prio; - int working; - int dogStart; - int stuck; - - int txTCount; - int txCCount; - unsigned char *txMsg; - register int x; - unsigned long now; - - if (bbDebug>1) - printf("pepTxTask started for link %d\n", link); - - while(1) { - if (pBBLink[link]->abortFlag != 0) { - /* let the dog know we are ready */ - pBBLink[link]->txAbortAck = 1; - -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, NULL, XACT_HIST_STATE_TX_ABORT); -#endif - - if (bbDebug) - printf("pepTxTask(%d): resetting due to abort status\n", link); - - while (pBBLink[link]->abortFlag != 0) - taskDelay(RESET_POLL_TIME); /* wait for link to reset */ - - if (bbDebug) - printf("pepTxTask(%d): restarting after abort\n", link); - } - else - { - if (pBBLink[link]->DelayCount) - semTake(pBBLink[link]->linkEventSem, 2 * sysClkRateGet()); - else - semTake(pBBLink[link]->linkEventSem, WAIT_FOREVER); - } - - if (bbDebug>5) - printf("pepTxTask(%d): got an event\n", link); - - working = 1; - while ((working != 0) && (pBBLink[link]->abortFlag == 0) && - (pBBLink[link]->busyList.elements < PepMaxOutstandMsgs)) { - working = 0; - - prio = BB_NUM_PRIO-1; - while ((prio >= 0) && (pBBLink[link]->abortFlag == 0)) { - /* see if the queue has anything in it */ - semTake(pBBLink[link]->queue[prio].sem, WAIT_FOREVER); - - if ((pnode = pBBLink[link]->queue[prio].head) != NULL) - { - now = tickGet(); - while (pBBLink[link]->deviceStatus[pnode->txMsg.node] == BB_BUSY) - { - if ((pBBLink[link]->syntheticDelay[pnode->txMsg.node] != 0) - && (pBBLink[link]->syntheticDelay[pnode->txMsg.node] < now)) - { - if (bbDebug) - printf("pepTxTask(%d): terminating synthetic idle on node %d\n", link, pnode->txMsg.node); - (pBBLink[link]->deviceStatus[pnode->txMsg.node])--; - pBBLink[link]->syntheticDelay[pnode->txMsg.node] = 0; - pBBLink[link]->DelayCount--; - } - else - { - if ((pnode = pnode->next) == NULL) - break; - } - } - } - - /* Start of unpleasant patch. - Create an artificial delay to prevent back-to-back message - loading of the PEP FIFO, since this has proven to induce protocol - errors. - */ - if (PepLinkLoadDelay > 0) { - for (x=0 ; x < PepLinkLoadDelay ; x++); - } - /* End unpleasant patch */ - - if (pnode != NULL) { /* have an xact to start processing */ - working = 1; - - /* delete the node from the inbound fifo queue */ - listDel(&(pBBLink[link]->queue[prio]), pnode); - - semGive(pBBLink[link]->queue[prio].sem); -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, pnode, XACT_HIST_STATE_TX); -#endif - - - if (bbDebug>3) - printf("pepTxTask(%d): got xact, pnode=%p\n", link, pnode); - - /* Send the message in polled mode */ - txTCount = pnode->txMsg.length; - - /* BUG -- would be nice if we verify the length >6 here */ - - txCCount = 0; - txMsg = &(pnode->txMsg.length); - - while ((txCCount < txTCount -1) && (pBBLink[link]->abortFlag == 0)) { - - stuck = 1000; - while (((pBBLink[link]->l.PepLink.bbRegs->stat_ctl & PEP_BB_TFNF) - != PEP_BB_TFNF) && - (pBBLink[link]->abortFlag == 0) && - --stuck) - for(x=0;x<100;x++); /* wait for TX ready */ - - if (!stuck) - { -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, pnode, XACT_HIST_STATE_TX_STUCK); -#endif - txStuck(link); - } - else if (txCCount == 0) { /* first byte is package type */ - if (bbDebug>30) - printf("pepTxTask(%d): outputting %2.2X\n",link,0x81); - pBBLink[link]->l.PepLink.bbRegs->data = 0x81; - } - else if (txCCount == 1) { /* unused 2nd byte of package */ - if (bbDebug>30) - printf("pepTxTask(%d): outputting %2.2X\n",link,0x00); - pBBLink[link]->l.PepLink.bbRegs->data = 0x00; -#if 0 - } else if (txCCount == (txTCount -1)) { /* last byte of package */ - pBBLink[link]->l.PepLink.bbRegs->stat_ctl = *txMsg; - if (bbDebug>30) - printf("pepTxTask(%d): outputting last byte %2.2X\n", - link,*txMsg); -#endif - } else { /* regular ol' message byte */ - pBBLink[link]->l.PepLink.bbRegs->data = *txMsg; - if (bbDebug>30) - printf("pepTxTask(%d): outputting %2.2X\n",link,*txMsg); - if (txCCount != 6) - txMsg++; - else - txMsg = pnode->txMsg.data; - } - txCCount++; - } - - if (pBBLink[link]->abortFlag == 0) { - - /* don't add to busy list if was a RAC_RESET_SLAVE */ - if ((pnode->txMsg.cmd == RAC_RESET_SLAVE) && (pnode->txMsg.tasks == 0)) - { -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, pnode, XACT_HIST_STATE_TX_RESET); -#endif - if (bbDebug) - printf("pepTxTask(%d): RAC_RESET_SLAVE sent\n", link); - - pBBLink[link]->l.PepLink.bbRegs->stat_ctl = *txMsg; - if (bbDebug>30) - printf("pepTxTask(%d): outputting last byte %2.2X\n", - link,*txMsg); - - pnode->status = BB_OK; - - if (pnode->finishProc != NULL) { - if (bbDebug>4) - printf("pepTxTask(%d): invoking the callbackRequest\n", - link); - callbackRequest(pnode); /* schedule completion processing */ - } - else - { - /* If there is a semaphore for synchronous I/O, unlock it */ - if (pnode->psyncSem != NULL) - semGive(*(pnode->psyncSem)); - } - taskDelay(15); - } - else - { - /* Lock the busy list */ - semTake(pBBLink[link]->busyList.sem, WAIT_FOREVER); - - pBBLink[link]->l.PepLink.bbRegs->stat_ctl = *txMsg; - if (bbDebug>30) - printf("pepTxTask(%d): outputting last byte %2.2X\n", - link,*txMsg); - - /* set the retire time */ - pnode->retire = tickGet(); - if (pnode->ageLimit) - pnode->retire += pnode->ageLimit; - else - pnode->retire += BB_DEFAULT_RETIRE_TIME * sysClkRateGet(); - - if (pBBLink[link]->busyList.head == NULL) - dogStart = 1; - else - dogStart = 0; - - /* Add pnode to the busy list */ - listAddTail(&(pBBLink[link]->busyList), pnode); - - /* Count the outstanding messages */ - (pBBLink[link]->deviceStatus[pnode->txMsg.node])++; - - semGive(pBBLink[link]->busyList.sem); - - /* If something just added to empty busy list, start the dog */ - if (dogStart) { - now = tickGet(); - wdStart(pBBLink[link]->watchDogId, - pBBLink[link]->busyList.head->retire - now, - pepTmoHandler, link); - } - } - } else { /* if abortFlag != 0 */ - /* Aborted transmission operation, re-queue the message */ - semTake(pBBLink[link]->queue[BB_Q_HIGH].sem, WAIT_FOREVER); - listAddHead(&(pBBLink[link]->queue[BB_Q_HIGH]), pnode); - semGive(pBBLink[link]->queue[BB_Q_HIGH].sem); -#ifdef BB_SUPER_DEBUG - BBSetHistEvent(link, pnode, XACT_HIST_STATE_TX_ABORT); -#endif - } - - } else { /* if pnode == NULL */ - /* we have no xacts that can be processed at this time */ - semGive(pBBLink[link]->queue[prio].sem); - } - prio--; /* look at the next prio queue */ - } - } - } -} - /****************************************************************** - * FUNCTION: dumpStat() - * PURPOSE : Temporary function. Shows contents of status - * register on PB-BIT module corresponding to link. - * ARGS IN : link - * ARGS OUT: none - * GLOBALS: none - ******************************************************************/ -int pepDumpStat(int link) -{ - unsigned char stat_ctl; - - stat_ctl = pBBLink[link]->l.PepLink.bbRegs->stat_ctl; - - printf("stat_ctl reg: %2X\n",stat_ctl); - return(OK); -} - -/* pulseSysMon.c */ -/* Function for pulsing a bit on System Monitor Board */ -/* TEMPORARY ROUTINE TO FIND BITBUS PROBLEMS*/ -typedef struct SysmonStruct { - char Pad[36]; /*** nF0 - nF17 36 bytes ***/ - unsigned short SysmonStatusLink; /*** nF18 ***/ - unsigned short SysmonDio; /*** nF19 ***/ - unsigned short SysmonIntMask; /*** nF20 ***/ - unsigned short SysmonTemperature; /*** nF21 ***/ - unsigned short SysmonWatchdog; /*** nF22 ***/ - unsigned short SysmonVXIVector; /*** nF23 ***/ - unsigned short SysmonIntVector; /*** nF24 ***/ - unsigned short SysmonIRQ1; /*** nF25 ***/ - unsigned short SysmonIRQ2; /*** nF26 ***/ - unsigned short SysmonIRQ3; /*** nF27 ***/ - unsigned short SysmonIRQ4; /*** nF28 ***/ - unsigned short SysmonIRQ5; /*** nF29 ***/ - unsigned short SysmonIRQ6; /*** nF30 ***/ - unsigned short SysmonIRQ7; /*** nF31 ***/ -} SysmonStruct; - -int bitbusTriggerWidth = 1500; - -long pulseSysMon() { - volatile SysmonStruct *SysmonBase; - volatile unsigned short *pReg; - int i; - unsigned short probeVal; - volatile int j = 0; - - if (sysBusToLocalAdrs(VME_AM_SUP_SHORT_IO, (char *)0x8b80, - (char **)&(SysmonBase)) == ERROR) { - printf("can't convert to local address, aborting\n"); - return(1); - } - pReg = &(SysmonBase->SysmonDio); - - if(bbDebug) printf("Error Trigger\n"); - - probeVal = 0xffff; - vxMemProbe((char*) pReg, WRITE, 2, (char*)&probeVal); - for (i=0 ; i < bitbusTriggerWidth ; i++) { - j++; - j--; - } - probeVal = 0x0000; - vxMemProbe((char*) pReg, WRITE, 2, (char*)&probeVal); - - return(0); -} - - -long bbDump() { - int i,j; - - for (j=0; jinp.type) { - case (VME_IO) : - if(pwf->inp.value.vmeio.card >= BB_NUM_LINKS) { - epicsPrintf("%s.INP >> card number invalid\n", pwf->name); - pwf->pact = 1; /* don't allow processing */ - return -1; - } - if(pwf->ftvl != menuFtypeUSHORT) { - epicsPrintf("%s.FTVL >> expected USHORT \n", pwf->name); - pwf->pact = 1; /* don't allow processing */ - return -1; - } - pwf->nord = 0; - break; - default : - epicsPrintf("%s.INP >> expected VME_IO INP field\n", pwf->name); - pwf->pact = 1; /* don't allow processing */ - return -1; - } - return(0); -} - - -static long read_91s(pwf) - struct waveformRecord *pwf; -{ - long nRequest = BB_NUM_NODES; - - if(pwf->nelm < BB_NUM_NODES) nRequest = pwf->nelm; - - memcpy( pwf->bptr, (void *)&bbNode91[pwf->inp.value.vmeio.card][0], - nRequest * 2); - - pwf->nord = nRequest; - - return(0); -} - -static long read_TMOs(pwf) - struct waveformRecord *pwf; -{ - long nRequest = BB_NUM_NODES; - - if(pwf->nelm < BB_NUM_NODES) nRequest = pwf->nelm; - - memcpy( pwf->bptr, (void *)&bbNodeTMO[pwf->inp.value.vmeio.card][0], - nRequest * 2); - - pwf->nord = nRequest; - - return(0); -} - - -static long init_bo_record(pbo) - struct boRecord *pbo; -{ - - - /* bo.out must be a VME_IO type such that Cx indicates the bitbus link - * that isdesired to be cleared. - */ - switch (pbo->out.type) { - case (VME_IO) : - if(pbo->out.value.vmeio.card >= BB_NUM_LINKS) { - epicsPrintf("%s.OUT >> card number invalid\n", pbo->name); - pbo->pact = 1; /* don't allow processing */ - return -1; - } - break; - default : - epicsPrintf("%s.OUT >> expected VME_IO type\n", pbo->name); - pbo->pact = 1; /* don't allow processing */ - return -1; - } - return(0); -} - - -static long clear_stats(pbo) - struct boRecord *pbo; -{ - int i; - - if(pbo->out.value.vmeio.card < BB_NUM_LINKS) { - for (i=1;iout.value.vmeio.card][i] = 0; - bbNode91[pbo->out.value.vmeio.card][i] = 0; - } - } - else { - epicsPrintf("%s.OUT >> card number invalid\n", pbo->name); - } - - return(0); -} - diff --git a/src/drv/old/drvBitBus.h b/src/drv/old/drvBitBus.h deleted file mode 100644 index 23ae80a18..000000000 --- a/src/drv/old/drvBitBus.h +++ /dev/null @@ -1,279 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -#ifndef EPICS_DRVBITBUS_H -#define EPICS_DRVBITBUS_H - -/* #define BB_SUPER_DEBUG */ - -/* - * Author: John Winans - * Date: 09-10-91 - * BitBus driver - */ - -/***************************************************************************** - * - * This history stuff below is used to save the recent history of operation. - * This history includes dumps of messages that are queued, transmitted and - * received. This information is saved along with the relative tick time. - * - *****************************************************************************/ -#ifdef BB_SUPER_DEBUG -#define BB_SUPER_DEBUG_HIST_SIZ 50 /* How many messages to save */ - -typedef struct XactHistStruct -{ - struct dpvtBitBusHead Xact; /* BB message operated on */ - unsigned long Time; /* getTick() when operated on */ - int State; /* What was being done to the message */ -} XactHistStruct; - -#define XACT_HIST_STATE_QUEUE 0 /* Some task queued a transaction */ -#define XACT_HIST_STATE_TX 1 /* Transmitter sent a transaction */ -#define XACT_HIST_STATE_RX 2 /* Receiver received a response */ -#define XACT_HIST_STATE_WD_TIMEOUT 3 /* Watchdog times out a transaction */ -#define XACT_HIST_STATE_RESET 4 /* No message... link was reset */ -#define XACT_HIST_STATE_RX_UNSOLICITED 5 /* RX'd message not solicited */ -#define XACT_HIST_STATE_RX_ABORT 6 /* RX task got a link about status */ -#define XACT_HIST_STATE_TX_ABORT 7 /* TX task got a link about status */ -#define XACT_HIST_STATE_RX_URCMD 8 /* RX task got unsolicited RCMD */ -#define XACT_HIST_STATE_TX_RESET 9 /* TX task got a link about status */ -#define XACT_HIST_STATE_TX_STUCK 10 /* TX fifo is stuck on the 8044 */ - -/* One of these is allocated for each bitbus link */ -typedef struct HistoryStruct -{ - SEM_ID sem; /* Use when 'making' history */ - XactHistStruct Xact[BB_SUPER_DEBUG_HIST_SIZ]; - int Next; /* Next history slot to use */ - unsigned long Num; /* Total history messages */ -} HistoryStruct; - -static int BBSetHistEvent(int link, struct dpvtBitBusHead *pXact, int State); -#endif - - -/****************************************************************************** - * - * The BUSY/IDLE notion is used to count the number of outstanding - * messages for a specific node. The idea is that up to BUSY messages - * can be sent to a node before waiting before deciding not to send any more. - * According to the BitBus specs, this value is 7. However, it also - * states that responses can come back out of order. If this is even true - * for messages sent to the SAME TASK ON THE SAME NODE, the received messages - * CAN NOT be routed back to their initiators properly. Because the node# - * and task# is all we have to identify what a response message is for, - * I am limiting the per-node maximum to 1. - * - ******************************************************************************/ - -#define BB_BUSY 1 /* deviceStatus value if device is currently busy */ -#define BB_IDLE 0 /* deviceStatus value if device is currently idle */ - -/****************************************************************************** - * - * This list structure is used in the bitbus driver to represent its queues. - * - ******************************************************************************/ -struct bbList { - struct dpvtBitBusHead *head; /* head of the linked list */ - struct dpvtBitBusHead *tail; /* tail of the linked list */ - int elements; /* holds number of elements on the list */ - SEM_ID sem; /* semaphore for the queue list */ -}; - /***************************************************************************** - * Memory Map of XVME-402 BITBUS CARD - * - * This board is rather stupid in that it wastes a whole Kilo of space - * for its 5 1-byte regs. So the dm* fields in the structure below are - * for those filler locations. - * - *****************************************************************************/ -typedef struct XycomBBRegsStruct { - unsigned char dm0; - unsigned char stat_ctl; - unsigned char dm2; - unsigned char int_vec; - unsigned char dm4; - unsigned char data; - unsigned char dm6; - unsigned char cmnd; - unsigned char dm8; - unsigned char fifo_stat; - unsigned char dmA[1014]; /* Board occupies 1024 bytes in memory*/ -} XycomBBRegsStruct; - -#define XYCOM_BB_MAX_OUTSTAND_MSGS 4 /* per-link max pending messages */ -#define RESET_POLL_TIME 10 /* time to sleep when waiting on a link abort */ - -#define BB_SEND_CMD 0x0 /* command to initiate sending of msg */ - -#define XVME_ENABLE_INT 0x08 /* Allow xvme interupts */ - -#define XVME_TX_INT 0x20 /* int enable TX only */ -#define XVME_TX_PEND 0x10 /* transmit interrupt currently pending */ - -#define XVME_RX_INT 0x80 /* int exable RX only */ -#define XVME_RX_PEND 0x40 /* receive interrupt currently pending */ - -#define XVME_NO_INT 0 /* disable all interrupts */ - -/****************************************************************************** - * - * Fifo status register format for Xycom board - * - * +----+----+----+----+----+----+----+----+ - * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | Bits - * +----+----+----+----+----+----+----+----+ - * "1" "1" RCMD RFNE "1" "1" "1" TFNF data - * - * RCMD = "1"= command received ( end of message ) - * "0"= No command - * - * RFNE = "1" = Receive Fifo Not Empty - * "0" = Receive Fifo empty - * - * TFNF = "1" = Transmit Fifo Not Full - * "0" = transmit fifo full - * - * NOTE: - * A write to bit 7 of the Fifo status register can be used to reset the - * xvme board. - * - *****************************************************************************/ -#define XVME_RCMD 0x20 /* Command has been received */ -#define XVME_RFNE 0x10 /* Receive Fifo is Not Empty */ -#define XVME_TFNF 0x01 /* Transmit FIFO is Not Full */ -#define XVME_FSVALID 0x31 /* these are the only valid status bits */ -#define XVME_FSIDLE 0x01 /* fifo_stat & FSVALID = 0x1 when it is idle */ -#define XVME_RESET 0x80 /* Write this and you reset the XVME card */ - -/****************************************************************************** - * - * The XycomBBLinkStruct structure holds all the xvme-card specific data - * required for the operation of the link. - * - ******************************************************************************/ -typedef struct XycomBBLinkStruct { - volatile XycomBBRegsStruct *bbRegs;/* pointer to board registers */ - SEM_ID rxInt; /* given when rx interrupts occur */ -} XycomBBLinkStruct; - - /**************************************************************************** - * Memory Map of PEP Modular PB-BIT BITBUS CARD - * - * This board is rather stupid in that it wastes a bunch of bytes - * for its regs. So the dm* fields in the structure below are - * for those filler locations. - * - ***************************************************************************/ -typedef struct PepBBRegsStruct { - unsigned char dm0; - unsigned char data; - unsigned char dm2; - unsigned char stat_ctl; - unsigned char dm[29]; - unsigned char int_vec; -} PepBBRegsStruct; - -/****************************************************************************** - * - * status register format for PEP's PB-BIT board - * - * +----+----+----+----+----+----+----+----+ - * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | Bits - * +----+----+----+----+----+----+----+----+ - * X X X STF LBP TFF RFNE IRQP - * - * STF = "1"= self-test failed - * "0"= passed - * - * LBP = "1"= last data byte was last of package - * "0"= 1+ bytes left - * - * TFF = "1"= only one more byte may be written to TFIFO - * "0"= 1+ more bytes may be written - * - * RFNE = "1"= Receive Fifo Not Empty - * "0"= Receive Fifo empty - * - * IRQP = "1"= no irq pending - * "0"= irq pending - * - * - *****************************************************************************/ -#define PEP_BB_RCMD 0x08 /* Command has been received */ -#define PEP_BB_RFNE 0x02 /* Receive Fifo is Not Empty */ -#define PEP_BB_TFNF 0x04 /* Transmit FIFO is Not Full */ -#define PEP_BB_FSVALID 0x1f /* these are the only valid status bits */ - -/****************************************************************************** - * - * The PepBBLinkStruct structure holds all the card specific data required for - * the operation of the link. - * - ******************************************************************************/ -typedef struct PepBBLinkStruct { - - volatile PepBBRegsStruct *bbRegs; /* pointer to board registers */ - SEM_ID rxInt; /* given when rx interrupts occur */ - -} PepBBLinkStruct; - /***************************************************************************** - * - * Holds the user-configured board addresses etc. These MUST be set before - * the driver is initialized. And may not be changed after the init phase. - * - * NOTE: - * The setting of these items is intended to be done via records in the future. - * - * The busyList.sem is used to lock the busyList as well as the deviceStatus - * table. - * - *****************************************************************************/ -typedef struct BitbusLinkStruct -{ - unsigned long LinkType; /* Type of link (XYCOM, PEP,...) */ - unsigned long BaseAddr; /* Base address within A16 */ - unsigned long IrqVector; /* Irq vector base */ - unsigned long IrqLevel; /* Irq level */ - - WDOG_ID watchDogId; /* watchdog for timeouts */ - SEM_ID watchDogSem; /* set by the watch dog int handler */ - - unsigned char abortFlag; /* set to 1 if link is being reset by the dog */ - unsigned char txAbortAck; /* set to 1 by txTask to ack abort Sequence */ - unsigned char rxAbortAck; /* set to 1 by rxTask to ack abort Sequence */ - - int nukeEm; /* manual link restart flag */ - SEM_ID linkEventSem; /* given when this link requires service */ - struct bbList queue[BB_NUM_PRIO]; /* prioritized request queues */ - struct bbList busyList; /* messages waiting on a response */ - unsigned char deviceStatus[BB_APERLINK];/* mark a device as idle or busy */ - unsigned long syntheticDelay[BB_APERLINK]; /* holds the wakeup time for 91-delays */ - int DelayCount; /* holds total number of syntheticDelays in progress */ - - union - { - PepBBLinkStruct PepLink; - XycomBBLinkStruct XycomLink; - } l; - -#ifdef BB_SUPER_DEBUG - HistoryStruct History; -#endif - -} BitbusLinkStruct; - -#define BB_CONF_HOSED 0 /* Link is not present */ -#define BB_CONF_TYPE_XYCOM 1 /* Link is a Xycom board */ -#define BB_CONF_TYPE_PEP 2 /* Link is a PEP board */ - -#endif diff --git a/src/drv/old/drvBitBusErr.h b/src/drv/old/drvBitBusErr.h index 9be688f54..f6b1894f0 100644 --- a/src/drv/old/drvBitBusErr.h +++ b/src/drv/old/drvBitBusErr.h @@ -7,7 +7,9 @@ * and higher are distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ -/* share/src/drv/drvBitBusErr.h $Id$ */ + +/* $Id$ */ + /* Author: John Winans * Date: 12-5-91 */ diff --git a/src/drv/old/drvBitBusInterface.h b/src/drv/old/drvBitBusInterface.h index f15746087..f75a3a140 100644 --- a/src/drv/old/drvBitBusInterface.h +++ b/src/drv/old/drvBitBusInterface.h @@ -7,8 +7,9 @@ * and higher are distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ + /* drvBitBusInterface.h */ -/* share/src/drv %W% %G% */ + /* Author: John Winans * Date: 09-10-91 */ @@ -85,56 +86,6 @@ struct dpvtBitBusHead { #define BB_NONODE 2 /* transmit message to non-existant node */ #define BB_TIMEOUT 3 /* response took too long from node */ -#if 0 /* JRW moved to drvBitbus.h */ -/****************************************************************************** - * - * The BUSY/IDLE notion is used to count the number of outstanding - * messages for a specific node. The idea is that up to BUSY messages - * can be sent to a node before waiting before deciding not to send any more. - * According to the BitBus specs, this value is 7. However, it also - * states that responses can come back out of order. If this is even true - * for messages sent to the SAME TASK ON THE SAME NODE, the received messages - * CAN NOT be routed back to their initiators properly. Because the node# - * and task# is all we have to identify what a response message is for, - * I am limiting the per-node maximum to 1. - * - ******************************************************************************/ - -#define BB_BUSY 1 /* deviceStatus value if device is currently busy */ -#define BB_IDLE 0 /* deviceStatus value if device is currently idle */ - -struct bbList { - struct dpvtBitBusHead *head; /* head of the linked list */ - struct dpvtBitBusHead *tail; /* tail of the linked list */ - int elements; /* holds number of elements on the list */ - SEM_ID sem; /* semaphore for the queue list */ -}; - -/****************************************************************************** - * - * The bbLink structure holds all the required link-specific queueing - * information. - * - ******************************************************************************/ -struct bbLink { - int linkType; /* the type of link (defined in link.h) */ - int linkId; /* the link number of this structure */ - - int nukeEm; /* manual link restart flag */ - - SEM_ID linkEventSem; /* given when this link requires service */ - - struct bbList queue[BB_NUM_PRIO]; /* prioritized request queues */ - - /* - * In order to modify either the busyList entries or the deviceStatus - * table, the busyList.sem MUST be held first. - */ - struct bbList busyList; /* messages waiting on a response */ - unsigned char deviceStatus[BB_APERLINK];/* mark a device as idle or busy */ -}; -#endif - #define BB_STANDARD_TX_ROUTE 0x40 /* Route value for TX message */ #define BB_RAC_TASK 0x00 /* RAC task ID */ @@ -160,7 +111,7 @@ struct bbIdWord { unsigned int taskMods; /* One of BB_MOD_* */ unsigned int revCode; /* Revision code number of the BUG's code */ }; - + /****************************************************************************** * * List of GPIB command definitions (defined by the GPIB-BUG interface spec) @@ -169,7 +120,7 @@ struct bbIdWord { #define BB_232_CMD 0x60 /* or'd with the port number */ #define DD_232_PORT 0x1F /* port number is lowest 5 bits */ #define BB_232_BREAK 0x40 /* or'd with the port number */ - + /****************************************************************************** * * List of GPIB command definitions (defined by the GPIB-BUG interface spec) @@ -206,7 +157,7 @@ struct bbIdWord { #define BB_IBSTAT_EOI 0x20 #define BB_IBSTAT_SRQ 0x10 #define BB_IBSTAT_TMO 0x01 - + /****************************************************************************** * * Partial List of RAC Command Definitions (defined in BitBus Specification) @@ -251,5 +202,9 @@ struct bbIdWord { #define BB_RAC_PROTECTED 0x95 #define BB_UNKNOWN_RAC_CMND 0x96 -#endif +/* A couple of routine definitions */ +int BBConfig(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); +int BBSnoop(int link,int node,int seconds); + +#endif diff --git a/src/drv/old/drvXy010.c b/src/drv/old/drvXy010.c deleted file mode 100644 index d7d953aea..000000000 --- a/src/drv/old/drvXy010.c +++ /dev/null @@ -1,161 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* - * initialize the Xycom SRM010 bus controller card - */ -/* base/src/drv $Id$ */ -/* Author: Jeff Hill - * Date: 06-30-29 - * Initialize xy010 bus controller - */ - -static char *sccsID = "@(#)drvXy010.c 1.3\t6/3/93"; - -#include -#include -#include -#include -#include -#include - -#include -#include - - -/* - * These will hopefully go away - * as the drivers become more autonomous - */ - -static long xy010_id_check(char *); -static long xy010_io_report(int); -static long xy010_init(void); -static long xy010_map(void); - -struct { - long number; - DRVSUPFUN report; - DRVSUPFUN init; -} drvXy010={ - 2, - xy010_io_report, - xy010_init}; - - -#define CSR_ADDR 0x81 -#define XY010_ID "VMEIDXYC010" -#define XY_LED 0x3 /* set the Xycom status LEDs to OK */ - -LOCAL char *xy010_addr; - - -/* - * initialize the Xycom SRM010 bus controller card - */ -long -xy010_init() -{ - char *pctlreg; - - if(xy010_map()<0){ - return ERROR; - } - - if(xy010_id_check(xy010_addr)<0){ - return OK; - } - - /* Pointer to status control register. */ - pctlreg = xy010_addr + CSR_ADDR; - *pctlreg = XY_LED; - - return OK; -} - - -/* - * - * xy010_map() - * - * - */ -LOCAL -long xy010_map() -{ - int status; - - status = sysBusToLocalAdrs( - VME_AM_SUP_SHORT_IO, - xy010ScA16Base, - &xy010_addr); - - if (status < 0){ - printf("%s: xy010 A16 base addr map failed\n", __FILE__); - return ERROR; - } - - return OK; -} - - -/* - * - * xy010_id_check() - * - * - */ -LOCAL -long xy010_id_check(pBase) -char *pBase; -{ - char *pID; - char *pCmp; - char ID; - int status; - - pID = pBase; - pCmp = XY010_ID; - while(*pCmp){ - pID++; /* ID chars stored at odd addr */ - status = vxMemProbe(pID, READ, sizeof(ID), &ID); - if(status < 0){ - return ERROR; - } - if(*pCmp != ID){ - return ERROR; - } - pID++; - pCmp++; - } - return OK; -} - - -/* - * - * xy010_io_report() - * - * - */ -long xy010_io_report(int level) -{ - - if(xy010_map()<0){ - return ERROR; - } - - if (xy010_id_check(xy010_addr) == OK) { - printf("SC: XY010:\tcard 0\n"); - } - - return OK; -} - -