📄 z85230rhdlc.c
字号:
* Restart DMA with the next avail. buffer */ rxBuf = &(channel->rxFrameBuf); frame = &(rxBuf->frames[ rxBuf->write ]); /* restart DMA */ z85230DmaStart( SCC_DMA_CHAN_RX, channel->hw.rxfpga, frame->buf, frame->maxSize ); /* * Obtain actual frame size received from the FPGA register: */ frame_size = (cha)?sysInWordNoSwap ((UINT32)FPGA_SCC_CHB_CNTR) :sysInWordNoSwap ((UINT32)FPGA_SCC_CHA_CNTR); --frame_size; frame0->size = (--frame_size); /*logMsg(">>>> FR %x NewFR %x SZ %d\n",(int)frame0,(int)frame ,frame_size,0,0,0);*/ /* z85230DmaSetFrameSize( rxBuf0 , frame_size-2 ); */ intUnlock( old_level ); } else {/* * Disabling Rx (RxEnable interrupt) has unfortunate side effect * of disabling Tx (TxEnable interrupt) as well. Consequently Rx * will always be enabled during half-duplex mode. */ rxBuf = &(channel->rxFrameBuf); frame = &(rxBuf->frames[ rxBuf->write ]); /* received a frame that we transmitted because we are in * half duplex mode, or a frame with a bad CRC, or * a frame too short -> discard it */ frame->read = frame->size = 0; old_level = intLock(); /* restart DMA */ /* z85230DmaAbort( SCC_DMA_CHAN_RX ); */ sysOutLong( (UINT32)GT64260_DMACC( SCC_DMA_CHAN_RX ), 0x200 ); z85230DmaStart( SCC_DMA_CHAN_RX, channel->hw.rxfpga, frame->buf, frame->maxSize ); intUnlock( old_level ); } if ( channel->hw.txDone && channel->hw.halfDuplex ) { /* finished transmitting - turn off transmitter * Lets assume that if no cycles have been designated, * then we want the fastest means possible to turn of * The Tx Clock */ if( channel->hw.clockDelay > 0 ) { z85230ClkStart( channel->channel, channel->hw.clockDelay ); } else { z85230HwDisableTx( channel ); channel->hw.txing = 0 ; } } #endif /* VME_181 */ } /* end of z85230RHDLCfpgaInt *//*************************************************************************** * z85230RHDLCTxDmaInt - interrupt callback * * Invoked through the FPGA request upon * end-of-dma transfer to the Zilog chip. * */void z85230RHDLCTxDmaInt( struct _Z85230_CHAN * channel ) {#ifndef VME_181 UINT32 txDesc; Z8530_CHAN * hw = &(channel->hw);#endif Z85230BUF_FRAMES * txBuf = &(channel->txFrameBuf); #ifndef VME_181 txDesc = (UINT32)(hw->txfpga) + (hw->txIndex * DRI_DESC_OFFSET); if (sysInLong(txDesc + DRI_CMDSTAT_OFFSET) != DRI_COMPLETE) return; sysOutLong(txDesc + DRI_CMDSTAT_OFFSET, 0); channel->hw.txIndex = (channel->hw.txIndex + 1) % Z85230_MAX_DESC;#endif /* end of frame reached - allow underrun so that ESCC will close it * properly */ /* reset tx underrun/eom latch */ semGive( channel->writeSem ); /* start new frame */ txBuf->frames[ txBuf->read ].size = 0; txBuf->frames[ txBuf->read ].read = 0; txBuf->read = (txBuf->read + 1) % txBuf->size; txBuf->frames[ txBuf->read ].read = 0; /* In half duplex, indicate the transmit is complete */ if( channel->hw.halfDuplex == TRUE ) channel->hw.txDone = TRUE ; else channel->hw.txing = 0;#ifdef VME_181 /* * Sync I/O operation EIEIO_SYNC; */ sysOutWordNoSwap ( (UINT32)FPGA_SCC_CHA_CNTX,0);#endif /* VME_181 */ }/*************************************************************************** * z85230RHDLCOpen - open channel in RHDLC mode * * RETURNS * Z85230_OK: success * anything else: fail */int z85230RHDLCOpen( struct _Z85230_CHAN * channel ) { Z8530_CHAN * hw = &(channel->hw); volatile unsigned char * cr = channel->hw.cr; unsigned char rr; int res = FALSE; int oldLevel; int i; /* initialize variables */ rhdlc[ channel->channel ].rxAddr = 0xff; rhdlc[ channel->channel ].abort = FALSE; rhdlc[ channel->channel ].rxStatus = malloc( Z85230RHDLC_DEFAULT_RX_BUFFERFRAMES * sizeof( unsigned char ) ); if ( rhdlc[ channel->channel ].rxStatus == NULL ) { errno = Z85230_ERR_OUT_OF_MEM ; return ERROR; } for ( i = 0; i < Z85230RHDLC_DEFAULT_RX_BUFFERFRAMES; i++ ) { rhdlc[ channel->channel ].rxStatus[ i ] = 0; } /* allocate buffers */ res = z85230BufCreateFrames( &(channel->txFrameBuf), NULL, Z85230RHDLC_DEFAULT_BUFFERSIZE, Z85230RHDLC_DEFAULT_TX_BUFFERFRAMES ); if ( res != Z85230_OK ) { free( rhdlc[ channel->channel ].rxStatus ); return Z85230_ERR_OUT_OF_MEM; } res = z85230BufCreateFrames( &(channel->rxFrameBuf), NULL, Z85230RHDLC_DEFAULT_BUFFERSIZE, Z85230RHDLC_DEFAULT_RX_BUFFERFRAMES ); if ( res != Z85230_OK ) { /* out of memory - clean up */ free( rhdlc[ channel->channel ].rxStatus ); z85230BufDeleteFrames( &(channel->txFrameBuf) ); errno = Z85230_ERR_OUT_OF_MEM ; return ERROR; } oldLevel = intLock(); /* reset the chip */ REG_8530_READ( cr, &rr ); /* write reg 9 - master interrupt control and reset */ REG_8530_WRITE(cr, SCC_WR0_SEL_WR9); if ( channel->channel == Z85230_CHANNEL_A ) { REG_8530_WRITE( cr, SCC_WR9_CH_A_RST ); /* reset channel A */ } else { /* channel B */ REG_8530_WRITE( cr, SCC_WR9_CH_B_RST ); /* reset channel B */ } /* Delay for about 1 uSec (typically) before further chip accesses */ Z8530_RESET_DELAY; /* reset the chip again */ REG_8530_READ( cr, &rr ); /* write reg 4 - misc parms & modes */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR4 ); REG_8530_WRITE( cr, SCC_WR4_SYNC_EN | SCC_WR4_SDLC | SCC_WR4_1_CLOCK ); /* write reg 10 - misc tx/rx control */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR10 ); /* clear sync, loop, poll */ REG_8530_WRITE( cr, SCC_WR10_CRC_PRESET /* | SCC_WR10_MARK_IDLE */ ); /* write reg 6 - secondary address */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR6 ); REG_8530_WRITE( cr, 0 ); /* write reg 7 - sdlc flag */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR7 ); REG_8530_WRITE( cr, SCC_WR7_SDLC_FLAG ); /* write reg 2 - interrupt vector */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR2 ); REG_8530_WRITE( cr, hw->intVec ); /* write reg 11 - clock mode */ hw->writeReg11 = SCC_WR11_RX_RTXC | SCC_WR11_TX_BR_GEN | SCC_WR11_TRXC_OI | SCC_WR11_OUT_TX_CLK; REG_8530_WRITE( cr, SCC_WR0_SEL_WR11 ); REG_8530_WRITE( cr, hw->writeReg11 ); /* write reg 14 - misc control bits */ hw->writeReg14 = SCC_WR14_BR_EN | SCC_WR14_BR_SRC | SCC_WR14_SRC_BR; REG_8530_WRITE( cr, SCC_WR0_SEL_WR14 ); REG_8530_WRITE( cr, hw->writeReg14 ); /* write reg 15 - disable external/status interrupts */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR15 ); REG_8530_WRITE( cr, SCC_WR15_SDLC_FIFO_EN | SCC_WR15_SYNC_IE ); /* write reg 1 - disable interrupts and xfer mode */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR1 ); REG_8530_WRITE( cr, 0 ); /* end initialization as per ZILOG application note */ /* * write reg 7` - SDLC options */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR15 ); REG_8530_READ( cr, &rr ); REG_8530_WRITE( cr, SCC_WR0_SEL_WR15 ); REG_8530_WRITE( cr, rr | SCC_WR15_WR7P_EN ); /* D0=1 points to WR7' */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR7 ); REG_8530_WRITE( cr, SCC_WR7P_EXT_READ_ENB | /* SCC_WR7P_TXD_HIGH | */ /* SCC_WR7P_AUTO_RTS | */ SCC_WR7P_TX_FIFO_INT_LVL | SCC_WR7P_AUTO_EOM_RST | SCC_WR7P_AUTO_TX_FLAG ); /* reset external interrupts and errors */ REG_8530_WRITE( cr, SCC_WR0_RST_INT ); REG_8530_WRITE( cr, SCC_WR0_ERR_RST ); /* RHDLC address */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR6 ); REG_8530_WRITE( cr, rhdlc[ channel->channel ].rxAddr ); /* write reg 3 - receive params */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR3 ); REG_8530_WRITE( cr, SCC_WR3_RX_8_BITS | SCC_WR3_ENTER_HUNT | SCC_WR3_RX_CRC_EN | SCC_WR3_RX_EN ); /* write reg 5 - tx params */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR5 ); REG_8530_WRITE( cr, SCC_WR5_TX_8_BITS | SCC_WR5_DTR | SCC_WR5_TX_CRC_EN | SCC_WR5_TX_EN | SCC_WR5_SDLC_CRC ); /*SCC_WR5_TX_CRC_EN | SCC_WR5_TX_EN | SCC_WR5_CRC16 ); */ /* write reg 9 - enable master interrupt control */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR9 ); REG_8530_WRITE( cr, SCC_WR9_MIE | hw->intType ); /* reset Tx CRC generator and any pending ext/status interrupts */ REG_8530_WRITE( cr, SCC_WR0_RST_TX_CRC ); REG_8530_WRITE( cr, SCC_WR0_RST_INT ); REG_8530_WRITE( cr, SCC_WR0_RST_INT ); /* reset SCC register counter */ REG_8530_READ( cr, &rr ); intUnlock( oldLevel ); /* baudrate */ channel->hw.baudRate = z85230HwSetRate( channel, Z85230RHDLC_DEFAULT_BAUDRATE ); /* options */ z85230RHDLCOptsSet( channel, CS8 | CREAD | CLOCAL );#ifdef VME_181 /* default mode is interrupt mode */ z85230RHDLCModeSet( channel, Z85230_MODE_INT );#else /* default mode is DMA mode */ z85230RHDLCModeSet( channel, Z85230_MODE_DMA );#endif channel->hw.halfDuplex = 0; channel->hw.txing = 0; channel->hw.txDone = 0; channel->hw.crcCheck = 1; channel->hw.clockDelay = 0 ; return Z85230_OK; }/*************************************************************************** * z85230RHDLCClose - close RHDLC channel * * RETURNS * Z85230_OK: success * anything else: fail */int z85230RHDLCClose( struct _Z85230_CHAN * channel ) { volatile unsigned char * cr = channel->hw.cr; int oldLevel; /* release buffers */ z85230BufDeleteFrames( &(channel->rxFrameBuf) ); z85230BufDeleteFrames( &(channel->txFrameBuf) ); free( rhdlc[ channel->channel ].rxStatus ); oldLevel = intLock(); /* disable interrupts */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR1 ); REG_8530_WRITE( cr, 0 ); #ifndef VME_181 z85230HwDisablePort(channel);#endif intUnlock( oldLevel ); return Z85230_OK; }/*************************************************************************** * z85230RHDLCRead - read from channel into buffer * * RETURNS * number of bytes read, or <0 on failure */int z85230RHDLCRead( struct _Z85230_CHAN * channel, unsigned char * buf, int size ) { /* TODO: check channel status */ Z85230BUF_FRAMES * rxBuf = &(channel->rxFrameBuf); int bytesRead = 0; int i ; STATUS result = OK ; if ( channel->blocking ) { /* decrement counting semaphore with timeout */ semTake( channel->readSem, channel->readTimeout ); } else { /* decrement counting semaphore, returning instantly if empty */ semTake( channel->readSem, NO_WAIT ); } for( i=0; i<1; i++) { if ( rxBuf->frames[ rxBuf->read ].size > size ) { /* frame too large */ result = ERROR ; break ; } if ( z85230BufNumFrames( rxBuf ) == 0 ) { /* nothing to read */ result = ERROR ; break ; } Z85230_ASSERT( rxBuf->frames[ rxBuf->read ].size >= 2 ); if( rxBuf->frames[ rxBuf->read ].size < 2 ) DRV_LOG(DRV_DEBUG_RX,"RHDLCRead: Size 0\n",0,0,0,0,0,0); if ( rhdlc[ channel->channel ].rxStatus[ rxBuf->read ] != 0 ) { result = ERROR ; break ; } } if( result == ERROR ) { /* a problem occured - report it */ channel->readError = rhdlc[ channel->channel ].rxStatus[ rxBuf->read ]; rhdlc[ channel->channel ].rxStatus[ rxBuf->read ] = 0; return result ; } /* address */ bytesRead += z85230BufReadFrameByte( rxBuf, &(buf[ 0 ]) ); /* command */ bytesRead += z85230BufReadFrameByte( rxBuf, &(buf[ 1 ]) ); switch ( channel->hw.options & CSIZE ) { case CS5: bytesRead += z85230BufReadFrame( rxBuf, &(buf[ 2 ]), size - 2, 5 ); break; case CS6: bytesRead += z85230BufReadFrame( rxBuf, &(buf[ 2 ]), size - 2, 6 ); break; case CS7: bytesRead += z85230BufReadFrame( rxBuf, &(buf[ 2 ]), size - 2, 7 ); break; default: /* CS8 */ bytesRead += z85230BufReadFrame( rxBuf, &(buf[ 2 ]), size - 2, 8 ); break; } return bytesRead;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -