win-pvdrivers

diff xenpci/xenbus.c @ 0:435e5753300f

Initial upload of files
author James Harper <james.harper@bendigoit.com.au>
date Sat Nov 10 14:40:56 2007 +1100 (2007-11-10)
parents
children 8f643f8e229b
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xenpci/xenbus.c	Sat Nov 10 14:40:56 2007 +1100
     1.3 @@ -0,0 +1,788 @@
     1.4 +/*
     1.5 +PV Drivers for Windows Xen HVM Domains
     1.6 +Copyright (C) 2007 James Harper
     1.7 +
     1.8 +This program is free software; you can redistribute it and/or
     1.9 +modify it under the terms of the GNU General Public License
    1.10 +as published by the Free Software Foundation; either version 2
    1.11 +of the License, or (at your option) any later version.
    1.12 +
    1.13 +This program is distributed in the hope that it will be useful,
    1.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.16 +GNU General Public License for more details.
    1.17 +
    1.18 +You should have received a copy of the GNU General Public License
    1.19 +along with this program; if not, write to the Free Software
    1.20 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    1.21 +*/
    1.22 +
    1.23 +#include "xenpci.h"
    1.24 +#include "io/xs_wire.h"
    1.25 +#include <stdlib.h>
    1.26 +
    1.27 +#pragma warning( disable : 4204 ) 
    1.28 +#pragma warning( disable : 4221 ) 
    1.29 +
    1.30 +struct xenbus_req_info
    1.31 +{
    1.32 +  int In_Use:1;
    1.33 +  KEVENT WaitEvent;
    1.34 +  void *Reply;
    1.35 +};
    1.36 +
    1.37 +typedef struct {
    1.38 +  char Path[128];
    1.39 +  PXENBUS_WATCH_CALLBACK ServiceRoutine;
    1.40 +  PVOID ServiceContext;
    1.41 +  int Count;
    1.42 +  int Active;
    1.43 +} XENBUS_WATCH_ENTRY, *PXENBUS_WATCH_ENTRY;
    1.44 +
    1.45 +typedef struct {
    1.46 +  char Path[128];
    1.47 +  char Token[10];
    1.48 +} XENBUS_WATCH_RING;
    1.49 +
    1.50 +#define WATCH_RING_SIZE 128
    1.51 +
    1.52 +static XENBUS_WATCH_RING XenBus_WatchRing[WATCH_RING_SIZE];
    1.53 +static int XenBus_WatchRingReadIndex;
    1.54 +static int XenBus_WatchRingWriteIndex;
    1.55 +
    1.56 +#define MAX_WATCH_ENTRIES 128
    1.57 +
    1.58 +static XENBUS_WATCH_ENTRY XenBus_WatchEntries[MAX_WATCH_ENTRIES];
    1.59 +
    1.60 +#define NR_REQS 32
    1.61 +//#define XENSTORE_RING_SIZE 1024
    1.62 +
    1.63 +//#define XENSTORE_RING_SIZE 1024
    1.64 +//typedef uint32_t XENSTORE_RING_IDX;
    1.65 +//#define MASK_XENSTORE_IDX(idx) ((idx) & (XENSTORE_RING_SIZE-1))
    1.66 +
    1.67 +static struct xenstore_domain_interface *xen_store_interface;
    1.68 +
    1.69 +static struct xenbus_req_info req_info[NR_REQS];
    1.70 +static int nr_live_reqs;
    1.71 +//static spinlock_t req_lock = SPIN_LOCK_UNLOCKED;
    1.72 +
    1.73 +static HANDLE XenBus_ReadThreadHandle;
    1.74 +static KEVENT XenBus_ReadThreadEvent;
    1.75 +
    1.76 +static HANDLE XenBus_WatchThreadHandle;
    1.77 +static KEVENT XenBus_WatchThreadEvent;
    1.78 +
    1.79 +static void
    1.80 +XenBus_ReadThreadProc(PVOID StartContext);
    1.81 +static void
    1.82 +XenBus_WatchThreadProc(PVOID StartContext);
    1.83 +
    1.84 +static BOOLEAN
    1.85 +XenBus_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext);
    1.86 +
    1.87 +static int allocate_xenbus_id(void)
    1.88 +{
    1.89 +  static int probe;
    1.90 +  int o_probe;
    1.91 +
    1.92 +  //KdPrint((__DRIVER_NAME " --> allocate_xenbus_id\n"));
    1.93 +
    1.94 +  for (;;)
    1.95 +  {
    1.96 +//    spin_lock(&req_lock);
    1.97 +    if (nr_live_reqs < NR_REQS)
    1.98 +      break;
    1.99 +//    spin_unlock(&req_lock);
   1.100 +//    wait_event(req_wq, (nr_live_reqs < NR_REQS));
   1.101 +  }
   1.102 +
   1.103 +  o_probe = probe;
   1.104 +
   1.105 +  for (;;)
   1.106 +  {
   1.107 +    if (!req_info[o_probe].In_Use)
   1.108 +      break;
   1.109 +    o_probe = (o_probe + 1) % NR_REQS;
   1.110 +//    BUG_ON(o_probe == probe);
   1.111 +  }
   1.112 +  nr_live_reqs++;
   1.113 +  req_info[o_probe].In_Use = 1;
   1.114 +  probe = (o_probe + 1) % NR_REQS;
   1.115 +  //spin_unlock(&req_lock);
   1.116 +  //init_waitqueue_head(&req_info[o_probe].waitq);
   1.117 +  KeInitializeEvent(&req_info[o_probe].WaitEvent, SynchronizationEvent, FALSE);
   1.118 +
   1.119 +  //KdPrint((__DRIVER_NAME " <-- allocate_xenbus_id\n"));
   1.120 +
   1.121 +  return o_probe;
   1.122 +}
   1.123 +
   1.124 +static void release_xenbus_id(int id)
   1.125 +{
   1.126 +//    BUG_ON(!req_info[id].in_use);
   1.127 +//    spin_lock(&req_lock);
   1.128 +    req_info[id].In_Use = 0;
   1.129 +    nr_live_reqs--;
   1.130 +    req_info[id].In_Use = 0;
   1.131 +//    if (nr_live_reqs == NR_REQS - 1)
   1.132 +//        wake_up(&req_wq);
   1.133 +//    spin_unlock(&req_lock);
   1.134 +}
   1.135 +
   1.136 +
   1.137 +static char *errmsg(struct xsd_sockmsg *rep)
   1.138 +{
   1.139 +  char *res;
   1.140 +  if (!rep) {
   1.141 +    char msg[] = "No reply";
   1.142 +    size_t len = strlen(msg) + 1;
   1.143 +    return memcpy(ExAllocatePoolWithTag(NonPagedPool, len, XENPCI_POOL_TAG), msg, len);
   1.144 +  }
   1.145 +  if (rep->type != XS_ERROR)
   1.146 +    return NULL;
   1.147 +  res = ExAllocatePoolWithTag(NonPagedPool, rep->len + 1, XENPCI_POOL_TAG);
   1.148 +  memcpy(res, rep + 1, rep->len);
   1.149 +  res[rep->len] = 0;
   1.150 +  ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
   1.151 +  return res;
   1.152 +}
   1.153 +
   1.154 +static void memcpy_from_ring(const void *Ring,
   1.155 +        void *Dest,
   1.156 +        int off,
   1.157 +        int len)
   1.158 +{
   1.159 +  int c1, c2;
   1.160 +  const char *ring = Ring;
   1.161 +  char *dest = Dest;
   1.162 +  c1 = min(len, XENSTORE_RING_SIZE - off);
   1.163 +  c2 = len - c1;
   1.164 +  memcpy(dest, ring + off, c1);
   1.165 +  memcpy(dest + c1, ring, c2);
   1.166 +}
   1.167 +
   1.168 +void wait_for_watch(void)
   1.169 +{
   1.170 +//    DEFINE_WAIT(w);
   1.171 +//    add_waiter(w,watch_queue);
   1.172 +//    schedule();
   1.173 +//    remove_waiter(w);
   1.174 +//    wake(current);
   1.175 +}
   1.176 +
   1.177 +struct write_req {
   1.178 +    const void *data;
   1.179 +    unsigned len;
   1.180 +};
   1.181 +
   1.182 +static evtchn_port_t xen_store_evtchn;
   1.183 +
   1.184 +static void xb_write(int type, int req_id, xenbus_transaction_t trans_id,
   1.185 +                     const struct write_req *req, int nr_reqs)
   1.186 +{
   1.187 +  XENSTORE_RING_IDX prod;
   1.188 +  int r;
   1.189 +  size_t len = 0;
   1.190 +  const struct write_req *cur_req;
   1.191 +  size_t req_off;
   1.192 +  size_t total_off;
   1.193 +  size_t this_chunk;
   1.194 +  struct xsd_sockmsg m = {type, req_id, trans_id };
   1.195 +  struct write_req header_req = { &m, sizeof(m) };
   1.196 +
   1.197 +  //KdPrint((__DRIVER_NAME " --> xb_write\n"));
   1.198 +
   1.199 +  for (r = 0; r < nr_reqs; r++)
   1.200 +    len += req[r].len;
   1.201 +  m.len = len;
   1.202 +  len += sizeof(m);
   1.203 +
   1.204 +  cur_req = &header_req;
   1.205 +
   1.206 +//  BUG_ON(len > XENSTORE_RING_SIZE);
   1.207 +  /* Wait for the ring to drain to the point where we can send the
   1.208 +     message. */
   1.209 +  prod = xen_store_interface->req_prod;
   1.210 +
   1.211 +  //KdPrint((__DRIVER_NAME " prod = %08x\n", prod));
   1.212 +
   1.213 +  if (prod + len - xen_store_interface->req_cons > XENSTORE_RING_SIZE)
   1.214 +  {
   1.215 +    /* Wait for there to be space on the ring */
   1.216 +    //KdPrint((__DRIVER_NAME " prod %d, len %d, cons %d, size %d; waiting.\n", prod, len, xen_store_interface->req_cons, XENSTORE_RING_SIZE));
   1.217 +//    wait_event(xb_waitq, xen_store_interface->req_prod + len - xen_store_interface->req_cons <= XENSTORE_RING_SIZE);
   1.218 +    //KdPrint((__DRIVER_NAME " Back from wait.\n"));
   1.219 +    prod = xen_store_interface->req_prod;
   1.220 +  }
   1.221 +
   1.222 +  /* We're now guaranteed to be able to send the message without
   1.223 +     overflowing the ring.  Do so. */
   1.224 +
   1.225 +  total_off = 0;
   1.226 +  req_off = 0;
   1.227 +
   1.228 +  while (total_off < len)
   1.229 +  {
   1.230 +    this_chunk = min(cur_req->len - req_off,XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
   1.231 +    memcpy((char *)xen_store_interface->req + MASK_XENSTORE_IDX(prod), (char *)cur_req->data + req_off, this_chunk);
   1.232 +    prod += this_chunk;
   1.233 +    req_off += this_chunk;
   1.234 +    total_off += this_chunk;
   1.235 +    if (req_off == cur_req->len)
   1.236 +    {
   1.237 +      req_off = 0;
   1.238 +      if (cur_req == &header_req)
   1.239 +        cur_req = req;
   1.240 +      else
   1.241 +        cur_req++;
   1.242 +    }
   1.243 +  }
   1.244 +
   1.245 +  //KdPrint((__DRIVER_NAME " Complete main loop of xb_write.\n"));
   1.246 +
   1.247 +//  BUG_ON(req_off != 0);
   1.248 +//  BUG_ON(total_off != len);
   1.249 +//  BUG_ON(prod > xen_store_interface->req_cons + XENSTORE_RING_SIZE);
   1.250 +
   1.251 +  /* Remote must see entire message before updating indexes */
   1.252 +  //_WriteBarrier();
   1.253 +  KeMemoryBarrier();
   1.254 +
   1.255 +  xen_store_interface->req_prod += len;
   1.256 +
   1.257 +  //KdPrint((__DRIVER_NAME " prod = %08x\n", xen_store_interface->req_prod));
   1.258 +
   1.259 +  /* Send evtchn to notify remote */
   1.260 +  EvtChn_Notify(xen_store_evtchn);
   1.261 +
   1.262 +  //KdPrint((__DRIVER_NAME " <-- xb_write\n"));
   1.263 +}
   1.264 +
   1.265 +static struct xsd_sockmsg *
   1.266 +xenbus_msg_reply(int type,
   1.267 +                 xenbus_transaction_t trans,
   1.268 +                 struct write_req *io,
   1.269 +                 int nr_reqs)
   1.270 +{
   1.271 +  int id;
   1.272 +//  DEFINE_WAIT(w);
   1.273 +  struct xsd_sockmsg *rep;
   1.274 +
   1.275 +  //KdPrint((__DRIVER_NAME " --> xenbus_msg_reply\n"));
   1.276 +
   1.277 +  id = allocate_xenbus_id();
   1.278 +//  add_waiter(w, req_info[id].waitq);
   1.279 +
   1.280 +  xb_write(type, id, trans, io, nr_reqs);
   1.281 +//
   1.282 +//  schedule();
   1.283 +//  remove_waiter(w);
   1.284 +//  wake(current);
   1.285 +//
   1.286 +  //KdPrint((__DRIVER_NAME "     starting wait\n"));
   1.287 +
   1.288 +  KeWaitForSingleObject(&req_info[id].WaitEvent, Executive, KernelMode, FALSE, NULL);
   1.289 +
   1.290 +  //KdPrint((__DRIVER_NAME "     wait complete\n"));
   1.291 +
   1.292 +  rep = req_info[id].Reply;
   1.293 +//  BUG_ON(rep->req_id != id);
   1.294 +  release_xenbus_id(id);
   1.295 +  //KdPrint((__DRIVER_NAME " <-- xenbus_msg_reply\n"));
   1.296 +  return rep;
   1.297 +//  return NULL;
   1.298 +}
   1.299 +
   1.300 +char *
   1.301 +XenBus_Read(xenbus_transaction_t xbt, const char *path, char **value)
   1.302 +{
   1.303 +    struct write_req req[] = { {path, strlen(path) + 1} };
   1.304 +    struct xsd_sockmsg *rep;
   1.305 +    char *res;
   1.306 +    char *msg;
   1.307 +
   1.308 +    rep = xenbus_msg_reply(XS_READ, xbt, req, ARRAY_SIZE(req));
   1.309 +    msg = errmsg(rep);
   1.310 +    if (msg) {
   1.311 +      *value = NULL;
   1.312 +      return msg;
   1.313 +    }
   1.314 +    res = ExAllocatePoolWithTag(NonPagedPool, rep->len + 1, XENPCI_POOL_TAG);
   1.315 +    memcpy(res, rep + 1, rep->len);
   1.316 +    res[rep->len] = 0;
   1.317 +    ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
   1.318 +    *value = res;
   1.319 +    return NULL;
   1.320 +}
   1.321 +
   1.322 +char *
   1.323 +XenBus_Write(xenbus_transaction_t xbt, const char *path, const char *value)
   1.324 +{
   1.325 +    struct write_req req[] = {
   1.326 +        {path, strlen(path) + 1},
   1.327 +        {value, strlen(value) + 1},
   1.328 +    };
   1.329 +    struct xsd_sockmsg *rep;
   1.330 +    char *msg;
   1.331 +
   1.332 +    rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req));
   1.333 +    msg = errmsg(rep);
   1.334 +    if (msg)
   1.335 +      return msg;
   1.336 +    ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
   1.337 +    return NULL;
   1.338 +}
   1.339 +
   1.340 +char* xenbus_wait_for_value(const char* path,const char* value)
   1.341 +{
   1.342 +  UNREFERENCED_PARAMETER(path);
   1.343 +  UNREFERENCED_PARAMETER(value);
   1.344 +//  for(;;)
   1.345 +//  {
   1.346 +//    char *res, *msg;
   1.347 +//    int r;
   1.348 +//
   1.349 +//    msg = xenbus_read(XBT_NIL, path, &res);
   1.350 +//    if(msg) return msg;
   1.351 +//
   1.352 +//    r = strcmp(value,res);
   1.353 +//    ExFreePoolWithTag(res, XENPCI_POOL_TAG);
   1.354 +//
   1.355 +//    if(r==0)
   1.356 +//      break;
   1.357 +//    else
   1.358 +//      wait_for_watch();
   1.359 +//    }
   1.360 +    return NULL;
   1.361 +}
   1.362 +
   1.363 +NTSTATUS
   1.364 +XenBus_Init()
   1.365 +{
   1.366 +  //KdPrint((__DRIVER_NAME " --> XenBus_Init\n"));
   1.367 +
   1.368 +  xen_store_evtchn = EvtChn_GetXenStorePort();
   1.369 +  xen_store_interface = EvtChn_GetXenStoreRingAddr();
   1.370 +
   1.371 +  //KdPrint((__DRIVER_NAME "     xen_store_evtchn = %08x\n", xen_store_evtchn));
   1.372 +  //KdPrint((__DRIVER_NAME "     xen_store_interface = %08x\n", xen_store_interface));
   1.373 +
   1.374 +  KeInitializeEvent(&XenBus_ReadThreadEvent, SynchronizationEvent, FALSE);
   1.375 +  KeInitializeEvent(&XenBus_WatchThreadEvent, SynchronizationEvent, FALSE);
   1.376 +
   1.377 +  //KdPrint((__DRIVER_NAME " <-- XenBus_Init\n"));
   1.378 +
   1.379 +  return STATUS_SUCCESS;
   1.380 +}
   1.381 +
   1.382 +NTSTATUS
   1.383 +XenBus_Start()
   1.384 +{
   1.385 +  OBJECT_ATTRIBUTES oa;
   1.386 +  NTSTATUS status;
   1.387 +  int i;
   1.388 +
   1.389 +  //KdPrint((__DRIVER_NAME " --> XenBus_Start\n"));
   1.390 +
   1.391 +  InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
   1.392 +  status = PsCreateSystemThread(&XenBus_ReadThreadHandle, THREAD_ALL_ACCESS, &oa, NULL, NULL, XenBus_ReadThreadProc, NULL);
   1.393 +
   1.394 +  // remove all existing watches already in Xen too...
   1.395 +
   1.396 +  for (i = 0; i < MAX_WATCH_ENTRIES; i++)
   1.397 +    XenBus_WatchEntries[i].Active = 0;
   1.398 +
   1.399 +  InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
   1.400 +  status = PsCreateSystemThread(&XenBus_WatchThreadHandle, THREAD_ALL_ACCESS, &oa, NULL, NULL, XenBus_WatchThreadProc, NULL);
   1.401 +
   1.402 +  EvtChn_Bind(xen_store_evtchn, XenBus_Interrupt, NULL);
   1.403 +
   1.404 +  //KdPrint((__DRIVER_NAME " <-- XenBus_Start\n"));
   1.405 +
   1.406 +  return STATUS_SUCCESS;
   1.407 +}
   1.408 +
   1.409 +NTSTATUS
   1.410 +XenBus_Stop()
   1.411 +{
   1.412 +  int i;
   1.413 +
   1.414 +  for (i = 0; i < MAX_WATCH_ENTRIES; i++)
   1.415 +  {
   1.416 +    if (!XenBus_WatchEntries[i].Active)
   1.417 +      continue;
   1.418 +    XenBus_RemWatch(XBT_NIL, XenBus_WatchEntries[i].Path, XenBus_WatchEntries[i].ServiceRoutine, XenBus_WatchEntries[i].ServiceContext);
   1.419 +  }
   1.420 +
   1.421 +  EvtChn_Unbind(xen_store_evtchn);
   1.422 +
   1.423 +  // Does this actually stop the threads???
   1.424 +  ZwClose(XenBus_WatchThreadHandle);
   1.425 +  ZwClose(XenBus_ReadThreadHandle);
   1.426 +
   1.427 +  return STATUS_SUCCESS;
   1.428 +}
   1.429 +
   1.430 +char *
   1.431 +XenBus_List(xenbus_transaction_t xbt, const char *pre, char ***contents)
   1.432 +{
   1.433 +  struct xsd_sockmsg *reply, *repmsg;
   1.434 +  struct write_req req[] = { { pre, strlen(pre)+1 } };
   1.435 +  ULONG nr_elems, x, i;
   1.436 +  char **res;
   1.437 +  char *msg;
   1.438 +
   1.439 +  //KdPrint((__DRIVER_NAME " --> xenbus_ls\n"));
   1.440 +
   1.441 +  repmsg = xenbus_msg_reply(XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
   1.442 +  msg = errmsg(repmsg);
   1.443 +  if (msg) {
   1.444 +    *contents = NULL;
   1.445 +    //KdPrint((__DRIVER_NAME " <-- xenbus_ls (error)\n"));
   1.446 +    return msg;
   1.447 +  }
   1.448 +  reply = repmsg + 1;
   1.449 +  for (x = nr_elems = 0; x < repmsg->len; x++)
   1.450 +    nr_elems += (((char *)reply)[x] == 0);
   1.451 +  res = ExAllocatePoolWithTag(NonPagedPool, sizeof(res[0]) * (nr_elems + 1), XENPCI_POOL_TAG);
   1.452 +  for (x = i = 0; i < nr_elems; i++) {
   1.453 +    int l = strlen((char *)reply + x);
   1.454 +    res[i] = ExAllocatePoolWithTag(NonPagedPool, l + 1, XENPCI_POOL_TAG);
   1.455 +    memcpy(res[i], (char *)reply + x, l + 1);
   1.456 +    x += l + 1;
   1.457 +  }
   1.458 +  res[i] = NULL;
   1.459 +  ExFreePoolWithTag(repmsg, XENPCI_POOL_TAG);
   1.460 +  *contents = res;
   1.461 +  //KdPrint((__DRIVER_NAME " <-- xenbus_ls\n"));
   1.462 +  return NULL;
   1.463 +}
   1.464 +
   1.465 +void
   1.466 +do_ls_test(const char *pre)
   1.467 +{
   1.468 +  char **dirs;
   1.469 +  int x;
   1.470 +  char *msg;
   1.471 +
   1.472 +  //KdPrint((__DRIVER_NAME " <-- do_ls_test(\"%s\")\n", pre));
   1.473 +
   1.474 +  msg = XenBus_List(XBT_NIL, pre, &dirs);
   1.475 +  if (msg)
   1.476 +  {
   1.477 +    //KdPrint((__DRIVER_NAME "     Error in xenbus ls: %s\n", msg));
   1.478 +    ExFreePoolWithTag(msg, XENPCI_POOL_TAG);
   1.479 +    return;
   1.480 +  }
   1.481 +  for (x = 0; dirs[x]; x++)
   1.482 +  {
   1.483 +    //KdPrint((__DRIVER_NAME "     ls %s[%d] -> %s\n", pre, x, dirs[x]));
   1.484 +    ExFreePoolWithTag(dirs[x], XENPCI_POOL_TAG);
   1.485 +  }
   1.486 +  ExFreePoolWithTag(dirs, XENPCI_POOL_TAG);
   1.487 +  //KdPrint((__DRIVER_NAME " --> do_ls_test\n"));
   1.488 +}
   1.489 +
   1.490 +int ReadThreadSetCount;
   1.491 +int ReadThreadWaitCount;
   1.492 +
   1.493 +static void
   1.494 +XenBus_ReadThreadProc(PVOID StartContext) {
   1.495 +  int NewWriteIndex;
   1.496 +  struct xsd_sockmsg msg;
   1.497 +  char *payload;
   1.498 +  char *path, *token;
   1.499 +
   1.500 +  UNREFERENCED_PARAMETER(StartContext);
   1.501 +
   1.502 +  for(;;)
   1.503 +  {
   1.504 +    KeWaitForSingleObject(&XenBus_ReadThreadEvent, Executive, KernelMode, FALSE, NULL);
   1.505 +    //KdPrint((__DRIVER_NAME "     ReadThread Woken (Count = %d)\n", ReadThreadWaitCount++));
   1.506 +    while (xen_store_interface->rsp_prod != xen_store_interface->rsp_cons)
   1.507 +    {
   1.508 +      //KdPrint((__DRIVER_NAME "     a - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
   1.509 +      if (xen_store_interface->rsp_prod - xen_store_interface->rsp_cons < sizeof(msg))
   1.510 +      {
   1.511 +        //KdPrint((__DRIVER_NAME " +++ Message incomplete (not even a full header)\n"));
   1.512 +        break;
   1.513 +      }
   1.514 +      //_ReadBarrier();
   1.515 +      KeMemoryBarrier();
   1.516 +      memcpy_from_ring(xen_store_interface->rsp, &msg, MASK_XENSTORE_IDX(xen_store_interface->rsp_cons), sizeof(msg));
   1.517 +      if (xen_store_interface->rsp_prod - xen_store_interface->rsp_cons < sizeof(msg) + msg.len)
   1.518 +      {
   1.519 +        //KdPrint((__DRIVER_NAME " +++ Message incomplete (header but not full body)\n"));
   1.520 +        break;
   1.521 +      }
   1.522 +  
   1.523 +      if(msg.type == XS_WATCH_EVENT)
   1.524 +      {
   1.525 +        payload = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
   1.526 +  
   1.527 +        memcpy_from_ring(xen_store_interface->rsp, payload, MASK_XENSTORE_IDX(xen_store_interface->rsp_cons), msg.len + sizeof(msg));
   1.528 +  
   1.529 +        xen_store_interface->rsp_cons += msg.len + sizeof(msg);
   1.530 +        //KdPrint((__DRIVER_NAME "     b - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
   1.531 +  
   1.532 +        path = payload + sizeof(msg);
   1.533 +        token = path + strlen(path) + 1;
   1.534 +
   1.535 +        NewWriteIndex = (XenBus_WatchRingWriteIndex + 1) & 127;
   1.536 +        if (NewWriteIndex != XenBus_WatchRingReadIndex)
   1.537 +        {
   1.538 +          strncpy(XenBus_WatchRing[NewWriteIndex].Path, path, 128);
   1.539 +          strncpy(XenBus_WatchRing[NewWriteIndex].Token, token, 10);
   1.540 +          XenBus_WatchRingWriteIndex = NewWriteIndex;
   1.541 +        }
   1.542 +        else
   1.543 +        {
   1.544 +          KdPrint((__DRIVER_NAME " +++ Queue full Path = %s Token = %s\n", path, token));
   1.545 +          // drop the message on the floor
   1.546 +          continue;
   1.547 +        }
   1.548 +
   1.549 +        ExFreePoolWithTag(payload, XENPCI_POOL_TAG);
   1.550 +        //KdPrint((__DRIVER_NAME " +++ Watch Path = %s Token = %s\n", path, token));
   1.551 +        KeSetEvent(&XenBus_WatchThreadEvent, 1, FALSE);
   1.552 +      }
   1.553 +      else
   1.554 +      {  
   1.555 +        req_info[msg.req_id].Reply = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
   1.556 +        memcpy_from_ring(xen_store_interface->rsp, req_info[msg.req_id].Reply, MASK_XENSTORE_IDX(xen_store_interface->rsp_cons), msg.len + sizeof(msg));
   1.557 +        xen_store_interface->rsp_cons += msg.len + sizeof(msg);
   1.558 +        //KdPrint((__DRIVER_NAME "     c - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
   1.559 +        //KdPrint((__DRIVER_NAME " +++ Message = %s\n", ((char *)req_info[msg.req_id].Reply) + sizeof(msg)));
   1.560 +        KeSetEvent(&req_info[msg.req_id].WaitEvent, 1, FALSE);
   1.561 +      }
   1.562 +    }
   1.563 +  }
   1.564 +}
   1.565 +
   1.566 +static void
   1.567 +XenBus_WatchThreadProc(PVOID StartContext)
   1.568 +{
   1.569 +  int index;
   1.570 +  PXENBUS_WATCH_ENTRY entry;
   1.571 +
   1.572 +  UNREFERENCED_PARAMETER(StartContext);
   1.573 +
   1.574 +  for(;;)
   1.575 +  {
   1.576 +    KeWaitForSingleObject(&XenBus_WatchThreadEvent, Executive, KernelMode, FALSE, NULL);
   1.577 +    while (XenBus_WatchRingReadIndex != XenBus_WatchRingWriteIndex)
   1.578 +    {
   1.579 +      XenBus_WatchRingReadIndex = (XenBus_WatchRingReadIndex + 1) & 127;
   1.580 +      index = atoi(XenBus_WatchRing[XenBus_WatchRingReadIndex].Token);
   1.581 +      //XenBus_WatchRing[XenBus_WatchRingReadIndex].Path
   1.582 +      //XenBus_WatchRing[XenBus_WatchRingReadIndex].Token
   1.583 +
   1.584 +      entry = &XenBus_WatchEntries[index];
   1.585 +      if (!entry->Active)
   1.586 +      {
   1.587 +        KdPrint((__DRIVER_NAME " +++ Watch not active! = %s Token = %s\n", XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, XenBus_WatchRing[XenBus_WatchRingReadIndex].Token));
   1.588 +        continue;
   1.589 +      }
   1.590 +      entry->Count++;
   1.591 +      if (!entry->ServiceRoutine)
   1.592 +      {
   1.593 +        KdPrint((__DRIVER_NAME " +++ no handler for watch! = %s Token = %s\n", XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, XenBus_WatchRing[XenBus_WatchRingReadIndex].Token));
   1.594 +        continue;
   1.595 +      }
   1.596 +      //KdPrint((__DRIVER_NAME " +++ Watch Triggered Path = %s Token = %d (%s)\n", XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, index, XenBus_WatchRing[XenBus_WatchRingReadIndex].Token));
   1.597 +      entry->ServiceRoutine(XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, entry->ServiceContext);
   1.598 +    }
   1.599 +  }
   1.600 +}    
   1.601 +
   1.602 +char *
   1.603 +XenBus_AddWatch(xenbus_transaction_t xbt, const char *Path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
   1.604 +{
   1.605 +  struct xsd_sockmsg *rep;
   1.606 +  char *msg;
   1.607 +  int i;
   1.608 +  char Token[20];
   1.609 +  struct write_req req[2];
   1.610 +
   1.611 +  //KdPrint((__DRIVER_NAME " --> XenBus_AddWatch\n"));
   1.612 +
   1.613 +  // check that Path < 128 chars
   1.614 +
   1.615 +  for (i = 0; i < MAX_WATCH_ENTRIES; i++)
   1.616 +    if (XenBus_WatchEntries[i].Active == 0)
   1.617 +      break;
   1.618 +  
   1.619 +  if (i == MAX_WATCH_ENTRIES)
   1.620 +  {
   1.621 +    KdPrint((__DRIVER_NAME " +++ No more watch slots left\n"));
   1.622 +    return NULL;
   1.623 +  }
   1.624 +
   1.625 +  req[0].data = Path;
   1.626 +  req[0].len = strlen(Path) + 1;
   1.627 +
   1.628 +  RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", i);
   1.629 +  req[1].data = Token;
   1.630 +  req[1].len = strlen(Token) + 1;
   1.631 +
   1.632 +  rep = xenbus_msg_reply(XS_WATCH, xbt, req, ARRAY_SIZE(req));
   1.633 +
   1.634 +  msg = errmsg(rep);
   1.635 +  if (msg)
   1.636 +    return msg;
   1.637 +
   1.638 +  ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
   1.639 +
   1.640 +  strncpy(XenBus_WatchEntries[i].Path, Path, 128);
   1.641 +  XenBus_WatchEntries[i].ServiceRoutine = ServiceRoutine;
   1.642 +  XenBus_WatchEntries[i].ServiceContext = ServiceContext;
   1.643 +  XenBus_WatchEntries[i].Count = 0;
   1.644 +  XenBus_WatchEntries[i].Active = 1;
   1.645 +
   1.646 +  //KdPrint((__DRIVER_NAME " <-- XenBus_AddWatch\n"));
   1.647 +
   1.648 +  return NULL;
   1.649 +}
   1.650 +
   1.651 +char *
   1.652 +XenBus_RemWatch(xenbus_transaction_t xbt, const char *Path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
   1.653 +{
   1.654 +  struct xsd_sockmsg *rep;
   1.655 +  char *msg;
   1.656 +  int i;
   1.657 +  char Token[20];
   1.658 +  struct write_req req[2];
   1.659 +
   1.660 +  //KdPrint((__DRIVER_NAME " --> XenBus_RemWatch\n"));
   1.661 +
   1.662 +  // check that Path < 128 chars
   1.663 +
   1.664 +  for (i = 0; i < MAX_WATCH_ENTRIES; i++) {
   1.665 +    if (XenBus_WatchEntries[i].Active == 1 && strcmp(XenBus_WatchEntries[i].Path, Path) == 0 && XenBus_WatchEntries[i].ServiceRoutine == ServiceRoutine && XenBus_WatchEntries[i].ServiceContext == ServiceContext)
   1.666 +      break;
   1.667 +  }
   1.668 +
   1.669 +  if (i == MAX_WATCH_ENTRIES)
   1.670 +  {
   1.671 +    KdPrint((__DRIVER_NAME "     Watch not set - can't remove\n"));
   1.672 +    return NULL;
   1.673 +  }
   1.674 +
   1.675 +  req[0].data = Path;
   1.676 +  req[0].len = strlen(Path) + 1;
   1.677 +
   1.678 +  RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", i);
   1.679 +  req[1].data = Token;
   1.680 +  req[1].len = strlen(Token) + 1;
   1.681 +
   1.682 +  rep = xenbus_msg_reply(XS_UNWATCH, xbt, req, ARRAY_SIZE(req));
   1.683 +
   1.684 +  msg = errmsg(rep);
   1.685 +  if (msg)
   1.686 +    return msg;
   1.687 +
   1.688 +  ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
   1.689 +
   1.690 +  XenBus_WatchEntries[i].Active = 0;
   1.691 +
   1.692 +  //KdPrint((__DRIVER_NAME " <-- XenBus_RemWatch\n"));
   1.693 +
   1.694 +  return NULL;
   1.695 +}
   1.696 +
   1.697 +
   1.698 +char *
   1.699 +XenBus_StartTransaction(xenbus_transaction_t *xbt)
   1.700 +{
   1.701 +  /* xenstored becomes angry if you send a length 0 message, so just
   1.702 +     shove a nul terminator on the end */
   1.703 +  struct write_req req = { "", 1};
   1.704 +  struct xsd_sockmsg *rep;
   1.705 +  char *err;
   1.706 +
   1.707 +  rep = xenbus_msg_reply(XS_TRANSACTION_START, 0, &req, 1);
   1.708 +  err = errmsg(rep);
   1.709 +  if (err)
   1.710 +    return err;
   1.711 +  *xbt = atoi((char *)(rep + 1));
   1.712 +  //sscanf((char *)(rep + 1), "%u", xbt);
   1.713 +  ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
   1.714 +  return NULL;
   1.715 +}
   1.716 +
   1.717 +char *
   1.718 +XenBus_EndTransaction(xenbus_transaction_t t, int abort, int *retry)
   1.719 +{
   1.720 +  struct xsd_sockmsg *rep;
   1.721 +  struct write_req req;
   1.722 +  char *err;
   1.723 +
   1.724 +  *retry = 0;
   1.725 +
   1.726 +  req.data = abort ? "F" : "T";
   1.727 +  req.len = 2;
   1.728 +  rep = xenbus_msg_reply(XS_TRANSACTION_END, t, &req, 1);
   1.729 +  err = errmsg(rep);
   1.730 +  if (err) {
   1.731 +    if (!strcmp(err, "EAGAIN")) {
   1.732 +      *retry = 1;
   1.733 +      ExFreePoolWithTag(err, XENPCI_POOL_TAG);
   1.734 +      return NULL;
   1.735 +    } else {
   1.736 +      return err;
   1.737 +    }
   1.738 +  }
   1.739 +  ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
   1.740 +  return NULL;
   1.741 +}
   1.742 +/*
   1.743 +void
   1.744 +XenBus_ThreadProc(PVOID StartContext)
   1.745 +{
   1.746 +  char *response;
   1.747 +
   1.748 +  //KdPrint((__DRIVER_NAME " --> XenBus_ThreadProc\n"));
   1.749 +
   1.750 +  //do_ls_test("device");
   1.751 +
   1.752 +//  do_ls_test("local");
   1.753 +
   1.754 +//  do_ls_test("control");
   1.755 +
   1.756 +//  do_ls_test(".");
   1.757 +
   1.758 +  response = XenBus_AddWatch(XBT_NIL, SHUTDOWN_PATH, XenBus_ShutdownHandler, NULL);
   1.759 +
   1.760 +  //KdPrint((__DRIVER_NAME " <-- watch response = '%s'\n", response)); 
   1.761 +
   1.762 +  //KdPrint((__DRIVER_NAME " <-- XenBus_ThreadProc\n"));
   1.763 +}
   1.764 +*/
   1.765 +
   1.766 +static BOOLEAN
   1.767 +XenBus_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext)
   1.768 +{
   1.769 +  UNREFERENCED_PARAMETER(Interrupt);
   1.770 +  UNREFERENCED_PARAMETER(ServiceContext);
   1.771 +
   1.772 +  //KdPrint((__DRIVER_NAME " --> XenBus_Interrupt (Count = %d)\n", ReadThreadSetCount++));
   1.773 +
   1.774 +  KeSetEvent(&XenBus_ReadThreadEvent, 1, FALSE);
   1.775 +
   1.776 +  //KdPrint((__DRIVER_NAME " <-- XenBus_Interrupt\n"));
   1.777 +
   1.778 +  return TRUE;
   1.779 +}
   1.780 +
   1.781 +char *
   1.782 +XenBus_Printf(xenbus_transaction_t xbt, const char *path, const char *fmt, ...)
   1.783 +{
   1.784 +  va_list ap;
   1.785 +  char buf[1024];
   1.786 +
   1.787 +  va_start(ap, fmt);
   1.788 +  RtlStringCbVPrintfA(buf, ARRAY_SIZE(buf), fmt, ap);
   1.789 +  va_end(ap);
   1.790 +  return XenBus_Write(xbt, path, buf);
   1.791 +}
   1.792 \ No newline at end of file