win-pvdrivers

view xenpci/xenpci_fdo.c @ 266:b88529df8b60

More wdm updates
author James Harper <james.harper@bendigoit.com.au>
date Wed May 07 10:47:03 2008 +1000 (2008-05-07)
parents aef4bd71120b
children f157f82e0293
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 NTSTATUS
30 XenPCI_PrepareHardware(WDFDEVICE hDevice, WDFCMRESLIST Resources, WDFCMRESLIST ResourcesTranslated);
31 static NTSTATUS
32 XenPCI_ReleaseHardware(WDFDEVICE Device, WDFCMRESLIST ResourcesTranslated);
33 static NTSTATUS
34 XenPCI_D0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState);
35 static NTSTATUS
36 XenPCI_D0EntryPostInterruptsEnabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState);
37 static NTSTATUS
38 XenPCI_D0Exit(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState);
39 static NTSTATUS
40 XenPCI_D0ExitPreInterruptsDisabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState);
41 static VOID
42 XenPCI_IoDefault(WDFQUEUE Queue, WDFREQUEST Request);
43 static VOID
44 XenPCI_IoRead(WDFQUEUE Queue, WDFREQUEST Request, size_t Length);
45 static NTSTATUS
46 XenPCI_InterruptEnable(WDFINTERRUPT Interrupt, WDFDEVICE AssociatedDevice);
47 static NTSTATUS
48 XenPCI_InterruptDisable(WDFINTERRUPT Interrupt, WDFDEVICE AssociatedDevice);
49 static NTSTATUS
50 XenPCI_ChildListCreateDevice(WDFCHILDLIST ChildList, PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, PWDFDEVICE_INIT ChildInit);
51 static NTSTATUS
52 XenPCI_DeviceResourceRequirementsQuery(WDFDEVICE Device, WDFIORESREQLIST IoResourceRequirementsList);
53 static NTSTATUS
54 XenPCI_FilterRemoveResourceRequirements(WDFDEVICE Device, WDFIORESREQLIST IoResourceRequirementsList);
55 static NTSTATUS
56 XenPCI_FilterAddResourceRequirements(WDFDEVICE Device, WDFIORESREQLIST RequirementsList);
57 static NTSTATUS
58 XenPCI_RemoveAddedResources(WDFDEVICE Device, WDFCMRESLIST ResourcesRaw, WDFCMRESLIST ResourcesTranslated);
59 #endif
61 static VOID
62 XenBus_SysrqHandler(char *Path, PVOID Data);
63 static VOID
64 XenBus_ShutdownHandler(char *Path, PVOID Data);
65 static VOID
66 XenBus_BalloonHandler(char *Path, PVOID Data);
67 /*
68 static VOID
69 XenPCI_XenBusWatchHandler(char *Path, PVOID Data);
70 */
72 /* Global (driver-wide) variables */
73 static BOOLEAN AutoEnumerate;
74 static LIST_ENTRY ShutdownMsgList;
76 #pragma warning(disable : 4200) // zero-sized array
78 typedef struct {
79 LIST_ENTRY ListEntry;
80 ULONG Ptr;
81 // ULONG Len;
82 CHAR Buf[0];
83 } SHUTDOWN_MSG_ENTRY, *PSHUTDOWN_MSG_ENTRY;
85 static KSPIN_LOCK ShutdownMsgLock;
87 CM_PARTIAL_RESOURCE_DESCRIPTOR InterruptRaw;
88 CM_PARTIAL_RESOURCE_DESCRIPTOR InterruptTranslated;
90 NTSTATUS
91 XenPci_Power_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
92 {
93 NTSTATUS status;
94 PIO_STACK_LOCATION stack;
95 PXENPCI_DEVICE_DATA xpdd;
97 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
99 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
100 stack = IoGetCurrentIrpStackLocation(irp);
101 IoSkipCurrentIrpStackLocation(irp);
102 status = PoCallDriver(xpdd->common.lower_do, irp);
104 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
106 return status;
107 }
109 NTSTATUS
110 XenPci_Dummy_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
111 {
112 NTSTATUS status;
113 PIO_STACK_LOCATION stack;
114 PXENPCI_DEVICE_DATA xpdd;
116 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
118 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
119 stack = IoGetCurrentIrpStackLocation(irp);
120 IoSkipCurrentIrpStackLocation(irp);
121 status = IoCallDriver(xpdd->common.lower_do, irp);
123 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
125 return status;
126 }
128 /*
129 * Many XEN_IFACE functions allocate memory. Clients must use this to free it.
130 * (Xenbus_Read, XenBus_List, XenBus_AddWatch, XenBus_RemWatch)
131 */
132 static void
133 XenPCI_FreeMem(PVOID Ptr)
134 {
135 ExFreePoolWithTag(Ptr, XENPCI_POOL_TAG);
136 }
138 /*
139 * Alloc MMIO from the device's MMIO region. There is no corresponding free() fn
140 */
141 PHYSICAL_ADDRESS
142 XenPci_AllocMMIO(PXENPCI_DEVICE_DATA xpdd, ULONG len)
143 {
144 PHYSICAL_ADDRESS addr;
146 len = (len + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
148 addr = xpdd->platform_mmio_addr;
149 addr.QuadPart += xpdd->platform_mmio_alloc;
150 xpdd->platform_mmio_alloc += len;
152 ASSERT(xpdd->platform_mmio_alloc <= xpdd->platform_mmio_len);
154 return addr;
155 }
157 static NTSTATUS
158 XenPci_Init(PXENPCI_DEVICE_DATA xpdd)
159 {
160 struct xen_add_to_physmap xatp;
161 int ret;
162 PHYSICAL_ADDRESS shared_info_area_unmapped;
164 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
166 hvm_get_stubs(xpdd);
168 shared_info_area_unmapped = XenPci_AllocMMIO(xpdd, PAGE_SIZE);
169 KdPrint((__DRIVER_NAME " shared_info_area_unmapped.QuadPart = %lx\n", shared_info_area_unmapped.QuadPart));
170 xatp.domid = DOMID_SELF;
171 xatp.idx = 0;
172 xatp.space = XENMAPSPACE_shared_info;
173 xatp.gpfn = (xen_pfn_t)(shared_info_area_unmapped.QuadPart >> PAGE_SHIFT);
174 KdPrint((__DRIVER_NAME " gpfn = %d\n", xatp.gpfn));
175 ret = HYPERVISOR_memory_op(xpdd, XENMEM_add_to_physmap, &xatp);
176 KdPrint((__DRIVER_NAME " hypervisor memory op ret = %d\n", ret));
177 xpdd->shared_info_area = MmMapIoSpace(shared_info_area_unmapped,
178 PAGE_SIZE, MmCached);
179 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
181 return STATUS_SUCCESS;
182 }
184 #if 0
185 WDFQUEUE ReadQueue;
186 #endif
188 static NTSTATUS
189 XenPci_Pnp_IoCompletion(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
190 {
191 PKEVENT event = (PKEVENT)context;
193 UNREFERENCED_PARAMETER(device_object);
195 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
197 if (irp->PendingReturned)
198 {
199 KeSetEvent(event, IO_NO_INCREMENT, FALSE);
200 }
202 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
204 return STATUS_MORE_PROCESSING_REQUIRED;
205 }
207 static NTSTATUS
208 XenPci_QueueWorkItem(PDEVICE_OBJECT device_object, PIO_WORKITEM_ROUTINE routine, PVOID context)
209 {
210 PIO_WORKITEM work_item;
211 NTSTATUS status = STATUS_SUCCESS;
213 work_item = IoAllocateWorkItem(device_object);
214 IoQueueWorkItem(work_item, routine, DelayedWorkQueue, context);
216 return status;
217 }
219 static NTSTATUS
220 XenPci_SendAndWaitForIrp(PDEVICE_OBJECT device_object, PIRP irp)
221 {
222 NTSTATUS status;
223 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
224 KEVENT event;
226 UNREFERENCED_PARAMETER(device_object);
228 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
230 KeInitializeEvent(&event, NotificationEvent, FALSE);
232 IoCopyCurrentIrpStackLocationToNext(irp);
233 IoSetCompletionRoutine(irp, XenPci_Pnp_IoCompletion, &event, TRUE, TRUE, TRUE);
235 status = IoCallDriver(xpdd->common.lower_do, irp);
237 if (status == STATUS_PENDING)
238 {
239 KdPrint((__DRIVER_NAME " waiting ...\n"));
240 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
241 KdPrint((__DRIVER_NAME " ... done\n"));
242 status = irp->IoStatus.Status;
243 }
245 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
247 return status;
248 }
250 static VOID
251 XenPci_Pnp_StartDeviceCallback(PDEVICE_OBJECT device_object, PVOID context)
252 {
253 NTSTATUS status = STATUS_SUCCESS;
254 PXENPCI_DEVICE_DATA xpdd = device_object->DeviceExtension;
255 PIRP irp = context;
257 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
259 XenPci_Init(xpdd);
261 GntTbl_Init(xpdd);
263 EvtChn_Init(xpdd);
265 XenBus_Init(xpdd);
267 irp->IoStatus.Status = status;
269 IoCompleteRequest(irp, IO_NO_INCREMENT);
271 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
272 }
274 static NTSTATUS
275 XenPci_Pnp_StartDevice(PDEVICE_OBJECT device_object, PIRP irp)
276 {
277 NTSTATUS status;
278 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
279 PIO_STACK_LOCATION stack;
280 PCM_PARTIAL_RESOURCE_LIST res_list;
281 PCM_PARTIAL_RESOURCE_DESCRIPTOR res_descriptor;
282 ULONG i;
284 UNREFERENCED_PARAMETER(device_object);
286 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
288 stack = IoGetCurrentIrpStackLocation(irp);
290 IoMarkIrpPending(irp);
292 status = XenPci_SendAndWaitForIrp(device_object, irp);
294 res_list = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
296 for (i = 0; i < res_list->Count; i++)
297 {
298 res_descriptor = &res_list->PartialDescriptors[i];
299 switch (res_descriptor->Type)
300 {
301 case CmResourceTypeInterrupt:
302 KdPrint((__DRIVER_NAME " irq_number = %d\n", res_descriptor->u.Interrupt.Vector));
303 xpdd->irq_number = res_descriptor->u.Interrupt.Vector;
304 memcpy(&InterruptRaw, res_descriptor, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
305 break;
306 }
307 }
309 res_list = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
311 for (i = 0; i < res_list->Count; i++)
312 {
313 res_descriptor = &res_list->PartialDescriptors[i];
314 switch (res_descriptor->Type) {
315 case CmResourceTypePort:
316 break;
317 case CmResourceTypeMemory:
318 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));
319 xpdd->platform_mmio_addr = res_descriptor->u.Memory.Start;
320 xpdd->platform_mmio_len = res_descriptor->u.Memory.Length;
321 xpdd->platform_mmio_alloc = 0;
322 break;
323 case CmResourceTypeInterrupt:
324 KdPrint((__DRIVER_NAME " irq_vector = %d\n", res_descriptor->u.Interrupt.Vector));
325 xpdd->irq_level = (KIRQL)res_descriptor->u.Interrupt.Level;
326 xpdd->irq_vector = res_descriptor->u.Interrupt.Vector;
327 xpdd->irq_affinity = res_descriptor->u.Interrupt.Affinity;
328 memcpy(&InterruptTranslated, res_descriptor, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
329 break;
330 case CmResourceTypeDevicePrivate:
331 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] ));
332 break;
333 default:
334 KdPrint((__DRIVER_NAME " Unhandled resource type (0x%x)\n", res_descriptor->Type));
335 break;
336 }
337 }
339 XenPci_QueueWorkItem(device_object, XenPci_Pnp_StartDeviceCallback, irp);
341 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
343 return STATUS_PENDING;
344 }
346 static NTSTATUS
347 XenPci_Pnp_StopDevice(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
348 {
349 NTSTATUS status = STATUS_SUCCESS;
351 UNREFERENCED_PARAMETER(device_object);
352 UNREFERENCED_PARAMETER(context);
354 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
356 irp->IoStatus.Status = status;
357 IoCompleteRequest(irp, IO_NO_INCREMENT);
359 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
361 return irp->IoStatus.Status;
362 }
364 static NTSTATUS
365 XenPci_Pnp_QueryRemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
366 {
367 NTSTATUS status;
368 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
370 UNREFERENCED_PARAMETER(device_object);
372 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
374 if (FALSE)
375 {
376 /* We are in the paging or hibernation path - can't remove */
377 status = irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
378 IoCompleteRequest(irp, IO_NO_INCREMENT);
379 }
380 else
381 {
382 IoSkipCurrentIrpStackLocation(irp);
383 status = IoCallDriver(xpdd->common.lower_do, irp);
384 }
386 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
388 return status;
389 }
391 static NTSTATUS
392 XenPci_Pnp_RemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
393 {
394 NTSTATUS status;
395 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
397 UNREFERENCED_PARAMETER(device_object);
399 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
401 irp->IoStatus.Status = STATUS_SUCCESS;
402 IoSkipCurrentIrpStackLocation(irp);
403 status = IoCallDriver(xpdd->common.lower_do, irp);
404 IoDetachDevice(xpdd->common.lower_do);
406 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
408 return status;
409 }
411 #if 0
412 static VOID
413 XenPci_XenBusWatchHandler(PVOID context, char *path)
414 {
415 NTSTATUS status;
416 char **bits;
417 int count;
418 int i;
419 // WDFDEVICE Device = Data;
420 // WDFCHILDLIST ChildList;
421 // WDF_CHILD_LIST_ITERATOR ChildIterator;
422 // WDFDEVICE ChildDevice;
423 // PXENPCI_XEN_DEVICE_DATA ChildDeviceData;
424 // XENPCI_IDENTIFICATION_DESCRIPTION description;
425 PXEN_CHILD child = NULL;
426 PXENPCI_DEVICE_DATA xpdd = context;
428 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
430 #if (NTDDI_VERSION >= NTDDI_WS03SP1)
431 KeAcquireGuardedMutex(&xpdd->WatchHandlerMutex);
432 #endif
434 KdPrint((__DRIVER_NAME " path = %s\n", path));
435 bits = SplitString(path, '/', 3, &count);
436 KdPrint((__DRIVER_NAME " Count = %s\n", count));
438 ASSERT(count >= 2);
440 for (i = 0; i < 16; i++)
441 {
442 if (xpdd->child_devices[i].pdo != NULL && strncmp(xpdd->child_devices[i].path, path, strlen(xpdd->child_devices[i].path)) == 0 && path[strlen(xpdd->child_devices[i].path] == '/')
443 {
444 child = &xpdd->child_devices[i];
445 break;
446 }
447 }
449 if (child == NULL && count >= 2)
450 IoInvalidateDeviceRelations(xpdd->common.fdo, BusRelations);
451 else if (count > 2)
452 {
453 // forward on to the child
454 }
456 #if 0
457 ChildDeviceData = NULL;
458 WDF_CHILD_LIST_ITERATOR_INIT(&ChildIterator, WdfRetrievePresentChildren);
459 WdfChildListBeginIteration(ChildList, &ChildIterator);
460 while (NT_SUCCESS(WdfChildListRetrieveNextDevice(ChildList, &ChildIterator, &ChildDevice, NULL)))
461 {
462 ChildDeviceData = GetXenDeviceData(ChildDevice);
463 if (!ChildDeviceData)
464 {
465 KdPrint((" No child device data, should never happen\n"));
466 continue;
467 }
468 if (strncmp(ChildDeviceData->Path, Path, strlen(ChildDeviceData->Path)) == 0 && Path[strlen(ChildDeviceData->Path)] == '/')
469 {
470 if (Count == 3 && ChildDeviceData->WatchHandler != NULL)
471 ChildDeviceData->WatchHandler(Path, ChildDeviceData->WatchContext);
472 break;
473 }
474 ChildDeviceData = NULL;
475 }
476 WdfChildListEndIteration(ChildList, &ChildIterator);
477 if (Count >= 2 && ChildDeviceData == NULL)
478 {
479 RtlZeroMemory(&description, sizeof(description));
480 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&description.Header, sizeof(description));
481 strncpy(description.Path, Path, 128);
482 strncpy(description.DeviceType, Bits[1], 128);
483 KdPrint((__DRIVER_NAME " Adding child for %s\n", description.DeviceType));
484 status = WdfChildListAddOrUpdateChildDescriptionAsPresent(ChildList, &description.Header, NULL);
485 }
486 FreeSplitString(Bits, Count);
488 #if (NTDDI_VERSION >= NTDDI_WS03SP1)
489 KeReleaseGuardedMutex(&xpdd->WatchHandlerMutex);
490 #endif
492 #endif
494 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
495 }
496 #endif
498 static VOID
499 XenPci_Pnp_QueryBusRelationsCallback(PDEVICE_OBJECT device_object, PVOID context)
500 {
501 NTSTATUS status = STATUS_SUCCESS;
502 PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
503 PIRP irp = context;
504 int devices = 0;
505 PDEVICE_RELATIONS dev_relations;
506 PXEN_CHILD child;
507 //char *response;
508 char *msgTypes;
509 char **Types;
510 int i;
511 //CHAR buffer[128];
512 PDEVICE_OBJECT pdo;
514 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
516 msgTypes = XenBus_List(xpdd, XBT_NIL, "device", &Types);
517 if (!msgTypes)
518 {
519 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
520 {
521 if (child->state == CHILD_STATE_DELETED)
522 KdPrint((__DRIVER_NAME " Found deleted child - this shouldn't happen\n" ));
523 child->state = CHILD_STATE_DELETED;
524 }
526 for (i = 0; Types[i]; i++)
527 {
528 //RtlStringCbPrintfA(buffer, ARRAY_SIZE(buffer), "device/%s", Types[i]);
530 for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
531 {
532 if (strcmp(child->context->path, Types[i]) == 0)
533 {
534 KdPrint((__DRIVER_NAME " Existing device %s\n", Types[i]));
535 ASSERT(child->state != CHILD_STATE_DELETED);
536 child->state = CHILD_STATE_ADDED;
537 devices++;
538 break;
539 }
540 }
541 if (child == (PXEN_CHILD)&xpdd->child_list)
542 {
543 KdPrint((__DRIVER_NAME " New device %s\n", Types[i]));
544 child = ExAllocatePoolWithTag(NonPagedPool, sizeof(XEN_CHILD), XENPCI_POOL_TAG);
545 child->state = CHILD_STATE_ADDED;
546 status = IoCreateDeviceSecure(
547 xpdd->common.fdo->DriverObject,
548 sizeof(XENPCI_PDO_DEVICE_DATA),
549 NULL,
550 FILE_DEVICE_UNKNOWN,
551 FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN,
552 FALSE,
553 &SDDL_DEVOBJ_SYS_ALL_ADM_ALL,
554 (LPCGUID)&GUID_XENPCI_DEVCLASS,
555 &pdo);
556 if (!NT_SUCCESS(status))
557 KdPrint((__DRIVER_NAME " IoCreateDevice status = %08X\n", status));
558 child->context = (PXENPCI_PDO_DEVICE_DATA)pdo->DeviceExtension;
559 child->context->common.fdo = NULL;
560 child->context->common.pdo = pdo;
561 child->context->common.lower_do = NULL;
562 child->context->bus_fdo = device_object;
563 strcpy(child->context->path, Types[i]);
564 child->context->index = 0;
565 child->context->mmio_phys = XenPci_AllocMMIO(xpdd, PAGE_SIZE);
566 InsertTailList(&xpdd->child_list, (PLIST_ENTRY)child);
567 devices++;
568 }
569 ExFreePoolWithTag(Types[i], XENPCI_POOL_TAG);
570 }
571 dev_relations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (devices - 1), XENPCI_POOL_TAG);
572 for (child = (PXEN_CHILD)xpdd->child_list.Flink, devices = 0; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
573 {
574 if (child->state == CHILD_STATE_ADDED)
575 dev_relations->Objects[devices++] = child->context->common.pdo;
576 }
577 dev_relations->Count = devices;
579 status = STATUS_SUCCESS;
580 }
581 else
582 {
583 devices = 0;
584 dev_relations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (devices - 1), XENPCI_POOL_TAG);
585 dev_relations->Count = devices;
586 }
588 XenPCI_FreeMem(Types);
590 irp->IoStatus.Status = status;
591 irp->IoStatus.Information = (ULONG_PTR)dev_relations;
593 IoCompleteRequest (irp, IO_NO_INCREMENT);
595 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
596 }
598 static NTSTATUS
599 XenPci_Pnp_QueryBusRelations(PDEVICE_OBJECT device_object, PIRP irp)
600 {
601 NTSTATUS status;
603 UNREFERENCED_PARAMETER(device_object);
605 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
607 IoMarkIrpPending(irp);
609 status = XenPci_SendAndWaitForIrp(device_object, irp);
611 XenPci_QueueWorkItem(device_object, XenPci_Pnp_QueryBusRelationsCallback, irp);
613 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
615 return STATUS_PENDING;
616 }
618 static VOID
619 XenPci_Pnp_FilterResourceRequirementsCallback(PDEVICE_OBJECT device_object, PVOID context)
620 {
621 NTSTATUS status = STATUS_SUCCESS;
622 //PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
623 PIRP irp = context;
624 PIO_RESOURCE_REQUIREMENTS_LIST irrl;
625 ULONG irl;
626 ULONG ird;
628 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (status = %08X)\n", irp->IoStatus.Status));
630 irrl = (PIO_RESOURCE_REQUIREMENTS_LIST)irp->IoStatus.Information;
631 for (irl = 0; irl < irrl->AlternativeLists; irl++)
632 {
633 for (ird = 0; ird < irrl->List[irl].Count; ird++)
634 {
635 if (irrl->List[irl].Descriptors[ird].Type == CmResourceTypeMemory)
636 {
637 irrl->List[irl].Descriptors[ird].ShareDisposition = CmResourceShareShared;
638 }
639 }
640 }
641 irp->IoStatus.Status = status;
642 IoCompleteRequest (irp, IO_NO_INCREMENT);
644 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
646 return;
647 }
649 static NTSTATUS
650 XenPci_Pnp_FilterResourceRequirements(PDEVICE_OBJECT device_object, PIRP irp)
651 {
652 NTSTATUS status;
654 UNREFERENCED_PARAMETER(device_object);
656 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
658 IoMarkIrpPending(irp);
660 status = XenPci_SendAndWaitForIrp(device_object, irp);
662 XenPci_QueueWorkItem(device_object, XenPci_Pnp_FilterResourceRequirementsCallback, irp);
664 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
666 return STATUS_PENDING;
667 }
669 NTSTATUS
670 XenPci_Pnp_Fdo(PDEVICE_OBJECT device_object, PIRP irp)
671 {
672 PIO_STACK_LOCATION stack;
673 NTSTATUS status;
674 PXENPCI_DEVICE_DATA xpdd;
676 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
678 xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
680 stack = IoGetCurrentIrpStackLocation(irp);
682 switch (stack->MinorFunction)
683 {
684 case IRP_MN_START_DEVICE:
685 KdPrint((__DRIVER_NAME " IRP_MN_START_DEVICE\n"));
686 return XenPci_Pnp_StartDevice(device_object, irp);
688 case IRP_MN_QUERY_STOP_DEVICE:
689 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_STOP_DEVICE\n"));
690 IoSkipCurrentIrpStackLocation(irp);
691 irp->IoStatus.Status = STATUS_SUCCESS;
692 break;
694 case IRP_MN_STOP_DEVICE:
695 KdPrint((__DRIVER_NAME " IRP_MN_STOP_DEVICE\n"));
696 IoCopyCurrentIrpStackLocationToNext(irp);
697 IoSetCompletionRoutine(irp, XenPci_Pnp_StopDevice, NULL, TRUE, TRUE, TRUE);
698 break;
700 case IRP_MN_CANCEL_STOP_DEVICE:
701 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_STOP_DEVICE\n"));
702 IoSkipCurrentIrpStackLocation(irp);
703 irp->IoStatus.Status = STATUS_SUCCESS;
704 break;
706 case IRP_MN_QUERY_REMOVE_DEVICE:
707 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_REMOVE_DEVICE\n"));
708 return XenPci_Pnp_QueryRemoveDevice(device_object, irp);
710 case IRP_MN_REMOVE_DEVICE:
711 KdPrint((__DRIVER_NAME " IRP_MN_REMOVE_DEVICE\n"));
712 return XenPci_Pnp_QueryRemoveDevice(device_object, irp);
713 break;
715 case IRP_MN_CANCEL_REMOVE_DEVICE:
716 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_REMOVE_DEVICE\n"));
717 IoSkipCurrentIrpStackLocation(irp);
718 irp->IoStatus.Status = STATUS_SUCCESS;
719 break;
721 case IRP_MN_SURPRISE_REMOVAL:
722 KdPrint((__DRIVER_NAME " IRP_MN_SURPRISE_REMOVAL\n"));
723 IoSkipCurrentIrpStackLocation(irp);
724 irp->IoStatus.Status = STATUS_SUCCESS;
725 break;
727 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
728 KdPrint((__DRIVER_NAME " IRP_MN_DEVICE_USAGE_NOTIFICATION\n"));
729 IoSkipCurrentIrpStackLocation(irp);
730 irp->IoStatus.Status = STATUS_SUCCESS;
731 break;
733 case IRP_MN_QUERY_DEVICE_RELATIONS:
734 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_RELATIONS\n"));
735 switch (stack->Parameters.QueryDeviceRelations.Type)
736 {
737 case BusRelations:
738 KdPrint((__DRIVER_NAME " BusRelations\n"));
739 return XenPci_Pnp_QueryBusRelations(device_object, irp);
740 break;
741 default:
742 IoSkipCurrentIrpStackLocation(irp);
743 break;
744 }
745 break;
747 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
748 KdPrint((__DRIVER_NAME " IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"));
749 return XenPci_Pnp_FilterResourceRequirements(device_object, irp);
751 default:
752 KdPrint((__DRIVER_NAME " Unhandled Minor = %d\n", stack->MinorFunction));
753 IoSkipCurrentIrpStackLocation(irp);
754 break;
755 }
757 status = IoCallDriver(xpdd->common.lower_do, irp);
759 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
761 return status;
762 }
764 #if 0
766 static NTSTATUS
767 XenPCI_D0Entry(
768 IN WDFDEVICE Device,
769 IN WDF_POWER_DEVICE_STATE PreviousState
770 )
771 {
772 NTSTATUS status = STATUS_SUCCESS;
774 UNREFERENCED_PARAMETER(Device);
775 UNREFERENCED_PARAMETER(PreviousState);
777 KdPrint((__DRIVER_NAME " --> EvtDeviceD0Entry\n"));
779 KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Entry\n"));
781 return status;
782 }
784 static NTSTATUS
785 XenPCI_D0EntryPostInterruptsEnabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState)
786 {
787 NTSTATUS status = STATUS_SUCCESS;
788 //OBJECT_ATTRIBUTES oa;
789 char *response;
790 char *msgTypes;
791 char **Types;
792 int i;
793 char buffer[128];
794 WDFCHILDLIST ChildList;
796 UNREFERENCED_PARAMETER(PreviousState);
798 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
800 XenBus_Start(Device);
802 response = XenBus_AddWatch(Device, XBT_NIL, SYSRQ_PATH, XenBus_SysrqHandler, Device);
803 KdPrint((__DRIVER_NAME " sysrqwatch response = '%s'\n", response));
805 response = XenBus_AddWatch(Device, XBT_NIL, SHUTDOWN_PATH, XenBus_ShutdownHandler, Device);
806 KdPrint((__DRIVER_NAME " shutdown watch response = '%s'\n", response));
808 response = XenBus_AddWatch(Device, XBT_NIL, BALLOON_PATH, XenBus_BalloonHandler, Device);
809 KdPrint((__DRIVER_NAME " shutdown watch response = '%s'\n", response));
811 response = XenBus_AddWatch(Device, XBT_NIL, "device", XenPCI_XenBusWatchHandler, Device);
812 KdPrint((__DRIVER_NAME " device watch response = '%s'\n", response));
814 ChildList = WdfFdoGetDefaultChildList(Device);
816 WdfChildListBeginScan(ChildList);
817 msgTypes = XenBus_List(Device, XBT_NIL, "device", &Types);
818 if (!msgTypes) {
819 for (i = 0; Types[i]; i++)
820 {
821 RtlStringCbPrintfA(buffer, ARRAY_SIZE(buffer), "device/%s", Types[i]);
822 XenPCI_XenBusWatchHandler(buffer, Device);
823 ExFreePoolWithTag(Types[i], XENPCI_POOL_TAG);
824 }
825 }
826 WdfChildListEndScan(ChildList);
828 XenPCI_FreeMem(Types);
830 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
832 return status;
833 }
835 static NTSTATUS
836 XenPCI_D0ExitPreInterruptsDisabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState)
837 {
838 NTSTATUS status = STATUS_SUCCESS;
840 UNREFERENCED_PARAMETER(TargetState);
842 KdPrint((__DRIVER_NAME " --> D0ExitPreInterruptsDisabled\n"));
844 XenBus_Stop(Device);
846 KdPrint((__DRIVER_NAME " <-- D0ExitPreInterruptsDisabled\n"));
848 return status;
849 }
851 static NTSTATUS
852 XenPCI_D0Exit(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState)
853 {
854 NTSTATUS status = STATUS_SUCCESS;
856 UNREFERENCED_PARAMETER(Device);
857 UNREFERENCED_PARAMETER(TargetState);
859 KdPrint((__DRIVER_NAME " --> DeviceD0Exit\n"));
861 XenBus_Close(Device);
863 KdPrint((__DRIVER_NAME " <-- DeviceD0Exit\n"));
865 return status;
866 }
868 static VOID
869 XenPCI_IoDefault(
870 IN WDFQUEUE Queue,
871 IN WDFREQUEST Request
872 )
873 {
874 UNREFERENCED_PARAMETER(Queue);
876 KdPrint((__DRIVER_NAME " --> EvtDeviceIoDefault\n"));
878 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
880 KdPrint((__DRIVER_NAME " <-- EvtDeviceIoDefault\n"));
881 }
883 static VOID
884 XenPCI_IoRead(WDFQUEUE Queue, WDFREQUEST Request, size_t Length)
885 {
886 PSHUTDOWN_MSG_ENTRY Entry;
887 size_t Remaining;
888 size_t CopyLen;
889 PCHAR Buffer;
890 size_t BufLen;
891 KIRQL OldIrql;
893 UNREFERENCED_PARAMETER(Queue);
894 UNREFERENCED_PARAMETER(Length);
896 KdPrint((__DRIVER_NAME " --> IoRead\n"));
898 WdfRequestRetrieveOutputBuffer(Request, 1, &Buffer, &BufLen);
900 KeAcquireSpinLock(&ShutdownMsgLock, &OldIrql);
902 Entry = (PSHUTDOWN_MSG_ENTRY)RemoveHeadList(&ShutdownMsgList);
904 if ((PLIST_ENTRY)Entry == &ShutdownMsgList)
905 {
906 KdPrint((__DRIVER_NAME " <-- IoRead (Nothing in queue... xenpci is now broken)\n"));
907 return;
908 }
910 Remaining = strlen(Entry->Buf + Entry->Ptr);
911 CopyLen = min(Remaining, BufLen);
913 memcpy(Buffer, Entry->Buf + Entry->Ptr, CopyLen);
915 if (Entry->Buf[Entry->Ptr] == 0)
916 {
917 KdPrint((__DRIVER_NAME " All done... stopping queue\n"));
918 if (IsListEmpty(&ShutdownMsgList))
919 WdfIoQueueStop(ReadQueue, NULL, NULL);
920 }
921 else
922 {
923 KdPrint((__DRIVER_NAME " More to do...\n"));
924 Entry->Ptr += (ULONG)CopyLen;
925 InsertHeadList(&ShutdownMsgList, &Entry->ListEntry);
926 }
928 KeReleaseSpinLock(&ShutdownMsgLock, OldIrql);
930 WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, CopyLen);
932 KdPrint((__DRIVER_NAME " <-- IoRead\n"));
933 }
936 static NTSTATUS
937 XenPCI_InterruptEnable(WDFINTERRUPT Interrupt, WDFDEVICE AssociatedDevice)
938 {
939 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(AssociatedDevice);
941 UNREFERENCED_PARAMETER(Interrupt);
943 KdPrint((__DRIVER_NAME " --> EvtInterruptEnable\n"));
945 xpdd->shared_info_area->vcpu_info[0].evtchn_upcall_mask = 0;
947 KdPrint((__DRIVER_NAME " <-- EvtInterruptEnable\n"));
949 return STATUS_SUCCESS;
950 }
952 static NTSTATUS
953 XenPCI_InterruptDisable(WDFINTERRUPT Interrupt, WDFDEVICE AssociatedDevice)
954 {
955 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(AssociatedDevice);
957 UNREFERENCED_PARAMETER(Interrupt);
959 //KdPrint((__DRIVER_NAME " --> EvtInterruptDisable\n"));
961 xpdd->shared_info_area->vcpu_info[0].evtchn_upcall_mask = 1;
962 // should we kick off any pending interrupts here?
964 //KdPrint((__DRIVER_NAME " <-- EvtInterruptDisable\n"));
966 return STATUS_SUCCESS;
967 }
969 static NTSTATUS
970 XenPCI_ChildListCreateDevice(
971 WDFCHILDLIST ChildList,
972 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription,
973 PWDFDEVICE_INIT ChildInit)
974 {
975 NTSTATUS status;
976 WDFDEVICE ChildDevice = NULL;
977 PXENPCI_IDENTIFICATION_DESCRIPTION XenIdentificationDesc;
978 DECLARE_UNICODE_STRING_SIZE(buffer, 20);
979 WDF_OBJECT_ATTRIBUTES PdoAttributes;
980 DECLARE_CONST_UNICODE_STRING(DeviceLocation, L"Xen Bus");
981 WDF_QUERY_INTERFACE_CONFIG qiConfig;
982 PXENPCI_XEN_DEVICE_DATA ChildDeviceData = NULL;
983 UNICODE_STRING DeviceType;
984 ANSI_STRING AnsiBuf;
986 UNREFERENCED_PARAMETER(ChildList);
988 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
990 XenIdentificationDesc = CONTAINING_RECORD(IdentificationDescription, XENPCI_IDENTIFICATION_DESCRIPTION, Header);
992 RtlInitAnsiString(&AnsiBuf, XenIdentificationDesc->DeviceType);
993 RtlAnsiStringToUnicodeString(&DeviceType, &AnsiBuf, TRUE);
995 KdPrint((__DRIVER_NAME " Type = %s\n", XenIdentificationDesc->DeviceType));
997 //DeviceInit = WdfPdoInitAllocate(Device);
998 WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_CONTROLLER);
1000 status = RtlUnicodeStringPrintf(&buffer, L"Xen\\%wZ\0", &DeviceType);
1001 status = WdfPdoInitAssignDeviceID(ChildInit, &buffer);
1002 status = WdfPdoInitAddHardwareID(ChildInit, &buffer);
1003 status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
1005 status = RtlUnicodeStringPrintf(&buffer, L"%02d", 0);
1006 status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
1008 status = RtlUnicodeStringPrintf(&buffer, L"%wZ", &DeviceType);
1009 status = WdfPdoInitAddDeviceText(ChildInit, &buffer, &DeviceLocation, 0x409);
1011 WdfPdoInitSetDefaultLocale(ChildInit, 0x409);
1013 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&PdoAttributes, XENPCI_XEN_DEVICE_DATA);
1015 // WDF_PDO_EVENT_CALLBACKS_INIT(&PdoCallbacks);
1016 // PdoCallbacks.EvtDeviceResourceRequirementsQuery = XenPCI_DeviceResourceRequirementsQuery;
1017 // WdfPdoInitSetEventCallbacks(ChildInit, &PdoCallbacks);
1019 status = WdfDeviceCreate(&ChildInit, &PdoAttributes, &ChildDevice);
1020 if (!NT_SUCCESS(status))
1022 KdPrint((__DRIVER_NAME " WdfDeviceCreate status = %08X\n", status));
1025 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFilePaging, TRUE);
1026 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFileHibernation, TRUE);
1027 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFileDump, TRUE);
1029 ChildDeviceData = GetXenDeviceData(ChildDevice);
1030 ChildDeviceData->Magic = XEN_DATA_MAGIC;
1031 ChildDeviceData->AutoEnumerate = AutoEnumerate;
1032 ChildDeviceData->WatchHandler = NULL;
1033 strncpy(ChildDeviceData->Path, XenIdentificationDesc->Path, 128);
1034 ChildDeviceData->DeviceIndex = XenIdentificationDesc->DeviceIndex;
1035 memcpy(&ChildDeviceData->InterruptRaw, &InterruptRaw, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1036 memcpy(&ChildDeviceData->InterruptTranslated, &InterruptTranslated, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1038 ChildDeviceData->XenInterface.InterfaceHeader.Size = sizeof(ChildDeviceData->XenInterface);
1039 ChildDeviceData->XenInterface.InterfaceHeader.Version = 2;
1040 ChildDeviceData->XenInterface.InterfaceHeader.Context = WdfPdoGetParent(ChildDevice);
1041 ChildDeviceData->XenInterface.InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
1042 ChildDeviceData->XenInterface.InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
1044 ChildDeviceData->XenInterface.AllocMMIO = XenPci_AllocMMIO;
1045 ChildDeviceData->XenInterface.FreeMem = XenPCI_FreeMem;
1047 ChildDeviceData->XenInterface.EvtChn_Bind = EvtChn_Bind;
1048 ChildDeviceData->XenInterface.EvtChn_Unbind = EvtChn_Unbind;
1049 ChildDeviceData->XenInterface.EvtChn_Mask = EvtChn_Mask;
1050 ChildDeviceData->XenInterface.EvtChn_Unmask = EvtChn_Unmask;
1051 ChildDeviceData->XenInterface.EvtChn_Notify = EvtChn_Notify;
1052 ChildDeviceData->XenInterface.EvtChn_AllocUnbound = EvtChn_AllocUnbound;
1053 ChildDeviceData->XenInterface.EvtChn_BindDpc = EvtChn_BindDpc;
1055 ChildDeviceData->XenInterface.GntTbl_GetRef = GntTbl_GetRef;
1056 ChildDeviceData->XenInterface.GntTbl_PutRef = GntTbl_PutRef;
1057 ChildDeviceData->XenInterface.GntTbl_GrantAccess = GntTbl_GrantAccess;
1058 ChildDeviceData->XenInterface.GntTbl_EndAccess = GntTbl_EndAccess;
1060 ChildDeviceData->XenInterface.XenBus_Read = XenBus_Read;
1061 ChildDeviceData->XenInterface.XenBus_Write = XenBus_Write;
1062 ChildDeviceData->XenInterface.XenBus_Printf = XenBus_Printf;
1063 ChildDeviceData->XenInterface.XenBus_StartTransaction = XenBus_StartTransaction;
1064 ChildDeviceData->XenInterface.XenBus_EndTransaction = XenBus_EndTransaction;
1065 ChildDeviceData->XenInterface.XenBus_List = XenBus_List;
1066 ChildDeviceData->XenInterface.XenBus_AddWatch = XenBus_AddWatch;
1067 ChildDeviceData->XenInterface.XenBus_RemWatch = XenBus_RemWatch;
1069 WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig, (PINTERFACE)&ChildDeviceData->XenInterface, &GUID_XEN_IFACE, NULL);
1070 status = WdfDeviceAddQueryInterface(ChildDevice, &qiConfig);
1071 if (!NT_SUCCESS(status)) {
1072 return status;
1075 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1077 return status;
1080 struct {
1081 ULONG do_spin;
1082 ULONG nr_spinning;
1083 } typedef SUSPEND_INFO, *PSUSPEND_INFO;
1085 static VOID
1086 XenPci_Suspend(
1087 PRKDPC Dpc,
1088 PVOID Context,
1089 PVOID SystemArgument1,
1090 PVOID SystemArgument2)
1092 WDFDEVICE Device = Context;
1093 // PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
1094 PSUSPEND_INFO suspend_info = SystemArgument1;
1095 ULONG ActiveProcessorCount;
1096 KIRQL OldIrql;
1097 int cancelled;
1099 UNREFERENCED_PARAMETER(Dpc);
1100 UNREFERENCED_PARAMETER(SystemArgument2);
1102 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (CPU = %d)\n", KeGetCurrentProcessorNumber()));
1103 KdPrint((__DRIVER_NAME " Device = %p\n", Device));
1105 if (KeGetCurrentProcessorNumber() != 0)
1107 KdPrint((__DRIVER_NAME " spinning...\n"));
1108 InterlockedIncrement((volatile LONG *)&suspend_info->nr_spinning);
1109 KeMemoryBarrier();
1110 while(suspend_info->do_spin)
1112 /* we should be able to wait more nicely than this... */
1114 KeMemoryBarrier();
1115 InterlockedDecrement((volatile LONG *)&suspend_info->nr_spinning);
1116 KdPrint((__DRIVER_NAME " ...done spinning\n"));
1117 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n", KeGetCurrentProcessorNumber()));
1118 return;
1120 ActiveProcessorCount = (ULONG)KeNumberProcessors;
1122 KdPrint((__DRIVER_NAME " waiting for all other processors to spin\n"));
1123 while (suspend_info->nr_spinning < ActiveProcessorCount - 1)
1125 /* we should be able to wait more nicely than this... */
1127 KdPrint((__DRIVER_NAME " all other processors are spinning\n"));
1129 KeRaiseIrql(HIGH_LEVEL, &OldIrql);
1130 KdPrint((__DRIVER_NAME " calling suspend\n"));
1131 cancelled = HYPERVISOR_shutdown(Device, SHUTDOWN_suspend);
1132 KdPrint((__DRIVER_NAME " back from suspend, cancelled = %d\n", cancelled));
1133 KeLowerIrql(OldIrql);
1135 KdPrint((__DRIVER_NAME " waiting for all other processors to stop spinning\n"));
1136 suspend_info->do_spin = 0;
1137 while (suspend_info->nr_spinning != 0)
1139 /* we should be able to wait more nicely than this... */
1141 KdPrint((__DRIVER_NAME " all other processors have stopped spinning\n"));
1143 // TODO: Enable xenbus
1144 // TODO: Enable our IRQ
1146 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n", KeGetCurrentProcessorNumber()));
1149 static VOID
1150 XenPci_BeginSuspend(WDFDEVICE Device)
1152 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
1153 // KAFFINITY ActiveProcessorMask = 0;
1154 ULONG ActiveProcessorCount;
1155 ULONG i;
1156 PSUSPEND_INFO suspend_info;
1157 PKDPC Dpc;
1158 KIRQL OldIrql;
1160 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1161 KdPrint((__DRIVER_NAME " Device = %p\n", Device));
1163 if (!xpdd->suspending)
1165 xpdd->suspending = 1;
1166 suspend_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(SUSPEND_INFO), XENPCI_POOL_TAG);
1167 suspend_info->do_spin = 1;
1168 RtlZeroMemory(suspend_info, sizeof(SUSPEND_INFO));
1169 // TODO: Disable xenbus
1170 // TODO: Disable our IRQ
1171 //ActiveProcessorCount = KeQueryActiveProcessorCount(&ActiveProcessorMask);
1172 ActiveProcessorCount = (ULONG)KeNumberProcessors;
1173 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1174 for (i = 0; i < ActiveProcessorCount; i++)
1176 Dpc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KDPC), XENPCI_POOL_TAG);
1177 KeInitializeDpc(Dpc, XenPci_Suspend, Device);
1178 KeSetTargetProcessorDpc(Dpc, (CCHAR)i);
1179 KeInsertQueueDpc(Dpc, suspend_info, NULL);
1181 KeLowerIrql(OldIrql);
1183 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1186 static void
1187 XenBus_ShutdownHandler(char *Path, PVOID Data)
1189 WDFDEVICE Device = Data;
1190 char *res;
1191 char *Value;
1192 xenbus_transaction_t xbt;
1193 int retry;
1194 PSHUTDOWN_MSG_ENTRY Entry;
1196 UNREFERENCED_PARAMETER(Path);
1198 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1199 KdPrint((__DRIVER_NAME " Device = %p\n", Device));
1201 res = XenBus_StartTransaction(Device, &xbt);
1202 if (res)
1204 KdPrint(("Error starting transaction\n"));
1205 XenPCI_FreeMem(res);
1206 return;
1209 res = XenBus_Read(Device, XBT_NIL, SHUTDOWN_PATH, &Value);
1210 if (res)
1212 KdPrint(("Error reading shutdown path\n"));
1213 XenPCI_FreeMem(res);
1214 XenBus_EndTransaction(Device, xbt, 1, &retry);
1215 return;
1218 if (Value != NULL && strlen(Value) != 0)
1220 res = XenBus_Write(Device, XBT_NIL, SHUTDOWN_PATH, "");
1221 if (res)
1223 KdPrint(("Error writing shutdown path\n"));
1224 XenPCI_FreeMem(res);
1225 // end trans?
1226 return;
1230 if (Value != NULL)
1232 KdPrint((__DRIVER_NAME " Shutdown Value = %s\n", Value));
1233 KdPrint((__DRIVER_NAME " strlen(...) = %d\n", strlen(Value)));
1235 else
1237 KdPrint((__DRIVER_NAME " Shutdown Value = <null>\n"));
1240 res = XenBus_EndTransaction(Device, xbt, 0, &retry);
1241 if (res)
1243 KdPrint(("Error ending transaction\n"));
1244 XenPCI_FreeMem(res);
1245 return;
1248 if (Value != NULL && strlen(Value) != 0)
1250 if (strcmp(Value, "suspend") == 0)
1252 KdPrint((__DRIVER_NAME " Suspend detected\n"));
1253 XenPci_BeginSuspend(Device);
1255 else
1257 Entry = (PSHUTDOWN_MSG_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(SHUTDOWN_MSG_ENTRY) + strlen(Value) + 1 + 1, XENPCI_POOL_TAG);
1258 Entry->Ptr = 0;
1259 RtlStringCbPrintfA(Entry->Buf, sizeof(SHUTDOWN_MSG_ENTRY) + strlen(Value) + 1 + 1, "%s\n", Value);
1260 InsertTailList(&ShutdownMsgList, &Entry->ListEntry);
1261 WdfIoQueueStart(ReadQueue);
1265 XenPCI_FreeMem(Value);
1267 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1270 static VOID
1271 XenBus_BalloonHandler(char *Path, PVOID Data)
1273 WDFDEVICE Device = Data;
1274 char *value;
1275 xenbus_transaction_t xbt;
1276 int retry;
1278 UNREFERENCED_PARAMETER(Path);
1280 KdPrint((__DRIVER_NAME " --> XenBus_BalloonHandler\n"));
1282 XenBus_StartTransaction(Device, &xbt);
1284 XenBus_Read(Device, XBT_NIL, BALLOON_PATH, &value);
1286 KdPrint((__DRIVER_NAME " Balloon Value = %s\n", value));
1288 // use the memory_op(unsigned int op, void *arg) hypercall to adjust this
1289 // use XENMEM_increase_reservation and XENMEM_decrease_reservation
1291 XenBus_EndTransaction(Device, xbt, 0, &retry);
1293 XenPCI_FreeMem(value);
1295 KdPrint((__DRIVER_NAME " <-- XenBus_BalloonHandler\n"));
1298 static VOID
1299 XenBus_SysrqHandler(char *Path, PVOID Data)
1301 WDFDEVICE Device = Data;
1302 char *Value;
1303 xenbus_transaction_t xbt;
1304 int retry;
1305 char letter;
1306 char *res;
1308 UNREFERENCED_PARAMETER(Path);
1310 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1312 XenBus_StartTransaction(Device, &xbt);
1314 XenBus_Read(Device, XBT_NIL, SYSRQ_PATH, &Value);
1316 KdPrint((__DRIVER_NAME " SysRq Value = %s\n", Value));
1318 if (Value != NULL && strlen(Value) != 0)
1320 letter = *Value;
1321 res = XenBus_Write(Device, XBT_NIL, SYSRQ_PATH, "");
1322 if (res)
1324 KdPrint(("Error writing sysrq path\n"));
1325 XenPCI_FreeMem(res);
1326 XenBus_EndTransaction(Device, xbt, 0, &retry);
1327 return;
1330 else
1332 letter = 0;
1335 XenBus_EndTransaction(Device, xbt, 0, &retry);
1337 if (Value != NULL)
1339 XenPCI_FreeMem(Value);
1342 switch (letter)
1344 case 'B':
1345 KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000001, 0x00000000, 0x00000000, 0x00000000);
1346 break;
1347 default:
1348 KdPrint((" Unhandled sysrq letter %c\n", letter));
1349 break;
1352 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1355 static NTSTATUS
1356 XenPCI_DeviceResourceRequirementsQuery(WDFDEVICE Device, WDFIORESREQLIST IoResourceRequirementsList)
1358 NTSTATUS status;
1359 WDFIORESLIST resourceList;
1360 IO_RESOURCE_DESCRIPTOR descriptor;
1361 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
1363 //KdPrint((__DRIVER_NAME " --> DeviceResourceRequirementsQuery\n"));
1365 status = WdfIoResourceListCreate(IoResourceRequirementsList, WDF_NO_OBJECT_ATTRIBUTES, &resourceList);
1366 if (!NT_SUCCESS(status))
1367 return status;
1369 RtlZeroMemory(&descriptor, sizeof(descriptor));
1371 descriptor.Option = 0;
1372 descriptor.Type = CmResourceTypeMemory;
1373 descriptor.ShareDisposition = CmResourceShareShared; //CmResourceShareDeviceExclusive;
1374 descriptor.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
1375 descriptor.u.Memory.Length = PAGE_SIZE;
1376 descriptor.u.Memory.Alignment = PAGE_SIZE;
1377 descriptor.u.Memory.MinimumAddress.QuadPart
1378 = xpdd->platform_mmio_addr.QuadPart + PAGE_SIZE;
1379 descriptor.u.Memory.MaximumAddress.QuadPart
1380 = xpdd->platform_mmio_addr.QuadPart + xpdd->platform_mmio_len - 1;
1382 //KdPrint((__DRIVER_NAME " MinimumAddress = %08x, MaximumAddress = %08X\n", descriptor.u.Memory.MinimumAddress.LowPart, descriptor.u.Memory.MaximumAddress.LowPart));
1384 status = WdfIoResourceListAppendDescriptor(resourceList, &descriptor);
1385 if (!NT_SUCCESS(status))
1386 return status;
1388 status = WdfIoResourceRequirementsListAppendIoResList(IoResourceRequirementsList, resourceList);
1389 if (!NT_SUCCESS(status))
1390 return status;
1392 //KdPrint((__DRIVER_NAME " <-- DeviceResourceRequirementsQuery\n"));
1394 return status;
1396 #endif