win-pvdrivers

view xenpci/xenbus.c @ 641:4bb8c4fc6fa5

Added tag 0.10.0.91 for changeset 40c8aada72eb
author James Harper <james.harper@bendigoit.com.au>
date Sun Aug 23 18:00:14 2009 +1000 (2009-08-23)
parents 51012d703b75
children 84e37987cdbc
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 //KdPrint((__DRIVER_NAME " rsp_prod = %d, rsp_cons = %d\n", xpdd->xen_store_interface->rsp_prod, xpdd->xen_store_interface->rsp_cons));
270 while (xpdd->xen_store_interface->rsp_prod != xpdd->xen_store_interface->rsp_cons)
271 {
272 if (xpdd->xen_store_interface->rsp_prod - xpdd->xen_store_interface->rsp_cons < sizeof(msg))
273 {
274 KdPrint((__DRIVER_NAME " +++ Message incomplete (not even a full header)\n"));
275 break;
276 }
277 KeMemoryBarrier();
278 memcpy_from_ring(xpdd->xen_store_interface->rsp, &msg,
279 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons), sizeof(msg));
280 if (xpdd->xen_store_interface->rsp_prod - xpdd->xen_store_interface->rsp_cons < sizeof(msg) + msg.len)
281 {
282 //KdPrint((__DRIVER_NAME " +++ Message incomplete (header but not full body)\n"));
283 break;
284 }
286 if (msg.type != XS_WATCH_EVENT)
287 {
288 /* process reply - only ever one outstanding */
289 xpdd->xb_reply = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
290 memcpy_from_ring(xpdd->xen_store_interface->rsp,
291 xpdd->xb_reply,
292 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons),
293 msg.len + sizeof(msg));
294 xpdd->xen_store_interface->rsp_cons += msg.len + sizeof(msg);
295 KeSetEvent(&xpdd->xb_request_complete_event, IO_NO_INCREMENT, FALSE);
296 }
297 else
298 {
299 /* process watch */
300 WDF_WORKITEM_CONFIG_INIT(&workitem_config, XenBus_WatchWorkItemProc);
301 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&workitem_attributes, xsd_sockmsg_t);
302 workitem_attributes.ParentObject = xpdd->wdf_device;
303 workitem_attributes.ContextSizeOverride = sizeof(msg) + msg.len;
304 status = WdfWorkItemCreate(&workitem_config, &workitem_attributes, &workitem);
305 if (!NT_SUCCESS(status))
306 {
307 KdPrint((__DRIVER_NAME " Failed to create work item for watch\n"));
308 xpdd->xen_store_interface->rsp_cons += msg.len + sizeof(msg);
309 continue;
310 }
311 memcpy_from_ring(xpdd->xen_store_interface->rsp,
312 WdfObjectGetTypedContext(workitem, xsd_sockmsg_t),
313 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons), msg.len + sizeof(msg));
314 xpdd->xen_store_interface->rsp_cons += msg.len + sizeof(msg);
315 WdfWorkItemEnqueue(workitem);
316 }
317 }
319 //FUNCTION_EXIT();
320 }
322 static NTSTATUS
323 XenBus_Connect(PXENPCI_DEVICE_DATA xpdd)
324 {
325 PHYSICAL_ADDRESS pa_xen_store_interface;
326 xen_ulong_t xen_store_mfn;
328 xpdd->xen_store_evtchn = (evtchn_port_t)hvm_get_parameter(xpdd, HVM_PARAM_STORE_EVTCHN);
329 xen_store_mfn = (xen_ulong_t)hvm_get_parameter(xpdd, HVM_PARAM_STORE_PFN);
330 pa_xen_store_interface.QuadPart = (ULONGLONG)xen_store_mfn << PAGE_SHIFT;
331 xpdd->xen_store_interface = MmMapIoSpace(pa_xen_store_interface, PAGE_SIZE, MmNonCached);
333 EvtChn_BindDpc(xpdd, xpdd->xen_store_evtchn, XenBus_Dpc, xpdd);
335 return STATUS_SUCCESS;
336 }
338 static NTSTATUS
339 XenBus_Disconnect(PXENPCI_DEVICE_DATA xpdd)
340 {
341 EvtChn_Unbind(xpdd, xpdd->xen_store_evtchn);
343 MmUnmapIoSpace(xpdd->xen_store_interface, PAGE_SIZE);
345 return STATUS_SUCCESS;
346 }
348 NTSTATUS
349 XenBus_Init(PXENPCI_DEVICE_DATA xpdd)
350 {
351 NTSTATUS status;
352 int i;
354 FUNCTION_ENTER();
356 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
358 ExInitializeFastMutex(&xpdd->xb_request_mutex);
359 ExInitializeFastMutex(&xpdd->xb_watch_mutex);
361 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
362 {
363 xpdd->XenBus_WatchEntries[i].Active = 0;
364 }
366 KeInitializeEvent(&xpdd->xb_request_complete_event, SynchronizationEvent, FALSE);
368 status = XenBus_Connect(xpdd);
369 if (!NT_SUCCESS(status))
370 {
371 return status;
372 }
374 FUNCTION_EXIT();
376 return STATUS_SUCCESS;
377 }
379 char *
380 XenBus_SendRemWatch(
381 PVOID context,
382 xenbus_transaction_t xbt,
383 char *path,
384 int index)
385 {
386 struct xsd_sockmsg *rep;
387 char *msg;
388 char Token[20];
389 struct write_req req[2];
391 req[0].data = path;
392 req[0].len = (ULONG)strlen(path) + 1;
394 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", index);
395 req[1].data = Token;
396 req[1].len = (ULONG)strlen(Token) + 1;
398 rep = xenbus_format_msg_reply(context, XS_UNWATCH, xbt, req, ARRAY_SIZE(req));
400 msg = errmsg(rep);
401 if (msg)
402 return msg;
404 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
406 return NULL;
407 }
409 NTSTATUS
410 XenBus_Halt(PXENPCI_DEVICE_DATA xpdd)
411 {
412 int i;
414 FUNCTION_ENTER();
416 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
418 /* we need to remove the watches as a watch firing could lead to a XenBus_Read/Write/Printf */
419 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
420 {
421 if (xpdd->XenBus_WatchEntries[i].Active)
422 {
423 xpdd->XenBus_WatchEntries[i].Active = 0;
424 XenBus_SendRemWatch(xpdd, XBT_NIL, xpdd->XenBus_WatchEntries[i].Path, i);
425 }
426 }
428 XenBus_Disconnect(xpdd);
430 FUNCTION_EXIT();
432 return STATUS_SUCCESS;
433 }
435 char *
436 XenBus_List(
437 PVOID Context,
438 xenbus_transaction_t xbt,
439 char *pre,
440 char ***contents)
441 {
442 PXENPCI_DEVICE_DATA xpdd = Context;
443 struct xsd_sockmsg *reply, *repmsg;
444 struct write_req req[] = { { pre, (ULONG)strlen(pre)+1 } };
445 ULONG nr_elems, x, i;
446 char **res;
447 char *msg;
449 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
451 repmsg = xenbus_format_msg_reply(xpdd, XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
452 msg = errmsg(repmsg);
453 if (msg)
454 {
455 *contents = NULL;
456 return msg;
457 }
458 reply = repmsg + 1;
459 for (x = nr_elems = 0; x < repmsg->len; x++)
460 {
461 nr_elems += (((char *)reply)[x] == 0);
462 }
463 res = ExAllocatePoolWithTag(NonPagedPool, sizeof(res[0]) * (nr_elems + 1),
464 XENPCI_POOL_TAG);
465 for (x = i = 0; i < nr_elems; i++)
466 {
467 int l = (int)strlen((char *)reply + x);
468 res[i] = ExAllocatePoolWithTag(NonPagedPool, l + 1, XENPCI_POOL_TAG);
469 memcpy(res[i], (char *)reply + x, l + 1);
470 x += l + 1;
471 }
472 res[i] = NULL;
473 ExFreePoolWithTag(repmsg, XENPCI_POOL_TAG);
474 *contents = res;
476 return NULL;
477 }
479 /* Called at PASSIVE_LEVEL */
480 static char *
481 XenBus_SendAddWatch(
482 PVOID Context,
483 xenbus_transaction_t xbt,
484 char *Path,
485 int slot)
486 {
487 PXENPCI_DEVICE_DATA xpdd = Context;
488 struct xsd_sockmsg *rep;
489 char *msg;
490 char Token[20];
491 struct write_req req[2];
493 req[0].data = Path;
494 req[0].len = (ULONG)strlen(Path) + 1;
496 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", slot);
497 req[1].data = Token;
498 req[1].len = (ULONG)strlen(Token) + 1;
500 rep = xenbus_format_msg_reply(xpdd, XS_WATCH, xbt, req, ARRAY_SIZE(req));
502 msg = errmsg(rep);
503 if (!msg)
504 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
506 return msg;
507 }
509 /* called at PASSIVE_LEVEL */
510 NTSTATUS
511 XenBus_Suspend(PXENPCI_DEVICE_DATA xpdd)
512 {
513 int i;
515 /* we need to remove the watches as a watch firing could lead to a XenBus_Read/Write/Printf */
516 for (i = 0; i < MAX_WATCH_ENTRIES; i++) {
517 if (xpdd->XenBus_WatchEntries[i].Active)
518 XenBus_SendRemWatch(xpdd, XBT_NIL, xpdd->XenBus_WatchEntries[i].Path, i);
519 }
520 XenBus_Disconnect(xpdd);
522 return STATUS_SUCCESS;
523 }
525 /* called at PASSIVE_LEVEL */
526 NTSTATUS
527 XenBus_Resume(PXENPCI_DEVICE_DATA xpdd)
528 {
529 NTSTATUS status;
530 int i;
532 FUNCTION_ENTER();
534 status = XenBus_Connect(xpdd);
535 if (!NT_SUCCESS(status))
536 {
537 return status;
538 }
540 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
541 {
542 if (xpdd->XenBus_WatchEntries[i].Active)
543 {
544 //KdPrint((__DRIVER_NAME " Adding watch for path = %s\n", xpdd->XenBus_WatchEntries[i].Path));
545 XenBus_SendAddWatch(xpdd, XBT_NIL, xpdd->XenBus_WatchEntries[i].Path, i);
546 }
547 }
548 FUNCTION_EXIT();
550 return STATUS_SUCCESS;
551 }
553 char *
554 XenBus_AddWatch(
555 PVOID Context,
556 xenbus_transaction_t xbt,
557 char *Path,
558 PXENBUS_WATCH_CALLBACK ServiceRoutine,
559 PVOID ServiceContext)
560 {
561 PXENPCI_DEVICE_DATA xpdd = Context;
562 char *msg;
563 int i;
564 PXENBUS_WATCH_ENTRY w_entry;
566 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
568 ASSERT(strlen(Path) < ARRAY_SIZE(w_entry->Path));
570 ExAcquireFastMutex(&xpdd->xb_watch_mutex);
572 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
573 if (xpdd->XenBus_WatchEntries[i].Active == 0)
574 break;
576 if (i == MAX_WATCH_ENTRIES)
577 {
578 KdPrint((__DRIVER_NAME " +++ No more watch slots left\n"));
579 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
580 return NULL;
581 }
583 /* must init watchentry before starting watch */
585 w_entry = &xpdd->XenBus_WatchEntries[i];
586 strncpy(w_entry->Path, Path, ARRAY_SIZE(w_entry->Path));
587 w_entry->ServiceRoutine = ServiceRoutine;
588 w_entry->ServiceContext = ServiceContext;
589 w_entry->Count = 0;
590 w_entry->Active = 1;
592 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
594 msg = XenBus_SendAddWatch(xpdd, xbt, Path, i);
596 if (msg)
597 {
598 xpdd->XenBus_WatchEntries[i].Active = 0;
599 return msg;
600 }
602 return NULL;
603 }
605 char *
606 XenBus_RemWatch(
607 PVOID Context,
608 xenbus_transaction_t xbt,
609 char *Path,
610 PXENBUS_WATCH_CALLBACK ServiceRoutine,
611 PVOID ServiceContext)
612 {
613 PXENPCI_DEVICE_DATA xpdd = Context;
614 char *msg;
615 int i;
617 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
619 ExAcquireFastMutex(&xpdd->xb_watch_mutex);
621 // check that Path < 128 chars
623 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
624 {
625 if (xpdd->XenBus_WatchEntries[i].Active
626 && !strcmp(xpdd->XenBus_WatchEntries[i].Path, Path)
627 && xpdd->XenBus_WatchEntries[i].ServiceRoutine == ServiceRoutine
628 && xpdd->XenBus_WatchEntries[i].ServiceContext == ServiceContext)
629 {
630 KdPrint((__DRIVER_NAME " Match\n"));
631 break;
632 }
633 }
635 if (i == MAX_WATCH_ENTRIES)
636 {
637 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
638 KdPrint((__DRIVER_NAME " Watch not set - can't remove\n"));
639 return NULL;
640 }
642 xpdd->XenBus_WatchEntries[i].Active = 0;
643 xpdd->XenBus_WatchEntries[i].Path[0] = 0;
645 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
647 msg = XenBus_SendRemWatch(Context, xbt, Path, i);
649 return msg;
650 }
652 char *
653 XenBus_StartTransaction(PVOID Context, xenbus_transaction_t *xbt)
654 {
655 PXENPCI_DEVICE_DATA xpdd = Context;
656 /* xenstored becomes angry if you send a length 0 message, so just
657 shove a nul terminator on the end */
658 struct write_req req = { "", 1};
659 struct xsd_sockmsg *rep;
660 char *err;
662 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
664 rep = xenbus_format_msg_reply(xpdd, XS_TRANSACTION_START, 0, &req, 1);
665 err = errmsg(rep);
666 if (err)
667 return err;
668 *xbt = atoi((char *)(rep + 1));
669 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
671 return NULL;
672 }
674 char *
675 XenBus_EndTransaction(
676 PVOID Context,
677 xenbus_transaction_t t,
678 int abort,
679 int *retry)
680 {
681 PXENPCI_DEVICE_DATA xpdd = Context;
682 struct xsd_sockmsg *rep;
683 struct write_req req;
684 char *err;
686 *retry = 0;
688 req.data = abort ? "F" : "T";
689 req.len = 2;
690 rep = xenbus_format_msg_reply(xpdd, XS_TRANSACTION_END, t, &req, 1);
691 err = errmsg(rep);
692 if (err) {
693 if (!strcmp(err, "EAGAIN")) {
694 *retry = 1;
695 ExFreePoolWithTag(err, XENPCI_POOL_TAG);
696 return NULL;
697 } else {
698 return err;
699 }
700 }
701 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
703 return NULL;
704 }
706 char *
707 XenBus_Printf(
708 PVOID Context,
709 xenbus_transaction_t xbt,
710 char *path,
711 char *fmt,
712 ...)
713 {
714 PXENPCI_DEVICE_DATA xpdd = Context;
715 va_list ap;
716 char buf[512];
717 char *retval;
719 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
721 va_start(ap, fmt);
722 RtlStringCbVPrintfA(buf, ARRAY_SIZE(buf), fmt, ap);
723 va_end(ap);
724 retval = XenBus_Write(xpdd, xbt, path, buf);
726 return retval;
727 }