feat: a better boot command line parser
[lunaix-os.git] / lunaix-os / hal / char / uart / 16550_base.c
1 #include <lunaix/mm/valloc.h>
2 #include <lunaix/status.h>
3
4 #include <usr/lunaix/serial.h>
5
6 #include "16550.h"
7
8 struct uart16550*
9 uart_alloc(ptr_t base_addr)
10 {
11     struct uart16550* uart = valloc(sizeof(struct uart16550));
12
13     // load registers default value
14     uart->cntl_save.rmc = UART_rMC_DTR | UART_rMC_RTS | UART_rMC_IEN;
15     uart->cntl_save.rie = 0;
16
17     uart->base_addr = base_addr;
18     return uart;
19 }
20
21 void
22 uart_free(struct uart16550* uart)
23 {
24     vfree(uart);
25 }
26
27 int
28 uart_general_tx(struct serial_dev* sdev, u8_t* data, size_t len)
29 {
30     struct uart16550* uart = UART16550(sdev);
31
32     size_t i = 0;
33     while (i < len) {
34         while (!uart_can_transmit(uart))
35             ;
36         uart_write_byte(uart, data[i++]);
37     }
38
39     serial_end_xmit(sdev, len);
40
41     return RXTX_DONE;
42 }
43
44 int
45 uart_general_exec_cmd(struct serial_dev* sdev, u32_t req, va_list args)
46 {
47     struct uart16550* uart = UART16550(sdev);
48     switch (req) {
49         case SERIO_RXEN:
50             uart_setie(uart);
51             break;
52         case SERIO_RXDA:
53             uart_clrie(uart);
54             break;
55         default:
56             return ENOTSUP;
57     }
58     return 0;
59 }
60
61 void
62 uart_general_irq_handler(int iv, struct llist_header* ports)
63 {
64     char tmpbuf[32];
65     struct uart16550 *pos, *n;
66     llist_for_each(pos, n, ports, local_ports)
67     {
68         int is = uart_intr_identify(pos);
69         if (iv == pos->iv && (is == UART_CHR_TIMEOUT)) {
70             goto done;
71         }
72     }
73
74     return;
75
76 done:
77     char recv;
78     int i = 0;
79     while ((recv = uart_read_byte(pos))) {
80         tmpbuf[i++] = recv;
81         if (likely(i < 32)) {
82             continue;
83         }
84
85         if (!serial_accept_buffer(pos->sdev, tmpbuf, i)) {
86             uart_clear_rxfifo(pos);
87             return;
88         }
89
90         i = 0;
91     }
92
93     serial_accept_buffer(pos->sdev, tmpbuf, i);
94     serial_accept_one(pos->sdev, 0);
95     
96     serial_end_recv(pos->sdev);
97 }