教程介绍和环境搭建 (#19)
[lunaix-os.git] / lunaix-os / hal / char / uart / 16550.h
1 #ifndef __LUNAIX_16550_H
2 #define __LUNAIX_16550_H
3
4 #include <hal/serial.h>
5 #include <lunaix/types.h>
6
7 #define UART_rRxTX 0
8 #define UART_rIE 1
9 #define UART_rII 2
10 #define UART_rFC 2
11 #define UART_rLC 3
12 #define UART_rMC 4
13 #define UART_rLS 5
14 #define UART_rMS 6
15 #define UART_rSC 7
16 #define UART_rDLL 0
17 #define UART_rDLM 1
18
19 #define UART_INTRX 0x1
20 #define UART_DLAB (1 << 7)
21 #define UART_LOOP (1 << 4)
22
23 #define UART_rIE_ERBFI 1
24 #define UART_rIE_ETBEI (1 << 1)
25 #define UART_rIE_ELSI (1 << 2)
26 #define UART_rIE_EDSSI (1 << 3)
27
28 #define UART_rLS_THRE (1 << 5)
29 #define UART_rLS_DR 1
30 #define UART_rLS_BI (1 << 4)
31
32 #define UART_rII_FIFOEN (0b11 << 6)
33 #define UART_rII_ID 0b1111
34
35 #define UART_rFC_EN 1
36 #define UART_rFC_DMA1 (1 << 3)
37 #define UART_rFC_XMIT_RESET (1 << 2)
38 #define UART_rFC_RCVR_RESET (1 << 1)
39
40 #define UART_rMC_DTR 1
41 #define UART_rMC_RTS (1 << 1)
42 #define UART_rMC_IEN (1 << 3)
43
44 #define UART_FIFO1 0b00
45 #define UART_FIFO4 0b01
46 #define UART_FIFO8 0b10
47 #define UART_FIFO14 0b11
48
49 #define UART_NO_INTR 0b0001
50 #define UART_LINE_UDPDATE 0b0110
51 #define UART_DATA_OK 0b0100
52 #define UART_CHR_TIMEOUT 0b1100
53 #define UART_SENT_ALL 0b0010
54 #define UART_MODEM_UPDATE 0b0000
55
56 struct uart16550
57 {
58     struct llist_header local_ports;
59     struct serial_dev* sdev;
60     ptr_t base_addr;
61     int iv;
62
63     struct
64     {
65         u8_t rie;
66         u8_t rfc;
67         u8_t rmc;
68     } cntl_save;
69
70     u32_t (*read_reg)(struct uart16550* uart, ptr_t regoff);
71     void (*write_reg)(struct uart16550* uart, ptr_t regoff, u32_t val);
72 };
73
74 #define UART16550(sdev) ((struct uart16550*)(sdev)->backend)
75
76 static inline void
77 uart_setup(struct uart16550* uart)
78 {
79     uart->write_reg(uart, UART_rMC, uart->cntl_save.rmc);
80     uart->write_reg(uart, UART_rIE, uart->cntl_save.rie);
81 }
82
83 static inline void
84 uart_clrie(struct uart16550* uart)
85 {
86     uart->cntl_save.rie = uart->read_reg(uart, UART_rIE);
87     uart->write_reg(uart, UART_rIE, 0);
88 }
89
90 static inline void
91 uart_setie(struct uart16550* uart)
92 {
93     uart->write_reg(uart, UART_rIE, uart->cntl_save.rie | 1);
94 }
95
96 struct uart16550*
97 uart_alloc(ptr_t base_addr);
98
99 void
100 uart_free(struct uart16550*);
101
102 static inline int
103 uart_baud_divisor(struct uart16550* uart, int div)
104 {
105     u32_t rlc = uart->read_reg(uart, UART_rLC);
106
107     uart->write_reg(uart, UART_rLC, UART_DLAB | rlc);
108     u8_t ls = (div & 0xff), ms = (div & 0xff00) >> 8;
109
110     uart->write_reg(uart, UART_rLS, ls);
111     uart->write_reg(uart, UART_rMS, ms);
112
113     uart->write_reg(uart, UART_rLC, rlc & ~UART_DLAB);
114
115     return 0;
116 }
117
118 static inline int
119 uart_testport(struct uart16550* uart, char test_code)
120 {
121     u32_t rmc = uart->cntl_save.rmc;
122     uart->write_reg(uart, UART_rMC, rmc | UART_LOOP);
123
124     uart->write_reg(uart, UART_rRxTX, test_code);
125
126     u32_t result = (char)uart->read_reg(uart, UART_rRxTX) == test_code;
127     uart->write_reg(uart, UART_rMC, rmc & ~UART_LOOP);
128
129     return result;
130 }
131
132 static inline int
133 uart_pending_data(struct uart16550* uart)
134 {
135     return uart->read_reg(uart, UART_rLS) & UART_rLS_DR;
136 }
137
138 static inline int
139 uart_can_transmit(struct uart16550* uart)
140 {
141     return uart->read_reg(uart, UART_rLS) & UART_rLS_THRE;
142 }
143
144 /**
145  * @brief End of receiving
146  *
147  * @param uart
148  * @return int
149  */
150 static inline int
151 uart_eorcv(struct uart16550* uart)
152 {
153     return uart->read_reg(uart, UART_rLS) & UART_rLS_BI;
154 }
155
156 static inline int
157 uart_enable_fifo(struct uart16550* uart, int trig_lvl)
158 {
159     uart->cntl_save.rfc =
160       UART_rFC_EN | ((trig_lvl & 0b11) << 6) | UART_rFC_DMA1;
161     uart->write_reg(uart, UART_rFC, uart->cntl_save.rfc);
162
163     return uart->read_reg(uart, UART_rII) & UART_rII_FIFOEN;
164 }
165
166 static inline void
167 uart_clear_rxfifo(struct uart16550* uart)
168 {
169     uart->write_reg(uart, UART_rFC, uart->cntl_save.rfc | UART_rFC_RCVR_RESET);
170 }
171
172 static inline void
173 uart_clear_txfifo(struct uart16550* uart)
174 {
175     uart->write_reg(uart, UART_rFC, uart->cntl_save.rfc | UART_rFC_XMIT_RESET);
176 }
177
178 static inline void
179 uart_clear_fifo(struct uart16550* uart)
180 {
181     u32_t rfc = uart->cntl_save.rfc | UART_rFC_XMIT_RESET | UART_rFC_RCVR_RESET;
182     uart->write_reg(uart, UART_rFC, rfc);
183 }
184
185 static inline int
186 uart_intr_identify(struct uart16550* uart)
187 {
188     u32_t rii = uart->read_reg(uart, UART_rII);
189     return (rii & UART_rII_ID);
190 }
191
192 static inline u8_t
193 uart_read_byte(struct uart16550* uart)
194 {
195     return (u8_t)uart->read_reg(uart, UART_rRxTX);
196 }
197
198 static inline void
199 uart_write_byte(struct uart16550* uart, u8_t val)
200 {
201     uart->write_reg(uart, UART_rRxTX, val);
202 }
203
204 int
205 uart_general_exec_cmd(struct serial_dev* sdev, u32_t req, va_list args);
206
207 int
208 uart_general_tx(struct serial_dev* sdev, u8_t* data, size_t len);
209
210 void
211 uart_general_irq_handler(int iv, struct llist_header* ports);
212
213 #endif /* __LUNAIX_16550_H */