win-pvdrivers

view xenpci/xenbus.c @ 20:1414d099b564

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