www.pudn.com > vXworksBSPfors3c44b0.rar > sngks32cSio.c


/* sngks32cSio.c - Samsung S3C44B0X serial driver */ 
 
 
/* Copyright 1984-2001 Wind River Systems, Inc. */ 
#include "copyright_wrs.h" 
 
/* 
modification history 
-------------------- 
01o,27jul04,a_m  BSP定制 for 多刃剑开发板 
01c,30nov01,m_h  Save pChan->baudRate when setting baud 
01b,26apr01,m_h  convert tabs to spaces for readability 
01a,12apr01,m_h  created from snds100 template. 
*/ 
 
/* 
DESCRIPTION 
 
This is the serial I/O driver for Samsung's KS32C50100 microprocessor which is an 
ARM based processor with several integrated peripherals.  It has an interrupt 
controller, two 32-bit timers, one Ethernet controller,two HDLC controllers, 
one IIC controller, general purpose I/O ports, and a 2 channel DMA controller. 
 
The 2 UART channels integrated with the processor are controlled by this 
driver.  Both the UARTs can work in interrupt mode as well as DMA mode. 
This driver supports only the interrupt mode for the UARTs. 
 
All the UART registers are accessible as 32-bit integers from the internal 
system registers.  The macros SNGKS32C_REG_READ and SNGKS32C_REG_WRITE read and write 
32-bit integers from and to the given addresses.  SNGKS32C_SIO_DEFAULT_BAUD is 
defined to 38400 in this file.  This is the default baud rate with which  
the UART channels will be initialized.  The channels are also initialized  
with one start bit, one stop bit, 8 bit data and no parity bits. 
 
The driver is typically only called only by the BSP. The directly callable 
routines in this module are sngks32cDevInit(), sngks32cDevInit2(), sngks32cIntRcv(),  
sngks32cIntTx(), and sngks32cIntErr(). 
 
The BSP calls sngks32cDevInit() to initialize or reset the device. 
It connects the driver's interrupt handlers (sngks32cIntRcv(), sngks32cIntTx(), 
and sngks32cIntErr()), using intConnect(). 
After connecting the interrupt handlers, the BSP calls sngks32cDevInit2() 
to inform the driver that interrupt mode operation is now possible. 
 
INCLUDES: 
sngks32cSio.h sioLib.h 
 
SEE ALSO: 
 
 
*/ 
 
#include "vxWorks.h" 
#include "sioLib.h" 
#include "intLib.h" 
#include "errno.h" 
#include "sngks32cSio.h" 
#include "ioLib.h" 
 
#define SNGKS32C_BAUD_MIN         1200 
#define SNGKS32C_BAUD_MAX         460860 
#define SNGKS32C_SIO_DEFAULT_BAUD 38400 
 
/* Hardware abstraction macros */ 
 
/* local defines  */ 
 
#ifndef SNGKS32C_SIO_REG_READ 
#define SNGKS32C_SIO_REG_READ(pChan, reg, result) \ 
    ((result) = (*(volatile UINT32 *)((UINT32)(pChan)->regs + (reg)))) 
#endif    /*SNGKS32C_SIO_REG_READ*/ 
 
#ifndef SNGKS32C_SIO_REG_WRITE 
#define SNGKS32C_SIO_REG_WRITE(pChan, reg, data) \ 
    ((*(volatile UINT32 *)((UINT32)(pChan)->regs + (reg))) = (data)) 
#endif    /*SNGKS32C_SIO_REG_WRITE*/ 
 
 
/* for backward compatibility */ 
 
#ifndef    SIO_HUP 
#   define SIO_OPEN    0x100A    /* open channel, raise DTR, RTS */ 
#   define SIO_HUP     0x100B    /* hang-up, lower DTR, RTS */ 
#endif 
 
/* forward static declarations */ 
 
LOCAL int    sngks32cTxStartup (SIO_CHAN * pSioChan); 
LOCAL int    sngks32cCallbackInstall (SIO_CHAN *pSioChan, int callbackType, 
                                      STATUS (*callback)(), void *callbackArg); 
LOCAL int    sngks32cPollOutput (SIO_CHAN *pSioChan, char    outChar); 
LOCAL int    sngks32cPollInput (SIO_CHAN *pSioChan, char *thisChar); 
LOCAL int    sngks32cIoctl (SIO_CHAN *pSioChan, int request, void *arg); 
LOCAL STATUS dummyCallback (void); 
 
/* local variables */ 
 
LOCAL    SIO_DRV_FUNCS sngks32cSioDrvFuncs = 
    { 
    sngks32cIoctl, 
    sngks32cTxStartup, 
    sngks32cCallbackInstall, 
    sngks32cPollInput, 
    sngks32cPollOutput 
    }; 
 
LOCAL BOOL sngks32cIntrMode = FALSE;    /* interrupt mode allowed flag */ 
 
/****************************************************************************** 
* 
* sngks32cDevInit - initialize a SNGKS32C_DUSART 
* 
* This routine initializes the driver 
* function pointers and then resets the chip in a quiescent state. 
* The BSP must have already initialized all the device addresses and the 
* baudFreq fields in the SNGKS32C_DUSART structure before passing it to 
* this routine. 
* 
* RETURNS: N/A 
*/ 
 
void sngks32cDevInit 
    ( 
    SNGKS32C_CHAN * pChan 
    ) 
    { 
    /* initialize each channel's driver function pointers */ 
 
    pChan->sio.pDrvFuncs    = &sngks32cSioDrvFuncs; 
 
    /* install dummy driver callbacks */ 
 
    pChan->getTxChar     = dummyCallback; 
    pChan->putRcvChar    = dummyCallback; 
     
    /* reset the chip */ 
 
	/*SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_ULCON,(INT_CLK | PARITY_NONE | ONE_STOP | WORD_LEN));*/ 
	/*  : deleeted and added */ 
	SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_ULCON,(PARITY_NONE | ONE_STOP | WORD_LEN)); 
	SNGKS32C_SIO_REG_WRITE(pChan,S3C44B0X_UFCON,0x97);	/*0值禁止使用FIFO*/ 
	SNGKS32C_SIO_REG_WRITE(pChan,S3C44B0X_UMCON,0); 
 
    /* setting polled mode is one way to make the device quiet */ 
 
    sngks32cIoctl ((SIO_CHAN *)pChan, SIO_MODE_SET, (void *)SIO_MODE_POLL); 
    sngks32cIoctl ((SIO_CHAN *)pChan, SIO_BAUD_SET, (void *)SNGKS32C_SIO_DEFAULT_BAUD); 
 
    } 
 
/****************************************************************************** 
* 
* sngks32cDevInit2 - initialize a SNGKS32C_DUSART, part 2 
* 
* This routine is called by the BSP after interrupts have been connected. 
* The driver can now operate in interrupt mode.  Before this routine is 
* called only polled mode operations should be allowed. 
* 
* RETURNS: N/A 
* ARGSUSED 
*/ 
 
void sngks32cDevInit2 
    ( 
    SNGKS32C_CHAN * pChan        /* device to initialize */ 
    ) 
    { 
    char      outchar = '\0'; 
    UINT32    status; 
 
    /*  
     * Dummy write to TXBUF to start TX empty interrupt 
     */ 
 
    SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UTXBUF,outchar); 
 
    /* Interrupt mode is allowed */ 
 
    /*SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UCON,UCON_RX|UCON_TX|UCON_BREAK);*/ 
	/*  : deleted and added */ 
    SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UCON,UCON_TX_LEVEL|UCON_RX|UCON_TX|0x80); 
    SNGKS32C_SIO_REG_READ(pChan,SNGKS32C_USTAT, status);     
    while ((status & USTAT_TX_READY) != USTAT_TX_READY) 
        SNGKS32C_SIO_REG_READ(pChan,SNGKS32C_USTAT, status); /*  : added */ 
    /*SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UCON,UCON_RX|UCON_TX);*/ 
	/*  : deleted and added */ 
    SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UCON,UCON_TX_LEVEL|UCON_RX|UCON_TX|0x80); 
    sngks32cIntrMode = TRUE; 
    } 
 
/****************************************************************************** 
* 
* sngks32cIntRcv - handle a channel's receive-character interrupt 
* 
* RETURNS: N/A 
*/  
 
void sngks32cIntRcv 
    ( 
    SNGKS32C_CHAN *    pChan        /* channel generating the interrupt */ 
    ) 
    { 
    char            inChar; 
    UINT32        status; 
    FAST int     oldlevel;    		/*  : added */ 
  
	oldlevel = intLock ();			/*  : added */ 
 
    /* 
     * Grab the input character from the chip and hand it off via a 
     * callback. For chips with input FIFO's it is more efficient 
     * to empty the entire FIFO here. 
     */ 
    /*SNGKS32C_SIO_REG_READ(pChan,SNGKS32C_USTAT, status); 
 
    if((status & USTAT_RX_READY) == USTAT_RX_READY) 
        { 
        SNGKS32C_SIO_REG_READ(pChan,SNGKS32C_URXBUF, inChar); 
        (*pChan->putRcvChar) (pChan->putRcvArg, inChar); 
        }*/ 
	/*  : deleted and added, 循环处理FIFO */ 
    while(1){ 
		SNGKS32C_SIO_REG_READ(pChan,S3C44B0X_UFSTAT, status); 
    	if((status & UFSTAT_RX_COUNT) == 0) break; 
        SNGKS32C_SIO_REG_READ(pChan,SNGKS32C_URXBUF, inChar); 
        (*pChan->putRcvChar) (pChan->putRcvArg, inChar); 
    } 
	 
	intUnlock (oldlevel);			/*  : added */ 
    } 
static int sending = 0;		/*  : added */		 
/****************************************************************************** 
* 
* sngks32cIntTx - handle a channels transmitter-ready interrupt 
* 
* RETURNS: N/A 
*/  
 
void sngks32cIntTx 
    ( 
    SNGKS32C_CHAN *    pChan        /* channel generating the interrupt */ 
    ) 
    { 
    char      outChar; 
    UINT32    status; 
    FAST int     oldlevel; 	/*  : added */ 
    /* 
     * If there's a character to transmit then write it out, else reset 
     * the transmitter. For chips with output FIFO's it is more efficient 
     * to fill the entire FIFO here. 
     */ 
 
    /*SNGKS32C_SIO_REG_READ(pChan,SNGKS32C_USTAT, status);     
 
    if((status & USTAT_TX_READY) != USTAT_TX_READY)     
        return;*/ 
	/*  : deleted and added, 针对FIFO */ 
 	SNGKS32C_SIO_REG_READ(pChan,S3C44B0X_UFSTAT, status); 
	 
	if((status & UFSTAT_TX_FULL) == UFSTAT_TX_FULL)  
		return; 
 
	oldlevel = intLock ();	/*  : added */ 
 
    if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR){ 
        SNGKS32C_SIO_REG_WRITE(pChan, SNGKS32C_UTXBUF, outChar); 
		while(1){			/*  : added */ 
			SNGKS32C_SIO_REG_READ(pChan,S3C44B0X_UFSTAT, status);     
    		if((status & UFSTAT_TX_FULL) == UFSTAT_TX_FULL) break; 
 
			if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) == ERROR) break; 
 
			SNGKS32C_SIO_REG_WRITE(pChan, SNGKS32C_UTXBUF, outChar); 
		}	 
    }	 
    else 
        {     
        intDisable (pChan->intLevelTx); 
		sending = 0;		/*  : added */ 
        /**(UINT32 *) S3C44B0X_INTPEND = (1 << pChan->intLevelTx);*/ 
		/*  : deleted and added */ 
		*(UINT32 *) S3C44B0X_I_ISPC = (1 << pChan->intLevelTx); 
        } 
    intUnlock (oldlevel); 
    } 
/****************************************************************************** 
* 
* sngks32cTxStartup - start the interrupt transmitter 
* 
* RETURNS: OK on success, ENOSYS if the device is polled-only, or 
* EIO on hardware error. 
*/ 
 
LOCAL int sngks32cTxStartup 
    ( 
    SIO_CHAN * pSioChan                 /* channel to start */ 
    ) 
    { 
    char      outChar;			/*  : added */ 
    UINT32    status;			/*  : added */ 
    FAST int     oldlevel;    	/*  : added */ 
 
    SNGKS32C_CHAN * pChan = (SNGKS32C_CHAN *)pSioChan; 
	/*  : deleted */ 
    /**(UINT32 *) SNGKS32C_INTPENDTST |= (1 << pChan->intLevelTx);*/ 
 
	/*  : added */ 
	SNGKS32C_SIO_REG_READ(pChan,S3C44B0X_UFSTAT, status);     
    if((status & UFSTAT_TX_FULL) == UFSTAT_TX_FULL)     
        return (OK); 
	if(sending == 1) return OK; 
    oldlevel = intLock (); 
	 
    intEnable (pChan->intLevelTx); 
 
	/*  : added */ 
	sending = 1; 
    if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR) 
        SNGKS32C_SIO_REG_WRITE(pChan, SNGKS32C_UTXBUF, outChar); 
    intUnlock (oldlevel); 
 
 
    return (OK); 
    } 
 
/****************************************************************************** 
* 
* sngks32cCallbackInstall - install ISR callbacks to get/put chars 
* 
* This driver allows interrupt callbacks for transmitting characters 
* and receiving characters. In general, drivers may support other 
* types of callbacks too. 
* 
* RETURNS: OK on success, or ENOSYS for an unsupported callback type. 
*/  
 
LOCAL int sngks32cCallbackInstall 
    ( 
    SIO_CHAN *    pSioChan,               /* channel */ 
    int           callbackType,           /* type of callback */ 
    STATUS        (*callback)(),          /* callback */ 
    void *        callbackArg             /* parameter to callback */ 
    ) 
    { 
    SNGKS32C_CHAN * pChan = (SNGKS32C_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); 
    } 
    } 
 
/******************************************************************************* 
* 
* sngks32cPollOutput - output a character in polled mode 
* 
* RETURNS: OK if a character arrived, EIO on device error, EAGAIN 
* if the output buffer if full. ENOSYS if the device is 
* interrupt-only. 
*/ 
 
LOCAL int sngks32cPollOutput 
    ( 
    SIO_CHAN *pSioChan, 
    char      outChar 
    ) 
    { 
    SNGKS32C_CHAN * pChan = (SNGKS32C_CHAN *)pSioChan; 
    UINT32    status; 
 
    /* is the transmitter ready to accept a character? */ 
 
    SNGKS32C_SIO_REG_READ (pChan, SNGKS32C_USTAT, status); 
    if ((status & USTAT_TX_READY) == 0x00) 
        return (EAGAIN); 
 
    /* write out the character */ 
 
    SNGKS32C_SIO_REG_WRITE(pChan, SNGKS32C_UTXBUF, outChar); 
    return (OK); 
    } 
 
/****************************************************************************** 
* 
* sngks32cPollInput - poll the device for input 
* 
* RETURNS: OK if a character arrived, EIO on device error, EAGAIN 
* if the input buffer if empty, ENOSYS if the device is 
* interrupt-only. 
*/ 
 
LOCAL int sngks32cPollInput 
    ( 
    SIO_CHAN *    pSioChan, 
    char *        thisChar 
    ) 
    { 
    SNGKS32C_CHAN * pChan = (SNGKS32C_CHAN *)pSioChan; 
    UINT32    status; 
 
    SNGKS32C_SIO_REG_READ (pChan,SNGKS32C_USTAT, status); 
 
    if ((status & USTAT_RX_AVAIL) == 0x00) 
        return (EAGAIN);    /* no input available at this time */ 
 
    /* got a character */ 
 
    SNGKS32C_SIO_REG_READ(pChan, SNGKS32C_URXBUF, *thisChar); 
 
    return (OK); 
    } 
 
/****************************************************************************** 
* 
* sngks32cModeSet - toggle between interrupt and polled mode 
* 
* RETURNS: OK on success, EIO on unsupported mode. 
*/ 
 
LOCAL int sngks32cModeSet 
    ( 
    SNGKS32C_CHAN * pChan,        /* channel */ 
    uint_t          newMode       /* new mode */ 
    ) 
    { 
    UINT32    temp; 
 
    if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT))     
    return (EIO); 
 
 
    /* Don't enter interrupt mode unless it is allowed. */ 
 
    if ((newMode == SIO_MODE_INT) && (!sngks32cIntrMode)) 
    return (EIO); 
 
    /* set the new mode */ 
 
    pChan->mode = newMode; 
 
    if (pChan->mode == SIO_MODE_INT) 
        { 
         
        SNGKS32C_SIO_REG_READ(pChan, SNGKS32C_UCON, temp); 
        temp &=UCON_RX_TX_RESET;    /**Reset RX and TX mode bits*/ 
        temp |= (UCON_RX|UCON_TX); 
        SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UCON, temp); 
        intEnable(pChan->intLevelRx); 
        } 
    else 
        { 
        SNGKS32C_SIO_REG_READ(pChan, SNGKS32C_UCON, temp); 
        temp &=UCON_RX_TX_RESET;    /**Reset RX and TX mode bits*/ 
        temp |= (UCON_RX|UCON_TX); 
        SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UCON, temp); 
        intDisable (pChan->intLevelTx); 
        intDisable (pChan->intLevelRx); 
        } 
     
    return (OK); 
    } 
 
 
/******************************************************************************* 
* 
* sngks32cHup - hang up the modem control lines  
* 
* Resets the RTS and DTR signals. 
* 
* RETURNS: OK 
*/ 
 
LOCAL STATUS sngks32cHup 
    ( 
    SNGKS32C_CHAN * pChan     /* pointer to channel */ 
    ) 
    { 
    FAST int     oldlevel;    /* current interrupt level mask */ 
 
    oldlevel = intLock (); 
 
    /* set RTS and DTR low */ 
 
/*    SNGKS32C_SIO_REG_WRITE(pChan, SNGKS32C_USTAT, USTAT_DTR_LOW);            */ 
    intUnlock (oldlevel); 
 
    return (OK); 
 
    }     
 
/******************************************************************************* 
* 
* sngks32cOpen - Set the modem control lines  
* 
* Set the modem control lines(RTS, DTR) TRUE if not already set.   
* 
* RETURNS: OK 
*/ 
 
LOCAL STATUS sngks32cOpen 
    ( 
    SNGKS32C_CHAN * pChan     /* pointer to channel */ 
    ) 
    { 
    FAST int     oldlevel;    /* current interrupt level mask */ 
 
    oldlevel = intLock (); 
 
    /* set RTS and DTR active */ 
 
/*    SNGKS32C_SIO_REG_WRITE(pChan, SNGKS32C_USTAT, USTAT_DTR_HIGH);    */ 
    intUnlock (oldlevel); 
 
    return (OK); 
    } 
 
/****************************************************************************** 
* 
* sngks32cOptSet - set hardware options 
* 
* This routine sets up the hardware according to the specified option 
* argument.  If the hardware cannot support a particular option value, then 
* it should ignore that portion of the request. 
* 
* RETURNS: OK upon success, or EIO for invalid arguments. 
*/ 
 
LOCAL int sngks32cOptSet 
    ( 
    SNGKS32C_CHAN * pChan,        /* channel */ 
    uint_t    newOpts              /* new options */ 
    ) 
    { 
         
    UINT8 dataBits = 0x03; 
    UINT8 stopBits = 0x00; 
    BOOL hdweFlowCtrl=TRUE; 
    BOOL rcvrEnable = TRUE; 
    int  lvl; 
    UINT8 temp=PARITY_NONE; 
    UINT32 result;     
 
    if (pChan == NULL || newOpts & 0xffffff00) 
    return EIO; 
 
    /* do nothing if options already set */ 
 
    if (pChan->options == newOpts) 
    return OK; 
 
    /* ignore requests for unsupported options */ 
 
    /* decode individual request elements */ 
 
    switch (newOpts & CSIZE) 
    { 
    case CS5: 
        dataBits = 0x00; break; 
    case CS6: 
        dataBits = 0x01; break; 
    case CS7: 
        dataBits = 0x02; break; 
    default: 
    case CS8: 
        dataBits = 0x03; break; 
    } 
 
    if (newOpts & STOPB) 
        stopBits = 0x04; 
    else 
        stopBits = 0x00; 
 
    switch (newOpts & (PARENB|PARODD)) 
    { 
    case PARENB|PARODD: 
        /* enable odd parity */ 
            temp=PARITY_ODD; 
        break; 
 
    case PARENB: 
        /* enable even parity */ 
        temp=PARITY_EVEN;  
        break; 
 
    case PARODD: 
        /* invalid mode, not normally used. */ 
        break; 
 
    default: 
    case 0: 
        temp=PARITY_NONE ;/* no parity */ 
        break; 
    } 
 
    if (newOpts & CLOCAL) 
    { 
        /* clocal disables hardware flow control */ 
        hdweFlowCtrl = FALSE; 
    } 
 
    if ((newOpts & CREAD) == 0) 
        rcvrEnable = FALSE; 
 
 
    lvl = intLock (); 
 
    /* 
     * Reset the device according to dataBits, stopBits, hdweFlowCtrl, 
     * rcvrEnable, and parity selections. 
     */ 
     
    SNGKS32C_SIO_REG_READ(pChan, SNGKS32C_ULCON, result);     
    SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_ULCON,(result|dataBits|temp|stopBits)); 
     
    intUnlock (lvl); 
 
    pChan->options = newOpts; 
 
    return (OK); 
    } 
 
/******************************************************************************* 
* 
* sngks32cIoctl - special device control 
* 
* This routine handles the IOCTL messages from the user. It supports commands  
* to get/set baud rate, mode(INT,POLL), hardware options(parity, number of  
* data bits) and modem control(RTS/CTS and DTR/DSR handshakes). 
* The ioctl commands SIO_HUP and SIO_OPEN are used to implement the HUPCL(hang 
* up on last close) function. 
* 
* As on a UNIX system, requesting a baud rate of zero is translated into 
* a hangup request.  The DTR and RTS lines are dropped.  This should cause 
* a connected modem to drop the connection.  The SIO_HUP command will only 
* hangup if the HUPCL option is active.  The SIO_OPEN function will raise 
* DTR and RTS lines whenever it is called. Use the BAUD_RATE=0 function 
* to hangup when HUPCL is not active. 
* 
* The CLOCAL option will disable hardware flow control.  When selected, 
* hardware flow control is not used.  When not selected hardware flow control 
* is based on the RTS/CTS signals.  CTS is the clear to send input 
* from the other end.  It must be true for this end to begin sending new 
* characters.  In most drivers, the RTS signal will be assumed to be connected 
* to the opposite end's CTS signal and can be used to control output from 
* the other end.  Raising RTS asserts CTS at the other end and the other end 
* can send data.  Lowering RTS de-asserts CTS and the other end will stop 
* sending data. (This is non-EIA defined use of RTS). 
* 
* RETURNS: OK on success, ENOSYS on unsupported request, EIO on failed 
* request. 
*/ 
 
LOCAL int sngks32cIoctl 
    ( 
    SIO_CHAN *    pSioChan,        /* device to control */ 
    int        request,        /* request code */ 
    void *    someArg            /* some argument */ 
    ) 
    { 
    SNGKS32C_CHAN *pChan = (SNGKS32C_CHAN *) pSioChan; 
    int     oldlevel;        /* current interrupt level mask */ 
    int     arg = (int)someArg; 
     
    switch (request) 
    { 
    case SIO_BAUD_SET: 
 
        /* 
         * like unix, a baud request for 0 is really a request to 
         * hangup. 
         */ 
 
        if (arg == 0) 
        return sngks32cHup (pChan); 
 
        /* 
         * Set the baud rate. Return EIO for an invalid baud rate, or 
         * OK on success. 
         */ 
 
        if (arg < SNGKS32C_BAUD_MIN || arg > SNGKS32C_BAUD_MAX) 
            { 
        return (EIO); 
            } 
 
        /* Calculate the baud rate constant for the new baud rate */ 
            switch(arg) 
                { 
                case 1200: 
                    /* disable interrupts during chip access */ 
                    oldlevel = intLock (); 
                    SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UBRDIV,SNGKS32C_CNT0_1200|SNGKS32C_CNT1_VAL); 
                    intUnlock (oldlevel); 
                    pChan->baudRate=arg; 
                    return (OK); 
 
                case 2400: 
                    /* disable interrupts during chip access */ 
                    oldlevel = intLock (); 
                    SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UBRDIV,SNGKS32C_CNT0_2400|SNGKS32C_CNT1_VAL); 
                    intUnlock (oldlevel); 
                    pChan->baudRate=arg; 
                    return (OK); 
 
                case 4800: 
                    /* disable interrupts during chip access */ 
                    oldlevel = intLock (); 
                    SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UBRDIV,SNGKS32C_CNT0_4800|SNGKS32C_CNT1_VAL); 
                    intUnlock (oldlevel); 
                    pChan->baudRate=arg; 
                    return (OK); 
 
                case 9600: 
                    /* disable interrupts during chip access */ 
                    oldlevel = intLock (); 
                    SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UBRDIV,SNGKS32C_CNT0_9600|SNGKS32C_CNT1_VAL); 
                    intUnlock (oldlevel); 
                    pChan->baudRate=arg; 
                    return (OK); 
 
                case 19200: 
                    /* disable interrupts during chip access */ 
                    oldlevel = intLock (); 
                    SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UBRDIV,SNGKS32C_CNT0_19200|SNGKS32C_CNT1_VAL); 
                    intUnlock (oldlevel); 
                    pChan->baudRate=arg; 
                    return (OK); 
 
                case 38400: 
                    /* disable interrupts during chip access */ 
                    oldlevel = intLock (); 
                    SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UBRDIV,SNGKS32C_CNT0_38400|SNGKS32C_CNT1_VAL); 
                    intUnlock (oldlevel); 
                    pChan->baudRate=arg; 
                    return (OK); 
 
                case 57600: 
                    /* disable interrupts during chip access */ 
                    oldlevel = intLock (); 
                    SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UBRDIV,SNGKS32C_CNT0_57600|SNGKS32C_CNT1_VAL); 
                    intUnlock (oldlevel); 
                    pChan->baudRate=arg; 
                    return (OK); 
 
                case 115200: 
                    /* disable interrupts during chip access */ 
                    oldlevel = intLock (); 
                    SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UBRDIV,SNGKS32C_CNT0_115200|SNGKS32C_CNT1_VAL); 
                    intUnlock (oldlevel); 
                    pChan->baudRate=arg; 
                    return (OK); 
 
                          
                default: 
                    return(EIO); 
 
                } 
            break; 
 
    case SIO_BAUD_GET: 
 
            /* Get the baud rate and return OK */ 
            *(int *)arg = pChan->baudRate; 
            break; 
 
    case SIO_MODE_SET: 
 
        /* 
         * Set the mode (e.g., to interrupt or polled). Return OK 
         * or EIO for an unknown or unsupported mode. 
         */ 
 
        return (sngks32cModeSet (pChan, arg)); 
 
    case SIO_MODE_GET: 
             
        /* Get the current mode and return OK.  */ 
 
        *(int *)arg = pChan->mode; 
        return (OK); 
 
    case SIO_AVAIL_MODES_GET: 
 
        /* Get the available modes and return OK.  */ 
 
        *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;  
        return (OK); 
 
    case SIO_HW_OPTS_SET: 
 
        /* 
         * Optional command to set the hardware options (as defined 
         * in sioLib.h). 
         * Return OK, or ENOSYS if this command is not implemented. 
         * Note: several hardware options are specified at once. 
         * This routine should set as many as it can and then return 
         * OK. The SIO_HW_OPTS_GET is used to find out which options 
         * were actually set. 
         */ 
 
        return (sngks32cOptSet (pChan, arg)); 
 
    case SIO_HW_OPTS_GET: 
 
        /* 
         * Optional command to get the hardware options (as defined 
         * in sioLib.h). Return OK or ENOSYS if this command is not 
         * implemented.  Note: if this command is unimplemented, it 
         * will be assumed that the driver options are CREAD | CS8 
         * (e.g., eight data bits, one stop bit, no parity, ints enabled). 
         */ 
 
        *(int *)arg = pChan->options; 
        return (OK); 
 
    case SIO_HUP: 
 
            /* check if hupcl option is enabled */ 
 
            if (pChan->options & HUPCL)  
                return (sngks32cHup (pChan)); 
            return (OK); 
 
    case SIO_OPEN: 
            return (sngks32cOpen (pChan)); /* always open */ 
 
    default: 
        return (ENOSYS); 
    } 
    return (ENOSYS); 
    } 
 
/******************************************************************************* 
* 
* dummyCallback - dummy callback routine 
* 
* RETURNS: ERROR. 
*/ 
 
LOCAL STATUS dummyCallback (void) 
    { 
    return (ERROR); 
    }