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