📄 z85230rhdlc.c
字号:
if (z85230HwEnablePort(channel) != OK) return ERROR;#endif /* VME_181 */ } channel->hw.mode = newMode;#ifndef VME_181 /* To set timeout value */ z85230HwSetTimeout(channel, 0);#endif return result; /** was OK aak */ }/*************************************************************************** * z85230RHDLCGotFrame - called from ISRs on reception of end-of-frame * * checks CRC * checks for frame overflow * crops CRC off the frame * prepares for a new frame */static void z85230RHDLCGotFrame( struct _Z85230_CHAN * channel, unsigned char status ) { Z85230BUF_FRAMES * rxBuf = &(channel->rxFrameBuf); Z85230BUF_FRAME * frame = &(rxBuf->frames[ rxBuf->write ]); /* check CRC */ if ( status & SCC_RR1_CRC_ERR ) { if ( channel->hw.crcCheck ) { /* throw away bad frame */ frame->read = frame->size = 0; rhdlc[ channel->channel ].rxStatus[ rxBuf->write ] = Z85230_ERR_BAD_CRC ; errno = Z85230_ERR_BAD_CRC ; DRV_LOG(DRV_DEBUG_RX_ERR,"RHDLCGotFrame: BAD_CRC\n",0,0,0,0,0,0); } } /* check for overflow */ if ( rxBuf->read == ( (rxBuf->write + 1) % rxBuf->size ) ) { rhdlc[ channel->channel ].rxStatus[ rxBuf->write ] |= RHDLC_FRAME_OVERFLOW; errno = RHDLC_FRAME_OVERFLOW ; DRV_LOG(DRV_DEBUG_RX_ERR,"RHDLCGotFrame: OVERFLOW\n",0,0,0,0,0,0); return; } /* crop off CRC */ -- (frame->size); -- (frame->size); DRV_LOG(DRV_DEBUG_RX,"RHDLCGotFrame: %d bytes\n",frame->size,0,0,0,0,0); /* new frame */ rxBuf->write = (rxBuf->write + 1) % rxBuf->size; frame = &(rxBuf->frames[ rxBuf->write ]); frame->size = frame->read = 0; /* increment counting semaphore */ semGive( channel->readSem ); }/*************************************************************************** * z85230RHDLCExInt - interrupt callback * */void z85230RHDLCExInt( struct _Z85230_CHAN * channel, unsigned char intStatus ) { unsigned char rr, status; volatile unsigned char * cr = channel->hw.cr; /* check RR0 */ REG_8530_READ( cr, &rr ); /* read register 1 */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR1 ); REG_8530_READ( cr, &status ); if ( !(rr & SCC_RR0_SYNC) ) { } if ( rr & SCC_RR0_BREAK ) { Z85230BUF_FRAME * frame = &channel->rxFrameBuf.frames[ channel->rxFrameBuf.write ]; if( (channel->hw.halfDuplex == FALSE) ||( (channel->hw.txDone == TRUE) &&(channel->hw.halfDuplex == TRUE )) ) { /* drop frame */ frame->read = frame->size = 0; } } if ( rr & SCC_RR0_RX_AVAIL ) { } if ( rr & SCC_RR0_TX_UND ) { if ( channel->hw.mode == Z85230_MODE_DMA ) { /* transfer complete */ REG_8530_WRITE( cr, SCC_WR0_RST_TX_INT ); REG_8530_WRITE( cr, SCC_WR0_ERR_RST ); } } /* reset EXT/STATUS interrupts */ REG_8530_WRITE( cr, SCC_WR0_RST_INT ); }/*************************************************************************** * z85230RHDLCRxInt - interrupt callback * * When the ESCC receives the closing flag, an interrupt is generated * that results in the final verification of the message and the buffering * scheme to update, and prepare for the next frame. * * Note that if CRC checking is enabled and the z85230 ESCC finds a CRC error * in the received Raw HDLC message, the z85230 ESCC will trigger a CRC error * which will be caught by the driver. If the driver is blocking on a read * call, it will eventually time out if no other message has been received. * The VxWorks errno value will be set to indicate a CRC error was observed. * If no read call is in progress the CRC error is discarded. * * NOMANUAL aak updated */void z85230RHDLCRxInt( struct _Z85230_CHAN * channel, unsigned char intStatus ) { volatile char * cr = channel->hw.cr; unsigned char rr, status; short frameByteCount = 0; unsigned char * rxStatus = &(rhdlc[ channel->channel ].rxStatus[ channel->rxFrameBuf.write ]); Z85230BUF_FRAMES * rxBuf = NULL ; Z85230BUF_FRAME * frame = NULL ; #ifdef VME_181 int old_level ;#endif/* int frame_size ; */ do { /* read the LSB of the number of bytes in the frame */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR6 ); REG_8530_READ( cr, &rr ); frameByteCount = rr; /* read the MSB of the number of bytes in the frame */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR7 ); REG_8530_READ( cr, &rr ); frameByteCount |= (rr << 8); REG_8530_WRITE( cr, SCC_WR0_SEL_WR1 ); REG_8530_READ( cr, &status ); /* read register 0 */ REG_8530_READ( cr, &rr ); if ( rr & SCC_RR0_RX_AVAIL ) { /* read the received character */ /* select data register */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR8 ); REG_8530_READ( cr, &rr ); /* deposit new char in buffer */ if ( (*rxStatus & RHDLC_FRAME_OVERFLOW) == 0 ) { if ( z85230BufWriteFrameByte( &(channel->rxFrameBuf), rr ) < 1 ) { *rxStatus |= RHDLC_BUFFER_OVERFLOW; errno = RHDLC_FRAME_OVERFLOW ; } } } /* else drop frame */ if ( status & SCC_RR1_END_FRAME ) { if ( (status & SCC_RR1_CRC_ERR ) &&( channel->hw.crcCheck == 1) ) { *rxStatus |= RHDLC_BADCRC; DRV_LOG(DRV_DEBUG_RX_ERR,"RHDLC_BADCRC\n",0,0,0,0,0,0); } else { /* aak reset the error state */ *rxStatus &= (~RHDLC_BADCRC); DRV_LOG(DRV_DEBUG_RX,"END_FRAME\n",0,0,0,0,0,0); } /* if we are receiving the frame we sent (loopback) */ if ( (channel->hw.halfDuplex && channel->hw.txing) ) { 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 - throw it away */ frame->read = frame->size = 0; if( channel->hw.mode == Z85230_MODE_DMA ) /* PT#1654 */ {#ifdef VME_181 old_level = intLock(); /* restart DMA */ z85230DmaAbort( SCC_DMA_CHAN_RX ); z85230DmaStart( SCC_DMA_CHAN_RX, channel->hw.rxfpga, frame->buf, frame->maxSize ); intUnlock( old_level );#endif } } /* Half-duplex mode */ else /* If we aren't receiving a frame we sent * (i.e. Rx interrupt in full-duplex mode) * Note: the MODE_DMA case is handled in z85230RHDLCfpgaInt() */ /* if ( !(channel->hw.halfDuplex && channel->hw.txing) ) */ if( channel->hw.mode == Z85230_MODE_INT ) { /* MODE_INT only: end of frame */ z85230RHDLCGotFrame( channel, status ); } 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 ) {#ifdef VME_181 z85230ClkStart( channel->channel, channel->hw.clockDelay );#endif } else { z85230HwDisableTx( channel ); channel->hw.txing = 0 ; } } } /* end of EOF case */ /* Check rr0 to see if more chars available */ REG_8530_READ( cr, &rr ); } while ( rr & SCC_RR0_RX_AVAIL ); }/*************************************************************************** * z85230RHDLCTxInt - interrupt callback */void z85230RHDLCTxInt( struct _Z85230_CHAN * channel, unsigned char intStatus ) { char outChar; volatile char * cr = channel->hw.cr; Z85230BUF_FRAMES * txBuf = &(channel->txFrameBuf); /* check abort */ if ( rhdlc[ channel->channel ].abort ) { /* clear buffer */ z85230BufFlushFrames( &(channel->txFrameBuf) ); rhdlc[ channel->channel ].abort = FALSE; return; } /* get next character from buffer */ if ( z85230BufReadFrameByte( &(channel->txFrameBuf), &outChar ) <= 0 ) { /* frame is empty - begin sending the next frame */ /* if next frame is valid */ if ( txBuf->read != txBuf->write ) { /* next 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; } else { /* tx buffer is empty - disable interrupts */ REG_8530_WRITE(cr, SCC_WR0_RST_TX_INT); /* wake up blocking writes */ semGive( channel->writeSem ); /* handle half duplex */ if ( channel->hw.halfDuplex ) { channel->hw.txDone = 1; } else { channel->hw.txing = 0; } } } else { /* got a character - write it to the ESCC */ REG_8530_WRITE(cr, SCC_WR0_SEL_WR8); /* select data register */ REG_8530_WRITE(cr, outChar); /* if this is the last character in the frame */ if ( txBuf->frames[ txBuf->read ].read == txBuf->frames[ txBuf->read ].size ) { /* reset tx underrun/eom latch */ /* next interrupt we get will be after CRC and flag has completely * cleared pins */ REG_8530_WRITE( cr, SCC_WR0_RST_TX_UND ); } } }/*************************************************************************** * z85230RHDLCRxDmaInt - interrupt callback */void z85230RHDLCRxDmaInt( struct _Z85230_CHAN * channel ) { /* logMsg("RHDLCRxDmaInt\n",0,0,0,0,0,0); */ }/*************************************************************************** * z85230RHDLCfpgaInt - FPGA interrupt callback in DMA Rx mode * * Disable the associated receiving IDMA Channel Enable bit * and read the actual data counter from the FPGA register. * The disable operation will flash all the received data within the internal on-chip * buffer, write it to the SDRAM buffer, update the DMA byte count and the destination * address accordingly. * z85230DmaAbort is not called from within due to potential overhead / endless loop risk * * NOMANUAL */void z85230RHDLCfpgaInt( struct _Z85230_CHAN * channel ){ unsigned char * rxStatus = &(rhdlc[ channel->channel ].rxStatus[ channel->rxFrameBuf.write ]); int cha = channel->channel;#ifndef VME_181 unsigned int intStatus; Z85230BUF_FRAMES * rxBuf = &(channel->rxFrameBuf); Z85230BUF_FRAME * frame = &(rxBuf->frames[ rxBuf->write ]); UINT32 bytesRead; Z8530_CHAN * hw = &(channel->hw); UINT32 i = hw->rxIndex; UINT32 rxDesc = (UINT32)(hw->rxfpga) + (i * DRI_DESC_OFFSET); intStatus = sysInLong ( (UINT32)FPGA_SCC_INT_CNTRL); if (cha == Z85230_CHANNEL_A) { if (intStatus & ERRA_CRC) *rxStatus = SCC_RR1_CRC_ERR; } else { if (intStatus & ERRB_CRC) *rxStatus = SCC_RR1_CRC_ERR; } bytesRead = sysInLong(rxDesc + DRI_BYTECNT_OFFSET) & 0xFFFF; if (bytesRead > 0 && bytesRead <= Z85230RHDLC_DEFAULT_BUFFERSIZE) { bcopy(hw->rxBuf[i], frame->buf, bytesRead); frame->size = bytesRead; z85230RHDLCGotFrame( channel, *rxStatus ); } /* Reload the descriptor */ sysOutLong(rxDesc + DRI_BUF_OFFSET, (UINT32)hw->rxBuf[i]); sysOutLong(rxDesc + DRI_BYTECNT_OFFSET, Z85230RHDLC_DEFAULT_BUFFERSIZE << 16); sysOutLong(rxDesc + DRI_CMDSTAT_OFFSET, DRI_ENABLE); hw->rxIndex = (i + 1) % Z85230_MAX_DESC; /* move to next desc */#else UINT16 frame_size ; Z85230BUF_FRAMES * rxBuf = NULL; Z85230BUF_FRAME *frame0, *frame = NULL ; int old_level ; /* if we aren't receiving a frame we sent (loopback) */ if ( !(channel->hw.halfDuplex && channel->hw.txing) ) { old_level = intLock(); /* Disable the IDMA to flush the data into the SDRAM */ sysOutLong( (UINT32)GT64260_DMACC( SCC_DMA_CHAN_RX ), 0x200 ); frame_size = sysInLong( (UINT32)GT64260_DMACC( SCC_DMA_CHAN_RX ) ); frame_size = z85230DmaBytesTransfered(SCC_DMA_CHAN_RX); /* Save pointer to the Rx structure */ rxBuf = &(channel->rxFrameBuf); frame0 = &(rxBuf->frames[ rxBuf->write ]); z85230DmaSetFrameSize( &(channel->rxFrameBuf), frame_size ); /* We need to determine the status of this frame and send it down * this routine does not yet know what statuses are expected in DMA mode */ z85230RHDLCGotFrame( channel, *rxStatus ); /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -