📄 smc8260sio.c
字号:
/* smc8260Sio.c - Motorola MPC8260 SMC UART serial driver *//* Copyright 1984-2001 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01e,22oct01,g_h Clean warning.01d,12oct01,g_h Clean for T2.201c,07may01,g_h rename to smc8260Sio.c01b,26apr99,elk added SMC2.01a,10mar99,elk adapted from ppc860Sio.c (ver 01b).*//*DESCRIPTIONThis 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.USAGEA 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 (exceptthe SIO_DRV_FUNCS) before calling smc8260DevInit().The BSP's sysHwInit2() routine typically calls sysSerialHwInit2() whichconnects the chip's interrupts via intConnect().INCLUDE FILES: smc8260Sio.h*//* includes */#include "vxWorks.h"#include "intLib.h"#include "errno.h"#include "sioLib.h"#include "drv/mem/m8260Siu.h"#include "drv/sio/m8260Brg.h"#include "drv/sio/m8260Cp.h"#include "drv/sio/m8260CpmMux.h"#include "smc8260Sio.h"void bcopyLongs(char *source, char *destination, int nlongs);/* defines */#define DEFAULT_BAUD 9600/* forward declarations */LOCAL STATUS smc8260Ioctl (PPC8260SMC_CHAN *pChan,int request,int arg);LOCAL void smc8260ResetChannel (PPC8260SMC_CHAN *pChan);LOCAL int smc8260PollOutput (SIO_CHAN *,char);LOCAL int smc8260PollInput (SIO_CHAN *,char *);LOCAL void smc8260Startup (PPC8260SMC_CHAN *);LOCAL int smc8260CallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);/* local driver function table */LOCAL SIO_DRV_FUNCS smc8260SioDrvFuncs = { (int (*)()) smc8260Ioctl, (int (*)()) smc8260Startup, (int (*)()) 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 - reset the SMC channel** This routine reset the SMC channel** RETURNS: N/A.*/LOCAL 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 */ 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** This routine is the 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; /* enable this SMC's interrupt */ pChan->uart.pSmcReg->smce = SMCE_RX; /* reset the receiver status bit */ pChan->uart.pSmcReg->smcm = SMCM_RX_MSK | SMCM_TX_MSK; /* enables receive and transmit interrupts */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -