win-pvdrivers

view xenpci/xenpci_fdo.c @ 547:ac614e49832c

Fixed another typo
author James Harper <james.harper@bendigoit.com.au>
date Sun Mar 08 14:37:45 2009 +1100 (2009-03-08)
parents e75bb8d68370
children a88fe72e3597
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 FUNCTION_ENTER();
472 xpdd->hibernated = FALSE;
474 switch (previous_state)
475 {
476 case WdfPowerDeviceD0:
477 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
478 break;
479 case WdfPowerDeviceD1:
480 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
481 break;
482 case WdfPowerDeviceD2:
483 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
484 break;
485 case WdfPowerDeviceD3:
486 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
487 break;
488 case WdfPowerDeviceD3Final:
489 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
490 break;
491 case WdfPowerDevicePrepareForHibernation:
492 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
493 break;
494 default:
495 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
496 break;
497 }
499 XenPci_Init(xpdd);
500 if (tpr_patch_requested && !xpdd->tpr_patched)
501 {
502 XenPci_MapHalThenPatchKernel(xpdd);
503 xpdd->tpr_patched = TRUE;
504 }
505 GntTbl_Init(xpdd);
506 EvtChn_Init(xpdd);
508 FUNCTION_EXIT();
510 return status;
511 }
513 NTSTATUS
514 XenPci_EvtDeviceD0EntryPostInterruptsEnabled(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
515 {
516 NTSTATUS status = STATUS_SUCCESS;
517 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
518 PCHAR response;
520 UNREFERENCED_PARAMETER(previous_state);
522 FUNCTION_ENTER();
524 XenBus_Init(xpdd);
526 response = XenBus_AddWatch(xpdd, XBT_NIL, SYSRQ_PATH, XenPci_SysrqHandler, xpdd);
528 response = XenBus_AddWatch(xpdd, XBT_NIL, SHUTDOWN_PATH, XenPci_ShutdownHandler, device);
530 response = XenBus_AddWatch(xpdd, XBT_NIL, "device", XenPci_DeviceWatchHandler, xpdd);
532 #if 0
533 response = XenBus_AddWatch(xpdd, XBT_NIL, BALLOON_PATH, XenPci_BalloonHandler, Device);
534 KdPrint((__DRIVER_NAME " balloon watch response = '%s'\n", response));
535 #endif
537 #if 0
538 status = IoSetDeviceInterfaceState(&xpdd->legacy_interface_name, TRUE);
539 if (!NT_SUCCESS(status))
540 {
541 KdPrint((__DRIVER_NAME " IoSetDeviceInterfaceState (legacy) failed with status 0x%08x\n", status));
542 }
544 status = IoSetDeviceInterfaceState(&xpdd->interface_name, TRUE);
545 if (!NT_SUCCESS(status))
546 {
547 KdPrint((__DRIVER_NAME " IoSetDeviceInterfaceState failed with status 0x%08x\n", status));
548 }
549 #endif
551 FUNCTION_EXIT();
553 return status;
554 }
556 NTSTATUS
557 XenPci_EvtDeviceD0ExitPreInterruptsDisabled(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
558 {
559 NTSTATUS status = STATUS_SUCCESS;
561 UNREFERENCED_PARAMETER(device);
563 FUNCTION_ENTER();
565 switch (target_state)
566 {
567 case WdfPowerDeviceD0:
568 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
569 break;
570 case WdfPowerDeviceD1:
571 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
572 break;
573 case WdfPowerDeviceD2:
574 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
575 break;
576 case WdfPowerDeviceD3:
577 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
578 break;
579 case WdfPowerDeviceD3Final:
580 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
581 break;
582 case WdfPowerDevicePrepareForHibernation:
583 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
584 break;
585 default:
586 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
587 break;
588 }
590 FUNCTION_EXIT();
592 return status;
593 }
595 NTSTATUS
596 XenPci_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
597 {
598 NTSTATUS status = STATUS_SUCCESS;
599 PXENPCI_DEVICE_DATA xpdd = GetXpdd(device);
601 FUNCTION_ENTER();
603 switch (target_state)
604 {
605 case WdfPowerDeviceD0:
606 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
607 break;
608 case WdfPowerDeviceD1:
609 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
610 break;
611 case WdfPowerDeviceD2:
612 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
613 break;
614 case WdfPowerDeviceD3:
615 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
616 break;
617 case WdfPowerDeviceD3Final:
618 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
619 break;
620 case WdfPowerDevicePrepareForHibernation:
621 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
622 xpdd->hibernated = TRUE;
623 break;
624 default:
625 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
626 break;
627 }
629 FUNCTION_EXIT();
631 return status;
632 }
634 NTSTATUS
635 XenPci_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
636 {
637 NTSTATUS status = STATUS_SUCCESS;
639 UNREFERENCED_PARAMETER(device);
640 UNREFERENCED_PARAMETER(resources_translated);
642 FUNCTION_ENTER();
643 FUNCTION_EXIT();
645 return status;
646 }
648 VOID
649 XenPci_EvtChildListScanForChildren(WDFCHILDLIST child_list)
650 {
651 NTSTATUS status;
652 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
653 char *msg;
654 char **devices;
655 char **instances;
656 ULONG i, j;
657 CHAR path[128];
658 XENPCI_PDO_IDENTIFICATION_DESCRIPTION child_description;
660 FUNCTION_ENTER();
662 WdfChildListBeginScan(child_list);
664 msg = XenBus_List(xpdd, XBT_NIL, "device", &devices);
665 if (!msg)
666 {
667 for (i = 0; devices[i]; i++)
668 {
669 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s", devices[i]);
671 for (j = 0; j < WdfCollectionGetCount(xpdd->veto_devices); j++)
672 {
673 WDFOBJECT ws = WdfCollectionGetItem(xpdd->veto_devices, j);
674 UNICODE_STRING val;
675 ANSI_STRING s;
676 WdfStringGetUnicodeString(ws, &val);
677 RtlUnicodeStringToAnsiString(&s, &val, TRUE);
678 if (!strcmp(devices[i], s.Buffer))
679 {
680 RtlFreeAnsiString(&s);
681 break;
682 }
683 RtlFreeAnsiString(&s);
684 }
685 if (j < WdfCollectionGetCount(xpdd->veto_devices))
686 {
687 XenPci_FreeMem(devices[i]);
688 continue;
689 }
691 msg = XenBus_List(xpdd, XBT_NIL, path, &instances);
692 if (!msg)
693 {
694 for (j = 0; instances[j]; j++)
695 {
696 /* the device comparison is done as a memory compare so zero-ing the structure is important */
697 RtlZeroMemory(&child_description, sizeof(child_description));
698 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&child_description.header, sizeof(child_description));
699 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s/%s", devices[i], instances[j]);
700 RtlStringCbCopyA(child_description.path, ARRAY_SIZE(child_description.path), path);
701 RtlStringCbCopyA(child_description.device, ARRAY_SIZE(child_description.device), devices[i]);
702 child_description.index = atoi(instances[j]);
703 status = WdfChildListAddOrUpdateChildDescriptionAsPresent(child_list, &child_description.header, NULL);
704 if (!NT_SUCCESS(status))
705 {
706 KdPrint((__DRIVER_NAME " WdfChildListAddOrUpdateChildDescriptionAsPresent failed with status 0x%08x\n", status));
707 }
708 XenPci_FreeMem(instances[j]);
709 }
710 XenPci_FreeMem(instances);
711 }
712 else
713 {
714 // wtf do we do here???
715 KdPrint((__DRIVER_NAME " Failed to list %s tree\n", devices[i]));
716 }
717 XenPci_FreeMem(devices[i]);
718 }
719 XenPci_FreeMem(devices);
720 }
721 else
722 {
723 // wtf do we do here???
724 KdPrint((__DRIVER_NAME " Failed to list device tree\n"));
725 }
727 WdfChildListEndScan(child_list);
729 FUNCTION_EXIT();
730 }
732 #if 0
733 #if 0
734 static VOID
735 XenBus_BalloonHandler(char *Path, PVOID Data);
736 #endif
738 #pragma warning(disable : 4200) // zero-sized array
740 NTSTATUS
741 XenPci_Power_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
742 {
743 NTSTATUS status;
744 PIO_STACK_LOCATION stack;
745 POWER_STATE_TYPE power_type;
746 POWER_STATE power_state;
747 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
749 UNREFERENCED_PARAMETER(device_object);
751 FUNCTION_ENTER();
753 stack = IoGetCurrentIrpStackLocation(irp);
754 power_type = stack->Parameters.Power.Type;
755 power_state = stack->Parameters.Power.State;
757 switch (stack->MinorFunction)
758 {
759 case IRP_MN_POWER_SEQUENCE:
760 //irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
761 KdPrint((__DRIVER_NAME " IRP_MN_POWER_SEQUENCE\n"));
762 break;
763 case IRP_MN_QUERY_POWER:
764 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_POWER\n"));
765 break;
766 case IRP_MN_SET_POWER:
767 KdPrint((__DRIVER_NAME " IRP_MN_SET_POWER\n"));
768 switch (power_type) {
769 case DevicePowerState:
770 KdPrint((__DRIVER_NAME " DevicePowerState\n"));
771 break;
772 case SystemPowerState:
773 KdPrint((__DRIVER_NAME " SystemPowerState\n"));
774 break;
775 default:
776 KdPrint((__DRIVER_NAME " %d\n", power_type));
777 }
778 break;
779 case IRP_MN_WAIT_WAKE:
780 KdPrint((__DRIVER_NAME " IRP_MN_WAIT_WAKE\n"));
781 break;
782 default:
783 KdPrint((__DRIVER_NAME " IRP_MN_%d\n", stack->MinorFunction));
784 break;
785 }
786 PoStartNextPowerIrp(irp);
787 IoSkipCurrentIrpStackLocation(irp);
788 status = PoCallDriver(xpdd->common.lower_do, irp);
790 FUNCTION_EXIT();
792 return status;
793 }
795 NTSTATUS
796 XenPci_Dummy_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
797 {
798 NTSTATUS status;
799 PIO_STACK_LOCATION stack;
800 PXENPCI_DEVICE_DATA xpdd;
802 FUNCTION_ENTER();
804 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
805 stack = IoGetCurrentIrpStackLocation(irp);
806 IoSkipCurrentIrpStackLocation(irp);
807 status = IoCallDriver(xpdd->common.lower_do, irp);
809 FUNCTION_EXIT();
811 return status;
812 }
814 static NTSTATUS
815 XenPci_Pnp_IoCompletion(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
816 {
817 PKEVENT event = (PKEVENT)context;
819 UNREFERENCED_PARAMETER(device_object);
821 FUNCTION_ENTER();
823 if (irp->PendingReturned)
824 {
825 KeSetEvent(event, IO_NO_INCREMENT, FALSE);
826 }
828 FUNCTION_EXIT();
830 return STATUS_MORE_PROCESSING_REQUIRED;
831 }
833 static NTSTATUS
834 XenPci_QueueWorkItem(PDEVICE_OBJECT device_object, PIO_WORKITEM_ROUTINE routine, PVOID context)
835 {
836 PIO_WORKITEM work_item;
837 NTSTATUS status = STATUS_SUCCESS;
839 work_item = IoAllocateWorkItem(device_object);
840 IoQueueWorkItem(work_item, routine, DelayedWorkQueue, context);
842 return status;
843 }
845 static NTSTATUS
846 XenPci_SendAndWaitForIrp(PDEVICE_OBJECT device_object, PIRP irp)
847 {
848 NTSTATUS status;
849 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
850 KEVENT event;
852 UNREFERENCED_PARAMETER(device_object);
854 FUNCTION_ENTER();
856 KeInitializeEvent(&event, NotificationEvent, FALSE);
858 IoCopyCurrentIrpStackLocationToNext(irp);
859 IoSetCompletionRoutine(irp, XenPci_Pnp_IoCompletion, &event, TRUE, TRUE, TRUE);
861 status = IoCallDriver(xpdd->common.lower_do, irp);
863 if (status == STATUS_PENDING)
864 {
865 KdPrint((__DRIVER_NAME " waiting ...\n"));
866 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
867 KdPrint((__DRIVER_NAME " ... done\n"));
868 status = irp->IoStatus.Status;
869 }
871 FUNCTION_EXIT();
873 return status;
874 }
876 static NTSTATUS
877 XenPci_ProcessShutdownIrp(PXENPCI_DEVICE_DATA xpdd)
878 {
879 PIO_STACK_LOCATION stack;
880 NTSTATUS status;
881 PIRP irp;
882 KIRQL old_irql;
883 ULONG length;
885 FUNCTION_ENTER();
887 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
888 if (xpdd->shutdown_irp)
889 {
890 irp = xpdd->shutdown_irp;
891 stack = IoGetCurrentIrpStackLocation(irp);
892 KdPrint((__DRIVER_NAME " stack = %p\n", stack));
893 KdPrint((__DRIVER_NAME " length = %d, buffer = %p\n", stack->Parameters.Read.Length, irp->AssociatedIrp.SystemBuffer));
894 length = min(xpdd->shutdown_prod - xpdd->shutdown_cons, stack->Parameters.Read.Length);
895 KdPrint((__DRIVER_NAME " length = %d\n", length));
896 if (length > 0)
897 {
898 memcpy(irp->AssociatedIrp.SystemBuffer, &xpdd->shutdown_ring[xpdd->shutdown_cons & (SHUTDOWN_RING_SIZE - 1)], length);
899 xpdd->shutdown_cons += length;
900 if (xpdd->shutdown_cons > SHUTDOWN_RING_SIZE)
901 {
902 xpdd->shutdown_cons -= SHUTDOWN_RING_SIZE;
903 xpdd->shutdown_prod -= SHUTDOWN_RING_SIZE;
904 xpdd->shutdown_start -= SHUTDOWN_RING_SIZE;
905 }
906 xpdd->shutdown_irp = NULL;
907 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
908 status = STATUS_SUCCESS;
909 irp->IoStatus.Status = status;
910 irp->IoStatus.Information = length;
911 IoSetCancelRoutine(irp, NULL);
912 IoCompleteRequest(irp, IO_NO_INCREMENT);
913 }
914 else
915 {
916 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
917 KdPrint((__DRIVER_NAME " nothing to read... pending\n"));
918 IoMarkIrpPending(irp);
919 status = STATUS_PENDING;
920 }
921 }
922 else
923 {
924 KdPrint((__DRIVER_NAME " no pending irp\n"));
925 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
926 status = STATUS_SUCCESS;
927 }
929 FUNCTION_EXIT();
931 return status;
932 }
934 static VOID
935 XenBus_ShutdownIoCancel(PDEVICE_OBJECT device_object, PIRP irp)
936 {
937 PXENPCI_DEVICE_DATA xpdd;
938 KIRQL old_irql;
940 FUNCTION_ENTER();
942 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
943 IoReleaseCancelSpinLock(irp->CancelIrql);
944 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
945 if (irp == xpdd->shutdown_irp)
946 {
947 KdPrint((__DRIVER_NAME " Not the current irp???\n"));
948 xpdd->shutdown_irp = NULL;
949 }
950 irp->IoStatus.Status = STATUS_CANCELLED;
951 irp->IoStatus.Information = 0;
952 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
953 IoCompleteRequest(irp, IO_NO_INCREMENT);
955 FUNCTION_EXIT();
956 }
958 struct {
959 volatile ULONG do_spin;
960 volatile ULONG abort_spin;
961 volatile LONG nr_spinning;
962 KDPC dpcs[MAX_VIRT_CPUS];
963 KEVENT spin_event;
964 KEVENT resume_event;
965 } typedef SUSPEND_INFO, *PSUSPEND_INFO;
967 /* runs at PASSIVE_LEVEL */
968 static DDKAPI VOID
969 XenPci_CompleteResume(PDEVICE_OBJECT device_object, PVOID context)
970 {
971 PSUSPEND_INFO suspend_info = context;
972 PXENPCI_DEVICE_DATA xpdd;
973 PXEN_CHILD child;
975 UNREFERENCED_PARAMETER(context);
976 FUNCTION_ENTER();
978 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
980 while (suspend_info->nr_spinning)
981 {
982 KdPrint((__DRIVER_NAME " %d processors are still spinning\n", suspend_info->nr_spinning));
983 KeWaitForSingleObject(&suspend_info->spin_event, Executive, KernelMode, FALSE, NULL);
984 }
985 KdPrint((__DRIVER_NAME " all other processors have stopped spinning\n"));
987 XenBus_Resume(xpdd);
989 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
990 {
991 XenPci_Pdo_Resume(child->context->common.pdo);
992 }
994 xpdd->suspend_state = SUSPEND_STATE_NONE;
996 FUNCTION_EXIT();
997 }
999 /* Called at DISPATCH_LEVEL */
1000 static DDKAPI VOID
1001 XenPci_Suspend(
1002 PRKDPC Dpc,
1003 PVOID Context,
1004 PVOID SystemArgument1,
1005 PVOID SystemArgument2)
1007 PXENPCI_DEVICE_DATA xpdd = Context;
1008 PSUSPEND_INFO suspend_info = SystemArgument1;
1009 ULONG ActiveProcessorCount;
1010 KIRQL old_irql;
1011 int cancelled = 0;
1012 PXEN_CHILD child;
1014 //PUCHAR gnttbl_backup[PAGE_SIZE * NR_GRANT_FRAMES];
1016 UNREFERENCED_PARAMETER(Dpc);
1017 UNREFERENCED_PARAMETER(SystemArgument2);
1019 FUNCTION_ENTER();
1020 FUNCTION_MSG("(CPU = %d)\n", KeGetCurrentProcessorNumber());
1022 if (KeGetCurrentProcessorNumber() != 0)
1024 KdPrint((__DRIVER_NAME " CPU %d spinning...\n", KeGetCurrentProcessorNumber()));
1025 KeRaiseIrql(HIGH_LEVEL, &old_irql);
1026 InterlockedIncrement(&suspend_info->nr_spinning);
1027 while(suspend_info->do_spin && !suspend_info->abort_spin)
1029 KeStallExecutionProcessor(1);
1030 KeMemoryBarrier();
1032 if (suspend_info->abort_spin)
1034 KdPrint((__DRIVER_NAME " CPU %d spin aborted\n", KeGetCurrentProcessorNumber()));
1035 KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000003, 0x00000001, 0x00000000, 0x00000000);
1036 return;
1038 KeLowerIrql(old_irql);
1039 InterlockedDecrement(&suspend_info->nr_spinning);
1040 KeSetEvent(&suspend_info->spin_event, IO_NO_INCREMENT, FALSE);
1041 FUNCTION_EXIT();
1042 return;
1044 ActiveProcessorCount = (ULONG)KeNumberProcessors;
1046 KeRaiseIrql(HIGH_LEVEL, &old_irql);
1047 xpdd->suspend_state = SUSPEND_STATE_HIGH_IRQL;
1048 while (suspend_info->nr_spinning < (LONG)ActiveProcessorCount - 1 && !suspend_info->abort_spin)
1050 KeStallExecutionProcessor(1);
1051 //HYPERVISOR_yield(xpdd);
1052 KeMemoryBarrier();
1054 if (suspend_info->abort_spin)
1056 KdPrint((__DRIVER_NAME " CPU %d spin aborted\n", KeGetCurrentProcessorNumber()));
1057 KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000003, 0x00000003, 0x00000000, 0x00000000);
1058 return;
1060 cancelled = hvm_shutdown(Context, SHUTDOWN_suspend);
1061 KdPrint((__DRIVER_NAME " back from suspend, cancelled = %d\n", cancelled));
1063 XenPci_Init(xpdd);
1065 GntTbl_InitMap(Context);
1067 /* this enables interrupts again too */
1068 EvtChn_Init(xpdd);
1070 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
1072 child->context->device_state.resume_state = RESUME_STATE_BACKEND_RESUME;
1074 KeLowerIrql(old_irql);
1075 xpdd->suspend_state = SUSPEND_STATE_RESUMING;
1076 suspend_info->do_spin = FALSE;
1077 KeMemoryBarrier();
1078 KeSetEvent(&suspend_info->resume_event, IO_NO_INCREMENT, FALSE);
1079 FUNCTION_EXIT();
1082 /* Called at PASSIVE_LEVEL */
1083 static VOID DDKAPI
1084 XenPci_BeginSuspend(PDEVICE_OBJECT device_object, PVOID context)
1086 //KAFFINITY ActiveProcessorMask = 0; // this is for Vista+
1087 PXENPCI_DEVICE_DATA xpdd = device_object->DeviceExtension;
1088 ULONG ActiveProcessorCount;
1089 ULONG i;
1090 PSUSPEND_INFO suspend_info;
1091 //PKDPC Dpc;
1092 KIRQL OldIrql;
1093 PXEN_CHILD child;
1095 UNREFERENCED_PARAMETER(context);
1096 FUNCTION_ENTER();
1098 if (xpdd->suspend_state == SUSPEND_STATE_NONE)
1100 xpdd->suspend_state = SUSPEND_STATE_SCHEDULED;
1101 KeMemoryBarrier();
1103 suspend_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(SUSPEND_INFO), XENPCI_POOL_TAG);
1104 RtlZeroMemory(suspend_info, sizeof(SUSPEND_INFO));
1105 KeInitializeEvent(&suspend_info->spin_event, SynchronizationEvent, FALSE);
1106 KeInitializeEvent(&suspend_info->resume_event, SynchronizationEvent, FALSE);
1108 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
1110 XenPci_Pdo_Suspend(child->context->common.pdo);
1113 XenBus_Suspend(xpdd);
1115 EvtChn_Shutdown(xpdd);
1117 //ActiveProcessorCount = KeQueryActiveProcessorCount(&ActiveProcessorMask); // this is for Vista+
1118 ActiveProcessorCount = (ULONG)KeNumberProcessors;
1119 /* Go to HIGH_LEVEL to prevent any races with Dpc's on the current processor */
1120 KeRaiseIrql(HIGH_LEVEL, &OldIrql);
1121 suspend_info->do_spin = TRUE;
1122 for (i = 0; i < ActiveProcessorCount; i++)
1124 //Dpc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KDPC), XENPCI_POOL_TAG);
1125 KeInitializeDpc(&suspend_info->dpcs[i], XenPci_Suspend, xpdd);
1126 KeSetTargetProcessorDpc(&suspend_info->dpcs[i], (CCHAR)i);
1127 KeSetImportanceDpc(&suspend_info->dpcs[i], HighImportance);
1128 KdPrint((__DRIVER_NAME " queuing Dpc for CPU %d\n", i));
1129 KeInsertQueueDpc(&suspend_info->dpcs[i], suspend_info, NULL);
1131 KdPrint((__DRIVER_NAME " All Dpc's queued\n"));
1132 KeMemoryBarrier();
1133 KeLowerIrql(OldIrql);
1134 KdPrint((__DRIVER_NAME " Waiting for resume_event\n"));
1135 KeWaitForSingleObject(&suspend_info->resume_event, Executive, KernelMode, FALSE, NULL);
1136 KdPrint((__DRIVER_NAME " Got resume_event\n"));
1137 //xpdd->log_interrupts = TRUE;
1138 XenPci_CompleteResume(device_object, suspend_info);
1140 FUNCTION_EXIT();
1143 static void
1144 XenPci_ShutdownHandler(char *path, PVOID context)
1146 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)context;
1147 char *res;
1148 char *value;
1149 KIRQL old_irql;
1150 PIO_WORKITEM work_item;
1152 UNREFERENCED_PARAMETER(path);
1154 FUNCTION_ENTER();
1156 res = XenBus_Read(xpdd, XBT_NIL, SHUTDOWN_PATH, &value);
1157 if (res)
1159 KdPrint(("Error reading shutdown path - %s\n", res));
1160 XenPci_FreeMem(res);
1161 return;
1164 KdPrint((__DRIVER_NAME " Shutdown value = %s\n", value));
1166 if (strlen(value) != 0)
1168 if (strcmp(value, "suspend") == 0)
1170 KdPrint((__DRIVER_NAME " Suspend detected\n"));
1171 /* we have to queue this as a work item as we stop the xenbus thread, which we are currently running in! */
1172 work_item = IoAllocateWorkItem(xpdd->common.fdo);
1173 IoQueueWorkItem(work_item, XenPci_BeginSuspend, DelayedWorkQueue, NULL);
1174 //XenPci_BeginSuspend(xpdd);
1176 else
1178 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
1179 if (xpdd->shutdown_start >= xpdd->shutdown_cons)
1180 xpdd->shutdown_prod = xpdd->shutdown_start;
1181 else
1182 xpdd->shutdown_start = xpdd->shutdown_prod;
1183 memcpy(&xpdd->shutdown_ring[xpdd->shutdown_prod], value, strlen(value));
1184 xpdd->shutdown_prod += (ULONG)strlen(value);
1185 xpdd->shutdown_ring[xpdd->shutdown_prod++] = '\r';
1186 xpdd->shutdown_ring[xpdd->shutdown_prod++] = '\n';
1187 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
1188 XenPci_ProcessShutdownIrp(xpdd);
1192 //XenPci_FreeMem(value);
1194 FUNCTION_EXIT();
1197 static VOID
1198 XenPci_DumpPdoConfigs(PXENPCI_DEVICE_DATA xpdd)
1200 PXEN_CHILD child;
1202 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
1204 XenPci_DumpPdoConfig(child->context->common.pdo);
1208 static VOID
1209 XenPci_SysrqHandler(char *path, PVOID context)
1211 PXENPCI_DEVICE_DATA xpdd = context;
1212 char *value;
1213 char letter;
1214 char *res;
1216 UNREFERENCED_PARAMETER(path);
1218 FUNCTION_ENTER();
1220 XenBus_Read(xpdd, XBT_NIL, SYSRQ_PATH, &value);
1222 KdPrint((__DRIVER_NAME " SysRq Value = %s\n", value));
1224 if (value != NULL && strlen(value) != 0)
1226 letter = *value;
1227 res = XenBus_Write(xpdd, XBT_NIL, SYSRQ_PATH, "");
1228 if (res)
1230 KdPrint(("Error writing sysrq path\n"));
1231 XenPci_FreeMem(res);
1232 return;
1235 else
1237 letter = 0;
1240 if (value != NULL)
1242 XenPci_FreeMem(value);
1245 switch (letter)
1247 case 0:
1248 break;
1249 case 'B': /* cause a bug check */
1250 KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000001, 0x00000000, 0x00000000, 0x00000000);
1251 break;
1252 case 'X': /* stop delivering events */
1253 xpdd->interrupts_masked = TRUE;
1254 break;
1255 case 'C':
1256 /* show some debugging info */
1257 XenPci_DumpPdoConfigs(xpdd);
1258 break;
1259 default:
1260 KdPrint((" Unhandled sysrq letter %c\n", letter));
1261 break;
1264 FUNCTION_EXIT();
1267 static DDKAPI VOID
1268 XenPci_Pnp_StartDeviceCallback(PDEVICE_OBJECT device_object, PVOID context)
1270 NTSTATUS status = STATUS_SUCCESS;
1271 PXENPCI_DEVICE_DATA xpdd = device_object->DeviceExtension;
1272 PIRP irp = context;
1273 char *response;
1275 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1277 XenPci_Init(xpdd);
1279 GntTbl_Init(xpdd);
1281 EvtChn_Init(xpdd);
1282 EvtChn_ConnectInterrupt(xpdd);
1283 XenBus_Init(xpdd);
1285 response = XenBus_AddWatch(xpdd, XBT_NIL, SYSRQ_PATH, XenPci_SysrqHandler, xpdd);
1286 KdPrint((__DRIVER_NAME " sysrqwatch response = '%s'\n", response));
1288 #if 0
1289 response = XenBus_AddWatch(xpdd, XBT_NIL, SHUTDOWN_PATH, XenPci_ShutdownHandler, xpdd);
1290 KdPrint((__DRIVER_NAME " shutdown watch response = '%s'\n", response));
1291 #endif
1293 response = XenBus_AddWatch(xpdd, XBT_NIL, "device", XenPci_DeviceWatchHandler, xpdd);
1294 KdPrint((__DRIVER_NAME " device watch response = '%s'\n", response));
1296 #if 0
1297 response = XenBus_AddWatch(xpdd, XBT_NIL, BALLOON_PATH, XenPci_BalloonHandler, Device);
1298 KdPrint((__DRIVER_NAME " balloon watch response = '%s'\n", response));
1299 #endif
1301 status = IoSetDeviceInterfaceState(&xpdd->legacy_interface_name, TRUE);
1302 if (!NT_SUCCESS(status))
1304 KdPrint((__DRIVER_NAME " IoSetDeviceInterfaceState (legacy) failed with status 0x%08x\n", status));
1307 status = IoSetDeviceInterfaceState(&xpdd->interface_name, TRUE);
1308 if (!NT_SUCCESS(status))
1310 KdPrint((__DRIVER_NAME " IoSetDeviceInterfaceState failed with status 0x%08x\n", status));
1313 irp->IoStatus.Status = status;
1315 IoCompleteRequest(irp, IO_NO_INCREMENT);
1317 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1320 static NTSTATUS
1321 XenPci_Pnp_StartDevice(PDEVICE_OBJECT device_object, PIRP irp)
1323 NTSTATUS status;
1324 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1325 PIO_STACK_LOCATION stack;
1326 PCM_PARTIAL_RESOURCE_LIST res_list;
1327 PCM_PARTIAL_RESOURCE_DESCRIPTOR res_descriptor;
1328 ULONG i;
1330 UNREFERENCED_PARAMETER(device_object);
1332 FUNCTION_ENTER();
1334 stack = IoGetCurrentIrpStackLocation(irp);
1336 IoMarkIrpPending(irp);
1338 status = XenPci_SendAndWaitForIrp(device_object, irp);
1340 res_list = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
1342 for (i = 0; i < res_list->Count; i++)
1344 res_descriptor = &res_list->PartialDescriptors[i];
1345 switch (res_descriptor->Type)
1347 case CmResourceTypeInterrupt:
1348 KdPrint((__DRIVER_NAME " irq_number = %03x\n", res_descriptor->u.Interrupt.Vector));
1349 xpdd->irq_number = res_descriptor->u.Interrupt.Vector;
1350 //memcpy(&InterruptRaw, res_descriptor, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
1351 break;
1355 res_list = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
1357 for (i = 0; i < res_list->Count; i++)
1359 res_descriptor = &res_list->PartialDescriptors[i];
1360 switch (res_descriptor->Type) {
1361 case CmResourceTypePort:
1362 KdPrint((__DRIVER_NAME " IoPort Address(%x) Length: %d\n", res_descriptor->u.Port.Start.LowPart, res_descriptor->u.Port.Length));
1363 xpdd->platform_ioport_addr = res_descriptor->u.Port.Start.LowPart;
1364 xpdd->platform_ioport_len = res_descriptor->u.Port.Length;
1365 break;
1366 case CmResourceTypeMemory:
1367 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));
1368 KdPrint((__DRIVER_NAME " Memory flags = %04X\n", res_descriptor->Flags));
1369 xpdd->platform_mmio_addr = res_descriptor->u.Memory.Start;
1370 xpdd->platform_mmio_len = res_descriptor->u.Memory.Length;
1371 xpdd->platform_mmio_alloc = 0;
1372 xpdd->platform_mmio_flags = res_descriptor->Flags;
1373 break;
1374 case CmResourceTypeInterrupt:
1375 KdPrint((__DRIVER_NAME " irq_vector = %03x\n", res_descriptor->u.Interrupt.Vector));
1376 KdPrint((__DRIVER_NAME " irq_level = %03x\n", res_descriptor->u.Interrupt.Level));
1377 xpdd->irq_level = (KIRQL)res_descriptor->u.Interrupt.Level;
1378 xpdd->irq_vector = res_descriptor->u.Interrupt.Vector;
1379 xpdd->irq_affinity = res_descriptor->u.Interrupt.Affinity;
1381 xpdd->irq_mode = (res_descriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED)?Latched:LevelSensitive;
1382 KdPrint((__DRIVER_NAME " irq_mode = %s\n", (xpdd->irq_mode == Latched)?"Latched":"LevelSensitive"));
1383 switch(res_descriptor->ShareDisposition)
1385 case CmResourceShareDeviceExclusive:
1386 KdPrint((__DRIVER_NAME " ShareDisposition = CmResourceShareDeviceExclusive\n"));
1387 break;
1388 case CmResourceShareDriverExclusive:
1389 KdPrint((__DRIVER_NAME " ShareDisposition = CmResourceShareDriverExclusive\n"));
1390 break;
1391 case CmResourceShareShared:
1392 KdPrint((__DRIVER_NAME " ShareDisposition = CmResourceShareShared\n"));
1393 break;
1394 default:
1395 KdPrint((__DRIVER_NAME " ShareDisposition = %d\n", res_descriptor->ShareDisposition));
1396 break;
1398 break;
1399 case CmResourceTypeDevicePrivate:
1400 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]));
1401 break;
1402 default:
1403 KdPrint((__DRIVER_NAME " Unhandled resource type (0x%x)\n", res_descriptor->Type));
1404 break;
1408 XenPci_QueueWorkItem(device_object, XenPci_Pnp_StartDeviceCallback, irp);
1410 FUNCTION_EXIT();
1412 return STATUS_PENDING;
1415 static NTSTATUS
1416 XenPci_Pnp_StopDevice(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
1418 NTSTATUS status = STATUS_SUCCESS;
1420 UNREFERENCED_PARAMETER(device_object);
1421 UNREFERENCED_PARAMETER(context);
1423 FUNCTION_ENTER();
1425 irp->IoStatus.Status = status;
1426 IoCompleteRequest(irp, IO_NO_INCREMENT);
1428 FUNCTION_EXIT();
1430 return irp->IoStatus.Status;
1433 static NTSTATUS
1434 XenPci_Pnp_QueryStopRemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
1436 NTSTATUS status;
1437 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1439 UNREFERENCED_PARAMETER(device_object);
1441 FUNCTION_ENTER();
1443 if (xpdd->common.device_usage_paging
1444 || xpdd->common.device_usage_dump
1445 || xpdd->common.device_usage_hibernation)
1447 /* We are in the paging or hibernation path - can't remove */
1448 status = irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1449 IoCompleteRequest(irp, IO_NO_INCREMENT);
1451 else
1453 IoSkipCurrentIrpStackLocation(irp);
1454 status = IoCallDriver(xpdd->common.lower_do, irp);
1457 FUNCTION_EXIT();
1459 return status;
1462 static NTSTATUS
1463 XenPci_Pnp_RemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
1465 NTSTATUS status;
1466 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1468 UNREFERENCED_PARAMETER(device_object);
1470 FUNCTION_ENTER();
1472 irp->IoStatus.Status = STATUS_SUCCESS;
1473 IoSkipCurrentIrpStackLocation(irp);
1474 status = IoCallDriver(xpdd->common.lower_do, irp);
1475 IoDetachDevice(xpdd->common.lower_do);
1477 FUNCTION_EXIT();
1479 return status;
1482 static DDKAPI VOID
1483 XenPci_Pnp_QueryBusRelationsCallback(PDEVICE_OBJECT device_object, PVOID context)
1485 NTSTATUS status = STATUS_SUCCESS;
1486 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1487 PXENPCI_PDO_DEVICE_DATA xppdd;
1488 PIRP irp = context;
1489 int device_count = 0;
1490 PDEVICE_RELATIONS dev_relations;
1491 PXEN_CHILD child, old_child;
1492 //char *response;
1493 char *msg;
1494 char **devices;
1495 char **instances;
1496 int i, j;
1497 CHAR path[128];
1498 PDEVICE_OBJECT pdo;
1499 PDEVICE_RELATIONS oldRelations;
1500 int prevcount, length;
1502 FUNCTION_ENTER();
1504 msg = XenBus_List(xpdd, XBT_NIL, "device", &devices);
1505 if (!msg)
1507 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
1509 if (child->state == CHILD_STATE_DELETED)
1511 KdPrint((__DRIVER_NAME " Found deleted child - this shouldn't happen\n" ));
1513 child->state = CHILD_STATE_DELETED;
1516 for (i = 0; devices[i]; i++)
1518 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s", devices[i]);
1519 msg = XenBus_List(xpdd, XBT_NIL, path, &instances);
1520 if (!msg)
1522 for (j = 0; instances[j]; j++)
1524 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s/%s", devices[i], instances[j]);
1526 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
1528 if (strcmp(child->context->path, path) == 0)
1530 KdPrint((__DRIVER_NAME " Existing device %s\n", path));
1531 ASSERT(child->state == CHILD_STATE_DELETED);
1532 child->state = CHILD_STATE_ADDED;
1533 device_count++;
1534 break;
1538 if (child == (PXEN_CHILD)&xpdd->child_list)
1540 KdPrint((__DRIVER_NAME " New device %s\n", path));
1541 child = ExAllocatePoolWithTag(NonPagedPool, sizeof(XEN_CHILD), XENPCI_POOL_TAG);
1542 child->state = CHILD_STATE_ADDED;
1543 status = IoCreateDevice(
1544 xpdd->common.fdo->DriverObject,
1545 sizeof(XENPCI_PDO_DEVICE_DATA),
1546 NULL,
1547 FILE_DEVICE_UNKNOWN,
1548 FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN,
1549 FALSE,
1550 &pdo);
1551 if (!NT_SUCCESS(status))
1553 KdPrint((__DRIVER_NAME " IoCreateDevice status = %08X\n", status));
1555 RtlZeroMemory(pdo->DeviceExtension, sizeof(XENPCI_PDO_DEVICE_DATA));
1556 child->context = xppdd = pdo->DeviceExtension;
1557 xppdd->common.fdo = NULL;
1558 xppdd->common.pdo = pdo;
1559 ObReferenceObject(pdo);
1560 xppdd->common.lower_do = NULL;
1561 INIT_PNP_STATE(&xppdd->common);
1562 xppdd->common.device_usage_paging = 0;
1563 xppdd->common.device_usage_dump = 0;
1564 xppdd->common.device_usage_hibernation = 0;
1565 xppdd->bus_fdo = xpdd->common.fdo;
1566 xppdd->bus_pdo = xpdd->common.pdo;
1567 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), path);
1568 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), devices[i]);
1569 xppdd->index = atoi(instances[j]);
1570 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
1571 xppdd->backend_state = XenbusStateUnknown;
1572 xppdd->backend_path[0] = '\0';
1573 InsertTailList(&xpdd->child_list, (PLIST_ENTRY)child);
1574 device_count++;
1576 XenPci_FreeMem(instances[j]);
1578 XenPci_FreeMem(instances);
1580 XenPci_FreeMem(devices[i]);
1582 XenPci_FreeMem(devices);
1584 //
1585 // Keep track of old relations structure
1586 //
1587 oldRelations = (PDEVICE_RELATIONS) irp->IoStatus.Information;
1588 if (oldRelations)
1590 prevcount = oldRelations->Count;
1592 else
1594 prevcount = 0;
1597 //
1598 // Need to allocate a new relations structure and add our
1599 // PDOs to it.
1600 //
1602 length = sizeof(DEVICE_RELATIONS) + ((device_count + prevcount) * sizeof (PDEVICE_OBJECT)) -1;
1604 dev_relations = (PDEVICE_RELATIONS) ExAllocatePoolWithTag (PagedPool, length, XENPCI_POOL_TAG);
1605 if (!dev_relations)
1607 KdPrint((__DRIVER_NAME "**** Failed to allocate a new buffer for query device relations\n"));
1608 //
1609 // Fail the IRP
1610 //
1611 irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES;
1612 IoCompleteRequest (irp, IO_NO_INCREMENT);
1613 return;
1616 //
1617 // Copy in the device objects so far
1618 //
1619 if (prevcount)
1621 RtlCopyMemory (dev_relations->Objects, oldRelations->Objects, prevcount * sizeof (PDEVICE_OBJECT));
1624 for (child = (PXEN_CHILD)xpdd->child_list.Flink, device_count = 0; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
1626 if (child->state == CHILD_STATE_ADDED)
1628 ObReferenceObject(child->context->common.pdo);
1629 dev_relations->Objects[prevcount++] = child->context->common.pdo;
1633 dev_relations->Count = prevcount + device_count;
1635 child = (PXEN_CHILD)xpdd->child_list.Flink;
1636 while (child != (PXEN_CHILD)&xpdd->child_list)
1638 if (child->state == CHILD_STATE_DELETED)
1640 KdPrint((__DRIVER_NAME " Removing deleted child from device list\n"));
1641 old_child = child;
1642 child = (PXEN_CHILD)child->entry.Flink;
1643 RemoveEntryList((PLIST_ENTRY)old_child);
1644 xppdd = old_child->context;
1645 xppdd->reported_missing = TRUE;
1646 ObDereferenceObject(xppdd->common.pdo);
1647 ExFreePoolWithTag(old_child, XENPCI_POOL_TAG);
1649 else
1651 child = (PXEN_CHILD)child->entry.Flink;
1655 status = STATUS_SUCCESS;
1657 else
1659 //
1660 // Fail the IRP
1661 //
1662 irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES;
1663 IoCompleteRequest (irp, IO_NO_INCREMENT);
1664 return;
1667 irp->IoStatus.Status = status;
1668 //
1669 // Replace the relations structure in the IRP with the new
1670 // one.
1671 //
1672 if (oldRelations)
1674 ExFreePool (oldRelations);
1676 irp->IoStatus.Information = (ULONG_PTR)dev_relations;
1678 IoCompleteRequest (irp, IO_NO_INCREMENT);
1680 FUNCTION_EXIT();
1683 static NTSTATUS
1684 XenPci_Pnp_QueryBusRelations(PDEVICE_OBJECT device_object, PIRP irp)
1686 NTSTATUS status;
1688 UNREFERENCED_PARAMETER(device_object);
1690 FUNCTION_ENTER();
1692 IoMarkIrpPending(irp);
1694 status = XenPci_SendAndWaitForIrp(device_object, irp);
1696 XenPci_QueueWorkItem(device_object, XenPci_Pnp_QueryBusRelationsCallback, irp);
1698 FUNCTION_EXIT();
1700 return STATUS_PENDING;
1703 static DDKAPI VOID
1704 XenPci_Pnp_FilterResourceRequirementsCallback(PDEVICE_OBJECT device_object, PVOID context)
1706 NTSTATUS status = STATUS_SUCCESS;
1707 //PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1708 PIRP irp = context;
1710 UNREFERENCED_PARAMETER(device_object);
1712 FUNCTION_ENTER();
1713 irp->IoStatus.Status = status;
1714 IoCompleteRequest (irp, IO_NO_INCREMENT);
1716 FUNCTION_EXIT();
1719 static NTSTATUS
1720 XenPci_Pnp_FilterResourceRequirements(PDEVICE_OBJECT device_object, PIRP irp)
1722 NTSTATUS status;
1724 UNREFERENCED_PARAMETER(device_object);
1726 FUNCTION_ENTER();
1728 IoMarkIrpPending(irp);
1730 status = XenPci_SendAndWaitForIrp(device_object, irp);
1732 XenPci_QueueWorkItem(device_object, XenPci_Pnp_FilterResourceRequirementsCallback, irp);
1734 FUNCTION_EXIT();
1736 return STATUS_PENDING;
1739 static NTSTATUS
1740 XenPci_Pnp_DeviceUsageNotification(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
1742 NTSTATUS status;
1743 PXENPCI_DEVICE_DATA xpdd;
1744 PIO_STACK_LOCATION stack;
1746 UNREFERENCED_PARAMETER(context);
1748 FUNCTION_ENTER();
1750 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1751 stack = IoGetCurrentIrpStackLocation(irp);
1752 status = irp->IoStatus.Status;
1754 /* fail if we are in a stop or remove pending state */
1755 if (!NT_SUCCESS(irp->IoStatus.Status))
1757 switch (stack->Parameters.UsageNotification.Type)
1759 case DeviceUsageTypePaging:
1760 if (stack->Parameters.UsageNotification.InPath)
1761 xpdd->common.device_usage_paging--;
1762 else
1763 xpdd->common.device_usage_paging++;
1764 break;
1765 case DeviceUsageTypeDumpFile:
1766 if (stack->Parameters.UsageNotification.InPath)
1767 xpdd->common.device_usage_dump--;
1768 else
1769 xpdd->common.device_usage_dump++;
1770 break;
1771 case DeviceUsageTypeHibernation:
1772 if (stack->Parameters.UsageNotification.InPath)
1773 xpdd->common.device_usage_hibernation--;
1774 else
1775 xpdd->common.device_usage_hibernation++;
1776 break;
1777 default:
1778 KdPrint((__DRIVER_NAME " Unknown usage type %x\n",
1779 stack->Parameters.UsageNotification.Type));
1780 break;
1782 if (xpdd->common.device_usage_paging
1783 || xpdd->common.device_usage_dump
1784 || xpdd->common.device_usage_hibernation)
1786 xpdd->common.fdo->Flags &= ~DO_POWER_PAGABLE;
1788 IoInvalidateDeviceState(xpdd->common.pdo);
1790 IoCompleteRequest(irp, IO_NO_INCREMENT);
1792 FUNCTION_EXIT();
1794 return status;
1798 NTSTATUS
1799 XenPci_Pnp_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1801 NTSTATUS status;
1802 PIO_STACK_LOCATION stack;
1803 PXENPCI_DEVICE_DATA xpdd = device_object->DeviceExtension;;
1805 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1807 stack = IoGetCurrentIrpStackLocation(irp);
1809 switch (stack->MinorFunction)
1811 case IRP_MN_START_DEVICE:
1812 KdPrint((__DRIVER_NAME " IRP_MN_START_DEVICE\n"));
1813 return XenPci_Pnp_StartDevice(device_object, irp);
1815 case IRP_MN_QUERY_STOP_DEVICE:
1816 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_STOP_DEVICE\n"));
1817 status = XenPci_Pnp_QueryStopRemoveDevice(device_object, irp);
1818 if (NT_SUCCESS(status))
1819 SET_PNP_STATE(&xpdd->common, RemovePending);
1820 return status;
1822 case IRP_MN_STOP_DEVICE:
1823 KdPrint((__DRIVER_NAME " IRP_MN_STOP_DEVICE\n"));
1824 IoCopyCurrentIrpStackLocationToNext(irp);
1825 IoSetCompletionRoutine(irp, XenPci_Pnp_StopDevice, NULL, TRUE, TRUE, TRUE);
1826 break;
1828 case IRP_MN_CANCEL_STOP_DEVICE:
1829 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_STOP_DEVICE\n"));
1830 IoSkipCurrentIrpStackLocation(irp);
1831 REVERT_PNP_STATE(&xpdd->common);
1832 irp->IoStatus.Status = STATUS_SUCCESS;
1833 break;
1835 case IRP_MN_QUERY_REMOVE_DEVICE:
1836 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_REMOVE_DEVICE\n"));
1837 status = XenPci_Pnp_QueryStopRemoveDevice(device_object, irp);
1838 if (NT_SUCCESS(status))
1839 SET_PNP_STATE(&xpdd->common, RemovePending);
1840 return status;
1842 case IRP_MN_REMOVE_DEVICE:
1843 KdPrint((__DRIVER_NAME " IRP_MN_REMOVE_DEVICE\n"));
1844 return XenPci_Pnp_RemoveDevice(device_object, irp);
1845 break;
1847 case IRP_MN_CANCEL_REMOVE_DEVICE:
1848 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_REMOVE_DEVICE\n"));
1849 IoSkipCurrentIrpStackLocation(irp);
1850 REVERT_PNP_STATE(&xpdd->common);
1851 irp->IoStatus.Status = STATUS_SUCCESS;
1852 break;
1854 case IRP_MN_SURPRISE_REMOVAL:
1855 KdPrint((__DRIVER_NAME " IRP_MN_SURPRISE_REMOVAL\n"));
1856 IoSkipCurrentIrpStackLocation(irp);
1857 irp->IoStatus.Status = STATUS_SUCCESS;
1858 break;
1860 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1861 KdPrint((__DRIVER_NAME " IRP_MN_DEVICE_USAGE_NOTIFICATION\n"));
1862 switch (stack->Parameters.UsageNotification.Type)
1864 case DeviceUsageTypePaging:
1865 KdPrint((__DRIVER_NAME " type = DeviceUsageTypePaging = %d\n", stack->Parameters.UsageNotification.InPath));
1866 if (stack->Parameters.UsageNotification.InPath)
1867 xpdd->common.device_usage_paging++;
1868 else
1869 xpdd->common.device_usage_paging--;
1870 irp->IoStatus.Status = STATUS_SUCCESS;
1871 break;
1872 case DeviceUsageTypeDumpFile:
1873 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeDumpFile = %d\n", stack->Parameters.UsageNotification.InPath));
1874 if (stack->Parameters.UsageNotification.InPath)
1875 xpdd->common.device_usage_dump++;
1876 else
1877 xpdd->common.device_usage_dump--;
1878 irp->IoStatus.Status = STATUS_SUCCESS;
1879 break;
1880 case DeviceUsageTypeHibernation:
1881 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeHibernation = %d\n", stack->Parameters.UsageNotification.InPath));
1882 if (stack->Parameters.UsageNotification.InPath)
1883 xpdd->common.device_usage_hibernation++;
1884 else
1885 xpdd->common.device_usage_hibernation--;
1886 irp->IoStatus.Status = STATUS_SUCCESS;
1887 break;
1888 default:
1889 KdPrint((__DRIVER_NAME " type = unsupported (%d)\n", stack->Parameters.UsageNotification.Type));
1890 irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
1891 IoCompleteRequest(irp, IO_NO_INCREMENT);
1892 return STATUS_NOT_SUPPORTED;
1894 if (!xpdd->common.device_usage_paging
1895 && !xpdd->common.device_usage_dump
1896 && !xpdd->common.device_usage_hibernation)
1898 xpdd->common.fdo->Flags |= DO_POWER_PAGABLE;
1900 IoInvalidateDeviceState(xpdd->common.pdo);
1901 IoCopyCurrentIrpStackLocationToNext(irp);
1902 IoSetCompletionRoutine(irp, XenPci_Pnp_DeviceUsageNotification, NULL, TRUE, TRUE, TRUE);
1903 break;
1905 case IRP_MN_QUERY_DEVICE_RELATIONS:
1906 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_RELATIONS\n"));
1907 switch (stack->Parameters.QueryDeviceRelations.Type)
1909 case BusRelations:
1910 KdPrint((__DRIVER_NAME " BusRelations\n"));
1911 return XenPci_Pnp_QueryBusRelations(device_object, irp);
1912 break;
1913 default:
1914 IoSkipCurrentIrpStackLocation(irp);
1915 break;
1917 break;
1919 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1920 KdPrint((__DRIVER_NAME " IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"));
1921 return XenPci_Pnp_FilterResourceRequirements(device_object, irp);
1923 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1924 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_PNP_DEVICE_STATE\n"));
1925 irp->IoStatus.Status = STATUS_SUCCESS;
1926 if (xpdd->common.device_usage_paging
1927 || xpdd->common.device_usage_dump
1928 || xpdd->common.device_usage_hibernation)
1930 irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
1932 IoSkipCurrentIrpStackLocation(irp);
1933 break;
1935 default:
1936 KdPrint((__DRIVER_NAME " Unhandled Minor = %d\n", stack->MinorFunction));
1937 IoSkipCurrentIrpStackLocation(irp);
1938 break;
1941 status = IoCallDriver(xpdd->common.lower_do, irp);
1943 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1945 return status;
1948 NTSTATUS
1949 XenPci_Irp_Create_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1951 PXENPCI_DEVICE_DATA xpdd;
1952 NTSTATUS status;
1953 PIO_STACK_LOCATION stack;
1954 PFILE_OBJECT file;
1956 FUNCTION_ENTER();
1958 stack = IoGetCurrentIrpStackLocation(irp);
1959 file = stack->FileObject;
1961 KdPrint((__DRIVER_NAME " filename = %wZ\n", &file->FileName));
1962 if (wcscmp(L"\\xenbus", file->FileName.Buffer) == 0)
1964 status = XenPci_Irp_Create_XenBus(device_object, irp);
1966 else
1968 // legacy interface
1969 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1970 file->FsContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(ULONG), XENPCI_POOL_TAG);
1971 *(PULONG)file->FsContext = DEVICE_INTERFACE_TYPE_LEGACY;
1972 status = STATUS_SUCCESS;
1973 irp->IoStatus.Status = status;
1974 IoCompleteRequest(irp, IO_NO_INCREMENT);
1976 KdPrint((__DRIVER_NAME " context = %p\n", file->FsContext));
1977 KdPrint((__DRIVER_NAME " type = %d\n", *(PULONG)file->FsContext));
1978 FUNCTION_EXIT();
1980 return status;
1983 NTSTATUS
1984 XenPci_Irp_Close_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1986 PXENPCI_DEVICE_DATA xpdd;
1987 NTSTATUS status;
1988 PIO_STACK_LOCATION stack;
1989 PFILE_OBJECT file;
1991 FUNCTION_ENTER();
1993 stack = IoGetCurrentIrpStackLocation(irp);
1994 file = stack->FileObject;
1996 if (*(PULONG)file->FsContext == DEVICE_INTERFACE_TYPE_XENBUS)
1998 status = XenPci_Irp_Close_XenBus(device_object, irp);
2000 else
2002 // wait until pending irp's
2003 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
2004 status = STATUS_SUCCESS;
2005 irp->IoStatus.Status = status;
2006 IoCompleteRequest(irp, IO_NO_INCREMENT);
2009 FUNCTION_EXIT();
2011 return status;
2014 NTSTATUS
2015 XenPci_Irp_Read_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
2017 PXENPCI_DEVICE_DATA xpdd;
2018 NTSTATUS status;
2019 PIO_STACK_LOCATION stack;
2020 KIRQL old_irql;
2021 PFILE_OBJECT file;
2023 FUNCTION_ENTER();
2025 stack = IoGetCurrentIrpStackLocation(irp);
2026 file = stack->FileObject;
2028 if (*(PULONG)file->FsContext == DEVICE_INTERFACE_TYPE_XENBUS)
2030 status = XenPci_Irp_Read_XenBus(device_object, irp);
2032 else
2034 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
2035 stack = IoGetCurrentIrpStackLocation(irp);
2036 if (stack->Parameters.Read.Length == 0)
2038 irp->IoStatus.Information = 0;
2039 status = STATUS_SUCCESS;
2040 irp->IoStatus.Status = status;
2041 IoCompleteRequest(irp, IO_NO_INCREMENT);
2043 else
2045 KdPrint((__DRIVER_NAME " stack = %p\n", stack));
2046 KdPrint((__DRIVER_NAME " length = %d, buffer = %p\n", stack->Parameters.Read.Length, irp->AssociatedIrp.SystemBuffer));
2048 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
2049 xpdd->shutdown_irp = irp;
2050 IoSetCancelRoutine(irp, XenBus_ShutdownIoCancel);
2051 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
2052 status = XenPci_ProcessShutdownIrp(xpdd);
2055 FUNCTION_EXIT();
2057 return status;
2060 NTSTATUS
2061 XenPci_Irp_Write_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
2063 PXENPCI_DEVICE_DATA xpdd;
2064 NTSTATUS status;
2065 PIO_STACK_LOCATION stack;
2066 PFILE_OBJECT file;
2068 FUNCTION_ENTER();
2070 stack = IoGetCurrentIrpStackLocation(irp);
2071 file = stack->FileObject;
2073 KdPrint((__DRIVER_NAME " context = %p\n", file->FsContext));
2074 KdPrint((__DRIVER_NAME " type = %d\n", *(PULONG)file->FsContext));
2076 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
2077 stack = IoGetCurrentIrpStackLocation(irp);
2079 if (*(PULONG)file->FsContext == DEVICE_INTERFACE_TYPE_XENBUS)
2081 status = XenPci_Irp_Write_XenBus(device_object, irp);
2083 else
2085 status = STATUS_UNSUCCESSFUL;
2086 irp->IoStatus.Status = status;
2087 IoCompleteRequest(irp, IO_NO_INCREMENT);
2090 FUNCTION_EXIT();
2092 return status;
2095 NTSTATUS
2096 XenPci_Irp_Cleanup_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
2098 NTSTATUS status;
2099 PIO_STACK_LOCATION stack;
2100 PFILE_OBJECT file;
2102 UNREFERENCED_PARAMETER(device_object);
2104 FUNCTION_ENTER();
2106 stack = IoGetCurrentIrpStackLocation(irp);
2107 file = stack->FileObject;
2109 if (*(PULONG)file->FsContext == DEVICE_INTERFACE_TYPE_XENBUS)
2111 status = XenPci_Irp_Cleanup_XenBus(device_object, irp);
2113 else
2115 status = STATUS_SUCCESS;
2116 irp->IoStatus.Status = status;
2117 IoCompleteRequest(irp, IO_NO_INCREMENT);
2119 FUNCTION_EXIT();
2121 return status;
2124 DDKAPI NTSTATUS
2125 XenPci_SystemControl_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
2127 NTSTATUS status;
2128 PIO_STACK_LOCATION stack;
2129 PXENPCI_COMMON common = device_object->DeviceExtension;
2131 FUNCTION_ENTER();
2133 UNREFERENCED_PARAMETER(device_object);
2135 stack = IoGetCurrentIrpStackLocation(irp);
2136 DbgPrint(__DRIVER_NAME " Minor = %d\n", stack->MinorFunction);
2137 IoSkipCurrentIrpStackLocation(irp);
2138 status = IoCallDriver(common->lower_do, irp);
2140 FUNCTION_EXIT();
2142 return status;
2145 #endif
2147 #if 0
2148 static VOID
2149 XenPci_BalloonHandler(char *Path, PVOID Data)
2151 WDFDEVICE Device = Data;
2152 char *value;
2153 xenbus_transaction_t xbt;
2154 int retry;
2156 UNREFERENCED_PARAMETER(Path);
2158 KdPrint((__DRIVER_NAME " --> XenBus_BalloonHandler\n"));
2160 XenBus_StartTransaction(Device, &xbt);
2162 XenBus_Read(Device, XBT_NIL, BALLOON_PATH, &value);
2164 KdPrint((__DRIVER_NAME " Balloon Value = %s\n", value));
2166 // use the memory_op(unsigned int op, void *arg) hypercall to adjust this
2167 // use XENMEM_increase_reservation and XENMEM_decrease_reservation
2169 XenBus_EndTransaction(Device, xbt, 0, &retry);
2171 XenPci_FreeMem(value);
2173 KdPrint((__DRIVER_NAME " <-- XenBus_BalloonHandler\n"));
2175 #endif