📄 shmuartsio.c
字号:
/* shmuartSio.c - shared memory serial I/O driver */
/*
$RCSfile: shmuartSio.c $
Copyright 2002 by Dy-4 Systems, Inc. All Rights Reserved.
$Revision: 1.8 $
$Name: AV4-ISP-R1.2-1 AV4-ISP-R1.2-0 HMTST2 HMTST1 DVT_AV4_4.101 AV4-VSP-R1.0-2 AV4-VSP-R1.0 CT-ISP-1.1 AV4 ISP 1.1 CT_R0.1_AV4/CAV4 champtools2.22 CAV4_CP1 CHAMPtools FW 3.0 champtools2.21_1215 champtools2.21 champ221_build1 champtools2.2 CHAMPtools_2.1.1_AV3 CHAMPtools_2.1_106 CHAMPtools_2.0_AV3 $ $State: Developmental $ $Locker: $
$Source: L:/SWRND/champAV2/src/vx/src/drv/sio/rcs/shmuartSio.c $
Target: CHAMP-AV II
Description: Serial I/O for the ppc74xx is performed using
shared memory.
Usage:
$Log: shmuartSio.c $
Revision 1.8 2003/08/05 16:33:13Z esaunder
Modified to utilize the AV3 timer resource management functions
(bslTimerAlloc); the timer is allocated under the name "shmuart".
Revision 1.7 2003/05/27 19:11:57 dsessler
corrected compile error for sioCallbackInstall
Revision 1.6 2003/05/21 21:01:38 dsessler
T2.2 fix for paths of included files under the bsp
Revision 1.5 2002/05/28 14:41:15 coopertr
Revision 1.4 2002/05/21 11:49:17 coopertr
Revision 1.3 2002/03/25 12:57:29 coopertr
Revision 1.2 2002/03/21 12:28:31 coopertr
*/
/*
USAGE
The driver is typically called only by the BSP. The directly callable
routines in this module are sioDevInit(), sioDevInit2(), sioIntRcv(),
and sioIntTx().
The BSP calls sioDevInit() to initialize or reset the device.
It connects the driver's interrupt handlers using intConnect().
After connecting the interrupt handlers, the BSP calls sioDevInit2()
to inform the driver that interrupt mode operation is now possible.
*/
#include "vxWorks.h"
#include "sioLib.h"
#include "intLib.h"
#include "errno.h"
#include "bsl.h"
#include "bslBoardInfo.h"
#include "bslSio.h"
#include "h/drv/sio/shmuartSio.h"
/* for backward compatibility */
#ifndef SIO_HUP
# define SIO_OPEN 0x100A /* open channel, raise DTR, RTS */
# define SIO_HUP 0x100B /* hang-up, lower DTR, RTS */
#endif
#define SHMUART_ACTIVE_FREQ 19200
#define SHMUART_IDLE_FREQ 50
static const char sioTimer[] = "shmuart";
/* forward static declarations */
LOCAL int shmuartSioPollInput (SIO_CHAN *pSioChan, char *thisChar);
LOCAL int shmuartSioPollOutput (SIO_CHAN *pSioChan, char outChar);
LOCAL int shmuartSioTxStartup (SIO_CHAN *pSioChan);
LOCAL int shmuartSioIoctl (SIO_CHAN *pSioChan, int request, void *arg);
LOCAL int shmuartSioGenCallbackInstall (SIO_CHAN *pSioChan, int callbackType,
STATUS (*callback)(void *, ...), void *callbackArg);
LOCAL STATUS shmuartDummyCallback (void);
/* local variables */
LOCAL SIO_DRV_FUNCS shmuartSioDrvFuncs = /* for shmuart devices */
{
shmuartSioIoctl,
shmuartSioTxStartup,
(void *)shmuartSioGenCallbackInstall,
shmuartSioPollInput,
shmuartSioPollOutput
};
LOCAL BOOL shmuartSioIntrMode = FALSE; /* interrupt mode allowed flag */
LOCAL int shmuartTimerId = -1;
/******************************************************************************
*
* shmuartSioDevInit - initialize a SHMUART_PORT
*
* This routine initializes the driver function pointers and clears the
* shmuart buffers.
*
* RETURNS: N/A
* NOMANUAL
*/
void shmuartSioDevInit
(
SHMUART_PORT * pChan
)
{
int procId;
int shmuartSize;
boardInfoStruct *pBi;
/* install dummy driver callbacks */
pChan->getTxChar = shmuartDummyCallback;
pChan->putRcvChar = shmuartDummyCallback;
/* get shmuart base addresses */
procId = bslProcGetId ();
pBi = bslBoardGetBoardInfo ();
pChan->txShmuart = bslShmuartGetAddr (procId, SHMUART_TX);
pChan->rcvShmuart = bslShmuartGetAddr (procId, SHMUART_RX);
shmuartSize = pBi->shmuartSize;
/* If shmuarts are present, reset them. */
if (pChan->txShmuart != 0)
bslShmuartInit (pChan->txShmuart, shmuartSize);
if (pChan->rcvShmuart != 0)
bslShmuartInit (pChan->rcvShmuart, shmuartSize);
/* Install device entry points */
pChan->pDrvFuncs = &shmuartSioDrvFuncs;
/* set to polled mode; OS will later change to int mode */
pChan->txEnabled = 0;
sioIoctl ((SIO_CHAN *) pChan, SIO_MODE_SET, (void *)SIO_MODE_POLL);
}
/******************************************************************************
*
* shmuartSioDevInit2 - initialize the serial driver, part 2
*
* This routine is called by the BSP after interrupts have been connected.
* The driver can now operate in interrupt mode. Before this routine is
* called only polled mode operations are allowed.
*
* RETURNS: N/A
* NOMANUAL
*/
void shmuartSioDevInit2
(
SHMUART_PORT * pChan /* device to initialize */
)
{
shmuartSioIntrMode = TRUE;
(void) bslTimerAlloc( sioTimer, EXCL, &shmuartTimerId );
/* Connect and enable timer interrupt */
intConnect (INUM_TO_IVEC(bslTimerToId (shmuartTimerId)),
shmuartSioIntTx,
(long) pChan);
pChan->txEnabled = 0;
bslTimerStop (shmuartTimerId);
bslTimerSetFreq (shmuartTimerId, SHMUART_IDLE_FREQ);
bslTimerIntEnable (shmuartTimerId);
}
/******************************************************************************
*
* shmuartSioIntTx - handle a channels interrupt (timer expiration)
*
* If there is a character to transmit:
* Send the next character to the serial output port. The next character is
* obtained by calling a callback function, which will return a status
* indicating whether another character was ready to send or not.
*
* If there is a character to receive:
* This function passes the received character on to vxWorks by calling
* the appropriate callback function. For devices which can store multiple
* characters in an rx fifo, it is most efficient if this function empties
* the fifo.
* Therefore, this function has to determine if the serial driver is
* in interrupt mode or not. If it is in interrupt mode, then we can
* call the proper callback function when a character is received. If
* in polled mode we just drop through the function.
*
* If the driver is still in interrupt mode after checking the buffers
* then a new timer is created.
*
* RETURNS: N/A
* NOMANUAL
*/
void shmuartSioIntTx
(
SHMUART_PORT *pChan /* channel generating the interrupt */
)
{
char rxChar, txChar;
int status = 0;
int active = FALSE;
if (pChan->txShmuart == 0)
return;
/* more room and more data to put... */
if (pChan->txEnabled)
{
if((bslShmuartQuery (pChan->txShmuart)) != -1)
{
/*
* Get char from vxWorks and put in shmuart transmit buffer
*/
if ((*pChan->getTxChar) (pChan->getTxArg, &txChar) != ERROR)
{
active = TRUE;
status = bslShmuartPut (pChan->txShmuart, txChar);
}
else
pChan->txEnabled = 0;
}
}
/* If interrupt mode and rx buffer not empty, get an input char */
if(((pChan->mode) == SIO_MODE_INT) && (bslShmuartQuery (pChan->rcvShmuart)))
{
if ((bslShmuartGet (pChan->rcvShmuart, &rxChar)) == 0)
{
active = TRUE;
(*pChan->putRcvChar) (pChan->putRcvArg, rxChar);
}
}
if(active)
bslTimerSetFreq (shmuartTimerId, SHMUART_ACTIVE_FREQ);
else
bslTimerSetFreq (shmuartTimerId, SHMUART_IDLE_FREQ);
}
/******************************************************************************
*
* shmuartSioTxStartup - start the interrupt driven transmitter
*
* Not needed in this shared memory serial driver.
* NOMANUAL
*/
LOCAL int shmuartSioTxStartup
(
SIO_CHAN * pSioChan /* channel to start */
)
{
char txChar;
SHMUART_PORT * pChan = (SHMUART_PORT *)pSioChan;
if (pChan->txShmuart == 0)
while ((*pChan->getTxChar) (pChan->getTxArg, &txChar) != ERROR);
else
{
pChan->txEnabled = 1;
bslTimerSetFreq (shmuartTimerId, SHMUART_ACTIVE_FREQ);
}
return (OK);
}
/***************************************************************************
*
* shmuartSioGenCallbackInstall - install ISR callbacks to get/put chars for a
* generic SIO device
*
* This driver allows interrupt callbacks for transmitting characters
* and receiving characters. In general, drivers may support other
* types of callbacks too.
*
* RETURNS: OK on success, or ENOSYS for an unsupported callback type.
* NOMANUAL
*/
LOCAL int shmuartSioGenCallbackInstall
(
SIO_CHAN * pSioChan, /* channel */
int callbackType, /* type of callback */
STATUS (*callback)(void *, ...), /* callback */
void * callbackArg /* parameter to callback */
)
{
SHMUART_PORT * pChan = (SHMUART_PORT *)pSioChan;
switch (callbackType)
{
case SIO_CALLBACK_GET_TX_CHAR:
pChan->getTxChar = (void *)callback;
pChan->getTxArg = callbackArg;
return (OK);
case SIO_CALLBACK_PUT_RCV_CHAR:
pChan->putRcvChar = (void *)callback;
pChan->putRcvArg = callbackArg;
return (OK);
default:
return (ENOSYS);
}
}
/*******************************************************************************
*
* shmuartSioPollOutput - output a character in polled mode
*
* RETURNS: OK if a character arrived, EIO on device error, EAGAIN
* if the output buffer if full. ENOSYS if the device is
* interrupt-only.
* NOMANUAL
*/
LOCAL int shmuartSioPollOutput
(
SIO_CHAN * pSioChan,
char outChar
)
{
int status;
SHMUART_PORT * pChan = (SHMUART_PORT *)pSioChan;
/* If no tx shmuart, return OK, discarding character. */
if (pChan->txShmuart == 0)
status = OK;
/* If transmit shmuart buffer not full then add char */
else if ((bslShmuartQuery (pChan->txShmuart)) != -1)
status = bslShmuartPut (pChan->txShmuart,outChar);
/* else no room; caller must retry later */
else
status = EAGAIN;
return (status);
}
/******************************************************************************
*
* shmuartSioPollInput - poll the device for input
*
* RETURNS: OK if a character arrived, EIO on device error, EAGAIN
* if the input buffer if empty, ENOSYS if the device is
* interrupt-only.
* NOMANUAL
*/
LOCAL int shmuartSioPollInput
(
SIO_CHAN * pSioChan,
char * thisChar
)
{
int status;
SHMUART_PORT * pChan = (SHMUART_PORT *)pSioChan;
if (pChan->rcvShmuart == 0)
status = EAGAIN;
else if ((bslShmuartQuery (pChan->rcvShmuart)) != 0)
status = bslShmuartGet (pChan->rcvShmuart, thisChar);
else
status = EAGAIN;
return (status);
}
/******************************************************************************
*
* sioModeSet - toggle between interrupt and polled mode
*
* If switching from polled mode to interrupt mode and timer
* has expired, create a new one.
*
* RETURNS: OK on success, EIO on unsupported mode.
* NOMANUAL
*/
LOCAL int shmuartSioModeSet
(
SHMUART_PORT * pChan, /* channel */
uint_t newMode /* new mode */
)
{
if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT))
return (EIO);
/* Don't enter interrupt mode unless it is allowed. */
if ((newMode == SIO_MODE_INT) && (!shmuartSioIntrMode))
return (EIO);
pChan->mode = newMode;
/* If we have just switched to interrupt mode, start the timer */
if (pChan->mode == SIO_MODE_INT)
{
pChan->txEnabled = 1;
bslTimerSetFreq (shmuartTimerId, SHMUART_ACTIVE_FREQ);
bslTimerStart (shmuartTimerId);
}
else
bslTimerStop (shmuartTimerId);
return (OK);
}
/*******************************************************************************
*
* shmuartSioIoctl - special device control
*
* This routine handles the IOCTL messages from the user. It supports commands
* to get/set baud rate, mode(INT,POLL), hardware options(parity, number of
* data bits) and modem control(RTS/CTS and DTR/DSR handshakes).
*
* RETURNS: OK on success, ENOSYS on unsupported request, EIO on failed
* request.
* NOMANUAL
*/
LOCAL int shmuartSioIoctl
(
SIO_CHAN * pSioChan, /* device to control */
int request, /* request code */
void * someArg /* some argument */
)
{
SHMUART_PORT *pChan = (SHMUART_PORT *) pSioChan;
int arg = (int)someArg;
switch (request)
{
case SIO_BAUD_SET: /* fixed baud rate */
return (ENOSYS);
case SIO_BAUD_GET: /* fixed baud rate */
*(int *)arg = SIO_BAUD_RATE;
return (OK);
case SIO_MODE_SET: /* int or polled mode */
return (shmuartSioModeSet (pChan, arg));
case SIO_MODE_GET: /* int or polled mode */
*(int *)arg = pChan->mode;
return (OK);
case SIO_AVAIL_MODES_GET: /* get mode options */
*(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
return (OK);
case SIO_HUP:
return (OK);
case SIO_OPEN:
return (OK);
default:
return (ENOSYS);
}
}
/*******************************************************************************
*
* shmuartDummyCallback - dummy callback routine
*
* RETURNS: ERROR
* NOMANUAL
*/
LOCAL STATUS shmuartDummyCallback (void)
{
return (ERROR);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -