win-pvdrivers

view xenpci/xenpci_fdo.c @ 353:a7c4b65e754a

Bugfixes for save/restore
author James Harper <james.harper@bendigoit.com.au>
date Wed Jul 02 09:54:40 2008 +1000 (2008-07-02)
parents 6cfd70daada3
children d2ebc66da34c
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 <wdmsec.h>
22 #include <stdlib.h>
24 #define SYSRQ_PATH "control/sysrq"
25 #define SHUTDOWN_PATH "control/shutdown"
26 #define BALLOON_PATH "memory/target"
28 static VOID
29 XenBus_BalloonHandler(char *Path, PVOID Data);
31 /*
32 static VOID
33 XenPCI_XenBusWatchHandler(char *Path, PVOID Data);
34 */
36 #pragma warning(disable : 4200) // zero-sized array
38 //CM_PARTIAL_RESOURCE_DESCRIPTOR InterruptRaw;
39 //CM_PARTIAL_RESOURCE_DESCRIPTOR InterruptTranslated;
41 NTSTATUS
42 XenPci_Power_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
43 {
44 NTSTATUS status;
45 PIO_STACK_LOCATION stack;
46 POWER_STATE_TYPE power_type;
47 POWER_STATE power_state;
48 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
49 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
51 UNREFERENCED_PARAMETER(device_object);
53 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
55 stack = IoGetCurrentIrpStackLocation(irp);
56 power_type = stack->Parameters.Power.Type;
57 power_state = stack->Parameters.Power.State;
59 switch (stack->MinorFunction)
60 {
61 case IRP_MN_POWER_SEQUENCE:
62 KdPrint((__DRIVER_NAME " IRP_MN_POWER_SEQUENCE\n"));
63 break;
64 case IRP_MN_QUERY_POWER:
65 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_POWER\n"));
66 break;
67 case IRP_MN_SET_POWER:
68 KdPrint((__DRIVER_NAME " IRP_MN_SET_POWER\n"));
69 switch (power_type) {
70 case DevicePowerState:
71 KdPrint((__DRIVER_NAME " DevicePowerState\n"));
72 break;
73 case SystemPowerState:
74 KdPrint((__DRIVER_NAME " SystemPowerState\n"));
75 break;
76 default:
77 break;
78 }
79 break;
80 case IRP_MN_WAIT_WAKE:
81 break;
82 }
83 PoStartNextPowerIrp(irp);
84 IoSkipCurrentIrpStackLocation(irp);
85 status = PoCallDriver (xpdd->common.lower_do, irp);
87 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
89 return status;
90 }
92 NTSTATUS
93 XenPci_Dummy_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
94 {
95 NTSTATUS status;
96 PIO_STACK_LOCATION stack;
97 PXENPCI_DEVICE_DATA xpdd;
99 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
101 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
102 stack = IoGetCurrentIrpStackLocation(irp);
103 IoSkipCurrentIrpStackLocation(irp);
104 status = IoCallDriver(xpdd->common.lower_do, irp);
106 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
108 return status;
109 }
111 /*
112 * Alloc MMIO from the device's MMIO region. There is no corresponding free() fn
113 */
114 PHYSICAL_ADDRESS
115 XenPci_AllocMMIO(PXENPCI_DEVICE_DATA xpdd, ULONG len)
116 {
117 PHYSICAL_ADDRESS addr;
119 len = (len + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
121 addr = xpdd->platform_mmio_addr;
122 addr.QuadPart += xpdd->platform_mmio_alloc;
123 xpdd->platform_mmio_alloc += len;
125 ASSERT(xpdd->platform_mmio_alloc <= xpdd->platform_mmio_len);
127 return addr;
128 }
130 static NTSTATUS
131 XenPci_Init(PXENPCI_DEVICE_DATA xpdd)
132 {
133 struct xen_add_to_physmap xatp;
134 int ret;
136 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
138 hvm_get_stubs(xpdd);
140 if (!xpdd->shared_info_area_unmapped.QuadPart)
141 {
142 xpdd->shared_info_area_unmapped = XenPci_AllocMMIO(xpdd, PAGE_SIZE);
143 xpdd->shared_info_area = MmMapIoSpace(xpdd->shared_info_area_unmapped,
144 PAGE_SIZE, MmNonCached);
145 }
146 KdPrint((__DRIVER_NAME " shared_info_area_unmapped.QuadPart = %lx\n", xpdd->shared_info_area_unmapped.QuadPart));
147 xatp.domid = DOMID_SELF;
148 xatp.idx = 0;
149 xatp.space = XENMAPSPACE_shared_info;
150 xatp.gpfn = (xen_pfn_t)(xpdd->shared_info_area_unmapped.QuadPart >> PAGE_SHIFT);
151 KdPrint((__DRIVER_NAME " gpfn = %d\n", xatp.gpfn));
152 ret = HYPERVISOR_memory_op(xpdd, XENMEM_add_to_physmap, &xatp);
153 KdPrint((__DRIVER_NAME " hypervisor memory op ret = %d\n", ret));
155 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
157 return STATUS_SUCCESS;
158 }
160 static NTSTATUS
161 XenPci_Pnp_IoCompletion(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
162 {
163 PKEVENT event = (PKEVENT)context;
165 UNREFERENCED_PARAMETER(device_object);
167 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
169 if (irp->PendingReturned)
170 {
171 KeSetEvent(event, IO_NO_INCREMENT, FALSE);
172 }
174 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
176 return STATUS_MORE_PROCESSING_REQUIRED;
177 }
179 static NTSTATUS
180 XenPci_QueueWorkItem(PDEVICE_OBJECT device_object, PIO_WORKITEM_ROUTINE routine, PVOID context)
181 {
182 PIO_WORKITEM work_item;
183 NTSTATUS status = STATUS_SUCCESS;
185 work_item = IoAllocateWorkItem(device_object);
186 IoQueueWorkItem(work_item, routine, DelayedWorkQueue, context);
188 return status;
189 }
191 static NTSTATUS
192 XenPci_SendAndWaitForIrp(PDEVICE_OBJECT device_object, PIRP irp)
193 {
194 NTSTATUS status;
195 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
196 KEVENT event;
198 UNREFERENCED_PARAMETER(device_object);
200 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
202 KeInitializeEvent(&event, NotificationEvent, FALSE);
204 IoCopyCurrentIrpStackLocationToNext(irp);
205 IoSetCompletionRoutine(irp, XenPci_Pnp_IoCompletion, &event, TRUE, TRUE, TRUE);
207 status = IoCallDriver(xpdd->common.lower_do, irp);
209 if (status == STATUS_PENDING)
210 {
211 KdPrint((__DRIVER_NAME " waiting ...\n"));
212 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
213 KdPrint((__DRIVER_NAME " ... done\n"));
214 status = irp->IoStatus.Status;
215 }
217 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
219 return status;
220 }
222 static NTSTATUS
223 XenPci_ProcessShutdownIrp(PXENPCI_DEVICE_DATA xpdd)
224 {
225 PIO_STACK_LOCATION stack;
226 NTSTATUS status;
227 PIRP irp;
228 KIRQL old_irql;
229 ULONG length;
231 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
233 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
234 if (xpdd->shutdown_irp)
235 {
236 irp = xpdd->shutdown_irp;
237 stack = IoGetCurrentIrpStackLocation(irp);
238 KdPrint((__DRIVER_NAME " stack = %p\n", stack));
239 KdPrint((__DRIVER_NAME " length = %d, buffer = %p\n", stack->Parameters.Read.Length, irp->AssociatedIrp.SystemBuffer));
240 length = min(xpdd->shutdown_prod - xpdd->shutdown_cons, stack->Parameters.Read.Length);
241 KdPrint((__DRIVER_NAME " length = %d\n", length));
242 if (length > 0)
243 {
244 memcpy(irp->AssociatedIrp.SystemBuffer, &xpdd->shutdown_ring[xpdd->shutdown_cons & (SHUTDOWN_RING_SIZE - 1)], length);
245 xpdd->shutdown_cons += length;
246 if (xpdd->shutdown_cons > SHUTDOWN_RING_SIZE)
247 {
248 xpdd->shutdown_cons -= SHUTDOWN_RING_SIZE;
249 xpdd->shutdown_prod -= SHUTDOWN_RING_SIZE;
250 xpdd->shutdown_start -= SHUTDOWN_RING_SIZE;
251 }
252 xpdd->shutdown_irp = NULL;
253 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
254 status = STATUS_SUCCESS;
255 irp->IoStatus.Status = status;
256 irp->IoStatus.Information = length;
257 IoSetCancelRoutine(irp, NULL);
258 IoCompleteRequest(irp, IO_NO_INCREMENT);
259 }
260 else
261 {
262 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
263 KdPrint((__DRIVER_NAME " nothing to read... pending\n"));
264 IoMarkIrpPending(irp);
265 status = STATUS_PENDING;
266 }
267 }
268 else
269 {
270 KdPrint((__DRIVER_NAME " no pending irp\n"));
271 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
272 status = STATUS_SUCCESS;
273 }
275 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
277 return status;
278 }
280 static VOID
281 XenBus_ShutdownIoCancel(PDEVICE_OBJECT device_object, PIRP irp)
282 {
283 PXENPCI_DEVICE_DATA xpdd;
284 KIRQL old_irql;
286 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
288 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
289 IoReleaseCancelSpinLock(irp->CancelIrql);
290 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
291 if (irp == xpdd->shutdown_irp)
292 {
293 KdPrint((__DRIVER_NAME " Not the current irp???\n"));
294 xpdd->shutdown_irp = NULL;
295 }
296 irp->IoStatus.Status = STATUS_CANCELLED;
297 irp->IoStatus.Information = 0;
298 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
299 IoCompleteRequest(irp, IO_NO_INCREMENT);
301 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
302 }
304 static VOID
305 XenPci_CompleteResume(PDEVICE_OBJECT device_object, PVOID context)
306 {
307 PXENPCI_DEVICE_DATA xpdd;
308 PXEN_CHILD child;
310 UNREFERENCED_PARAMETER(context);
311 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
313 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
315 XenBus_Resume(xpdd);
317 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
318 {
319 XenPci_Resume(child->context->common.pdo);
320 child->context->device_state.resume_state = RESUME_STATE_FRONTEND_RESUME;
321 // how can we signal children that they are ready to restart again?
322 }
324 xpdd->suspending = 0;
326 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
327 }
329 struct {
330 volatile ULONG do_spin;
331 volatile LONG nr_spinning;
332 } typedef SUSPEND_INFO, *PSUSPEND_INFO;
334 /* Called at DISPATCH_LEVEL */
335 static VOID
336 XenPci_Suspend(
337 PRKDPC Dpc,
338 PVOID Context,
339 PVOID SystemArgument1,
340 PVOID SystemArgument2)
341 {
342 PXENPCI_DEVICE_DATA xpdd = Context;
343 PSUSPEND_INFO suspend_info = SystemArgument1;
344 ULONG ActiveProcessorCount;
345 KIRQL old_irql;
346 int cancelled;
347 PIO_WORKITEM work_item;
348 PXEN_CHILD child;
349 //PUCHAR gnttbl_backup[PAGE_SIZE * NR_GRANT_FRAMES];
351 UNREFERENCED_PARAMETER(Dpc);
352 UNREFERENCED_PARAMETER(SystemArgument2);
354 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (CPU = %d)\n", KeGetCurrentProcessorNumber()));
356 if (KeGetCurrentProcessorNumber() != 0)
357 {
358 KeRaiseIrql(HIGH_LEVEL, &old_irql);
359 KdPrint((__DRIVER_NAME " spinning...\n"));
360 InterlockedIncrement(&suspend_info->nr_spinning);
361 KeMemoryBarrier();
362 while(suspend_info->do_spin)
363 {
364 HYPERVISOR_yield(xpdd);
365 /* we should be able to wait more nicely than this... */
366 }
367 KeMemoryBarrier();
368 InterlockedDecrement(&suspend_info->nr_spinning);
369 KdPrint((__DRIVER_NAME " ...done spinning\n"));
370 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n", KeGetCurrentProcessorNumber()));
371 KeLowerIrql(old_irql);
372 return;
373 }
374 ActiveProcessorCount = (ULONG)KeNumberProcessors;
376 KeRaiseIrql(HIGH_LEVEL, &old_irql);
378 KdPrint((__DRIVER_NAME " waiting for all other processors to spin\n"));
379 while (suspend_info->nr_spinning < (LONG)ActiveProcessorCount - 1)
380 {
381 HYPERVISOR_yield(xpdd);
382 }
383 KdPrint((__DRIVER_NAME " all other processors are spinning\n"));
385 // make a backup of the grant table - we are going to keep it instead of throwing it away
386 //memcpy(gnttbl_backup, xpdd->gnttab_table, PAGE_SIZE * NR_GRANT_FRAMES);
388 KdPrint((__DRIVER_NAME " calling suspend\n"));
389 cancelled = hvm_shutdown(Context, SHUTDOWN_suspend);
390 KdPrint((__DRIVER_NAME " back from suspend, cancelled = %d\n", cancelled));
392 XenPci_Init(xpdd);
394 GntTbl_Map(Context, 0, NR_GRANT_FRAMES - 1);
396 /* this enabled interrupts again too */
397 EvtChn_Init(xpdd);
399 //memcpy(xpdd->gnttab_table, gnttbl_backup, PAGE_SIZE * NR_GRANT_FRAMES);
401 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
402 {
403 child->context->device_state.resume_state = RESUME_STATE_BACKEND_RESUME;
404 }
406 KeLowerIrql(old_irql);
408 KdPrint((__DRIVER_NAME " waiting for all other processors to stop spinning\n"));
409 suspend_info->do_spin = 0;
410 while (suspend_info->nr_spinning != 0)
411 {
412 HYPERVISOR_yield(xpdd);
413 }
414 KdPrint((__DRIVER_NAME " all other processors have stopped spinning\n"));
416 work_item = IoAllocateWorkItem(xpdd->common.fdo);
417 IoQueueWorkItem(work_item, XenPci_CompleteResume, DelayedWorkQueue, NULL);
419 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
420 }
422 /* Called at PASSIVE_LEVEL */
423 static VOID
424 XenPci_BeginSuspend(PXENPCI_DEVICE_DATA xpdd)
425 {
426 //KAFFINITY ActiveProcessorMask = 0; // this is for Vista+
427 ULONG ActiveProcessorCount;
428 ULONG i;
429 PSUSPEND_INFO suspend_info;
430 PKDPC Dpc;
431 KIRQL OldIrql;
433 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
435 if (!xpdd->suspending)
436 {
437 xpdd->suspending = 1;
438 suspend_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(SUSPEND_INFO), XENPCI_POOL_TAG);
439 RtlZeroMemory(suspend_info, sizeof(SUSPEND_INFO));
440 suspend_info->do_spin = 1;
442 // I think we need to synchronise with the interrupt here...
444 for (i = 0; i < MAX_VIRT_CPUS; i++)
445 {
446 xpdd->shared_info_area->vcpu_info[i].evtchn_upcall_mask = 1;
447 }
448 KeMemoryBarrier();
449 EvtChn_Shutdown(xpdd);
450 KeFlushQueuedDpcs();
452 //ActiveProcessorCount = KeQueryActiveProcessorCount(&ActiveProcessorMask); // this is for Vista+
453 ActiveProcessorCount = (ULONG)KeNumberProcessors;
454 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
455 for (i = 0; i < ActiveProcessorCount; i++)
456 {
457 Dpc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KDPC), XENPCI_POOL_TAG);
458 KeInitializeDpc(Dpc, XenPci_Suspend, xpdd);
459 KeSetTargetProcessorDpc(Dpc, (CCHAR)i);
460 KeInsertQueueDpc(Dpc, suspend_info, NULL);
461 }
462 KeLowerIrql(OldIrql);
463 }
464 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
465 }
467 static void
468 XenPci_ShutdownHandler(char *path, PVOID context)
469 {
470 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)context;
471 char *res;
472 char *value;
473 KIRQL old_irql;
475 UNREFERENCED_PARAMETER(path);
477 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
479 res = XenBus_Read(xpdd, XBT_NIL, SHUTDOWN_PATH, &value);
480 if (res)
481 {
482 KdPrint(("Error reading shutdown path - %s\n", res));
483 XenPci_FreeMem(res);
484 return;
485 }
487 KdPrint((__DRIVER_NAME " Shutdown value = %s\n", value));
489 if (strlen(value) != 0)
490 {
491 if (strcmp(value, "suspend") == 0)
492 {
493 KdPrint((__DRIVER_NAME " Suspend detected\n"));
494 XenPci_BeginSuspend(xpdd);
495 }
496 else
497 {
498 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
499 if (xpdd->shutdown_start >= xpdd->shutdown_cons)
500 xpdd->shutdown_prod = xpdd->shutdown_start;
501 else
502 xpdd->shutdown_start = xpdd->shutdown_prod;
503 memcpy(&xpdd->shutdown_ring[xpdd->shutdown_prod], value, strlen(value));
504 xpdd->shutdown_prod += (ULONG)strlen(value);
505 xpdd->shutdown_ring[xpdd->shutdown_prod++] = '\r';
506 xpdd->shutdown_ring[xpdd->shutdown_prod++] = '\n';
507 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
508 XenPci_ProcessShutdownIrp(xpdd);
509 }
510 }
512 //XenPci_FreeMem(value);
514 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
515 }
517 static VOID
518 XenPci_SysrqHandler(char *path, PVOID context)
519 {
520 PXENPCI_DEVICE_DATA xpdd = context;
521 char *value;
522 char letter;
523 char *res;
525 UNREFERENCED_PARAMETER(path);
527 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
529 XenBus_Read(xpdd, XBT_NIL, SYSRQ_PATH, &value);
531 KdPrint((__DRIVER_NAME " SysRq Value = %s\n", value));
533 if (value != NULL && strlen(value) != 0)
534 {
535 letter = *value;
536 res = XenBus_Write(xpdd, XBT_NIL, SYSRQ_PATH, "");
537 if (res)
538 {
539 KdPrint(("Error writing sysrq path\n"));
540 XenPci_FreeMem(res);
541 return;
542 }
543 }
544 else
545 {
546 letter = 0;
547 }
549 if (value != NULL)
550 {
551 XenPci_FreeMem(value);
552 }
554 switch (letter)
555 {
556 case 'B':
557 KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000001, 0x00000000, 0x00000000, 0x00000000);
558 break;
559 default:
560 KdPrint((" Unhandled sysrq letter %c\n", letter));
561 break;
562 }
564 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
565 }
567 static VOID
568 XenPci_DeviceWatchHandler(char *path, PVOID context)
569 {
570 char **bits;
571 int count;
572 char *err;
573 char *value;
574 PXENPCI_DEVICE_DATA xpdd = context;
576 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
578 // KdPrint((__DRIVER_NAME " path = %s\n", path));
579 bits = SplitString(path, '/', 4, &count);
580 // KdPrint((__DRIVER_NAME " count = %d\n", count));
582 if (count == 3)
583 {
584 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
585 if (err)
586 {
587 /* obviously path no longer exists, in which case the removal is being taken care of elsewhere and we shouldn't invalidate now */
588 XenPci_FreeMem(err);
589 }
590 else
591 {
592 XenPci_FreeMem(value);
593 /* we probably have to be a bit smarter here and do nothing if xenpci isn't running yet */
594 KdPrint((__DRIVER_NAME " Invalidating Device Relations\n"));
595 IoInvalidateDeviceRelations(xpdd->common.pdo, BusRelations);
596 }
597 }
598 FreeSplitString(bits, count);
600 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
601 }
603 static VOID
604 XenPci_Pnp_StartDeviceCallback(PDEVICE_OBJECT device_object, PVOID context)
605 {
606 NTSTATUS status = STATUS_SUCCESS;
607 PXENPCI_DEVICE_DATA xpdd = device_object->DeviceExtension;
608 PIRP irp = context;
609 char *response;
611 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
613 XenPci_Init(xpdd);
615 GntTbl_Init(xpdd);
617 EvtChn_Init(xpdd);
619 XenBus_Init(xpdd);
621 response = XenBus_AddWatch(xpdd, XBT_NIL, SYSRQ_PATH, XenPci_SysrqHandler, xpdd);
622 KdPrint((__DRIVER_NAME " sysrqwatch response = '%s'\n", response));
624 response = XenBus_AddWatch(xpdd, XBT_NIL, SHUTDOWN_PATH, XenPci_ShutdownHandler, xpdd);
625 KdPrint((__DRIVER_NAME " shutdown watch response = '%s'\n", response));
627 response = XenBus_AddWatch(xpdd, XBT_NIL, "device", XenPci_DeviceWatchHandler, xpdd);
628 KdPrint((__DRIVER_NAME " device watch response = '%s'\n", response));
630 #if 0
631 response = XenBus_AddWatch(xpdd, XBT_NIL, BALLOON_PATH, XenPci_BalloonHandler, Device);
632 KdPrint((__DRIVER_NAME " balloon watch response = '%s'\n", response));
633 #endif
635 status = IoSetDeviceInterfaceState(&xpdd->interface_name, TRUE);
636 if (!NT_SUCCESS(status))
637 {
638 KdPrint((__DRIVER_NAME " IoSetDeviceInterfaceState failed with status 0x%08x\n", status));
639 }
641 irp->IoStatus.Status = status;
643 IoCompleteRequest(irp, IO_NO_INCREMENT);
645 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
646 }
648 static NTSTATUS
649 XenPci_Pnp_StartDevice(PDEVICE_OBJECT device_object, PIRP irp)
650 {
651 NTSTATUS status;
652 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
653 PIO_STACK_LOCATION stack;
654 PCM_PARTIAL_RESOURCE_LIST res_list;
655 PCM_PARTIAL_RESOURCE_DESCRIPTOR res_descriptor;
656 ULONG i;
658 UNREFERENCED_PARAMETER(device_object);
660 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
662 stack = IoGetCurrentIrpStackLocation(irp);
664 IoMarkIrpPending(irp);
666 status = XenPci_SendAndWaitForIrp(device_object, irp);
668 res_list = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
670 for (i = 0; i < res_list->Count; i++)
671 {
672 res_descriptor = &res_list->PartialDescriptors[i];
673 switch (res_descriptor->Type)
674 {
675 case CmResourceTypeInterrupt:
676 KdPrint((__DRIVER_NAME " irq_number = %03x\n", res_descriptor->u.Interrupt.Vector));
677 xpdd->irq_number = res_descriptor->u.Interrupt.Vector;
678 //memcpy(&InterruptRaw, res_descriptor, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
679 break;
680 }
681 }
683 res_list = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
685 for (i = 0; i < res_list->Count; i++)
686 {
687 res_descriptor = &res_list->PartialDescriptors[i];
688 switch (res_descriptor->Type) {
689 case CmResourceTypePort:
690 break;
691 case CmResourceTypeMemory:
692 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));
693 KdPrint((__DRIVER_NAME " Memory flags = %04X\n", res_descriptor->Flags));
694 xpdd->platform_mmio_addr = res_descriptor->u.Memory.Start;
695 xpdd->platform_mmio_len = res_descriptor->u.Memory.Length;
696 xpdd->platform_mmio_alloc = 0;
697 xpdd->platform_mmio_flags = res_descriptor->Flags;
698 break;
699 case CmResourceTypeInterrupt:
700 KdPrint((__DRIVER_NAME " irq_vector = %03x\n", res_descriptor->u.Interrupt.Vector));
701 KdPrint((__DRIVER_NAME " irq_level = %03x\n", res_descriptor->u.Interrupt.Level));
702 xpdd->irq_level = (KIRQL)res_descriptor->u.Interrupt.Level;
703 xpdd->irq_vector = res_descriptor->u.Interrupt.Vector;
704 xpdd->irq_affinity = res_descriptor->u.Interrupt.Affinity;
705 //memcpy(&InterruptTranslated, res_descriptor, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
706 break;
707 case CmResourceTypeDevicePrivate:
708 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] ));
709 break;
710 default:
711 KdPrint((__DRIVER_NAME " Unhandled resource type (0x%x)\n", res_descriptor->Type));
712 break;
713 }
714 }
716 XenPci_QueueWorkItem(device_object, XenPci_Pnp_StartDeviceCallback, irp);
718 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
720 return STATUS_PENDING;
721 }
723 static NTSTATUS
724 XenPci_Pnp_StopDevice(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
725 {
726 NTSTATUS status = STATUS_SUCCESS;
728 UNREFERENCED_PARAMETER(device_object);
729 UNREFERENCED_PARAMETER(context);
731 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
733 irp->IoStatus.Status = status;
734 IoCompleteRequest(irp, IO_NO_INCREMENT);
736 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
738 return irp->IoStatus.Status;
739 }
741 static NTSTATUS
742 XenPci_Pnp_QueryStopRemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
743 {
744 NTSTATUS status;
745 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
747 UNREFERENCED_PARAMETER(device_object);
749 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
751 if (xpdd->common.device_usage_paging
752 || xpdd->common.device_usage_dump
753 || xpdd->common.device_usage_hibernation)
754 {
755 /* We are in the paging or hibernation path - can't remove */
756 status = irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
757 IoCompleteRequest(irp, IO_NO_INCREMENT);
758 }
759 else
760 {
761 IoSkipCurrentIrpStackLocation(irp);
762 status = IoCallDriver(xpdd->common.lower_do, irp);
763 }
765 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
767 return status;
768 }
770 static NTSTATUS
771 XenPci_Pnp_RemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
772 {
773 NTSTATUS status;
774 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
776 UNREFERENCED_PARAMETER(device_object);
778 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
780 irp->IoStatus.Status = STATUS_SUCCESS;
781 IoSkipCurrentIrpStackLocation(irp);
782 status = IoCallDriver(xpdd->common.lower_do, irp);
783 IoDetachDevice(xpdd->common.lower_do);
785 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
787 return status;
788 }
790 static VOID
791 XenPci_Pnp_QueryBusRelationsCallback(PDEVICE_OBJECT device_object, PVOID context)
792 {
793 NTSTATUS status = STATUS_SUCCESS;
794 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
795 PXENPCI_PDO_DEVICE_DATA xppdd;
796 PIRP irp = context;
797 int device_count = 0;
798 PDEVICE_RELATIONS dev_relations;
799 PXEN_CHILD child, old_child;
800 //char *response;
801 char *msg;
802 char **devices;
803 char **instances;
804 int i, j;
805 CHAR path[128];
806 PDEVICE_OBJECT pdo;
808 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
810 msg = XenBus_List(xpdd, XBT_NIL, "device", &devices);
811 if (!msg)
812 {
813 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
814 {
815 if (child->state == CHILD_STATE_DELETED)
816 KdPrint((__DRIVER_NAME " Found deleted child - this shouldn't happen\n" ));
817 child->state = CHILD_STATE_DELETED;
818 }
820 for (i = 0; devices[i]; i++)
821 {
822 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s", devices[i]);
823 msg = XenBus_List(xpdd, XBT_NIL, path, &instances);
824 if (!msg)
825 {
826 for (j = 0; instances[j]; j++)
827 {
828 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s/%s", devices[i], instances[j]);
830 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
831 {
832 if (strcmp(child->context->path, path) == 0)
833 {
834 KdPrint((__DRIVER_NAME " Existing device %s\n", path));
835 ASSERT(child->state == CHILD_STATE_DELETED);
836 child->state = CHILD_STATE_ADDED;
837 device_count++;
838 break;
839 }
840 }
842 if (child == (PXEN_CHILD)&xpdd->child_list)
843 {
844 KdPrint((__DRIVER_NAME " New device %s\n", path));
845 child = ExAllocatePoolWithTag(NonPagedPool, sizeof(XEN_CHILD), XENPCI_POOL_TAG);
846 child->state = CHILD_STATE_ADDED;
847 status = IoCreateDeviceSecure(
848 xpdd->common.fdo->DriverObject,
849 sizeof(XENPCI_PDO_DEVICE_DATA),
850 NULL,
851 FILE_DEVICE_UNKNOWN,
852 FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN,
853 FALSE,
854 &SDDL_DEVOBJ_SYS_ALL_ADM_ALL,
855 (LPCGUID)&GUID_XENPCI_DEVCLASS,
856 &pdo);
857 if (!NT_SUCCESS(status))
858 KdPrint((__DRIVER_NAME " IoCreateDevice status = %08X\n", status));
859 RtlZeroMemory(pdo->DeviceExtension, sizeof(XENPCI_PDO_DEVICE_DATA));
860 child->context = xppdd = pdo->DeviceExtension;
861 xppdd->common.fdo = NULL;
862 xppdd->common.pdo = pdo;
863 ObReferenceObject(pdo);
864 xppdd->common.lower_do = NULL;
865 INIT_PNP_STATE(&xppdd->common);
866 xppdd->common.device_usage_paging = 0;
867 xppdd->common.device_usage_dump = 0;
868 xppdd->common.device_usage_hibernation = 0;
869 xppdd->bus_fdo = xpdd->common.fdo;
870 xppdd->bus_pdo = xpdd->common.pdo;
871 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), path);
872 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), devices[i]);
873 xppdd->index = atoi(instances[j]);
874 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
875 xppdd->backend_state = XenbusStateUnknown;
876 xppdd->backend_path[0] = '\0';
877 InsertTailList(&xpdd->child_list, (PLIST_ENTRY)child);
878 device_count++;
879 }
880 XenPci_FreeMem(instances[j]);
881 }
882 XenPci_FreeMem(instances);
883 }
884 XenPci_FreeMem(devices[i]);
885 }
886 XenPci_FreeMem(devices);
887 dev_relations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (device_count - 1), XENPCI_POOL_TAG);
888 for (child = (PXEN_CHILD)xpdd->child_list.Flink, device_count = 0; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
889 {
890 if (child->state == CHILD_STATE_ADDED)
891 {
892 ObReferenceObject(child->context->common.pdo);
893 dev_relations->Objects[device_count++] = child->context->common.pdo;
894 }
895 }
896 dev_relations->Count = device_count;
898 child = (PXEN_CHILD)xpdd->child_list.Flink;
899 while (child != (PXEN_CHILD)&xpdd->child_list)
900 {
901 if (child->state == CHILD_STATE_DELETED)
902 {
903 KdPrint((__DRIVER_NAME " Removing deleted child from device list\n" ));
904 old_child = child;
905 child = (PXEN_CHILD)child->entry.Flink;
906 RemoveEntryList((PLIST_ENTRY)old_child);
907 xppdd = old_child->context;
908 xppdd->reported_missing = TRUE;
909 ObDereferenceObject(xppdd->common.pdo);
910 ExFreePoolWithTag(old_child, XENPCI_POOL_TAG);
911 }
912 else
913 child = (PXEN_CHILD)child->entry.Flink;
914 }
916 status = STATUS_SUCCESS;
917 }
918 else
919 {
920 /* this should probably fail in an even worse way - a failure here means we failed to do an ls in xenbus so something is really really wrong */
921 device_count = 0;
922 dev_relations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (device_count - 1), XENPCI_POOL_TAG);
923 dev_relations->Count = device_count;
924 }
926 irp->IoStatus.Status = status;
927 irp->IoStatus.Information = (ULONG_PTR)dev_relations;
929 IoCompleteRequest (irp, IO_NO_INCREMENT);
931 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
932 }
934 static NTSTATUS
935 XenPci_Pnp_QueryBusRelations(PDEVICE_OBJECT device_object, PIRP irp)
936 {
937 NTSTATUS status;
939 UNREFERENCED_PARAMETER(device_object);
941 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
943 IoMarkIrpPending(irp);
945 status = XenPci_SendAndWaitForIrp(device_object, irp);
947 XenPci_QueueWorkItem(device_object, XenPci_Pnp_QueryBusRelationsCallback, irp);
949 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
951 return STATUS_PENDING;
952 }
954 static VOID
955 XenPci_Pnp_FilterResourceRequirementsCallback(PDEVICE_OBJECT device_object, PVOID context)
956 {
957 NTSTATUS status = STATUS_SUCCESS;
958 //PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
959 PIRP irp = context;
960 PIO_RESOURCE_REQUIREMENTS_LIST irrl;
961 ULONG irl;
962 ULONG ird;
964 UNREFERENCED_PARAMETER(device_object);
966 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (status = %08X)\n", irp->IoStatus.Status));
968 irrl = (PIO_RESOURCE_REQUIREMENTS_LIST)irp->IoStatus.Information;
969 for (irl = 0; irl < irrl->AlternativeLists; irl++)
970 {
971 for (ird = 0; ird < irrl->List[irl].Count; ird++)
972 {
973 if (irrl->List[irl].Descriptors[ird].Type == CmResourceTypeMemory)
974 {
975 irrl->List[irl].Descriptors[ird].ShareDisposition = CmResourceShareShared;
976 }
977 }
978 }
979 irp->IoStatus.Status = status;
980 IoCompleteRequest (irp, IO_NO_INCREMENT);
982 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
984 return;
985 }
987 static NTSTATUS
988 XenPci_Pnp_FilterResourceRequirements(PDEVICE_OBJECT device_object, PIRP irp)
989 {
990 NTSTATUS status;
992 UNREFERENCED_PARAMETER(device_object);
994 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
996 IoMarkIrpPending(irp);
998 status = XenPci_SendAndWaitForIrp(device_object, irp);
1000 XenPci_QueueWorkItem(device_object, XenPci_Pnp_FilterResourceRequirementsCallback, irp);
1002 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1004 return STATUS_PENDING;
1007 static NTSTATUS
1008 XenPci_Pnp_DeviceUsageNotification(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
1010 NTSTATUS status;
1011 PXENPCI_DEVICE_DATA xpdd;
1012 PIO_STACK_LOCATION stack;
1014 UNREFERENCED_PARAMETER(context);
1016 KdPrint((__DRIVER_NAME " --> " __FUNCTION__"\n"));
1018 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1019 stack = IoGetCurrentIrpStackLocation(irp);
1020 status = irp->IoStatus.Status;
1022 /* fail if we are in a stop or remove pending state */
1023 if (!NT_SUCCESS(irp->IoStatus.Status))
1025 switch (stack->Parameters.UsageNotification.Type)
1027 case DeviceUsageTypePaging:
1028 if (stack->Parameters.UsageNotification.InPath)
1029 xpdd->common.device_usage_paging--;
1030 else
1031 xpdd->common.device_usage_paging++;
1032 break;
1033 case DeviceUsageTypeDumpFile:
1034 if (stack->Parameters.UsageNotification.InPath)
1035 xpdd->common.device_usage_dump--;
1036 else
1037 xpdd->common.device_usage_dump++;
1038 break;
1039 case DeviceUsageTypeHibernation:
1040 if (stack->Parameters.UsageNotification.InPath)
1041 xpdd->common.device_usage_hibernation--;
1042 else
1043 xpdd->common.device_usage_hibernation++;
1044 break;
1046 if (xpdd->common.device_usage_paging
1047 || xpdd->common.device_usage_dump
1048 || xpdd->common.device_usage_hibernation)
1050 xpdd->common.fdo->Flags &= ~DO_POWER_PAGABLE;
1052 IoInvalidateDeviceState(xpdd->common.pdo);
1054 IoCompleteRequest(irp, IO_NO_INCREMENT);
1056 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1058 return status;
1062 NTSTATUS
1063 XenPci_Pnp_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1065 NTSTATUS status;
1066 PIO_STACK_LOCATION stack;
1067 PXENPCI_DEVICE_DATA xpdd;
1069 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1071 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1073 stack = IoGetCurrentIrpStackLocation(irp);
1075 switch (stack->MinorFunction)
1077 case IRP_MN_START_DEVICE:
1078 KdPrint((__DRIVER_NAME " IRP_MN_START_DEVICE\n"));
1079 return XenPci_Pnp_StartDevice(device_object, irp);
1081 case IRP_MN_QUERY_STOP_DEVICE:
1082 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_STOP_DEVICE\n"));
1083 status = XenPci_Pnp_QueryStopRemoveDevice(device_object, irp);
1084 if (NT_SUCCESS(status))
1085 SET_PNP_STATE(&xpdd->common, RemovePending);
1086 return status;
1088 case IRP_MN_STOP_DEVICE:
1089 KdPrint((__DRIVER_NAME " IRP_MN_STOP_DEVICE\n"));
1090 IoCopyCurrentIrpStackLocationToNext(irp);
1091 IoSetCompletionRoutine(irp, XenPci_Pnp_StopDevice, NULL, TRUE, TRUE, TRUE);
1092 break;
1094 case IRP_MN_CANCEL_STOP_DEVICE:
1095 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_STOP_DEVICE\n"));
1096 IoSkipCurrentIrpStackLocation(irp);
1097 REVERT_PNP_STATE(&xpdd->common);
1098 irp->IoStatus.Status = STATUS_SUCCESS;
1099 break;
1101 case IRP_MN_QUERY_REMOVE_DEVICE:
1102 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_REMOVE_DEVICE\n"));
1103 status = XenPci_Pnp_QueryStopRemoveDevice(device_object, irp);
1104 if (NT_SUCCESS(status))
1105 SET_PNP_STATE(&xpdd->common, RemovePending);
1106 return status;
1108 case IRP_MN_REMOVE_DEVICE:
1109 KdPrint((__DRIVER_NAME " IRP_MN_REMOVE_DEVICE\n"));
1110 return XenPci_Pnp_RemoveDevice(device_object, irp);
1111 break;
1113 case IRP_MN_CANCEL_REMOVE_DEVICE:
1114 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_REMOVE_DEVICE\n"));
1115 IoSkipCurrentIrpStackLocation(irp);
1116 REVERT_PNP_STATE(&xpdd->common);
1117 irp->IoStatus.Status = STATUS_SUCCESS;
1118 break;
1120 case IRP_MN_SURPRISE_REMOVAL:
1121 KdPrint((__DRIVER_NAME " IRP_MN_SURPRISE_REMOVAL\n"));
1122 IoSkipCurrentIrpStackLocation(irp);
1123 irp->IoStatus.Status = STATUS_SUCCESS;
1124 break;
1126 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1127 KdPrint((__DRIVER_NAME " IRP_MN_DEVICE_USAGE_NOTIFICATION\n"));
1128 switch (stack->Parameters.UsageNotification.Type)
1130 case DeviceUsageTypePaging:
1131 KdPrint((__DRIVER_NAME " type = DeviceUsageTypePaging = %d\n", stack->Parameters.UsageNotification.InPath));
1132 if (stack->Parameters.UsageNotification.InPath)
1133 xpdd->common.device_usage_paging++;
1134 else
1135 xpdd->common.device_usage_paging--;
1136 irp->IoStatus.Status = STATUS_SUCCESS;
1137 break;
1138 case DeviceUsageTypeDumpFile:
1139 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeDumpFile = %d\n", stack->Parameters.UsageNotification.InPath));
1140 if (stack->Parameters.UsageNotification.InPath)
1141 xpdd->common.device_usage_dump++;
1142 else
1143 xpdd->common.device_usage_dump--;
1144 irp->IoStatus.Status = STATUS_SUCCESS;
1145 break;
1146 case DeviceUsageTypeHibernation:
1147 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeHibernation = %d\n", stack->Parameters.UsageNotification.InPath));
1148 if (stack->Parameters.UsageNotification.InPath)
1149 xpdd->common.device_usage_hibernation++;
1150 else
1151 xpdd->common.device_usage_hibernation--;
1152 irp->IoStatus.Status = STATUS_SUCCESS;
1153 break;
1154 default:
1155 KdPrint((__DRIVER_NAME " type = unsupported (%d)\n", stack->Parameters.UsageNotification.Type));
1156 irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
1157 IoCompleteRequest(irp, IO_NO_INCREMENT);
1158 return STATUS_NOT_SUPPORTED;
1160 if (!xpdd->common.device_usage_paging
1161 && !xpdd->common.device_usage_dump
1162 && !xpdd->common.device_usage_hibernation)
1164 xpdd->common.fdo->Flags |= DO_POWER_PAGABLE;
1166 IoInvalidateDeviceState(xpdd->common.pdo);
1167 IoCopyCurrentIrpStackLocationToNext(irp);
1168 IoSetCompletionRoutine(irp, XenPci_Pnp_DeviceUsageNotification, NULL, TRUE, TRUE, TRUE);
1169 break;
1171 case IRP_MN_QUERY_DEVICE_RELATIONS:
1172 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_RELATIONS\n"));
1173 switch (stack->Parameters.QueryDeviceRelations.Type)
1175 case BusRelations:
1176 KdPrint((__DRIVER_NAME " BusRelations\n"));
1177 return XenPci_Pnp_QueryBusRelations(device_object, irp);
1178 break;
1179 default:
1180 IoSkipCurrentIrpStackLocation(irp);
1181 break;
1183 break;
1185 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1186 KdPrint((__DRIVER_NAME " IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"));
1187 return XenPci_Pnp_FilterResourceRequirements(device_object, irp);
1189 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1190 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_PNP_DEVICE_STATE\n"));
1191 irp->IoStatus.Status = STATUS_SUCCESS;
1192 if (xpdd->common.device_usage_paging
1193 || xpdd->common.device_usage_dump
1194 || xpdd->common.device_usage_hibernation)
1196 irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
1198 IoSkipCurrentIrpStackLocation(irp);
1199 break;
1201 default:
1202 //KdPrint((__DRIVER_NAME " Unhandled Minor = %d\n", stack->MinorFunction));
1203 IoSkipCurrentIrpStackLocation(irp);
1204 break;
1207 status = IoCallDriver(xpdd->common.lower_do, irp);
1209 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1211 return status;
1214 NTSTATUS
1215 XenPci_Irp_Create_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1217 PXENPCI_DEVICE_DATA xpdd;
1218 NTSTATUS status;
1220 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1222 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1223 status = STATUS_SUCCESS;
1224 irp->IoStatus.Status = status;
1225 IoCompleteRequest(irp, IO_NO_INCREMENT);
1227 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1229 return status;
1232 NTSTATUS
1233 XenPci_Irp_Close_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1235 PXENPCI_DEVICE_DATA xpdd;
1236 NTSTATUS status;
1238 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1240 // wait until pending irp's
1241 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1242 status = STATUS_SUCCESS;
1243 irp->IoStatus.Status = status;
1244 IoCompleteRequest(irp, IO_NO_INCREMENT);
1246 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1248 return status;
1251 NTSTATUS
1252 XenPci_Irp_Read_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1254 PXENPCI_DEVICE_DATA xpdd;
1255 NTSTATUS status;
1256 PIO_STACK_LOCATION stack;
1257 KIRQL old_irql;
1259 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1261 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1262 stack = IoGetCurrentIrpStackLocation(irp);
1263 if (stack->Parameters.Read.Length == 0)
1265 irp->IoStatus.Information = 0;
1266 status = STATUS_SUCCESS;
1267 irp->IoStatus.Status = status;
1268 IoCompleteRequest(irp, IO_NO_INCREMENT);
1270 else
1272 KdPrint((__DRIVER_NAME " stack = %p\n", stack));
1273 KdPrint((__DRIVER_NAME " length = %d, buffer = %p\n", stack->Parameters.Read.Length, irp->AssociatedIrp.SystemBuffer));
1275 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
1276 xpdd->shutdown_irp = irp;
1277 IoSetCancelRoutine(irp, XenBus_ShutdownIoCancel);
1278 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
1279 status = XenPci_ProcessShutdownIrp(xpdd);
1281 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1283 return status;
1287 NTSTATUS
1288 XenPci_Irp_Cleanup_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1290 NTSTATUS status;
1292 UNREFERENCED_PARAMETER(device_object);
1294 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1296 status = STATUS_SUCCESS;
1297 irp->IoStatus.Status = status;
1298 IoCompleteRequest(irp, IO_NO_INCREMENT);
1300 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1302 return status;
1305 #if 0
1306 static VOID
1307 XenPci_BalloonHandler(char *Path, PVOID Data)
1309 WDFDEVICE Device = Data;
1310 char *value;
1311 xenbus_transaction_t xbt;
1312 int retry;
1314 UNREFERENCED_PARAMETER(Path);
1316 KdPrint((__DRIVER_NAME " --> XenBus_BalloonHandler\n"));
1318 XenBus_StartTransaction(Device, &xbt);
1320 XenBus_Read(Device, XBT_NIL, BALLOON_PATH, &value);
1322 KdPrint((__DRIVER_NAME " Balloon Value = %s\n", value));
1324 // use the memory_op(unsigned int op, void *arg) hypercall to adjust this
1325 // use XENMEM_increase_reservation and XENMEM_decrease_reservation
1327 XenBus_EndTransaction(Device, xbt, 0, &retry);
1329 XenPci_FreeMem(value);
1331 KdPrint((__DRIVER_NAME " <-- XenBus_BalloonHandler\n"));
1333 #endif