win-pvdrivers

view xenpci/xenpci.c @ 198:c5f21187ef46

Working on suspend/resume. Suspend works (well... you get a checkpoint file), but resume fails.
author James Harper <james.harper@bendigoit.com.au>
date Thu Feb 28 09:06:35 2008 +1100 (2008-02-28)
parents a3bf7c523a4f
children 71b9f608bb80
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 <stdlib.h>
23 #define SYSRQ_PATH "control/sysrq"
24 #define SHUTDOWN_PATH "control/shutdown"
25 #define BALLOON_PATH "memory/target"
27 DRIVER_INITIALIZE DriverEntry;
28 static NTSTATUS
29 XenPCI_AddDevice(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit);
30 static NTSTATUS
31 XenPCI_PrepareHardware(WDFDEVICE hDevice, WDFCMRESLIST Resources, WDFCMRESLIST ResourcesTranslated);
32 static NTSTATUS
33 XenPCI_ReleaseHardware(WDFDEVICE Device, WDFCMRESLIST ResourcesTranslated);
34 static NTSTATUS
35 XenPCI_D0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState);
36 static NTSTATUS
37 XenPCI_D0EntryPostInterruptsEnabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState);
38 static NTSTATUS
39 XenPCI_D0Exit(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState);
40 static NTSTATUS
41 XenPCI_D0ExitPreInterruptsDisabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState);
42 static VOID
43 XenPCI_IoDefault(WDFQUEUE Queue, WDFREQUEST Request);
44 static VOID
45 XenPCI_IoRead(WDFQUEUE Queue, WDFREQUEST Request, size_t Length);
46 static NTSTATUS
47 XenPCI_InterruptEnable(WDFINTERRUPT Interrupt, WDFDEVICE AssociatedDevice);
48 static NTSTATUS
49 XenPCI_InterruptDisable(WDFINTERRUPT Interrupt, WDFDEVICE AssociatedDevice);
50 static NTSTATUS
51 XenPCI_ChildListCreateDevice(WDFCHILDLIST ChildList, PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, PWDFDEVICE_INIT ChildInit);
52 static NTSTATUS
53 XenPCI_DeviceResourceRequirementsQuery(WDFDEVICE Device, WDFIORESREQLIST IoResourceRequirementsList);
54 static NTSTATUS
55 XenPCI_FilterRemoveResourceRequirements(WDFDEVICE Device, WDFIORESREQLIST IoResourceRequirementsList);
56 static NTSTATUS
57 XenPCI_FilterAddResourceRequirements(WDFDEVICE Device, WDFIORESREQLIST RequirementsList);
58 static NTSTATUS
59 XenPCI_RemoveAddedResources(WDFDEVICE Device, WDFCMRESLIST ResourcesRaw, WDFCMRESLIST ResourcesTranslated);
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 static VOID
68 XenPCI_XenBusWatchHandler(char *Path, PVOID Data);
70 #ifdef ALLOC_PRAGMA
71 #pragma alloc_text (INIT, DriverEntry)
72 #pragma alloc_text (PAGE, XenPCI_AddDevice)
73 #endif
75 /* Global (driver-wide) variables */
76 static BOOLEAN AutoEnumerate;
77 static LIST_ENTRY ShutdownMsgList;
79 #pragma warning(disable : 4200) // zero-sized array
81 typedef struct {
82 LIST_ENTRY ListEntry;
83 ULONG Ptr;
84 // ULONG Len;
85 CHAR Buf[0];
86 } SHUTDOWN_MSG_ENTRY, *PSHUTDOWN_MSG_ENTRY;
88 static KSPIN_LOCK ShutdownMsgLock;
90 CM_PARTIAL_RESOURCE_DESCRIPTOR InterruptRaw;
91 CM_PARTIAL_RESOURCE_DESCRIPTOR InterruptTranslated;
93 NTSTATUS
94 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
95 {
96 WDF_DRIVER_CONFIG config;
97 NTSTATUS status;
99 KdPrint((__DRIVER_NAME " --> DriverEntry\n"));
101 InitializeListHead(&ShutdownMsgList);
102 KeInitializeSpinLock(&ShutdownMsgLock);
104 WDF_DRIVER_CONFIG_INIT(&config, XenPCI_AddDevice);
105 status = WdfDriverCreate(
106 DriverObject,
107 RegistryPath,
108 WDF_NO_OBJECT_ATTRIBUTES,
109 &config,
110 WDF_NO_HANDLE);
111 if(!NT_SUCCESS(status))
112 {
113 KdPrint((__DRIVER_NAME " WdfDriverCreate failed with status 0x%08x\n", status));
114 }
116 KdPrint((__DRIVER_NAME " <-- DriverEntry\n"));
118 return status;
119 }
121 /*
122 * Many XEN_IFACE functions allocate memory. Clients must use this to free it.
123 * (Xenbus_Read, XenBus_List, XenBus_AddWatch, XenBus_RemWatch)
124 */
125 static void
126 XenPCI_FreeMem(PVOID Ptr)
127 {
128 ExFreePoolWithTag(Ptr, XENPCI_POOL_TAG);
129 }
131 static NTSTATUS
132 get_hypercall_stubs(WDFDEVICE Device)
133 {
134 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
135 DWORD32 cpuid_output[4];
136 char xensig[13];
137 ULONG i;
138 ULONG pages;
139 ULONG msr;
141 __cpuid(cpuid_output, 0x40000000);
142 *(ULONG*)(xensig + 0) = cpuid_output[1];
143 *(ULONG*)(xensig + 4) = cpuid_output[2];
144 *(ULONG*)(xensig + 8) = cpuid_output[3];
145 xensig[12] = '\0';
146 KdPrint((__DRIVER_NAME " Xen Signature = %s, EAX = 0x%08x\n", xensig, cpuid_output[0]));
148 __cpuid(cpuid_output, 0x40000002);
149 pages = cpuid_output[0];
150 msr = cpuid_output[1];
151 //KdPrint((__DRIVER_NAME " Hypercall area is %u pages.\n", pages));
153 xpdd->hypercall_stubs = ExAllocatePoolWithTag(NonPagedPool, pages * PAGE_SIZE, XENPCI_POOL_TAG);
154 KdPrint((__DRIVER_NAME " Hypercall area at %p\n", xpdd->hypercall_stubs));
156 if (!xpdd->hypercall_stubs)
157 return 1;
158 for (i = 0; i < pages; i++) {
159 ULONGLONG pfn;
160 pfn = (MmGetPhysicalAddress(xpdd->hypercall_stubs + i * PAGE_SIZE).QuadPart >> PAGE_SHIFT);
161 KdPrint((__DRIVER_NAME " pfn = %16lX\n", pfn));
162 __writemsr(msr, (pfn << PAGE_SHIFT) + i);
163 }
164 return STATUS_SUCCESS;
165 }
167 static NTSTATUS
168 free_hypercall_stubs(WDFDEVICE Device)
169 {
170 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
172 ExFreePoolWithTag(xpdd->hypercall_stubs, XENPCI_POOL_TAG);
174 return STATUS_SUCCESS;
175 }
177 /*
178 * Alloc MMIO from the device's MMIO region. There is no corresponding free() fn
179 */
180 PHYSICAL_ADDRESS
181 XenPCI_AllocMMIO(WDFDEVICE Device, ULONG len)
182 {
183 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
185 PHYSICAL_ADDRESS addr;
187 len = (len + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
189 addr = xpdd->platform_mmio_addr;
190 addr.QuadPart += xpdd->platform_mmio_alloc;
191 xpdd->platform_mmio_alloc += len;
193 ASSERT(xpdd->platform_mmio_alloc <= xpdd->platform_mmio_len);
195 return addr;
196 }
198 static int
199 init_xen_info(WDFDEVICE Device)
200 {
201 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
202 struct xen_add_to_physmap xatp;
203 int ret;
204 PHYSICAL_ADDRESS shared_info_area_unmapped;
206 shared_info_area_unmapped = XenPCI_AllocMMIO(Device, PAGE_SIZE);
207 KdPrint((__DRIVER_NAME " shared_info_area_unmapped.QuadPart = %lx\n", shared_info_area_unmapped.QuadPart));
208 xatp.domid = DOMID_SELF;
209 xatp.idx = 0;
210 xatp.space = XENMAPSPACE_shared_info;
211 xatp.gpfn = (xen_pfn_t)(shared_info_area_unmapped.QuadPart >> PAGE_SHIFT);
212 KdPrint((__DRIVER_NAME " gpfn = %d\n", xatp.gpfn));
213 ret = HYPERVISOR_memory_op(Device, XENMEM_add_to_physmap, &xatp);
214 KdPrint((__DRIVER_NAME " hypervisor memory op ret = %d\n", ret));
215 xpdd->shared_info_area = MmMapIoSpace(shared_info_area_unmapped,
216 PAGE_SIZE, MmCached);
217 return 0;
218 }
220 static int
221 set_callback_irq(WDFDEVICE Device, ULONGLONG irq)
222 {
223 struct xen_hvm_param a;
224 int retval;
226 KdPrint((__DRIVER_NAME " --> set_callback_irq\n"));
227 a.domid = DOMID_SELF;
228 a.index = HVM_PARAM_CALLBACK_IRQ;
229 a.value = irq;
230 retval = HYPERVISOR_hvm_op(Device, HVMOP_set_param, &a);
231 KdPrint((__DRIVER_NAME " HYPERVISOR_hvm_op retval = %d\n", retval));
232 KdPrint((__DRIVER_NAME " <-- set_callback_irq\n"));
233 return retval;
234 }
236 WDFQUEUE ReadQueue;
238 static NTSTATUS
239 XenPCI_AddDevice(
240 IN WDFDRIVER Driver,
241 IN PWDFDEVICE_INIT DeviceInit
242 )
243 {
244 NTSTATUS Status;
245 WDF_CHILD_LIST_CONFIG config;
246 WDF_OBJECT_ATTRIBUTES attributes;
247 WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
248 WDF_IO_QUEUE_CONFIG IoQConfig;
249 WDF_INTERRUPT_CONFIG InterruptConfig;
250 PNP_BUS_INFORMATION busInfo;
251 DECLARE_CONST_UNICODE_STRING(DeviceName, L"\\Device\\XenShutdown");
252 DECLARE_CONST_UNICODE_STRING(SymbolicName, L"\\DosDevices\\XenShutdown");
253 WDFDEVICE Device;
254 PXENPCI_DEVICE_DATA xpdd;
255 PWSTR InterfaceList;
257 UNREFERENCED_PARAMETER(Driver);
259 KdPrint((__DRIVER_NAME " --> DeviceAdd\n"));
261 WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);
262 WDF_CHILD_LIST_CONFIG_INIT(&config, sizeof(XENPCI_IDENTIFICATION_DESCRIPTION), XenPCI_ChildListCreateDevice);
263 WdfFdoInitSetDefaultChildListConfig(DeviceInit, &config, WDF_NO_OBJECT_ATTRIBUTES);
265 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
266 pnpPowerCallbacks.EvtDevicePrepareHardware = XenPCI_PrepareHardware;
267 pnpPowerCallbacks.EvtDeviceReleaseHardware = XenPCI_ReleaseHardware;
268 pnpPowerCallbacks.EvtDeviceD0Entry = XenPCI_D0Entry;
269 pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled
270 = XenPCI_D0EntryPostInterruptsEnabled;
271 pnpPowerCallbacks.EvtDeviceD0ExitPreInterruptsDisabled
272 = XenPCI_D0ExitPreInterruptsDisabled;
273 pnpPowerCallbacks.EvtDeviceD0Exit = XenPCI_D0Exit;
274 WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
276 WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);
278 Status = WdfDeviceInitAssignName(DeviceInit, &DeviceName);
279 if (!NT_SUCCESS(Status))
280 {
281 KdPrint((__DRIVER_NAME " WdfDeviceInitAssignName failed 0x%08x\n", Status));
282 return Status;
283 }
285 /*initialize storage for the device context*/
286 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, XENPCI_DEVICE_DATA);
288 /*create a device instance.*/
289 Status = WdfDeviceCreate(&DeviceInit, &attributes, &Device);
290 if(!NT_SUCCESS(Status))
291 {
292 KdPrint((__DRIVER_NAME " WdfDeviceCreate failed with Status 0x%08x\n", Status));
293 return Status;
294 }
295 xpdd = GetDeviceData(Device);
296 xpdd->Device = Device;
298 WdfDeviceSetSpecialFileSupport(Device, WdfSpecialFilePaging, TRUE);
299 WdfDeviceSetSpecialFileSupport(Device, WdfSpecialFileHibernation, TRUE);
300 WdfDeviceSetSpecialFileSupport(Device, WdfSpecialFileDump, TRUE);
302 Status = IoGetDeviceInterfaces(&GUID_XENHIDE_IFACE, NULL, 0, &InterfaceList);
303 if (!NT_SUCCESS(Status) || InterfaceList == NULL || *InterfaceList == 0)
304 {
305 AutoEnumerate = FALSE;
306 KdPrint((__DRIVER_NAME " XenHide not loaded or GPLPV not specified\n", Status));
307 }
308 else
309 {
310 AutoEnumerate = TRUE;
311 KdPrint((__DRIVER_NAME " XenHide loaded and GPLPV specified\n", Status));
312 }
314 #if (NTDDI_VERSION >= NTDDI_WS03SP1)
315 KeInitializeGuardedMutex(&xpdd->WatchHandlerMutex);
316 #endif
317 busInfo.BusTypeGuid = GUID_XENPCI_DEVCLASS;
318 busInfo.LegacyBusType = Internal;
319 busInfo.BusNumber = 0;
321 WdfDeviceSetBusInformationForChildren(Device, &busInfo);
323 WDF_INTERRUPT_CONFIG_INIT(&InterruptConfig, EvtChn_Interrupt, NULL);
324 InterruptConfig.EvtInterruptEnable = XenPCI_InterruptEnable;
325 InterruptConfig.EvtInterruptDisable = XenPCI_InterruptDisable;
326 Status = WdfInterruptCreate(Device, &InterruptConfig, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->XenInterrupt);
327 if (!NT_SUCCESS (Status))
328 {
329 KdPrint((__DRIVER_NAME " WdfInterruptCreate failed 0x%08x\n", Status));
330 return Status;
331 }
333 Status = WdfDeviceCreateDeviceInterface(Device, (LPGUID)&GUID_XEN_IFACE, NULL);
334 if (!NT_SUCCESS(Status))
335 {
336 KdPrint((__DRIVER_NAME " WdfDeviceCreateDeviceInterface failed 0x%08x\n", Status));
337 return Status;
338 }
339 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&IoQConfig, WdfIoQueueDispatchSequential);
340 IoQConfig.EvtIoDefault = XenPCI_IoDefault;
342 Status = WdfIoQueueCreate(Device, &IoQConfig, WDF_NO_OBJECT_ATTRIBUTES, NULL);
343 if (!NT_SUCCESS(Status))
344 {
345 KdPrint((__DRIVER_NAME " WdfIoQueueCreate failed 0x%08x\n", Status));
346 return Status;
347 }
349 WDF_IO_QUEUE_CONFIG_INIT(&IoQConfig, WdfIoQueueDispatchSequential);
350 IoQConfig.EvtIoRead = XenPCI_IoRead;
352 Status = WdfIoQueueCreate(Device, &IoQConfig, WDF_NO_OBJECT_ATTRIBUTES, &ReadQueue);
353 if (!NT_SUCCESS(Status))
354 {
355 KdPrint((__DRIVER_NAME " WdfIoQueueCreate (ReadQueue) failed 0x%08x\n", Status));
356 return Status;
357 }
359 WdfIoQueueStopSynchronously(ReadQueue);
360 WdfDeviceConfigureRequestDispatching(Device, ReadQueue, WdfRequestTypeRead);
362 Status = WdfDeviceCreateSymbolicLink(Device, &SymbolicName);
363 if (!NT_SUCCESS(Status))
364 {
365 KdPrint((__DRIVER_NAME " WdfDeviceCreateSymbolicLink failed 0x%08x\n", Status));
366 return Status;
367 }
369 KdPrint((__DRIVER_NAME " <-- DeviceAdd\n"));
370 return Status;
371 }
373 static NTSTATUS
374 XenPCI_PrepareHardware(
375 IN WDFDEVICE Device,
376 IN WDFCMRESLIST ResourceList,
377 IN WDFCMRESLIST ResourceListTranslated)
378 {
379 NTSTATUS status = STATUS_SUCCESS;
380 PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;
381 ULONG i;
382 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
384 KdPrint((__DRIVER_NAME " --> EvtDevicePrepareHardware\n"));
386 for (i = 0; i < WdfCmResourceListGetCount(ResourceList); i++)
387 {
388 descriptor = WdfCmResourceListGetDescriptor(ResourceList, i);
389 if(!descriptor)
390 continue;
391 switch (descriptor->Type)
392 {
393 case CmResourceTypeInterrupt:
394 xpdd->irqNumber = descriptor->u.Interrupt.Vector;
395 break;
396 }
397 }
399 //KdPrint((__DRIVER_NAME " GSI = %d\n", irqNumber));
401 //KdPrint((__DRIVER_NAME " ResourceListTranslated\n"));
402 for (i = 0; i < WdfCmResourceListGetCount(ResourceListTranslated); i++)
403 {
404 descriptor = WdfCmResourceListGetDescriptor(ResourceListTranslated, i);
405 if(!descriptor)
406 {
407 KdPrint((__DRIVER_NAME " --> EvtDevicePrepareHardware (No descriptor)\n"));
408 return STATUS_DEVICE_CONFIGURATION_ERROR;
409 }
410 switch (descriptor->Type) {
411 case CmResourceTypePort:
412 //KdPrint((__DRIVER_NAME " I/O mapped CSR: (%x) Length: (%d)\n", descriptor->u.Port.Start.LowPart, descriptor->u.Port.Length));
413 break;
414 case CmResourceTypeMemory:
415 KdPrint((__DRIVER_NAME " Memory mapped CSR:(%x:%x) Length:(%d)\n", descriptor->u.Memory.Start.LowPart, descriptor->u.Memory.Start.HighPart, descriptor->u.Memory.Length));
416 xpdd->platform_mmio_addr = descriptor->u.Memory.Start;
417 xpdd->platform_mmio_len = descriptor->u.Memory.Length;
418 xpdd->platform_mmio_alloc = 0;
419 break;
420 case CmResourceTypeInterrupt:
421 //KdPrint((__DRIVER_NAME " Interrupt level: 0x%0x, Vector: 0x%0x\n", descriptor->u.Interrupt.Level, descriptor->u.Interrupt.Vector));
422 memcpy(&InterruptRaw, WdfCmResourceListGetDescriptor(ResourceList, i), sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
423 memcpy(&InterruptTranslated, WdfCmResourceListGetDescriptor(ResourceListTranslated, i), sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
424 break;
425 case CmResourceTypeDevicePrivate:
426 //KdPrint((__DRIVER_NAME " Private Data: 0x%02x 0x%02x 0x%02x\n", descriptor->u.DevicePrivate.Data[0], descriptor->u.DevicePrivate.Data[1], descriptor->u.DevicePrivate.Data[2] ));
427 break;
428 default:
429 //KdPrint((__DRIVER_NAME " Unhandled resource type (0x%x)\n", descriptor->Type));
430 break;
431 }
432 }
434 get_hypercall_stubs(Device);
436 if (init_xen_info(Device))
437 return STATUS_ACCESS_DENIED;
439 GntTbl_Init(Device);
441 EvtChn_Init(Device);
443 set_callback_irq(Device, xpdd->irqNumber);
445 XenBus_Init(Device);
447 //KdPrint((__DRIVER_NAME " upcall_pending = %d\n", shared_info_area->vcpu_info[0].evtchn_upcall_pending));
449 xpdd->shared_info_area->vcpu_info[0].evtchn_upcall_mask = 0;
451 //xen_reboot_init();
453 KdPrint((__DRIVER_NAME " <-- EvtDevicePrepareHardware\n"));
455 return status;
456 }
458 static NTSTATUS
459 XenPCI_ReleaseHardware(WDFDEVICE Device, WDFCMRESLIST ResourcesTranslated)
460 {
461 UNREFERENCED_PARAMETER(ResourcesTranslated);
463 free_hypercall_stubs(Device);
465 return STATUS_SUCCESS;
466 }
468 static NTSTATUS
469 XenPCI_D0Entry(
470 IN WDFDEVICE Device,
471 IN WDF_POWER_DEVICE_STATE PreviousState
472 )
473 {
474 NTSTATUS status = STATUS_SUCCESS;
476 UNREFERENCED_PARAMETER(Device);
477 UNREFERENCED_PARAMETER(PreviousState);
479 KdPrint((__DRIVER_NAME " --> EvtDeviceD0Entry\n"));
481 KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Entry\n"));
483 return status;
484 }
486 static NTSTATUS
487 XenPCI_D0EntryPostInterruptsEnabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState)
488 {
489 NTSTATUS status = STATUS_SUCCESS;
490 //OBJECT_ATTRIBUTES oa;
491 char *response;
492 char *msgTypes;
493 char **Types;
494 int i;
495 char buffer[128];
496 WDFCHILDLIST ChildList;
498 UNREFERENCED_PARAMETER(PreviousState);
500 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
502 XenBus_Start(Device);
504 response = XenBus_AddWatch(Device, XBT_NIL, SYSRQ_PATH, XenBus_SysrqHandler, Device);
505 KdPrint((__DRIVER_NAME " sysrqwatch response = '%s'\n", response));
507 response = XenBus_AddWatch(Device, XBT_NIL, SHUTDOWN_PATH, XenBus_ShutdownHandler, Device);
508 KdPrint((__DRIVER_NAME " shutdown watch response = '%s'\n", response));
510 response = XenBus_AddWatch(Device, XBT_NIL, BALLOON_PATH, XenBus_BalloonHandler, Device);
511 KdPrint((__DRIVER_NAME " shutdown watch response = '%s'\n", response));
513 response = XenBus_AddWatch(Device, XBT_NIL, "device", XenPCI_XenBusWatchHandler, Device);
514 KdPrint((__DRIVER_NAME " device watch response = '%s'\n", response));
516 ChildList = WdfFdoGetDefaultChildList(Device);
518 WdfChildListBeginScan(ChildList);
519 msgTypes = XenBus_List(Device, XBT_NIL, "device", &Types);
520 if (!msgTypes) {
521 for (i = 0; Types[i]; i++)
522 {
523 RtlStringCbPrintfA(buffer, ARRAY_SIZE(buffer), "device/%s", Types[i]);
524 XenPCI_XenBusWatchHandler(buffer, Device);
525 ExFreePoolWithTag(Types[i], XENPCI_POOL_TAG);
526 }
527 }
528 WdfChildListEndScan(ChildList);
530 XenPCI_FreeMem(Types);
532 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
534 return status;
535 }
537 static NTSTATUS
538 XenPCI_D0ExitPreInterruptsDisabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState)
539 {
540 NTSTATUS status = STATUS_SUCCESS;
542 UNREFERENCED_PARAMETER(TargetState);
544 KdPrint((__DRIVER_NAME " --> D0ExitPreInterruptsDisabled\n"));
546 XenBus_Stop(Device);
548 KdPrint((__DRIVER_NAME " <-- D0ExitPreInterruptsDisabled\n"));
550 return status;
551 }
553 static NTSTATUS
554 XenPCI_D0Exit(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState)
555 {
556 NTSTATUS status = STATUS_SUCCESS;
558 UNREFERENCED_PARAMETER(Device);
559 UNREFERENCED_PARAMETER(TargetState);
561 KdPrint((__DRIVER_NAME " --> DeviceD0Exit\n"));
563 XenBus_Close(Device);
565 KdPrint((__DRIVER_NAME " <-- DeviceD0Exit\n"));
567 return status;
568 }
570 static VOID
571 XenPCI_IoDefault(
572 IN WDFQUEUE Queue,
573 IN WDFREQUEST Request
574 )
575 {
576 UNREFERENCED_PARAMETER(Queue);
578 KdPrint((__DRIVER_NAME " --> EvtDeviceIoDefault\n"));
580 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
582 KdPrint((__DRIVER_NAME " <-- EvtDeviceIoDefault\n"));
583 }
586 static VOID
587 XenPCI_IoRead(WDFQUEUE Queue, WDFREQUEST Request, size_t Length)
588 {
589 PSHUTDOWN_MSG_ENTRY Entry;
590 size_t Remaining;
591 size_t CopyLen;
592 PCHAR Buffer;
593 size_t BufLen;
594 KIRQL OldIrql;
596 UNREFERENCED_PARAMETER(Queue);
597 UNREFERENCED_PARAMETER(Length);
599 KdPrint((__DRIVER_NAME " --> IoRead\n"));
601 WdfRequestRetrieveOutputBuffer(Request, 1, &Buffer, &BufLen);
603 KeAcquireSpinLock(&ShutdownMsgLock, &OldIrql);
605 Entry = (PSHUTDOWN_MSG_ENTRY)RemoveHeadList(&ShutdownMsgList);
607 if ((PLIST_ENTRY)Entry == &ShutdownMsgList)
608 {
609 KdPrint((__DRIVER_NAME " <-- IoRead (Nothing in queue... xenpci is now broken)\n"));
610 return;
611 }
613 Remaining = strlen(Entry->Buf + Entry->Ptr);
614 CopyLen = min(Remaining, BufLen);
616 memcpy(Buffer, Entry->Buf + Entry->Ptr, CopyLen);
618 if (Entry->Buf[Entry->Ptr] == 0)
619 {
620 KdPrint((__DRIVER_NAME " All done... stopping queue\n"));
621 if (IsListEmpty(&ShutdownMsgList))
622 WdfIoQueueStop(ReadQueue, NULL, NULL);
623 }
624 else
625 {
626 KdPrint((__DRIVER_NAME " More to do...\n"));
627 Entry->Ptr += (ULONG)CopyLen;
628 InsertHeadList(&ShutdownMsgList, &Entry->ListEntry);
629 }
631 KeReleaseSpinLock(&ShutdownMsgLock, OldIrql);
633 WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, CopyLen);
635 KdPrint((__DRIVER_NAME " <-- IoRead\n"));
636 }
639 static NTSTATUS
640 XenPCI_InterruptEnable(WDFINTERRUPT Interrupt, WDFDEVICE AssociatedDevice)
641 {
642 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(AssociatedDevice);
644 UNREFERENCED_PARAMETER(Interrupt);
646 KdPrint((__DRIVER_NAME " --> EvtInterruptEnable\n"));
648 xpdd->shared_info_area->vcpu_info[0].evtchn_upcall_mask = 0;
650 KdPrint((__DRIVER_NAME " <-- EvtInterruptEnable\n"));
652 return STATUS_SUCCESS;
653 }
655 static NTSTATUS
656 XenPCI_InterruptDisable(WDFINTERRUPT Interrupt, WDFDEVICE AssociatedDevice)
657 {
658 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(AssociatedDevice);
660 UNREFERENCED_PARAMETER(Interrupt);
662 //KdPrint((__DRIVER_NAME " --> EvtInterruptDisable\n"));
664 xpdd->shared_info_area->vcpu_info[0].evtchn_upcall_mask = 1;
665 // should we kick off any pending interrupts here?
667 //KdPrint((__DRIVER_NAME " <-- EvtInterruptDisable\n"));
669 return STATUS_SUCCESS;
670 }
672 static NTSTATUS
673 XenPCI_ChildListCreateDevice(
674 WDFCHILDLIST ChildList,
675 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription,
676 PWDFDEVICE_INIT ChildInit)
677 {
678 NTSTATUS status;
679 WDFDEVICE ChildDevice = NULL;
680 PXENPCI_IDENTIFICATION_DESCRIPTION XenIdentificationDesc;
681 DECLARE_UNICODE_STRING_SIZE(buffer, 20);
682 WDF_OBJECT_ATTRIBUTES PdoAttributes;
683 DECLARE_CONST_UNICODE_STRING(DeviceLocation, L"Xen Bus");
684 WDF_QUERY_INTERFACE_CONFIG qiConfig;
685 PXENPCI_XEN_DEVICE_DATA ChildDeviceData = NULL;
686 UNICODE_STRING DeviceType;
687 ANSI_STRING AnsiBuf;
689 UNREFERENCED_PARAMETER(ChildList);
691 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
693 XenIdentificationDesc = CONTAINING_RECORD(IdentificationDescription, XENPCI_IDENTIFICATION_DESCRIPTION, Header);
695 RtlInitAnsiString(&AnsiBuf, XenIdentificationDesc->DeviceType);
696 RtlAnsiStringToUnicodeString(&DeviceType, &AnsiBuf, TRUE);
698 KdPrint((__DRIVER_NAME " Type = %s\n", XenIdentificationDesc->DeviceType));
700 //DeviceInit = WdfPdoInitAllocate(Device);
701 WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_CONTROLLER);
703 status = RtlUnicodeStringPrintf(&buffer, L"Xen\\%wZ\0", &DeviceType);
704 status = WdfPdoInitAssignDeviceID(ChildInit, &buffer);
705 status = WdfPdoInitAddHardwareID(ChildInit, &buffer);
706 status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
708 status = RtlUnicodeStringPrintf(&buffer, L"%02d", 0);
709 status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
711 status = RtlUnicodeStringPrintf(&buffer, L"%wZ", &DeviceType);
712 status = WdfPdoInitAddDeviceText(ChildInit, &buffer, &DeviceLocation, 0x409);
714 WdfPdoInitSetDefaultLocale(ChildInit, 0x409);
716 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&PdoAttributes, XENPCI_XEN_DEVICE_DATA);
718 // WDF_PDO_EVENT_CALLBACKS_INIT(&PdoCallbacks);
719 // PdoCallbacks.EvtDeviceResourceRequirementsQuery = XenPCI_DeviceResourceRequirementsQuery;
720 // WdfPdoInitSetEventCallbacks(ChildInit, &PdoCallbacks);
722 status = WdfDeviceCreate(&ChildInit, &PdoAttributes, &ChildDevice);
723 if (!NT_SUCCESS(status))
724 {
725 KdPrint((__DRIVER_NAME " WdfDeviceCreate status = %08X\n", status));
726 }
728 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFilePaging, TRUE);
729 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFileHibernation, TRUE);
730 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFileDump, TRUE);
732 ChildDeviceData = GetXenDeviceData(ChildDevice);
733 ChildDeviceData->Magic = XEN_DATA_MAGIC;
734 ChildDeviceData->AutoEnumerate = AutoEnumerate;
735 ChildDeviceData->WatchHandler = NULL;
736 strncpy(ChildDeviceData->Path, XenIdentificationDesc->Path, 128);
737 ChildDeviceData->DeviceIndex = XenIdentificationDesc->DeviceIndex;
738 memcpy(&ChildDeviceData->InterruptRaw, &InterruptRaw, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
739 memcpy(&ChildDeviceData->InterruptTranslated, &InterruptTranslated, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
741 ChildDeviceData->XenInterface.InterfaceHeader.Size = sizeof(ChildDeviceData->XenInterface);
742 ChildDeviceData->XenInterface.InterfaceHeader.Version = 1;
743 ChildDeviceData->XenInterface.InterfaceHeader.Context = WdfPdoGetParent(ChildDevice);
744 ChildDeviceData->XenInterface.InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
745 ChildDeviceData->XenInterface.InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
747 ChildDeviceData->XenInterface.AllocMMIO = XenPCI_AllocMMIO;
748 ChildDeviceData->XenInterface.FreeMem = XenPCI_FreeMem;
750 ChildDeviceData->XenInterface.EvtChn_Bind = EvtChn_Bind;
751 ChildDeviceData->XenInterface.EvtChn_Unbind = EvtChn_Unbind;
752 ChildDeviceData->XenInterface.EvtChn_Mask = EvtChn_Mask;
753 ChildDeviceData->XenInterface.EvtChn_Unmask = EvtChn_Unmask;
754 ChildDeviceData->XenInterface.EvtChn_Notify = EvtChn_Notify;
755 ChildDeviceData->XenInterface.EvtChn_AllocUnbound = EvtChn_AllocUnbound;
756 ChildDeviceData->XenInterface.EvtChn_BindDpc = EvtChn_BindDpc;
758 ChildDeviceData->XenInterface.GntTbl_GrantAccess = GntTbl_GrantAccess;
759 ChildDeviceData->XenInterface.GntTbl_EndAccess = GntTbl_EndAccess;
761 ChildDeviceData->XenInterface.XenBus_Read = XenBus_Read;
762 ChildDeviceData->XenInterface.XenBus_Write = XenBus_Write;
763 ChildDeviceData->XenInterface.XenBus_Printf = XenBus_Printf;
764 ChildDeviceData->XenInterface.XenBus_StartTransaction = XenBus_StartTransaction;
765 ChildDeviceData->XenInterface.XenBus_EndTransaction = XenBus_EndTransaction;
766 ChildDeviceData->XenInterface.XenBus_List = XenBus_List;
767 ChildDeviceData->XenInterface.XenBus_AddWatch = XenBus_AddWatch;
768 ChildDeviceData->XenInterface.XenBus_RemWatch = XenBus_RemWatch;
770 WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig, (PINTERFACE)&ChildDeviceData->XenInterface, &GUID_XEN_IFACE, NULL);
771 status = WdfDeviceAddQueryInterface(ChildDevice, &qiConfig);
772 if (!NT_SUCCESS(status)) {
773 return status;
774 }
776 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
778 return status;
779 }
781 VOID
782 XenPCI_XenBusWatchHandler(char *Path, PVOID Data)
783 {
784 NTSTATUS status;
785 char **Bits;
786 int Count;
787 WDFDEVICE Device = Data;
788 WDFCHILDLIST ChildList;
789 WDF_CHILD_LIST_ITERATOR ChildIterator;
790 WDFDEVICE ChildDevice;
791 PXENPCI_XEN_DEVICE_DATA ChildDeviceData;
792 XENPCI_IDENTIFICATION_DESCRIPTION description;
793 #if (NTDDI_VERSION >= NTDDI_WS03SP1)
794 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
795 #endif
797 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
799 #if (NTDDI_VERSION >= NTDDI_WS03SP1)
800 KeAcquireGuardedMutex(&xpdd->WatchHandlerMutex);
801 #endif
803 KdPrint((__DRIVER_NAME " Path = %s\n", Path));
805 ChildList = WdfFdoGetDefaultChildList(Device);
807 Bits = SplitString(Path, '/', 3, &Count);
809 KdPrint((__DRIVER_NAME " Count = %s\n", Count));
811 ChildDeviceData = NULL;
812 WDF_CHILD_LIST_ITERATOR_INIT(&ChildIterator, WdfRetrievePresentChildren);
813 WdfChildListBeginIteration(ChildList, &ChildIterator);
814 while (NT_SUCCESS(WdfChildListRetrieveNextDevice(ChildList, &ChildIterator, &ChildDevice, NULL)))
815 {
816 ChildDeviceData = GetXenDeviceData(ChildDevice);
817 if (!ChildDeviceData)
818 {
819 KdPrint((" No child device data, should never happen\n"));
820 continue;
821 }
822 if (strncmp(ChildDeviceData->Path, Path, strlen(ChildDeviceData->Path)) == 0 && Path[strlen(ChildDeviceData->Path)] == '/')
823 {
824 if (Count == 3 && ChildDeviceData->WatchHandler != NULL)
825 ChildDeviceData->WatchHandler(Path, ChildDeviceData->WatchContext);
826 break;
827 }
828 ChildDeviceData = NULL;
829 }
830 WdfChildListEndIteration(ChildList, &ChildIterator);
831 if (Count >= 2 && ChildDeviceData == NULL)
832 {
833 RtlZeroMemory(&description, sizeof(description));
834 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&description.Header, sizeof(description));
835 strncpy(description.Path, Path, 128);
836 strncpy(description.DeviceType, Bits[1], 128);
837 KdPrint((__DRIVER_NAME " Adding child for %s\n", description.DeviceType));
838 status = WdfChildListAddOrUpdateChildDescriptionAsPresent(ChildList, &description.Header, NULL);
839 }
840 FreeSplitString(Bits, Count);
842 #if (NTDDI_VERSION >= NTDDI_WS03SP1)
843 KeReleaseGuardedMutex(&xpdd->WatchHandlerMutex);
844 #endif
846 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
847 }
849 struct {
850 ULONG do_spin;
851 ULONG nr_spinning;
852 } typedef SUSPEND_INFO, *PSUSPEND_INFO;
854 static VOID
855 XenPci_Suspend(
856 PRKDPC Dpc,
857 PVOID Context,
858 PVOID SystemArgument1,
859 PVOID SystemArgument2)
860 {
861 WDFDEVICE Device = Context;
862 // PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
863 PSUSPEND_INFO suspend_info = SystemArgument1;
864 ULONG ActiveProcessorCount;
865 KIRQL OldIrql;
866 int cancelled;
868 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (CPU = %d)\n", KeGetCurrentProcessorNumber()));
869 KdPrint((__DRIVER_NAME " Device = %p\n", Device));
871 if (KeGetCurrentProcessorNumber() != 0)
872 {
873 KdPrint((__DRIVER_NAME " spinning...\n"));
874 InterlockedIncrement((volatile LONG *)&suspend_info->nr_spinning);
875 KeMemoryBarrier();
876 while(suspend_info->do_spin)
877 {
878 /* we should be able to wait more nicely than this... */
879 }
880 KeMemoryBarrier();
881 InterlockedDecrement((volatile LONG *)&suspend_info->nr_spinning);
882 KdPrint((__DRIVER_NAME " ...done spinning\n"));
883 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n", KeGetCurrentProcessorNumber()));
884 return;
885 }
886 ActiveProcessorCount = KeNumberProcessors;
888 KdPrint((__DRIVER_NAME " waiting for all other processors to spin\n"));
889 while (suspend_info->nr_spinning < ActiveProcessorCount - 1)
890 {
891 /* we should be able to wait more nicely than this... */
892 }
893 KdPrint((__DRIVER_NAME " all other processors are spinning\n"));
895 KeRaiseIrql(HIGH_LEVEL, &OldIrql);
896 KdPrint((__DRIVER_NAME " calling suspend\n"));
897 cancelled = HYPERVISOR_shutdown(Device, SHUTDOWN_suspend);
898 KdPrint((__DRIVER_NAME " back from suspend, cancelled = %d\n", cancelled));
899 KeLowerIrql(OldIrql);
901 KdPrint((__DRIVER_NAME " waiting for all other processors to stop spinning\n"));
902 suspend_info->do_spin = 0;
903 while (suspend_info->nr_spinning != 0)
904 {
905 /* we should be able to wait more nicely than this... */
906 }
907 KdPrint((__DRIVER_NAME " all other processors have stopped spinning\n"));
909 // TODO: Enable xenbus
910 // TODO: Enable our IRQ
912 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n", KeGetCurrentProcessorNumber()));
913 }
915 static VOID
916 XenPci_BeginSuspend(WDFDEVICE Device)
917 {
918 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
919 // KAFFINITY ActiveProcessorMask = 0;
920 ULONG ActiveProcessorCount;
921 ULONG i;
922 PSUSPEND_INFO suspend_info;
923 PKDPC Dpc;
924 KIRQL OldIrql;
926 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
927 KdPrint((__DRIVER_NAME " Device = %p\n", Device));
929 if (!xpdd->suspending)
930 {
931 xpdd->suspending = 1;
932 suspend_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(SUSPEND_INFO), XENPCI_POOL_TAG);
933 suspend_info->do_spin = 1;
934 RtlZeroMemory(suspend_info, sizeof(SUSPEND_INFO));
935 // TODO: Disable xenbus
936 // TODO: Disable our IRQ
937 //ActiveProcessorCount = KeQueryActiveProcessorCount(&ActiveProcessorMask);
938 ActiveProcessorCount = KeNumberProcessors;
939 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
940 for (i = 0; i < ActiveProcessorCount; i++)
941 {
942 Dpc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KDPC), XENPCI_POOL_TAG);
943 KeInitializeDpc(Dpc, XenPci_Suspend, Device);
944 KeSetTargetProcessorDpc(Dpc, (CCHAR)i);
945 KeInsertQueueDpc(Dpc, suspend_info, NULL);
946 }
947 KeLowerIrql(OldIrql);
948 }
949 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
950 }
952 static void
953 XenBus_ShutdownHandler(char *Path, PVOID Data)
954 {
955 WDFDEVICE Device = Data;
956 char *res;
957 char *Value;
958 xenbus_transaction_t xbt;
959 int retry;
960 PSHUTDOWN_MSG_ENTRY Entry;
962 UNREFERENCED_PARAMETER(Path);
964 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
965 KdPrint((__DRIVER_NAME " Device = %p\n", Device));
967 res = XenBus_StartTransaction(Device, &xbt);
968 if (res)
969 {
970 KdPrint(("Error starting transaction\n"));
971 XenPCI_FreeMem(res);
972 return;
973 }
975 res = XenBus_Read(Device, XBT_NIL, SHUTDOWN_PATH, &Value);
976 if (res)
977 {
978 KdPrint(("Error reading shutdown path\n"));
979 XenPCI_FreeMem(res);
980 XenBus_EndTransaction(Device, xbt, 1, &retry);
981 return;
982 }
984 if (Value != NULL && strlen(Value) != 0)
985 {
986 res = XenBus_Write(Device, XBT_NIL, SHUTDOWN_PATH, "");
987 if (res)
988 {
989 KdPrint(("Error writing shutdown path\n"));
990 XenPCI_FreeMem(res);
991 // end trans?
992 return;
993 }
994 }
996 if (Value != NULL)
997 {
998 KdPrint((__DRIVER_NAME " Shutdown Value = %s\n", Value));
999 KdPrint((__DRIVER_NAME " strlen(...) = %d\n", strlen(Value)));
1001 else
1003 KdPrint((__DRIVER_NAME " Shutdown Value = <null>\n"));
1006 res = XenBus_EndTransaction(Device, xbt, 0, &retry);
1007 if (res)
1009 KdPrint(("Error ending transaction\n"));
1010 XenPCI_FreeMem(res);
1011 return;
1014 if (Value != NULL && strlen(Value) != 0)
1016 if (strcmp(Value, "suspend") == 0)
1018 KdPrint((__DRIVER_NAME " Suspend detected\n"));
1019 XenPci_BeginSuspend(Device);
1021 else
1023 Entry = (PSHUTDOWN_MSG_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(SHUTDOWN_MSG_ENTRY) + strlen(Value) + 1 + 1, XENPCI_POOL_TAG);
1024 Entry->Ptr = 0;
1025 RtlStringCbPrintfA(Entry->Buf, sizeof(SHUTDOWN_MSG_ENTRY) + strlen(Value) + 1 + 1, "%s\n", Value);
1026 InsertTailList(&ShutdownMsgList, &Entry->ListEntry);
1027 WdfIoQueueStart(ReadQueue);
1031 XenPCI_FreeMem(Value);
1033 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1036 static VOID
1037 XenBus_BalloonHandler(char *Path, PVOID Data)
1039 WDFDEVICE Device = Data;
1040 char *value;
1041 xenbus_transaction_t xbt;
1042 int retry;
1044 UNREFERENCED_PARAMETER(Path);
1046 KdPrint((__DRIVER_NAME " --> XenBus_BalloonHandler\n"));
1048 XenBus_StartTransaction(Device, &xbt);
1050 XenBus_Read(Device, XBT_NIL, BALLOON_PATH, &value);
1052 KdPrint((__DRIVER_NAME " Balloon Value = %s\n", value));
1054 // use the memory_op(unsigned int op, void *arg) hypercall to adjust this
1055 // use XENMEM_increase_reservation and XENMEM_decrease_reservation
1057 XenBus_EndTransaction(Device, xbt, 0, &retry);
1059 XenPCI_FreeMem(value);
1061 KdPrint((__DRIVER_NAME " <-- XenBus_BalloonHandler\n"));
1064 static VOID
1065 XenBus_SysrqHandler(char *Path, PVOID Data)
1067 WDFDEVICE Device = Data;
1068 char *Value;
1069 xenbus_transaction_t xbt;
1070 int retry;
1071 char letter;
1072 char *res;
1074 UNREFERENCED_PARAMETER(Path);
1076 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1078 XenBus_StartTransaction(Device, &xbt);
1080 XenBus_Read(Device, XBT_NIL, SYSRQ_PATH, &Value);
1082 KdPrint((__DRIVER_NAME " SysRq Value = %s\n", Value));
1084 if (Value != NULL && strlen(Value) != 0)
1086 letter = *Value;
1087 res = XenBus_Write(Device, XBT_NIL, SYSRQ_PATH, "");
1088 if (res)
1090 KdPrint(("Error writing sysrq path\n"));
1091 XenPCI_FreeMem(res);
1092 XenBus_EndTransaction(Device, xbt, 0, &retry);
1093 return;
1096 else
1098 letter = 0;
1101 XenBus_EndTransaction(Device, xbt, 0, &retry);
1103 if (Value != NULL)
1105 XenPCI_FreeMem(Value);
1108 switch (letter)
1110 case 'B':
1111 KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000001, 0x00000000, 0x00000000, 0x00000000);
1112 break;
1113 default:
1114 KdPrint((" Unhandled sysrq letter %c\n", letter));
1115 break;
1118 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1121 static NTSTATUS
1122 XenPCI_DeviceResourceRequirementsQuery(WDFDEVICE Device, WDFIORESREQLIST IoResourceRequirementsList)
1124 NTSTATUS status;
1125 WDFIORESLIST resourceList;
1126 IO_RESOURCE_DESCRIPTOR descriptor;
1127 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
1129 //KdPrint((__DRIVER_NAME " --> DeviceResourceRequirementsQuery\n"));
1131 status = WdfIoResourceListCreate(IoResourceRequirementsList, WDF_NO_OBJECT_ATTRIBUTES, &resourceList);
1132 if (!NT_SUCCESS(status))
1133 return status;
1135 RtlZeroMemory(&descriptor, sizeof(descriptor));
1137 descriptor.Option = 0;
1138 descriptor.Type = CmResourceTypeMemory;
1139 descriptor.ShareDisposition = CmResourceShareShared; //CmResourceShareDeviceExclusive;
1140 descriptor.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
1141 descriptor.u.Memory.Length = PAGE_SIZE;
1142 descriptor.u.Memory.Alignment = PAGE_SIZE;
1143 descriptor.u.Memory.MinimumAddress.QuadPart
1144 = xpdd->platform_mmio_addr.QuadPart + PAGE_SIZE;
1145 descriptor.u.Memory.MaximumAddress.QuadPart
1146 = xpdd->platform_mmio_addr.QuadPart + xpdd->platform_mmio_len - 1;
1148 //KdPrint((__DRIVER_NAME " MinimumAddress = %08x, MaximumAddress = %08X\n", descriptor.u.Memory.MinimumAddress.LowPart, descriptor.u.Memory.MaximumAddress.LowPart));
1150 status = WdfIoResourceListAppendDescriptor(resourceList, &descriptor);
1151 if (!NT_SUCCESS(status))
1152 return status;
1154 status = WdfIoResourceRequirementsListAppendIoResList(IoResourceRequirementsList, resourceList);
1155 if (!NT_SUCCESS(status))
1156 return status;
1158 //KdPrint((__DRIVER_NAME " <-- DeviceResourceRequirementsQuery\n"));
1160 return status;