win-pvdrivers

view xenpci/xenpci_fdo.c @ 537:2a74ac2f43bb

more big updates
dma now working under xp
author James Harper <james.harper@bendigoit.com.au>
date Wed Feb 18 22:18:23 2009 +1100 (2009-02-18)
parents 1d39de3ab8d6
children e75bb8d68370
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>
22 #include <aux_klib.h>
24 #define SYSRQ_PATH "control/sysrq"
25 #define SHUTDOWN_PATH "control/shutdown"
26 #define BALLOON_PATH "memory/target"
28 static VOID
29 XenPci_MapHalThenPatchKernel(PXENPCI_DEVICE_DATA xpdd)
30 {
31 NTSTATUS status;
32 PAUX_MODULE_EXTENDED_INFO amei;
33 ULONG module_info_buffer_size;
34 ULONG i;
36 FUNCTION_ENTER();
38 status = AuxKlibInitialize();
39 amei = NULL;
40 /* buffer size could change between requesting and allocating - need to loop until we are successful */
41 while ((status = AuxKlibQueryModuleInformation(&module_info_buffer_size, sizeof(AUX_MODULE_EXTENDED_INFO), amei)) == STATUS_BUFFER_TOO_SMALL || amei == NULL)
42 {
43 if (amei != NULL)
44 ExFreePoolWithTag(amei, XENPCI_POOL_TAG);
45 amei = ExAllocatePoolWithTag(NonPagedPool, module_info_buffer_size, XENPCI_POOL_TAG);
46 }
48 KdPrint((__DRIVER_NAME " AuxKlibQueryModuleInformation = %d\n", status));
49 for (i = 0; i < module_info_buffer_size / sizeof(AUX_MODULE_EXTENDED_INFO); i++)
50 {
51 if (strcmp((PCHAR)amei[i].FullPathName + amei[i].FileNameOffset, "hal.dll") == 0)
52 {
53 KdPrint((__DRIVER_NAME " hal.dll found at %p - %p\n",
54 amei[i].BasicInfo.ImageBase,
55 ((PUCHAR)amei[i].BasicInfo.ImageBase) + amei[i].ImageSize));
56 XenPci_PatchKernel(xpdd, amei[i].BasicInfo.ImageBase, amei[i].ImageSize);
57 }
58 }
59 ExFreePoolWithTag(amei, XENPCI_POOL_TAG);
60 FUNCTION_EXIT();
61 }
63 #if 0
64 PMDL
65 XenPCI_AllocMMIO(WDFDEVICE device, ULONG len)
66 {
67 PMDL mdl = ExAllocatePoolWithTag(NonPagedPool, MmSizeOfMdl(0, len), XENPCI_POOL_TAG);
68 PVOID va = MmAllocateMappingAddress(len, XENPCI_POOL_TAG);
70 for (i = 0; i < ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, len);
72 }
73 #endif
75 /*
76 * Alloc MMIO from the device's MMIO region. There is no corresponding free() fn
77 */
78 PHYSICAL_ADDRESS
79 XenPci_AllocMMIO(PXENPCI_DEVICE_DATA xpdd, ULONG len)
80 {
81 PHYSICAL_ADDRESS addr;
83 len = (len + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
85 addr = xpdd->platform_mmio_addr;
86 addr.QuadPart += xpdd->platform_mmio_alloc;
87 xpdd->platform_mmio_alloc += len;
89 ASSERT(xpdd->platform_mmio_alloc <= xpdd->platform_mmio_len);
91 return addr;
92 }
94 extern ULONG tpr_patch_requested;
96 NTSTATUS
97 XenPci_EvtDeviceQueryRemove(WDFDEVICE device)
98 {
99 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
100 NTSTATUS status;
102 FUNCTION_ENTER();
103 if (xpdd->removable)
104 status = STATUS_SUCCESS;
105 else
106 status = STATUS_UNSUCCESSFUL;
107 FUNCTION_EXIT();
108 return status;
109 }
111 static NTSTATUS
112 XenPci_Init(PXENPCI_DEVICE_DATA xpdd)
113 {
114 struct xen_add_to_physmap xatp;
115 int ret;
117 FUNCTION_ENTER();
119 hvm_get_stubs(xpdd);
121 if (!xpdd->shared_info_area)
122 {
123 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
124 /* this should be safe as this part will never be called on resume where IRQL == HIGH_LEVEL */
125 xpdd->shared_info_area_unmapped = XenPci_AllocMMIO(xpdd, PAGE_SIZE);
126 xpdd->shared_info_area = MmMapIoSpace(xpdd->shared_info_area_unmapped,
127 PAGE_SIZE, MmNonCached);
128 }
129 KdPrint((__DRIVER_NAME " shared_info_area_unmapped.QuadPart = %lx\n", xpdd->shared_info_area_unmapped.QuadPart));
130 xatp.domid = DOMID_SELF;
131 xatp.idx = 0;
132 xatp.space = XENMAPSPACE_shared_info;
133 xatp.gpfn = (xen_pfn_t)(xpdd->shared_info_area_unmapped.QuadPart >> PAGE_SHIFT);
134 KdPrint((__DRIVER_NAME " gpfn = %x\n", xatp.gpfn));
135 ret = HYPERVISOR_memory_op(xpdd, XENMEM_add_to_physmap, &xatp);
136 KdPrint((__DRIVER_NAME " hypervisor memory op (XENMAPSPACE_shared_info) ret = %d\n", ret));
138 FUNCTION_EXIT();
140 return STATUS_SUCCESS;
141 }
143 static NTSTATUS
144 XenPci_Resume(PXENPCI_DEVICE_DATA xpdd)
145 {
146 return XenPci_Init(xpdd);
147 }
149 static VOID
150 XenPci_SysrqHandler(char *path, PVOID context)
151 {
152 PXENPCI_DEVICE_DATA xpdd = context;
153 char *value;
154 char letter;
155 char *res;
157 UNREFERENCED_PARAMETER(path);
159 FUNCTION_ENTER();
161 XenBus_Read(xpdd, XBT_NIL, SYSRQ_PATH, &value);
163 KdPrint((__DRIVER_NAME " SysRq Value = %s\n", value));
165 if (value != NULL && strlen(value) != 0)
166 {
167 letter = *value;
168 res = XenBus_Write(xpdd, XBT_NIL, SYSRQ_PATH, "");
169 if (res)
170 {
171 KdPrint(("Error writing sysrq path\n"));
172 XenPci_FreeMem(res);
173 return;
174 }
175 }
176 else
177 {
178 letter = 0;
179 }
181 if (value != NULL)
182 {
183 XenPci_FreeMem(value);
184 }
186 switch (letter)
187 {
188 case 0:
189 break;
190 case 'B': /* cause a bug check */
191 KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000001, 0x00000000, 0x00000000, 0x00000000);
192 break;
193 default:
194 KdPrint((" Unhandled sysrq letter %c\n", letter));
195 break;
196 }
198 FUNCTION_EXIT();
199 }
201 #if 0
202 static VOID
203 XenPci_PrintPendingInterrupts()
204 {
205 PULONG bitmap = (PULONG)0xFFFE0200;
206 int i;
207 int j;
208 ULONG value;
210 for (i = 0; i < 8; i++)
211 {
212 value = bitmap[(7 - i) * 4];
213 if (value)
214 {
215 for (j = 0; j < 32; j++)
216 {
217 if ((value >> j) & 1)
218 KdPrint((" Interrupt pending on pin %d\n", ((7 - i) << 5) | j));
219 }
220 }
221 }
222 }
223 #endif
225 static VOID
226 XenPci_Suspend0(PVOID context)
227 {
228 PXENPCI_DEVICE_DATA xpdd = context;
229 ULONG cancelled;
231 FUNCTION_ENTER();
233 GntTbl_Suspend(xpdd);
235 cancelled = hvm_shutdown(xpdd, SHUTDOWN_suspend);
236 KdPrint((__DRIVER_NAME " back from suspend, cancelled = %d\n", cancelled));
238 if (qemu_filtered_by_qemu)
239 {
240 XenPci_HideQemuDevices();
241 ASSERT(qemu_filtered_by_qemu);
242 }
244 XenPci_Resume(xpdd);
245 GntTbl_Resume(xpdd);
246 EvtChn_Resume(xpdd); /* this enables interrupts again too */
248 FUNCTION_EXIT();
249 }
251 static VOID
252 XenPci_SuspendN(PVOID context)
253 {
254 UNREFERENCED_PARAMETER(context);
256 FUNCTION_ENTER();
257 KdPrint((__DRIVER_NAME " doing nothing on cpu N\n"));
258 FUNCTION_EXIT();
259 }
261 /* Called at PASSIVE_LEVEL */
262 static VOID DDKAPI
263 XenPci_SuspendResume(WDFWORKITEM workitem)
264 {
265 NTSTATUS status;
266 //KAFFINITY ActiveProcessorMask = 0; // this is for Vista+
267 WDFDEVICE device = WdfWorkItemGetParentObject(workitem);
268 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
269 WDFCHILDLIST child_list = WdfFdoGetDefaultChildList(device);
270 WDF_CHILD_LIST_ITERATOR child_iterator;
271 WDFDEVICE child_device;
273 FUNCTION_ENTER();
275 if (xpdd->suspend_state == SUSPEND_STATE_NONE)
276 {
277 xpdd->suspend_state = SUSPEND_STATE_SCHEDULED;
278 KeMemoryBarrier();
280 WDF_CHILD_LIST_ITERATOR_INIT(&child_iterator, WdfRetrievePresentChildren);
281 WdfChildListBeginIteration(child_list, &child_iterator);
282 while ((status = WdfChildListRetrieveNextDevice(child_list, &child_iterator, &child_device, NULL)) == STATUS_SUCCESS)
283 {
284 KdPrint((__DRIVER_NAME " Suspending child\n"));
285 XenPci_Pdo_Suspend(child_device);
286 }
287 KdPrint((__DRIVER_NAME " WdfChildListRetrieveNextDevice = %08x, STATUS_NO_MORE_ENTRIES = %08x\n", status, STATUS_NO_MORE_ENTRIES));
288 WdfChildListEndIteration(child_list, &child_iterator);
290 XenBus_Suspend(xpdd);
291 EvtChn_Suspend(xpdd);
292 XenPci_HighSync(XenPci_Suspend0, XenPci_SuspendN, xpdd);
294 xpdd->suspend_state = SUSPEND_STATE_RESUMING;
295 XenBus_Resume(xpdd);
297 WdfChildListBeginIteration(child_list, &child_iterator);
298 while ((status = WdfChildListRetrieveNextDevice(child_list, &child_iterator, &child_device, NULL)) == STATUS_SUCCESS)
299 {
300 KdPrint((__DRIVER_NAME " Resuming child\n"));
301 XenPci_Pdo_Resume(child_device);
302 }
303 KdPrint((__DRIVER_NAME " WdfChildListRetrieveNextDevice = %08x, STATUS_NO_MORE_ENTRIES = %08x\n", status, STATUS_NO_MORE_ENTRIES));
304 WdfChildListEndIteration(child_list, &child_iterator);
306 xpdd->suspend_state = SUSPEND_STATE_NONE;
307 }
308 FUNCTION_EXIT();
309 }
311 static void
312 XenPci_ShutdownHandler(char *path, PVOID context)
313 {
314 NTSTATUS status;
315 WDFDEVICE device = context;
316 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
317 char *res;
318 char *value;
319 //KIRQL old_irql;
320 WDF_OBJECT_ATTRIBUTES attributes;
321 WDF_WORKITEM_CONFIG workitem_config;
322 WDFWORKITEM workitem;
324 UNREFERENCED_PARAMETER(path);
326 FUNCTION_ENTER();
328 res = XenBus_Read(xpdd, XBT_NIL, SHUTDOWN_PATH, &value);
329 if (res)
330 {
331 KdPrint(("Error reading shutdown path - %s\n", res));
332 XenPci_FreeMem(res);
333 return;
334 }
336 KdPrint((__DRIVER_NAME " Shutdown value = %s\n", value));
338 if (strlen(value) && strcmp(value, "suspend") == 0)
339 {
340 {
341 KdPrint((__DRIVER_NAME " Suspend detected\n"));
342 /* we have to queue this as a work item as we stop the xenbus thread, which we are currently running in! */
343 WDF_WORKITEM_CONFIG_INIT(&workitem_config, XenPci_SuspendResume);
344 WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
345 attributes.ParentObject = device;
346 status = WdfWorkItemCreate(&workitem_config, &attributes, &workitem);
347 // TODO: check status here
348 WdfWorkItemEnqueue(workitem);
349 }
350 }
352 XenPci_FreeMem(value);
354 FUNCTION_EXIT();
355 }
357 static VOID
358 XenPci_DeviceWatchHandler(char *path, PVOID context)
359 {
360 char **bits;
361 int count;
362 char *err;
363 char *value;
364 PXENPCI_DEVICE_DATA xpdd = context;
366 FUNCTION_ENTER();
368 bits = SplitString(path, '/', 4, &count);
369 if (count == 3)
370 {
371 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
372 if (err)
373 {
374 /* obviously path no longer exists, in which case the removal is being taken care of elsewhere and we shouldn't invalidate now */
375 XenPci_FreeMem(err);
376 }
377 else
378 {
379 XenPci_FreeMem(value);
380 /* we probably have to be a bit smarter here and do nothing if xenpci isn't running yet */
381 KdPrint((__DRIVER_NAME " Invalidating Device Relations\n"));
382 //IoInvalidateDeviceRelations(xpdd->common.pdo, BusRelations);
383 }
384 }
385 FreeSplitString(bits, count);
387 FUNCTION_EXIT();
388 }
390 NTSTATUS
391 XenPci_EvtDevicePrepareHardware (WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
392 {
393 NTSTATUS status = STATUS_SUCCESS;
394 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
395 PCM_PARTIAL_RESOURCE_DESCRIPTOR raw_descriptor, translated_descriptor;
396 ULONG i;
398 FUNCTION_ENTER();
400 ASSERT(WdfCmResourceListGetCount(resources_raw) == WdfCmResourceListGetCount(resources_translated));
402 for (i = 0; i < WdfCmResourceListGetCount(resources_raw); i++)
403 {
404 raw_descriptor = WdfCmResourceListGetDescriptor(resources_raw, i);
405 translated_descriptor = WdfCmResourceListGetDescriptor(resources_translated, i);
406 switch (raw_descriptor->Type) {
407 case CmResourceTypePort:
408 KdPrint((__DRIVER_NAME " IoPort Address(%x) Length: %d\n", translated_descriptor->u.Port.Start.LowPart, translated_descriptor->u.Port.Length));
409 xpdd->platform_ioport_addr = translated_descriptor->u.Port.Start.LowPart;
410 xpdd->platform_ioport_len = translated_descriptor->u.Port.Length;
411 break;
412 case CmResourceTypeMemory:
413 KdPrint((__DRIVER_NAME " Memory mapped CSR:(%x:%x) Length:(%d)\n", translated_descriptor->u.Memory.Start.LowPart, translated_descriptor->u.Memory.Start.HighPart, translated_descriptor->u.Memory.Length));
414 KdPrint((__DRIVER_NAME " Memory flags = %04X\n", translated_descriptor->Flags));
415 #if 0
416 mmio_freelist_free = 0;
417 for (j = 0; j < translated_descriptor->u.Memory.Length >> PAGE_SHIFT; j++)
418 put_mmio_on_freelist((xpdd->platform_mmio_addr >> PAGE_SHIFT) + j);
419 #endif
420 xpdd->platform_mmio_addr = translated_descriptor->u.Memory.Start;
421 xpdd->platform_mmio_len = translated_descriptor->u.Memory.Length;
422 xpdd->platform_mmio_flags = translated_descriptor->Flags;
423 break;
424 case CmResourceTypeInterrupt:
425 xpdd->irq_level = (KIRQL)translated_descriptor->u.Interrupt.Level;
426 xpdd->irq_vector = translated_descriptor->u.Interrupt.Vector;
427 xpdd->irq_affinity = translated_descriptor->u.Interrupt.Affinity;
428 xpdd->irq_mode = (translated_descriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED)?Latched:LevelSensitive;
429 xpdd->irq_number = raw_descriptor->u.Interrupt.Vector;
430 KdPrint((__DRIVER_NAME " irq_number = %03x\n", raw_descriptor->u.Interrupt.Vector));
431 KdPrint((__DRIVER_NAME " irq_vector = %03x\n", translated_descriptor->u.Interrupt.Vector));
432 KdPrint((__DRIVER_NAME " irq_level = %03x\n", translated_descriptor->u.Interrupt.Level));
433 KdPrint((__DRIVER_NAME " irq_mode = %s\n", (xpdd->irq_mode == Latched)?"Latched":"LevelSensitive"));
434 switch(translated_descriptor->ShareDisposition)
435 {
436 case CmResourceShareDeviceExclusive:
437 KdPrint((__DRIVER_NAME " ShareDisposition = CmResourceShareDeviceExclusive\n"));
438 break;
439 case CmResourceShareDriverExclusive:
440 KdPrint((__DRIVER_NAME " ShareDisposition = CmResourceShareDriverExclusive\n"));
441 break;
442 case CmResourceShareShared:
443 KdPrint((__DRIVER_NAME " ShareDisposition = CmResourceShareShared\n"));
444 break;
445 default:
446 KdPrint((__DRIVER_NAME " ShareDisposition = %d\n", translated_descriptor->ShareDisposition));
447 break;
448 }
449 break;
450 case CmResourceTypeDevicePrivate:
451 KdPrint((__DRIVER_NAME " Private Data: 0x%02x 0x%02x 0x%02x\n", translated_descriptor->u.DevicePrivate.Data[0], translated_descriptor->u.DevicePrivate.Data[1], translated_descriptor->u.DevicePrivate.Data[2]));
452 break;
453 default:
454 KdPrint((__DRIVER_NAME " Unhandled resource type (0x%x)\n", translated_descriptor->Type));
455 break;
456 }
457 }
459 FUNCTION_EXIT();
461 return status;
462 }
464 NTSTATUS
465 XenPci_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
466 {
467 NTSTATUS status = STATUS_SUCCESS;
468 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
470 UNREFERENCED_PARAMETER(previous_state);
472 FUNCTION_ENTER();
474 XenPci_Init(xpdd);
475 if (tpr_patch_requested && !xpdd->tpr_patched)
476 {
477 XenPci_MapHalThenPatchKernel(xpdd);
478 xpdd->tpr_patched = TRUE;
479 }
480 GntTbl_Init(xpdd);
481 EvtChn_Init(xpdd);
483 FUNCTION_EXIT();
485 return status;
486 }
488 NTSTATUS
489 XenPci_EvtDeviceD0EntryPostInterruptsEnabled(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
490 {
491 NTSTATUS status = STATUS_SUCCESS;
492 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
493 PCHAR response;
495 UNREFERENCED_PARAMETER(previous_state);
497 FUNCTION_ENTER();
499 XenBus_Init(xpdd);
501 response = XenBus_AddWatch(xpdd, XBT_NIL, SYSRQ_PATH, XenPci_SysrqHandler, xpdd);
503 response = XenBus_AddWatch(xpdd, XBT_NIL, SHUTDOWN_PATH, XenPci_ShutdownHandler, device);
505 response = XenBus_AddWatch(xpdd, XBT_NIL, "device", XenPci_DeviceWatchHandler, xpdd);
507 #if 0
508 response = XenBus_AddWatch(xpdd, XBT_NIL, BALLOON_PATH, XenPci_BalloonHandler, Device);
509 KdPrint((__DRIVER_NAME " balloon watch response = '%s'\n", response));
510 #endif
512 #if 0
513 status = IoSetDeviceInterfaceState(&xpdd->legacy_interface_name, TRUE);
514 if (!NT_SUCCESS(status))
515 {
516 KdPrint((__DRIVER_NAME " IoSetDeviceInterfaceState (legacy) failed with status 0x%08x\n", status));
517 }
519 status = IoSetDeviceInterfaceState(&xpdd->interface_name, TRUE);
520 if (!NT_SUCCESS(status))
521 {
522 KdPrint((__DRIVER_NAME " IoSetDeviceInterfaceState failed with status 0x%08x\n", status));
523 }
524 #endif
526 FUNCTION_EXIT();
528 return status;
529 }
531 NTSTATUS
532 XenPci_EvtDeviceD0ExitPreInterruptsDisabled(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
533 {
534 NTSTATUS status = STATUS_SUCCESS;
536 UNREFERENCED_PARAMETER(device);
537 UNREFERENCED_PARAMETER(target_state);
539 FUNCTION_ENTER();
540 FUNCTION_EXIT();
542 return status;
543 }
545 NTSTATUS
546 XenPci_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
547 {
548 NTSTATUS status = STATUS_SUCCESS;
550 UNREFERENCED_PARAMETER(device);
551 UNREFERENCED_PARAMETER(target_state);
553 FUNCTION_ENTER();
554 FUNCTION_EXIT();
556 return status;
557 }
559 NTSTATUS
560 XenPci_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
561 {
562 NTSTATUS status = STATUS_SUCCESS;
564 UNREFERENCED_PARAMETER(device);
565 UNREFERENCED_PARAMETER(resources_translated);
567 FUNCTION_ENTER();
568 FUNCTION_EXIT();
570 return status;
571 }
573 VOID
574 XenPci_EvtChildListScanForChildren(WDFCHILDLIST child_list)
575 {
576 NTSTATUS status;
577 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
578 char *msg;
579 char **devices;
580 char **instances;
581 int i, j;
582 CHAR path[128];
583 XENPCI_PDO_IDENTIFICATION_DESCRIPTION child_description;
585 FUNCTION_ENTER();
587 WdfChildListBeginScan(child_list);
589 msg = XenBus_List(xpdd, XBT_NIL, "device", &devices);
590 if (!msg)
591 {
592 for (i = 0; devices[i]; i++)
593 {
594 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s", devices[i]);
595 msg = XenBus_List(xpdd, XBT_NIL, path, &instances);
596 if (!msg)
597 {
598 for (j = 0; instances[j]; j++)
599 {
600 /* the device comparison is done as a memory compare so zero-ing the structure is important */
601 RtlZeroMemory(&child_description, sizeof(child_description));
602 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&child_description.header, sizeof(child_description));
603 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s/%s", devices[i], instances[j]);
604 RtlStringCbCopyA(child_description.path, ARRAY_SIZE(child_description.path), path);
605 RtlStringCbCopyA(child_description.device, ARRAY_SIZE(child_description.device), devices[i]);
606 child_description.index = atoi(instances[j]);
607 status = WdfChildListAddOrUpdateChildDescriptionAsPresent(child_list, &child_description.header, NULL);
608 if (!NT_SUCCESS(status))
609 {
610 KdPrint((__DRIVER_NAME " WdfChildListAddOrUpdateChildDescriptionAsPresent failed with status 0x%08x\n", status));
611 }
612 XenPci_FreeMem(instances[j]);
613 }
614 XenPci_FreeMem(instances);
615 }
616 else
617 {
618 // wtf do we do here???
619 KdPrint((__DRIVER_NAME " Failed to list %s tree\n", devices[i]));
620 }
621 XenPci_FreeMem(devices[i]);
622 }
623 XenPci_FreeMem(devices);
624 }
625 else
626 {
627 // wtf do we do here???
628 KdPrint((__DRIVER_NAME " Failed to list device tree\n"));
629 }
631 WdfChildListEndScan(child_list);
633 FUNCTION_EXIT();
634 }
636 #if 0
637 #if 0
638 static VOID
639 XenBus_BalloonHandler(char *Path, PVOID Data);
640 #endif
642 #pragma warning(disable : 4200) // zero-sized array
644 NTSTATUS
645 XenPci_Power_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
646 {
647 NTSTATUS status;
648 PIO_STACK_LOCATION stack;
649 POWER_STATE_TYPE power_type;
650 POWER_STATE power_state;
651 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
653 UNREFERENCED_PARAMETER(device_object);
655 FUNCTION_ENTER();
657 stack = IoGetCurrentIrpStackLocation(irp);
658 power_type = stack->Parameters.Power.Type;
659 power_state = stack->Parameters.Power.State;
661 switch (stack->MinorFunction)
662 {
663 case IRP_MN_POWER_SEQUENCE:
664 //irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
665 KdPrint((__DRIVER_NAME " IRP_MN_POWER_SEQUENCE\n"));
666 break;
667 case IRP_MN_QUERY_POWER:
668 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_POWER\n"));
669 break;
670 case IRP_MN_SET_POWER:
671 KdPrint((__DRIVER_NAME " IRP_MN_SET_POWER\n"));
672 switch (power_type) {
673 case DevicePowerState:
674 KdPrint((__DRIVER_NAME " DevicePowerState\n"));
675 break;
676 case SystemPowerState:
677 KdPrint((__DRIVER_NAME " SystemPowerState\n"));
678 break;
679 default:
680 KdPrint((__DRIVER_NAME " %d\n", power_type));
681 }
682 break;
683 case IRP_MN_WAIT_WAKE:
684 KdPrint((__DRIVER_NAME " IRP_MN_WAIT_WAKE\n"));
685 break;
686 default:
687 KdPrint((__DRIVER_NAME " IRP_MN_%d\n", stack->MinorFunction));
688 break;
689 }
690 PoStartNextPowerIrp(irp);
691 IoSkipCurrentIrpStackLocation(irp);
692 status = PoCallDriver(xpdd->common.lower_do, irp);
694 FUNCTION_EXIT();
696 return status;
697 }
699 NTSTATUS
700 XenPci_Dummy_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
701 {
702 NTSTATUS status;
703 PIO_STACK_LOCATION stack;
704 PXENPCI_DEVICE_DATA xpdd;
706 FUNCTION_ENTER();
708 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
709 stack = IoGetCurrentIrpStackLocation(irp);
710 IoSkipCurrentIrpStackLocation(irp);
711 status = IoCallDriver(xpdd->common.lower_do, irp);
713 FUNCTION_EXIT();
715 return status;
716 }
718 static NTSTATUS
719 XenPci_Pnp_IoCompletion(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
720 {
721 PKEVENT event = (PKEVENT)context;
723 UNREFERENCED_PARAMETER(device_object);
725 FUNCTION_ENTER();
727 if (irp->PendingReturned)
728 {
729 KeSetEvent(event, IO_NO_INCREMENT, FALSE);
730 }
732 FUNCTION_EXIT();
734 return STATUS_MORE_PROCESSING_REQUIRED;
735 }
737 static NTSTATUS
738 XenPci_QueueWorkItem(PDEVICE_OBJECT device_object, PIO_WORKITEM_ROUTINE routine, PVOID context)
739 {
740 PIO_WORKITEM work_item;
741 NTSTATUS status = STATUS_SUCCESS;
743 work_item = IoAllocateWorkItem(device_object);
744 IoQueueWorkItem(work_item, routine, DelayedWorkQueue, context);
746 return status;
747 }
749 static NTSTATUS
750 XenPci_SendAndWaitForIrp(PDEVICE_OBJECT device_object, PIRP irp)
751 {
752 NTSTATUS status;
753 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
754 KEVENT event;
756 UNREFERENCED_PARAMETER(device_object);
758 FUNCTION_ENTER();
760 KeInitializeEvent(&event, NotificationEvent, FALSE);
762 IoCopyCurrentIrpStackLocationToNext(irp);
763 IoSetCompletionRoutine(irp, XenPci_Pnp_IoCompletion, &event, TRUE, TRUE, TRUE);
765 status = IoCallDriver(xpdd->common.lower_do, irp);
767 if (status == STATUS_PENDING)
768 {
769 KdPrint((__DRIVER_NAME " waiting ...\n"));
770 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
771 KdPrint((__DRIVER_NAME " ... done\n"));
772 status = irp->IoStatus.Status;
773 }
775 FUNCTION_EXIT();
777 return status;
778 }
780 static NTSTATUS
781 XenPci_ProcessShutdownIrp(PXENPCI_DEVICE_DATA xpdd)
782 {
783 PIO_STACK_LOCATION stack;
784 NTSTATUS status;
785 PIRP irp;
786 KIRQL old_irql;
787 ULONG length;
789 FUNCTION_ENTER();
791 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
792 if (xpdd->shutdown_irp)
793 {
794 irp = xpdd->shutdown_irp;
795 stack = IoGetCurrentIrpStackLocation(irp);
796 KdPrint((__DRIVER_NAME " stack = %p\n", stack));
797 KdPrint((__DRIVER_NAME " length = %d, buffer = %p\n", stack->Parameters.Read.Length, irp->AssociatedIrp.SystemBuffer));
798 length = min(xpdd->shutdown_prod - xpdd->shutdown_cons, stack->Parameters.Read.Length);
799 KdPrint((__DRIVER_NAME " length = %d\n", length));
800 if (length > 0)
801 {
802 memcpy(irp->AssociatedIrp.SystemBuffer, &xpdd->shutdown_ring[xpdd->shutdown_cons & (SHUTDOWN_RING_SIZE - 1)], length);
803 xpdd->shutdown_cons += length;
804 if (xpdd->shutdown_cons > SHUTDOWN_RING_SIZE)
805 {
806 xpdd->shutdown_cons -= SHUTDOWN_RING_SIZE;
807 xpdd->shutdown_prod -= SHUTDOWN_RING_SIZE;
808 xpdd->shutdown_start -= SHUTDOWN_RING_SIZE;
809 }
810 xpdd->shutdown_irp = NULL;
811 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
812 status = STATUS_SUCCESS;
813 irp->IoStatus.Status = status;
814 irp->IoStatus.Information = length;
815 IoSetCancelRoutine(irp, NULL);
816 IoCompleteRequest(irp, IO_NO_INCREMENT);
817 }
818 else
819 {
820 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
821 KdPrint((__DRIVER_NAME " nothing to read... pending\n"));
822 IoMarkIrpPending(irp);
823 status = STATUS_PENDING;
824 }
825 }
826 else
827 {
828 KdPrint((__DRIVER_NAME " no pending irp\n"));
829 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
830 status = STATUS_SUCCESS;
831 }
833 FUNCTION_EXIT();
835 return status;
836 }
838 static VOID
839 XenBus_ShutdownIoCancel(PDEVICE_OBJECT device_object, PIRP irp)
840 {
841 PXENPCI_DEVICE_DATA xpdd;
842 KIRQL old_irql;
844 FUNCTION_ENTER();
846 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
847 IoReleaseCancelSpinLock(irp->CancelIrql);
848 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
849 if (irp == xpdd->shutdown_irp)
850 {
851 KdPrint((__DRIVER_NAME " Not the current irp???\n"));
852 xpdd->shutdown_irp = NULL;
853 }
854 irp->IoStatus.Status = STATUS_CANCELLED;
855 irp->IoStatus.Information = 0;
856 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
857 IoCompleteRequest(irp, IO_NO_INCREMENT);
859 FUNCTION_EXIT();
860 }
862 struct {
863 volatile ULONG do_spin;
864 volatile ULONG abort_spin;
865 volatile LONG nr_spinning;
866 KDPC dpcs[MAX_VIRT_CPUS];
867 KEVENT spin_event;
868 KEVENT resume_event;
869 } typedef SUSPEND_INFO, *PSUSPEND_INFO;
871 /* runs at PASSIVE_LEVEL */
872 static DDKAPI VOID
873 XenPci_CompleteResume(PDEVICE_OBJECT device_object, PVOID context)
874 {
875 PSUSPEND_INFO suspend_info = context;
876 PXENPCI_DEVICE_DATA xpdd;
877 PXEN_CHILD child;
879 UNREFERENCED_PARAMETER(context);
880 FUNCTION_ENTER();
882 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
884 while (suspend_info->nr_spinning)
885 {
886 KdPrint((__DRIVER_NAME " %d processors are still spinning\n", suspend_info->nr_spinning));
887 KeWaitForSingleObject(&suspend_info->spin_event, Executive, KernelMode, FALSE, NULL);
888 }
889 KdPrint((__DRIVER_NAME " all other processors have stopped spinning\n"));
891 XenBus_Resume(xpdd);
893 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
894 {
895 XenPci_Pdo_Resume(child->context->common.pdo);
896 }
898 xpdd->suspend_state = SUSPEND_STATE_NONE;
900 FUNCTION_EXIT();
901 }
903 /* Called at DISPATCH_LEVEL */
904 static DDKAPI VOID
905 XenPci_Suspend(
906 PRKDPC Dpc,
907 PVOID Context,
908 PVOID SystemArgument1,
909 PVOID SystemArgument2)
910 {
911 PXENPCI_DEVICE_DATA xpdd = Context;
912 PSUSPEND_INFO suspend_info = SystemArgument1;
913 ULONG ActiveProcessorCount;
914 KIRQL old_irql;
915 int cancelled = 0;
916 PXEN_CHILD child;
918 //PUCHAR gnttbl_backup[PAGE_SIZE * NR_GRANT_FRAMES];
920 UNREFERENCED_PARAMETER(Dpc);
921 UNREFERENCED_PARAMETER(SystemArgument2);
923 FUNCTION_ENTER();
924 FUNCTION_MSG("(CPU = %d)\n", KeGetCurrentProcessorNumber());
926 if (KeGetCurrentProcessorNumber() != 0)
927 {
928 KdPrint((__DRIVER_NAME " CPU %d spinning...\n", KeGetCurrentProcessorNumber()));
929 KeRaiseIrql(HIGH_LEVEL, &old_irql);
930 InterlockedIncrement(&suspend_info->nr_spinning);
931 while(suspend_info->do_spin && !suspend_info->abort_spin)
932 {
933 KeStallExecutionProcessor(1);
934 KeMemoryBarrier();
935 }
936 if (suspend_info->abort_spin)
937 {
938 KdPrint((__DRIVER_NAME " CPU %d spin aborted\n", KeGetCurrentProcessorNumber()));
939 KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000003, 0x00000001, 0x00000000, 0x00000000);
940 return;
941 }
942 KeLowerIrql(old_irql);
943 InterlockedDecrement(&suspend_info->nr_spinning);
944 KeSetEvent(&suspend_info->spin_event, IO_NO_INCREMENT, FALSE);
945 FUNCTION_EXIT();
946 return;
947 }
948 ActiveProcessorCount = (ULONG)KeNumberProcessors;
950 KeRaiseIrql(HIGH_LEVEL, &old_irql);
951 xpdd->suspend_state = SUSPEND_STATE_HIGH_IRQL;
952 while (suspend_info->nr_spinning < (LONG)ActiveProcessorCount - 1 && !suspend_info->abort_spin)
953 {
954 KeStallExecutionProcessor(1);
955 //HYPERVISOR_yield(xpdd);
956 KeMemoryBarrier();
957 }
958 if (suspend_info->abort_spin)
959 {
960 KdPrint((__DRIVER_NAME " CPU %d spin aborted\n", KeGetCurrentProcessorNumber()));
961 KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000003, 0x00000003, 0x00000000, 0x00000000);
962 return;
963 }
964 cancelled = hvm_shutdown(Context, SHUTDOWN_suspend);
965 KdPrint((__DRIVER_NAME " back from suspend, cancelled = %d\n", cancelled));
967 XenPci_Init(xpdd);
969 GntTbl_InitMap(Context);
971 /* this enables interrupts again too */
972 EvtChn_Init(xpdd);
974 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
975 {
976 child->context->device_state.resume_state = RESUME_STATE_BACKEND_RESUME;
977 }
978 KeLowerIrql(old_irql);
979 xpdd->suspend_state = SUSPEND_STATE_RESUMING;
980 suspend_info->do_spin = FALSE;
981 KeMemoryBarrier();
982 KeSetEvent(&suspend_info->resume_event, IO_NO_INCREMENT, FALSE);
983 FUNCTION_EXIT();
984 }
986 /* Called at PASSIVE_LEVEL */
987 static VOID DDKAPI
988 XenPci_BeginSuspend(PDEVICE_OBJECT device_object, PVOID context)
989 {
990 //KAFFINITY ActiveProcessorMask = 0; // this is for Vista+
991 PXENPCI_DEVICE_DATA xpdd = device_object->DeviceExtension;
992 ULONG ActiveProcessorCount;
993 ULONG i;
994 PSUSPEND_INFO suspend_info;
995 //PKDPC Dpc;
996 KIRQL OldIrql;
997 PXEN_CHILD child;
999 UNREFERENCED_PARAMETER(context);
1000 FUNCTION_ENTER();
1002 if (xpdd->suspend_state == SUSPEND_STATE_NONE)
1004 xpdd->suspend_state = SUSPEND_STATE_SCHEDULED;
1005 KeMemoryBarrier();
1007 suspend_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(SUSPEND_INFO), XENPCI_POOL_TAG);
1008 RtlZeroMemory(suspend_info, sizeof(SUSPEND_INFO));
1009 KeInitializeEvent(&suspend_info->spin_event, SynchronizationEvent, FALSE);
1010 KeInitializeEvent(&suspend_info->resume_event, SynchronizationEvent, FALSE);
1012 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
1014 XenPci_Pdo_Suspend(child->context->common.pdo);
1017 XenBus_Suspend(xpdd);
1019 EvtChn_Shutdown(xpdd);
1021 //ActiveProcessorCount = KeQueryActiveProcessorCount(&ActiveProcessorMask); // this is for Vista+
1022 ActiveProcessorCount = (ULONG)KeNumberProcessors;
1023 /* Go to HIGH_LEVEL to prevent any races with Dpc's on the current processor */
1024 KeRaiseIrql(HIGH_LEVEL, &OldIrql);
1025 suspend_info->do_spin = TRUE;
1026 for (i = 0; i < ActiveProcessorCount; i++)
1028 //Dpc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KDPC), XENPCI_POOL_TAG);
1029 KeInitializeDpc(&suspend_info->dpcs[i], XenPci_Suspend, xpdd);
1030 KeSetTargetProcessorDpc(&suspend_info->dpcs[i], (CCHAR)i);
1031 KeSetImportanceDpc(&suspend_info->dpcs[i], HighImportance);
1032 KdPrint((__DRIVER_NAME " queuing Dpc for CPU %d\n", i));
1033 KeInsertQueueDpc(&suspend_info->dpcs[i], suspend_info, NULL);
1035 KdPrint((__DRIVER_NAME " All Dpc's queued\n"));
1036 KeMemoryBarrier();
1037 KeLowerIrql(OldIrql);
1038 KdPrint((__DRIVER_NAME " Waiting for resume_event\n"));
1039 KeWaitForSingleObject(&suspend_info->resume_event, Executive, KernelMode, FALSE, NULL);
1040 KdPrint((__DRIVER_NAME " Got resume_event\n"));
1041 //xpdd->log_interrupts = TRUE;
1042 XenPci_CompleteResume(device_object, suspend_info);
1044 FUNCTION_EXIT();
1047 static void
1048 XenPci_ShutdownHandler(char *path, PVOID context)
1050 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)context;
1051 char *res;
1052 char *value;
1053 KIRQL old_irql;
1054 PIO_WORKITEM work_item;
1056 UNREFERENCED_PARAMETER(path);
1058 FUNCTION_ENTER();
1060 res = XenBus_Read(xpdd, XBT_NIL, SHUTDOWN_PATH, &value);
1061 if (res)
1063 KdPrint(("Error reading shutdown path - %s\n", res));
1064 XenPci_FreeMem(res);
1065 return;
1068 KdPrint((__DRIVER_NAME " Shutdown value = %s\n", value));
1070 if (strlen(value) != 0)
1072 if (strcmp(value, "suspend") == 0)
1074 KdPrint((__DRIVER_NAME " Suspend detected\n"));
1075 /* we have to queue this as a work item as we stop the xenbus thread, which we are currently running in! */
1076 work_item = IoAllocateWorkItem(xpdd->common.fdo);
1077 IoQueueWorkItem(work_item, XenPci_BeginSuspend, DelayedWorkQueue, NULL);
1078 //XenPci_BeginSuspend(xpdd);
1080 else
1082 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
1083 if (xpdd->shutdown_start >= xpdd->shutdown_cons)
1084 xpdd->shutdown_prod = xpdd->shutdown_start;
1085 else
1086 xpdd->shutdown_start = xpdd->shutdown_prod;
1087 memcpy(&xpdd->shutdown_ring[xpdd->shutdown_prod], value, strlen(value));
1088 xpdd->shutdown_prod += (ULONG)strlen(value);
1089 xpdd->shutdown_ring[xpdd->shutdown_prod++] = '\r';
1090 xpdd->shutdown_ring[xpdd->shutdown_prod++] = '\n';
1091 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
1092 XenPci_ProcessShutdownIrp(xpdd);
1096 //XenPci_FreeMem(value);
1098 FUNCTION_EXIT();
1101 static VOID
1102 XenPci_DumpPdoConfigs(PXENPCI_DEVICE_DATA xpdd)
1104 PXEN_CHILD child;
1106 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
1108 XenPci_DumpPdoConfig(child->context->common.pdo);
1112 static VOID
1113 XenPci_SysrqHandler(char *path, PVOID context)
1115 PXENPCI_DEVICE_DATA xpdd = context;
1116 char *value;
1117 char letter;
1118 char *res;
1120 UNREFERENCED_PARAMETER(path);
1122 FUNCTION_ENTER();
1124 XenBus_Read(xpdd, XBT_NIL, SYSRQ_PATH, &value);
1126 KdPrint((__DRIVER_NAME " SysRq Value = %s\n", value));
1128 if (value != NULL && strlen(value) != 0)
1130 letter = *value;
1131 res = XenBus_Write(xpdd, XBT_NIL, SYSRQ_PATH, "");
1132 if (res)
1134 KdPrint(("Error writing sysrq path\n"));
1135 XenPci_FreeMem(res);
1136 return;
1139 else
1141 letter = 0;
1144 if (value != NULL)
1146 XenPci_FreeMem(value);
1149 switch (letter)
1151 case 0:
1152 break;
1153 case 'B': /* cause a bug check */
1154 KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000001, 0x00000000, 0x00000000, 0x00000000);
1155 break;
1156 case 'X': /* stop delivering events */
1157 xpdd->interrupts_masked = TRUE;
1158 break;
1159 case 'C':
1160 /* show some debugging info */
1161 XenPci_DumpPdoConfigs(xpdd);
1162 break;
1163 default:
1164 KdPrint((" Unhandled sysrq letter %c\n", letter));
1165 break;
1168 FUNCTION_EXIT();
1171 static DDKAPI VOID
1172 XenPci_Pnp_StartDeviceCallback(PDEVICE_OBJECT device_object, PVOID context)
1174 NTSTATUS status = STATUS_SUCCESS;
1175 PXENPCI_DEVICE_DATA xpdd = device_object->DeviceExtension;
1176 PIRP irp = context;
1177 char *response;
1179 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1181 XenPci_Init(xpdd);
1183 GntTbl_Init(xpdd);
1185 EvtChn_Init(xpdd);
1186 EvtChn_ConnectInterrupt(xpdd);
1187 XenBus_Init(xpdd);
1189 response = XenBus_AddWatch(xpdd, XBT_NIL, SYSRQ_PATH, XenPci_SysrqHandler, xpdd);
1190 KdPrint((__DRIVER_NAME " sysrqwatch response = '%s'\n", response));
1192 #if 0
1193 response = XenBus_AddWatch(xpdd, XBT_NIL, SHUTDOWN_PATH, XenPci_ShutdownHandler, xpdd);
1194 KdPrint((__DRIVER_NAME " shutdown watch response = '%s'\n", response));
1195 #endif
1197 response = XenBus_AddWatch(xpdd, XBT_NIL, "device", XenPci_DeviceWatchHandler, xpdd);
1198 KdPrint((__DRIVER_NAME " device watch response = '%s'\n", response));
1200 #if 0
1201 response = XenBus_AddWatch(xpdd, XBT_NIL, BALLOON_PATH, XenPci_BalloonHandler, Device);
1202 KdPrint((__DRIVER_NAME " balloon watch response = '%s'\n", response));
1203 #endif
1205 status = IoSetDeviceInterfaceState(&xpdd->legacy_interface_name, TRUE);
1206 if (!NT_SUCCESS(status))
1208 KdPrint((__DRIVER_NAME " IoSetDeviceInterfaceState (legacy) failed with status 0x%08x\n", status));
1211 status = IoSetDeviceInterfaceState(&xpdd->interface_name, TRUE);
1212 if (!NT_SUCCESS(status))
1214 KdPrint((__DRIVER_NAME " IoSetDeviceInterfaceState failed with status 0x%08x\n", status));
1217 irp->IoStatus.Status = status;
1219 IoCompleteRequest(irp, IO_NO_INCREMENT);
1221 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1224 static NTSTATUS
1225 XenPci_Pnp_StartDevice(PDEVICE_OBJECT device_object, PIRP irp)
1227 NTSTATUS status;
1228 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1229 PIO_STACK_LOCATION stack;
1230 PCM_PARTIAL_RESOURCE_LIST res_list;
1231 PCM_PARTIAL_RESOURCE_DESCRIPTOR res_descriptor;
1232 ULONG i;
1234 UNREFERENCED_PARAMETER(device_object);
1236 FUNCTION_ENTER();
1238 stack = IoGetCurrentIrpStackLocation(irp);
1240 IoMarkIrpPending(irp);
1242 status = XenPci_SendAndWaitForIrp(device_object, irp);
1244 res_list = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
1246 for (i = 0; i < res_list->Count; i++)
1248 res_descriptor = &res_list->PartialDescriptors[i];
1249 switch (res_descriptor->Type)
1251 case CmResourceTypeInterrupt:
1252 KdPrint((__DRIVER_NAME " irq_number = %03x\n", res_descriptor->u.Interrupt.Vector));
1253 xpdd->irq_number = res_descriptor->u.Interrupt.Vector;
1254 //memcpy(&InterruptRaw, res_descriptor, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
1255 break;
1259 res_list = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
1261 for (i = 0; i < res_list->Count; i++)
1263 res_descriptor = &res_list->PartialDescriptors[i];
1264 switch (res_descriptor->Type) {
1265 case CmResourceTypePort:
1266 KdPrint((__DRIVER_NAME " IoPort Address(%x) Length: %d\n", res_descriptor->u.Port.Start.LowPart, res_descriptor->u.Port.Length));
1267 xpdd->platform_ioport_addr = res_descriptor->u.Port.Start.LowPart;
1268 xpdd->platform_ioport_len = res_descriptor->u.Port.Length;
1269 break;
1270 case CmResourceTypeMemory:
1271 KdPrint((__DRIVER_NAME " Memory mapped CSR:(%x:%x) Length:(%d)\n", res_descriptor->u.Memory.Start.LowPart, res_descriptor->u.Memory.Start.HighPart, res_descriptor->u.Memory.Length));
1272 KdPrint((__DRIVER_NAME " Memory flags = %04X\n", res_descriptor->Flags));
1273 xpdd->platform_mmio_addr = res_descriptor->u.Memory.Start;
1274 xpdd->platform_mmio_len = res_descriptor->u.Memory.Length;
1275 xpdd->platform_mmio_alloc = 0;
1276 xpdd->platform_mmio_flags = res_descriptor->Flags;
1277 break;
1278 case CmResourceTypeInterrupt:
1279 KdPrint((__DRIVER_NAME " irq_vector = %03x\n", res_descriptor->u.Interrupt.Vector));
1280 KdPrint((__DRIVER_NAME " irq_level = %03x\n", res_descriptor->u.Interrupt.Level));
1281 xpdd->irq_level = (KIRQL)res_descriptor->u.Interrupt.Level;
1282 xpdd->irq_vector = res_descriptor->u.Interrupt.Vector;
1283 xpdd->irq_affinity = res_descriptor->u.Interrupt.Affinity;
1285 xpdd->irq_mode = (res_descriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED)?Latched:LevelSensitive;
1286 KdPrint((__DRIVER_NAME " irq_mode = %s\n", (xpdd->irq_mode == Latched)?"Latched":"LevelSensitive"));
1287 switch(res_descriptor->ShareDisposition)
1289 case CmResourceShareDeviceExclusive:
1290 KdPrint((__DRIVER_NAME " ShareDisposition = CmResourceShareDeviceExclusive\n"));
1291 break;
1292 case CmResourceShareDriverExclusive:
1293 KdPrint((__DRIVER_NAME " ShareDisposition = CmResourceShareDriverExclusive\n"));
1294 break;
1295 case CmResourceShareShared:
1296 KdPrint((__DRIVER_NAME " ShareDisposition = CmResourceShareShared\n"));
1297 break;
1298 default:
1299 KdPrint((__DRIVER_NAME " ShareDisposition = %d\n", res_descriptor->ShareDisposition));
1300 break;
1302 break;
1303 case CmResourceTypeDevicePrivate:
1304 KdPrint((__DRIVER_NAME " Private Data: 0x%02x 0x%02x 0x%02x\n", res_descriptor->u.DevicePrivate.Data[0], res_descriptor->u.DevicePrivate.Data[1], res_descriptor->u.DevicePrivate.Data[2]));
1305 break;
1306 default:
1307 KdPrint((__DRIVER_NAME " Unhandled resource type (0x%x)\n", res_descriptor->Type));
1308 break;
1312 XenPci_QueueWorkItem(device_object, XenPci_Pnp_StartDeviceCallback, irp);
1314 FUNCTION_EXIT();
1316 return STATUS_PENDING;
1319 static NTSTATUS
1320 XenPci_Pnp_StopDevice(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
1322 NTSTATUS status = STATUS_SUCCESS;
1324 UNREFERENCED_PARAMETER(device_object);
1325 UNREFERENCED_PARAMETER(context);
1327 FUNCTION_ENTER();
1329 irp->IoStatus.Status = status;
1330 IoCompleteRequest(irp, IO_NO_INCREMENT);
1332 FUNCTION_EXIT();
1334 return irp->IoStatus.Status;
1337 static NTSTATUS
1338 XenPci_Pnp_QueryStopRemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
1340 NTSTATUS status;
1341 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1343 UNREFERENCED_PARAMETER(device_object);
1345 FUNCTION_ENTER();
1347 if (xpdd->common.device_usage_paging
1348 || xpdd->common.device_usage_dump
1349 || xpdd->common.device_usage_hibernation)
1351 /* We are in the paging or hibernation path - can't remove */
1352 status = irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1353 IoCompleteRequest(irp, IO_NO_INCREMENT);
1355 else
1357 IoSkipCurrentIrpStackLocation(irp);
1358 status = IoCallDriver(xpdd->common.lower_do, irp);
1361 FUNCTION_EXIT();
1363 return status;
1366 static NTSTATUS
1367 XenPci_Pnp_RemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
1369 NTSTATUS status;
1370 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1372 UNREFERENCED_PARAMETER(device_object);
1374 FUNCTION_ENTER();
1376 irp->IoStatus.Status = STATUS_SUCCESS;
1377 IoSkipCurrentIrpStackLocation(irp);
1378 status = IoCallDriver(xpdd->common.lower_do, irp);
1379 IoDetachDevice(xpdd->common.lower_do);
1381 FUNCTION_EXIT();
1383 return status;
1386 static DDKAPI VOID
1387 XenPci_Pnp_QueryBusRelationsCallback(PDEVICE_OBJECT device_object, PVOID context)
1389 NTSTATUS status = STATUS_SUCCESS;
1390 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1391 PXENPCI_PDO_DEVICE_DATA xppdd;
1392 PIRP irp = context;
1393 int device_count = 0;
1394 PDEVICE_RELATIONS dev_relations;
1395 PXEN_CHILD child, old_child;
1396 //char *response;
1397 char *msg;
1398 char **devices;
1399 char **instances;
1400 int i, j;
1401 CHAR path[128];
1402 PDEVICE_OBJECT pdo;
1403 PDEVICE_RELATIONS oldRelations;
1404 int prevcount, length;
1406 FUNCTION_ENTER();
1408 msg = XenBus_List(xpdd, XBT_NIL, "device", &devices);
1409 if (!msg)
1411 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
1413 if (child->state == CHILD_STATE_DELETED)
1415 KdPrint((__DRIVER_NAME " Found deleted child - this shouldn't happen\n" ));
1417 child->state = CHILD_STATE_DELETED;
1420 for (i = 0; devices[i]; i++)
1422 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s", devices[i]);
1423 msg = XenBus_List(xpdd, XBT_NIL, path, &instances);
1424 if (!msg)
1426 for (j = 0; instances[j]; j++)
1428 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s/%s", devices[i], instances[j]);
1430 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
1432 if (strcmp(child->context->path, path) == 0)
1434 KdPrint((__DRIVER_NAME " Existing device %s\n", path));
1435 ASSERT(child->state == CHILD_STATE_DELETED);
1436 child->state = CHILD_STATE_ADDED;
1437 device_count++;
1438 break;
1442 if (child == (PXEN_CHILD)&xpdd->child_list)
1444 KdPrint((__DRIVER_NAME " New device %s\n", path));
1445 child = ExAllocatePoolWithTag(NonPagedPool, sizeof(XEN_CHILD), XENPCI_POOL_TAG);
1446 child->state = CHILD_STATE_ADDED;
1447 status = IoCreateDevice(
1448 xpdd->common.fdo->DriverObject,
1449 sizeof(XENPCI_PDO_DEVICE_DATA),
1450 NULL,
1451 FILE_DEVICE_UNKNOWN,
1452 FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN,
1453 FALSE,
1454 &pdo);
1455 if (!NT_SUCCESS(status))
1457 KdPrint((__DRIVER_NAME " IoCreateDevice status = %08X\n", status));
1459 RtlZeroMemory(pdo->DeviceExtension, sizeof(XENPCI_PDO_DEVICE_DATA));
1460 child->context = xppdd = pdo->DeviceExtension;
1461 xppdd->common.fdo = NULL;
1462 xppdd->common.pdo = pdo;
1463 ObReferenceObject(pdo);
1464 xppdd->common.lower_do = NULL;
1465 INIT_PNP_STATE(&xppdd->common);
1466 xppdd->common.device_usage_paging = 0;
1467 xppdd->common.device_usage_dump = 0;
1468 xppdd->common.device_usage_hibernation = 0;
1469 xppdd->bus_fdo = xpdd->common.fdo;
1470 xppdd->bus_pdo = xpdd->common.pdo;
1471 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), path);
1472 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), devices[i]);
1473 xppdd->index = atoi(instances[j]);
1474 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
1475 xppdd->backend_state = XenbusStateUnknown;
1476 xppdd->backend_path[0] = '\0';
1477 InsertTailList(&xpdd->child_list, (PLIST_ENTRY)child);
1478 device_count++;
1480 XenPci_FreeMem(instances[j]);
1482 XenPci_FreeMem(instances);
1484 XenPci_FreeMem(devices[i]);
1486 XenPci_FreeMem(devices);
1488 //
1489 // Keep track of old relations structure
1490 //
1491 oldRelations = (PDEVICE_RELATIONS) irp->IoStatus.Information;
1492 if (oldRelations)
1494 prevcount = oldRelations->Count;
1496 else
1498 prevcount = 0;
1501 //
1502 // Need to allocate a new relations structure and add our
1503 // PDOs to it.
1504 //
1506 length = sizeof(DEVICE_RELATIONS) + ((device_count + prevcount) * sizeof (PDEVICE_OBJECT)) -1;
1508 dev_relations = (PDEVICE_RELATIONS) ExAllocatePoolWithTag (PagedPool, length, XENPCI_POOL_TAG);
1509 if (!dev_relations)
1511 KdPrint((__DRIVER_NAME "**** Failed to allocate a new buffer for query device relations\n"));
1512 //
1513 // Fail the IRP
1514 //
1515 irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES;
1516 IoCompleteRequest (irp, IO_NO_INCREMENT);
1517 return;
1520 //
1521 // Copy in the device objects so far
1522 //
1523 if (prevcount)
1525 RtlCopyMemory (dev_relations->Objects, oldRelations->Objects, prevcount * sizeof (PDEVICE_OBJECT));
1528 for (child = (PXEN_CHILD)xpdd->child_list.Flink, device_count = 0; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
1530 if (child->state == CHILD_STATE_ADDED)
1532 ObReferenceObject(child->context->common.pdo);
1533 dev_relations->Objects[prevcount++] = child->context->common.pdo;
1537 dev_relations->Count = prevcount + device_count;
1539 child = (PXEN_CHILD)xpdd->child_list.Flink;
1540 while (child != (PXEN_CHILD)&xpdd->child_list)
1542 if (child->state == CHILD_STATE_DELETED)
1544 KdPrint((__DRIVER_NAME " Removing deleted child from device list\n"));
1545 old_child = child;
1546 child = (PXEN_CHILD)child->entry.Flink;
1547 RemoveEntryList((PLIST_ENTRY)old_child);
1548 xppdd = old_child->context;
1549 xppdd->reported_missing = TRUE;
1550 ObDereferenceObject(xppdd->common.pdo);
1551 ExFreePoolWithTag(old_child, XENPCI_POOL_TAG);
1553 else
1555 child = (PXEN_CHILD)child->entry.Flink;
1559 status = STATUS_SUCCESS;
1561 else
1563 //
1564 // Fail the IRP
1565 //
1566 irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES;
1567 IoCompleteRequest (irp, IO_NO_INCREMENT);
1568 return;
1571 irp->IoStatus.Status = status;
1572 //
1573 // Replace the relations structure in the IRP with the new
1574 // one.
1575 //
1576 if (oldRelations)
1578 ExFreePool (oldRelations);
1580 irp->IoStatus.Information = (ULONG_PTR)dev_relations;
1582 IoCompleteRequest (irp, IO_NO_INCREMENT);
1584 FUNCTION_EXIT();
1587 static NTSTATUS
1588 XenPci_Pnp_QueryBusRelations(PDEVICE_OBJECT device_object, PIRP irp)
1590 NTSTATUS status;
1592 UNREFERENCED_PARAMETER(device_object);
1594 FUNCTION_ENTER();
1596 IoMarkIrpPending(irp);
1598 status = XenPci_SendAndWaitForIrp(device_object, irp);
1600 XenPci_QueueWorkItem(device_object, XenPci_Pnp_QueryBusRelationsCallback, irp);
1602 FUNCTION_EXIT();
1604 return STATUS_PENDING;
1607 static DDKAPI VOID
1608 XenPci_Pnp_FilterResourceRequirementsCallback(PDEVICE_OBJECT device_object, PVOID context)
1610 NTSTATUS status = STATUS_SUCCESS;
1611 //PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1612 PIRP irp = context;
1614 UNREFERENCED_PARAMETER(device_object);
1616 FUNCTION_ENTER();
1617 irp->IoStatus.Status = status;
1618 IoCompleteRequest (irp, IO_NO_INCREMENT);
1620 FUNCTION_EXIT();
1623 static NTSTATUS
1624 XenPci_Pnp_FilterResourceRequirements(PDEVICE_OBJECT device_object, PIRP irp)
1626 NTSTATUS status;
1628 UNREFERENCED_PARAMETER(device_object);
1630 FUNCTION_ENTER();
1632 IoMarkIrpPending(irp);
1634 status = XenPci_SendAndWaitForIrp(device_object, irp);
1636 XenPci_QueueWorkItem(device_object, XenPci_Pnp_FilterResourceRequirementsCallback, irp);
1638 FUNCTION_EXIT();
1640 return STATUS_PENDING;
1643 static NTSTATUS
1644 XenPci_Pnp_DeviceUsageNotification(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
1646 NTSTATUS status;
1647 PXENPCI_DEVICE_DATA xpdd;
1648 PIO_STACK_LOCATION stack;
1650 UNREFERENCED_PARAMETER(context);
1652 FUNCTION_ENTER();
1654 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1655 stack = IoGetCurrentIrpStackLocation(irp);
1656 status = irp->IoStatus.Status;
1658 /* fail if we are in a stop or remove pending state */
1659 if (!NT_SUCCESS(irp->IoStatus.Status))
1661 switch (stack->Parameters.UsageNotification.Type)
1663 case DeviceUsageTypePaging:
1664 if (stack->Parameters.UsageNotification.InPath)
1665 xpdd->common.device_usage_paging--;
1666 else
1667 xpdd->common.device_usage_paging++;
1668 break;
1669 case DeviceUsageTypeDumpFile:
1670 if (stack->Parameters.UsageNotification.InPath)
1671 xpdd->common.device_usage_dump--;
1672 else
1673 xpdd->common.device_usage_dump++;
1674 break;
1675 case DeviceUsageTypeHibernation:
1676 if (stack->Parameters.UsageNotification.InPath)
1677 xpdd->common.device_usage_hibernation--;
1678 else
1679 xpdd->common.device_usage_hibernation++;
1680 break;
1681 default:
1682 KdPrint((__DRIVER_NAME " Unknown usage type %x\n",
1683 stack->Parameters.UsageNotification.Type));
1684 break;
1686 if (xpdd->common.device_usage_paging
1687 || xpdd->common.device_usage_dump
1688 || xpdd->common.device_usage_hibernation)
1690 xpdd->common.fdo->Flags &= ~DO_POWER_PAGABLE;
1692 IoInvalidateDeviceState(xpdd->common.pdo);
1694 IoCompleteRequest(irp, IO_NO_INCREMENT);
1696 FUNCTION_EXIT();
1698 return status;
1702 NTSTATUS
1703 XenPci_Pnp_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1705 NTSTATUS status;
1706 PIO_STACK_LOCATION stack;
1707 PXENPCI_DEVICE_DATA xpdd = device_object->DeviceExtension;;
1709 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1711 stack = IoGetCurrentIrpStackLocation(irp);
1713 switch (stack->MinorFunction)
1715 case IRP_MN_START_DEVICE:
1716 KdPrint((__DRIVER_NAME " IRP_MN_START_DEVICE\n"));
1717 return XenPci_Pnp_StartDevice(device_object, irp);
1719 case IRP_MN_QUERY_STOP_DEVICE:
1720 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_STOP_DEVICE\n"));
1721 status = XenPci_Pnp_QueryStopRemoveDevice(device_object, irp);
1722 if (NT_SUCCESS(status))
1723 SET_PNP_STATE(&xpdd->common, RemovePending);
1724 return status;
1726 case IRP_MN_STOP_DEVICE:
1727 KdPrint((__DRIVER_NAME " IRP_MN_STOP_DEVICE\n"));
1728 IoCopyCurrentIrpStackLocationToNext(irp);
1729 IoSetCompletionRoutine(irp, XenPci_Pnp_StopDevice, NULL, TRUE, TRUE, TRUE);
1730 break;
1732 case IRP_MN_CANCEL_STOP_DEVICE:
1733 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_STOP_DEVICE\n"));
1734 IoSkipCurrentIrpStackLocation(irp);
1735 REVERT_PNP_STATE(&xpdd->common);
1736 irp->IoStatus.Status = STATUS_SUCCESS;
1737 break;
1739 case IRP_MN_QUERY_REMOVE_DEVICE:
1740 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_REMOVE_DEVICE\n"));
1741 status = XenPci_Pnp_QueryStopRemoveDevice(device_object, irp);
1742 if (NT_SUCCESS(status))
1743 SET_PNP_STATE(&xpdd->common, RemovePending);
1744 return status;
1746 case IRP_MN_REMOVE_DEVICE:
1747 KdPrint((__DRIVER_NAME " IRP_MN_REMOVE_DEVICE\n"));
1748 return XenPci_Pnp_RemoveDevice(device_object, irp);
1749 break;
1751 case IRP_MN_CANCEL_REMOVE_DEVICE:
1752 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_REMOVE_DEVICE\n"));
1753 IoSkipCurrentIrpStackLocation(irp);
1754 REVERT_PNP_STATE(&xpdd->common);
1755 irp->IoStatus.Status = STATUS_SUCCESS;
1756 break;
1758 case IRP_MN_SURPRISE_REMOVAL:
1759 KdPrint((__DRIVER_NAME " IRP_MN_SURPRISE_REMOVAL\n"));
1760 IoSkipCurrentIrpStackLocation(irp);
1761 irp->IoStatus.Status = STATUS_SUCCESS;
1762 break;
1764 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1765 KdPrint((__DRIVER_NAME " IRP_MN_DEVICE_USAGE_NOTIFICATION\n"));
1766 switch (stack->Parameters.UsageNotification.Type)
1768 case DeviceUsageTypePaging:
1769 KdPrint((__DRIVER_NAME " type = DeviceUsageTypePaging = %d\n", stack->Parameters.UsageNotification.InPath));
1770 if (stack->Parameters.UsageNotification.InPath)
1771 xpdd->common.device_usage_paging++;
1772 else
1773 xpdd->common.device_usage_paging--;
1774 irp->IoStatus.Status = STATUS_SUCCESS;
1775 break;
1776 case DeviceUsageTypeDumpFile:
1777 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeDumpFile = %d\n", stack->Parameters.UsageNotification.InPath));
1778 if (stack->Parameters.UsageNotification.InPath)
1779 xpdd->common.device_usage_dump++;
1780 else
1781 xpdd->common.device_usage_dump--;
1782 irp->IoStatus.Status = STATUS_SUCCESS;
1783 break;
1784 case DeviceUsageTypeHibernation:
1785 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeHibernation = %d\n", stack->Parameters.UsageNotification.InPath));
1786 if (stack->Parameters.UsageNotification.InPath)
1787 xpdd->common.device_usage_hibernation++;
1788 else
1789 xpdd->common.device_usage_hibernation--;
1790 irp->IoStatus.Status = STATUS_SUCCESS;
1791 break;
1792 default:
1793 KdPrint((__DRIVER_NAME " type = unsupported (%d)\n", stack->Parameters.UsageNotification.Type));
1794 irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
1795 IoCompleteRequest(irp, IO_NO_INCREMENT);
1796 return STATUS_NOT_SUPPORTED;
1798 if (!xpdd->common.device_usage_paging
1799 && !xpdd->common.device_usage_dump
1800 && !xpdd->common.device_usage_hibernation)
1802 xpdd->common.fdo->Flags |= DO_POWER_PAGABLE;
1804 IoInvalidateDeviceState(xpdd->common.pdo);
1805 IoCopyCurrentIrpStackLocationToNext(irp);
1806 IoSetCompletionRoutine(irp, XenPci_Pnp_DeviceUsageNotification, NULL, TRUE, TRUE, TRUE);
1807 break;
1809 case IRP_MN_QUERY_DEVICE_RELATIONS:
1810 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_RELATIONS\n"));
1811 switch (stack->Parameters.QueryDeviceRelations.Type)
1813 case BusRelations:
1814 KdPrint((__DRIVER_NAME " BusRelations\n"));
1815 return XenPci_Pnp_QueryBusRelations(device_object, irp);
1816 break;
1817 default:
1818 IoSkipCurrentIrpStackLocation(irp);
1819 break;
1821 break;
1823 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1824 KdPrint((__DRIVER_NAME " IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"));
1825 return XenPci_Pnp_FilterResourceRequirements(device_object, irp);
1827 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1828 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_PNP_DEVICE_STATE\n"));
1829 irp->IoStatus.Status = STATUS_SUCCESS;
1830 if (xpdd->common.device_usage_paging
1831 || xpdd->common.device_usage_dump
1832 || xpdd->common.device_usage_hibernation)
1834 irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
1836 IoSkipCurrentIrpStackLocation(irp);
1837 break;
1839 default:
1840 KdPrint((__DRIVER_NAME " Unhandled Minor = %d\n", stack->MinorFunction));
1841 IoSkipCurrentIrpStackLocation(irp);
1842 break;
1845 status = IoCallDriver(xpdd->common.lower_do, irp);
1847 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1849 return status;
1852 NTSTATUS
1853 XenPci_Irp_Create_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1855 PXENPCI_DEVICE_DATA xpdd;
1856 NTSTATUS status;
1857 PIO_STACK_LOCATION stack;
1858 PFILE_OBJECT file;
1860 FUNCTION_ENTER();
1862 stack = IoGetCurrentIrpStackLocation(irp);
1863 file = stack->FileObject;
1865 KdPrint((__DRIVER_NAME " filename = %wZ\n", &file->FileName));
1866 if (wcscmp(L"\\xenbus", file->FileName.Buffer) == 0)
1868 status = XenPci_Irp_Create_XenBus(device_object, irp);
1870 else
1872 // legacy interface
1873 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1874 file->FsContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(ULONG), XENPCI_POOL_TAG);
1875 *(PULONG)file->FsContext = DEVICE_INTERFACE_TYPE_LEGACY;
1876 status = STATUS_SUCCESS;
1877 irp->IoStatus.Status = status;
1878 IoCompleteRequest(irp, IO_NO_INCREMENT);
1880 KdPrint((__DRIVER_NAME " context = %p\n", file->FsContext));
1881 KdPrint((__DRIVER_NAME " type = %d\n", *(PULONG)file->FsContext));
1882 FUNCTION_EXIT();
1884 return status;
1887 NTSTATUS
1888 XenPci_Irp_Close_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1890 PXENPCI_DEVICE_DATA xpdd;
1891 NTSTATUS status;
1892 PIO_STACK_LOCATION stack;
1893 PFILE_OBJECT file;
1895 FUNCTION_ENTER();
1897 stack = IoGetCurrentIrpStackLocation(irp);
1898 file = stack->FileObject;
1900 if (*(PULONG)file->FsContext == DEVICE_INTERFACE_TYPE_XENBUS)
1902 status = XenPci_Irp_Close_XenBus(device_object, irp);
1904 else
1906 // wait until pending irp's
1907 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1908 status = STATUS_SUCCESS;
1909 irp->IoStatus.Status = status;
1910 IoCompleteRequest(irp, IO_NO_INCREMENT);
1913 FUNCTION_EXIT();
1915 return status;
1918 NTSTATUS
1919 XenPci_Irp_Read_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1921 PXENPCI_DEVICE_DATA xpdd;
1922 NTSTATUS status;
1923 PIO_STACK_LOCATION stack;
1924 KIRQL old_irql;
1925 PFILE_OBJECT file;
1927 FUNCTION_ENTER();
1929 stack = IoGetCurrentIrpStackLocation(irp);
1930 file = stack->FileObject;
1932 if (*(PULONG)file->FsContext == DEVICE_INTERFACE_TYPE_XENBUS)
1934 status = XenPci_Irp_Read_XenBus(device_object, irp);
1936 else
1938 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1939 stack = IoGetCurrentIrpStackLocation(irp);
1940 if (stack->Parameters.Read.Length == 0)
1942 irp->IoStatus.Information = 0;
1943 status = STATUS_SUCCESS;
1944 irp->IoStatus.Status = status;
1945 IoCompleteRequest(irp, IO_NO_INCREMENT);
1947 else
1949 KdPrint((__DRIVER_NAME " stack = %p\n", stack));
1950 KdPrint((__DRIVER_NAME " length = %d, buffer = %p\n", stack->Parameters.Read.Length, irp->AssociatedIrp.SystemBuffer));
1952 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
1953 xpdd->shutdown_irp = irp;
1954 IoSetCancelRoutine(irp, XenBus_ShutdownIoCancel);
1955 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
1956 status = XenPci_ProcessShutdownIrp(xpdd);
1959 FUNCTION_EXIT();
1961 return status;
1964 NTSTATUS
1965 XenPci_Irp_Write_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1967 PXENPCI_DEVICE_DATA xpdd;
1968 NTSTATUS status;
1969 PIO_STACK_LOCATION stack;
1970 PFILE_OBJECT file;
1972 FUNCTION_ENTER();
1974 stack = IoGetCurrentIrpStackLocation(irp);
1975 file = stack->FileObject;
1977 KdPrint((__DRIVER_NAME " context = %p\n", file->FsContext));
1978 KdPrint((__DRIVER_NAME " type = %d\n", *(PULONG)file->FsContext));
1980 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1981 stack = IoGetCurrentIrpStackLocation(irp);
1983 if (*(PULONG)file->FsContext == DEVICE_INTERFACE_TYPE_XENBUS)
1985 status = XenPci_Irp_Write_XenBus(device_object, irp);
1987 else
1989 status = STATUS_UNSUCCESSFUL;
1990 irp->IoStatus.Status = status;
1991 IoCompleteRequest(irp, IO_NO_INCREMENT);
1994 FUNCTION_EXIT();
1996 return status;
1999 NTSTATUS
2000 XenPci_Irp_Cleanup_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
2002 NTSTATUS status;
2003 PIO_STACK_LOCATION stack;
2004 PFILE_OBJECT file;
2006 UNREFERENCED_PARAMETER(device_object);
2008 FUNCTION_ENTER();
2010 stack = IoGetCurrentIrpStackLocation(irp);
2011 file = stack->FileObject;
2013 if (*(PULONG)file->FsContext == DEVICE_INTERFACE_TYPE_XENBUS)
2015 status = XenPci_Irp_Cleanup_XenBus(device_object, irp);
2017 else
2019 status = STATUS_SUCCESS;
2020 irp->IoStatus.Status = status;
2021 IoCompleteRequest(irp, IO_NO_INCREMENT);
2023 FUNCTION_EXIT();
2025 return status;
2028 DDKAPI NTSTATUS
2029 XenPci_SystemControl_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
2031 NTSTATUS status;
2032 PIO_STACK_LOCATION stack;
2033 PXENPCI_COMMON common = device_object->DeviceExtension;
2035 FUNCTION_ENTER();
2037 UNREFERENCED_PARAMETER(device_object);
2039 stack = IoGetCurrentIrpStackLocation(irp);
2040 DbgPrint(__DRIVER_NAME " Minor = %d\n", stack->MinorFunction);
2041 IoSkipCurrentIrpStackLocation(irp);
2042 status = IoCallDriver(common->lower_do, irp);
2044 FUNCTION_EXIT();
2046 return status;
2049 #endif
2051 #if 0
2052 static VOID
2053 XenPci_BalloonHandler(char *Path, PVOID Data)
2055 WDFDEVICE Device = Data;
2056 char *value;
2057 xenbus_transaction_t xbt;
2058 int retry;
2060 UNREFERENCED_PARAMETER(Path);
2062 KdPrint((__DRIVER_NAME " --> XenBus_BalloonHandler\n"));
2064 XenBus_StartTransaction(Device, &xbt);
2066 XenBus_Read(Device, XBT_NIL, BALLOON_PATH, &value);
2068 KdPrint((__DRIVER_NAME " Balloon Value = %s\n", value));
2070 // use the memory_op(unsigned int op, void *arg) hypercall to adjust this
2071 // use XENMEM_increase_reservation and XENMEM_decrease_reservation
2073 XenBus_EndTransaction(Device, xbt, 0, &retry);
2075 XenPci_FreeMem(value);
2077 KdPrint((__DRIVER_NAME " <-- XenBus_BalloonHandler\n"));
2079 #endif