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*/ 
}