📄 smc8260sio.c
字号:
/* smc8260Sio.c - Motorola MPC8260 SMC UART serial driver */
/* Copyright 1984-2001 Wind River Systems, Inc. */
#include "copyright_wrs.h"
/*
modification history
--------------------
01c,07may01,g_h rename to smc8260Sio.c
01b,26apr99,elk added SMC2.
01a,10mar99,elk adapted from ppc860Sio.c (ver 01b).
*/
/*
DESCRIPTION
This is the driver for the SMCs in the internal Communications Processor (CP)
of the Motorola MPC8260. This driver only supports the SMCs in
asynchronous UART mode.
USAGE
A PPC8260SMC_CHAN structure is used to describe the chip.
The BSP's sysHwInit() routine typically calls sysSerialHwInit(),
which initializes all the values in the PPC8260SMC_CHAN structure (except
the SIO_DRV_FUNCS) before calling smc8260DevInit().
The BSP's sysHwInit2() routine typically calls sysSerialHwInit2() which
connects the chip's interrupts via intConnect().
INCLUDE FILES: drv/sio/smc8260Sio.h
*/
/* includes */
#include "vxWorks.h"
#include "intLib.h"
#include "errno.h"
#include "sioLib.h"
#include "m8260Brg.h"
#include "smc8260Sio.h"
void bcopyLongs(char *source, char *destination, int nlongs);
/* defines */
#define DEFAULT_BAUD 9600
/* forward declarations */
static STATUS smc8260Ioctl (PPC8260SMC_CHAN *pChan,int request,int arg);
static void smc8260ResetChannel (PPC8260SMC_CHAN *pChan);
static int smc8260PollOutput (SIO_CHAN *,char);
static int smc8260PollInput (SIO_CHAN *,char *);
static void smc8260Startup (PPC8260SMC_CHAN *);
static int smc8260CallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);
/* local driver function table */
static SIO_DRV_FUNCS smc8260SioDrvFuncs =
{
(int (*)()) smc8260Ioctl,
(int (*)()) smc8260Startup,
smc8260CallbackInstall,
(int (*)()) smc8260PollInput,
(int (*)(SIO_CHAN *,char)) smc8260PollOutput
};
/*******************************************************************************
*
* smc8260DevInit - initialize the SMC
*
* This routine is called to initialize the chip to a quiescent state.
* Note that the `smcNum' field of PPC8260SMC_CHAN must be either 1 or 2.
*
* RETURNS: N/A.
*/
void smc8260DevInit
(
PPC8260SMC_CHAN *pChan
)
{
/* masks off this SMC's interrupt. */
*M8260_SIMR_L(pChan->regBase) &= (~(0x00001000 >> (pChan->uart.smcNum - 1)));
pChan->baudRate = DEFAULT_BAUD;
pChan->pDrvFuncs = &smc8260SioDrvFuncs;
}
/*******************************************************************************
*
* smc8260ResetChannel - initialize the SMC
*
* RETURNS: N/A.
*/
static void smc8260ResetChannel
(
PPC8260SMC_CHAN *pChan
)
{
int smc; /* the SMC number being initialized */
int baud; /* the baud rate generator being used */
int frame;
int oldlevel = intLock (); /* lock interrupts */
smc = pChan->uart.smcNum - 1; /* get SMC number */
baud = pChan->bgrNum - 1; /* get BRG number */
pChan->uart.intMask = 0x00001000 >> smc;
/* set up SMC as NMSI, select Baud Rate Generator */
if (smc == 0) /* SMC 1 */
{
* CMXSMR(pChan->regBase) &= 0x0f;
}
else /* SMC 2 */
{
* CMXSMR(pChan->regBase) &= 0xf0;
}
switch( baud )
{
default: /* default to BRG1 */
case 0: /* Select BRG1 */
* CMXSMR(pChan->regBase) |= (0x00 >> (4 * smc));
break;
case 1: /* Select BRG2 */
* CMXSMR(pChan->regBase) |= (0x00 >> (4 * smc));
break;
case 6: /* select BRG7 */
* CMXSMR(pChan->regBase) |= (0x10 >> (4 * smc));
break;
case 7: /* select BRG8 */
* CMXSMR(pChan->regBase) |= (0x10 >> (4 * smc));
break;
}
/* reset baud rate generator, wait for reset to clear... */
*pChan->pBaud |= M8260_BRGC_RST;
while (*pChan->pBaud & M8260_BRGC_RST);
smc8260Ioctl (pChan, SIO_BAUD_SET, pChan->baudRate);
/* set up transmit buffer descriptors */
pChan->uart.txBdBase = (SMC_BUF *) (pChan->regBase +
((UINT32) pChan->uart.txBdBase ));
pChan->uart.pSmc->param.tbase = (UINT16) ((UINT32) pChan->uart.txBdBase);
pChan->uart.pSmc->param.tbptr = (UINT16) ((UINT32) pChan->uart.txBdBase);
pChan->uart.txBdNext = 0;
/* initialize each transmit buffer descriptor */
for (frame = 0; frame < pChan->uart.txBdNum; frame++)
{
pChan->uart.txBdBase[frame].statusMode = BD_TX_INTERRUPT_BIT;
pChan->uart.txBdBase[frame].dataPointer = pChan->uart.txBufBase +
(frame * pChan->uart.txBufSize);
}
/* set the last BD to wrap to the first */
pChan->uart.txBdBase[(frame - 1)].statusMode |= BD_TX_WRAP_BIT;
/* set up receive buffer descriptors */
pChan->uart.rxBdBase = (SMC_BUF *) (pChan->regBase +
((UINT32) pChan->uart.rxBdBase ));
pChan->uart.pSmc->param.rbase = (UINT16) ((UINT32) pChan->uart.rxBdBase);
pChan->uart.pSmc->param.rbptr = (UINT16) ((UINT32) pChan->uart.rxBdBase);
pChan->uart.rxBdNext = 0;
/* initialize each receive buffer descriptor */
for (frame = 0; frame < pChan->uart.rxBdNum; frame++)
{
pChan->uart.rxBdBase[frame].statusMode = BD_RX_EMPTY_BIT |
BD_RX_INTERRUPT_BIT;
pChan->uart.rxBdBase[frame].dataLength = 1; /* char oriented */
pChan->uart.rxBdBase[frame].dataPointer = pChan->uart.rxBufBase + frame;
}
/* set the last BD to wrap to the first */
pChan->uart.rxBdBase[(frame - 1)].statusMode |= BD_RX_WRAP_BIT;
/* set SMC attributes to standard UART mode */
pChan->uart.pSmcReg->smcmr = SMCMR_STD_MODE;
/* initialize parameter RAM area for this SMC */
pChan->uart.pSmc->param.rfcr = 0x18; /* supervisor data access */
pChan->uart.pSmc->param.tfcr = 0x18; /* supervisor data access */
pChan->uart.pSmc->param.mrblr = 0x1; /* one character rx buffers */
pChan->uart.pSmc->param.maxidl = 0x0; /* no idle features */
pChan->uart.pSmc->param.brkln = 0x0; /* no breaks received yet */
pChan->uart.pSmc->param.brkec = 0x0; /* zero break condition ctr */
pChan->uart.pSmc->param.brkcr = 0x1; /* xmit 1 BRK on stop */
/* clear all events */
pChan->uart.pSmcReg->smce = SMCE_ALL_EVENTS;
/* enables the transmitter and receiver */
pChan->uart.pSmcReg->smcmr |= SMCMR_TEN | SMCMR_REN;
/* unmask interrupt (Tx, Rx only) */
pChan->uart.pSmcReg->smcm = SMCM_TX_MSK | SMCM_RX_MSK;
*M8260_SIMR_L(pChan->regBase) |= pChan->uart.intMask;
intUnlock (oldlevel); /* UNLOCK INTERRUPTS */
}
/*******************************************************************************
*
* smc8260Ioctl - special device control
*
* RETURNS: OK on success, EIO on device error, ENOSYS on unsupported
* request.
*
*/
LOCAL STATUS smc8260Ioctl
(
PPC8260SMC_CHAN * pChan, /* device to control */
int request, /* request code */
int arg /* some argument */
)
{
int baudRate;
int oldlevel;
STATUS status = OK;
switch (request)
{
case SIO_BAUD_SET:
if (arg >= SMC_MIN_BAUD && arg <= SMC_MAX_BAUD)
{
/* calculate proper counter value, then enable BRG */
baudRate = (pChan->clockRate + (8 * arg)) / (16 * arg);
if (--baudRate > 0xfff)
*pChan->pBaud = (BRGC_CD_MSK &
(((baudRate + 8) / 16) << M8260_BRGC_CD_SHIFT)) | M8260_BRGC_EN |
M8260_BRGC_DIV16;
else
*pChan->pBaud = (BRGC_CD_MSK &
(baudRate << 1)) | M8260_BRGC_EN;
pChan->baudRate = arg;
}
else
status = EIO;
break;
case SIO_BAUD_GET:
* (int *) arg = pChan->baudRate;
break;
case SIO_MODE_SET:
if (!((int) arg == SIO_MODE_POLL || (int) arg == SIO_MODE_INT))
{
status = EIO;
break;
}
/* lock interrupt */
oldlevel = intLock();
/* initialize channel on first MODE_SET */
if (!pChan->channelMode)
smc8260ResetChannel(pChan);
/*
* if switching from POLL to INT mode, wait for all characters to
* clear the output pins
*/
if ((pChan->channelMode == SIO_MODE_POLL) && (arg == SIO_MODE_INT))
{
int i;
for (i=0; i < pChan->uart.txBdNum; i++)
while (pChan->uart.txBdBase
[(pChan->uart.txBdNext + i) % pChan->uart.txBdNum].
statusMode & BD_TX_READY_BIT);
}
if (arg == SIO_MODE_INT)
{
* M8260_SIPNR_L(pChan->regBase) = pChan->uart.intMask;
/* reset the SMC's interrupt status bit */
* M8260_SIMR_L(pChan->regBase) |= pChan->uart.intMask;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -