win-pvdrivers

view xenpci/xenbus.c @ 716:5bdb7251370c

Use WinDDK 7600.16385.0
Update userspace binaries to build for XP not 2K (2K not supported in new DDK)
Fix lots of PREfast errors
Make build and installer less dependant on DDK version
Fix IRQL crash in DpgPrint hooking
author James Harper <james.harper@bendigoit.com.au>
date Tue Dec 22 22:44:07 2009 +1100 (2009-12-22)
parents 4baaaaa23235
children 467005e7f509
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 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->xen_store_evtchn);
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 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 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
215 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
217 rep = xenbus_format_msg_reply(xpdd, XS_WRITE, xbt, req, ARRAY_SIZE(req));
218 msg = errmsg(rep);
219 if (msg)
220 return msg;
221 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
223 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
225 return NULL;
226 }
228 /* Called at PASSIVE_LEVEL */
229 static VOID
230 XenBus_WatchWorkItemProc(WDFWORKITEM workitem)
231 {
232 WDFDEVICE device = WdfWorkItemGetParentObject(workitem);
233 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
234 xsd_sockmsg_t *msg;
235 PCHAR path;
236 int index;
237 PXENBUS_WATCH_ENTRY entry;
239 //FUNCTION_ENTER();
240 msg = WdfObjectGetTypedContext(workitem, xsd_sockmsg_t);
241 path = (PCHAR)msg + sizeof(xsd_sockmsg_t);
242 index = atoi(path + strlen(path) + 1);
243 if (index < 0 || index >= MAX_WATCH_ENTRIES)
244 {
245 KdPrint((__DRIVER_NAME " Watch index %d out of range\n", index));
246 WdfObjectDelete(workitem);
247 return;
248 }
249 ExAcquireFastMutex(&xpdd->xb_watch_mutex);
250 entry = &xpdd->XenBus_WatchEntries[index];
251 if (!entry->Active || !entry->ServiceRoutine)
252 {
253 KdPrint((__DRIVER_NAME " No watch for index %d\n", index));
254 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
255 WdfObjectDelete(workitem);
256 return;
257 }
258 entry->Count++;
259 entry->ServiceRoutine(path, entry->ServiceContext);
260 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
261 WdfObjectDelete(workitem);
262 //FUNCTION_ENTER();
263 }
265 /* Called at DISPATCH_LEVEL */
266 static VOID
267 XenBus_Dpc(PVOID ServiceContext)
268 {
269 NTSTATUS status;
270 PXENPCI_DEVICE_DATA xpdd = ServiceContext;
271 xsd_sockmsg_t msg;
272 ULONG msg_len;
273 WDF_WORKITEM_CONFIG workitem_config;
274 WDF_OBJECT_ATTRIBUTES workitem_attributes;
275 WDFWORKITEM workitem;
277 //FUNCTION_ENTER();
279 KeAcquireSpinLockAtDpcLevel(&xpdd->xb_ring_spinlock);
281 while (xpdd->xen_store_interface->rsp_prod != xpdd->xen_store_interface->rsp_cons)
282 {
283 if (!xpdd->xb_msg)
284 {
285 if (xpdd->xen_store_interface->rsp_prod - xpdd->xen_store_interface->rsp_cons < sizeof(xsd_sockmsg_t))
286 {
287 KdPrint((__DRIVER_NAME " +++ Message incomplete (not even a full header)\n"));
288 break;
289 }
290 KeMemoryBarrier();
291 memcpy_from_ring(xpdd->xen_store_interface->rsp, &msg,
292 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons), sizeof(xsd_sockmsg_t));
293 xpdd->xb_msg = ExAllocatePoolWithTag(NonPagedPool, sizeof(xsd_sockmsg_t) + msg.len, XENPCI_POOL_TAG);
294 memcpy(xpdd->xb_msg, &msg, sizeof(xsd_sockmsg_t));
295 xpdd->xb_msg_offset = sizeof(xsd_sockmsg_t);
296 xpdd->xen_store_interface->rsp_cons += sizeof(xsd_sockmsg_t);
297 }
299 msg_len = min(xpdd->xen_store_interface->rsp_prod - xpdd->xen_store_interface->rsp_cons, sizeof(xsd_sockmsg_t) + xpdd->xb_msg->len - xpdd->xb_msg_offset);
300 KeMemoryBarrier(); /* make sure the data in the ring is valid */
301 ASSERT(xpdd->xb_msg_offset + msg_len <= sizeof(xsd_sockmsg_t) + xpdd->xb_msg->len);
302 memcpy_from_ring(xpdd->xen_store_interface->rsp,
303 (PUCHAR)xpdd->xb_msg + xpdd->xb_msg_offset,
304 MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons),
305 msg_len);
306 xpdd->xen_store_interface->rsp_cons += msg_len;
307 xpdd->xb_msg_offset += msg_len;
309 if (xpdd->xb_msg_offset < sizeof(xsd_sockmsg_t) + xpdd->xb_msg->len)
310 {
311 KdPrint((__DRIVER_NAME " +++ Message incomplete (header but not full body)\n"));
312 EvtChn_Notify(xpdd, xpdd->xen_store_evtchn); /* there is room on the ring now */
313 break;
314 }
316 if (xpdd->xb_msg->type != XS_WATCH_EVENT)
317 {
318 /* process reply - only ever one outstanding */
319 ASSERT(xpdd->xb_reply == NULL);
320 xpdd->xb_reply = xpdd->xb_msg;
321 xpdd->xb_msg = NULL;
322 KeSetEvent(&xpdd->xb_request_complete_event, IO_NO_INCREMENT, FALSE);
323 }
324 else
325 {
326 /* process watch */
327 WDF_WORKITEM_CONFIG_INIT(&workitem_config, XenBus_WatchWorkItemProc);
328 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&workitem_attributes, xsd_sockmsg_t);
329 workitem_attributes.ParentObject = xpdd->wdf_device;
330 workitem_attributes.ContextSizeOverride = xpdd->xb_msg_offset;
331 status = WdfWorkItemCreate(&workitem_config, &workitem_attributes, &workitem);
332 if (!NT_SUCCESS(status))
333 {
334 KdPrint((__DRIVER_NAME " Failed to create work item for watch\n"));
335 continue;
336 }
337 memcpy(WdfObjectGetTypedContext(workitem, xsd_sockmsg_t), xpdd->xb_msg, xpdd->xb_msg_offset);
338 xpdd->xb_msg = NULL;
339 WdfWorkItemEnqueue(workitem);
340 }
341 EvtChn_Notify(xpdd, xpdd->xen_store_evtchn); /* there is room on the ring now */
342 }
343 KeReleaseSpinLockFromDpcLevel(&xpdd->xb_ring_spinlock);
345 //FUNCTION_EXIT();
346 }
348 static NTSTATUS
349 XenBus_Connect(PXENPCI_DEVICE_DATA xpdd)
350 {
351 PHYSICAL_ADDRESS pa_xen_store_interface;
352 xen_ulong_t xen_store_mfn;
354 xpdd->xen_store_evtchn = (evtchn_port_t)hvm_get_parameter(xpdd, HVM_PARAM_STORE_EVTCHN);
355 xen_store_mfn = (xen_ulong_t)hvm_get_parameter(xpdd, HVM_PARAM_STORE_PFN);
356 pa_xen_store_interface.QuadPart = (ULONGLONG)xen_store_mfn << PAGE_SHIFT;
357 xpdd->xen_store_interface = MmMapIoSpace(pa_xen_store_interface, PAGE_SIZE, MmNonCached);
359 EvtChn_BindDpc(xpdd, xpdd->xen_store_evtchn, XenBus_Dpc, xpdd);
361 return STATUS_SUCCESS;
362 }
364 static NTSTATUS
365 XenBus_Disconnect(PXENPCI_DEVICE_DATA xpdd)
366 {
367 EvtChn_Unbind(xpdd, xpdd->xen_store_evtchn);
369 MmUnmapIoSpace(xpdd->xen_store_interface, PAGE_SIZE);
371 return STATUS_SUCCESS;
372 }
374 NTSTATUS
375 XenBus_Init(PXENPCI_DEVICE_DATA xpdd)
376 {
377 NTSTATUS status;
378 int i;
380 FUNCTION_ENTER();
382 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
384 KeInitializeSpinLock(&xpdd->xb_ring_spinlock);
385 ExInitializeFastMutex(&xpdd->xb_request_mutex);
386 ExInitializeFastMutex(&xpdd->xb_watch_mutex);
388 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
389 {
390 xpdd->XenBus_WatchEntries[i].Active = 0;
391 }
393 KeInitializeEvent(&xpdd->xb_request_complete_event, SynchronizationEvent, FALSE);
395 status = XenBus_Connect(xpdd);
396 if (!NT_SUCCESS(status))
397 {
398 FUNCTION_EXIT();
399 return status;
400 }
402 FUNCTION_EXIT();
404 return STATUS_SUCCESS;
405 }
407 char *
408 XenBus_SendRemWatch(
409 PVOID context,
410 xenbus_transaction_t xbt,
411 char *path,
412 int index)
413 {
414 struct xsd_sockmsg *rep;
415 char *msg;
416 char Token[20];
417 struct write_req req[2];
419 req[0].data = path;
420 req[0].len = (ULONG)strlen(path) + 1;
422 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", index);
423 req[1].data = Token;
424 req[1].len = (ULONG)strlen(Token) + 1;
426 rep = xenbus_format_msg_reply(context, XS_UNWATCH, xbt, req, ARRAY_SIZE(req));
428 msg = errmsg(rep);
429 if (msg)
430 return msg;
432 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
434 return NULL;
435 }
437 NTSTATUS
438 XenBus_Halt(PXENPCI_DEVICE_DATA xpdd)
439 {
440 int i;
442 FUNCTION_ENTER();
444 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
446 /* we need to remove the watches as a watch firing could lead to a XenBus_Read/Write/Printf */
447 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
448 {
449 if (xpdd->XenBus_WatchEntries[i].Active)
450 {
451 xpdd->XenBus_WatchEntries[i].Active = 0;
452 XenBus_SendRemWatch(xpdd, XBT_NIL, xpdd->XenBus_WatchEntries[i].Path, i);
453 }
454 }
456 XenBus_Disconnect(xpdd);
458 FUNCTION_EXIT();
460 return STATUS_SUCCESS;
461 }
463 char *
464 XenBus_List(
465 PVOID Context,
466 xenbus_transaction_t xbt,
467 char *pre,
468 char ***contents)
469 {
470 PXENPCI_DEVICE_DATA xpdd = Context;
471 struct xsd_sockmsg *reply, *repmsg;
472 struct write_req req[] = { { pre, (ULONG)strlen(pre)+1 } };
473 ULONG nr_elems, x, i;
474 char **res;
475 char *msg;
477 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
479 repmsg = xenbus_format_msg_reply(xpdd, XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
480 msg = errmsg(repmsg);
481 if (msg)
482 {
483 *contents = NULL;
484 return msg;
485 }
486 reply = repmsg + 1;
487 for (x = nr_elems = 0; x < repmsg->len; x++)
488 {
489 nr_elems += (((char *)reply)[x] == 0);
490 }
491 res = ExAllocatePoolWithTag(NonPagedPool, sizeof(res[0]) * (nr_elems + 1),
492 XENPCI_POOL_TAG);
493 for (x = i = 0; i < nr_elems; i++)
494 {
495 int l = (int)strlen((char *)reply + x);
496 res[i] = ExAllocatePoolWithTag(NonPagedPool, l + 1, XENPCI_POOL_TAG);
497 memcpy(res[i], (char *)reply + x, l + 1);
498 x += l + 1;
499 }
500 res[i] = NULL;
501 ExFreePoolWithTag(repmsg, XENPCI_POOL_TAG);
502 *contents = res;
504 return NULL;
505 }
507 /* Called at PASSIVE_LEVEL */
508 static char *
509 XenBus_SendAddWatch(
510 PVOID Context,
511 xenbus_transaction_t xbt,
512 char *Path,
513 int slot)
514 {
515 PXENPCI_DEVICE_DATA xpdd = Context;
516 struct xsd_sockmsg *rep;
517 char *msg;
518 char Token[20];
519 struct write_req req[2];
521 req[0].data = Path;
522 req[0].len = (ULONG)strlen(Path) + 1;
524 RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", slot);
525 req[1].data = Token;
526 req[1].len = (ULONG)strlen(Token) + 1;
528 rep = xenbus_format_msg_reply(xpdd, XS_WATCH, xbt, req, ARRAY_SIZE(req));
530 msg = errmsg(rep);
531 if (!msg)
532 ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
534 return msg;
535 }
537 /* called at PASSIVE_LEVEL */
538 NTSTATUS
539 XenBus_Suspend(PXENPCI_DEVICE_DATA xpdd)
540 {
541 int i;
543 /* we need to remove the watches as a watch firing could lead to a XenBus_Read/Write/Printf */
544 for (i = 0; i < MAX_WATCH_ENTRIES; i++) {
545 if (xpdd->XenBus_WatchEntries[i].Active)
546 XenBus_SendRemWatch(xpdd, XBT_NIL, xpdd->XenBus_WatchEntries[i].Path, i);
547 }
548 XenBus_Disconnect(xpdd);
550 return STATUS_SUCCESS;
551 }
553 /* called at PASSIVE_LEVEL */
554 NTSTATUS
555 XenBus_Resume(PXENPCI_DEVICE_DATA xpdd)
556 {
557 NTSTATUS status;
558 int i;
560 FUNCTION_ENTER();
562 status = XenBus_Connect(xpdd);
563 if (!NT_SUCCESS(status))
564 {
565 return status;
566 }
568 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
569 {
570 if (xpdd->XenBus_WatchEntries[i].Active)
571 {
572 //KdPrint((__DRIVER_NAME " Adding watch for path = %s\n", xpdd->XenBus_WatchEntries[i].Path));
573 XenBus_SendAddWatch(xpdd, XBT_NIL, xpdd->XenBus_WatchEntries[i].Path, i);
574 }
575 }
576 FUNCTION_EXIT();
578 return STATUS_SUCCESS;
579 }
581 char *
582 XenBus_AddWatch(
583 PVOID Context,
584 xenbus_transaction_t xbt,
585 char *Path,
586 PXENBUS_WATCH_CALLBACK ServiceRoutine,
587 PVOID ServiceContext)
588 {
589 PXENPCI_DEVICE_DATA xpdd = Context;
590 char *msg;
591 int i;
592 PXENBUS_WATCH_ENTRY w_entry;
594 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
596 ASSERT(strlen(Path) < ARRAY_SIZE(w_entry->Path));
598 ExAcquireFastMutex(&xpdd->xb_watch_mutex);
600 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
601 if (xpdd->XenBus_WatchEntries[i].Active == 0)
602 break;
604 if (i == MAX_WATCH_ENTRIES)
605 {
606 KdPrint((__DRIVER_NAME " +++ No more watch slots left\n"));
607 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
608 return NULL;
609 }
611 /* must init watchentry before starting watch */
613 w_entry = &xpdd->XenBus_WatchEntries[i];
614 RtlStringCbCopyA(w_entry->Path, ARRAY_SIZE(w_entry->Path), Path);
615 w_entry->ServiceRoutine = ServiceRoutine;
616 w_entry->ServiceContext = ServiceContext;
617 w_entry->Count = 0;
618 w_entry->Active = 1;
620 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
622 msg = XenBus_SendAddWatch(xpdd, xbt, Path, i);
624 if (msg)
625 {
626 xpdd->XenBus_WatchEntries[i].Active = 0;
627 return msg;
628 }
630 return NULL;
631 }
633 char *
634 XenBus_RemWatch(
635 PVOID Context,
636 xenbus_transaction_t xbt,
637 char *Path,
638 PXENBUS_WATCH_CALLBACK ServiceRoutine,
639 PVOID ServiceContext)
640 {
641 PXENPCI_DEVICE_DATA xpdd = Context;
642 char *msg;
643 int i;
645 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
647 ExAcquireFastMutex(&xpdd->xb_watch_mutex);
649 // check that Path < 128 chars
651 for (i = 0; i < MAX_WATCH_ENTRIES; i++)
652 {
653 if (xpdd->XenBus_WatchEntries[i].Active
654 && !strcmp(xpdd->XenBus_WatchEntries[i].Path, Path)
655 && xpdd->XenBus_WatchEntries[i].ServiceRoutine == ServiceRoutine
656 && xpdd->XenBus_WatchEntries[i].ServiceContext == ServiceContext)
657 {
658 KdPrint((__DRIVER_NAME " Match\n"));
659 break;
660 }
661 }
663 if (i == MAX_WATCH_ENTRIES)
664 {
665 ExReleaseFastMutex(&xpdd->xb_watch_mutex);
666 KdPrint((__DRIVER_NAME " Watch not set - can't remove\n"));
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 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 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 }