win-pvdrivers

view xenpci/xenbus_device_interface.c @ 536:1d39de3ab8d6

mostly finished migration back to kmdf
author James Harper <james.harper@bendigoit.com.au>
date Sat Feb 14 13:35:48 2009 +1100 (2009-02-14)
parents c8824436c717
children 2a74ac2f43bb
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"
23 typedef struct {
24 LIST_ENTRY entry;
25 PVOID data;
26 ULONG length;
27 ULONG offset;
28 } xenbus_read_queue_item_t;
30 typedef struct
31 {
32 LIST_ENTRY entry;
33 CHAR path[128];
34 CHAR token[128];
35 WDFFILEOBJECT file_object;
36 } watch_context_t;
38 VOID
39 XenPci_EvtDeviceFileCreate(WDFDEVICE device, WDFREQUEST request, WDFFILEOBJECT file_object)
40 {
41 NTSTATUS status;
42 PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object);
43 WDF_IO_QUEUE_CONFIG queue_config;
45 FUNCTION_ENTER();
47 xpdid->type = DEVICE_INTERFACE_TYPE_XENBUS;
48 KeInitializeSpinLock(&xpdid->lock);
49 InitializeListHead(&xpdid->read_list_head);
50 InitializeListHead(&xpdid->watch_list_head);
51 xpdid->len = 0;
52 WDF_IO_QUEUE_CONFIG_INIT(&queue_config, WdfIoQueueDispatchManual);
53 //queue_config.EvtIoRead = XenPci_EvtIoRead;
54 status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdid->io_queue);
55 if (!NT_SUCCESS(status)) {
56 KdPrint(("Error creating queue 0x%x\n", status));
57 WdfRequestComplete(request, STATUS_UNSUCCESSFUL);
58 }
59 //WdfIoQueueStop(xpdid->io_queue, NULL, NULL);
61 WdfRequestComplete(request, STATUS_SUCCESS);
63 FUNCTION_EXIT();
64 }
66 VOID
67 XenPci_ProcessReadRequest(WDFQUEUE queue, WDFREQUEST request, size_t length)
68 {
69 NTSTATUS status;
70 WDFFILEOBJECT file_object = WdfRequestGetFileObject(request);
71 PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object);
72 ULONG dst_length = length;
73 ULONG dst_offset = 0;
74 ULONG copy_length;
75 xenbus_read_queue_item_t *list_entry;
76 PVOID buffer;
78 UNREFERENCED_PARAMETER(queue);
80 status = WdfRequestRetrieveOutputBuffer(request, length, &buffer, NULL);
81 if (!NT_SUCCESS(status))
82 {
83 KdPrint((__DRIVER_NAME, " WdfRequestRetrieveOutputBuffer failed status = %08x\n", status));
84 WdfRequestSetInformation(request, 0);
85 return;
86 }
87 ASSERT(NT_SUCCESS(status)); // lazy?
89 while(dst_offset < dst_length && (list_entry = (xenbus_read_queue_item_t *)RemoveHeadList(&xpdid->read_list_head)) != (xenbus_read_queue_item_t *)&xpdid->read_list_head)
90 {
91 copy_length = min(list_entry->length - list_entry->offset, dst_length - dst_offset);
92 memcpy((PUCHAR)buffer + dst_offset, (PUCHAR)list_entry->data + list_entry->offset, copy_length);
93 list_entry->offset += copy_length;
94 dst_offset += copy_length;
95 if (list_entry->offset == list_entry->length)
96 {
97 // free the list entry
98 // free the data
99 }
100 else
101 {
102 InsertHeadList(&xpdid->read_list_head, (PLIST_ENTRY)list_entry);
103 }
104 }
105 WdfRequestSetInformation(request, dst_offset);
107 FUNCTION_EXIT();
108 }
110 static VOID
111 XenPci_IoWatch(char *path, PVOID context)
112 {
113 NTSTATUS status;
114 watch_context_t *watch_context = context;
115 WDFFILEOBJECT file_object = watch_context->file_object;
116 PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object);
117 KIRQL old_irql;
118 struct xsd_sockmsg *rep;
119 xenbus_read_queue_item_t *list_entry;
120 WDFREQUEST request;
122 FUNCTION_ENTER();
124 KeAcquireSpinLock(&xpdid->lock, &old_irql);
126 rep = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct xsd_sockmsg) + strlen(path) + 1 + strlen(watch_context->token) + 1, XENPCI_POOL_TAG);
127 rep->type = XS_WATCH_EVENT;
128 rep->req_id = 0;
129 rep->tx_id = 0;
130 rep->len = strlen(path) + 1 + strlen(watch_context->token) + 1;
131 strcpy((PCHAR)(rep + 1), path);
132 strcpy((PCHAR)(rep + 1) + strlen(path) + 1, watch_context->token);
134 list_entry = (xenbus_read_queue_item_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(xenbus_read_queue_item_t), XENPCI_POOL_TAG);
135 list_entry->data = rep;
136 list_entry->length = sizeof(*rep) + rep->len;
137 list_entry->offset = 0;
138 InsertTailList(&xpdid->read_list_head, (PLIST_ENTRY)list_entry);
140 status = WdfIoQueueRetrieveNextRequest(xpdid->io_queue, &request);
141 if (NT_SUCCESS(status))
142 {
143 WDF_REQUEST_PARAMETERS parameters;
144 WDF_REQUEST_PARAMETERS_INIT(&parameters);
145 WdfRequestGetParameters(request, &parameters);
147 KdPrint((__DRIVER_NAME " found pending read - MinorFunction = %d, length = %d\n", (ULONG)parameters.MinorFunction, (ULONG)parameters.Parameters.Read.Length));
148 XenPci_ProcessReadRequest(xpdid->io_queue, request, parameters.Parameters.Read.Length);
149 KeReleaseSpinLock(&xpdid->lock, old_irql);
150 WdfRequestComplete(request, STATUS_SUCCESS);
151 }
152 else
153 {
154 KdPrint((__DRIVER_NAME " no pending read (%08x)\n", status));
155 KeReleaseSpinLock(&xpdid->lock, old_irql);
156 }
158 FUNCTION_EXIT();
159 }
161 VOID
162 XenPci_EvtFileCleanup(WDFFILEOBJECT file_object)
163 {
164 PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object);
165 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfFileObjectGetDevice(file_object));
166 watch_context_t *watch_context;
167 KIRQL old_irql;
168 PCHAR msg;
170 FUNCTION_ENTER();
172 KeAcquireSpinLock(&xpdid->lock, &old_irql);
174 while (!IsListEmpty(&xpdid->watch_list_head))
175 {
176 watch_context = (watch_context_t *)RemoveHeadList(&xpdid->watch_list_head);
177 KeReleaseSpinLock(&xpdid->lock, old_irql);
178 msg = XenBus_RemWatch(xpdd, XBT_NIL, watch_context->path, XenPci_IoWatch, watch_context);
179 if (msg != NULL)
180 {
181 KdPrint((__DRIVER_NAME " Error freeing watch (%s)\n", msg));
182 XenPci_FreeMem(msg);
183 }
184 ExFreePoolWithTag(watch_context, XENPCI_POOL_TAG);
185 WdfObjectDereference(file_object);
186 KeAcquireSpinLock(&xpdid->lock, &old_irql);
187 }
189 KeReleaseSpinLock(&xpdid->lock, old_irql);
191 FUNCTION_EXIT();
192 }
194 VOID
195 XenPci_EvtFileClose(WDFFILEOBJECT file_object)
196 {
197 UNREFERENCED_PARAMETER(file_object);
198 FUNCTION_ENTER();
199 FUNCTION_EXIT();
200 }
202 VOID
203 XenPci_EvtIoRead(WDFQUEUE queue, WDFREQUEST request, size_t length)
204 {
205 NTSTATUS status;
206 WDFFILEOBJECT file_object = WdfRequestGetFileObject(request);
207 PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object);
208 KIRQL old_irql;
210 FUNCTION_ENTER();
211 status = WdfRequestForwardToIoQueue(request, xpdid->io_queue);
212 if (!NT_SUCCESS(status))
213 {
214 KdPrint((__DRIVER_NAME " could not forward request (%08x)\n", status));
215 }
216 KeAcquireSpinLock(&xpdid->lock, &old_irql);
217 if (!IsListEmpty(&xpdid->read_list_head))
218 {
219 status = WdfIoQueueRetrieveNextRequest(xpdid->io_queue, &request);
220 if (NT_SUCCESS(status))
221 {
222 KdPrint((__DRIVER_NAME " found pending read\n"));
223 XenPci_ProcessReadRequest(xpdid->io_queue, request, length);
224 KeReleaseSpinLock(&xpdid->lock, old_irql);
225 WdfRequestComplete(request, STATUS_SUCCESS);
226 }
227 else
228 {
229 KdPrint((__DRIVER_NAME " no pending read (%08x)\n", status));
230 KeReleaseSpinLock(&xpdid->lock, old_irql);
231 }
232 }
233 else
234 {
235 KdPrint((__DRIVER_NAME " no data to read\n"));
236 KeReleaseSpinLock(&xpdid->lock, old_irql);
237 }
239 FUNCTION_EXIT();
240 return;
241 }
243 VOID
244 XenPci_EvtIoWrite(WDFQUEUE queue, WDFREQUEST request, size_t length)
245 {
246 NTSTATUS status;
247 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfIoQueueGetDevice(queue));
248 WDFFILEOBJECT file_object = WdfRequestGetFileObject(request);
249 PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object);
250 KIRQL old_irql;
251 PUCHAR buffer;
252 PUCHAR src_ptr;
253 ULONG src_len;
254 PUCHAR dst_ptr;
255 ULONG copy_len;
256 struct xsd_sockmsg *rep;
257 xenbus_read_queue_item_t *list_entry;
258 watch_context_t *watch_context;
259 PCHAR watch_path;
260 PCHAR watch_token;
261 PCHAR msg;
263 FUNCTION_ENTER();
265 status = WdfRequestRetrieveInputBuffer(request, length, &buffer, NULL);
266 ASSERT(NT_SUCCESS(status));
268 src_ptr = (PUCHAR)buffer;
269 src_len = length;
270 dst_ptr = xpdid->u.buffer + xpdid->len;
271 while (src_len != 0)
272 {
273 KdPrint((__DRIVER_NAME " %d bytes of write buffer remaining\n", src_len));
274 /* get a complete msg header */
275 if (xpdid->len < sizeof(xpdid->u.msg))
276 {
277 copy_len = min(sizeof(xpdid->u.msg) - xpdid->len, src_len);
278 if (!copy_len)
279 continue;
280 memcpy(dst_ptr, src_ptr, copy_len);
281 dst_ptr += copy_len;
282 src_ptr += copy_len;
283 src_len -= copy_len;
284 xpdid->len += copy_len;
285 }
286 /* exit if we can't get that */
287 if (xpdid->len < sizeof(xpdid->u.msg))
288 continue;
289 /* get a complete msg body */
290 if (xpdid->len < sizeof(xpdid->u.msg) + xpdid->u.msg.len)
291 {
292 copy_len = min(sizeof(xpdid->u.msg) + xpdid->u.msg.len - xpdid->len, src_len);
293 if (!copy_len)
294 continue;
295 memcpy(dst_ptr, src_ptr, copy_len);
296 dst_ptr += copy_len;
297 src_ptr += copy_len;
298 src_len -= copy_len;
299 xpdid->len += copy_len;
300 }
301 /* exit if we can't get that */
302 if (xpdid->len < sizeof(xpdid->u.msg) + xpdid->u.msg.len)
303 {
304 continue;
305 }
307 switch (xpdid->u.msg.type)
308 {
309 case XS_WATCH:
310 case XS_UNWATCH:
311 KeAcquireSpinLock(&xpdid->lock, &old_irql);
312 watch_context = (watch_context_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(watch_context_t), XENPCI_POOL_TAG);
313 watch_path = xpdid->u.buffer + sizeof(struct xsd_sockmsg);
314 watch_token = xpdid->u.buffer + sizeof(struct xsd_sockmsg) + strlen(watch_path) + 1;
315 strcpy(watch_context->path, watch_path);
316 strcpy(watch_context->token, watch_token);
317 watch_context->file_object = file_object;
318 if (xpdid->u.msg.type == XS_WATCH)
319 InsertTailList(&xpdid->watch_list_head, &watch_context->entry);
320 KeReleaseSpinLock(&xpdid->lock, old_irql);
321 if (xpdid->u.msg.type == XS_WATCH)
322 msg = XenBus_AddWatch(xpdd, XBT_NIL, watch_path, XenPci_IoWatch, watch_context);
323 else
324 msg = XenBus_RemWatch(xpdd, XBT_NIL, watch_path, XenPci_IoWatch, watch_context);
325 KeAcquireSpinLock(&xpdid->lock, &old_irql);
326 if (msg != NULL)
327 {
328 rep = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct xsd_sockmsg) + strlen(msg) + 1, XENPCI_POOL_TAG);
329 rep->type = XS_ERROR;
330 rep->req_id = xpdid->u.msg.req_id;
331 rep->tx_id = xpdid->u.msg.tx_id;
332 rep->len = strlen(msg) + 0;
333 strcpy((PCHAR)(rep + 1), msg);
334 if (xpdid->u.msg.type == XS_WATCH)
335 RemoveEntryList(&watch_context->entry);
336 }
337 else
338 {
339 if (xpdid->u.msg.type == XS_WATCH)
340 {
341 WdfObjectReference(file_object);
342 }
343 else
344 {
345 RemoveEntryList(&watch_context->entry);
346 WdfObjectDereference(file_object);
347 }
348 rep = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct xsd_sockmsg), XENPCI_POOL_TAG);
349 rep->type = xpdid->u.msg.type;
350 rep->req_id = xpdid->u.msg.req_id;
351 rep->tx_id = xpdid->u.msg.tx_id;
352 rep->len = 0;
353 }
354 KeReleaseSpinLock(&xpdid->lock, old_irql);
355 break;
356 default:
357 rep = XenBus_Raw(xpdd, &xpdid->u.msg);
358 break;
359 }
360 xpdid->len = 0;
362 KeAcquireSpinLock(&xpdid->lock, &old_irql);
363 list_entry = (xenbus_read_queue_item_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(xenbus_read_queue_item_t), XENPCI_POOL_TAG);
364 list_entry->data = rep;
365 list_entry->length = sizeof(*rep) + rep->len;
366 list_entry->offset = 0;
367 InsertTailList(&xpdid->read_list_head, (PLIST_ENTRY)list_entry);
368 KeReleaseSpinLock(&xpdid->lock, old_irql);
369 }
370 KdPrint((__DRIVER_NAME " completing request with length %d\n", length));
371 WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, length);
373 FUNCTION_EXIT();
374 }
376 #if 0
377 NTSTATUS
378 XenPci_Irp_Create_XenBus(PDEVICE_OBJECT device_object, PIRP irp)
379 {
380 NTSTATUS status;
381 PIO_STACK_LOCATION stack;
382 PFILE_OBJECT file;
383 device_interface_xenbus_context_t *dixc;
385 FUNCTION_ENTER();
387 UNREFERENCED_PARAMETER(device_object);
388 stack = IoGetCurrentIrpStackLocation(irp);
389 file = stack->FileObject;
390 dixc = (device_interface_xenbus_context_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(device_interface_xenbus_context_t), XENPCI_POOL_TAG);
391 dixc->type = DEVICE_INTERFACE_TYPE_XENBUS;
392 KeInitializeSpinLock(&dixc->lock);
393 InitializeListHead(&dixc->read_list_head);
394 dixc->len = 0;
395 file->FsContext = dixc;
396 status = STATUS_SUCCESS;
397 dixc->pending_read_irp = NULL;
398 irp->IoStatus.Status = status;
399 IoCompleteRequest(irp, IO_NO_INCREMENT);
401 FUNCTION_EXIT();
403 return status;
404 }
406 NTSTATUS
407 XenPci_Irp_Close_XenBus(PDEVICE_OBJECT device_object, PIRP irp)
408 {
409 PXENPCI_DEVICE_DATA xpdd;
410 NTSTATUS status;
412 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
413 status = STATUS_SUCCESS;
414 irp->IoStatus.Status = status;
415 IoCompleteRequest(irp, IO_NO_INCREMENT);
416 // cleanup dixc here
418 return status;
419 }
421 static NTSTATUS
422 XenPci_Irp_Read_XenBus_Complete(device_interface_xenbus_context_t *dixc, PIRP irp)
423 {
424 KIRQL old_irql;
425 ULONG dst_length;
426 ULONG dst_offset;
427 ULONG copy_length;
428 xenbus_read_queue_item_t *list_entry;
429 PIO_STACK_LOCATION stack;
430 NTSTATUS status;
432 FUNCTION_ENTER();
434 KdPrint((__DRIVER_NAME " A - dixc = %p, irp = %p\n", dixc, irp));
435 stack = IoGetCurrentIrpStackLocation(irp);
436 KdPrint((__DRIVER_NAME " Aa\n"));
437 dst_length = stack->Parameters.Read.Length;
438 KdPrint((__DRIVER_NAME " B - dst_length = %d\n", dst_length));
439 dst_offset = 0;
440 KdPrint((__DRIVER_NAME " C\n"));
441 KeAcquireSpinLock(&dixc->lock, &old_irql);
442 KdPrint((__DRIVER_NAME " D"));
443 while(dst_offset < dst_length && (list_entry = (xenbus_read_queue_item_t *)RemoveHeadList(&dixc->read_list_head)) != (xenbus_read_queue_item_t *)&dixc->read_list_head)
444 {
445 KdPrint((__DRIVER_NAME " E\n"));
446 copy_length = min(list_entry->length - list_entry->offset, dst_length - dst_offset);
447 KdPrint((__DRIVER_NAME " copying %d bytes\n", copy_length));
448 memcpy((PUCHAR)irp->AssociatedIrp.SystemBuffer + dst_offset, (PUCHAR)list_entry->data + list_entry->offset, copy_length);
449 list_entry->offset += copy_length;
450 dst_offset += copy_length;
451 if (list_entry->offset == list_entry->length)
452 {
453 // free the list entry
454 // free the data
455 }
456 else
457 {
458 InsertHeadList(&dixc->read_list_head, (PLIST_ENTRY)list_entry);
459 }
460 }
461 KeReleaseSpinLock(&dixc->lock, old_irql);
462 KdPrint((__DRIVER_NAME " F\n"));
464 if (dst_offset > 0)
465 {
466 KdPrint((__DRIVER_NAME " completing request\n"));
467 status = STATUS_SUCCESS;
468 irp->IoStatus.Status = status;
469 irp->IoStatus.Information = dst_offset;
470 IoSetCancelRoutine(irp, NULL);
471 IoCompleteRequest(irp, IO_NO_INCREMENT);
472 }
473 else
474 {
475 KdPrint((__DRIVER_NAME " pending request\n"));
476 status = STATUS_PENDING;
477 }
479 FUNCTION_EXIT();
481 return status;
482 }
484 static VOID
485 XenPci_Irp_Read_Cancel(PDEVICE_OBJECT device_object, PIRP irp)
486 {
487 PIO_STACK_LOCATION stack;
488 PFILE_OBJECT file;
489 device_interface_xenbus_context_t *dixc;
490 KIRQL old_irql;
492 FUNCTION_ENTER();
494 UNREFERENCED_PARAMETER(device_object);
496 stack = IoGetCurrentIrpStackLocation(irp);
497 file = stack->FileObject;
498 dixc = file->FsContext;
499 IoReleaseCancelSpinLock(irp->CancelIrql);
500 KeAcquireSpinLock(&dixc->lock, &old_irql);
501 if (irp != dixc->pending_read_irp)
502 {
503 KdPrint((__DRIVER_NAME " Not the current irp???\n"));
504 }
505 dixc->pending_read_irp = NULL;
506 irp->IoStatus.Status = STATUS_CANCELLED;
507 irp->IoStatus.Information = 0;
508 KeReleaseSpinLock(&dixc->lock, old_irql);
509 IoCompleteRequest(irp, IO_NO_INCREMENT);
511 FUNCTION_EXIT();
512 }
514 NTSTATUS
515 XenPci_Irp_Read_XenBus(PDEVICE_OBJECT device_object, PIRP irp)
516 {
517 NTSTATUS status;
518 PIO_STACK_LOCATION stack;
519 PFILE_OBJECT file;
520 device_interface_xenbus_context_t *dixc;
521 KIRQL old_irql;
523 UNREFERENCED_PARAMETER(device_object);
525 stack = IoGetCurrentIrpStackLocation(irp);
526 file = stack->FileObject;
527 dixc = file->FsContext;
529 ASSERT(!dixc->pending_read_irp);
531 if (stack->Parameters.Read.Length == 0)
532 {
533 status = STATUS_SUCCESS;
534 irp->IoStatus.Status = status;
535 irp->IoStatus.Information = 0;
536 IoCompleteRequest(irp, IO_NO_INCREMENT);
537 }
538 else
539 {
540 status = XenPci_Irp_Read_XenBus_Complete(dixc, irp);
541 if (status == STATUS_PENDING)
542 {
543 IoMarkIrpPending(irp);
544 KeAcquireSpinLock(&dixc->lock, &old_irql);
545 dixc->pending_read_irp = irp;
546 KeReleaseSpinLock(&dixc->lock, old_irql);
547 IoSetCancelRoutine(irp, XenPci_Irp_Read_Cancel);
548 }
549 }
550 return status;
551 }
553 NTSTATUS
554 XenPci_Irp_Write_XenBus(PDEVICE_OBJECT device_object, PIRP irp)
555 {
556 NTSTATUS status;
557 PIO_STACK_LOCATION stack;
558 PFILE_OBJECT file;
559 device_interface_xenbus_context_t *dixc;
560 PUCHAR src_ptr;
561 ULONG src_len;
562 PUCHAR dst_ptr;
563 ULONG copy_len;
564 struct xsd_sockmsg *rep;
565 PXENPCI_DEVICE_DATA xpdd;
566 KIRQL old_irql;
567 xenbus_read_queue_item_t *list_entry;
568 PIRP read_irp;
569 NTSTATUS read_status;
571 FUNCTION_ENTER();
573 xpdd = device_object->DeviceExtension;
574 stack = IoGetCurrentIrpStackLocation(irp);
575 file = stack->FileObject;
576 dixc = file->FsContext;
578 KdPrint((__DRIVER_NAME " write length = %d\n", stack->Parameters.Write.Length));
580 src_ptr = (PUCHAR)irp->AssociatedIrp.SystemBuffer;
581 src_len = stack->Parameters.Write.Length;
582 dst_ptr = dixc->u.buffer + dixc->len;
583 while (src_len != 0)
584 {
585 /* get a complete msg header */
586 if (dixc->len < sizeof(dixc->u.msg))
587 {
588 copy_len = min(sizeof(dixc->u.msg) - dixc->len, src_len);
589 if (!copy_len)
590 continue;
591 memcpy(dst_ptr, src_ptr, copy_len);
592 dst_ptr += copy_len;
593 src_ptr += copy_len;
594 src_len -= copy_len;
595 dixc->len += copy_len;
596 }
597 /* exit if we can't get that */
598 if (dixc->len < sizeof(dixc->u.msg))
599 continue;
600 /* get a complete msg body */
601 if (dixc->len < sizeof(dixc->u.msg) + dixc->u.msg.len)
602 {
603 copy_len = min(sizeof(dixc->u.msg) + dixc->u.msg.len - dixc->len, src_len);
604 if (!copy_len)
605 continue;
606 memcpy(dst_ptr, src_ptr, copy_len);
607 dst_ptr += copy_len;
608 src_ptr += copy_len;
609 src_len -= copy_len;
610 dixc->len += copy_len;
611 }
612 /* exit if we can't get that */
613 if (dixc->len < sizeof(dixc->u.msg) + dixc->u.msg.len)
614 {
615 continue;
616 }
618 rep = XenBus_Raw(xpdd, &dixc->u.msg);
619 KeAcquireSpinLock(&dixc->lock, &old_irql);
620 list_entry = (xenbus_read_queue_item_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(xenbus_read_queue_item_t), XENPCI_POOL_TAG);
621 list_entry->data = rep;
622 list_entry->length = sizeof(*rep) + rep->len;
623 list_entry->offset = 0;
624 InsertTailList(&dixc->read_list_head, (PLIST_ENTRY)list_entry);
625 read_irp = dixc->pending_read_irp;
626 dixc->pending_read_irp = NULL;
627 KeReleaseSpinLock(&dixc->lock, old_irql);
628 if (read_irp)
629 {
630 read_status = XenPci_Irp_Read_XenBus_Complete(dixc, read_irp);
631 ASSERT(read_status == STATUS_SUCCESS);
632 }
633 }
634 status = STATUS_SUCCESS;
635 irp->IoStatus.Status = status;
636 irp->IoStatus.Information = stack->Parameters.Write.Length;
638 KdPrint((__DRIVER_NAME " Information = %d\n", irp->IoStatus.Information));
640 IoCompleteRequest(irp, IO_NO_INCREMENT);
642 FUNCTION_EXIT();
644 return status;
645 }
647 NTSTATUS
648 XenPci_Irp_Cleanup_XenBus(PDEVICE_OBJECT device_object, PIRP irp)
649 {
650 PXENPCI_DEVICE_DATA xpdd;
651 NTSTATUS status;
653 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
654 status = STATUS_SUCCESS;
655 irp->IoStatus.Status = status;
656 IoCompleteRequest(irp, IO_NO_INCREMENT);
658 return status;
659 }
660 #endif