win-pvdrivers

view xenpci/xenbus.c @ 38:a5617e7e9f54

fixups from manual merge
author Andy Grover <andy.grover@oracle.com>
date Wed Dec 05 11:37:53 2007 -0800 (2007-12-05)
parents 3ac5c4431dbb
children 932802ddab71
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 NTSTATUS Status;
303 int i;
305 //KdPrint((__DRIVER_NAME " --> XenBus_Init\n"));
307 xpdd->xen_store_evtchn = EvtChn_GetXenStorePort(Device);
308 xpdd->xen_store_interface = EvtChn_GetXenStoreRingAddr(Device);
310 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
311 xpdd->XenBus_WatchEntries[i].Active = 0;
313 KeInitializeEvent(&xpdd->XenBus_ReadThreadEvent, SynchronizationEvent, FALSE);
314 KeInitializeEvent(&xpdd->XenBus_WatchThreadEvent, SynchronizationEvent, FALSE);
315 xpdd->XenBus_ShuttingDown = FALSE;
317 //InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
318 //Status = PsCreateSystemThread(&XenBus_ReadThreadHandle, THREAD_ALL_ACCESS, &oa, NULL, NULL, XenBus_ReadThreadProc, NULL);
319 Status = PsCreateSystemThread(&xpdd->XenBus_ReadThreadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenBus_ReadThreadProc, NULL);
321 //InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
322 //Status = PsCreateSystemThread(&XenBus_WatchThreadHandle, THREAD_ALL_ACCESS, &oa, NULL, NULL, XenBus_WatchThreadProc, NULL);
323 Status = PsCreateSystemThread(&xpdd->XenBus_WatchThreadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenBus_WatchThreadProc, NULL);
325 KdPrint((__DRIVER_NAME " <-- XenBus_Init\n"));
327 return STATUS_SUCCESS;
328 }
330 NTSTATUS
331 XenBus_Start(WDFDEVICE Device)
332 {
333 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
335 KdPrint((__DRIVER_NAME " --> XenBus_Start\n"));
337 EvtChn_Bind(Device, xpdd->xen_store_evtchn, XenBus_Interrupt, NULL);
339 KdPrint((__DRIVER_NAME " <-- XenBus_Start\n"));
341 return STATUS_SUCCESS;
342 }
344 NTSTATUS
345 XenBus_Stop(WDFDEVICE Device)
346 {
347 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
348 int i;
350 KdPrint((__DRIVER_NAME " --> XenBus_Stop\n"));
352 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
353 {
354 if (xpdd->XenBus_WatchEntries[i].Active)
355 XenBus_RemWatch(Device, XBT_NIL, xpdd->XenBus_WatchEntries[i].Path,
356 xpdd->XenBus_WatchEntries[i].ServiceRoutine,
357 xpdd->XenBus_WatchEntries[i].ServiceContext);
358 }
360 EvtChn_Unbind(Device, xpdd->xen_store_evtchn);
362 KdPrint((__DRIVER_NAME " <-- XenBus_Stop\n"));
364 return STATUS_SUCCESS;
365 }
367 NTSTATUS
368 XenBus_Close(WDFDEVICE Device)
369 {
370 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
371 KWAIT_BLOCK WaitBlockArray[2];
372 PVOID WaitArray[2];
374 xpdd->XenBus_ShuttingDown = TRUE;
376 KdPrint((__DRIVER_NAME " Signalling Threads\n"));
377 KeSetEvent(&xpdd->XenBus_ReadThreadEvent, 1, FALSE);
378 KeSetEvent(&xpdd->XenBus_WatchThreadEvent, 1, FALSE);
379 KdPrint((__DRIVER_NAME " Waiting for threads to die\n"));
380 ObReferenceObjectByHandle(xpdd->XenBus_ReadThreadHandle, THREAD_ALL_ACCESS, NULL, KernelMode, &WaitArray[0], NULL);
381 ObReferenceObjectByHandle(xpdd->XenBus_WatchThreadHandle, THREAD_ALL_ACCESS, NULL, KernelMode, &WaitArray[1], NULL);
382 KeWaitForMultipleObjects(2, WaitArray, WaitAll, Executive, KernelMode, FALSE, NULL, WaitBlockArray);
383 KdPrint((__DRIVER_NAME " Threads are dead\n"));
385 xpdd->XenBus_ShuttingDown = FALSE;
387 ObDereferenceObject(WaitArray[0]);
388 ObDereferenceObject(WaitArray[1]);
390 ZwClose(xpdd->XenBus_WatchThreadHandle);
391 ZwClose(xpdd->XenBus_ReadThreadHandle);
393 KdPrint((__DRIVER_NAME " <-- XenBus_Close\n"));
395 return STATUS_SUCCESS;
396 }
398 char *
399 XenBus_List(
400 PVOID Context,
401 xenbus_transaction_t xbt,
402 const char *pre,
403 char ***contents)
404 {
405 WDFDEVICE Device = Context;
406 struct xsd_sockmsg *reply, *repmsg;
407 struct write_req req[] = { { pre, strlen(pre)+1 } };
408 ULONG nr_elems, x, i;
409 char **res;
410 char *msg;
412 //KdPrint((__DRIVER_NAME " --> xenbus_ls\n"));
414 repmsg = xenbus_msg_reply(Device, XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
415 msg = errmsg(repmsg);
416 if (msg)
417 {
418 *contents = NULL;
419 //KdPrint((__DRIVER_NAME " <-- xenbus_ls (error)\n"));
420 return msg;
421 }
422 reply = repmsg + 1;
423 for (x = nr_elems = 0; x < repmsg->len; x++)
424 {
425 nr_elems += (((char *)reply)[x] == 0);
426 }
427 res = ExAllocatePoolWithTag(NonPagedPool, sizeof(res[0]) * (nr_elems + 1),
428 XENPCI_POOL_TAG);
429 for (x = i = 0; i < nr_elems; i++)
430 {
431 int l = strlen((char *)reply + x);
432 res[i] = ExAllocatePoolWithTag(NonPagedPool, l + 1, XENPCI_POOL_TAG);
433 memcpy(res[i], (char *)reply + x, l + 1);
434 x += l + 1;
435 }
436 res[i] = NULL;
437 ExFreePoolWithTag(repmsg, XENPCI_POOL_TAG);
438 *contents = res;
439 //KdPrint((__DRIVER_NAME " <-- xenbus_ls\n"));
440 return NULL;
441 }
443 static void
444 XenBus_ReadThreadProc(PVOID StartContext)
445 {
446 int NewWriteIndex;
447 struct xsd_sockmsg msg;
448 char *payload;
449 char *path, *token;
450 WDFDEVICE Device = StartContext;
451 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
453 for(;;)
454 {
455 KeWaitForSingleObject(&xpdd->XenBus_ReadThreadEvent, Executive, KernelMode, FALSE, NULL);
456 if (xpdd->XenBus_ShuttingDown)
457 {
458 KdPrint((__DRIVER_NAME " Shutdown detected in ReadThreadProc\n"));
459 PsTerminateSystemThread(0);
460 }
461 //KdPrint((__DRIVER_NAME " ReadThread Woken (Count = %d)\n", ReadThreadWaitCount++));
462 while (xpdd->xen_store_interface->rsp_prod != xpdd->xen_store_interface->rsp_cons)
463 {
464 //KdPrint((__DRIVER_NAME " a - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
465 if (xpdd->xen_store_interface->rsp_prod - xpdd->xen_store_interface->rsp_cons < sizeof(msg))
466 {
467 //KdPrint((__DRIVER_NAME " +++ Message incomplete (not even a full header)\n"));
468 break;
469 }
470 //_ReadBarrier();
471 KeMemoryBarrier();
472 memcpy_from_ring(xpdd->xen_store_interface->rsp, &msg,
473 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons), sizeof(msg));
474 if (xpdd->xen_store_interface->rsp_prod - xpdd->xen_store_interface->rsp_cons < sizeof(msg) + msg.len)
475 {
476 //KdPrint((__DRIVER_NAME " +++ Message incomplete (header but not full body)\n"));
477 break;
478 }
480 if (msg.type != XS_WATCH_EVENT)
481 {
482 xpdd->req_info[msg.req_id].Reply = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
483 memcpy_from_ring(xpdd->xen_store_interface->rsp,
484 xpdd->req_info[msg.req_id].Reply,
485 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons),
486 msg.len + sizeof(msg));
487 xpdd->xen_store_interface->rsp_cons += msg.len + sizeof(msg);
488 KeSetEvent(&xpdd->req_info[msg.req_id].WaitEvent, 1, FALSE);
489 }
490 else // a watch: add to watch ring and signal watch thread
491 {
492 payload = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
493 memcpy_from_ring(xpdd->xen_store_interface->rsp, payload,
494 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons), msg.len + sizeof(msg));
495 xpdd->xen_store_interface->rsp_cons += msg.len + sizeof(msg);
496 path = payload + sizeof(msg);
497 token = path + strlen(path) + 1;
499 NewWriteIndex = (xpdd->XenBus_WatchRingWriteIndex + 1) & 127;
500 if (NewWriteIndex != xpdd->XenBus_WatchRingReadIndex)
501 {
502 strncpy(xpdd->XenBus_WatchRing[NewWriteIndex].Path, path, 128);
503 strncpy(xpdd->XenBus_WatchRing[NewWriteIndex].Token, token, 10);
504 xpdd->XenBus_WatchRingWriteIndex = NewWriteIndex;
505 }
506 else
507 {
508 KdPrint((__DRIVER_NAME " +++ Queue full Path = %s Token = %s\n", path, token));
509 // drop the message on the floor
510 continue;
511 }
513 ExFreePoolWithTag(payload, XENPCI_POOL_TAG);
514 //KdPrint((__DRIVER_NAME " +++ Watch Path = %s Token = %s\n", path, token));
515 KeSetEvent(&xpdd->XenBus_WatchThreadEvent, 1, FALSE);
516 }
517 }
518 }
519 }
521 static void
522 XenBus_WatchThreadProc(PVOID StartContext)
523 {
524 int index;
525 PXENBUS_WATCH_ENTRY entry;
526 WDFDEVICE Device = StartContext;
527 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
529 for(;;)
530 {
531 KeWaitForSingleObject(&xpdd->XenBus_WatchThreadEvent, Executive, KernelMode, FALSE, NULL);
532 if (xpdd->XenBus_ShuttingDown)
533 {
534 KdPrint((__DRIVER_NAME " Shutdown detected in WatchThreadProc\n"));
535 PsTerminateSystemThread(0);
536 }
537 while (xpdd->XenBus_WatchRingReadIndex != xpdd->XenBus_WatchRingWriteIndex)
538 {
539 xpdd->XenBus_WatchRingReadIndex =
540 (xpdd->XenBus_WatchRingReadIndex + 1) % WATCH_RING_SIZE;
541 index = atoi(xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Token);
542 //XenBus_WatchRing[XenBus_WatchRingReadIndex].Path
543 //XenBus_WatchRing[XenBus_WatchRingReadIndex].Token
545 entry = &xpdd->XenBus_WatchEntries[index];
546 if (!entry->Active)
547 {
548 KdPrint((__DRIVER_NAME " +++ Watch not active! = %s Token = %s\n",
549 xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Path,
550 xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Token));
551 continue;
552 }
553 entry->Count++;
554 if (!entry->ServiceRoutine)
555 {
556 KdPrint((__DRIVER_NAME " +++ no handler for watch! = %s Token = %s\n",
557 xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Path,
558 xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Token));
559 continue;
560 }
561 //KdPrint((__DRIVER_NAME " +++ Watch Triggered Path = %s Token = %d (%s)\n", XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, index, XenBus_WatchRing[XenBus_WatchRingReadIndex].Token));
562 entry->ServiceRoutine(xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Path, entry->ServiceContext);
563 }
564 }
565 }
567 char *
568 XenBus_AddWatch(
569 PVOID Context,
570 xenbus_transaction_t xbt,
571 const char *Path,
572 PXENBUS_WATCH_CALLBACK ServiceRoutine,
573 PVOID ServiceContext)
574 {
575 WDFDEVICE Device = Context;
576 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
577 struct xsd_sockmsg *rep;
578 char *msg;
579 int i;
580 char Token[20];
581 struct write_req req[2];
583 // KdPrint((__DRIVER_NAME " --> XenBus_AddWatch\n"));
585 // check that Path < 128 chars
587 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
588 if (xpdd->XenBus_WatchEntries[i].Active == 0)
589 break;
591 if (i == MAX_WATCH_ENTRIES)
592 {
593 KdPrint((__DRIVER_NAME " +++ No more watch slots left\n"));
594 return NULL;
595 }
597 req[0].data = Path;
598 req[0].len = strlen(Path) + 1;
600 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", i);
601 req[1].data = Token;
602 req[1].len = strlen(Token) + 1;
604 rep = xenbus_msg_reply(Device, XS_WATCH, xbt, req, ARRAY_SIZE(req));
606 msg = errmsg(rep);
607 if (msg)
608 return msg;
610 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
612 strncpy(xpdd->XenBus_WatchEntries[i].Path, Path, 128);
613 xpdd->XenBus_WatchEntries[i].ServiceRoutine = ServiceRoutine;
614 xpdd->XenBus_WatchEntries[i].ServiceContext = ServiceContext;
615 xpdd->XenBus_WatchEntries[i].Count = 0;
616 xpdd->XenBus_WatchEntries[i].Active = 1;
618 // KdPrint((__DRIVER_NAME " <-- XenBus_AddWatch\n"));
620 return NULL;
621 }
623 char *
624 XenBus_RemWatch(
625 PVOID Context,
626 xenbus_transaction_t xbt,
627 const char *Path,
628 PXENBUS_WATCH_CALLBACK ServiceRoutine,
629 PVOID ServiceContext)
630 {
631 WDFDEVICE Device = Context;
632 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
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_RemWatch\n"));
641 // check that Path < 128 chars
643 for (i = 0; i < MAX_WATCH_ENTRIES; i++) {
644 if (xpdd->XenBus_WatchEntries[i].Active == 1
645 && strcmp(xpdd->XenBus_WatchEntries[i].Path, Path) == 0
646 && xpdd->XenBus_WatchEntries[i].ServiceRoutine == ServiceRoutine
647 && xpdd->XenBus_WatchEntries[i].ServiceContext == ServiceContext)
648 break;
649 }
651 if (i == MAX_WATCH_ENTRIES)
652 {
653 KdPrint((__DRIVER_NAME " Watch not set - can't remove\n"));
654 return NULL;
655 }
657 req[0].data = Path;
658 req[0].len = strlen(Path) + 1;
660 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", i);
661 req[1].data = Token;
662 req[1].len = strlen(Token) + 1;
664 rep = xenbus_msg_reply(Device, XS_UNWATCH, xbt, req, ARRAY_SIZE(req));
666 msg = errmsg(rep);
667 if (msg)
668 return msg;
670 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
672 xpdd->XenBus_WatchEntries[i].Active = 0;
674 //KdPrint((__DRIVER_NAME " <-- XenBus_RemWatch\n"));
676 return NULL;
677 }
680 char *
681 XenBus_StartTransaction(PVOID Context, xenbus_transaction_t *xbt)
682 {
683 WDFDEVICE Device = Context;
684 /* xenstored becomes angry if you send a length 0 message, so just
685 shove a nul terminator on the end */
686 struct write_req req = { "", 1};
687 struct xsd_sockmsg *rep;
688 char *err;
690 rep = xenbus_msg_reply(Device, XS_TRANSACTION_START, 0, &req, 1);
691 err = errmsg(rep);
692 if (err)
693 return err;
694 *xbt = atoi((char *)(rep + 1));
695 //sscanf((char *)(rep + 1), "%u", xbt);
696 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
697 return NULL;
698 }
700 char *
701 XenBus_EndTransaction(
702 PVOID Context,
703 xenbus_transaction_t t,
704 int abort,
705 int *retry)
706 {
707 WDFDEVICE Device = Context;
708 struct xsd_sockmsg *rep;
709 struct write_req req;
710 char *err;
712 *retry = 0;
714 req.data = abort ? "F" : "T";
715 req.len = 2;
716 rep = xenbus_msg_reply(Device, XS_TRANSACTION_END, t, &req, 1);
717 err = errmsg(rep);
718 if (err) {
719 if (!strcmp(err, "EAGAIN")) {
720 *retry = 1;
721 ExFreePoolWithTag(err, XENPCI_POOL_TAG);
722 return NULL;
723 } else {
724 return err;
725 }
726 }
727 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
728 return NULL;
729 }
731 static BOOLEAN
732 XenBus_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext)
733 {
734 WDFDEVICE Device = ServiceContext;
735 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
737 UNREFERENCED_PARAMETER(Interrupt);
739 //KdPrint((__DRIVER_NAME " --> XenBus_Interrupt (Count = %d)\n", ReadThreadSetCount++));
741 KeSetEvent(&xpdd->XenBus_ReadThreadEvent, 1, FALSE);
743 //KdPrint((__DRIVER_NAME " <-- XenBus_Interrupt\n"));
745 return TRUE;
746 }
748 char *
749 XenBus_Printf(
750 PVOID Context,
751 xenbus_transaction_t xbt,
752 const char *path,
753 const char *fmt,
754 ...)
755 {
756 WDFDEVICE Device = Context;
757 va_list ap;
758 char buf[1024];
760 va_start(ap, fmt);
761 RtlStringCbVPrintfA(buf, ARRAY_SIZE(buf), fmt, ap);
762 va_end(ap);
763 return XenBus_Write(Device, xbt, path, buf);
764 }