win-pvdrivers

view xenpci/xenbus.c @ 35:2e1d570b69e9

Final commit before 0.4.0
author James Harper <james.harper@bendigoit.com.au>
date Wed Dec 05 19:56:11 2007 +1100 (2007-12-05)
parents b55f3c61e509
children 3ac5c4431dbb a70cbf588756
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 BOOLEAN XenBus_ShuttingDown;
78 static void
79 XenBus_ReadThreadProc(PVOID StartContext);
80 static void
81 XenBus_WatchThreadProc(PVOID StartContext);
83 static BOOLEAN
84 XenBus_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext);
86 static int allocate_xenbus_id(void)
87 {
88 static int probe;
89 int o_probe;
91 //KdPrint((__DRIVER_NAME " --> allocate_xenbus_id\n"));
93 for (;;)
94 {
95 // spin_lock(&req_lock);
96 if (nr_live_reqs < NR_REQS)
97 break;
98 // spin_unlock(&req_lock);
99 // wait_event(req_wq, (nr_live_reqs < NR_REQS));
100 }
102 o_probe = probe;
104 for (;;)
105 {
106 if (!req_info[o_probe].In_Use)
107 break;
108 o_probe = (o_probe + 1) % NR_REQS;
109 // BUG_ON(o_probe == probe);
110 }
111 nr_live_reqs++;
112 req_info[o_probe].In_Use = 1;
113 probe = (o_probe + 1) % NR_REQS;
114 //spin_unlock(&req_lock);
115 //init_waitqueue_head(&req_info[o_probe].waitq);
116 KeInitializeEvent(&req_info[o_probe].WaitEvent, SynchronizationEvent, FALSE);
118 //KdPrint((__DRIVER_NAME " <-- allocate_xenbus_id\n"));
120 return o_probe;
121 }
123 static void release_xenbus_id(int id)
124 {
125 // BUG_ON(!req_info[id].in_use);
126 // spin_lock(&req_lock);
127 req_info[id].In_Use = 0;
128 nr_live_reqs--;
129 req_info[id].In_Use = 0;
130 // if (nr_live_reqs == NR_REQS - 1)
131 // wake_up(&req_wq);
132 // spin_unlock(&req_lock);
133 }
136 static char *errmsg(struct xsd_sockmsg *rep)
137 {
138 char *res;
139 if (!rep) {
140 char msg[] = "No reply";
141 size_t len = strlen(msg) + 1;
142 return memcpy(ExAllocatePoolWithTag(NonPagedPool, len, XENPCI_POOL_TAG), msg, len);
143 }
144 if (rep->type != XS_ERROR)
145 return NULL;
146 res = ExAllocatePoolWithTag(NonPagedPool, rep->len + 1, XENPCI_POOL_TAG);
147 memcpy(res, rep + 1, rep->len);
148 res[rep->len] = 0;
149 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
150 return res;
151 }
153 static void memcpy_from_ring(const void *Ring,
154 void *Dest,
155 int off,
156 int len)
157 {
158 int c1, c2;
159 const char *ring = Ring;
160 char *dest = Dest;
161 c1 = min(len, XENSTORE_RING_SIZE - off);
162 c2 = len - c1;
163 memcpy(dest, ring + off, c1);
164 memcpy(dest + c1, ring, c2);
165 }
167 void wait_for_watch(void)
168 {
169 // DEFINE_WAIT(w);
170 // add_waiter(w,watch_queue);
171 // schedule();
172 // remove_waiter(w);
173 // wake(current);
174 }
176 struct write_req {
177 const void *data;
178 unsigned len;
179 };
181 static evtchn_port_t xen_store_evtchn;
183 static void xb_write(int type, int req_id, xenbus_transaction_t trans_id,
184 const struct write_req *req, int nr_reqs)
185 {
186 XENSTORE_RING_IDX prod;
187 int r;
188 size_t len = 0;
189 const struct write_req *cur_req;
190 size_t req_off;
191 size_t total_off;
192 size_t this_chunk;
193 struct xsd_sockmsg m = {type, req_id, trans_id };
194 struct write_req header_req = { &m, sizeof(m) };
196 //KdPrint((__DRIVER_NAME " --> xb_write\n"));
198 for (r = 0; r < nr_reqs; r++)
199 len += req[r].len;
200 m.len = len;
201 len += sizeof(m);
203 cur_req = &header_req;
205 // BUG_ON(len > XENSTORE_RING_SIZE);
206 /* Wait for the ring to drain to the point where we can send the
207 message. */
208 prod = xen_store_interface->req_prod;
210 //KdPrint((__DRIVER_NAME " prod = %08x\n", prod));
212 if (prod + len - xen_store_interface->req_cons > XENSTORE_RING_SIZE)
213 {
214 /* Wait for there to be space on the ring */
215 //KdPrint((__DRIVER_NAME " prod %d, len %d, cons %d, size %d; waiting.\n", prod, len, xen_store_interface->req_cons, XENSTORE_RING_SIZE));
216 // wait_event(xb_waitq, xen_store_interface->req_prod + len - xen_store_interface->req_cons <= XENSTORE_RING_SIZE);
217 //KdPrint((__DRIVER_NAME " Back from wait.\n"));
218 prod = xen_store_interface->req_prod;
219 }
221 /* We're now guaranteed to be able to send the message without
222 overflowing the ring. Do so. */
224 total_off = 0;
225 req_off = 0;
227 while (total_off < len)
228 {
229 this_chunk = min(cur_req->len - req_off,XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
230 memcpy((char *)xen_store_interface->req + MASK_XENSTORE_IDX(prod), (char *)cur_req->data + req_off, this_chunk);
231 prod += this_chunk;
232 req_off += this_chunk;
233 total_off += this_chunk;
234 if (req_off == cur_req->len)
235 {
236 req_off = 0;
237 if (cur_req == &header_req)
238 cur_req = req;
239 else
240 cur_req++;
241 }
242 }
244 //KdPrint((__DRIVER_NAME " Complete main loop of xb_write.\n"));
246 // BUG_ON(req_off != 0);
247 // BUG_ON(total_off != len);
248 // BUG_ON(prod > xen_store_interface->req_cons + XENSTORE_RING_SIZE);
250 /* Remote must see entire message before updating indexes */
251 //_WriteBarrier();
252 KeMemoryBarrier();
254 xen_store_interface->req_prod += len;
256 //KdPrint((__DRIVER_NAME " prod = %08x\n", xen_store_interface->req_prod));
258 /* Send evtchn to notify remote */
259 EvtChn_Notify(xen_store_evtchn);
261 //KdPrint((__DRIVER_NAME " <-- xb_write\n"));
262 }
264 static struct xsd_sockmsg *
265 xenbus_msg_reply(int type, xenbus_transaction_t trans, struct write_req *io, int nr_reqs)
266 {
267 int id;
268 // DEFINE_WAIT(w);
269 struct xsd_sockmsg *rep;
271 // KdPrint((__DRIVER_NAME " --> xenbus_msg_reply\n"));
273 id = allocate_xenbus_id();
274 // add_waiter(w, req_info[id].waitq);
276 xb_write(type, id, trans, io, nr_reqs);
277 //
278 // schedule();
279 // remove_waiter(w);
280 // wake(current);
281 //
282 // KdPrint((__DRIVER_NAME " starting wait\n"));
284 KeWaitForSingleObject(&req_info[id].WaitEvent, Executive, KernelMode, FALSE, NULL);
286 //KdPrint((__DRIVER_NAME " wait complete\n"));
288 rep = req_info[id].Reply;
289 // BUG_ON(rep->req_id != id);
290 release_xenbus_id(id);
291 // KdPrint((__DRIVER_NAME " <-- xenbus_msg_reply\n"));
292 return rep;
293 }
295 char *
296 XenBus_Read(xenbus_transaction_t xbt, const char *path, char **value)
297 {
298 struct write_req req[] = { {path, strlen(path) + 1} };
299 struct xsd_sockmsg *rep;
300 char *res;
301 char *msg;
303 rep = xenbus_msg_reply(XS_READ, xbt, req, ARRAY_SIZE(req));
304 msg = errmsg(rep);
305 if (msg) {
306 *value = NULL;
307 return msg;
308 }
309 res = ExAllocatePoolWithTag(NonPagedPool, rep->len + 1, XENPCI_POOL_TAG);
310 memcpy(res, rep + 1, rep->len);
311 res[rep->len] = 0;
312 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
313 *value = res;
314 return NULL;
315 }
317 char *
318 XenBus_Write(xenbus_transaction_t xbt, const char *path, const char *value)
319 {
320 struct write_req req[] = {
321 {path, strlen(path) + 1},
322 {value, strlen(value) + 1},
323 };
324 struct xsd_sockmsg *rep;
325 char *msg;
327 rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req));
328 msg = errmsg(rep);
329 if (msg)
330 return msg;
331 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
332 return NULL;
333 }
335 char* xenbus_wait_for_value(const char* path,const char* value)
336 {
337 UNREFERENCED_PARAMETER(path);
338 UNREFERENCED_PARAMETER(value);
339 // for(;;)
340 // {
341 // char *res, *msg;
342 // int r;
343 //
344 // msg = xenbus_read(XBT_NIL, path, &res);
345 // if(msg) return msg;
346 //
347 // r = strcmp(value,res);
348 // ExFreePoolWithTag(res, XENPCI_POOL_TAG);
349 //
350 // if(r==0)
351 // break;
352 // else
353 // wait_for_watch();
354 // }
355 return NULL;
356 }
358 NTSTATUS
359 XenBus_Init()
360 {
361 NTSTATUS Status;
362 OBJECT_ATTRIBUTES oa;
363 int i;
365 KdPrint((__DRIVER_NAME " --> XenBus_Init\n"));
367 xen_store_evtchn = EvtChn_GetXenStorePort();
368 xen_store_interface = EvtChn_GetXenStoreRingAddr();
370 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
371 XenBus_WatchEntries[i].Active = 0;
373 KeInitializeEvent(&XenBus_ReadThreadEvent, SynchronizationEvent, FALSE);
374 KeInitializeEvent(&XenBus_WatchThreadEvent, SynchronizationEvent, FALSE);
375 XenBus_ShuttingDown = FALSE;
377 //InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
378 //Status = PsCreateSystemThread(&XenBus_ReadThreadHandle, THREAD_ALL_ACCESS, &oa, NULL, NULL, XenBus_ReadThreadProc, NULL);
379 Status = PsCreateSystemThread(&XenBus_ReadThreadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenBus_ReadThreadProc, NULL);
381 //InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
382 //Status = PsCreateSystemThread(&XenBus_WatchThreadHandle, THREAD_ALL_ACCESS, &oa, NULL, NULL, XenBus_WatchThreadProc, NULL);
383 Status = PsCreateSystemThread(&XenBus_WatchThreadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenBus_WatchThreadProc, NULL);
385 KdPrint((__DRIVER_NAME " <-- XenBus_Init\n"));
387 return STATUS_SUCCESS;
388 }
390 NTSTATUS
391 XenBus_Start()
392 {
393 KdPrint((__DRIVER_NAME " --> XenBus_Start\n"));
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 KdPrint((__DRIVER_NAME " --> XenBus_Stop\n"));
409 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
410 {
411 if (XenBus_WatchEntries[i].Active)
412 XenBus_RemWatch(XBT_NIL, XenBus_WatchEntries[i].Path, XenBus_WatchEntries[i].ServiceRoutine, XenBus_WatchEntries[i].ServiceContext);
413 }
415 EvtChn_Unbind(xen_store_evtchn);
417 KdPrint((__DRIVER_NAME " <-- XenBus_Stop\n"));
419 return STATUS_SUCCESS;
420 }
422 NTSTATUS
423 XenBus_Close()
424 {
425 PKWAIT_BLOCK WaitBlockArray[2];
426 PVOID WaitArray[2];
428 XenBus_ShuttingDown = TRUE;
430 KdPrint((__DRIVER_NAME " Signalling Threads\n"));
431 KeSetEvent(&XenBus_ReadThreadEvent, 1, FALSE);
432 KeSetEvent(&XenBus_WatchThreadEvent, 1, FALSE);
433 KdPrint((__DRIVER_NAME " Waiting for threads to die\n"));
434 ObReferenceObjectByHandle(XenBus_ReadThreadHandle, THREAD_ALL_ACCESS, NULL, KernelMode, &WaitArray[0], NULL);
435 ObReferenceObjectByHandle(XenBus_WatchThreadHandle, THREAD_ALL_ACCESS, NULL, KernelMode, &WaitArray[1], NULL);
436 KeWaitForMultipleObjects(2, WaitArray, WaitAll, Executive, KernelMode, FALSE, NULL, WaitBlockArray);
437 KdPrint((__DRIVER_NAME " Threads are dead\n"));
439 XenBus_ShuttingDown = FALSE;
441 ObDereferenceObject(WaitArray[0]);
442 ObDereferenceObject(WaitArray[1]);
444 ZwClose(XenBus_WatchThreadHandle);
445 ZwClose(XenBus_ReadThreadHandle);
447 KdPrint((__DRIVER_NAME " <-- XenBus_Close\n"));
449 return STATUS_SUCCESS;
450 }
452 char *
453 XenBus_List(xenbus_transaction_t xbt, const char *pre, char ***contents)
454 {
455 struct xsd_sockmsg *reply, *repmsg;
456 struct write_req req[] = { { pre, strlen(pre)+1 } };
457 ULONG nr_elems, x, i;
458 char **res;
459 char *msg;
461 //KdPrint((__DRIVER_NAME " --> xenbus_ls\n"));
463 repmsg = xenbus_msg_reply(XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
464 msg = errmsg(repmsg);
465 if (msg) {
466 *contents = NULL;
467 //KdPrint((__DRIVER_NAME " <-- xenbus_ls (error)\n"));
468 return msg;
469 }
470 reply = repmsg + 1;
471 for (x = nr_elems = 0; x < repmsg->len; x++)
472 nr_elems += (((char *)reply)[x] == 0);
473 res = ExAllocatePoolWithTag(NonPagedPool, sizeof(res[0]) * (nr_elems + 1), XENPCI_POOL_TAG);
474 for (x = i = 0; i < nr_elems; i++) {
475 int l = strlen((char *)reply + x);
476 res[i] = ExAllocatePoolWithTag(NonPagedPool, l + 1, XENPCI_POOL_TAG);
477 memcpy(res[i], (char *)reply + x, l + 1);
478 x += l + 1;
479 }
480 res[i] = NULL;
481 ExFreePoolWithTag(repmsg, XENPCI_POOL_TAG);
482 *contents = res;
483 //KdPrint((__DRIVER_NAME " <-- xenbus_ls\n"));
484 return NULL;
485 }
487 void
488 do_ls_test(const char *pre)
489 {
490 char **dirs;
491 int x;
492 char *msg;
494 //KdPrint((__DRIVER_NAME " <-- do_ls_test(\"%s\")\n", pre));
496 msg = XenBus_List(XBT_NIL, pre, &dirs);
497 if (msg)
498 {
499 //KdPrint((__DRIVER_NAME " Error in xenbus ls: %s\n", msg));
500 ExFreePoolWithTag(msg, XENPCI_POOL_TAG);
501 return;
502 }
503 for (x = 0; dirs[x]; x++)
504 {
505 //KdPrint((__DRIVER_NAME " ls %s[%d] -> %s\n", pre, x, dirs[x]));
506 ExFreePoolWithTag(dirs[x], XENPCI_POOL_TAG);
507 }
508 ExFreePoolWithTag(dirs, XENPCI_POOL_TAG);
509 //KdPrint((__DRIVER_NAME " --> do_ls_test\n"));
510 }
512 static void
513 XenBus_ReadThreadProc(PVOID StartContext) {
514 int NewWriteIndex;
515 struct xsd_sockmsg msg;
516 char *payload;
517 char *path, *token;
519 UNREFERENCED_PARAMETER(StartContext);
521 for(;;)
522 {
523 KeWaitForSingleObject(&XenBus_ReadThreadEvent, Executive, KernelMode, FALSE, NULL);
524 if (XenBus_ShuttingDown)
525 {
526 KdPrint((__DRIVER_NAME " Shutdown detected in ReadThreadProc\n"));
527 PsTerminateSystemThread(0);
528 }
529 //KdPrint((__DRIVER_NAME " ReadThread Woken (Count = %d)\n", ReadThreadWaitCount++));
530 while (xen_store_interface->rsp_prod != xen_store_interface->rsp_cons)
531 {
532 //KdPrint((__DRIVER_NAME " a - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
533 if (xen_store_interface->rsp_prod - xen_store_interface->rsp_cons < sizeof(msg))
534 {
535 //KdPrint((__DRIVER_NAME " +++ Message incomplete (not even a full header)\n"));
536 break;
537 }
538 //_ReadBarrier();
539 KeMemoryBarrier();
540 memcpy_from_ring(xen_store_interface->rsp, &msg, MASK_XENSTORE_IDX(xen_store_interface->rsp_cons), sizeof(msg));
541 if (xen_store_interface->rsp_prod - xen_store_interface->rsp_cons < sizeof(msg) + msg.len)
542 {
543 //KdPrint((__DRIVER_NAME " +++ Message incomplete (header but not full body)\n"));
544 break;
545 }
547 if(msg.type == XS_WATCH_EVENT)
548 {
549 payload = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
551 memcpy_from_ring(xen_store_interface->rsp, payload, MASK_XENSTORE_IDX(xen_store_interface->rsp_cons), msg.len + sizeof(msg));
553 xen_store_interface->rsp_cons += msg.len + sizeof(msg);
554 //KdPrint((__DRIVER_NAME " b - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
556 path = payload + sizeof(msg);
557 token = path + strlen(path) + 1;
559 NewWriteIndex = (XenBus_WatchRingWriteIndex + 1) & 127;
560 if (NewWriteIndex != XenBus_WatchRingReadIndex)
561 {
562 strncpy(XenBus_WatchRing[NewWriteIndex].Path, path, 128);
563 strncpy(XenBus_WatchRing[NewWriteIndex].Token, token, 10);
564 XenBus_WatchRingWriteIndex = NewWriteIndex;
565 }
566 else
567 {
568 KdPrint((__DRIVER_NAME " +++ Queue full Path = %s Token = %s\n", path, token));
569 // drop the message on the floor
570 continue;
571 }
573 ExFreePoolWithTag(payload, XENPCI_POOL_TAG);
574 //KdPrint((__DRIVER_NAME " +++ Watch Path = %s Token = %s\n", path, token));
575 KeSetEvent(&XenBus_WatchThreadEvent, 1, FALSE);
576 }
577 else
578 {
579 req_info[msg.req_id].Reply = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
580 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));
581 xen_store_interface->rsp_cons += msg.len + sizeof(msg);
582 //KdPrint((__DRIVER_NAME " c - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
583 //KdPrint((__DRIVER_NAME " +++ Message = %s\n", ((char *)req_info[msg.req_id].Reply) + sizeof(msg)));
584 KeSetEvent(&req_info[msg.req_id].WaitEvent, 1, FALSE);
585 }
586 }
587 }
588 }
590 static void
591 XenBus_WatchThreadProc(PVOID StartContext)
592 {
593 int index;
594 PXENBUS_WATCH_ENTRY entry;
596 UNREFERENCED_PARAMETER(StartContext);
598 for(;;)
599 {
600 KeWaitForSingleObject(&XenBus_WatchThreadEvent, Executive, KernelMode, FALSE, NULL);
601 if (XenBus_ShuttingDown)
602 {
603 KdPrint((__DRIVER_NAME " Shutdown detected in WatchThreadProc\n"));
604 PsTerminateSystemThread(0);
605 }
606 while (XenBus_WatchRingReadIndex != XenBus_WatchRingWriteIndex)
607 {
608 XenBus_WatchRingReadIndex = (XenBus_WatchRingReadIndex + 1) & 127;
609 index = atoi(XenBus_WatchRing[XenBus_WatchRingReadIndex].Token);
610 //XenBus_WatchRing[XenBus_WatchRingReadIndex].Path
611 //XenBus_WatchRing[XenBus_WatchRingReadIndex].Token
613 entry = &XenBus_WatchEntries[index];
614 if (!entry->Active)
615 {
616 KdPrint((__DRIVER_NAME " +++ Watch not active! = %s Token = %s\n", XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, XenBus_WatchRing[XenBus_WatchRingReadIndex].Token));
617 continue;
618 }
619 entry->Count++;
620 if (!entry->ServiceRoutine)
621 {
622 KdPrint((__DRIVER_NAME " +++ no handler for watch! = %s Token = %s\n", XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, XenBus_WatchRing[XenBus_WatchRingReadIndex].Token));
623 continue;
624 }
625 //KdPrint((__DRIVER_NAME " +++ Watch Triggered Path = %s Token = %d (%s)\n", XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, index, XenBus_WatchRing[XenBus_WatchRingReadIndex].Token));
626 entry->ServiceRoutine(XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, entry->ServiceContext);
627 }
628 }
629 }
631 char *
632 XenBus_AddWatch(xenbus_transaction_t xbt, const char *Path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
633 {
634 struct xsd_sockmsg *rep;
635 char *msg;
636 int i;
637 char Token[20];
638 struct write_req req[2];
640 // KdPrint((__DRIVER_NAME " --> XenBus_AddWatch\n"));
642 // check that Path < 128 chars
644 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
645 if (XenBus_WatchEntries[i].Active == 0)
646 break;
648 if (i == MAX_WATCH_ENTRIES)
649 {
650 KdPrint((__DRIVER_NAME " +++ No more watch slots left\n"));
651 return NULL;
652 }
654 req[0].data = Path;
655 req[0].len = strlen(Path) + 1;
657 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", i);
658 req[1].data = Token;
659 req[1].len = strlen(Token) + 1;
661 rep = xenbus_msg_reply(XS_WATCH, xbt, req, ARRAY_SIZE(req));
663 msg = errmsg(rep);
664 if (msg)
665 return msg;
667 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
669 strncpy(XenBus_WatchEntries[i].Path, Path, 128);
670 XenBus_WatchEntries[i].ServiceRoutine = ServiceRoutine;
671 XenBus_WatchEntries[i].ServiceContext = ServiceContext;
672 XenBus_WatchEntries[i].Count = 0;
673 XenBus_WatchEntries[i].Active = 1;
675 // KdPrint((__DRIVER_NAME " <-- XenBus_AddWatch\n"));
677 return NULL;
678 }
680 char *
681 XenBus_RemWatch(xenbus_transaction_t xbt, const char *Path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
682 {
683 struct xsd_sockmsg *rep;
684 char *msg;
685 int i;
686 char Token[20];
687 struct write_req req[2];
689 //KdPrint((__DRIVER_NAME " --> XenBus_RemWatch\n"));
691 // check that Path < 128 chars
693 for (i = 0; i < MAX_WATCH_ENTRIES; i++) {
694 if (XenBus_WatchEntries[i].Active == 1 && strcmp(XenBus_WatchEntries[i].Path, Path) == 0 && XenBus_WatchEntries[i].ServiceRoutine == ServiceRoutine && XenBus_WatchEntries[i].ServiceContext == ServiceContext)
695 break;
696 }
698 if (i == MAX_WATCH_ENTRIES)
699 {
700 KdPrint((__DRIVER_NAME " Watch not set - can't remove\n"));
701 return NULL;
702 }
704 req[0].data = Path;
705 req[0].len = strlen(Path) + 1;
707 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", i);
708 req[1].data = Token;
709 req[1].len = strlen(Token) + 1;
711 rep = xenbus_msg_reply(XS_UNWATCH, xbt, req, ARRAY_SIZE(req));
713 msg = errmsg(rep);
714 if (msg)
715 return msg;
717 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
719 XenBus_WatchEntries[i].Active = 0;
721 //KdPrint((__DRIVER_NAME " <-- XenBus_RemWatch\n"));
723 return NULL;
724 }
727 char *
728 XenBus_StartTransaction(xenbus_transaction_t *xbt)
729 {
730 /* xenstored becomes angry if you send a length 0 message, so just
731 shove a nul terminator on the end */
732 struct write_req req = { "", 1};
733 struct xsd_sockmsg *rep;
734 char *err;
736 rep = xenbus_msg_reply(XS_TRANSACTION_START, 0, &req, 1);
737 err = errmsg(rep);
738 if (err)
739 return err;
740 *xbt = atoi((char *)(rep + 1));
741 //sscanf((char *)(rep + 1), "%u", xbt);
742 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
743 return NULL;
744 }
746 char *
747 XenBus_EndTransaction(xenbus_transaction_t t, int abort, int *retry)
748 {
749 struct xsd_sockmsg *rep;
750 struct write_req req;
751 char *err;
753 *retry = 0;
755 req.data = abort ? "F" : "T";
756 req.len = 2;
757 rep = xenbus_msg_reply(XS_TRANSACTION_END, t, &req, 1);
758 err = errmsg(rep);
759 if (err) {
760 if (!strcmp(err, "EAGAIN")) {
761 *retry = 1;
762 ExFreePoolWithTag(err, XENPCI_POOL_TAG);
763 return NULL;
764 } else {
765 return err;
766 }
767 }
768 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
769 return NULL;
770 }
771 /*
772 void
773 XenBus_ThreadProc(PVOID StartContext)
774 {
775 char *response;
777 //KdPrint((__DRIVER_NAME " --> XenBus_ThreadProc\n"));
779 //do_ls_test("device");
781 // do_ls_test("local");
783 // do_ls_test("control");
785 // do_ls_test(".");
787 response = XenBus_AddWatch(XBT_NIL, SHUTDOWN_PATH, XenBus_ShutdownHandler, NULL);
789 //KdPrint((__DRIVER_NAME " <-- watch response = '%s'\n", response));
791 //KdPrint((__DRIVER_NAME " <-- XenBus_ThreadProc\n"));
792 }
793 */
795 static BOOLEAN
796 XenBus_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext)
797 {
798 UNREFERENCED_PARAMETER(Interrupt);
799 UNREFERENCED_PARAMETER(ServiceContext);
801 //KdPrint((__DRIVER_NAME " --> XenBus_Interrupt (Count = %d)\n", ReadThreadSetCount++));
803 KeSetEvent(&XenBus_ReadThreadEvent, 1, FALSE);
805 //KdPrint((__DRIVER_NAME " <-- XenBus_Interrupt\n"));
807 return TRUE;
808 }
810 char *
811 XenBus_Printf(xenbus_transaction_t xbt, const char *path, const char *fmt, ...)
812 {
813 va_list ap;
814 char buf[1024];
816 va_start(ap, fmt);
817 RtlStringCbVPrintfA(buf, ARRAY_SIZE(buf), fmt, ap);
818 va_end(ap);
819 return XenBus_Write(xbt, path, buf);