www.pudn.com > 860bsp.rar > scc2Modem.c
#include "copyright_wrs.h"
#include "vxWorks.h"
#include "iv.h"
#include "intLib.h"
#include "config.h"
#include "sysLib.h"
#include "rngLib.h"
#include "drv/sio/ppc860Sio.h"
#include "drv/multi/ppc860Cpm.h"
#include "bsc860.h"
#include "scc2Modem.h"
static STATUS scc2ModemIoctl (PPC860SCC2MODEM_CHAN *pChan,int request,int arg);
static void scc2ModemResetChannel (PPC860SCC2MODEM_CHAN *pChan);
static int scc2ModemRead (PPC860SCC2MODEM_CHAN *,char*,int);
static int scc2ModemWrite (PPC860SCC2MODEM_CHAN *,char *,int);
static void scc2ModemInterrupt (PPC860SCC2MODEM_CHAN *);
static int scc2ModemOpen ( PPC860SCC2MODEM_CHAN *, char *, int);
static int scc2Read (PPC860SCC2MODEM_CHAN *,char*);
int scc2ModemDrvNum=0;
/*
scc2 uart channnel reset,it is not a function of the scc2 uart driver.It is same
as the function "scc2ModemInit()" in "sysSerial.c"
parameter: PPC860SCC_CHAN *pChan, all parameters of the uart channel belong to this
structure
return: none
*/
void scc2ModemResetChannel
(
PPC860SCC2MODEM_CHAN *pChan
)
{
int oldlevel = intLock (); /* lock interrupts */
UINT32 regBase;
int i=0;
pChan->clockRate = BRGCLK_FREQ;
pChan->regBase = vxImmrGet();
regBase =pChan->regBase;
pChan->bgrNum = 3;
pChan->uart.sccNum = 2;
pChan->uart.txBdNum = SCC2MODEM_TXBDNUM;
pChan->uart.rxBdNum = SCC2MODEM_RXBDNUM;
pChan->uart.txBdBase = (SCC_BUF *)(0x2a00);/*bd结构*/
pChan->uart.rxBdBase = (SCC_BUF *)(0x2b00); /*bd结构*/
pChan->uart.txBufSize = SCC2MODEM_TXBUFFER;
pChan->uart.rxBufSize = SCC2MODEM_RXBUFFER;
pChan->uart.pScc = (SCC *) ((UINT32) PPC860_DPR_SCC2
(MPC860_DPRAM_BASE (regBase))) ;
pChan->uart.pSccReg = (SCC_REG *)((UINT32) MPC860_GSMR_L2 (regBase));
pChan->uart.pSccReg->sccm = 0;
pChan->pBaud = (UINT32 *) ((UINT32) MPC860_BRGC3 (regBase));
pChan->channelMode = 0; /*中断或轮询*/
*(pChan->pBaud)=0x0001028c; /*50M/9600/16=326=0x146,产生9600波特率*/
*MPC860_SICR(regBase)&=0xffff00ff;
*MPC860_SICR(regBase)|=0x00001200; /*brg3,NMSI*/
*MPC860_SDCR(regBase) =0x00000001; /*Normal mode*/
pChan->uart.pScc->param.tbase=SCC2_RBASE_OFFSET; /*0xa00*/
pChan->uart.pScc->param.rbase=SCC2_TBASE_OFFSET; /*0xb00*/
*MPC860_CPCR(regBase)=0x0041; /*write value to rbptr and tbptr*/
pChan->uart.pScc->param.rfcr=0x10; /*normal*/
pChan->uart.pScc->param.tfcr=0x10; /*normal*/
pChan->uart.pScc->param.mrblr=SCC2MODEM_RXBUFFER; /*maxium buffer 16 bytes*/
*SCC_MAX_IDL((UINT32)PPC860_DPR_SCC2(MPC860_DPRAM_BASE (regBase)))=0x0000;
*SCC_BRKCR((UINT32)PPC860_DPR_SCC2(MPC860_DPRAM_BASE (regBase)))=0x00011;
/*only one break charcter*/
*SCC_PAREC((UINT32)PPC860_DPR_SCC2(MPC860_DPRAM_BASE (regBase)))=0x0000;
*SCC_FRMEC((UINT32)PPC860_DPR_SCC2(MPC860_DPRAM_BASE (regBase)))=0x0000;
*SCC_NOSEC((UINT32)PPC860_DPR_SCC2(MPC860_DPRAM_BASE (regBase)))=0x0000;
*SCC_BRKEC((UINT32)PPC860_DPR_SCC2(MPC860_DPRAM_BASE (regBase)))=0x0000;
/*clear parec, frmec ,nosec , brkec*/
*SCC_UADDR1((UINT32)PPC860_DPR_SCC2(MPC860_DPRAM_BASE (regBase)))=0x0000;
*SCC_UADDR2((UINT32)PPC860_DPR_SCC2(MPC860_DPRAM_BASE (regBase)))=0x0000;
/*clear UADDR1, UADDR2*/
*SCC_TOSEQ((UINT32)PPC860_DPR_SCC2(MPC860_DPRAM_BASE (regBase)))=0x0000;
/*clear TOSEQ*/
*SCC_CHARACTER1((UINT32)PPC860_DPR_SCC2(MPC860_DPRAM_BASE (regBase)))=0x8000;
*SCC_CHARACTER2((UINT32)PPC860_DPR_SCC2(MPC860_DPRAM_BASE (regBase)))=0x8000;
*SCC_CHARACTER3((UINT32)PPC860_DPR_SCC2(MPC860_DPRAM_BASE (regBase)))=0x8000;
*SCC_CHARACTER4((UINT32)PPC860_DPR_SCC2(MPC860_DPRAM_BASE (regBase)))=0x8000;
*SCC_CHARACTER5((UINT32)PPC860_DPR_SCC2(MPC860_DPRAM_BASE (regBase)))=0x8000;
*SCC_CHARACTER6((UINT32)PPC860_DPR_SCC2(MPC860_DPRAM_BASE (regBase)))=0x8000;
*SCC_CHARACTER7((UINT32)PPC860_DPR_SCC2(MPC860_DPRAM_BASE (regBase)))=0x8000;
*SCC_CHARACTER8((UINT32)PPC860_DPR_SCC2(MPC860_DPRAM_BASE (regBase)))=0x8000;
/*clear from character1 to character8 */
*SCC_RCCM((UINT32)PPC860_DPR_SCC2(MPC860_DPRAM_BASE (regBase)))=0xc0ff;
/*set rccm*/
/*初始化BD*/
for(i=0;iuart.txBdBase[i].statusMode = BD_TX_INTERRUPT_BIT;
pChan->uart.txBdBase[i].dataPointer = pChan->uart.txBufBase +
(i * pChan->uart.txBufSize);
pChan->uart.txBdBase[i].dataLength=0;
}
pChan->uart.txBdBase[(i - 1)].statusMode |= BD_TX_WRAP_BIT;
pChan->uart.txBdNext = 0;
for(i=0;iuart.rxBdBase[i].statusMode = BD_RX_INTERRUPT_BIT|BD_RX_EMPTY_BIT ;
pChan->uart.rxBdBase[i].dataPointer =pChan->uart.rxBufBase +
(i * pChan->uart.rxBufSize);
pChan->uart.rxBdBase[i].dataLength=0;
}
pChan->uart.rxBdBase[(i - 1)].statusMode |= BD_RX_WRAP_BIT;
pChan->uart.rxBdNext = 0;
pChan->uart.pSccReg->scce=0xffff;
/*clear all previous events*/
pChan->uart.pSccReg->sccm=0x0003;
/* enable TX and Rx interrupts*/
*MPC860_CIMR(regBase)|=0x20000000;
/*scc2 allowed to generate a sysytem interrupt*/
*MPC860_CICR(regBase)|=0x00000000;
/*set cmp interrupt level ,default level 4*/
pChan->uart.pSccReg->gsmrh=0x00000020;
/*a small Rx FIFO width*/
pChan->uart.pSccReg->gsmrl=0x00028004;
/*uart mode ,normal operate*/
pChan->uart.pSccReg->psmr=0xb000;
/*automatic flow control
8 bit characters
no parity
1 stop bit
asynchronous SCC UART operation*/
pChan->uart.pSccReg->gsmrl|=SCC_GSMRL_ENT|SCC_GSMRL_ENR;
/*enable transmitter
enable receiver
*/
intUnlock (oldlevel);
/* UNLOCK INTERRUPTS */
}
/* driver function table */
/* 打开一个多通道HDLC设备 */
/*
参数:1、PPC860SCC2MODEM_CHAN *pchan:此设备的数据结构,是联系驱动程序和I/O设备的纽带,所有
的调用都要通过此结构体来完成用户需要。
2、char * remainder:保留参数,没有使用,因此必须为0
3、 int mode:打开模式,没有使用,必须为0
返回值:设备数据结构的值
*/
int scc2ModemOpen
(
PPC860SCC2MODEM_CHAN *pChan,
char * remainder,
int mode
)
{
/* serial devices should have no file name part */
if (remainder[0] != 0)
return (ERROR);
else
return ((int) pChan);
}
/*
SCC2口发送数据函数,该发送过程采用写满一个缓冲区,发送一个缓冲区的形式,如果当前待写入的缓冲区
正处于发送状态,程序会等待10000个循环,如果还没有将数据发送完成,返回错误,如果要发送的数据量
比较大的时候,可能需要等待的更长时间。
参数:PPC860SCC2MODEM_CHAN *pChan,这个设备的数据结构
char *buffer,待发送的数据指针
int bufferLen 待发送的数据长度
返回值:EAGAIN,数据发送失败
OK,数据发送成功
*/
int scc2ModemWrite
(
PPC860SCC2MODEM_CHAN *pChan,
char *buffer,
int bufferLen
)
{
int i=0,j=0,k=0;
int activeTxBd=pChan->uart.txBdNext;
if (pChan->uart.txBdBase[activeTxBd].statusMode &BD_TX_READY_BIT)
return(EAGAIN);
/*如果有未发送数据,返回错误*/
pChan->uart.pSccReg->scce = SCCE_TX;
/*reset the transmiter status bit */
for(i=0,j=0;iuart.txBdBase[activeTxBd].statusMode &BD_TX_READY_BIT))
/*is this buffer ready ?*/
pChan->uart.txBdBase[activeTxBd].dataPointer[j]=buffer[i];
else
{
while((pChan->uart.txBdBase[activeTxBd].statusMode &BD_TX_READY_BIT)|(k<10000))
k++;
if(pChan->uart.txBdBase[activeTxBd].statusMode &BD_TX_READY_BIT)
/*after 1000 loops,is the tx buffer OK ?*/
return(i);
else
pChan->uart.txBdBase[activeTxBd].dataPointer[j]=buffer[i];
}
if(j>=(pChan->uart.txBufSize)) /*this buffer load full*/
{
pChan->uart.txBdBase[activeTxBd].dataLength=j+1;
/*data length is j+1*/
pChan->uart.txBdBase[activeTxBd].statusMode|=BD_TX_READY_BIT;
/*transmiter this buffer*/
activeTxBd=(activeTxBd+1)%(pChan->uart.txBdNum);
/*point to next BD*/
j=0;
}
}
pChan->uart.txBdBase[activeTxBd].dataLength=j+1;
/*data length is j+1*/
pChan->uart.txBdBase[activeTxBd].statusMode|=BD_TX_READY_BIT;
/*transmiter this buffer*/
activeTxBd=(activeTxBd+1)%(pChan->uart.txBdNum);
/*point to next BD*/
return(bufferLen);
/*all data is transmitered*/
}
/*
读取SCC2口数据,采用轮询方式,检查所有的接收缓冲区,取走所有的数据
参数:PPC860SCC2MODEM_CHAN *pChan,这个设备的数据结构
char *buffer,读取数据的指针
int bufferLen,读取数据的长度
返回值:1、EAGIAN, 无数据或读取失败
2、
*/
int scc2Read
(
PPC860SCC2MODEM_CHAN *pChan,
char *buffer
)
{
int activeRxBd=pChan->uart.rxBdNext;
int i=0,j=0;
int tempLen=0;
int bufLen=0;
if (!(pChan->uart.pSccReg->scce & SCCE_RX))
return (EAGAIN);
pChan->uart.pSccReg->scce|=SCCE_RX;
while(!(pChan->uart.rxBdBase[activeRxBd].statusMode & BD_RX_EMPTY_BIT))
{
tempLen=pChan->uart.rxBdBase[activeRxBd].dataLength;
for(j=0;juart.rxBdBase[activeRxBd].dataPointer[j];
}
/*load this buffer*/
pChan->uart.rxBdBase[activeRxBd].statusMode |=BD_RX_EMPTY_BIT;
/*set this buffer empty*/
bufLen=bufLen+tempLen;
/*count the buffer length*/
pChan->uart.pSccReg->scce|=SCCE_RX;
activeRxBd=(activeRxBd+1)%(pChan->uart.rxBdNum);
/*point to next BD*/
}
return(bufLen);
}
/*
读取SCC2口数据
参数:PPC860SCC2MODEM_CHAN *pChan,这个设备的数据结构
char *buffer,读取数据的指针
int bufferLen,读取数据的长度
返回值:1、EAGIAN, 无数据或读取失败
2、OK,读取成功
*/
int scc2ModemRead
(
PPC860SCC2MODEM_CHAN *pChan,
char *buffer,
int maxBufLen
)
{
int bufLen;
bufLen=rngBufGet(pChan->scc2RingId,buffer,maxBufLen);
return(bufLen);
}
/*
SCC2中断服务程序,检查所有的接收缓冲区,取走所有的数据,然后将收到的数据发送到消息队列中
参数:PPC860SCC2MODEM_CHAN *pChan,这个设备的数据结构
返回值:无
*/
void scc2ModemInterrupt
(
PPC860SCC2MODEM_CHAN *pChan
)
{
char buffer[2*SCC2MODEM_RXBDNUM*SCC2MODEM_RXBUFFER];
int bufferLen;
if((bufferLen=scc2Read(pChan,buffer))!=0)
rngBufPut(pChan->scc2RingId,buffer,bufferLen);
pChan->uart.pSccReg->scce = (pChan->uart.pSccReg->scce&~(SCCE_RX|SCCE_TX));
*CISR(pChan->regBase)|=CISR_SCC2;
/*中断服务程序结束*/
}
/*
通道控制函数,用来改变通道的工作参数
参数:PPC860SCC2MODEM_CHAN *pChan,这个设备的数据结构
int request,包括:
1、SIO_BAUD_SET,设置波特率,arg代表波特率的数值,从50到115200
2、SIO_BAUD_GET,获取当前通道的波特率值,arg代表当前通道波特率的数值
3、SIO_MODE_SET,通道模式设置,arg参数有两种,SIO_MODE_POLL为轮询
方式,SIO_MODE_INT为中断方式
4、SIO_MODE_GET,获取当前通道的工作模式,arg代表当前的工作模式
5、SIO_AVAIL_MODES_GET,获取当前可供选择的通道工作模式,arg代表获取的
所有工作模式
int arg,根据不同的request的值,有不同的含义
返回值:错误代码
*/
STATUS scc2ModemIoctl
(
PPC860SCC2MODEM_CHAN *pChan,
int request,
int arg
)
{
int baudRate;
int oldlevel;
STATUS status = OK;
switch (request)
{
case SIO_BAUD_SET:
if (arg >= 50 && arg <= 115200)
{
/* 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)
scc2ModemResetChannel(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) |= CISR_SCC2;
* CIMR(pChan->regBase) |= CISR_SCC2;
pChan->uart.pSccReg->scce = SCCE_RX;
/* reset the receiver status bit */
pChan->uart.pSccReg->sccm =0x0001;
/* enables receive interrupts */
}
else
{
pChan->uart.pSccReg->sccm = 0;
/* mask off the receive and transmit intrs */
* CIMR(pChan->regBase) &= (~ CISR_SCC2);
/* mask off this SMC's interrupt */
}
pChan->channelMode = arg;
intUnlock(oldlevel);
break;
case SIO_MODE_GET:
* (int *) arg = pChan->channelMode;
break;
case SIO_AVAIL_MODES_GET:
*(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
break;
default:
status = ENOSYS;
}
return (status);
}
/*
scc2 uart 设备安装,主要调用iosDrvInstall()完成
参数:无
返回值:无
*/
STATUS scc2ModemDrv( void )
{
/* check if driver already installed */
if (scc2ModemDrvNum > 0)
return (OK);
scc2ModemDrvNum=iosDrvInstall (scc2ModemOpen, (FUNCPTR) NULL,
scc2ModemOpen,(FUNCPTR) NULL,
scc2ModemRead, scc2ModemWrite, scc2ModemIoctl);
return (scc2ModemDrvNum == ERROR ? ERROR : OK);
}
/*
scc2 uart 设备安装
参数:PPC860SCC2MODEM_CHAN *pChan,这个设备的数据结构
char * name,设备的名称
FAST int channel,设备的物理通道号,只有一个,只能为1
返回值:错误,没安装成功
正确
*/
STATUS scc2ModemDevCreate
(
PPC860SCC2MODEM_CHAN *pChan,
char * name, /* name to use for this device */
FAST int channel /* physical channel for this device */
)
{
if (scc2ModemDrvNum <= 0)
{
return (ERROR);
}
/* if this doesn't represent a valid channel, don't do it */
if(channel < 0)
return (ERROR);
/* if this device already exists, don't create it */
if (pChan->creatFlag)
return (ERROR);
pChan->uart.pSccReg->gsmrl|=SCC_GSMRL_ENT|SCC_GSMRL_ENR;
/*enable transmitter
enable receiver
uart should be enabled after the driver is installed*/
/* mark the device as created, and add the device to the I/O system */
pChan->creatFlag = TRUE;
return (iosDevAdd (pChan->devHdr, name, scc2ModemDrvNum));
/*scc2 uart driver is finished installing*/
/*writen by d.c.peng,8.5,2001*/
}