]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/staging/vboxvideo/hgsmi_base.c
Merge tag 'for-linus-20170812' of git://git.infradead.org/linux-mtd
[karo-tx-linux.git] / drivers / staging / vboxvideo / hgsmi_base.c
1 /*
2  * Copyright (C) 2006-2017 Oracle Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  */
22
23 #include "vbox_drv.h"
24 #include "vbox_err.h"
25 #include "vboxvideo_guest.h"
26 #include "vboxvideo_vbe.h"
27 #include "hgsmi_channels.h"
28 #include "hgsmi_ch_setup.h"
29
30 /**
31  * Inform the host of the location of the host flags in VRAM via an HGSMI cmd.
32  * @param    ctx          the context of the guest heap to use.
33  * @param    location     the offset chosen for the flags within guest VRAM.
34  * @returns 0 on success, -errno on failure
35  */
36 int hgsmi_report_flags_location(struct gen_pool *ctx, u32 location)
37 {
38         struct hgsmi_buffer_location *p;
39
40         p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_HGSMI,
41                                HGSMI_CC_HOST_FLAGS_LOCATION);
42         if (!p)
43                 return -ENOMEM;
44
45         p->buf_location = location;
46         p->buf_len = sizeof(struct hgsmi_host_flags);
47
48         hgsmi_buffer_submit(ctx, p);
49         hgsmi_buffer_free(ctx, p);
50
51         return 0;
52 }
53
54 /**
55  * Notify the host of HGSMI-related guest capabilities via an HGSMI command.
56  * @param    ctx                 the context of the guest heap to use.
57  * @param    caps                the capabilities to report, see vbva_caps.
58  * @returns 0 on success, -errno on failure
59  */
60 int hgsmi_send_caps_info(struct gen_pool *ctx, u32 caps)
61 {
62         struct vbva_caps *p;
63
64         p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA, VBVA_INFO_CAPS);
65         if (!p)
66                 return -ENOMEM;
67
68         p->rc = VERR_NOT_IMPLEMENTED;
69         p->caps = caps;
70
71         hgsmi_buffer_submit(ctx, p);
72
73         WARN_ON_ONCE(RT_FAILURE(p->rc));
74
75         hgsmi_buffer_free(ctx, p);
76
77         return 0;
78 }
79
80 int hgsmi_test_query_conf(struct gen_pool *ctx)
81 {
82         u32 value = 0;
83         int ret;
84
85         ret = hgsmi_query_conf(ctx, U32_MAX, &value);
86         if (ret)
87                 return ret;
88
89         return value == U32_MAX ? 0 : -EIO;
90 }
91
92 /**
93  * Query the host for an HGSMI configuration parameter via an HGSMI command.
94  * @param  ctx        the context containing the heap used
95  * @param  index      the index of the parameter to query,
96  *                    @see vbva_conf32::index
97  * @param  value_ret  where to store the value of the parameter on success
98  * @returns 0 on success, -errno on failure
99  */
100 int hgsmi_query_conf(struct gen_pool *ctx, u32 index, u32 *value_ret)
101 {
102         struct vbva_conf32 *p;
103
104         p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA,
105                                VBVA_QUERY_CONF32);
106         if (!p)
107                 return -ENOMEM;
108
109         p->index = index;
110         p->value = U32_MAX;
111
112         hgsmi_buffer_submit(ctx, p);
113
114         *value_ret = p->value;
115
116         hgsmi_buffer_free(ctx, p);
117
118         return 0;
119 }
120
121 /**
122  * Pass the host a new mouse pointer shape via an HGSMI command.
123  *
124  * @param  ctx      the context containing the heap to be used
125  * @param  flags    cursor flags, @see VMMDevReqMousePointer::flags
126  * @param  hot_x    horizontal position of the hot spot
127  * @param  hot_y    vertical position of the hot spot
128  * @param  width    width in pixels of the cursor
129  * @param  height   height in pixels of the cursor
130  * @param  pixels   pixel data, @see VMMDevReqMousePointer for the format
131  * @param  len      size in bytes of the pixel data
132  * @returns 0 on success, -errno on failure
133  */
134 int hgsmi_update_pointer_shape(struct gen_pool *ctx, u32 flags,
135                                u32 hot_x, u32 hot_y, u32 width, u32 height,
136                                u8 *pixels, u32 len)
137 {
138         struct vbva_mouse_pointer_shape *p;
139         u32 pixel_len = 0;
140         int rc;
141
142         if (flags & VBOX_MOUSE_POINTER_SHAPE) {
143                 /*
144                  * Size of the pointer data:
145                  * sizeof (AND mask) + sizeof (XOR_MASK)
146                  */
147                 pixel_len = ((((width + 7) / 8) * height + 3) & ~3) +
148                          width * 4 * height;
149                 if (pixel_len > len)
150                         return -EINVAL;
151
152                 /*
153                  * If shape is supplied, then always create the pointer visible.
154                  * See comments in 'vboxUpdatePointerShape'
155                  */
156                 flags |= VBOX_MOUSE_POINTER_VISIBLE;
157         }
158
159         p = hgsmi_buffer_alloc(ctx, sizeof(*p) + pixel_len, HGSMI_CH_VBVA,
160                                VBVA_MOUSE_POINTER_SHAPE);
161         if (!p)
162                 return -ENOMEM;
163
164         p->result = VINF_SUCCESS;
165         p->flags = flags;
166         p->hot_X = hot_x;
167         p->hot_y = hot_y;
168         p->width = width;
169         p->height = height;
170         if (pixel_len)
171                 memcpy(p->data, pixels, pixel_len);
172
173         hgsmi_buffer_submit(ctx, p);
174
175         switch (p->result) {
176         case VINF_SUCCESS:
177                 rc = 0;
178                 break;
179         case VERR_NO_MEMORY:
180                 rc = -ENOMEM;
181                 break;
182         case VERR_NOT_SUPPORTED:
183                 rc = -EBUSY;
184                 break;
185         default:
186                 rc = -EINVAL;
187         }
188
189         hgsmi_buffer_free(ctx, p);
190
191         return rc;
192 }
193
194 /**
195  * Report the guest cursor position.  The host may wish to use this information
196  * to re-position its own cursor (though this is currently unlikely).  The
197  * current host cursor position is returned.
198  * @param  ctx              The context containing the heap used.
199  * @param  report_position  Are we reporting a position?
200  * @param  x                Guest cursor X position.
201  * @param  y                Guest cursor Y position.
202  * @param  x_host           Host cursor X position is stored here.  Optional.
203  * @param  y_host           Host cursor Y position is stored here.  Optional.
204  * @returns 0 on success, -errno on failure
205  */
206 int hgsmi_cursor_position(struct gen_pool *ctx, bool report_position,
207                           u32 x, u32 y, u32 *x_host, u32 *y_host)
208 {
209         struct vbva_cursor_position *p;
210
211         p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA,
212                                VBVA_CURSOR_POSITION);
213         if (!p)
214                 return -ENOMEM;
215
216         p->report_position = report_position;
217         p->x = x;
218         p->y = y;
219
220         hgsmi_buffer_submit(ctx, p);
221
222         *x_host = p->x;
223         *y_host = p->y;
224
225         hgsmi_buffer_free(ctx, p);
226
227         return 0;
228 }
229
230 /**
231  * @todo Mouse pointer position to be read from VMMDev memory, address of the
232  * memory region can be queried from VMMDev via an IOCTL. This VMMDev memory
233  * region will contain host information which is needed by the guest.
234  *
235  * Reading will not cause a switch to the host.
236  *
237  * Have to take into account:
238  *  * synchronization: host must write to the memory only from EMT,
239  *    large structures must be read under flag, which tells the host
240  *    that the guest is currently reading the memory (OWNER flag?).
241  *  * guest writes: may be allocate a page for the host info and make
242  *    the page readonly for the guest.
243  *  * the information should be available only for additions drivers.
244  *  * VMMDev additions driver will inform the host which version of the info
245  *    it expects, host must support all versions.
246  */