📄 ks8695sio.c
字号:
/* ks8695Sio.c - KS8695/P/X UART tty driver */
/*
modification history
--------------------
11/13/2003 LIQUN RUAN (RLQ) modified for KS8695/X
09/22/2003 Ritter Yeh created
*/
#include "vxWorks.h"
#include <stdio.h>
#include "intLib.h"
#include "errnoLib.h"
#include "errno.h"
#include "sioLib.h"
#include "ks8695Sio.h"
/* local defines */
#define KS8695P_UART_REG(pChan, reg) \
(*(volatile UINT32 *)((UINT32)(pChan)->regs + (reg)))
#define KS8695P_UART_REG_READ(pChan, reg, result) \
(result) = (KS8695P_UART_REG(pChan, reg))
#define KS8695P_UART_REG_WRITE(pChan, reg, data) \
(KS8695P_UART_REG(pChan, reg)) = (data)
#define KS8695P_UART_REG_BIT_SET(pChan, reg, data) \
(KS8695P_UART_REG(pChan, reg)) |= (data)
#define KS8695P_UART_REG_BIT_CLR(pChan, reg, data) \
(KS8695P_UART_REG(pChan, reg)) &= ~(data)
/* locals */
/* function prototypes */
LOCAL STATUS ks8695pDummyCallback (void);
LOCAL void ks8695pInitChannel (KS8695P_CHAN * pChan);
LOCAL STATUS ks8695pIoctl (SIO_CHAN * pSioChan, int request, int arg);
LOCAL int ks8695pTxStartup (SIO_CHAN * pSioChan);
LOCAL int ks8695pCallbackInstall (SIO_CHAN * pSioChan, int callbackType,
STATUS (*callback)(), void * callbackArg);
LOCAL int ks8695pPollInput (SIO_CHAN * pSioChan, char *);
LOCAL int ks8695pPollOutput (SIO_CHAN * pSioChan, char);
/* driver functions */
LOCAL SIO_DRV_FUNCS ks8695pSioDrvFuncs =
{
(int (*)())ks8695pIoctl,
ks8695pTxStartup,
ks8695pCallbackInstall,
ks8695pPollInput,
ks8695pPollOutput
};
/*******************************************************************************
*
* ks8695pDummyCallback - dummy callback routine.
*
* RETURNS: ERROR, always.
*/
LOCAL STATUS ks8695pDummyCallback (void)
{
printf("%s\n", __FUNCTION__);
return ERROR;
}
/*******************************************************************************
*
* ks8695pSioDevInit - initialise an AMBA channel
*
* This routine initialises some SIO_CHAN function pointers and then resets
* the chip to a quiescent state. Before this routine is called, the BSP
* must already have initialised all the device addresses, etc. in the
* KS8695P_CHAN structure.
*
* RETURNS: N/A
*/
void ks8695pSioDevInit
(
KS8695P_CHAN * pChan /* ptr to KS8695P_CHAN describing this channel */
)
{
int oldlevel = intLock();
/* initialise the driver function pointers in the SIO_CHAN */
pChan->sio.pDrvFuncs = &ks8695pSioDrvFuncs;
/* set the non BSP-specific constants */
pChan->getTxChar = ks8695pDummyCallback;
pChan->putRcvChar = ks8695pDummyCallback;
pChan->channelMode = 0; /* undefined */
/* initialise the chip */
ks8695pInitChannel (pChan);
intUnlock (oldlevel);
}
/*******************************************************************************
*
* ks8695pInitChannel - initialise UART
*
* This routine performs hardware initialisation of the UART channel.
*
* RETURNS: N/A
*/
LOCAL void ks8695pInitChannel
(
KS8695P_CHAN * pChan /* ptr to KS8695P_CHAN describing this channel */
)
{
/* Program UART line control register
Set 8 bits, 1 stop bit, no parity.
*/
KS8695P_UART_REG_WRITE(pChan, REG_UART_LINE_CTRL, 0);
KS8695P_UART_REG_BIT_SET(pChan, REG_UART_LINE_CTRL,REG_URLC_8_BIT);
/* Set baud rate divisor */
switch (pChan->baudRate)
{
case 9600:
KS8695P_UART_REG_WRITE(pChan, REG_UART_DIVISOR, UART_BAUD_RATE_9600);
break;
case 19200:
KS8695P_UART_REG_WRITE(pChan, REG_UART_DIVISOR, UART_BAUD_RATE_19200);
break;
case 38400:
KS8695P_UART_REG_WRITE(pChan, REG_UART_DIVISOR, UART_BAUD_RATE_38400);
break;
case 56000:
KS8695P_UART_REG_WRITE(pChan, REG_UART_DIVISOR, UART_BAUD_RATE_56000);
break;
case 115200:
KS8695P_UART_REG_WRITE(pChan, REG_UART_DIVISOR, UART_BAUD_RATE_115200);
break;
default:
KS8695P_UART_REG_WRITE(pChan, REG_UART_DIVISOR, UART_BAUD_RATE_9600);
break;
}
/* Set the FIFO mode (14 bytes length) ,reset the TX & RX FIFO's ,and enable FIFO mode */
KS8695P_UART_REG_WRITE(pChan, REG_UART_FIFO_CTRL, 0);
KS8695P_UART_REG_BIT_SET(pChan, REG_UART_FIFO_CTRL,
REG_URFC_URFRT_14 |
REG_URFC_ENABLE);
KS8695P_UART_REG_BIT_SET(pChan, REG_UART_FIFO_CTRL,
REG_URFC_TX_RST |
REG_URFC_RX_RST );
}
/*******************************************************************************
*
* ks8695pIoctl - special device control
*
* This routine handles the IOCTL messages from the user.
*
* RETURNS: OK on success, ENOSYS on unsupported request, EIO on failed
* request.
*/
LOCAL STATUS ks8695pIoctl
(
SIO_CHAN * pSioChan, /* ptr to SIO_CHAN describing this channel */
int request, /* request code */
int arg /* some argument */
)
{
int oldlevel; /* current interrupt level mask */
STATUS status; /* status to return */
KS8695P_CHAN * pChan = (KS8695P_CHAN *)pSioChan;
status = OK; /* preset to return OK */
switch (request)
{
case SIO_BAUD_SET:
/*
* Set the baud rate. Return EIO for an invalid baud rate, or
* OK on success.
*/
/* disable interrupts during chip access */
oldlevel = intLock ();
pChan->baudRate = arg;
/* Set baud rate divisor in UART */
switch (pChan->baudRate)
{
case 9600:
KS8695P_UART_REG_WRITE(pChan, REG_UART_DIVISOR, UART_BAUD_RATE_9600);
break;
case 19200:
KS8695P_UART_REG_WRITE(pChan, REG_UART_DIVISOR, UART_BAUD_RATE_19200);
break;
case 38400:
KS8695P_UART_REG_WRITE(pChan, REG_UART_DIVISOR, UART_BAUD_RATE_38400);
break;
case 56000:
KS8695P_UART_REG_WRITE(pChan, REG_UART_DIVISOR, UART_BAUD_RATE_56000);
break;
case 115200:
KS8695P_UART_REG_WRITE(pChan, REG_UART_DIVISOR, UART_BAUD_RATE_115200);
break;
default:
KS8695P_UART_REG_WRITE(pChan, REG_UART_DIVISOR, UART_BAUD_RATE_9600);
break;
}
/*
* Set word format, enable FIFOs: set 8 bits, 1 stop bit, no parity.
* This also latches the writes to the two (sub)registers above.
*/
KS8695P_UART_REG_WRITE(pChan, REG_UART_LINE_CTRL, 0);
KS8695P_UART_REG_BIT_SET(pChan, REG_UART_LINE_CTRL,REG_URLC_8_BIT);
intUnlock (oldlevel);
break;
case SIO_BAUD_GET:
/* Get the baud rate and return OK */
*(int *)arg = pChan->baudRate;
break;
case SIO_MODE_SET:
/*
* Set the mode (e.g., to interrupt or polled). Return OK
* or EIO for an unknown or unsupported mode.
*/
if ((arg != SIO_MODE_POLL) && (arg != SIO_MODE_INT))
{
status = EIO;
break;
}
oldlevel = intLock ();
if (arg == SIO_MODE_INT)
{
/* Ensure that only Receive ints are generated. */
intEnable (INT_LVL_UTS);
intEnable (INT_LVL_URS);
/*
* There is no point in enabling the Tx interrupt, as it
* will interrupt immediately and be disabled.
*/
}
else
{
/* Disable all interrupts for this UART. */
intDisable (INT_LVL_UTS);
intDisable (INT_LVL_URS);
}
pChan->channelMode = arg;
intUnlock (oldlevel);
break;
case SIO_MODE_GET:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -