#pragma once #include // The channel takes the lower 4 bits; the data pointer the upper 28. So a mail // must be aligned to a 16-byte boundary. #define MAIL_ALIGN 16 enum { PROPERTY_CHANNEL = 8, }; enum { MAILBOX_REQUEST = 0, MAILBOX_RESPONSE = 1, }; enum { MAILBOX_DELIVERY_ERROR = 0, MAILBOX_ERROR = 0x80000001, MAILBOX_SUCCESS = 0x80000000, }; enum { TAG_END = 0, TAG_FRAMEBUFFER_ALLOCATE = 0x00040001, TAG_FRAMEBUFFER_RELEASE = 0x00048001, TAG_FRAMEBUFFER_SET_PHYSICAL_SCREEN_SIZE = 0x00048003, TAG_FRAMEBUFFER_SET_VIRTUAL_SCREEN_SIZE = 0x00048004, TAG_FRAMEBUFFER_SET_DEPTH = 0x00048005, }; typedef struct Tag { union { uint32_t all; struct { uint16_t command : 12; // Command. uint8_t type : 4; // Command type. uint8_t device : 4; // Hardware device. uint16_t zeroes : 12; // Reserved. } id; }; uint32_t size; // Buffer size. uint32_t code; // Request/response code. uint32_t data[]; // Buffer data. } Tag; typedef struct __attribute__((aligned(MAIL_ALIGN))) Mail { uint32_t size; // Buffer size. uint32_t code; // Request/response code. Tag tags[]; // Variable quantity. } Mail; #define MAIL_SIZE(TYPE) (sizeof(TYPE) + (2 * sizeof(uint32_t))) void mbox_init(); const Mail* mbox_read(uint8_t channel); void mbox_write(uint8_t channel, volatile const void* mail);