win-pvdrivers

view xenpci/xenbus.c @ 651:8b3dae86a7f6

nothing
author James Harper <james.harper@bendigoit.com.au>
date Mon Sep 07 13:31:22 2009 +1000 (2009-09-07)
parents 84e37987cdbc
children e5522de3be37
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 WDF_DECLARE_CONTEXT_TYPE(xsd_sockmsg_t)
28 struct write_req {
29 void *data;
30 unsigned len;
31 };
33 // This routine free's the rep structure if there was an error!!!
34 static char *errmsg(struct xsd_sockmsg *rep)
35 {
36 char *res;
38 if (!rep) {
39 char msg[] = "No reply";
40 size_t len = strlen(msg) + 1;
41 return memcpy(ExAllocatePoolWithTag(NonPagedPool, len, XENPCI_POOL_TAG), msg, len);
42 }
43 if (rep->type != XS_ERROR)
44 return NULL;
45 res = ExAllocatePoolWithTag(NonPagedPool, rep->len + 1, XENPCI_POOL_TAG);
46 memcpy(res, rep + 1, rep->len);
47 res[rep->len] = 0;
48 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
49 return res;
50 }
52 static void memcpy_from_ring(void *Ring,
53 void *Dest,
54 int off,
55 int len)
56 {
57 int c1, c2;
58 char *ring = Ring;
59 char *dest = Dest;
60 c1 = min(len, XENSTORE_RING_SIZE - off);
61 c2 = len - c1;
62 memcpy(dest, ring + off, c1);
63 memcpy(dest + c1, ring, c2);
64 }
66 /* called with xenbus_mutex held */
67 static void xb_write(
68 PXENPCI_DEVICE_DATA xpdd,
69 PVOID data,
70 ULONG len
71 )
72 {
73 XENSTORE_RING_IDX prod;
74 ULONG copy_len;
75 PUCHAR ptr;
76 ULONG remaining;
78 //FUNCTION_ENTER();
80 ASSERT(len <= XENSTORE_RING_SIZE);
81 prod = xpdd->xen_store_interface->req_prod;
82 ptr = data;
83 remaining = len;
84 while (remaining)
85 {
86 copy_len = min(remaining, XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
87 memcpy((PUCHAR)xpdd->xen_store_interface->req + MASK_XENSTORE_IDX(prod), ptr, copy_len);
88 prod += (XENSTORE_RING_IDX)copy_len;
89 ptr += copy_len;
90 remaining -= copy_len;
91 }
92 /* Remote must see entire message before updating indexes */
93 KeMemoryBarrier();
94 xpdd->xen_store_interface->req_prod = prod;
95 EvtChn_Notify(xpdd, xpdd->xen_store_evtchn);
97 //FUNCTION_EXIT();
98 }
100 /* takes and releases xb_request_mutex */
101 static struct xsd_sockmsg *
102 xenbus_format_msg_reply(
103 PXENPCI_DEVICE_DATA xpdd,
104 int type,
105 xenbus_transaction_t trans_id,
106 struct write_req *req,
107 int nr_reqs)
108 {
109 struct xsd_sockmsg msg;
110 struct xsd_sockmsg *reply;
111 int i;
113 //FUNCTION_ENTER();
115 msg.type = type;
116 msg.req_id = 0;
117 msg.tx_id = trans_id;
118 msg.len = 0;
119 for (i = 0; i < nr_reqs; i++)
120 msg.len += req[i].len;
122 ExAcquireFastMutex(&xpdd->xb_request_mutex);
123 xb_write(xpdd, &msg, sizeof(msg));
124 for (i = 0; i < nr_reqs; i++)
125 xb_write(xpdd, req[i].data, req[i].len);
127 KeWaitForSingleObject(&xpdd->xb_request_complete_event, Executive, KernelMode, FALSE, NULL);
128 reply = xpdd->xb_reply;
129 xpdd->xb_reply = NULL;
130 ExReleaseFastMutex(&xpdd->xb_request_mutex);
132 //FUNCTION_EXIT();
134 return reply;
135 }
137 /* takes and releases xb_request_mutex */
138 struct xsd_sockmsg *
139 XenBus_Raw(
140 PXENPCI_DEVICE_DATA xpdd,
141 struct xsd_sockmsg *msg)
142 {
143 struct xsd_sockmsg *reply;
145 //FUNCTION_ENTER();
147 ExAcquireFastMutex(&xpdd->xb_request_mutex);
148 xb_write(xpdd, msg, sizeof(struct xsd_sockmsg) + msg->len);
149 KeWaitForSingleObject(&xpdd->xb_request_complete_event, Executive, KernelMode, FALSE, NULL);
150 reply = xpdd->xb_reply;
151 xpdd->xb_reply = NULL;
152 ExReleaseFastMutex(&xpdd->xb_request_mutex);
154 //FUNCTION_EXIT();
156 return reply;
157 }
159 /* Called at PASSIVE_LEVEL */
160 char *
161 XenBus_Read(
162 PVOID Context,
163 xenbus_transaction_t xbt,
164 char *path,
165 char **value)
166 {
167 PXENPCI_DEVICE_DATA xpdd = Context;
168 struct write_req req[] = { {path, (ULONG)strlen(path) + 1} };
169 struct xsd_sockmsg *rep;
170 char *res;
171 char *msg;
173 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
175 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
177 rep = xenbus_format_msg_reply(xpdd, XS_READ, xbt, req, ARRAY_SIZE(req));
178 msg = errmsg(rep);
179 if (msg) {
180 *value = NULL;
181 return msg;
182 }
183 res = ExAllocatePoolWithTag(NonPagedPool, rep->len + 1, XENPCI_POOL_TAG);
184 memcpy(res, rep + 1, rep->len);
185 res[rep->len] = 0;
186 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
187 *value = res;
189 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
191 return NULL;
192 }
194 /* Called at PASSIVE_LEVEL */
195 char *
196 XenBus_Write(
197 PVOID Context,
198 xenbus_transaction_t xbt,
199 char *path,
200 char *value)
201 {
202 PXENPCI_DEVICE_DATA xpdd = Context;
203 struct write_req req[] = {
204 {path, (ULONG)strlen(path) + 1},
205 {value, (ULONG)strlen(value)},
206 };
207 struct xsd_sockmsg *rep;
208 char *msg;
210 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
212 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
214 rep = xenbus_format_msg_reply(xpdd, XS_WRITE, xbt, req, ARRAY_SIZE(req));
215 msg = errmsg(rep);
216 if (msg)
217 return msg;
218 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
220 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
222 return NULL;
223 }
225 /* Called at PASSIVE_LEVEL */
226 static VOID
227 XenBus_WatchWorkItemProc(WDFWORKITEM workitem)
228 {
229 WDFDEVICE device = WdfWorkItemGetParentObject(workitem);
230 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
231 xsd_sockmsg_t *msg;
232 PCHAR path;
233 int index;
234 PXENBUS_WATCH_ENTRY entry;
236 //FUNCTION_ENTER();
237 msg = WdfObjectGetTypedContext(workitem, xsd_sockmsg_t);
238 path = (PCHAR)msg + sizeof(xsd_sockmsg_t);
239 index = atoi(path + strlen(path) + 1);
240 ExAcquireFastMutex(&xpdd->xb_watch_mutex);
241 entry = &xpdd->XenBus_WatchEntries[index];
242 if (!entry->Active || !entry->ServiceRoutine)
243 {
244 KdPrint((__DRIVER_NAME " No watch for index %d\n", index));
245 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
246 WdfObjectDelete(workitem);
247 return;
248 }
249 entry->Count++;
250 entry->ServiceRoutine(path, entry->ServiceContext);
251 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
252 WdfObjectDelete(workitem);
253 //FUNCTION_ENTER();
254 }
256 /* Called at DISPATCH_LEVEL */
257 static VOID
258 XenBus_Dpc(PVOID ServiceContext)
259 {
260 NTSTATUS status;
261 PXENPCI_DEVICE_DATA xpdd = ServiceContext;
262 xsd_sockmsg_t msg;
263 WDF_WORKITEM_CONFIG workitem_config;
264 WDF_OBJECT_ATTRIBUTES workitem_attributes;
265 WDFWORKITEM workitem;
267 //FUNCTION_ENTER();
269 KeAcquireSpinLockAtDpcLevel(&xpdd->xb_ring_spinlock);
271 //KdPrint((__DRIVER_NAME " rsp_prod = %d, rsp_cons = %d\n", xpdd->xen_store_interface->rsp_prod, xpdd->xen_store_interface->rsp_cons));
272 while (xpdd->xen_store_interface->rsp_prod != xpdd->xen_store_interface->rsp_cons)
273 {
274 if (xpdd->xen_store_interface->rsp_prod - xpdd->xen_store_interface->rsp_cons < sizeof(msg))
275 {
276 KdPrint((__DRIVER_NAME " +++ Message incomplete (not even a full header)\n"));
277 break;
278 }
279 KeMemoryBarrier();
280 memcpy_from_ring(xpdd->xen_store_interface->rsp, &msg,
281 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons), sizeof(msg));
282 if (xpdd->xen_store_interface->rsp_prod - xpdd->xen_store_interface->rsp_cons < sizeof(msg) + msg.len)
283 {
284 //KdPrint((__DRIVER_NAME " +++ Message incomplete (header but not full body)\n"));
285 break;
286 }
288 if (msg.type != XS_WATCH_EVENT)
289 {
290 /* process reply - only ever one outstanding */
291 xpdd->xb_reply = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
292 memcpy_from_ring(xpdd->xen_store_interface->rsp,
293 xpdd->xb_reply,
294 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons),
295 msg.len + sizeof(msg));
296 xpdd->xen_store_interface->rsp_cons += msg.len + sizeof(msg);
297 KeSetEvent(&xpdd->xb_request_complete_event, IO_NO_INCREMENT, FALSE);
298 }
299 else
300 {
301 /* process watch */
302 WDF_WORKITEM_CONFIG_INIT(&workitem_config, XenBus_WatchWorkItemProc);
303 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&workitem_attributes, xsd_sockmsg_t);
304 workitem_attributes.ParentObject = xpdd->wdf_device;
305 workitem_attributes.ContextSizeOverride = sizeof(msg) + msg.len;
306 status = WdfWorkItemCreate(&workitem_config, &workitem_attributes, &workitem);
307 if (!NT_SUCCESS(status))
308 {
309 KdPrint((__DRIVER_NAME " Failed to create work item for watch\n"));
310 xpdd->xen_store_interface->rsp_cons += msg.len + sizeof(msg);
311 continue;
312 }
313 memcpy_from_ring(xpdd->xen_store_interface->rsp,
314 WdfObjectGetTypedContext(workitem, xsd_sockmsg_t),
315 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons), msg.len + sizeof(msg));
316 xpdd->xen_store_interface->rsp_cons += msg.len + sizeof(msg);
317 WdfWorkItemEnqueue(workitem);
318 }
319 }
320 KeReleaseSpinLockFromDpcLevel(&xpdd->xb_ring_spinlock);
322 //FUNCTION_EXIT();
323 }
325 static NTSTATUS
326 XenBus_Connect(PXENPCI_DEVICE_DATA xpdd)
327 {
328 PHYSICAL_ADDRESS pa_xen_store_interface;
329 xen_ulong_t xen_store_mfn;
331 xpdd->xen_store_evtchn = (evtchn_port_t)hvm_get_parameter(xpdd, HVM_PARAM_STORE_EVTCHN);
332 xen_store_mfn = (xen_ulong_t)hvm_get_parameter(xpdd, HVM_PARAM_STORE_PFN);
333 pa_xen_store_interface.QuadPart = (ULONGLONG)xen_store_mfn << PAGE_SHIFT;
334 xpdd->xen_store_interface = MmMapIoSpace(pa_xen_store_interface, PAGE_SIZE, MmNonCached);
336 EvtChn_BindDpc(xpdd, xpdd->xen_store_evtchn, XenBus_Dpc, xpdd);
338 return STATUS_SUCCESS;
339 }
341 static NTSTATUS
342 XenBus_Disconnect(PXENPCI_DEVICE_DATA xpdd)
343 {
344 EvtChn_Unbind(xpdd, xpdd->xen_store_evtchn);
346 MmUnmapIoSpace(xpdd->xen_store_interface, PAGE_SIZE);
348 return STATUS_SUCCESS;
349 }
351 NTSTATUS
352 XenBus_Init(PXENPCI_DEVICE_DATA xpdd)
353 {
354 NTSTATUS status;
355 int i;
357 FUNCTION_ENTER();
359 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
361 KeInitializeSpinLock(&xpdd->xb_ring_spinlock);
362 ExInitializeFastMutex(&xpdd->xb_request_mutex);
363 ExInitializeFastMutex(&xpdd->xb_watch_mutex);
365 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
366 {
367 xpdd->XenBus_WatchEntries[i].Active = 0;
368 }
370 KeInitializeEvent(&xpdd->xb_request_complete_event, SynchronizationEvent, FALSE);
372 status = XenBus_Connect(xpdd);
373 if (!NT_SUCCESS(status))
374 {
375 return status;
376 }
378 FUNCTION_EXIT();
380 return STATUS_SUCCESS;
381 }
383 char *
384 XenBus_SendRemWatch(
385 PVOID context,
386 xenbus_transaction_t xbt,
387 char *path,
388 int index)
389 {
390 struct xsd_sockmsg *rep;
391 char *msg;
392 char Token[20];
393 struct write_req req[2];
395 req[0].data = path;
396 req[0].len = (ULONG)strlen(path) + 1;
398 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", index);
399 req[1].data = Token;
400 req[1].len = (ULONG)strlen(Token) + 1;
402 rep = xenbus_format_msg_reply(context, XS_UNWATCH, xbt, req, ARRAY_SIZE(req));
404 msg = errmsg(rep);
405 if (msg)
406 return msg;
408 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
410 return NULL;
411 }
413 NTSTATUS
414 XenBus_Halt(PXENPCI_DEVICE_DATA xpdd)
415 {
416 int i;
418 FUNCTION_ENTER();
420 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
422 /* we need to remove the watches as a watch firing could lead to a XenBus_Read/Write/Printf */
423 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
424 {
425 if (xpdd->XenBus_WatchEntries[i].Active)
426 {
427 xpdd->XenBus_WatchEntries[i].Active = 0;
428 XenBus_SendRemWatch(xpdd, XBT_NIL, xpdd->XenBus_WatchEntries[i].Path, i);
429 }
430 }
432 XenBus_Disconnect(xpdd);
434 FUNCTION_EXIT();
436 return STATUS_SUCCESS;
437 }
439 char *
440 XenBus_List(
441 PVOID Context,
442 xenbus_transaction_t xbt,
443 char *pre,
444 char ***contents)
445 {
446 PXENPCI_DEVICE_DATA xpdd = Context;
447 struct xsd_sockmsg *reply, *repmsg;
448 struct write_req req[] = { { pre, (ULONG)strlen(pre)+1 } };
449 ULONG nr_elems, x, i;
450 char **res;
451 char *msg;
453 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
455 repmsg = xenbus_format_msg_reply(xpdd, XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
456 msg = errmsg(repmsg);
457 if (msg)
458 {
459 *contents = NULL;
460 return msg;
461 }
462 reply = repmsg + 1;
463 for (x = nr_elems = 0; x < repmsg->len; x++)
464 {
465 nr_elems += (((char *)reply)[x] == 0);
466 }
467 res = ExAllocatePoolWithTag(NonPagedPool, sizeof(res[0]) * (nr_elems + 1),
468 XENPCI_POOL_TAG);
469 for (x = i = 0; i < nr_elems; i++)
470 {
471 int l = (int)strlen((char *)reply + x);
472 res[i] = ExAllocatePoolWithTag(NonPagedPool, l + 1, XENPCI_POOL_TAG);
473 memcpy(res[i], (char *)reply + x, l + 1);
474 x += l + 1;
475 }
476 res[i] = NULL;
477 ExFreePoolWithTag(repmsg, XENPCI_POOL_TAG);
478 *contents = res;
480 return NULL;
481 }
483 /* Called at PASSIVE_LEVEL */
484 static char *
485 XenBus_SendAddWatch(
486 PVOID Context,
487 xenbus_transaction_t xbt,
488 char *Path,
489 int slot)
490 {
491 PXENPCI_DEVICE_DATA xpdd = Context;
492 struct xsd_sockmsg *rep;
493 char *msg;
494 char Token[20];
495 struct write_req req[2];
497 req[0].data = Path;
498 req[0].len = (ULONG)strlen(Path) + 1;
500 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", slot);
501 req[1].data = Token;
502 req[1].len = (ULONG)strlen(Token) + 1;
504 rep = xenbus_format_msg_reply(xpdd, XS_WATCH, xbt, req, ARRAY_SIZE(req));
506 msg = errmsg(rep);
507 if (!msg)
508 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
510 return msg;
511 }
513 /* called at PASSIVE_LEVEL */
514 NTSTATUS
515 XenBus_Suspend(PXENPCI_DEVICE_DATA xpdd)
516 {
517 int i;
519 /* we need to remove the watches as a watch firing could lead to a XenBus_Read/Write/Printf */
520 for (i = 0; i < MAX_WATCH_ENTRIES; i++) {
521 if (xpdd->XenBus_WatchEntries[i].Active)
522 XenBus_SendRemWatch(xpdd, XBT_NIL, xpdd->XenBus_WatchEntries[i].Path, i);
523 }
524 XenBus_Disconnect(xpdd);
526 return STATUS_SUCCESS;
527 }
529 /* called at PASSIVE_LEVEL */
530 NTSTATUS
531 XenBus_Resume(PXENPCI_DEVICE_DATA xpdd)
532 {
533 NTSTATUS status;
534 int i;
536 FUNCTION_ENTER();
538 status = XenBus_Connect(xpdd);
539 if (!NT_SUCCESS(status))
540 {
541 return status;
542 }
544 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
545 {
546 if (xpdd->XenBus_WatchEntries[i].Active)
547 {
548 //KdPrint((__DRIVER_NAME " Adding watch for path = %s\n", xpdd->XenBus_WatchEntries[i].Path));
549 XenBus_SendAddWatch(xpdd, XBT_NIL, xpdd->XenBus_WatchEntries[i].Path, i);
550 }
551 }
552 FUNCTION_EXIT();
554 return STATUS_SUCCESS;
555 }
557 char *
558 XenBus_AddWatch(
559 PVOID Context,
560 xenbus_transaction_t xbt,
561 char *Path,
562 PXENBUS_WATCH_CALLBACK ServiceRoutine,
563 PVOID ServiceContext)
564 {
565 PXENPCI_DEVICE_DATA xpdd = Context;
566 char *msg;
567 int i;
568 PXENBUS_WATCH_ENTRY w_entry;
570 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
572 ASSERT(strlen(Path) < ARRAY_SIZE(w_entry->Path));
574 ExAcquireFastMutex(&xpdd->xb_watch_mutex);
576 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
577 if (xpdd->XenBus_WatchEntries[i].Active == 0)
578 break;
580 if (i == MAX_WATCH_ENTRIES)
581 {
582 KdPrint((__DRIVER_NAME " +++ No more watch slots left\n"));
583 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
584 return NULL;
585 }
587 /* must init watchentry before starting watch */
589 w_entry = &xpdd->XenBus_WatchEntries[i];
590 strncpy(w_entry->Path, Path, ARRAY_SIZE(w_entry->Path));
591 w_entry->ServiceRoutine = ServiceRoutine;
592 w_entry->ServiceContext = ServiceContext;
593 w_entry->Count = 0;
594 w_entry->Active = 1;
596 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
598 msg = XenBus_SendAddWatch(xpdd, xbt, Path, i);
600 if (msg)
601 {
602 xpdd->XenBus_WatchEntries[i].Active = 0;
603 return msg;
604 }
606 return NULL;
607 }
609 char *
610 XenBus_RemWatch(
611 PVOID Context,
612 xenbus_transaction_t xbt,
613 char *Path,
614 PXENBUS_WATCH_CALLBACK ServiceRoutine,
615 PVOID ServiceContext)
616 {
617 PXENPCI_DEVICE_DATA xpdd = Context;
618 char *msg;
619 int i;
621 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
623 ExAcquireFastMutex(&xpdd->xb_watch_mutex);
625 // check that Path < 128 chars
627 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
628 {
629 if (xpdd->XenBus_WatchEntries[i].Active
630 && !strcmp(xpdd->XenBus_WatchEntries[i].Path, Path)
631 && xpdd->XenBus_WatchEntries[i].ServiceRoutine == ServiceRoutine
632 && xpdd->XenBus_WatchEntries[i].ServiceContext == ServiceContext)
633 {
634 KdPrint((__DRIVER_NAME " Match\n"));
635 break;
636 }
637 }
639 if (i == MAX_WATCH_ENTRIES)
640 {
641 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
642 KdPrint((__DRIVER_NAME " Watch not set - can't remove\n"));
643 return NULL;
644 }
646 xpdd->XenBus_WatchEntries[i].Active = 0;
647 xpdd->XenBus_WatchEntries[i].Path[0] = 0;
649 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
651 msg = XenBus_SendRemWatch(Context, xbt, Path, i);
653 return msg;
654 }
656 char *
657 XenBus_StartTransaction(PVOID Context, xenbus_transaction_t *xbt)
658 {
659 PXENPCI_DEVICE_DATA xpdd = Context;
660 /* xenstored becomes angry if you send a length 0 message, so just
661 shove a nul terminator on the end */
662 struct write_req req = { "", 1};
663 struct xsd_sockmsg *rep;
664 char *err;
666 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
668 rep = xenbus_format_msg_reply(xpdd, XS_TRANSACTION_START, 0, &req, 1);
669 err = errmsg(rep);
670 if (err)
671 return err;
672 *xbt = atoi((char *)(rep + 1));
673 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
675 return NULL;
676 }
678 char *
679 XenBus_EndTransaction(
680 PVOID Context,
681 xenbus_transaction_t t,
682 int abort,
683 int *retry)
684 {
685 PXENPCI_DEVICE_DATA xpdd = Context;
686 struct xsd_sockmsg *rep;
687 struct write_req req;
688 char *err;
690 *retry = 0;
692 req.data = abort ? "F" : "T";
693 req.len = 2;
694 rep = xenbus_format_msg_reply(xpdd, XS_TRANSACTION_END, t, &req, 1);
695 err = errmsg(rep);
696 if (err) {
697 if (!strcmp(err, "EAGAIN")) {
698 *retry = 1;
699 ExFreePoolWithTag(err, XENPCI_POOL_TAG);
700 return NULL;
701 } else {
702 return err;
703 }
704 }
705 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
707 return NULL;
708 }
710 char *
711 XenBus_Printf(
712 PVOID Context,
713 xenbus_transaction_t xbt,
714 char *path,
715 char *fmt,
716 ...)
717 {
718 PXENPCI_DEVICE_DATA xpdd = Context;
719 va_list ap;
720 char buf[512];
721 char *retval;
723 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
725 va_start(ap, fmt);
726 RtlStringCbVPrintfA(buf, ARRAY_SIZE(buf), fmt, ap);
727 va_end(ap);
728 retval = XenBus_Write(xpdd, xbt, path, buf);
730 return retval;
731 }