📄 z8530sio_dy4.c
字号:
/* z8530Sio.c - Z8530 SCC Serial Communications Controller driver *//* Copyright 2000-2002 Dy 4 Systems, Inc. *//* Copyright 1995-1996 Wind River Systems, Inc. *//*modification history--------------------01m,30nov05,tis eliminate compiler warnings CR#12001.01l,28nov05,sch CR 2631 fix - changed max baud rate to 153600 from 3840001k,23feb00,elp Clear SCC_WR5_RTS to enable TX & change include file name01j,09jun97,mas now uses BSP-defined macros for register access and reset delay loop/count (SPR 8566); updated documentation.01i,05jun97,db fixed warning messages.01h,23may97,db added hardware options and modem control flow(SPR #1037).01g,27dec96,dat fixed spr 7683, int ack in wrong place (z8530IntRd).01f,11jun96,dbt fixed spr 6325. replaced everywhere *cr = 0 with *cr = zero. Update Copyright.01g,13oct95,ms initialize all the non-BSP specific fields in z8530DevInit()01f,21sep95,myz fixed the interrupt race problem01e,03aug95,myz fixed the warning messages01d,20jun95,ms fixed comments for mangen01c,15jun95,ms updated for new driver structure01b,28apr95,ms z8530IntRd now only reads the data register once.01a,21dec94,ms written (using z8530Serial.c + the VxMon polled driver).*//*DESCRIPTIONThis is the driver for the Z8530 SCC (Serial Communications Controller).It uses the SCCs in asynchronous mode only.USAGEA Z8530_DUSART structure is used to describe the chip. This data structurecontains two Z8530_CHAN structures which describe the chip's two serialchannels. Supported baud rates range from 50 to 38400. The default baudrate is Z8530_DEFAULT_BAUD (9600). The BSP may redefine this.The BSP's sysHwInit() routine typically calls sysSerialHwInit()which initializes all the values in the Z8530_DUSART structure (exceptthe SIO_DRV_FUNCS) before calling z8530DevInit().The BSP's sysHwInit2() routine typically calls sysSerialHwInit2() whichconnects the chips interrupts via intConnect() (either the singleinterrupt z8530Int or the three interrupts z8530IntWr, z8530IntRd,and z8530IntEx).This driver handles setting of hardware options such as parity(odd, even) andnumber of data bits(5, 6, 7, 8). Hardware flow control is provided with thesignals CTS on transmit and DSR on read. Refer to the target documentationfor the RS232 port configuration. The function HUPCL(hang up on last close) issupported. Default hardware options are defined by Z8530_DEFAULT_OPTIONS.The BSP may redefine them.All device registers are accessed via BSP-defined macros so that memory-mapped as well as I/O space accesses can be supported. The BSP may re-define the REG_8530_READ and REG_8530_WRITE macros as needed. By default,they are defined as simple memory-mapped accesses.The BSP may define DATA_REG_8530_DIRECT to cause direct access to the Z8530data register, where hardware permits it. By default, it is not defined.The BSP may redefine the macro for the channel reset delay Z8530_RESET_DELAYas well as the channel reset delay counter value Z8530_RESET_DELAY_COUNT asrequired. The delay is defined as the minimum time between successive chipaccesses (6 PCLKs + 200 nSec for a Z8530, 4 PCLKs for a Z85C30 or Z85230)plus an additional 4 PCLKs. At a typical PCLK frequency of 10 MHz, each PCLKis 100 nSec, giving a minimum reset delay of:Z8530: 10 PCLKs + 200 nSec = 1200 nSec = 1.2 uSecZ85x30: 8 PCLKs = 800 nSec = 0.8 uSecINCLUDE FILES: drv/sio/z8530Sio.h*/#include "vxWorks.h"#include "sioLib.h"#include "intLib.h"#include "errno.h"#include "drv/sio/z8530Sio.h"#include "boardName.h"#ifndef SIO_HUP# define SIO_OPEN 0x100A# define SIO_HUP 0x100B#endif/* forward static declarations */static void z8530InitChannel (Z8530_CHAN *);static int z8530Ioctl (SIO_CHAN *, int, void *);static int z8530TxStartup (SIO_CHAN *);static int z8530CallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);static int z8530PollInput (SIO_CHAN *, char *);static int z8530PollOutput (SIO_CHAN *, char);LOCAL STATUS z8530OptsSet (Z8530_CHAN *, UINT);LOCAL STATUS z8530Open (Z8530_CHAN * pChan );LOCAL STATUS z8530Hup (Z8530_CHAN * pChan );/* driver functions */static SIO_DRV_FUNCS z8530SioDrvFuncs = { (int (*)())z8530Ioctl, (int (*)())z8530TxStartup, (int (*)())z8530CallbackInstall, (int (*)())z8530PollInput, (int (*)(SIO_CHAN *,char))z8530PollOutput };/* defines */#ifndef Z8530_DEFAULT_BAUD# define Z8530_DEFAULT_BAUD 9600#endif#ifndef Z8530_DEFAULT_OPTIONS /* no handshake, rcvr enabled, 8 data bits, 1 stop bit, no parity */# define Z8530_DEFAULT_OPTIONS (CLOCAL | CREAD | CS8)#endif#ifndef REG_8530_READ# define REG_8530_READ(reg,pVal) *(pVal) = (*(reg))#endif /* REG_8530_READ */#ifndef REG_8530_WRITE# define REG_8530_WRITE(reg,val) (*(reg) = (val))#endif /* REG_8530_WRITE */#ifndef Z8530_RESET_DELAY_COUNT# define Z8530_RESET_DELAY_COUNT 1000#endif /* Z8530_REST_DELAY_COUNT */#ifndef Z8530_RESET_DELAY# define Z8530_RESET_DELAY \ { \ int i; \ for (i = 0; i < Z8530_RESET_DELAY_COUNT; i++) \ ; /* do nothing */ \ }#endif /* Z8530_REST_DELAY *//******************************************************************************** z8530DummyCallback - dummy callback routine.** This routine is used as an intialization default only.** RETURNS: ERROR always*/ static STATUS z8530DummyCallback (void) { return (ERROR); }/******************************************************************************** z8530TxStartup - start the interrupt transmitter.** This routine starts the transmitter if it isn't already transmitting.* This routine should only be called in interrupt mode.** RETURNS: OK always*/static int z8530TxStartup ( SIO_CHAN * pSioChan ) { Z8530_CHAN * pChan = (Z8530_CHAN *)pSioChan; char outChar; int lvl; if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR) { lvl = intLock ();#ifndef DATA_REG_8530_DIRECT REG_8530_WRITE(pChan->cr, SCC_WR0_SEL_WR8); /* select data register */ REG_8530_WRITE(pChan->cr, outChar);#else REG_8530_WRITE(pChan->dr, outChar);#endif /* DATA_REG_8530_DIRECT */ intUnlock (lvl); } return (OK); }/******************************************************************************** z8530CallbackInstall - install ISR callbacks to get/put chars.** This routine installs the specified type of callback routine and its* associated argument for use in read/write character buffer management* as defined in Stream I/O (SIO).** RETURNS: OK or ENOSYS if unknown callback type.*/ static int z8530CallbackInstall ( SIO_CHAN * pSioChan, int callbackType, STATUS (*callback)(), void * callbackArg ) { Z8530_CHAN * pChan = (Z8530_CHAN *)pSioChan; switch (callbackType) { case SIO_CALLBACK_GET_TX_CHAR: pChan->getTxChar = callback; pChan->getTxArg = callbackArg; return (OK); case SIO_CALLBACK_PUT_RCV_CHAR: pChan->putRcvChar = callback; pChan->putRcvArg = callbackArg; return (OK); default: return (ENOSYS); } }/******************************************************************************** z8530PollOutput - output a character in polled mode.** This routine is called to transmit a single character when the driver is* set to polled mode (no interrupts).** RETURNS: OK if a character arrived, EIO on device error, EAGAIN* if the output buffer if full.*/static int z8530PollOutput ( SIO_CHAN * pSioChan, char outChar ) { Z8530_CHAN * pChan = (Z8530_CHAN *)pSioChan; volatile char ch; /* is the transitter ready to accept a character? */ REG_8530_READ(pChan->cr, &ch); if ((ch & SCC_RR0_TX_EMPTY) == 0x00) return (EAGAIN); /* write out the character */#ifndef DATA_REG_8530_DIRECT REG_8530_WRITE(pChan->cr, SCC_WR0_SEL_WR8); /* select data register */ REG_8530_WRITE(pChan->cr, outChar);#else REG_8530_WRITE(pChan->dr, outChar);#endif /* DATA_REG_8530_DIRECT */ return (OK); }/******************************************************************************** z8530PollInput - poll the device for input.** This routine is called to receive a single character when the driver is* set to polled mode (no interrupts).** RETURNS: OK if a character arrived, EIO on device error, EAGAIN* if the input buffer if empty.*/static int z8530PollInput ( SIO_CHAN * pSioChan, char * thisChar ) { Z8530_CHAN * pChan = (Z8530_CHAN *)pSioChan; volatile char ch; /* is a character available? */ REG_8530_READ(pChan->cr, &ch); if ((ch & SCC_RR0_RX_AVAIL) == 0x00) return (EAGAIN); /* yes, get a character */#ifndef DATA_REG_8530_DIRECT REG_8530_WRITE(pChan->cr, SCC_WR0_SEL_WR8); /* select data register */ REG_8530_READ(pChan->cr, thisChar);#else REG_8530_READ(pChan->dr, thisChar);#endif /* DATA_REG_8530_DIRECT */ /* check for errors */ REG_8530_WRITE(pChan->cr, SCC_WR0_SEL_WR1); /* read reg 1 */ REG_8530_READ(pChan->cr, &ch); if ((ch & 0x70) != 0) /* reset if errors */ REG_8530_WRITE(pChan->cr, SCC_WR0_ERR_RST); return (OK); }/******************************************************************************** z8530ModeSet - set driver mode** This routine sets the driver SIO mode. Currently there are only two:* polled and interrupt.** RETURNS: OK if successful* ERROR if illegal mode specified*/static STATUS z8530ModeSet ( Z8530_CHAN * pChan, uint_t newMode ) { int oldlevel; int zero = 0; volatile char * cr = pChan->cr; /* SCC control reg adr */ if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT)) return (ERROR); oldlevel = intLock (); pChan->mode = newMode; if (pChan->mode == SIO_MODE_INT) { 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); } else { REG_8530_WRITE(cr, SCC_WR0_SEL_WR1); /* no interrupts */ REG_8530_WRITE(cr, zero); } intUnlock(oldlevel); return (OK); }/********************************************************************************* z8530InitChannel - initialize a single channel** This routine initializes the specified Z8530 channel to a known and* quiescent state at a default baud rate, no handshake signals. It is* called by z8530DevInit().** RETURNS: N/A*/static void z8530InitChannel ( Z8530_CHAN * pChan ) { int baudConstant; int zero = 0; volatile char * cr = pChan->cr; /* SCC control reg adr */ /* SCC_WR0_NULL_CODE sync the state machine */ REG_8530_WRITE(cr, zero); REG_8530_WRITE(cr, zero); /* reset any error or interrupts */ REG_8530_WRITE(cr, SCC_WR0_ERR_RST); REG_8530_WRITE(cr, SCC_WR0_RST_INT); /* write reg 9 - master interrupt control and reset */ REG_8530_WRITE(cr, SCC_WR0_SEL_WR9); /* reset specified channel */ if (pChan->channel == SCC_CHANNEL_A) REG_8530_WRITE(cr, SCC_WR9_CH_A_RST); /* reset channel A */ else 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 /* initialize registers */ /* write reg 4 - misc parms & modes */ REG_8530_WRITE(cr, SCC_WR0_SEL_WR4); REG_8530_WRITE(cr, SCC_WR4_1_STOP | SCC_WR4_16_CLOCK); /* write reg 3 - receive params */ REG_8530_WRITE(cr, SCC_WR0_SEL_WR3); REG_8530_WRITE(cr, (unsigned char)SCC_WR3_RX_8_BITS); /* write reg 5 - tx params */ REG_8530_WRITE(cr, SCC_WR0_SEL_WR5); REG_8530_WRITE(cr, (UINT8)(SCC_WR5_TX_8_BITS | SCC_WR5_DTR | SCC_WR5_RTS));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -