//! Raspberry PI 3 Model B/B+ use bcm2837::atags::Atags; use once::*; use alloc::string::String; #[path = "../../../../drivers/gpu/fb.rs"] pub mod fb; pub mod irq; pub mod mailbox; pub mod serial; pub mod timer; use fb::FramebufferInfo; pub const IO_REMAP_BASE: usize = bcm2837::consts::IO_BASE; pub const IO_REMAP_END: usize = bcm2837::consts::KERNEL_OFFSET + 0x4000_1000; /// Initialize serial port before other initializations. pub fn init_serial_early() { assert_has_not_been_called!("board::init must be called only once"); serial::init(); println!("Hello Raspberry Pi!"); } /// Initialize raspi3 drivers pub fn init_driver() { #[cfg(not(feature = "nographic"))] fb::init(); timer::init(); } /// Returns the (start address, end address) of the physical memory on this /// system if it can be determined. If it cannot, `None` is returned. /// /// This function is expected to return `Some` under all normal cirumstances. pub fn probe_memory() -> Option<(usize, usize)> { let mut atags: Atags = Atags::get(); while let Some(atag) = atags.next() { if let Some(mem) = atag.mem() { return Some((mem.start as usize, (mem.start + mem.size) as usize)); } } None } pub fn probe_fb_info(width: u32, height: u32, depth: u32) -> Result<(FramebufferInfo, usize), String> { let (width, height) = if width == 0 || height == 0 { mailbox::framebuffer_get_physical_size()? } else { (width, height) }; let depth = if depth == 0 { mailbox::framebuffer_get_depth()? } else { depth }; let info = mailbox::framebuffer_alloc(width, height, depth)?; if info.bus_addr == 0 || info.screen_size == 0 { Err(format!("mailbox call returned an invalid address/size"))?; } if info.pitch == 0 || info.pitch != info.xres * info.depth / 8 { Err(format!( "mailbox call returned an invalid pitch value {}", info.pitch ))?; } use crate::arch::memory; let paddr = info.bus_addr & !0xC0000000; let vaddr = memory::ioremap(paddr as usize, info.screen_size as usize, "fb"); if vaddr == 0 { Err(format!( "cannot remap memory range [{:#x?}..{:#x?}]", paddr, paddr + info.screen_size ))?; } Ok((info, vaddr)) }