Module Name:    src
Committed By:   macallan
Date:           Sun Sep 28 14:38:29 UTC 2014

Modified Files:
        src/sys/arch/evbarm/rpi: rpi_machdep.c vcprop.h
Added Files:
        src/sys/arch/evbarm/rpi: vcprop_subr.c

Log Message:
add hardware cursor support


To generate a diff of this commit:
cvs rdiff -u -r1.47 -r1.48 src/sys/arch/evbarm/rpi/rpi_machdep.c
cvs rdiff -u -r1.12 -r1.13 src/sys/arch/evbarm/rpi/vcprop.h
cvs rdiff -u -r0 -r1.1 src/sys/arch/evbarm/rpi/vcprop_subr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/evbarm/rpi/rpi_machdep.c
diff -u src/sys/arch/evbarm/rpi/rpi_machdep.c:1.47 src/sys/arch/evbarm/rpi/rpi_machdep.c:1.48
--- src/sys/arch/evbarm/rpi/rpi_machdep.c:1.47	Fri Sep 12 15:29:30 2014
+++ src/sys/arch/evbarm/rpi/rpi_machdep.c	Sun Sep 28 14:38:29 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: rpi_machdep.c,v 1.47 2014/09/12 15:29:30 jmcneill Exp $	*/
+/*	$NetBSD: rpi_machdep.c,v 1.48 2014/09/28 14:38:29 macallan Exp $	*/
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rpi_machdep.c,v 1.47 2014/09/12 15:29:30 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rpi_machdep.c,v 1.48 2014/09/28 14:38:29 macallan Exp $");
 
 #include "opt_evbarm_boardtype.h"
 #include "opt_ddb.h"
@@ -71,6 +71,7 @@ __KERNEL_RCSID(0, "$NetBSD: rpi_machdep.
 #include <arm/broadcom/bcm2835var.h>
 #include <arm/broadcom/bcm2835_pmvar.h>
 #include <arm/broadcom/bcm2835_mbox.h>
+#include <arm/broadcom/bcm_amba.h>
 
 #include <evbarm/rpi/vcio.h>
 #include <evbarm/rpi/vcpm.h>
@@ -376,16 +377,21 @@ static struct __aligned(16) {
 	},
 };
 
-int rpi_fb_set_video(int);
-int rpi_video_on = WSDISPLAYIO_VIDEO_ON;
-
 extern void bcmgenfb_set_console_dev(device_t dev);
 void bcmgenfb_set_ioctl(int(*)(void *, void *, u_long, void *, int, struct lwp *));
 extern void bcmgenfb_ddb_trap_callback(int where);
 static int	rpi_ioctl(void *, void *, u_long, void *, int, lwp_t *);
 
+int rpi_video_on = WSDISPLAYIO_VIDEO_ON;
+uint32_t hcursor = 0;
+bus_addr_t pcursor = 0;
+uint32_t *cmem = NULL;
+int cursor_x = 0, cursor_y = 0, hot_x = 0, hot_y = 0, cursor_on = 0;
+uint32_t cursor_cmap[4];
+uint8_t cursor_mask[8 * 64], cursor_bitmap[8 * 64];
 #endif
 
+
 static void
 rpi_bootparams(void)
 {
@@ -731,8 +737,10 @@ rpi_fb_get_edid_mode(uint32_t *pwidth, u
  *  - If "console=fb" is present, attach framebuffer to console.
  */
 static bool
-rpi_fb_init(prop_dictionary_t dict)
+rpi_fb_init(prop_dictionary_t dict, void *aux)
 {
+	struct amba_attach_args *aaa = aux;
+	bus_space_handle_t hc;
 	uint32_t width = 0, height = 0;
 	uint32_t res;
 	char *ptr;
@@ -818,49 +826,105 @@ rpi_fb_init(prop_dictionary_t dict)
 		prop_dictionary_set_uint32(dict, "wsdisplay_type", integer);
 	}
 
+	hcursor = rpi_alloc_mem(64 * 64 * 4, PAGE_SIZE,
+	    MEM_FLAG_L1_NONALLOCATING | MEM_FLAG_HINT_PERMALOCK);
+	pcursor = rpi_lock_mem(hcursor);
+#ifdef RPI_IOCTL_DEBUG
+	printf("hcursor: %08x\n", hcursor);
+	printf("pcursor: %08x\n", (uint32_t)pcursor);
+	printf("fb: %08x\n", (uint32_t)vb_setfb.vbt_allocbuf.address);
+#endif
+	if (bus_space_map(aaa->aaa_iot, pcursor, 64 * 64 * 4,
+	    BUS_SPACE_MAP_LINEAR|BUS_SPACE_MAP_PREFETCHABLE, &hc) != 0) {
+		printf("couldn't map cursor memory\n");
+	} else {
+		int i, j, k;
+
+		cmem = bus_space_vaddr(aaa->aaa_iot, hc);
+		k = 0;
+		for (j = 0; j < 64; j++) {
+			for (i = 0; i < 64; i++) {
+				cmem[i + k] = 
+				 ((i & 8) ^ (j & 8)) ? 0xa0ff0000 : 0xa00000ff;
+			}
+			k += 64;
+		}
+		cpu_dcache_wb_range(cmem, 64 * 64 * 4);
+		rpi_fb_initcursor(pcursor, 0, 0);
+	}	
+#ifdef RPI_IOCTL_DEBUG
+	rpi_fb_movecursor(600, 400, 1);
+#else
+	rpi_fb_movecursor(cursor_x, cursor_y, cursor_on);
+#endif
 	return true;
 }
 
-int
-rpi_fb_set_video(int b)
+static int
+rpi_fb_do_cursor(struct wsdisplay_cursor *cur)
 {
-	int error;
-	uint32_t res;
+	int pos = 0;
+	int shape = 0;
 
-	/*
-	 * might as well put it here since we need to re-init it every time
-	 * and it's not like this is going to be called very often anyway
-	 */
-	struct __aligned(16) {
-		struct vcprop_buffer_hdr	vb_hdr;
-		struct vcprop_tag_blankscreen	vbt_blank;
-		struct vcprop_tag end;
-	} vb_setblank =
-	{
-		.vb_hdr = {
-			.vpb_len = sizeof(vb_setblank),
-			.vpb_rcode = VCPROP_PROCESS_REQUEST,
-		},
-		.vbt_blank = {
-			.tag = {
-				.vpt_tag = VCPROPTAG_BLANK_SCREEN,
-				.vpt_len = VCPROPTAG_LEN(vb_setblank.vbt_blank),
-				.vpt_rcode = VCPROPTAG_REQUEST,
-			},
-			.state = (b != 0) ? VCPROP_BLANK_OFF : VCPROP_BLANK_ON,
-		},
-		.end = {
-			.vpt_tag = VCPROPTAG_NULL,
-		},
-	};
+	if (cur->which & WSDISPLAY_CURSOR_DOCUR) {
+		if (cursor_on != cur->enable) {
+			cursor_on = cur->enable;
+			pos = 1;
+		}
+	}
+	if (cur->which & WSDISPLAY_CURSOR_DOHOT) {
 
-	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setblank,
-	    sizeof(vb_setblank), &res);
-#ifdef RPI_IOCTL_DEBUG
-	printf("%s: %d %d %d %08x %08x\n", __func__, b,
-	    vb_setblank.vbt_blank.state, error, res, vb_setblank.vbt_blank.tag.vpt_rcode);
-#endif
-	return (error == 0);
+		hot_x = cur->hot.x;
+		hot_y = cur->hot.y;
+		pos = 1;
+		shape = 1;
+	}
+	if (cur->which & WSDISPLAY_CURSOR_DOPOS) {
+
+		cursor_x = cur->pos.x;
+		cursor_y = cur->pos.y;
+		pos = 1;
+	}
+	if (cur->which & WSDISPLAY_CURSOR_DOCMAP) {
+		int i;
+		uint32_t val;
+
+		for (i = 0; i < min(cur->cmap.count, 3); i++) {
+			val = (cur->cmap.red[i] << 16 ) |
+			      (cur->cmap.green[i] << 8) |
+			      (cur->cmap.blue[i] ) |
+			      0xff000000;
+			cursor_cmap[i + cur->cmap.index + 2] = val;
+		}
+		shape = 1;
+	}
+	if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) {
+
+		copyin(cur->mask, cursor_mask, 64 * 8);
+		copyin(cur->image, cursor_bitmap, 64 * 8);
+		shape = 1;
+	}
+	if (shape) {
+		int i, j, idx;
+		uint8_t mask;
+
+		for (i = 0; i < 64 * 8; i++) {
+			mask = 0x01;
+			for (j = 0; j < 8; j++) {
+				idx = ((cursor_mask[i] & mask) ? 2 : 0) |
+				    ((cursor_bitmap[i] & mask) ? 1 : 0);
+				cmem[i * 8 + j] = cursor_cmap[idx];
+				mask = mask << 1;
+			}
+		}
+		/* just in case */
+		cpu_dcache_wb_range(cmem, 64 * 64 * 4);
+		rpi_fb_initcursor(pcursor, hot_x, hot_y);
+	}
+	if (pos) {
+		rpi_fb_movecursor(cursor_x, cursor_y, cursor_on);
+	}
+	return 0;
 }
 
 static int
@@ -880,6 +944,37 @@ rpi_ioctl(void *v, void *vs, u_long cmd,
 	case WSDISPLAYIO_GVIDEO:
 		*(int *)data = rpi_video_on;
 		return 0;
+	case WSDISPLAYIO_GCURPOS:
+		{
+			struct wsdisplay_curpos *cp = (void *)data;
+
+			cp->x = cursor_x;
+			cp->y = cursor_y;
+		}
+		return 0;
+	case WSDISPLAYIO_SCURPOS:
+		{
+			struct wsdisplay_curpos *cp = (void *)data;
+
+			cursor_x = cp->x;
+			cursor_y = cp->y;
+			rpi_fb_movecursor(cursor_x, cursor_y, cursor_on);
+		}
+		return 0;
+	case WSDISPLAYIO_GCURMAX:
+		{
+			struct wsdisplay_curpos *cp = (void *)data;
+
+			cp->x = 64;
+			cp->y = 64;
+		}
+		return 0;
+	case WSDISPLAYIO_SCURSOR:
+		{
+			struct wsdisplay_cursor *cursor = (void *)data;
+
+			return rpi_fb_do_cursor(cursor);
+		}
 	default:
 		return EPASSTHROUGH;
 	}
@@ -942,7 +1037,7 @@ rpi_device_register(device_t dev, void *
 		db_trap_callback = bcmgenfb_ddb_trap_callback;
 #endif
 
-		if (rpi_fb_init(dict) == false)
+		if (rpi_fb_init(dict, aux) == false)
 			return;
 		if (get_bootconf_option(boot_args, "console",
 		    BOOTOPT_TYPE_STRING, &ptr) && strncmp(ptr, "fb", 2) == 0) {

Index: src/sys/arch/evbarm/rpi/vcprop.h
diff -u src/sys/arch/evbarm/rpi/vcprop.h:1.12 src/sys/arch/evbarm/rpi/vcprop.h:1.13
--- src/sys/arch/evbarm/rpi/vcprop.h:1.12	Sun Sep 28 12:57:22 2014
+++ src/sys/arch/evbarm/rpi/vcprop.h	Sun Sep 28 14:38:29 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: vcprop.h,v 1.12 2014/09/28 12:57:22 macallan Exp $	*/
+/*	$NetBSD: vcprop.h,v 1.13 2014/09/28 14:38:29 macallan Exp $	*/
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -287,7 +287,7 @@ struct vcprop_tag_cursorinfo {
 	struct vcprop_tag tag;
 	uint32_t width;
 	uint32_t height;
-	uint32_t __pad;		/* unused */
+	uint32_t format;
 	uint32_t pixels;	/* bus address in VC memory */
 	uint32_t hotspot_x;
 	uint32_t hotspot_y;
@@ -356,3 +356,13 @@ vcprop_tag_resplen(struct vcprop_tag *vp
 }
 
 #endif	/* _EVBARM_RPI_VCPROP_H_ */
+
+uint32_t rpi_alloc_mem(uint32_t, uint32_t, uint32_t);
+bus_addr_t rpi_lock_mem(uint32_t);
+int rpi_unlock_mem(uint32_t);
+int rpi_release_mem(uint32_t);
+
+int rpi_fb_set_video(int);
+
+int rpi_fb_movecursor(int, int, int);
+int rpi_fb_initcursor(bus_addr_t, int, int);

Added files:

Index: src/sys/arch/evbarm/rpi/vcprop_subr.c
diff -u /dev/null src/sys/arch/evbarm/rpi/vcprop_subr.c:1.1
--- /dev/null	Sun Sep 28 14:38:29 2014
+++ src/sys/arch/evbarm/rpi/vcprop_subr.c	Sun Sep 28 14:38:29 2014
@@ -0,0 +1,343 @@
+/*	$NetBSD: vcprop_subr.c,v 1.1 2014/09/28 14:38:29 macallan Exp $	*/
+
+/*
+ * Copyright (c) 2014 Michael Lorenz
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Mailbox property interface wrapper functions
+ */
+ 
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/bus.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <arm/arm32/machdep.h>
+
+#include <arm/broadcom/bcm2835reg.h>
+#include <arm/broadcom/bcm2835var.h>
+#include <arm/broadcom/bcm2835_pmvar.h>
+#include <arm/broadcom/bcm2835_mbox.h>
+
+#include <evbarm/rpi/vcio.h>
+#include <evbarm/rpi/vcpm.h>
+#include <evbarm/rpi/vcprop.h>
+
+#include <evbarm/rpi/rpi.h>
+
+#include <dev/wscons/wsconsio.h>
+
+int
+rpi_fb_set_video(int b)
+{
+	int error;
+	uint32_t res;
+
+	/*
+	 * might as well put it here since we need to re-init it every time
+	 * and it's not like this is going to be called very often anyway
+	 */
+	struct __aligned(16) {
+		struct vcprop_buffer_hdr	vb_hdr;
+		struct vcprop_tag_blankscreen	vbt_blank;
+		struct vcprop_tag end;
+	} vb_setblank =
+	{
+		.vb_hdr = {
+			.vpb_len = sizeof(vb_setblank),
+			.vpb_rcode = VCPROP_PROCESS_REQUEST,
+		},
+		.vbt_blank = {
+			.tag = {
+				.vpt_tag = VCPROPTAG_BLANK_SCREEN,
+				.vpt_len = VCPROPTAG_LEN(vb_setblank.vbt_blank),
+				.vpt_rcode = VCPROPTAG_REQUEST,
+			},
+			.state = (b != 0) ? VCPROP_BLANK_OFF : VCPROP_BLANK_ON,
+		},
+		.end = {
+			.vpt_tag = VCPROPTAG_NULL,
+		},
+	};
+
+	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setblank,
+	    sizeof(vb_setblank), &res);
+#ifdef RPI_IOCTL_DEBUG
+	printf("%s: %d %d %d %08x %08x\n", __func__, b,
+	    vb_setblank.vbt_blank.state, error, res,
+	    vb_setblank.vbt_blank.tag.vpt_rcode);
+#endif
+	return (error == 0);
+}
+
+uint32_t
+rpi_alloc_mem(uint32_t size, uint32_t align, uint32_t flags)
+{
+	int error;
+	uint32_t res;
+
+	struct __aligned(16) {
+		struct vcprop_buffer_hdr	vb_hdr;
+		struct vcprop_tag_allocmem	vbt_am;
+		struct vcprop_tag end;
+	} vb_allocmem =
+	{
+		.vb_hdr = {
+			.vpb_len = sizeof(vb_allocmem),
+			.vpb_rcode = VCPROP_PROCESS_REQUEST,
+		},
+		.vbt_am = {
+			.tag = {
+				.vpt_tag = VCPROPTAG_ALLOCMEM,
+				.vpt_len = VCPROPTAG_LEN(vb_allocmem.vbt_am),
+				.vpt_rcode = VCPROPTAG_REQUEST,
+			},
+			.size = size,
+			.align = align,
+			.flags = flags,
+		},
+		.end = {
+			.vpt_tag = VCPROPTAG_NULL,
+		},
+	};
+
+	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_allocmem,
+	    sizeof(vb_allocmem), &res);
+#ifdef RPI_IOCTL_DEBUG
+	printf("%s: %d %d %08x %08x\n", __func__,
+	    vb_allocmem.vbt_am.size, error, res,
+	    vb_allocmem.vbt_am.tag.vpt_rcode);
+#endif
+	if (error == 0)
+		return vb_allocmem.vbt_am.size;
+	return 0;
+}
+
+bus_addr_t
+rpi_lock_mem(uint32_t handle)
+{
+	int error;
+	uint32_t res;
+
+	struct __aligned(16) {
+		struct vcprop_buffer_hdr	vb_hdr;
+		struct vcprop_tag_lockmem	vbt_lm;
+		struct vcprop_tag end;
+	} vb_lockmem =
+	{
+		.vb_hdr = {
+			.vpb_len = sizeof(vb_lockmem),
+			.vpb_rcode = VCPROP_PROCESS_REQUEST,
+		},
+		.vbt_lm = {
+			.tag = {
+				.vpt_tag = VCPROPTAG_LOCKMEM,
+				.vpt_len = VCPROPTAG_LEN(vb_lockmem.vbt_lm),
+				.vpt_rcode = VCPROPTAG_REQUEST,
+			},
+			.handle = handle,
+		},
+		.end = {
+			.vpt_tag = VCPROPTAG_NULL,
+		},
+	};
+
+	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_lockmem,
+	    sizeof(vb_lockmem), &res);
+#ifdef RPI_IOCTL_DEBUG
+	printf("%s: %d %d %08x %08x\n", __func__,
+	    vb_lockmem.vbt_lm.handle, error, res,
+	    vb_lockmem.vbt_lm.tag.vpt_rcode);
+#endif
+	if (error == 0)
+		return (vb_lockmem.vbt_lm.handle /*& 0x3fffffff*/);
+	return 0;
+}
+
+int
+rpi_unlock_mem(uint32_t handle)
+{
+	int error;
+	uint32_t res;
+
+	struct __aligned(16) {
+		struct vcprop_buffer_hdr	vb_hdr;
+		struct vcprop_tag_lockmem	vbt_lm;
+		struct vcprop_tag end;
+	} vb_unlockmem =
+	{
+		.vb_hdr = {
+			.vpb_len = sizeof(vb_unlockmem),
+			.vpb_rcode = VCPROP_PROCESS_REQUEST,
+		},
+		.vbt_lm = {
+			.tag = {
+				.vpt_tag = VCPROPTAG_UNLOCKMEM,
+				.vpt_len = VCPROPTAG_LEN(vb_unlockmem.vbt_lm),
+				.vpt_rcode = VCPROPTAG_REQUEST,
+			},
+			.handle = handle,
+		},
+		.end = {
+			.vpt_tag = VCPROPTAG_NULL,
+		},
+	};
+
+	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_unlockmem,
+	    sizeof(vb_unlockmem), &res);
+#ifdef RPI_IOCTL_DEBUG
+	printf("%s: %d %d %08x %08x\n", __func__,
+	    vb_unlockmem.vbt_lm.handle, error, res,
+	    vb_unlockmem.vbt_lm.tag.vpt_rcode);
+#endif
+	return (error == 0);
+}
+
+int
+rpi_release_mem(uint32_t handle)
+{
+	int error;
+	uint32_t res;
+
+	struct __aligned(16) {
+		struct vcprop_buffer_hdr	vb_hdr;
+		struct vcprop_tag_lockmem	vbt_lm;
+		struct vcprop_tag end;
+	} vb_releasemem =
+	{
+		.vb_hdr = {
+			.vpb_len = sizeof(vb_releasemem),
+			.vpb_rcode = VCPROP_PROCESS_REQUEST,
+		},
+		.vbt_lm = {
+			.tag = {
+				.vpt_tag = VCPROPTAG_RELEASEMEM,
+				.vpt_len = VCPROPTAG_LEN(vb_releasemem.vbt_lm),
+				.vpt_rcode = VCPROPTAG_REQUEST,
+			},
+			.handle = handle,
+		},
+		.end = {
+			.vpt_tag = VCPROPTAG_NULL,
+		},
+	};
+
+	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_releasemem,
+	    sizeof(vb_releasemem), &res);
+#ifdef RPI_IOCTL_DEBUG
+	printf("%s: %d %d %08x %08x\n", __func__,
+	    vb_releasemem.vbt_lm.handle, error, res,
+	    vb_releasemem.vbt_lm.tag.vpt_rcode);
+#endif
+	return (error == 0);
+}
+
+int
+rpi_fb_movecursor(int x, int y, int on)
+{
+	int error;
+	uint32_t res;
+
+	struct __aligned(16) {
+		struct vcprop_buffer_hdr	vb_hdr;
+		struct vcprop_tag_cursorstate	vbt_cs;
+		struct vcprop_tag end;
+	} vb_cursorstate =
+	{
+		.vb_hdr = {
+			.vpb_len = sizeof(vb_cursorstate),
+			.vpb_rcode = VCPROP_PROCESS_REQUEST,
+		},
+		.vbt_cs = {
+			.tag = {
+				.vpt_tag = VCPROPTAG_SET_CURSOR_STATE,
+				.vpt_len = VCPROPTAG_LEN(vb_cursorstate.vbt_cs),
+				.vpt_rcode = VCPROPTAG_REQUEST,
+			},
+			.enable = (on != 0) ? 1 : 0,
+			.x = x,
+			.y = y,
+			.flags = 1,
+		},
+		.end = {
+			.vpt_tag = VCPROPTAG_NULL,
+		},
+	};
+
+	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_cursorstate,
+	    sizeof(vb_cursorstate), &res);
+#ifdef RPI_IOCTL_DEBUG
+	printf("%s: %08x %d %08x %08x\n", __func__,
+	    vb_cursorstate.vbt_cs.enable, error, res,
+	    vb_cursorstate.vbt_cs.tag.vpt_rcode);
+#endif
+	return (error == 0);
+}
+
+int
+rpi_fb_initcursor(bus_addr_t pixels, int hx, int hy)
+{
+	int error;
+	uint32_t res;
+	
+
+	struct __aligned(16) {
+		struct vcprop_buffer_hdr	vb_hdr;
+		struct vcprop_tag_cursorinfo	vbt_ci;
+		struct vcprop_tag end;
+	} vb_cursorinfo =
+	{
+		.vb_hdr = {
+			.vpb_len = sizeof(vb_cursorinfo),
+			.vpb_rcode = VCPROP_PROCESS_REQUEST,
+		},
+		.vbt_ci = {
+			.tag = {
+				.vpt_tag = VCPROPTAG_SET_CURSOR_INFO,
+				.vpt_len = VCPROPTAG_LEN(vb_cursorinfo.vbt_ci),
+				.vpt_rcode = VCPROPTAG_REQUEST,
+			},
+			.width = 64,
+			.height = 64,
+			.format = 0,
+			.pixels = pixels,
+			.hotspot_x = hx,
+			.hotspot_y = hy,
+		},
+		.end = {
+			.vpt_tag = VCPROPTAG_NULL,
+		},
+	};
+
+	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_cursorinfo,
+	    sizeof(vb_cursorinfo), &res);
+#ifdef RPI_IOCTL_DEBUG
+	printf("%s: %d %d %08x %08x\n", __func__,
+	    vb_cursorinfo.vbt_ci.width, error, res,
+	    vb_cursorinfo.vbt_ci.tag.vpt_rcode);
+#endif
+	return (error == 0);
+}

Reply via email to