Revision 252
made some more changes to uart
uart.c | ||
---|---|---|
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 |
} |
Also available in: Unified diff