This source file includes following definitions.
- uartinit
- uartputc
- uartputc_sync
- uartstart
- uartgetc
- uartintr
1
2
3
4
5 #include "types.h"
6 #include "param.h"
7 #include "memlayout.h"
8 #include "riscv.h"
9 #include "spinlock.h"
10 #include "proc.h"
11 #include "defs.h"
12
13
14
15
16 #define Reg(reg) ((volatile unsigned char *)(UART0 + (reg)))
17
18
19
20
21
22 #define RHR 0
23 #define THR 0
24 #define IER 1
25 #define IER_RX_ENABLE (1<<0)
26 #define IER_TX_ENABLE (1<<1)
27 #define FCR 2
28 #define FCR_FIFO_ENABLE (1<<0)
29 #define FCR_FIFO_CLEAR (3<<1)
30 #define ISR 2
31 #define LCR 3
32 #define LCR_EIGHT_BITS (3<<0)
33 #define LCR_BAUD_LATCH (1<<7)
34 #define LSR 5
35 #define LSR_RX_READY (1<<0)
36 #define LSR_TX_IDLE (1<<5)
37
38 #define ReadReg(reg) (*(Reg(reg)))
39 #define WriteReg(reg, v) (*(Reg(reg)) = (v))
40
41
42 struct spinlock uart_tx_lock;
43 #define UART_TX_BUF_SIZE 32
44 char uart_tx_buf[UART_TX_BUF_SIZE];
45 uint64 uart_tx_w;
46 uint64 uart_tx_r;
47
48 extern volatile int panicked;
49
50 void uartstart();
51
52 void
53 uartinit(void)
54 {
55
56 WriteReg(IER, 0x00);
57
58
59 WriteReg(LCR, LCR_BAUD_LATCH);
60
61
62 WriteReg(0, 0x03);
63
64
65 WriteReg(1, 0x00);
66
67
68
69 WriteReg(LCR, LCR_EIGHT_BITS);
70
71
72 WriteReg(FCR, FCR_FIFO_ENABLE | FCR_FIFO_CLEAR);
73
74
75 WriteReg(IER, IER_TX_ENABLE | IER_RX_ENABLE);
76
77 initlock(&uart_tx_lock, "uart");
78 }
79
80
81
82
83
84
85
86 void
87 uartputc(int c)
88 {
89 acquire(&uart_tx_lock);
90
91 if(panicked){
92 for(;;)
93 ;
94 }
95 while(uart_tx_w == uart_tx_r + UART_TX_BUF_SIZE){
96
97
98 sleep(&uart_tx_r, &uart_tx_lock);
99 }
100 uart_tx_buf[uart_tx_w % UART_TX_BUF_SIZE] = c;
101 uart_tx_w += 1;
102 uartstart();
103 release(&uart_tx_lock);
104 }
105
106
107
108
109
110
111 void
112 uartputc_sync(int c)
113 {
114 push_off();
115
116 if(panicked){
117 for(;;)
118 ;
119 }
120
121
122 while((ReadReg(LSR) & LSR_TX_IDLE) == 0)
123 ;
124 WriteReg(THR, c);
125
126 pop_off();
127 }
128
129
130
131
132
133 void
134 uartstart()
135 {
136 while(1){
137 if(uart_tx_w == uart_tx_r){
138
139 ReadReg(ISR);
140 return;
141 }
142
143 if((ReadReg(LSR) & LSR_TX_IDLE) == 0){
144
145
146
147 return;
148 }
149
150 int c = uart_tx_buf[uart_tx_r % UART_TX_BUF_SIZE];
151 uart_tx_r += 1;
152
153
154 wakeup(&uart_tx_r);
155
156 WriteReg(THR, c);
157 }
158 }
159
160
161
162 int
163 uartgetc(void)
164 {
165 if(ReadReg(LSR) & 0x01){
166
167 return ReadReg(RHR);
168 } else {
169 return -1;
170 }
171 }
172
173
174
175
176 void
177 uartintr(void)
178 {
179
180 while(1){
181 int c = uartgetc();
182 if(c == -1)
183 break;
184 consoleintr(c);
185 }
186
187
188 acquire(&uart_tx_lock);
189 uartstart();
190 release(&uart_tx_lock);
191 }