win-pvdrivers

view xenpci/xenbus.c @ 13:be8c09632f31

fixes to xenpci

Move xenpci globals into XENPCI_DEVICE_DATA struct
External interfaces take a PVOID Context field
Use __writemsr intrinsic
Some lines broken for length
Dead (?) io queue code removed
XEN_IFACE_XEN removed, no one seems to use it?
Use case 3: in XenPCI_XenBusWatchHandler instead of default:
Xenvbd and xennet changed to pass back context field when calling xenpci interfaces
author Andy Grover <andy@groveronline.com>
date Wed Nov 28 14:51:17 2007 -0800 (2007-11-28)
parents b55f3c61e509
children 7f0f866dced6
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 _XENBUS_WATCH_ENTRY {
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 _XENBUS_WATCH_RING
43 {
44 char Path[128];
45 char Token[10];
46 } XENBUS_WATCH_RING;
48 #define WATCH_RING_SIZE 128
50 static XENBUS_WATCH_RING XenBus_WatchRing[WATCH_RING_SIZE];
51 static int XenBus_WatchRingReadIndex;
52 static int XenBus_WatchRingWriteIndex;
54 #define MAX_WATCH_ENTRIES 128
56 static XENBUS_WATCH_ENTRY XenBus_WatchEntries[MAX_WATCH_ENTRIES];
58 #define NR_REQS 32
59 //#define XENSTORE_RING_SIZE 1024
61 //#define XENSTORE_RING_SIZE 1024
62 //typedef uint32_t XENSTORE_RING_IDX;
63 //#define MASK_XENSTORE_IDX(idx) ((idx) & (XENSTORE_RING_SIZE-1))
65 static struct xenstore_domain_interface *xen_store_interface;
67 static struct xenbus_req_info req_info[NR_REQS];
68 static int nr_live_reqs;
69 //static spinlock_t req_lock = SPIN_LOCK_UNLOCKED;
71 static HANDLE XenBus_ReadThreadHandle;
72 static KEVENT XenBus_ReadThreadEvent;
74 static HANDLE XenBus_WatchThreadHandle;
75 static KEVENT XenBus_WatchThreadEvent;
77 static void
78 XenBus_ReadThreadProc(PVOID StartContext);
79 static void
80 XenBus_WatchThreadProc(PVOID StartContext);
82 static BOOLEAN
83 XenBus_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext);
85 static int allocate_xenbus_id(void)
86 {
87 static int probe;
88 int o_probe;
90 //KdPrint((__DRIVER_NAME " --> allocate_xenbus_id\n"));
92 for (;;)
93 {
94 // spin_lock(&req_lock);
95 if (nr_live_reqs < NR_REQS)
96 break;
97 // spin_unlock(&req_lock);
98 // wait_event(req_wq, (nr_live_reqs < NR_REQS));
99 }
101 o_probe = probe;
103 for (;;)
104 {
105 if (!req_info[o_probe].In_Use)
106 break;
107 o_probe = (o_probe + 1) % NR_REQS;
108 // BUG_ON(o_probe == probe);
109 }
110 nr_live_reqs++;
111 req_info[o_probe].In_Use = 1;
112 probe = (o_probe + 1) % NR_REQS;
113 //spin_unlock(&req_lock);
114 //init_waitqueue_head(&req_info[o_probe].waitq);
115 KeInitializeEvent(&req_info[o_probe].WaitEvent, SynchronizationEvent, FALSE);
117 //KdPrint((__DRIVER_NAME " <-- allocate_xenbus_id\n"));
119 return o_probe;
120 }
122 static void release_xenbus_id(int id)
123 {
124 // BUG_ON(!req_info[id].in_use);
125 // spin_lock(&req_lock);
126 req_info[id].In_Use = 0;
127 nr_live_reqs--;
128 req_info[id].In_Use = 0;
129 // if (nr_live_reqs == NR_REQS - 1)
130 // wake_up(&req_wq);
131 // spin_unlock(&req_lock);
132 }
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 void xb_write (
180 WDFDEVICE Device,
181 int type,
182 int req_id,
183 xenbus_transaction_t trans_id,
184 const struct write_req *req,
185 int nr_reqs)
186 {
187 PXENPCI_DEVICE_DATA deviceData = GetDeviceData(Device);
188 XENSTORE_RING_IDX prod;
189 int r;
190 size_t len = 0;
191 const struct write_req *cur_req;
192 size_t req_off;
193 size_t total_off;
194 size_t this_chunk;
195 struct xsd_sockmsg m = {type, req_id, trans_id };
196 struct write_req header_req = { &m, sizeof(m) };
198 //KdPrint((__DRIVER_NAME " --> xb_write\n"));
200 for (r = 0; r < nr_reqs; r++)
201 len += req[r].len;
202 m.len = len;
203 len += sizeof(m);
205 cur_req = &header_req;
207 // BUG_ON(len > XENSTORE_RING_SIZE);
208 /* Wait for the ring to drain to the point where we can send the
209 message. */
210 prod = xen_store_interface->req_prod;
212 //KdPrint((__DRIVER_NAME " prod = %08x\n", prod));
214 if (prod + len - xen_store_interface->req_cons > XENSTORE_RING_SIZE)
215 {
216 /* Wait for there to be space on the ring */
217 //KdPrint((__DRIVER_NAME " prod %d, len %d, cons %d, size %d; waiting.\n", prod, len, xen_store_interface->req_cons, XENSTORE_RING_SIZE));
218 // wait_event(xb_waitq, xen_store_interface->req_prod + len - xen_store_interface->req_cons <= XENSTORE_RING_SIZE);
219 //KdPrint((__DRIVER_NAME " Back from wait.\n"));
220 prod = xen_store_interface->req_prod;
221 }
223 /* We're now guaranteed to be able to send the message without
224 overflowing the ring. Do so. */
226 total_off = 0;
227 req_off = 0;
229 while (total_off < len)
230 {
231 this_chunk = min(cur_req->len - req_off,XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
232 memcpy((char *)xen_store_interface->req + MASK_XENSTORE_IDX(prod), (char *)cur_req->data + req_off, this_chunk);
233 prod += this_chunk;
234 req_off += this_chunk;
235 total_off += this_chunk;
236 if (req_off == cur_req->len)
237 {
238 req_off = 0;
239 if (cur_req == &header_req)
240 cur_req = req;
241 else
242 cur_req++;
243 }
244 }
246 //KdPrint((__DRIVER_NAME " Complete main loop of xb_write.\n"));
248 // BUG_ON(req_off != 0);
249 // BUG_ON(total_off != len);
250 // BUG_ON(prod > xen_store_interface->req_cons + XENSTORE_RING_SIZE);
252 /* Remote must see entire message before updating indexes */
253 //_WriteBarrier();
254 KeMemoryBarrier();
256 xen_store_interface->req_prod += len;
258 //KdPrint((__DRIVER_NAME " prod = %08x\n", xen_store_interface->req_prod));
260 /* Send evtchn to notify remote */
261 EvtChn_Notify(Device, deviceData->xen_store_evtchn);
263 //KdPrint((__DRIVER_NAME " <-- xb_write\n"));
264 }
266 static struct xsd_sockmsg *
267 xenbus_msg_reply(
268 WDFDEVICE Device,
269 int type,
270 xenbus_transaction_t trans,
271 struct write_req *io,
272 int nr_reqs)
273 {
274 int id;
275 // DEFINE_WAIT(w);
276 struct xsd_sockmsg *rep;
278 KdPrint((__DRIVER_NAME " --> xenbus_msg_reply\n"));
280 id = allocate_xenbus_id();
281 // add_waiter(w, req_info[id].waitq);
283 xb_write(Device, type, id, trans, io, nr_reqs);
284 //
285 // schedule();
286 // remove_waiter(w);
287 // wake(current);
288 //
289 KdPrint((__DRIVER_NAME " starting wait\n"));
291 KeWaitForSingleObject(&req_info[id].WaitEvent, Executive, KernelMode, FALSE, NULL);
293 //KdPrint((__DRIVER_NAME " wait complete\n"));
295 rep = req_info[id].Reply;
296 // BUG_ON(rep->req_id != id);
297 release_xenbus_id(id);
298 KdPrint((__DRIVER_NAME " <-- xenbus_msg_reply\n"));
299 return rep;
300 }
302 char *
303 XenBus_Read (
304 PVOID Context,
305 xenbus_transaction_t xbt,
306 const char *path,
307 char **value)
308 {
309 WDFDEVICE Device = Context;
310 struct write_req req[] = { {path, strlen(path) + 1} };
311 struct xsd_sockmsg *rep;
312 char *res;
313 char *msg;
315 rep = xenbus_msg_reply(Device, XS_READ, xbt, req, ARRAY_SIZE(req));
316 msg = errmsg(rep);
317 if (msg) {
318 *value = NULL;
319 return msg;
320 }
321 res = ExAllocatePoolWithTag(NonPagedPool, rep->len + 1, XENPCI_POOL_TAG);
322 memcpy(res, rep + 1, rep->len);
323 res[rep->len] = 0;
324 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
325 *value = res;
326 return NULL;
327 }
329 char *
330 XenBus_Write(
331 PVOID Context,
332 xenbus_transaction_t xbt,
333 const char *path,
334 const char *value)
335 {
336 WDFDEVICE Device = Context;
337 struct write_req req[] = {
338 {path, strlen(path) + 1},
339 {value, strlen(value) + 1},
340 };
341 struct xsd_sockmsg *rep;
342 char *msg;
344 rep = xenbus_msg_reply(Device, XS_WRITE, xbt, req, ARRAY_SIZE(req));
345 msg = errmsg(rep);
346 if (msg)
347 return msg;
348 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
349 return NULL;
350 }
352 char* xenbus_wait_for_value(const char* path,const char* value)
353 {
354 UNREFERENCED_PARAMETER(path);
355 UNREFERENCED_PARAMETER(value);
356 // for(;;)
357 // {
358 // char *res, *msg;
359 // int r;
360 //
361 // msg = xenbus_read(XBT_NIL, path, &res);
362 // if(msg) return msg;
363 //
364 // r = strcmp(value,res);
365 // ExFreePoolWithTag(res, XENPCI_POOL_TAG);
366 //
367 // if(r==0)
368 // break;
369 // else
370 // wait_for_watch();
371 // }
372 return NULL;
373 }
375 NTSTATUS
376 XenBus_Init(WDFDEVICE Device)
377 {
378 PXENPCI_DEVICE_DATA deviceData = GetDeviceData(Device);
379 //KdPrint((__DRIVER_NAME " --> XenBus_Init\n"));
381 deviceData->xen_store_evtchn = EvtChn_GetXenStorePort(Device);
382 xen_store_interface = EvtChn_GetXenStoreRingAddr(Device);
384 //KdPrint((__DRIVER_NAME " xen_store_evtchn = %08x\n", xen_store_evtchn));
385 //KdPrint((__DRIVER_NAME " xen_store_interface = %08x\n", xen_store_interface));
387 KeInitializeEvent(&XenBus_ReadThreadEvent, SynchronizationEvent, FALSE);
388 KeInitializeEvent(&XenBus_WatchThreadEvent, SynchronizationEvent, FALSE);
390 //KdPrint((__DRIVER_NAME " <-- XenBus_Init\n"));
392 return STATUS_SUCCESS;
393 }
395 NTSTATUS
396 XenBus_Start(WDFDEVICE Device)
397 {
398 PXENPCI_DEVICE_DATA deviceData = GetDeviceData(Device);
399 OBJECT_ATTRIBUTES oa;
400 NTSTATUS status;
401 int i;
403 KdPrint((__DRIVER_NAME " --> XenBus_Start\n"));
405 InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
406 status = PsCreateSystemThread(&XenBus_ReadThreadHandle, THREAD_ALL_ACCESS, &oa, NULL, NULL, XenBus_ReadThreadProc, NULL);
408 // remove all existing watches already in Xen too...
410 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
411 XenBus_WatchEntries[i].Active = 0;
413 InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
414 status = PsCreateSystemThread(&XenBus_WatchThreadHandle, THREAD_ALL_ACCESS, &oa, NULL, NULL, XenBus_WatchThreadProc, NULL);
416 EvtChn_Bind(Device, deviceData->xen_store_evtchn, XenBus_Interrupt, NULL);
418 KdPrint((__DRIVER_NAME " <-- XenBus_Start\n"));
420 return STATUS_SUCCESS;
421 }
423 NTSTATUS
424 XenBus_Stop(WDFDEVICE Device)
425 {
426 PXENPCI_DEVICE_DATA deviceData = GetDeviceData(Device);
427 int i;
429 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
430 {
431 if (!XenBus_WatchEntries[i].Active)
432 continue;
433 XenBus_RemWatch(Device, XBT_NIL, XenBus_WatchEntries[i].Path, XenBus_WatchEntries[i].ServiceRoutine, XenBus_WatchEntries[i].ServiceContext);
434 }
436 EvtChn_Unbind(Device, deviceData->xen_store_evtchn);
438 // Does this actually stop the threads???
439 ZwClose(XenBus_WatchThreadHandle);
440 ZwClose(XenBus_ReadThreadHandle);
442 return STATUS_SUCCESS;
443 }
445 char *
446 XenBus_List(
447 PVOID Context,
448 xenbus_transaction_t xbt,
449 const char *pre,
450 char ***contents)
451 {
452 WDFDEVICE Device = Context;
453 struct xsd_sockmsg *reply, *repmsg;
454 struct write_req req[] = { { pre, strlen(pre)+1 } };
455 ULONG nr_elems, x, i;
456 char **res;
457 char *msg;
459 //KdPrint((__DRIVER_NAME " --> xenbus_ls\n"));
461 repmsg = xenbus_msg_reply(Device, XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
462 msg = errmsg(repmsg);
463 if (msg) {
464 *contents = NULL;
465 //KdPrint((__DRIVER_NAME " <-- xenbus_ls (error)\n"));
466 return msg;
467 }
468 reply = repmsg + 1;
469 for (x = nr_elems = 0; x < repmsg->len; x++)
470 nr_elems += (((char *)reply)[x] == 0);
471 res = ExAllocatePoolWithTag(NonPagedPool, sizeof(res[0]) * (nr_elems + 1), XENPCI_POOL_TAG);
472 for (x = i = 0; i < nr_elems; i++) {
473 int l = strlen((char *)reply + x);
474 res[i] = ExAllocatePoolWithTag(NonPagedPool, l + 1, XENPCI_POOL_TAG);
475 memcpy(res[i], (char *)reply + x, l + 1);
476 x += l + 1;
477 }
478 res[i] = NULL;
479 ExFreePoolWithTag(repmsg, XENPCI_POOL_TAG);
480 *contents = res;
481 //KdPrint((__DRIVER_NAME " <-- xenbus_ls\n"));
482 return NULL;
483 }
485 #if 0 // test code
486 void
487 do_ls_test(const char *pre)
488 {
489 char **dirs;
490 int x;
491 char *msg;
493 //KdPrint((__DRIVER_NAME " <-- do_ls_test(\"%s\")\n", pre));
495 msg = XenBus_List(XBT_NIL, pre, &dirs);
496 if (msg)
497 {
498 //KdPrint((__DRIVER_NAME " Error in xenbus ls: %s\n", msg));
499 ExFreePoolWithTag(msg, XENPCI_POOL_TAG);
500 return;
501 }
502 for (x = 0; dirs[x]; x++)
503 {
504 //KdPrint((__DRIVER_NAME " ls %s[%d] -> %s\n", pre, x, dirs[x]));
505 ExFreePoolWithTag(dirs[x], XENPCI_POOL_TAG);
506 }
507 ExFreePoolWithTag(dirs, XENPCI_POOL_TAG);
508 //KdPrint((__DRIVER_NAME " --> do_ls_test\n"));
509 }
510 #endif
512 int ReadThreadSetCount;
513 int ReadThreadWaitCount;
515 static void
516 XenBus_ReadThreadProc(PVOID StartContext) {
517 int NewWriteIndex;
518 struct xsd_sockmsg msg;
519 char *payload;
520 char *path, *token;
522 UNREFERENCED_PARAMETER(StartContext);
524 for(;;)
525 {
526 KeWaitForSingleObject(&XenBus_ReadThreadEvent, Executive, KernelMode, FALSE, NULL);
527 //KdPrint((__DRIVER_NAME " ReadThread Woken (Count = %d)\n", ReadThreadWaitCount++));
528 while (xen_store_interface->rsp_prod != xen_store_interface->rsp_cons)
529 {
530 //KdPrint((__DRIVER_NAME " a - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
531 if (xen_store_interface->rsp_prod - xen_store_interface->rsp_cons < sizeof(msg))
532 {
533 //KdPrint((__DRIVER_NAME " +++ Message incomplete (not even a full header)\n"));
534 break;
535 }
536 //_ReadBarrier();
537 KeMemoryBarrier();
538 memcpy_from_ring(xen_store_interface->rsp, &msg, MASK_XENSTORE_IDX(xen_store_interface->rsp_cons), sizeof(msg));
539 if (xen_store_interface->rsp_prod - xen_store_interface->rsp_cons < sizeof(msg) + msg.len)
540 {
541 //KdPrint((__DRIVER_NAME " +++ Message incomplete (header but not full body)\n"));
542 break;
543 }
545 if(msg.type == XS_WATCH_EVENT)
546 {
547 payload = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
549 memcpy_from_ring(xen_store_interface->rsp, payload, MASK_XENSTORE_IDX(xen_store_interface->rsp_cons), msg.len + sizeof(msg));
551 xen_store_interface->rsp_cons += msg.len + sizeof(msg);
552 //KdPrint((__DRIVER_NAME " b - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
554 path = payload + sizeof(msg);
555 token = path + strlen(path) + 1;
557 NewWriteIndex = (XenBus_WatchRingWriteIndex + 1) & 127;
558 if (NewWriteIndex != XenBus_WatchRingReadIndex)
559 {
560 strncpy(XenBus_WatchRing[NewWriteIndex].Path, path, 128);
561 strncpy(XenBus_WatchRing[NewWriteIndex].Token, token, 10);
562 XenBus_WatchRingWriteIndex = NewWriteIndex;
563 }
564 else
565 {
566 KdPrint((__DRIVER_NAME " +++ Queue full Path = %s Token = %s\n", path, token));
567 // drop the message on the floor
568 continue;
569 }
571 ExFreePoolWithTag(payload, XENPCI_POOL_TAG);
572 //KdPrint((__DRIVER_NAME " +++ Watch Path = %s Token = %s\n", path, token));
573 KeSetEvent(&XenBus_WatchThreadEvent, 1, FALSE);
574 }
575 else
576 {
577 req_info[msg.req_id].Reply = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
578 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));
579 xen_store_interface->rsp_cons += msg.len + sizeof(msg);
580 //KdPrint((__DRIVER_NAME " c - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
581 //KdPrint((__DRIVER_NAME " +++ Message = %s\n", ((char *)req_info[msg.req_id].Reply) + sizeof(msg)));
582 KeSetEvent(&req_info[msg.req_id].WaitEvent, 1, FALSE);
583 }
584 }
585 }
586 }
588 static void
589 XenBus_WatchThreadProc(PVOID StartContext)
590 {
591 int index;
592 PXENBUS_WATCH_ENTRY entry;
594 UNREFERENCED_PARAMETER(StartContext);
596 for(;;)
597 {
598 KeWaitForSingleObject(&XenBus_WatchThreadEvent, Executive, KernelMode, FALSE, NULL);
599 while (XenBus_WatchRingReadIndex != XenBus_WatchRingWriteIndex)
600 {
601 XenBus_WatchRingReadIndex = (XenBus_WatchRingReadIndex + 1) & 127;
602 index = atoi(XenBus_WatchRing[XenBus_WatchRingReadIndex].Token);
603 //XenBus_WatchRing[XenBus_WatchRingReadIndex].Path
604 //XenBus_WatchRing[XenBus_WatchRingReadIndex].Token
606 entry = &XenBus_WatchEntries[index];
607 if (!entry->Active)
608 {
609 KdPrint((__DRIVER_NAME " +++ Watch not active! = %s Token = %s\n", XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, XenBus_WatchRing[XenBus_WatchRingReadIndex].Token));
610 continue;
611 }
612 entry->Count++;
613 if (!entry->ServiceRoutine)
614 {
615 KdPrint((__DRIVER_NAME " +++ no handler for watch! = %s Token = %s\n", XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, XenBus_WatchRing[XenBus_WatchRingReadIndex].Token));
616 continue;
617 }
618 //KdPrint((__DRIVER_NAME " +++ Watch Triggered Path = %s Token = %d (%s)\n", XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, index, XenBus_WatchRing[XenBus_WatchRingReadIndex].Token));
619 entry->ServiceRoutine(XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, entry->ServiceContext);
620 }
621 }
622 }
624 char *
625 XenBus_AddWatch (
626 PVOID Context,
627 xenbus_transaction_t xbt,
628 const char *Path,
629 PXENBUS_WATCH_CALLBACK ServiceRoutine,
630 PVOID ServiceContext)
631 {
632 WDFDEVICE Device = Context;
633 struct xsd_sockmsg *rep;
634 char *msg;
635 int i;
636 char Token[20];
637 struct write_req req[2];
639 KdPrint((__DRIVER_NAME " --> XenBus_AddWatch\n"));
641 // check that Path < 128 chars
643 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
644 if (XenBus_WatchEntries[i].Active == 0)
645 break;
647 if (i == MAX_WATCH_ENTRIES)
648 {
649 KdPrint((__DRIVER_NAME " +++ No more watch slots left\n"));
650 return NULL;
651 }
653 req[0].data = Path;
654 req[0].len = strlen(Path) + 1;
656 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", i);
657 req[1].data = Token;
658 req[1].len = strlen(Token) + 1;
660 rep = xenbus_msg_reply(Device, XS_WATCH, xbt, req, ARRAY_SIZE(req));
662 msg = errmsg(rep);
663 if (msg)
664 return msg;
666 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
668 strncpy(XenBus_WatchEntries[i].Path, Path, 128);
669 XenBus_WatchEntries[i].ServiceRoutine = ServiceRoutine;
670 XenBus_WatchEntries[i].ServiceContext = ServiceContext;
671 XenBus_WatchEntries[i].Count = 0;
672 XenBus_WatchEntries[i].Active = 1;
674 KdPrint((__DRIVER_NAME " <-- XenBus_AddWatch\n"));
676 return NULL;
677 }
679 char *
680 XenBus_RemWatch(
681 PVOID Context,
682 xenbus_transaction_t xbt,
683 const char *Path,
684 PXENBUS_WATCH_CALLBACK ServiceRoutine,
685 PVOID ServiceContext)
686 {
687 WDFDEVICE Device = Context;
688 struct xsd_sockmsg *rep;
689 char *msg;
690 int i;
691 char Token[20];
692 struct write_req req[2];
694 //KdPrint((__DRIVER_NAME " --> XenBus_RemWatch\n"));
696 // check that Path < 128 chars
698 for (i = 0; i < MAX_WATCH_ENTRIES; i++) {
699 if (XenBus_WatchEntries[i].Active == 1 && strcmp(XenBus_WatchEntries[i].Path, Path) == 0 && XenBus_WatchEntries[i].ServiceRoutine == ServiceRoutine && XenBus_WatchEntries[i].ServiceContext == ServiceContext)
700 break;
701 }
703 if (i == MAX_WATCH_ENTRIES)
704 {
705 KdPrint((__DRIVER_NAME " Watch not set - can't remove\n"));
706 return NULL;
707 }
709 req[0].data = Path;
710 req[0].len = strlen(Path) + 1;
712 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", i);
713 req[1].data = Token;
714 req[1].len = strlen(Token) + 1;
716 rep = xenbus_msg_reply(Device, XS_UNWATCH, xbt, req, ARRAY_SIZE(req));
718 msg = errmsg(rep);
719 if (msg)
720 return msg;
722 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
724 XenBus_WatchEntries[i].Active = 0;
726 //KdPrint((__DRIVER_NAME " <-- XenBus_RemWatch\n"));
728 return NULL;
729 }
732 char *
733 XenBus_StartTransaction(PVOID Context, xenbus_transaction_t *xbt)
734 {
735 WDFDEVICE Device = Context;
736 /* xenstored becomes angry if you send a length 0 message, so just
737 shove a nul terminator on the end */
738 struct write_req req = { "", 1};
739 struct xsd_sockmsg *rep;
740 char *err;
742 rep = xenbus_msg_reply(Device, XS_TRANSACTION_START, 0, &req, 1);
743 err = errmsg(rep);
744 if (err)
745 return err;
746 *xbt = atoi((char *)(rep + 1));
747 //sscanf((char *)(rep + 1), "%u", xbt);
748 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
749 return NULL;
750 }
752 char *
753 XenBus_EndTransaction(PVOID Context, xenbus_transaction_t t, int abort, int *retry)
754 {
755 WDFDEVICE Device = Context;
756 struct xsd_sockmsg *rep;
757 struct write_req req;
758 char *err;
760 *retry = 0;
762 req.data = abort ? "F" : "T";
763 req.len = 2;
764 rep = xenbus_msg_reply(Device, XS_TRANSACTION_END, t, &req, 1);
765 err = errmsg(rep);
766 if (err) {
767 if (!strcmp(err, "EAGAIN")) {
768 *retry = 1;
769 ExFreePoolWithTag(err, XENPCI_POOL_TAG);
770 return NULL;
771 } else {
772 return err;
773 }
774 }
775 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
776 return NULL;
777 }
778 /*
779 void
780 XenBus_ThreadProc(PVOID StartContext)
781 {
782 char *response;
784 //KdPrint((__DRIVER_NAME " --> XenBus_ThreadProc\n"));
786 //do_ls_test("device");
788 // do_ls_test("local");
790 // do_ls_test("control");
792 // do_ls_test(".");
794 response = XenBus_AddWatch(XBT_NIL, SHUTDOWN_PATH, XenBus_ShutdownHandler, NULL);
796 //KdPrint((__DRIVER_NAME " <-- watch response = '%s'\n", response));
798 //KdPrint((__DRIVER_NAME " <-- XenBus_ThreadProc\n"));
799 }
800 */
802 static BOOLEAN
803 XenBus_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext)
804 {
805 UNREFERENCED_PARAMETER(Interrupt);
806 UNREFERENCED_PARAMETER(ServiceContext);
808 //KdPrint((__DRIVER_NAME " --> XenBus_Interrupt (Count = %d)\n", ReadThreadSetCount++));
810 KeSetEvent(&XenBus_ReadThreadEvent, 1, FALSE);
812 //KdPrint((__DRIVER_NAME " <-- XenBus_Interrupt\n"));
814 return TRUE;
815 }
817 char *
818 XenBus_Printf(PVOID Context, xenbus_transaction_t xbt, const char *path, const char *fmt, ...)
819 {
820 WDFDEVICE Device = Context;
821 va_list ap;
822 char buf[1024];
824 va_start(ap, fmt);
825 RtlStringCbVPrintfA(buf, ARRAY_SIZE(buf), fmt, ap);
826 va_end(ap);
827 return XenBus_Write(Device, xbt, path, buf);