xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/vboxvideo/hgsmi_base.c (revision 41ec02673d281bbb3d38e6c78504ce6e30c228c1)
1 /*	$NetBSD: hgsmi_base.c,v 1.2 2021/12/18 23:45:44 riastradh Exp $	*/
2 
3 // SPDX-License-Identifier: MIT
4 /* Copyright (C) 2006-2017 Oracle Corporation */
5 
6 #include <sys/cdefs.h>
7 __KERNEL_RCSID(0, "$NetBSD: hgsmi_base.c,v 1.2 2021/12/18 23:45:44 riastradh Exp $");
8 
9 #include <linux/vbox_err.h>
10 #include "vbox_drv.h"
11 #include "vboxvideo_guest.h"
12 #include "vboxvideo_vbe.h"
13 #include "hgsmi_channels.h"
14 #include "hgsmi_ch_setup.h"
15 
16 /**
17  * Inform the host of the location of the host flags in VRAM via an HGSMI cmd.
18  * Return: 0 or negative errno value.
19  * @ctx:        The context of the guest heap to use.
20  * @location:   The offset chosen for the flags within guest VRAM.
21  */
hgsmi_report_flags_location(struct gen_pool * ctx,u32 location)22 int hgsmi_report_flags_location(struct gen_pool *ctx, u32 location)
23 {
24 	struct hgsmi_buffer_location *p;
25 
26 	p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_HGSMI,
27 			       HGSMI_CC_HOST_FLAGS_LOCATION);
28 	if (!p)
29 		return -ENOMEM;
30 
31 	p->buf_location = location;
32 	p->buf_len = sizeof(struct hgsmi_host_flags);
33 
34 	hgsmi_buffer_submit(ctx, p);
35 	hgsmi_buffer_free(ctx, p);
36 
37 	return 0;
38 }
39 
40 /**
41  * Notify the host of HGSMI-related guest capabilities via an HGSMI command.
42  * Return: 0 or negative errno value.
43  * @ctx:        The context of the guest heap to use.
44  * @caps:       The capabilities to report, see vbva_caps.
45  */
hgsmi_send_caps_info(struct gen_pool * ctx,u32 caps)46 int hgsmi_send_caps_info(struct gen_pool *ctx, u32 caps)
47 {
48 	struct vbva_caps *p;
49 
50 	p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA, VBVA_INFO_CAPS);
51 	if (!p)
52 		return -ENOMEM;
53 
54 	p->rc = VERR_NOT_IMPLEMENTED;
55 	p->caps = caps;
56 
57 	hgsmi_buffer_submit(ctx, p);
58 
59 	WARN_ON_ONCE(p->rc < 0);
60 
61 	hgsmi_buffer_free(ctx, p);
62 
63 	return 0;
64 }
65 
hgsmi_test_query_conf(struct gen_pool * ctx)66 int hgsmi_test_query_conf(struct gen_pool *ctx)
67 {
68 	u32 value = 0;
69 	int ret;
70 
71 	ret = hgsmi_query_conf(ctx, U32_MAX, &value);
72 	if (ret)
73 		return ret;
74 
75 	return value == U32_MAX ? 0 : -EIO;
76 }
77 
78 /**
79  * Query the host for an HGSMI configuration parameter via an HGSMI command.
80  * Return: 0 or negative errno value.
81  * @ctx:        The context containing the heap used.
82  * @index:      The index of the parameter to query.
83  * @value_ret:  Where to store the value of the parameter on success.
84  */
hgsmi_query_conf(struct gen_pool * ctx,u32 index,u32 * value_ret)85 int hgsmi_query_conf(struct gen_pool *ctx, u32 index, u32 *value_ret)
86 {
87 	struct vbva_conf32 *p;
88 
89 	p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA,
90 			       VBVA_QUERY_CONF32);
91 	if (!p)
92 		return -ENOMEM;
93 
94 	p->index = index;
95 	p->value = U32_MAX;
96 
97 	hgsmi_buffer_submit(ctx, p);
98 
99 	*value_ret = p->value;
100 
101 	hgsmi_buffer_free(ctx, p);
102 
103 	return 0;
104 }
105 
106 /**
107  * Pass the host a new mouse pointer shape via an HGSMI command.
108  * Return: 0 or negative errno value.
109  * @ctx:        The context containing the heap to be used.
110  * @flags:      Cursor flags.
111  * @hot_x:      Horizontal position of the hot spot.
112  * @hot_y:      Vertical position of the hot spot.
113  * @width:      Width in pixels of the cursor.
114  * @height:     Height in pixels of the cursor.
115  * @pixels:     Pixel data, @see VMMDevReqMousePointer for the format.
116  * @len:        Size in bytes of the pixel data.
117  */
hgsmi_update_pointer_shape(struct gen_pool * ctx,u32 flags,u32 hot_x,u32 hot_y,u32 width,u32 height,u8 * pixels,u32 len)118 int hgsmi_update_pointer_shape(struct gen_pool *ctx, u32 flags,
119 			       u32 hot_x, u32 hot_y, u32 width, u32 height,
120 			       u8 *pixels, u32 len)
121 {
122 	struct vbva_mouse_pointer_shape *p;
123 	u32 pixel_len = 0;
124 	int rc;
125 
126 	if (flags & VBOX_MOUSE_POINTER_SHAPE) {
127 		/*
128 		 * Size of the pointer data:
129 		 * sizeof (AND mask) + sizeof (XOR_MASK)
130 		 */
131 		pixel_len = ((((width + 7) / 8) * height + 3) & ~3) +
132 			 width * 4 * height;
133 		if (pixel_len > len)
134 			return -EINVAL;
135 
136 		/*
137 		 * If shape is supplied, then always create the pointer visible.
138 		 * See comments in 'vboxUpdatePointerShape'
139 		 */
140 		flags |= VBOX_MOUSE_POINTER_VISIBLE;
141 	}
142 
143 	p = hgsmi_buffer_alloc(ctx, sizeof(*p) + pixel_len, HGSMI_CH_VBVA,
144 			       VBVA_MOUSE_POINTER_SHAPE);
145 	if (!p)
146 		return -ENOMEM;
147 
148 	p->result = VINF_SUCCESS;
149 	p->flags = flags;
150 	p->hot_X = hot_x;
151 	p->hot_y = hot_y;
152 	p->width = width;
153 	p->height = height;
154 	if (pixel_len)
155 		memcpy(p->data, pixels, pixel_len);
156 
157 	hgsmi_buffer_submit(ctx, p);
158 
159 	switch (p->result) {
160 	case VINF_SUCCESS:
161 		rc = 0;
162 		break;
163 	case VERR_NO_MEMORY:
164 		rc = -ENOMEM;
165 		break;
166 	case VERR_NOT_SUPPORTED:
167 		rc = -EBUSY;
168 		break;
169 	default:
170 		rc = -EINVAL;
171 	}
172 
173 	hgsmi_buffer_free(ctx, p);
174 
175 	return rc;
176 }
177 
178 /**
179  * Report the guest cursor position.  The host may wish to use this information
180  * to re-position its own cursor (though this is currently unlikely).  The
181  * current host cursor position is returned.
182  * Return: 0 or negative errno value.
183  * @ctx:              The context containing the heap used.
184  * @report_position:  Are we reporting a position?
185  * @x:                Guest cursor X position.
186  * @y:                Guest cursor Y position.
187  * @x_host:           Host cursor X position is stored here.  Optional.
188  * @y_host:           Host cursor Y position is stored here.  Optional.
189  */
hgsmi_cursor_position(struct gen_pool * ctx,bool report_position,u32 x,u32 y,u32 * x_host,u32 * y_host)190 int hgsmi_cursor_position(struct gen_pool *ctx, bool report_position,
191 			  u32 x, u32 y, u32 *x_host, u32 *y_host)
192 {
193 	struct vbva_cursor_position *p;
194 
195 	p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA,
196 			       VBVA_CURSOR_POSITION);
197 	if (!p)
198 		return -ENOMEM;
199 
200 	p->report_position = report_position;
201 	p->x = x;
202 	p->y = y;
203 
204 	hgsmi_buffer_submit(ctx, p);
205 
206 	*x_host = p->x;
207 	*y_host = p->y;
208 
209 	hgsmi_buffer_free(ctx, p);
210 
211 	return 0;
212 }
213