win-pvdrivers

view xenpci/xenpci_pdo.c @ 982:e9011a1ba5bb

started rewriting xenpci<->child interface
author James Harper <james.harper@bendigoit.com.au>
date Mon Aug 13 17:10:03 2012 +1000 (2012-08-13)
parents 941699790045
children
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 #if 0
39 /*
40 Called at PASSIVE_LEVEL(?)
41 Called during restore
42 */
43 static ULONG
44 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
45 {
46 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
47 char path[128];
48 char *value;
49 char *err;
50 ULONG backend_state;
52 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
53 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
54 if (err)
55 {
56 XenPci_FreeMem(err);
57 return XenbusStateUnknown;
58 }
59 else
60 {
61 backend_state = atoi(value);
62 XenPci_FreeMem(value);
63 return backend_state;
64 }
65 }
67 static NTSTATUS
68 XenPciPdo_ReconfigureCompletionRoutine(
69 PDEVICE_OBJECT device_object,
70 PIRP irp,
71 PVOID context)
72 {
73 UNREFERENCED_PARAMETER(device_object);
75 if (irp->PendingReturned)
76 {
77 KeSetEvent ((PKEVENT)context, IO_NO_INCREMENT, FALSE);
78 }
79 return STATUS_MORE_PROCESSING_REQUIRED;
80 }
82 static VOID
83 XenPci_UpdateBackendState(PVOID context)
84 {
85 WDFDEVICE device = context;
86 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
87 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
88 ULONG new_backend_state;
90 FUNCTION_ENTER();
92 ExAcquireFastMutex(&xppdd->backend_state_mutex);
94 new_backend_state = XenPci_ReadBackendState(xppdd);
95 if (new_backend_state == XenbusStateUnknown)
96 {
97 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
98 {
99 ExReleaseFastMutex(&xppdd->backend_state_mutex);
100 return;
101 }
102 KdPrint(("Failed to read path, assuming closed\n"));
103 new_backend_state = XenbusStateClosed;
104 }
106 if (xppdd->backend_state == new_backend_state)
107 {
108 KdPrint((__DRIVER_NAME " state unchanged\n"));
109 ExReleaseFastMutex(&xppdd->backend_state_mutex);
110 return;
111 }
113 xppdd->backend_state = new_backend_state;
115 switch (xppdd->backend_state)
116 {
117 case XenbusStateUnknown:
118 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
119 break;
121 case XenbusStateInitialising:
122 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
123 break;
125 case XenbusStateInitWait:
126 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
127 break;
129 case XenbusStateInitialised:
130 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
131 break;
133 case XenbusStateConnected:
134 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
135 break;
137 case XenbusStateClosing:
138 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
139 if (xppdd->frontend_state != XenbusStateClosing)
140 {
141 xppdd->backend_initiated_remove = TRUE;
142 KdPrint((__DRIVER_NAME " Requesting eject\n"));
143 WdfPdoRequestEject(device);
144 }
145 break;
147 case XenbusStateClosed:
148 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
149 break;
151 default:
152 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", xppdd->backend_state));
153 break;
154 }
156 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
158 ExReleaseFastMutex(&xppdd->backend_state_mutex);
159 FUNCTION_EXIT();
161 return;
162 }
164 static VOID
165 XenPci_BackendStateHandler(char *path, PVOID context)
166 {
167 UNREFERENCED_PARAMETER(path);
169 /* check that path == device/id/state */
170 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
172 XenPci_UpdateBackendState(context);
173 }
175 static NTSTATUS
176 XenPci_GetBackendAndAddWatch(WDFDEVICE device)
177 {
178 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
179 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
180 char path[128];
181 PCHAR res;
182 PCHAR value;
184 FUNCTION_ENTER();
185 /* Get backend path */
186 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
187 "%s/backend", xppdd->path);
188 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
189 if (res)
190 {
191 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
192 XenPci_FreeMem(res);
193 return STATUS_UNSUCCESSFUL;
194 }
195 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
196 XenPci_FreeMem(value);
198 /* Get backend id */
199 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
200 "%s/backend-id", xppdd->path);
201 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
202 if (res) {
203 KdPrint((__DRIVER_NAME " Failed to read backend id\n"));
204 XenPci_FreeMem(res);
205 return STATUS_UNSUCCESSFUL;
206 }
207 xppdd->backend_id = (domid_t)atoi(value);
208 XenPci_FreeMem(value);
210 /* Add watch on backend state */
211 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
212 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
214 FUNCTION_EXIT();
215 return STATUS_SUCCESS;
216 }
218 static NTSTATUS
219 XenConfig_InitConfigPage(WDFDEVICE device)
220 {
221 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
222 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
223 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
224 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
225 PUCHAR ptr;
226 PDEVICE_OBJECT curr, prev;
227 PDRIVER_OBJECT fdo_driver_object;
228 PUCHAR fdo_driver_extension;
230 FUNCTION_ENTER();
232 ptr = MmGetMdlVirtualAddress(xppdd->config_page_mdl);
233 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(device));
234 //curr = WdfDeviceWdmGetAttachedDevice(device);
235 while (curr != NULL)
236 {
237 fdo_driver_object = curr->DriverObject;
238 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
239 if (fdo_driver_object)
240 {
241 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
242 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
243 if (fdo_driver_extension)
244 {
245 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
246 ObDereferenceObject(curr);
247 break;
248 }
249 }
250 prev = curr;
251 curr = IoGetLowerDeviceObject(curr);
252 ObDereferenceObject(prev);
253 }
255 FUNCTION_EXIT();
257 return STATUS_SUCCESS;
258 }
260 static NTSTATUS
261 XenPci_EvtChn_Bind(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
262 {
263 WDFDEVICE device = context;
264 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
265 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
267 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext, EVT_ACTION_FLAGS_DEFAULT);
268 }
270 static NTSTATUS
271 XenPci_EvtChn_BindDpc(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
272 {
273 WDFDEVICE device = context;
274 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
275 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
277 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext, EVT_ACTION_FLAGS_DEFAULT);
278 }
280 static NTSTATUS
281 XenPci_EvtChn_Unbind(PVOID context, evtchn_port_t Port)
282 {
283 WDFDEVICE device = context;
284 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
285 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
287 return EvtChn_Unbind(xpdd, Port);
288 }
290 static NTSTATUS
291 XenPci_EvtChn_Mask(PVOID context, evtchn_port_t Port)
292 {
293 WDFDEVICE device = context;
294 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
295 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
297 return EvtChn_Mask(xpdd, Port);
298 }
300 static NTSTATUS
301 XenPci_EvtChn_Unmask(PVOID context, evtchn_port_t Port)
302 {
303 WDFDEVICE device = context;
304 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
305 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
307 return EvtChn_Unmask(xpdd, Port);
308 }
310 static NTSTATUS
311 XenPci_EvtChn_Notify(PVOID context, evtchn_port_t Port)
312 {
313 WDFDEVICE device = context;
314 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
315 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
317 return EvtChn_Notify(xpdd, Port);
318 }
320 static BOOLEAN
321 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port, BOOLEAN *last_interrupt)
322 {
323 WDFDEVICE device = context;
324 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
325 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
327 return EvtChn_AckEvent(xpdd, port, last_interrupt);
328 }
330 typedef struct {
331 PXEN_EVTCHN_SYNC_ROUTINE sync_routine;
332 PVOID sync_context;
333 } sync_context_t;
335 static BOOLEAN
336 XenPci_EvtChn_Sync_Routine(WDFINTERRUPT interrupt, WDFCONTEXT context)
337 {
338 sync_context_t *wdf_sync_context = context;
339 UNREFERENCED_PARAMETER(interrupt);
340 return wdf_sync_context->sync_routine(wdf_sync_context->sync_context);
341 }
343 static BOOLEAN
344 XenPci_EvtChn_Sync(PVOID context, PXEN_EVTCHN_SYNC_ROUTINE sync_routine, PVOID sync_context)
345 {
346 WDFDEVICE device = context;
347 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
348 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
349 sync_context_t wdf_sync_context;
351 wdf_sync_context.sync_routine = sync_routine;
352 wdf_sync_context.sync_context = sync_context;
354 return WdfInterruptSynchronize(xpdd->interrupt, XenPci_EvtChn_Sync_Routine, &wdf_sync_context);
355 }
357 static grant_ref_t
358 XenPci_GntTbl_GrantAccess(PVOID context, uint32_t frame, int readonly, grant_ref_t ref, ULONG tag)
359 {
360 WDFDEVICE device = context;
361 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
362 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
364 return GntTbl_GrantAccess(xpdd, xppdd->backend_id, frame, readonly, ref, tag);
365 }
367 static BOOLEAN
368 XenPci_GntTbl_EndAccess(PVOID context, grant_ref_t ref, BOOLEAN keepref, ULONG tag)
369 {
370 WDFDEVICE device = context;
371 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
372 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
374 return GntTbl_EndAccess(xpdd, ref, keepref, tag);
375 }
377 static VOID
378 XenPci_GntTbl_PutRef(PVOID context, grant_ref_t ref, ULONG tag)
379 {
380 WDFDEVICE device = context;
381 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
382 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
384 GntTbl_PutRef(xpdd, ref, tag);
385 }
387 static grant_ref_t
388 XenPci_GntTbl_GetRef(PVOID context, ULONG tag)
389 {
390 WDFDEVICE device = context;
391 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
392 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
394 return GntTbl_GetRef(xpdd, tag);
395 }
397 PCHAR
398 XenPci_XenBus_Read(PVOID context, xenbus_transaction_t xbt, char *path, char **value)
399 {
400 WDFDEVICE device = context;
401 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
402 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
403 return XenBus_Read(xpdd, xbt, path, value);
404 }
406 PCHAR
407 XenPci_XenBus_Write(PVOID context, xenbus_transaction_t xbt, char *path, char *value)
408 {
409 WDFDEVICE device = context;
410 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
411 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
412 return XenBus_Write(xpdd, xbt, path, value);
413 }
415 PCHAR
416 XenPci_XenBus_Printf(PVOID context, xenbus_transaction_t xbt, char *path, char *fmt, ...)
417 {
418 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
419 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
420 //return XenBus_Printf(xpdd, xbt, path, value);
421 UNREFERENCED_PARAMETER(context);
422 UNREFERENCED_PARAMETER(xbt);
423 UNREFERENCED_PARAMETER(path);
424 UNREFERENCED_PARAMETER(fmt);
425 return NULL;
426 }
428 PCHAR
429 XenPci_XenBus_StartTransaction(PVOID context, xenbus_transaction_t *xbt)
430 {
431 WDFDEVICE device = context;
432 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
433 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
434 return XenBus_StartTransaction(xpdd, xbt);
435 }
437 PCHAR
438 XenPci_XenBus_EndTransaction(PVOID context, xenbus_transaction_t xbt, int abort, int *retry)
439 {
440 WDFDEVICE device = context;
441 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
442 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
443 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
444 }
446 PCHAR
447 XenPci_XenBus_List(PVOID context, xenbus_transaction_t xbt, char *prefix, char ***contents)
448 {
449 WDFDEVICE device = context;
450 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
451 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
452 return XenBus_List(xpdd, xbt, prefix, contents);
453 }
455 PCHAR
456 XenPci_XenBus_AddWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
457 {
458 WDFDEVICE device = context;
459 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
460 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
461 PCHAR retval;
463 FUNCTION_ENTER();
464 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
465 if (retval == NULL)
466 {
467 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
468 }
469 else
470 {
471 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
472 }
473 FUNCTION_EXIT();
474 return retval;
475 }
477 PCHAR
478 XenPci_XenBus_RemWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
479 {
480 WDFDEVICE device = context;
481 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
482 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
483 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
484 }
487 /*
488 Called at PASSIVE_LEVEL
489 Called during restore
490 */
491 static NTSTATUS
492 XenPci_ChangeFrontendState(WDFDEVICE device, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
493 {
494 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
495 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
496 LARGE_INTEGER timeout;
497 ULONG remaining;
498 ULONG thiswait;
499 char path[128];
501 FUNCTION_ENTER();
503 xppdd->frontend_state = frontend_state_set;
505 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
506 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
508 remaining = maximum_wait_ms;
510 while (xppdd->backend_state != backend_state_response)
511 {
512 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
513 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
514 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
515 {
516 /* it's possible that the workitems are blocked because the pagefile isn't available. Lets just re-read the backend value for now */
517 XenPci_UpdateBackendState(device);
518 remaining -= thiswait;
519 if (remaining == 0)
520 {
521 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
522 return STATUS_UNSUCCESSFUL;
523 }
524 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
525 }
526 }
527 FUNCTION_EXIT();
528 return STATUS_SUCCESS;
529 }
531 static NTSTATUS
532 XenPci_ChangeFrontendStateMap(WDFDEVICE device, PXENPCI_STATE_MAP_ELEMENT map)
533 {
534 NTSTATUS status;
536 FUNCTION_ENTER();
537 while(map->front_target)
538 {
539 //KdPrint((__DRIVER_NAME " Changing state to %d expecting %d\n", (ULONG)map->front_target, (ULONG)map->back_expected));
540 if (!NT_SUCCESS(status = XenPci_ChangeFrontendState(device, (ULONG)map->front_target, (ULONG)map->back_expected, (ULONG)map->wait * 100)))
541 {
542 FUNCTION_EXIT();
543 return status;
544 }
545 map++;
546 }
547 FUNCTION_EXIT();
548 return STATUS_SUCCESS;
549 }
551 static NTSTATUS
552 XenPci_XenConfigDevice(WDFDEVICE device);
554 static NTSTATUS
555 XenPci_XenShutdownDevice(PVOID context)
556 {
557 WDFDEVICE device = context;
558 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
559 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
560 PUCHAR in_ptr;
561 ULONG i;
562 UCHAR type;
563 PVOID setting;
564 PVOID value;
565 PVOID value2;
567 FUNCTION_ENTER();
569 if (xppdd->backend_state == XenbusStateConnected)
570 {
571 XenPci_ChangeFrontendStateMap(device, xppdd->xb_shutdown_map);
572 }
573 else if (xppdd->backend_state == XenbusStateClosing)
574 {
575 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
576 }
577 if (xppdd->assigned_resources_start != NULL)
578 {
579 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
580 in_ptr = xppdd->assigned_resources_start;
581 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
582 {
583 switch (type)
584 {
585 case XEN_INIT_TYPE_RING: /* frontend ring */
586 FreePages(value);
587 break;
588 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
589 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
590 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
591 EvtChn_Unbind(xpdd, PtrToUlong(value));
592 EvtChn_Close(xpdd, PtrToUlong(value));
593 break;
594 case XEN_INIT_TYPE_GRANT_ENTRIES:
595 for (i = 0; i < PtrToUlong(value); i++)
596 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value2)[i], FALSE, PtrToUlong(setting));
597 break;
598 }
599 }
600 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
601 xppdd->assigned_resources_start = NULL;
602 }
604 FUNCTION_EXIT();
606 return STATUS_SUCCESS;
607 }
609 struct dummy_sring {
610 RING_IDX req_prod, req_event;
611 RING_IDX rsp_prod, rsp_event;
612 uint8_t pad[48];
613 };
615 static NTSTATUS
616 XenPci_XenConfigDeviceSpecifyBuffers(WDFDEVICE device, PUCHAR src, PUCHAR dst)
617 {
618 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
619 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
620 NTSTATUS status = STATUS_SUCCESS;
621 ULONG i;
622 char path[128];
623 PCHAR setting, value;
624 PCHAR res;
625 PVOID address;
626 UCHAR type;
627 PUCHAR in_ptr;
628 PUCHAR out_ptr;
629 XENPCI_VECTORS vectors;
630 ULONG event_channel;
631 PMDL ring;
632 grant_ref_t gref;
633 PVOID value2;
634 int map_no;
636 FUNCTION_ENTER();
638 xppdd->xb_pre_connect_map[0].front_target = 0;
639 xppdd->xb_post_connect_map[0].front_target = 0;
640 xppdd->xb_shutdown_map[0].front_target = 0;
642 in_ptr = src;
643 out_ptr = dst;
645 // always add vectors
646 vectors.magic = XEN_DATA_MAGIC;
647 vectors.length = sizeof(XENPCI_VECTORS);
648 vectors.context = device;
649 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
650 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
651 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
652 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
653 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
654 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
655 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
656 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
657 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
658 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
659 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
660 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
661 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
662 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
663 RtlStringCbCopyA(vectors.path, 128, xppdd->path);
664 RtlStringCbCopyA(vectors.backend_path, 128, xppdd->backend_path);
665 //vectors.pdo_event_channel = xpdd->pdo_event_channel;
666 vectors.XenBus_Read = XenPci_XenBus_Read;
667 vectors.XenBus_Write = XenPci_XenBus_Write;
668 vectors.XenBus_Printf = XenPci_XenBus_Printf;
669 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
670 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
671 vectors.XenBus_List = XenPci_XenBus_List;
672 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
673 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
675 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
677 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
678 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
680 // need to make sure we never get here while backend state is connected or closing...
681 // first pass, possibly before state == Connected
682 in_ptr = src;
683 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
684 {
685 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
687 switch (type)
688 {
689 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
690 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
691 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
692 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
693 break;
694 case XEN_INIT_TYPE_RING: /* frontend ring */
695 /* we only allocate and do the SHARED_RING_INIT here */
696 if ((ring = AllocatePage()) != 0)
697 {
698 address = MmGetMdlVirtualAddress(ring);
699 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
700 SHARED_RING_INIT((struct dummy_sring *)address);
701 if ((gref = GntTbl_GrantAccess(
702 xpdd, xppdd->backend_id, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF, (ULONG)'XPDO')) != INVALID_GRANT_REF)
703 {
704 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
705 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %d\n", setting, gref));
706 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
707 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
708 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
709 // add the grant entry too so it gets freed automatically
710 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
711 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, (ULONG)'XPDO');
712 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
713 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
714 }
715 else
716 {
717 FreePages(ring);
718 status = STATUS_UNSUCCESSFUL;
719 goto error;
720 }
721 }
722 else
723 {
724 status = STATUS_UNSUCCESSFUL;
725 goto error;
726 }
727 break;
728 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
729 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
730 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
731 if ((event_channel = EvtChn_AllocUnbound(xpdd, xppdd->backend_id)) != 0)
732 {
733 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
734 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
735 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
736 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
737 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
738 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
739 {
740 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path, EVT_ACTION_FLAGS_DEFAULT);
741 }
742 else if (type == XEN_INIT_TYPE_EVENT_CHANNEL_DPC)
743 {
744 #pragma warning(suppress:4055)
745 EvtChn_BindDpc(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2, EVT_ACTION_FLAGS_DEFAULT);
746 }
747 else
748 {
749 #pragma warning(suppress:4055)
750 EvtChn_Bind(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2, EVT_ACTION_FLAGS_DEFAULT);
751 }
752 }
753 else
754 {
755 status = STATUS_UNSUCCESSFUL;
756 goto error;
757 }
758 break;
759 case XEN_INIT_TYPE_XB_STATE_MAP_PRE_CONNECT:
760 map_no = 0;
761 while ((xppdd->xb_pre_connect_map[map_no].front_target = __GET_XEN_INIT_UCHAR(&in_ptr)) != 0)
762 {
763 xppdd->xb_pre_connect_map[map_no].back_expected = __GET_XEN_INIT_UCHAR(&in_ptr);
764 xppdd->xb_pre_connect_map[map_no].wait = __GET_XEN_INIT_UCHAR(&in_ptr);
765 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, xppdd->xb_pre_connect_map[map_no].front_target);
766 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, xppdd->xb_pre_connect_map[map_no].back_expected);
767 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, xppdd->xb_pre_connect_map[map_no].wait);
768 map_no++;
769 }
770 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, 0);
771 break;
772 case XEN_INIT_TYPE_XB_STATE_MAP_POST_CONNECT:
773 map_no = 0;
774 while ((xppdd->xb_post_connect_map[map_no].front_target = __GET_XEN_INIT_UCHAR(&in_ptr)) != 0)
775 {
776 xppdd->xb_post_connect_map[map_no].back_expected = __GET_XEN_INIT_UCHAR(&in_ptr);
777 xppdd->xb_post_connect_map[map_no].wait = __GET_XEN_INIT_UCHAR(&in_ptr);
778 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, xppdd->xb_post_connect_map[map_no].front_target);
779 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, xppdd->xb_post_connect_map[map_no].back_expected);
780 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, xppdd->xb_post_connect_map[map_no].wait);
781 map_no++;
782 }
783 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, 0);
784 break;
785 case XEN_INIT_TYPE_XB_STATE_MAP_SHUTDOWN:
786 map_no = 0;
787 while ((xppdd->xb_shutdown_map[map_no].front_target = __GET_XEN_INIT_UCHAR(&in_ptr)) != 0)
788 {
789 xppdd->xb_shutdown_map[map_no].back_expected = __GET_XEN_INIT_UCHAR(&in_ptr);
790 xppdd->xb_shutdown_map[map_no].wait = __GET_XEN_INIT_UCHAR(&in_ptr);
791 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, xppdd->xb_shutdown_map[map_no].front_target);
792 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, xppdd->xb_shutdown_map[map_no].back_expected);
793 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, xppdd->xb_shutdown_map[map_no].wait);
794 map_no++;
795 }
796 __ADD_XEN_INIT_UCHAR(&xppdd->requested_resources_ptr, 0);
797 break;
798 }
799 }
800 if (!NT_SUCCESS(status))
801 {
802 goto error;
803 }
805 if (XenPci_ChangeFrontendStateMap(device, xppdd->xb_pre_connect_map) != STATUS_SUCCESS)
806 {
807 status = STATUS_UNSUCCESSFUL;
808 goto error;
809 }
811 // second pass, possibly after state == Connected
812 in_ptr = src;
813 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
814 {
815 switch(type)
816 {
817 case XEN_INIT_TYPE_READ_STRING_BACK:
818 case XEN_INIT_TYPE_READ_STRING_FRONT:
819 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
820 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
821 else
822 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
823 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
824 if (res)
825 {
826 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
827 XenPci_FreeMem(res);
828 ADD_XEN_INIT_RSP(&out_ptr, type, setting, "", "");
829 }
830 else
831 {
832 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
833 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, value2);
834 XenPci_FreeMem(value);
835 }
836 break;
837 case XEN_INIT_TYPE_VECTORS:
838 // this is always done so ignore the request
839 break;
840 case XEN_INIT_TYPE_GRANT_ENTRIES:
841 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
842 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
843 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
844 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(setting));
845 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(setting));
846 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
847 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
848 for (i = 0; i < PtrToUlong(value); i++)
849 {
850 gref = GntTbl_GetRef(xpdd, PtrToUlong(setting));
851 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
852 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
853 }
854 break;
855 /* just need to eat these */
856 case XEN_INIT_TYPE_XB_STATE_MAP_PRE_CONNECT:
857 case XEN_INIT_TYPE_XB_STATE_MAP_POST_CONNECT:
858 case XEN_INIT_TYPE_XB_STATE_MAP_SHUTDOWN:
859 while ((__GET_XEN_INIT_UCHAR(&in_ptr)) != 0)
860 {
861 __GET_XEN_INIT_UCHAR(&in_ptr);
862 __GET_XEN_INIT_UCHAR(&in_ptr);
863 }
864 break;
865 }
866 }
867 if (qemu_hide_flags_value)
868 {
869 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_HIDE_FLAGS, NULL, UlongToPtr(qemu_hide_flags_value), NULL);
870 }
871 else
872 {
873 DECLARE_UNICODE_STRING_SIZE(my_device_name, 128);
875 RtlUnicodeStringPrintf(&my_device_name, L"#%S#", xppdd->device);
877 for (i = 0; i < WdfCollectionGetCount(qemu_hide_devices); i++)
878 {
879 WDFSTRING wdf_string = WdfCollectionGetItem(qemu_hide_devices, i);
880 UNICODE_STRING hide_device_name;
882 WdfStringGetUnicodeString(wdf_string, &hide_device_name);
884 if (RtlCompareUnicodeString(&hide_device_name, &my_device_name, TRUE) != 0)
885 {
886 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_HIDE_FILTER, NULL, NULL, NULL);
887 break;
888 }
889 }
890 }
892 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
894 if (XenPci_ChangeFrontendStateMap(device, xppdd->xb_post_connect_map) != STATUS_SUCCESS)
895 {
896 status = STATUS_UNSUCCESSFUL;
897 goto error;
898 }
899 FUNCTION_EXIT();
900 return status;
902 error:
903 KdPrint((__DRIVER_NAME " Error\n"));
904 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000);
905 FUNCTION_EXIT_STATUS(status);
906 return status;
907 }
909 static NTSTATUS
910 XenPci_XenConfigDevice(WDFDEVICE device)
911 {
912 NTSTATUS status;
913 PUCHAR src, dst;
914 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
916 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
917 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
918 memcpy(src, dst, xppdd->config_page_length);
920 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
922 MmUnmapIoSpace(dst, xppdd->config_page_length);
923 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
925 return status;
926 }
928 static NTSTATUS
929 XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp)
930 {
931 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
932 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
933 PIO_STACK_LOCATION stack;
934 PCM_PARTIAL_RESOURCE_LIST prl;
935 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
936 ULONG i;
937 //char path[128];
938 //PMDL mdl;
940 FUNCTION_ENTER();
941 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
943 stack = IoGetCurrentIrpStackLocation(irp);
945 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
946 for (i = 0; i < prl->Count; i++)
947 {
948 prd = & prl->PartialDescriptors[i];
949 switch (prd->Type)
950 {
951 case CmResourceTypeMemory:
952 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
953 {
954 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
955 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
956 }
957 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
958 {
959 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
960 prd->Type = CmResourceTypeInterrupt;
961 prd->ShareDisposition = CmResourceShareShared;
962 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
963 prd->u.Interrupt.Level = 0; // Set group and level to zero (group = upper word)
964 prd->u.Interrupt.Level = xpdd->irq_number & 0xffff; // Only set the lower word
965 prd->u.Interrupt.Vector = xpdd->irq_number;
966 prd->u.Interrupt.Affinity = xpdd->irq_affinity; //KeQueryActiveProcessors();
967 xppdd->irq_number = xpdd->irq_number;
968 }
969 break;
970 }
971 }
973 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
974 for (i = 0; i < prl->Count; i++)
975 {
976 prd = & prl->PartialDescriptors[i];
977 switch (prd->Type)
978 {
979 case CmResourceTypeMemory:
980 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
981 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
982 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
983 {
984 if (prd->u.Memory.Length == 0)
985 {
986 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0]));
987 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
988 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
989 KdPrint((__DRIVER_NAME " New Start = %08x%08x, Length = %d\n", prd->u.Memory.Start.HighPart, prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
990 }
991 xppdd->config_page_phys = prd->u.Memory.Start;
992 xppdd->config_page_length = prd->u.Memory.Length;
993 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
994 //xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
996 #if 0
997 status = XenPci_XenConfigDevice(device);
998 if (!NT_SUCCESS(status))
999 {
1000 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1001 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
1002 FUNCTION_EXIT_STATUS(status);
1003 return status;
1005 #endif
1007 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
1009 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1010 prd->Type = CmResourceTypeInterrupt;
1011 prd->ShareDisposition = CmResourceShareShared;
1012 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
1013 prd->u.Interrupt.Level = 0; // Set group and level to zero (group = upper word)
1014 prd->u.Interrupt.Level = xpdd->irq_level & 0xffff; // Only set the lower word
1015 prd->u.Interrupt.Vector = xpdd->irq_vector;
1016 prd->u.Interrupt.Affinity = xpdd->irq_affinity; //KeQueryActiveProcessors();
1017 xppdd->irq_vector = xpdd->irq_vector;
1018 xppdd->irq_level = xpdd->irq_level;
1020 break;
1024 IoSkipCurrentIrpStackLocation(irp);
1026 FUNCTION_EXIT();
1028 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
1031 #if 0
1032 static NTSTATUS
1033 XenPciPdo_EvtDeviceResourcesQuery(WDFDEVICE device, WDFCMRESLIST resources)
1036 #endif
1038 #endif
1040 static NTSTATUS
1041 XenPciPdo_EvtDeviceResourceRequirementsQuery(WDFDEVICE device, WDFIORESREQLIST requirements_list)
1043 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1044 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1045 WDFIORESLIST res_list;
1046 IO_RESOURCE_DESCRIPTOR ird;
1048 //FUNCTION_ENTER();
1050 WdfIoResourceRequirementsListSetInterfaceType(requirements_list, PNPBus);
1052 WdfIoResourceListCreate(requirements_list, WDF_NO_OBJECT_ATTRIBUTES, &res_list);
1053 ird.Option = 0;
1054 ird.Type = CmResourceTypeMemory;
1055 ird.ShareDisposition = CmResourceShareShared;
1056 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
1057 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
1058 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
1059 ird.u.Memory.Length = 0;
1060 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
1061 WdfIoResourceListAppendDescriptor(res_list, &ird);
1063 ird.Option = 0;
1064 ird.Type = CmResourceTypeMemory;
1065 ird.ShareDisposition = CmResourceShareShared;
1066 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
1067 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
1068 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
1069 ird.u.Memory.Length = 0;
1070 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
1071 WdfIoResourceListAppendDescriptor(res_list, &ird);
1073 WdfIoResourceRequirementsListAppendIoResList(requirements_list, res_list);
1075 //FUNCTION_EXIT();
1077 return STATUS_SUCCESS;
1080 NTSTATUS
1081 XenPciPdo_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
1083 NTSTATUS status = STATUS_SUCCESS;
1084 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1085 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1086 CHAR path[128];
1088 FUNCTION_ENTER();
1089 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
1091 switch (previous_state)
1093 case WdfPowerDeviceD0:
1094 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1095 break;
1096 case WdfPowerDeviceD1:
1097 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1098 break;
1099 case WdfPowerDeviceD2:
1100 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
1101 break;
1102 case WdfPowerDeviceD3:
1103 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
1104 if (xppdd->hiber_usage_kludge)
1106 KdPrint((__DRIVER_NAME " (but really WdfPowerDevicePrepareForHibernation)\n"));
1107 previous_state = WdfPowerDevicePrepareForHibernation;
1109 break;
1110 case WdfPowerDeviceD3Final:
1111 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
1112 break;
1113 case WdfPowerDevicePrepareForHibernation:
1114 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
1115 break;
1116 default:
1117 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
1118 break;
1121 #if 0
1122 status = XenPci_GetBackendAndAddWatch(device);
1123 if (!NT_SUCCESS(status))
1125 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
1126 FUNCTION_EXIT_STATUS(status);
1127 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;
1161 #endif
1163 FUNCTION_EXIT();
1165 return status;
1168 NTSTATUS
1169 XenPciPdo_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
1171 NTSTATUS status = STATUS_SUCCESS;
1172 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1173 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1174 char path[128];
1176 UNREFERENCED_PARAMETER(device);
1177 UNREFERENCED_PARAMETER(target_state);
1179 FUNCTION_ENTER();
1180 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
1182 switch (target_state)
1184 case WdfPowerDeviceD0:
1185 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1186 break;
1187 case WdfPowerDeviceD1:
1188 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1189 break;
1190 case WdfPowerDeviceD2:
1191 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
1192 break;
1193 case WdfPowerDeviceD3:
1194 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
1195 if (xppdd->hiber_usage_kludge)
1197 KdPrint((__DRIVER_NAME " (but really WdfPowerDevicePrepareForHibernation)\n"));
1198 target_state = WdfPowerDevicePrepareForHibernation;
1200 break;
1201 case WdfPowerDeviceD3Final:
1202 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
1203 break;
1204 case WdfPowerDevicePrepareForHibernation:
1205 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
1206 break;
1207 default:
1208 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
1209 break;
1212 #if 0
1213 if (target_state == WdfPowerDevicePrepareForHibernation)
1215 KdPrint((__DRIVER_NAME " not powering down as we are hibernating\n"));
1216 // should we set the backend state here so it's correct on resume???
1218 else
1220 status = XenPci_XenShutdownDevice(device);
1222 /* Remove watch on backend state */
1223 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1224 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
1225 #endif
1227 FUNCTION_EXIT();
1229 return status;
1232 NTSTATUS
1233 XenPciPdo_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
1235 NTSTATUS status = STATUS_SUCCESS;
1237 UNREFERENCED_PARAMETER(device);
1238 UNREFERENCED_PARAMETER(resources_raw);
1239 UNREFERENCED_PARAMETER(resources_translated);
1241 FUNCTION_ENTER();
1242 FUNCTION_EXIT();
1244 return status;
1247 NTSTATUS
1248 XenPciPdo_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
1250 NTSTATUS status = STATUS_SUCCESS;
1252 UNREFERENCED_PARAMETER(device);
1253 UNREFERENCED_PARAMETER(resources_translated);
1255 FUNCTION_ENTER();
1256 FUNCTION_EXIT();
1258 return status;
1261 static VOID
1262 XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
1264 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1266 FUNCTION_ENTER();
1268 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
1269 switch (notification_type)
1271 case WdfSpecialFilePaging:
1272 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
1273 break;
1274 case WdfSpecialFileHibernation:
1275 xppdd->hiber_usage_kludge = is_in_notification_path;
1276 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
1277 break;
1278 case WdfSpecialFileDump:
1279 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
1280 break;
1281 default:
1282 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
1283 break;
1286 FUNCTION_EXIT();
1289 static VOID
1290 XenPci_EvtDevicePnpStateChange(WDFDEVICE device, PCWDF_DEVICE_PNP_NOTIFICATION_DATA notification_data)
1292 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1294 //FUNCTION_ENTER();
1296 if (xppdd->backend_initiated_remove
1297 && notification_data->Type == StateNotificationEnterState
1298 && notification_data->Data.EnterState.CurrentState == WdfDevStatePnpQueryRemovePending
1299 && notification_data->Data.EnterState.NewState == WdfDevStatePnpQueryCanceled)
1301 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1303 KdPrint((__DRIVER_NAME " Eject failed, doing surprise removal\n"));
1304 xppdd->do_not_enumerate = TRUE;
1305 XenPci_EvtChildListScanForChildren(xpdd->child_list);
1308 //FUNCTION_EXIT();
1310 //return STATUS_SUCCESS;
1313 NTSTATUS
1314 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
1315 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
1316 PWDFDEVICE_INIT child_init)
1318 NTSTATUS status = STATUS_SUCCESS;
1319 WDF_OBJECT_ATTRIBUTES child_attributes;
1320 WDFDEVICE child_device;
1321 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
1322 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
1323 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
1324 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
1325 PXENPCI_PDO_DEVICE_DATA xppdd;
1326 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
1327 WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
1328 WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
1329 UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
1330 WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
1332 FUNCTION_ENTER();
1334 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
1336 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
1337 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
1338 //child_pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPciPdo_EvtDeviceD0EntryPostInterruptsEnabled;
1339 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
1340 //child_pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPciPdo_EvtDeviceD0ExitPreInterruptsDisabled;
1341 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenPciPdo_EvtDevicePrepareHardware;
1342 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenPciPdo_EvtDeviceReleaseHardware;
1343 child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
1344 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
1346 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
1347 identification->device, identification->index, identification->path));
1349 #if 0
1350 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
1351 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
1352 if (!NT_SUCCESS(status)) {
1353 return status;
1355 #endif
1357 WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
1358 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
1359 pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
1360 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
1361 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
1362 WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
1364 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
1365 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
1366 if (!NT_SUCCESS(status))
1368 return status;
1370 status = WdfPdoInitAddHardwareID(child_init, &buffer);
1371 if (!NT_SUCCESS(status))
1373 return status;
1375 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
1376 if (!NT_SUCCESS(status))
1378 return status;
1381 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
1382 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
1383 if (!NT_SUCCESS(status))
1385 return status;
1388 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
1389 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
1390 if (!NT_SUCCESS(status))
1392 return status;
1394 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
1396 WdfDeviceInitSetPowerNotPageable(child_init);
1398 WdfDeviceInitRegisterPnpStateChangeCallback(child_init, WdfDevStatePnpQueryCanceled, XenPci_EvtDevicePnpStateChange, StateNotificationEnterState);
1400 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
1401 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
1402 if (!NT_SUCCESS(status))
1404 return status;
1407 xppdd = GetXppdd(child_device);
1409 xppdd->wdf_device = child_device;
1410 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
1412 #if 0
1413 xppdd->config_page_mdl = AllocateUncachedPage();
1415 xppdd->device_state.magic = XEN_DEVICE_STATE_MAGIC;
1416 xppdd->device_state.length = sizeof(XENPCI_DEVICE_STATE);
1417 xppdd->device_state.suspend_resume_state_pdo = SR_STATE_RUNNING;
1418 xppdd->device_state.suspend_resume_state_fdo = SR_STATE_RUNNING;
1419 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
1420 #endif
1421 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
1422 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
1423 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
1425 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
1426 child_pnp_capabilities.LockSupported = WdfFalse;
1427 child_pnp_capabilities.EjectSupported = WdfTrue;
1428 child_pnp_capabilities.Removable = WdfTrue;
1429 child_pnp_capabilities.DockDevice = WdfFalse;
1430 child_pnp_capabilities.UniqueID = WdfFalse;
1431 child_pnp_capabilities.SilentInstall = WdfTrue;
1432 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
1433 child_pnp_capabilities.HardwareDisabled = WdfFalse;
1434 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
1436 WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
1437 child_power_capabilities.DeviceD1 = WdfTrue;
1438 child_power_capabilities.WakeFromD1 = WdfTrue;
1439 child_power_capabilities.DeviceWake = PowerDeviceD1;
1440 child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD0;
1441 child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
1442 child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
1443 child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
1444 child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
1445 child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
1446 WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
1448 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
1449 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
1450 xppdd->index = identification->index;
1451 #if 0
1452 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
1453 ExInitializeFastMutex(&xppdd->backend_state_mutex);
1454 xppdd->backend_state = XenbusStateUnknown;
1455 #endif
1456 //xppdd->frontend_state = XenbusStateUnknown;
1457 xppdd->backend_path[0] = '\0';
1458 xppdd->backend_id = 0;
1460 FUNCTION_EXIT();
1462 return status;
1465 #if 0
1466 static __forceinline VOID
1467 XenPci_Pdo_ChangeSuspendState(WDFDEVICE device, ULONG new_state)
1469 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1470 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1472 FUNCTION_ENTER();
1473 KdPrint((__DRIVER_NAME " setting pdo state to %d\n", new_state));
1474 xppdd->device_state.suspend_resume_state_pdo = new_state;
1475 KeMemoryBarrier();
1476 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xpdd->pdo_event_channel));
1477 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
1478 while(xppdd->device_state.suspend_resume_state_fdo != xppdd->device_state.suspend_resume_state_pdo)
1480 KdPrint((__DRIVER_NAME " waiting...\n"));
1481 KeWaitForSingleObject(&xpdd->pdo_suspend_event, Executive, KernelMode, FALSE, NULL);
1483 KdPrint((__DRIVER_NAME " fdo state set to %d\n", new_state));
1484 FUNCTION_EXIT();
1487 /* called at PASSIVE_LEVEL */
1488 NTSTATUS
1489 XenPci_Pdo_Suspend(WDFDEVICE device)
1491 NTSTATUS status = STATUS_SUCCESS;
1492 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1493 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1494 char path[128];
1495 PUCHAR in_ptr;
1496 UCHAR type;
1497 PVOID setting;
1498 PVOID value;
1499 PVOID value2;
1500 int i;
1502 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
1504 if (xppdd->backend_state == XenbusStateConnected)
1506 xppdd->restart_on_resume = TRUE;
1507 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_SUSPENDING);
1509 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
1510 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
1511 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
1513 if (xppdd->assigned_resources_start != NULL)
1515 in_ptr = xppdd->assigned_resources_ptr;
1516 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1517 in_ptr = xppdd->assigned_resources_start;
1518 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
1520 switch (type)
1522 case XEN_INIT_TYPE_RING: /* frontend ring */
1523 FreePages(value);
1524 break;
1525 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
1526 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
1527 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
1528 EvtChn_Unbind(xpdd, PtrToUlong(value));
1529 EvtChn_Close(xpdd, PtrToUlong(value));
1530 break;
1531 case XEN_INIT_TYPE_GRANT_ENTRIES:
1532 for (i = 0; i < (int)PtrToUlong(value); i++)
1533 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value2)[i], FALSE, PtrToUlong(setting));
1534 break;
1539 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1540 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
1542 else
1544 xppdd->restart_on_resume = FALSE;
1547 FUNCTION_EXIT();
1549 return status;
1552 NTSTATUS
1553 XenPci_Pdo_Resume(WDFDEVICE device)
1555 NTSTATUS status = STATUS_SUCCESS;
1556 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1557 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1558 ULONG old_backend_state;
1559 PUCHAR src, dst;
1561 FUNCTION_ENTER();
1562 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
1564 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
1565 old_backend_state = xppdd->backend_state;
1567 if (xppdd->restart_on_resume)
1569 status = XenPci_GetBackendAndAddWatch(device);
1571 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
1573 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
1574 // this is probably an unrecoverable situation...
1575 FUNCTION_EXIT();
1576 return STATUS_UNSUCCESSFUL;
1578 if (xppdd->assigned_resources_ptr)
1580 // reset things - feed the 'requested resources' back in
1581 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1582 src = xppdd->requested_resources_start;
1583 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
1584 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
1586 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
1588 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
1590 MmUnmapIoSpace(dst, xppdd->config_page_length);
1591 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
1593 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
1595 // this is definitely an unrecoverable situation...
1596 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
1597 FUNCTION_EXIT();
1598 return STATUS_UNSUCCESSFUL;
1600 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RESUMING);
1601 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RUNNING);
1604 FUNCTION_EXIT();
1606 return STATUS_SUCCESS;
1608 #endif