sylveos

Toy Operating System
Log | Files | Refs

mailbox.zig (4225B)


      1 const std = @import("std");
      2 
      3 const mem = @import("../mem.zig");
      4 
      5 const BOX_STATUS = mem.BASE_ADDRESS + 0xB898;
      6 const BOX_READ = mem.BASE_ADDRESS + 0xB880;
      7 const BOX_WRITE = mem.BASE_ADDRESS + 0xB8A0;
      8 
      9 const BOX_FULL: u32 = 1 << 31;
     10 const BOX_EMPTY: u32 = 1 << 30;
     11 const BOX_CHANNEL: u32 = 8;
     12 
     13 const Error = error{
     14     Invalidresponse,
     15 };
     16 
     17 fn Message(comptime T: type) type {
     18     return packed struct {
     19         message_size: u32, // msg[0]
     20         request_code: u32, // msg[1]
     21         message_tag: u32, // msg[2]
     22         bytes_available: u32, // msg[3]
     23         response_code: u32, // msg[4]
     24         data: T, // msg[5..]
     25         end_tag: u32, // msg[..]
     26 
     27         const Self = @This();
     28 
     29         pub fn new(tag: u32) Self {
     30             return .{
     31                 .message_size = @sizeOf(Self),
     32                 .request_code = 0,
     33                 .message_tag = tag,
     34                 .bytes_available = @sizeOf(T),
     35                 .response_code = 0,
     36                 .data = std.mem.zeroes(T),
     37                 .end_tag = 0,
     38             };
     39         }
     40 
     41         pub fn send(self: *align(16) Self) !u32 {
     42             mem.barrier(.Write);
     43 
     44             while ((mem.get_u32(@ptrFromInt(BOX_STATUS)) & BOX_FULL) != 0) {}
     45 
     46             mem.put_u32_barrier(@ptrFromInt(BOX_WRITE), @intFromPtr(self) | BOX_CHANNEL);
     47 
     48             while ((mem.get_u32(@ptrFromInt(BOX_STATUS)) & BOX_EMPTY) != 0) {}
     49 
     50             const value = mem.get_u32_barrier(@ptrFromInt(BOX_READ));
     51 
     52             if ((value & 0xf) != BOX_CHANNEL) return Error.Invalidresponse;
     53 
     54             return value;
     55         }
     56     };
     57 }
     58 
     59 const SERIAL_TAG = 0x00010004;
     60 pub fn get_serial_number() !u64 {
     61     var message: Message(u64) align(16) = .new(SERIAL_TAG);
     62     _ = try message.send();
     63 
     64     return message.data;
     65 }
     66 
     67 const ARM_MEMORY_INFO_TAG = 0x00010005;
     68 const VC_MEMORY_INFO_TAG = 0x00010006;
     69 const MemoryInfo = packed struct(u64) {
     70     base_address: u32,
     71     memory_size: u32,
     72 };
     73 
     74 pub fn get_arm_memory_info() !MemoryInfo {
     75     var message: Message(MemoryInfo) align(16) = .new(ARM_MEMORY_INFO_TAG);
     76     _ = try message.send();
     77 
     78     return message.data;
     79 }
     80 
     81 pub fn get_vc_memory_info() !MemoryInfo {
     82     var message: Message(MemoryInfo) align(16) = .new(VC_MEMORY_INFO_TAG);
     83     _ = try message.send();
     84 
     85     return message.data;
     86 }
     87 
     88 const MODEL_TAG = 0x00010001;
     89 pub fn get_board_model() !u32 {
     90     var message: Message(u32) align(16) = .new(MODEL_TAG);
     91     _ = try message.send();
     92 
     93     return message.data;
     94 }
     95 
     96 const REVISION_TAG = 0x00010002;
     97 pub fn get_board_revision() !u32 {
     98     var message: Message(u32) align(16) = .new(REVISION_TAG);
     99     _ = try message.send();
    100 
    101     return message.data;
    102 }
    103 
    104 const TEMP_TAG = 0x00030006;
    105 pub const TemperatureId = enum(u32) {
    106     SoC = 0,
    107     ARM = 1,
    108 };
    109 pub fn get_temperature(id: TemperatureId) !u32 {
    110     const TemperatureRequest = packed struct(u64) {
    111         id: u32,
    112         value: u32,
    113     };
    114     var message: Message(TemperatureRequest) align(16) = .new(TEMP_TAG);
    115     message.data.id = @intFromEnum(id);
    116     _ = try message.send();
    117 
    118     return message.data.value;
    119 }
    120 
    121 pub const ClockId = enum(u32) {
    122     EMMC = 1,
    123     UART = 2,
    124     ARM = 3,
    125     Core = 4,
    126     V3D = 5,
    127     H254 = 6,
    128     ISP = 7,
    129     SDRAM = 8,
    130     Pixel = 9,
    131     PWM = 10,
    132     HEVC = 11,
    133     EMMC2 = 12,
    134     M2MC = 13,
    135     PixelBvB = 14,
    136 };
    137 
    138 pub const ClockRate = enum(u32) {
    139     Current = 0x00030002,
    140     Real = 0x00030047,
    141     Max = 0x00030004,
    142     Min = 0x00030007,
    143 };
    144 
    145 pub fn get_clock_rate(id: ClockId, rate: ClockRate) !u32 {
    146     const GetClockRateRequest = packed struct(u64) {
    147         id: u32,
    148         rate: u32,
    149     };
    150     var message: Message(GetClockRateRequest) align(16) = .new(@intFromEnum(rate));
    151     message.data.id = @intFromEnum(id);
    152     _ = try message.send();
    153 
    154     return message.data.rate;
    155 }
    156 
    157 const CLOCK_HZ_SET = 0x00038002;
    158 pub fn set_clock_rate(id: ClockId, rate: u32, skip_turbo: bool) !u32 {
    159     const SetClockRateRequest = packed struct(u96) { id: u32, rate: u32, skip_turbo: u32 };
    160     var message: Message(SetClockRateRequest) align(16) = .new(CLOCK_HZ_SET);
    161     message.data.id = @intFromEnum(id);
    162     message.data.skip_turbo = if (skip_turbo) 1 else 0;
    163     message.data.rate = rate;
    164     _ = try message.send();
    165 
    166     return message.data.rate;
    167 }