44 |
44 |
#define UART_GET_DLM(n) (((n)>>8)&0xFF)
|
45 |
45 |
|
46 |
46 |
/// IER
|
47 |
|
#define UART_INT_EN_RECEIVED_DATA_POS 0
|
48 |
|
#define UART_INT_EN_TRANSMITTER_EMPTY_POS 1
|
|
47 |
#define UART_INT_EN_RX_POS 0
|
|
48 |
#define UART_INT_EN_TX_POS 1
|
49 |
49 |
#define UART_INT_EN_RECEIVER_LINE_STAT_POS 2
|
50 |
50 |
#define UART_INT_EN_MODEM_STAT_POS 3
|
51 |
51 |
|
52 |
|
#define UART_INT_EN_RECEIVED_DATA (BIT(0))
|
53 |
|
#define UART_INT_EN_TRANSMITTER_EMPTY (BIT(1))
|
|
52 |
#define UART_INT_EN_RX (BIT(0))
|
|
53 |
#define UART_INT_EN_TX (BIT(1))
|
54 |
54 |
#define UART_INT_EN_RECEIVER_LINE_STAT (BIT(2))
|
55 |
55 |
#define UART_INT_EN_MODEM_STAT (BIT(3))
|
56 |
56 |
|
57 |
|
#define UART_INT_EN_GET_RECEIVED_DATA(n) (((n)&UART_INT_EN_RECEIVED_DATA )>>UART_INT_EN_RECEIVED_DATA_POS )
|
58 |
|
#define UART_INT_EN_GET_TRANSMITTER_EMPTY(n) (((n)&UART_INT_EN_TRANSMITTER_EMPTY )>>UART_INT_EN_TRANSMITTER_EMPTY_POS )
|
59 |
|
#define UART_INT_EN_GET_RECEIVER_LINE_STAT(n) (((n)&UART_INT_EN_RECEIVER_LINE_STAT)>>UART_INT_EN_RECEIVER_LINE_STAT_POS)
|
60 |
|
#define UART_INT_EN_GET_MODEM_STAT(n) (((n)&UART_INT_EN_MODEM_STAT )>>UART_INT_EN_MODEM_STAT_POS )
|
|
57 |
#define UART_GET_INT_EN_RX(n) (((n)&UART_INT_EN_RX )>>UART_INT_EN_RX_POS )
|
|
58 |
#define UART_GET_INT_EN_TX(n) (((n)&UART_INT_EN_TX )>>UART_INT_EN_TX_POS )
|
|
59 |
#define UART_GET_INT_EN_RECEIVER_LINE_STAT(n) (((n)&UART_INT_EN_RECEIVER_LINE_STAT)>>UART_INT_EN_RECEIVER_LINE_STAT_POS)
|
|
60 |
#define UART_GET_INT_EN_MODEM_STAT(n) (((n)&UART_INT_EN_MODEM_STAT )>>UART_INT_EN_MODEM_STAT_POS )
|
61 |
61 |
|
62 |
62 |
/// LSR
|
63 |
63 |
#define UART_RECEIVER_READY_POS 0
|
... | ... | |
69 |
69 |
#define UART_GET_RECEIVER_READY(n) (((n)&UART_RECEIVER_READY )>>UART_RECEIVER_READY_POS )
|
70 |
70 |
#define UART_GET_TRANSMITTER_EMPTY(n) (((n)&UART_TRANSMITTER_EMPTY )>>UART_TRANSMITTER_EMPTY_POS )
|
71 |
71 |
|
|
72 |
static void uart_parse_config(uart_config *config){
|
|
73 |
/// LCR
|
|
74 |
config->bits_per_char = UART_GET_BITS_PER_CHAR (config->lcr);
|
|
75 |
config->stop_bits = UART_GET_STOP_BITS (config->lcr);
|
|
76 |
config->parity = UART_GET_PARITY (config->lcr); if((config->parity & BIT(0)) == 0) config->parity = uart_parity_none;
|
|
77 |
config->break_control = UART_GET_BREAK_CONTROL (config->lcr);
|
|
78 |
config->dlab = UART_GET_DLAB (config->lcr);
|
|
79 |
/// IER
|
|
80 |
config->received_data_int = UART_GET_INT_EN_RX (config->ier);
|
|
81 |
config->transmitter_empty_int = UART_GET_INT_EN_TX (config->ier);
|
|
82 |
config->receiver_line_stat_int = UART_GET_INT_EN_RECEIVER_LINE_STAT(config->ier);
|
|
83 |
config->modem_stat_int = UART_GET_INT_EN_MODEM_STAT (config->ier);
|
|
84 |
/// DIV LATCH
|
|
85 |
config->divisor_latch = UART_GET_DIV_LATCH(config->dlm, config->dll);
|
|
86 |
}
|
|
87 |
|
|
88 |
static int uart_get_lcr(int base_addr, uint8_t *p){
|
|
89 |
return util_sys_inb(base_addr+UART_LCR, p);
|
|
90 |
}
|
|
91 |
static int uart_set_lcr(int base_addr, uint8_t config){
|
|
92 |
if(sys_outb(base_addr+UART_LCR, config)) return WRITE_ERROR;
|
|
93 |
return SUCCESS;
|
|
94 |
}
|
|
95 |
static int uart_get_lsr(int base_addr, uint8_t *p){
|
|
96 |
return util_sys_inb(base_addr+UART_LSR, p);
|
|
97 |
}
|
|
98 |
|
|
99 |
static int uart_enable_divisor_latch(int base_addr){
|
|
100 |
int ret = SUCCESS;
|
|
101 |
uint8_t conf; if((ret = uart_get_lcr(base_addr, &conf))) return ret;
|
|
102 |
return uart_set_lcr(base_addr, conf | UART_DLAB);
|
|
103 |
}
|
|
104 |
static int uart_disable_divisor_latch(int base_addr){
|
|
105 |
int ret = SUCCESS;
|
|
106 |
uint8_t conf; if((ret = uart_get_lcr(base_addr, &conf))) return ret;
|
|
107 |
return uart_set_lcr(base_addr, conf & (~UART_DLAB));
|
|
108 |
}
|
|
109 |
|
|
110 |
static int uart_get_ier(int base_addr, uint8_t *p){
|
|
111 |
int ret;
|
|
112 |
if((ret = uart_disable_divisor_latch(base_addr))) return ret;
|
|
113 |
return util_sys_inb(base_addr+UART_IER, p);
|
|
114 |
}
|
|
115 |
static int uart_set_ier(int base_addr, uint8_t n){
|
|
116 |
int ret;
|
|
117 |
if((ret = uart_disable_divisor_latch(base_addr))) return ret;
|
|
118 |
if(sys_outb(base_addr+UART_IER, n)) return WRITE_ERROR;
|
|
119 |
return SUCCESS;
|
|
120 |
}
|
|
121 |
|
72 |
122 |
int uart_get_config(int base_addr, uart_config *config){
|
73 |
123 |
int ret = SUCCESS;
|
74 |
124 |
|
75 |
125 |
config->base_addr = base_addr;
|
76 |
126 |
|
77 |
|
if((ret = util_sys_inb(base_addr+UART_LCR, &config->lcr))) return ret;
|
|
127 |
if((ret = uart_get_lcr(base_addr, &config->lcr))) return ret;
|
78 |
128 |
|
79 |
|
if((ret = util_sys_inb(base_addr+UART_IER, &config->ier))) return ret;
|
|
129 |
if((ret = uart_get_ier(base_addr, &config->ier))) return ret;
|
80 |
130 |
|
81 |
131 |
if((ret = uart_enable_divisor_latch (base_addr))) return ret;
|
82 |
132 |
if((ret = util_sys_inb(base_addr+UART_DLL, &config->dll ))) return ret;
|
... | ... | |
86 |
136 |
uart_parse_config(config);
|
87 |
137 |
return ret;
|
88 |
138 |
}
|
89 |
|
void uart_parse_config(uart_config *config){
|
90 |
|
/// LCR
|
91 |
|
config->bits_per_char = UART_GET_BITS_PER_CHAR (config->lcr);
|
92 |
|
config->stop_bits = UART_GET_STOP_BITS (config->lcr);
|
93 |
|
config->parity = UART_GET_PARITY (config->lcr); if((config->parity & BIT(0)) == 0) config->parity = uart_parity_none;
|
94 |
|
config->break_control = UART_GET_BREAK_CONTROL (config->lcr);
|
95 |
|
config->dlab = UART_GET_DLAB (config->lcr);
|
96 |
|
/// IER
|
97 |
|
config->received_data_int = UART_INT_EN_GET_RECEIVED_DATA (config->ier);
|
98 |
|
config->transmitter_empty_int = UART_INT_EN_GET_TRANSMITTER_EMPTY (config->ier);
|
99 |
|
config->receiver_line_stat_int = UART_INT_EN_GET_RECEIVER_LINE_STAT(config->ier);
|
100 |
|
config->modem_stat_int = UART_INT_EN_GET_MODEM_STAT (config->ier);
|
101 |
|
/// DIV LATCH
|
102 |
|
config->divisor_latch = UART_GET_DIV_LATCH(config->dlm, config->dll);
|
103 |
|
}
|
104 |
139 |
void uart_print_config(uart_config config){
|
105 |
140 |
|
106 |
141 |
printf("%s configuration:\n", (config.base_addr == COM1_ADDR ? "COM1" : "COM2"));
|
... | ... | |
119 |
154 |
(config.transmitter_empty_int ? "ENABLED":"DISABLED"));
|
120 |
155 |
}
|
121 |
156 |
|
122 |
|
int uart_enable_divisor_latch(int base_addr){
|
123 |
|
int ret = SUCCESS;
|
124 |
|
uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret;
|
125 |
|
return uart_write_config(base_addr, conf | UART_DLAB);
|
126 |
|
}
|
127 |
|
int uart_disable_divisor_latch(int base_addr){
|
128 |
|
int ret = SUCCESS;
|
129 |
|
uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret;
|
130 |
|
return uart_write_config(base_addr, conf & (~UART_DLAB));
|
131 |
|
}
|
132 |
|
|
133 |
|
int uart_write_config(int base_addr, uint8_t config){
|
134 |
|
if(sys_outb(base_addr+UART_LCR, config)) return WRITE_ERROR;
|
135 |
|
return SUCCESS;
|
136 |
|
}
|
137 |
157 |
int uart_set_bits_per_character(int base_addr, uint8_t bits_per_char){
|
138 |
158 |
if(bits_per_char < 5 || bits_per_char > 8) return INVALID_ARG;
|
139 |
159 |
int ret = SUCCESS;
|
140 |
160 |
bits_per_char = (bits_per_char-5)&0x3;
|
141 |
|
uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret;
|
|
161 |
uint8_t conf; if((ret = uart_get_lcr(base_addr, &conf))) return ret;
|
142 |
162 |
conf = (conf & (~UART_BITS_PER_CHAR)) | bits_per_char;
|
143 |
|
return uart_write_config(base_addr, conf);
|
|
163 |
return uart_set_lcr(base_addr, conf);
|
144 |
164 |
}
|
145 |
165 |
int uart_set_stop_bits(int base_addr, uint8_t stop){
|
146 |
166 |
if(stop != 1 && stop != 2) return INVALID_ARG;
|
147 |
167 |
int ret = SUCCESS;
|
148 |
168 |
stop -= 1;
|
149 |
169 |
stop = (stop&1)<<2;
|
150 |
|
uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret;
|
|
170 |
uint8_t conf; if((ret = uart_get_lcr(base_addr, &conf))) return ret;
|
151 |
171 |
conf = (conf & (~UART_STOP_BITS)) | stop;
|
152 |
|
return uart_write_config(base_addr, conf);
|
|
172 |
return uart_set_lcr(base_addr, conf);
|
153 |
173 |
}
|
154 |
174 |
int uart_set_parity(int base_addr, uart_parity par){
|
155 |
175 |
int ret = SUCCESS;
|
156 |
176 |
uint8_t parity = par << 3;
|
157 |
|
uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret;
|
|
177 |
uint8_t conf; if((ret = uart_get_lcr(base_addr, &conf))) return ret;
|
158 |
178 |
conf = (conf & (~UART_PARITY)) | parity;
|
159 |
|
return uart_write_config(base_addr, conf);
|
|
179 |
return uart_set_lcr(base_addr, conf);
|
160 |
180 |
}
|
161 |
181 |
int uart_set_bit_rate(int base_addr, float bit_rate){
|
162 |
182 |
int ret = SUCCESS;
|
... | ... | |
170 |
190 |
return SUCCESS;
|
171 |
191 |
}
|
172 |
192 |
|
173 |
|
/// PRIVATE
|
174 |
|
int uart_get_lsr(int base_addr, uint8_t *p){
|
175 |
|
return util_sys_inb(base_addr+UART_LSR, p);
|
176 |
|
}
|
177 |
|
/**
|
178 |
|
* @brief Get char from RBR.
|
179 |
|
*/
|
180 |
|
int uart_get_char(int base_addr, uint8_t *p){
|
|
193 |
static int uart_get_char(int base_addr, uint8_t *p){
|
181 |
194 |
int ret;
|
182 |
195 |
if((ret = uart_disable_divisor_latch(base_addr))) return ret;
|
183 |
196 |
return util_sys_inb(base_addr+UART_RBR, p);
|
184 |
197 |
}
|
185 |
|
int uart_send_char(int base_addr, uint8_t c){
|
|
198 |
static int uart_send_char(int base_addr, uint8_t c){
|
186 |
199 |
int ret;
|
187 |
200 |
if((ret = uart_disable_divisor_latch(base_addr))) return ret;
|
188 |
|
if(sys_outb(base_addr, c)) return WRITE_ERROR;
|
|
201 |
if(sys_outb(base_addr+UART_THR, c)) return WRITE_ERROR;
|
189 |
202 |
return SUCCESS;
|
190 |
203 |
}
|
191 |
|
int uart_receiver_ready(int base_addr){
|
|
204 |
static int uart_receiver_ready(int base_addr){
|
192 |
205 |
uint8_t lsr;
|
193 |
206 |
if(uart_get_lsr(base_addr, &lsr)) return false;
|
194 |
207 |
return UART_GET_RECEIVER_READY(lsr);
|
195 |
208 |
}
|
196 |
|
int uart_transmitter_empty(int base_addr){
|
|
209 |
static int uart_transmitter_empty(int base_addr){
|
197 |
210 |
uint8_t lsr;
|
198 |
211 |
if(uart_get_lsr(base_addr, &lsr)) return false;
|
199 |
212 |
return UART_GET_TRANSMITTER_EMPTY(lsr);
|
200 |
213 |
}
|
201 |
|
///PUBLIC
|
|
214 |
|
|
215 |
int uart_enable_int_rx(int base_addr){
|
|
216 |
int ret;
|
|
217 |
uint8_t ier;
|
|
218 |
if((ret = uart_get_ier(base_addr, &ier))) return ret;
|
|
219 |
ier |= UART_INT_EN_RX;
|
|
220 |
return uart_set_ier(base_addr, ier);
|
|
221 |
}
|
|
222 |
int uart_disable_int_rx(int base_addr){
|
|
223 |
int ret;
|
|
224 |
uint8_t ier;
|
|
225 |
if((ret = uart_get_ier(base_addr, &ier))) return ret;
|
|
226 |
ier &= ~UART_INT_EN_RX;
|
|
227 |
return uart_set_ier(base_addr, ier);
|
|
228 |
}
|
|
229 |
int uart_enable_int_tx(int base_addr){
|
|
230 |
int ret;
|
|
231 |
uint8_t ier;
|
|
232 |
if((ret = uart_get_ier(base_addr, &ier))) return ret;
|
|
233 |
ier |= UART_INT_EN_TX;
|
|
234 |
return uart_set_ier(base_addr, ier);
|
|
235 |
}
|
|
236 |
int uart_disable_int_tx(int base_addr){
|
|
237 |
int ret;
|
|
238 |
uint8_t ier;
|
|
239 |
if((ret = uart_get_ier(base_addr, &ier))) return ret;
|
|
240 |
ier &= ~UART_INT_EN_TX;
|
|
241 |
return uart_set_ier(base_addr, ier);
|
|
242 |
}
|
|
243 |
|
202 |
244 |
int uart_get_char_poll(int base_addr, uint8_t *p){
|
203 |
245 |
int ret;
|
204 |
246 |
while(!uart_receiver_ready(base_addr)){}
|
... | ... | |
211 |
253 |
if((ret = uart_send_char(base_addr, c))) return ret;
|
212 |
254 |
return SUCCESS;
|
213 |
255 |
}
|
214 |
|
int uart_send_memory_poll(int base_addr, void *str, size_t n){
|
215 |
|
int ret;
|
216 |
|
uint8_t *p = str;
|
217 |
|
for(size_t i = 0; i < n; ++i, ++p){
|
218 |
|
if((ret = uart_send_char_poll(base_addr, *p))) return ret;
|
219 |
|
}
|
220 |
|
return SUCCESS;
|
221 |
|
}
|