//! What differs from board to board, behind three small traits. The rest of //! the arm64 code only talks to `board::current()`. //! //! - `virt`: QEMU's generic Arm board. Implemented and tested; addresses //! come from its device tree, with the usual values as a fallback. //! - `raspi3`: the Raspberry Pi 3 (BCM2837). A skeleton: the addresses are //! written down, the drivers are TODO (see the README's Pi roadmap). pub mod pl011; pub mod raspi3; pub mod virt; /// A serial port: one byte out. pub trait Uart: Sync { fn putc(&self, byte: u8); } /// An interrupt controller. pub trait IrqController: Sync { /// Reset it and switch it on (all interrupts still disabled). fn init(&self); /// Let interrupt number `irq` through. fn enable(&self, irq: u32); /// Which interrupt is this? (`None`: a spurious one, nothing to do.) fn ack(&self) -> Option; /// Done with `irq`. fn eoi(&self, irq: u32); } /// What kind of memory a 1 GiB block of physical addresses holds. #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum Kind { /// RAM: cached, can hold code. Normal, /// Device registers: uncached, in order, never executed. Device, } /// A board. pub trait Board: Sync { fn name(&self) -> &'static str; fn uart(&self) -> &dyn Uart; fn irq(&self) -> &dyn IrqController; /// The interrupt number of the EL1 virtual timer at this controller. fn timer_irq(&self) -> u32; /// The physical memory map, in 1 GiB blocks: (first address, kind). fn memory_map(&self) -> &'static [(u64, Kind)]; /// Read the device tree at `dtb` (if any) and use what it says. /// Returns lines for the boot log. fn configure(&self, dtb: Option<&super::dtb::Fdt>) -> alloc::vec::Vec; } /// The board this kernel was built for. (Only `virt` for now; picking the /// Pi 3 will be a cargo feature once its drivers exist.) pub fn current() -> &'static dyn Board { &virt::VIRT }