xref: /netbsd-src/sys/arch/evbarm/rpi/vcprop_subr.c (revision fd9b697d9c834c84bcd0e32d1c314b466a1cd21a)
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