2 * xen backend driver infrastructure
3 * (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; under version 2 of the License.
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 General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, see <http://www.gnu.org/licenses/>.
17 * Contributions after 2012-01-13 are licensed under the terms of the
18 * GNU GPL, version 2 or (at your option) any later version.
22 * TODO: add some xenbus / xenstore concepts overview here.
25 #include "qemu/osdep.h"
26 #include <sys/signal.h>
29 #include "hw/sysbus.h"
30 #include "hw/boards.h"
32 #include "qapi/error.h"
33 #include "hw/xen/xen-legacy-backend.h"
34 #include "hw/xen/xen_pvdev.h"
35 #include "monitor/qdev.h"
37 #include <xen/grant_table.h>
39 DeviceState
*xen_sysdev
;
42 /* ------------------------------------------------------------- */
45 struct xs_handle
*xenstore
;
46 const char *xen_protocol
;
49 static bool xen_feature_grant_copy
;
52 int xenstore_write_be_str(struct XenLegacyDevice
*xendev
, const char *node
,
55 return xenstore_write_str(xendev
->be
, node
, val
);
58 int xenstore_write_be_int(struct XenLegacyDevice
*xendev
, const char *node
,
61 return xenstore_write_int(xendev
->be
, node
, ival
);
64 int xenstore_write_be_int64(struct XenLegacyDevice
*xendev
, const char *node
,
67 return xenstore_write_int64(xendev
->be
, node
, ival
);
70 char *xenstore_read_be_str(struct XenLegacyDevice
*xendev
, const char *node
)
72 return xenstore_read_str(xendev
->be
, node
);
75 int xenstore_read_be_int(struct XenLegacyDevice
*xendev
, const char *node
,
78 return xenstore_read_int(xendev
->be
, node
, ival
);
81 char *xenstore_read_fe_str(struct XenLegacyDevice
*xendev
, const char *node
)
83 return xenstore_read_str(xendev
->fe
, node
);
86 int xenstore_read_fe_int(struct XenLegacyDevice
*xendev
, const char *node
,
89 return xenstore_read_int(xendev
->fe
, node
, ival
);
92 int xenstore_read_fe_uint64(struct XenLegacyDevice
*xendev
, const char *node
,
95 return xenstore_read_uint64(xendev
->fe
, node
, uval
);
98 /* ------------------------------------------------------------- */
100 int xen_be_set_state(struct XenLegacyDevice
*xendev
, enum xenbus_state state
)
104 rc
= xenstore_write_be_int(xendev
, "state", state
);
108 xen_pv_printf(xendev
, 1, "backend state: %s -> %s\n",
109 xenbus_strstate(xendev
->be_state
), xenbus_strstate(state
));
110 xendev
->be_state
= state
;
114 void xen_be_set_max_grant_refs(struct XenLegacyDevice
*xendev
,
115 unsigned int nr_refs
)
117 assert(xendev
->ops
->flags
& DEVOPS_FLAG_NEED_GNTDEV
);
119 if (xengnttab_set_max_grants(xendev
->gnttabdev
, nr_refs
)) {
120 xen_pv_printf(xendev
, 0, "xengnttab_set_max_grants failed: %s\n",
125 void *xen_be_map_grant_refs(struct XenLegacyDevice
*xendev
, uint32_t *refs
,
126 unsigned int nr_refs
, int prot
)
130 assert(xendev
->ops
->flags
& DEVOPS_FLAG_NEED_GNTDEV
);
132 ptr
= xengnttab_map_domain_grant_refs(xendev
->gnttabdev
, nr_refs
,
133 xen_domid
, refs
, prot
);
135 xen_pv_printf(xendev
, 0,
136 "xengnttab_map_domain_grant_refs failed: %s\n",
143 void xen_be_unmap_grant_refs(struct XenLegacyDevice
*xendev
, void *ptr
,
144 unsigned int nr_refs
)
146 assert(xendev
->ops
->flags
& DEVOPS_FLAG_NEED_GNTDEV
);
148 if (xengnttab_unmap(xendev
->gnttabdev
, ptr
, nr_refs
)) {
149 xen_pv_printf(xendev
, 0, "xengnttab_unmap failed: %s\n",
154 static int compat_copy_grant_refs(struct XenLegacyDevice
*xendev
,
156 XenGrantCopySegment segs
[],
157 unsigned int nr_segs
)
159 uint32_t *refs
= g_new(uint32_t, nr_segs
);
160 int prot
= to_domain
? PROT_WRITE
: PROT_READ
;
164 for (i
= 0; i
< nr_segs
; i
++) {
165 XenGrantCopySegment
*seg
= &segs
[i
];
167 refs
[i
] = to_domain
?
168 seg
->dest
.foreign
.ref
: seg
->source
.foreign
.ref
;
171 pages
= xengnttab_map_domain_grant_refs(xendev
->gnttabdev
, nr_segs
,
172 xen_domid
, refs
, prot
);
174 xen_pv_printf(xendev
, 0,
175 "xengnttab_map_domain_grant_refs failed: %s\n",
181 for (i
= 0; i
< nr_segs
; i
++) {
182 XenGrantCopySegment
*seg
= &segs
[i
];
183 void *page
= pages
+ (i
* XC_PAGE_SIZE
);
186 memcpy(page
+ seg
->dest
.foreign
.offset
, seg
->source
.virt
,
189 memcpy(seg
->dest
.virt
, page
+ seg
->source
.foreign
.offset
,
194 if (xengnttab_unmap(xendev
->gnttabdev
, pages
, nr_segs
)) {
195 xen_pv_printf(xendev
, 0, "xengnttab_unmap failed: %s\n",
203 int xen_be_copy_grant_refs(struct XenLegacyDevice
*xendev
,
205 XenGrantCopySegment segs
[],
206 unsigned int nr_segs
)
208 xengnttab_grant_copy_segment_t
*xengnttab_segs
;
212 assert(xendev
->ops
->flags
& DEVOPS_FLAG_NEED_GNTDEV
);
214 if (!xen_feature_grant_copy
) {
215 return compat_copy_grant_refs(xendev
, to_domain
, segs
, nr_segs
);
218 xengnttab_segs
= g_new0(xengnttab_grant_copy_segment_t
, nr_segs
);
220 for (i
= 0; i
< nr_segs
; i
++) {
221 XenGrantCopySegment
*seg
= &segs
[i
];
222 xengnttab_grant_copy_segment_t
*xengnttab_seg
= &xengnttab_segs
[i
];
225 xengnttab_seg
->flags
= GNTCOPY_dest_gref
;
226 xengnttab_seg
->dest
.foreign
.domid
= xen_domid
;
227 xengnttab_seg
->dest
.foreign
.ref
= seg
->dest
.foreign
.ref
;
228 xengnttab_seg
->dest
.foreign
.offset
= seg
->dest
.foreign
.offset
;
229 xengnttab_seg
->source
.virt
= seg
->source
.virt
;
231 xengnttab_seg
->flags
= GNTCOPY_source_gref
;
232 xengnttab_seg
->source
.foreign
.domid
= xen_domid
;
233 xengnttab_seg
->source
.foreign
.ref
= seg
->source
.foreign
.ref
;
234 xengnttab_seg
->source
.foreign
.offset
=
235 seg
->source
.foreign
.offset
;
236 xengnttab_seg
->dest
.virt
= seg
->dest
.virt
;
239 xengnttab_seg
->len
= seg
->len
;
242 rc
= xengnttab_grant_copy(xendev
->gnttabdev
, nr_segs
, xengnttab_segs
);
245 xen_pv_printf(xendev
, 0, "xengnttab_copy failed: %s\n",
249 for (i
= 0; i
< nr_segs
; i
++) {
250 xengnttab_grant_copy_segment_t
*xengnttab_seg
=
253 if (xengnttab_seg
->status
!= GNTST_okay
) {
254 xen_pv_printf(xendev
, 0, "segment[%u] status: %d\n", i
,
255 xengnttab_seg
->status
);
260 g_free(xengnttab_segs
);
265 * get xen backend device, allocate a new one if it doesn't exist.
267 static struct XenLegacyDevice
*xen_be_get_xendev(const char *type
, int dom
,
269 struct XenDevOps
*ops
)
271 struct XenLegacyDevice
*xendev
;
273 xendev
= xen_pv_find_xendev(type
, dom
, dev
);
278 /* init new xendev */
279 xendev
= g_malloc0(ops
->size
);
280 object_initialize(&xendev
->qdev
, ops
->size
, TYPE_XENBACKEND
);
281 OBJECT(xendev
)->free
= g_free
;
282 qdev_set_parent_bus(DEVICE(xendev
), xen_sysbus
);
283 qdev_set_id(DEVICE(xendev
), g_strdup_printf("xen-%s-%d", type
, dev
));
284 qdev_init_nofail(DEVICE(xendev
));
285 object_unref(OBJECT(xendev
));
292 snprintf(xendev
->be
, sizeof(xendev
->be
), "backend/%s/%d/%d",
293 xendev
->type
, xendev
->dom
, xendev
->dev
);
294 snprintf(xendev
->name
, sizeof(xendev
->name
), "%s-%d",
295 xendev
->type
, xendev
->dev
);
297 xendev
->debug
= debug
;
298 xendev
->local_port
= -1;
300 xendev
->evtchndev
= xenevtchn_open(NULL
, 0);
301 if (xendev
->evtchndev
== NULL
) {
302 xen_pv_printf(NULL
, 0, "can't open evtchn device\n");
303 qdev_unplug(DEVICE(xendev
), NULL
);
306 qemu_set_cloexec(xenevtchn_fd(xendev
->evtchndev
));
308 xen_pv_insert_xendev(xendev
);
310 if (xendev
->ops
->alloc
) {
311 xendev
->ops
->alloc(xendev
);
319 * Sync internal data structures on xenstore updates.
320 * Node specifies the changed field. node = NULL means
321 * update all fields (used for initialization).
323 static void xen_be_backend_changed(struct XenLegacyDevice
*xendev
,
326 if (node
== NULL
|| strcmp(node
, "online") == 0) {
327 if (xenstore_read_be_int(xendev
, "online", &xendev
->online
) == -1) {
333 xen_pv_printf(xendev
, 2, "backend update: %s\n", node
);
334 if (xendev
->ops
->backend_changed
) {
335 xendev
->ops
->backend_changed(xendev
, node
);
340 static void xen_be_frontend_changed(struct XenLegacyDevice
*xendev
,
345 if (node
== NULL
|| strcmp(node
, "state") == 0) {
346 if (xenstore_read_fe_int(xendev
, "state", &fe_state
) == -1) {
347 fe_state
= XenbusStateUnknown
;
349 if (xendev
->fe_state
!= fe_state
) {
350 xen_pv_printf(xendev
, 1, "frontend state: %s -> %s\n",
351 xenbus_strstate(xendev
->fe_state
),
352 xenbus_strstate(fe_state
));
354 xendev
->fe_state
= fe_state
;
356 if (node
== NULL
|| strcmp(node
, "protocol") == 0) {
357 g_free(xendev
->protocol
);
358 xendev
->protocol
= xenstore_read_fe_str(xendev
, "protocol");
359 if (xendev
->protocol
) {
360 xen_pv_printf(xendev
, 1, "frontend protocol: %s\n",
366 xen_pv_printf(xendev
, 2, "frontend update: %s\n", node
);
367 if (xendev
->ops
->frontend_changed
) {
368 xendev
->ops
->frontend_changed(xendev
, node
);
373 /* ------------------------------------------------------------- */
374 /* Check for possible state transitions and perform them. */
377 * Initial xendev setup. Read frontend path, register watch for it.
378 * Should succeed once xend finished setting up the backend device.
380 * Also sets initial state (-> Initializing) when done. Which
381 * only affects the xendev->be_state variable as xenbus should
382 * already be put into that state by xend.
384 static int xen_be_try_setup(struct XenLegacyDevice
*xendev
)
386 char token
[XEN_BUFSIZE
];
389 if (xenstore_read_be_int(xendev
, "state", &be_state
) == -1) {
390 xen_pv_printf(xendev
, 0, "reading backend state failed\n");
394 if (be_state
!= XenbusStateInitialising
) {
395 xen_pv_printf(xendev
, 0, "initial backend state is wrong (%s)\n",
396 xenbus_strstate(be_state
));
400 xendev
->fe
= xenstore_read_be_str(xendev
, "frontend");
401 if (xendev
->fe
== NULL
) {
402 xen_pv_printf(xendev
, 0, "reading frontend path failed\n");
406 /* setup frontend watch */
407 snprintf(token
, sizeof(token
), "fe:%p", xendev
);
408 if (!xs_watch(xenstore
, xendev
->fe
, token
)) {
409 xen_pv_printf(xendev
, 0, "watching frontend path (%s) failed\n",
413 xen_be_set_state(xendev
, XenbusStateInitialising
);
415 xen_be_backend_changed(xendev
, NULL
);
416 xen_be_frontend_changed(xendev
, NULL
);
421 * Try initialize xendev. Prepare everything the backend can do
422 * without synchronizing with the frontend. Fakes hotplug-status. No
423 * hotplug involved here because this is about userspace drivers, thus
424 * there are kernel backend devices which could invoke hotplug.
426 * Goes to InitWait on success.
428 static int xen_be_try_init(struct XenLegacyDevice
*xendev
)
432 if (!xendev
->online
) {
433 xen_pv_printf(xendev
, 1, "not online\n");
437 if (xendev
->ops
->init
) {
438 rc
= xendev
->ops
->init(xendev
);
441 xen_pv_printf(xendev
, 1, "init() failed\n");
445 xenstore_write_be_str(xendev
, "hotplug-status", "connected");
446 xen_be_set_state(xendev
, XenbusStateInitWait
);
451 * Try to initialise xendev. Depends on the frontend being ready
452 * for it (shared ring and evtchn info in xenstore, state being
453 * Initialised or Connected).
455 * Goes to Connected on success.
457 static int xen_be_try_initialise(struct XenLegacyDevice
*xendev
)
461 if (xendev
->fe_state
!= XenbusStateInitialised
&&
462 xendev
->fe_state
!= XenbusStateConnected
) {
463 if (xendev
->ops
->flags
& DEVOPS_FLAG_IGNORE_STATE
) {
464 xen_pv_printf(xendev
, 2, "frontend not ready, ignoring\n");
466 xen_pv_printf(xendev
, 2, "frontend not ready (yet)\n");
471 if (xendev
->ops
->flags
& DEVOPS_FLAG_NEED_GNTDEV
) {
472 xendev
->gnttabdev
= xengnttab_open(NULL
, 0);
473 if (xendev
->gnttabdev
== NULL
) {
474 xen_pv_printf(NULL
, 0, "can't open gnttab device\n");
478 xendev
->gnttabdev
= NULL
;
481 if (xendev
->ops
->initialise
) {
482 rc
= xendev
->ops
->initialise(xendev
);
485 xen_pv_printf(xendev
, 0, "initialise() failed\n");
489 xen_be_set_state(xendev
, XenbusStateConnected
);
494 * Try to let xendev know that it is connected. Depends on the
495 * frontend being Connected. Note that this may be called more
496 * than once since the backend state is not modified.
498 static void xen_be_try_connected(struct XenLegacyDevice
*xendev
)
500 if (!xendev
->ops
->connected
) {
504 if (xendev
->fe_state
!= XenbusStateConnected
) {
505 if (xendev
->ops
->flags
& DEVOPS_FLAG_IGNORE_STATE
) {
506 xen_pv_printf(xendev
, 2, "frontend not ready, ignoring\n");
508 xen_pv_printf(xendev
, 2, "frontend not ready (yet)\n");
513 xendev
->ops
->connected(xendev
);
517 * Teardown connection.
519 * Goes to Closed when done.
521 static void xen_be_disconnect(struct XenLegacyDevice
*xendev
,
522 enum xenbus_state state
)
524 if (xendev
->be_state
!= XenbusStateClosing
&&
525 xendev
->be_state
!= XenbusStateClosed
&&
526 xendev
->ops
->disconnect
) {
527 xendev
->ops
->disconnect(xendev
);
529 if (xendev
->gnttabdev
) {
530 xengnttab_close(xendev
->gnttabdev
);
531 xendev
->gnttabdev
= NULL
;
533 if (xendev
->be_state
!= state
) {
534 xen_be_set_state(xendev
, state
);
539 * Try to reset xendev, for reconnection by another frontend instance.
541 static int xen_be_try_reset(struct XenLegacyDevice
*xendev
)
543 if (xendev
->fe_state
!= XenbusStateInitialising
) {
547 xen_pv_printf(xendev
, 1, "device reset (for re-connect)\n");
548 xen_be_set_state(xendev
, XenbusStateInitialising
);
553 * state change dispatcher function
555 void xen_be_check_state(struct XenLegacyDevice
*xendev
)
559 /* frontend may request shutdown from almost anywhere */
560 if (xendev
->fe_state
== XenbusStateClosing
||
561 xendev
->fe_state
== XenbusStateClosed
) {
562 xen_be_disconnect(xendev
, xendev
->fe_state
);
566 /* check for possible backend state transitions */
568 switch (xendev
->be_state
) {
569 case XenbusStateUnknown
:
570 rc
= xen_be_try_setup(xendev
);
572 case XenbusStateInitialising
:
573 rc
= xen_be_try_init(xendev
);
575 case XenbusStateInitWait
:
576 rc
= xen_be_try_initialise(xendev
);
578 case XenbusStateConnected
:
579 /* xendev->be_state doesn't change */
580 xen_be_try_connected(xendev
);
583 case XenbusStateClosed
:
584 rc
= xen_be_try_reset(xendev
);
595 /* ------------------------------------------------------------- */
597 static int xenstore_scan(const char *type
, int dom
, struct XenDevOps
*ops
)
599 struct XenLegacyDevice
*xendev
;
600 char path
[XEN_BUFSIZE
], token
[XEN_BUFSIZE
];
602 unsigned int cdev
, j
;
605 snprintf(token
, sizeof(token
), "be:%p:%d:%p", type
, dom
, ops
);
606 snprintf(path
, sizeof(path
), "backend/%s/%d", type
, dom
);
607 if (!xs_watch(xenstore
, path
, token
)) {
608 xen_pv_printf(NULL
, 0, "xen be: watching backend path (%s) failed\n",
613 /* look for backends */
614 dev
= xs_directory(xenstore
, 0, path
, &cdev
);
618 for (j
= 0; j
< cdev
; j
++) {
619 xendev
= xen_be_get_xendev(type
, dom
, atoi(dev
[j
]), ops
);
620 if (xendev
== NULL
) {
623 xen_be_check_state(xendev
);
629 void xenstore_update_be(char *watch
, char *type
, int dom
,
630 struct XenDevOps
*ops
)
632 struct XenLegacyDevice
*xendev
;
633 char path
[XEN_BUFSIZE
], *bepath
;
634 unsigned int len
, dev
;
636 len
= snprintf(path
, sizeof(path
), "backend/%s/%d", type
, dom
);
637 if (strncmp(path
, watch
, len
) != 0) {
640 if (sscanf(watch
+ len
, "/%u/%255s", &dev
, path
) != 2) {
642 if (sscanf(watch
+ len
, "/%u", &dev
) != 1) {
650 xendev
= xen_be_get_xendev(type
, dom
, dev
, ops
);
651 if (xendev
!= NULL
) {
652 bepath
= xs_read(xenstore
, 0, xendev
->be
, &len
);
653 if (bepath
== NULL
) {
654 xen_pv_del_xendev(xendev
);
657 xen_be_backend_changed(xendev
, path
);
658 xen_be_check_state(xendev
);
663 void xenstore_update_fe(char *watch
, struct XenLegacyDevice
*xendev
)
668 len
= strlen(xendev
->fe
);
669 if (strncmp(xendev
->fe
, watch
, len
) != 0) {
672 if (watch
[len
] != '/') {
675 node
= watch
+ len
+ 1;
677 xen_be_frontend_changed(xendev
, node
);
678 xen_be_check_state(xendev
);
680 /* -------------------------------------------------------------------- */
682 int xen_be_init(void)
684 xengnttab_handle
*gnttabdev
;
686 xenstore
= xs_daemon_open();
688 xen_pv_printf(NULL
, 0, "can't connect to xenstored\n");
692 qemu_set_fd_handler(xs_fileno(xenstore
), xenstore_update
, NULL
, NULL
);
694 if (xen_xc
== NULL
|| xen_fmem
== NULL
) {
695 /* Check if xen_init() have been called */
699 gnttabdev
= xengnttab_open(NULL
, 0);
700 if (gnttabdev
!= NULL
) {
701 if (xengnttab_grant_copy(gnttabdev
, 0, NULL
) == 0) {
702 xen_feature_grant_copy
= true;
704 xengnttab_close(gnttabdev
);
707 xen_sysdev
= qdev_create(NULL
, TYPE_XENSYSDEV
);
708 qdev_init_nofail(xen_sysdev
);
709 xen_sysbus
= qbus_create(TYPE_XENSYSBUS
, DEVICE(xen_sysdev
), "xen-sysbus");
710 qbus_set_bus_hotplug_handler(xen_sysbus
, &error_abort
);
715 qemu_set_fd_handler(xs_fileno(xenstore
), NULL
, NULL
, NULL
);
716 xs_daemon_close(xenstore
);
722 static void xen_set_dynamic_sysbus(void)
724 Object
*machine
= qdev_get_machine();
725 ObjectClass
*oc
= object_get_class(machine
);
726 MachineClass
*mc
= MACHINE_CLASS(oc
);
728 machine_class_allow_dynamic_sysbus_dev(mc
, TYPE_XENSYSDEV
);
731 int xen_be_register(const char *type
, struct XenDevOps
*ops
)
736 if (ops
->backend_register
) {
737 rc
= ops
->backend_register();
743 snprintf(path
, sizeof(path
), "device-model/%u/backends/%s", xen_domid
,
745 xenstore_mkdir(path
, XS_PERM_NONE
);
747 return xenstore_scan(type
, xen_domid
, ops
);
750 void xen_be_register_common(void)
752 xen_set_dynamic_sysbus();
754 xen_be_register("console", &xen_console_ops
);
755 xen_be_register("vkbd", &xen_kbdmouse_ops
);
757 xen_be_register("9pfs", &xen_9pfs_ops
);
759 #ifdef CONFIG_USB_LIBUSB
760 xen_be_register("qusb", &xen_usb_ops
);
764 int xen_be_bind_evtchn(struct XenLegacyDevice
*xendev
)
766 if (xendev
->local_port
!= -1) {
769 xendev
->local_port
= xenevtchn_bind_interdomain
770 (xendev
->evtchndev
, xendev
->dom
, xendev
->remote_port
);
771 if (xendev
->local_port
== -1) {
772 xen_pv_printf(xendev
, 0, "xenevtchn_bind_interdomain failed\n");
775 xen_pv_printf(xendev
, 2, "bind evtchn port %d\n", xendev
->local_port
);
776 qemu_set_fd_handler(xenevtchn_fd(xendev
->evtchndev
),
777 xen_pv_evtchn_event
, NULL
, xendev
);
782 static Property xendev_properties
[] = {
783 DEFINE_PROP_END_OF_LIST(),
786 static void xendev_class_init(ObjectClass
*klass
, void *data
)
788 DeviceClass
*dc
= DEVICE_CLASS(klass
);
790 dc
->props
= xendev_properties
;
791 set_bit(DEVICE_CATEGORY_MISC
, dc
->categories
);
792 /* xen-backend devices can be plugged/unplugged dynamically */
793 dc
->user_creatable
= true;
796 static const TypeInfo xendev_type_info
= {
797 .name
= TYPE_XENBACKEND
,
798 .parent
= TYPE_XENSYSDEV
,
799 .class_init
= xendev_class_init
,
800 .instance_size
= sizeof(struct XenLegacyDevice
),
803 static void xen_sysbus_class_init(ObjectClass
*klass
, void *data
)
805 HotplugHandlerClass
*hc
= HOTPLUG_HANDLER_CLASS(klass
);
807 hc
->unplug
= qdev_simple_device_unplug_cb
;
810 static const TypeInfo xensysbus_info
= {
811 .name
= TYPE_XENSYSBUS
,
813 .class_init
= xen_sysbus_class_init
,
814 .interfaces
= (InterfaceInfo
[]) {
815 { TYPE_HOTPLUG_HANDLER
},
820 static Property xen_sysdev_properties
[] = {
821 {/* end of property list */},
824 static void xen_sysdev_class_init(ObjectClass
*klass
, void *data
)
826 DeviceClass
*dc
= DEVICE_CLASS(klass
);
828 dc
->props
= xen_sysdev_properties
;
829 dc
->bus_type
= TYPE_XENSYSBUS
;
832 static const TypeInfo xensysdev_info
= {
833 .name
= TYPE_XENSYSDEV
,
834 .parent
= TYPE_SYS_BUS_DEVICE
,
835 .instance_size
= sizeof(SysBusDevice
),
836 .class_init
= xen_sysdev_class_init
,
839 static void xenbe_register_types(void)
841 type_register_static(&xensysbus_info
);
842 type_register_static(&xensysdev_info
);
843 type_register_static(&xendev_type_info
);
846 type_init(xenbe_register_types
)