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

📄 ns16550sio.c

📁 cpc-1631的BSP包for VxWorks操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
		
	if (pChan->options & CLOCAL) 
               	REG(IER, pChan) = pChan->ier | RxFIFO_BIT | TxFIFO_BIT;
	else  
		{
		mask = REG(MSR, pChan) & MSR_CTS;

   		/* if the CTS is asserted enable Tx interrupt */

   		if (mask & MSR_CTS)
			pChan->ier |= TxFIFO_BIT;    /* enable Tx interrupt */
		else
           		pChan->ier &= (~TxFIFO_BIT); /* disable Tx interrupt */

		REG(IER, pChan) = pChan->ier; 
		}	
	}
    else
        {
        /* disable all ns16550 interrupts */ 

        REG(IER, pChan) = 0;   
	}

    pChan->channelMode = newMode;

    intUnlock (oldlevel);

    return (OK);
   }

/*******************************************************************************
*
* ns16550Ioctl - special device control
*
* Includes commands to get/set baud rate, mode(INT,POLL), hardware options(
* parity, number of data bits), and modem control(RTS/CTS and DTR/DSR).
* The ioctl command SIO_HUP is sent by ttyDrv when the last close() function 
* call is made. Likewise SIO_OPEN is sent when the first open() function call
* is made.
*
* RETURNS: OK on success, EIO on device error, ENOSYS on unsupported
*          request.
*/

LOCAL STATUS ns16550Ioctl
    (
    NS16550_CHAN * 	pChan,		/* pointer to channel */
    int			request,	/* request code */
    int        		arg		/* some argument */
    )
    {
    FAST STATUS  status;

    status = OK;

    switch (request)
	{
	case SIO_BAUD_SET:
	    if (arg < NS16550_MIN_RATE || arg > NS16550_MAX_RATE)
		status = EIO;		/* baud rate out of range */
	    else
	        status = ns16550BaudSet (pChan, arg);
	    break;

        case SIO_BAUD_GET:
            *(int *)arg = pChan->baudRate;
            break; 

        case SIO_MODE_SET:
	    status = (ns16550ModeSet (pChan, arg) == OK) ? OK : EIO;
            break;          

        case SIO_MODE_GET:
            *(int *)arg = pChan->channelMode;
            break;

        case SIO_AVAIL_MODES_GET:
            *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
            break;

        case SIO_HW_OPTS_SET:
    	    status = (ns16550OptsSet (pChan, arg) == OK) ? OK : EIO;
    	    break;

        case SIO_HW_OPTS_GET:
            *(int *)arg = pChan->options;
            break;

        case SIO_HUP:
            /* check if hupcl option is enabled */

    	    if (pChan->options & HUPCL) 
	    	status = ns16550Hup (pChan);
            break;
	
	case SIO_OPEN:
            /* check if hupcl option is enabled */

    	    if (pChan->options & HUPCL) 
	    	status = ns16550Open (pChan);
	    break;

        default:
            status = ENOSYS;
	}
    return (status);
    }

/*******************************************************************************
*
* ns16550IntWr - handle a transmitter interrupt 
*
* This routine handles write interrupts from the UART. It reads a character
* and puts it in the transmit holding register of the device for transfer.
*
* If there are no more characters to transmit, transmission is disabled by 
* clearing the transmit interrupt enable bit in the IER(int enable register).
*
* RETURNS: N/A
*
*/

void ns16550IntWr 
    (
    NS16550_CHAN * pChan		/* pointer to channel */	
    )
    {
    char           outChar;
    UINT8          intStatus;

    if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
        REG(THR,pChan) = outChar;	/* write char to Transmit Holding Reg */
    else
        {
        pChan->ier &= (~TxFIFO_BIT);	/* indicates to disable Tx Int */
        REG(IER, pChan) = pChan->ier;
        }
    intStatus = REG(LSR, pChan);     /* read LSR to reset interrupt */
    }

/*******************************************************************************
*
* ns16550IntRd - handle a receiver interrupt 
*
* This routine handles read interrupts from the UART.
*
* RETURNS: N/A
*
*/

void ns16550IntRd 
    (
    NS16550_CHAN * pChan	/* pointer to channel */
    )
    {
    char   inchar;

    /* read character from Receive Holding Reg. */

    inchar = REG(RBR, pChan);

    (*pChan->putRcvChar) (pChan->putRcvArg, inchar);
    }

/*******************************************************************************
*
* ns16550IntEx - miscellaneous interrupt processing
*
* This routine handles miscellaneous interrupts on the UART.
* Not implemented yet.
*
* RETURNS: N/A
*
*/

void ns16550IntEx 
    (
    NS16550_CHAN *pChan		/* pointer to channel */
    )
    {

    /* Nothing for now... */
    }

/********************************************************************************
*
* ns16550Int - interrupt level processing
*
* This routine handles four sources of interrupts from the UART. They are
* prioritized in the following order by the Interrupt Identification Register:
* Receiver Line Status, Received Data Ready, Transmit Holding Register Empty
* and Modem Status.
*
* When a modem status interrupt occurs, the transmit interrupt is enabled if
* the CTS signal is TRUE.
*
* RETURNS: N/A
*
*/

void ns16550Int 
    (
    NS16550_CHAN * pChan	/* pointer to channel */
    )
    {
    FAST volatile char        intStatus;

    /* read the Interrrupt Status Register (Int. Ident.) */

    intStatus = (REG(IIR, pChan)) & 0x0f;

    /*
     * This UART chip always produces level active interrupts, and the IIR 
     * only indicates the highest priority interrupt.  
     * In the case that receive and transmit interrupts happened at
     * the same time, we must clear both interrupt pending to prevent
     * edge-triggered interrupt(output from interrupt controller) from locking
     * up. One way doing it is to disable all the interrupts at the beginning
     * of the ISR and enable at the end.
     */

    REG(IER,pChan) = 0;    /* disable interrupt */

    switch (intStatus)
	{
	case IIR_RLS:
            /* overrun,parity error and break interrupt */

            intStatus = REG(LSR, pChan); /* read LSR to reset interrupt */
	    break;

        case IIR_RDA:     		/* received data available */
	case IIR_TIMEOUT: 
	   /*
	    * receiver FIFO interrupt. In some case, IIR_RDA will
            * not be indicated in IIR register when there is more
	    * than one character in FIFO.
	    */

            ns16550IntRd (pChan);  	/* RxChar Avail */
            break;

       	case IIR_THRE:  /* transmitter holding register ready */
	    {
            char outChar;

            if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
                REG(THR, pChan) = outChar;   /* char to Transmit Holding Reg */
            else
                pChan->ier &= (~TxFIFO_BIT); /* indicates to disable Tx Int */

            }
            intStatus = REG(LSR, pChan);     /* read LSR to reset interrupt */

            break;

	case IIR_MSTAT: /* modem status register */
	   {
	   char	msr;

	   msr = REG(MSR, pChan);

	   /* if CTS is asserted by modem, enable tx interrupt */

	   if ((msr & MSR_CTS) && (msr & MSR_DCTS)) 
	   	pChan->ier |= TxFIFO_BIT;
           else
           	pChan->ier &= (~TxFIFO_BIT); 
	   }
	   break;

        default:
	    break;
        }
    
    REG(IER, pChan) = pChan->ier; /* enable interrupts accordingly */

    }

/*******************************************************************************
*
* ns16550TxStartup - transmitter startup routine
*
* Call interrupt level character output routine and enable interrupt if it is
* in interrupt mode with no hardware flow control.
* If the option for hardware flow control is enabled and CTS is set TRUE,
* then the Tx interrupt is enabled.
* 
* RETURNS: OK, or ENOSYS if in polled mode.
*/

LOCAL int ns16550TxStartup
    (
    NS16550_CHAN * pChan 	/* pointer to channel */
    )
    {
    char mask;

    if (pChan->channelMode == SIO_MODE_INT)
	{
	if (pChan->options & CLOCAL)
		{
		/* No modem control */

		pChan->ier |= TxFIFO_BIT;
 		REG(IER,pChan) = pChan->ier; 
		}
	else
		{
		mask = REG(MSR, pChan) & MSR_CTS;

   		/* if the CTS is asserted enable Tx interrupt */

   		if (mask & MSR_CTS)
			pChan->ier |= TxFIFO_BIT;    /* enable Tx interrupt */
		else
           		pChan->ier &= (~TxFIFO_BIT); /* disable Tx interrupt */

		REG(IER, pChan) = pChan->ier; 
		}
	return (OK);
	}
    else
	{
        return (ENOSYS);
	}
    }

/******************************************************************************
*
* ns16550PollOutput - output a character in polled mode.
*
* RETURNS: OK if a character arrived, EIO on device error, EAGAIN
* if the output buffer if full.
*/

LOCAL int ns16550PollOutput
    (
    NS16550_CHAN *  pChan,	/* pointer to channel */
    char            outChar	/* char to send */
    )
    {
    char pollStatus = REG(LSR, pChan);
    char msr = REG(MSR, pChan);

    /* is the transmitter ready to accept a character? */

    if ((pollStatus & LSR_THRE) == 0x00)
        return (EAGAIN);

    if (!(pChan->options & CLOCAL))	 /* modem flow control ? */
    	{
    	if (msr & MSR_CTS)
    		REG(THR, pChan) = outChar;
	else
		return (EAGAIN);
	}
    else
    	REG(THR, pChan) = outChar;       /* transmit character */

    return (OK);
    }
/******************************************************************************
*
* ns16550PollInput - poll the device for input.
*
* RETURNS: OK if a character arrived, EIO on device error, EAGAIN
* if the input buffer if empty.
*/

LOCAL int ns16550PollInput
    (
    NS16550_CHAN *  pChan,	/* pointer to channel */
    char *          pChar 	/* pointer to char */
    )
    {

    char pollStatus = REG(LSR, pChan);

    if ((pollStatus & LSR_DR) == 0x00)
        return (EAGAIN);

    /* got a character */

    *pChar = REG(RBR, pChan);

    return (OK);
    }

/******************************************************************************
*
* ns16550CallbackInstall - install ISR callbacks to get/put chars.
*
* This routine installs the callback functions for the driver
*
* RETURNS: OK on success or ENOSYS on unsupported callback type.
*/

LOCAL int ns16550CallbackInstall
    (
    SIO_CHAN *  pSioChan,	/* pointer to device to control */
    int         callbackType,	/* callback type(tx or receive) */
    STATUS      (*callback)(),	/* pointer to callback function */
    void *      callbackArg	/* callback function argument */
    )
    {
    NS16550_CHAN * pChan = (NS16550_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);
        }

    }


⌨️ 快捷键说明

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