win-pvdrivers

view xenpci/xenpci_fdo.c @ 403:abdcb860cfdf

More suspend/resume updates.
author James Harper <james.harper@bendigoit.com.au>
date Mon Jul 21 11:47:29 2008 +1000 (2008-07-21)
parents 04883e1dc65c
children b9028997f48b
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 #if 0
29 static VOID
30 XenBus_BalloonHandler(char *Path, PVOID Data);
31 #endif
33 /*
34 static VOID
35 XenPCI_XenBusWatchHandler(char *Path, PVOID Data);
36 */
38 #pragma warning(disable : 4200) // zero-sized array
40 //CM_PARTIAL_RESOURCE_DESCRIPTOR InterruptRaw;
41 //CM_PARTIAL_RESOURCE_DESCRIPTOR InterruptTranslated;
43 NTSTATUS
44 XenPci_Power_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
45 {
46 NTSTATUS status;
47 PIO_STACK_LOCATION stack;
48 POWER_STATE_TYPE power_type;
49 POWER_STATE power_state;
50 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
51 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
53 UNREFERENCED_PARAMETER(device_object);
55 FUNCTION_ENTER();
57 stack = IoGetCurrentIrpStackLocation(irp);
58 power_type = stack->Parameters.Power.Type;
59 power_state = stack->Parameters.Power.State;
61 switch (stack->MinorFunction)
62 {
63 case IRP_MN_POWER_SEQUENCE:
64 KdPrint((__DRIVER_NAME " IRP_MN_POWER_SEQUENCE\n"));
65 break;
66 case IRP_MN_QUERY_POWER:
67 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_POWER\n"));
68 break;
69 case IRP_MN_SET_POWER:
70 KdPrint((__DRIVER_NAME " IRP_MN_SET_POWER\n"));
71 switch (power_type) {
72 case DevicePowerState:
73 KdPrint((__DRIVER_NAME " DevicePowerState\n"));
74 break;
75 case SystemPowerState:
76 KdPrint((__DRIVER_NAME " SystemPowerState\n"));
77 break;
78 default:
79 break;
80 }
81 break;
82 case IRP_MN_WAIT_WAKE:
83 break;
84 }
85 PoStartNextPowerIrp(irp);
86 IoSkipCurrentIrpStackLocation(irp);
87 status = PoCallDriver (xpdd->common.lower_do, irp);
89 FUNCTION_EXIT();
91 return status;
92 }
94 NTSTATUS
95 XenPci_Dummy_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
96 {
97 NTSTATUS status;
98 PIO_STACK_LOCATION stack;
99 PXENPCI_DEVICE_DATA xpdd;
101 FUNCTION_ENTER();
103 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
104 stack = IoGetCurrentIrpStackLocation(irp);
105 IoSkipCurrentIrpStackLocation(irp);
106 status = IoCallDriver(xpdd->common.lower_do, irp);
108 FUNCTION_EXIT();
110 return status;
111 }
113 /*
114 * Alloc MMIO from the device's MMIO region. There is no corresponding free() fn
115 */
116 PHYSICAL_ADDRESS
117 XenPci_AllocMMIO(PXENPCI_DEVICE_DATA xpdd, ULONG len)
118 {
119 PHYSICAL_ADDRESS addr;
121 len = (len + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
123 addr = xpdd->platform_mmio_addr;
124 addr.QuadPart += xpdd->platform_mmio_alloc;
125 xpdd->platform_mmio_alloc += len;
127 ASSERT(xpdd->platform_mmio_alloc <= xpdd->platform_mmio_len);
129 return addr;
130 }
132 static NTSTATUS
133 XenPci_Init(PXENPCI_DEVICE_DATA xpdd)
134 {
135 struct xen_add_to_physmap xatp;
136 int ret;
138 FUNCTION_ENTER();
140 hvm_get_stubs(xpdd);
142 if (!xpdd->shared_info_area_unmapped.QuadPart)
143 {
144 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
145 /* this should be safe as this part will never be called on resume where IRQL == HIGH_LEVEL */
146 xpdd->shared_info_area_unmapped = XenPci_AllocMMIO(xpdd, PAGE_SIZE);
147 xpdd->shared_info_area = MmMapIoSpace(xpdd->shared_info_area_unmapped,
148 PAGE_SIZE, MmNonCached);
149 }
150 KdPrint((__DRIVER_NAME " shared_info_area_unmapped.QuadPart = %lx\n", xpdd->shared_info_area_unmapped.QuadPart));
151 xatp.domid = DOMID_SELF;
152 xatp.idx = 0;
153 xatp.space = XENMAPSPACE_shared_info;
154 xatp.gpfn = (xen_pfn_t)(xpdd->shared_info_area_unmapped.QuadPart >> PAGE_SHIFT);
155 KdPrint((__DRIVER_NAME " gpfn = %d\n", xatp.gpfn));
156 ret = HYPERVISOR_memory_op(xpdd, XENMEM_add_to_physmap, &xatp);
157 KdPrint((__DRIVER_NAME " hypervisor memory op ret = %d\n", ret));
159 FUNCTION_EXIT();
161 return STATUS_SUCCESS;
162 }
164 static NTSTATUS
165 XenPci_Pnp_IoCompletion(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
166 {
167 PKEVENT event = (PKEVENT)context;
169 UNREFERENCED_PARAMETER(device_object);
171 FUNCTION_ENTER();
173 if (irp->PendingReturned)
174 {
175 KeSetEvent(event, IO_NO_INCREMENT, FALSE);
176 }
178 FUNCTION_EXIT();
180 return STATUS_MORE_PROCESSING_REQUIRED;
181 }
183 static NTSTATUS
184 XenPci_QueueWorkItem(PDEVICE_OBJECT device_object, PIO_WORKITEM_ROUTINE routine, PVOID context)
185 {
186 PIO_WORKITEM work_item;
187 NTSTATUS status = STATUS_SUCCESS;
189 work_item = IoAllocateWorkItem(device_object);
190 IoQueueWorkItem(work_item, routine, DelayedWorkQueue, context);
192 return status;
193 }
195 static NTSTATUS
196 XenPci_SendAndWaitForIrp(PDEVICE_OBJECT device_object, PIRP irp)
197 {
198 NTSTATUS status;
199 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
200 KEVENT event;
202 UNREFERENCED_PARAMETER(device_object);
204 FUNCTION_ENTER();
206 KeInitializeEvent(&event, NotificationEvent, FALSE);
208 IoCopyCurrentIrpStackLocationToNext(irp);
209 IoSetCompletionRoutine(irp, XenPci_Pnp_IoCompletion, &event, TRUE, TRUE, TRUE);
211 status = IoCallDriver(xpdd->common.lower_do, irp);
213 if (status == STATUS_PENDING)
214 {
215 KdPrint((__DRIVER_NAME " waiting ...\n"));
216 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
217 KdPrint((__DRIVER_NAME " ... done\n"));
218 status = irp->IoStatus.Status;
219 }
221 FUNCTION_EXIT();
223 return status;
224 }
226 static NTSTATUS
227 XenPci_ProcessShutdownIrp(PXENPCI_DEVICE_DATA xpdd)
228 {
229 PIO_STACK_LOCATION stack;
230 NTSTATUS status;
231 PIRP irp;
232 KIRQL old_irql;
233 ULONG length;
235 FUNCTION_ENTER();
237 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
238 if (xpdd->shutdown_irp)
239 {
240 irp = xpdd->shutdown_irp;
241 stack = IoGetCurrentIrpStackLocation(irp);
242 KdPrint((__DRIVER_NAME " stack = %p\n", stack));
243 KdPrint((__DRIVER_NAME " length = %d, buffer = %p\n", stack->Parameters.Read.Length, irp->AssociatedIrp.SystemBuffer));
244 length = min(xpdd->shutdown_prod - xpdd->shutdown_cons, stack->Parameters.Read.Length);
245 KdPrint((__DRIVER_NAME " length = %d\n", length));
246 if (length > 0)
247 {
248 memcpy(irp->AssociatedIrp.SystemBuffer, &xpdd->shutdown_ring[xpdd->shutdown_cons & (SHUTDOWN_RING_SIZE - 1)], length);
249 xpdd->shutdown_cons += length;
250 if (xpdd->shutdown_cons > SHUTDOWN_RING_SIZE)
251 {
252 xpdd->shutdown_cons -= SHUTDOWN_RING_SIZE;
253 xpdd->shutdown_prod -= SHUTDOWN_RING_SIZE;
254 xpdd->shutdown_start -= SHUTDOWN_RING_SIZE;
255 }
256 xpdd->shutdown_irp = NULL;
257 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
258 status = STATUS_SUCCESS;
259 irp->IoStatus.Status = status;
260 irp->IoStatus.Information = length;
261 IoSetCancelRoutine(irp, NULL);
262 IoCompleteRequest(irp, IO_NO_INCREMENT);
263 }
264 else
265 {
266 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
267 KdPrint((__DRIVER_NAME " nothing to read... pending\n"));
268 IoMarkIrpPending(irp);
269 status = STATUS_PENDING;
270 }
271 }
272 else
273 {
274 KdPrint((__DRIVER_NAME " no pending irp\n"));
275 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
276 status = STATUS_SUCCESS;
277 }
279 FUNCTION_EXIT();
281 return status;
282 }
284 static VOID
285 XenBus_ShutdownIoCancel(PDEVICE_OBJECT device_object, PIRP irp)
286 {
287 PXENPCI_DEVICE_DATA xpdd;
288 KIRQL old_irql;
290 FUNCTION_ENTER();
292 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
293 IoReleaseCancelSpinLock(irp->CancelIrql);
294 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
295 if (irp == xpdd->shutdown_irp)
296 {
297 KdPrint((__DRIVER_NAME " Not the current irp???\n"));
298 xpdd->shutdown_irp = NULL;
299 }
300 irp->IoStatus.Status = STATUS_CANCELLED;
301 irp->IoStatus.Information = 0;
302 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
303 IoCompleteRequest(irp, IO_NO_INCREMENT);
305 FUNCTION_EXIT();
306 }
308 struct {
309 volatile ULONG do_spin;
310 volatile LONG nr_spinning;
311 KEVENT stopped_spinning_event;
312 } typedef SUSPEND_INFO, *PSUSPEND_INFO;
314 /* runs at PASSIVE_LEVEL */
315 static DDKAPI VOID
316 XenPci_CompleteResume(PDEVICE_OBJECT device_object, PVOID context)
317 {
318 PSUSPEND_INFO suspend_info = context;
319 PXENPCI_DEVICE_DATA xpdd;
320 PXEN_CHILD child;
322 UNREFERENCED_PARAMETER(context);
323 FUNCTION_ENTER();
325 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
327 while (suspend_info->nr_spinning != 0)
328 {
329 KdPrint((__DRIVER_NAME " %d processors are still spinning\n", suspend_info->nr_spinning));
330 KeWaitForSingleObject(&suspend_info->stopped_spinning_event, Executive, KernelMode, FALSE, NULL);
331 }
332 KdPrint((__DRIVER_NAME " all other processors have stopped spinning\n"));
334 /* this has to be done at PASSIVE_LEVEL */
335 EvtChn_ConnectInterrupt(xpdd);
337 XenBus_Resume(xpdd);
339 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
340 {
341 XenPci_Pdo_Resume(child->context->common.pdo);
342 child->context->device_state.resume_state = RESUME_STATE_FRONTEND_RESUME;
343 // how can we signal children that they are ready to restart again?
344 // maybe we can fake an interrupt?
345 }
347 xpdd->suspend_state = SUSPEND_STATE_NONE;
349 FUNCTION_EXIT();
350 }
352 /* Called at DISPATCH_LEVEL */
353 static DDKAPI VOID
354 XenPci_Suspend(
355 PRKDPC Dpc,
356 PVOID Context,
357 PVOID SystemArgument1,
358 PVOID SystemArgument2)
359 {
360 PXENPCI_DEVICE_DATA xpdd = Context;
361 PSUSPEND_INFO suspend_info = SystemArgument1;
362 ULONG ActiveProcessorCount;
363 KIRQL old_irql;
364 int cancelled;
365 PIO_WORKITEM work_item;
366 PXEN_CHILD child;
367 //PUCHAR gnttbl_backup[PAGE_SIZE * NR_GRANT_FRAMES];
369 UNREFERENCED_PARAMETER(Dpc);
370 UNREFERENCED_PARAMETER(SystemArgument2);
372 FUNCTION_ENTER();
373 FUNCTION_MSG(("(CPU = %d)\n", KeGetCurrentProcessorNumber()));
375 if (KeGetCurrentProcessorNumber() != 0)
376 {
377 KeRaiseIrql(HIGH_LEVEL, &old_irql);
378 KdPrint((__DRIVER_NAME " spinning...\n"));
379 InterlockedIncrement(&suspend_info->nr_spinning);
380 KeMemoryBarrier();
381 while(suspend_info->do_spin)
382 {
383 KeStallExecutionProcessor(1);
384 KeMemoryBarrier();
385 /* can't call HYPERVISOR_yield() here as the stubs will be reset and we will crash */
386 }
387 KeMemoryBarrier();
388 InterlockedDecrement(&suspend_info->nr_spinning);
389 KdPrint((__DRIVER_NAME " ...done spinning\n"));
390 FUNCTION_MSG(("(CPU = %d)\n", KeGetCurrentProcessorNumber()));
391 KeLowerIrql(old_irql);
392 KeSetEvent(&suspend_info->stopped_spinning_event, IO_NO_INCREMENT, FALSE);
393 FUNCTION_EXIT();
394 return;
395 }
396 ActiveProcessorCount = (ULONG)KeNumberProcessors;
398 KeRaiseIrql(HIGH_LEVEL, &old_irql);
400 KdPrint((__DRIVER_NAME " waiting for all other processors to spin\n"));
401 while (suspend_info->nr_spinning < (LONG)ActiveProcessorCount - 1)
402 {
403 HYPERVISOR_yield(xpdd);
404 KeMemoryBarrier();
405 }
406 KdPrint((__DRIVER_NAME " all other processors are spinning\n"));
408 xpdd->suspend_state = SUSPEND_STATE_HIGH_IRQL;
409 KeMemoryBarrier();
411 KdPrint((__DRIVER_NAME " calling suspend\n"));
412 cancelled = hvm_shutdown(Context, SHUTDOWN_suspend);
413 KdPrint((__DRIVER_NAME " back from suspend, cancelled = %d\n", cancelled));
415 XenPci_Init(xpdd);
417 GntTbl_InitMap(Context);
419 /* this enables interrupts again too */
420 EvtChn_Init(xpdd);
422 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
423 {
424 child->context->device_state.resume_state = RESUME_STATE_BACKEND_RESUME;
425 }
427 KeLowerIrql(old_irql);
428 xpdd->suspend_state = SUSPEND_STATE_RESUMING;
429 KeMemoryBarrier();
431 KdPrint((__DRIVER_NAME " waiting for all other processors to stop spinning\n"));
432 suspend_info->do_spin = 0;
433 KeMemoryBarrier();
435 work_item = IoAllocateWorkItem(xpdd->common.fdo);
436 IoQueueWorkItem(work_item, XenPci_CompleteResume, DelayedWorkQueue, suspend_info);
438 FUNCTION_EXIT();
439 }
441 /* Called at PASSIVE_LEVEL */
442 static VOID DDKAPI
443 XenPci_BeginSuspend(PDEVICE_OBJECT device_object, PVOID context)
444 {
445 //KAFFINITY ActiveProcessorMask = 0; // this is for Vista+
446 PXENPCI_DEVICE_DATA xpdd = device_object->DeviceExtension;
447 ULONG ActiveProcessorCount;
448 ULONG i;
449 PSUSPEND_INFO suspend_info;
450 PKDPC Dpc;
451 KIRQL OldIrql;
452 PXEN_CHILD child;
454 UNREFERENCED_PARAMETER(context);
455 FUNCTION_ENTER();
457 if (xpdd->suspend_state == SUSPEND_STATE_NONE)
458 {
459 xpdd->suspend_state = SUSPEND_STATE_SCHEDULED;
460 KeMemoryBarrier();
462 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
463 {
464 XenPci_Pdo_Suspend(child->context->common.pdo);
465 }
467 XenBus_StopThreads(xpdd);
469 suspend_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(SUSPEND_INFO), XENPCI_POOL_TAG);
470 RtlZeroMemory(suspend_info, sizeof(SUSPEND_INFO));
471 KeInitializeEvent(&suspend_info->stopped_spinning_event, SynchronizationEvent, FALSE);
472 suspend_info->do_spin = 1;
474 for (i = 0; i < MAX_VIRT_CPUS; i++)
475 {
476 xpdd->shared_info_area->vcpu_info[i].evtchn_upcall_mask = 1;
477 }
478 KeMemoryBarrier();
479 EvtChn_Shutdown(xpdd);
481 //ActiveProcessorCount = KeQueryActiveProcessorCount(&ActiveProcessorMask); // this is for Vista+
482 ActiveProcessorCount = (ULONG)KeNumberProcessors;
483 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
484 for (i = 0; i < ActiveProcessorCount; i++)
485 {
486 Dpc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KDPC), XENPCI_POOL_TAG);
487 KeInitializeDpc(Dpc, XenPci_Suspend, xpdd);
488 KeSetTargetProcessorDpc(Dpc, (CCHAR)i);
489 KeInsertQueueDpc(Dpc, suspend_info, NULL);
490 }
491 KeLowerIrql(OldIrql);
492 }
493 FUNCTION_EXIT();
494 }
496 static void
497 XenPci_ShutdownHandler(char *path, PVOID context)
498 {
499 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)context;
500 char *res;
501 char *value;
502 KIRQL old_irql;
503 PIO_WORKITEM work_item;
505 UNREFERENCED_PARAMETER(path);
507 FUNCTION_ENTER();
509 res = XenBus_Read(xpdd, XBT_NIL, SHUTDOWN_PATH, &value);
510 if (res)
511 {
512 KdPrint(("Error reading shutdown path - %s\n", res));
513 XenPci_FreeMem(res);
514 return;
515 }
517 KdPrint((__DRIVER_NAME " Shutdown value = %s\n", value));
519 if (strlen(value) != 0)
520 {
521 if (strcmp(value, "suspend") == 0)
522 {
523 KdPrint((__DRIVER_NAME " Suspend detected\n"));
524 /* we have to queue this as a work item as we stop the xenbus thread, which we are currently running in! */
525 work_item = IoAllocateWorkItem(xpdd->common.fdo);
526 IoQueueWorkItem(work_item, XenPci_BeginSuspend, DelayedWorkQueue, NULL);
527 //XenPci_BeginSuspend(xpdd);
528 }
529 else
530 {
531 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
532 if (xpdd->shutdown_start >= xpdd->shutdown_cons)
533 xpdd->shutdown_prod = xpdd->shutdown_start;
534 else
535 xpdd->shutdown_start = xpdd->shutdown_prod;
536 memcpy(&xpdd->shutdown_ring[xpdd->shutdown_prod], value, strlen(value));
537 xpdd->shutdown_prod += (ULONG)strlen(value);
538 xpdd->shutdown_ring[xpdd->shutdown_prod++] = '\r';
539 xpdd->shutdown_ring[xpdd->shutdown_prod++] = '\n';
540 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
541 XenPci_ProcessShutdownIrp(xpdd);
542 }
543 }
545 //XenPci_FreeMem(value);
547 FUNCTION_EXIT();
548 }
550 static DDKAPI void
551 XenBus_DummyXenbusThreadProc(PVOID StartContext)
552 {
553 PXENPCI_DEVICE_DATA xpdd = StartContext;
554 char *value;
555 char *err;
556 LARGE_INTEGER wait_time;
557 int thread_id;
559 thread_id = (int)PsGetCurrentThreadId();
560 for(;;)
561 {
562 KdPrint((__DRIVER_NAME " %08X: writing 666\n", thread_id));
563 XenBus_Write(xpdd, XBT_NIL, "james", "666");
564 err = XenBus_Read(xpdd, XBT_NIL, "james", &value);
565 if (err)
566 {
567 KdPrint((__DRIVER_NAME " %08X: error on read - %s\n", thread_id, err));
568 XenPci_FreeMem(err);
569 }
570 else
571 {
572 KdPrint((__DRIVER_NAME " %08X: read %s\n", thread_id, value));
573 XenPci_FreeMem(value);
574 }
575 KdPrint((__DRIVER_NAME " %08X: writing 362436\n", thread_id));
576 XenBus_Write(xpdd, XBT_NIL, "james", "362436");
577 err = XenBus_Read(xpdd, XBT_NIL, "james", &value);
578 if (err)
579 {
580 KdPrint((__DRIVER_NAME " %08X: error on read - %s\n", thread_id, err));
581 XenPci_FreeMem(err);
582 }
583 else
584 {
585 KdPrint((__DRIVER_NAME " %08X: read %s\n", thread_id, value));
586 XenPci_FreeMem(value);
587 }
588 /*
589 wait_time.QuadPart = 1000 * (-1 * 10 * 1000);
590 KeDelayExecutionThread(KernelMode, FALSE, &wait_time);
591 */
592 }
593 }
595 static VOID
596 XenPci_SysrqHandler(char *path, PVOID context)
597 {
598 PXENPCI_DEVICE_DATA xpdd = context;
599 NTSTATUS status;
600 HANDLE thread_handle;
601 char *value;
602 char letter;
603 char *res;
605 UNREFERENCED_PARAMETER(path);
607 FUNCTION_ENTER();
609 XenBus_Read(xpdd, XBT_NIL, SYSRQ_PATH, &value);
611 KdPrint((__DRIVER_NAME " SysRq Value = %s\n", value));
613 if (value != NULL && strlen(value) != 0)
614 {
615 letter = *value;
616 res = XenBus_Write(xpdd, XBT_NIL, SYSRQ_PATH, "");
617 if (res)
618 {
619 KdPrint(("Error writing sysrq path\n"));
620 XenPci_FreeMem(res);
621 return;
622 }
623 }
624 else
625 {
626 letter = 0;
627 }
629 if (value != NULL)
630 {
631 XenPci_FreeMem(value);
632 }
634 switch (letter)
635 {
636 case 'B':
637 KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000001, 0x00000000, 0x00000000, 0x00000000);
638 break;
639 case 'X':
640 status = PsCreateSystemThread(&thread_handle, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenBus_DummyXenbusThreadProc, xpdd);
641 break;
642 default:
643 KdPrint((" Unhandled sysrq letter %c\n", letter));
644 break;
645 }
647 FUNCTION_EXIT();
648 }
650 static VOID
651 XenPci_DeviceWatchHandler(char *path, PVOID context)
652 {
653 char **bits;
654 int count;
655 char *err;
656 char *value;
657 PXENPCI_DEVICE_DATA xpdd = context;
659 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
661 // KdPrint((__DRIVER_NAME " path = %s\n", path));
662 bits = SplitString(path, '/', 4, &count);
663 // KdPrint((__DRIVER_NAME " count = %d\n", count));
665 if (count == 3)
666 {
667 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
668 if (err)
669 {
670 /* obviously path no longer exists, in which case the removal is being taken care of elsewhere and we shouldn't invalidate now */
671 XenPci_FreeMem(err);
672 }
673 else
674 {
675 XenPci_FreeMem(value);
676 /* we probably have to be a bit smarter here and do nothing if xenpci isn't running yet */
677 KdPrint((__DRIVER_NAME " Invalidating Device Relations\n"));
678 IoInvalidateDeviceRelations(xpdd->common.pdo, BusRelations);
679 }
680 }
681 FreeSplitString(bits, count);
683 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
684 }
686 static DDKAPI VOID
687 XenPci_Pnp_StartDeviceCallback(PDEVICE_OBJECT device_object, PVOID context)
688 {
689 NTSTATUS status = STATUS_SUCCESS;
690 PXENPCI_DEVICE_DATA xpdd = device_object->DeviceExtension;
691 PIRP irp = context;
692 char *response;
694 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
696 XenPci_Init(xpdd);
698 GntTbl_Init(xpdd);
700 EvtChn_Init(xpdd);
701 EvtChn_ConnectInterrupt(xpdd);
703 XenBus_Init(xpdd);
705 response = XenBus_AddWatch(xpdd, XBT_NIL, SYSRQ_PATH, XenPci_SysrqHandler, xpdd);
706 KdPrint((__DRIVER_NAME " sysrqwatch response = '%s'\n", response));
708 response = XenBus_AddWatch(xpdd, XBT_NIL, SHUTDOWN_PATH, XenPci_ShutdownHandler, xpdd);
709 KdPrint((__DRIVER_NAME " shutdown watch response = '%s'\n", response));
711 response = XenBus_AddWatch(xpdd, XBT_NIL, "device", XenPci_DeviceWatchHandler, xpdd);
712 KdPrint((__DRIVER_NAME " device watch response = '%s'\n", response));
714 #if 0
715 response = XenBus_AddWatch(xpdd, XBT_NIL, BALLOON_PATH, XenPci_BalloonHandler, Device);
716 KdPrint((__DRIVER_NAME " balloon watch response = '%s'\n", response));
717 #endif
719 status = IoSetDeviceInterfaceState(&xpdd->interface_name, TRUE);
720 if (!NT_SUCCESS(status))
721 {
722 KdPrint((__DRIVER_NAME " IoSetDeviceInterfaceState failed with status 0x%08x\n", status));
723 }
725 irp->IoStatus.Status = status;
727 IoCompleteRequest(irp, IO_NO_INCREMENT);
729 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
730 }
732 static NTSTATUS
733 XenPci_Pnp_StartDevice(PDEVICE_OBJECT device_object, PIRP irp)
734 {
735 NTSTATUS status;
736 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
737 PIO_STACK_LOCATION stack;
738 PCM_PARTIAL_RESOURCE_LIST res_list;
739 PCM_PARTIAL_RESOURCE_DESCRIPTOR res_descriptor;
740 ULONG i;
742 UNREFERENCED_PARAMETER(device_object);
744 FUNCTION_ENTER();
746 stack = IoGetCurrentIrpStackLocation(irp);
748 IoMarkIrpPending(irp);
750 status = XenPci_SendAndWaitForIrp(device_object, irp);
752 res_list = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
754 for (i = 0; i < res_list->Count; i++)
755 {
756 res_descriptor = &res_list->PartialDescriptors[i];
757 switch (res_descriptor->Type)
758 {
759 case CmResourceTypeInterrupt:
760 KdPrint((__DRIVER_NAME " irq_number = %03x\n", res_descriptor->u.Interrupt.Vector));
761 xpdd->irq_number = res_descriptor->u.Interrupt.Vector;
762 //memcpy(&InterruptRaw, res_descriptor, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
763 break;
764 }
765 }
767 res_list = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
769 for (i = 0; i < res_list->Count; i++)
770 {
771 res_descriptor = &res_list->PartialDescriptors[i];
772 switch (res_descriptor->Type) {
773 case CmResourceTypePort:
774 break;
775 case CmResourceTypeMemory:
776 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));
777 KdPrint((__DRIVER_NAME " Memory flags = %04X\n", res_descriptor->Flags));
778 xpdd->platform_mmio_addr = res_descriptor->u.Memory.Start;
779 xpdd->platform_mmio_len = res_descriptor->u.Memory.Length;
780 xpdd->platform_mmio_alloc = 0;
781 xpdd->platform_mmio_flags = res_descriptor->Flags;
782 break;
783 case CmResourceTypeInterrupt:
784 KdPrint((__DRIVER_NAME " irq_vector = %03x\n", res_descriptor->u.Interrupt.Vector));
785 KdPrint((__DRIVER_NAME " irq_level = %03x\n", res_descriptor->u.Interrupt.Level));
786 xpdd->irq_level = (KIRQL)res_descriptor->u.Interrupt.Level;
787 xpdd->irq_vector = res_descriptor->u.Interrupt.Vector;
788 xpdd->irq_affinity = res_descriptor->u.Interrupt.Affinity;
789 //memcpy(&InterruptTranslated, res_descriptor, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
790 break;
791 case CmResourceTypeDevicePrivate:
792 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] ));
793 break;
794 default:
795 KdPrint((__DRIVER_NAME " Unhandled resource type (0x%x)\n", res_descriptor->Type));
796 break;
797 }
798 }
800 XenPci_QueueWorkItem(device_object, XenPci_Pnp_StartDeviceCallback, irp);
802 FUNCTION_EXIT();
804 return STATUS_PENDING;
805 }
807 static NTSTATUS
808 XenPci_Pnp_StopDevice(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
809 {
810 NTSTATUS status = STATUS_SUCCESS;
812 UNREFERENCED_PARAMETER(device_object);
813 UNREFERENCED_PARAMETER(context);
815 FUNCTION_ENTER();
817 irp->IoStatus.Status = status;
818 IoCompleteRequest(irp, IO_NO_INCREMENT);
820 FUNCTION_EXIT();
822 return irp->IoStatus.Status;
823 }
825 static NTSTATUS
826 XenPci_Pnp_QueryStopRemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
827 {
828 NTSTATUS status;
829 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
831 UNREFERENCED_PARAMETER(device_object);
833 FUNCTION_ENTER();
835 if (xpdd->common.device_usage_paging
836 || xpdd->common.device_usage_dump
837 || xpdd->common.device_usage_hibernation)
838 {
839 /* We are in the paging or hibernation path - can't remove */
840 status = irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
841 IoCompleteRequest(irp, IO_NO_INCREMENT);
842 }
843 else
844 {
845 IoSkipCurrentIrpStackLocation(irp);
846 status = IoCallDriver(xpdd->common.lower_do, irp);
847 }
849 FUNCTION_EXIT();
851 return status;
852 }
854 static NTSTATUS
855 XenPci_Pnp_RemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
856 {
857 NTSTATUS status;
858 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
860 UNREFERENCED_PARAMETER(device_object);
862 FUNCTION_ENTER();
864 irp->IoStatus.Status = STATUS_SUCCESS;
865 IoSkipCurrentIrpStackLocation(irp);
866 status = IoCallDriver(xpdd->common.lower_do, irp);
867 IoDetachDevice(xpdd->common.lower_do);
869 FUNCTION_EXIT();
871 return status;
872 }
874 static DDKAPI VOID
875 XenPci_Pnp_QueryBusRelationsCallback(PDEVICE_OBJECT device_object, PVOID context)
876 {
877 NTSTATUS status = STATUS_SUCCESS;
878 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
879 PXENPCI_PDO_DEVICE_DATA xppdd;
880 PIRP irp = context;
881 int device_count = 0;
882 PDEVICE_RELATIONS dev_relations;
883 PXEN_CHILD child, old_child;
884 //char *response;
885 char *msg;
886 char **devices;
887 char **instances;
888 int i, j;
889 CHAR path[128];
890 PDEVICE_OBJECT pdo;
892 FUNCTION_ENTER();
894 msg = XenBus_List(xpdd, XBT_NIL, "device", &devices);
895 if (!msg)
896 {
897 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
898 {
899 if (child->state == CHILD_STATE_DELETED)
900 KdPrint((__DRIVER_NAME " Found deleted child - this shouldn't happen\n" ));
901 child->state = CHILD_STATE_DELETED;
902 }
904 for (i = 0; devices[i]; i++)
905 {
906 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s", devices[i]);
907 msg = XenBus_List(xpdd, XBT_NIL, path, &instances);
908 if (!msg)
909 {
910 for (j = 0; instances[j]; j++)
911 {
912 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s/%s", devices[i], instances[j]);
914 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
915 {
916 if (strcmp(child->context->path, path) == 0)
917 {
918 KdPrint((__DRIVER_NAME " Existing device %s\n", path));
919 ASSERT(child->state == CHILD_STATE_DELETED);
920 child->state = CHILD_STATE_ADDED;
921 device_count++;
922 break;
923 }
924 }
926 if (child == (PXEN_CHILD)&xpdd->child_list)
927 {
928 KdPrint((__DRIVER_NAME " New device %s\n", path));
929 child = ExAllocatePoolWithTag(NonPagedPool, sizeof(XEN_CHILD), XENPCI_POOL_TAG);
930 child->state = CHILD_STATE_ADDED;
931 status = IoCreateDevice(
932 xpdd->common.fdo->DriverObject,
933 sizeof(XENPCI_PDO_DEVICE_DATA),
934 NULL,
935 FILE_DEVICE_UNKNOWN,
936 FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN,
937 FALSE,
938 &pdo);
939 if (!NT_SUCCESS(status))
940 KdPrint((__DRIVER_NAME " IoCreateDevice status = %08X\n", status));
941 RtlZeroMemory(pdo->DeviceExtension, sizeof(XENPCI_PDO_DEVICE_DATA));
942 child->context = xppdd = pdo->DeviceExtension;
943 xppdd->common.fdo = NULL;
944 xppdd->common.pdo = pdo;
945 ObReferenceObject(pdo);
946 xppdd->common.lower_do = NULL;
947 INIT_PNP_STATE(&xppdd->common);
948 xppdd->common.device_usage_paging = 0;
949 xppdd->common.device_usage_dump = 0;
950 xppdd->common.device_usage_hibernation = 0;
951 xppdd->bus_fdo = xpdd->common.fdo;
952 xppdd->bus_pdo = xpdd->common.pdo;
953 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), path);
954 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), devices[i]);
955 xppdd->index = atoi(instances[j]);
956 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
957 xppdd->backend_state = XenbusStateUnknown;
958 xppdd->backend_path[0] = '\0';
959 InsertTailList(&xpdd->child_list, (PLIST_ENTRY)child);
960 device_count++;
961 }
962 XenPci_FreeMem(instances[j]);
963 }
964 XenPci_FreeMem(instances);
965 }
966 XenPci_FreeMem(devices[i]);
967 }
968 XenPci_FreeMem(devices);
969 dev_relations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (device_count - 1), XENPCI_POOL_TAG);
970 for (child = (PXEN_CHILD)xpdd->child_list.Flink, device_count = 0; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
971 {
972 if (child->state == CHILD_STATE_ADDED)
973 {
974 ObReferenceObject(child->context->common.pdo);
975 dev_relations->Objects[device_count++] = child->context->common.pdo;
976 }
977 }
978 dev_relations->Count = device_count;
980 child = (PXEN_CHILD)xpdd->child_list.Flink;
981 while (child != (PXEN_CHILD)&xpdd->child_list)
982 {
983 if (child->state == CHILD_STATE_DELETED)
984 {
985 KdPrint((__DRIVER_NAME " Removing deleted child from device list\n" ));
986 old_child = child;
987 child = (PXEN_CHILD)child->entry.Flink;
988 RemoveEntryList((PLIST_ENTRY)old_child);
989 xppdd = old_child->context;
990 xppdd->reported_missing = TRUE;
991 ObDereferenceObject(xppdd->common.pdo);
992 ExFreePoolWithTag(old_child, XENPCI_POOL_TAG);
993 }
994 else
995 child = (PXEN_CHILD)child->entry.Flink;
996 }
998 status = STATUS_SUCCESS;
999 }
1000 else
1002 /* 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 */
1003 device_count = 0;
1004 dev_relations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (device_count - 1), XENPCI_POOL_TAG);
1005 dev_relations->Count = device_count;
1008 irp->IoStatus.Status = status;
1009 irp->IoStatus.Information = (ULONG_PTR)dev_relations;
1011 IoCompleteRequest (irp, IO_NO_INCREMENT);
1013 FUNCTION_EXIT();
1016 static NTSTATUS
1017 XenPci_Pnp_QueryBusRelations(PDEVICE_OBJECT device_object, PIRP irp)
1019 NTSTATUS status;
1021 UNREFERENCED_PARAMETER(device_object);
1023 FUNCTION_ENTER();
1025 IoMarkIrpPending(irp);
1027 status = XenPci_SendAndWaitForIrp(device_object, irp);
1029 XenPci_QueueWorkItem(device_object, XenPci_Pnp_QueryBusRelationsCallback, irp);
1031 FUNCTION_EXIT();
1033 return STATUS_PENDING;
1036 static DDKAPI VOID
1037 XenPci_Pnp_FilterResourceRequirementsCallback(PDEVICE_OBJECT device_object, PVOID context)
1039 NTSTATUS status = STATUS_SUCCESS;
1040 //PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1041 PIRP irp = context;
1042 PIO_RESOURCE_REQUIREMENTS_LIST irrl;
1043 ULONG irl;
1044 ULONG ird;
1046 UNREFERENCED_PARAMETER(device_object);
1048 FUNCTION_ENTER();
1049 FUNCTION_MSG(("IoStatus.status = %08X\n", irp->IoStatus.Status));
1051 irrl = (PIO_RESOURCE_REQUIREMENTS_LIST)irp->IoStatus.Information;
1052 for (irl = 0; irl < irrl->AlternativeLists; irl++)
1054 for (ird = 0; ird < irrl->List[irl].Count; ird++)
1056 if (irrl->List[irl].Descriptors[ird].Type == CmResourceTypeMemory)
1058 irrl->List[irl].Descriptors[ird].ShareDisposition = CmResourceShareShared;
1062 irp->IoStatus.Status = status;
1063 IoCompleteRequest (irp, IO_NO_INCREMENT);
1065 FUNCTION_EXIT();
1068 static NTSTATUS
1069 XenPci_Pnp_FilterResourceRequirements(PDEVICE_OBJECT device_object, PIRP irp)
1071 NTSTATUS status;
1073 UNREFERENCED_PARAMETER(device_object);
1075 FUNCTION_ENTER();
1077 IoMarkIrpPending(irp);
1079 status = XenPci_SendAndWaitForIrp(device_object, irp);
1081 XenPci_QueueWorkItem(device_object, XenPci_Pnp_FilterResourceRequirementsCallback, irp);
1083 FUNCTION_EXIT();
1085 return STATUS_PENDING;
1088 static NTSTATUS
1089 XenPci_Pnp_DeviceUsageNotification(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
1091 NTSTATUS status;
1092 PXENPCI_DEVICE_DATA xpdd;
1093 PIO_STACK_LOCATION stack;
1095 UNREFERENCED_PARAMETER(context);
1097 FUNCTION_ENTER();
1099 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1100 stack = IoGetCurrentIrpStackLocation(irp);
1101 status = irp->IoStatus.Status;
1103 /* fail if we are in a stop or remove pending state */
1104 if (!NT_SUCCESS(irp->IoStatus.Status))
1106 switch (stack->Parameters.UsageNotification.Type)
1108 case DeviceUsageTypePaging:
1109 if (stack->Parameters.UsageNotification.InPath)
1110 xpdd->common.device_usage_paging--;
1111 else
1112 xpdd->common.device_usage_paging++;
1113 break;
1114 case DeviceUsageTypeDumpFile:
1115 if (stack->Parameters.UsageNotification.InPath)
1116 xpdd->common.device_usage_dump--;
1117 else
1118 xpdd->common.device_usage_dump++;
1119 break;
1120 case DeviceUsageTypeHibernation:
1121 if (stack->Parameters.UsageNotification.InPath)
1122 xpdd->common.device_usage_hibernation--;
1123 else
1124 xpdd->common.device_usage_hibernation++;
1125 break;
1126 default:
1127 KdPrint((__DRIVER_NAME " Unknown usage type %x\n",
1128 stack->Parameters.UsageNotification.Type));
1129 break;
1131 if (xpdd->common.device_usage_paging
1132 || xpdd->common.device_usage_dump
1133 || xpdd->common.device_usage_hibernation)
1135 xpdd->common.fdo->Flags &= ~DO_POWER_PAGABLE;
1137 IoInvalidateDeviceState(xpdd->common.pdo);
1139 IoCompleteRequest(irp, IO_NO_INCREMENT);
1141 FUNCTION_EXIT();
1143 return status;
1147 NTSTATUS
1148 XenPci_Pnp_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1150 NTSTATUS status;
1151 PIO_STACK_LOCATION stack;
1152 PXENPCI_DEVICE_DATA xpdd;
1154 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1156 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1158 stack = IoGetCurrentIrpStackLocation(irp);
1160 switch (stack->MinorFunction)
1162 case IRP_MN_START_DEVICE:
1163 KdPrint((__DRIVER_NAME " IRP_MN_START_DEVICE\n"));
1164 return XenPci_Pnp_StartDevice(device_object, irp);
1166 case IRP_MN_QUERY_STOP_DEVICE:
1167 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_STOP_DEVICE\n"));
1168 status = XenPci_Pnp_QueryStopRemoveDevice(device_object, irp);
1169 if (NT_SUCCESS(status))
1170 SET_PNP_STATE(&xpdd->common, RemovePending);
1171 return status;
1173 case IRP_MN_STOP_DEVICE:
1174 KdPrint((__DRIVER_NAME " IRP_MN_STOP_DEVICE\n"));
1175 IoCopyCurrentIrpStackLocationToNext(irp);
1176 IoSetCompletionRoutine(irp, XenPci_Pnp_StopDevice, NULL, TRUE, TRUE, TRUE);
1177 break;
1179 case IRP_MN_CANCEL_STOP_DEVICE:
1180 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_STOP_DEVICE\n"));
1181 IoSkipCurrentIrpStackLocation(irp);
1182 REVERT_PNP_STATE(&xpdd->common);
1183 irp->IoStatus.Status = STATUS_SUCCESS;
1184 break;
1186 case IRP_MN_QUERY_REMOVE_DEVICE:
1187 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_REMOVE_DEVICE\n"));
1188 status = XenPci_Pnp_QueryStopRemoveDevice(device_object, irp);
1189 if (NT_SUCCESS(status))
1190 SET_PNP_STATE(&xpdd->common, RemovePending);
1191 return status;
1193 case IRP_MN_REMOVE_DEVICE:
1194 KdPrint((__DRIVER_NAME " IRP_MN_REMOVE_DEVICE\n"));
1195 return XenPci_Pnp_RemoveDevice(device_object, irp);
1196 break;
1198 case IRP_MN_CANCEL_REMOVE_DEVICE:
1199 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_REMOVE_DEVICE\n"));
1200 IoSkipCurrentIrpStackLocation(irp);
1201 REVERT_PNP_STATE(&xpdd->common);
1202 irp->IoStatus.Status = STATUS_SUCCESS;
1203 break;
1205 case IRP_MN_SURPRISE_REMOVAL:
1206 KdPrint((__DRIVER_NAME " IRP_MN_SURPRISE_REMOVAL\n"));
1207 IoSkipCurrentIrpStackLocation(irp);
1208 irp->IoStatus.Status = STATUS_SUCCESS;
1209 break;
1211 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1212 KdPrint((__DRIVER_NAME " IRP_MN_DEVICE_USAGE_NOTIFICATION\n"));
1213 switch (stack->Parameters.UsageNotification.Type)
1215 case DeviceUsageTypePaging:
1216 KdPrint((__DRIVER_NAME " type = DeviceUsageTypePaging = %d\n", stack->Parameters.UsageNotification.InPath));
1217 if (stack->Parameters.UsageNotification.InPath)
1218 xpdd->common.device_usage_paging++;
1219 else
1220 xpdd->common.device_usage_paging--;
1221 irp->IoStatus.Status = STATUS_SUCCESS;
1222 break;
1223 case DeviceUsageTypeDumpFile:
1224 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeDumpFile = %d\n", stack->Parameters.UsageNotification.InPath));
1225 if (stack->Parameters.UsageNotification.InPath)
1226 xpdd->common.device_usage_dump++;
1227 else
1228 xpdd->common.device_usage_dump--;
1229 irp->IoStatus.Status = STATUS_SUCCESS;
1230 break;
1231 case DeviceUsageTypeHibernation:
1232 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeHibernation = %d\n", stack->Parameters.UsageNotification.InPath));
1233 if (stack->Parameters.UsageNotification.InPath)
1234 xpdd->common.device_usage_hibernation++;
1235 else
1236 xpdd->common.device_usage_hibernation--;
1237 irp->IoStatus.Status = STATUS_SUCCESS;
1238 break;
1239 default:
1240 KdPrint((__DRIVER_NAME " type = unsupported (%d)\n", stack->Parameters.UsageNotification.Type));
1241 irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
1242 IoCompleteRequest(irp, IO_NO_INCREMENT);
1243 return STATUS_NOT_SUPPORTED;
1245 if (!xpdd->common.device_usage_paging
1246 && !xpdd->common.device_usage_dump
1247 && !xpdd->common.device_usage_hibernation)
1249 xpdd->common.fdo->Flags |= DO_POWER_PAGABLE;
1251 IoInvalidateDeviceState(xpdd->common.pdo);
1252 IoCopyCurrentIrpStackLocationToNext(irp);
1253 IoSetCompletionRoutine(irp, XenPci_Pnp_DeviceUsageNotification, NULL, TRUE, TRUE, TRUE);
1254 break;
1256 case IRP_MN_QUERY_DEVICE_RELATIONS:
1257 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_RELATIONS\n"));
1258 switch (stack->Parameters.QueryDeviceRelations.Type)
1260 case BusRelations:
1261 KdPrint((__DRIVER_NAME " BusRelations\n"));
1262 return XenPci_Pnp_QueryBusRelations(device_object, irp);
1263 break;
1264 default:
1265 IoSkipCurrentIrpStackLocation(irp);
1266 break;
1268 break;
1270 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1271 KdPrint((__DRIVER_NAME " IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"));
1272 return XenPci_Pnp_FilterResourceRequirements(device_object, irp);
1274 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1275 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_PNP_DEVICE_STATE\n"));
1276 irp->IoStatus.Status = STATUS_SUCCESS;
1277 if (xpdd->common.device_usage_paging
1278 || xpdd->common.device_usage_dump
1279 || xpdd->common.device_usage_hibernation)
1281 irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
1283 IoSkipCurrentIrpStackLocation(irp);
1284 break;
1286 default:
1287 //KdPrint((__DRIVER_NAME " Unhandled Minor = %d\n", stack->MinorFunction));
1288 IoSkipCurrentIrpStackLocation(irp);
1289 break;
1292 status = IoCallDriver(xpdd->common.lower_do, irp);
1294 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1296 return status;
1299 NTSTATUS
1300 XenPci_Irp_Create_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1302 PXENPCI_DEVICE_DATA xpdd;
1303 NTSTATUS status;
1305 FUNCTION_ENTER();
1307 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1308 status = STATUS_SUCCESS;
1309 irp->IoStatus.Status = status;
1310 IoCompleteRequest(irp, IO_NO_INCREMENT);
1312 FUNCTION_EXIT();
1314 return status;
1317 NTSTATUS
1318 XenPci_Irp_Close_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1320 PXENPCI_DEVICE_DATA xpdd;
1321 NTSTATUS status;
1323 FUNCTION_ENTER();
1325 // wait until pending irp's
1326 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1327 status = STATUS_SUCCESS;
1328 irp->IoStatus.Status = status;
1329 IoCompleteRequest(irp, IO_NO_INCREMENT);
1331 FUNCTION_EXIT();
1333 return status;
1336 NTSTATUS
1337 XenPci_Irp_Read_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1339 PXENPCI_DEVICE_DATA xpdd;
1340 NTSTATUS status;
1341 PIO_STACK_LOCATION stack;
1342 KIRQL old_irql;
1344 FUNCTION_ENTER();
1346 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1347 stack = IoGetCurrentIrpStackLocation(irp);
1348 if (stack->Parameters.Read.Length == 0)
1350 irp->IoStatus.Information = 0;
1351 status = STATUS_SUCCESS;
1352 irp->IoStatus.Status = status;
1353 IoCompleteRequest(irp, IO_NO_INCREMENT);
1355 else
1357 KdPrint((__DRIVER_NAME " stack = %p\n", stack));
1358 KdPrint((__DRIVER_NAME " length = %d, buffer = %p\n", stack->Parameters.Read.Length, irp->AssociatedIrp.SystemBuffer));
1360 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
1361 xpdd->shutdown_irp = irp;
1362 IoSetCancelRoutine(irp, XenBus_ShutdownIoCancel);
1363 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
1364 status = XenPci_ProcessShutdownIrp(xpdd);
1367 FUNCTION_EXIT();
1369 return status;
1373 NTSTATUS
1374 XenPci_Irp_Cleanup_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1376 NTSTATUS status;
1378 UNREFERENCED_PARAMETER(device_object);
1380 FUNCTION_ENTER();
1382 status = STATUS_SUCCESS;
1383 irp->IoStatus.Status = status;
1384 IoCompleteRequest(irp, IO_NO_INCREMENT);
1386 FUNCTION_EXIT();
1388 return status;
1391 #if 0
1392 static VOID
1393 XenPci_BalloonHandler(char *Path, PVOID Data)
1395 WDFDEVICE Device = Data;
1396 char *value;
1397 xenbus_transaction_t xbt;
1398 int retry;
1400 UNREFERENCED_PARAMETER(Path);
1402 KdPrint((__DRIVER_NAME " --> XenBus_BalloonHandler\n"));
1404 XenBus_StartTransaction(Device, &xbt);
1406 XenBus_Read(Device, XBT_NIL, BALLOON_PATH, &value);
1408 KdPrint((__DRIVER_NAME " Balloon Value = %s\n", value));
1410 // use the memory_op(unsigned int op, void *arg) hypercall to adjust this
1411 // use XENMEM_increase_reservation and XENMEM_decrease_reservation
1413 XenBus_EndTransaction(Device, xbt, 0, &retry);
1415 XenPci_FreeMem(value);
1417 KdPrint((__DRIVER_NAME " <-- XenBus_BalloonHandler\n"));
1419 #endif