1 /*        $NetBSD: vcprop_subr.c,v 1.10 2021/03/08 13:53:08 mlelstv Exp $       */
2 
3 /*
4  * Copyright (c) 2014 Michael Lorenz
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29  * Mailbox property interface wrapper functions
30  */
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: vcprop_subr.c,v 1.10 2021/03/08 13:53:08 mlelstv Exp $");
33 
34 #include <sys/param.h>
35 #include <sys/bus.h>
36 #include <sys/device.h>
37 #include <sys/endian.h>
38 
39 #include <uvm/uvm_extern.h>
40 
41 #include <arm/broadcom/bcm2835reg.h>
42 #include <arm/broadcom/bcm2835var.h>
43 #include <arm/broadcom/bcm2835_mbox.h>
44 
45 #include <evbarm/rpi/vcio.h>
46 #include <evbarm/rpi/vcpm.h>
47 #include <evbarm/rpi/vcprop.h>
48 
49 #include <dev/wscons/wsconsio.h>
50 
51 int
rpi_fb_set_video(int b)52 rpi_fb_set_video(int b)
53 {
54           int error;
55           uint32_t res;
56 
57           /*
58            * might as well put it here since we need to re-init it every time
59            * and it's not like this is going to be called very often anyway
60            */
61           struct __aligned(16) {
62                     struct vcprop_buffer_hdr      vb_hdr;
63                     struct vcprop_tag_blankscreen vbt_blank;
64                     struct vcprop_tag end;
65           } vb_setblank =
66           {
67                     .vb_hdr = {
68                               .vpb_len = htole32(sizeof(vb_setblank)),
69                               .vpb_rcode = htole32(VCPROP_PROCESS_REQUEST),
70                     },
71                     .vbt_blank = {
72                               .tag = {
73                                         .vpt_tag = htole32(VCPROPTAG_BLANK_SCREEN),
74                                         .vpt_len = htole32(VCPROPTAG_LEN(
75                                             vb_setblank.vbt_blank)),
76                                         .vpt_rcode = htole32(VCPROPTAG_REQUEST),
77                               },
78                               .state = htole32((b != 0) ?
79                                   VCPROP_BLANK_OFF : VCPROP_BLANK_ON),
80                     },
81                     .end = {
82                               .vpt_tag = htole32(VCPROPTAG_NULL),
83                     },
84           };
85 
86           error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setblank,
87               sizeof(vb_setblank), &res);
88 #ifdef RPI_IOCTL_DEBUG
89           printf("%s: %d %d %d %08x %08x\n", __func__, b,
90               le32toh(vb_setblank.vbt_blank.state), error, res,
91               le32toh(vb_setblank.vbt_blank.tag.vpt_rcode));
92 #endif
93           if (error)
94                     return error;
95 
96           if (!vcprop_buffer_success_p(&vb_setblank.vb_hdr) ||
97               !vcprop_tag_success_p(&vb_setblank.vbt_blank.tag)) {
98                     return EIO;
99           }
100 
101           return 0;
102 }
103 
104 uint32_t
rpi_alloc_mem(uint32_t size,uint32_t align,uint32_t flags)105 rpi_alloc_mem(uint32_t size, uint32_t align, uint32_t flags)
106 {
107           int error;
108           uint32_t res;
109 
110           struct __aligned(16) {
111                     struct vcprop_buffer_hdr      vb_hdr;
112                     struct vcprop_tag_allocmem    vbt_am;
113                     struct vcprop_tag end;
114           } vb_allocmem =
115           {
116                     .vb_hdr = {
117                               .vpb_len = htole32(sizeof(vb_allocmem)),
118                               .vpb_rcode = htole32(VCPROP_PROCESS_REQUEST),
119                     },
120                     .vbt_am = {
121                               .tag = {
122                                         .vpt_tag = htole32(VCPROPTAG_ALLOCMEM),
123                                         .vpt_len =
124                                             htole32(VCPROPTAG_LEN(vb_allocmem.vbt_am)),
125                                         .vpt_rcode = htole32(VCPROPTAG_REQUEST),
126                               },
127                               .size = htole32(size),
128                               .align = htole32(align),
129                               .flags = htole32(flags),
130                     },
131                     .end = {
132                               .vpt_tag = htole32(VCPROPTAG_NULL),
133                     },
134           };
135 
136           error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_allocmem,
137               sizeof(vb_allocmem), &res);
138 #ifdef RPI_IOCTL_DEBUG
139           printf("%s: %d %d %08x %08x\n", __func__,
140               le32toh(vb_allocmem.vbt_am.size), error, res,
141               le32toh(vb_allocmem.vbt_am.tag.vpt_rcode));
142 #endif
143           if (error)
144                     return error;
145 
146           if (!vcprop_buffer_success_p(&vb_allocmem.vb_hdr) ||
147               !vcprop_tag_success_p(&vb_allocmem.vbt_am.tag)) {
148                     return EIO;
149           }
150 
151           /* Return the handle from the VC */
152           return le32toh(vb_allocmem.vbt_am.size);
153 }
154 
155 bus_addr_t
rpi_lock_mem(uint32_t handle)156 rpi_lock_mem(uint32_t handle)
157 {
158           int error;
159           uint32_t res;
160 
161           struct __aligned(16) {
162                     struct vcprop_buffer_hdr      vb_hdr;
163                     struct vcprop_tag_lockmem     vbt_lm;
164                     struct vcprop_tag end;
165           } vb_lockmem =
166           {
167                     .vb_hdr = {
168                               .vpb_len = htole32(sizeof(vb_lockmem)),
169                               .vpb_rcode = htole32(VCPROP_PROCESS_REQUEST),
170                     },
171                     .vbt_lm = {
172                               .tag = {
173                                         .vpt_tag = htole32(VCPROPTAG_LOCKMEM),
174                                         .vpt_len =
175                                             htole32(VCPROPTAG_LEN(vb_lockmem.vbt_lm)),
176                                         .vpt_rcode = htole32(VCPROPTAG_REQUEST),
177                               },
178                               .handle = htole32(handle),
179                     },
180                     .end = {
181                               .vpt_tag = htole32(VCPROPTAG_NULL),
182                     },
183           };
184 
185           error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_lockmem,
186               sizeof(vb_lockmem), &res);
187 #ifdef RPI_IOCTL_DEBUG
188           printf("%s: %d %d %08x %08x\n", __func__,
189               le32toh(vb_lockmem.vbt_lm.handle), error, res,
190               le32toh(vb_lockmem.vbt_lm.tag.vpt_rcode));
191 #endif
192           if (error)
193                     return 0;
194 
195           if (!vcprop_buffer_success_p(&vb_lockmem.vb_hdr) ||
196               !vcprop_tag_success_p(&vb_lockmem.vbt_lm.tag)) {
197                     return 0;
198           }
199 
200           return le32toh(vb_lockmem.vbt_lm.handle);
201 }
202 
203 int
rpi_unlock_mem(uint32_t handle)204 rpi_unlock_mem(uint32_t handle)
205 {
206           int error;
207           uint32_t res;
208 
209           struct __aligned(16) {
210                     struct vcprop_buffer_hdr      vb_hdr;
211                     struct vcprop_tag_lockmem     vbt_lm;
212                     struct vcprop_tag end;
213           } vb_unlockmem =
214           {
215                     .vb_hdr = {
216                               .vpb_len = htole32(sizeof(vb_unlockmem)),
217                               .vpb_rcode = htole32(VCPROP_PROCESS_REQUEST),
218                     },
219                     .vbt_lm = {
220                               .tag = {
221                                         .vpt_tag = htole32(VCPROPTAG_UNLOCKMEM),
222                                         .vpt_len =
223                                             htole32(VCPROPTAG_LEN(vb_unlockmem.vbt_lm)),
224                                         .vpt_rcode = htole32(VCPROPTAG_REQUEST),
225                               },
226                               .handle = htole32(handle),
227                     },
228                     .end = {
229                               .vpt_tag = htole32(VCPROPTAG_NULL),
230                     },
231           };
232 
233           error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_unlockmem,
234               sizeof(vb_unlockmem), &res);
235 #ifdef RPI_IOCTL_DEBUG
236           printf("%s: %d %d %08x %08x\n", __func__,
237               le32toh(vb_unlockmem.vbt_lm.handle), error, res,
238               le32toh(vb_unlockmem.vbt_lm.tag.vpt_rcode));
239 #endif
240           if (error)
241                     return error;
242 
243           if (!vcprop_buffer_success_p(&vb_unlockmem.vb_hdr) ||
244               !vcprop_tag_success_p(&vb_unlockmem.vbt_lm.tag)) {
245                     return EIO;
246           }
247 
248           return 0;
249 }
250 
251 int
rpi_release_mem(uint32_t handle)252 rpi_release_mem(uint32_t handle)
253 {
254           int error;
255           uint32_t res;
256 
257           struct __aligned(16) {
258                     struct vcprop_buffer_hdr      vb_hdr;
259                     struct vcprop_tag_lockmem     vbt_lm;
260                     struct vcprop_tag end;
261           } vb_releasemem =
262           {
263                     .vb_hdr = {
264                               .vpb_len = htole32(sizeof(vb_releasemem)),
265                               .vpb_rcode = htole32(VCPROP_PROCESS_REQUEST),
266                     },
267                     .vbt_lm = {
268                               .tag = {
269                                         .vpt_tag = htole32(VCPROPTAG_RELEASEMEM),
270                                         .vpt_len = htole32(VCPROPTAG_LEN(
271                                             vb_releasemem.vbt_lm)),
272                                         .vpt_rcode = htole32(VCPROPTAG_REQUEST),
273                               },
274                               .handle = htole32(handle),
275                     },
276                     .end = {
277                               .vpt_tag = htole32(VCPROPTAG_NULL),
278                     },
279           };
280 
281           error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_releasemem,
282               sizeof(vb_releasemem), &res);
283 #ifdef RPI_IOCTL_DEBUG
284           printf("%s: %d %d %08x %08x\n", __func__,
285               le32toh(vb_releasemem.vbt_lm.handle), error, res,
286               le32toh(vb_releasemem.vbt_lm.tag.vpt_rcode));
287 #endif
288           if (error)
289                     return error;
290 
291           if (!vcprop_buffer_success_p(&vb_releasemem.vb_hdr) ||
292               !vcprop_tag_success_p(&vb_releasemem.vbt_lm.tag)) {
293                     return EIO;
294           }
295 
296           return 0;
297 }
298 
299 int
rpi_fb_movecursor(int x,int y,int on)300 rpi_fb_movecursor(int x, int y, int on)
301 {
302           int error;
303           uint32_t res;
304 
305           struct __aligned(16) {
306                     struct vcprop_buffer_hdr      vb_hdr;
307                     struct vcprop_tag_cursorstate vbt_cs;
308                     struct vcprop_tag end;
309           } vb_cursorstate =
310           {
311                     .vb_hdr = {
312                               .vpb_len = htole32(sizeof(vb_cursorstate)),
313                               .vpb_rcode = htole32(VCPROP_PROCESS_REQUEST),
314                     },
315                     .vbt_cs = {
316                               .tag = {
317                                         .vpt_tag = htole32(VCPROPTAG_SET_CURSOR_STATE),
318                                         .vpt_len = htole32(VCPROPTAG_LEN(
319                                             vb_cursorstate.vbt_cs)),
320                                         .vpt_rcode = htole32(VCPROPTAG_REQUEST),
321                               },
322                               .enable = htole32((on != 0) ? 1 : 0),
323                               .x = htole32(x),
324                               .y = htole32(y),
325                               .flags = htole32(1),
326                     },
327                     .end = {
328                               .vpt_tag = htole32(VCPROPTAG_NULL),
329                     },
330           };
331 
332           error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_cursorstate,
333               sizeof(vb_cursorstate), &res);
334 #ifdef RPI_IOCTL_DEBUG
335           printf("%s: %08x %d %08x %08x\n", __func__,
336               le32toh(vb_cursorstate.vbt_cs.enable), error, res,
337               le32toh(vb_cursorstate.vbt_cs.tag.vpt_rcode));
338 #endif
339           if (error)
340                     return error;
341 
342           if (!vcprop_buffer_success_p(&vb_cursorstate.vb_hdr) ||
343               !vcprop_tag_success_p(&vb_cursorstate.vbt_cs.tag)) {
344                     return EIO;
345           }
346 
347           return 0;
348 }
349 
350 int
rpi_fb_initcursor(bus_addr_t pixels,int hx,int hy)351 rpi_fb_initcursor(bus_addr_t pixels, int hx, int hy)
352 {
353           int error;
354           uint32_t res;
355 
356 
357           struct __aligned(16) {
358                     struct vcprop_buffer_hdr      vb_hdr;
359                     struct vcprop_tag_cursorinfo  vbt_ci;
360                     struct vcprop_tag end;
361           } vb_cursorinfo =
362           {
363                     .vb_hdr = {
364                               .vpb_len = htole32(sizeof(vb_cursorinfo)),
365                               .vpb_rcode = htole32(VCPROP_PROCESS_REQUEST),
366                     },
367                     .vbt_ci = {
368                               .tag = {
369                                         .vpt_tag = htole32(VCPROPTAG_SET_CURSOR_INFO),
370                                         .vpt_len = htole32(VCPROPTAG_LEN(
371                                             vb_cursorinfo.vbt_ci)),
372                                         .vpt_rcode = htole32(VCPROPTAG_REQUEST),
373                               },
374                               .width = htole32(64),
375                               .height = htole32(64),
376                               .format = htole32(0),
377                               .pixels = htole32(pixels),
378                               .hotspot_x = htole32(hx),
379                               .hotspot_y = htole32(hy),
380                     },
381                     .end = {
382                               .vpt_tag = htole32(VCPROPTAG_NULL),
383                     },
384           };
385 
386           error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_cursorinfo,
387               sizeof(vb_cursorinfo), &res);
388 #ifdef RPI_IOCTL_DEBUG
389           printf("%s: %d %d %08x %08x\n", __func__,
390               le32toh(vb_cursorinfo.vbt_ci.width), error, res,
391               le32toh(vb_cursorinfo.vbt_ci.tag.vpt_rcode));
392 #endif
393           if (error)
394                     return error;
395 
396           if (!vcprop_buffer_success_p(&vb_cursorinfo.vb_hdr) ||
397               !vcprop_tag_success_p(&vb_cursorinfo.vbt_ci.tag)) {
398                     return EIO;
399           }
400 
401           return 0;
402 }
403 
404 int
rpi_fb_get_pixelorder(uint32_t * orderp)405 rpi_fb_get_pixelorder(uint32_t *orderp)
406 {
407           int error;
408           uint32_t res;
409 
410 
411           struct __aligned(16) {
412                     struct vcprop_buffer_hdr      vb_hdr;
413                     struct vcprop_tag_fbpixelorder          vbt_po;
414                     struct vcprop_tag end;
415           } vb_pixelorder =
416           {
417                     .vb_hdr = {
418                               .vpb_len = htole32(sizeof(vb_pixelorder)),
419                               .vpb_rcode = htole32(VCPROP_PROCESS_REQUEST),
420                     },
421                     .vbt_po = {
422                               .tag = {
423                                         .vpt_tag = htole32(VCPROPTAG_GET_FB_PIXEL_ORDER),
424                                         .vpt_len = htole32(VCPROPTAG_LEN(
425                                             vb_pixelorder.vbt_po)),
426                                         .vpt_rcode = htole32(VCPROPTAG_REQUEST),
427                               },
428                     },
429                     .end = {
430                               .vpt_tag = htole32(VCPROPTAG_NULL),
431                     },
432           };
433 
434           error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_pixelorder,
435               sizeof(vb_pixelorder), &res);
436 #ifdef RPI_IOCTL_DEBUG
437           printf("%s: %d %d %08x %08x\n", __func__,
438               le32toh(vb_pixelorder.vbt_po.order), error, res,
439               le32toh(vb_pixelorder.vbt_po.tag.vpt_rcode));
440 #endif
441           if (error)
442                     return error;
443 
444           if (!vcprop_buffer_success_p(&vb_pixelorder.vb_hdr) ||
445               !vcprop_tag_success_p(&vb_pixelorder.vbt_po.tag)) {
446                     return EIO;
447           }
448 
449           *orderp = vb_pixelorder.vbt_po.order;
450 
451           return 0;
452 }
453 
454 int
rpi_fb_set_pixelorder(uint32_t order)455 rpi_fb_set_pixelorder(uint32_t order)
456 {
457           int error;
458           uint32_t res;
459 
460 
461           struct __aligned(16) {
462                     struct vcprop_buffer_hdr      vb_hdr;
463                     struct vcprop_tag_fbpixelorder          vbt_po;
464                     struct vcprop_tag end;
465           } vb_pixelorder =
466           {
467                     .vb_hdr = {
468                               .vpb_len = htole32(sizeof(vb_pixelorder)),
469                               .vpb_rcode = htole32(VCPROP_PROCESS_REQUEST),
470                     },
471                     .vbt_po = {
472                               .tag = {
473                                         .vpt_tag = htole32(VCPROPTAG_SET_FB_PIXEL_ORDER),
474                                         .vpt_len = htole32(VCPROPTAG_LEN(
475                                             vb_pixelorder.vbt_po)),
476                                         .vpt_rcode = htole32(VCPROPTAG_REQUEST),
477                               },
478                               .order = order
479                     },
480                     .end = {
481                               .vpt_tag = htole32(VCPROPTAG_NULL),
482                     },
483           };
484 
485           error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_pixelorder,
486               sizeof(vb_pixelorder), &res);
487 #ifdef RPI_IOCTL_DEBUG
488           printf("%s: %d %d %08x %08x\n", __func__,
489               le32toh(vb_pixelorder.vbt_po.order), error, res,
490               le32toh(vb_pixelorder.vbt_po.tag.vpt_rcode));
491 #endif
492           if (error)
493                     return error;
494 
495           if (!vcprop_buffer_success_p(&vb_pixelorder.vb_hdr) ||
496               !vcprop_tag_success_p(&vb_pixelorder.vbt_po.tag)) {
497                     return EIO;
498           }
499 
500           return 0;
501 }
502 
503 int
rpi_set_domain(uint32_t domain,uint32_t state)504 rpi_set_domain(uint32_t domain, uint32_t state)
505 {
506           int error;
507           uint32_t tag, res;
508 
509           tag = VCPROPTAG_SET_DOMAIN_STATE;
510           if (domain == VCPROP_DOMAIN_USB) {
511                     /* use old interface */
512                     tag = VCPROPTAG_SET_POWERSTATE;
513                     domain = VCPROP_POWER_USB;
514           }
515 
516           /*
517            * might as well put it here since we need to re-init it every time
518            * and it's not like this is going to be called very often anyway
519            */
520           struct __aligned(16) {
521                     struct vcprop_buffer_hdr      vb_hdr;
522                     struct vcprop_tag_powerstate  vbt_power;
523                     struct vcprop_tag end;
524           } vb_setpower =
525           {
526                     .vb_hdr = {
527                               .vpb_len = sizeof(vb_setpower),
528                               .vpb_rcode = VCPROP_PROCESS_REQUEST,
529                     },
530                     .vbt_power = {
531                               .tag = {
532                                         .vpt_tag = tag,
533                                         .vpt_len = VCPROPTAG_LEN(vb_setpower.vbt_power),
534                                         .vpt_rcode = VCPROPTAG_REQUEST,
535                               },
536                               .id = domain,
537                               .state = state
538                     },
539                     .end = {
540                               .vpt_tag = VCPROPTAG_NULL,
541                     },
542           };
543 
544           error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setpower,
545               sizeof(vb_setpower), &res);
546 #ifdef RPI_IOCTL_DEBUG
547           printf("%s: %08x %08x %d %08x %08x %d %d %08x %08x\n", __func__,
548               tag, domain, state,
549               vb_setpower.vbt_power.tag.vpt_tag,
550               vb_setpower.vbt_power.id,
551               vb_setpower.vbt_power.state,
552               error, res,
553               vb_setpower.vbt_power.tag.vpt_rcode);
554 #endif
555           if (error)
556                     return error;
557 
558           if (!vcprop_buffer_success_p(&vb_setpower.vb_hdr) ||
559               !vcprop_tag_success_p(&vb_setpower.vbt_power.tag)) {
560                     return EIO;
561           }
562 
563           return 0;
564 }
565 
566 int
rpi_get_domain(uint32_t domain,uint32_t * statep)567 rpi_get_domain(uint32_t domain, uint32_t *statep)
568 {
569           int error;
570           uint32_t tag, res;
571 
572           tag = VCPROPTAG_GET_DOMAIN_STATE;
573           if (domain == VCPROP_DOMAIN_USB) {
574                     /* use old interface */
575                     tag = VCPROPTAG_GET_POWERSTATE;
576                     domain = VCPROP_POWER_USB;
577           }
578 
579           /*
580            * might as well put it here since we need to re-init it every time
581            * and it's not like this is going to be called very often anyway
582            */
583           struct __aligned(16) {
584                     struct vcprop_buffer_hdr      vb_hdr;
585                     struct vcprop_tag_powerstate  vbt_power;
586                     struct vcprop_tag end;
587           } vb_setpower =
588           {
589                     .vb_hdr = {
590                               .vpb_len = sizeof(vb_setpower),
591                               .vpb_rcode = VCPROP_PROCESS_REQUEST,
592                     },
593                     .vbt_power = {
594                               .tag = {
595                                         .vpt_tag = tag,
596                                         .vpt_len = VCPROPTAG_LEN(vb_setpower.vbt_power),
597                                         .vpt_rcode = VCPROPTAG_REQUEST,
598                               },
599                               .id = domain,
600                               .state = ~0
601                     },
602                     .end = {
603                               .vpt_tag = VCPROPTAG_NULL,
604                     },
605           };
606 
607           error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setpower,
608               sizeof(vb_setpower), &res);
609 #ifdef RPI_IOCTL_DEBUG
610           printf("%s: %08x %08x %d %08x %08x %d %d %08x %08x\n", __func__,
611               tag, domain, *statep,
612               vb_setpower.vbt_power.tag.vpt_tag,
613               vb_setpower.vbt_power.id,
614               vb_setpower.vbt_power.state,
615               error, res,
616               vb_setpower.vbt_power.tag.vpt_rcode);
617 #endif
618           if (error)
619                     return error;
620 
621           if (!vcprop_buffer_success_p(&vb_setpower.vb_hdr) ||
622               !vcprop_tag_success_p(&vb_setpower.vbt_power.tag)) {
623                     return EIO;
624           }
625 
626           *statep = vb_setpower.vbt_power.state;
627 
628           return 0;
629 }
630 
631 int
rpi_vchiq_init(uint32_t * channelbasep)632 rpi_vchiq_init(uint32_t *channelbasep)
633 {
634           int error;
635           uint32_t tag, res;
636           struct __aligned(16) {
637                     struct vcprop_buffer_hdr      vb_hdr;
638                     struct vcprop_tag_vchiqinit   vbt_vchiq;
639                     struct vcprop_tag end;
640           } vb;
641 
642           tag = VCPROPTAG_VCHIQ_INIT;
643 
644           VCPROP_INIT_REQUEST(vb);
645           VCPROP_INIT_TAG(vb.vbt_vchiq, tag);
646           vb.vbt_vchiq.base = *channelbasep;
647 
648           error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb, sizeof(vb), &res);
649           if (error)
650                     return error;
651 
652           if (!vcprop_buffer_success_p(&vb.vb_hdr) ||
653               !vcprop_tag_success_p(&vb.vbt_vchiq.tag)) {
654                     return EIO;
655           }
656           *channelbasep = vb.vbt_vchiq.base;
657 
658           return 0;
659 }
660 
661 int
rpi_notify_xhci_reset(uint32_t address)662 rpi_notify_xhci_reset(uint32_t address)
663 {
664           int error;
665           uint32_t tag, res;
666           struct __aligned(16) {
667                     struct vcprop_buffer_hdr      vb_hdr;
668                     struct vcprop_tag_notifyxhcireset       vbt_nhr;
669                     struct vcprop_tag end;
670           } vb;
671 
672           tag = VCPROPTAG_NOTIFY_XHCI_RESET;
673 
674           VCPROP_INIT_REQUEST(vb);
675           VCPROP_INIT_TAG(vb.vbt_nhr, tag);
676           vb.vbt_nhr.deviceaddress = address;
677 
678           error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb, sizeof(vb), &res);
679           if (error)
680                     return error;
681 
682           if (!vcprop_buffer_success_p(&vb.vb_hdr) ||
683               !vcprop_tag_success_p(&vb.vbt_nhr.tag)) {
684                     return EIO;
685           }
686 
687           return 0;
688 }
689 
690