win-pvdrivers

view xenpci/xenpci_pdo.c @ 900:938de6b8623d

fix memory leak on suspend/resume
author James Harper <james.harper@bendigoit.com.au>
date Thu Mar 31 20:20:36 2011 +1100 (2011-03-31)
parents e315b8490131
children 1e795031439a
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>
22 #include <io/ring.h>
24 #pragma warning(disable : 4200) // zero-sized array
25 #pragma warning(disable: 4127) // conditional expression is constant
27 /* Not really necessary but keeps PREfast happy */
28 static EVT_WDF_INTERRUPT_SYNCHRONIZE XenPci_EvtChn_Sync_Routine;
29 static EVT_WDF_DEVICE_D0_ENTRY XenPciPdo_EvtDeviceD0Entry;
30 static EVT_WDF_DEVICE_D0_EXIT XenPciPdo_EvtDeviceD0Exit;
31 static EVT_WDF_DEVICE_PREPARE_HARDWARE XenPciPdo_EvtDevicePrepareHardware;
32 static EVT_WDF_DEVICE_RELEASE_HARDWARE XenPciPdo_EvtDeviceReleaseHardware;
33 static EVT_WDF_DEVICE_USAGE_NOTIFICATION XenPciPdo_EvtDeviceUsageNotification;
34 static EVT_WDFDEVICE_WDM_IRP_PREPROCESS XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE;
35 static EVT_WDF_DEVICE_RESOURCE_REQUIREMENTS_QUERY XenPciPdo_EvtDeviceResourceRequirementsQuery;
36 static EVT_WDF_DEVICE_PNP_STATE_CHANGE_NOTIFICATION XenPci_EvtDevicePnpStateChange;
38 /*
39 Called at PASSIVE_LEVEL(?)
40 Called during restore
41 */
42 static ULONG
43 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
44 {
45 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
46 char path[128];
47 char *value;
48 char *err;
49 ULONG backend_state;
51 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
52 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
53 if (err)
54 {
55 XenPci_FreeMem(err);
56 return XenbusStateUnknown;
57 }
58 else
59 {
60 backend_state = atoi(value);
61 XenPci_FreeMem(value);
62 return backend_state;
63 }
64 }
66 static NTSTATUS
67 XenPciPdo_ReconfigureCompletionRoutine(
68 PDEVICE_OBJECT device_object,
69 PIRP irp,
70 PVOID context)
71 {
72 UNREFERENCED_PARAMETER(device_object);
74 if (irp->PendingReturned)
75 {
76 KeSetEvent ((PKEVENT)context, IO_NO_INCREMENT, FALSE);
77 }
78 return STATUS_MORE_PROCESSING_REQUIRED;
79 }
81 static VOID
82 XenPci_UpdateBackendState(PVOID context)
83 {
84 WDFDEVICE device = context;
85 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
86 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
87 ULONG new_backend_state;
89 FUNCTION_ENTER();
91 ExAcquireFastMutex(&xppdd->backend_state_mutex);
93 new_backend_state = XenPci_ReadBackendState(xppdd);
94 if (new_backend_state == XenbusStateUnknown)
95 {
96 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
97 {
98 ExReleaseFastMutex(&xppdd->backend_state_mutex);
99 return;
100 }
101 KdPrint(("Failed to read path, assuming closed\n"));
102 new_backend_state = XenbusStateClosed;
103 }
105 if (xppdd->backend_state == new_backend_state)
106 {
107 KdPrint((__DRIVER_NAME " state unchanged\n"));
108 ExReleaseFastMutex(&xppdd->backend_state_mutex);
109 return;
110 }
112 xppdd->backend_state = new_backend_state;
114 switch (xppdd->backend_state)
115 {
116 case XenbusStateUnknown:
117 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
118 break;
120 case XenbusStateInitialising:
121 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
122 break;
124 case XenbusStateInitWait:
125 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
126 break;
128 case XenbusStateInitialised:
129 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
130 break;
132 case XenbusStateConnected:
133 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
134 break;
136 case XenbusStateClosing:
137 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
138 if (xppdd->frontend_state != XenbusStateClosing)
139 {
140 xppdd->backend_initiated_remove = TRUE;
141 KdPrint((__DRIVER_NAME " Requesting eject\n"));
142 WdfPdoRequestEject(device);
143 }
144 break;
146 case XenbusStateClosed:
147 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
148 break;
150 default:
151 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", xppdd->backend_state));
152 break;
153 }
155 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
157 ExReleaseFastMutex(&xppdd->backend_state_mutex);
158 FUNCTION_EXIT();
160 return;
161 }
163 static VOID
164 XenPci_BackendStateHandler(char *path, PVOID context)
165 {
166 UNREFERENCED_PARAMETER(path);
168 /* check that path == device/id/state */
169 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
171 XenPci_UpdateBackendState(context);
172 }
174 static NTSTATUS
175 XenPci_GetBackendAndAddWatch(WDFDEVICE device)
176 {
177 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
178 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
179 char path[128];
180 PCHAR res;
181 PCHAR value;
183 FUNCTION_ENTER();
184 /* Get backend path */
185 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
186 "%s/backend", xppdd->path);
187 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
188 if (res)
189 {
190 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
191 XenPci_FreeMem(res);
192 return STATUS_UNSUCCESSFUL;
193 }
194 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
195 XenPci_FreeMem(value);
197 /* Add watch on backend state */
198 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
199 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
201 FUNCTION_EXIT();
202 return STATUS_SUCCESS;
203 }
205 static NTSTATUS
206 XenConfig_InitConfigPage(WDFDEVICE device)
207 {
208 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
209 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
210 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
211 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
212 PUCHAR ptr;
213 PDEVICE_OBJECT curr, prev;
214 PDRIVER_OBJECT fdo_driver_object;
215 PUCHAR fdo_driver_extension;
217 FUNCTION_ENTER();
219 ptr = MmGetMdlVirtualAddress(xppdd->config_page_mdl);
220 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(device));
221 //curr = WdfDeviceWdmGetAttachedDevice(device);
222 while (curr != NULL)
223 {
224 fdo_driver_object = curr->DriverObject;
225 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
226 if (fdo_driver_object)
227 {
228 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
229 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
230 if (fdo_driver_extension)
231 {
232 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
233 ObDereferenceObject(curr);
234 break;
235 }
236 }
237 prev = curr;
238 curr = IoGetLowerDeviceObject(curr);
239 ObDereferenceObject(prev);
240 }
242 FUNCTION_EXIT();
244 return STATUS_SUCCESS;
245 }
247 static NTSTATUS
248 XenPci_EvtChn_Bind(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
249 {
250 WDFDEVICE device = context;
251 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
252 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
254 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext, EVT_ACTION_FLAGS_DEFAULT);
255 }
257 static NTSTATUS
258 XenPci_EvtChn_BindDpc(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
259 {
260 WDFDEVICE device = context;
261 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
262 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
264 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext, EVT_ACTION_FLAGS_DEFAULT);
265 }
267 static NTSTATUS
268 XenPci_EvtChn_Unbind(PVOID context, evtchn_port_t Port)
269 {
270 WDFDEVICE device = context;
271 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
272 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
274 return EvtChn_Unbind(xpdd, Port);
275 }
277 static NTSTATUS
278 XenPci_EvtChn_Mask(PVOID context, evtchn_port_t Port)
279 {
280 WDFDEVICE device = context;
281 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
282 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
284 return EvtChn_Mask(xpdd, Port);
285 }
287 static NTSTATUS
288 XenPci_EvtChn_Unmask(PVOID context, evtchn_port_t Port)
289 {
290 WDFDEVICE device = context;
291 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
292 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
294 return EvtChn_Unmask(xpdd, Port);
295 }
297 static NTSTATUS
298 XenPci_EvtChn_Notify(PVOID context, evtchn_port_t Port)
299 {
300 WDFDEVICE device = context;
301 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
302 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
304 return EvtChn_Notify(xpdd, Port);
305 }
307 static BOOLEAN
308 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port, BOOLEAN *last_interrupt)
309 {
310 WDFDEVICE device = context;
311 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
312 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
314 return EvtChn_AckEvent(xpdd, port, last_interrupt);
315 }
317 typedef struct {
318 PXEN_EVTCHN_SYNC_ROUTINE sync_routine;
319 PVOID sync_context;
320 } sync_context_t;
322 static BOOLEAN
323 XenPci_EvtChn_Sync_Routine(WDFINTERRUPT interrupt, WDFCONTEXT context)
324 {
325 sync_context_t *wdf_sync_context = context;
326 UNREFERENCED_PARAMETER(interrupt);
327 return wdf_sync_context->sync_routine(wdf_sync_context->sync_context);
328 }
330 static BOOLEAN
331 XenPci_EvtChn_Sync(PVOID context, PXEN_EVTCHN_SYNC_ROUTINE sync_routine, PVOID sync_context)
332 {
333 WDFDEVICE device = context;
334 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
335 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
336 sync_context_t wdf_sync_context;
338 wdf_sync_context.sync_routine = sync_routine;
339 wdf_sync_context.sync_context = sync_context;
341 return WdfInterruptSynchronize(xpdd->interrupt, XenPci_EvtChn_Sync_Routine, &wdf_sync_context);
342 }
344 static grant_ref_t
345 XenPci_GntTbl_GrantAccess(PVOID context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref, ULONG tag)
346 {
347 WDFDEVICE device = context;
348 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
349 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
351 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref, tag);
352 }
354 static BOOLEAN
355 XenPci_GntTbl_EndAccess(PVOID context, grant_ref_t ref, BOOLEAN keepref, ULONG tag)
356 {
357 WDFDEVICE device = context;
358 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
359 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
361 return GntTbl_EndAccess(xpdd, ref, keepref, tag);
362 }
364 static VOID
365 XenPci_GntTbl_PutRef(PVOID context, grant_ref_t ref, ULONG tag)
366 {
367 WDFDEVICE device = context;
368 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
369 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
371 GntTbl_PutRef(xpdd, ref, tag);
372 }
374 static grant_ref_t
375 XenPci_GntTbl_GetRef(PVOID context, ULONG tag)
376 {
377 WDFDEVICE device = context;
378 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
379 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
381 return GntTbl_GetRef(xpdd, tag);
382 }
384 PCHAR
385 XenPci_XenBus_Read(PVOID context, xenbus_transaction_t xbt, char *path, char **value)
386 {
387 WDFDEVICE device = context;
388 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
389 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
390 return XenBus_Read(xpdd, xbt, path, value);
391 }
393 PCHAR
394 XenPci_XenBus_Write(PVOID context, xenbus_transaction_t xbt, char *path, char *value)
395 {
396 WDFDEVICE device = context;
397 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
398 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
399 return XenBus_Write(xpdd, xbt, path, value);
400 }
402 PCHAR
403 XenPci_XenBus_Printf(PVOID context, xenbus_transaction_t xbt, char *path, char *fmt, ...)
404 {
405 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
406 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
407 //return XenBus_Printf(xpdd, xbt, path, value);
408 UNREFERENCED_PARAMETER(context);
409 UNREFERENCED_PARAMETER(xbt);
410 UNREFERENCED_PARAMETER(path);
411 UNREFERENCED_PARAMETER(fmt);
412 return NULL;
413 }
415 PCHAR
416 XenPci_XenBus_StartTransaction(PVOID context, xenbus_transaction_t *xbt)
417 {
418 WDFDEVICE device = context;
419 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
420 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
421 return XenBus_StartTransaction(xpdd, xbt);
422 }
424 PCHAR
425 XenPci_XenBus_EndTransaction(PVOID context, xenbus_transaction_t xbt, int abort, int *retry)
426 {
427 WDFDEVICE device = context;
428 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
429 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
430 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
431 }
433 PCHAR
434 XenPci_XenBus_List(PVOID context, xenbus_transaction_t xbt, char *prefix, char ***contents)
435 {
436 WDFDEVICE device = context;
437 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
438 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
439 return XenBus_List(xpdd, xbt, prefix, contents);
440 }
442 PCHAR
443 XenPci_XenBus_AddWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
444 {
445 WDFDEVICE device = context;
446 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
447 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
448 PCHAR retval;
450 FUNCTION_ENTER();
451 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
452 if (retval == NULL)
453 {
454 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
455 }
456 else
457 {
458 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
459 }
460 FUNCTION_EXIT();
461 return retval;
462 }
464 PCHAR
465 XenPci_XenBus_RemWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
466 {
467 WDFDEVICE device = context;
468 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
469 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
470 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
471 }
473 /*
474 Called at PASSIVE_LEVEL
475 Called during restore
476 */
478 static NTSTATUS
479 XenPci_ChangeFrontendState(WDFDEVICE device, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
480 {
481 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
482 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
483 LARGE_INTEGER timeout;
484 ULONG remaining;
485 ULONG thiswait;
486 char path[128];
488 FUNCTION_ENTER();
490 xppdd->frontend_state = frontend_state_set;
492 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
493 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
495 remaining = maximum_wait_ms;
497 while (xppdd->backend_state != backend_state_response)
498 {
499 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
500 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
501 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
502 {
503 /* it's possible that the workitems are blocked because the pagefile isn't available. Lets just re-read the backend value for now */
504 XenPci_UpdateBackendState(device);
505 remaining -= thiswait;
506 if (remaining == 0)
507 {
508 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
509 return STATUS_UNSUCCESSFUL;
510 }
511 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
512 }
513 }
514 FUNCTION_EXIT();
515 return STATUS_SUCCESS;
516 }
518 static NTSTATUS
519 XenPci_ChangeFrontendStateMap(WDFDEVICE device, PXENPCI_STATE_MAP_ELEMENT map)
520 {
521 NTSTATUS status;
523 FUNCTION_ENTER();
524 while(map->front_target)
525 {
526 //KdPrint((__DRIVER_NAME " Changing state to %d expecting %d\n", (ULONG)map->front_target, (ULONG)map->back_expected));
527 if (!NT_SUCCESS(status = XenPci_ChangeFrontendState(device, (ULONG)map->front_target, (ULONG)map->back_expected, (ULONG)map->wait * 100)))
528 {
529 FUNCTION_EXIT();
530 return status;
531 }
532 map++;
533 }
534 FUNCTION_EXIT();
535 return STATUS_SUCCESS;
536 }
538 static NTSTATUS
539 XenPci_XenConfigDevice(WDFDEVICE device);
541 static NTSTATUS
542 XenPci_XenShutdownDevice(PVOID context)
543 {
544 WDFDEVICE device = context;
545 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
546 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
547 PUCHAR in_ptr;
548 ULONG i;
549 UCHAR type;
550 PVOID setting;
551 PVOID value;
552 PVOID value2;
554 FUNCTION_ENTER();
556 if (xppdd->backend_state == XenbusStateConnected)
557 {
558 XenPci_ChangeFrontendStateMap(device, xppdd->xb_shutdown_map);
559 }
560 else
561 {
562 if (xppdd->backend_state == XenbusStateClosing)
563 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
564 }
566 if (xppdd->assigned_resources_start != NULL)
567 {
568 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
569 in_ptr = xppdd->assigned_resources_start;
570 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
571 {
572 switch (type)
573 {
574 case XEN_INIT_TYPE_RING: /* frontend ring */
575 FreePages(value);
576 break;
577 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
578 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
579 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
580 EvtChn_Unbind(xpdd, PtrToUlong(value));
581 EvtChn_Close(xpdd, PtrToUlong(value));
582 break;
583 case XEN_INIT_TYPE_GRANT_ENTRIES:
584 for (i = 0; i < PtrToUlong(value); i++)
585 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value2)[i], FALSE, PtrToUlong(setting));
586 break;
587 }
588 }
589 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
590 xppdd->assigned_resources_start = NULL;
591 }
593 FUNCTION_EXIT();
595 return STATUS_SUCCESS;
596 }
598 struct dummy_sring {
599 RING_IDX req_prod, req_event;
600 RING_IDX rsp_prod, rsp_event;
601 uint8_t pad[48];
602 };
604 static NTSTATUS
605 XenPci_XenConfigDeviceSpecifyBuffers(WDFDEVICE device, PUCHAR src, PUCHAR dst)
606 {
607 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
608 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
609 NTSTATUS status = STATUS_SUCCESS;
610 ULONG i;
611 char path[128];
612 PCHAR setting, value;
613 PCHAR res;
614 PVOID address;
615 UCHAR type;
616 PUCHAR in_ptr;
617 PUCHAR out_ptr;
618 XENPCI_VECTORS vectors;
619 ULONG event_channel;
620 PMDL ring;
621 grant_ref_t gref;
622 PVOID value2;
623 int map_no;
625 FUNCTION_ENTER();
627 xppdd->xb_pre_connect_map[0].front_target = 0;
628 xppdd->xb_post_connect_map[0].front_target = 0;
629 xppdd->xb_shutdown_map[0].front_target = 0;
631 in_ptr = src;
632 out_ptr = dst;
634 // always add vectors
635 vectors.magic = XEN_DATA_MAGIC;
636 vectors.length = sizeof(XENPCI_VECTORS);
637 vectors.context = device;
638 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
639 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
640 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
641 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
642 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
643 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
644 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
645 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
646 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
647 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
648 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
649 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
650 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
651 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
652 RtlStringCbCopyA(vectors.path, 128, xppdd->path);
653 RtlStringCbCopyA(vectors.backend_path, 128, xppdd->backend_path);
654 //vectors.pdo_event_channel = xpdd->pdo_event_channel;
655 vectors.XenBus_Read = XenPci_XenBus_Read;
656 vectors.XenBus_Write = XenPci_XenBus_Write;
657 vectors.XenBus_Printf = XenPci_XenBus_Printf;
658 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
659 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
660 vectors.XenBus_List = XenPci_XenBus_List;
661 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
662 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
664 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
666 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
667 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
669 // need to make sure we never get here while backend state is connected or closing...
670 // first pass, possibly before state == Connected
671 in_ptr = src;
672 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
673 {
674 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
676 switch (type)
677 {
678 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
679 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
680 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
681 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
682 break;
683 case XEN_INIT_TYPE_RING: /* frontend ring */
684 /* we only allocate and do the SHARED_RING_INIT here */
685 if ((ring = AllocatePage()) != 0)
686 {
687 address = MmGetMdlVirtualAddress(ring);
688 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
689 SHARED_RING_INIT((struct dummy_sring *)address);
690 if ((gref = GntTbl_GrantAccess(
691 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF, (ULONG)'XPDO')) != INVALID_GRANT_REF)
692 {
693 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
694 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %d\n", setting, gref));
695 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
696 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
697 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
698 // add the grant entry too so it gets freed automatically
699 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
700 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, (ULONG)'XPDO');
701 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
702 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
703 }
704 else
705 {
706 FreePages(ring);
707 status = STATUS_UNSUCCESSFUL;
708 goto error;
709 }
710 }
711 else
712 {
713 status = STATUS_UNSUCCESSFUL;
714 goto error;
715 }
716 break;
717 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
718 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
719 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
720 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
721 {
722 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
723 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
724 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
725 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
726 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
727 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
728 {
729 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path, EVT_ACTION_FLAGS_DEFAULT);
730 }
731 else if (type == XEN_INIT_TYPE_EVENT_CHANNEL_DPC)
732 {
733 #pragma warning(suppress:4055)
734 EvtChn_BindDpc(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2, EVT_ACTION_FLAGS_DEFAULT);
735 }
736 else
737 {
738 #pragma warning(suppress:4055)
739 EvtChn_Bind(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2, EVT_ACTION_FLAGS_DEFAULT);
740 }
741 }
742 else
743 {
744 status = STATUS_UNSUCCESSFUL;
745 goto error;
746 }
747 break;
748 case XEN_INIT_TYPE_XB_STATE_MAP_PRE_CONNECT:
749 map_no = 0;
750 while ((xppdd->xb_pre_connect_map[map_no].front_target = __GET_XEN_INIT_UCHAR(&in_ptr)) != 0)
751 {
752 xppdd->xb_pre_connect_map[map_no].back_expected = __GET_XEN_INIT_UCHAR(&in_ptr);
753 xppdd->xb_pre_connect_map[map_no].wait = __GET_XEN_INIT_UCHAR(&in_ptr);
754 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, xppdd->xb_pre_connect_map[map_no].front_target);
755 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, xppdd->xb_pre_connect_map[map_no].back_expected);
756 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, xppdd->xb_pre_connect_map[map_no].wait);
757 map_no++;
758 }
759 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, 0);
760 break;
761 case XEN_INIT_TYPE_XB_STATE_MAP_POST_CONNECT:
762 map_no = 0;
763 while ((xppdd->xb_post_connect_map[map_no].front_target = __GET_XEN_INIT_UCHAR(&in_ptr)) != 0)
764 {
765 xppdd->xb_post_connect_map[map_no].back_expected = __GET_XEN_INIT_UCHAR(&in_ptr);
766 xppdd->xb_post_connect_map[map_no].wait = __GET_XEN_INIT_UCHAR(&in_ptr);
767 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, xppdd->xb_post_connect_map[map_no].front_target);
768 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, xppdd->xb_post_connect_map[map_no].back_expected);
769 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, xppdd->xb_post_connect_map[map_no].wait);
770 map_no++;
771 }
772 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, 0);
773 break;
774 case XEN_INIT_TYPE_XB_STATE_MAP_SHUTDOWN:
775 map_no = 0;
776 while ((xppdd->xb_shutdown_map[map_no].front_target = __GET_XEN_INIT_UCHAR(&in_ptr)) != 0)
777 {
778 xppdd->xb_shutdown_map[map_no].back_expected = __GET_XEN_INIT_UCHAR(&in_ptr);
779 xppdd->xb_shutdown_map[map_no].wait = __GET_XEN_INIT_UCHAR(&in_ptr);
780 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, xppdd->xb_shutdown_map[map_no].front_target);
781 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, xppdd->xb_shutdown_map[map_no].back_expected);
782 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, xppdd->xb_shutdown_map[map_no].wait);
783 map_no++;
784 }
785 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, 0);
786 break;
787 }
788 }
789 if (!NT_SUCCESS(status))
790 {
791 goto error;
792 }
794 if (XenPci_ChangeFrontendStateMap(device, xppdd->xb_pre_connect_map) != STATUS_SUCCESS)
795 {
796 status = STATUS_UNSUCCESSFUL;
797 goto error;
798 }
800 // second pass, possibly after state == Connected
801 in_ptr = src;
802 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
803 {
804 switch(type)
805 {
806 case XEN_INIT_TYPE_READ_STRING_BACK:
807 case XEN_INIT_TYPE_READ_STRING_FRONT:
808 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
809 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
810 else
811 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
812 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
813 if (res)
814 {
815 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
816 XenPci_FreeMem(res);
817 ADD_XEN_INIT_RSP(&out_ptr, type, setting, "", "");
818 }
819 else
820 {
821 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
822 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, value2);
823 XenPci_FreeMem(value);
824 }
825 break;
826 case XEN_INIT_TYPE_VECTORS:
827 // this is always done so ignore the request
828 break;
829 case XEN_INIT_TYPE_GRANT_ENTRIES:
830 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
831 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
832 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
833 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(setting));
834 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(setting));
835 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
836 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
837 for (i = 0; i < PtrToUlong(value); i++)
838 {
839 gref = GntTbl_GetRef(xpdd, PtrToUlong(setting));
840 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
841 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
842 }
843 break;
844 /* just need to eat these */
845 case XEN_INIT_TYPE_XB_STATE_MAP_PRE_CONNECT:
846 case XEN_INIT_TYPE_XB_STATE_MAP_POST_CONNECT:
847 case XEN_INIT_TYPE_XB_STATE_MAP_SHUTDOWN:
848 while ((__GET_XEN_INIT_UCHAR(&in_ptr)) != 0)
849 {
850 __GET_XEN_INIT_UCHAR(&in_ptr);
851 __GET_XEN_INIT_UCHAR(&in_ptr);
852 }
853 break;
854 }
855 }
856 if (qemu_hide_flags_value)
857 {
858 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_HIDE_FLAGS, NULL, UlongToPtr(qemu_hide_flags_value), NULL);
859 }
860 else
861 {
862 DECLARE_UNICODE_STRING_SIZE(my_device_name, 128);
864 RtlUnicodeStringPrintf(&my_device_name, L"#%S#", xppdd->device);
866 for (i = 0; i < WdfCollectionGetCount(qemu_hide_devices); i++)
867 {
868 WDFSTRING wdf_string = WdfCollectionGetItem(qemu_hide_devices, i);
869 UNICODE_STRING hide_device_name;
871 WdfStringGetUnicodeString(wdf_string, &hide_device_name);
873 if (RtlCompareUnicodeString(&hide_device_name, &my_device_name, TRUE) != 0)
874 {
875 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_HIDE_FILTER, NULL, NULL, NULL);
876 break;
877 }
878 }
879 }
881 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
883 if (XenPci_ChangeFrontendStateMap(device, xppdd->xb_post_connect_map) != STATUS_SUCCESS)
884 {
885 status = STATUS_UNSUCCESSFUL;
886 goto error;
887 }
888 FUNCTION_EXIT();
889 return status;
891 error:
892 KdPrint((__DRIVER_NAME " Error\n"));
893 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000);
894 FUNCTION_EXIT_STATUS(status);
895 return status;
896 }
898 static NTSTATUS
899 XenPci_XenConfigDevice(WDFDEVICE device)
900 {
901 NTSTATUS status;
902 PUCHAR src, dst;
903 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
905 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
906 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
907 memcpy(src, dst, xppdd->config_page_length);
909 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
911 MmUnmapIoSpace(dst, xppdd->config_page_length);
912 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
914 return status;
915 }
917 static NTSTATUS
918 XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp)
919 {
920 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
921 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
922 PIO_STACK_LOCATION stack;
923 PCM_PARTIAL_RESOURCE_LIST prl;
924 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
925 ULONG i;
926 //char path[128];
927 //PMDL mdl;
929 FUNCTION_ENTER();
930 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
932 stack = IoGetCurrentIrpStackLocation(irp);
934 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
935 for (i = 0; i < prl->Count; i++)
936 {
937 prd = & prl->PartialDescriptors[i];
938 switch (prd->Type)
939 {
940 case CmResourceTypeMemory:
941 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
942 {
943 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
944 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
945 }
946 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
947 {
948 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
949 prd->Type = CmResourceTypeInterrupt;
950 prd->ShareDisposition = CmResourceShareShared;
951 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
952 prd->u.Interrupt.Level = 0; // Set group and level to zero (group = upper word)
953 prd->u.Interrupt.Level = xpdd->irq_number & 0xffff; // Only set the lower word
954 prd->u.Interrupt.Vector = xpdd->irq_number;
955 prd->u.Interrupt.Affinity = xpdd->irq_affinity; //KeQueryActiveProcessors();
956 xppdd->irq_number = xpdd->irq_number;
957 }
958 break;
959 }
960 }
962 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
963 for (i = 0; i < prl->Count; i++)
964 {
965 prd = & prl->PartialDescriptors[i];
966 switch (prd->Type)
967 {
968 case CmResourceTypeMemory:
969 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
970 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
971 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
972 {
973 if (prd->u.Memory.Length == 0)
974 {
975 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0]));
976 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
977 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
978 KdPrint((__DRIVER_NAME " New Start = %08x%08x, Length = %d\n", prd->u.Memory.Start.HighPart, prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
979 }
980 xppdd->config_page_phys = prd->u.Memory.Start;
981 xppdd->config_page_length = prd->u.Memory.Length;
982 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
983 //xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
985 #if 0
986 status = XenPci_XenConfigDevice(device);
987 if (!NT_SUCCESS(status))
988 {
989 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
990 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
991 FUNCTION_EXIT_STATUS(status);
992 return status;
993 }
994 #endif
995 }
996 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
997 {
998 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
999 prd->Type = CmResourceTypeInterrupt;
1000 prd->ShareDisposition = CmResourceShareShared;
1001 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
1002 prd->u.Interrupt.Level = 0; // Set group and level to zero (group = upper word)
1003 prd->u.Interrupt.Level = xpdd->irq_level & 0xffff; // Only set the lower word
1004 prd->u.Interrupt.Vector = xpdd->irq_vector;
1005 prd->u.Interrupt.Affinity = xpdd->irq_affinity; //KeQueryActiveProcessors();
1006 xppdd->irq_vector = xpdd->irq_vector;
1007 xppdd->irq_level = xpdd->irq_level;
1009 break;
1013 IoSkipCurrentIrpStackLocation(irp);
1015 FUNCTION_EXIT();
1017 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
1020 #if 0
1021 static NTSTATUS
1022 XenPciPdo_EvtDeviceResourcesQuery(WDFDEVICE device, WDFCMRESLIST resources)
1025 #endif
1027 static NTSTATUS
1028 XenPciPdo_EvtDeviceResourceRequirementsQuery(WDFDEVICE device, WDFIORESREQLIST requirements_list)
1030 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1031 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1032 WDFIORESLIST res_list;
1033 IO_RESOURCE_DESCRIPTOR ird;
1035 //FUNCTION_ENTER();
1037 WdfIoResourceRequirementsListSetInterfaceType(requirements_list, PNPBus);
1039 WdfIoResourceListCreate(requirements_list, WDF_NO_OBJECT_ATTRIBUTES, &res_list);
1040 ird.Option = 0;
1041 ird.Type = CmResourceTypeMemory;
1042 ird.ShareDisposition = CmResourceShareShared;
1043 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
1044 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
1045 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
1046 ird.u.Memory.Length = 0;
1047 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
1048 WdfIoResourceListAppendDescriptor(res_list, &ird);
1050 ird.Option = 0;
1051 ird.Type = CmResourceTypeMemory;
1052 ird.ShareDisposition = CmResourceShareShared;
1053 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
1054 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
1055 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
1056 ird.u.Memory.Length = 0;
1057 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
1058 WdfIoResourceListAppendDescriptor(res_list, &ird);
1060 WdfIoResourceRequirementsListAppendIoResList(requirements_list, res_list);
1062 //FUNCTION_EXIT();
1064 return STATUS_SUCCESS;
1067 NTSTATUS
1068 XenPciPdo_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
1070 NTSTATUS status = STATUS_SUCCESS;
1071 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1072 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1073 CHAR path[128];
1075 FUNCTION_ENTER();
1076 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
1078 switch (previous_state)
1080 case WdfPowerDeviceD0:
1081 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1082 break;
1083 case WdfPowerDeviceD1:
1084 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1085 break;
1086 case WdfPowerDeviceD2:
1087 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
1088 break;
1089 case WdfPowerDeviceD3:
1090 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
1091 break;
1092 case WdfPowerDeviceD3Final:
1093 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
1094 break;
1095 case WdfPowerDevicePrepareForHibernation:
1096 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
1097 break;
1098 default:
1099 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
1100 break;
1103 if (previous_state == WdfPowerDevicePrepareForHibernation
1104 || (previous_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
1106 KdPrint((__DRIVER_NAME " starting up from hibernation\n"));
1108 else
1112 #if 0
1113 if (previous_state == WdfPowerDevicePrepareForHibernation || previous_state == WdfPowerDeviceD3 || previous_state == WdfPowerDeviceD3Final)
1115 xppdd->requested_resources_ptr = xppdd->requested_resources_start;
1116 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
1118 XenConfig_InitConfigPage(device);
1119 #endif
1121 status = XenPci_GetBackendAndAddWatch(device);
1122 if (!NT_SUCCESS(status))
1124 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
1125 FUNCTION_EXIT_STATUS(status);
1126 return status;
1129 if (previous_state == WdfPowerDeviceD3 || previous_state == WdfPowerDeviceD3Final)
1131 xppdd->requested_resources_ptr = xppdd->requested_resources_start;
1132 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
1133 XenConfig_InitConfigPage(device);
1134 status = XenPci_XenConfigDevice(device);
1136 else if (previous_state == WdfPowerDevicePrepareForHibernation)
1138 PVOID src, dst;
1140 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1141 src = xppdd->requested_resources_start;
1142 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
1143 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
1145 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
1147 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
1149 MmUnmapIoSpace(dst, xppdd->config_page_length);
1150 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
1153 if (!NT_SUCCESS(status))
1155 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1156 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
1157 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
1158 FUNCTION_EXIT_STATUS(status);
1159 return status;
1162 FUNCTION_EXIT();
1164 return status;
1167 NTSTATUS
1168 XenPciPdo_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
1170 NTSTATUS status = STATUS_SUCCESS;
1171 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1172 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1173 char path[128];
1175 UNREFERENCED_PARAMETER(device);
1176 UNREFERENCED_PARAMETER(target_state);
1178 FUNCTION_ENTER();
1179 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
1181 switch (target_state)
1183 case WdfPowerDeviceD0:
1184 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1185 break;
1186 case WdfPowerDeviceD1:
1187 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1188 break;
1189 case WdfPowerDeviceD2:
1190 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
1191 break;
1192 case WdfPowerDeviceD3:
1193 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
1194 break;
1195 case WdfPowerDeviceD3Final:
1196 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
1197 break;
1198 case WdfPowerDevicePrepareForHibernation:
1199 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
1200 break;
1201 default:
1202 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
1203 break;
1206 if (target_state == WdfPowerDevicePrepareForHibernation
1207 || (target_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
1209 KdPrint((__DRIVER_NAME " not powering down as we are hibernating\n"));
1211 else
1213 status = XenPci_XenShutdownDevice(device);
1216 /* Remove watch on backend state */
1217 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1218 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
1220 FUNCTION_EXIT();
1222 return status;
1225 NTSTATUS
1226 XenPciPdo_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
1228 NTSTATUS status = STATUS_SUCCESS;
1230 UNREFERENCED_PARAMETER(device);
1231 UNREFERENCED_PARAMETER(resources_raw);
1232 UNREFERENCED_PARAMETER(resources_translated);
1234 FUNCTION_ENTER();
1235 FUNCTION_EXIT();
1237 return status;
1240 NTSTATUS
1241 XenPciPdo_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
1243 NTSTATUS status = STATUS_SUCCESS;
1245 UNREFERENCED_PARAMETER(device);
1246 UNREFERENCED_PARAMETER(resources_translated);
1248 FUNCTION_ENTER();
1249 FUNCTION_EXIT();
1251 return status;
1254 static VOID
1255 XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
1257 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1259 FUNCTION_ENTER();
1261 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
1262 switch (notification_type)
1264 case WdfSpecialFilePaging:
1265 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
1266 break;
1267 case WdfSpecialFileHibernation:
1268 xppdd->hiber_usage_kludge = is_in_notification_path;
1269 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
1270 break;
1271 case WdfSpecialFileDump:
1272 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
1273 break;
1274 default:
1275 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
1276 break;
1279 FUNCTION_EXIT();
1282 static VOID
1283 XenPci_EvtDevicePnpStateChange(WDFDEVICE device, PCWDF_DEVICE_PNP_NOTIFICATION_DATA notification_data)
1285 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1287 //FUNCTION_ENTER();
1289 if (xppdd->backend_initiated_remove
1290 && notification_data->Type == StateNotificationEnterState
1291 && notification_data->Data.EnterState.CurrentState == WdfDevStatePnpQueryRemovePending
1292 && notification_data->Data.EnterState.NewState == WdfDevStatePnpQueryCanceled)
1294 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1296 KdPrint((__DRIVER_NAME " Eject failed, doing surprise removal\n"));
1297 xppdd->do_not_enumerate = TRUE;
1298 XenPci_EvtChildListScanForChildren(xpdd->child_list);
1301 //FUNCTION_EXIT();
1303 //return STATUS_SUCCESS;
1306 NTSTATUS
1307 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
1308 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
1309 PWDFDEVICE_INIT child_init)
1311 NTSTATUS status = STATUS_SUCCESS;
1312 WDF_OBJECT_ATTRIBUTES child_attributes;
1313 WDFDEVICE child_device;
1314 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
1315 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
1316 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
1317 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
1318 PXENPCI_PDO_DEVICE_DATA xppdd;
1319 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
1320 WDF_QUERY_INTERFACE_CONFIG interface_config;
1321 BUS_INTERFACE_STANDARD bus_interface;
1322 WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
1323 WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
1324 UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
1325 WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
1327 FUNCTION_ENTER();
1329 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
1331 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
1332 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
1333 //child_pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPciPdo_EvtDeviceD0EntryPostInterruptsEnabled;
1334 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
1335 //child_pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPciPdo_EvtDeviceD0ExitPreInterruptsDisabled;
1336 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenPciPdo_EvtDevicePrepareHardware;
1337 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenPciPdo_EvtDeviceReleaseHardware;
1338 child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
1339 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
1341 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
1342 identification->device, identification->index, identification->path));
1344 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
1345 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
1346 if (!NT_SUCCESS(status))
1348 return status;
1351 WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
1352 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
1353 pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
1354 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
1355 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
1356 WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
1358 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
1359 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
1360 if (!NT_SUCCESS(status))
1362 return status;
1364 status = WdfPdoInitAddHardwareID(child_init, &buffer);
1365 if (!NT_SUCCESS(status))
1367 return status;
1369 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
1370 if (!NT_SUCCESS(status))
1372 return status;
1375 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
1376 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
1377 if (!NT_SUCCESS(status))
1379 return status;
1382 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
1383 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
1384 if (!NT_SUCCESS(status))
1386 return status;
1388 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
1390 WdfDeviceInitSetPowerNotPageable(child_init);
1392 WdfDeviceInitRegisterPnpStateChangeCallback(child_init, WdfDevStatePnpQueryCanceled, XenPci_EvtDevicePnpStateChange, StateNotificationEnterState);
1394 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
1395 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
1396 if (!NT_SUCCESS(status))
1398 return status;
1401 xppdd = GetXppdd(child_device);
1403 xppdd->wdf_device = child_device;
1404 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
1406 xppdd->config_page_mdl = AllocateUncachedPage();
1408 xppdd->device_state.magic = XEN_DEVICE_STATE_MAGIC;
1409 xppdd->device_state.length = sizeof(XENPCI_DEVICE_STATE);
1410 xppdd->device_state.suspend_resume_state_pdo = SR_STATE_RUNNING;
1411 xppdd->device_state.suspend_resume_state_fdo = SR_STATE_RUNNING;
1412 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
1413 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
1414 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
1415 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
1417 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
1418 child_pnp_capabilities.LockSupported = WdfFalse;
1419 child_pnp_capabilities.EjectSupported = WdfTrue;
1420 child_pnp_capabilities.Removable = WdfTrue;
1421 child_pnp_capabilities.DockDevice = WdfFalse;
1422 child_pnp_capabilities.UniqueID = WdfFalse;
1423 child_pnp_capabilities.SilentInstall = WdfTrue;
1424 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
1425 child_pnp_capabilities.HardwareDisabled = WdfFalse;
1426 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
1428 WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
1429 child_power_capabilities.DeviceD1 = WdfTrue;
1430 child_power_capabilities.WakeFromD1 = WdfTrue;
1431 child_power_capabilities.DeviceWake = PowerDeviceD1;
1432 child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
1433 child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
1434 child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
1435 child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
1436 child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
1437 child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
1438 WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
1440 status = WdfFdoQueryForInterface(xpdd->wdf_device, &GUID_BUS_INTERFACE_STANDARD, (PINTERFACE)&bus_interface,
1441 sizeof(BUS_INTERFACE_STANDARD), 1, NULL);
1442 if (!NT_SUCCESS(status))
1444 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface failed - %08x\n", status));
1445 return status;
1447 WDF_QUERY_INTERFACE_CONFIG_INIT(&interface_config, (PINTERFACE)&bus_interface, &GUID_BUS_INTERFACE_STANDARD, NULL);
1448 status = WdfDeviceAddQueryInterface(child_device, &interface_config);
1449 if (!NT_SUCCESS(status))
1451 KdPrint((__DRIVER_NAME " WdfDeviceAddQueryInterface failed - %08x\n", status));
1452 return status;
1455 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
1456 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
1457 xppdd->index = identification->index;
1458 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
1459 ExInitializeFastMutex(&xppdd->backend_state_mutex);
1460 xppdd->backend_state = XenbusStateUnknown;
1461 xppdd->frontend_state = XenbusStateUnknown;
1462 xppdd->backend_path[0] = '\0';
1464 FUNCTION_EXIT();
1466 return status;
1469 static __forceinline VOID
1470 XenPci_Pdo_ChangeSuspendState(WDFDEVICE device, ULONG new_state)
1472 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1473 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1475 FUNCTION_ENTER();
1476 KdPrint((__DRIVER_NAME " setting pdo state to %d\n", new_state));
1477 xppdd->device_state.suspend_resume_state_pdo = new_state;
1478 KeMemoryBarrier();
1479 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xpdd->pdo_event_channel));
1480 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
1481 while(xppdd->device_state.suspend_resume_state_fdo != xppdd->device_state.suspend_resume_state_pdo)
1483 KdPrint((__DRIVER_NAME " waiting...\n"));
1484 KeWaitForSingleObject(&xpdd->pdo_suspend_event, Executive, KernelMode, FALSE, NULL);
1486 KdPrint((__DRIVER_NAME " fdo state set to %d\n", new_state));
1487 FUNCTION_EXIT();
1490 /* called at PASSIVE_LEVEL */
1491 NTSTATUS
1492 XenPci_Pdo_Suspend(WDFDEVICE device)
1494 NTSTATUS status = STATUS_SUCCESS;
1495 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1496 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1497 char path[128];
1498 PUCHAR in_ptr;
1499 UCHAR type;
1500 PVOID setting;
1501 PVOID value;
1502 PVOID value2;
1503 int i;
1505 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
1507 if (xppdd->backend_state == XenbusStateConnected)
1509 xppdd->restart_on_resume = TRUE;
1510 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_SUSPENDING);
1512 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
1513 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
1514 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
1516 if (xppdd->assigned_resources_start != NULL)
1518 in_ptr = xppdd->assigned_resources_ptr;
1519 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1520 in_ptr = xppdd->assigned_resources_start;
1521 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
1523 switch (type)
1525 case XEN_INIT_TYPE_RING: /* frontend ring */
1526 FreePages(value);
1527 break;
1528 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
1529 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
1530 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
1531 EvtChn_Unbind(xpdd, PtrToUlong(value));
1532 EvtChn_Close(xpdd, PtrToUlong(value));
1533 break;
1534 case XEN_INIT_TYPE_GRANT_ENTRIES:
1535 for (i = 0; i < (int)PtrToUlong(value); i++)
1536 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value2)[i], FALSE, PtrToUlong(setting));
1537 break;
1542 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1543 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
1545 else
1547 xppdd->restart_on_resume = FALSE;
1550 FUNCTION_EXIT();
1552 return status;
1555 NTSTATUS
1556 XenPci_Pdo_Resume(WDFDEVICE device)
1558 NTSTATUS status = STATUS_SUCCESS;
1559 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1560 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1561 ULONG old_backend_state;
1562 PUCHAR src, dst;
1564 FUNCTION_ENTER();
1565 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
1567 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
1568 old_backend_state = xppdd->backend_state;
1570 if (xppdd->restart_on_resume)
1572 status = XenPci_GetBackendAndAddWatch(device);
1574 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
1576 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
1577 // this is probably an unrecoverable situation...
1578 FUNCTION_EXIT();
1579 return STATUS_UNSUCCESSFUL;
1581 if (xppdd->assigned_resources_ptr)
1583 // reset things - feed the 'requested resources' back in
1584 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1585 src = xppdd->requested_resources_start;
1586 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
1587 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
1589 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
1591 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
1593 MmUnmapIoSpace(dst, xppdd->config_page_length);
1594 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
1596 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
1598 // this is definitely an unrecoverable situation...
1599 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
1600 FUNCTION_EXIT();
1601 return STATUS_UNSUCCESSFUL;
1603 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RESUMING);
1604 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RUNNING);
1607 FUNCTION_EXIT();
1609 return STATUS_SUCCESS;