1 /*
2  * Copyright (C) 2016 EPAM Systems Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; version 2.1 only. with the special
7  * exception on linking described in file LICENSE.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU Lesser General Public License for more details.
13  */
14 
15 #include "libxl_internal.h"
16 
libxl__device_vdispl_setdefault(libxl__gc * gc,uint32_t domid,libxl_device_vdispl * vdispl,bool hotplug)17 static int libxl__device_vdispl_setdefault(libxl__gc *gc, uint32_t domid,
18                                            libxl_device_vdispl *vdispl,
19                                            bool hotplug)
20 {
21     return libxl__resolve_domid(gc, vdispl->backend_domname,
22                                 &vdispl->backend_domid);
23 }
24 
libxl__device_from_vdispl(libxl__gc * gc,uint32_t domid,libxl_device_vdispl * vdispl,libxl__device * device)25 static int libxl__device_from_vdispl(libxl__gc *gc, uint32_t domid,
26                                      libxl_device_vdispl *vdispl,
27                                      libxl__device *device)
28 {
29    device->backend_devid   = vdispl->devid;
30    device->backend_domid   = vdispl->backend_domid;
31    device->backend_kind    = LIBXL__DEVICE_KIND_VDISPL;
32    device->devid           = vdispl->devid;
33    device->domid           = domid;
34    device->kind            = LIBXL__DEVICE_KIND_VDISPL;
35 
36    return 0;
37 }
38 
libxl__vdispl_from_xenstore(libxl__gc * gc,const char * libxl_path,libxl_devid devid,libxl_device_vdispl * vdispl)39 static int libxl__vdispl_from_xenstore(libxl__gc *gc, const char *libxl_path,
40                                        libxl_devid devid,
41                                        libxl_device_vdispl *vdispl)
42 {
43     const char *be_path;
44     int rc;
45 
46     vdispl->devid = devid;
47     rc = libxl__xs_read_mandatory(gc, XBT_NULL,
48                                   GCSPRINTF("%s/backend", libxl_path),
49                                   &be_path);
50     if (rc) return rc;
51 
52     return libxl__backendpath_parse_domid(gc, be_path, &vdispl->backend_domid);
53 }
54 
libxl__update_config_vdispl(libxl__gc * gc,libxl_device_vdispl * dst,libxl_device_vdispl * src)55 static void libxl__update_config_vdispl(libxl__gc *gc,
56                                         libxl_device_vdispl *dst,
57                                         libxl_device_vdispl *src)
58 {
59     dst->devid = src->devid;
60     dst->be_alloc = src->be_alloc;
61 }
62 
libxl_device_vdispl_compare(libxl_device_vdispl * d1,libxl_device_vdispl * d2)63 static int libxl_device_vdispl_compare(libxl_device_vdispl *d1,
64                                        libxl_device_vdispl *d2)
65 {
66     return COMPARE_DEVID(d1, d2);
67 }
68 
libxl__device_vdispl_add(libxl__egc * egc,uint32_t domid,libxl_device_vdispl * vdispl,libxl__ao_device * aodev)69 static void libxl__device_vdispl_add(libxl__egc *egc, uint32_t domid,
70                                      libxl_device_vdispl *vdispl,
71                                      libxl__ao_device *aodev)
72 {
73     libxl__device_add_async(egc, domid, &libxl__vdispl_devtype, vdispl, aodev);
74 }
75 
libxl__set_xenstore_vdispl(libxl__gc * gc,uint32_t domid,libxl_device_vdispl * vdispl,flexarray_t * back,flexarray_t * front,flexarray_t * ro_front)76 static int libxl__set_xenstore_vdispl(libxl__gc *gc, uint32_t domid,
77                                       libxl_device_vdispl *vdispl,
78                                       flexarray_t *back, flexarray_t *front,
79                                       flexarray_t *ro_front)
80 {
81     int i;
82 
83     flexarray_append_pair(ro_front, "be-alloc",
84                           GCSPRINTF("%d", vdispl->be_alloc));
85 
86     for (i = 0; i < vdispl->num_connectors; i++) {
87         flexarray_append_pair(ro_front, GCSPRINTF("%d/resolution", i),
88                               GCSPRINTF("%dx%d", vdispl->connectors[i].width,
89                                                  vdispl->connectors[i].height));
90         flexarray_append_pair(ro_front, GCSPRINTF("%d/id", i),
91                               vdispl->connectors[i].id);
92     }
93 
94     return 0;
95 }
96 
libxl__device_vdispl_getconnectors(libxl_ctx * ctx,const char * path,libxl_vdisplinfo * info)97 static int libxl__device_vdispl_getconnectors(libxl_ctx *ctx,
98                                               const char *path,
99                                               libxl_vdisplinfo *info)
100 {
101     GC_INIT(ctx);
102     char *connector = NULL;
103     char *connector_path;
104     int i, rc;
105 
106     info->num_connectors = 0;
107 
108     connector_path = GCSPRINTF("%s/%d", path, info->num_connectors);
109 
110     while ((connector = xs_read(ctx->xsh, XBT_NULL, connector_path, NULL)) !=
111            NULL) {
112         free(connector);
113         connector_path = GCSPRINTF("%s/%d", path, ++info->num_connectors);
114     }
115 
116     info->connectors = libxl__calloc(NOGC, info->num_connectors,
117                                      sizeof(*info->connectors));
118 
119     for (i = 0; i < info->num_connectors; i++) {
120         char *value;
121         char *value_path;
122 
123         value_path = GCSPRINTF("%s/%d/id", path, i);
124         info->connectors[i].id = xs_read(ctx->xsh, XBT_NULL, value_path, NULL);
125         if (info->connectors[i].id == NULL) { rc = ERROR_FAIL; goto out; }
126 
127         value_path = GCSPRINTF("%s/%d/resolution", path, i);
128         value = xs_read(ctx->xsh, XBT_NULL, value_path, NULL);
129         if (value == NULL) { rc = ERROR_FAIL; goto out; }
130 
131         rc = sscanf(value, "%ux%u", &info->connectors[i].width,
132                     &info->connectors[i].height);
133         free(value);
134 
135         if (rc != 2) {
136             rc = ERROR_FAIL; goto out;
137         }
138 
139         value_path = GCSPRINTF("%s/%d/req-ring-ref", path, i);
140         value = xs_read(ctx->xsh, XBT_NULL, value_path, NULL);
141         info->connectors[i].req_rref = value ? strtoul(value, NULL, 10) : -1;
142         free(value);
143 
144         value_path = GCSPRINTF("%s/%d/req-event-channel", path, i);
145         value = xs_read(ctx->xsh, XBT_NULL, value_path, NULL);
146         info->connectors[i].req_evtch = value ? strtoul(value, NULL, 10) : -1;
147         free(value);
148 
149         value_path = GCSPRINTF("%s/%d/evt-ring-ref", path, i);
150         value = xs_read(ctx->xsh, XBT_NULL, value_path, NULL);
151         info->connectors[i].evt_rref = value ? strtoul(value, NULL, 10) : -1;
152         free(value);
153 
154         value_path = GCSPRINTF("%s/%d/evt-event-channel", path, i);
155         value = xs_read(ctx->xsh, XBT_NULL, value_path, NULL);
156         info->connectors[i].evt_evtch = value ? strtoul(value, NULL, 10) : -1;
157         free(value);
158     }
159 
160     rc = 0;
161 
162 out:
163     return rc;
164 }
165 
libxl_device_vdispl_getinfo(libxl_ctx * ctx,uint32_t domid,libxl_device_vdispl * vdispl,libxl_vdisplinfo * info)166 int libxl_device_vdispl_getinfo(libxl_ctx *ctx, uint32_t domid,
167                                 libxl_device_vdispl *vdispl,
168                                 libxl_vdisplinfo *info)
169 {
170     GC_INIT(ctx);
171     char *libxl_path, *dompath, *devpath;
172     char *val;
173     int rc;
174 
175     libxl_vdisplinfo_init(info);
176     dompath = libxl__xs_get_dompath(gc, domid);
177     info->devid = vdispl->devid;
178 
179     devpath = GCSPRINTF("%s/device/vdispl/%d", dompath, info->devid);
180     libxl_path = GCSPRINTF("%s/device/vdispl/%d",
181                            libxl__xs_libxl_path(gc, domid),
182                            info->devid);
183     info->backend = xs_read(ctx->xsh, XBT_NULL,
184                             GCSPRINTF("%s/backend", libxl_path),
185                             NULL);
186     if (!info->backend) { rc = ERROR_FAIL; goto out; }
187 
188     rc = libxl__backendpath_parse_domid(gc, info->backend, &info->backend_id);
189     if (rc) goto out;
190 
191     val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", devpath));
192     info->state = val ? strtoul(val, NULL, 10) : -1;
193 
194     info->frontend = xs_read(ctx->xsh, XBT_NULL,
195                              GCSPRINTF("%s/frontend", libxl_path),
196                              NULL);
197     info->frontend_id = domid;
198 
199     val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/be-alloc", devpath));
200     info->be_alloc = val ? strtoul(val, NULL, 10) : 0;
201 
202     rc = libxl__device_vdispl_getconnectors(ctx, devpath, info);
203     if (rc) goto out;
204 
205     rc = 0;
206 
207 out:
208      GC_FREE;
209      return rc;
210 }
211 
libxl_devid_to_device_vdispl(libxl_ctx * ctx,uint32_t domid,int devid,libxl_device_vdispl * vdispl)212 int libxl_devid_to_device_vdispl(libxl_ctx *ctx, uint32_t domid,
213                                  int devid, libxl_device_vdispl *vdispl)
214 {
215     GC_INIT(ctx);
216 
217     libxl_device_vdispl *vdispls = NULL;
218     int n, i;
219     int rc;
220 
221     libxl_device_vdispl_init(vdispl);
222 
223     vdispls = libxl__device_list(gc, &libxl__vdispl_devtype, domid, &n);
224 
225     if (!vdispls) { rc = ERROR_NOTFOUND; goto out; }
226 
227     for (i = 0; i < n; ++i) {
228         if (devid == vdispls[i].devid) {
229             libxl_device_vdispl_copy(ctx, vdispl, &vdispls[i]);
230             rc = 0;
231             goto out;
232         }
233     }
234 
235     rc = ERROR_NOTFOUND;
236 
237 out:
238 
239     if (vdispls)
240         libxl__device_list_free(&libxl__vdispl_devtype, vdispls, n);
241 
242     GC_FREE;
243     return rc;
244 }
245 
246 LIBXL_DEFINE_DEVICE_ADD(vdispl)
247 static LIBXL_DEFINE_DEVICES_ADD(vdispl)
248 LIBXL_DEFINE_DEVICE_REMOVE(vdispl)
249 static LIBXL_DEFINE_UPDATE_DEVID(vdispl, "vdispl")
250 LIBXL_DEFINE_DEVICE_LIST(vdispl)
251 
252 DEFINE_DEVICE_TYPE_STRUCT(vdispl,
253     .update_config = (device_update_config_fn_t)libxl__update_config_vdispl,
254     .from_xenstore = (device_from_xenstore_fn_t)libxl__vdispl_from_xenstore,
255     .set_xenstore_config = (device_set_xenstore_config_fn_t)
256                            libxl__set_xenstore_vdispl
257 );
258 
259 /*
260  * Local variables:
261  * mode: C
262  * c-basic-offset: 4
263  * indent-tabs-mode: nil
264  * End:
265  */
266