parent
81af2c82fd
commit
4257b76183
@ -0,0 +1,80 @@
|
|||||||
|
use crate::IO_BASE;
|
||||||
|
use volatile::{ReadOnly, Volatile, WriteOnly};
|
||||||
|
|
||||||
|
/// The base address for the `MU` registers.
|
||||||
|
const MAILBOX_BASE: usize = IO_BASE + 0xB000 + 0x880;
|
||||||
|
|
||||||
|
/// Available mailbox channels
|
||||||
|
///
|
||||||
|
/// (ref: https://github.com/raspberrypi/firmware/wiki/Mailboxes)
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub enum MailboxChannel {
|
||||||
|
Framebuffer = 1,
|
||||||
|
Property = 8,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read from mailbox status register (MAILx_STA).
|
||||||
|
#[repr(u32)]
|
||||||
|
enum MailboxStatus {
|
||||||
|
MailboxEmpty = 1 << 30,
|
||||||
|
MailboxFull = 1 << 31,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mailbox registers. We basically only support mailbox 0 & 1. We
|
||||||
|
/// deliver to the VC in mailbox 1, it delivers to us in mailbox 0. See
|
||||||
|
/// BCM2835-ARM-Peripherals.pdf section 1.3 for an explanation about
|
||||||
|
/// the placement of memory barriers.
|
||||||
|
///
|
||||||
|
/// (ref: https://github.com/raspberrypi/firmware/wiki/Mailboxes)
|
||||||
|
#[repr(C)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
struct Registers {
|
||||||
|
MAIL0_RD: ReadOnly<u32>, // 0x00
|
||||||
|
__reserved0: [u32; 3],
|
||||||
|
MAIL0_POL: ReadOnly<u32>, // 0x10
|
||||||
|
MAIL0_SND: ReadOnly<u32>, // 0x14
|
||||||
|
MAIL0_STA: ReadOnly<u32>, // 0x18
|
||||||
|
MAIL0_CNF: Volatile<u32>, // 0x1c
|
||||||
|
|
||||||
|
MAIL1_WRT: WriteOnly<u32>, // 0x20
|
||||||
|
__reserved1: [u32; 3],
|
||||||
|
_MAIL1_POL: ReadOnly<u32>, // 0x30
|
||||||
|
_MAIL1_SND: ReadOnly<u32>, // 0x34
|
||||||
|
MAIL1_STA: ReadOnly<u32>, // 0x38
|
||||||
|
_MAIL1_CNF: Volatile<u32>, // 0x3c
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The Raspberry Pi's mailbox.
|
||||||
|
///
|
||||||
|
/// (ref: https://github.com/raspberrypi/firmware/wiki/Accessing-mailboxes)
|
||||||
|
pub struct Mailbox {
|
||||||
|
registers: &'static mut Registers,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mailbox {
|
||||||
|
/// Returns a new instance of `Mailbox`.
|
||||||
|
#[inline]
|
||||||
|
pub fn new() -> Mailbox {
|
||||||
|
Mailbox {
|
||||||
|
registers: unsafe { &mut *(MAILBOX_BASE as *mut Registers) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read from the requested channel of mailbox 0.
|
||||||
|
pub fn read(&self, channel: MailboxChannel) -> u32 {
|
||||||
|
loop {
|
||||||
|
while self.registers.MAIL0_STA.read() & (MailboxStatus::MailboxEmpty as u32) != 0 {}
|
||||||
|
let data = self.registers.MAIL0_RD.read();
|
||||||
|
if data & 0xF == channel as u32 {
|
||||||
|
return data & !0xF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write to the requested channel of mailbox 1.
|
||||||
|
pub fn write(&mut self, channel: MailboxChannel, data: u32) {
|
||||||
|
while self.registers.MAIL1_STA.read() & (MailboxStatus::MailboxFull as u32) != 0 {}
|
||||||
|
self.registers.MAIL1_WRT.write((data & !0xF) | (channel as u32));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue