1#![forbid(unsafe_code)]
17
18pub mod resolver;
19mod spec;
20
21use self::spec::ControlRegister;
22use self::spec::DmaControlRegister;
23use self::spec::FIFO_SIZE;
24use self::spec::FifoLevelSelect;
25use self::spec::FractionalBaudRateRegister;
26use self::spec::InterruptFifoLevelSelectRegister;
27use self::spec::InterruptRegister;
28use self::spec::LineControlRegister;
29use self::spec::REGISTERS_SIZE;
30use self::spec::Register;
31use self::spec::UARTPCELL_ID;
32use self::spec::UARTPERIPH_ID;
33use chipset_device::ChipsetDevice;
34use chipset_device::io::IoError;
35use chipset_device::io::IoResult;
36use chipset_device::mmio::MmioIntercept;
37use chipset_device::poll_device::PollDevice;
38use futures::AsyncRead;
39use futures::AsyncWrite;
40use inspect::Inspect;
41use inspect::InspectMut;
42use inspect_counters::Counter;
43use serial_core::SerialIo;
44use std::collections::VecDeque;
45use std::io::ErrorKind;
46use std::ops::RangeInclusive;
47use std::pin::Pin;
48use std::task::Context;
49use std::task::Poll;
50use std::task::Waker;
51use std::task::ready;
52use thiserror::Error;
53use vmcore::device_state::ChangeDeviceState;
54use vmcore::line_interrupt::LineInterrupt;
55
56#[derive(InspectMut)]
58pub struct SerialPl011 {
59 #[inspect(skip)]
61 debug_name: String,
62 #[inspect(skip)]
63 mmio_region: (&'static str, RangeInclusive<u64>),
64 wait_for_rts: bool,
69
70 interrupt: LineInterrupt,
72 #[inspect(mut)]
73 io: Box<dyn SerialIo>,
74
75 state: State,
77 #[inspect(skip)]
78 rx_waker: Option<Waker>,
79 #[inspect(skip)]
80 tx_waker: Option<Waker>,
81 stats: SerialStats,
82}
83
84#[derive(Inspect, Default)]
85struct SerialStats {
86 rx_bytes: Counter,
87 tx_bytes: Counter,
88 rx_dropped: Counter,
89 tx_dropped: Counter,
90}
91
92#[derive(Inspect)]
93struct State {
94 #[inspect(with = "VecDeque::len")]
95 tx_buffer: VecDeque<u8>,
96 #[inspect(with = "VecDeque::len")]
97 rx_buffer: VecDeque<u8>,
98 rx_overrun: bool,
99 connected: bool,
100 ilpr: u8, ibrd: u16, fbrd: FractionalBaudRateRegister, lcr: LineControlRegister, cr: ControlRegister, ifls: InterruptFifoLevelSelectRegister, imsc: InterruptRegister, ris: InterruptRegister, dmacr: DmaControlRegister, new_ibrd: u16,
113 new_fbrd: FractionalBaudRateRegister,
114}
115
116const TX_BUFFER_MAX: usize = 256;
118const RX_BUFFER_MAX: usize = 256;
119
120#[derive(Debug, Error)]
122pub enum ConfigurationError {
123 #[error("unaligned base address: {0}")]
125 UnalignedBaseAddress(u64),
126 #[error("invalid register width: {0}")]
128 InvalidRegisterWidth(u8),
129}
130
131impl SerialPl011 {
132 pub fn new(
137 debug_name: String,
138 base: u64,
139 interrupt: LineInterrupt,
140 io: Box<dyn SerialIo>,
141 ) -> Result<Self, ConfigurationError> {
142 if base & (REGISTERS_SIZE - 1) != 0 {
143 return Err(ConfigurationError::UnalignedBaseAddress(base));
144 }
145
146 let mut this = Self {
147 debug_name,
148 mmio_region: ("registers", base..=base + (REGISTERS_SIZE - 1)),
149 wait_for_rts: false,
150 state: State::new(),
151 interrupt,
152 io,
153 rx_waker: None,
154 tx_waker: None,
155 stats: Default::default(),
156 };
157 if this.io.is_connected() {
158 this.state.connect();
159 }
160 this.sync();
161 Ok(this)
162 }
163
164 fn sync(&mut self) {
166 if !self.state.tx_buffer.is_empty() {
168 if let Some(waker) = self.tx_waker.take() {
169 waker.wake();
170 }
171 }
172
173 if self.state.should_poll_rx(self.wait_for_rts)
175 && self.state.rx_buffer.len() <= RX_BUFFER_MAX / 2
176 {
177 if let Some(waker) = self.rx_waker.take() {
178 waker.wake();
179 }
180 }
181
182 self.state.ris.set_rt(!self.state.rx_buffer.is_empty());
190
191 self.interrupt.set_level(self.state.pending_interrupt());
193 }
194
195 fn poll_tx(&mut self, cx: &mut Context<'_>) -> Poll<()> {
196 while !self.state.tx_buffer.is_empty() {
197 if !self.state.connected {
198 self.stats.tx_dropped.add(self.state.tx_buffer.len() as u64);
200 if self.state.tx_buffer.len() > self.state.tx_fifo_trigger() {
201 self.state.ris.set_tx(true);
202 }
203 self.state.tx_buffer.clear();
204 break;
205 }
206 let (buf, _) = self.state.tx_buffer.as_slices();
207 let old_len = self.state.tx_buffer.len();
208 match ready!(Pin::new(&mut self.io).poll_write(cx, buf)) {
209 Ok(n) => {
210 assert_ne!(n, 0);
211 self.state.tx_buffer.drain(..n);
212 self.stats.tx_bytes.add(n as u64);
213 }
214 Err(err) if err.kind() == ErrorKind::BrokenPipe => {
215 tracing::info!(
216 port = self.debug_name,
217 "serial output broken pipe, disconnecting"
218 );
219 self.state.disconnect();
220 }
221 Err(err) => {
222 tracelimit::error_ratelimited!(
223 port = self.debug_name,
224 len = buf.len(),
225 error = &err as &dyn std::error::Error,
226 "serial write failed, dropping data"
227 );
228 self.stats.tx_dropped.add(buf.len() as u64);
229 self.state.tx_buffer.drain(..buf.len());
230 }
231 }
232 let tx_fifo_trigger = self.state.tx_fifo_trigger();
233 if old_len > tx_fifo_trigger && self.state.tx_buffer.len() <= tx_fifo_trigger {
234 self.state.ris.set_tx(true);
235 }
236 }
237 self.tx_waker = Some(cx.waker().clone());
239 Poll::Pending
240 }
241
242 fn poll_rx(&mut self, cx: &mut Context<'_>) -> Poll<()> {
243 let mut buf = [0; RX_BUFFER_MAX];
244 loop {
245 if !self.state.connected {
246 if let Err(err) = ready!(self.io.poll_connect(cx)) {
248 tracing::info!(
249 port = self.debug_name,
250 error = &err as &dyn std::error::Error,
251 "serial backend failure"
252 );
253 break Poll::Ready(());
254 }
255 tracing::trace!(port = self.debug_name, "serial connected");
256 self.state.connect();
257 }
258 if !self.state.should_poll_rx(self.wait_for_rts) {
259 self.rx_waker = Some(cx.waker().clone());
261 if let Err(err) = ready!(self.io.poll_disconnect(cx)) {
262 tracing::info!(
263 port = self.debug_name,
264 error = &err as &dyn std::error::Error,
265 "serial backend failure"
266 );
267 break Poll::Ready(());
268 }
269 tracing::trace!(port = self.debug_name, "serial disconnected");
270 self.state.disconnect();
271 continue;
272 }
273 let avail_space = RX_BUFFER_MAX - self.state.rx_buffer.len();
274 let buf = &mut buf[..avail_space];
275 match ready!(Pin::new(&mut self.io).poll_read(cx, buf)) {
276 Ok(0) => {
277 tracing::trace!(port = self.debug_name, "serial disconnected");
278 self.state.disconnect();
279 }
280 Ok(n) => {
281 let rx_fifo_trigger = self.state.rx_fifo_trigger();
282 if self.state.rx_buffer.len() < rx_fifo_trigger
283 && self.state.rx_buffer.len() + n >= rx_fifo_trigger
284 {
285 self.state.ris.set_rx(true);
286 }
287 self.state.rx_buffer.extend(&buf[..n]);
288 self.stats.rx_bytes.add(n as u64);
289 }
290 Err(err) => {
291 tracing::error!(
292 port = self.debug_name,
293 error = &err as &dyn std::error::Error,
294 "failed to read serial input, disconnecting"
295 );
296 self.state.disconnect();
297 break Poll::Ready(());
298 }
299 }
300 }
301 }
302
303 fn register(&self, addr: u64) -> Result<Register, IoError> {
304 if addr & 3 != 0 {
306 return Err(IoError::UnalignedAccess);
307 }
308 Ok(Register((addr & (REGISTERS_SIZE - 1)) as u16))
309 }
310
311 fn read(&mut self, addr: u64, data: &mut [u8]) -> IoResult {
312 let register = match self.register(addr) {
313 Err(e) => return IoResult::Err(e),
314 Ok(r) => r,
315 };
316
317 data.fill(0);
318 let val: u16 = match register {
319 Register::UARTDR => self.state.read_dr().into(),
320 Register::UARTRSR => 0, Register::UARTFR => self.state.read_fr(),
322 Register::UARTILPR => self.state.ilpr as u16,
323 Register::UARTIBRD => self.state.ibrd,
324 Register::UARTFBRD => u8::from(self.state.fbrd) as u16,
325 Register::UARTLCR_H => u8::from(self.state.lcr) as u16,
326 Register::UARTCR => u16::from(self.state.cr),
327 Register::UARTIFLS => u16::from(self.state.ifls),
328 Register::UARTIMSC => u16::from(self.state.imsc),
329 Register::UARTRIS => u16::from(self.state.ris),
330 Register::UARTMIS => u16::from(self.state.ris) & u16::from(self.state.imsc),
331 Register::UARTDMACR => u16::from(self.state.dmacr),
332 Register::UARTPERIPHID0 => UARTPERIPH_ID[0],
333 Register::UARTPERIPHID1 => UARTPERIPH_ID[1],
334 Register::UARTPERIPHID2 => UARTPERIPH_ID[2],
335 Register::UARTPERIPHID3 => UARTPERIPH_ID[3],
336 Register::UARTPCELLID0 => UARTPCELL_ID[0],
337 Register::UARTPCELLID1 => UARTPCELL_ID[1],
338 Register::UARTPCELLID2 => UARTPCELL_ID[2],
339 Register::UARTPCELLID3 => UARTPCELL_ID[3],
340 _ => return IoResult::Err(IoError::InvalidRegister),
341 };
342
343 data[0] = val.to_le_bytes()[0];
347 if data.len() > 1 {
348 data[1] = val.to_le_bytes()[1];
349 }
350
351 self.sync();
352 IoResult::Ok
353 }
354
355 fn write(&mut self, addr: u64, data: &[u8]) -> IoResult {
356 let register = match self.register(addr) {
357 Err(e) => return IoResult::Err(e),
358 Ok(r) => r,
359 };
360
361 tracing::trace!(?register, ?data, "serial write");
362
363 match register {
365 Register::UARTDR => self.state.write_dr(&mut self.stats, data[0]),
366 Register::UARTECR => {}
367 Register::UARTILPR => self.state.ilpr = data[0],
368 Register::UARTFBRD => self.state.write_fbrd(data[0]),
369 Register::UARTLCR_H => self.state.write_lcrh(&mut self.stats, data[0]),
370 _ => {
371 let Some(data) = data.get(..2) else {
373 return IoResult::Err(IoError::InvalidAccessSize);
374 };
375 let data16 = u16::from_le_bytes(data.try_into().unwrap());
376 match register {
377 Register::UARTIBRD => self.state.new_ibrd = data16,
378 Register::UARTCR => self.state.write_cr(data16),
379 Register::UARTIFLS => self.state.write_ifls(data16),
380 Register::UARTIMSC => self.state.write_imsc(data16),
381 Register::UARTICR => self.state.write_icr(data16),
382 Register::UARTDMACR => self.state.write_dmacr(data16),
383 _ => return IoResult::Err(IoError::InvalidRegister),
384 };
385 }
386 }
387 self.sync();
388 IoResult::Ok
389 }
390}
391
392impl ChangeDeviceState for SerialPl011 {
393 fn start(&mut self) {}
394
395 async fn stop(&mut self) {}
396
397 async fn reset(&mut self) {
398 self.state = State::new();
399 self.state.connect();
400 self.sync();
401 }
402}
403
404impl ChipsetDevice for SerialPl011 {
405 fn supports_mmio(&mut self) -> Option<&mut dyn MmioIntercept> {
406 Some(self)
407 }
408
409 fn supports_poll_device(&mut self) -> Option<&mut dyn PollDevice> {
410 Some(self)
411 }
412}
413
414impl PollDevice for SerialPl011 {
415 fn poll_device(&mut self, cx: &mut Context<'_>) {
416 let _ = self.poll_tx(cx);
417 let _ = self.poll_rx(cx);
418 self.sync();
419 }
420}
421
422impl State {
423 fn new() -> Self {
424 let cr = ControlRegister::new()
441 .with_enabled(true)
442 .with_rxe(true)
443 .with_txe(true);
444
445 let lcr = LineControlRegister::new().with_enable_fifos(true);
446
447 Self {
448 tx_buffer: VecDeque::new(),
449 rx_buffer: VecDeque::new(),
450 rx_overrun: false,
451 connected: false,
452 ilpr: 0,
453 ibrd: 0,
454 fbrd: FractionalBaudRateRegister::new(),
455 lcr,
456 cr,
457 ifls: InterruptFifoLevelSelectRegister::new()
458 .with_txiflsel(FifoLevelSelect::BYTES_16.0)
459 .with_rxiflsel(FifoLevelSelect::BYTES_16.0),
460 imsc: InterruptRegister::new(),
461 ris: InterruptRegister::new(),
462 dmacr: DmaControlRegister::new(),
463 new_ibrd: 0,
464 new_fbrd: FractionalBaudRateRegister::new(),
465 }
466 }
467
468 fn connect(&mut self) {
470 if !self.connected {
471 self.connected = true;
472 self.ris.set_cts(true);
474 self.ris.set_dcd(true);
475 self.ris.set_dsr(true);
476 }
477 }
478
479 fn disconnect(&mut self) {
481 if self.connected {
482 self.connected = false;
483 self.ris.set_cts(true);
485 self.ris.set_dcd(true);
486 self.ris.set_dsr(true);
487 }
488 }
489
490 fn tx_fifo_trigger(&self) -> usize {
491 if self.lcr.enable_fifos() {
492 match FifoLevelSelect(self.ifls.txiflsel()) {
493 FifoLevelSelect::BYTES_4 => 4, FifoLevelSelect::BYTES_8 => 8, FifoLevelSelect::BYTES_16 => 16, FifoLevelSelect::BYTES_24 => 24, FifoLevelSelect::BYTES_28 => 28, _ => 16, }
500 } else {
501 0
502 }
503 }
504
505 fn rx_fifo_trigger(&self) -> usize {
506 if self.lcr.enable_fifos() {
507 match FifoLevelSelect(self.ifls.rxiflsel()) {
508 FifoLevelSelect::BYTES_4 => 4, FifoLevelSelect::BYTES_8 => 8, FifoLevelSelect::BYTES_16 => 16, FifoLevelSelect::BYTES_24 => 24, FifoLevelSelect::BYTES_28 => 28, _ => 16, }
515 } else {
516 1
517 }
518 }
519
520 fn fifo_size(&self) -> usize {
521 if self.lcr.enable_fifos() {
522 FIFO_SIZE
523 } else {
524 1
525 }
526 }
527
528 fn should_poll_rx(&self, wait_for_rts: bool) -> bool {
530 if self.cr.loopback() {
532 return false;
533 }
534
535 if !self.connected {
537 return false;
538 }
539
540 if wait_for_rts && (!self.cr.dtr() || !self.cr.rts()) {
546 return false;
547 }
548
549 self.rx_buffer.len() < RX_BUFFER_MAX
551 }
552
553 fn pending_interrupt(&mut self) -> bool {
554 u16::from(self.ris) & u16::from(self.imsc) != 0
555 }
556
557 fn read_dr(&mut self) -> u8 {
558 if self.rx_buffer.is_empty() {
559 return 0;
560 }
561
562 let rx = self.rx_buffer.pop_front().unwrap_or(0);
563 if self.rx_buffer.len() < self.rx_fifo_trigger() {
564 self.ris.set_rx(false);
565 }
566 rx
567 }
568
569 fn write_dr(&mut self, stats: &mut SerialStats, data: u8) {
570 if self.cr.loopback() {
571 if self.cr.enabled() && self.cr.txe() {
574 if self.cr.rxe() {
575 if self.rx_buffer.len() >= TX_BUFFER_MAX {
576 stats
577 .rx_dropped
578 .add((self.rx_buffer.len() - TX_BUFFER_MAX) as u64);
579 self.rx_buffer.truncate(TX_BUFFER_MAX);
580 self.rx_overrun = true;
581 self.ris.set_oe(true);
582 }
583
584 self.rx_buffer.push_back(data);
585 if self.rx_buffer.len() == self.rx_fifo_trigger() {
586 self.ris.set_rx(true);
587 }
588 }
589 }
590 } else {
591 if self.tx_buffer.len() >= TX_BUFFER_MAX {
592 tracing::debug!("tx fifo overrun, dropping output data");
595 stats
596 .tx_dropped
597 .add((self.tx_buffer.len() - (TX_BUFFER_MAX - 1)) as u64);
598 self.tx_buffer.truncate(TX_BUFFER_MAX - 1);
599 }
600 self.tx_buffer.push_back(data);
601
602 if self.tx_buffer.len() > self.tx_fifo_trigger() {
603 self.ris.set_tx(false);
604 }
605 }
606 }
607
608 fn write_fbrd(&mut self, data: u8) {
609 self.new_fbrd = FractionalBaudRateRegister::from(data).clear_reserved();
610 }
611
612 fn write_lcrh(&mut self, stats: &mut SerialStats, data: u8) {
613 if self.cr.enabled() {
615 return;
616 }
617
618 if self.new_ibrd != self.ibrd || u8::from(self.new_fbrd) != u8::from(self.fbrd) {
619 self.ibrd = self.new_ibrd;
620 self.fbrd = self.new_fbrd;
621 }
622
623 let lcr = LineControlRegister::from(data);
624 if self.lcr.enable_fifos() && !lcr.enable_fifos() {
625 stats.rx_dropped.add(self.rx_buffer.len() as u64);
628 self.rx_buffer.clear();
629
630 stats.tx_dropped.add(self.tx_buffer.len() as u64);
631 self.tx_buffer.clear();
632 }
633
634 self.lcr = lcr;
635 }
636
637 fn write_cr(&mut self, data: u16) {
638 self.cr = ControlRegister::from(data).clear_reserved();
639 }
640
641 fn write_ifls(&mut self, data: u16) {
642 self.ifls = InterruptFifoLevelSelectRegister::from(data).clear_reserved();
643 }
644
645 fn write_imsc(&mut self, data: u16) {
646 self.imsc = InterruptRegister::from(data).clear_reserved();
647 }
648
649 fn write_icr(&mut self, data: u16) {
650 self.ris = InterruptRegister::from(u16::from(self.ris) & !data);
651 }
652
653 fn write_dmacr(&mut self, data: u16) {
654 self.dmacr = DmaControlRegister::from(data).clear_reserved()
655 }
656
657 fn read_fr(&self) -> u16 {
658 let fifo_size = self.fifo_size();
659 let fr = spec::FlagRegister::new()
660 .with_cts(self.connected)
661 .with_dcd(self.connected)
662 .with_dsr(self.connected)
663 .with_busy(!self.tx_buffer.is_empty())
664 .with_rxfe(self.rx_buffer.is_empty())
665 .with_txff(self.tx_buffer.len() >= fifo_size)
666 .with_rxff(self.rx_buffer.len() >= fifo_size)
667 .with_txfe(self.tx_buffer.is_empty());
668
669 fr.into()
670 }
671}
672
673impl MmioIntercept for SerialPl011 {
674 fn mmio_read(&mut self, addr: u64, data: &mut [u8]) -> IoResult {
675 self.read(addr, data)
676 }
677
678 fn mmio_write(&mut self, addr: u64, data: &[u8]) -> IoResult {
679 self.write(addr, data)
680 }
681
682 fn get_static_regions(&mut self) -> &[(&str, RangeInclusive<u64>)] {
683 std::slice::from_ref(&self.mmio_region)
684 }
685}
686
687mod save_restore {
688 use crate::SerialPl011;
689 use crate::State;
690 use vmcore::save_restore::RestoreError;
691 use vmcore::save_restore::SaveError;
692 use vmcore::save_restore::SaveRestore;
693
694 mod state {
695 use mesh::payload::Protobuf;
696 use vmcore::save_restore::SavedStateRoot;
697
698 #[derive(Protobuf, SavedStateRoot)]
699 #[mesh(package = "serial.PL011")]
700 pub struct SavedState {
701 #[mesh(1)]
702 pub(super) tx_buffer: Vec<u8>,
703 #[mesh(2)]
704 pub(super) rx_buffer: Vec<u8>,
705 #[mesh(3)]
706 pub(super) rx_overrun: bool,
707 #[mesh(4)]
708 pub(super) connected: bool,
709 #[mesh(5)]
710 pub(super) ilpr: u8,
711 #[mesh(6)]
712 pub(super) ibrd: u16,
713 #[mesh(7)]
714 pub(super) fbrd: u8,
715 #[mesh(8)]
716 pub(super) lcr: u8,
717 #[mesh(9)]
718 pub(super) cr: u16,
719 #[mesh(10)]
720 pub(super) ifls: u16,
721 #[mesh(11)]
722 pub(super) imsc: u16,
723 #[mesh(12)]
724 pub(super) ris: u16,
725 #[mesh(13)]
726 pub(super) dmacr: u16,
727 #[mesh(14)]
728 pub(super) new_ibrd: u16,
729 #[mesh(15)]
730 pub(super) new_fbrd: u8,
731 }
732 }
733
734 impl SaveRestore for SerialPl011 {
735 type SavedState = state::SavedState;
736
737 fn save(&mut self) -> Result<Self::SavedState, SaveError> {
738 let State {
739 ref tx_buffer,
740 ref rx_buffer,
741 rx_overrun,
742 connected,
743 ilpr,
744 ibrd,
745 fbrd,
746 lcr,
747 cr,
748 ifls,
749 imsc,
750 ris,
751 dmacr,
752 new_ibrd,
753 new_fbrd,
754 } = self.state;
755 Ok(state::SavedState {
756 tx_buffer: tx_buffer.clone().into(),
757 rx_buffer: rx_buffer.clone().into(),
758 rx_overrun,
759 connected,
760 ilpr,
761 ibrd,
762 fbrd: fbrd.into(),
763 lcr: lcr.into(),
764 cr: cr.into(),
765 ifls: ifls.into(),
766 imsc: imsc.into(),
767 ris: ris.into(),
768 dmacr: dmacr.into(),
769 new_ibrd,
770 new_fbrd: new_fbrd.into(),
771 })
772 }
773
774 fn restore(&mut self, state: Self::SavedState) -> Result<(), RestoreError> {
775 let state::SavedState {
776 tx_buffer,
777 rx_buffer,
778 rx_overrun,
779 connected,
780 ilpr,
781 ibrd,
782 fbrd,
783 lcr,
784 cr,
785 ifls,
786 imsc,
787 ris,
788 dmacr,
789 new_ibrd,
790 new_fbrd,
791 } = state;
792 self.state = State {
793 tx_buffer: tx_buffer.into(),
794 rx_buffer: rx_buffer.into(),
795 rx_overrun,
796 connected,
797 ilpr,
798 ibrd,
799 fbrd: fbrd.into(),
800 lcr: lcr.into(),
801 cr: cr.into(),
802 ifls: ifls.into(),
803 imsc: imsc.into(),
804 ris: ris.into(),
805 dmacr: dmacr.into(),
806 new_ibrd,
807 new_fbrd: new_fbrd.into(),
808 };
809 if self.io.is_connected() {
810 self.state.connect();
811 } else {
812 self.state.disconnect();
813 }
814 self.sync();
815 Ok(())
816 }
817 }
818}
819
820#[cfg(test)]
821mod tests {
822 use super::*;
823 use chipset_device::io::IoError;
824 use chipset_device::io::IoResult;
825 use chipset_device::mmio::MmioIntercept;
826 use futures::AsyncRead;
827 use futures::AsyncWrite;
828 use inspect::InspectMut;
829 use pal_async::async_test;
830 use serial_core::SerialIo;
831 use std::future::poll_fn;
832 use std::io;
833 use std::pin::Pin;
834 use std::task::Context;
835 use std::task::Poll;
836 use vmcore::line_interrupt::LineInterrupt;
837
838 const PL011_SERIAL0_BASE: u64 = 0xEFFEC000;
839
840 const UARTCR_TXE: u16 = 0x0100;
841 const UARTCR_RXE: u16 = 0x0200;
842 const UARTCR_UARTEN: u16 = 0x0001;
843
844 const UARTLCR_H_FIFO_ENABLE: u16 = 0x0010;
845 const UARTLCR_H_8BITS: u16 = 0x0060;
846
847 #[derive(InspectMut)]
849 pub struct SerialIoMock {
850 data: Vec<u8>,
851 }
852
853 impl SerialIo for SerialIoMock {
854 fn is_connected(&self) -> bool {
855 true
856 }
857
858 fn poll_connect(&mut self, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
859 Poll::Ready(Ok(()))
860 }
861
862 fn poll_disconnect(&mut self, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
863 Poll::Ready(Ok(()))
864 }
865 }
866
867 impl AsyncRead for SerialIoMock {
868 fn poll_read(
869 mut self: Pin<&mut Self>,
870 _cx: &mut Context<'_>,
871 buf: &mut [u8],
872 ) -> Poll<io::Result<usize>> {
873 if self.data.is_empty() {
874 return Poll::Ready(Err(ErrorKind::ConnectionAborted.into()));
875 }
876 let n = buf.len().min(self.data.len());
877 for (s, d) in self.data.drain(..n).zip(buf) {
878 *d = s;
879 }
880 Poll::Ready(Ok(n))
881 }
882 }
883
884 impl AsyncWrite for SerialIoMock {
885 fn poll_write(
886 mut self: Pin<&mut Self>,
887 _cx: &mut Context<'_>,
888 buf: &[u8],
889 ) -> Poll<io::Result<usize>> {
890 let buf = &buf[..buf.len().min(FIFO_SIZE)];
891 self.data.extend_from_slice(buf);
892 Poll::Ready(Ok(buf.len()))
893 }
894
895 fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
896 Poll::Ready(Ok(()))
897 }
898
899 fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
900 Poll::Ready(Ok(()))
901 }
902 }
903
904 impl SerialIoMock {
905 pub fn new() -> Self {
906 Self { data: Vec::new() }
907 }
908 }
909
910 #[test]
911 fn test_read() {
912 let serial_io = SerialIoMock::new();
913 let mut serial = SerialPl011::new(
914 "com1".to_string(),
915 PL011_SERIAL0_BASE,
916 LineInterrupt::detached(),
917 Box::new(serial_io),
918 )
919 .unwrap();
920
921 let mut data = vec![0; 1];
922 serial.mmio_read(0, &mut data).unwrap();
923
924 let mut data = vec![0; 2];
925 serial.mmio_read(0, &mut data).unwrap();
926
927 let mut data = vec![0; 4];
928 serial.mmio_read(0, &mut data).unwrap();
929
930 assert!(matches!(
931 serial.mmio_read(1, &mut data),
932 IoResult::Err(IoError::UnalignedAccess)
933 ));
934 assert!(matches!(
935 serial.mmio_read(2, &mut data),
936 IoResult::Err(IoError::UnalignedAccess)
937 ));
938 assert!(matches!(
939 serial.mmio_read(3, &mut data),
940 IoResult::Err(IoError::UnalignedAccess)
941 ));
942
943 serial
944 .mmio_read(Register::UARTDR.0 as u64, &mut data)
945 .unwrap();
946 serial
947 .mmio_read(Register::UARTRSR.0 as u64, &mut data)
948 .unwrap();
949 serial
950 .mmio_read(Register::UARTECR.0 as u64, &mut data)
951 .unwrap();
952 serial
953 .mmio_read(Register::UARTFR.0 as u64, &mut data)
954 .unwrap();
955 serial
956 .mmio_read(Register::UARTILPR.0 as u64, &mut data)
957 .unwrap();
958 serial
959 .mmio_read(Register::UARTIBRD.0 as u64, &mut data)
960 .unwrap();
961 serial
962 .mmio_read(Register::UARTFBRD.0 as u64, &mut data)
963 .unwrap();
964 serial
965 .mmio_read(Register::UARTLCR_H.0 as u64, &mut data)
966 .unwrap();
967 serial
968 .mmio_read(Register::UARTCR.0 as u64, &mut data)
969 .unwrap();
970 serial
971 .mmio_read(Register::UARTIFLS.0 as u64, &mut data)
972 .unwrap();
973 serial
974 .mmio_read(Register::UARTIMSC.0 as u64, &mut data)
975 .unwrap();
976 serial
977 .mmio_read(Register::UARTRIS.0 as u64, &mut data)
978 .unwrap();
979 serial
980 .mmio_read(Register::UARTMIS.0 as u64, &mut data)
981 .unwrap();
982 assert!(matches!(
983 serial.mmio_read(Register::UARTICR.0 as u64, &mut data),
984 IoResult::Err(IoError::InvalidRegister)
985 ));
986 serial
987 .mmio_read(Register::UARTDMACR.0 as u64, &mut data)
988 .unwrap();
989
990 serial
991 .mmio_read(Register::UARTPERIPHID0.0 as u64, &mut data)
992 .unwrap();
993 serial
994 .mmio_read(Register::UARTPERIPHID1.0 as u64, &mut data)
995 .unwrap();
996 serial
997 .mmio_read(Register::UARTPERIPHID2.0 as u64, &mut data)
998 .unwrap();
999 serial
1000 .mmio_read(Register::UARTPERIPHID3.0 as u64, &mut data)
1001 .unwrap();
1002 serial
1003 .mmio_read(Register::UARTPCELLID0.0 as u64, &mut data)
1004 .unwrap();
1005 serial
1006 .mmio_read(Register::UARTPCELLID1.0 as u64, &mut data)
1007 .unwrap();
1008 serial
1009 .mmio_read(Register::UARTPCELLID2.0 as u64, &mut data)
1010 .unwrap();
1011 serial
1012 .mmio_read(Register::UARTPCELLID3.0 as u64, &mut data)
1013 .unwrap();
1014 }
1015
1016 #[test]
1017 fn test_write() {
1018 let serial_io = SerialIoMock::new();
1019 let mut serial = SerialPl011::new(
1020 "com1".to_string(),
1021 PL011_SERIAL0_BASE,
1022 LineInterrupt::detached(),
1023 Box::new(serial_io),
1024 )
1025 .unwrap();
1026
1027 let data = vec![0; 1];
1028 assert!(matches!(
1029 serial.mmio_write(Register::UARTIBRD.0.into(), &data),
1030 IoResult::Err(IoError::InvalidAccessSize)
1031 ));
1032
1033 let data = vec![0; 2];
1034 serial.mmio_write(0, &data).unwrap();
1035
1036 let data = vec![0; 3];
1037 serial.mmio_write(0, &data).unwrap();
1038
1039 let data = vec![0; 4];
1040 serial.mmio_write(0, &data).unwrap();
1041
1042 let data = vec![0; 5];
1043 serial.mmio_write(0, &data).unwrap();
1044
1045 assert!(matches!(
1046 serial.mmio_write(1, &data),
1047 IoResult::Err(IoError::UnalignedAccess)
1048 ));
1049 assert!(matches!(
1050 serial.mmio_write(2, &data),
1051 IoResult::Err(IoError::UnalignedAccess)
1052 ));
1053 assert!(matches!(
1054 serial.mmio_write(3, &data),
1055 IoResult::Err(IoError::UnalignedAccess)
1056 ));
1057
1058 serial.mmio_write(Register::UARTDR.0 as u64, &data).unwrap();
1059 serial
1060 .mmio_write(Register::UARTRSR.0 as u64, &data)
1061 .unwrap();
1062 serial
1063 .mmio_write(Register::UARTECR.0 as u64, &data)
1064 .unwrap();
1065 assert!(matches!(
1066 serial.mmio_write(Register::UARTFR.0 as u64, &data),
1067 IoResult::Err(IoError::InvalidRegister)
1068 ));
1069 serial
1070 .mmio_write(Register::UARTILPR.0 as u64, &data)
1071 .unwrap();
1072 serial
1073 .mmio_write(Register::UARTIBRD.0 as u64, &data)
1074 .unwrap();
1075 serial
1076 .mmio_write(Register::UARTFBRD.0 as u64, &data)
1077 .unwrap();
1078 serial
1079 .mmio_write(Register::UARTLCR_H.0 as u64, &data)
1080 .unwrap();
1081 serial.mmio_write(Register::UARTCR.0 as u64, &data).unwrap();
1082 serial
1083 .mmio_write(Register::UARTIFLS.0 as u64, &data)
1084 .unwrap();
1085 serial
1086 .mmio_write(Register::UARTIMSC.0 as u64, &data)
1087 .unwrap();
1088 assert!(matches!(
1089 serial.mmio_write(Register::UARTRIS.0 as u64, &data),
1090 IoResult::Err(IoError::InvalidRegister)
1091 ));
1092 assert!(matches!(
1093 serial.mmio_write(Register::UARTMIS.0 as u64, &data),
1094 IoResult::Err(IoError::InvalidRegister)
1095 ));
1096 serial
1097 .mmio_write(Register::UARTICR.0 as u64, &data)
1098 .unwrap();
1099 serial
1100 .mmio_write(Register::UARTDMACR.0 as u64, &data)
1101 .unwrap();
1102
1103 assert!(matches!(
1104 serial.mmio_write(Register::UARTPERIPHID0.0 as u64, &data),
1105 IoResult::Err(IoError::InvalidRegister)
1106 ));
1107 assert!(matches!(
1108 serial.mmio_write(Register::UARTPERIPHID1.0 as u64, &data),
1109 IoResult::Err(IoError::InvalidRegister)
1110 ));
1111 assert!(matches!(
1112 serial.mmio_write(Register::UARTPERIPHID2.0 as u64, &data),
1113 IoResult::Err(IoError::InvalidRegister)
1114 ));
1115 assert!(matches!(
1116 serial.mmio_write(Register::UARTPERIPHID3.0 as u64, &data),
1117 IoResult::Err(IoError::InvalidRegister)
1118 ));
1119 assert!(matches!(
1120 serial.mmio_write(Register::UARTPCELLID0.0 as u64, &data),
1121 IoResult::Err(IoError::InvalidRegister)
1122 ));
1123 assert!(matches!(
1124 serial.mmio_write(Register::UARTPCELLID1.0 as u64, &data),
1125 IoResult::Err(IoError::InvalidRegister)
1126 ));
1127 assert!(matches!(
1128 serial.mmio_write(Register::UARTPCELLID2.0 as u64, &data),
1129 IoResult::Err(IoError::InvalidRegister)
1130 ));
1131 assert!(matches!(
1132 serial.mmio_write(Register::UARTPCELLID3.0 as u64, &data),
1133 IoResult::Err(IoError::InvalidRegister)
1134 ));
1135 }
1136
1137 fn read(serial: &mut SerialPl011, r: Register) -> u16 {
1138 let mut data = vec![0; 2];
1139 serial.mmio_read(r.0 as u64, &mut data).unwrap();
1140 u16::from_ne_bytes(data[..2].try_into().unwrap())
1141 }
1142
1143 fn write(serial: &mut SerialPl011, r: Register, val: u16) {
1144 let mut data = vec![0; 2];
1145 data[..2].copy_from_slice(&val.to_ne_bytes());
1146 serial.mmio_write(r.0 as u64, &data).unwrap();
1147 }
1148
1149 #[test]
1150 fn test_init() {
1151 let serial_io = SerialIoMock::new();
1152 let mut serial = SerialPl011::new(
1153 "com1".to_string(),
1154 PL011_SERIAL0_BASE,
1155 LineInterrupt::detached(),
1156 Box::new(serial_io),
1157 )
1158 .unwrap();
1159
1160 assert_eq!(read(&mut serial, Register::UARTPERIPHID0), UARTPERIPH_ID[0]);
1161 assert_eq!(read(&mut serial, Register::UARTPERIPHID1), UARTPERIPH_ID[1]);
1162 assert_eq!(read(&mut serial, Register::UARTPERIPHID2), UARTPERIPH_ID[2]);
1163 assert_eq!(read(&mut serial, Register::UARTPERIPHID3), UARTPERIPH_ID[3]);
1164 assert_eq!(read(&mut serial, Register::UARTPCELLID0), UARTPCELL_ID[0]);
1165 assert_eq!(read(&mut serial, Register::UARTPCELLID1), UARTPCELL_ID[1]);
1166 assert_eq!(read(&mut serial, Register::UARTPCELLID2), UARTPCELL_ID[2]);
1167 assert_eq!(read(&mut serial, Register::UARTPCELLID3), UARTPCELL_ID[3]);
1168
1169 write(&mut serial, Register::UARTIMSC, 0);
1171 write(&mut serial, Register::UARTICR, 0x7ff);
1173 write(&mut serial, Register::UARTDMACR, 0x0);
1175
1176 write(&mut serial, Register::UARTCR, UARTCR_RXE | UARTCR_TXE);
1179 read(&mut serial, Register::UARTCR);
1180 read(&mut serial, Register::UARTCR);
1181 write(&mut serial, Register::UARTCR, 0x0000);
1182
1183 write(&mut serial, Register::UARTFBRD, 0x0004);
1186 write(&mut serial, Register::UARTIBRD, 0x0027);
1187 write(
1191 &mut serial,
1192 Register::UARTLCR_H,
1193 UARTLCR_H_FIFO_ENABLE | UARTLCR_H_8BITS,
1194 );
1195
1196 write(&mut serial, Register::UARTCR, UARTCR_RXE | UARTCR_TXE);
1198 read(&mut serial, Register::UARTCR);
1199 read(&mut serial, Register::UARTCR);
1200 write(
1201 &mut serial,
1202 Register::UARTCR,
1203 UARTCR_RXE | UARTCR_TXE | UARTCR_UARTEN,
1204 );
1205 }
1206
1207 #[async_test]
1208 async fn test_writeread_data() {
1209 let serial_io = SerialIoMock::new();
1210 let mut serial = SerialPl011::new(
1211 "com1".to_string(),
1212 PL011_SERIAL0_BASE,
1213 LineInterrupt::detached(),
1214 Box::new(serial_io),
1215 )
1216 .unwrap();
1217
1218 write(&mut serial, Register::UARTCR, 0x400 | 0x800); for n in 1..FIFO_SIZE as u16 {
1221 write(&mut serial, Register::UARTDR, n);
1222 }
1223
1224 poll_fn(|cx| {
1225 serial.poll_device(cx);
1226 std::task::Poll::Ready(())
1227 })
1228 .await;
1229
1230 for n in FIFO_SIZE as u16..1 {
1231 assert_eq!(read(&mut serial, Register::UARTDR), n);
1232 }
1233 }
1234
1235 #[test]
1236 fn test_write_ifls() {
1237 let serial_io = SerialIoMock::new();
1238 let mut serial = SerialPl011::new(
1239 "com1".to_string(),
1240 PL011_SERIAL0_BASE,
1241 LineInterrupt::detached(),
1242 Box::new(serial_io),
1243 )
1244 .unwrap();
1245
1246 write(&mut serial, Register::UARTIFLS, 0b000000);
1247 assert_eq!(u16::from(serial.state.ifls), 0b000000);
1248
1249 write(&mut serial, Register::UARTIFLS, 0b001001);
1250 assert_eq!(u16::from(serial.state.ifls), 0b001001);
1251
1252 write(&mut serial, Register::UARTIFLS, 0b100100);
1253 assert_eq!(u16::from(serial.state.ifls), 0b100100);
1254
1255 write(&mut serial, Register::UARTIFLS, 0b11001001);
1256 assert_eq!(u16::from(serial.state.ifls), 0b001001); }
1258
1259 #[test]
1260 fn test_write_icr() {
1261 let serial_io = SerialIoMock::new();
1262 let mut serial = SerialPl011::new(
1263 "com1".to_string(),
1264 PL011_SERIAL0_BASE,
1265 LineInterrupt::detached(),
1266 Box::new(serial_io),
1267 )
1268 .unwrap();
1269
1270 serial.state.ris = InterruptRegister::from(0b11111111111).clear_reserved();
1271 write(&mut serial, Register::UARTICR, 0b00000000000);
1272 assert_eq!(u16::from(serial.state.ris), 0b11110111111);
1273
1274 serial.state.ris = InterruptRegister::from(0b11111111111).clear_reserved();
1275 write(&mut serial, Register::UARTICR, 0b100000000000); assert_eq!(u16::from(serial.state.ris), 0b11110111111);
1277
1278 serial.state.ris = InterruptRegister::from(0b11111111111).clear_reserved();
1279 write(&mut serial, Register::UARTICR, 0b11111111111);
1280 assert_eq!(u16::from(serial.state.ris), 0b00000000000);
1281
1282 serial.state.ris = InterruptRegister::from(0b11111111111).clear_reserved();
1283 write(&mut serial, Register::UARTICR, 0b111111111111); assert_eq!(u16::from(serial.state.ris), 0b00000000000);
1285
1286 serial.state.ris = InterruptRegister::from(0b11111111111).clear_reserved();
1287 write(&mut serial, Register::UARTICR, 0b01111011110);
1288 assert_eq!(u16::from(serial.state.ris), 0b10000100001);
1289 }
1290}