Project

General

Profile

Statistics
| Revision:

root / proj / src / uart.c @ 241

History | View | Annotate | Download (5.16 KB)

1 235 up20180642
#include <lcom/lcf.h>
2
3
#include "uart.h"
4
5
#include "errors.h"
6
7 241 up20180642
#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 235 up20180642
int uart_get_config(int base_addr, uart_config *config){
43
    int ret = SUCCESS;
44
45
    config->base_addr = base_addr;
46
47
    if((ret = util_sys_inb(base_addr+UART_LCR, &config->config))) return ret;
48
49
    if((ret = uart_enable_divisor_latch(base_addr))) return ret;
50
    if((ret = util_sys_inb(base_addr+UART_DLL, &config->dll   ))) return ret;
51
    if((ret = util_sys_inb(base_addr+UART_DLM, &config->dlm   ))) return ret;
52
53
    uart_parse_config(config);
54
    return ret;
55
}
56
void uart_parse_config(uart_config *config){
57
    config->bits_per_char        = UART_GET_BITS_PER_CHAR(config->config);
58
    config->stop_bits            = UART_GET_STOP_BITS    (config->config);
59
    config->parity               = UART_GET_PARITY       (config->config);
60
    config->break_control        = UART_GET_BREAK_CONTROL(config->config);
61 241 up20180642
    config->dlab                 = UART_GET_DLAB         (config->config);
62
    config->divisor_latch        = UART_GET_DIV_LATCH    (config->dlm, config->dll);
63 235 up20180642
}
64
void uart_print_config(uart_config config){
65
    printf("Base address: 0x%X\n", config.base_addr);
66
    printf("Configuration: 0x%02X\n", config.config);
67
    printf("Number of bits per char: %d\n", config.bits_per_char);
68
    printf("Number of stop bits: %d\n", config.stop_bits);
69
    printf("Parity: ");
70
    if((config.parity&1) == 0) printf("no parity\n");
71
    else switch(config.parity){
72
        case uart_parity_odd : printf("odd parity\n"     ); break;
73
        case uart_parity_even: printf("even parity\n"    ); break;
74
        case uart_parity_par1: printf("parity bit is 1\n"); break;
75
        case uart_parity_par0: printf("parity bit is 0\n"); break;
76
        default              : printf("invalid\n"        ); break;
77
    }
78
    printf("Break control: %d\n", config.break_control);
79
    printf("Divisor latch: %d\n", config.divisor_latch);
80 241 up20180642
    printf("Bit rate: %d\n", UART_BITRATE/config.divisor_latch);
81 235 up20180642
}
82
83
int uart_enable_divisor_latch(int base_addr){
84
    int ret = SUCCESS;
85
    uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret;
86
    return uart_write_config(base_addr, conf | UART_DLAB);
87
}
88
int uart_disable_divisor_latch(int base_addr){
89
    int ret = SUCCESS;
90
    uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret;
91
    return uart_write_config(base_addr, conf & (~UART_DLAB));
92
}
93
94
int uart_write_config(int base_addr, uint8_t config){
95
    if(sys_outb(base_addr+UART_LCR, config)) return WRITE_ERROR;
96
    return SUCCESS;
97
}
98
int uart_set_bits_per_character(int base_addr, uint8_t bits_per_char){
99
    if(bits_per_char < 5 || bits_per_char > 8) return INVALID_ARG;
100
    int ret = SUCCESS;
101
    bits_per_char = (bits_per_char-5)&0x3;
102
    uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret;
103
    conf = (conf & (~UART_BITS_PER_CHAR)) | bits_per_char;
104
    return uart_write_config(base_addr, conf);
105
}
106
int uart_set_stop_bits(int base_addr, uint8_t stop){
107
    if(stop != 1 && stop != 2) return INVALID_ARG;
108
    int ret = SUCCESS;
109
    stop -= 1;
110
    stop = (stop&1)<<2;
111
    uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret;
112
    conf = (conf & (~UART_STOP_BITS)) | stop;
113
    return uart_write_config(base_addr, conf);
114
}
115
int uart_set_parity(int base_addr, uart_parity par){
116
    int ret = SUCCESS;
117
    uint8_t parity = par << 3;
118
    uint8_t conf; if((ret = util_sys_inb(base_addr+UART_LCR, &conf))) return ret;
119
    conf = (conf & (~UART_PARITY)) | parity;
120
    return uart_write_config(base_addr, conf);
121
}
122 241 up20180642
int uart_set_bit_rate(int base_addr, float bit_rate){
123 235 up20180642
    int ret = SUCCESS;
124
    uint16_t latch = UART_BITRATE/bit_rate;
125 241 up20180642
    uint8_t dll = UART_GET_DLL(latch);
126
    uint8_t dlm = UART_GET_DLM(latch);
127 235 up20180642
    if((ret = uart_enable_divisor_latch(base_addr))) return ret;
128
    if(sys_outb(base_addr+UART_DLL, dll)) return WRITE_ERROR;
129
    if(sys_outb(base_addr+UART_DLM, dlm)) return WRITE_ERROR;
130
    if((ret = util_sys_inb(base_addr+UART_DLM, &dlm))) return ret;
131
    return SUCCESS;
132
}