win-pvdrivers

view xenpci/xenbus.c @ 1022:cd72cd0e1c19

hooking debug doesn't survive hibernate under win8. Remove it.
Remove initial balloon down - doesn't work under xen 4.2 without xenbus being loaded
author James Harper <james.harper@bendigoit.com.au>
date Tue Feb 19 15:11:49 2013 +1100 (2013-02-19)
parents df03fde445b8
children 37c0c84a42e8
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 /* Not really necessary but keeps PREfast happy */
27 static EVT_WDF_WORKITEM XenBus_WatchWorkItemProc;
29 WDF_DECLARE_CONTEXT_TYPE(xsd_sockmsg_t)
31 struct write_req {
32 void *data;
33 unsigned len;
34 };
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();
83 XN_ASSERT(len <= XENSTORE_RING_SIZE);
84 prod = xpdd->xen_store_interface->req_prod;
85 ptr = data;
86 remaining = len;
87 while (remaining)
88 {
89 copy_len = min(remaining, XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
90 memcpy((PUCHAR)xpdd->xen_store_interface->req + MASK_XENSTORE_IDX(prod), ptr, copy_len);
91 prod += (XENSTORE_RING_IDX)copy_len;
92 ptr += copy_len;
93 remaining -= copy_len;
94 }
95 /* Remote must see entire message before updating indexes */
96 KeMemoryBarrier();
97 xpdd->xen_store_interface->req_prod = prod;
98 EvtChn_Notify(xpdd, xpdd->xenbus_event);
100 //FUNCTION_EXIT();
101 }
103 /* takes and releases xb_request_mutex */
104 static struct xsd_sockmsg *
105 xenbus_format_msg_reply(
106 PXENPCI_DEVICE_DATA xpdd,
107 int type,
108 xenbus_transaction_t trans_id,
109 struct write_req *req,
110 int nr_reqs)
111 {
112 struct xsd_sockmsg msg;
113 struct xsd_sockmsg *reply;
114 int i;
116 //FUNCTION_ENTER();
118 msg.type = type;
119 msg.req_id = 0;
120 msg.tx_id = trans_id;
121 msg.len = 0;
122 for (i = 0; i < nr_reqs; i++)
123 msg.len += req[i].len;
125 ExAcquireFastMutex(&xpdd->xb_request_mutex);
126 xb_write(xpdd, &msg, sizeof(msg));
127 for (i = 0; i < nr_reqs; i++)
128 xb_write(xpdd, req[i].data, req[i].len);
130 KeWaitForSingleObject(&xpdd->xb_request_complete_event, Executive, KernelMode, FALSE, NULL);
131 reply = xpdd->xb_reply;
132 xpdd->xb_reply = NULL;
133 ExReleaseFastMutex(&xpdd->xb_request_mutex);
135 //FUNCTION_EXIT();
137 return reply;
138 }
140 /* takes and releases xb_request_mutex */
141 struct xsd_sockmsg *
142 XenBus_Raw(
143 PXENPCI_DEVICE_DATA xpdd,
144 struct xsd_sockmsg *msg)
145 {
146 struct xsd_sockmsg *reply;
148 //FUNCTION_ENTER();
150 ExAcquireFastMutex(&xpdd->xb_request_mutex);
151 xb_write(xpdd, msg, sizeof(struct xsd_sockmsg) + msg->len);
152 KeWaitForSingleObject(&xpdd->xb_request_complete_event, Executive, KernelMode, FALSE, NULL);
153 reply = xpdd->xb_reply;
154 xpdd->xb_reply = NULL;
155 ExReleaseFastMutex(&xpdd->xb_request_mutex);
157 //FUNCTION_EXIT();
159 return reply;
160 }
162 /* Called at PASSIVE_LEVEL */
163 char *
164 XenBus_Read(
165 PVOID Context,
166 xenbus_transaction_t xbt,
167 char *path,
168 char **value)
169 {
170 PXENPCI_DEVICE_DATA xpdd = Context;
171 struct write_req req[] = { {path, (ULONG)strlen(path) + 1} };
172 struct xsd_sockmsg *rep;
173 char *res;
174 char *msg;
176 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
178 XN_ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
180 rep = xenbus_format_msg_reply(xpdd, XS_READ, xbt, req, ARRAY_SIZE(req));
181 msg = errmsg(rep);
182 if (msg) {
183 *value = NULL;
184 return msg;
185 }
186 res = ExAllocatePoolWithTag(NonPagedPool, rep->len + 1, XENPCI_POOL_TAG);
187 memcpy(res, rep + 1, rep->len);
188 res[rep->len] = 0;
189 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
190 *value = res;
192 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
194 return NULL;
195 }
197 /* Called at PASSIVE_LEVEL */
198 char *
199 XenBus_Write(
200 PVOID Context,
201 xenbus_transaction_t xbt,
202 char *path,
203 char *value)
204 {
205 PXENPCI_DEVICE_DATA xpdd = Context;
206 struct write_req req[] = {
207 {path, (ULONG)strlen(path) + 1},
208 {value, (ULONG)strlen(value)},
209 };
210 struct xsd_sockmsg *rep;
211 char *msg;
213 XN_ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
215 rep = xenbus_format_msg_reply(xpdd, XS_WRITE, xbt, req, ARRAY_SIZE(req));
216 msg = errmsg(rep);
217 if (msg)
218 return msg;
219 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
221 return NULL;
222 }
224 /* Called at PASSIVE_LEVEL */
225 static VOID
226 XenBus_WatchWorkItemProc(WDFWORKITEM workitem)
227 {
228 WDFDEVICE device = WdfWorkItemGetParentObject(workitem);
229 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
230 xsd_sockmsg_t *msg;
231 PCHAR path;
232 int index;
233 PXENBUS_WATCH_ENTRY entry;
234 PXN_WATCH_CALLBACK service_routine;
235 PVOID service_context;
237 //FUNCTION_ENTER();
238 msg = WdfObjectGetTypedContext(workitem, xsd_sockmsg_t);
239 path = (PCHAR)msg + sizeof(xsd_sockmsg_t);
240 index = atoi(path + strlen(path) + 1);
241 if (index < 0 || index >= MAX_WATCH_ENTRIES)
242 {
243 KdPrint((__DRIVER_NAME " Watch index %d out of range\n", index));
244 WdfObjectDelete(workitem);
245 //FUNCTION_ENTER();
246 return;
247 }
248 ExAcquireFastMutex(&xpdd->xb_watch_mutex);
249 entry = &xpdd->XenBus_WatchEntries[index];
250 if (!entry->Active || !entry->ServiceRoutine)
251 {
252 KdPrint((__DRIVER_NAME " No watch for index %d\n", index));
253 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
254 WdfObjectDelete(workitem);
255 //FUNCTION_ENTER();
256 return;
257 }
258 entry->Count++;
259 service_routine = entry->ServiceRoutine;
260 service_context = entry->ServiceContext;
261 service_routine(path, service_context);
262 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
263 WdfObjectDelete(workitem);
264 //FUNCTION_EXIT();
265 }
267 /* Called at DISPATCH_LEVEL */
268 static VOID
269 XenBus_Dpc(PVOID ServiceContext)
270 {
271 NTSTATUS status;
272 PXENPCI_DEVICE_DATA xpdd = ServiceContext;
273 xsd_sockmsg_t msg;
274 ULONG msg_len;
275 WDF_WORKITEM_CONFIG workitem_config;
276 WDF_OBJECT_ATTRIBUTES workitem_attributes;
277 WDFWORKITEM workitem;
278 ULONG rsp_prod;
280 //FUNCTION_ENTER();
282 KeAcquireSpinLockAtDpcLevel(&xpdd->xb_ring_spinlock);
284 /* snapshot rsp_prod so it doesn't change while we are looking at it */
285 while ((rsp_prod = xpdd->xen_store_interface->rsp_prod) != xpdd->xen_store_interface->rsp_cons)
286 {
287 KeMemoryBarrier(); /* make sure the data in the ring is valid */
288 if (!xpdd->xb_msg)
289 {
290 if (rsp_prod - xpdd->xen_store_interface->rsp_cons < sizeof(xsd_sockmsg_t))
291 {
292 //KdPrint((__DRIVER_NAME " +++ Message incomplete (not even a full header)\n"));
293 break;
294 }
295 memcpy_from_ring(xpdd->xen_store_interface->rsp, &msg,
296 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons), sizeof(xsd_sockmsg_t));
297 xpdd->xb_msg = ExAllocatePoolWithTag(NonPagedPool, sizeof(xsd_sockmsg_t) + msg.len, XENPCI_POOL_TAG);
298 memcpy(xpdd->xb_msg, &msg, sizeof(xsd_sockmsg_t));
299 xpdd->xb_msg_offset = sizeof(xsd_sockmsg_t);
300 xpdd->xen_store_interface->rsp_cons += sizeof(xsd_sockmsg_t);
301 }
303 msg_len = min(rsp_prod - xpdd->xen_store_interface->rsp_cons, sizeof(xsd_sockmsg_t) + xpdd->xb_msg->len - xpdd->xb_msg_offset);
304 XN_ASSERT(xpdd->xb_msg_offset + msg_len <= sizeof(xsd_sockmsg_t) + xpdd->xb_msg->len);
305 memcpy_from_ring(xpdd->xen_store_interface->rsp,
306 (PUCHAR)xpdd->xb_msg + xpdd->xb_msg_offset,
307 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons),
308 msg_len);
309 xpdd->xen_store_interface->rsp_cons += msg_len;
310 xpdd->xb_msg_offset += msg_len;
312 if (xpdd->xb_msg_offset < sizeof(xsd_sockmsg_t) + xpdd->xb_msg->len)
313 {
314 //KdPrint((__DRIVER_NAME " +++ Message incomplete (header but not full body)\n"));
315 EvtChn_Notify(xpdd, xpdd->xenbus_event); /* there is room on the ring now */
316 break;
317 }
319 if (xpdd->xb_msg->type != XS_WATCH_EVENT)
320 {
321 /* process reply - only ever one outstanding */
322 XN_ASSERT(xpdd->xb_reply == NULL);
323 xpdd->xb_reply = xpdd->xb_msg;
324 xpdd->xb_msg = NULL;
325 KeSetEvent(&xpdd->xb_request_complete_event, IO_NO_INCREMENT, FALSE);
326 }
327 else
328 {
329 /* process watch */
330 WDF_WORKITEM_CONFIG_INIT(&workitem_config, XenBus_WatchWorkItemProc);
331 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&workitem_attributes, xsd_sockmsg_t);
332 workitem_attributes.ParentObject = xpdd->wdf_device;
333 workitem_attributes.ContextSizeOverride = xpdd->xb_msg_offset;
334 status = WdfWorkItemCreate(&workitem_config, &workitem_attributes, &workitem);
335 if (!NT_SUCCESS(status))
336 {
337 KdPrint((__DRIVER_NAME " Failed to create work item for watch\n"));
338 continue;
339 }
340 memcpy(WdfObjectGetTypedContext(workitem, xsd_sockmsg_t), xpdd->xb_msg, xpdd->xb_msg_offset);
341 xpdd->xb_msg = NULL;
342 WdfWorkItemEnqueue(workitem);
343 }
344 EvtChn_Notify(xpdd, xpdd->xenbus_event); /* there is room on the ring now */
345 }
346 KeReleaseSpinLockFromDpcLevel(&xpdd->xb_ring_spinlock);
348 //FUNCTION_EXIT();
349 }
351 static NTSTATUS
352 XenBus_Connect(PXENPCI_DEVICE_DATA xpdd)
353 {
354 PHYSICAL_ADDRESS pa_xen_store_interface;
355 xen_ulong_t xen_store_mfn;
357 xpdd->xenbus_event = (evtchn_port_t)hvm_get_parameter(xpdd, HVM_PARAM_STORE_EVTCHN);
358 xen_store_mfn = (xen_ulong_t)hvm_get_parameter(xpdd, HVM_PARAM_STORE_PFN);
359 pa_xen_store_interface.QuadPart = (ULONGLONG)xen_store_mfn << PAGE_SHIFT;
360 xpdd->xen_store_interface = MmMapIoSpace(pa_xen_store_interface, PAGE_SIZE, MmNonCached);
362 EvtChn_BindDpc(xpdd, xpdd->xenbus_event, XenBus_Dpc, xpdd, EVT_ACTION_FLAGS_NO_SUSPEND);
364 return STATUS_SUCCESS;
365 }
367 static NTSTATUS
368 XenBus_Disconnect(PXENPCI_DEVICE_DATA xpdd)
369 {
370 EvtChn_Unbind(xpdd, xpdd->xenbus_event);
372 MmUnmapIoSpace(xpdd->xen_store_interface, PAGE_SIZE);
374 return STATUS_SUCCESS;
375 }
377 NTSTATUS
378 XenBus_Init(PXENPCI_DEVICE_DATA xpdd)
379 {
380 NTSTATUS status;
381 int i;
383 FUNCTION_ENTER();
385 XN_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
387 KeInitializeSpinLock(&xpdd->xb_ring_spinlock);
388 ExInitializeFastMutex(&xpdd->xb_request_mutex);
389 ExInitializeFastMutex(&xpdd->xb_watch_mutex);
391 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
392 {
393 xpdd->XenBus_WatchEntries[i].Active = 0;
394 }
396 KeInitializeEvent(&xpdd->xb_request_complete_event, SynchronizationEvent, FALSE);
398 status = XenBus_Connect(xpdd);
399 if (!NT_SUCCESS(status))
400 {
401 FUNCTION_EXIT();
402 return status;
403 }
405 FUNCTION_EXIT();
407 return STATUS_SUCCESS;
408 }
410 char *
411 XenBus_SendRemWatch(
412 PVOID context,
413 xenbus_transaction_t xbt,
414 char *path,
415 int index)
416 {
417 struct xsd_sockmsg *rep;
418 char *msg;
419 char Token[20];
420 struct write_req req[2];
422 req[0].data = path;
423 req[0].len = (ULONG)strlen(path) + 1;
425 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", index);
426 req[1].data = Token;
427 req[1].len = (ULONG)strlen(Token) + 1;
429 rep = xenbus_format_msg_reply(context, XS_UNWATCH, xbt, req, ARRAY_SIZE(req));
431 msg = errmsg(rep);
432 if (msg)
433 return msg;
435 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
437 return NULL;
438 }
440 NTSTATUS
441 XenBus_Halt(PXENPCI_DEVICE_DATA xpdd)
442 {
443 int i;
445 FUNCTION_ENTER();
447 XN_ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
449 /* we need to remove the watches as a watch firing could lead to a XenBus_Read/Write/Printf */
450 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
451 {
452 if (xpdd->XenBus_WatchEntries[i].Active)
453 {
454 xpdd->XenBus_WatchEntries[i].Active = 0;
455 XenBus_SendRemWatch(xpdd, XBT_NIL, xpdd->XenBus_WatchEntries[i].Path, i);
456 }
457 }
459 XenBus_Disconnect(xpdd);
461 FUNCTION_EXIT();
463 return STATUS_SUCCESS;
464 }
466 char *
467 XenBus_List(
468 PVOID Context,
469 xenbus_transaction_t xbt,
470 char *pre,
471 char ***contents)
472 {
473 PXENPCI_DEVICE_DATA xpdd = Context;
474 struct xsd_sockmsg *reply, *repmsg;
475 struct write_req req[] = { { pre, (ULONG)strlen(pre)+1 } };
476 ULONG nr_elems, x, i;
477 char **res;
478 char *msg;
480 XN_ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
482 repmsg = xenbus_format_msg_reply(xpdd, XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
483 msg = errmsg(repmsg);
484 if (msg)
485 {
486 *contents = NULL;
487 return msg;
488 }
489 reply = repmsg + 1;
490 for (x = nr_elems = 0; x < repmsg->len; x++)
491 {
492 nr_elems += (((char *)reply)[x] == 0);
493 }
494 res = ExAllocatePoolWithTag(NonPagedPool, sizeof(res[0]) * (nr_elems + 1),
495 XENPCI_POOL_TAG);
496 for (x = i = 0; i < nr_elems; i++)
497 {
498 int l = (int)strlen((char *)reply + x);
499 res[i] = ExAllocatePoolWithTag(NonPagedPool, l + 1, XENPCI_POOL_TAG);
500 memcpy(res[i], (char *)reply + x, l + 1);
501 x += l + 1;
502 }
503 res[i] = NULL;
504 ExFreePoolWithTag(repmsg, XENPCI_POOL_TAG);
505 *contents = res;
507 return NULL;
508 }
510 /* Called at PASSIVE_LEVEL */
511 static char *
512 XenBus_SendAddWatch(
513 PVOID Context,
514 xenbus_transaction_t xbt,
515 char *Path,
516 int slot)
517 {
518 PXENPCI_DEVICE_DATA xpdd = Context;
519 struct xsd_sockmsg *rep;
520 char *msg;
521 char Token[20];
522 struct write_req req[2];
524 req[0].data = Path;
525 req[0].len = (ULONG)strlen(Path) + 1;
527 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", slot);
528 req[1].data = Token;
529 req[1].len = (ULONG)strlen(Token) + 1;
531 rep = xenbus_format_msg_reply(xpdd, XS_WATCH, xbt, req, ARRAY_SIZE(req));
533 msg = errmsg(rep);
534 if (!msg)
535 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
537 return msg;
538 }
540 /* called at PASSIVE_LEVEL */
541 NTSTATUS
542 XenBus_Suspend(PXENPCI_DEVICE_DATA xpdd)
543 {
544 int i;
546 /* we need to remove the watches as a watch firing could lead to a XenBus_Read/Write/Printf */
547 for (i = 0; i < MAX_WATCH_ENTRIES; i++) {
548 if (xpdd->XenBus_WatchEntries[i].Active)
549 XenBus_SendRemWatch(xpdd, XBT_NIL, xpdd->XenBus_WatchEntries[i].Path, i);
550 }
551 XenBus_Disconnect(xpdd);
553 return STATUS_SUCCESS;
554 }
556 /* called at PASSIVE_LEVEL */
557 NTSTATUS
558 XenBus_Resume(PXENPCI_DEVICE_DATA xpdd)
559 {
560 NTSTATUS status;
561 int i;
563 FUNCTION_ENTER();
565 status = XenBus_Connect(xpdd);
566 if (!NT_SUCCESS(status))
567 {
568 return status;
569 }
571 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
572 {
573 if (xpdd->XenBus_WatchEntries[i].Active)
574 {
575 KdPrint((__DRIVER_NAME " Adding watch for path = %s\n", xpdd->XenBus_WatchEntries[i].Path));
576 XenBus_SendAddWatch(xpdd, XBT_NIL, xpdd->XenBus_WatchEntries[i].Path, i);
577 }
578 }
580 FUNCTION_EXIT();
582 return STATUS_SUCCESS;
583 }
585 char *
586 XenBus_AddWatch(
587 PVOID Context,
588 xenbus_transaction_t xbt,
589 char *Path,
590 PXN_WATCH_CALLBACK ServiceRoutine,
591 PVOID ServiceContext)
592 {
593 PXENPCI_DEVICE_DATA xpdd = Context;
594 char *msg;
595 int i;
596 PXENBUS_WATCH_ENTRY w_entry;
598 XN_ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
600 XN_ASSERT(strlen(Path) < ARRAY_SIZE(w_entry->Path));
602 ExAcquireFastMutex(&xpdd->xb_watch_mutex);
604 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
605 if (xpdd->XenBus_WatchEntries[i].Active == 0)
606 break;
608 if (i == MAX_WATCH_ENTRIES)
609 {
610 KdPrint((__DRIVER_NAME " +++ No more watch slots left\n"));
611 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
612 return NULL;
613 }
615 /* must init watchentry before starting watch */
617 w_entry = &xpdd->XenBus_WatchEntries[i];
618 RtlStringCbCopyA(w_entry->Path, ARRAY_SIZE(w_entry->Path), Path);
619 w_entry->ServiceRoutine = ServiceRoutine;
620 w_entry->ServiceContext = ServiceContext;
621 w_entry->Count = 0;
622 w_entry->Active = 1;
624 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
626 msg = XenBus_SendAddWatch(xpdd, xbt, Path, i);
628 if (msg)
629 {
630 xpdd->XenBus_WatchEntries[i].Active = 0;
631 return msg;
632 }
634 return NULL;
635 }
637 char *
638 XenBus_RemWatch(
639 PVOID Context,
640 xenbus_transaction_t xbt,
641 char *Path,
642 PXN_WATCH_CALLBACK ServiceRoutine,
643 PVOID ServiceContext) {
644 PXENPCI_DEVICE_DATA xpdd = Context;
645 char *msg;
646 int i;
648 XN_ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
650 ExAcquireFastMutex(&xpdd->xb_watch_mutex);
652 // check that Path < 128 chars
654 for (i = 0; i < MAX_WATCH_ENTRIES; i++) {
655 if (xpdd->XenBus_WatchEntries[i].Active
656 && !strcmp(xpdd->XenBus_WatchEntries[i].Path, Path)
657 && xpdd->XenBus_WatchEntries[i].ServiceRoutine == ServiceRoutine
658 && xpdd->XenBus_WatchEntries[i].ServiceContext == ServiceContext) {
659 KdPrint((__DRIVER_NAME " Match\n"));
660 break;
661 }
662 }
664 if (i == MAX_WATCH_ENTRIES) {
665 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
666 KdPrint((__DRIVER_NAME " Watch not set for %s - can't remove\n", Path));
667 return NULL;
668 }
670 xpdd->XenBus_WatchEntries[i].Active = 0;
671 xpdd->XenBus_WatchEntries[i].Path[0] = 0;
673 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
675 msg = XenBus_SendRemWatch(Context, xbt, Path, i);
677 return msg;
678 }
680 char *
681 XenBus_StartTransaction(PVOID Context, xenbus_transaction_t *xbt)
682 {
683 PXENPCI_DEVICE_DATA xpdd = 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 XN_ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
692 rep = xenbus_format_msg_reply(xpdd, XS_TRANSACTION_START, 0, &req, 1);
693 err = errmsg(rep);
694 if (err)
695 return err;
696 *xbt = atoi((char *)(rep + 1));
697 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
699 return NULL;
700 }
702 char *
703 XenBus_EndTransaction(
704 PVOID Context,
705 xenbus_transaction_t t,
706 int abort,
707 int *retry)
708 {
709 PXENPCI_DEVICE_DATA xpdd = Context;
710 struct xsd_sockmsg *rep;
711 struct write_req req;
712 char *err;
714 *retry = 0;
716 req.data = abort ? "F" : "T";
717 req.len = 2;
718 rep = xenbus_format_msg_reply(xpdd, XS_TRANSACTION_END, t, &req, 1);
719 err = errmsg(rep);
720 if (err) {
721 if (!strcmp(err, "EAGAIN")) {
722 *retry = 1;
723 ExFreePoolWithTag(err, XENPCI_POOL_TAG);
724 return NULL;
725 } else {
726 return err;
727 }
728 }
729 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
731 return NULL;
732 }
734 char *
735 XenBus_Printf(
736 PVOID Context,
737 xenbus_transaction_t xbt,
738 char *path,
739 char *fmt,
740 ...)
741 {
742 PXENPCI_DEVICE_DATA xpdd = Context;
743 va_list ap;
744 char buf[512];
745 char *retval;
747 XN_ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
749 va_start(ap, fmt);
750 RtlStringCbVPrintfA(buf, ARRAY_SIZE(buf), fmt, ap);
751 va_end(ap);
752 retval = XenBus_Write(xpdd, xbt, path, buf);
754 return retval;
755 }