win-pvdrivers

view xenpci/xenbus.c @ 523:331f861accf0

removed debugging kdprint's
author James Harper <james.harper@bendigoit.com.au>
date Fri Dec 26 23:18:55 2008 +1100 (2008-12-26)
parents 4e7d9cc9f816
children 6a2d1517e10c
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 <stdlib.h>
23 #pragma warning( disable : 4204 )
24 #pragma warning( disable : 4221 )
26 struct write_req {
27 void *data;
28 unsigned len;
29 };
31 static DDKAPI void
32 XenBus_ReadThreadProc(PVOID StartContext);
33 static DDKAPI void
34 XenBus_WatchThreadProc(PVOID StartContext);
36 // This routine free's the rep structure if there was an error!!!
37 static char *errmsg(struct xsd_sockmsg *rep)
38 {
39 char *res;
41 if (!rep) {
42 char msg[] = "No reply";
43 size_t len = strlen(msg) + 1;
44 return memcpy(ExAllocatePoolWithTag(NonPagedPool, len, XENPCI_POOL_TAG), msg, len);
45 }
46 if (rep->type != XS_ERROR)
47 return NULL;
48 res = ExAllocatePoolWithTag(NonPagedPool, rep->len + 1, XENPCI_POOL_TAG);
49 memcpy(res, rep + 1, rep->len);
50 res[rep->len] = 0;
51 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
52 return res;
53 }
55 static void memcpy_from_ring(void *Ring,
56 void *Dest,
57 int off,
58 int len)
59 {
60 int c1, c2;
61 char *ring = Ring;
62 char *dest = Dest;
63 c1 = min(len, XENSTORE_RING_SIZE - off);
64 c2 = len - c1;
65 memcpy(dest, ring + off, c1);
66 memcpy(dest + c1, ring, c2);
67 }
69 /* called with xenbus_mutex held */
70 static void xb_write(
71 PXENPCI_DEVICE_DATA xpdd,
72 PVOID data,
73 ULONG len
74 )
75 {
76 XENSTORE_RING_IDX prod;
77 ULONG copy_len;
78 PUCHAR ptr;
79 ULONG remaining;
81 //FUNCTION_ENTER();
82 //KdPrint((__DRIVER_NAME " len = %d\n", len));
84 ASSERT(len <= XENSTORE_RING_SIZE);
85 /* Wait for the ring to drain to the point where we can send the
86 message. */
87 prod = xpdd->xen_store_interface->req_prod;
89 while (prod + len - xpdd->xen_store_interface->req_cons > XENSTORE_RING_SIZE)
90 {
91 /* Wait for there to be space on the ring */
92 /* not sure if I can wait here like this... */
93 KeWaitForSingleObject(&xpdd->XenBus_ReadThreadEvent, Executive, KernelMode, FALSE, NULL);
94 prod = xpdd->xen_store_interface->req_prod;
95 }
97 /* We're now guaranteed to be able to send the message without
98 overflowing the ring. Do so. */
100 ptr = data;
101 remaining = len;
102 while (remaining)
103 {
104 copy_len = min(remaining, XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
105 //KdPrint((__DRIVER_NAME " copy_len = %d\n", copy_len));
106 memcpy((PUCHAR)xpdd->xen_store_interface->req + MASK_XENSTORE_IDX(prod), ptr, copy_len);
107 prod += (XENSTORE_RING_IDX)copy_len;
108 ptr += copy_len;
109 remaining -= copy_len;
110 }
111 /* Remote must see entire message before updating indexes */
112 KeMemoryBarrier();
113 xpdd->xen_store_interface->req_prod = prod;
114 EvtChn_Notify(xpdd, xpdd->xen_store_evtchn);
116 //FUNCTION_EXIT();
117 }
119 /* takes and releases xb_request_mutex */
120 static struct xsd_sockmsg *
121 xenbus_format_msg_reply(
122 PXENPCI_DEVICE_DATA xpdd,
123 int type,
124 xenbus_transaction_t trans_id,
125 struct write_req *req,
126 int nr_reqs)
127 {
128 struct xsd_sockmsg msg;
129 struct xsd_sockmsg *reply;
130 int i;
132 FUNCTION_ENTER();
134 msg.type = type;
135 msg.req_id = 0;
136 msg.tx_id = trans_id;
137 msg.len = 0;
138 for (i = 0; i < nr_reqs; i++)
139 msg.len += req[i].len;
141 ExAcquireFastMutex(&xpdd->xb_request_mutex);
142 xb_write(xpdd, &msg, sizeof(msg));
143 for (i = 0; i < nr_reqs; i++)
144 xb_write(xpdd, req[i].data, req[i].len);
146 //KdPrint((__DRIVER_NAME " waiting...\n"));
147 KeWaitForSingleObject(&xpdd->xb_request_complete_event, Executive, KernelMode, FALSE, NULL);
148 //KdPrint((__DRIVER_NAME " ...done waiting\n"));
149 reply = xpdd->xb_reply;
150 xpdd->xb_reply = NULL;
151 ExReleaseFastMutex(&xpdd->xb_request_mutex);
153 FUNCTION_EXIT();
155 return reply;
156 }
158 /* takes and releases xb_request_mutex */
159 struct xsd_sockmsg *
160 XenBus_Raw(
161 PXENPCI_DEVICE_DATA xpdd,
162 struct xsd_sockmsg *msg)
163 {
164 struct xsd_sockmsg *reply;
166 ExAcquireFastMutex(&xpdd->xb_request_mutex);
167 xb_write(xpdd, msg, sizeof(struct xsd_sockmsg) + msg->len);
168 KeWaitForSingleObject(&xpdd->xb_request_complete_event, Executive, KernelMode, FALSE, NULL);
169 reply = xpdd->xb_reply;
170 xpdd->xb_reply = NULL;
171 ExReleaseFastMutex(&xpdd->xb_request_mutex);
173 return reply;
174 }
176 /*
177 Called at PASSIVE_LEVEL
178 */
179 char *
180 XenBus_Read(
181 PVOID Context,
182 xenbus_transaction_t xbt,
183 char *path,
184 char **value)
185 {
186 PXENPCI_DEVICE_DATA xpdd = Context;
187 struct write_req req[] = { {path, (ULONG)strlen(path) + 1} };
188 struct xsd_sockmsg *rep;
189 char *res;
190 char *msg;
192 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
194 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
196 rep = xenbus_format_msg_reply(xpdd, XS_READ, xbt, req, ARRAY_SIZE(req));
197 msg = errmsg(rep);
198 if (msg) {
199 *value = NULL;
200 return msg;
201 }
202 res = ExAllocatePoolWithTag(NonPagedPool, rep->len + 1, XENPCI_POOL_TAG);
203 memcpy(res, rep + 1, rep->len);
204 res[rep->len] = 0;
205 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
206 *value = res;
208 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
210 return NULL;
211 }
213 /*
214 Called at PASSIVE_LEVEL
215 */
216 char *
217 XenBus_Write(
218 PVOID Context,
219 xenbus_transaction_t xbt,
220 char *path,
221 char *value)
222 {
223 PXENPCI_DEVICE_DATA xpdd = Context;
224 struct write_req req[] = {
225 {path, (ULONG)strlen(path) + 1},
226 {value, (ULONG)strlen(value)},
227 };
228 struct xsd_sockmsg *rep;
229 char *msg;
231 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
233 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
235 rep = xenbus_format_msg_reply(xpdd, XS_WRITE, xbt, req, ARRAY_SIZE(req));
236 msg = errmsg(rep);
237 if (msg)
238 return msg;
239 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
241 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
243 return NULL;
244 }
246 static VOID
247 XenBus_Dpc(PVOID ServiceContext)
248 {
249 PXENPCI_DEVICE_DATA xpdd = ServiceContext;
251 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
253 KeSetEvent(&xpdd->XenBus_ReadThreadEvent, IO_NO_INCREMENT, FALSE);
255 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
257 return;
258 }
260 NTSTATUS
261 XenBus_Connect(PXENPCI_DEVICE_DATA xpdd)
262 {
263 PHYSICAL_ADDRESS pa_xen_store_interface;
264 xen_ulong_t xen_store_mfn;
266 xpdd->xen_store_evtchn = (evtchn_port_t)hvm_get_parameter(xpdd, HVM_PARAM_STORE_EVTCHN);
267 xen_store_mfn = (xen_ulong_t)hvm_get_parameter(xpdd, HVM_PARAM_STORE_PFN);
268 pa_xen_store_interface.QuadPart = (ULONGLONG)xen_store_mfn << PAGE_SHIFT;
269 xpdd->xen_store_interface = MmMapIoSpace(pa_xen_store_interface, PAGE_SIZE, MmNonCached);
271 EvtChn_BindDpc(xpdd, xpdd->xen_store_evtchn, XenBus_Dpc, xpdd);
273 xpdd->XenBus_ShuttingDown = FALSE;
274 KeMemoryBarrier();
276 return STATUS_SUCCESS;
277 }
279 NTSTATUS
280 XenBus_Init(PXENPCI_DEVICE_DATA xpdd)
281 {
282 NTSTATUS status;
283 HANDLE thread_handle;
284 int i;
286 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
288 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
290 ExInitializeFastMutex(&xpdd->xb_request_mutex);
291 ExInitializeFastMutex(&xpdd->xb_watch_mutex);
293 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
294 {
295 xpdd->XenBus_WatchEntries[i].Active = 0;
296 }
298 KeInitializeEvent(&xpdd->XenBus_ReadThreadEvent, SynchronizationEvent, FALSE);
299 KeInitializeEvent(&xpdd->XenBus_WatchThreadEvent, SynchronizationEvent, FALSE);
300 KeInitializeEvent(&xpdd->xb_request_complete_event, SynchronizationEvent, FALSE);
302 xpdd->XenBus_ShuttingDown = FALSE;
304 status = XenBus_Connect(xpdd);
305 if (!NT_SUCCESS(status))
306 {
307 return status;
308 }
310 status = PsCreateSystemThread(&thread_handle, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenBus_ReadThreadProc, xpdd);
311 if (!NT_SUCCESS(status))
312 {
313 KdPrint((__DRIVER_NAME " Could not start read thread\n"));
314 return status;
315 }
316 KdPrint((__DRIVER_NAME " Started ReadThread\n"));
318 status = ObReferenceObjectByHandle(thread_handle, THREAD_ALL_ACCESS, NULL, KernelMode, &xpdd->XenBus_ReadThread, NULL);
319 ZwClose(thread_handle);
320 if (!NT_SUCCESS(status))
321 {
322 KdPrint((__DRIVER_NAME " ObReferenceObjectByHandle(XenBus_ReadThread) = %08x\n", status));
323 return status;
324 }
326 status = PsCreateSystemThread(&thread_handle, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenBus_WatchThreadProc, xpdd);
327 if (!NT_SUCCESS(status))
328 {
329 KdPrint((__DRIVER_NAME " Could not start watch thread\n"));
330 return status;
331 }
332 KdPrint((__DRIVER_NAME " Started WatchThread\n"));
333 status = ObReferenceObjectByHandle(thread_handle, THREAD_ALL_ACCESS, NULL, KernelMode, &xpdd->XenBus_WatchThread, NULL);
334 ZwClose(thread_handle);
335 if (!NT_SUCCESS(status))
336 {
337 KdPrint((__DRIVER_NAME " ObReferenceObjectByHandle(XenBus_WatchThread) = %08x\n", status));
338 }
340 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
342 return STATUS_SUCCESS;
343 }
345 char *
346 XenBus_SendRemWatch(
347 PVOID context,
348 xenbus_transaction_t xbt,
349 char *path,
350 int index)
351 {
352 struct xsd_sockmsg *rep;
353 char *msg;
354 char Token[20];
355 struct write_req req[2];
357 req[0].data = path;
358 req[0].len = (ULONG)strlen(path) + 1;
360 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", index);
361 req[1].data = Token;
362 req[1].len = (ULONG)strlen(Token) + 1;
364 rep = xenbus_format_msg_reply(context, XS_UNWATCH, xbt, req, ARRAY_SIZE(req));
366 msg = errmsg(rep);
367 if (msg)
368 return msg;
370 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
372 return NULL;
373 }
375 NTSTATUS
376 XenBus_StopThreads(PXENPCI_DEVICE_DATA xpdd)
377 {
378 NTSTATUS status;
379 //KWAIT_BLOCK WaitBlockArray[2];
380 int i;
381 LARGE_INTEGER timeout;
383 FUNCTION_ENTER();
385 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
387 /* we need to remove the watches as a watch firing could lead to a XenBus_Read/Write/Printf */
388 for (i = 0; i < MAX_WATCH_ENTRIES; i++) {
389 if (xpdd->XenBus_WatchEntries[i].Active)
390 XenBus_SendRemWatch(xpdd, XBT_NIL, xpdd->XenBus_WatchEntries[i].Path, i);
391 }
393 xpdd->XenBus_ShuttingDown = TRUE;
394 KeMemoryBarrier();
396 KeSetEvent(&xpdd->XenBus_ReadThreadEvent, IO_NO_INCREMENT, FALSE);
397 KeSetEvent(&xpdd->XenBus_WatchThreadEvent, IO_NO_INCREMENT, FALSE);
399 timeout.QuadPart = (LONGLONG)-1 * 1000 * 1000 * 10;
400 while ((status = KeWaitForSingleObject(xpdd->XenBus_ReadThread, Executive, KernelMode, FALSE, &timeout)) != STATUS_SUCCESS)
401 {
402 timeout.QuadPart = (LONGLONG)-1 * 1000 * 1000 * 10;
403 }
404 ObDereferenceObject(xpdd->XenBus_ReadThread);
405 timeout.QuadPart = (LONGLONG)-1 * 1000 * 1000 * 10;
406 while ((status = KeWaitForSingleObject(xpdd->XenBus_WatchThread, Executive, KernelMode, FALSE, &timeout)) != STATUS_SUCCESS)
407 {
408 timeout.QuadPart = (LONGLONG)-1 * 1000 * 1000 * 10;
409 }
410 ObDereferenceObject(xpdd->XenBus_WatchThread);
412 xpdd->XenBus_ShuttingDown = FALSE;
414 FUNCTION_EXIT();
416 return STATUS_SUCCESS;
417 }
419 char *
420 XenBus_List(
421 PVOID Context,
422 xenbus_transaction_t xbt,
423 char *pre,
424 char ***contents)
425 {
426 PXENPCI_DEVICE_DATA xpdd = Context;
427 struct xsd_sockmsg *reply, *repmsg;
428 struct write_req req[] = { { pre, (ULONG)strlen(pre)+1 } };
429 ULONG nr_elems, x, i;
430 char **res;
431 char *msg;
433 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
435 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
437 repmsg = xenbus_format_msg_reply(xpdd, XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
438 msg = errmsg(repmsg);
439 if (msg)
440 {
441 *contents = NULL;
442 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
443 return msg;
444 }
445 reply = repmsg + 1;
446 for (x = nr_elems = 0; x < repmsg->len; x++)
447 {
448 nr_elems += (((char *)reply)[x] == 0);
449 }
450 res = ExAllocatePoolWithTag(NonPagedPool, sizeof(res[0]) * (nr_elems + 1),
451 XENPCI_POOL_TAG);
452 for (x = i = 0; i < nr_elems; i++)
453 {
454 int l = (int)strlen((char *)reply + x);
455 res[i] = ExAllocatePoolWithTag(NonPagedPool, l + 1, XENPCI_POOL_TAG);
456 memcpy(res[i], (char *)reply + x, l + 1);
457 x += l + 1;
458 }
459 res[i] = NULL;
460 ExFreePoolWithTag(repmsg, XENPCI_POOL_TAG);
461 *contents = res;
462 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
463 return NULL;
464 }
466 static DDKAPI void
467 XenBus_ReadThreadProc(PVOID StartContext)
468 {
469 int NewWriteIndex;
470 struct xsd_sockmsg msg;
471 char *payload;
472 char *path, *token;
473 PXENPCI_DEVICE_DATA xpdd = StartContext;
475 for(;;)
476 {
477 KeWaitForSingleObject(&xpdd->XenBus_ReadThreadEvent, Executive, KernelMode, FALSE, NULL);
478 //Print((__DRIVER_NAME " +++ thread woken\n"));
479 if (xpdd->XenBus_ShuttingDown)
480 {
481 KdPrint((__DRIVER_NAME " Shutdown detected in ReadThreadProc\n"));
482 PsTerminateSystemThread(0);
483 }
484 while (xpdd->xen_store_interface->rsp_prod != xpdd->xen_store_interface->rsp_cons)
485 {
486 //KdPrint((__DRIVER_NAME " a - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
487 if (xpdd->xen_store_interface->rsp_prod - xpdd->xen_store_interface->rsp_cons < sizeof(msg))
488 {
489 //KdPrint((__DRIVER_NAME " +++ Message incomplete (not even a full header)\n"));
490 break;
491 }
492 KeMemoryBarrier();
493 memcpy_from_ring(xpdd->xen_store_interface->rsp, &msg,
494 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons), sizeof(msg));
495 if (xpdd->xen_store_interface->rsp_prod - xpdd->xen_store_interface->rsp_cons < sizeof(msg) + msg.len)
496 {
497 //KdPrint((__DRIVER_NAME " +++ Message incomplete (header but not full body)\n"));
498 break;
499 }
501 if (msg.type != XS_WATCH_EVENT)
502 {
503 xpdd->xb_reply = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
504 memcpy_from_ring(xpdd->xen_store_interface->rsp,
505 xpdd->xb_reply,
506 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons),
507 msg.len + sizeof(msg));
508 xpdd->xen_store_interface->rsp_cons += msg.len + sizeof(msg);
509 //KdPrint((__DRIVER_NAME " +++ Setting event\n"));
510 KeSetEvent(&xpdd->xb_request_complete_event, IO_NO_INCREMENT, FALSE);
511 }
512 else // a watch: add to watch ring and signal watch thread
513 {
514 payload = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
515 memcpy_from_ring(xpdd->xen_store_interface->rsp, payload,
516 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons), msg.len + sizeof(msg));
517 xpdd->xen_store_interface->rsp_cons += msg.len + sizeof(msg);
518 path = payload + sizeof(msg);
519 token = path + strlen(path) + 1;
521 NewWriteIndex = (xpdd->XenBus_WatchRingWriteIndex + 1) & 127;
522 if (NewWriteIndex != xpdd->XenBus_WatchRingReadIndex)
523 {
524 strncpy(xpdd->XenBus_WatchRing[NewWriteIndex].Path, path, 128);
525 strncpy(xpdd->XenBus_WatchRing[NewWriteIndex].Token, token, 10);
526 xpdd->XenBus_WatchRingWriteIndex = NewWriteIndex;
527 }
528 else
529 {
530 //KdPrint((__DRIVER_NAME " +++ Queue full Path = %s Token = %s\n", path, token));
531 // drop the message on the floor
532 continue;
533 }
535 ExFreePoolWithTag(payload, XENPCI_POOL_TAG);
536 KeSetEvent(&xpdd->XenBus_WatchThreadEvent, IO_NO_INCREMENT, FALSE);
537 }
538 }
539 }
540 }
542 static DDKAPI void
543 XenBus_WatchThreadProc(PVOID StartContext)
544 {
545 int index;
546 PXENBUS_WATCH_ENTRY entry;
547 PXENPCI_DEVICE_DATA xpdd = StartContext;
549 for(;;)
550 {
551 KeWaitForSingleObject(&xpdd->XenBus_WatchThreadEvent, Executive, KernelMode, FALSE, NULL);
552 ExAcquireFastMutex(&xpdd->xb_watch_mutex);
553 if (xpdd->XenBus_ShuttingDown)
554 {
555 KdPrint((__DRIVER_NAME " Shutdown detected in WatchThreadProc\n"));
556 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
557 PsTerminateSystemThread(0);
558 KdPrint((__DRIVER_NAME " WatchThreadProc still running... wtf?\n"));
559 }
560 while (xpdd->XenBus_WatchRingReadIndex != xpdd->XenBus_WatchRingWriteIndex)
561 {
562 xpdd->XenBus_WatchRingReadIndex =
563 (xpdd->XenBus_WatchRingReadIndex + 1) % WATCH_RING_SIZE;
564 index = atoi(xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Token);
566 entry = &xpdd->XenBus_WatchEntries[index];
567 if (!entry->Active || !entry->ServiceRoutine)
568 {
569 KdPrint((__DRIVER_NAME " No watch for index %d\n", index));
570 continue;
571 }
572 entry->Count++;
573 entry->ServiceRoutine(xpdd->XenBus_WatchRing[xpdd->XenBus_WatchRingReadIndex].Path, entry->ServiceContext);
574 }
575 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
576 }
577 }
579 /*
580 Called at PASSIVE_LEVEL
581 */
582 static char *
583 XenBus_SendAddWatch(
584 PVOID Context,
585 xenbus_transaction_t xbt,
586 char *Path,
587 int slot)
588 {
589 PXENPCI_DEVICE_DATA xpdd = Context;
590 struct xsd_sockmsg *rep;
591 char *msg;
592 char Token[20];
593 struct write_req req[2];
595 req[0].data = Path;
596 req[0].len = (ULONG)strlen(Path) + 1;
598 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", slot);
599 req[1].data = Token;
600 req[1].len = (ULONG)strlen(Token) + 1;
602 rep = xenbus_format_msg_reply(xpdd, XS_WATCH, xbt, req, ARRAY_SIZE(req));
604 msg = errmsg(rep);
605 if (!msg)
606 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
608 return msg;
609 }
611 /* called at PASSIVE_LEVEL */
612 NTSTATUS
613 XenBus_Suspend(PXENPCI_DEVICE_DATA xpdd)
614 {
615 int i;
617 /* we need to remove the watches as a watch firing could lead to a XenBus_Read/Write/Printf */
618 for (i = 0; i < MAX_WATCH_ENTRIES; i++) {
619 if (xpdd->XenBus_WatchEntries[i].Active)
620 XenBus_SendRemWatch(xpdd, XBT_NIL, xpdd->XenBus_WatchEntries[i].Path, i);
621 }
623 // need to synchronise with readthread here too to ensure that it won't do anything silly
625 return STATUS_SUCCESS;
626 }
628 /* called at PASSIVE_LEVEL */
629 NTSTATUS
630 XenBus_Resume(PXENPCI_DEVICE_DATA xpdd)
631 {
632 NTSTATUS status;
633 int i;
635 FUNCTION_ENTER();
637 status = XenBus_Connect(xpdd);
638 if (!NT_SUCCESS(status))
639 {
640 return status;
641 }
643 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
644 {
645 if (xpdd->XenBus_WatchEntries[i].Active)
646 {
647 KdPrint((__DRIVER_NAME " Adding watch for path = %s\n", xpdd->XenBus_WatchEntries[i].Path));
648 XenBus_SendAddWatch(xpdd, XBT_NIL, xpdd->XenBus_WatchEntries[i].Path, i);
649 }
650 }
651 FUNCTION_EXIT();
653 return STATUS_SUCCESS;
654 }
656 char *
657 XenBus_AddWatch(
658 PVOID Context,
659 xenbus_transaction_t xbt,
660 char *Path,
661 PXENBUS_WATCH_CALLBACK ServiceRoutine,
662 PVOID ServiceContext)
663 {
664 PXENPCI_DEVICE_DATA xpdd = Context;
665 char *msg;
666 int i;
667 PXENBUS_WATCH_ENTRY w_entry;
669 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
671 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
673 ASSERT(strlen(Path) < ARRAY_SIZE(w_entry->Path));
675 ExAcquireFastMutex(&xpdd->xb_watch_mutex);
677 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
678 if (xpdd->XenBus_WatchEntries[i].Active == 0)
679 break;
681 if (i == MAX_WATCH_ENTRIES)
682 {
683 KdPrint((__DRIVER_NAME " +++ No more watch slots left\n"));
684 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
685 return NULL;
686 }
688 /* must init watchentry before starting watch */
690 w_entry = &xpdd->XenBus_WatchEntries[i];
691 strncpy(w_entry->Path, Path, ARRAY_SIZE(w_entry->Path));
692 w_entry->ServiceRoutine = ServiceRoutine;
693 w_entry->ServiceContext = ServiceContext;
694 w_entry->Count = 0;
695 w_entry->Active = 1;
697 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
699 msg = XenBus_SendAddWatch(xpdd, xbt, Path, i);
701 if (msg)
702 {
703 xpdd->XenBus_WatchEntries[i].Active = 0;
704 //KdPrint((__DRIVER_NAME " <-- XenBus_AddWatch (%s)\n", msg));
705 return msg;
706 }
708 //KdPrint((__DRIVER_NAME " <-- XenBus_AddWatch\n"));
710 return NULL;
711 }
713 char *
714 XenBus_RemWatch(
715 PVOID Context,
716 xenbus_transaction_t xbt,
717 char *Path,
718 PXENBUS_WATCH_CALLBACK ServiceRoutine,
719 PVOID ServiceContext)
720 {
721 PXENPCI_DEVICE_DATA xpdd = Context;
722 char *msg;
723 int i;
725 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
726 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
728 ExAcquireFastMutex(&xpdd->xb_watch_mutex);
730 // check that Path < 128 chars
732 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
733 {
734 #if 0
735 if (xpdd->XenBus_WatchEntries[i].Active)
736 {
737 KdPrint((__DRIVER_NAME " (%d == 1) = %d\n", xpdd->XenBus_WatchEntries[i].Active, xpdd->XenBus_WatchEntries[i].Active == 1));
738 KdPrint((__DRIVER_NAME " strcmp(%s, %s) = %d\n", xpdd->XenBus_WatchEntries[i].Path, Path, strcmp(xpdd->XenBus_WatchEntries[i].Path, Path)));
739 KdPrint((__DRIVER_NAME " (%p == %p) = %d\n", xpdd->XenBus_WatchEntries[i].ServiceRoutine, ServiceRoutine, xpdd->XenBus_WatchEntries[i].ServiceRoutine == ServiceRoutine));
740 KdPrint((__DRIVER_NAME " (%p == %p) = %d\n", xpdd->XenBus_WatchEntries[i].ServiceContext, ServiceContext, xpdd->XenBus_WatchEntries[i].ServiceContext == ServiceContext));
741 #endif
742 if (xpdd->XenBus_WatchEntries[i].Active == 1
743 && strcmp(xpdd->XenBus_WatchEntries[i].Path, Path) == 0
744 && xpdd->XenBus_WatchEntries[i].ServiceRoutine == ServiceRoutine
745 && xpdd->XenBus_WatchEntries[i].ServiceContext == ServiceContext)
746 {
747 KdPrint((__DRIVER_NAME " Match\n"));
748 break;
749 }
750 #if 0
751 }
752 #endif
753 }
755 if (i == MAX_WATCH_ENTRIES)
756 {
757 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
758 KdPrint((__DRIVER_NAME " Watch not set - can't remove\n"));
759 return NULL;
760 }
762 xpdd->XenBus_WatchEntries[i].Active = 0;
763 xpdd->XenBus_WatchEntries[i].Path[0] = 0;
765 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
767 msg = XenBus_SendRemWatch(Context, xbt, Path, i);
769 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
771 return msg;
772 }
775 char *
776 XenBus_StartTransaction(PVOID Context, xenbus_transaction_t *xbt)
777 {
778 PXENPCI_DEVICE_DATA xpdd = Context;
779 /* xenstored becomes angry if you send a length 0 message, so just
780 shove a nul terminator on the end */
781 struct write_req req = { "", 1};
782 struct xsd_sockmsg *rep;
783 char *err;
785 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
786 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
788 rep = xenbus_format_msg_reply(xpdd, XS_TRANSACTION_START, 0, &req, 1);
789 err = errmsg(rep);
790 if (err)
791 return err;
792 *xbt = atoi((char *)(rep + 1));
793 //sscanf((char *)(rep + 1), "%u", xbt);
794 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
796 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
798 return NULL;
799 }
801 char *
802 XenBus_EndTransaction(
803 PVOID Context,
804 xenbus_transaction_t t,
805 int abort,
806 int *retry)
807 {
808 PXENPCI_DEVICE_DATA xpdd = Context;
809 struct xsd_sockmsg *rep;
810 struct write_req req;
811 char *err;
813 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
815 *retry = 0;
817 req.data = abort ? "F" : "T";
818 req.len = 2;
819 rep = xenbus_format_msg_reply(xpdd, XS_TRANSACTION_END, t, &req, 1);
820 err = errmsg(rep);
821 if (err) {
822 if (!strcmp(err, "EAGAIN")) {
823 *retry = 1;
824 ExFreePoolWithTag(err, XENPCI_POOL_TAG);
825 return NULL;
826 } else {
827 return err;
828 }
829 }
830 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
832 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
834 return NULL;
835 }
837 char *
838 XenBus_Printf(
839 PVOID Context,
840 xenbus_transaction_t xbt,
841 char *path,
842 char *fmt,
843 ...)
844 {
845 PXENPCI_DEVICE_DATA xpdd = Context;
846 va_list ap;
847 char buf[512];
848 char *retval;
850 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
851 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
853 va_start(ap, fmt);
854 RtlStringCbVPrintfA(buf, ARRAY_SIZE(buf), fmt, ap);
855 va_end(ap);
856 retval = XenBus_Write(xpdd, xbt, path, buf);
858 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
860 return retval;
861 }