X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/8efc0cf32160c68772a2ce1887e6a397852d3d96..28c176b668c841a3b7fb093faccf0efa39257603:/lunaix-os/hal/char/uart/16550_base.c diff --git a/lunaix-os/hal/char/uart/16550_base.c b/lunaix-os/hal/char/uart/16550_base.c index e3dda36..a84e3d0 100644 --- a/lunaix-os/hal/char/uart/16550_base.c +++ b/lunaix-os/hal/char/uart/16550_base.c @@ -2,6 +2,7 @@ #include #include +#include #include "16550.h" @@ -41,6 +42,28 @@ uart_general_tx(struct serial_dev* sdev, u8_t* data, size_t len) return RXTX_DONE; } +#define UART_LCR_RESET \ + (UART_rLC_STOPB | \ + UART_rLC_PAREN | \ + UART_rLC_PAREVN | \ + UART_rLC_DLAB | 0b11) + +static void +uart_set_control_mode(struct uart16550* uart, tcflag_t cflags) +{ + uart->cntl_save.rie &= ~(UART_rIE_ERBFI | UART_rIE_EDSSI); + uart->cntl_save.rie |= (!(cflags & _CLOCAL)) * UART_rIE_EDSSI; + uart->cntl_save.rie |= (!!(cflags & _CREAD)) * UART_rIE_ERBFI; + uart_setie(uart); + + uart->cntl_save.rlc &= ~UART_LCR_RESET; + uart->cntl_save.rlc |= (!!(cflags & _CSTOPB)) * UART_rLC_STOPB; + uart->cntl_save.rlc |= (!!(cflags & _CPARENB)) * UART_rLC_PAREN; + uart->cntl_save.rlc |= (!(cflags & _CPARODD)) * UART_rLC_PAREVN; + uart->cntl_save.rlc |= (cflags & _CSZ_MASK) >> 2; + uart_setlc(uart); +} + int uart_general_exec_cmd(struct serial_dev* sdev, u32_t req, va_list args) { @@ -52,6 +75,12 @@ uart_general_exec_cmd(struct serial_dev* sdev, u32_t req, va_list args) case SERIO_RXDA: uart_clrie(uart); break; + case SERIO_SETBRDIV: + // TODO + break; + case SERIO_SETCNTRLMODE: + uart_set_control_mode(uart, va_arg(args, tcflag_t)); + break; default: return ENOTSUP; } @@ -66,7 +95,7 @@ uart_general_irq_handler(int iv, struct llist_header* ports) llist_for_each(pos, n, ports, local_ports) { int is = uart_intr_identify(pos); - if (iv == pos->iv && (is == UART_DATA_OK || is == UART_CHR_TIMEOUT)) { + if (iv == pos->iv && (is == UART_CHR_TIMEOUT)) { goto done; } } @@ -91,5 +120,7 @@ done: } serial_accept_buffer(pos->sdev, tmpbuf, i); + serial_accept_one(pos->sdev, 0); + serial_end_recv(pos->sdev); }