win-pvdrivers

view xenpci/xenbus.c @ 6:8f643f8e229b

Bug Fixes... trying to find a problem that turned out to be me running an old version of xen by mistake!
author James Harper <james.harper@bendigoit.com.au>
date Mon Nov 12 22:26:30 2007 +1100 (2007-11-12)
parents 435e5753300f
children b55f3c61e509
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 xenbus_req_info
28 {
29 int In_Use:1;
30 KEVENT WaitEvent;
31 void *Reply;
32 };
34 typedef struct {
35 char Path[128];
36 PXENBUS_WATCH_CALLBACK ServiceRoutine;
37 PVOID ServiceContext;
38 int Count;
39 int Active;
40 } XENBUS_WATCH_ENTRY, *PXENBUS_WATCH_ENTRY;
42 typedef struct {
43 char Path[128];
44 char Token[10];
45 } XENBUS_WATCH_RING;
47 #define WATCH_RING_SIZE 128
49 static XENBUS_WATCH_RING XenBus_WatchRing[WATCH_RING_SIZE];
50 static int XenBus_WatchRingReadIndex;
51 static int XenBus_WatchRingWriteIndex;
53 #define MAX_WATCH_ENTRIES 128
55 static XENBUS_WATCH_ENTRY XenBus_WatchEntries[MAX_WATCH_ENTRIES];
57 #define NR_REQS 32
58 //#define XENSTORE_RING_SIZE 1024
60 //#define XENSTORE_RING_SIZE 1024
61 //typedef uint32_t XENSTORE_RING_IDX;
62 //#define MASK_XENSTORE_IDX(idx) ((idx) & (XENSTORE_RING_SIZE-1))
64 static struct xenstore_domain_interface *xen_store_interface;
66 static struct xenbus_req_info req_info[NR_REQS];
67 static int nr_live_reqs;
68 //static spinlock_t req_lock = SPIN_LOCK_UNLOCKED;
70 static HANDLE XenBus_ReadThreadHandle;
71 static KEVENT XenBus_ReadThreadEvent;
73 static HANDLE XenBus_WatchThreadHandle;
74 static KEVENT XenBus_WatchThreadEvent;
76 static void
77 XenBus_ReadThreadProc(PVOID StartContext);
78 static void
79 XenBus_WatchThreadProc(PVOID StartContext);
81 static BOOLEAN
82 XenBus_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext);
84 static int allocate_xenbus_id(void)
85 {
86 static int probe;
87 int o_probe;
89 //KdPrint((__DRIVER_NAME " --> allocate_xenbus_id\n"));
91 for (;;)
92 {
93 // spin_lock(&req_lock);
94 if (nr_live_reqs < NR_REQS)
95 break;
96 // spin_unlock(&req_lock);
97 // wait_event(req_wq, (nr_live_reqs < NR_REQS));
98 }
100 o_probe = probe;
102 for (;;)
103 {
104 if (!req_info[o_probe].In_Use)
105 break;
106 o_probe = (o_probe + 1) % NR_REQS;
107 // BUG_ON(o_probe == probe);
108 }
109 nr_live_reqs++;
110 req_info[o_probe].In_Use = 1;
111 probe = (o_probe + 1) % NR_REQS;
112 //spin_unlock(&req_lock);
113 //init_waitqueue_head(&req_info[o_probe].waitq);
114 KeInitializeEvent(&req_info[o_probe].WaitEvent, SynchronizationEvent, FALSE);
116 //KdPrint((__DRIVER_NAME " <-- allocate_xenbus_id\n"));
118 return o_probe;
119 }
121 static void release_xenbus_id(int id)
122 {
123 // BUG_ON(!req_info[id].in_use);
124 // spin_lock(&req_lock);
125 req_info[id].In_Use = 0;
126 nr_live_reqs--;
127 req_info[id].In_Use = 0;
128 // if (nr_live_reqs == NR_REQS - 1)
129 // wake_up(&req_wq);
130 // spin_unlock(&req_lock);
131 }
134 static char *errmsg(struct xsd_sockmsg *rep)
135 {
136 char *res;
137 if (!rep) {
138 char msg[] = "No reply";
139 size_t len = strlen(msg) + 1;
140 return memcpy(ExAllocatePoolWithTag(NonPagedPool, len, XENPCI_POOL_TAG), msg, len);
141 }
142 if (rep->type != XS_ERROR)
143 return NULL;
144 res = ExAllocatePoolWithTag(NonPagedPool, rep->len + 1, XENPCI_POOL_TAG);
145 memcpy(res, rep + 1, rep->len);
146 res[rep->len] = 0;
147 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
148 return res;
149 }
151 static void memcpy_from_ring(const void *Ring,
152 void *Dest,
153 int off,
154 int len)
155 {
156 int c1, c2;
157 const char *ring = Ring;
158 char *dest = Dest;
159 c1 = min(len, XENSTORE_RING_SIZE - off);
160 c2 = len - c1;
161 memcpy(dest, ring + off, c1);
162 memcpy(dest + c1, ring, c2);
163 }
165 void wait_for_watch(void)
166 {
167 // DEFINE_WAIT(w);
168 // add_waiter(w,watch_queue);
169 // schedule();
170 // remove_waiter(w);
171 // wake(current);
172 }
174 struct write_req {
175 const void *data;
176 unsigned len;
177 };
179 static evtchn_port_t xen_store_evtchn;
181 static void xb_write(int type, int req_id, xenbus_transaction_t trans_id,
182 const struct write_req *req, int nr_reqs)
183 {
184 XENSTORE_RING_IDX prod;
185 int r;
186 size_t len = 0;
187 const struct write_req *cur_req;
188 size_t req_off;
189 size_t total_off;
190 size_t this_chunk;
191 struct xsd_sockmsg m = {type, req_id, trans_id };
192 struct write_req header_req = { &m, sizeof(m) };
194 //KdPrint((__DRIVER_NAME " --> xb_write\n"));
196 for (r = 0; r < nr_reqs; r++)
197 len += req[r].len;
198 m.len = len;
199 len += sizeof(m);
201 cur_req = &header_req;
203 // BUG_ON(len > XENSTORE_RING_SIZE);
204 /* Wait for the ring to drain to the point where we can send the
205 message. */
206 prod = xen_store_interface->req_prod;
208 //KdPrint((__DRIVER_NAME " prod = %08x\n", prod));
210 if (prod + len - xen_store_interface->req_cons > XENSTORE_RING_SIZE)
211 {
212 /* Wait for there to be space on the ring */
213 //KdPrint((__DRIVER_NAME " prod %d, len %d, cons %d, size %d; waiting.\n", prod, len, xen_store_interface->req_cons, XENSTORE_RING_SIZE));
214 // wait_event(xb_waitq, xen_store_interface->req_prod + len - xen_store_interface->req_cons <= XENSTORE_RING_SIZE);
215 //KdPrint((__DRIVER_NAME " Back from wait.\n"));
216 prod = xen_store_interface->req_prod;
217 }
219 /* We're now guaranteed to be able to send the message without
220 overflowing the ring. Do so. */
222 total_off = 0;
223 req_off = 0;
225 while (total_off < len)
226 {
227 this_chunk = min(cur_req->len - req_off,XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
228 memcpy((char *)xen_store_interface->req + MASK_XENSTORE_IDX(prod), (char *)cur_req->data + req_off, this_chunk);
229 prod += this_chunk;
230 req_off += this_chunk;
231 total_off += this_chunk;
232 if (req_off == cur_req->len)
233 {
234 req_off = 0;
235 if (cur_req == &header_req)
236 cur_req = req;
237 else
238 cur_req++;
239 }
240 }
242 //KdPrint((__DRIVER_NAME " Complete main loop of xb_write.\n"));
244 // BUG_ON(req_off != 0);
245 // BUG_ON(total_off != len);
246 // BUG_ON(prod > xen_store_interface->req_cons + XENSTORE_RING_SIZE);
248 /* Remote must see entire message before updating indexes */
249 //_WriteBarrier();
250 KeMemoryBarrier();
252 xen_store_interface->req_prod += len;
254 //KdPrint((__DRIVER_NAME " prod = %08x\n", xen_store_interface->req_prod));
256 /* Send evtchn to notify remote */
257 EvtChn_Notify(xen_store_evtchn);
259 //KdPrint((__DRIVER_NAME " <-- xb_write\n"));
260 }
262 static struct xsd_sockmsg *
263 xenbus_msg_reply(int type, xenbus_transaction_t trans, struct write_req *io, int nr_reqs)
264 {
265 int id;
266 // DEFINE_WAIT(w);
267 struct xsd_sockmsg *rep;
269 KdPrint((__DRIVER_NAME " --> xenbus_msg_reply\n"));
271 id = allocate_xenbus_id();
272 // add_waiter(w, req_info[id].waitq);
274 xb_write(type, id, trans, io, nr_reqs);
275 //
276 // schedule();
277 // remove_waiter(w);
278 // wake(current);
279 //
280 KdPrint((__DRIVER_NAME " starting wait\n"));
282 KeWaitForSingleObject(&req_info[id].WaitEvent, Executive, KernelMode, FALSE, NULL);
284 KdPrint((__DRIVER_NAME " wait complete\n"));
286 rep = req_info[id].Reply;
287 // BUG_ON(rep->req_id != id);
288 release_xenbus_id(id);
289 KdPrint((__DRIVER_NAME " <-- xenbus_msg_reply\n"));
290 return rep;
291 }
293 char *
294 XenBus_Read(xenbus_transaction_t xbt, const char *path, char **value)
295 {
296 struct write_req req[] = { {path, strlen(path) + 1} };
297 struct xsd_sockmsg *rep;
298 char *res;
299 char *msg;
301 rep = xenbus_msg_reply(XS_READ, xbt, req, ARRAY_SIZE(req));
302 msg = errmsg(rep);
303 if (msg) {
304 *value = NULL;
305 return msg;
306 }
307 res = ExAllocatePoolWithTag(NonPagedPool, rep->len + 1, XENPCI_POOL_TAG);
308 memcpy(res, rep + 1, rep->len);
309 res[rep->len] = 0;
310 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
311 *value = res;
312 return NULL;
313 }
315 char *
316 XenBus_Write(xenbus_transaction_t xbt, const char *path, const char *value)
317 {
318 struct write_req req[] = {
319 {path, strlen(path) + 1},
320 {value, strlen(value) + 1},
321 };
322 struct xsd_sockmsg *rep;
323 char *msg;
325 rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req));
326 msg = errmsg(rep);
327 if (msg)
328 return msg;
329 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
330 return NULL;
331 }
333 char* xenbus_wait_for_value(const char* path,const char* value)
334 {
335 UNREFERENCED_PARAMETER(path);
336 UNREFERENCED_PARAMETER(value);
337 // for(;;)
338 // {
339 // char *res, *msg;
340 // int r;
341 //
342 // msg = xenbus_read(XBT_NIL, path, &res);
343 // if(msg) return msg;
344 //
345 // r = strcmp(value,res);
346 // ExFreePoolWithTag(res, XENPCI_POOL_TAG);
347 //
348 // if(r==0)
349 // break;
350 // else
351 // wait_for_watch();
352 // }
353 return NULL;
354 }
356 NTSTATUS
357 XenBus_Init()
358 {
359 //KdPrint((__DRIVER_NAME " --> XenBus_Init\n"));
361 xen_store_evtchn = EvtChn_GetXenStorePort();
362 xen_store_interface = EvtChn_GetXenStoreRingAddr();
364 //KdPrint((__DRIVER_NAME " xen_store_evtchn = %08x\n", xen_store_evtchn));
365 //KdPrint((__DRIVER_NAME " xen_store_interface = %08x\n", xen_store_interface));
367 KeInitializeEvent(&XenBus_ReadThreadEvent, SynchronizationEvent, FALSE);
368 KeInitializeEvent(&XenBus_WatchThreadEvent, SynchronizationEvent, FALSE);
370 //KdPrint((__DRIVER_NAME " <-- XenBus_Init\n"));
372 return STATUS_SUCCESS;
373 }
375 NTSTATUS
376 XenBus_Start()
377 {
378 OBJECT_ATTRIBUTES oa;
379 NTSTATUS status;
380 int i;
382 KdPrint((__DRIVER_NAME " --> XenBus_Start\n"));
384 InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
385 status = PsCreateSystemThread(&XenBus_ReadThreadHandle, THREAD_ALL_ACCESS, &oa, NULL, NULL, XenBus_ReadThreadProc, NULL);
387 // remove all existing watches already in Xen too...
389 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
390 XenBus_WatchEntries[i].Active = 0;
392 InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
393 status = PsCreateSystemThread(&XenBus_WatchThreadHandle, THREAD_ALL_ACCESS, &oa, NULL, NULL, XenBus_WatchThreadProc, NULL);
395 EvtChn_Bind(xen_store_evtchn, XenBus_Interrupt, NULL);
397 KdPrint((__DRIVER_NAME " <-- XenBus_Start\n"));
399 return STATUS_SUCCESS;
400 }
402 NTSTATUS
403 XenBus_Stop()
404 {
405 int i;
407 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
408 {
409 if (!XenBus_WatchEntries[i].Active)
410 continue;
411 XenBus_RemWatch(XBT_NIL, XenBus_WatchEntries[i].Path, XenBus_WatchEntries[i].ServiceRoutine, XenBus_WatchEntries[i].ServiceContext);
412 }
414 EvtChn_Unbind(xen_store_evtchn);
416 // Does this actually stop the threads???
417 ZwClose(XenBus_WatchThreadHandle);
418 ZwClose(XenBus_ReadThreadHandle);
420 return STATUS_SUCCESS;
421 }
423 char *
424 XenBus_List(xenbus_transaction_t xbt, const char *pre, char ***contents)
425 {
426 struct xsd_sockmsg *reply, *repmsg;
427 struct write_req req[] = { { pre, strlen(pre)+1 } };
428 ULONG nr_elems, x, i;
429 char **res;
430 char *msg;
432 //KdPrint((__DRIVER_NAME " --> xenbus_ls\n"));
434 repmsg = xenbus_msg_reply(XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
435 msg = errmsg(repmsg);
436 if (msg) {
437 *contents = NULL;
438 //KdPrint((__DRIVER_NAME " <-- xenbus_ls (error)\n"));
439 return msg;
440 }
441 reply = repmsg + 1;
442 for (x = nr_elems = 0; x < repmsg->len; x++)
443 nr_elems += (((char *)reply)[x] == 0);
444 res = ExAllocatePoolWithTag(NonPagedPool, sizeof(res[0]) * (nr_elems + 1), XENPCI_POOL_TAG);
445 for (x = i = 0; i < nr_elems; i++) {
446 int l = strlen((char *)reply + x);
447 res[i] = ExAllocatePoolWithTag(NonPagedPool, l + 1, XENPCI_POOL_TAG);
448 memcpy(res[i], (char *)reply + x, l + 1);
449 x += l + 1;
450 }
451 res[i] = NULL;
452 ExFreePoolWithTag(repmsg, XENPCI_POOL_TAG);
453 *contents = res;
454 //KdPrint((__DRIVER_NAME " <-- xenbus_ls\n"));
455 return NULL;
456 }
458 void
459 do_ls_test(const char *pre)
460 {
461 char **dirs;
462 int x;
463 char *msg;
465 //KdPrint((__DRIVER_NAME " <-- do_ls_test(\"%s\")\n", pre));
467 msg = XenBus_List(XBT_NIL, pre, &dirs);
468 if (msg)
469 {
470 //KdPrint((__DRIVER_NAME " Error in xenbus ls: %s\n", msg));
471 ExFreePoolWithTag(msg, XENPCI_POOL_TAG);
472 return;
473 }
474 for (x = 0; dirs[x]; x++)
475 {
476 //KdPrint((__DRIVER_NAME " ls %s[%d] -> %s\n", pre, x, dirs[x]));
477 ExFreePoolWithTag(dirs[x], XENPCI_POOL_TAG);
478 }
479 ExFreePoolWithTag(dirs, XENPCI_POOL_TAG);
480 //KdPrint((__DRIVER_NAME " --> do_ls_test\n"));
481 }
483 int ReadThreadSetCount;
484 int ReadThreadWaitCount;
486 static void
487 XenBus_ReadThreadProc(PVOID StartContext) {
488 int NewWriteIndex;
489 struct xsd_sockmsg msg;
490 char *payload;
491 char *path, *token;
493 UNREFERENCED_PARAMETER(StartContext);
495 for(;;)
496 {
497 KeWaitForSingleObject(&XenBus_ReadThreadEvent, Executive, KernelMode, FALSE, NULL);
498 //KdPrint((__DRIVER_NAME " ReadThread Woken (Count = %d)\n", ReadThreadWaitCount++));
499 while (xen_store_interface->rsp_prod != xen_store_interface->rsp_cons)
500 {
501 //KdPrint((__DRIVER_NAME " a - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
502 if (xen_store_interface->rsp_prod - xen_store_interface->rsp_cons < sizeof(msg))
503 {
504 //KdPrint((__DRIVER_NAME " +++ Message incomplete (not even a full header)\n"));
505 break;
506 }
507 //_ReadBarrier();
508 KeMemoryBarrier();
509 memcpy_from_ring(xen_store_interface->rsp, &msg, MASK_XENSTORE_IDX(xen_store_interface->rsp_cons), sizeof(msg));
510 if (xen_store_interface->rsp_prod - xen_store_interface->rsp_cons < sizeof(msg) + msg.len)
511 {
512 //KdPrint((__DRIVER_NAME " +++ Message incomplete (header but not full body)\n"));
513 break;
514 }
516 if(msg.type == XS_WATCH_EVENT)
517 {
518 payload = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
520 memcpy_from_ring(xen_store_interface->rsp, payload, MASK_XENSTORE_IDX(xen_store_interface->rsp_cons), msg.len + sizeof(msg));
522 xen_store_interface->rsp_cons += msg.len + sizeof(msg);
523 //KdPrint((__DRIVER_NAME " b - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
525 path = payload + sizeof(msg);
526 token = path + strlen(path) + 1;
528 NewWriteIndex = (XenBus_WatchRingWriteIndex + 1) & 127;
529 if (NewWriteIndex != XenBus_WatchRingReadIndex)
530 {
531 strncpy(XenBus_WatchRing[NewWriteIndex].Path, path, 128);
532 strncpy(XenBus_WatchRing[NewWriteIndex].Token, token, 10);
533 XenBus_WatchRingWriteIndex = NewWriteIndex;
534 }
535 else
536 {
537 KdPrint((__DRIVER_NAME " +++ Queue full Path = %s Token = %s\n", path, token));
538 // drop the message on the floor
539 continue;
540 }
542 ExFreePoolWithTag(payload, XENPCI_POOL_TAG);
543 //KdPrint((__DRIVER_NAME " +++ Watch Path = %s Token = %s\n", path, token));
544 KeSetEvent(&XenBus_WatchThreadEvent, 1, FALSE);
545 }
546 else
547 {
548 req_info[msg.req_id].Reply = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
549 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));
550 xen_store_interface->rsp_cons += msg.len + sizeof(msg);
551 //KdPrint((__DRIVER_NAME " c - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
552 //KdPrint((__DRIVER_NAME " +++ Message = %s\n", ((char *)req_info[msg.req_id].Reply) + sizeof(msg)));
553 KeSetEvent(&req_info[msg.req_id].WaitEvent, 1, FALSE);
554 }
555 }
556 }
557 }
559 static void
560 XenBus_WatchThreadProc(PVOID StartContext)
561 {
562 int index;
563 PXENBUS_WATCH_ENTRY entry;
565 UNREFERENCED_PARAMETER(StartContext);
567 for(;;)
568 {
569 KeWaitForSingleObject(&XenBus_WatchThreadEvent, Executive, KernelMode, FALSE, NULL);
570 while (XenBus_WatchRingReadIndex != XenBus_WatchRingWriteIndex)
571 {
572 XenBus_WatchRingReadIndex = (XenBus_WatchRingReadIndex + 1) & 127;
573 index = atoi(XenBus_WatchRing[XenBus_WatchRingReadIndex].Token);
574 //XenBus_WatchRing[XenBus_WatchRingReadIndex].Path
575 //XenBus_WatchRing[XenBus_WatchRingReadIndex].Token
577 entry = &XenBus_WatchEntries[index];
578 if (!entry->Active)
579 {
580 KdPrint((__DRIVER_NAME " +++ Watch not active! = %s Token = %s\n", XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, XenBus_WatchRing[XenBus_WatchRingReadIndex].Token));
581 continue;
582 }
583 entry->Count++;
584 if (!entry->ServiceRoutine)
585 {
586 KdPrint((__DRIVER_NAME " +++ no handler for watch! = %s Token = %s\n", XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, XenBus_WatchRing[XenBus_WatchRingReadIndex].Token));
587 continue;
588 }
589 //KdPrint((__DRIVER_NAME " +++ Watch Triggered Path = %s Token = %d (%s)\n", XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, index, XenBus_WatchRing[XenBus_WatchRingReadIndex].Token));
590 entry->ServiceRoutine(XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, entry->ServiceContext);
591 }
592 }
593 }
595 char *
596 XenBus_AddWatch(xenbus_transaction_t xbt, const char *Path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
597 {
598 struct xsd_sockmsg *rep;
599 char *msg;
600 int i;
601 char Token[20];
602 struct write_req req[2];
604 KdPrint((__DRIVER_NAME " --> XenBus_AddWatch\n"));
606 // check that Path < 128 chars
608 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
609 if (XenBus_WatchEntries[i].Active == 0)
610 break;
612 if (i == MAX_WATCH_ENTRIES)
613 {
614 KdPrint((__DRIVER_NAME " +++ No more watch slots left\n"));
615 return NULL;
616 }
618 req[0].data = Path;
619 req[0].len = strlen(Path) + 1;
621 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", i);
622 req[1].data = Token;
623 req[1].len = strlen(Token) + 1;
625 rep = xenbus_msg_reply(XS_WATCH, xbt, req, ARRAY_SIZE(req));
627 msg = errmsg(rep);
628 if (msg)
629 return msg;
631 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
633 strncpy(XenBus_WatchEntries[i].Path, Path, 128);
634 XenBus_WatchEntries[i].ServiceRoutine = ServiceRoutine;
635 XenBus_WatchEntries[i].ServiceContext = ServiceContext;
636 XenBus_WatchEntries[i].Count = 0;
637 XenBus_WatchEntries[i].Active = 1;
639 KdPrint((__DRIVER_NAME " <-- XenBus_AddWatch\n"));
641 return NULL;
642 }
644 char *
645 XenBus_RemWatch(xenbus_transaction_t xbt, const char *Path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
646 {
647 struct xsd_sockmsg *rep;
648 char *msg;
649 int i;
650 char Token[20];
651 struct write_req req[2];
653 //KdPrint((__DRIVER_NAME " --> XenBus_RemWatch\n"));
655 // check that Path < 128 chars
657 for (i = 0; i < MAX_WATCH_ENTRIES; i++) {
658 if (XenBus_WatchEntries[i].Active == 1 && strcmp(XenBus_WatchEntries[i].Path, Path) == 0 && XenBus_WatchEntries[i].ServiceRoutine == ServiceRoutine && XenBus_WatchEntries[i].ServiceContext == ServiceContext)
659 break;
660 }
662 if (i == MAX_WATCH_ENTRIES)
663 {
664 KdPrint((__DRIVER_NAME " Watch not set - can't remove\n"));
665 return NULL;
666 }
668 req[0].data = Path;
669 req[0].len = strlen(Path) + 1;
671 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", i);
672 req[1].data = Token;
673 req[1].len = strlen(Token) + 1;
675 rep = xenbus_msg_reply(XS_UNWATCH, xbt, req, ARRAY_SIZE(req));
677 msg = errmsg(rep);
678 if (msg)
679 return msg;
681 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
683 XenBus_WatchEntries[i].Active = 0;
685 //KdPrint((__DRIVER_NAME " <-- XenBus_RemWatch\n"));
687 return NULL;
688 }
691 char *
692 XenBus_StartTransaction(xenbus_transaction_t *xbt)
693 {
694 /* xenstored becomes angry if you send a length 0 message, so just
695 shove a nul terminator on the end */
696 struct write_req req = { "", 1};
697 struct xsd_sockmsg *rep;
698 char *err;
700 rep = xenbus_msg_reply(XS_TRANSACTION_START, 0, &req, 1);
701 err = errmsg(rep);
702 if (err)
703 return err;
704 *xbt = atoi((char *)(rep + 1));
705 //sscanf((char *)(rep + 1), "%u", xbt);
706 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
707 return NULL;
708 }
710 char *
711 XenBus_EndTransaction(xenbus_transaction_t t, int abort, int *retry)
712 {
713 struct xsd_sockmsg *rep;
714 struct write_req req;
715 char *err;
717 *retry = 0;
719 req.data = abort ? "F" : "T";
720 req.len = 2;
721 rep = xenbus_msg_reply(XS_TRANSACTION_END, t, &req, 1);
722 err = errmsg(rep);
723 if (err) {
724 if (!strcmp(err, "EAGAIN")) {
725 *retry = 1;
726 ExFreePoolWithTag(err, XENPCI_POOL_TAG);
727 return NULL;
728 } else {
729 return err;
730 }
731 }
732 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
733 return NULL;
734 }
735 /*
736 void
737 XenBus_ThreadProc(PVOID StartContext)
738 {
739 char *response;
741 //KdPrint((__DRIVER_NAME " --> XenBus_ThreadProc\n"));
743 //do_ls_test("device");
745 // do_ls_test("local");
747 // do_ls_test("control");
749 // do_ls_test(".");
751 response = XenBus_AddWatch(XBT_NIL, SHUTDOWN_PATH, XenBus_ShutdownHandler, NULL);
753 //KdPrint((__DRIVER_NAME " <-- watch response = '%s'\n", response));
755 //KdPrint((__DRIVER_NAME " <-- XenBus_ThreadProc\n"));
756 }
757 */
759 static BOOLEAN
760 XenBus_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext)
761 {
762 UNREFERENCED_PARAMETER(Interrupt);
763 UNREFERENCED_PARAMETER(ServiceContext);
765 //KdPrint((__DRIVER_NAME " --> XenBus_Interrupt (Count = %d)\n", ReadThreadSetCount++));
767 KeSetEvent(&XenBus_ReadThreadEvent, 1, FALSE);
769 //KdPrint((__DRIVER_NAME " <-- XenBus_Interrupt\n"));
771 return TRUE;
772 }
774 char *
775 XenBus_Printf(xenbus_transaction_t xbt, const char *path, const char *fmt, ...)
776 {
777 va_list ap;
778 char buf[1024];
780 va_start(ap, fmt);
781 RtlStringCbVPrintfA(buf, ARRAY_SIZE(buf), fmt, ap);
782 va_end(ap);
783 return XenBus_Write(xbt, path, buf);