ia64/xen-unstable

changeset 16231:93938fee0bf5

pv-qemu 4/10: Refactor xenfb event handlers

This patch is a simple code re-factoring to move the event loop
integration directly into the xenfb.c file. It is to facilitate
the patches which follow.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
author Keir Fraser <keir@xensource.com>
date Thu Oct 25 14:38:47 2007 +0100 (2007-10-25)
parents 1ed990bc8da9
children 54b72f14eb25
files tools/ioemu/hw/xen_machine_pv.c tools/ioemu/hw/xenfb.c tools/ioemu/hw/xenfb.h
line diff
     1.1 --- a/tools/ioemu/hw/xen_machine_pv.c	Thu Oct 25 14:37:23 2007 +0100
     1.2 +++ b/tools/ioemu/hw/xen_machine_pv.c	Thu Oct 25 14:38:47 2007 +0100
     1.3 @@ -213,22 +213,6 @@ void xen_pvfb_invalidate(void *opaque)
     1.4  /* Screen dump is not used in Xen, so no need to impl this ? */
     1.5  void xen_pvfb_screen_dump(void *opaque, const char *name) { }
     1.6  
     1.7 -void xen_pvfb_dispatch_store(void *opaque) {
     1.8 -    int ret;
     1.9 -    if ((ret = xenfb_dispatch_store(opaque)) < 0) {
    1.10 -        fprintf(stderr, "Failure while dispatching store: %d\n", ret);
    1.11 -        exit(1);
    1.12 -    }
    1.13 -}
    1.14 -
    1.15 -void xen_pvfb_dispatch_channel(void *opaque) {
    1.16 -    int ret;
    1.17 -    if ((ret = xenfb_dispatch_channel(opaque)) < 0) {
    1.18 -        fprintf(stderr, "Failure while dispatching store: %d\n", ret);
    1.19 -        exit(1);
    1.20 -    }
    1.21 -}
    1.22 -
    1.23  /* The Xen PV machine currently provides
    1.24   *   - a virtual framebuffer
    1.25   *   - ....
    1.26 @@ -242,7 +226,7 @@ static void xen_init_pv(uint64_t ram_siz
    1.27  {
    1.28      struct xenfb *xenfb;
    1.29      extern int domid;
    1.30 -    int fd, i;
    1.31 +    int i;
    1.32  
    1.33      /* Prepare scancode mapping table */
    1.34  	for (i = 0; i < 128; i++) {
    1.35 @@ -281,19 +265,6 @@ static void xen_init_pv(uint64_t ram_siz
    1.36                                   xenfb->abs_pointer_wanted,
    1.37                                   "Xen PVFB Mouse");
    1.38  
    1.39 -    /* Listen for events from xenstore */
    1.40 -    fd = xenfb_get_store_fd(xenfb);
    1.41 -    if (qemu_set_fd_handler2(fd, NULL, xen_pvfb_dispatch_store, NULL, xenfb) < 0) {
    1.42 -        fprintf(stderr, "Could not register event handler (%s)\n",
    1.43 -                strerror(errno));
    1.44 -    }
    1.45 -
    1.46 -    /* Listen for events from the event channel */
    1.47 -    fd = xenfb_get_channel_fd(xenfb);
    1.48 -    if (qemu_set_fd_handler2(fd, NULL, xen_pvfb_dispatch_channel, NULL, xenfb) < 0) {
    1.49 -        fprintf(stderr, "Could not register event handler (%s)\n",
    1.50 -                strerror(errno));
    1.51 -    }
    1.52  
    1.53      /* Setup QEMU display */
    1.54      dpy_resize(ds, xenfb->width, xenfb->height);
     2.1 --- a/tools/ioemu/hw/xenfb.c	Thu Oct 25 14:37:23 2007 +0100
     2.2 +++ b/tools/ioemu/hw/xenfb.c	Thu Oct 25 14:38:47 2007 +0100
     2.3 @@ -8,7 +8,6 @@
     2.4  #include <xen/io/fbif.h>
     2.5  #include <xen/io/kbdif.h>
     2.6  #include <xen/io/protocols.h>
     2.7 -#include <sys/select.h>
     2.8  #include <stdbool.h>
     2.9  #include <xen/event_channel.h>
    2.10  #include <sys/mman.h>
    2.11 @@ -18,6 +17,7 @@
    2.12  #include <time.h>
    2.13  #include <xs.h>
    2.14  
    2.15 +#include "vl.h"
    2.16  #include "xenfb.h"
    2.17  
    2.18  // FIXME defend against malicious frontend?
    2.19 @@ -505,6 +505,115 @@ static void xenfb_dev_fatal(struct xenfb
    2.20  	xenfb_switch_state(dev, XenbusStateClosing);
    2.21  }
    2.22  
    2.23 +
    2.24 +static void xenfb_detach_dom(struct xenfb_private *xenfb)
    2.25 +{
    2.26 +	xenfb_unbind(&xenfb->fb);
    2.27 +	xenfb_unbind(&xenfb->kbd);
    2.28 +	if (xenfb->pub.pixels) {
    2.29 +		munmap(xenfb->pub.pixels, xenfb->fb_len);
    2.30 +		xenfb->pub.pixels = NULL;
    2.31 +	}
    2.32 +}
    2.33 +
    2.34 +static void xenfb_on_fb_event(struct xenfb_private *xenfb)
    2.35 +{
    2.36 +	uint32_t prod, cons;
    2.37 +	struct xenfb_page *page = xenfb->fb.page;
    2.38 +
    2.39 +	prod = page->out_prod;
    2.40 +	if (prod == page->out_cons)
    2.41 +		return;
    2.42 +	rmb();			/* ensure we see ring contents up to prod */
    2.43 +	for (cons = page->out_cons; cons != prod; cons++) {
    2.44 +		union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
    2.45 +
    2.46 +		switch (event->type) {
    2.47 +		case XENFB_TYPE_UPDATE:
    2.48 +                    if (xenfb->pub.update)
    2.49 +			xenfb->pub.update(&xenfb->pub,
    2.50 +					  event->update.x, event->update.y,
    2.51 +					  event->update.width, event->update.height);
    2.52 +                    break;
    2.53 +		}
    2.54 +	}
    2.55 +	mb();			/* ensure we're done with ring contents */
    2.56 +	page->out_cons = cons;
    2.57 +	xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
    2.58 +}
    2.59 +
    2.60 +static void xenfb_on_kbd_event(struct xenfb_private *xenfb)
    2.61 +{
    2.62 +	struct xenkbd_page *page = xenfb->kbd.page;
    2.63 +
    2.64 +	/* We don't understand any keyboard events, so just ignore them. */
    2.65 +	if (page->out_prod == page->out_cons)
    2.66 +		return;
    2.67 +	page->out_cons = page->out_prod;
    2.68 +	xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
    2.69 +}
    2.70 +
    2.71 +static int xenfb_on_state_change(struct xenfb_device *dev)
    2.72 +{
    2.73 +	enum xenbus_state state;
    2.74 +
    2.75 +	state = xenfb_read_state(dev->xenfb->xsh, dev->otherend);
    2.76 +
    2.77 +	switch (state) {
    2.78 +	case XenbusStateUnknown:
    2.79 +		/* There was an error reading the frontend state.  The
    2.80 +		   domain has probably gone away; in any case, there's
    2.81 +		   not much point in us continuing. */
    2.82 +		return -1;
    2.83 +	case XenbusStateInitialising:
    2.84 +	case XenbusStateInitWait:
    2.85 +	case XenbusStateInitialised:
    2.86 +	case XenbusStateConnected:
    2.87 +		break;
    2.88 +	case XenbusStateClosing:
    2.89 +		xenfb_unbind(dev);
    2.90 +		xenfb_switch_state(dev, state);
    2.91 +		break;
    2.92 +	case XenbusStateClosed:
    2.93 +		xenfb_switch_state(dev, state);
    2.94 +	}
    2.95 +	return 0;
    2.96 +}
    2.97 +
    2.98 +static void xenfb_dispatch_channel(void *xenfb_pub)
    2.99 +{
   2.100 +	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
   2.101 +	evtchn_port_t port;
   2.102 +	port = xc_evtchn_pending(xenfb->evt_xch);
   2.103 +	if (port == -1)
   2.104 +		exit(1);
   2.105 +
   2.106 +	if (port == xenfb->fb.port)
   2.107 +		xenfb_on_fb_event(xenfb);
   2.108 +	else if (port == xenfb->kbd.port)
   2.109 +		xenfb_on_kbd_event(xenfb);
   2.110 +
   2.111 +	if (xc_evtchn_unmask(xenfb->evt_xch, port) == -1)
   2.112 +		exit(1);
   2.113 +}
   2.114 +
   2.115 +static void xenfb_dispatch_store(void *xenfb_pub)
   2.116 +{
   2.117 +	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
   2.118 +	unsigned dummy;
   2.119 +	char **vec;
   2.120 +	int r;
   2.121 +
   2.122 +	vec = xs_read_watch(xenfb->xsh, &dummy);
   2.123 +	free(vec);
   2.124 +	r = xenfb_on_state_change(&xenfb->fb);
   2.125 +	if (r == 0)
   2.126 +		r = xenfb_on_state_change(&xenfb->kbd);
   2.127 +	if (r == -1)
   2.128 +		exit(1);
   2.129 +}
   2.130 +
   2.131 +
   2.132  int xenfb_attach_dom(struct xenfb *xenfb_pub, int domid)
   2.133  {
   2.134  	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
   2.135 @@ -585,6 +694,14 @@ int xenfb_attach_dom(struct xenfb *xenfb
   2.136  		val = 0;
   2.137  	xenfb->pub.abs_pointer_wanted = val;
   2.138  
   2.139 +	/* Listen for events from xenstore */
   2.140 +	if (qemu_set_fd_handler2(xs_fileno(xenfb->xsh), NULL, xenfb_dispatch_store, NULL, xenfb) < 0)
   2.141 +		goto error;
   2.142 +
   2.143 +	/* Listen for events from the event channel */
   2.144 +	if (qemu_set_fd_handler2(xc_evtchn_fd(xenfb->evt_xch), NULL, xenfb_dispatch_channel, NULL, xenfb) < 0)
   2.145 +		goto error;
   2.146 +
   2.147  	return 0;
   2.148  
   2.149   error:
   2.150 @@ -596,160 +713,6 @@ int xenfb_attach_dom(struct xenfb *xenfb
   2.151          return -1;
   2.152  }
   2.153  
   2.154 -static void xenfb_detach_dom(struct xenfb_private *xenfb)
   2.155 -{
   2.156 -	xenfb_unbind(&xenfb->fb);
   2.157 -	xenfb_unbind(&xenfb->kbd);
   2.158 -	if (xenfb->pub.pixels) {
   2.159 -		munmap(xenfb->pub.pixels, xenfb->fb_len);
   2.160 -		xenfb->pub.pixels = NULL;
   2.161 -	}
   2.162 -}
   2.163 -
   2.164 -static void xenfb_on_fb_event(struct xenfb_private *xenfb)
   2.165 -{
   2.166 -	uint32_t prod, cons;
   2.167 -	struct xenfb_page *page = xenfb->fb.page;
   2.168 -
   2.169 -	prod = page->out_prod;
   2.170 -	if (prod == page->out_cons)
   2.171 -		return;
   2.172 -	rmb();			/* ensure we see ring contents up to prod */
   2.173 -	for (cons = page->out_cons; cons != prod; cons++) {
   2.174 -		union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
   2.175 -
   2.176 -		switch (event->type) {
   2.177 -		case XENFB_TYPE_UPDATE:
   2.178 -                    if (xenfb->pub.update)
   2.179 -			xenfb->pub.update(&xenfb->pub,
   2.180 -					  event->update.x, event->update.y,
   2.181 -					  event->update.width, event->update.height);
   2.182 -                    break;
   2.183 -		}
   2.184 -	}
   2.185 -	mb();			/* ensure we're done with ring contents */
   2.186 -	page->out_cons = cons;
   2.187 -	xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
   2.188 -}
   2.189 -
   2.190 -static void xenfb_on_kbd_event(struct xenfb_private *xenfb)
   2.191 -{
   2.192 -	struct xenkbd_page *page = xenfb->kbd.page;
   2.193 -
   2.194 -	/* We don't understand any keyboard events, so just ignore them. */
   2.195 -	if (page->out_prod == page->out_cons)
   2.196 -		return;
   2.197 -	page->out_cons = page->out_prod;
   2.198 -	xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
   2.199 -}
   2.200 -
   2.201 -static int xenfb_on_state_change(struct xenfb_device *dev)
   2.202 -{
   2.203 -	enum xenbus_state state;
   2.204 -
   2.205 -	state = xenfb_read_state(dev->xenfb->xsh, dev->otherend);
   2.206 -
   2.207 -	switch (state) {
   2.208 -	case XenbusStateUnknown:
   2.209 -		/* There was an error reading the frontend state.  The
   2.210 -		   domain has probably gone away; in any case, there's
   2.211 -		   not much point in us continuing. */
   2.212 -		return -1;
   2.213 -	case XenbusStateInitialising:
   2.214 -	case XenbusStateInitWait:
   2.215 -	case XenbusStateInitialised:
   2.216 -	case XenbusStateConnected:
   2.217 -		break;
   2.218 -	case XenbusStateClosing:
   2.219 -		xenfb_unbind(dev);
   2.220 -		xenfb_switch_state(dev, state);
   2.221 -		break;
   2.222 -	case XenbusStateClosed:
   2.223 -		xenfb_switch_state(dev, state);
   2.224 -	}
   2.225 -	return 0;
   2.226 -}
   2.227 -
   2.228 -int xenfb_dispatch_channel(struct xenfb *xenfb_pub)
   2.229 -{
   2.230 -	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
   2.231 -	evtchn_port_t port;
   2.232 -	port = xc_evtchn_pending(xenfb->evt_xch);
   2.233 -	if (port == -1)
   2.234 -		return -1;
   2.235 -
   2.236 -	if (port == xenfb->fb.port)
   2.237 -		xenfb_on_fb_event(xenfb);
   2.238 -	else if (port == xenfb->kbd.port)
   2.239 -		xenfb_on_kbd_event(xenfb);
   2.240 -
   2.241 -	if (xc_evtchn_unmask(xenfb->evt_xch, port) == -1)
   2.242 -		return -1;
   2.243 -
   2.244 -	return 0;
   2.245 -}
   2.246 -
   2.247 -int xenfb_dispatch_store(struct xenfb *xenfb_pub)
   2.248 -{
   2.249 -	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
   2.250 -	unsigned dummy;
   2.251 -	char **vec;
   2.252 -	int r;
   2.253 -
   2.254 -	vec = xs_read_watch(xenfb->xsh, &dummy);
   2.255 -	free(vec);
   2.256 -	r = xenfb_on_state_change(&xenfb->fb);
   2.257 -	if (r == 0)
   2.258 -		r = xenfb_on_state_change(&xenfb->kbd);
   2.259 -	if (r == -1)
   2.260 -		return -2;
   2.261 -
   2.262 -	return 0;
   2.263 -}
   2.264 -
   2.265 -
   2.266 -/* Returns 0 normally, -1 on error, or -2 if the domain went away. */
   2.267 -int xenfb_poll(struct xenfb *xenfb_pub, fd_set *readfds)
   2.268 -{
   2.269 -	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
   2.270 -	int ret;
   2.271 -
   2.272 -	if (FD_ISSET(xc_evtchn_fd(xenfb->evt_xch), readfds)) {
   2.273 -		if ((ret = xenfb_dispatch_channel(xenfb_pub)) < 0)
   2.274 -			return ret;
   2.275 -	}
   2.276 -
   2.277 -	if (FD_ISSET(xs_fileno(xenfb->xsh), readfds)) {
   2.278 -		if ((ret = xenfb_dispatch_store(xenfb_pub)) < 0)
   2.279 -			return ret;
   2.280 -	}
   2.281 -
   2.282 -	return 0;
   2.283 -}
   2.284 -
   2.285 -int xenfb_select_fds(struct xenfb *xenfb_pub, fd_set *readfds)
   2.286 -{
   2.287 -	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
   2.288 -	int fd1 = xc_evtchn_fd(xenfb->evt_xch);
   2.289 -	int fd2 = xs_fileno(xenfb->xsh);
   2.290 -
   2.291 -	FD_SET(fd1, readfds);
   2.292 -	FD_SET(fd2, readfds);
   2.293 -	return fd1 > fd2 ? fd1 + 1 : fd2 + 1;
   2.294 -}
   2.295 -
   2.296 -int xenfb_get_store_fd(struct xenfb *xenfb_pub)
   2.297 -{
   2.298 -	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
   2.299 -	return xs_fileno(xenfb->xsh);
   2.300 -}
   2.301 -
   2.302 -int xenfb_get_channel_fd(struct xenfb *xenfb_pub)
   2.303 -{
   2.304 -	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
   2.305 -	return xc_evtchn_fd(xenfb->evt_xch);
   2.306 -}
   2.307 -
   2.308  static int xenfb_kbd_event(struct xenfb_private *xenfb,
   2.309  			   union xenkbd_in_event *event)
   2.310  {
     3.1 --- a/tools/ioemu/hw/xenfb.h	Thu Oct 25 14:37:23 2007 +0100
     3.2 +++ b/tools/ioemu/hw/xenfb.h	Thu Oct 25 14:38:47 2007 +0100
     3.3 @@ -25,13 +25,6 @@ void xenfb_teardown(struct xenfb *xenfb)
     3.4  
     3.5  int xenfb_attach_dom(struct xenfb *xenfb, int domid);
     3.6  
     3.7 -int xenfb_dispatch_store(struct xenfb *xenfb_pub);
     3.8 -int xenfb_dispatch_channel(struct xenfb *xenfb_pub);
     3.9 -int xenfb_select_fds(struct xenfb *xenfb, fd_set *readfds);
    3.10 -int xenfb_poll(struct xenfb *xenfb, fd_set *readfds);
    3.11 -int xenfb_get_store_fd(struct xenfb *xenfb_pub);
    3.12 -int xenfb_get_channel_fd(struct xenfb *xenfb_pub);
    3.13 -
    3.14  int xenfb_send_key(struct xenfb *xenfb, bool down, int keycode);
    3.15  int xenfb_send_motion(struct xenfb *xenfb, int rel_x, int rel_y);
    3.16  int xenfb_send_position(struct xenfb *xenfb, int abs_x, int abs_y);