win-pvdrivers

view xenpci/xenpci_pdo.c @ 747:f43c89df09b2

Big changes to the way the device hiding works. Should fix the way Vista and above need a reboot into safe mode after install.
author James Harper <james.harper@bendigoit.com.au>
date Sun Jan 10 10:07:32 2010 +1100 (2010-01-10)
parents 5bdb7251370c
children acc551273d8b
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;
37 /*
38 Called at PASSIVE_LEVEL(?)
39 Called during restore
40 */
41 static ULONG
42 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
43 {
44 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
45 char path[128];
46 char *value;
47 char *err;
48 ULONG backend_state;
50 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
51 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
52 if (err)
53 {
54 XenPci_FreeMem(err);
55 return XenbusStateUnknown;
56 }
57 else
58 {
59 backend_state = atoi(value);
60 XenPci_FreeMem(value);
61 return backend_state;
62 }
63 }
65 static NTSTATUS
66 XenPciPdo_ReconfigureCompletionRoutine(
67 PDEVICE_OBJECT device_object,
68 PIRP irp,
69 PVOID context)
70 {
71 UNREFERENCED_PARAMETER(device_object);
73 if (irp->PendingReturned)
74 {
75 KeSetEvent ((PKEVENT)context, IO_NO_INCREMENT, FALSE);
76 }
77 return STATUS_MORE_PROCESSING_REQUIRED;
78 }
80 static VOID
81 XenPci_UpdateBackendState(PVOID context)
82 {
83 WDFDEVICE device = context;
84 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
85 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
86 ULONG new_backend_state;
88 FUNCTION_ENTER();
90 ExAcquireFastMutex(&xppdd->backend_state_mutex);
92 new_backend_state = XenPci_ReadBackendState(xppdd);
93 if (new_backend_state == XenbusStateUnknown)
94 {
95 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
96 {
97 ExReleaseFastMutex(&xppdd->backend_state_mutex);
98 return;
99 }
100 KdPrint(("Failed to read path, assuming closed\n"));
101 new_backend_state = XenbusStateClosed;
102 }
104 if (xppdd->backend_state == new_backend_state)
105 {
106 KdPrint((__DRIVER_NAME " state unchanged\n"));
107 ExReleaseFastMutex(&xppdd->backend_state_mutex);
108 return;
109 }
111 xppdd->backend_state = new_backend_state;
113 switch (xppdd->backend_state)
114 {
115 case XenbusStateUnknown:
116 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
117 break;
119 case XenbusStateInitialising:
120 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
121 break;
123 case XenbusStateInitWait:
124 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
125 break;
127 case XenbusStateInitialised:
128 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
129 break;
131 case XenbusStateConnected:
132 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
133 break;
135 case XenbusStateClosing:
136 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
137 if (xppdd->frontend_state != XenbusStateClosing)
138 {
139 KdPrint((__DRIVER_NAME " Requesting eject\n"));
140 WdfPdoRequestEject(device);
141 }
142 break;
144 case XenbusStateClosed:
145 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
146 break;
148 default:
149 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", xppdd->backend_state));
150 break;
151 }
153 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
155 ExReleaseFastMutex(&xppdd->backend_state_mutex);
156 FUNCTION_EXIT();
158 return;
159 }
161 static VOID
162 XenPci_BackendStateHandler(char *path, PVOID context)
163 {
164 UNREFERENCED_PARAMETER(path);
166 /* check that path == device/id/state */
167 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
169 XenPci_UpdateBackendState(context);
170 }
172 static NTSTATUS
173 XenPci_GetBackendAndAddWatch(WDFDEVICE device)
174 {
175 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
176 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
177 char path[128];
178 PCHAR res;
179 PCHAR value;
181 FUNCTION_ENTER();
182 /* Get backend path */
183 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
184 "%s/backend", xppdd->path);
185 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
186 if (res)
187 {
188 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
189 XenPci_FreeMem(res);
190 return STATUS_UNSUCCESSFUL;
191 }
192 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
193 XenPci_FreeMem(value);
195 /* Add watch on backend state */
196 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
197 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
199 FUNCTION_EXIT();
200 return STATUS_SUCCESS;
201 }
203 static NTSTATUS
204 XenConfig_InitConfigPage(WDFDEVICE device)
205 {
206 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
207 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
208 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
209 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
210 PUCHAR ptr;
211 PDEVICE_OBJECT curr, prev;
212 PDRIVER_OBJECT fdo_driver_object;
213 PUCHAR fdo_driver_extension;
215 FUNCTION_ENTER();
217 ptr = MmGetMdlVirtualAddress(xppdd->config_page_mdl);
218 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(device));
219 //curr = WdfDeviceWdmGetAttachedDevice(device);
220 while (curr != NULL)
221 {
222 fdo_driver_object = curr->DriverObject;
223 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
224 if (fdo_driver_object)
225 {
226 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
227 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
228 if (fdo_driver_extension)
229 {
230 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
231 ObDereferenceObject(curr);
232 break;
233 }
234 }
235 prev = curr;
236 curr = IoGetLowerDeviceObject(curr);
237 ObDereferenceObject(prev);
238 }
240 FUNCTION_EXIT();
242 return STATUS_SUCCESS;
243 }
245 static NTSTATUS
246 XenPci_EvtChn_Bind(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
247 {
248 WDFDEVICE device = context;
249 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
250 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
252 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext);
253 }
255 static NTSTATUS
256 XenPci_EvtChn_BindDpc(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
257 {
258 WDFDEVICE device = context;
259 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
260 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
262 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext);
263 }
265 static NTSTATUS
266 XenPci_EvtChn_Unbind(PVOID context, evtchn_port_t Port)
267 {
268 WDFDEVICE device = context;
269 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
270 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
272 return EvtChn_Unbind(xpdd, Port);
273 }
275 static NTSTATUS
276 XenPci_EvtChn_Mask(PVOID context, evtchn_port_t Port)
277 {
278 WDFDEVICE device = context;
279 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
280 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
282 return EvtChn_Mask(xpdd, Port);
283 }
285 static NTSTATUS
286 XenPci_EvtChn_Unmask(PVOID context, evtchn_port_t Port)
287 {
288 WDFDEVICE device = context;
289 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
290 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
292 return EvtChn_Unmask(xpdd, Port);
293 }
295 static NTSTATUS
296 XenPci_EvtChn_Notify(PVOID context, evtchn_port_t Port)
297 {
298 WDFDEVICE device = context;
299 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
300 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
302 return EvtChn_Notify(xpdd, Port);
303 }
305 static BOOLEAN
306 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port, BOOLEAN *last_interrupt)
307 {
308 WDFDEVICE device = context;
309 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
310 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
312 return EvtChn_AckEvent(xpdd, port, last_interrupt);
313 }
315 typedef struct {
316 PXEN_EVTCHN_SYNC_ROUTINE sync_routine;
317 PVOID sync_context;
318 } sync_context_t;
320 static BOOLEAN
321 XenPci_EvtChn_Sync_Routine(WDFINTERRUPT interrupt, WDFCONTEXT context)
322 {
323 sync_context_t *wdf_sync_context = context;
324 UNREFERENCED_PARAMETER(interrupt);
325 return wdf_sync_context->sync_routine(wdf_sync_context->sync_context);
326 }
328 static BOOLEAN
329 XenPci_EvtChn_Sync(PVOID context, PXEN_EVTCHN_SYNC_ROUTINE sync_routine, PVOID sync_context)
330 {
331 WDFDEVICE device = context;
332 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
333 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
334 sync_context_t wdf_sync_context;
336 wdf_sync_context.sync_routine = sync_routine;
337 wdf_sync_context.sync_context = sync_context;
339 return WdfInterruptSynchronize(xpdd->interrupt, XenPci_EvtChn_Sync_Routine, &wdf_sync_context);
340 }
342 static grant_ref_t
343 XenPci_GntTbl_GrantAccess(PVOID context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref)
344 {
345 WDFDEVICE device = context;
346 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
347 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
349 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref);
350 }
352 static BOOLEAN
353 XenPci_GntTbl_EndAccess(PVOID context, grant_ref_t ref, BOOLEAN keepref)
354 {
355 WDFDEVICE device = context;
356 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
357 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
359 return GntTbl_EndAccess(xpdd, ref, keepref);
360 }
362 static VOID
363 XenPci_GntTbl_PutRef(PVOID context, grant_ref_t ref)
364 {
365 WDFDEVICE device = context;
366 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
367 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
369 GntTbl_PutRef(xpdd, ref);
370 }
372 static grant_ref_t
373 XenPci_GntTbl_GetRef(PVOID context)
374 {
375 WDFDEVICE device = context;
376 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
377 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
379 return GntTbl_GetRef(xpdd);
380 }
382 PCHAR
383 XenPci_XenBus_Read(PVOID context, xenbus_transaction_t xbt, char *path, char **value)
384 {
385 WDFDEVICE device = context;
386 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
387 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
388 return XenBus_Read(xpdd, xbt, path, value);
389 }
391 PCHAR
392 XenPci_XenBus_Write(PVOID context, xenbus_transaction_t xbt, char *path, char *value)
393 {
394 WDFDEVICE device = context;
395 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
396 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
397 return XenBus_Write(xpdd, xbt, path, value);
398 }
400 PCHAR
401 XenPci_XenBus_Printf(PVOID context, xenbus_transaction_t xbt, char *path, char *fmt, ...)
402 {
403 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
404 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
405 //return XenBus_Printf(xpdd, xbt, path, value);
406 UNREFERENCED_PARAMETER(context);
407 UNREFERENCED_PARAMETER(xbt);
408 UNREFERENCED_PARAMETER(path);
409 UNREFERENCED_PARAMETER(fmt);
410 return NULL;
411 }
413 PCHAR
414 XenPci_XenBus_StartTransaction(PVOID context, xenbus_transaction_t *xbt)
415 {
416 WDFDEVICE device = context;
417 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
418 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
419 return XenBus_StartTransaction(xpdd, xbt);
420 }
422 PCHAR
423 XenPci_XenBus_EndTransaction(PVOID context, xenbus_transaction_t xbt, int abort, int *retry)
424 {
425 WDFDEVICE device = context;
426 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
427 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
428 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
429 }
431 PCHAR
432 XenPci_XenBus_List(PVOID context, xenbus_transaction_t xbt, char *prefix, char ***contents)
433 {
434 WDFDEVICE device = context;
435 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
436 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
437 return XenBus_List(xpdd, xbt, prefix, contents);
438 }
440 PCHAR
441 XenPci_XenBus_AddWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
442 {
443 WDFDEVICE device = context;
444 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
445 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
446 PCHAR retval;
448 FUNCTION_ENTER();
449 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
450 if (retval == NULL)
451 {
452 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
453 }
454 else
455 {
456 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
457 }
458 FUNCTION_EXIT();
459 return retval;
460 }
462 PCHAR
463 XenPci_XenBus_RemWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
464 {
465 WDFDEVICE device = context;
466 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
467 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
468 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
469 }
471 /*
472 Called at PASSIVE_LEVEL
473 Called during restore
474 */
476 static NTSTATUS
477 XenPci_ChangeFrontendState(WDFDEVICE device, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
478 {
479 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
480 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
481 LARGE_INTEGER timeout;
482 ULONG remaining;
483 ULONG thiswait;
484 char path[128];
486 FUNCTION_ENTER();
488 xppdd->frontend_state = frontend_state_set;
490 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
491 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
493 remaining = maximum_wait_ms;
495 while (xppdd->backend_state != backend_state_response)
496 {
497 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
498 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
499 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
500 {
501 /* it's possible that the workitems are blocked because the pagefile isn't available. Lets just re-read the backend value for now */
502 XenPci_UpdateBackendState(device);
503 remaining -= thiswait;
504 if (remaining == 0)
505 {
506 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
507 return STATUS_UNSUCCESSFUL;
508 }
509 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
510 }
511 }
512 FUNCTION_EXIT();
513 return STATUS_SUCCESS;
514 }
516 static NTSTATUS
517 XenPci_XenConfigDevice(WDFDEVICE device);
519 static NTSTATUS
520 XenPci_XenShutdownDevice(PVOID context)
521 {
522 WDFDEVICE device = context;
523 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
524 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
525 PUCHAR in_ptr;
526 ULONG i;
527 UCHAR type;
528 PVOID setting;
529 PVOID value;
530 PVOID value2;
532 FUNCTION_ENTER();
534 if (xppdd->backend_state == XenbusStateConnected)
535 {
536 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
537 if (xppdd->backend_state == XenbusStateClosing)
538 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
539 if (xppdd->backend_state == XenbusStateClosed)
540 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
541 }
542 else
543 {
544 if (xppdd->backend_state == XenbusStateClosing)
545 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
546 }
548 if (xppdd->assigned_resources_start != NULL)
549 {
550 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
551 in_ptr = xppdd->assigned_resources_start;
552 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
553 {
554 switch (type)
555 {
556 case XEN_INIT_TYPE_RING: /* frontend ring */
557 FreePages(value);
558 break;
559 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
560 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
561 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
562 EvtChn_Unbind(xpdd, PtrToUlong(value));
563 EvtChn_Close(xpdd, PtrToUlong(value));
564 break;
565 case XEN_INIT_TYPE_GRANT_ENTRIES:
566 for (i = 0; i < PtrToUlong(setting); i++)
567 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value)[i], FALSE);
568 break;
569 }
570 }
571 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
572 xppdd->assigned_resources_start = NULL;
573 }
575 FUNCTION_EXIT();
577 return STATUS_SUCCESS;
578 }
580 struct dummy_sring {
581 RING_IDX req_prod, req_event;
582 RING_IDX rsp_prod, rsp_event;
583 uint8_t pad[48];
584 };
586 static NTSTATUS
587 XenPci_XenConfigDeviceSpecifyBuffers(WDFDEVICE device, PUCHAR src, PUCHAR dst)
588 {
589 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
590 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
591 NTSTATUS status = STATUS_SUCCESS;
592 ULONG i;
593 char path[128];
594 PCHAR setting, value;
595 PCHAR res;
596 PVOID address;
597 UCHAR type;
598 PUCHAR in_ptr;
599 PUCHAR out_ptr;
600 XENPCI_VECTORS vectors;
601 ULONG event_channel;
602 ULONG run_type = 0;
603 PMDL ring;
604 grant_ref_t gref;
605 BOOLEAN done_xenbus_init = FALSE;
606 PVOID value2;
608 FUNCTION_ENTER();
610 in_ptr = src;
611 out_ptr = dst;
613 // always add vectors
614 vectors.magic = XEN_DATA_MAGIC;
615 vectors.length = sizeof(XENPCI_VECTORS);
616 vectors.context = device;
617 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
618 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
619 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
620 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
621 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
622 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
623 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
624 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
625 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
626 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
627 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
628 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
629 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
630 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
631 RtlStringCbCopyA(vectors.path, 128, xppdd->path);
632 RtlStringCbCopyA(vectors.backend_path, 128, xppdd->backend_path);
633 //vectors.pdo_event_channel = xpdd->pdo_event_channel;
634 vectors.XenBus_Read = XenPci_XenBus_Read;
635 vectors.XenBus_Write = XenPci_XenBus_Write;
636 vectors.XenBus_Printf = XenPci_XenBus_Printf;
637 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
638 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
639 vectors.XenBus_List = XenPci_XenBus_List;
640 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
641 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
643 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
645 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
646 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
648 #if 0
649 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
650 {
651 BOOLEAN condition;
652 PCHAR xb_value;
653 switch (type)
654 {
655 case XEN_INIT_TYPE_MATCH_FRONT:
656 case XEN_INIT_TYPE_MATCH_BACK:
657 if (type == XEN_INIT_TYPE_MATCH_FRONT)
658 {
659 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
660 }
661 else
662 {
663 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
664 }
665 KdPrint((__DRIVER_NAME " testing path = %s\n", path));
666 res = XenBus_Read(xpdd, XBT_NIL, path, &xb_value);
667 if (res)
668 {
669 KdPrint((__DRIVER_NAME " read failed (%s)\n", res));
670 XenPci_FreeMem(res);
671 }
672 else
673 {
674 KdPrint((__DRIVER_NAME " testing %s vs %s\n", xb_value, value));
675 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_IF_MATCH)
676 condition = (strcmp(xb_value, value) == 0)?TRUE:FALSE;
677 else
678 condition = (strcmp(xb_value, value) != 0)?TRUE:FALSE;
679 KdPrint((__DRIVER_NAME " condition = %d\n", condition));
681 if ((PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_ONLY_IF_QEMU_HIDE) && qemu_protocol_version && condition)
682 condition = FALSE;
684 if (condition)
685 {
686 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_SET_INACTIVE)
687 {
688 active = FALSE;
689 KdPrint((__DRIVER_NAME " set inactive\n"));
690 }
691 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_DONT_CONFIG)
692 {
693 dont_config = TRUE;
694 KdPrint((__DRIVER_NAME " set inactive with dont config\n"));
695 }
696 }
697 XenPci_FreeMem(xb_value);
698 }
699 break;
700 }
701 }
702 if (dont_config)
703 {
704 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
705 FUNCTION_EXIT();
706 return status;
707 }
708 #endif
710 // first pass, possibly before state == Connected
711 in_ptr = src;
712 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
713 {
714 if (!done_xenbus_init)
715 {
716 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000) != STATUS_SUCCESS)
717 {
718 status = STATUS_UNSUCCESSFUL;
719 goto error;
720 }
721 done_xenbus_init = TRUE;
722 }
724 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
726 switch (type)
727 {
728 case XEN_INIT_TYPE_RUN:
729 run_type++;
730 break;
731 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
732 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
733 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
734 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
735 break;
736 case XEN_INIT_TYPE_RING: /* frontend ring */
737 /* we only allocate and do the SHARED_RING_INIT here */
738 if ((ring = AllocatePage()) != 0)
739 {
740 address = MmGetMdlVirtualAddress(ring);
741 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
742 SHARED_RING_INIT((struct dummy_sring *)address);
743 if ((gref = GntTbl_GrantAccess(
744 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
745 {
746 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
747 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
748 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
749 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
750 // add the grant entry too so it gets freed automatically
751 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
752 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
753 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
754 }
755 else
756 {
757 FreePages(ring);
758 status = STATUS_UNSUCCESSFUL;
759 goto error;
760 }
761 }
762 else
763 {
764 status = STATUS_UNSUCCESSFUL;
765 goto error;
766 }
767 break;
768 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
769 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
770 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
771 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
772 {
773 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
774 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
775 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
776 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
777 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
778 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
779 {
780 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
781 }
782 else if (type == XEN_INIT_TYPE_EVENT_CHANNEL_DPC)
783 {
784 #pragma warning(suppress:4055)
785 EvtChn_BindDpc(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
786 }
787 else
788 {
789 #pragma warning(suppress:4055)
790 EvtChn_Bind(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
791 }
792 }
793 else
794 {
795 status = STATUS_UNSUCCESSFUL;
796 goto error;
797 }
798 break;
799 }
800 }
801 if (!NT_SUCCESS(status))
802 {
803 goto error;
804 }
805 // If XEN_INIT_TYPE_RUN was specified more than once then we skip XenbusStateInitialised here and go straight to XenbusStateConnected at the end
806 if (run_type == 1)
807 {
808 if (XenPci_ChangeFrontendState(device, XenbusStateInitialised, XenbusStateConnected, 2000) != STATUS_SUCCESS)
809 {
810 status = STATUS_UNSUCCESSFUL;
811 goto error;
812 }
813 }
815 // second pass, possibly after state == Connected
816 in_ptr = src;
817 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
818 {
819 switch(type)
820 {
821 case XEN_INIT_TYPE_READ_STRING_BACK:
822 case XEN_INIT_TYPE_READ_STRING_FRONT:
823 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
824 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
825 else
826 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
827 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
828 if (res)
829 {
830 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
831 XenPci_FreeMem(res);
832 ADD_XEN_INIT_RSP(&out_ptr, type, setting, "", "");
833 }
834 else
835 {
836 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
837 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, value2);
838 XenPci_FreeMem(value);
839 }
840 break;
841 case XEN_INIT_TYPE_VECTORS:
842 // this is always done so ignore the request
843 break;
844 case XEN_INIT_TYPE_GRANT_ENTRIES:
845 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
846 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
847 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
848 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
849 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
850 for (i = 0; i < PtrToUlong(value); i++)
851 {
852 gref = GntTbl_GetRef(xpdd);
853 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
854 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
855 }
856 break;
857 }
858 }
859 if (qemu_hide_flags_value)
860 {
861 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_HIDE_FLAGS, NULL, UlongToPtr(qemu_hide_flags_value), NULL);
862 }
863 else
864 {
865 DECLARE_UNICODE_STRING_SIZE(my_device_name, 128);
867 RtlUnicodeStringPrintf(&my_device_name, L"#%S#", xppdd->device);
869 for (i = 0; i < WdfCollectionGetCount(qemu_hide_devices); i++)
870 {
871 WDFSTRING wdf_string = WdfCollectionGetItem(qemu_hide_devices, i);
872 UNICODE_STRING hide_device_name;
874 WdfStringGetUnicodeString(wdf_string, &hide_device_name);
876 if (RtlCompareUnicodeString(&hide_device_name, &my_device_name, TRUE) != 0)
877 {
878 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_HIDE_FILTER, NULL, NULL, NULL);
879 break;
880 }
881 }
882 }
884 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
886 if (run_type)
887 {
888 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 2000) != STATUS_SUCCESS)
889 {
890 status = STATUS_UNSUCCESSFUL;
891 goto error;
892 }
893 }
894 FUNCTION_EXIT();
895 return status;
897 error:
898 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000);
899 FUNCTION_EXIT_STATUS(status);
900 return status;
901 }
903 static NTSTATUS
904 XenPci_XenConfigDevice(WDFDEVICE device)
905 {
906 NTSTATUS status;
907 PUCHAR src, dst;
908 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
910 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
911 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
912 memcpy(src, dst, xppdd->config_page_length);
914 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
916 MmUnmapIoSpace(dst, xppdd->config_page_length);
917 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
919 return status;
920 }
922 static NTSTATUS
923 XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp)
924 {
925 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
926 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
927 PIO_STACK_LOCATION stack;
928 PCM_PARTIAL_RESOURCE_LIST prl;
929 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
930 ULONG i;
931 //char path[128];
932 //PMDL mdl;
934 FUNCTION_ENTER();
935 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
937 stack = IoGetCurrentIrpStackLocation(irp);
939 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
940 for (i = 0; i < prl->Count; i++)
941 {
942 prd = & prl->PartialDescriptors[i];
943 switch (prd->Type)
944 {
945 case CmResourceTypeMemory:
946 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
947 {
948 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
949 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
950 }
951 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
952 {
953 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
954 prd->Type = CmResourceTypeInterrupt;
955 prd->ShareDisposition = CmResourceShareShared;
956 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
957 prd->u.Interrupt.Level = 0; // Set group and level to zero (group = upper word)
958 prd->u.Interrupt.Level = xpdd->irq_number & 0xffff; // Only set the lower word
959 prd->u.Interrupt.Vector = xpdd->irq_number;
960 prd->u.Interrupt.Affinity = xpdd->irq_affinity; //KeQueryActiveProcessors();
961 xppdd->irq_number = xpdd->irq_number;
962 }
963 break;
964 }
965 }
967 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
968 for (i = 0; i < prl->Count; i++)
969 {
970 prd = & prl->PartialDescriptors[i];
971 switch (prd->Type)
972 {
973 case CmResourceTypeMemory:
974 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
975 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
976 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
977 {
978 if (prd->u.Memory.Length == 0)
979 {
980 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0]));
981 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
982 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
983 KdPrint((__DRIVER_NAME " New Start = %08x%08x, Length = %d\n", prd->u.Memory.Start.HighPart, prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
984 }
985 xppdd->config_page_phys = prd->u.Memory.Start;
986 xppdd->config_page_length = prd->u.Memory.Length;
987 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
988 //xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
990 #if 0
991 status = XenPci_XenConfigDevice(device);
992 if (!NT_SUCCESS(status))
993 {
994 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
995 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
996 FUNCTION_EXIT_STATUS(status);
997 return status;
998 }
999 #endif
1001 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
1003 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1004 prd->Type = CmResourceTypeInterrupt;
1005 prd->ShareDisposition = CmResourceShareShared;
1006 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
1007 prd->u.Interrupt.Level = 0; // Set group and level to zero (group = upper word)
1008 prd->u.Interrupt.Level = xpdd->irq_level & 0xffff; // Only set the lower word
1009 prd->u.Interrupt.Vector = xpdd->irq_vector;
1010 prd->u.Interrupt.Affinity = xpdd->irq_affinity; //KeQueryActiveProcessors();
1011 xppdd->irq_vector = xpdd->irq_vector;
1012 xppdd->irq_level = xpdd->irq_level;
1014 break;
1018 IoSkipCurrentIrpStackLocation(irp);
1020 FUNCTION_EXIT();
1022 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
1025 #if 0
1026 static NTSTATUS
1027 XenPciPdo_EvtDeviceResourcesQuery(WDFDEVICE device, WDFCMRESLIST resources)
1030 #endif
1032 static NTSTATUS
1033 XenPciPdo_EvtDeviceResourceRequirementsQuery(WDFDEVICE device, WDFIORESREQLIST requirements_list)
1035 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1036 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1037 WDFIORESLIST res_list;
1038 IO_RESOURCE_DESCRIPTOR ird;
1040 //FUNCTION_ENTER();
1042 WdfIoResourceRequirementsListSetInterfaceType(requirements_list, PNPBus);
1044 WdfIoResourceListCreate(requirements_list, WDF_NO_OBJECT_ATTRIBUTES, &res_list);
1045 ird.Option = 0;
1046 ird.Type = CmResourceTypeMemory;
1047 ird.ShareDisposition = CmResourceShareShared;
1048 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
1049 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
1050 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
1051 ird.u.Memory.Length = 0;
1052 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
1053 WdfIoResourceListAppendDescriptor(res_list, &ird);
1055 ird.Option = 0;
1056 ird.Type = CmResourceTypeMemory;
1057 ird.ShareDisposition = CmResourceShareShared;
1058 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
1059 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
1060 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
1061 ird.u.Memory.Length = 0;
1062 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
1063 WdfIoResourceListAppendDescriptor(res_list, &ird);
1065 WdfIoResourceRequirementsListAppendIoResList(requirements_list, res_list);
1067 //FUNCTION_EXIT();
1069 return STATUS_SUCCESS;
1072 NTSTATUS
1073 XenPciPdo_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
1075 NTSTATUS status = STATUS_SUCCESS;
1076 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1077 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1078 CHAR path[128];
1080 FUNCTION_ENTER();
1082 switch (previous_state)
1084 case WdfPowerDeviceD0:
1085 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1086 break;
1087 case WdfPowerDeviceD1:
1088 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1089 break;
1090 case WdfPowerDeviceD2:
1091 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
1092 break;
1093 case WdfPowerDeviceD3:
1094 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
1095 break;
1096 case WdfPowerDeviceD3Final:
1097 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
1098 break;
1099 case WdfPowerDevicePrepareForHibernation:
1100 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
1101 break;
1102 default:
1103 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
1104 break;
1107 if (previous_state == WdfPowerDevicePrepareForHibernation
1108 || (previous_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
1110 KdPrint((__DRIVER_NAME " starting up from hibernation\n"));
1112 else
1116 if (previous_state == WdfPowerDevicePrepareForHibernation || previous_state == WdfPowerDeviceD3 || previous_state == WdfPowerDeviceD3Final)
1118 xppdd->requested_resources_ptr = xppdd->requested_resources_start;
1119 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
1122 XenConfig_InitConfigPage(device);
1124 status = XenPci_GetBackendAndAddWatch(device);
1125 if (!NT_SUCCESS(status))
1127 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
1128 FUNCTION_EXIT_STATUS(status);
1129 return status;
1131 status = XenPci_XenConfigDevice(device);
1132 if (!NT_SUCCESS(status))
1134 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1135 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
1136 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
1137 FUNCTION_EXIT_STATUS(status);
1138 return status;
1141 FUNCTION_EXIT();
1143 return status;
1146 NTSTATUS
1147 XenPciPdo_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
1149 NTSTATUS status = STATUS_SUCCESS;
1150 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1151 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1152 char path[128];
1154 UNREFERENCED_PARAMETER(device);
1155 UNREFERENCED_PARAMETER(target_state);
1157 FUNCTION_ENTER();
1159 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
1162 switch (target_state)
1164 case WdfPowerDeviceD0:
1165 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1166 break;
1167 case WdfPowerDeviceD1:
1168 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1169 break;
1170 case WdfPowerDeviceD2:
1171 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
1172 break;
1173 case WdfPowerDeviceD3:
1174 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
1175 break;
1176 case WdfPowerDeviceD3Final:
1177 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
1178 break;
1179 case WdfPowerDevicePrepareForHibernation:
1180 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
1181 break;
1182 default:
1183 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
1184 break;
1187 if (target_state == WdfPowerDevicePrepareForHibernation
1188 || (target_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
1190 KdPrint((__DRIVER_NAME " not powering down as we are hibernating\n"));
1192 else
1194 status = XenPci_XenShutdownDevice(device);
1197 /* Remove watch on backend state */
1198 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1199 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
1201 FUNCTION_EXIT();
1203 return status;
1206 NTSTATUS
1207 XenPciPdo_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
1209 NTSTATUS status = STATUS_SUCCESS;
1211 UNREFERENCED_PARAMETER(device);
1212 UNREFERENCED_PARAMETER(resources_raw);
1213 UNREFERENCED_PARAMETER(resources_translated);
1215 FUNCTION_ENTER();
1216 FUNCTION_EXIT();
1218 return status;
1221 NTSTATUS
1222 XenPciPdo_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
1224 NTSTATUS status = STATUS_SUCCESS;
1226 UNREFERENCED_PARAMETER(device);
1227 UNREFERENCED_PARAMETER(resources_translated);
1229 FUNCTION_ENTER();
1230 FUNCTION_EXIT();
1232 return status;
1235 static VOID
1236 XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
1238 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1240 FUNCTION_ENTER();
1242 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
1243 switch (notification_type)
1245 case WdfSpecialFilePaging:
1246 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
1247 break;
1248 case WdfSpecialFileHibernation:
1249 xppdd->hiber_usage_kludge = is_in_notification_path;
1250 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
1251 break;
1252 case WdfSpecialFileDump:
1253 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
1254 break;
1255 default:
1256 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
1257 break;
1260 FUNCTION_EXIT();
1263 NTSTATUS
1264 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
1265 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
1266 PWDFDEVICE_INIT child_init)
1268 NTSTATUS status = STATUS_SUCCESS;
1269 WDF_OBJECT_ATTRIBUTES child_attributes;
1270 WDFDEVICE child_device;
1271 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
1272 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
1273 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
1274 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
1275 PXENPCI_PDO_DEVICE_DATA xppdd;
1276 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
1277 WDF_QUERY_INTERFACE_CONFIG interface_config;
1278 BUS_INTERFACE_STANDARD bus_interface;
1279 WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
1280 WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
1281 UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
1282 WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
1284 FUNCTION_ENTER();
1286 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
1288 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
1289 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
1290 //child_pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPciPdo_EvtDeviceD0EntryPostInterruptsEnabled;
1291 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
1292 //child_pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPciPdo_EvtDeviceD0ExitPreInterruptsDisabled;
1293 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenPciPdo_EvtDevicePrepareHardware;
1294 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenPciPdo_EvtDeviceReleaseHardware;
1295 child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
1296 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
1298 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
1299 identification->device, identification->index, identification->path));
1301 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
1302 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
1303 if (!NT_SUCCESS(status))
1305 return status;
1308 WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
1309 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
1310 pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
1311 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
1312 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
1313 WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
1315 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
1316 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
1317 if (!NT_SUCCESS(status))
1319 return status;
1321 status = WdfPdoInitAddHardwareID(child_init, &buffer);
1322 if (!NT_SUCCESS(status))
1324 return status;
1326 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
1327 if (!NT_SUCCESS(status))
1329 return status;
1332 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
1333 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
1334 if (!NT_SUCCESS(status))
1336 return status;
1339 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
1340 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
1341 if (!NT_SUCCESS(status))
1343 return status;
1345 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
1347 WdfDeviceInitSetPowerNotPageable(child_init);
1349 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
1350 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
1351 if (!NT_SUCCESS(status))
1353 return status;
1356 xppdd = GetXppdd(child_device);
1358 xppdd->wdf_device = child_device;
1359 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
1361 xppdd->config_page_mdl = AllocateUncachedPage();
1363 xppdd->device_state.magic = XEN_DEVICE_STATE_MAGIC;
1364 xppdd->device_state.length = sizeof(XENPCI_DEVICE_STATE);
1365 xppdd->device_state.suspend_resume_state_pdo = SR_STATE_RUNNING;
1366 xppdd->device_state.suspend_resume_state_fdo = SR_STATE_RUNNING;
1367 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
1368 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
1369 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
1370 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
1372 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
1373 child_pnp_capabilities.LockSupported = WdfFalse;
1374 child_pnp_capabilities.EjectSupported = WdfTrue;
1375 child_pnp_capabilities.Removable = WdfTrue;
1376 child_pnp_capabilities.DockDevice = WdfFalse;
1377 child_pnp_capabilities.UniqueID = WdfFalse;
1378 child_pnp_capabilities.SilentInstall = WdfTrue;
1379 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
1380 child_pnp_capabilities.HardwareDisabled = WdfFalse;
1381 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
1383 WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
1384 child_power_capabilities.DeviceD1 = WdfTrue;
1385 child_power_capabilities.WakeFromD1 = WdfTrue;
1386 child_power_capabilities.DeviceWake = PowerDeviceD1;
1387 child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
1388 child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
1389 child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
1390 child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
1391 child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
1392 child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
1393 WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
1395 bus_interface.Size = sizeof(BUS_INTERFACE_STANDARD);
1396 bus_interface.Version = 1; //BUS_INTERFACE_STANDARD_VERSION;
1397 bus_interface.Context = xppdd;
1398 bus_interface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
1399 bus_interface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
1400 bus_interface.TranslateBusAddress = XenPci_BIS_TranslateBusAddress;
1401 bus_interface.GetDmaAdapter = XenPci_BIS_GetDmaAdapter;
1402 bus_interface.SetBusData = XenPci_BIS_SetBusData;
1403 bus_interface.GetBusData = XenPci_BIS_GetBusData;
1404 WDF_QUERY_INTERFACE_CONFIG_INIT(&interface_config, (PINTERFACE)&bus_interface, &GUID_BUS_INTERFACE_STANDARD, NULL);
1405 status = WdfDeviceAddQueryInterface(child_device, &interface_config);
1406 if (!NT_SUCCESS(status))
1408 return status;
1411 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
1412 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
1413 xppdd->index = identification->index;
1414 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
1415 ExInitializeFastMutex(&xppdd->backend_state_mutex);
1416 xppdd->backend_state = XenbusStateUnknown;
1417 xppdd->frontend_state = XenbusStateUnknown;
1418 xppdd->backend_path[0] = '\0';
1420 FUNCTION_EXIT();
1422 return status;
1425 static __forceinline VOID
1426 XenPci_Pdo_ChangeSuspendState(WDFDEVICE device, ULONG new_state)
1428 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1429 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1431 FUNCTION_ENTER();
1432 KdPrint((__DRIVER_NAME " setting pdo state to %d\n", new_state));
1433 xppdd->device_state.suspend_resume_state_pdo = new_state;
1434 KeMemoryBarrier();
1435 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xpdd->pdo_event_channel));
1436 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
1437 while(xppdd->device_state.suspend_resume_state_fdo != xppdd->device_state.suspend_resume_state_pdo)
1439 KdPrint((__DRIVER_NAME " waiting...\n"));
1440 KeWaitForSingleObject(&xpdd->pdo_suspend_event, Executive, KernelMode, FALSE, NULL);
1442 KdPrint((__DRIVER_NAME " fdo state set to %d\n", new_state));
1443 FUNCTION_EXIT();
1446 /* called at PASSIVE_LEVEL */
1447 NTSTATUS
1448 XenPci_Pdo_Suspend(WDFDEVICE device)
1450 NTSTATUS status = STATUS_SUCCESS;
1451 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1452 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1453 //LARGE_INTEGER wait_time;
1454 char path[128];
1455 PUCHAR in_ptr;
1456 UCHAR type;
1457 PVOID setting;
1458 PVOID value;
1459 PVOID value2;
1461 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
1463 if (xppdd->backend_state == XenbusStateConnected)
1465 xppdd->restart_on_resume = TRUE;
1466 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_SUSPENDING);
1468 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
1469 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
1470 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
1472 if (xppdd->assigned_resources_start != NULL)
1474 in_ptr = xppdd->assigned_resources_ptr;
1475 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1476 in_ptr = xppdd->assigned_resources_start;
1477 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
1479 switch (type)
1481 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
1482 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
1483 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
1484 EvtChn_Unbind(xpdd, PtrToUlong(value));
1485 EvtChn_Close(xpdd, PtrToUlong(value));
1486 break;
1491 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1492 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, xppdd);
1494 else
1496 xppdd->restart_on_resume = FALSE;
1499 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1501 return status;
1504 NTSTATUS
1505 XenPci_Pdo_Resume(WDFDEVICE device)
1507 NTSTATUS status = STATUS_SUCCESS;
1508 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1509 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1510 ULONG old_backend_state;
1511 PUCHAR src, dst;
1513 FUNCTION_ENTER();
1514 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
1516 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
1517 old_backend_state = xppdd->backend_state;
1519 if (xppdd->restart_on_resume)
1521 status = XenPci_GetBackendAndAddWatch(device);
1523 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
1525 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
1526 // this is probably an unrecoverable situation...
1527 FUNCTION_EXIT();
1528 return STATUS_UNSUCCESSFUL;
1530 if (xppdd->assigned_resources_ptr)
1532 // reset things - feed the 'requested resources' back in
1533 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1534 src = xppdd->requested_resources_start;
1535 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
1536 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
1538 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
1540 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
1542 MmUnmapIoSpace(dst, xppdd->config_page_length);
1543 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
1545 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
1547 // this is definitely an unrecoverable situation...
1548 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
1549 FUNCTION_EXIT();
1550 return STATUS_UNSUCCESSFUL;
1552 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RESUMING);
1553 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RUNNING);
1556 FUNCTION_EXIT();
1558 return STATUS_SUCCESS;