📄 ppc860sioscc.c
字号:
/* ppc860SioScc.c - Motorola MPC860 SCC UART serial driver */
/* Copyright 1984-1996 Wind River Systems, Inc. */
/* Copyright 1997 Motorola, Inc., All Rights Reserved */
#include "copyright_wrs.h"
/*
modification history
--------------------
01h,04feb98,kla hooks for SCC Serial devices com2,3 & 4.
01g,04apr97,srr setup to run on MPC860.
01f,28may96,dat fixed SPR #5526, baud rate divisor calculation
01e,10oct95,ms made poll input routine work if len(RX FIFO)>1 (SPR #5130).
01d,08sep95,myz fixed the SPR #4678
01c,20jun95,ms fixed comments for mangen
01b,15jun95,ms updated for new driver structure
01a,22may95,myz written (using m68360Serial.c).
*/
/*
DESCRIPTION
This is the driver for the SCC's in the internal Communications Processor (CP)
of the Motorola MPC860/821. This driver only supports the SCC's in asynchronous
UART mode.
USAGE
A PPC860SCC_CHAN structure is used to describe the chip.
The BSP's sysHwInit() routine typically calls sysSerialHwInit()
which initializes all the values in the PPC860SCC_CHAN structure (except
the SIO_DRV_FUNCS) before calling ppc860SccDevInit().
The BSP's sysHwInit2() routine typically calls sysSerialHwInit2() which
connects the chips interrupt (ppc860SccInt) via intConnect().
INCLUDE FILES: drv/sio/ppc860Sio.h
drv/multi/ppc860Siu.h
drv/multi/ppc860Cpm.h
*/
/* includes */
#include "vxWorks.h"
#include "intLib.h"
#include "errno.h"
#include "sioLib.h"
#if 1
#include "drv/multi/ppc860Siu.h"
#include "drv/multi/ppc860Cpm.h"
#include "drv/sio/ppc860Sio.h"
#else
#include "ppc860Siu.h"
#include "ppc860Cpm.h"
#include "ppc860Sio.h"
#endif
/* defines */
#define DEFAULT_BAUD 9600
/* forward declarations */
static STATUS ppc860SccIoctl (PPC860SCC_CHAN *pChan,int request,int arg);
static void ppc860SccResetChannel (PPC860SCC_CHAN *pChan);
static int ppc860SccPollOutput (SIO_CHAN *,char);
static int ppc860SccPollInput (SIO_CHAN *,char *);
static void ppc860SccStartup (PPC860SCC_CHAN *);
static int ppc860SccCallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);
/* local driver function table */
static SIO_DRV_FUNCS ppc860SccSioDrvFuncs =
{
(int (*)())ppc860SccIoctl,
(int (*)())ppc860SccStartup,
(int (*)())ppc860SccCallbackInstall,
(int (*)())ppc860SccPollInput,
(int (*)(SIO_CHAN *,char))ppc860SccPollOutput
};
/*******************************************************************************
*
* ppc860SccDevInit - initialize the SCC
*
* This routine is called to initialize the chip to a quiescent state.
*/
void ppc860SccDevInit
(
PPC860SCC_CHAN *pChan
)
{
/* masks off this SCC's interrupt. */
*CIMR(pChan->regBase) &=
(~(CIPR_SCC4 << (3 - (pChan->uart.sccNum - 1) )));
pChan->baudRate = DEFAULT_BAUD;
pChan->pDrvFuncs = &ppc860SccSioDrvFuncs;
}
/*******************************************************************************
*
* ppc860SccResetChannel - initialize the SCC
*/
static void ppc860SccResetChannel
(
PPC860SCC_CHAN *pChan
)
{
int scc; /* the SCC number being initialized */
int baud; /* the baud rate generator being used */
int frame;
int oldlevel = intLock (); /* LOCK INTERRUPTS */
scc = pChan->uart.sccNum - 1; /* get SCC number */
baud = pChan->bgrNum - 1; /* get BRG number */
pChan->uart.intMask = CIPR_SCC4 << (3 - scc);
/* set up SCC as NMSI */
*SICR(pChan->regBase) |= (UINT32) (baud << (scc << 3));
*SICR(pChan->regBase) |= (UINT32) ((baud << 3) << (scc << 3));
/* setup SCC as NMSI and clear SCC clock sources */
*SICR(pChan->regBase) &= ~( (1 << ((scc << 3) + 6)) | /* SICR_SCx_MUX */
((7 << 3) << (scc << 3)) | /* SICR_RxCS_MSK */
(7 << (scc << 3)) ); /* SICR_TxCS_MUX */
/* setup SCC clock sources */
*SICR(pChan->regBase) |= (((baud << 3) << (scc << 3)) | /* SICR_RxCS_BRGx */
(baud << (scc << 3))); /* SICR_TxCS_BRGx */
/* reset baud rate generator */
*pChan->pBaud |= BRGC_RST;
while (*pChan->pBaud & BRGC_RST);
ppc860SccIoctl (pChan, SIO_BAUD_SET, pChan->baudRate);
/* set up transmit buffer descriptors */
pChan->uart.txBdBase = (SCC_BUF *) (pChan->regBase + ((UINT32) pChan->uart.txBdBase));
pChan->uart.pScc->param.tbase = (UINT16) ((UINT32) pChan->uart.txBdBase);
pChan->uart.pScc->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 = SCC_UART_TX_BD_INT;
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 |= SCC_UART_TX_BD_WRAP;
/* set up receive buffer descriptors */
pChan->uart.rxBdBase = (SCC_BUF *) (pChan->regBase +
((UINT32) pChan->uart.rxBdBase));
pChan->uart.pScc->param.rbase = (UINT16) ((UINT32) pChan->uart.rxBdBase);
pChan->uart.pScc->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 = SCC_UART_RX_BD_EMPTY | SCC_UART_RX_BD_INT;
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 |= SCC_UART_TX_BD_WRAP;
/* set SCC attributes to UART mode */
pChan->uart.pSccReg->gsmrl = SCC_GSMRL_RDCR_X16 | SCC_GSMRL_TDCR_X16 | SCC_GSMRL_UART;
pChan->uart.pSccReg->gsmrh = SCC_GSMRH_RFW | SCC_GSMRH_TFL;
pChan->uart.pSccReg->psmr = SCC_UART_PSMR_FLC | SCC_UART_PSMR_CL_8BIT;
pChan->uart.pSccReg->dsr = 0x7e7e; /* no fractional stop bits */
pChan->uart.pScc->param.rfcr = 0x18; /* supervisor data access */
pChan->uart.pScc->param.tfcr = 0x18; /* supervisor data access */
pChan->uart.pScc->param.mrblr = 0x1; /* one character rx buffers */
/* initialize parameter the SCC RAM */
((SCC_UART_PROTO *)pChan->uart.pScc->prot)->maxIdl = 0x0;
((SCC_UART_PROTO *)pChan->uart.pScc->prot)->brkcr = 0x1;
((SCC_UART_PROTO *)pChan->uart.pScc->prot)->parec = 0x0;
((SCC_UART_PROTO *)pChan->uart.pScc->prot)->frmer = 0x0;
((SCC_UART_PROTO *)pChan->uart.pScc->prot)->nosec = 0x0;
((SCC_UART_PROTO *)pChan->uart.pScc->prot)->brkec = 0x0;
((SCC_UART_PROTO *)pChan->uart.pScc->prot)->uaddr1 = 0x0;
((SCC_UART_PROTO *)pChan->uart.pScc->prot)->uaddr2 = 0x0;
((SCC_UART_PROTO *)pChan->uart.pScc->prot)->toseq = 0x0;
((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character1 = 0x8000;
((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character2 = 0x8000;
((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character3 = 0x8000;
((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character4 = 0x8000;
((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character5 = 0x8000;
((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character6 = 0x8000;
((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character7 = 0x8000;
((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character8 = 0x8000;
((SCC_UART_PROTO *)pChan->uart.pScc->prot)->rccm = 0x8000;
pChan->uart.pSccReg->scce = 0xffff; /* clr events */
/* enables the transmitter and receiver */
pChan->uart.pSccReg->gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
/* unmask interrupt */
pChan->uart.pSccReg->sccm = SCC_UART_SCCX_RX | SCC_UART_SCCX_TX;
*CIMR(pChan->regBase) |= pChan->uart.intMask;
intUnlock (oldlevel); /* UNLOCK INTERRUPTS */
}
/*******************************************************************************
*
* ppc860SccIoctl - special device control
*
* RETURNS: OK on success, EIO on device error, ENOSYS on unsupported
* request.
*
*/
LOCAL STATUS ppc860SccIoctl
(
PPC860SCC_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 XXX
if (arg >= 50 && arg <= 38400) /* could go higher... */
{
/* 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) << BRGC_CD_SHIFT)) | BRGC_EN | BRGC_DIV16;
else
*pChan->pBaud = (BRGC_CD_MSK & (baudRate << 1)) | BRGC_EN;
}
#endif
#if 1
if (arg > 300)
{
baudRate = pChan->clockRate / (16 * arg);
*pChan->pBaud = (BRGC_CD_MSK & (baudRate << 1)) | BRGC_EN;
}
else /* set bit DIV16 for 300 & less */
{
baudRate = pChan->clockRate / (16 * 16 * arg);
*pChan->pBaud = (BRGC_CD_MSK & (baudRate << 1)) | BRGC_EN | BRGC_DIV16;
}
#endif
pChan->baudRate = arg;
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)
ppc860SccResetChannel(pChan);
/*
* if switching from POLL to INT mode, wait for all characters to
* clear the output pins
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -