win-pvdrivers

view xenpci/xenpci_fdo.c @ 398:e7292fd9e55a

Fixup xenpci for mingw build with DBG enabled.

add FUNCTION_EXIT_STATUS macro
run unix2dos to fix line endings
update mingw makefiles
use FUNCTION_* macros in xenpci
author Andy Grover <andy.grover@oracle.com>
date Thu Jul 17 10:33:40 2008 -0700 (2008-07-17)
parents 46b6fa5bb7ad
children 04883e1dc65c
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_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;
453 UNREFERENCED_PARAMETER(context);
454 FUNCTION_ENTER();
456 if (xpdd->suspend_state == SUSPEND_STATE_NONE)
457 {
458 XenBus_StopThreads(xpdd);
459 xpdd->suspend_state = SUSPEND_STATE_SCHEDULED;
460 suspend_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(SUSPEND_INFO), XENPCI_POOL_TAG);
461 RtlZeroMemory(suspend_info, sizeof(SUSPEND_INFO));
462 KeInitializeEvent(&suspend_info->stopped_spinning_event, SynchronizationEvent, FALSE);
463 suspend_info->do_spin = 1;
465 for (i = 0; i < MAX_VIRT_CPUS; i++)
466 {
467 xpdd->shared_info_area->vcpu_info[i].evtchn_upcall_mask = 1;
468 }
469 KeMemoryBarrier();
470 EvtChn_Shutdown(xpdd);
472 //ActiveProcessorCount = KeQueryActiveProcessorCount(&ActiveProcessorMask); // this is for Vista+
473 ActiveProcessorCount = (ULONG)KeNumberProcessors;
474 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
475 for (i = 0; i < ActiveProcessorCount; i++)
476 {
477 Dpc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KDPC), XENPCI_POOL_TAG);
478 KeInitializeDpc(Dpc, XenPci_Suspend, xpdd);
479 KeSetTargetProcessorDpc(Dpc, (CCHAR)i);
480 KeInsertQueueDpc(Dpc, suspend_info, NULL);
481 }
482 KeLowerIrql(OldIrql);
483 }
484 FUNCTION_EXIT();
485 }
487 static void
488 XenPci_ShutdownHandler(char *path, PVOID context)
489 {
490 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)context;
491 char *res;
492 char *value;
493 KIRQL old_irql;
494 PIO_WORKITEM work_item;
496 UNREFERENCED_PARAMETER(path);
498 FUNCTION_ENTER();
500 res = XenBus_Read(xpdd, XBT_NIL, SHUTDOWN_PATH, &value);
501 if (res)
502 {
503 KdPrint(("Error reading shutdown path - %s\n", res));
504 XenPci_FreeMem(res);
505 return;
506 }
508 KdPrint((__DRIVER_NAME " Shutdown value = %s\n", value));
510 if (strlen(value) != 0)
511 {
512 if (strcmp(value, "suspend") == 0)
513 {
514 KdPrint((__DRIVER_NAME " Suspend detected\n"));
515 /* we have to queue this as a work item as we stop the xenbus thread, which we are currently running in! */
516 work_item = IoAllocateWorkItem(xpdd->common.fdo);
517 IoQueueWorkItem(work_item, XenPci_BeginSuspend, DelayedWorkQueue, NULL);
518 //XenPci_BeginSuspend(xpdd);
519 }
520 else
521 {
522 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
523 if (xpdd->shutdown_start >= xpdd->shutdown_cons)
524 xpdd->shutdown_prod = xpdd->shutdown_start;
525 else
526 xpdd->shutdown_start = xpdd->shutdown_prod;
527 memcpy(&xpdd->shutdown_ring[xpdd->shutdown_prod], value, strlen(value));
528 xpdd->shutdown_prod += (ULONG)strlen(value);
529 xpdd->shutdown_ring[xpdd->shutdown_prod++] = '\r';
530 xpdd->shutdown_ring[xpdd->shutdown_prod++] = '\n';
531 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
532 XenPci_ProcessShutdownIrp(xpdd);
533 }
534 }
536 //XenPci_FreeMem(value);
538 FUNCTION_EXIT();
539 }
541 static VOID
542 XenPci_SysrqHandler(char *path, PVOID context)
543 {
544 PXENPCI_DEVICE_DATA xpdd = context;
545 char *value;
546 char letter;
547 char *res;
549 UNREFERENCED_PARAMETER(path);
551 FUNCTION_ENTER();
553 XenBus_Read(xpdd, XBT_NIL, SYSRQ_PATH, &value);
555 KdPrint((__DRIVER_NAME " SysRq Value = %s\n", value));
557 if (value != NULL && strlen(value) != 0)
558 {
559 letter = *value;
560 res = XenBus_Write(xpdd, XBT_NIL, SYSRQ_PATH, "");
561 if (res)
562 {
563 KdPrint(("Error writing sysrq path\n"));
564 XenPci_FreeMem(res);
565 return;
566 }
567 }
568 else
569 {
570 letter = 0;
571 }
573 if (value != NULL)
574 {
575 XenPci_FreeMem(value);
576 }
578 switch (letter)
579 {
580 case 'B':
581 KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000001, 0x00000000, 0x00000000, 0x00000000);
582 break;
583 default:
584 KdPrint((" Unhandled sysrq letter %c\n", letter));
585 break;
586 }
588 FUNCTION_EXIT();
589 }
591 static VOID
592 XenPci_DeviceWatchHandler(char *path, PVOID context)
593 {
594 char **bits;
595 int count;
596 char *err;
597 char *value;
598 PXENPCI_DEVICE_DATA xpdd = context;
600 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
602 // KdPrint((__DRIVER_NAME " path = %s\n", path));
603 bits = SplitString(path, '/', 4, &count);
604 // KdPrint((__DRIVER_NAME " count = %d\n", count));
606 if (count == 3)
607 {
608 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
609 if (err)
610 {
611 /* obviously path no longer exists, in which case the removal is being taken care of elsewhere and we shouldn't invalidate now */
612 XenPci_FreeMem(err);
613 }
614 else
615 {
616 XenPci_FreeMem(value);
617 /* we probably have to be a bit smarter here and do nothing if xenpci isn't running yet */
618 KdPrint((__DRIVER_NAME " Invalidating Device Relations\n"));
619 IoInvalidateDeviceRelations(xpdd->common.pdo, BusRelations);
620 }
621 }
622 FreeSplitString(bits, count);
624 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
625 }
627 static DDKAPI VOID
628 XenPci_Pnp_StartDeviceCallback(PDEVICE_OBJECT device_object, PVOID context)
629 {
630 NTSTATUS status = STATUS_SUCCESS;
631 PXENPCI_DEVICE_DATA xpdd = device_object->DeviceExtension;
632 PIRP irp = context;
633 char *response;
635 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
637 XenPci_Init(xpdd);
639 GntTbl_Init(xpdd);
641 EvtChn_Init(xpdd);
642 EvtChn_ConnectInterrupt(xpdd);
644 XenBus_Init(xpdd);
646 response = XenBus_AddWatch(xpdd, XBT_NIL, SYSRQ_PATH, XenPci_SysrqHandler, xpdd);
647 KdPrint((__DRIVER_NAME " sysrqwatch response = '%s'\n", response));
649 response = XenBus_AddWatch(xpdd, XBT_NIL, SHUTDOWN_PATH, XenPci_ShutdownHandler, xpdd);
650 KdPrint((__DRIVER_NAME " shutdown watch response = '%s'\n", response));
652 response = XenBus_AddWatch(xpdd, XBT_NIL, "device", XenPci_DeviceWatchHandler, xpdd);
653 KdPrint((__DRIVER_NAME " device watch response = '%s'\n", response));
655 #if 0
656 response = XenBus_AddWatch(xpdd, XBT_NIL, BALLOON_PATH, XenPci_BalloonHandler, Device);
657 KdPrint((__DRIVER_NAME " balloon watch response = '%s'\n", response));
658 #endif
660 status = IoSetDeviceInterfaceState(&xpdd->interface_name, TRUE);
661 if (!NT_SUCCESS(status))
662 {
663 KdPrint((__DRIVER_NAME " IoSetDeviceInterfaceState failed with status 0x%08x\n", status));
664 }
666 irp->IoStatus.Status = status;
668 IoCompleteRequest(irp, IO_NO_INCREMENT);
670 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
671 }
673 static NTSTATUS
674 XenPci_Pnp_StartDevice(PDEVICE_OBJECT device_object, PIRP irp)
675 {
676 NTSTATUS status;
677 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
678 PIO_STACK_LOCATION stack;
679 PCM_PARTIAL_RESOURCE_LIST res_list;
680 PCM_PARTIAL_RESOURCE_DESCRIPTOR res_descriptor;
681 ULONG i;
683 UNREFERENCED_PARAMETER(device_object);
685 FUNCTION_ENTER();
687 stack = IoGetCurrentIrpStackLocation(irp);
689 IoMarkIrpPending(irp);
691 status = XenPci_SendAndWaitForIrp(device_object, irp);
693 res_list = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
695 for (i = 0; i < res_list->Count; i++)
696 {
697 res_descriptor = &res_list->PartialDescriptors[i];
698 switch (res_descriptor->Type)
699 {
700 case CmResourceTypeInterrupt:
701 KdPrint((__DRIVER_NAME " irq_number = %03x\n", res_descriptor->u.Interrupt.Vector));
702 xpdd->irq_number = res_descriptor->u.Interrupt.Vector;
703 //memcpy(&InterruptRaw, res_descriptor, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
704 break;
705 }
706 }
708 res_list = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
710 for (i = 0; i < res_list->Count; i++)
711 {
712 res_descriptor = &res_list->PartialDescriptors[i];
713 switch (res_descriptor->Type) {
714 case CmResourceTypePort:
715 break;
716 case CmResourceTypeMemory:
717 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));
718 KdPrint((__DRIVER_NAME " Memory flags = %04X\n", res_descriptor->Flags));
719 xpdd->platform_mmio_addr = res_descriptor->u.Memory.Start;
720 xpdd->platform_mmio_len = res_descriptor->u.Memory.Length;
721 xpdd->platform_mmio_alloc = 0;
722 xpdd->platform_mmio_flags = res_descriptor->Flags;
723 break;
724 case CmResourceTypeInterrupt:
725 KdPrint((__DRIVER_NAME " irq_vector = %03x\n", res_descriptor->u.Interrupt.Vector));
726 KdPrint((__DRIVER_NAME " irq_level = %03x\n", res_descriptor->u.Interrupt.Level));
727 xpdd->irq_level = (KIRQL)res_descriptor->u.Interrupt.Level;
728 xpdd->irq_vector = res_descriptor->u.Interrupt.Vector;
729 xpdd->irq_affinity = res_descriptor->u.Interrupt.Affinity;
730 //memcpy(&InterruptTranslated, res_descriptor, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
731 break;
732 case CmResourceTypeDevicePrivate:
733 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] ));
734 break;
735 default:
736 KdPrint((__DRIVER_NAME " Unhandled resource type (0x%x)\n", res_descriptor->Type));
737 break;
738 }
739 }
741 XenPci_QueueWorkItem(device_object, XenPci_Pnp_StartDeviceCallback, irp);
743 FUNCTION_EXIT();
745 return STATUS_PENDING;
746 }
748 static NTSTATUS
749 XenPci_Pnp_StopDevice(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
750 {
751 NTSTATUS status = STATUS_SUCCESS;
753 UNREFERENCED_PARAMETER(device_object);
754 UNREFERENCED_PARAMETER(context);
756 FUNCTION_ENTER();
758 irp->IoStatus.Status = status;
759 IoCompleteRequest(irp, IO_NO_INCREMENT);
761 FUNCTION_EXIT();
763 return irp->IoStatus.Status;
764 }
766 static NTSTATUS
767 XenPci_Pnp_QueryStopRemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
768 {
769 NTSTATUS status;
770 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
772 UNREFERENCED_PARAMETER(device_object);
774 FUNCTION_ENTER();
776 if (xpdd->common.device_usage_paging
777 || xpdd->common.device_usage_dump
778 || xpdd->common.device_usage_hibernation)
779 {
780 /* We are in the paging or hibernation path - can't remove */
781 status = irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
782 IoCompleteRequest(irp, IO_NO_INCREMENT);
783 }
784 else
785 {
786 IoSkipCurrentIrpStackLocation(irp);
787 status = IoCallDriver(xpdd->common.lower_do, irp);
788 }
790 FUNCTION_EXIT();
792 return status;
793 }
795 static NTSTATUS
796 XenPci_Pnp_RemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
797 {
798 NTSTATUS status;
799 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
801 UNREFERENCED_PARAMETER(device_object);
803 FUNCTION_ENTER();
805 irp->IoStatus.Status = STATUS_SUCCESS;
806 IoSkipCurrentIrpStackLocation(irp);
807 status = IoCallDriver(xpdd->common.lower_do, irp);
808 IoDetachDevice(xpdd->common.lower_do);
810 FUNCTION_EXIT();
812 return status;
813 }
815 static DDKAPI VOID
816 XenPci_Pnp_QueryBusRelationsCallback(PDEVICE_OBJECT device_object, PVOID context)
817 {
818 NTSTATUS status = STATUS_SUCCESS;
819 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
820 PXENPCI_PDO_DEVICE_DATA xppdd;
821 PIRP irp = context;
822 int device_count = 0;
823 PDEVICE_RELATIONS dev_relations;
824 PXEN_CHILD child, old_child;
825 //char *response;
826 char *msg;
827 char **devices;
828 char **instances;
829 int i, j;
830 CHAR path[128];
831 PDEVICE_OBJECT pdo;
833 FUNCTION_ENTER();
835 msg = XenBus_List(xpdd, XBT_NIL, "device", &devices);
836 if (!msg)
837 {
838 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
839 {
840 if (child->state == CHILD_STATE_DELETED)
841 KdPrint((__DRIVER_NAME " Found deleted child - this shouldn't happen\n" ));
842 child->state = CHILD_STATE_DELETED;
843 }
845 for (i = 0; devices[i]; i++)
846 {
847 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s", devices[i]);
848 msg = XenBus_List(xpdd, XBT_NIL, path, &instances);
849 if (!msg)
850 {
851 for (j = 0; instances[j]; j++)
852 {
853 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s/%s", devices[i], instances[j]);
855 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
856 {
857 if (strcmp(child->context->path, path) == 0)
858 {
859 KdPrint((__DRIVER_NAME " Existing device %s\n", path));
860 ASSERT(child->state == CHILD_STATE_DELETED);
861 child->state = CHILD_STATE_ADDED;
862 device_count++;
863 break;
864 }
865 }
867 if (child == (PXEN_CHILD)&xpdd->child_list)
868 {
869 KdPrint((__DRIVER_NAME " New device %s\n", path));
870 child = ExAllocatePoolWithTag(NonPagedPool, sizeof(XEN_CHILD), XENPCI_POOL_TAG);
871 child->state = CHILD_STATE_ADDED;
872 status = IoCreateDevice(
873 xpdd->common.fdo->DriverObject,
874 sizeof(XENPCI_PDO_DEVICE_DATA),
875 NULL,
876 FILE_DEVICE_UNKNOWN,
877 FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN,
878 FALSE,
879 &pdo);
880 if (!NT_SUCCESS(status))
881 KdPrint((__DRIVER_NAME " IoCreateDevice status = %08X\n", status));
882 RtlZeroMemory(pdo->DeviceExtension, sizeof(XENPCI_PDO_DEVICE_DATA));
883 child->context = xppdd = pdo->DeviceExtension;
884 xppdd->common.fdo = NULL;
885 xppdd->common.pdo = pdo;
886 ObReferenceObject(pdo);
887 xppdd->common.lower_do = NULL;
888 INIT_PNP_STATE(&xppdd->common);
889 xppdd->common.device_usage_paging = 0;
890 xppdd->common.device_usage_dump = 0;
891 xppdd->common.device_usage_hibernation = 0;
892 xppdd->bus_fdo = xpdd->common.fdo;
893 xppdd->bus_pdo = xpdd->common.pdo;
894 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), path);
895 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), devices[i]);
896 xppdd->index = atoi(instances[j]);
897 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
898 xppdd->backend_state = XenbusStateUnknown;
899 xppdd->backend_path[0] = '\0';
900 InsertTailList(&xpdd->child_list, (PLIST_ENTRY)child);
901 device_count++;
902 }
903 XenPci_FreeMem(instances[j]);
904 }
905 XenPci_FreeMem(instances);
906 }
907 XenPci_FreeMem(devices[i]);
908 }
909 XenPci_FreeMem(devices);
910 dev_relations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (device_count - 1), XENPCI_POOL_TAG);
911 for (child = (PXEN_CHILD)xpdd->child_list.Flink, device_count = 0; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
912 {
913 if (child->state == CHILD_STATE_ADDED)
914 {
915 ObReferenceObject(child->context->common.pdo);
916 dev_relations->Objects[device_count++] = child->context->common.pdo;
917 }
918 }
919 dev_relations->Count = device_count;
921 child = (PXEN_CHILD)xpdd->child_list.Flink;
922 while (child != (PXEN_CHILD)&xpdd->child_list)
923 {
924 if (child->state == CHILD_STATE_DELETED)
925 {
926 KdPrint((__DRIVER_NAME " Removing deleted child from device list\n" ));
927 old_child = child;
928 child = (PXEN_CHILD)child->entry.Flink;
929 RemoveEntryList((PLIST_ENTRY)old_child);
930 xppdd = old_child->context;
931 xppdd->reported_missing = TRUE;
932 ObDereferenceObject(xppdd->common.pdo);
933 ExFreePoolWithTag(old_child, XENPCI_POOL_TAG);
934 }
935 else
936 child = (PXEN_CHILD)child->entry.Flink;
937 }
939 status = STATUS_SUCCESS;
940 }
941 else
942 {
943 /* 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 */
944 device_count = 0;
945 dev_relations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (device_count - 1), XENPCI_POOL_TAG);
946 dev_relations->Count = device_count;
947 }
949 irp->IoStatus.Status = status;
950 irp->IoStatus.Information = (ULONG_PTR)dev_relations;
952 IoCompleteRequest (irp, IO_NO_INCREMENT);
954 FUNCTION_EXIT();
955 }
957 static NTSTATUS
958 XenPci_Pnp_QueryBusRelations(PDEVICE_OBJECT device_object, PIRP irp)
959 {
960 NTSTATUS status;
962 UNREFERENCED_PARAMETER(device_object);
964 FUNCTION_ENTER();
966 IoMarkIrpPending(irp);
968 status = XenPci_SendAndWaitForIrp(device_object, irp);
970 XenPci_QueueWorkItem(device_object, XenPci_Pnp_QueryBusRelationsCallback, irp);
972 FUNCTION_EXIT();
974 return STATUS_PENDING;
975 }
977 static DDKAPI VOID
978 XenPci_Pnp_FilterResourceRequirementsCallback(PDEVICE_OBJECT device_object, PVOID context)
979 {
980 NTSTATUS status = STATUS_SUCCESS;
981 //PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
982 PIRP irp = context;
983 PIO_RESOURCE_REQUIREMENTS_LIST irrl;
984 ULONG irl;
985 ULONG ird;
987 UNREFERENCED_PARAMETER(device_object);
989 FUNCTION_ENTER();
990 FUNCTION_MSG(("IoStatus.status = %08X\n", irp->IoStatus.Status));
992 irrl = (PIO_RESOURCE_REQUIREMENTS_LIST)irp->IoStatus.Information;
993 for (irl = 0; irl < irrl->AlternativeLists; irl++)
994 {
995 for (ird = 0; ird < irrl->List[irl].Count; ird++)
996 {
997 if (irrl->List[irl].Descriptors[ird].Type == CmResourceTypeMemory)
998 {
999 irrl->List[irl].Descriptors[ird].ShareDisposition = CmResourceShareShared;
1003 irp->IoStatus.Status = status;
1004 IoCompleteRequest (irp, IO_NO_INCREMENT);
1006 FUNCTION_EXIT();
1009 static NTSTATUS
1010 XenPci_Pnp_FilterResourceRequirements(PDEVICE_OBJECT device_object, PIRP irp)
1012 NTSTATUS status;
1014 UNREFERENCED_PARAMETER(device_object);
1016 FUNCTION_ENTER();
1018 IoMarkIrpPending(irp);
1020 status = XenPci_SendAndWaitForIrp(device_object, irp);
1022 XenPci_QueueWorkItem(device_object, XenPci_Pnp_FilterResourceRequirementsCallback, irp);
1024 FUNCTION_EXIT();
1026 return STATUS_PENDING;
1029 static NTSTATUS
1030 XenPci_Pnp_DeviceUsageNotification(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
1032 NTSTATUS status;
1033 PXENPCI_DEVICE_DATA xpdd;
1034 PIO_STACK_LOCATION stack;
1036 UNREFERENCED_PARAMETER(context);
1038 FUNCTION_ENTER();
1040 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1041 stack = IoGetCurrentIrpStackLocation(irp);
1042 status = irp->IoStatus.Status;
1044 /* fail if we are in a stop or remove pending state */
1045 if (!NT_SUCCESS(irp->IoStatus.Status))
1047 switch (stack->Parameters.UsageNotification.Type)
1049 case DeviceUsageTypePaging:
1050 if (stack->Parameters.UsageNotification.InPath)
1051 xpdd->common.device_usage_paging--;
1052 else
1053 xpdd->common.device_usage_paging++;
1054 break;
1055 case DeviceUsageTypeDumpFile:
1056 if (stack->Parameters.UsageNotification.InPath)
1057 xpdd->common.device_usage_dump--;
1058 else
1059 xpdd->common.device_usage_dump++;
1060 break;
1061 case DeviceUsageTypeHibernation:
1062 if (stack->Parameters.UsageNotification.InPath)
1063 xpdd->common.device_usage_hibernation--;
1064 else
1065 xpdd->common.device_usage_hibernation++;
1066 break;
1067 default:
1068 KdPrint((__DRIVER_NAME " Unknown usage type %x\n",
1069 stack->Parameters.UsageNotification.Type));
1070 break;
1072 if (xpdd->common.device_usage_paging
1073 || xpdd->common.device_usage_dump
1074 || xpdd->common.device_usage_hibernation)
1076 xpdd->common.fdo->Flags &= ~DO_POWER_PAGABLE;
1078 IoInvalidateDeviceState(xpdd->common.pdo);
1080 IoCompleteRequest(irp, IO_NO_INCREMENT);
1082 FUNCTION_EXIT();
1084 return status;
1088 NTSTATUS
1089 XenPci_Pnp_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1091 NTSTATUS status;
1092 PIO_STACK_LOCATION stack;
1093 PXENPCI_DEVICE_DATA xpdd;
1095 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1097 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1099 stack = IoGetCurrentIrpStackLocation(irp);
1101 switch (stack->MinorFunction)
1103 case IRP_MN_START_DEVICE:
1104 KdPrint((__DRIVER_NAME " IRP_MN_START_DEVICE\n"));
1105 return XenPci_Pnp_StartDevice(device_object, irp);
1107 case IRP_MN_QUERY_STOP_DEVICE:
1108 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_STOP_DEVICE\n"));
1109 status = XenPci_Pnp_QueryStopRemoveDevice(device_object, irp);
1110 if (NT_SUCCESS(status))
1111 SET_PNP_STATE(&xpdd->common, RemovePending);
1112 return status;
1114 case IRP_MN_STOP_DEVICE:
1115 KdPrint((__DRIVER_NAME " IRP_MN_STOP_DEVICE\n"));
1116 IoCopyCurrentIrpStackLocationToNext(irp);
1117 IoSetCompletionRoutine(irp, XenPci_Pnp_StopDevice, NULL, TRUE, TRUE, TRUE);
1118 break;
1120 case IRP_MN_CANCEL_STOP_DEVICE:
1121 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_STOP_DEVICE\n"));
1122 IoSkipCurrentIrpStackLocation(irp);
1123 REVERT_PNP_STATE(&xpdd->common);
1124 irp->IoStatus.Status = STATUS_SUCCESS;
1125 break;
1127 case IRP_MN_QUERY_REMOVE_DEVICE:
1128 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_REMOVE_DEVICE\n"));
1129 status = XenPci_Pnp_QueryStopRemoveDevice(device_object, irp);
1130 if (NT_SUCCESS(status))
1131 SET_PNP_STATE(&xpdd->common, RemovePending);
1132 return status;
1134 case IRP_MN_REMOVE_DEVICE:
1135 KdPrint((__DRIVER_NAME " IRP_MN_REMOVE_DEVICE\n"));
1136 return XenPci_Pnp_RemoveDevice(device_object, irp);
1137 break;
1139 case IRP_MN_CANCEL_REMOVE_DEVICE:
1140 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_REMOVE_DEVICE\n"));
1141 IoSkipCurrentIrpStackLocation(irp);
1142 REVERT_PNP_STATE(&xpdd->common);
1143 irp->IoStatus.Status = STATUS_SUCCESS;
1144 break;
1146 case IRP_MN_SURPRISE_REMOVAL:
1147 KdPrint((__DRIVER_NAME " IRP_MN_SURPRISE_REMOVAL\n"));
1148 IoSkipCurrentIrpStackLocation(irp);
1149 irp->IoStatus.Status = STATUS_SUCCESS;
1150 break;
1152 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1153 KdPrint((__DRIVER_NAME " IRP_MN_DEVICE_USAGE_NOTIFICATION\n"));
1154 switch (stack->Parameters.UsageNotification.Type)
1156 case DeviceUsageTypePaging:
1157 KdPrint((__DRIVER_NAME " type = DeviceUsageTypePaging = %d\n", stack->Parameters.UsageNotification.InPath));
1158 if (stack->Parameters.UsageNotification.InPath)
1159 xpdd->common.device_usage_paging++;
1160 else
1161 xpdd->common.device_usage_paging--;
1162 irp->IoStatus.Status = STATUS_SUCCESS;
1163 break;
1164 case DeviceUsageTypeDumpFile:
1165 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeDumpFile = %d\n", stack->Parameters.UsageNotification.InPath));
1166 if (stack->Parameters.UsageNotification.InPath)
1167 xpdd->common.device_usage_dump++;
1168 else
1169 xpdd->common.device_usage_dump--;
1170 irp->IoStatus.Status = STATUS_SUCCESS;
1171 break;
1172 case DeviceUsageTypeHibernation:
1173 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeHibernation = %d\n", stack->Parameters.UsageNotification.InPath));
1174 if (stack->Parameters.UsageNotification.InPath)
1175 xpdd->common.device_usage_hibernation++;
1176 else
1177 xpdd->common.device_usage_hibernation--;
1178 irp->IoStatus.Status = STATUS_SUCCESS;
1179 break;
1180 default:
1181 KdPrint((__DRIVER_NAME " type = unsupported (%d)\n", stack->Parameters.UsageNotification.Type));
1182 irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
1183 IoCompleteRequest(irp, IO_NO_INCREMENT);
1184 return STATUS_NOT_SUPPORTED;
1186 if (!xpdd->common.device_usage_paging
1187 && !xpdd->common.device_usage_dump
1188 && !xpdd->common.device_usage_hibernation)
1190 xpdd->common.fdo->Flags |= DO_POWER_PAGABLE;
1192 IoInvalidateDeviceState(xpdd->common.pdo);
1193 IoCopyCurrentIrpStackLocationToNext(irp);
1194 IoSetCompletionRoutine(irp, XenPci_Pnp_DeviceUsageNotification, NULL, TRUE, TRUE, TRUE);
1195 break;
1197 case IRP_MN_QUERY_DEVICE_RELATIONS:
1198 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_RELATIONS\n"));
1199 switch (stack->Parameters.QueryDeviceRelations.Type)
1201 case BusRelations:
1202 KdPrint((__DRIVER_NAME " BusRelations\n"));
1203 return XenPci_Pnp_QueryBusRelations(device_object, irp);
1204 break;
1205 default:
1206 IoSkipCurrentIrpStackLocation(irp);
1207 break;
1209 break;
1211 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1212 KdPrint((__DRIVER_NAME " IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"));
1213 return XenPci_Pnp_FilterResourceRequirements(device_object, irp);
1215 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1216 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_PNP_DEVICE_STATE\n"));
1217 irp->IoStatus.Status = STATUS_SUCCESS;
1218 if (xpdd->common.device_usage_paging
1219 || xpdd->common.device_usage_dump
1220 || xpdd->common.device_usage_hibernation)
1222 irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
1224 IoSkipCurrentIrpStackLocation(irp);
1225 break;
1227 default:
1228 //KdPrint((__DRIVER_NAME " Unhandled Minor = %d\n", stack->MinorFunction));
1229 IoSkipCurrentIrpStackLocation(irp);
1230 break;
1233 status = IoCallDriver(xpdd->common.lower_do, irp);
1235 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1237 return status;
1240 NTSTATUS
1241 XenPci_Irp_Create_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1243 PXENPCI_DEVICE_DATA xpdd;
1244 NTSTATUS status;
1246 FUNCTION_ENTER();
1248 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1249 status = STATUS_SUCCESS;
1250 irp->IoStatus.Status = status;
1251 IoCompleteRequest(irp, IO_NO_INCREMENT);
1253 FUNCTION_EXIT();
1255 return status;
1258 NTSTATUS
1259 XenPci_Irp_Close_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1261 PXENPCI_DEVICE_DATA xpdd;
1262 NTSTATUS status;
1264 FUNCTION_ENTER();
1266 // wait until pending irp's
1267 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1268 status = STATUS_SUCCESS;
1269 irp->IoStatus.Status = status;
1270 IoCompleteRequest(irp, IO_NO_INCREMENT);
1272 FUNCTION_EXIT();
1274 return status;
1277 NTSTATUS
1278 XenPci_Irp_Read_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1280 PXENPCI_DEVICE_DATA xpdd;
1281 NTSTATUS status;
1282 PIO_STACK_LOCATION stack;
1283 KIRQL old_irql;
1285 FUNCTION_ENTER();
1287 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
1288 stack = IoGetCurrentIrpStackLocation(irp);
1289 if (stack->Parameters.Read.Length == 0)
1291 irp->IoStatus.Information = 0;
1292 status = STATUS_SUCCESS;
1293 irp->IoStatus.Status = status;
1294 IoCompleteRequest(irp, IO_NO_INCREMENT);
1296 else
1298 KdPrint((__DRIVER_NAME " stack = %p\n", stack));
1299 KdPrint((__DRIVER_NAME " length = %d, buffer = %p\n", stack->Parameters.Read.Length, irp->AssociatedIrp.SystemBuffer));
1301 KeAcquireSpinLock(&xpdd->shutdown_ring_lock, &old_irql);
1302 xpdd->shutdown_irp = irp;
1303 IoSetCancelRoutine(irp, XenBus_ShutdownIoCancel);
1304 KeReleaseSpinLock(&xpdd->shutdown_ring_lock, old_irql);
1305 status = XenPci_ProcessShutdownIrp(xpdd);
1308 FUNCTION_EXIT();
1310 return status;
1314 NTSTATUS
1315 XenPci_Irp_Cleanup_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
1317 NTSTATUS status;
1319 UNREFERENCED_PARAMETER(device_object);
1321 FUNCTION_ENTER();
1323 status = STATUS_SUCCESS;
1324 irp->IoStatus.Status = status;
1325 IoCompleteRequest(irp, IO_NO_INCREMENT);
1327 FUNCTION_EXIT();
1329 return status;
1332 #if 0
1333 static VOID
1334 XenPci_BalloonHandler(char *Path, PVOID Data)
1336 WDFDEVICE Device = Data;
1337 char *value;
1338 xenbus_transaction_t xbt;
1339 int retry;
1341 UNREFERENCED_PARAMETER(Path);
1343 KdPrint((__DRIVER_NAME " --> XenBus_BalloonHandler\n"));
1345 XenBus_StartTransaction(Device, &xbt);
1347 XenBus_Read(Device, XBT_NIL, BALLOON_PATH, &value);
1349 KdPrint((__DRIVER_NAME " Balloon Value = %s\n", value));
1351 // use the memory_op(unsigned int op, void *arg) hypercall to adjust this
1352 // use XENMEM_increase_reservation and XENMEM_decrease_reservation
1354 XenBus_EndTransaction(Device, xbt, 0, &retry);
1356 XenPci_FreeMem(value);
1358 KdPrint((__DRIVER_NAME " <-- XenBus_BalloonHandler\n"));
1360 #endif