win-pvdrivers

annotate xenpci/xenbus.c @ 15:7f0f866dced6

wean xenbus.c off of global variables

rename some variables from deviceData to xpdd for brevity
some whitespace fixes
author Andy Grover <andy@groveronline.com>
date Wed Nov 28 16:49:26 2007 -0800 (2007-11-28)
parents be8c09632f31
children 1414d099b564
rev   line source
james@0 1 /*
james@0 2 PV Drivers for Windows Xen HVM Domains
james@0 3 Copyright (C) 2007 James Harper
james@0 4
james@0 5 This program is free software; you can redistribute it and/or
james@0 6 modify it under the terms of the GNU General Public License
james@0 7 as published by the Free Software Foundation; either version 2
james@0 8 of the License, or (at your option) any later version.
james@0 9
james@0 10 This program is distributed in the hope that it will be useful,
james@0 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
james@0 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
james@0 13 GNU General Public License for more details.
james@0 14
james@0 15 You should have received a copy of the GNU General Public License
james@0 16 along with this program; if not, write to the Free Software
james@0 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
james@0 18 */
james@0 19
james@0 20 #include "xenpci.h"
james@0 21 #include "io/xs_wire.h"
james@0 22 #include <stdlib.h>
james@0 23
james@0 24 #pragma warning( disable : 4204 )
james@0 25 #pragma warning( disable : 4221 )
james@0 26
andy@15 27 struct write_req {
andy@15 28 const void *data;
andy@15 29 unsigned len;
james@0 30 };
james@0 31
james@0 32 static void
james@0 33 XenBus_ReadThreadProc(PVOID StartContext);
james@0 34 static void
james@0 35 XenBus_WatchThreadProc(PVOID StartContext);
james@0 36 static BOOLEAN
james@0 37 XenBus_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext);
james@0 38
andy@15 39 static int allocate_xenbus_id(WDFDEVICE Device)
james@0 40 {
andy@15 41 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
andy@15 42
james@0 43 static int probe;
james@0 44 int o_probe;
james@0 45
james@0 46 //KdPrint((__DRIVER_NAME " --> allocate_xenbus_id\n"));
james@0 47
james@0 48 for (;;)
james@0 49 {
james@0 50 // spin_lock(&req_lock);
andy@15 51 if (xpdd->nr_live_reqs < NR_XB_REQS)
james@0 52 break;
james@0 53 // spin_unlock(&req_lock);
james@0 54 // wait_event(req_wq, (nr_live_reqs < NR_REQS));
james@0 55 }
james@0 56
james@0 57 o_probe = probe;
james@0 58
james@0 59 for (;;)
james@0 60 {
andy@15 61 if (!xpdd->req_info[o_probe].In_Use)
james@0 62 break;
andy@15 63 o_probe = (o_probe + 1) % NR_XB_REQS;
james@0 64 // BUG_ON(o_probe == probe);
james@0 65 }
andy@15 66 xpdd->nr_live_reqs++;
andy@15 67 xpdd->req_info[o_probe].In_Use = 1;
andy@15 68 probe = (o_probe + 1) % NR_XB_REQS;
james@0 69 //spin_unlock(&req_lock);
james@0 70 //init_waitqueue_head(&req_info[o_probe].waitq);
andy@15 71 KeInitializeEvent(&xpdd->req_info[o_probe].WaitEvent, SynchronizationEvent, FALSE);
james@0 72
james@0 73 //KdPrint((__DRIVER_NAME " <-- allocate_xenbus_id\n"));
james@0 74
james@0 75 return o_probe;
james@0 76 }
james@0 77
andy@15 78 static void release_xenbus_id(WDFDEVICE Device, int id)
james@0 79 {
andy@15 80 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
andy@15 81
james@0 82 // BUG_ON(!req_info[id].in_use);
james@0 83 // spin_lock(&req_lock);
andy@15 84 xpdd->req_info[id].In_Use = 0;
andy@15 85 xpdd->nr_live_reqs--;
andy@15 86 xpdd->req_info[id].In_Use = 0;
james@0 87 // if (nr_live_reqs == NR_REQS - 1)
james@0 88 // wake_up(&req_wq);
james@0 89 // spin_unlock(&req_lock);
james@0 90 }
james@0 91
james@0 92 static char *errmsg(struct xsd_sockmsg *rep)
james@0 93 {
james@0 94 char *res;
andy@15 95
james@0 96 if (!rep) {
james@0 97 char msg[] = "No reply";
james@0 98 size_t len = strlen(msg) + 1;
james@0 99 return memcpy(ExAllocatePoolWithTag(NonPagedPool, len, XENPCI_POOL_TAG), msg, len);
james@0 100 }
james@0 101 if (rep->type != XS_ERROR)
james@0 102 return NULL;
james@0 103 res = ExAllocatePoolWithTag(NonPagedPool, rep->len + 1, XENPCI_POOL_TAG);
james@0 104 memcpy(res, rep + 1, rep->len);
james@0 105 res[rep->len] = 0;
james@0 106 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
james@0 107 return res;
james@0 108 }
james@0 109
james@0 110 static void memcpy_from_ring(const void *Ring,
james@0 111 void *Dest,
james@0 112 int off,
james@0 113 int len)
james@0 114 {
james@0 115 int c1, c2;
james@0 116 const char *ring = Ring;
james@0 117 char *dest = Dest;
james@0 118 c1 = min(len, XENSTORE_RING_SIZE - off);
james@0 119 c2 = len - c1;
james@0 120 memcpy(dest, ring + off, c1);
james@0 121 memcpy(dest + c1, ring, c2);
james@0 122 }
james@0 123
andy@15 124 static void xb_write(
andy@13 125 WDFDEVICE Device,
andy@13 126 int type,
andy@13 127 int req_id,
andy@13 128 xenbus_transaction_t trans_id,
andy@13 129 const struct write_req *req,
andy@13 130 int nr_reqs)
james@0 131 {
andy@15 132 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
james@0 133 XENSTORE_RING_IDX prod;
james@0 134 int r;
james@0 135 size_t len = 0;
james@0 136 const struct write_req *cur_req;
james@0 137 size_t req_off;
james@0 138 size_t total_off;
james@0 139 size_t this_chunk;
james@0 140 struct xsd_sockmsg m = {type, req_id, trans_id };
james@0 141 struct write_req header_req = { &m, sizeof(m) };
james@0 142
james@0 143 //KdPrint((__DRIVER_NAME " --> xb_write\n"));
james@0 144
james@0 145 for (r = 0; r < nr_reqs; r++)
james@0 146 len += req[r].len;
james@0 147 m.len = len;
james@0 148 len += sizeof(m);
james@0 149
james@0 150 cur_req = &header_req;
james@0 151
james@0 152 // BUG_ON(len > XENSTORE_RING_SIZE);
james@0 153 /* Wait for the ring to drain to the point where we can send the
james@0 154 message. */
andy@15 155 prod = xpdd->xen_store_interface->req_prod;
james@0 156
james@0 157 //KdPrint((__DRIVER_NAME " prod = %08x\n", prod));
james@0 158
andy@15 159 if (prod + len - xpdd->xen_store_interface->req_cons > XENSTORE_RING_SIZE)
james@0 160 {
james@0 161 /* Wait for there to be space on the ring */
james@0 162 //KdPrint((__DRIVER_NAME " prod %d, len %d, cons %d, size %d; waiting.\n", prod, len, xen_store_interface->req_cons, XENSTORE_RING_SIZE));
james@0 163 // wait_event(xb_waitq, xen_store_interface->req_prod + len - xen_store_interface->req_cons <= XENSTORE_RING_SIZE);
james@0 164 //KdPrint((__DRIVER_NAME " Back from wait.\n"));
andy@15 165 prod = xpdd->xen_store_interface->req_prod;
james@0 166 }
james@0 167
james@0 168 /* We're now guaranteed to be able to send the message without
james@0 169 overflowing the ring. Do so. */
james@0 170
james@0 171 total_off = 0;
james@0 172 req_off = 0;
james@0 173
james@0 174 while (total_off < len)
james@0 175 {
james@0 176 this_chunk = min(cur_req->len - req_off,XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
andy@15 177 memcpy((char *)xpdd->xen_store_interface->req + MASK_XENSTORE_IDX(prod), (char *)cur_req->data + req_off, this_chunk);
james@0 178 prod += this_chunk;
james@0 179 req_off += this_chunk;
james@0 180 total_off += this_chunk;
james@0 181 if (req_off == cur_req->len)
james@0 182 {
james@0 183 req_off = 0;
james@0 184 if (cur_req == &header_req)
james@0 185 cur_req = req;
james@0 186 else
james@0 187 cur_req++;
james@0 188 }
james@0 189 }
james@0 190
james@0 191 //KdPrint((__DRIVER_NAME " Complete main loop of xb_write.\n"));
james@0 192
james@0 193 // BUG_ON(req_off != 0);
james@0 194 // BUG_ON(total_off != len);
james@0 195 // BUG_ON(prod > xen_store_interface->req_cons + XENSTORE_RING_SIZE);
james@0 196
james@0 197 /* Remote must see entire message before updating indexes */
james@0 198 //_WriteBarrier();
james@0 199 KeMemoryBarrier();
james@0 200
andy@15 201 xpdd->xen_store_interface->req_prod += len;
james@0 202
james@0 203 //KdPrint((__DRIVER_NAME " prod = %08x\n", xen_store_interface->req_prod));
james@0 204
james@0 205 /* Send evtchn to notify remote */
andy@15 206 EvtChn_Notify(Device, xpdd->xen_store_evtchn);
james@0 207
james@0 208 //KdPrint((__DRIVER_NAME " <-- xb_write\n"));
james@0 209 }
james@0 210
james@0 211 static struct xsd_sockmsg *
andy@13 212 xenbus_msg_reply(
andy@13 213 WDFDEVICE Device,
andy@13 214 int type,
andy@13 215 xenbus_transaction_t trans,
andy@13 216 struct write_req *io,
andy@13 217 int nr_reqs)
james@0 218 {
andy@15 219 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
james@0 220 int id;
james@0 221 // DEFINE_WAIT(w);
james@0 222 struct xsd_sockmsg *rep;
james@0 223
james@6 224 KdPrint((__DRIVER_NAME " --> xenbus_msg_reply\n"));
james@0 225
andy@15 226 id = allocate_xenbus_id(Device);
james@0 227 // add_waiter(w, req_info[id].waitq);
james@0 228
andy@13 229 xb_write(Device, type, id, trans, io, nr_reqs);
james@0 230 //
james@0 231 // schedule();
james@0 232 // remove_waiter(w);
james@0 233 // wake(current);
james@0 234 //
james@6 235 KdPrint((__DRIVER_NAME " starting wait\n"));
james@0 236
andy@15 237 KeWaitForSingleObject(&xpdd->req_info[id].WaitEvent, Executive, KernelMode, FALSE, NULL);
james@0 238
james@9 239 //KdPrint((__DRIVER_NAME " wait complete\n"));
james@0 240
andy@15 241 rep = xpdd->req_info[id].Reply;
james@0 242 // BUG_ON(rep->req_id != id);
andy@15 243 release_xenbus_id(Device, id);
james@6 244 KdPrint((__DRIVER_NAME " <-- xenbus_msg_reply\n"));
james@0 245 return rep;
james@0 246 }
james@0 247
james@0 248 char *
andy@15 249 XenBus_Read(
andy@13 250 PVOID Context,
andy@13 251 xenbus_transaction_t xbt,
andy@13 252 const char *path,
andy@13 253 char **value)
james@0 254 {
andy@13 255 WDFDEVICE Device = Context;
andy@13 256 struct write_req req[] = { {path, strlen(path) + 1} };
andy@13 257 struct xsd_sockmsg *rep;
andy@13 258 char *res;
andy@13 259 char *msg;
james@0 260
andy@13 261 rep = xenbus_msg_reply(Device, XS_READ, xbt, req, ARRAY_SIZE(req));
andy@13 262 msg = errmsg(rep);
andy@13 263 if (msg) {
andy@13 264 *value = NULL;
andy@13 265 return msg;
andy@13 266 }
andy@13 267 res = ExAllocatePoolWithTag(NonPagedPool, rep->len + 1, XENPCI_POOL_TAG);
andy@13 268 memcpy(res, rep + 1, rep->len);
andy@13 269 res[rep->len] = 0;
andy@13 270 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
andy@13 271 *value = res;
andy@13 272 return NULL;
james@0 273 }
james@0 274
james@0 275 char *
andy@13 276 XenBus_Write(
andy@13 277 PVOID Context,
andy@13 278 xenbus_transaction_t xbt,
andy@13 279 const char *path,
andy@13 280 const char *value)
james@0 281 {
andy@13 282 WDFDEVICE Device = Context;
andy@13 283 struct write_req req[] = {
andy@13 284 {path, strlen(path) + 1},
andy@13 285 {value, strlen(value) + 1},
andy@13 286 };
andy@13 287 struct xsd_sockmsg *rep;
andy@13 288 char *msg;
james@0 289
andy@13 290 rep = xenbus_msg_reply(Device, XS_WRITE, xbt, req, ARRAY_SIZE(req));
andy@13 291 msg = errmsg(rep);
andy@13 292 if (msg)
andy@13 293 return msg;
andy@13 294 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
andy@13 295 return NULL;
james@0 296 }
james@0 297
james@0 298 NTSTATUS
andy@13 299 XenBus_Init(WDFDEVICE Device)
james@0 300 {
andy@15 301 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
james@0 302 //KdPrint((__DRIVER_NAME " --> XenBus_Init\n"));
james@0 303
andy@15 304 xpdd->xen_store_evtchn = EvtChn_GetXenStorePort(Device);
andy@15 305 xpdd->xen_store_interface = EvtChn_GetXenStoreRingAddr(Device);
james@0 306
james@0 307 //KdPrint((__DRIVER_NAME " xen_store_evtchn = %08x\n", xen_store_evtchn));
james@0 308 //KdPrint((__DRIVER_NAME " xen_store_interface = %08x\n", xen_store_interface));
james@0 309
andy@15 310 KeInitializeEvent(&xpdd->XenBus_ReadThreadEvent, SynchronizationEvent, FALSE);
andy@15 311 KeInitializeEvent(&xpdd->XenBus_WatchThreadEvent, SynchronizationEvent, FALSE);
james@0 312
james@0 313 //KdPrint((__DRIVER_NAME " <-- XenBus_Init\n"));
james@0 314
james@0 315 return STATUS_SUCCESS;
james@0 316 }
james@0 317
james@0 318 NTSTATUS
andy@13 319 XenBus_Start(WDFDEVICE Device)
james@0 320 {
andy@15 321 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
james@0 322 OBJECT_ATTRIBUTES oa;
james@0 323 NTSTATUS status;
james@0 324 int i;
james@0 325
james@6 326 KdPrint((__DRIVER_NAME " --> XenBus_Start\n"));
james@0 327
james@0 328 InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
andy@15 329 status = PsCreateSystemThread(&xpdd->XenBus_ReadThreadHandle, THREAD_ALL_ACCESS,
andy@15 330 &oa, NULL, NULL, XenBus_ReadThreadProc, Device);
james@0 331
james@0 332 // remove all existing watches already in Xen too...
james@0 333
james@0 334 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
andy@15 335 xpdd->XenBus_WatchEntries[i].Active = 0;
james@0 336
james@0 337 InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
andy@15 338 status = PsCreateSystemThread(&xpdd->XenBus_WatchThreadHandle, THREAD_ALL_ACCESS,
andy@15 339 &oa, NULL, NULL, XenBus_WatchThreadProc, Device);
james@0 340
andy@15 341 EvtChn_Bind(Device, xpdd->xen_store_evtchn, XenBus_Interrupt, Device);
james@0 342
james@6 343 KdPrint((__DRIVER_NAME " <-- XenBus_Start\n"));
james@0 344
james@0 345 return STATUS_SUCCESS;
james@0 346 }
james@0 347
james@0 348 NTSTATUS
andy@13 349 XenBus_Stop(WDFDEVICE Device)
james@0 350 {
andy@15 351 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
james@0 352 int i;
james@0 353
james@0 354 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
james@0 355 {
andy@15 356 if (!xpdd->XenBus_WatchEntries[i].Active)
james@0 357 continue;
andy@15 358 XenBus_RemWatch(Device, XBT_NIL,
andy@15 359 xpdd->XenBus_WatchEntries[i].Path,
andy@15 360 xpdd->XenBus_WatchEntries[i].ServiceRoutine,
andy@15 361 xpdd->XenBus_WatchEntries[i].ServiceContext);
james@0 362 }
james@0 363
andy@15 364 EvtChn_Unbind(Device, xpdd->xen_store_evtchn);
james@0 365
james@0 366 // Does this actually stop the threads???
andy@15 367 ZwClose(xpdd->XenBus_WatchThreadHandle);
andy@15 368 ZwClose(xpdd->XenBus_ReadThreadHandle);
james@0 369
james@0 370 return STATUS_SUCCESS;
james@0 371 }
james@0 372
james@0 373 char *
andy@13 374 XenBus_List(
andy@13 375 PVOID Context,
andy@13 376 xenbus_transaction_t xbt,
andy@13 377 const char *pre,
andy@13 378 char ***contents)
james@0 379 {
andy@13 380 WDFDEVICE Device = Context;
james@0 381 struct xsd_sockmsg *reply, *repmsg;
james@0 382 struct write_req req[] = { { pre, strlen(pre)+1 } };
james@0 383 ULONG nr_elems, x, i;
james@0 384 char **res;
james@0 385 char *msg;
james@0 386
james@0 387 //KdPrint((__DRIVER_NAME " --> xenbus_ls\n"));
james@0 388
andy@13 389 repmsg = xenbus_msg_reply(Device, XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
james@0 390 msg = errmsg(repmsg);
andy@15 391 if (msg)
andy@15 392 {
james@0 393 *contents = NULL;
james@0 394 //KdPrint((__DRIVER_NAME " <-- xenbus_ls (error)\n"));
james@0 395 return msg;
james@0 396 }
james@0 397 reply = repmsg + 1;
james@0 398 for (x = nr_elems = 0; x < repmsg->len; x++)
andy@15 399 {
james@0 400 nr_elems += (((char *)reply)[x] == 0);
andy@15 401 }
andy@15 402 res = ExAllocatePoolWithTag(NonPagedPool, sizeof(res[0]) * (nr_elems + 1),
andy@15 403 XENPCI_POOL_TAG);
andy@15 404 for (x = i = 0; i < nr_elems; i++)
andy@15 405 {
james@0 406 int l = strlen((char *)reply + x);
james@0 407 res[i] = ExAllocatePoolWithTag(NonPagedPool, l + 1, XENPCI_POOL_TAG);
james@0 408 memcpy(res[i], (char *)reply + x, l + 1);
james@0 409 x += l + 1;
james@0 410 }
james@0 411 res[i] = NULL;
james@0 412 ExFreePoolWithTag(repmsg, XENPCI_POOL_TAG);
james@0 413 *contents = res;
james@0 414 //KdPrint((__DRIVER_NAME " <-- xenbus_ls\n"));
james@0 415 return NULL;
james@0 416 }
james@0 417
andy@15 418 static void
andy@15 419 XenBus_ReadThreadProc(PVOID StartContext)
james@0 420 {
james@0 421 int NewWriteIndex;
james@0 422 struct xsd_sockmsg msg;
james@0 423 char *payload;
james@0 424 char *path, *token;
andy@15 425 WDFDEVICE Device = StartContext;
andy@15 426 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
james@0 427
james@0 428 for(;;)
james@0 429 {
andy@15 430 KeWaitForSingleObject(&xpdd->XenBus_ReadThreadEvent, Executive, KernelMode, FALSE, NULL);
james@0 431 //KdPrint((__DRIVER_NAME " ReadThread Woken (Count = %d)\n", ReadThreadWaitCount++));
andy@15 432 while (xpdd->xen_store_interface->rsp_prod != xpdd->xen_store_interface->rsp_cons)
james@0 433 {
james@0 434 //KdPrint((__DRIVER_NAME " a - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
andy@15 435 if (xpdd->xen_store_interface->rsp_prod - xpdd->xen_store_interface->rsp_cons < sizeof(msg))
james@0 436 {
james@0 437 //KdPrint((__DRIVER_NAME " +++ Message incomplete (not even a full header)\n"));
james@0 438 break;
james@0 439 }
james@0 440 //_ReadBarrier();
james@0 441 KeMemoryBarrier();
andy@15 442 memcpy_from_ring(xpdd->xen_store_interface->rsp, &msg,
andy@15 443 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons), sizeof(msg));
andy@15 444 if (xpdd->xen_store_interface->rsp_prod - xpdd->xen_store_interface->rsp_cons < sizeof(msg) + msg.len)
james@0 445 {
james@0 446 //KdPrint((__DRIVER_NAME " +++ Message incomplete (header but not full body)\n"));
james@0 447 break;
james@0 448 }
james@0 449
james@0 450 if(msg.type == XS_WATCH_EVENT)
james@0 451 {
james@0 452 payload = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
james@0 453
andy@15 454 memcpy_from_ring(xpdd->xen_store_interface->rsp, payload,
andy@15 455 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons), msg.len + sizeof(msg));
james@0 456
andy@15 457 xpdd->xen_store_interface->rsp_cons += msg.len + sizeof(msg);
james@0 458 //KdPrint((__DRIVER_NAME " b - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
james@0 459
james@0 460 path = payload + sizeof(msg);
james@0 461 token = path + strlen(path) + 1;
james@0 462
andy@15 463 NewWriteIndex = (xpdd->XenBus_WatchRingWriteIndex + 1) & 127;
andy@15 464 if (NewWriteIndex != xpdd->XenBus_WatchRingReadIndex)
james@0 465 {
andy@15 466 strncpy(xpdd->XenBus_WatchRing[NewWriteIndex].Path, path, 128);
andy@15 467 strncpy(xpdd->XenBus_WatchRing[NewWriteIndex].Token, token, 10);
andy@15 468 xpdd->XenBus_WatchRingWriteIndex = NewWriteIndex;
james@0 469 }
james@0 470 else
james@0 471 {
james@0 472 KdPrint((__DRIVER_NAME " +++ Queue full Path = %s Token = %s\n", path, token));
james@0 473 // drop the message on the floor
james@0 474 continue;
james@0 475 }
james@0 476
james@0 477 ExFreePoolWithTag(payload, XENPCI_POOL_TAG);
james@0 478 //KdPrint((__DRIVER_NAME " +++ Watch Path = %s Token = %s\n", path, token));
andy@15 479 KeSetEvent(&xpdd->XenBus_WatchThreadEvent, 1, FALSE);
james@0 480 }
james@0 481 else
james@0 482 {
andy@15 483 xpdd->req_info[msg.req_id].Reply = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
andy@15 484 memcpy_from_ring(xpdd->xen_store_interface->rsp,
andy@15 485 xpdd->req_info[msg.req_id].Reply,
andy@15 486 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons),
andy@15 487 msg.len + sizeof(msg));
andy@15 488 xpdd->xen_store_interface->rsp_cons += msg.len + sizeof(msg);
james@0 489 //KdPrint((__DRIVER_NAME " c - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
james@0 490 //KdPrint((__DRIVER_NAME " +++ Message = %s\n", ((char *)req_info[msg.req_id].Reply) + sizeof(msg)));
andy@15 491 KeSetEvent(&xpdd->req_info[msg.req_id].WaitEvent, 1, FALSE);
james@0 492 }
james@0 493 }
james@0 494 }
james@0 495 }
james@0 496
james@0 497 static void
james@0 498 XenBus_WatchThreadProc(PVOID StartContext)
james@0 499 {
james@0 500 int index;
james@0 501 PXENBUS_WATCH_ENTRY entry;
andy@15 502 WDFDEVICE Device = StartContext;
andy@15 503 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
james@0 504
james@0 505 for(;;)
james@0 506 {
andy@15 507 KeWaitForSingleObject(&xpdd->XenBus_WatchThreadEvent, Executive,
andy@15 508 KernelMode, FALSE, NULL);
andy@15 509 while (xpdd->XenBus_WatchRingReadIndex != xpdd->XenBus_WatchRingWriteIndex)
james@0 510 {
andy@15 511 xpdd->XenBus_WatchRingReadIndex =
andy@15 512 (xpdd->XenBus_WatchRingReadIndex + 1) % WATCH_RING_SIZE;
andy@15 513 index = atoi(xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Token);
james@0 514 //XenBus_WatchRing[XenBus_WatchRingReadIndex].Path
james@0 515 //XenBus_WatchRing[XenBus_WatchRingReadIndex].Token
james@0 516
andy@15 517 entry = &xpdd->XenBus_WatchEntries[index];
james@0 518 if (!entry->Active)
james@0 519 {
andy@15 520 KdPrint((__DRIVER_NAME " +++ Watch not active! = %s Token = %s\n",
andy@15 521 xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Path,
andy@15 522 xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Token));
james@0 523 continue;
james@0 524 }
james@0 525 entry->Count++;
james@0 526 if (!entry->ServiceRoutine)
james@0 527 {
andy@15 528 KdPrint((__DRIVER_NAME " +++ no handler for watch! = %s Token = %s\n",
andy@15 529 xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Path,
andy@15 530 xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Token));
james@0 531 continue;
james@0 532 }
james@0 533 //KdPrint((__DRIVER_NAME " +++ Watch Triggered Path = %s Token = %d (%s)\n", XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, index, XenBus_WatchRing[XenBus_WatchRingReadIndex].Token));
andy@15 534 entry->ServiceRoutine(xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Path, entry->ServiceContext);
james@0 535 }
james@0 536 }
james@0 537 }
james@0 538
james@0 539 char *
andy@15 540 XenBus_AddWatch(
andy@13 541 PVOID Context,
andy@13 542 xenbus_transaction_t xbt,
andy@13 543 const char *Path,
andy@13 544 PXENBUS_WATCH_CALLBACK ServiceRoutine,
andy@13 545 PVOID ServiceContext)
james@0 546 {
andy@13 547 WDFDEVICE Device = Context;
andy@15 548 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
james@0 549 struct xsd_sockmsg *rep;
james@0 550 char *msg;
james@0 551 int i;
james@0 552 char Token[20];
james@0 553 struct write_req req[2];
james@0 554
james@6 555 KdPrint((__DRIVER_NAME " --> XenBus_AddWatch\n"));
james@0 556
james@0 557 // check that Path < 128 chars
james@0 558
james@0 559 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
andy@15 560 if (xpdd->XenBus_WatchEntries[i].Active == 0)
james@0 561 break;
james@0 562
james@0 563 if (i == MAX_WATCH_ENTRIES)
james@0 564 {
james@0 565 KdPrint((__DRIVER_NAME " +++ No more watch slots left\n"));
james@0 566 return NULL;
james@0 567 }
james@0 568
james@0 569 req[0].data = Path;
james@0 570 req[0].len = strlen(Path) + 1;
james@0 571
james@0 572 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", i);
james@0 573 req[1].data = Token;
james@0 574 req[1].len = strlen(Token) + 1;
james@0 575
andy@13 576 rep = xenbus_msg_reply(Device, XS_WATCH, xbt, req, ARRAY_SIZE(req));
james@0 577
james@0 578 msg = errmsg(rep);
james@0 579 if (msg)
james@0 580 return msg;
james@0 581
james@0 582 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
james@0 583
andy@15 584 strncpy(xpdd->XenBus_WatchEntries[i].Path, Path, 128);
andy@15 585 xpdd->XenBus_WatchEntries[i].ServiceRoutine = ServiceRoutine;
andy@15 586 xpdd->XenBus_WatchEntries[i].ServiceContext = ServiceContext;
andy@15 587 xpdd->XenBus_WatchEntries[i].Count = 0;
andy@15 588 xpdd->XenBus_WatchEntries[i].Active = 1;
james@0 589
james@6 590 KdPrint((__DRIVER_NAME " <-- XenBus_AddWatch\n"));
james@0 591
james@0 592 return NULL;
james@0 593 }
james@0 594
james@0 595 char *
andy@13 596 XenBus_RemWatch(
andy@13 597 PVOID Context,
andy@13 598 xenbus_transaction_t xbt,
andy@13 599 const char *Path,
andy@13 600 PXENBUS_WATCH_CALLBACK ServiceRoutine,
andy@13 601 PVOID ServiceContext)
james@0 602 {
andy@13 603 WDFDEVICE Device = Context;
andy@15 604 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
james@0 605 struct xsd_sockmsg *rep;
james@0 606 char *msg;
james@0 607 int i;
james@0 608 char Token[20];
james@0 609 struct write_req req[2];
james@0 610
james@0 611 //KdPrint((__DRIVER_NAME " --> XenBus_RemWatch\n"));
james@0 612
james@0 613 // check that Path < 128 chars
james@0 614
james@0 615 for (i = 0; i < MAX_WATCH_ENTRIES; i++) {
andy@15 616 if (xpdd->XenBus_WatchEntries[i].Active == 1
andy@15 617 && strcmp(xpdd->XenBus_WatchEntries[i].Path, Path) == 0
andy@15 618 && xpdd->XenBus_WatchEntries[i].ServiceRoutine == ServiceRoutine
andy@15 619 && xpdd->XenBus_WatchEntries[i].ServiceContext == ServiceContext)
james@0 620 break;
james@0 621 }
james@0 622
james@0 623 if (i == MAX_WATCH_ENTRIES)
james@0 624 {
james@0 625 KdPrint((__DRIVER_NAME " Watch not set - can't remove\n"));
james@0 626 return NULL;
james@0 627 }
james@0 628
james@0 629 req[0].data = Path;
james@0 630 req[0].len = strlen(Path) + 1;
james@0 631
james@0 632 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", i);
james@0 633 req[1].data = Token;
james@0 634 req[1].len = strlen(Token) + 1;
james@0 635
andy@13 636 rep = xenbus_msg_reply(Device, XS_UNWATCH, xbt, req, ARRAY_SIZE(req));
james@0 637
james@0 638 msg = errmsg(rep);
james@0 639 if (msg)
james@0 640 return msg;
james@0 641
james@0 642 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
james@0 643
andy@15 644 xpdd->XenBus_WatchEntries[i].Active = 0;
james@0 645
james@0 646 //KdPrint((__DRIVER_NAME " <-- XenBus_RemWatch\n"));
james@0 647
james@0 648 return NULL;
james@0 649 }
james@0 650
james@0 651
james@0 652 char *
andy@13 653 XenBus_StartTransaction(PVOID Context, xenbus_transaction_t *xbt)
james@0 654 {
andy@13 655 WDFDEVICE Device = Context;
james@0 656 /* xenstored becomes angry if you send a length 0 message, so just
james@0 657 shove a nul terminator on the end */
james@0 658 struct write_req req = { "", 1};
james@0 659 struct xsd_sockmsg *rep;
james@0 660 char *err;
james@0 661
andy@13 662 rep = xenbus_msg_reply(Device, XS_TRANSACTION_START, 0, &req, 1);
james@0 663 err = errmsg(rep);
james@0 664 if (err)
james@0 665 return err;
james@0 666 *xbt = atoi((char *)(rep + 1));
james@0 667 //sscanf((char *)(rep + 1), "%u", xbt);
james@0 668 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
james@0 669 return NULL;
james@0 670 }
james@0 671
james@0 672 char *
andy@15 673 XenBus_EndTransaction(
andy@15 674 PVOID Context,
andy@15 675 xenbus_transaction_t t,
andy@15 676 int abort,
andy@15 677 int *retry)
james@0 678 {
andy@13 679 WDFDEVICE Device = Context;
james@0 680 struct xsd_sockmsg *rep;
james@0 681 struct write_req req;
james@0 682 char *err;
james@0 683
james@0 684 *retry = 0;
james@0 685
james@0 686 req.data = abort ? "F" : "T";
james@0 687 req.len = 2;
andy@13 688 rep = xenbus_msg_reply(Device, XS_TRANSACTION_END, t, &req, 1);
james@0 689 err = errmsg(rep);
james@0 690 if (err) {
james@0 691 if (!strcmp(err, "EAGAIN")) {
james@0 692 *retry = 1;
james@0 693 ExFreePoolWithTag(err, XENPCI_POOL_TAG);
james@0 694 return NULL;
james@0 695 } else {
james@0 696 return err;
james@0 697 }
james@0 698 }
james@0 699 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
james@0 700 return NULL;
james@0 701 }
james@0 702
james@0 703 static BOOLEAN
james@0 704 XenBus_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext)
james@0 705 {
andy@15 706 WDFDEVICE Device = ServiceContext;
andy@15 707 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
andy@15 708
james@0 709 UNREFERENCED_PARAMETER(Interrupt);
james@0 710
james@0 711 //KdPrint((__DRIVER_NAME " --> XenBus_Interrupt (Count = %d)\n", ReadThreadSetCount++));
james@0 712
andy@15 713 KeSetEvent(&xpdd->XenBus_ReadThreadEvent, 1, FALSE);
james@0 714
james@0 715 //KdPrint((__DRIVER_NAME " <-- XenBus_Interrupt\n"));
james@0 716
james@0 717 return TRUE;
james@0 718 }
james@0 719
james@0 720 char *
andy@15 721 XenBus_Printf(
andy@15 722 PVOID Context,
andy@15 723 xenbus_transaction_t xbt,
andy@15 724 const char *path,
andy@15 725 const char *fmt,
andy@15 726 ...)
james@0 727 {
andy@13 728 WDFDEVICE Device = Context;
james@0 729 va_list ap;
james@0 730 char buf[1024];
james@0 731
james@0 732 va_start(ap, fmt);
james@0 733 RtlStringCbVPrintfA(buf, ARRAY_SIZE(buf), fmt, ap);
james@0 734 va_end(ap);
andy@13 735 return XenBus_Write(Device, xbt, path, buf);
james@0 736 }