📄 sccahdlcdrv.c
字号:
void sccParaInit(SCC_AHDLC_DEV *pSccDev){ volatile SCC_AHDLC_PARAM * pPram; pPram = pSccDev->pscc_params; /* rx/tx BD table base address -- offset from the beginning of dual-port RAM */ pPram->param.rbase = pSccDev->recvBD_base; pPram->param.tbase = pSccDev->transBD_base; pPram->param.rfcr = 0x10; /*Big-endian or true little-endian.*/ pPram->param.tfcr = 0x10; /*Big-endian or true little-endian.*/ pPram->param.mrblr = SCC_AHDLC_MRBLR; pPram->param.rstate = 0; pPram->param.res1 = 0; pPram->param.rbptr = 0; pPram->param.res2 = 0; pPram->param.res3 = 0; pPram->param.tstate = 0; pPram->param.res4 = 0; pPram->param.tbptr = 0; pPram->param.res5 = 0; pPram->param.res6 = 0; pPram->param.rcrc = 0; pPram->param.tcrc = 0; pPram->c_mask = CRC_16_MASK; pPram->c_pres = CRC_16_PRES; pPram->bof = 0x7e; pPram->eof = 0x7e; pPram->esc = 0x7d; pPram->zero = 0; pPram->rfthr = 1; pPram->txctl_tbl =0; pPram->rxctl_tbl =0; pPram->nof = 0; debug(("pPram->param.rfcr = 0x%x , addr = 0x %x \n " , pPram->param.rfcr,&pPram->param.rfcr ) ); if( _eSCCSuccess != sccCpcrCommand(CPCR_OPCODE_INITTR_PARA, pSccDev) ) { debug(( " sccCpcrCommand error \n ")); return; } else { debug(( " sccCpcrCommand Success \n ")); }}/* * sccRegInit(sccno) */void sccRegInit(SCC_AHDLC_DEV *pSccDev){ /* clear any previous event */ pSccDev->pscc_regs->scce = 0xffff; /* write to SCCM to allow interrupt of RXB TXB RXF and BSY */ pSccDev->pscc_regs->sccm = SCC_AHDLC_SCCE_RXB | SCC_AHDLC_SCCE_TXB | SCC_AHDLC_SCCE_RXF | SCC_AHDLC_SCCE_BSY; /* Write 0x0000_0000 to GSMR_Hx to enable normal CTS and CD behavior with idles (not flags) between frames. */ pSccDev->pscc_regs->gsmrh = 0x00000000; /* Write 0x0000_0000 to GSMR_L2 to configure CTS and CD to control transmission and reception in HDLC mode.*/ pSccDev->pscc_regs->gsmrl = SCC_GSMRL_AHDLC | SCC_AHDLC_CLCMODE_16 |0x20000000; pSccDev->pscc_regs->psmr = AHDLC_PSMR_CHLN ; /* no flow control.*/ debug(("gsmrl = %x \n " , pSccDev->pscc_regs->gsmrl )); /* pSccDev->pBaud = BRGC4(pSccDev->immrVal) ;*/ *pSccDev->pBaud = 0; *pSccDev->pBaud |= (650<<1 ); /* 0x145 set baudrate 9600*/ /* or 650*/ *pSccDev->pBaud |= 0 ;/*BRGC_DIV16;*/ *pSccDev->pBaud |= BRGC_EN; debug(("BRG4 = %x \n " , *BRGC4(pSccDev->immrVal))); /* Write to interrupt mask register (CIMR) to allow SCCx to generate a system interrupt.*/ *CIMR(pSccDev->immrVal) |= CIMR_SCC4;}/* * SCC4 interrupt service routine */void scc4hdlcISR(int dev){ INT16 event; BUFM_BUF * rbuf_p; SCC_AHDLC_BD * pBD; int len; int i; SCC_AHDLC_DEV * pSccDev =( SCC_AHDLC_DEV *) dev ; /* read the interrupt event */ event = pSccDev->pscc_regs->scce; /* clear the event */ pSccDev->pscc_regs->scce = event; /* statistics */ /* pSccDev->statistics.numIsrEnter++; */ if(event & SCC_AHDLC_SCCE_RXF) { pBD = &pSccDev->precv_BD[pSccDev->current_rBD]; while( 0 == (AHDLC_BD_RX_EMPTY_BIT & pBD->statusMode )) { if( pBD->statusMode & (AHDLC_BD_RX_BREAK_BIT | AHDLC_BD_RX_FRAME_CLOSE_BIT | AHDLC_BD_RX_AB_BIT | AHDLC_BD_RX_CR_BIT | AHDLC_BD_RX_OV_BIT )) { if ( pBD->statusMode &AHDLC_BD_RX_CR_BIT ) { pSccDev->statistics.pnumCrcec++; #if 0 logMsg(" %x ,len :%d num %d,add 0x%x\n" , pBD->statusMode ,pBD->dataLength ,pSccDev->current_rBD,(int)pBD->dataPointer); for(i =0; i< pBD->dataLength ; i++) { logMsg(" %x\n" ,pBD->dataPointer[i] ); } logMsg(" end\n "); #endif #ifdef AHDLC_CRC16 rbuf_p = &pSccDev->usr_recv_buf[pSccDev->rbuf_wptr]; if( 0 == rbuf_p->status) /* there are free bufs */ { len = pBD->dataLength ; rbuf_p->needcrc = 1; debug(( " scc4hdlcISR pSccDev->current_rBD =%d, pBD->dataLength = %d , len =%d, rbuf_wptr =%d \n " , pSccDev->current_rBD,pBD->dataLength ,len, pSccDev->rbuf_wptr)); bcopy( (const char *)pBD->dataPointer, (char *)rbuf_p->body, len); rbuf_p->len = len; rbuf_p->status = 1; pBD->dataLength =0; pSccDev->rbuf_wptr++; if(pSccDev->rbuf_wptr >= SCC_AHDLC_RECV_BUF_NUM) pSccDev->rbuf_wptr = 0; pSccDev->ready_to_read = TRUE; selWakeupAll( &pSccDev->selWakeupkist , SELREAD); semGive( pSccDev->readSem ); } #endif } else if ( pBD->statusMode &AHDLC_BD_RX_BREAK_BIT ) { pSccDev->statistics.rx_break++; } else if ( pBD->statusMode &AHDLC_BD_RX_FRAME_CLOSE_BIT ) { pSccDev->statistics.rx_frame_close++; } else if ( pBD->statusMode &AHDLC_BD_RX_AB_BIT ) { pSccDev->statistics.rx_ab++; } else if ( pBD->statusMode &AHDLC_BD_RX_OV_BIT ) { pSccDev->statistics.rxov++; } pSccDev->statistics.total++; } else /*if( (pBD->statusMode & BD_RX_FIRSTFRAME_BIT ) == BD_RX_FIRSTFRAME_BIT ) */ { rbuf_p = &pSccDev->usr_recv_buf[pSccDev->rbuf_wptr]; if( 0 == rbuf_p->status) /* there are free bufs */ { pSccDev->statistics.recive++; len = pBD->dataLength ; debug(( " scc4hdlcISR pSccDev->current_rBD =%d, pBD->dataLength = %d , len =%d, rbuf_wptr =%d \n " , pSccDev->current_rBD,pBD->dataLength ,len, pSccDev->rbuf_wptr)); bcopy( (const char *)pBD->dataPointer, (char *)rbuf_p->body, len); rbuf_p->len = len; rbuf_p->status = 1; pBD->dataLength =0; pSccDev->rbuf_wptr++; if(pSccDev->rbuf_wptr >= SCC_AHDLC_RECV_BUF_NUM) pSccDev->rbuf_wptr = 0; pSccDev->ready_to_read = TRUE; selWakeupAll( &pSccDev->selWakeupkist , SELREAD); semGive( pSccDev->readSem ); } } /* prepare the BD for next recv*/ if( pBD->statusMode & AHDLC_BD_RX_WRAP_BIT) { pSccDev->current_rBD = 0; pBD->statusMode = AHDLC_BD_RX_WRAP_BIT | AHDLC_BD_RX_EMPTY_BIT | AHDLC_BD_RX_INTERRUPT_BIT; } else { pSccDev->current_rBD++; pBD->statusMode = AHDLC_BD_RX_EMPTY_BIT | AHDLC_BD_RX_INTERRUPT_BIT; } /* check the next BD */ pBD = &pSccDev->precv_BD[pSccDev->current_rBD]; } } if(event & SCC_AHDLC_SCCE_TXB) { pSccDev->statistics.sent++; #ifdef AHDLC_USE_TIME3 timer3Enable( ); #else AHDLC_RX_CS(); semGive ( sccDev[0].writeSem ); sccDev[0].ready_to_write =TRUE; selWakeupAll( &sccDev[0].selWakeupkist , SELWRITE); #endif } }/* * sccHdlcEnable(sccno) * Enable scc. */void sccHdlcEnable(SCC_AHDLC_DEV * pSccDev ){ /* pend interrupt service routine */ #if 0 if(0 == sccno) (void) intConnect (IV_SCC3, (VOIDFUNCPTR) scc3hdlcISR, 0); else #endif (void) intConnect (IV_SCC4, (VOIDFUNCPTR) scc4hdlcISR, (int) pSccDev ); /* Write 0x00000030 to GSMR_L2 to enable the transmitter and receiver.*/ pSccDev->pscc_regs->gsmrl |= SCC_GSMRL_AHDLC | SCC_GSMRL_ENT | SCC_GSMRL_ENR| 0x20000000;/* | SCC_GSMRL_DIAG_LOOP;*/ }void sccHdlcDisable(SCC_AHDLC_DEV * pSccDev ){ /* pend interrupt service routine */ #if 0 if(0 == sccno) (void) intConnect (IV_SCC3, (VOIDFUNCPTR) scc3hdlcISR, 0); else #endif pSccDev->pscc_regs->gsmrl &= (~(SCC_GSMRL_ENT | SCC_GSMRL_ENR ) ) ;/* | SCC_GSMRL_DIAG_LOOP;*/}/********************************************************************************* ahdlcDrv - initialize the AHDLC driver** SEE ALSO: ahdlcDevCreate()*/STATUS ahdlcDrv ( ) { int i; /* check if driver already installed */ if (ahdlcDrvNum > 0) return (OK); if ( ( ahdlcDrvNum = iosDrvInstall (ahdlcOpen, (FUNCPTR) NULL, ahdlcOpen, ahdlcClose, ahdlcRead, ahdlcWrite, ahdlcIoctl) ) == ERROR) return (ERROR); return (OK); }/********************************************************************************* ahdlcDevCreate - create a device for an AHDLC port** This routine creates a device for a specified AHDLC port. Each port* to be used should have exactly one device associated with it by calling* this routine.** For instance, to create the device `/ahdlc/0', the proper call would be:* .CS* ahdlcDevCreate ("/ahdlc/0", 0);* .CE** RETURNS: OK, or ERROR if the driver is not installed, the channel is* invalid, or the device already exists.** SEE ALSO: ahdlcDrv()*/STATUS ahdlcDevCreate ( char *devName /* name to use for this device */ ){ SCC_AHDLC_DEV * pSccDev; if (ahdlcDrvNum < 1) { errnoSet (_eSCCNoDriver); return (ERROR); } /************************initiian start***********************************************/ pSccDev = sccDev; /* clear sccDev */ memset( pSccDev , 0 , sizeof(SCC_AHDLC_DEV) ); selWakeupListInit ( & pSccDev ->selWakeupkist); init_ports(); pSccDev->immrVal = vxImmrGet(); debug(("pSccDev->immrVal = %x \n" , pSccDev->immrVal )); /*分配用户缓冲区*/ pSccDev->usr_recv_buf = usrbuf ; memset( ( char * ) pSccDev->usr_recv_buf , 0, sizeof(BUFM_BUF)*SCC_AHDLC_RECV_BUF_NUM); /* 初始化BD 缓冲区指针*/ #ifdef USE_DMA if(NULL == (pSccDev->ptran_buf_malloc_address = (unsigned char *)cacheDmaMalloc(SCC_AHDL_FRAME_SIZE*SCC_NUM_TBD ))) { errnoSet (_eSCCNoCachMemory); debug((" cacheDmaMalloc: ptran_buf_malloc_address errot \n")); goto errExit; } if(NULL == (pSccDev->precv_buf_malloc_address = (unsigned char *)cacheDmaMalloc(SCC_AHDL_FRAME_SIZE*SCC_NUM_RBD ))) { errnoSet (_eSCCNoCachMemory); debug((" cacheDmaMalloc: precv_buf_malloc_address errot \n")); goto errExit; } pSccDev->ptran_buf_base = (unsigned char*) ( (unsigned int ) pSccDev->ptran_buf_malloc_address ); pSccDev->precv_buf_base = (unsigned char*) ( (unsigned int ) pSccDev->precv_buf_malloc_address); #else pSccDev->ptran_buf_base = (unsigned char *) txpbbuf ; pSccDev->precv_buf_base = (unsigned char *) rxpbbuf ; #endif /* 初始化参数寄存器指针*/ pSccDev->pscc_params = (volatile SCC_AHDLC_PARAM *)(MPC860_DPR_SCC4(pSccDev->immrVal)); pSccDev->pscc_regs = (volatile SCC_REG *)(GSMR_L4(pSccDev->immrVal)); /*初始化波特率寄存器指针*/ pSccDev->pBaud = BRGC4(pSccDev->immrVal); /* 初始化 发送和接收BD 指针*/ pSccDev->transBD_base = SCC4_AHDLC_BD_BASE; pSccDev->ptran_BD = (SCC_AHDLC_BD *)(SCC4_AHDLC_BD_BASE + pSccDev->immrVal); pSccDev->current_tBD = 0; pSccDev->recvBD_base = SCC4_AHDLC_BD_BASE + SCC_BD_SZ*SCC_NUM_TBD; pSccDev->precv_BD = (SCC_AHDLC_BD *)(SCC4_AHDLC_BD_BASE + pSccDev->immrVal + SCC_BD_SZ*SCC_NUM_TBD); pSccDev->current_rBD = 0; init_tranBD(pSccDev); init_recvBD(pSccDev); sccParaInit(pSccDev); /* initialize parameter of hdlc */ sccRegInit(pSccDev); /* initialize registers of HDLC */ #ifdef AHDLC_USE_TIME3 timer3initial( ); #endif debug(( "sccDevCreate finished \n " ));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -