⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3c2510sio.c

📁 S3c2510下的VXWORKS的BSP源代码(包括了以太网、串口、USB等等驱动)
💻 C
📖 第 1 页 / 共 2 页
字号:
/* s3c2510Sio.c - SAMSUNG S3C2510 UART controller driver */

/* Copyright 2002 SAMSUNG ELECTRONICS */

/*
modification history
--------------------
01a,08feb02,jmLee   created.
*/


#include "vxWorks.h"
#include "intLib.h"
#include "errno.h"

#include "drv/multi/s3c2510.h"
#include "config.h"
#include "drv/intrCtl/s3c2510Intr.h"
#include "drv/sio/s3c2510Sio.h"


#define DEFAULT_BAUD                    9600

/* Local Forward Declarations */

LOCAL STATUS    s3c2510SioDummyCallback(void);
LOCAL int       s3c2510SioBaudSet(S3C2510_SIO_CHAN *pChan, int baudRate);
LOCAL int       s3c2510SioOptsSet(S3C2510_SIO_CHAN *pChan, int options);
LOCAL int       s3c2510SioModeSet(S3C2510_SIO_CHAN *pChan, int sioMode);
LOCAL int       s3c2510SioOpen(S3C2510_SIO_CHAN *pChan);
LOCAL int       s3c2510SioHup(S3C2510_SIO_CHAN *pChan);


LOCAL int       s3c2510SioIoctl(SIO_CHAN *pSioChan, int cmd, void* arg);
LOCAL int       s3c2510SioTxStartup(SIO_CHAN *pSioChan);
LOCAL int       s3c2510SioCallbackInstall(SIO_CHAN *pSioChan, int callbackType, STATUS(*callback)(), void *callbackArg);
LOCAL int       s3c2510SioPollInput(SIO_CHAN *pSioChan, char *inChar);
LOCAL int       s3c2510SioPollOutput(SIO_CHAN *pSioChan, char outChar);

/* Driver Function Table */

LOCAL SIO_DRV_FUNCS s3c2510SioDrvFuncs = {
    s3c2510SioIoctl,
    s3c2510SioTxStartup,
    s3c2510SioCallbackInstall,
    s3c2510SioPollInput,
    s3c2510SioPollOutput
};


/******************************************************************************
*
* s3c2510SioDevInit - initialize a UART
*
* This routine is called to initialize the chip to a quiescent state. Note that
* the `ch' field of S3C2510_CHAN must be less than or equal to the maximum
* number of UART channels to configure as SIOs, as defined in s3c2510.h
*
* RETURNS: N/A
*/

void s3c2510SioDevInit(
    S3C2510_SIO_CHAN *pChan                                 /* device to initialize */
    )
{
    /* Enable peripheral clock. */
    *S3C2510_PCLKDIS &= ~(S3C2510_PCLKDIS_CUART << pChan->ch);

    /* Reset UART Status Register. */
    *S3C2510_USTAT(pChan->ch) = 0xffffffff;

    /* Initialize each channel's structure. */

    pChan->pDrvFuncs    = &s3c2510SioDrvFuncs;

    pChan->getTxChar    = s3c2510SioDummyCallback;
    pChan->putRcvChar   = s3c2510SioDummyCallback;

    s3c2510SioBaudSet(pChan, DEFAULT_BAUD);
    s3c2510SioOptsSet(pChan, CREAD | CS8);
    s3c2510SioModeSet(pChan, SIO_MODE_POLL);

}

/******************************************************************************
*
* s3c2510SioDevInit2 - initialize a UART, 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
*/

void s3c2510SioDevInit2(
    S3C2510_SIO_CHAN *pChan                                 /* device to initialize */
    )
{
}

/*******************************************************************************
*
* s3c2510SioIoctl - 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 s3c2510SioIoctl(
    SIO_CHAN *pSioChan,                                     /* device to control */
    int cmd,                                                /* request code */
    void *arg                                               /* some argument */
    )
{
    S3C2510_SIO_CHAN *pChan = (S3C2510_SIO_CHAN *)pSioChan;
    int status = OK;
    int lockKey;

    switch (cmd)
    {
	/* Set the baud rate. */
    case SIO_BAUD_SET:
        /* Disable interrupts during chip access. */
        lockKey = intLock();

        status = s3c2510SioBaudSet(pChan, (int)arg);

        /* Enable interrupts after chip access. */
        intUnlock(lockKey);
        break;

    /* Get the baud rate. */
    case SIO_BAUD_GET:
        *(int *)arg = pChan->baudRate;
        break;

    /* Set the hardware options (as defined in sioLib.h). */
    case SIO_HW_OPTS_SET:
        /* Disable interrupts during chip access. */
        lockKey = intLock();

        status = s3c2510SioOptsSet(pChan, (int)arg);

        /* Enable interrupts after chip access. */
        intUnlock(lockKey);
        break;

    /* Get the hardware options (as defined in sioLib.h). */
    case SIO_HW_OPTS_GET:
        *(int *)arg = pChan->options;
        break;

	/* Set the mode (e.g., to interrupt or polled). */
    case SIO_MODE_SET:
        /* Disable interrupts during chip access. */
        lockKey = intLock();

        status = s3c2510SioModeSet(pChan, (int)arg);

        /* Enable interrupts after chip access. */
        intUnlock(lockKey);
        break;

    /* Get the current mode. */
    case SIO_MODE_GET:
        *(int *)arg = pChan->sioMode;
        break;

    /* Get the available modes. */
    case SIO_AVAIL_MODES_GET:
        *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
        break;

    case SIO_OPEN:
        status = s3c2510SioOpen(pChan);
        break;

    case SIO_HUP:
        status = s3c2510SioHup(pChan);
        break;

    default:
        status = ENOSYS;
    }

    return (status);
}

/******************************************************************************
*
* s3c2510SioTxStartup - start the interrupt transmitter
*
* RETURNS: OK on success, ENOSYS if the device is polled-only, or EIO on
* hardware error.
*/

LOCAL int s3c2510SioTxStartup(
    SIO_CHAN *pSioChan                                      /* device to start */
    )
{
    S3C2510_SIO_CHAN *pChan = (S3C2510_SIO_CHAN *)pSioChan;

    if (pChan->sioMode != SIO_MODE_INT)                     /* polling mode */
    {
        return ENOSYS;
    }

    /* Enable Transmit Holding Register Empty Interrupt. */
    *S3C2510_UINT(pChan->ch) |= S3C2510_UINT_THEIE;

    return OK;
}

/******************************************************************************
*
* s3c2510SioCallbackInstall - 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 s3c2510SioCallbackInstall(
    SIO_CHAN *pSioChan,                                     /* device */
    int callbackType,                                       /* type of callback */
    STATUS (*callback)(),                                   /* callback */
    void* callbackArg                                       /* parameter to callback */
    )
{
    S3C2510_SIO_CHAN *pChan = (S3C2510_SIO_CHAN *)pSioChan;

    switch (callbackType)
    {
    case SIO_CALLBACK_GET_TX_CHAR:
        pChan->getTxChar    = callback;
        pChan->getTxArg     = callbackArg;
        break;

    case SIO_CALLBACK_PUT_RCV_CHAR:
        pChan->putRcvChar   = callback;
        pChan->putRcvArg    = callbackArg;
        break;

    default:
        return ENOSYS;
    }

    return OK;
}

/******************************************************************************
*
* s3c2510SioPollInput - 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 s3c2510SioPollInput(
    SIO_CHAN *pSioChan,                                     /* device to poll */
    char *inChar                                            /* buffer to receive char */
    )
{
    S3C2510_SIO_CHAN *pChan = (S3C2510_SIO_CHAN *)pSioChan;
    UINT32 stat;

    stat = *S3C2510_USTAT(pChan->ch);

    /* If no valid data present, retry later. */
    if (!(stat & S3C2510_USTAT_RDV))                        /* Receive Data Valid */
    {
        return EAGAIN;
    }

    /* Read character from Receive Data Register. */
    *inChar = (char)*S3C2510_URXBUF(pChan->ch);

    return OK;
}

/*******************************************************************************
*
* s3c2510SioPollOutput - 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 s3c2510SioPollOutput(
    SIO_CHAN *pSioChan,                                     /* device to poll */
    char outChar                                            /* char to transmit */
    )
{
    S3C2510_SIO_CHAN *pChan = (S3C2510_SIO_CHAN *)pSioChan;
    UINT32 stat;

    stat = *S3C2510_USTAT(pChan->ch);

    if (!(stat & S3C2510_USTAT_THE))                        /* Transmit Holding Register Empty */
    {
        return EAGAIN;
    }

    /* Write char to Transmit Data Register. */
    *S3C2510_UTXBUF(pChan->ch) = (VUINT8)outChar;

    return OK;
}

/*******************************************************************************
*
* s3c2510SioIntRx - handle a receive interrupt
*
* This routine handles read interrupts from the UART.
*
* RETURNS: NA
*/

void s3c2510SioIntRx(
    S3C2510_SIO_CHAN *pChan                                 /* device caused Rx interrupt */
    )
{
    int ch = pChan->ch;
    UINT32 stat;
    char inChar;

    stat = *S3C2510_USTAT(ch);

    if (stat & (S3C2510_USTAT_OER |                         /* Overrun Error */
                S3C2510_USTAT_PER |                         /* Parity Error */
                S3C2510_USTAT_FER))                         /* Frame Error */
    {
        /* Clear bits. */
        *S3C2510_USTAT(ch) |= (S3C2510_USTAT_OER |
                               S3C2510_USTAT_PER |
                               S3C2510_USTAT_FER);

#ifdef INCLUDE_LED
        LED_ON(LED8_MASK);
#endif  /* INCLUDE_LED */ 

        return;
    }

    if (ch == 0)                                            /* console UART */
    {
        if (stat & S3C2510_USTAT_RDV)                       /* Receive Data Valid */
        {
            /* Read character from Receive Data Register. */
            inChar = (char)*S3C2510_URXBUF(ch);

            /* Call callback routine. */
            (*pChan->putRcvChar)(pChan->putRcvArg, inChar);
        }
#ifdef INCLUDE_LED
        else
        {
            LED_ON(LED6_MASK);
        }
#endif  /* INCLUDE_LED */ 
    }
    else                                                    /* high-speed UART */
    {
        if (stat & S3C2510_HUSTAT_RFREA)                    /* Receive FIFO Trigger Level Reached */
        {
            UINT32 cnt, i;

            switch (*S3C2510_UCON(ch) & S3C2510_HUCON_RFTL_MASK)
            {
            case S3C2510_HUCON_RFTL_8:
                cnt = 8;
                break;

            case S3C2510_HUCON_RFTL_18:
                cnt = 18;
                break;

            case S3C2510_HUCON_RFTL_28:
                cnt = 28;
                break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -