win-pvdrivers

view xenpci/xenpci_pdo.c @ 1013:43e76afb2398

Fix compiler warnings under 2000
author James Harper <james.harper@bendigoit.com.au>
date Mon Feb 11 20:59:11 2013 +1100 (2013-02-11)
parents 9fb8690938b3
children df03fde445b8
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;
40 /*
41 Called at PASSIVE_LEVEL(?)
42 Called during restore
43 */
44 static ULONG
45 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
46 {
47 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
48 char path[128];
49 char *value;
50 char *err;
51 ULONG backend_state;
53 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
54 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
55 if (err)
56 {
57 XenPci_FreeMem(err);
58 return XenbusStateUnknown;
59 }
60 else
61 {
62 backend_state = atoi(value);
63 XenPci_FreeMem(value);
64 return backend_state;
65 }
66 }
68 static VOID
69 XenPci_UpdateBackendState(PVOID context)
70 {
71 WDFDEVICE device = context;
72 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
73 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
74 ULONG new_backend_state;
76 FUNCTION_ENTER();
78 ExAcquireFastMutex(&xppdd->backend_state_mutex);
80 new_backend_state = XenPci_ReadBackendState(xppdd);
81 if (new_backend_state == XenbusStateUnknown)
82 {
83 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
84 {
85 ExReleaseFastMutex(&xppdd->backend_state_mutex);
86 return;
87 }
88 KdPrint(("Failed to read path, assuming closed\n"));
89 new_backend_state = XenbusStateClosed;
90 }
92 if (xppdd->backend_state == new_backend_state)
93 {
94 KdPrint((__DRIVER_NAME " state unchanged\n"));
95 ExReleaseFastMutex(&xppdd->backend_state_mutex);
96 return;
97 }
99 xppdd->backend_state = new_backend_state;
101 switch (xppdd->backend_state)
102 {
103 case XenbusStateUnknown:
104 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
105 break;
107 case XenbusStateInitialising:
108 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
109 break;
111 case XenbusStateInitWait:
112 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
113 break;
115 case XenbusStateInitialised:
116 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
117 break;
119 case XenbusStateConnected:
120 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
121 break;
123 case XenbusStateClosing:
124 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
125 if (xppdd->frontend_state != XenbusStateClosing)
126 {
127 xppdd->backend_initiated_remove = TRUE;
128 KdPrint((__DRIVER_NAME " Requesting eject\n"));
129 WdfPdoRequestEject(device);
130 }
131 break;
133 case XenbusStateClosed:
134 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
135 break;
137 default:
138 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", xppdd->backend_state));
139 break;
140 }
142 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
144 ExReleaseFastMutex(&xppdd->backend_state_mutex);
145 FUNCTION_EXIT();
147 return;
148 }
150 static VOID
151 XenPci_BackendStateHandler(char *path, PVOID context)
152 {
153 UNREFERENCED_PARAMETER(path);
155 /* check that path == device/id/state */
156 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
158 XenPci_UpdateBackendState(context);
159 }
161 static NTSTATUS
162 XenPci_GetBackendDetails(WDFDEVICE device)
163 {
164 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
165 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
166 char path[128];
167 PCHAR res;
168 PCHAR value;
170 FUNCTION_ENTER();
171 /* Get backend path */
172 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
173 "%s/backend", xppdd->path);
174 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
175 if (res)
176 {
177 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
178 XenPci_FreeMem(res);
179 return STATUS_UNSUCCESSFUL;
180 }
181 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
182 XenPci_FreeMem(value);
184 /* Get backend id */
185 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
186 "%s/backend-id", xppdd->path);
187 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
188 if (res) {
189 KdPrint((__DRIVER_NAME " Failed to read backend id\n"));
190 XenPci_FreeMem(res);
191 return STATUS_UNSUCCESSFUL;
192 }
193 xppdd->backend_id = (domid_t)atoi(value);
194 XenPci_FreeMem(value);
195 FUNCTION_EXIT();
196 return STATUS_SUCCESS;
197 }
199 NTSTATUS
200 XenPci_SuspendPdo(WDFDEVICE device) {
201 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
202 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
203 PCHAR response;
204 CHAR path[128];
206 if (xppdd->device_callback) {
207 FUNCTION_MSG("Suspending %s\n", xppdd->device);
208 xppdd->device_callback(xppdd->device_callback_context, XN_DEVICE_CALLBACK_SUSPEND, NULL);
209 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
210 response = XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateCallback, xppdd);
211 if (response) {
212 FUNCTION_MSG("XnRemWatch - %s = %s\n", path, response);
213 XenPci_FreeMem(response);
214 }
215 }
216 return STATUS_SUCCESS;
217 }
219 NTSTATUS
220 XenPci_ResumePdo(WDFDEVICE device) {
221 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
222 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
223 PCHAR response;
224 CHAR path[128];
226 XenPci_GetBackendDetails(device);
227 if (xppdd->device_callback) {
228 FUNCTION_MSG("Resuming %s\n", xppdd->device);
229 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
230 response = XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackendStateCallback, xppdd);
231 if (response) {
232 FUNCTION_MSG("XnAddWatch - %s = %s\n", path, response);
233 XenPci_FreeMem(response);
234 xppdd->device_callback = NULL;
235 xppdd->device_callback_context = NULL;
236 FUNCTION_EXIT();
237 return STATUS_UNSUCCESSFUL;
238 }
239 xppdd->device_callback(xppdd->device_callback_context, XN_DEVICE_CALLBACK_RESUME, NULL);
240 }
241 return STATUS_SUCCESS;
242 }
244 NTSTATUS
245 XenPciPdo_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
246 {
247 NTSTATUS status = STATUS_SUCCESS;
248 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
249 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
250 CHAR path[128];
252 FUNCTION_ENTER();
253 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
255 switch (previous_state)
256 {
257 case WdfPowerDeviceD0:
258 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
259 break;
260 case WdfPowerDeviceD1:
261 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
262 break;
263 case WdfPowerDeviceD2:
264 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
265 break;
266 case WdfPowerDeviceD3:
267 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
268 if (xppdd->hiber_usage_kludge)
269 {
270 KdPrint((__DRIVER_NAME " (but really WdfPowerDevicePrepareForHibernation)\n"));
271 previous_state = WdfPowerDevicePrepareForHibernation;
272 }
273 break;
274 case WdfPowerDeviceD3Final:
275 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
276 break;
277 case WdfPowerDevicePrepareForHibernation:
278 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
279 break;
280 default:
281 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
282 break;
283 }
285 status = XenPci_GetBackendDetails(device);
286 if (!NT_SUCCESS(status))
287 {
288 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
289 FUNCTION_EXIT_STATUS(status);
290 return status;
291 }
293 if (previous_state == WdfPowerDeviceD3 || previous_state == WdfPowerDeviceD3Final)
294 {
295 #if 0
296 xppdd->requested_resources_ptr = xppdd->requested_resources_start;
297 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
298 XenConfig_InitConfigPage(device);
299 status = XenPci_XenConfigDevice(device);
300 #endif
301 }
302 else if (previous_state == WdfPowerDevicePrepareForHibernation)
303 {
304 #if 0
305 PVOID src, dst;
307 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
308 src = xppdd->requested_resources_start;
309 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
310 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
312 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
314 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
316 MmUnmapIoSpace(dst, xppdd->config_page_length);
317 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
318 #endif
319 }
321 if (!NT_SUCCESS(status))
322 {
323 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
324 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
325 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
326 FUNCTION_EXIT_STATUS(status);
327 return status;
328 }
330 FUNCTION_EXIT();
332 return status;
333 }
335 NTSTATUS
336 XenPciPdo_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
337 {
338 NTSTATUS status = STATUS_SUCCESS;
339 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
340 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
341 char path[128];
343 UNREFERENCED_PARAMETER(device);
344 UNREFERENCED_PARAMETER(target_state);
346 FUNCTION_ENTER();
347 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
349 switch (target_state)
350 {
351 case WdfPowerDeviceD0:
352 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
353 break;
354 case WdfPowerDeviceD1:
355 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
356 break;
357 case WdfPowerDeviceD2:
358 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
359 break;
360 case WdfPowerDeviceD3:
361 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
362 if (xppdd->hiber_usage_kludge)
363 {
364 KdPrint((__DRIVER_NAME " (but really WdfPowerDevicePrepareForHibernation)\n"));
365 target_state = WdfPowerDevicePrepareForHibernation;
366 }
367 break;
368 case WdfPowerDeviceD3Final:
369 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
370 break;
371 case WdfPowerDevicePrepareForHibernation:
372 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
373 break;
374 default:
375 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
376 break;
377 }
379 if (target_state == WdfPowerDevicePrepareForHibernation)
380 {
381 KdPrint((__DRIVER_NAME " not powering down as we are hibernating\n"));
382 // should we set the backend state here so it's correct on resume???
383 }
384 else
385 {
386 #if 0
387 status = XenPci_XenShutdownDevice(device);
388 #endif
389 }
391 /* Remove watch on backend state */
392 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
393 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
395 FUNCTION_EXIT();
397 return status;
398 }
400 NTSTATUS
401 XenPciPdo_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
402 {
403 NTSTATUS status = STATUS_SUCCESS;
405 UNREFERENCED_PARAMETER(device);
406 UNREFERENCED_PARAMETER(resources_raw);
407 UNREFERENCED_PARAMETER(resources_translated);
409 FUNCTION_ENTER();
410 FUNCTION_EXIT();
412 return status;
413 }
415 NTSTATUS
416 XenPciPdo_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
417 {
418 NTSTATUS status = STATUS_SUCCESS;
420 UNREFERENCED_PARAMETER(device);
421 UNREFERENCED_PARAMETER(resources_translated);
423 FUNCTION_ENTER();
424 FUNCTION_EXIT();
426 return status;
427 }
429 static VOID
430 XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
431 {
432 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
434 FUNCTION_ENTER();
436 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
437 switch (notification_type)
438 {
439 case WdfSpecialFilePaging:
440 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
441 break;
442 case WdfSpecialFileHibernation:
443 xppdd->hiber_usage_kludge = is_in_notification_path;
444 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
445 break;
446 case WdfSpecialFileDump:
447 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
448 break;
449 default:
450 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
451 break;
452 }
454 FUNCTION_EXIT();
455 }
457 static VOID
458 XenPci_EvtDevicePnpStateChange(WDFDEVICE device, PCWDF_DEVICE_PNP_NOTIFICATION_DATA notification_data)
459 {
460 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
462 //FUNCTION_ENTER();
464 if (xppdd->backend_initiated_remove
465 && notification_data->Type == StateNotificationEnterState
466 && notification_data->Data.EnterState.CurrentState == WdfDevStatePnpQueryRemovePending
467 && notification_data->Data.EnterState.NewState == WdfDevStatePnpQueryCanceled)
468 {
469 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
471 KdPrint((__DRIVER_NAME " Eject failed, doing surprise removal\n"));
472 xppdd->do_not_enumerate = TRUE;
473 XenPci_EvtChildListScanForChildren(xpdd->child_list);
474 }
476 //FUNCTION_EXIT();
478 //return STATUS_SUCCESS;
479 }
481 NTSTATUS
482 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
483 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
484 PWDFDEVICE_INIT child_init) {
485 NTSTATUS status = STATUS_SUCCESS;
486 WDF_OBJECT_ATTRIBUTES child_attributes;
487 WDFDEVICE child_device;
488 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
489 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
490 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
491 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
492 PXENPCI_PDO_DEVICE_DATA xppdd;
493 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
494 //WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
495 WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
496 //UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
497 WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
499 FUNCTION_ENTER();
501 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
503 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
504 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
505 //child_pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPciPdo_EvtDeviceD0EntryPostInterruptsEnabled;
506 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
507 //child_pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPciPdo_EvtDeviceD0ExitPreInterruptsDisabled;
508 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenPciPdo_EvtDevicePrepareHardware;
509 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenPciPdo_EvtDeviceReleaseHardware;
510 child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
511 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
513 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
514 identification->device, identification->index, identification->path));
516 //status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
517 // IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
518 //if (!NT_SUCCESS(status)) {
519 // return status;
520 //}
522 //WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
523 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
524 //pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
525 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
526 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
527 //WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
529 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
530 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
531 if (!NT_SUCCESS(status))
532 {
533 return status;
534 }
535 status = WdfPdoInitAddHardwareID(child_init, &buffer);
536 if (!NT_SUCCESS(status))
537 {
538 return status;
539 }
540 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
541 if (!NT_SUCCESS(status))
542 {
543 return status;
544 }
546 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
547 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
548 if (!NT_SUCCESS(status))
549 {
550 return status;
551 }
553 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
554 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
555 if (!NT_SUCCESS(status))
556 {
557 return status;
558 }
559 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
561 WdfDeviceInitSetPowerNotPageable(child_init);
563 WdfDeviceInitRegisterPnpStateChangeCallback(child_init, WdfDevStatePnpQueryCanceled, XenPci_EvtDevicePnpStateChange, StateNotificationEnterState);
565 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
566 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
567 if (!NT_SUCCESS(status))
568 {
569 return status;
570 }
572 xppdd = GetXppdd(child_device);
574 xppdd->wdf_device = child_device;
575 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
576 xppdd->xpdd = xpdd;
578 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
579 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
580 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
582 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
583 child_pnp_capabilities.LockSupported = WdfFalse;
584 child_pnp_capabilities.EjectSupported = WdfTrue;
585 child_pnp_capabilities.Removable = WdfTrue;
586 child_pnp_capabilities.DockDevice = WdfFalse;
587 child_pnp_capabilities.UniqueID = WdfFalse;
588 child_pnp_capabilities.SilentInstall = WdfTrue;
589 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
590 child_pnp_capabilities.HardwareDisabled = WdfFalse;
591 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
593 WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
594 child_power_capabilities.DeviceD1 = WdfTrue;
595 child_power_capabilities.WakeFromD1 = WdfTrue;
596 child_power_capabilities.DeviceWake = PowerDeviceD1;
597 child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD0;
598 child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
599 child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
600 child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
601 child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
602 child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
603 WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
605 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
606 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
607 xppdd->index = identification->index;
608 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
609 ExInitializeFastMutex(&xppdd->backend_state_mutex);
610 xppdd->backend_state = XenbusStateUnknown;
611 xppdd->frontend_state = XenbusStateUnknown;
612 xppdd->backend_path[0] = '\0';
613 xppdd->backend_id = 0;
615 FUNCTION_EXIT();
617 return status;