?? ppc860scc.c
字號:
#include "copyright_wrs.h"
/*
modification history
--------------------
2000.6.6 copy from ppc860sio.c
*/
/* includes */
#include "vxWorks.h"
#include "intLib.h"
#include "errno.h"
#include "sioLib.h"
#include "drv/multi/ppc860Siu.h"
#include "drv/multi/ppc860Cpm.h"
#include "drv/sio/ppc860Sio.h"
#include "mpc860p.h"
/* 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 ppc860SccDrvFuncs =
{
(int (*)()) ppc860SccIoctl,
(int (*)()) ppc860SccStartup,
ppc860SccCallbackInstall,
(int (*)()) ppc860SccPollInput,
(int (*)(SIO_CHAN *,char)) ppc860SccPollOutput
};
/******************************************************************************
*
*
* ppc860DevInit - initialize the SCC
*
* This routine is called to initialize the chip to a quiescent state.
* Note that the `smcNum' field of PPC860SCC_CHAN must be either 1 or 2.
*/
void ppc860SccDevInit
(
PPC860SCC_CHAN *pChan
)
{
/* masks off this SCC's interrupt. */
* CIMR(pChan->regBase) &= ~CIMR_SCC3 ;
pChan->baudRate = DEFAULT_BAUD;
pChan->pDrvFuncs = &ppc860SccDrvFuncs;
}
/******************************************************************************
*
*
* ppc860ResetChannel - initialize the SCC
*/
static void ppc860SccResetChannel
(
PPC860SCC_CHAN *pChan
)
{
int frame;
int oldlevel = intLock (); /* lock interrupts */
pChan->uart.intMask = CIMR_SCC3;
/* set up SCC3 as NMSI, select Baud Rate Generator */
* SICR(pChan->regBase) |= 0x00090000;
/* reset baud rate generator, wait for reset to clear... */
*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) SCC3_TBD_OFF;
pChan->uart.pScc->param.tbptr = (UINT16) SCC3_TBD_OFF;
pChan->uart.txBdNext = 0;
/* initialize each transmit buffer descriptor */
for (frame = 0; frame < pChan->uart.txBdNum; frame++)
{
pChan->uart.txBdBase[frame].statusMode = 0x9000;
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 |= 0x2000;
/* set up receive buffer descriptors */
pChan->uart.rxBdBase = (SCC_BUF *) (pChan->regBase +
((UINT32) pChan->uart.rxBdBase ));
pChan->uart.pScc->param.rbase = (UINT16) SCC3_RBD_OFF;
pChan->uart.pScc->param.rbptr = (UINT16) SCC3_RBD_OFF;
pChan->uart.rxBdNext = 0;
/* initialize each receive buffer descriptor */
for (frame = 0; frame < pChan->uart.rxBdNum; frame++)
{
pChan->uart.rxBdBase[frame].statusMode = 0x9000;
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 |= 0x2000;
/* set SCC attributes to standard UART mode */
pChan->uart.pSccReg->gsmrl = 0x00028004;
pChan->uart.pSccReg->gsmrh = 0x00000020;
pChan->uart.pSccReg->psmr = 0xb000;
/* initialize parameter RAM area for this SMC */
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 */
pChan->uart.pScc->proto.maxIdl = 0x0; /* maximum idle characters */
pChan->uart.pScc->proto.brkcr = 1; /* break count register (transmit) */
pChan->uart.pScc->proto.parec = 0; /* receive parity error counter */
pChan->uart.pScc->proto.frmer = 0; /* receive framing error counter */
pChan->uart.pScc->proto.nosec = 0; /* receive noise counter */
pChan->uart.pScc->proto.brkec = 0; /* receive break condition counter */
pChan->uart.pScc->proto.uaddr1 = 0; /* uart address character 1 */
pChan->uart.pScc->proto.uaddr2 = 0; /* uart address character 2 */
pChan->uart.pScc->proto.toseq = 0; /* transmit out-of-sequence character */
pChan->uart.pScc->proto.character1 = 0x8000;
pChan->uart.pScc->proto.character2 = 0x8000;
pChan->uart.pScc->proto.character3 = 0x8000;
pChan->uart.pScc->proto.character4 = 0x8000;
pChan->uart.pScc->proto.character5 = 0x8000;
pChan->uart.pScc->proto.character6 = 0x8000;
pChan->uart.pScc->proto.character7 = 0x8000;
pChan->uart.pScc->proto.character8 = 0x8000;
pChan->uart.pScc->proto.rccm = 0xc0ff;
/* clear all events */
pChan->uart.pSccReg->scce = 0x0067;
/* enables the transmitter and receiver */
pChan->uart.pSccReg->gsmrl = 0x00028034;
/* unmask interrupt (Tx, Rx only) */
pChan->uart.pSccReg->sccm = 0x0003;
*CIMR(pChan->regBase) |= pChan->uart.intMask;
intUnlock (oldlevel); /* UNLOCK INTERRUPTS */
}
/******************************************************************************
*
*
* ppc860Ioctl - 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 (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;
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)
ppc860SccResetChannel(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)
{
* CISR(pChan->regBase) = pChan->uart.intMask;
/* reset the SCC's interrupt status bit */
* CIMR(pChan->regBase) |= pChan->uart.intMask;
/* enable this SCC's interrupt */
pChan->uart.pSccReg->scce = 0x0001;
/* reset the receiver status bit */
pChan->uart.pSccReg->sccm = 0x0003;
/* enables receive and transmit interrupts */
}
else
{
pChan->uart.pSccReg->sccm = 0;
/* mask off the receive and transmit intrs */
* CIMR(pChan->regBase) &= (~(pChan->uart.intMask));
/* mask off this SCC's interrupt */
}
pChan->channelMode = arg;
intUnlock(oldlevel);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -