diff --git a/vchan/init.c b/vchan/init.c index a8192bf9..d870aea2 100644 --- a/vchan/init.c +++ b/vchan/init.c @@ -19,6 +19,8 @@ * */ +#ifndef WINNT + #include #include #include @@ -27,18 +29,66 @@ #include #include #include -#include #include #include #include -#include -#include "libvchan.h" #ifndef CONFIG_STUBDOM #include "../u2mfn/u2mfnlib.h" #else #include #endif +#endif + +#include +#include +#include +#include "libvchan.h" + + +static int fill_ctrl(struct libvchan *ctrl, struct vchan_interface *ring, int ring_ref) +{ + if (!ctrl || !ring) + return -1; + + ctrl->ring = ring; + ctrl->ring_ref = ring_ref; + + ring->cons_in = ring->prod_in = ring->cons_out = ring->prod_out = + 0; + ring->server_closed = ring->client_closed = 0; + ring->debug = 0xaabbccdd; + + return 0; +} + +#ifdef WINNT +static int ring_init(struct libvchan *ctrl) +{ + struct gntmem_handle* h; + grant_ref_t grants[1]; + int result; + struct vchan_interface *ring; + + h = gntmem_open(); + if (h == INVALID_HANDLE_VALUE) + return -1; + + gntmem_set_local_quota(h, 1); + gntmem_set_global_quota(h, 1); + + memset(grants, 0, sizeof(grants)); + ring = gntmem_grant_pages_to_domain(h, 0, 1, grants); + if (!ring) { + gntmem_close(h); + return -1; + } + + return fill_ctrl(ctrl, ring, grants[0]); +} + +#else + static int ring_init(struct libvchan *ctrl) { int mfn; @@ -52,7 +102,6 @@ static int ring_init(struct libvchan *ctrl) mfn = virtual_to_mfn(ring); #else - int u2mfn = open("/proc/u2mfn", O_RDONLY); ring = (struct vchan_interface *) u2mfn_alloc_kpage (); if (ring == MAP_FAILED) @@ -60,17 +109,13 @@ static int ring_init(struct libvchan *ctrl) if (u2mfn_get_last_mfn (&mfn) < 0) return -1; - close(u2mfn); #endif - ctrl->ring = ring; - ctrl->ring_ref = mfn; - ring->cons_in = ring->prod_in = ring->cons_out = ring->prod_out = - 0; - ring->server_closed = ring->client_closed = 0; - ring->debug = 0xaabbccdd; - return 0; + return fill_ctrl(ctrl, ring, mfn); } + +#endif + /** creates event channel; creates "ring-ref" and "event-channel" xenstore entries; @@ -88,12 +133,16 @@ static int server_interface_init(struct libvchan *ctrl, int devno) unsigned int len; /* XXX temp hack end */ #ifdef XENCTRL_HAS_XC_INTERFACE - xc_evtchn *evfd; + xc_evtchn *evfd; #else - int evfd; + EVTCHN evfd; #endif evtchn_port_or_error_t port; +#ifdef WINNT + xs = xs_domain_open(); +#else xs = xs_daemon_open(); +#endif if (!xs) { return ret; } @@ -119,6 +168,10 @@ static int server_interface_init(struct libvchan *ctrl, int devno) if (domid_s) domid = atoi(domid_s); + snprintf(buf, sizeof buf, "device/vchan/%d/version", devno); + if (!xs_write(xs, 0, buf, "2", strlen("2"))) + goto fail2; + snprintf(ref, sizeof ref, "%d", ctrl->ring_ref); snprintf(buf, sizeof buf, "device/vchan/%d/ring-ref", devno); if (!xs_write(xs, 0, buf, ref, strlen(ref))) @@ -153,8 +206,12 @@ static int server_interface_init(struct libvchan *ctrl, int devno) if (ret) #ifdef XENCTRL_HAS_XC_INTERFACE xc_evtchn_close(evfd); +#else +#ifdef WINNT + xc_evtchn_close(evfd); #else close(evfd); +#endif #endif fail: xs_daemon_close(xs); @@ -199,20 +256,29 @@ struct libvchan *libvchan_server_init(int devno) return ctrl; } + + int libvchan_server_handle_connected(struct libvchan *ctrl) { struct xs_handle *xs; char buf[64]; int ret = -1; int libvchan_fd; - fd_set rfds; +// fd_set rfds; +#ifdef WINNT + xs = xs_domain_open(); +#else xs = xs_daemon_open(); +#endif if (!xs) { return ret; } + +#ifndef WINNT // clear the pending flag xc_evtchn_pending(ctrl->evfd); +#endif snprintf(buf, sizeof buf, "device/vchan/%d", ctrl->devno); xs_rm(xs, 0, buf); @@ -232,6 +298,8 @@ fail2: return ret; } +#ifndef WINNT + /** retrieves ring-ref and event-channel numbers from xenstore (if they don't exist, return error, because nobody seems to listen); @@ -243,14 +311,16 @@ static int client_interface_init(struct libvchan *ctrl, int domain, int devno) unsigned int len; struct xs_handle *xs; #ifdef XENCTRL_HAS_XC_INTERFACE - xc_interface *xcfd; + xc_interface *xcfd; #else int xcfd; #endif + int xcg; char buf[64]; char *ref; + int version; #ifdef XENCTRL_HAS_XC_INTERFACE - xc_evtchn *evfd; + xc_evtchn *evfd; #else int evfd; #endif @@ -259,6 +329,18 @@ static int client_interface_init(struct libvchan *ctrl, int domain, int devno) if (!xs) { return ret; } + + version = 1; + snprintf(buf, sizeof buf, + "/local/domain/%d/device/vchan/%d/version", domain, + devno); + ref = xs_read(xs, 0, buf, &len); + if (ref) { + version = atoi(ref); + free(ref); + } + + snprintf(buf, sizeof buf, "/local/domain/%d/device/vchan/%d/ring-ref", domain, devno); @@ -266,9 +348,9 @@ static int client_interface_init(struct libvchan *ctrl, int domain, int devno) if (!ref) goto fail; ctrl->ring_ref = atoi(ref); + free(ref); if (!ctrl->ring_ref) goto fail; - free(ref); snprintf(buf, sizeof buf, "/local/domain/%d/device/vchan/%d/event-channel", domain, devno); @@ -276,26 +358,43 @@ static int client_interface_init(struct libvchan *ctrl, int domain, int devno) if (!ref) goto fail; remote_port = atoi(ref); + free(ref); if (!remote_port) goto fail; - free(ref); + + switch (version) { + case 1: + #ifdef XENCTRL_HAS_XC_INTERFACE - xcfd = xc_interface_open(NULL, NULL, 0); - if (!xcfd) - goto fail; + xcfd = xc_interface_open(NULL, NULL, 0); + if (!xcfd) + goto fail; #else - xcfd = xc_interface_open(); - if (xcfd < 0) - goto fail; + xcfd = xc_interface_open(); + if (xcfd < 0) + goto fail; #endif - ctrl->ring = (struct vchan_interface *) - xc_map_foreign_range(xcfd, domain, 4096, - PROT_READ | PROT_WRITE, ctrl->ring_ref); + ctrl->ring = (struct vchan_interface *) + xc_map_foreign_range(xcfd, domain, 4096, + PROT_READ | PROT_WRITE, ctrl->ring_ref); #ifdef XENCTRL_HAS_XC_INTERFACE - xc_interface_close(xcfd); + xc_interface_close(xcfd); #else - close(xcfd); + close(xcfd); #endif + break; + case 2: + xcg = xc_gnttab_open(); + if (xcg < 0) + goto fail; + ctrl->ring = (struct vchan_interface *) + xc_gnttab_map_grant_ref(xcg, domain, ctrl->ring_ref, PROT_READ | PROT_WRITE); + xc_gnttab_close(xcg); + break; + default: + goto fail; + } + if (ctrl->ring == 0 || ctrl->ring == MAP_FAILED) goto fail; #ifdef XENCTRL_HAS_XC_INTERFACE @@ -314,7 +413,7 @@ static int client_interface_init(struct libvchan *ctrl, int domain, int devno) #ifdef XENCTRL_HAS_XC_INTERFACE xc_evtchn_close(evfd); #else - close(evfd); + close(evfd); #endif else ret = 0; @@ -340,3 +439,14 @@ struct libvchan *libvchan_client_init(int domain, int devno) ctrl->is_server = 0; return ctrl; } + +#else + +// Windows domains can not be dom0 + +struct libvchan *libvchan_client_init(int domain, int devno) +{ + return NULL; +} + +#endif \ No newline at end of file diff --git a/vchan/io.c b/vchan/io.c index 23135a25..e735c86a 100644 --- a/vchan/io.c +++ b/vchan/io.c @@ -20,10 +20,15 @@ */ #include "libvchan.h" + +#ifndef WINNT #include -#include #include #include +#endif + +#include + /** \return How much data is immediately available for reading */ @@ -66,6 +71,22 @@ int libvchan_is_eof(struct libvchan *ctrl) /** \return -1 return value means peer has closed */ + +#ifdef WINNT +int libvchan_wait(struct libvchan *ctrl) +{ + int ret; + + ret = xc_evtchn_pending(ctrl->evfd); + if (ret!=-1 && xc_evtchn_unmask(ctrl->evfd, ctrl->evport)) + return -1; + if (ret!=-1 && libvchan_is_eof(ctrl)) + return -1; + return ret; +} + +#else + int libvchan_wait(struct libvchan *ctrl) { int ret; @@ -93,6 +114,7 @@ int libvchan_wait(struct libvchan *ctrl) return -1; return ret; } +#endif /** may sleep (only if no buffer space available); @@ -166,7 +188,7 @@ int libvchan_close(struct libvchan *ctrl) } /// The fd to use for select() set -int libvchan_fd_for_select(struct libvchan *ctrl) +EVTCHN libvchan_fd_for_select(struct libvchan *ctrl) { return xc_evtchn_fd(ctrl->evfd); } diff --git a/vchan/libvchan.h b/vchan/libvchan.h index 3f647462..63ab6e9f 100644 --- a/vchan/libvchan.h +++ b/vchan/libvchan.h @@ -22,7 +22,18 @@ #ifndef _LIBVCHAN_H #define _LIBVCHAN_H +#ifdef WINNT +#include +#include +#include +typedef HANDLE EVTCHN; +#define snprintf _snprintf +#else #include +typedef int EVTCHN; +#endif + + #include typedef uint32_t VCHAN_RING_IDX; @@ -42,9 +53,9 @@ struct libvchan { uint32_t ring_ref; /// descriptor to event channel interface #ifdef XENCTRL_HAS_XC_INTERFACE - xc_evtchn *evfd; + xc_evtchn *evfd; #else - int evfd; + EVTCHN evfd; #endif int evport; int devno; @@ -55,16 +66,16 @@ struct libvchan { }; struct libvchan *libvchan_server_init(int devno); -int libvchan_server_handle_connected(struct libvchan *ctrl); struct libvchan *libvchan_client_init(int domain, int devno); +int libvchan_server_handle_connected(struct libvchan *ctrl); int libvchan_write(struct libvchan *ctrl, char *data, int size); int libvchan_read(struct libvchan *ctrl, char *data, int size); int libvchan_wait(struct libvchan *ctrl); int libvchan_close(struct libvchan *ctrl); void libvchan_prepare_to_select(struct libvchan *ctrl); -int libvchan_fd_for_select(struct libvchan *ctrl); +EVTCHN libvchan_fd_for_select(struct libvchan *ctrl); int libvchan_is_eof(struct libvchan *ctrl); int libvchan_data_ready(struct libvchan *ctrl); int libvchan_buffer_space(struct libvchan *ctrl); diff --git a/vchan/sources b/vchan/sources new file mode 100644 index 00000000..1baae972 --- /dev/null +++ b/vchan/sources @@ -0,0 +1,24 @@ +TARGETNAME=libvchan +TARGETTYPE=LIBRARY +TARGETPATH=..\win\libs + +#BUILD_PASS0_CONSUMES=gntmem evtchn xenstore +#BUILD_PASS0_PRODUCES=vchan + +USE_MSVCRT=1 + +DLLDEF=libvchan.def + +C_DEFINES = $(C_DEFINES) /DCONFIG_STUBDOM + +INCLUDES=$(INCLUDES); \ + ..\win\include;\ + +SOURCES=io.c init.c + +TARGETLIBS=\ + $(SDK_LIB_PATH)\setupapi.lib \ + $(SDK_LIB_PATH)\kernel32.lib + + +