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

📄 serial_ti16550.c

📁 MIPS YAMON, a famous monitor inc. source, make file and PDF manuals.
💻 C
📖 第 1 页 / 共 3 页
字号:
    UINT16 *getptr;    /* check minor device number */    if(minor >= SERIAL_MAX_16550_DEVICES)    {        return(ERROR_SERIAL_UNKNOWN_DEVICE);    }    /* check for device initialization */    if( phy_lsr[minor] == NULL )    {        return( ERROR_SERIAL_UNKNOWN_DEVICE );    }    SERIAL_TI16550_irqpoll( minor ); /* service UART */    getptr= recv_getptr[minor];    if (getptr == recv_putptr[minor])        return( ERROR_SERIAL_NO_CHARACTER );    if (poll_retcode[minor] != OK)    {        poll_retcode[minor] = OK;        /* flush receive buffer up to the last received ctrl/c or break */        getptr = recv_flushptr[minor];        /* always read CTRL/C in case of 'break' or ctrl/c */        lstat = (*getptr & 0xff00) | CTRL_C;                rc = ERROR_SERIAL_COMM_BREAK;    }    else    {        lstat = *getptr;        rc = OK;    }    *p_param = lstat;    uart_statistics[minor].ua_rx_bytes++;    /* check for errors */    if (lstat & ((SERIAL_LSR_OE<<8) |                 (SERIAL_LSR_PE<<8) |                 (SERIAL_LSR_FE<<8)))    {        if (rc == OK) rc = ERROR_SERIAL_COMM_ERROR ;        if (lstat & (SERIAL_LSR_OE<<8)) uart_statistics[minor].ua_rx_overrun++;        if (lstat & (SERIAL_LSR_PE<<8)) uart_statistics[minor].ua_rx_parity++;        if (lstat & (SERIAL_LSR_FE<<8)) uart_statistics[minor].ua_rx_framing++;    }    if (++getptr >= &recv_buffer[minor][POLLSIZE])        getptr= &recv_buffer[minor][0];    recv_getptr[minor] = getptr;    /* compute room in buffer */    if ( (shadow_mcr[minor] & SERIAL_MCR_RTS) == 0 &&        (((UINT32)getptr - (UINT32)recv_putptr[minor]) &                ((POLLSIZE - 1) * sizeof(*getptr)))                               >= HW_LIMIT_START * sizeof(*getptr) )    {        shadow_mcr[minor] |= SERIAL_MCR_RTS;        PHY_MCR_W(minor, shadow_mcr[minor]);    }    return( rc );}/************************************************************************ * *                          SERIAL_TI16550_irqpoll *  Description : *  ------------- *  Disabling of interrupts around call of SERIAL_TI16550_irq() * ************************************************************************/static UINT32 SERIAL_TI16550_irqpoll(     UINT32 minor ){    UINT32 lstat;    if(sys_disable_int())    {        lstat = SERIAL_TI16550_irq( minor, 0 );        sys_enable_int();    }    else        lstat = SERIAL_TI16550_irq( minor, 0 );    return lstat;}/************************************************************************ * *                          SERIAL_TI16550_irq *  Description : *  ------------- *  This service empties the UART's FIFO buffer and puts the chars into *  the cyclic receive buffer. * *  This routine is called in both polled and interrupt mode. *    and requires interrupts to be disabled. * *  static variables written: *  poll_retcode  BREAK or CTRL/C has been read *  recv_putptr2  pointer to next free position in cyclic queue. * *  static variables read: *  phy_lsr       pointer to UART line status register *  phy_rbr       pointer to UART receive data register *  recv_getptr   pointer to first unread position in cyclic queue. *  recv_flushptr pointer to position of last read break or ctrl/c * ************************************************************************/static UINT32 SERIAL_TI16550_irq(     UINT32 minor,        UINT32 in_intrpt ){    UINT32 lstat; /* LSR_OE, LSR_PE, LSR_FE and LSR_BI are clear on read */    UINT8  rdata;    UINT16 *putptr;    UINT32 room;    putptr = recv_putptr[minor];    /* empty FIFO */    for(lstat = PHY_LSR_R(minor); lstat & SERIAL_LSR_DR; lstat = PHY_LSR_R(minor))    {        rdata = PHY_RBR_R(minor) & 0xff;        uart_statistics[minor].ua_rx_irqs += in_intrpt;        if(lstat & SERIAL_LSR_BI)        {            rdata = CTRL_C;            uart_statistics[minor].ua_rx_break++;        }        /* compute room left in buffer, AFTER this byte has been put */        room = ((UINT32)recv_getptr[minor] - (UINT32)putptr - 1) &                             ((POLLSIZE - 1) * sizeof(*putptr));        if (room <= HW_LIMIT_STOP * sizeof(*putptr) && shadow_flow[minor] != 0)        {            shadow_mcr[minor] &= ~SERIAL_MCR_RTS;            PHY_MCR_W(minor, shadow_mcr[minor]);        }        if(room == 0)        {            lstat |= SERIAL_LSR_OE;  /* overrun */            /* overwrite previous char (overflow anyway) */            if (--putptr < &recv_buffer[minor][0])                putptr= &recv_buffer[minor][POLLSIZE-1];        }        *putptr = (lstat << 8) | rdata;        if(rdata == CTRL_C)        {            poll_retcode[minor]  = ERROR_SERIAL_COMM_BREAK;            recv_flushptr[minor] = putptr;        }        /* increase putptr to its future position */        if( ++putptr >= &recv_buffer[minor][POLLSIZE] )            putptr= &recv_buffer[minor][0];    }    recv_putptr[minor] = putptr;    return lstat;}/************************************************************************ * *                          SERIAL_TI16550_write *  Description : *  ------------- *  This service writes a character on the specified channel * *  Parameters : *  ------------ * *  'major',     IN,    major device number *  'minor',     IN,    minor device number for multi device drivers *  'p_param',   IN,    pointer to character to write * *  Return values : *  --------------- *  'OK' = 0x00:                 character has been written on channel * ************************************************************************/static INT32 SERIAL_TI16550_write(    UINT32 major,          /* IN: major device number             */    UINT32 minor,          /* IN: minor device number             */    UINT8  *p_param )      /* IN: pointer to character to write   */{    /* check minor device number */    if(minor >= SERIAL_MAX_16550_DEVICES)    {        return(ERROR_SERIAL_UNKNOWN_DEVICE);    }    /* check for device initialization */    if( phy_lsr[minor] == NULL )    {        return( ERROR_SERIAL_UNKNOWN_DEVICE );    }    /* check line status and modem status */    for (;;)    {        /* OBS: LSR_OE, LSR_PE, LSR_FE and LSR_BI are cleared on read */        if ( (SERIAL_TI16550_irqpoll( minor ) & SERIAL_LSR_THRE) &&             ((PHY_MSR_R(minor) & SERIAL_MSR_CTS) || shadow_flow[minor] == 0)) break;    }    /* write character */    PHY_THR_W(minor, *p_param);    uart_statistics[minor].ua_tx_bytes++;    return( OK );}/************************************************************************ * *                          SERIAL_TI16550_ctrl *  Description : *  ------------- *  This service performs the actions defined by t_SERIAL_ctrl_command_ids *  on the specified channel. * *  Parameters : *  ------------ * *  'major',     IN,    major device number *  'minor',     IN,    minor device number for multi device drivers *  'p_param',   INOUT, IOCTL structure * *  Return values : *  --------------- *  'OK' = 0x00:                 normal return *  ERROR_SERIAL_COMM_BREAK:     break or ctrl/c received  *  ERROR_SERIAL_COMM_ERROR:     receive error, characters lost * ************************************************************************/static INT32 SERIAL_TI16550_ctrl(    UINT32 major,          /* IN: major device number             */    UINT32 minor,          /* IN: minor device number             */    t_SERIAL_ctrl_descriptor *p_param ) /* INOUT: IOCTL structure */{    UINT32 rcode;    /* check minor device number */    if(minor >= SERIAL_MAX_16550_DEVICES)    {        return(ERROR_SERIAL_UNKNOWN_DEVICE);    }    /* check for device initialization */    if( phy_lsr[minor] == NULL )    {        return( ERROR_SERIAL_UNKNOWN_DEVICE );    }    if(p_param == NULL)    {        return( ERROR_SERIAL_INVALID_ARGUMENT );    }    rcode = OK;    switch( p_param->sc_command )    {      case SERIAL_CTRL_POLL_BREAK:        SERIAL_TI16550_irqpoll(minor); /* service UART */        if( (rcode = poll_retcode[minor]) != OK )        {            /* flush read buffer */            rcode = SERIAL_TI16550_read( major, minor, (UINT8 *)&rcode );        }        break;      case SERIAL_CTRL_GET_STATISTICS:        memcpy((UINT8*)&p_param->sc_arg.sc_statistics,                (UINT8 *)&uart_statistics[minor],               sizeof(uart_statistics[minor]));        break;      case SERIAL_CTRL_GET_LSR:        p_param->sc_arg.sc_linestat = SERIAL_TI16550_irqpoll( minor );        break;      case SERIAL_CTRL_RCV_IRQ:        SERIAL_TI16550_irq( minor, 1 );        break ;      case SERIAL_CTRL_RCV_IRQ_ON:        PHY_IER_W(minor,    SERIAL_IER_RCVEN);	shadow_ier[minor] = SERIAL_IER_RCVEN;        break ;      case SERIAL_CTRL_RCV_IRQ_OFF:        shadow_ier[minor] = 0;	PHY_IER_W(minor, 0);        break;      case SERIAL_CTRL_FORCE_DTR:        if (p_param->sc_arg.sc_dtr == 0)            shadow_mcr[minor] &= ~SERIAL_MCR_DTR;        else            shadow_mcr[minor] |=  SERIAL_MCR_DTR;        PHY_MCR_W(minor, shadow_mcr[minor]);        break;      case SERIAL_CTRL_GET_MSR:        p_param->sc_arg.sc_msr = PHY_MSR_R(minor);        break;      case SERIAL_CTRL_SEND_BREAK:        if (size[minor] == sizeof(UINT8))	{            *(volatile UINT8*)(phy_lcr[minor]) |= SERIAL_LCR_BREAK;            sys_wait_ms(250);            *(volatile UINT8*)(phy_lcr[minor]) &= ~SERIAL_LCR_BREAK;	}	else	{            *(phy_lcr[minor]) |= SERIAL_LCR_BREAK;            sys_wait_ms(250);            *(phy_lcr[minor]) &= ~SERIAL_LCR_BREAK;	}        break;      default:        rcode = ERROR_SERIAL_INVALID_ARGUMENT;    }    return( rcode );}

⌨️ 快捷键说明

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