591 lines
19 KiB
C
591 lines
19 KiB
C
/* base/src/drv $Id$ */
|
||
/*
|
||
* Author: John Winans
|
||
* Date: 05-21-92
|
||
* EPICS BITBUS driver for message based I/O
|
||
*
|
||
* Experimental Physics and Industrial Control System (EPICS)
|
||
*
|
||
* Copyright 1991, the Regents of the University of California,
|
||
* and the University of Chicago Board of Governors.
|
||
*
|
||
* This software was produced under U.S. Government contracts:
|
||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||
*
|
||
* Initial development by:
|
||
* The Controls and Automation Group (AT-8)
|
||
* Ground Test Accelerator
|
||
* Accelerator Technology Division
|
||
* Los Alamos National Laboratory
|
||
*
|
||
* Co-developed with
|
||
* The Controls and Computing Group
|
||
* Accelerator Systems Division
|
||
* Advanced Photon Source
|
||
* Argonne National Laboratory
|
||
*
|
||
* Modification Log:
|
||
* -----------------
|
||
* .01 08-10-92 jrw created
|
||
*
|
||
*/
|
||
|
||
#include <vxWorks.h>
|
||
#include <types.h>
|
||
#include <iosLib.h>
|
||
#include <taskLib.h>
|
||
#include <memLib.h>
|
||
#include <semLib.h>
|
||
#include <wdLib.h>
|
||
#include <wdLib.h>
|
||
#include <tickLib.h>
|
||
#include <vme.h>
|
||
|
||
#include <task_params.h>
|
||
#include <module_types.h>
|
||
#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>
|
||
|
||
#include <drvMsg.h>
|
||
#include <drvBitBusInterface.h>
|
||
|
||
int drvBBMsgDebug = 0;
|
||
|
||
extern struct drvBitBusEt drvBitBus;
|
||
|
||
/******************************************************************************
|
||
*
|
||
******************************************************************************/
|
||
#define BBMSGLINK_PRI 50
|
||
#define BBMSGLINK_OPT VX_FP_TASK|VX_STDIO
|
||
#define BBMSGLINK_STACK 5000
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
******************************************************************************/
|
||
static long
|
||
report()
|
||
{
|
||
printf("Report for BITBUS message driver\n");
|
||
return(OK);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
******************************************************************************/
|
||
static long
|
||
init(pparms)
|
||
msgDrvIniParm *pparms;
|
||
{
|
||
if (drvBBMsgDebug)
|
||
printf("Init for BITBUS message driver\n");
|
||
|
||
return(OK);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* This function is called to allocate any structures needed to hold
|
||
* device-specific data that is added to the msgXact structure.
|
||
*
|
||
* It is also responsible for filling in the msgXact.phwpvt pointer.
|
||
*
|
||
******************************************************************************/
|
||
static long
|
||
genXact(p)
|
||
msgDrvGenXParm *p;
|
||
{
|
||
long stat = -1;
|
||
char message[100];
|
||
drvBBMsgLink *pdrvBBMsgLink;
|
||
struct dpvtBitBusHead *pdpvtBitBusHead;
|
||
|
||
if (p->plink->type != BITBUS_IO)
|
||
{
|
||
p->pmsgXact->prec->pact = TRUE;
|
||
sprintf("%s: invalid device type in devSup.ascii (%d)\n", p->pmsgXact->prec->name, p->plink->type);
|
||
errMessage(S_db_badField, message);
|
||
return(ERROR);
|
||
}
|
||
|
||
if (drvBBMsgDebug)
|
||
printf("BBMsg genXact entered for link %d, bug %d, port %d, parm %s\n", p->plink->value.bitbusio.link, p->plink->value.bitbusio.node, p->plink->value.bitbusio.port, p->plink->value.bitbusio.parm);
|
||
|
||
p->pmsgXact->phwpvt = p->pmsgXact->pparmBlock->pmsgHwpvt;
|
||
|
||
/* try to find the hwpvt structure for the required link, bug, and port */
|
||
while ((p->pmsgXact->phwpvt != NULL) && (stat == -1))
|
||
{
|
||
pdrvBBMsgLink = (drvBBMsgLink *)(p->pmsgXact->phwpvt->pmsgLink->p);
|
||
|
||
if ((pdrvBBMsgLink->link == p->plink->value.bitbusio.link)
|
||
&& (pdrvBBMsgLink->node == p->plink->value.bitbusio.node)
|
||
&& (pdrvBBMsgLink->port == p->plink->value.bitbusio.port))
|
||
{
|
||
if (pdrvBBMsgLink->pparmBlock != p->pmsgXact->pparmBlock)
|
||
{
|
||
sprintf(message, "%s: Two different devices on same BBMsg port\n", p->pmsgXact->prec->name);
|
||
errMessage(S_db_badField, message);
|
||
return(ERROR);
|
||
}
|
||
else
|
||
stat = 0; /* Found the correct hwpvt structure */
|
||
}
|
||
else
|
||
p->pmsgXact->phwpvt = p->pmsgXact->phwpvt->next;
|
||
}
|
||
if (stat != 0)
|
||
{ /* Could not find a msgHwpvt for the right link, create a new one */
|
||
if ((p->pmsgXact->phwpvt = drvMsg_genHwpvt(p->pmsgXact->pparmBlock, p->plink)) == NULL)
|
||
return(ERROR);
|
||
}
|
||
/* Set again in case hwpvt was just allocated (and to make compiler happy) */
|
||
pdrvBBMsgLink = (drvBBMsgLink *)(p->pmsgXact->phwpvt->pmsgLink->p);
|
||
|
||
p->pmsgXact->callback.callback = NULL;
|
||
p->pmsgXact->psyncSem = NULL;
|
||
|
||
/* Create the skeleton bitbus driver message */
|
||
pdpvtBitBusHead = (struct dpvtBitBusHead *) malloc(sizeof(struct dpvtBitBusHead));
|
||
(struct dpvtBitBusHead *)(p->pmsgXact->p) = pdpvtBitBusHead;
|
||
|
||
pdpvtBitBusHead->finishProc = NULL;
|
||
pdpvtBitBusHead->psyncSem = malloc(sizeof(SEM_ID));
|
||
*(pdpvtBitBusHead->psyncSem) = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY);
|
||
pdpvtBitBusHead->link = pdrvBBMsgLink->link;
|
||
|
||
pdpvtBitBusHead->txMsg.route = BB_STANDARD_TX_ROUTE;
|
||
pdpvtBitBusHead->txMsg.node = pdrvBBMsgLink->node;
|
||
pdpvtBitBusHead->txMsg.tasks = BB_MSG_TASK;
|
||
pdpvtBitBusHead->txMsg.cmd = 0xff;
|
||
|
||
pdpvtBitBusHead->rxMsg.data = (unsigned char *) malloc(BB_MAX_DAT_LEN);
|
||
|
||
/* in case I read before write */
|
||
pdpvtBitBusHead->rxMsg.cmd = 0;
|
||
pdpvtBitBusHead->rxMsg.length = BB_MSG_HEADER_SIZE;
|
||
pdpvtBitBusHead->status = BB_OK;
|
||
|
||
pdpvtBitBusHead->rxMaxLen = 0;
|
||
pdpvtBitBusHead->ageLimit = 0;
|
||
|
||
if (sscanf(p->plink->value.bitbusio.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.bitbusio.parm);
|
||
errMessage(S_db_badField, message);
|
||
return(ERROR);
|
||
}
|
||
|
||
return(OK);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* This function is called to allocate any structures needed to hold
|
||
* device-specific data that is added to the msgHwpvt structure.
|
||
*
|
||
* It is also responsible for filling in the msgHwpvt.pmsgLink pointer.
|
||
*
|
||
******************************************************************************/
|
||
static long
|
||
genHwpvt(p)
|
||
msgDrvGenHParm *p;
|
||
{
|
||
int stat = ERROR;
|
||
|
||
if (drvBBMsgDebug)
|
||
printf("BBMSG genHwpvt entered\n");
|
||
|
||
p->pmsgHwpvt->pmsgLink = drvBBMSGBlock.pmsgLink;
|
||
while ((p->pmsgHwpvt->pmsgLink != NULL) && (stat == ERROR))
|
||
{
|
||
if ((((drvBBMsgLink *)(p->pmsgHwpvt->pmsgLink->p))->link == p->plink->value.bitbusio.link)
|
||
&& (((drvBBMsgLink *)(p->pmsgHwpvt->pmsgLink->p))->node == p->plink->value.bitbusio.node)
|
||
&& (((drvBBMsgLink *)(p->pmsgHwpvt->pmsgLink->p))->port == p->plink->value.bitbusio.port))
|
||
stat = OK;
|
||
else
|
||
p->pmsgHwpvt->pmsgLink = p->pmsgHwpvt->pmsgLink->next;
|
||
}
|
||
if (stat != OK)
|
||
{
|
||
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
|
||
* device-specific data that is added to the msgLink structure.
|
||
*
|
||
******************************************************************************/
|
||
static long
|
||
genLink(p)
|
||
msgDrvGenLParm *p;
|
||
{
|
||
char name[20];
|
||
char message[100];
|
||
drvBBMsgLink *pdrvBBMsgLink;
|
||
|
||
if (drvBBMsgDebug)
|
||
printf("BBMsg genLink, link = %d, node = %d\n", p->plink->value.bitbusio.link, p->plink->value.bitbusio.node, p->plink->value.bitbusio.port);
|
||
|
||
switch (p->op) {
|
||
case MSG_GENLINK_CREATE:
|
||
|
||
/* BUG -- verify that the link and node numbers are within range! */
|
||
|
||
if (p->plink->value.bitbusio.port & (~DD_MSG_PORT))
|
||
{
|
||
sprintf(message, "drvBBMsg: port number %d out of range\n", p->plink->value.bitbusio.port);
|
||
errMessage(S_db_badField, message);
|
||
return(ERROR);
|
||
}
|
||
|
||
if ((p->pmsgLink->p = malloc(sizeof(drvBBMsgLink))) == NULL)
|
||
return(ERROR);
|
||
|
||
pdrvBBMsgLink = (drvBBMsgLink *)(p->pmsgLink->p);
|
||
|
||
pdrvBBMsgLink->link = p->plink->value.bitbusio.link;
|
||
pdrvBBMsgLink->node = p->plink->value.bitbusio.node;
|
||
pdrvBBMsgLink->port = p->plink->value.bitbusio.port;
|
||
pdrvBBMsgLink->pparmBlock = p->pparmBlock;
|
||
|
||
|
||
return(OK);
|
||
|
||
case MSG_GENLINK_ABORT:
|
||
|
||
if (drvBBMsgDebug)
|
||
printf("BBMsg genLink: called with abort status\n");
|
||
|
||
pdrvBBMsgLink = (drvBBMsgLink *)(p->pmsgLink->p);
|
||
/* BUG - free(p->pmsgLink->p); Don't forget to take it out of the list */
|
||
return(OK);
|
||
}
|
||
return(ERROR);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* 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
|
||
checkEvent(p)
|
||
msgChkEParm *p;
|
||
{
|
||
return(MSG_EVENT_NONE);
|
||
}
|
||
/******************************************************************************
|
||
*
|
||
* This IOCTL function is used to handle non-I/O related operations required
|
||
* to operate the RS-MSG interface.
|
||
*
|
||
******************************************************************************/
|
||
static long
|
||
command(p)
|
||
ioctlCommand *p;
|
||
{
|
||
msgXact *pxact;
|
||
struct dpvtBitBusHead *pdpvtBitBusHead;
|
||
drvBBMsgLink *pdrvBBMsgLink;
|
||
|
||
switch (p->cmd) {
|
||
case IOCTLMSG_BREAK: /* send a BREAK signal to the serial port. */
|
||
/* Build a break message to send */
|
||
pxact = (msgXact *) (p->pparm);
|
||
pdpvtBitBusHead = (struct dpvtBitBusHead *) pxact->p;
|
||
pdrvBBMsgLink = (drvBBMsgLink *)(pxact->phwpvt->pmsgLink->p);
|
||
pdpvtBitBusHead->status = BB_OK;
|
||
pdpvtBitBusHead->rxMaxLen = 0;
|
||
pdpvtBitBusHead->txMsg.length = BB_MSG_HEADER_SIZE;
|
||
pdpvtBitBusHead->txMsg.cmd = BB_MSG_BREAK + pdrvBBMsgLink->port;
|
||
pdpvtBitBusHead->rxMsg.cmd = 0;
|
||
|
||
if (drvBBMsgDebug > 7)
|
||
{
|
||
printf("drvBBMsg.control (tx L%d N%d P%d)\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port);
|
||
drvBitBusDumpMsg(&(pdpvtBitBusHead->txMsg));
|
||
}
|
||
|
||
(*(drvBitBus.qReq))(pdpvtBitBusHead, BB_Q_LOW);
|
||
semTake(*(pdpvtBitBusHead->psyncSem), WAIT_FOREVER);
|
||
|
||
if ((pdpvtBitBusHead->status == BB_OK) && !(pdpvtBitBusHead->rxMsg.cmd & 1))
|
||
return(OK);
|
||
else
|
||
return(ERROR);
|
||
}
|
||
|
||
if (drvBBMsgDebug)
|
||
printf("drvBBMsg.control: bad command 0x%02.2X\n", p->cmd);
|
||
return(ERROR);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* This function is used to write a string of characters out to an BB_MSG
|
||
* device.
|
||
*
|
||
* Note that the BUGs reply to the write messages with the first 13 bytes
|
||
* of the machine's response string (if there is one.) This response string
|
||
* will be left in the pdpvtBitBusHead->rxMsg buffer when the drvRead()
|
||
* function is called later.
|
||
*
|
||
******************************************************************************/
|
||
static long
|
||
drvWrite(pxact, pwrParm)
|
||
msgXact *pxact;
|
||
msgStrParm *pwrParm;
|
||
{
|
||
int len;
|
||
drvBBMsgLink *pdrvBBMsgLink = (drvBBMsgLink *)(pxact->phwpvt->pmsgLink->p);
|
||
struct dpvtBitBusHead *pdpvtBitBusHead = (struct dpvtBitBusHead *) pxact->p;
|
||
unsigned char loopLen;
|
||
|
||
/* build a bitbus message and call the bitbus driver */
|
||
|
||
if (pwrParm->len == -1)
|
||
len = strlen(pwrParm->buf);
|
||
else
|
||
len = pwrParm->len;
|
||
|
||
pdpvtBitBusHead->txMsg.data = (unsigned char *) pwrParm->buf;
|
||
pdpvtBitBusHead->status = BB_OK;
|
||
pdpvtBitBusHead->rxMaxLen = BB_MAX_MSG_LENGTH;
|
||
|
||
pdpvtBitBusHead->txMsg.cmd = BB_MSG_CMD + pdrvBBMsgLink->port;
|
||
pdpvtBitBusHead->rxMsg.cmd = 0;
|
||
|
||
while (len && (pdpvtBitBusHead->status == BB_OK) &&
|
||
!(pdpvtBitBusHead->rxMsg.cmd & 1))
|
||
{
|
||
if (len > BB_MAX_DAT_LEN)
|
||
loopLen = BB_MAX_DAT_LEN;
|
||
else
|
||
loopLen = len;
|
||
|
||
pdpvtBitBusHead->txMsg.length = loopLen + BB_MSG_HEADER_SIZE;
|
||
if (softBBMsg)
|
||
{
|
||
printf("drvBBMsg.drvWrite(tx L%d N%d P%d):\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port);
|
||
drvBitBusDumpMsg(&(pdpvtBitBusHead->txMsg));
|
||
}
|
||
else
|
||
{
|
||
(*(drvBitBus.qReq))(pdpvtBitBusHead, BB_Q_LOW); /* do it */
|
||
semTake(*(pdpvtBitBusHead->psyncSem), WAIT_FOREVER); /* wait for completion */
|
||
if (drvBBMsgDebug > 10)
|
||
{
|
||
printf("drvBBMsg.drvWrite (tx L%d N%d P%d)\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port);
|
||
drvBitBusDumpMsg(&(pdpvtBitBusHead->txMsg));
|
||
}
|
||
}
|
||
|
||
pdpvtBitBusHead->txMsg.data += loopLen;
|
||
len -= loopLen;
|
||
}
|
||
|
||
if ((pdpvtBitBusHead->status != BB_OK) || (pdpvtBitBusHead->rxMsg.cmd & 1))
|
||
{
|
||
if (drvBBMsgDebug)
|
||
printf("BBMsg write error on link %d, node %d, port %d, driver %02.2X, message %02.2X\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port, pdpvtBitBusHead->status, pdpvtBitBusHead->rxMsg.cmd);
|
||
|
||
pxact->status = XACT_IOERR;
|
||
}
|
||
|
||
return(pxact->status);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* This function is used to read a string of characters from an RS-Msg device.
|
||
*
|
||
* It is assumed that pdpvtBitBusHead->rxMsg has already got up to 13
|
||
* bytes of the response data already filled in (left there by the prior
|
||
* call to drvWrite().) If a call to this function is made when there is
|
||
* garbage in the initial pdpvtBitBusHead->rxMsg buffer, set the length field
|
||
* to 0 and the status field to BB_OK.
|
||
*
|
||
******************************************************************************/
|
||
static long
|
||
drvRead(pxact, prdParm)
|
||
msgXact *pxact;
|
||
msgStrParm *prdParm;
|
||
{
|
||
drvBBMsgLink *pdrvBBMsgLink = (drvBBMsgLink *)(pxact->phwpvt->pmsgLink->p);
|
||
struct dpvtBitBusHead *pdpvtBitBusHead = (struct dpvtBitBusHead *) pxact->p;
|
||
int len = prdParm->len;
|
||
int loopLen = 0;
|
||
unsigned char *tmp = pdpvtBitBusHead->rxMsg.data;
|
||
|
||
/* check if data already loaded into pdpvtBitBusHead->rxMsg */
|
||
if ((pdpvtBitBusHead->rxMsg.length > BB_MSG_HEADER_SIZE) && (pdpvtBitBusHead->status == BB_OK))
|
||
{
|
||
loopLen = pdpvtBitBusHead->rxMsg.length - BB_MSG_HEADER_SIZE;
|
||
|
||
if (prdParm->len < loopLen)
|
||
loopLen = prdParm->len;
|
||
|
||
if (drvBBMsgDebug > 9)
|
||
{
|
||
printf("drvBBMsg.drvRead (rx L%d N%d P%d)\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port);
|
||
drvBitBusDumpMsg(&(pdpvtBitBusHead->rxMsg));
|
||
}
|
||
bcopy(pdpvtBitBusHead->rxMsg.data, prdParm->buf, loopLen);
|
||
len -= loopLen;
|
||
}
|
||
|
||
pdpvtBitBusHead->txMsg.length = BB_MSG_HEADER_SIZE;
|
||
pdpvtBitBusHead->txMsg.cmd = BB_MSG_CMD + pdrvBBMsgLink->port;
|
||
|
||
pdpvtBitBusHead->rxMsg.data = (unsigned char *) (&(prdParm->buf[loopLen]));
|
||
|
||
if (!(pdpvtBitBusHead->rxMsg.cmd & BB_MSG_EOI))
|
||
{ /* If we did not hit EOI yet, keep reading */
|
||
|
||
while (len && (pdpvtBitBusHead->status == BB_OK))
|
||
{
|
||
if (len > BB_MAX_DAT_LEN)
|
||
loopLen = BB_MAX_DAT_LEN;
|
||
else
|
||
loopLen = len;
|
||
|
||
pdpvtBitBusHead->rxMaxLen = loopLen + BB_MSG_HEADER_SIZE;
|
||
if (softBBMsg)
|
||
{
|
||
printf("drvBB232.drvRead(tx L%d N%d P%d)\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port);
|
||
drvBitBusDumpMsg(&(pdpvtBitBusHead->txMsg));
|
||
pdpvtBitBusHead->status = BB_232_EOI;
|
||
}
|
||
else
|
||
{
|
||
if (drvBBMsgDebug > 10)
|
||
{
|
||
printf("drvBB232.drvRead(tx L%d N%d P%d)\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port);
|
||
drvBitBusDumpMsg(&(pdpvtBitBusHead->txMsg));
|
||
}
|
||
|
||
(*(drvBitBus.qReq))(pdpvtBitBusHead, BB_Q_LOW); /* do it */
|
||
semTake(*(pdpvtBitBusHead->psyncSem), WAIT_FOREVER); /* wait for completion */
|
||
|
||
if (drvBBMsgDebug > 9)
|
||
{
|
||
printf("drvBB232.drvRead (rx L%d N%d P%d)\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port);
|
||
drvBitBusDumpMsg(&(pdpvtBitBusHead->rxMsg));
|
||
}
|
||
}
|
||
|
||
if (pdpvtBitBusHead->rxMsg.cmd & (~BB_232_EOI))
|
||
{ /* Something is wrong... */
|
||
if (drvBBMsgDebug > 6)
|
||
{
|
||
printf("drvBB232.drvRead (rx L%d N%d P%d) Error response from BUG\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port);
|
||
drvBitBusDumpMsg(&(pdpvtBitBusHead->rxMsg));
|
||
}
|
||
pxact->status = XACT_IOERR;
|
||
break; /* note that we will fall thru to the null-term code */
|
||
}
|
||
if (pdpvtBitBusHead->rxMsg.cmd & BB_232_EOI)
|
||
{
|
||
pdpvtBitBusHead->rxMsg.data += pdpvtBitBusHead->rxMsg.length - BB_MSG_HEADER_SIZE;
|
||
len -= pdpvtBitBusHead->rxMsg.length - BB_MSG_HEADER_SIZE;
|
||
break;
|
||
}
|
||
|
||
pdpvtBitBusHead->rxMsg.data += loopLen;
|
||
len -= loopLen;
|
||
}
|
||
}
|
||
/* Null-terminate the input string (if there is room) */
|
||
if (len)
|
||
*(pdpvtBitBusHead->rxMsg.data) = '\0';
|
||
else
|
||
pxact->status = XACT_LENGTH;
|
||
|
||
/* Note that the following error check, takes priority over a length error */
|
||
if (pdpvtBitBusHead->status != BB_OK)
|
||
{
|
||
if (drvBBMsgDebug)
|
||
printf("BB232 read error on link %d, node %d, port %d\n", pdrvBBMsgLink->link, pdrvBBMsgLink->node, pdrvBBMsgLink->port);
|
||
pxact->status = XACT_IOERR;
|
||
}
|
||
|
||
/* BUG -- this can print unterminated strings !! */
|
||
if (drvBBMsgDebug > 7)
|
||
printf("drvRead: got >%s<\n", prdParm->buf);
|
||
|
||
pdpvtBitBusHead->rxMsg.length = BB_MSG_HEADER_SIZE; /* in case keep reading */
|
||
return(pxact->status);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* This handles any IOCTL calls made to BB-MSG devices.
|
||
*
|
||
******************************************************************************/
|
||
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:
|
||
if (drvBBMsgDebug)
|
||
printf("drvBBMsgBlock.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));
|
||
case MSGIOCTL_COMMAND:
|
||
return(command(pparm));
|
||
}
|
||
return(ERROR);
|
||
}
|
||
|
||
|
||
msgDrvBlock drvBBMsgBlock = {
|
||
"BBMSG", /* taskName */
|
||
BBMSGLINK_PRI, /* taskPri */
|
||
BBMSGLINK_OPT, /* taskOpt */
|
||
BBMSGLINK_STACK, /* taskStack */
|
||
NULL, /* pmsgLink (linked list header) */
|
||
drvWrite, /* drvWrite */
|
||
drvRead, /* drvRead */
|
||
drvIoctl /* drvIoctl */
|
||
};
|