embox

Форк
0
/
bcm2835_mailbox_property.c 
302 строки · 9.2 Кб
1
/**
2
 * @file
3
 * @brief Mailbox Property interface for Raspberry Pi
4
 *
5
 * @date 2021.07.05
6
 * @author kpishere (ref: https://www.valvers.com/open-software/raspberry-pi/bare-metal-programming-in-c-part-5/)
7
 */
8

9
#include <errno.h>
10
#include <stdint.h>
11
#include <stdarg.h>
12
#include <string.h>
13

14
#include <drivers/mailbox/bcm2835_mailbox.h>
15
#include "bcm2835_mailbox_property.h"
16

17
#define PROPERTY_BUFFER 8192
18

19
static int pt[PROPERTY_BUFFER] __attribute__((aligned(16)));
20
static int pt_index = 0;
21

22
void bcm2835_property_init( void )
23
{
24
    /* Fill in the size on-the-fly */
25
    pt[PT_OSIZE] = 12;
26

27
    /* Process request (All other values are reserved!) */
28
    pt[PT_OREQUEST_OR_RESPONSE] = 0;
29

30
    /* First available data slot */
31
    pt_index = 2;
32

33
    /* NULL tag to terminate tag list */
34
    pt[pt_index] = 0;
35
}
36

37
/**
38
    @brief Add a property tag to the current tag list. Data can be included. All data is uint32_t
39
    @param tag
40
*/
41
void bcm2835_property_add_tag( bcm2835_mailbox_tag_t tag, ... )
42
{
43
    va_list vl;
44
    va_start( vl, tag );
45

46
    pt[pt_index++] = tag;
47

48
    switch( tag )
49
    {
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 */
59
            pt[pt_index++] = 8;
60
            pt[pt_index++] = 0; /* Request */
61
            pt_index += 2;
62
            break;
63

64
        case TAG_GET_CLOCKS:
65
        case TAG_GET_COMMAND_LINE:
66
            /* Provide a 256-byte buffer */
67
            pt[pt_index++] = 256;
68
            pt[pt_index++] = 0; /* Request */
69
            pt_index += 256 >> 2;
70
            break;
71

72
        case TAG_GET_EDID_BLOCK:
73
            pt[pt_index++] = 136;
74
            pt[pt_index++] = 0; /* Request */
75
            pt[pt_index++] = va_arg( vl, int );
76
            pt_index += (136 - sizeof(uint32_t));
77
            break;
78
            
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:
85
        case TAG_GET_TIMING:
86
        case TAG_GET_TURBO:
87
        case TAG_GET_VOLTAGE:
88
        case TAG_GET_MAX_VOLTAGE:
89
        case TAG_GET_MIN_VOLTAGE:
90
        case TAG_GET_TEMPERATURE:
91
        case TAG_GET_MAX_TEMPERATURE:
92
        case TAG_LOCK_MEMORY:
93
        case TAG_UNLOCK_MEMORY:
94
        case TAG_RELEASE_MEMORY:
95
        case TAG_GET_DISPMANX_MEM_HANDLE:
96
            pt[pt_index++] = 8;
97
            pt[pt_index++] = 0; /* Request */
98
            pt[pt_index++] = va_arg( vl, int );
99
            pt[pt_index++] = 0;
100
            break;
101

102
        case TAG_SET_CLOCK_RATE:
103
        case TAG_ALLOCATE_MEMORY:
104
            pt[pt_index++] = 12;
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 */
109
            break;
110

111
        case TAG_EXECUTE_CODE:
112
            pt[pt_index++] = 28;
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 */
121
            break;
122

123
        case TAG_SET_CURSOR_INFO:
124
            pt[pt_index++] = 24;
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 */
132
            break;     
133
    
134
        case TAG_SET_CURSOR_STATE:
135
            pt[pt_index++] = 16;
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 */
141
            break;
142

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:
153
        case TAG_SET_TURBO:
154
        case TAG_SET_VOLTAGE:
155
            pt[pt_index++] = 8;
156
            pt[pt_index++] = 0; /* Request */
157

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 ) )                
167
            {
168
                pt[pt_index++] = va_arg( vl, int ); /* Width / device id */
169
                pt[pt_index++] = va_arg( vl, int ); /* Height / on/off / level / value */
170
            }
171
            else
172
            {
173
                pt_index += 2;
174
            }
175
            break;
176

177
        case TAG_GET_ALPHA_MODE:
178
        case TAG_SET_ALPHA_MODE:
179
        case TAG_GET_DEPTH:
180
        case TAG_SET_DEPTH:
181
        case TAG_GET_PIXEL_ORDER:
182
        case TAG_SET_PIXEL_ORDER:
183
        case TAG_GET_PITCH:
184
        case TAG_BLANK_SCREEN:
185
            pt[pt_index++] = 4;
186
            pt[pt_index++] = 0; /* Request */
187

188
            if( ( tag == TAG_SET_DEPTH ) ||
189
                ( tag == TAG_SET_PIXEL_ORDER ) ||
190
                ( tag == TAG_SET_ALPHA_MODE ) ||
191
                ( tag == TAG_BLANK_SCREEN ) )
192
            {
193
                /* Colour Depth, bits-per-pixel \ Pixel Order State / on/off */
194
                pt[pt_index++] = va_arg( vl, int );
195
            }
196
            else
197
            {
198
                pt_index += 1;
199
            }
200
            break;
201

202
        case TAG_GET_OVERSCAN:
203
        case TAG_SET_OVERSCAN:
204
            pt[pt_index++] = 16;
205
            pt[pt_index++] = 0; /* Request */
206

207
            if( ( tag == TAG_SET_OVERSCAN ) )
208
            {
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 */
213
            }
214
            else
215
            {
216
                pt_index += 4;
217
            }
218
            break;
219

220
        case TAG_RELEASE_BUFFER:
221
            pt[pt_index++] = 0; /* no arguments */
222
            pt[pt_index++] = 0; /* Request */
223
            break;
224

225
        default:
226
            /* Unsupported tags, just remove the tag from the list */
227
            pt_index--;
228
            break;
229
    }
230

231
    /* Make sure the tags are 0 terminated to end the list and update the buffer size */
232
    pt[pt_index] = 0;
233

234
    va_end( vl );
235
}
236

237
int bcm2835_property_process( void )
238
{
239
    int result;
240

241
    /* Fill in the size of the buffer */
242
    pt[PT_OSIZE] = ( pt_index + 1 ) << 2;
243
    pt[PT_OREQUEST_OR_RESPONSE] = 0;
244

245
    bcm2835_mailbox_write((unsigned int)pt, BCM2835_TAGS_ARM_TO_VC);
246
    
247
    result = bcm2835_mailbox_read( BCM2835_TAGS_ARM_TO_VC );
248

249
    return result;
250
}
251

252
bcm2835_mailbox_property_t* bcm2835_property_get( bcm2835_mailbox_tag_t tag )
253
{
254
    static bcm2835_mailbox_property_t property;
255
    int* tag_buffer = 0;
256

257
    property.tag = tag;
258

259
    /* Get the tag from the buffer. Start at the first tag position  */
260
    int index = 2;
261

262
    while( index < ( pt[PT_OSIZE] >> 2 ) )
263
    {
264
        /* printf( "Test Tag: [%d] %8.8X\r\n", index, pt[index] ); */
265
        if( pt[index] == tag )
266
        {
267
            tag_buffer = &pt[index];
268
            break;
269
        }
270

271
        /* Progress to the next tag if we haven't yet discovered the tag */
272
        index += ( pt[index + 1] >> 2 ) + 3;
273
    }
274

275
    /* Return NULL of the property tag cannot be found in the buffer */
276
    if( tag_buffer == 0 )
277
        return 0;
278

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 );
282

283
    return &property;
284
}
285

286
//
287
// A null terminated list of properties to retrieve
288
// 
289
void bcm2835_property_value32(bcm2835_mailbox_tag_t *props, uint32_t *value32) {
290
    bcm2835_mailbox_property_t *resp;
291

292
    bcm2835_property_init();
293
    for(int i = 0; props[i] != 0x0; i++) {
294
        bcm2835_property_add_tag( props[i] );
295

296
    }
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;
301
    }
302
}
303

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.