📄 z85230async.c
字号:
{ * stop the DMA * z85230DmaAbort( SCC_DMA_CHAN_RX ); bytesRead = z85230DmaBytesTransfered( SCC_DMA_CHAN_RX ); rxFragmentCount[cha]+=bytesRead; } */ if (bytesRead!=0xffff) /* if not Exit Code */ { /* Temporarely disable task context switching to protect the pointers */ taskLock(); z85230CopyDmaStream( &(channel->rxStreamBuf),dmaRxBuf[cha], bytesRead ); taskUnlock(); semGive(dmaSemID[cha]); /* signal the user read process */ z85230DmaStart( SCC_DMA_CHAN_RX, channel->hw.rxfpga, dmaRxBuf[cha], dmaRxBufSize ); /* logMsg("\nFPGA read=%d avail=%d\n",bytesRead,bytesAvail,0,0,0,0); */ } else rxTaskDone=TRUE;} while (!rxTaskDone);}#endif /* VME_181 *//*************************************************************************** * z85230AsyncRead - read from channel into buffer * * RETURNS * number of bytes read, or <0 on failure * * NOMANUAL aak updated */int z85230AsyncRead( struct _Z85230_CHAN * channel, unsigned char * buf, int size ) { unsigned char mask; int oldLevel ; int cha = channel->channel; int bytesAvail = 0 ; UINT32 count=0 ;/* static UINT32 packetCount =0 ; */if(( buf == NULL ) || ( size < 0 ) || ( size > Z85230ASYNC_DEFAULT_BUFFERSIZE)){ errno = Z85230_ERR_INVALID_PARAM ; return 0 ;}if( channel->hw.mode == Z85230_MODE_DMA ) { while( bytesAvail < size ) { /* if this is a non blocking read, just get out with what we have * already DMAed to the buffer */ if( channel->blocking ) semTake(dmaSemID[cha],1); /* timeout = 1 tick */ else break; bytesAvail = z85230BufStreamSize( &(channel->rxStreamBuf)); /* Since we only add to the buffer when we stop the dma transfer, * we will poll the dma every tick, until we have received all * the data or our time is up if( bytesAvail < size ) { taskDelay(1); } */ if( count++ > channel->readTimeout ) break ; } /* end while */ }else /* Z85230_MODE_INT */ { if ( channel->blocking ) { oldLevel = intLock(); async[ channel->channel ].blockingReadSize = size; intUnlock( oldLevel ); if ( channel->blocking && (z85230BufStreamSize( &(channel->rxStreamBuf) ) < size) ) { /* decrement counting semaphore with timeout */ semTake( channel->readSem, channel->readTimeout ); } else { /* decrement counting semaphore, returning instantly if empty */ semTake( channel->readSem, NO_WAIT ); } } } switch ( channel->hw.options & CSIZE ) { case CS5: mask = 0x1f; break; case CS6: mask = 0x3f; break; case CS7: mask = 0x7f; break; default: /* don't mask */ mask = 0xff; break; } return z85230BufReadStream( &(channel->rxStreamBuf), buf, size, mask ); }/*************************************************************************** * z85230AsyncWrite - write from buffer to channel, enable HW tx if buffer * was previously empty * * RETURNS * the number of bytes written, or <0 on failure * * NOMANUAL updated aak */int z85230AsyncWrite( struct _Z85230_CHAN * channel, unsigned char * buf, int size ) { unsigned char mask; int bytesWrittenTotal = 0; int bytesWritten = 0; int oldLevel ; /* validation */ if (buf == NULL || size <= 0 || size > Z85230ASYNC_DEFAULT_BUFFERSIZE) return bytesWrittenTotal ; if ( (channel->hw.options & CSIZE) == CS5 ) { mask = 0x1f; } else { mask = 0xff; }#ifndef VME_181 if ( channel->hw.mode == Z85230_MODE_DMA ) { while (bytesWrittenTotal < size) { bytesWrittenTotal = z85230HwSendByDesc(channel, buf, size, mask); if ( channel->blocking ) { /* Inform driver that we are waiting for tx buffer to empty */ oldLevel = intLock(); async[ channel->channel ].blockingOnWrite = TRUE; intUnlock( oldLevel ); /* driver will wake us up after the last byte has entered the tx fifo */ semTake( channel->writeSem, channel->writeTimeout ); } else break; } return bytesWrittenTotal; }#endif do { /* write the buffer to the stream */ bytesWritten = z85230BufWriteStream( &(channel->txStreamBuf), buf+bytesWritten , size-bytesWritten, mask ); z85230AsyncTxStartup( channel ); if ( channel->blocking ) { /* Inform driver that we are waiting for tx buffer to empty */ oldLevel = intLock(); async[ channel->channel ].blockingOnWrite = TRUE; intUnlock( oldLevel ); /* driver will wake us up after the last byte has entered the tx fifo */ if(semTake( channel->writeSem, channel->writeTimeout ) == ERROR ) { oldLevel = intLock(); /* if the bytes are still in the buffer, we haven't written them */ bytesWritten -= z85230BufStreamSize( &(channel->txStreamBuf) ); if( channel->hw.mode == Z85230_MODE_DMA ) {#ifdef VME_181 bytesWritten = z85230DmaBytesTransfered( SCC_DMA_CHAN_TX );#endif } /* empty the buffer */ z85230BufFlushStream( &(channel->txStreamBuf) ); intUnlock( oldLevel ); return bytesWritten ; } } bytesWrittenTotal += bytesWritten ; } while ( bytesWrittenTotal < size ); return bytesWrittenTotal; }/*************************************************************************** * z85230AsyncIoctl - generic I/O command interface * * RETURNS * Z85230_OK: command successfully run * Z85230_ERR_NOT_IMPLEMENTED: command not implemented * anything else: command failed */int z85230AsyncIoctl( struct _Z85230_CHAN * channel, int command, int arg ) { int oldLevel; Z8530_CHAN * hw = &( channel->hw );#ifdef VME_181 UINT32 addr; int cha = channel->channel;#endif switch( command ) { case FIONREAD: /* Gets # of Bytes ready to be read */ *(int *)arg = z85230BufStreamSize( &channel->rxStreamBuf ); return(OK); case FIOFLUSH: case Z85230_FLUSH: /* drop all rx'ed data */ taskDelay(1); oldLevel = intLock(); z85230BufFlushStream( &channel->rxStreamBuf ); intUnlock( oldLevel ); /* wait until tx'ed data is gone */ while ( z85230BufStreamSize( &channel->txStreamBuf ) > 0 ) { taskDelay( 0 ); } break; case FIOBAUDRATE: case Z85230_SET_BAUDRATE: /* check baud rate */ if ( arg < Z85230_MIN_ASYNC_BAUDRATE || arg > Z85230_MAX_ASYNC_BAUDRATE ) { return EIO; } /* if current baud == requested baud, do nothing */ if ( hw->baudRate == arg ) { return OK; } hw->baudRate = z85230HwSetRate( channel, arg );#ifdef VME_181 /* Ch.B Ch.A */ addr= (UINT32)((cha) ? FPGA_SCC_CHB_TIME : FPGA_SCC_CHA_TIME); /* The FPGA timeout setting should depend on baud rate and frame structure */ if (arg > 160) sysOutWordNoSwap(addr, (1000000/ arg * 11) /*- (1000000/ arg / 2) */ ); /* Rx Timeout Register - DEBUG*/ else sysOutWordNoSwap(addr, 0xFFFF); /* Max value in Rx Timeout Register */#endif return (OK); case Z85230_GET_BAUDRATE: *(int *)arg = hw->baudRate; /* return current baud rate */ return (OK); case Z85230_MODE_SET:#ifndef VME_181 if (arg != Z85230_MODE_DMA) return (EIO);#endif return (z85230AsyncModeSet( channel, arg ) == OK ? OK : EIO); case Z85230_MODE_GET: *(int *)arg = hw->mode; /* return current Z85230 mode */ return (OK); case Z85230_AVAIL_MODES_GET:#ifdef VME_181 *(int *)arg = Z85230_MODE_INT;#else *(int *)arg = Z85230_MODE_DMA;#endif return (OK); case Z85230_HW_OPTS_SET: return ((z85230AsyncOptsSet( channel, arg ) == OK) ? OK : EIO); break; case Z85230_HW_OPTS_GET: *(int *)arg = z85230HwGetOpts( channel ); break; case Z85230_HUP: /* check if hupcl option is enabled */ if ( hw->options & HUPCL ) return z85230AsyncHup( channel ); break; case Z85230_OPEN: /* check if hupcl option is enabled */ if ( hw->options & HUPCL ) return z85230AsyncConnect( channel ); break; default: return Z85230_ERR_NOT_IMPLEMENTED; } return Z85230_OK; }#ifndef VME_181/*************************************************************************** * z85230AsyncTxFpgaInt - FPGA TX interrupt callback in DMA mode * * Signal tranmission completed */void z85230AsyncTxFpgaInt( struct _Z85230_CHAN * channel ){ UINT32 txDesc; int bytes_written ; Z8530_CHAN * hw = &(channel->hw); UINT32 i = hw->txIndex; /* Get current TX descriptor */ txDesc = (UINT32)(hw->txfpga) + (i * DRI_DESC_OFFSET); /* Bytes sent */ bytes_written = sysInLong(txDesc + DRI_BYTECNT_OFFSET) & 0xFFFF; sysOutLong(txDesc + DRI_CMDSTAT_OFFSET, 0); /* reset interrupt */ hw->txIndex = (i + 1) % Z85230_MAX_DESC; /* move to next desc */ /* awaken blocking writes */ if ( async[ channel->channel ].blockingOnWrite ) { async[ channel->channel ].blockingOnWrite = FALSE; semGive( channel->writeSem ); }}/*************************************************************************** * z85230AsyncRxFpgaInt - FPGA RX interrupt callback in DMA mode * * Moves data from DMA buffer into the driver buffer */void z85230AsyncRxFpgaInt( struct _Z85230_CHAN * channel ){#ifndef VME_181 UINT32 intStatus; int cha = channel->channel;#endif UINT32 bytesRead; Z8530_CHAN * hw = &(channel->hw); UINT32 i = hw->rxIndex; UINT32 rxDesc = (UINT32)(hw->rxfpga) + (i * DRI_DESC_OFFSET); BOOL rx = TRUE; UINT8 rr; /* see if any error occurs, if yes just discard it */ REG_8530_WRITE( hw->cr, SCC_WR0_SEL_WR1 ); /* read register 1 */ REG_8530_READ( hw->cr, &rr ); /* parity */ if ( rr & SCC_RR1_PAR_ERR ) { channel->readError = Z85230_ERR_PARITY; rx = FALSE; }#ifndef VME_181 intStatus = sysInLong ( (UINT32)FPGA_SCC_INT_CNTRL); if (cha == Z85230_CHANNEL_A) { if (intStatus & ERRA_PARITY) { channel->readError = Z85230_ERR_PARITY; rx = FALSE; } } else { if (intStatus & ERRB_PARITY) { channel->readError = Z85230_ERR_PARITY; rx = FALSE; } }#endif /* rx fifo overflow */ if ( rr & SCC_RR1_RX_OV_ERR ) { channel->readError = Z85230_ERR_RX_OVERFLOW; rx = FALSE; } if (rx) { bytesRead = sysInLong(rxDesc + DRI_BYTECNT_OFFSET) & 0xFFFF; if (bytesRead > 0 && bytesRead <= Z85230ASYNC_DEFAULT_BUFFERSIZE) { z85230CopyDmaStream(&(channel->rxStreamBuf), hw->rxBuf[i], bytesRead); semGive(dmaSemID[channel->channel]); /* signal the user read process */ } } else { /* reset error */ REG_8530_WRITE(hw->cr, SCC_WR0_ERR_RST); /* Reset the interrupt in the Z8530 */ REG_8530_WRITE(hw->cr, SCC_WR0_RST_HI_IUS); /* Dummy read to ensure accomplishment of the prev. command */ REG_8530_READ(hw->cr, &rr); } /* Reload the descriptor */ sysOutLong(rxDesc + DRI_BUF_OFFSET, (UINT32)hw->rxBuf[i]); sysOutLong(rxDesc + DRI_BYTECNT_OFFSET, (Z85230ASYNC_DEFAULT_BUFFERSIZE / Z85230_MAX_DESC) << 16); sysOutLong(rxDesc + DRI_CMDSTAT_OFFSET, DRI_ENABLE); hw->rxIndex = (i + 1) % Z85230_MAX_DESC; /* move to next desc */}#endif /* VME_181 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -