win-pvdrivers

view xenpci/xenpci_fdo.c @ 387:48df739c66d4

Removed some debugging calls to the HLT instruction
author James Harper <james.harper@bendigoit.com.au>
date Fri Jul 11 14:05:34 2008 +1000 (2008-07-11)
parents e556065b2f1a
children 81b5f730455b
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 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
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 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
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 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
103 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
104 stack = IoGetCurrentIrpStackLocation(irp);
105 IoSkipCurrentIrpStackLocation(irp);
106 status = IoCallDriver(xpdd->common.lower_do, irp);
108 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
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 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
140 hvm_get_stubs(xpdd);
142 if (!xpdd->shared_info_area_unmapped.QuadPart)
143 {
144 xpdd->shared_info_area_unmapped = XenPci_AllocMMIO(xpdd, PAGE_SIZE);
145 xpdd->shared_info_area = MmMapIoSpace(xpdd->shared_info_area_unmapped,
146 PAGE_SIZE, MmNonCached);
147 }
148 KdPrint((__DRIVER_NAME " shared_info_area_unmapped.QuadPart = %lx\n", xpdd->shared_info_area_unmapped.QuadPart));
149 xatp.domid = DOMID_SELF;
150 xatp.idx = 0;
151 xatp.space = XENMAPSPACE_shared_info;
152 xatp.gpfn = (xen_pfn_t)(xpdd->shared_info_area_unmapped.QuadPart >> PAGE_SHIFT);
153 KdPrint((__DRIVER_NAME " gpfn = %d\n", xatp.gpfn));
154 ret = HYPERVISOR_memory_op(xpdd, XENMEM_add_to_physmap, &xatp);
155 KdPrint((__DRIVER_NAME " hypervisor memory op ret = %d\n", ret));
157 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
159 return STATUS_SUCCESS;
160 }
162 static NTSTATUS
163 XenPci_Pnp_IoCompletion(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
164 {
165 PKEVENT event = (PKEVENT)context;
167 UNREFERENCED_PARAMETER(device_object);
169 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
171 if (irp->PendingReturned)
172 {
173 KeSetEvent(event, IO_NO_INCREMENT, FALSE);
174 }
176 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
178 return STATUS_MORE_PROCESSING_REQUIRED;
179 }
181 static NTSTATUS
182 XenPci_QueueWorkItem(PDEVICE_OBJECT device_object, PIO_WORKITEM_ROUTINE routine, PVOID context)
183 {
184 PIO_WORKITEM work_item;
185 NTSTATUS status = STATUS_SUCCESS;
187 work_item = IoAllocateWorkItem(device_object);
188 IoQueueWorkItem(work_item, routine, DelayedWorkQueue, context);
190 return status;
191 }
193 static NTSTATUS
194 XenPci_SendAndWaitForIrp(PDEVICE_OBJECT device_object, PIRP irp)
195 {
196 NTSTATUS status;
197 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
198 KEVENT event;
200 UNREFERENCED_PARAMETER(device_object);
202 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
204 KeInitializeEvent(&event, NotificationEvent, FALSE);
206 IoCopyCurrentIrpStackLocationToNext(irp);
207 IoSetCompletionRoutine(irp, XenPci_Pnp_IoCompletion, &event, TRUE, TRUE, TRUE);
209 status = IoCallDriver(xpdd->common.lower_do, irp);
211 if (status == STATUS_PENDING)
212 {
213 KdPrint((__DRIVER_NAME " waiting ...\n"));
214 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
215 KdPrint((__DRIVER_NAME " ... done\n"));
216 status = irp->IoStatus.Status;
217 }
219 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
221 return status;
222 }
224 static NTSTATUS
225 XenPci_ProcessShutdownIrp(PXENPCI_DEVICE_DATA xpdd)
226 {
227 PIO_STACK_LOCATION stack;
228 NTSTATUS status;
229 PIRP irp;
230 KIRQL old_irql;
231 ULONG length;
233 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
235 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
236 if (xpdd->shutdown_irp)
237 {
238 irp = xpdd->shutdown_irp;
239 stack = IoGetCurrentIrpStackLocation(irp);
240 KdPrint((__DRIVER_NAME " stack = %p\n", stack));
241 KdPrint((__DRIVER_NAME " length = %d, buffer = %p\n", stack->Parameters.Read.Length, irp->AssociatedIrp.SystemBuffer));
242 length = min(xpdd->shutdown_prod - xpdd->shutdown_cons, stack->Parameters.Read.Length);
243 KdPrint((__DRIVER_NAME " length = %d\n", length));
244 if (length > 0)
245 {
246 memcpy(irp->AssociatedIrp.SystemBuffer, &xpdd->shutdown_ring[xpdd->shutdown_cons & (SHUTDOWN_RING_SIZE - 1)], length);
247 xpdd->shutdown_cons += length;
248 if (xpdd->shutdown_cons > SHUTDOWN_RING_SIZE)
249 {
250 xpdd->shutdown_cons -= SHUTDOWN_RING_SIZE;
251 xpdd->shutdown_prod -= SHUTDOWN_RING_SIZE;
252 xpdd->shutdown_start -= SHUTDOWN_RING_SIZE;
253 }
254 xpdd->shutdown_irp = NULL;
255 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
256 status = STATUS_SUCCESS;
257 irp->IoStatus.Status = status;
258 irp->IoStatus.Information = length;
259 IoSetCancelRoutine(irp, NULL);
260 IoCompleteRequest(irp, IO_NO_INCREMENT);
261 }
262 else
263 {
264 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
265 KdPrint((__DRIVER_NAME " nothing to read... pending\n"));
266 IoMarkIrpPending(irp);
267 status = STATUS_PENDING;
268 }
269 }
270 else
271 {
272 KdPrint((__DRIVER_NAME " no pending irp\n"));
273 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
274 status = STATUS_SUCCESS;
275 }
277 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
279 return status;
280 }
282 static VOID
283 XenBus_ShutdownIoCancel(PDEVICE_OBJECT device_object, PIRP irp)
284 {
285 PXENPCI_DEVICE_DATA xpdd;
286 KIRQL old_irql;
288 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
290 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
291 IoReleaseCancelSpinLock(irp->CancelIrql);
292 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
293 if (irp == xpdd->shutdown_irp)
294 {
295 KdPrint((__DRIVER_NAME " Not the current irp???\n"));
296 xpdd->shutdown_irp = NULL;
297 }
298 irp->IoStatus.Status = STATUS_CANCELLED;
299 irp->IoStatus.Information = 0;
300 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
301 IoCompleteRequest(irp, IO_NO_INCREMENT);
303 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
304 }
306 struct {
307 volatile ULONG do_spin;
308 volatile LONG nr_spinning;
309 KEVENT stopped_spinning_event;
310 } typedef SUSPEND_INFO, *PSUSPEND_INFO;
312 static DDKAPI VOID
313 XenPci_CompleteResume(PDEVICE_OBJECT device_object, PVOID context)
314 {
315 PSUSPEND_INFO suspend_info = context;
316 PXENPCI_DEVICE_DATA xpdd;
317 PXEN_CHILD child;
319 UNREFERENCED_PARAMETER(context);
320 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
322 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
324 while (suspend_info->nr_spinning != 0)
325 {
326 KdPrint((__DRIVER_NAME " %d processors are still spinning\n", suspend_info->nr_spinning));
327 KeWaitForSingleObject(&suspend_info->stopped_spinning_event, Executive, KernelMode, FALSE, NULL);
328 }
329 KdPrint((__DRIVER_NAME " all other processors have stopped spinning\n"));
331 XenBus_Resume(xpdd);
333 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
334 {
335 XenPci_Resume(child->context->common.pdo);
336 child->context->device_state.resume_state = RESUME_STATE_FRONTEND_RESUME;
337 // how can we signal children that they are ready to restart again?
338 // maybe we can fake an interrupt?
339 }
341 xpdd->suspend_state = SUSPEND_STATE_NONE;
343 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
344 }
346 /* Called at DISPATCH_LEVEL */
347 static DDKAPI VOID
348 XenPci_Suspend(
349 PRKDPC Dpc,
350 PVOID Context,
351 PVOID SystemArgument1,
352 PVOID SystemArgument2)
353 {
354 PXENPCI_DEVICE_DATA xpdd = Context;
355 PSUSPEND_INFO suspend_info = SystemArgument1;
356 ULONG ActiveProcessorCount;
357 KIRQL old_irql;
358 int cancelled;
359 PIO_WORKITEM work_item;
360 PXEN_CHILD child;
361 //PUCHAR gnttbl_backup[PAGE_SIZE * NR_GRANT_FRAMES];
363 UNREFERENCED_PARAMETER(Dpc);
364 UNREFERENCED_PARAMETER(SystemArgument2);
366 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (CPU = %d)\n", KeGetCurrentProcessorNumber()));
368 if (KeGetCurrentProcessorNumber() != 0)
369 {
370 KeRaiseIrql(HIGH_LEVEL, &old_irql);
371 KdPrint((__DRIVER_NAME " spinning...\n"));
372 InterlockedIncrement(&suspend_info->nr_spinning);
373 KeMemoryBarrier();
374 while(suspend_info->do_spin)
375 {
376 KeStallExecutionProcessor(1);
377 KeMemoryBarrier();
378 /* can't call HYPERVISOR_yield() here as the stubs will be reset and we will crash */
379 }
380 KeMemoryBarrier();
381 InterlockedDecrement(&suspend_info->nr_spinning);
382 KdPrint((__DRIVER_NAME " ...done spinning\n"));
383 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (cpu = %d)\n", KeGetCurrentProcessorNumber()));
384 KeLowerIrql(old_irql);
385 KeSetEvent(&suspend_info->stopped_spinning_event, IO_NO_INCREMENT, FALSE);
386 return;
387 }
388 ActiveProcessorCount = (ULONG)KeNumberProcessors;
390 KeRaiseIrql(HIGH_LEVEL, &old_irql);
392 KdPrint((__DRIVER_NAME " waiting for all other processors to spin\n"));
393 while (suspend_info->nr_spinning < (LONG)ActiveProcessorCount - 1)
394 {
395 HYPERVISOR_yield(xpdd);
396 KeMemoryBarrier();
397 }
398 KdPrint((__DRIVER_NAME " all other processors are spinning\n"));
400 xpdd->suspend_state = SUSPEND_STATE_HIGH_IRQL;
402 KdPrint((__DRIVER_NAME " calling suspend\n"));
403 cancelled = hvm_shutdown(Context, SHUTDOWN_suspend);
404 KdPrint((__DRIVER_NAME " back from suspend, cancelled = %d\n", cancelled));
406 XenPci_Init(xpdd);
408 GntTbl_InitMap(Context);
410 /* this enables interrupts again too */
411 EvtChn_Init(xpdd);
413 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
414 {
415 child->context->device_state.resume_state = RESUME_STATE_BACKEND_RESUME;
416 }
418 xpdd->suspend_state = SUSPEND_STATE_RESUMING;
419 KeLowerIrql(old_irql);
421 KdPrint((__DRIVER_NAME " waiting for all other processors to stop spinning\n"));
422 suspend_info->do_spin = 0;
423 KeMemoryBarrier();
425 work_item = IoAllocateWorkItem(xpdd->common.fdo);
426 IoQueueWorkItem(work_item, XenPci_CompleteResume, DelayedWorkQueue, suspend_info);
428 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
429 }
431 /* Called at PASSIVE_LEVEL */
432 static VOID
433 XenPci_BeginSuspend(PXENPCI_DEVICE_DATA xpdd)
434 {
435 //KAFFINITY ActiveProcessorMask = 0; // this is for Vista+
436 ULONG ActiveProcessorCount;
437 ULONG i;
438 PSUSPEND_INFO suspend_info;
439 PKDPC Dpc;
440 KIRQL OldIrql;
442 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
444 if (xpdd->suspend_state == SUSPEND_STATE_NONE)
445 {
446 xpdd->suspend_state = SUSPEND_STATE_SCHEDULED;
447 suspend_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(SUSPEND_INFO), XENPCI_POOL_TAG);
448 RtlZeroMemory(suspend_info, sizeof(SUSPEND_INFO));
449 KeInitializeEvent(&suspend_info->stopped_spinning_event, SynchronizationEvent, FALSE);
450 suspend_info->do_spin = 1;
452 // I think we need to synchronise with the interrupt here...
454 for (i = 0; i < MAX_VIRT_CPUS; i++)
455 {
456 xpdd->shared_info_area->vcpu_info[i].evtchn_upcall_mask = 1;
457 }
458 KeMemoryBarrier();
459 EvtChn_Shutdown(xpdd);
461 //ActiveProcessorCount = KeQueryActiveProcessorCount(&ActiveProcessorMask); // this is for Vista+
462 ActiveProcessorCount = (ULONG)KeNumberProcessors;
463 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
464 for (i = 0; i < ActiveProcessorCount; i++)
465 {
466 Dpc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KDPC), XENPCI_POOL_TAG);
467 KeInitializeDpc(Dpc, XenPci_Suspend, xpdd);
468 KeSetTargetProcessorDpc(Dpc, (CCHAR)i);
469 KeInsertQueueDpc(Dpc, suspend_info, NULL);
470 }
471 KeLowerIrql(OldIrql);
472 }
473 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
474 }
476 static void
477 XenPci_ShutdownHandler(char *path, PVOID context)
478 {
479 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)context;
480 char *res;
481 char *value;
482 KIRQL old_irql;
484 UNREFERENCED_PARAMETER(path);
486 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
488 res = XenBus_Read(xpdd, XBT_NIL, SHUTDOWN_PATH, &value);
489 if (res)
490 {
491 KdPrint(("Error reading shutdown path - %s\n", res));
492 XenPci_FreeMem(res);
493 return;
494 }
496 KdPrint((__DRIVER_NAME " Shutdown value = %s\n", value));
498 if (strlen(value) != 0)
499 {
500 if (strcmp(value, "suspend") == 0)
501 {
502 KdPrint((__DRIVER_NAME " Suspend detected\n"));
503 XenPci_BeginSuspend(xpdd);
504 }
505 else
506 {
507 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
508 if (xpdd->shutdown_start >= xpdd->shutdown_cons)
509 xpdd->shutdown_prod = xpdd->shutdown_start;
510 else
511 xpdd->shutdown_start = xpdd->shutdown_prod;
512 memcpy(&xpdd->shutdown_ring[xpdd->shutdown_prod], value, strlen(value));
513 xpdd->shutdown_prod += (ULONG)strlen(value);
514 xpdd->shutdown_ring[xpdd->shutdown_prod++] = '\r';
515 xpdd->shutdown_ring[xpdd->shutdown_prod++] = '\n';
516 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
517 XenPci_ProcessShutdownIrp(xpdd);
518 }
519 }
521 //XenPci_FreeMem(value);
523 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
524 }
526 static VOID
527 XenPci_SysrqHandler(char *path, PVOID context)
528 {
529 PXENPCI_DEVICE_DATA xpdd = context;
530 char *value;
531 char letter;
532 char *res;
534 UNREFERENCED_PARAMETER(path);
536 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
538 XenBus_Read(xpdd, XBT_NIL, SYSRQ_PATH, &value);
540 KdPrint((__DRIVER_NAME " SysRq Value = %s\n", value));
542 if (value != NULL && strlen(value) != 0)
543 {
544 letter = *value;
545 res = XenBus_Write(xpdd, XBT_NIL, SYSRQ_PATH, "");
546 if (res)
547 {
548 KdPrint(("Error writing sysrq path\n"));
549 XenPci_FreeMem(res);
550 return;
551 }
552 }
553 else
554 {
555 letter = 0;
556 }
558 if (value != NULL)
559 {
560 XenPci_FreeMem(value);
561 }
563 switch (letter)
564 {
565 case 'B':
566 KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000001, 0x00000000, 0x00000000, 0x00000000);
567 break;
568 default:
569 KdPrint((" Unhandled sysrq letter %c\n", letter));
570 break;
571 }
573 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
574 }
576 static VOID
577 XenPci_DeviceWatchHandler(char *path, PVOID context)
578 {
579 char **bits;
580 int count;
581 char *err;
582 char *value;
583 PXENPCI_DEVICE_DATA xpdd = context;
585 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
587 // KdPrint((__DRIVER_NAME " path = %s\n", path));
588 bits = SplitString(path, '/', 4, &count);
589 // KdPrint((__DRIVER_NAME " count = %d\n", count));
591 if (count == 3)
592 {
593 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
594 if (err)
595 {
596 /* obviously path no longer exists, in which case the removal is being taken care of elsewhere and we shouldn't invalidate now */
597 XenPci_FreeMem(err);
598 }
599 else
600 {
601 XenPci_FreeMem(value);
602 /* we probably have to be a bit smarter here and do nothing if xenpci isn't running yet */
603 KdPrint((__DRIVER_NAME " Invalidating Device Relations\n"));
604 IoInvalidateDeviceRelations(xpdd->common.pdo, BusRelations);
605 }
606 }
607 FreeSplitString(bits, count);
609 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
610 }
612 static DDKAPI VOID
613 XenPci_Pnp_StartDeviceCallback(PDEVICE_OBJECT device_object, PVOID context)
614 {
615 NTSTATUS status = STATUS_SUCCESS;
616 PXENPCI_DEVICE_DATA xpdd = device_object->DeviceExtension;
617 PIRP irp = context;
618 char *response;
620 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
622 XenPci_Init(xpdd);
624 GntTbl_Init(xpdd);
626 EvtChn_Init(xpdd);
628 XenBus_Init(xpdd);
630 response = XenBus_AddWatch(xpdd, XBT_NIL, SYSRQ_PATH, XenPci_SysrqHandler, xpdd);
631 KdPrint((__DRIVER_NAME " sysrqwatch response = '%s'\n", response));
633 response = XenBus_AddWatch(xpdd, XBT_NIL, SHUTDOWN_PATH, XenPci_ShutdownHandler, xpdd);
634 KdPrint((__DRIVER_NAME " shutdown watch response = '%s'\n", response));
636 response = XenBus_AddWatch(xpdd, XBT_NIL, "device", XenPci_DeviceWatchHandler, xpdd);
637 KdPrint((__DRIVER_NAME " device watch response = '%s'\n", response));
639 #if 0
640 response = XenBus_AddWatch(xpdd, XBT_NIL, BALLOON_PATH, XenPci_BalloonHandler, Device);
641 KdPrint((__DRIVER_NAME " balloon watch response = '%s'\n", response));
642 #endif
644 status = IoSetDeviceInterfaceState(&xpdd->interface_name, TRUE);
645 if (!NT_SUCCESS(status))
646 {
647 KdPrint((__DRIVER_NAME " IoSetDeviceInterfaceState failed with status 0x%08x\n", status));
648 }
650 irp->IoStatus.Status = status;
652 IoCompleteRequest(irp, IO_NO_INCREMENT);
654 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
655 }
657 static NTSTATUS
658 XenPci_Pnp_StartDevice(PDEVICE_OBJECT device_object, PIRP irp)
659 {
660 NTSTATUS status;
661 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
662 PIO_STACK_LOCATION stack;
663 PCM_PARTIAL_RESOURCE_LIST res_list;
664 PCM_PARTIAL_RESOURCE_DESCRIPTOR res_descriptor;
665 ULONG i;
667 UNREFERENCED_PARAMETER(device_object);
669 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
671 stack = IoGetCurrentIrpStackLocation(irp);
673 IoMarkIrpPending(irp);
675 status = XenPci_SendAndWaitForIrp(device_object, irp);
677 res_list = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
679 for (i = 0; i < res_list->Count; i++)
680 {
681 res_descriptor = &res_list->PartialDescriptors[i];
682 switch (res_descriptor->Type)
683 {
684 case CmResourceTypeInterrupt:
685 KdPrint((__DRIVER_NAME " irq_number = %03x\n", res_descriptor->u.Interrupt.Vector));
686 xpdd->irq_number = res_descriptor->u.Interrupt.Vector;
687 //memcpy(&InterruptRaw, res_descriptor, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
688 break;
689 }
690 }
692 res_list = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
694 for (i = 0; i < res_list->Count; i++)
695 {
696 res_descriptor = &res_list->PartialDescriptors[i];
697 switch (res_descriptor->Type) {
698 case CmResourceTypePort:
699 break;
700 case CmResourceTypeMemory:
701 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));
702 KdPrint((__DRIVER_NAME " Memory flags = %04X\n", res_descriptor->Flags));
703 xpdd->platform_mmio_addr = res_descriptor->u.Memory.Start;
704 xpdd->platform_mmio_len = res_descriptor->u.Memory.Length;
705 xpdd->platform_mmio_alloc = 0;
706 xpdd->platform_mmio_flags = res_descriptor->Flags;
707 break;
708 case CmResourceTypeInterrupt:
709 KdPrint((__DRIVER_NAME " irq_vector = %03x\n", res_descriptor->u.Interrupt.Vector));
710 KdPrint((__DRIVER_NAME " irq_level = %03x\n", res_descriptor->u.Interrupt.Level));
711 xpdd->irq_level = (KIRQL)res_descriptor->u.Interrupt.Level;
712 xpdd->irq_vector = res_descriptor->u.Interrupt.Vector;
713 xpdd->irq_affinity = res_descriptor->u.Interrupt.Affinity;
714 //memcpy(&InterruptTranslated, res_descriptor, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
715 break;
716 case CmResourceTypeDevicePrivate:
717 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] ));
718 break;
719 default:
720 KdPrint((__DRIVER_NAME " Unhandled resource type (0x%x)\n", res_descriptor->Type));
721 break;
722 }
723 }
725 XenPci_QueueWorkItem(device_object, XenPci_Pnp_StartDeviceCallback, irp);
727 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
729 return STATUS_PENDING;
730 }
732 static NTSTATUS
733 XenPci_Pnp_StopDevice(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
734 {
735 NTSTATUS status = STATUS_SUCCESS;
737 UNREFERENCED_PARAMETER(device_object);
738 UNREFERENCED_PARAMETER(context);
740 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
742 irp->IoStatus.Status = status;
743 IoCompleteRequest(irp, IO_NO_INCREMENT);
745 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
747 return irp->IoStatus.Status;
748 }
750 static NTSTATUS
751 XenPci_Pnp_QueryStopRemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
752 {
753 NTSTATUS status;
754 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
756 UNREFERENCED_PARAMETER(device_object);
758 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
760 if (xpdd->common.device_usage_paging
761 || xpdd->common.device_usage_dump
762 || xpdd->common.device_usage_hibernation)
763 {
764 /* We are in the paging or hibernation path - can't remove */
765 status = irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
766 IoCompleteRequest(irp, IO_NO_INCREMENT);
767 }
768 else
769 {
770 IoSkipCurrentIrpStackLocation(irp);
771 status = IoCallDriver(xpdd->common.lower_do, irp);
772 }
774 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
776 return status;
777 }
779 static NTSTATUS
780 XenPci_Pnp_RemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
781 {
782 NTSTATUS status;
783 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
785 UNREFERENCED_PARAMETER(device_object);
787 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
789 irp->IoStatus.Status = STATUS_SUCCESS;
790 IoSkipCurrentIrpStackLocation(irp);
791 status = IoCallDriver(xpdd->common.lower_do, irp);
792 IoDetachDevice(xpdd->common.lower_do);
794 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
796 return status;
797 }
799 static DDKAPI VOID
800 XenPci_Pnp_QueryBusRelationsCallback(PDEVICE_OBJECT device_object, PVOID context)
801 {
802 NTSTATUS status = STATUS_SUCCESS;
803 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
804 PXENPCI_PDO_DEVICE_DATA xppdd;
805 PIRP irp = context;
806 int device_count = 0;
807 PDEVICE_RELATIONS dev_relations;
808 PXEN_CHILD child, old_child;
809 //char *response;
810 char *msg;
811 char **devices;
812 char **instances;
813 int i, j;
814 CHAR path[128];
815 PDEVICE_OBJECT pdo;
817 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
819 msg = XenBus_List(xpdd, XBT_NIL, "device", &devices);
820 if (!msg)
821 {
822 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
823 {
824 if (child->state == CHILD_STATE_DELETED)
825 KdPrint((__DRIVER_NAME " Found deleted child - this shouldn't happen\n" ));
826 child->state = CHILD_STATE_DELETED;
827 }
829 for (i = 0; devices[i]; i++)
830 {
831 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s", devices[i]);
832 msg = XenBus_List(xpdd, XBT_NIL, path, &instances);
833 if (!msg)
834 {
835 for (j = 0; instances[j]; j++)
836 {
837 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s/%s", devices[i], instances[j]);
839 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
840 {
841 if (strcmp(child->context->path, path) == 0)
842 {
843 KdPrint((__DRIVER_NAME " Existing device %s\n", path));
844 ASSERT(child->state == CHILD_STATE_DELETED);
845 child->state = CHILD_STATE_ADDED;
846 device_count++;
847 break;
848 }
849 }
851 if (child == (PXEN_CHILD)&xpdd->child_list)
852 {
853 KdPrint((__DRIVER_NAME " New device %s\n", path));
854 child = ExAllocatePoolWithTag(NonPagedPool, sizeof(XEN_CHILD), XENPCI_POOL_TAG);
855 child->state = CHILD_STATE_ADDED;
856 status = IoCreateDevice(
857 xpdd->common.fdo->DriverObject,
858 sizeof(XENPCI_PDO_DEVICE_DATA),
859 NULL,
860 FILE_DEVICE_UNKNOWN,
861 FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN,
862 FALSE,
863 &pdo);
864 if (!NT_SUCCESS(status))
865 KdPrint((__DRIVER_NAME " IoCreateDevice status = %08X\n", status));
866 RtlZeroMemory(pdo->DeviceExtension, sizeof(XENPCI_PDO_DEVICE_DATA));
867 child->context = xppdd = pdo->DeviceExtension;
868 xppdd->common.fdo = NULL;
869 xppdd->common.pdo = pdo;
870 ObReferenceObject(pdo);
871 xppdd->common.lower_do = NULL;
872 INIT_PNP_STATE(&xppdd->common);
873 xppdd->common.device_usage_paging = 0;
874 xppdd->common.device_usage_dump = 0;
875 xppdd->common.device_usage_hibernation = 0;
876 xppdd->bus_fdo = xpdd->common.fdo;
877 xppdd->bus_pdo = xpdd->common.pdo;
878 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), path);
879 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), devices[i]);
880 xppdd->index = atoi(instances[j]);
881 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
882 xppdd->backend_state = XenbusStateUnknown;
883 xppdd->backend_path[0] = '\0';
884 InsertTailList(&xpdd->child_list, (PLIST_ENTRY)child);
885 device_count++;
886 }
887 XenPci_FreeMem(instances[j]);
888 }
889 XenPci_FreeMem(instances);
890 }
891 XenPci_FreeMem(devices[i]);
892 }
893 XenPci_FreeMem(devices);
894 dev_relations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (device_count - 1), XENPCI_POOL_TAG);
895 for (child = (PXEN_CHILD)xpdd->child_list.Flink, device_count = 0; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
896 {
897 if (child->state == CHILD_STATE_ADDED)
898 {
899 ObReferenceObject(child->context->common.pdo);
900 dev_relations->Objects[device_count++] = child->context->common.pdo;
901 }
902 }
903 dev_relations->Count = device_count;
905 child = (PXEN_CHILD)xpdd->child_list.Flink;
906 while (child != (PXEN_CHILD)&xpdd->child_list)
907 {
908 if (child->state == CHILD_STATE_DELETED)
909 {
910 KdPrint((__DRIVER_NAME " Removing deleted child from device list\n" ));
911 old_child = child;
912 child = (PXEN_CHILD)child->entry.Flink;
913 RemoveEntryList((PLIST_ENTRY)old_child);
914 xppdd = old_child->context;
915 xppdd->reported_missing = TRUE;
916 ObDereferenceObject(xppdd->common.pdo);
917 ExFreePoolWithTag(old_child, XENPCI_POOL_TAG);
918 }
919 else
920 child = (PXEN_CHILD)child->entry.Flink;
921 }
923 status = STATUS_SUCCESS;
924 }
925 else
926 {
927 /* 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 */
928 device_count = 0;
929 dev_relations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (device_count - 1), XENPCI_POOL_TAG);
930 dev_relations->Count = device_count;
931 }
933 irp->IoStatus.Status = status;
934 irp->IoStatus.Information = (ULONG_PTR)dev_relations;
936 IoCompleteRequest (irp, IO_NO_INCREMENT);
938 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
939 }
941 static NTSTATUS
942 XenPci_Pnp_QueryBusRelations(PDEVICE_OBJECT device_object, PIRP irp)
943 {
944 NTSTATUS status;
946 UNREFERENCED_PARAMETER(device_object);
948 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
950 IoMarkIrpPending(irp);
952 status = XenPci_SendAndWaitForIrp(device_object, irp);
954 XenPci_QueueWorkItem(device_object, XenPci_Pnp_QueryBusRelationsCallback, irp);
956 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
958 return STATUS_PENDING;
959 }
961 static DDKAPI VOID
962 XenPci_Pnp_FilterResourceRequirementsCallback(PDEVICE_OBJECT device_object, PVOID context)
963 {
964 NTSTATUS status = STATUS_SUCCESS;
965 //PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
966 PIRP irp = context;
967 PIO_RESOURCE_REQUIREMENTS_LIST irrl;
968 ULONG irl;
969 ULONG ird;
971 UNREFERENCED_PARAMETER(device_object);
973 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (status = %08X)\n", irp->IoStatus.Status));
975 irrl = (PIO_RESOURCE_REQUIREMENTS_LIST)irp->IoStatus.Information;
976 for (irl = 0; irl < irrl->AlternativeLists; irl++)
977 {
978 for (ird = 0; ird < irrl->List[irl].Count; ird++)
979 {
980 if (irrl->List[irl].Descriptors[ird].Type == CmResourceTypeMemory)
981 {
982 irrl->List[irl].Descriptors[ird].ShareDisposition = CmResourceShareShared;
983 }
984 }
985 }
986 irp->IoStatus.Status = status;
987 IoCompleteRequest (irp, IO_NO_INCREMENT);
989 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
991 return;
992 }
994 static NTSTATUS
995 XenPci_Pnp_FilterResourceRequirements(PDEVICE_OBJECT device_object, PIRP irp)
996 {
997 NTSTATUS status;
999 UNREFERENCED_PARAMETER(device_object);
1001 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1003 IoMarkIrpPending(irp);
1005 status = XenPci_SendAndWaitForIrp(device_object, irp);
1007 XenPci_QueueWorkItem(device_object, XenPci_Pnp_FilterResourceRequirementsCallback, irp);
1009 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1011 return STATUS_PENDING;
1014 static NTSTATUS
1015 XenPci_Pnp_DeviceUsageNotification(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
1017 NTSTATUS status;
1018 PXENPCI_DEVICE_DATA xpdd;
1019 PIO_STACK_LOCATION stack;
1021 UNREFERENCED_PARAMETER(context);
1023 KdPrint((__DRIVER_NAME " --> " __FUNCTION__"\n"));
1025 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1026 stack = IoGetCurrentIrpStackLocation(irp);
1027 status = irp->IoStatus.Status;
1029 /* fail if we are in a stop or remove pending state */
1030 if (!NT_SUCCESS(irp->IoStatus.Status))
1032 switch (stack->Parameters.UsageNotification.Type)
1034 case DeviceUsageTypePaging:
1035 if (stack->Parameters.UsageNotification.InPath)
1036 xpdd->common.device_usage_paging--;
1037 else
1038 xpdd->common.device_usage_paging++;
1039 break;
1040 case DeviceUsageTypeDumpFile:
1041 if (stack->Parameters.UsageNotification.InPath)
1042 xpdd->common.device_usage_dump--;
1043 else
1044 xpdd->common.device_usage_dump++;
1045 break;
1046 case DeviceUsageTypeHibernation:
1047 if (stack->Parameters.UsageNotification.InPath)
1048 xpdd->common.device_usage_hibernation--;
1049 else
1050 xpdd->common.device_usage_hibernation++;
1051 break;
1052 default:
1053 KdPrint((__DRIVER_NAME " Unknown usage type %x\n",
1054 stack->Parameters.UsageNotification.Type));
1055 break;
1057 if (xpdd->common.device_usage_paging
1058 || xpdd->common.device_usage_dump
1059 || xpdd->common.device_usage_hibernation)
1061 xpdd->common.fdo->Flags &= ~DO_POWER_PAGABLE;
1063 IoInvalidateDeviceState(xpdd->common.pdo);
1065 IoCompleteRequest(irp, IO_NO_INCREMENT);
1067 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1069 return status;
1073 NTSTATUS
1074 XenPci_Pnp_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1076 NTSTATUS status;
1077 PIO_STACK_LOCATION stack;
1078 PXENPCI_DEVICE_DATA xpdd;
1080 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1082 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1084 stack = IoGetCurrentIrpStackLocation(irp);
1086 switch (stack->MinorFunction)
1088 case IRP_MN_START_DEVICE:
1089 KdPrint((__DRIVER_NAME " IRP_MN_START_DEVICE\n"));
1090 return XenPci_Pnp_StartDevice(device_object, irp);
1092 case IRP_MN_QUERY_STOP_DEVICE:
1093 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_STOP_DEVICE\n"));
1094 status = XenPci_Pnp_QueryStopRemoveDevice(device_object, irp);
1095 if (NT_SUCCESS(status))
1096 SET_PNP_STATE(&xpdd->common, RemovePending);
1097 return status;
1099 case IRP_MN_STOP_DEVICE:
1100 KdPrint((__DRIVER_NAME " IRP_MN_STOP_DEVICE\n"));
1101 IoCopyCurrentIrpStackLocationToNext(irp);
1102 IoSetCompletionRoutine(irp, XenPci_Pnp_StopDevice, NULL, TRUE, TRUE, TRUE);
1103 break;
1105 case IRP_MN_CANCEL_STOP_DEVICE:
1106 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_STOP_DEVICE\n"));
1107 IoSkipCurrentIrpStackLocation(irp);
1108 REVERT_PNP_STATE(&xpdd->common);
1109 irp->IoStatus.Status = STATUS_SUCCESS;
1110 break;
1112 case IRP_MN_QUERY_REMOVE_DEVICE:
1113 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_REMOVE_DEVICE\n"));
1114 status = XenPci_Pnp_QueryStopRemoveDevice(device_object, irp);
1115 if (NT_SUCCESS(status))
1116 SET_PNP_STATE(&xpdd->common, RemovePending);
1117 return status;
1119 case IRP_MN_REMOVE_DEVICE:
1120 KdPrint((__DRIVER_NAME " IRP_MN_REMOVE_DEVICE\n"));
1121 return XenPci_Pnp_RemoveDevice(device_object, irp);
1122 break;
1124 case IRP_MN_CANCEL_REMOVE_DEVICE:
1125 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_REMOVE_DEVICE\n"));
1126 IoSkipCurrentIrpStackLocation(irp);
1127 REVERT_PNP_STATE(&xpdd->common);
1128 irp->IoStatus.Status = STATUS_SUCCESS;
1129 break;
1131 case IRP_MN_SURPRISE_REMOVAL:
1132 KdPrint((__DRIVER_NAME " IRP_MN_SURPRISE_REMOVAL\n"));
1133 IoSkipCurrentIrpStackLocation(irp);
1134 irp->IoStatus.Status = STATUS_SUCCESS;
1135 break;
1137 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1138 KdPrint((__DRIVER_NAME " IRP_MN_DEVICE_USAGE_NOTIFICATION\n"));
1139 switch (stack->Parameters.UsageNotification.Type)
1141 case DeviceUsageTypePaging:
1142 KdPrint((__DRIVER_NAME " type = DeviceUsageTypePaging = %d\n", stack->Parameters.UsageNotification.InPath));
1143 if (stack->Parameters.UsageNotification.InPath)
1144 xpdd->common.device_usage_paging++;
1145 else
1146 xpdd->common.device_usage_paging--;
1147 irp->IoStatus.Status = STATUS_SUCCESS;
1148 break;
1149 case DeviceUsageTypeDumpFile:
1150 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeDumpFile = %d\n", stack->Parameters.UsageNotification.InPath));
1151 if (stack->Parameters.UsageNotification.InPath)
1152 xpdd->common.device_usage_dump++;
1153 else
1154 xpdd->common.device_usage_dump--;
1155 irp->IoStatus.Status = STATUS_SUCCESS;
1156 break;
1157 case DeviceUsageTypeHibernation:
1158 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeHibernation = %d\n", stack->Parameters.UsageNotification.InPath));
1159 if (stack->Parameters.UsageNotification.InPath)
1160 xpdd->common.device_usage_hibernation++;
1161 else
1162 xpdd->common.device_usage_hibernation--;
1163 irp->IoStatus.Status = STATUS_SUCCESS;
1164 break;
1165 default:
1166 KdPrint((__DRIVER_NAME " type = unsupported (%d)\n", stack->Parameters.UsageNotification.Type));
1167 irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
1168 IoCompleteRequest(irp, IO_NO_INCREMENT);
1169 return STATUS_NOT_SUPPORTED;
1171 if (!xpdd->common.device_usage_paging
1172 && !xpdd->common.device_usage_dump
1173 && !xpdd->common.device_usage_hibernation)
1175 xpdd->common.fdo->Flags |= DO_POWER_PAGABLE;
1177 IoInvalidateDeviceState(xpdd->common.pdo);
1178 IoCopyCurrentIrpStackLocationToNext(irp);
1179 IoSetCompletionRoutine(irp, XenPci_Pnp_DeviceUsageNotification, NULL, TRUE, TRUE, TRUE);
1180 break;
1182 case IRP_MN_QUERY_DEVICE_RELATIONS:
1183 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_RELATIONS\n"));
1184 switch (stack->Parameters.QueryDeviceRelations.Type)
1186 case BusRelations:
1187 KdPrint((__DRIVER_NAME " BusRelations\n"));
1188 return XenPci_Pnp_QueryBusRelations(device_object, irp);
1189 break;
1190 default:
1191 IoSkipCurrentIrpStackLocation(irp);
1192 break;
1194 break;
1196 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1197 KdPrint((__DRIVER_NAME " IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"));
1198 return XenPci_Pnp_FilterResourceRequirements(device_object, irp);
1200 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1201 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_PNP_DEVICE_STATE\n"));
1202 irp->IoStatus.Status = STATUS_SUCCESS;
1203 if (xpdd->common.device_usage_paging
1204 || xpdd->common.device_usage_dump
1205 || xpdd->common.device_usage_hibernation)
1207 irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
1209 IoSkipCurrentIrpStackLocation(irp);
1210 break;
1212 default:
1213 //KdPrint((__DRIVER_NAME " Unhandled Minor = %d\n", stack->MinorFunction));
1214 IoSkipCurrentIrpStackLocation(irp);
1215 break;
1218 status = IoCallDriver(xpdd->common.lower_do, irp);
1220 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1222 return status;
1225 NTSTATUS
1226 XenPci_Irp_Create_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1228 PXENPCI_DEVICE_DATA xpdd;
1229 NTSTATUS status;
1231 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1233 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1234 status = STATUS_SUCCESS;
1235 irp->IoStatus.Status = status;
1236 IoCompleteRequest(irp, IO_NO_INCREMENT);
1238 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1240 return status;
1243 NTSTATUS
1244 XenPci_Irp_Close_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1246 PXENPCI_DEVICE_DATA xpdd;
1247 NTSTATUS status;
1249 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1251 // wait until pending irp's
1252 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1253 status = STATUS_SUCCESS;
1254 irp->IoStatus.Status = status;
1255 IoCompleteRequest(irp, IO_NO_INCREMENT);
1257 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1259 return status;
1262 NTSTATUS
1263 XenPci_Irp_Read_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1265 PXENPCI_DEVICE_DATA xpdd;
1266 NTSTATUS status;
1267 PIO_STACK_LOCATION stack;
1268 KIRQL old_irql;
1270 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1272 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1273 stack = IoGetCurrentIrpStackLocation(irp);
1274 if (stack->Parameters.Read.Length == 0)
1276 irp->IoStatus.Information = 0;
1277 status = STATUS_SUCCESS;
1278 irp->IoStatus.Status = status;
1279 IoCompleteRequest(irp, IO_NO_INCREMENT);
1281 else
1283 KdPrint((__DRIVER_NAME " stack = %p\n", stack));
1284 KdPrint((__DRIVER_NAME " length = %d, buffer = %p\n", stack->Parameters.Read.Length, irp->AssociatedIrp.SystemBuffer));
1286 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
1287 xpdd->shutdown_irp = irp;
1288 IoSetCancelRoutine(irp, XenBus_ShutdownIoCancel);
1289 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
1290 status = XenPci_ProcessShutdownIrp(xpdd);
1292 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1294 return status;
1298 NTSTATUS
1299 XenPci_Irp_Cleanup_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1301 NTSTATUS status;
1303 UNREFERENCED_PARAMETER(device_object);
1305 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1307 status = STATUS_SUCCESS;
1308 irp->IoStatus.Status = status;
1309 IoCompleteRequest(irp, IO_NO_INCREMENT);
1311 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1313 return status;
1316 #if 0
1317 static VOID
1318 XenPci_BalloonHandler(char *Path, PVOID Data)
1320 WDFDEVICE Device = Data;
1321 char *value;
1322 xenbus_transaction_t xbt;
1323 int retry;
1325 UNREFERENCED_PARAMETER(Path);
1327 KdPrint((__DRIVER_NAME " --> XenBus_BalloonHandler\n"));
1329 XenBus_StartTransaction(Device, &xbt);
1331 XenBus_Read(Device, XBT_NIL, BALLOON_PATH, &value);
1333 KdPrint((__DRIVER_NAME " Balloon Value = %s\n", value));
1335 // use the memory_op(unsigned int op, void *arg) hypercall to adjust this
1336 // use XENMEM_increase_reservation and XENMEM_decrease_reservation
1338 XenBus_EndTransaction(Device, xbt, 0, &retry);
1340 XenPci_FreeMem(value);
1342 KdPrint((__DRIVER_NAME " <-- XenBus_BalloonHandler\n"));
1344 #endif