Skip to content

Commit

Permalink
Split serial port and logger into "fully-featured" and "basic" crates (
Browse files Browse the repository at this point in the history
…#436)

* Move previous serial port implementation into `serial_port_basic` crate. 
* New `serial_port` crate is the fully-featured one that supports interrupt-based data receival.
* Introduce an "early" logger that can only use basic serial ports, for use during early boot. The main logger supports any generic writer that implements `fmt::Write`. 
* The `device_manager` now initializes the fully-featured serial ports.
  • Loading branch information
kevinaboos authored Aug 21, 2021
1 parent 7041ee4 commit d6b86b6
Show file tree
Hide file tree
Showing 14 changed files with 720 additions and 381 deletions.
17 changes: 15 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions applications/test_serial_echo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

extern crate alloc;
// #[macro_use] extern crate log;
// #[macro_use] extern crate terminal_print;
#[macro_use] extern crate terminal_print;
extern crate task;
extern crate bare_io;
extern crate io;
Expand All @@ -29,7 +29,13 @@ pub fn main(args: Vec<String>) -> isize {
.and_then(|s| SerialPortAddress::try_from(&**s).ok())
.unwrap_or(SerialPortAddress::COM1);

let serial_port = get_serial_port(serial_port_address);
let serial_port = match get_serial_port(serial_port_address) {
Some(sp) => sp.clone(),
_ => {
println!("Error: serial port {:?} was not initialized.", serial_port_address);
return -1;
}
};

if true {
let mut serial_port_io = LockableIo::<SerialPort, MutexIrqSafe<_>, _>::from(serial_port);
Expand Down
12 changes: 9 additions & 3 deletions kernel/console/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,18 @@ fn console_connection_detector(connection_listener: Receiver<SerialPortAddress>)
error!("Error receiving console connection request: {:?}", e);
"error receiving console connection request"
})?;
let serial_port = get_serial_port(serial_port_address);
let serial_port = match get_serial_port(serial_port_address) {
Some(sp) => sp.clone(),
_ => {
warn!("Serial port {:?} was not initialized, skipping console connection request", serial_port_address);
continue;
}
};

let new_console = Console::new_serial_console(
alloc::format!("console_{:?}", serial_port_address),
LockableIo::<_, MutexIrqSafe<SerialPort>, _>::from(serial_port),
LockableIo::<_, MutexIrqSafe<SerialPort>, _>::from(serial_port),
LockableIo::<_, MutexIrqSafe<SerialPort>, _>::from(serial_port.clone()),
LockableIo::<_, MutexIrqSafe<SerialPort>, _>::from(serial_port.clone()),
);

let (sender, receiver) = async_channel::new_channel(16);
Expand Down
6 changes: 6 additions & 0 deletions kernel/device_manager/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ path = "../memory"
[dependencies.apic]
path = "../apic"

[dependencies.serial_port]
path = "../serial_port"

[dependencies.logger]
path = "../logger"

[dependencies.e1000]
path = "../e1000"

Expand Down
35 changes: 32 additions & 3 deletions kernel/device_manager/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ extern crate e1000;
extern crate memory;
extern crate apic;
extern crate acpi;
extern crate serial_port;
extern crate logger;
extern crate keyboard;
extern crate pci;
extern crate mouse;
Expand All @@ -23,13 +25,15 @@ extern crate bare_io;
#[macro_use] extern crate derive_more;
extern crate mlx5;

use core::{array::IntoIter, convert::TryFrom};
use mpmc::Queue;
use event_types::Event;
use memory::MemoryManagementInfo;
use ethernet_smoltcp_device::EthernetNetworkInterface;
use network_manager::add_to_network_interfaces;
use alloc::vec::Vec;
use io::{ByteReaderWriterWrapper, LockableIo, ReaderWriter};
use serial_port::{SerialPortAddress, take_serial_port_basic};
use storage_manager::StorageDevice;

/// A randomly chosen IP address that must be outside of the DHCP range.
Expand All @@ -40,7 +44,11 @@ const DEFAULT_LOCAL_IP: &'static str = "10.0.2.15/24"; // the default QEMU user-
/// TODO: use DHCP to acquire gateway IP
const DEFAULT_GATEWAY_IP: [u8; 4] = [10, 0, 2, 2]; // the default QEMU user-slirp networking gateway IP

/// This is for early-stage initialization of things like VGA, ACPI, (IO)APIC, etc.
/// Performs early-stage initialization for simple devices needed during early boot.
///
/// This includes:
/// * local APICs ([`apic`]),
/// * [`acpi`] tables for system configuration info, including the IOAPIC.
pub fn early_init(kernel_mmi: &mut MemoryManagementInfo) -> Result<(), &'static str> {
// First, initialize the local apic info.
apic::init(&mut kernel_mmi.page_table)?;
Expand All @@ -52,9 +60,30 @@ pub fn early_init(kernel_mmi: &mut MemoryManagementInfo) -> Result<(), &'static
}


/// Initializes all other devices, such as the keyboard and mouse
/// as well as all devices discovered on the PCI bus.
/// Initializes all other devices not initialized during [`early_init()`].
///
/// Devices include:
/// * At least one [`serial_port`] (e.g., `COM1`) with full interrupt support,
/// * The fully-featured system [`logger`],
/// * PS2 [`keyboard`] and [`mouse`],
/// * All other devices discovered on the [`pci`] bus.
pub fn init(key_producer: Queue<Event>, mouse_producer: Queue<Event>) -> Result<(), &'static str> {

let serial_ports = logger::take_early_log_writers();
let logger_writers = IntoIter::new(serial_ports)
.flatten()
.flat_map(|sp| SerialPortAddress::try_from(sp.base_port_address())
.ok()
.map(|sp_addr| serial_port::init_serial_port(sp_addr, sp))
).map(|arc_ref| arc_ref.clone());

logger::init(None, logger_writers).map_err(|_e| "BUG: logger::init() failed")?;

// Ensure that COM1 is initialized, even if it wasn't used in [`logger::early_init()`].
if let Some(com1) = take_serial_port_basic(SerialPortAddress::COM1) {
serial_port::init_serial_port(SerialPortAddress::COM1, com1);
}

keyboard::init(key_producer);
mouse::init(mouse_producer);

Expand Down
3 changes: 2 additions & 1 deletion kernel/interrupts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,8 @@ extern "x86-interrupt" fn unimplemented_interrupt_handler(_stack_frame: &mut Exc
}
};

loop { }
// TODO: use const generics here to know which IRQ to send an EOI for (only needed for PIC).
eoi(None);
}


Expand Down
3 changes: 3 additions & 0 deletions kernel/logger/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,8 @@ log = "0.4.8"
[dependencies.irq_safety]
git = "https://github.com/theseus-os/irq_safety"

[dependencies.serial_port_basic]
path = "../serial_port_basic"

[lib]
crate-type = ["rlib"]
Loading

0 comments on commit d6b86b6

Please sign in to comment.