1use core::cell::Cell;
17use core::fmt::{self, Write};
18use core::mem::MaybeUninit;
19
20use x86::registers::io;
21
22use kernel::component::Component;
23use kernel::debug::IoWrite;
24use kernel::deferred_call::{DeferredCall, DeferredCallClient};
25use kernel::hil::uart::{
26 Configure, Error, Parameters, Parity, Receive, ReceiveClient, StopBits, Transmit,
27 TransmitClient, Width,
28};
29use kernel::utilities::cells::OptionalCell;
30use kernel::ErrorCode;
31use tock_cells::take_cell::TakeCell;
32use tock_registers::{register_bitfields, LocalRegisterCopy};
33
34pub const COM1_BASE: u16 = 0x03F8;
36
37pub const COM2_BASE: u16 = 0x02F8;
39
40pub const COM3_BASE: u16 = 0x03E8;
42
43pub const COM4_BASE: u16 = 0x02E8;
45
46const BAUD_CLOCK: u32 = 115_200;
48
49mod offsets {
52 pub(crate) const THR: u16 = 0;
54
55 pub(crate) const RBR: u16 = 0;
57
58 pub(crate) const DLL: u16 = 0;
60
61 pub(crate) const IER: u16 = 1;
63
64 pub(crate) const DLH: u16 = 1;
66
67 pub(crate) const IIR: u16 = 2;
69
70 pub(crate) const FCR: u16 = 2;
72
73 pub(crate) const LCR: u16 = 3;
75
76 pub(crate) const LSR: u16 = 5;
78}
79
80register_bitfields!(u8,
81 IIR[
83 INTERRUPT_PENDING OFFSET(0) NUMBITS(1) [],
84 INTERRUPT_ID OFFSET(1) NUMBITS(3) [
85 THRE = 0b001, RDA = 0b010 ]
88 ],
89
90 IER [
92 RDA OFFSET(0) NUMBITS(1) [], THRE OFFSET(1) NUMBITS(1) [] ],
96
97 LCR [
99 DLAB OFFSET(7) NUMBITS(1) [], PARITY OFFSET(3) NUMBITS(3) [
101 None = 0,
102 Odd = 1,
103 Even = 3,
104 Mark = 5,
105 Space = 7,
106 ],
107 STOP_BITS OFFSET(2) NUMBITS(1) [
108 One = 0,
109 Two = 1
110 ],
111 DATA_SIZE OFFSET(0) NUMBITS(2) [
112 Five = 0,
113 Six = 1,
114 Seven = 2,
115 Eight = 3
116 ]
117 ],
118
119 LSR [
121 THRE OFFSET(5) NUMBITS(1) [] ],
123);
124
125pub struct SerialPort<'a> {
126 base: u16,
128
129 tx_client: OptionalCell<&'a dyn TransmitClient>,
131
132 tx_buffer: TakeCell<'static, [u8]>,
134
135 tx_len: Cell<usize>,
137
138 tx_index: Cell<usize>,
140
141 tx_abort: Cell<bool>,
143
144 rx_client: OptionalCell<&'a dyn ReceiveClient>,
146
147 rx_buffer: TakeCell<'static, [u8]>,
149
150 rx_len: Cell<usize>,
152
153 rx_index: Cell<usize>,
155
156 rx_abort: Cell<bool>,
158
159 dc: DeferredCall,
161}
162
163impl SerialPort<'_> {
164 fn finish_tx(&self, res: Result<(), ErrorCode>) {
166 if let Some(b) = self.tx_buffer.take() {
167 self.tx_client.map(|c| {
168 c.transmitted_buffer(b, self.tx_len.get(), res);
169 });
170 }
171 }
172
173 fn finish_rx(&self, res: Result<(), ErrorCode>, error: Error) {
175 unsafe {
177 let ier_value = io::inb(self.base + offsets::IER);
178 let mut ier: LocalRegisterCopy<u8, IER::Register> = LocalRegisterCopy::new(ier_value);
179 ier.modify(IER::RDA::CLEAR);
180 io::outb(self.base + offsets::IER, ier.get());
181 }
182
183 if let Some(b) = self.rx_buffer.take() {
184 self.rx_client
185 .map(|c| c.received_buffer(b, self.rx_len.get(), res, error));
186 }
187 }
188
189 fn handle_tx_interrupt(&self) {
191 if self.tx_index.get() < self.tx_len.get() {
192 let tx_index = self.tx_index.get();
194 self.tx_buffer.map(|b| unsafe {
195 io::outb(self.base + offsets::THR, b[tx_index]);
196 });
197 self.tx_index.set(tx_index + 1);
198 } else {
199 self.finish_tx(Ok(()));
200 }
201 }
202
203 fn handle_rx_interrupt(&self) {
205 if self.rx_index.get() < self.rx_len.get() {
206 let rx_index = self.rx_index.get();
208 self.rx_buffer.map(|b| unsafe {
209 b[rx_index] = io::inb(self.base + offsets::RBR);
210 });
211 self.rx_index.set(rx_index + 1);
212 }
213
214 if self.rx_index.get() == self.rx_len.get() {
215 self.finish_rx(Ok(()), Error::None);
216 }
217 }
218
219 pub fn handle_interrupt(&self) {
221 loop {
225 let iir_val = unsafe { io::inb(self.base + offsets::IIR) };
226
227 let iir: LocalRegisterCopy<u8, IIR::Register> = LocalRegisterCopy::new(iir_val);
228
229 if iir.is_set(IIR::INTERRUPT_PENDING) {
230 return;
232 }
233
234 if iir.matches_all(IIR::INTERRUPT_ID::THRE) {
235 self.handle_tx_interrupt();
236 } else if iir.matches_all(IIR::INTERRUPT_ID::RDA) {
237 self.handle_rx_interrupt();
238 } else {
239 unimplemented!();
240 }
241 }
242 }
243}
244
245impl Configure for SerialPort<'_> {
246 fn configure(&self, params: Parameters) -> Result<(), ErrorCode> {
247 if params.baud_rate == 0 {
248 return Err(ErrorCode::INVAL);
249 }
250
251 if params.hw_flow_control {
252 return Err(ErrorCode::NOSUPPORT);
253 }
254
255 let divisor = BAUD_CLOCK / params.baud_rate;
256 if divisor == 0 || divisor > u16::MAX.into() {
257 return Err(ErrorCode::NOSUPPORT);
258 }
259
260 let mut lcr: LocalRegisterCopy<u8, LCR::Register> = LocalRegisterCopy::new(0);
263
264 lcr.modify(match params.width {
265 Width::Six => LCR::DATA_SIZE::Six,
266 Width::Seven => LCR::DATA_SIZE::Seven,
267 Width::Eight => LCR::DATA_SIZE::Eight,
268 });
269
270 lcr.modify(match params.stop_bits {
271 StopBits::One => LCR::STOP_BITS::One,
272 StopBits::Two => LCR::STOP_BITS::Two,
273 });
274
275 lcr.modify(match params.parity {
276 Parity::None => LCR::PARITY::None,
277 Parity::Odd => LCR::PARITY::Odd,
278 Parity::Even => LCR::PARITY::Even,
279 });
280
281 lcr.modify(LCR::DLAB::SET);
282
283 unsafe {
284 io::outb(self.base + offsets::LCR, lcr.get());
286
287 lcr.modify(LCR::DLAB::CLEAR);
289 let divisor_bytes = divisor.to_le_bytes();
290 io::outb(self.base + offsets::DLL, divisor_bytes[0]);
291 io::outb(self.base + offsets::DLH, divisor_bytes[1]);
292 io::outb(self.base + offsets::LCR, lcr.get());
293
294 io::outb(self.base + offsets::FCR, 0);
296
297 let _ = io::inb(self.base + offsets::IIR);
299
300 io::outb(self.base + offsets::IER, 0);
302 }
303
304 Ok(())
305 }
306}
307
308impl<'a> Transmit<'a> for SerialPort<'a> {
309 fn set_transmit_client(&self, client: &'a dyn TransmitClient) {
310 self.tx_client.set(client);
311 }
312
313 fn transmit_buffer(
314 &self,
315 tx_buffer: &'static mut [u8],
316 tx_len: usize,
317 ) -> Result<(), (ErrorCode, &'static mut [u8])> {
318 if self.tx_buffer.is_some() {
319 return Err((ErrorCode::BUSY, tx_buffer));
320 }
321
322 if tx_len == 0 || tx_len > tx_buffer.len() {
323 return Err((ErrorCode::SIZE, tx_buffer));
324 }
325
326 unsafe { io::outb(self.base + offsets::THR, tx_buffer[0]) };
328
329 self.tx_buffer.replace(tx_buffer);
330 self.tx_len.set(tx_len);
331 self.tx_index.set(1);
332
333 unsafe {
335 let ier_value = io::inb(self.base + offsets::IER);
336 let mut ier: LocalRegisterCopy<u8, IER::Register> = LocalRegisterCopy::new(ier_value);
337 ier.modify(IER::THRE::SET);
338 io::outb(self.base + offsets::IER, ier.get());
339 }
340
341 Ok(())
342 }
343
344 fn transmit_word(&self, _word: u32) -> Result<(), ErrorCode> {
345 unimplemented!()
346 }
347
348 fn transmit_abort(&self) -> Result<(), ErrorCode> {
349 if self.tx_buffer.is_none() {
350 return Ok(());
351 }
352
353 self.tx_abort.set(true);
354 self.dc.set();
355
356 Err(ErrorCode::BUSY)
357 }
358}
359
360impl<'a> Receive<'a> for SerialPort<'a> {
361 fn set_receive_client(&self, client: &'a dyn ReceiveClient) {
362 self.rx_client.set(client);
363 }
364
365 fn receive_buffer(
366 &self,
367 rx_buffer: &'static mut [u8],
368 rx_len: usize,
369 ) -> Result<(), (ErrorCode, &'static mut [u8])> {
370 if self.rx_buffer.is_some() {
371 return Err((ErrorCode::BUSY, rx_buffer));
372 }
373
374 if rx_len == 0 || rx_len > rx_buffer.len() {
375 return Err((ErrorCode::SIZE, rx_buffer));
376 }
377
378 self.rx_buffer.replace(rx_buffer);
379 self.rx_len.set(rx_len);
380 self.rx_index.set(0);
381
382 unsafe {
384 let ier_value = io::inb(self.base + offsets::IER);
385 let mut ier: LocalRegisterCopy<u8, IER::Register> = LocalRegisterCopy::new(ier_value);
386 ier.modify(IER::RDA::SET);
387 io::outb(self.base + offsets::IER, ier.get());
388 }
389
390 Ok(())
391 }
392
393 fn receive_word(&self) -> Result<(), ErrorCode> {
394 unimplemented!()
395 }
396
397 fn receive_abort(&self) -> Result<(), ErrorCode> {
398 if self.rx_buffer.is_none() {
399 return Ok(());
400 }
401
402 self.rx_abort.set(true);
403 self.dc.set();
404
405 Err(ErrorCode::BUSY)
406 }
407}
408
409impl DeferredCallClient for SerialPort<'_> {
410 fn handle_deferred_call(&self) {
411 if self.tx_abort.get() {
412 self.finish_tx(Err(ErrorCode::CANCEL));
413 self.tx_abort.set(false);
414 }
415
416 if self.rx_abort.get() {
417 self.finish_rx(Err(ErrorCode::CANCEL), Error::None);
418 self.rx_abort.set(false);
419 }
420 }
421
422 fn register(&'static self) {
423 self.dc.register(self);
424 }
425}
426
427pub struct SerialPortComponent {
429 base: u16,
430}
431
432impl SerialPortComponent {
433 pub unsafe fn new(base: u16) -> Self {
443 Self { base }
444 }
445}
446
447impl Component for SerialPortComponent {
448 type StaticInput = (&'static mut MaybeUninit<SerialPort<'static>>,);
449 type Output = &'static SerialPort<'static>;
450
451 fn finalize(self, s: Self::StaticInput) -> Self::Output {
452 let serial = s.0.write(SerialPort {
453 base: self.base,
454 tx_client: OptionalCell::empty(),
455 tx_buffer: TakeCell::empty(),
456 tx_len: Cell::new(0),
457 tx_index: Cell::new(0),
458 tx_abort: Cell::new(false),
459 rx_client: OptionalCell::empty(),
460 rx_buffer: TakeCell::empty(),
461 rx_len: Cell::new(0),
462 rx_index: Cell::new(0),
463 rx_abort: Cell::new(false),
464 dc: DeferredCall::new(),
465 });
466
467 serial.register();
469
470 serial
471 }
472}
473
474#[macro_export]
476macro_rules! serial_port_component_static {
477 () => {{
478 (kernel::static_buf!($crate::serial::SerialPort<'static>),)
479 }};
480}
481
482pub struct BlockingSerialPort(u16);
488
489impl BlockingSerialPort {
490 pub unsafe fn new(base: u16) -> Self {
500 Self(base)
501 }
502}
503
504impl Write for BlockingSerialPort {
505 fn write_str(&mut self, s: &str) -> fmt::Result {
506 self.write(s.as_bytes());
507 Ok(())
508 }
509}
510
511impl IoWrite for BlockingSerialPort {
512 fn write(&mut self, buf: &[u8]) -> usize {
513 unsafe {
514 for b in buf {
515 loop {
517 let line_status_value = io::inb(self.0 + offsets::LSR);
518 let lsr: LocalRegisterCopy<u8, LSR::Register> =
519 LocalRegisterCopy::new(line_status_value);
520 if lsr.is_set(LSR::THRE) {
521 break;
522 }
523 }
524
525 io::outb(self.0 + offsets::THR, *b);
526 }
527 }
528
529 buf.len()
530 }
531}