📄 z85230async.c
字号:
/* z85230Async.c - implements async protocol *//* Copyright 2000-2003 Dy 4 Systems, Inc. *//*modification history--------------------01c 07jun05,dle support 183 Serial IPM V201b 16sep03,aak add FIONREAD01a srr,13feb01 changed default clk mode to x16 in z85230AsyncOpen also changed max baud rate setting for ioctl-Z85230_SET_BAUDRATE see SRR+1*//*DESCRIPTION The Dy 4 sync/async serial driver is a serial communication driver thatallows an application to exercise the EIA-422 serial channels available on the target board (channels 3 and 4 implemented with the ZilogZ85230 Serial Communications Controller device). The high-level features of the async serial driver for each of the datatransfer modes supported are: - Full duplex communications up to 153.6 Kbits/s - Fully programmable baud rate from 300 bits/s to 153.6 Kbits/s - Selection of character sizes from 5 to 8 bits - Selection of odd/even/no parity - Selection of 1 or 2 stop bitsUSAGE*/#include <intLib.h>#include <tickLib.h>#include <msgQLib.h>#include "h/drv/sio/z85230Drv.h"#include "h/drv/sio/z85230Buf.h"#ifdef VME_181#include "h/drv/sio/z85230Dma.h"#include "h/drv/pciBridge/gt64260_dy4.h"#include "dy4181.h"#endif#ifdef VME_183#include "cwv183.h"#endif/* local functions */static STATUS z85230AsyncGetTxChar( struct _Z85230_CHAN * channel, char * ch );static STATUS z85230AsyncPutRxChar( struct _Z85230_CHAN * channel, char ch );static STATUS z85230AsyncTxStartup( Z85230_CHAN * channel );static STATUS z85230AsyncModeSet( Z85230_CHAN * channel, int newMode );static STATUS z85230AsyncConnect( Z85230_CHAN * channel );static STATUS z85230AsyncHup( Z85230_CHAN * channel );static STATUS z85230AsyncOptsSet( Z85230_CHAN * channel, unsigned int options );LOCAL STATUS z85230AsyncModeDmaInit( Z85230_CHAN *);#ifdef VME_181LOCAL void z85230AsyncRxTask( struct _Z85230_CHAN *);#endif/* local structs */typedef struct _Z85230ASYNC { int blockingReadSize; int blockingOnWrite;} Z85230ASYNC;/* local variables */LOCAL Z85230ASYNC async[ Z85230_NUM_CHANNELS ];#ifdef VME_181/* Receive DMA data buffer */LOCAL UINT8 *dmaRxBuf[Z85230_NUM_CHANNELS] = {NULL, NULL} ;/* Receive DMA data descriptor array */LOCAL UINT32 dmaRxBufSize = Z85230ASYNC_DEFAULT_BUFFERSIZE;LOCAL MSG_Q_ID dmaMsgQid[Z85230_NUM_CHANNELS]= {NULL, NULL} ;#endifLOCAL SEM_ID dmaSemID[Z85230_NUM_CHANNELS]= {NULL, NULL} ;/*************************************************************************** * z85230AsyncOptsSet - set the serial options * * Set the channel operating mode to that specified. All sioLib options * are supported: CLOCAL, HUPCL, CREAD, CSIZE, PARENB, and PARODD. * * RETURNS: * Returns OK to indicate success, otherwise ERROR is returned */static STATUS z85230AsyncOptsSet( Z85230_CHAN * channel, unsigned int options ) { channel->hw.options = options; return z85230HwSetOpts( channel, options, FALSE ); }/*************************************************************************** * z85230AsyncHup - hang up the modem control lines * * Resets the RTS and DTR signals. * * RETURNS: OK */static STATUS z85230AsyncHup( Z85230_CHAN * channel ) { /* SCC control reg adr */ volatile unsigned char * cr = channel->hw.cr; /* current interrupt level mask */ int oldlevel; /* contents of WR5 */ unsigned char wreg5; oldlevel = intLock(); REG_8530_WRITE( cr, SCC_WR0_SEL_WR5 ); REG_8530_READ( cr, &wreg5 ); REG_8530_WRITE( cr, SCC_WR0_SEL_WR5 ); REG_8530_WRITE( cr, wreg5 & ~(SCC_WR5_DTR | SCC_WR5_RTS) ); intUnlock( oldlevel ); return OK; } /*************************************************************************** * z85230AsyncConnect - Set the modem control lines * * Set the modem control line DTR TRUE if not already set. * It also clears the receiver, transmitter and enables the fifo. * * RETURNS: OK */static STATUS z85230AsyncConnect( Z85230_CHAN * channel ) { /* SCC control reg adr */ volatile unsigned char * cr = channel->hw.cr; /* current interrupt level mask */ int oldlevel; /* contents of WR5 */ unsigned char wreg5; /* get WR5 */ oldlevel = intLock(); REG_8530_WRITE( cr, SCC_WR0_SEL_WR5 ); REG_8530_READ( cr, &wreg5 ); intUnlock( oldlevel ); if ( (wreg5 & SCC_WR5_DTR) == 0 ) { /* RTS and DTR not set yet: set RTS and DTR TRUE */ oldlevel = intLock(); REG_8530_WRITE( cr, SCC_WR0_SEL_WR5 ); REG_8530_WRITE( cr, wreg5 | SCC_WR5_DTR ); intUnlock( oldlevel ); } return OK; }/*************************************************************************** * z85230AsyncGetTxChar - get char from tx buf */static STATUS z85230AsyncGetTxChar( struct _Z85230_CHAN * channel, char * ch ) { unsigned int options = channel->hw.options; if ( z85230BufReadStreamByte( &(channel->txStreamBuf), ch ) != 1 ) { return ERROR; } /* must mask out unused bits in CS5 - ESCC doesn't care for other * word sizes */ if ( (options & CSIZE) == CS5 ) { *ch &= 0x1f; } return OK; }/*************************************************************************** * z85230AsyncPutRxChar - write char to rx buf */static STATUS z85230AsyncPutRxChar( struct _Z85230_CHAN * channel, char ch ) { unsigned int options = channel->hw.options; /* mask out unused bits */ if ( (options & CSIZE) == CS5 ) { ch &= 0x1f; } else if ( (options & CSIZE) == CS6 ) { ch &= 0x3f; } else if ( (options & CSIZE) == CS7 ) { ch &= 0x7f; } if ( z85230BufWriteStreamByte( &(channel->rxStreamBuf), ch ) ) { return OK; } return ERROR; }/*************************************************************************** * z85230AsyncTxStartup - start interrupt transmitter * * NOMANUAL aak updated */LOCAL STATUS z85230AsyncTxStartup( Z85230_CHAN * channel ) { char outChar; int lvl;#ifdef VME_181 int size ;#endif int result = Z85230_ERR; lvl = intLock (); if ( channel->hw.mode == Z85230_MODE_DMA ) {#ifdef VME_181 /*Z85230BUF_STREAM* stream = &(channel->txStreamBuf);*/ UINT8 *ptr = z85230DmaGetTxStream( &(channel->txStreamBuf) ); Z85230_ASSERT( channel->channel == Z85230_CHANNEL_A || channel->channel == Z85230_CHANNEL_B ); /* get the stream size */ size = z85230DmaGetTxStreamSize( &(channel->txStreamBuf) ); /* start new DMA transfer */ result = z85230DmaStart(SCC_DMA_CHAN_TX, ptr, channel->hw.txfpga,size);#endif } else /* Z85230_MODE_INT */ { result=z85230AsyncGetTxChar( channel, &outChar ); if (result!= Z85230_ERR) { /* select data register */ REG_8530_WRITE( channel->hw.cr, SCC_WR0_SEL_WR8 ); REG_8530_WRITE( channel->hw.cr, outChar ); } } intUnlock (lvl); return result; }/***************************************************************************/LOCAL STATUS z85230AsyncModeReset( Z85230_CHAN * channel){ int cha = channel->channel;#ifdef VME_181 UINT16 var = 0xffff; UINT8 tmp; /* Send the termination signal to the DMA task */ msgQSend(dmaMsgQid[cha], (char*)&var, sizeof(UINT16),NO_WAIT, MSG_PRI_URGENT); /* * Reset the FPGA DMA facility */ tmp=sysInByte ((UINT32)FPGA_SCC_INT_CNTRL); switch ( cha ) { case Z85230_CHANNEL_A: /* FPGA: Disable the FPGA DMA facility for Ch.A */ sysOutByte ((UINT32)FPGA_SCC_INT_CNTRL, tmp & ~(0xF0)); gtDmaIntDisable(SCC_TXA_DMA_INT); break; case Z85230_CHANNEL_B: /* FPGA: Disable the FPGA DMA facility for Ch.B */ sysOutByte ((UINT32)FPGA_SCC_INT_CNTRL, tmp & ~(0x0F)); gtDmaIntDisable(SCC_TXB_DMA_INT); break; default: return ERROR; } taskLock(); /* reset the DMA channels */ z85230DmaAbort( SCC_DMA_CHAN_RX ); z85230DmaAbort( SCC_DMA_CHAN_TX ); /* Free Rx buffer if allocated */ if( dmaRxBuf[cha] != NULL ) { cacheDmaFree( dmaRxBuf[cha] ); dmaRxBuf[cha] = NULL ; } if(dmaMsgQid[cha] != NULL) { msgQDelete(dmaMsgQid[cha]); dmaMsgQid[cha] = NULL; }#else if(dmaSemID[cha] != NULL) { semDelete(dmaSemID[cha]); dmaSemID[cha] = NULL; } if (z85230HwDisablePort(channel) != OK) return ERROR; taskLock();#endif /* VME_181 */ /* get the streams into a known state */ z85230BufFlushStream( &(channel->txStreamBuf) ); z85230BufFlushStream( &(channel->rxStreamBuf) ); taskUnlock(); return OK;}/*************************************************************************** * z85230AsyncModeSet - change transmit/receive mode * * NOMANUAL aak updated */LOCAL STATUS z85230AsyncModeSet( Z85230_CHAN * channel, int newMode ) { int oldLevel; volatile unsigned char * cr = channel->hw.cr; int result=OK;#ifndef VME_181 UINT32 intCtrl;#endif channel->hw.mode = newMode; z85230AsyncModeReset(channel); if ( channel->hw.mode == Z85230_MODE_INT ) { oldLevel = intLock(); REG_8530_WRITE( cr, SCC_WR0_SEL_WR1 ); /* int and xfer mode */ REG_8530_WRITE( cr, SCC_WR1_INT_ALL_RX | SCC_WR1_TX_INT_EN | SCC_WR1_EXT_INT_EN );#ifndef VME_181 /* To set timeout value */ z85230HwSetTimeout(channel, 0); /* Enable SCC core interrupt */ intCtrl = sysInLong ((UINT32)FPGA_SCC_INT_CNTRL); sysOutLong((UINT32)FPGA_SCC_INT_CNTRL, (intCtrl|SCC_INT));#endif intUnlock( oldLevel ); } else if ( channel->hw.mode == Z85230_MODE_DMA ) {#ifndef VME_181 /* To set timeout value */ z85230HwSetTimeout(channel, channel->hw.baudRate);#endif result = z85230AsyncModeDmaInit(channel); } return result; }/*************************************************************************** * z85230AsyncModeDmaInit - switch to DMA mode * * Takes necessary steps to initialize HW and switch to the DMA mode * * Globals: * dmaRxBuf, dmaMsgQid * NOMANUAL */LOCAL STATUS z85230AsyncModeDmaInit( Z85230_CHAN * channel){ volatile unsigned char * cr = channel->hw.cr; int cha = channel->channel; int oldLevel, result=OK;#ifdef VME_181 char tname[10]; UINT8 tmp;#endif oldLevel = intLock(); REG_8530_WRITE( cr, SCC_WR0_SEL_WR1 ); /* int and xfer mode */ REG_8530_WRITE( cr, SCC_WR1_RDMA_RECTR | SCC_WR1_RDMA_FUNC | SCC_WR1_RDMA_EN ); REG_8530_WRITE( cr, SCC_WR0_SEL_WR14 ); REG_8530_WRITE( cr, SCC_WR14_BR_EN | SCC_WR14_BR_SRC | SCC_WR14_DTR_FUNC | SCC_WR14_SRC_BR ); REG_8530_WRITE( cr, SCC_WR0_SEL_WR7 ); REG_8530_WRITE( cr, SCC_WR7P_DTR_REQ_TIMING | SCC_WR7P_EXT_READ_ENB | SCC_WR7P_TX_FIFO_INT_LVL ); REG_8530_WRITE( cr, SCC_WR0_SEL_WR1 ); /* int and xfer mode */ REG_8530_WRITE( cr, SCC_WR1_RDMA_RECTR | SCC_WR1_RDMA_FUNC | SCC_WR1_RDMA_EN ); intUnlock( oldLevel ); if (!dmaSemID[cha]) { if((dmaSemID[cha] = semCCreate (SEM_Q_PRIORITY, 0)) == NULL) { Z85230_ASSERT(dmaSemID[cha]); return ERROR; } } #ifndef VME_181 result = z85230HwEnablePort(channel);#else /* Allocate a Rx DMA buffer */ if (!dmaRxBuf[cha]) { dmaRxBuf[cha] = cacheDmaMalloc( dmaRxBufSize ); if (dmaRxBuf[cha] == NULL) { Z85230_ASSERT(dmaRxBuf[cha]); return ERROR; } } if (!dmaMsgQid[cha]) { dmaMsgQid[cha] = msgQCreate(100, sizeof(UINT16), MSG_Q_FIFO); if (dmaMsgQid[cha] == NULL) { Z85230_ASSERT(dmaMsgQid[cha]); return ERROR; } } /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -