root / proj / src / uart.c @ 246
History | View | Annotate | Download (7.19 KB)
1 |
#include <lcom/lcf.h> |
---|---|
2 |
|
3 |
#include "uart.h" |
4 |
|
5 |
#include "errors.h" |
6 |
|
7 |
#define UART_RBR 0 |
8 |
#define UART_THR 0 |
9 |
#define UART_IER 1 |
10 |
#define UART_IIR 2 |
11 |
#define UART_FCR 2 |
12 |
#define UART_LCR 3 |
13 |
#define UART_MCR 4 |
14 |
#define UART_LSR 5 |
15 |
#define UART_MSR 6 |
16 |
#define UART_SR 7 |
17 |
|
18 |
#define UART_DLL 0 |
19 |
#define UART_DLM 1 |
20 |
|
21 |
#define UART_BITS_PER_CHAR_POS 0 |
22 |
#define UART_STOP_BITS_POS 2 |
23 |
#define UART_PARITY_POS 3 |
24 |
#define UART_BREAK_CONTROL_POS 6 |
25 |
#define UART_DLAB_POS 7 |
26 |
|
27 |
#define UART_BITS_PER_CHAR (BIT(0) | BIT(1)) |
28 |
#define UART_STOP_BITS (BIT(2)) |
29 |
#define UART_PARITY (BIT(3) | BIT(4) | BIT(5)) |
30 |
#define UART_BREAK_CONTROL (BIT(6)) |
31 |
#define UART_DLAB (BIT(7)) |
32 |
|
33 |
#define UART_GET_BITS_PER_CHAR(n) (((n)&UART_BITS_PER_CHAR) + 5) |
34 |
#define UART_GET_STOP_BITS(n) (((n)&UART_STOP_BITS)? 2 : 1) |
35 |
#define UART_GET_PARITY(n) (((n)&UART_PARITY )>>UART_PARITY_POS )
|
36 |
#define UART_GET_BREAK_CONTROL(n) (((n)&UART_BREAK_CONTROL)>>UART_BREAK_CONTROL_POS)
|
37 |
#define UART_GET_DLAB(n) (((n)&UART_DLAB )>>UART_DLAB_POS )
|
38 |
#define UART_GET_DIV_LATCH(m,l) ((m)<<8 | (l)) |
39 |
#define UART_GET_DLL(n) ((n)&0xFF) |
40 |
#define UART_GET_DLM(n) (((n)>>8)&0xFF) |
41 |
|
42 |
#define UART_RECEIVED_DATA_POS 0 |
43 |
#define UART_TRANSMITTER_EMPTY_POS 1 |
44 |
#define UART_RECEIVER_LINE_STAT_POS 2 |
45 |
#define UART_MODEM_STAT_POS 3 |
46 |
|
47 |
#define UART_RECEIVED_DATA (BIT(0)) |
48 |
#define UART_TRANSMITTER_EMPTY (BIT(1)) |
49 |
#define UART_RECEIVER_LINE_STAT (BIT(2)) |
50 |
#define UART_MODEM_STAT (BIT(3)) |
51 |
|
52 |
#define UART_GET_RECEIVED_DATA(n) (((n)&UART_RECEIVED_DATA )>>UART_RECEIVED_DATA_POS )
|
53 |
#define UART_GET_TRANSMITTER_EMPTY(n) (((n)&UART_TRANSMITTER_EMPTY )>>UART_TRANSMITTER_EMPTY_POS )
|
54 |
#define UART_GET_RECEIVER_LINE_STAT(n) (((n)&UART_RECEIVER_LINE_STAT)>>UART_RECEIVER_LINE_STAT_POS)
|
55 |
#define UART_GET_MODEM_STAT(n) (((n)&UART_MODEM_STAT )>>UART_MODEM_STAT_POS )
|
56 |
|
57 |
int uart_get_config(int base_addr, uart_config *config){ |
58 |
int ret = SUCCESS;
|
59 |
|
60 |
config->base_addr = base_addr; |
61 |
|
62 |
if((ret = util_sys_inb(base_addr+UART_LCR, &config->lcr))) return ret; |
63 |
|
64 |
if((ret = util_sys_inb(base_addr+UART_IER, &config->ier))) return ret; |
65 |
|
66 |
if((ret = uart_enable_divisor_latch (base_addr))) return ret; |
67 |
if((ret = util_sys_inb(base_addr+UART_DLL, &config->dll ))) return ret; |
68 |
if((ret = util_sys_inb(base_addr+UART_DLM, &config->dlm ))) return ret; |
69 |
if((ret = uart_disable_divisor_latch(base_addr))) return ret; |
70 |
|
71 |
uart_parse_config(config); |
72 |
return ret;
|
73 |
} |
74 |
void uart_parse_config(uart_config *config){
|
75 |
/// LCR
|
76 |
config->bits_per_char = UART_GET_BITS_PER_CHAR (config->lcr); |
77 |
config->stop_bits = UART_GET_STOP_BITS (config->lcr); |
78 |
config->parity = UART_GET_PARITY (config->lcr); |
79 |
config->break_control = UART_GET_BREAK_CONTROL (config->lcr); |
80 |
config->dlab = UART_GET_DLAB (config->lcr); |
81 |
/// IER
|
82 |
config->received_data_int = UART_GET_RECEIVED_DATA (config->ier); |
83 |
config->transmitter_empty_int = UART_GET_TRANSMITTER_EMPTY (config->ier); |
84 |
config->receiver_line_stat_int = UART_GET_RECEIVER_LINE_STAT(config->ier); |
85 |
config->modem_stat_int = UART_GET_MODEM_STAT (config->ier); |
86 |
/// DIV LATCH
|
87 |
config->divisor_latch = UART_GET_DIV_LATCH(config->dlm, config->dll); |
88 |
} |
89 |
void uart_print_config(uart_config config){
|
90 |
printf("Base address : 0x%X\n", config.base_addr);
|
91 |
printf(" LCR configuration : 0x%02X\n", config.lcr);
|
92 |
printf(" Number of bits per char : %d\n", config.bits_per_char);
|
93 |
printf(" Number of stop bits : %d\n", config.stop_bits);
|
94 |
printf(" Parity : ");
|
95 |
if((config.parity&1) == 0) printf("no parity\n"); |
96 |
else switch(config.parity){ |
97 |
case uart_parity_odd : printf("odd parity\n" ); break; |
98 |
case uart_parity_even: printf("even parity\n" ); break; |
99 |
case uart_parity_par1: printf("parity bit is 1\n"); break; |
100 |
case uart_parity_par0: printf("parity bit is 0\n"); break; |
101 |
default : printf("invalid\n" ); break; |
102 |
} |
103 |
printf(" Break control : %d\n", config.break_control);
|
104 |
printf(" DLAB : %d\n", config.dlab);
|
105 |
|
106 |
printf(" IER configuration : 0x%02X\n", config.ier);
|
107 |
printf(" Received data interrupts enabled : %d\n", config.received_data_int);
|
108 |
printf(" Transmitter empty interrupts enabled : %d\n", config.transmitter_empty_int);
|
109 |
printf(" Receiver line status interrupts enabled: %d\n", config.receiver_line_stat_int);
|
110 |
printf(" Modem status interrupts enabled : %d\n", config.modem_stat_int);
|
111 |
|
112 |
printf(" Divisor latch (DLM & DLL) : %d\n", config.divisor_latch);
|
113 |
printf(" Bit rate : %d\n", UART_BITRATE/config.divisor_latch);
|
114 |
} |
115 |
|
116 |
int uart_enable_divisor_latch(int base_addr){ |
117 |
int ret = SUCCESS;
|
118 |
uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret; |
119 |
return uart_write_config(base_addr, conf | UART_DLAB);
|
120 |
} |
121 |
int uart_disable_divisor_latch(int base_addr){ |
122 |
int ret = SUCCESS;
|
123 |
uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret; |
124 |
return uart_write_config(base_addr, conf & (~UART_DLAB));
|
125 |
} |
126 |
|
127 |
int uart_write_config(int base_addr, uint8_t config){ |
128 |
if(sys_outb(base_addr+UART_LCR, config)) return WRITE_ERROR; |
129 |
return SUCCESS;
|
130 |
} |
131 |
int uart_set_bits_per_character(int base_addr, uint8_t bits_per_char){ |
132 |
if(bits_per_char < 5 || bits_per_char > 8) return INVALID_ARG; |
133 |
int ret = SUCCESS;
|
134 |
bits_per_char = (bits_per_char-5)&0x3; |
135 |
uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret; |
136 |
conf = (conf & (~UART_BITS_PER_CHAR)) | bits_per_char; |
137 |
return uart_write_config(base_addr, conf);
|
138 |
} |
139 |
int uart_set_stop_bits(int base_addr, uint8_t stop){ |
140 |
if(stop != 1 && stop != 2) return INVALID_ARG; |
141 |
int ret = SUCCESS;
|
142 |
stop -= 1;
|
143 |
stop = (stop&1)<<2; |
144 |
uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret; |
145 |
conf = (conf & (~UART_STOP_BITS)) | stop; |
146 |
return uart_write_config(base_addr, conf);
|
147 |
} |
148 |
int uart_set_parity(int base_addr, uart_parity par){ |
149 |
int ret = SUCCESS;
|
150 |
uint8_t parity = par << 3;
|
151 |
uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret; |
152 |
conf = (conf & (~UART_PARITY)) | parity; |
153 |
return uart_write_config(base_addr, conf);
|
154 |
} |
155 |
int uart_set_bit_rate(int base_addr, float bit_rate){ |
156 |
int ret = SUCCESS;
|
157 |
uint16_t latch = UART_BITRATE/bit_rate; |
158 |
uint8_t dll = UART_GET_DLL(latch); |
159 |
uint8_t dlm = UART_GET_DLM(latch); |
160 |
if((ret = uart_enable_divisor_latch(base_addr))) return ret; |
161 |
if(sys_outb(base_addr+UART_DLL, dll)) return WRITE_ERROR; |
162 |
if(sys_outb(base_addr+UART_DLM, dlm)) return WRITE_ERROR; |
163 |
if((ret = util_sys_inb(base_addr+UART_DLM, &dlm))) return ret; |
164 |
return SUCCESS;
|
165 |
} |