os/drivers/chardev/
ns16550a.rs1use super::CharDevice;
5use crate::sync::{Condvar, UPIntrFreeCell};
6use crate::task::schedule;
7use alloc::collections::VecDeque;
8use bitflags::*;
9use volatile::{ReadOnly, Volatile, WriteOnly};
10
11bitflags! {
12 pub struct IER: u8 {
14 const RX_AVAILABLE = 1 << 0;
15 const TX_EMPTY = 1 << 1;
16 }
17
18 pub struct LSR: u8 {
20 const DATA_AVAILABLE = 1 << 0;
21 const THR_EMPTY = 1 << 5;
22 }
23
24 pub struct MCR: u8 {
26 const DATA_TERMINAL_READY = 1 << 0;
27 const REQUEST_TO_SEND = 1 << 1;
28 const AUX_OUTPUT1 = 1 << 2;
29 const AUX_OUTPUT2 = 1 << 3;
30 }
31}
32
33#[repr(C)]
34#[allow(dead_code)]
35struct ReadWithoutDLAB {
36 pub rbr: ReadOnly<u8>,
38 pub ier: Volatile<IER>,
40 pub iir: ReadOnly<u8>,
42 pub lcr: Volatile<u8>,
44 pub mcr: Volatile<MCR>,
46 pub lsr: ReadOnly<LSR>,
48 _padding1: ReadOnly<u8>,
50 _padding2: ReadOnly<u8>,
52}
53
54#[repr(C)]
55#[allow(dead_code)]
56struct WriteWithoutDLAB {
57 pub thr: WriteOnly<u8>,
59 pub ier: Volatile<IER>,
61 _padding0: ReadOnly<u8>,
63 pub lcr: Volatile<u8>,
65 pub mcr: Volatile<MCR>,
67 pub lsr: ReadOnly<LSR>,
69 _padding1: ReadOnly<u16>,
71}
72
73pub struct NS16550aRaw {
74 base_addr: usize,
75}
76
77impl NS16550aRaw {
78 fn read_end(&mut self) -> &mut ReadWithoutDLAB {
79 unsafe { &mut *(self.base_addr as *mut ReadWithoutDLAB) }
80 }
81
82 fn write_end(&mut self) -> &mut WriteWithoutDLAB {
83 unsafe { &mut *(self.base_addr as *mut WriteWithoutDLAB) }
84 }
85
86 pub fn new(base_addr: usize) -> Self {
87 Self { base_addr }
88 }
89
90 pub fn init(&mut self) {
91 let read_end = self.read_end();
92 let mut mcr = MCR::empty();
93 mcr |= MCR::DATA_TERMINAL_READY;
94 mcr |= MCR::REQUEST_TO_SEND;
95 mcr |= MCR::AUX_OUTPUT2;
96 read_end.mcr.write(mcr);
97 let ier = IER::RX_AVAILABLE;
98 read_end.ier.write(ier);
99 }
100
101 pub fn read(&mut self) -> Option<u8> {
102 let read_end = self.read_end();
103 let lsr = read_end.lsr.read();
104 if lsr.contains(LSR::DATA_AVAILABLE) {
105 Some(read_end.rbr.read())
106 } else {
107 None
108 }
109 }
110
111 pub fn write(&mut self, ch: u8) {
112 let write_end = self.write_end();
113 loop {
114 if write_end.lsr.read().contains(LSR::THR_EMPTY) {
115 write_end.thr.write(ch);
116 break;
117 }
118 }
119 }
120}
121
122struct NS16550aInner {
123 ns16550a: NS16550aRaw,
124 read_buffer: VecDeque<u8>,
125}
126
127pub struct NS16550a<const BASE_ADDR: usize> {
128 inner: UPIntrFreeCell<NS16550aInner>,
129 condvar: Condvar,
130}
131
132impl<const BASE_ADDR: usize> NS16550a<BASE_ADDR> {
133 pub fn new() -> Self {
134 let inner = NS16550aInner {
135 ns16550a: NS16550aRaw::new(BASE_ADDR),
136 read_buffer: VecDeque::new(),
137 };
138 Self {
140 inner: unsafe { UPIntrFreeCell::new(inner) },
141 condvar: Condvar::new(),
142 }
143 }
144
145 pub fn read_buffer_is_empty(&self) -> bool {
146 self.inner
147 .exclusive_session(|inner| inner.read_buffer.is_empty())
148 }
149}
150
151impl<const BASE_ADDR: usize> CharDevice for NS16550a<BASE_ADDR> {
152 fn init(&self) {
153 let mut inner = self.inner.exclusive_access();
154 inner.ns16550a.init();
155 drop(inner);
156 }
157
158 fn read(&self) -> u8 {
159 loop {
160 let mut inner = self.inner.exclusive_access();
161 if let Some(ch) = inner.read_buffer.pop_front() {
162 return ch;
163 } else {
164 let task_cx_ptr = self.condvar.wait_no_sched();
165 drop(inner);
166 schedule(task_cx_ptr);
167 }
168 }
169 }
170 fn write(&self, ch: u8) {
171 let mut inner = self.inner.exclusive_access();
172 inner.ns16550a.write(ch);
173 }
174 fn handle_irq(&self) {
175 let mut count = 0;
176 self.inner.exclusive_session(|inner| {
177 while let Some(ch) = inner.ns16550a.read() {
178 count += 1;
179 inner.read_buffer.push_back(ch);
180 }
181 });
182 if count > 0 {
183 self.condvar.signal();
184 }
185 }
186}