refactor: one more step towards arch-agnostic design
[lunaix-os.git] / lunaix-os / kernel / peripheral / serial.c
1 #include <hal/cpu.h>
2 #include <lunaix/peripheral/serial.h>
3 #include <lunaix/syslog.h>
4 #include <sys/port_io.h>
5
6 LOG_MODULE("UART")
7
8 void
9 serial_init_port(ptr_t port)
10 {
11     // disable interrupt, use irq instead
12     port_wrbyte(COM_RIE(port), 0);
13
14     // baud rate config (DLAB = 1)
15     port_wrbyte(COM_RCLINE(port), 0x80);
16     port_wrbyte(COM_RRXTX(port), BAUD_9600);
17     port_wrbyte(COM_RIE(port), 0);
18
19     // transmission size = 7bits, no parity, 1 stop bits
20     port_wrbyte(COM_RCLINE(port), 0x2);
21
22     // rx trigger level = 14, clear rx/tx buffer, enable buffer
23     port_wrbyte(COM_RCFIFO(port), 0xcf);
24
25     port_wrbyte(COM_RCMODEM(port), 0x1e);
26
27     port_wrbyte(COM_RRXTX(port), 0xaa);
28
29     if (port_rdbyte(COM_RRXTX(port)) != 0xaa) {
30         kprintf(KWARN "port.%p: faulty\n", port);
31         return;
32     }
33
34     port_wrbyte(COM_RCMODEM(port), 0xf);
35     port_wrbyte(COM_RIE(port), 0x1);
36     kprintf("port.%p: ok\n", port);
37 }
38
39 void
40 serial_init()
41 {
42     cpu_disable_interrupt();
43     serial_init_port(SERIAL_COM1);
44     serial_init_port(SERIAL_COM2);
45     cpu_enable_interrupt();
46 }
47
48 char
49 serial_rx_byte(ptr_t port)
50 {
51     while (!(port_rdbyte(COM_RSLINE(port)) & 0x01))
52         ;
53
54     return port_rdbyte(COM_RRXTX(port));
55 }
56
57 void
58 serial_rx_buffer(ptr_t port, char* data, size_t len)
59 {
60     for (size_t i = 0; i < len; i++) {
61         data[i] = serial_rx_byte(port);
62     }
63 }
64
65 void
66 serial_tx_byte(ptr_t port, char data)
67 {
68     while (!(port_rdbyte(COM_RSLINE(port)) & 0x20))
69         ;
70
71     port_wrbyte(COM_RRXTX(port), data);
72 }
73
74 void
75 serial_tx_buffer(ptr_t port, char* data, size_t len)
76 {
77     for (size_t i = 0; i < len; i++) {
78         serial_tx_byte(port, data[i]);
79     }
80 }
81
82 void
83 serial_clear_fifo(ptr_t port)
84 {
85     port_wrbyte(COM_RIE(port), 0x0);
86     port_wrbyte(COM_RCFIFO(port), 0x00);
87
88     port_wrbyte(COM_RCFIFO(port), 0xcf);
89     port_wrbyte(COM_RIE(port), 0x1);
90 }
91
92 void
93 serial_disable_irq(ptr_t port)
94 {
95     port_wrbyte(COM_RIE(port), 0x0);
96 }
97
98 void
99 serial_enable_irq(ptr_t port)
100 {
101     port_wrbyte(COM_RIE(port), 0x1);
102 }