3
* @brief Mailbox Property interface for Raspberry Pi
6
* @author kpishere (ref: https://www.valvers.com/open-software/raspberry-pi/bare-metal-programming-in-c-part-5/)
14
#include <drivers/mailbox/bcm2835_mailbox.h>
15
#include "bcm2835_mailbox_property.h"
17
#define PROPERTY_BUFFER 8192
19
static int pt[PROPERTY_BUFFER] __attribute__((aligned(16)));
20
static int pt_index = 0;
22
void bcm2835_property_init( void )
24
/* Fill in the size on-the-fly */
27
/* Process request (All other values are reserved!) */
28
pt[PT_OREQUEST_OR_RESPONSE] = 0;
30
/* First available data slot */
33
/* NULL tag to terminate tag list */
38
@brief Add a property tag to the current tag list. Data can be included. All data is uint32_t
41
void bcm2835_property_add_tag( bcm2835_mailbox_tag_t tag, ... )
50
case TAG_GET_FIRMWARE_VERSION:
51
case TAG_GET_BOARD_MODEL:
52
case TAG_GET_BOARD_REVISION:
53
case TAG_GET_BOARD_MAC_ADDRESS:
54
case TAG_GET_BOARD_SERIAL:
55
case TAG_GET_ARM_MEMORY:
56
case TAG_GET_VC_MEMORY:
57
case TAG_GET_DMA_CHANNELS:
58
/* Provide an 8-byte buffer for the response */
60
pt[pt_index++] = 0; /* Request */
65
case TAG_GET_COMMAND_LINE:
66
/* Provide a 256-byte buffer */
68
pt[pt_index++] = 0; /* Request */
72
case TAG_GET_EDID_BLOCK:
74
pt[pt_index++] = 0; /* Request */
75
pt[pt_index++] = va_arg( vl, int );
76
pt_index += (136 - sizeof(uint32_t));
79
case TAG_ALLOCATE_BUFFER:
80
case TAG_GET_MAX_CLOCK_RATE:
81
case TAG_GET_MIN_CLOCK_RATE:
82
case TAG_GET_CLOCK_RATE:
83
case TAG_GET_CLOCK_STATE:
84
case TAG_GET_POWER_STATE:
88
case TAG_GET_MAX_VOLTAGE:
89
case TAG_GET_MIN_VOLTAGE:
90
case TAG_GET_TEMPERATURE:
91
case TAG_GET_MAX_TEMPERATURE:
93
case TAG_UNLOCK_MEMORY:
94
case TAG_RELEASE_MEMORY:
95
case TAG_GET_DISPMANX_MEM_HANDLE:
97
pt[pt_index++] = 0; /* Request */
98
pt[pt_index++] = va_arg( vl, int );
102
case TAG_SET_CLOCK_RATE:
103
case TAG_ALLOCATE_MEMORY:
105
pt[pt_index++] = 0; /* Request */
106
pt[pt_index++] = va_arg( vl, int ); /* Clock ID / size */
107
pt[pt_index++] = va_arg( vl, int ); /* Rate (in Hz) / alignment */
108
pt[pt_index++] = va_arg( vl, int ); /* Skip turbo setting if == 1 / flags */
111
case TAG_EXECUTE_CODE:
113
pt[pt_index++] = 0; /* Request */
114
pt[pt_index++] = va_arg( vl, int ); /* function pointer */
115
pt[pt_index++] = va_arg( vl, int ); /* r0 */
116
pt[pt_index++] = va_arg( vl, int ); /* r1 */
117
pt[pt_index++] = va_arg( vl, int ); /* r2 */
118
pt[pt_index++] = va_arg( vl, int ); /* r3 */
119
pt[pt_index++] = va_arg( vl, int ); /* r4 */
120
pt[pt_index++] = va_arg( vl, int ); /* r5 */
123
case TAG_SET_CURSOR_INFO:
125
pt[pt_index++] = 0; /* Request */
126
pt[pt_index++] = va_arg( vl, int ); /* width */
127
pt[pt_index++] = va_arg( vl, int ); /* height */
128
pt[pt_index++] = va_arg( vl, int ); /* (unused) */
129
pt[pt_index++] = va_arg( vl, int ); /* pinter to pixels */
130
pt[pt_index++] = va_arg( vl, int ); /* hotspot X */
131
pt[pt_index++] = va_arg( vl, int ); /* hotspot Y */
134
case TAG_SET_CURSOR_STATE:
136
pt[pt_index++] = 0; /* Request */
137
pt[pt_index++] = va_arg( vl, int ); /* enable */
138
pt[pt_index++] = va_arg( vl, int ); /* x */
139
pt[pt_index++] = va_arg( vl, int ); /* y */
140
pt[pt_index++] = va_arg( vl, int ); /* flags: 0=display coords, 1=framebuffer coords */
143
case TAG_GET_PHYSICAL_SIZE:
144
case TAG_SET_PHYSICAL_SIZE:
145
case TAG_TEST_PHYSICAL_SIZE:
146
case TAG_GET_VIRTUAL_SIZE:
147
case TAG_SET_VIRTUAL_SIZE:
148
case TAG_TEST_VIRTUAL_SIZE:
149
case TAG_GET_VIRTUAL_OFFSET:
150
case TAG_SET_VIRTUAL_OFFSET:
151
case TAG_SET_POWER_STATE:
152
case TAG_SET_CLOCK_STATE:
154
case TAG_SET_VOLTAGE:
156
pt[pt_index++] = 0; /* Request */
158
if( ( tag == TAG_SET_PHYSICAL_SIZE ) ||
159
( tag == TAG_SET_VIRTUAL_SIZE ) ||
160
( tag == TAG_SET_VIRTUAL_OFFSET ) ||
161
( tag == TAG_TEST_PHYSICAL_SIZE ) ||
162
( tag == TAG_TEST_VIRTUAL_SIZE ) ||
163
( tag == TAG_SET_POWER_STATE ) ||
164
( tag == TAG_SET_CLOCK_STATE ) ||
165
( tag == TAG_SET_TURBO ) ||
166
( tag == TAG_SET_VOLTAGE ) )
168
pt[pt_index++] = va_arg( vl, int ); /* Width / device id */
169
pt[pt_index++] = va_arg( vl, int ); /* Height / on/off / level / value */
177
case TAG_GET_ALPHA_MODE:
178
case TAG_SET_ALPHA_MODE:
181
case TAG_GET_PIXEL_ORDER:
182
case TAG_SET_PIXEL_ORDER:
184
case TAG_BLANK_SCREEN:
186
pt[pt_index++] = 0; /* Request */
188
if( ( tag == TAG_SET_DEPTH ) ||
189
( tag == TAG_SET_PIXEL_ORDER ) ||
190
( tag == TAG_SET_ALPHA_MODE ) ||
191
( tag == TAG_BLANK_SCREEN ) )
193
/* Colour Depth, bits-per-pixel \ Pixel Order State / on/off */
194
pt[pt_index++] = va_arg( vl, int );
202
case TAG_GET_OVERSCAN:
203
case TAG_SET_OVERSCAN:
205
pt[pt_index++] = 0; /* Request */
207
if( ( tag == TAG_SET_OVERSCAN ) )
209
pt[pt_index++] = va_arg( vl, int ); /* Top pixels */
210
pt[pt_index++] = va_arg( vl, int ); /* Bottom pixels */
211
pt[pt_index++] = va_arg( vl, int ); /* Left pixels */
212
pt[pt_index++] = va_arg( vl, int ); /* Right pixels */
220
case TAG_RELEASE_BUFFER:
221
pt[pt_index++] = 0; /* no arguments */
222
pt[pt_index++] = 0; /* Request */
226
/* Unsupported tags, just remove the tag from the list */
231
/* Make sure the tags are 0 terminated to end the list and update the buffer size */
237
int bcm2835_property_process( void )
241
/* Fill in the size of the buffer */
242
pt[PT_OSIZE] = ( pt_index + 1 ) << 2;
243
pt[PT_OREQUEST_OR_RESPONSE] = 0;
245
bcm2835_mailbox_write((unsigned int)pt, BCM2835_TAGS_ARM_TO_VC);
247
result = bcm2835_mailbox_read( BCM2835_TAGS_ARM_TO_VC );
252
bcm2835_mailbox_property_t* bcm2835_property_get( bcm2835_mailbox_tag_t tag )
254
static bcm2835_mailbox_property_t property;
259
/* Get the tag from the buffer. Start at the first tag position */
262
while( index < ( pt[PT_OSIZE] >> 2 ) )
264
/* printf( "Test Tag: [%d] %8.8X\r\n", index, pt[index] ); */
265
if( pt[index] == tag )
267
tag_buffer = &pt[index];
271
/* Progress to the next tag if we haven't yet discovered the tag */
272
index += ( pt[index + 1] >> 2 ) + 3;
275
/* Return NULL of the property tag cannot be found in the buffer */
276
if( tag_buffer == 0 )
279
/* Return the required data */
280
property.byte_length = tag_buffer[T_ORESPONSE] & 0xFFFF;
281
memcpy( property.data.buffer_8, &tag_buffer[T_OVALUE], property.byte_length );
287
// A null terminated list of properties to retrieve
289
void bcm2835_property_value32(bcm2835_mailbox_tag_t *props, uint32_t *value32) {
290
bcm2835_mailbox_property_t *resp;
292
bcm2835_property_init();
293
for(int i = 0; props[i] != 0x0; i++) {
294
bcm2835_property_add_tag( props[i] );
297
bcm2835_property_process();
298
for(int i = 0; props[i] != 0x0; i++) {
299
resp = bcm2835_property_get( props[i] );
300
value32[i] = resp->data.value_32;