much debugging and addition of watchdig timeouts on I/O operations

This commit is contained in:
John Winans
1992-04-29 15:24:01 +00:00
parent 60594fdef6
commit f39ad61d47
+349 -165
View File
@@ -1,8 +1,4 @@
/*
* drvRs232.c
* share/src/drv $Id$
*/
/* share/src/drv $Id$ */
/*
* Author: John Winans
* Date: 04-13-92
@@ -35,6 +31,8 @@
*
*/
#define DRVRS232_C
#include <vxWorks.h>
#include <types.h>
#include <iosLib.h>
@@ -51,6 +49,8 @@
#include <drvSup.h>
#include <devSup.h>
#include <dbDefs.h>
#include <dbCommon.h>
#include <dbAccess.h>
#include <link.h>
#include <callback.h>
#include <fast_lock.h>
@@ -58,7 +58,11 @@
#include <drvMsg.h>
#include <drvRs232.h>
static msgDrvBlock drv232Block;
int drv232Debug = 1;
static void callbackAbortSerial();
static void dogAbortSerial();
/******************************************************************************
*
******************************************************************************/
@@ -81,12 +85,13 @@ report()
*
******************************************************************************/
static long
init(parm)
int parm;
init(pparms)
msgDrvIniParm *pparms;
{
printf("Init for RS-232 driver\n");
return(OK);
}
/******************************************************************************
*
* This function is called to allocate any structures needed to hold
@@ -96,35 +101,53 @@ int parm;
*
******************************************************************************/
static long
genXact(pparmBlock, plink, pmsgXact)
msgParmBlock *pparmBlock;
struct link *plink;
msgXact *pmsgXact;
genXact(p)
msgDrvGenXParm *p;
{
long stat = ERROR;
long stat = -1;
char message[100];
dev232Link *pdev232Link;
printf("rs232-genXact entered\n");
printf("RS-232 genXact entered for link %d, addr %d, parm %s\n", p->plink->value.gpibio.link, p->plink->value.gpibio.addr, p->plink->value.gpibio.parm);
pmsgXact->phwpvt = pparmBlock->pmsgHwpvt;
while ((pmsgXact->phwpvt != NULL) && (stat == ERROR))
p->pmsgXact->phwpvt = p->pmsgXact->pparmBlock->pmsgHwpvt;
pdev232Link = (dev232Link *)(p->pmsgXact->phwpvt->pmsgLink->p);
while ((p->pmsgXact->phwpvt != NULL) && (stat == -1))
{
if ((((dev232Link *)(pmsgXact->phwpvt->pmsgLink->p))->link == plink->value.gpibio.link)
&& (((dev232Link *)(pmsgXact->phwpvt->pmsgLink->p))->port == plink->value.gpibio.addr))
stat = OK;
if ((pdev232Link->link == p->plink->value.gpibio.link)
&& (pdev232Link->port == p->plink->value.gpibio.addr))
{
if (pdev232Link->pparmBlock != p->pmsgXact->pparmBlock)
{
sprintf(message, "%s: Two different devices on same RS-232 port\n", p->pmsgXact->prec->name);
errMessage(S_db_badField, message);
return(ERROR);
}
else
stat = 0; /* Found the correct hwpvt structure */
}
else
pmsgXact->phwpvt = pparmBlock->pmsgHwpvt->next;
p->pmsgXact->phwpvt = p->pmsgXact->phwpvt->next;
}
if (stat != OK)
if (stat != 0)
{ /* Could not find a msgHwpvt for the right link, create a new one */
if ((pmsgXact->phwpvt = drvMsg_genHwpvt(pparmBlock, plink)) == NULL)
if ((p->pmsgXact->phwpvt = drvMsg_genHwpvt(p->pmsgXact->pparmBlock, p->plink)) == NULL)
return(ERROR);
}
pmsgXact->finishProc = NULL;
pmsgXact->psyncSem = NULL;
p->pmsgXact->callback.callback = NULL;
p->pmsgXact->psyncSem = NULL;
if (sscanf(p->plink->value.gpibio.parm,"%d", &(p->pmsgXact->parm)) != 1)
{
p->pmsgXact->prec->pact = TRUE;
sprintf("%s: invalid parameter string >%s<\n", p->pmsgXact->prec->name, p->plink->value.gpibio.parm);
errMessage(S_db_badField, message);
return(ERROR);
}
return(OK);
}
/******************************************************************************
*
* This function is called to allocate any structures needed to hold
@@ -134,30 +157,29 @@ printf("rs232-genXact entered\n");
*
******************************************************************************/
static long
genHwpvt(pparmBlock, plink, pmsgHwpvt)
msgParmBlock *pparmBlock;
struct link *plink; /* I/O link structure from record */
msgHwpvt *pmsgHwpvt;
genHwpvt(p)
msgDrvGenHParm *p;
{
int stat = ERROR;
printf("rs232-genHwpvt entered\n");
pmsgHwpvt->pmsgLink = drv232Block.pmsgLink;
while ((pmsgHwpvt->pmsgLink != NULL) && (stat == ERROR))
p->pmsgHwpvt->pmsgLink = drv232Block.pmsgLink;
while ((p->pmsgHwpvt->pmsgLink != NULL) && (stat == ERROR))
{
if ((((dev232Link *)(pmsgHwpvt->pmsgLink->p))->link == plink->value.gpibio.link)
&& (((dev232Link *)(pmsgHwpvt->pmsgLink->p))->port == plink->value.gpibio.addr))
if ((((dev232Link *)(p->pmsgHwpvt->pmsgLink->p))->link == p->plink->value.gpibio.link)
&& (((dev232Link *)(p->pmsgHwpvt->pmsgLink->p))->port == p->plink->value.gpibio.addr))
stat = OK;
else
pmsgHwpvt->pmsgLink = pmsgHwpvt->pmsgLink->next;
p->pmsgHwpvt->pmsgLink = p->pmsgHwpvt->pmsgLink->next;
}
if (stat != OK)
{
if ((pmsgHwpvt->pmsgLink = drvMsg_genLink(pparmBlock->pdrvBlock, plink)) == NULL)
if ((p->pmsgHwpvt->pmsgLink = drvMsg_genLink(p->pparmBlock, p->plink)) == NULL)
return(ERROR);
}
return(OK);
}
/******************************************************************************
*
* This function is called to allocate any structures needed to hold
@@ -165,182 +187,344 @@ printf("rs232-genHwpvt entered\n");
*
******************************************************************************/
static long
genLink(pmsgLink, plink, opCode)
msgLink *pmsgLink;
struct link *plink;
int opCode;
genLink(p)
msgDrvGenLParm *p;
{
char name[20];
char message[100];
dev232Link *pdev232Link;
switch (opCode) {
printf("In RS-232's genLink, link = %d, addr = %d\n", p->plink->value.gpibio.link,p->plink->value.gpibio.addr);
switch (p->op) {
case MSG_GENLINK_CREATE:
if ((pmsgLink->p = malloc(sizeof(dev232Link))) == NULL)
if ((p->pmsgLink->p = malloc(sizeof(dev232Link))) == NULL)
return(ERROR);
((dev232Link *)(pmsgLink->p))->link = plink->value.gpibio.link;
((dev232Link *)(pmsgLink->p))->port = plink->value.gpibio.addr;
pdev232Link = (dev232Link *)(p->pmsgLink->p);
pdev232Link->link = p->plink->value.gpibio.link;
pdev232Link->port = p->plink->value.gpibio.addr;
pdev232Link->pparmBlock = p->pparmBlock;
if ((pdev232Link->doggie = wdCreate()) == NULL)
{
printf("RS-232 driver can't create a watchdog\n");
/* errMessage(******, message); */
return(ERROR);
}
sprintf(name, "/tyCo/%d", p->plink->value.gpibio.addr);
printf ("in genlink opening >%s<, baud %d\n", name, ((dev232ParmBlock *)(p->pparmBlock->p))->baud);
if ((((dev232Link *)(p->pmsgLink->p))->ttyFd = open(name, O_RDWR, 0)) != -1)
{
printf("Successful open w/fd=%d\n", pdev232Link->ttyFd);
/* set baud rate and unbuffered mode */
(void) ioctl (pdev232Link->ttyFd, FIOBAUDRATE, ((dev232ParmBlock *)(p->pparmBlock->p))->baud);
(void) ioctl (pdev232Link->ttyFd, FIOSETOPTIONS, ((dev232ParmBlock *)(p->pparmBlock->p))->ttyOptions);
pdev232Link->callback.callback = callbackAbortSerial;
pdev232Link->callback.priority = priorityHigh;
pdev232Link->callback.user = (void *) pdev232Link;
sprintf(name, "/tyCo/%d", plink->value.gpibio.addr);
if ((((dev232Link *)(pmsgLink->p))->ttyFd = open(name, O_RDWR, 0)) != -1)
return(OK);
free(pmsgLink->p);
return(ERROR);
}
else
{
printf("RS-232 genLink failed to open the tty port\n");
free(p->pmsgLink->p);
return(ERROR);
}
case MSG_GENLINK_ABORT:
return(free(pmsgLink->p));
printf("RS-232 genLink called with abort status\n");
pdev232Link = (dev232Link *)(p->pmsgLink->p);
/* free(p->pmsgLink->p); Don't forget to take it out of the list */
return(OK);
}
return(ERROR);
}
/******************************************************************************
*
* This function is called to verify the validity of the link information
* given in a link.value structure (defined in link.h)
* This function is called to allow the device to indicate that a device-related
* event has occurred. If an event had occurred, it would have to place the
* address of a valid transaction structure in pxact. This xact structure
* will then be processed by the message link task as indicated by the
* return code of this function.
*
* MSG_EVENT_NONE = no event has occurred, pxact not filled in.
* MSG_EVENT_WRITE = event occurred, process the writeOp assoc'd w/pxact.
* MSG_EVENT_READ = event occurred, process the readOp assoc'd w/pxact.
*
* Note that MSG_EVENT_READ only makes sense when returned with a transaction
* that has deferred readback specified for its readOp function. Because if
* it is NOT a deferred readback, it will be done immediately after the writeOp.
* Even if that writeOp was due to a MSG_EVENT_WRITE from this function.
*
******************************************************************************/
static long
checkLink()
{
return(ERROR);
}
static long
checkEvent(pdrvBlock, pmsgLink, pxact)
msgDrvBlock *pdrvBlock;
msgLink *pmsgLink;
msgXact *pxact;
checkEvent(p)
msgChkEParm *p;
{
return(MSG_EVENT_NONE);
}
#if FALSE
/******************************************************************************
*
* Check to see if a link number is valid or not.
*
* Return -1 if invalid link number.
* 0 if valid link number and is currently open.
* 1 if valid link number, but not open.
*
******************************************************************************/
int
checkLink(link)
int link;
static void
dogAbortSerial(pdev232Link)
dev232Link *pdev232Link;
{
if ((link < 1) || (link >= NUM_TY_LINKS))
return(-1);
logMsg("RS-232 driver watch-dog timeout on link %d, port %d, fd=%d\n", pdev232Link->link, pdev232Link->port, pdev232Link->ttyFd);
if (rsLink[link] == NULL)
return(1);
else
return(0);
/* Annoying vxWorks implementation... can't IOCTL from here */
callbackRequest(&(pdev232Link->callback));
}
drv232Write()
static void
callbackAbortSerial(p)
CALLBACK *p;
{
/* Perform the transaction operation */
xact->status = XACT_OK; /* All well, so far */
((dev232Link *)(p->user))->dogAbort = TRUE;
len = xact->txLen;
if (len == -1)
len = strlen(xact->txMsg);
if(len > 0)
{
if (write(rsLink[link].ttyFd, xact->txMsg, len) != len)
{
printf("write error to link %d\n", link);
xact->status = XACT_IOERR;
}
}
}
drv232Read()
{
if ((xact->rxLen > 0) && (xact->status == XACT_OK))
{
if (xact->rxEoi != -1)
{
len = xact->rxLen;
ch = xact->rxMsg;
eoi = xact->rxEoi & 0xff;
*ch = eoi + 1; /* make sure gets into loop on first */
while (len > 0)
{
read(rsLink[link].ttyFd, ch, 1);
if (*ch == eoi)
break;
ch++;
len--;
}
if (*ch != eoi)
xact->status = XACT_LENGTH;
}
else
{ /* Read xact->rxLen bytes from the device */
len = xact->rxLen;
while(len)
len -= read(rsLink[link].ttyFd, xact->rxMsg, len);
}
}
ioctl(((dev232Link *)(p->user))->ttyFd, FIOCANCEL);
/* I am not sure if I should really do this, but... */
ioctl(((dev232Link *)(p->user))->ttyFd, FIOFLUSH);
}
/* create an interactive RS232 transaction from the console */
static SEM_ID iSem;
static int firstFlag = 1;
rsx(l, ch)
int l;
unsigned char *ch;
/******************************************************************************
*
* This function is used to write a string of characters out to an RS-232
* device.
*
******************************************************************************/
static long
drvWrite(pxact, pwrParm)
msgXact *pxact;
msgStrParm *pwrParm;
{
struct xact232 xact;
unsigned char rxBuf[100];
dev232Link *pdev232Link = (dev232Link *)(pxact->phwpvt->pmsgLink->p);
int len;
char *out;
char in;
if (firstFlag)
if (wdStart(pdev232Link->doggie, ((dev232ParmBlock *)(pxact->pparmBlock->p))->dmaTimeout, dogAbortSerial, pdev232Link) == ERROR)
{
iSem = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY);
firstFlag = 0;
printf("RS-232 driver can not start watchdog timer\n");
/* errMessage(***,message); */
pxact->status = XACT_IOERR;
return(pxact->status);
}
xact.finishProc = NULL;
xact.psyncSem = &iSem;
xact.link = l;
xact.txMsg = ch;
xact.txLen = -1;
if (((dev232ParmBlock *)(pxact->pparmBlock->p))->flags & ECHO)
{ /* ping-pong the characters out */
xact.rxMsg = rxBuf;
xact.rxEoi = '\r';
xact.rxLen = sizeof(rxBuf);
/*BUG ??? This will only work if we are sure that the RX buffer is clean */
ioctl(pdev232Link->ttyFd, FIORFLUSH);
rxBuf[0] = '\0';
if (qXact(&xact, RS_Q_LOW) == ERROR)
return(ERROR);
out = pwrParm->buf;
while ((*out != '\0') && (pxact->status == XACT_OK))
{
if (drv232Debug > 5)
printf("out >%c<\n", *out);
if (write(pdev232Link->ttyFd, out, 1) != 1)
{
printf("RS-232 write error on link %d, port %d\n", pdev232Link->link, pdev232Link->port);
pxact->status = XACT_IOERR;
}
else
{
if (read(pdev232Link->ttyFd, &in, 1) != 1)
{
printf("Read problem encountered in echo reading mode of a write operation\n");
if (pdev232Link->dogAbort)
pxact->status = XACT_TIMEOUT;
else
pxact->status = XACT_IOERR;
}
else
{
if (*out != in)
printf("echo response out of sync! sent >%c< got >%c<\n", *out, in);
if (drv232Debug > 5)
printf("in >%c<\n", in);
if ((*out == '\r') && (((dev232ParmBlock *)(pxact->pparmBlock->p))->flags & CRLF))
{
if (read(pdev232Link->ttyFd, &in, 1) != 1)
{
printf("Read problem encountered in echo reading mode of a write operation\n");
if (pdev232Link->dogAbort)
pxact->status = XACT_TIMEOUT;
else
pxact->status = XACT_IOERR;
}
else
{
if (drv232Debug > 5)
printf("in >%c<\n", in);
}
}
}
}
out++;
}
}
else
{
if (pwrParm->len == -1)
len = strlen(pwrParm->buf);
else
len = pwrParm->len;
semTake(iSem, WAIT_FOREVER);
if (drv232Debug > 4)
printf("block-writing >%s<\n", pwrParm->buf);
printf("Sent >%s< got >%s<\n", ch, rxBuf);
return(xact.status);
if (write(pdev232Link->ttyFd, pwrParm->buf, len) != len)
{
printf("RS-232 write error on link %d, port %d\n", pdev232Link->link, pdev232Link->port);
pxact->status = XACT_IOERR;
}
}
if (wdCancel(pdev232Link->doggie) == ERROR)
printf("Can not cancel RS-232 watchdog timer\n");
return(pxact->status);
}
/******************************************************************************
*
* This function is used to read a string of characters from an RS-232 device.
*
******************************************************************************/
static long
drvRead(pxact, prdParm)
msgXact *pxact;
msgStrParm *prdParm;
{
dev232Link *pdev232Link = (dev232Link *)(pxact->phwpvt->pmsgLink->p);
int len;
int clen;
char *ch;
int flags;
int eoi;
dev232ParmBlock *pdev232ParmBlock = (dev232ParmBlock *)(pxact->pparmBlock->p);
pdev232Link->dogAbort = FALSE;
if (wdStart(pdev232Link->doggie, pdev232ParmBlock->dmaTimeout, dogAbortSerial, pdev232Link) == ERROR)
{
printf("RS-232 driver can not start watchdog timer\n");
/* errMessage(***,message); */
pxact->status = XACT_IOERR;
return(pxact->status);
}
ch = prdParm->buf;
len = prdParm->len - 1;
flags = pdev232ParmBlock->flags;
/* BUG -- This should have a timeout check specified in here */
if ((pdev232ParmBlock->eoi != -1) || (flags & KILL_CRLF))
{
eoi = 0;
while ((!eoi) && (len > 0))
{
if (read(pdev232Link->ttyFd, ch, 1) != 1)
{
printf("Read problem encountered in eoi/KILL_CRLF reading mode\n");
if (pdev232Link->dogAbort)
pxact->status = XACT_TIMEOUT;
else
pxact->status = XACT_IOERR;
eoi = 1;
}
else
{
if (drv232Debug > 6)
printf("in >%c<\n", *ch);
if (*ch == pdev232ParmBlock->eoi)
eoi = 1;
if (!(flags & KILL_CRLF) || ((*ch != '\n') && (*ch != '\r')))
{
ch++;
len--; /* To count the \n's and \r's or not to count... */
}
}
}
if (len == 0)
{
printf("buffer length overrun during read operation\n");
pxact->status = XACT_LENGTH;
}
*ch = '\0';
}
else
{ /* Read xact->rxLen bytes from the device */
while(len)
{
clen = read(pdev232Link->ttyFd, ch, len);
if (pdev232Link->dogAbort)
{
printf("Read problem encountered in raw mode\n");
pxact->status = XACT_TIMEOUT;
len = 0;
}
else
{
len -= clen;
ch += clen;
}
}
*ch = '\0';
}
if (drv232Debug)
printf("drvRead: got >%s<\n", prdParm->buf);
if (wdCancel(pdev232Link->doggie) == ERROR)
printf("Can not cancel RS-232 watchdog timer, dogAbort=%d \n", pdev232Link->dogAbort);
return(pxact->status);
}
static long
drvIoctl(cmd, pparm)
int cmd;
void *pparm;
{
switch (cmd) {
case MSGIOCTL_REPORT:
return(report());
case MSGIOCTL_INIT:
return(init(pparm));
case MSGIOCTL_INITREC:
printf("drv232Block.drvIoctl got a MSGIOCTL_INITREC request!\n");
return(ERROR);
case MSGIOCTL_GENXACT:
return(genXact(pparm));
case MSGIOCTL_GENHWPVT:
return(genHwpvt(pparm));
case MSGIOCTL_GENLINK:
return(genLink(pparm));
case MSGIOCTL_CHECKEVENT:
return(checkEvent(pparm));
}
return(ERROR);
}
#endif
static msgDrvBlock drv232Block = {
report,
init,
NULL,
genXact,
genHwpvt,
genLink,
checkLink,
checkEvent,
NULL,
msgDrvBlock drv232Block = {
"RS232",
RSLINK_PRI,
RSLINK_OPT,
RSLINK_STACK,
NULL
NULL,
drvWrite,
drvRead,
drvIoctl
};