win-pvdrivers

annotate xenpci/xenpci_pdo.c @ 1019:df03fde445b8

tidyup xenpci
author James Harper <james.harper@bendigoit.com.au>
date Tue Feb 12 20:45:25 2013 +1100 (2013-02-12)
parents 9fb8690938b3
children cd72cd0e1c19
rev   line source
james@259 1 /*
james@259 2 PV Drivers for Windows Xen HVM Domains
james@259 3 Copyright (C) 2007 James Harper
james@259 4
james@259 5 This program is free software; you can redistribute it and/or
james@259 6 modify it under the terms of the GNU General Public License
james@259 7 as published by the Free Software Foundation; either version 2
james@259 8 of the License, or (at your option) any later version.
james@259 9
james@259 10 This program is distributed in the hope that it will be useful,
james@259 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
james@259 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
james@259 13 GNU General Public License for more details.
james@259 14
james@259 15 You should have received a copy of the GNU General Public License
james@259 16 along with this program; if not, write to the Free Software
james@259 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
james@259 18 */
james@259 19
james@259 20 #include "xenpci.h"
james@259 21 #include <stdlib.h>
james@267 22 #include <io/ring.h>
james@259 23
james@259 24 #pragma warning(disable : 4200) // zero-sized array
james@267 25 #pragma warning(disable: 4127) // conditional expression is constant
james@259 26
james@716 27 /* Not really necessary but keeps PREfast happy */
james@716 28 static EVT_WDF_INTERRUPT_SYNCHRONIZE XenPci_EvtChn_Sync_Routine;
james@716 29 static EVT_WDF_DEVICE_D0_ENTRY XenPciPdo_EvtDeviceD0Entry;
james@716 30 static EVT_WDF_DEVICE_D0_EXIT XenPciPdo_EvtDeviceD0Exit;
james@716 31 static EVT_WDF_DEVICE_USAGE_NOTIFICATION XenPciPdo_EvtDeviceUsageNotification;
james@818 32 static EVT_WDF_DEVICE_PNP_STATE_CHANGE_NOTIFICATION XenPci_EvtDevicePnpStateChange;
james@716 33
james@1005 34
james@1005 35
james@536 36 /*
james@536 37 Called at PASSIVE_LEVEL(?)
james@536 38 Called during restore
james@536 39 */
james@536 40 static ULONG
james@536 41 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
james@536 42 {
james@536 43 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 44 char path[128];
james@536 45 char *value;
james@536 46 char *err;
james@536 47 ULONG backend_state;
james@536 48
james@536 49 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@536 50 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@536 51 if (err)
james@536 52 {
james@536 53 XenPci_FreeMem(err);
james@536 54 return XenbusStateUnknown;
james@536 55 }
james@536 56 else
james@536 57 {
james@536 58 backend_state = atoi(value);
james@536 59 XenPci_FreeMem(value);
james@536 60 return backend_state;
james@536 61 }
james@536 62 }
james@536 63
james@536 64 static NTSTATUS
james@1004 65 XenPci_GetBackendDetails(WDFDEVICE device)
james@536 66 {
james@536 67 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 68 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 69 char path[128];
james@536 70 PCHAR res;
james@536 71 PCHAR value;
james@536 72
james@624 73 FUNCTION_ENTER();
james@536 74 /* Get backend path */
james@536 75 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
james@536 76 "%s/backend", xppdd->path);
james@536 77 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@536 78 if (res)
james@536 79 {
james@536 80 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
james@536 81 XenPci_FreeMem(res);
james@536 82 return STATUS_UNSUCCESSFUL;
james@536 83 }
james@536 84 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
james@536 85 XenPci_FreeMem(value);
james@536 86
james@972 87 /* Get backend id */
james@972 88 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
james@972 89 "%s/backend-id", xppdd->path);
james@972 90 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@972 91 if (res) {
james@972 92 KdPrint((__DRIVER_NAME " Failed to read backend id\n"));
james@972 93 XenPci_FreeMem(res);
james@972 94 return STATUS_UNSUCCESSFUL;
james@972 95 }
james@976 96 xppdd->backend_id = (domid_t)atoi(value);
james@972 97 XenPci_FreeMem(value);
james@624 98 FUNCTION_EXIT();
james@536 99 return STATUS_SUCCESS;
james@536 100 }
james@536 101
james@1005 102 NTSTATUS
james@1005 103 XenPci_SuspendPdo(WDFDEVICE device) {
james@536 104 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@1005 105 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
james@1005 106 PCHAR response;
james@1005 107 CHAR path[128];
james@536 108
james@1005 109 if (xppdd->device_callback) {
james@1005 110 FUNCTION_MSG("Suspending %s\n", xppdd->device);
james@1005 111 xppdd->device_callback(xppdd->device_callback_context, XN_DEVICE_CALLBACK_SUSPEND, NULL);
james@1005 112 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@1005 113 response = XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateCallback, xppdd);
james@1005 114 if (response) {
james@1005 115 FUNCTION_MSG("XnRemWatch - %s = %s\n", path, response);
james@1005 116 XenPci_FreeMem(response);
james@536 117 }
james@536 118 }
james@536 119 return STATUS_SUCCESS;
james@536 120 }
james@536 121
james@1005 122 NTSTATUS
james@1005 123 XenPci_ResumePdo(WDFDEVICE device) {
james@536 124 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@1005 125 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
james@1005 126 PCHAR response;
james@1005 127 CHAR path[128];
james@536 128
james@1005 129 XenPci_GetBackendDetails(device);
james@1005 130 if (xppdd->device_callback) {
james@1005 131 FUNCTION_MSG("Resuming %s\n", xppdd->device);
james@1005 132 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@1005 133 response = XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackendStateCallback, xppdd);
james@1005 134 if (response) {
james@1005 135 FUNCTION_MSG("XnAddWatch - %s = %s\n", path, response);
james@1005 136 XenPci_FreeMem(response);
james@1005 137 xppdd->device_callback = NULL;
james@1005 138 xppdd->device_callback_context = NULL;
james@1005 139 FUNCTION_EXIT();
james@1005 140 return STATUS_UNSUCCESSFUL;
james@536 141 }
james@1005 142 xppdd->device_callback(xppdd->device_callback_context, XN_DEVICE_CALLBACK_RESUME, NULL);
james@536 143 }
james@538 144 return STATUS_SUCCESS;
james@538 145 }
james@538 146
james@538 147 NTSTATUS
james@1019 148 XenPciPdo_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state) {
james@538 149 NTSTATUS status = STATUS_SUCCESS;
james@551 150 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@1019 151 //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@551 152 CHAR path[128];
james@538 153
james@538 154 FUNCTION_ENTER();
james@812 155 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@538 156
james@1019 157 switch (previous_state) {
james@538 158 case WdfPowerDeviceD0:
james@538 159 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 160 break;
james@538 161 case WdfPowerDeviceD1:
james@538 162 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 163 break;
james@538 164 case WdfPowerDeviceD2:
james@538 165 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
james@538 166 break;
james@538 167 case WdfPowerDeviceD3:
james@538 168 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
james@1019 169 if (xppdd->hiber_usage_kludge) {
james@927 170 KdPrint((__DRIVER_NAME " (but really WdfPowerDevicePrepareForHibernation)\n"));
james@927 171 previous_state = WdfPowerDevicePrepareForHibernation;
james@927 172 }
james@538 173 break;
james@538 174 case WdfPowerDeviceD3Final:
james@538 175 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
james@538 176 break;
james@538 177 case WdfPowerDevicePrepareForHibernation:
james@538 178 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
james@538 179 break;
james@538 180 default:
james@538 181 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
james@538 182 break;
james@538 183 }
james@634 184
james@1004 185 status = XenPci_GetBackendDetails(device);
james@1019 186 if (!NT_SUCCESS(status)) {
james@551 187 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
james@702 188 FUNCTION_EXIT_STATUS(status);
james@551 189 return status;
james@551 190 }
james@832 191
james@1019 192 if (!NT_SUCCESS(status)) {
james@551 193 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@1019 194 //XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
james@551 195 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
james@702 196 FUNCTION_EXIT_STATUS(status);
james@551 197 return status;
james@551 198 }
james@538 199
james@536 200 FUNCTION_EXIT();
james@536 201
james@538 202 return status;
james@538 203 }
james@538 204
james@538 205 NTSTATUS
james@1019 206 XenPciPdo_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state) {
james@538 207 NTSTATUS status = STATUS_SUCCESS;
james@538 208 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@1019 209 //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@538 210 char path[128];
james@538 211
james@538 212 UNREFERENCED_PARAMETER(device);
james@538 213 UNREFERENCED_PARAMETER(target_state);
james@538 214
james@538 215 FUNCTION_ENTER();
james@538 216 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@538 217
james@1019 218 switch (target_state) {
james@538 219 case WdfPowerDeviceD0:
james@538 220 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 221 break;
james@538 222 case WdfPowerDeviceD1:
james@538 223 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 224 break;
james@538 225 case WdfPowerDeviceD2:
james@538 226 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
james@538 227 break;
james@538 228 case WdfPowerDeviceD3:
james@538 229 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
james@1019 230 if (xppdd->hiber_usage_kludge) {
james@927 231 KdPrint((__DRIVER_NAME " (but really WdfPowerDevicePrepareForHibernation)\n"));
james@927 232 target_state = WdfPowerDevicePrepareForHibernation;
james@927 233 }
james@538 234 break;
james@538 235 case WdfPowerDeviceD3Final:
james@538 236 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
james@538 237 break;
james@538 238 case WdfPowerDevicePrepareForHibernation:
james@538 239 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
james@538 240 break;
james@538 241 default:
james@538 242 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
james@538 243 break;
james@538 244 }
james@692 245
james@927 246 if (target_state == WdfPowerDevicePrepareForHibernation)
james@538 247 {
james@538 248 KdPrint((__DRIVER_NAME " not powering down as we are hibernating\n"));
james@927 249 // should we set the backend state here so it's correct on resume???
james@538 250 }
amir@679 251
amir@679 252 /* Remove watch on backend state */
amir@679 253 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@1019 254 //XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
james@538 255
james@538 256 FUNCTION_EXIT();
james@538 257
james@538 258 return status;
james@538 259 }
james@538 260
james@538 261 static VOID
james@538 262 XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
james@538 263 {
james@538 264 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@538 265
james@538 266 FUNCTION_ENTER();
james@538 267
james@538 268 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@538 269 switch (notification_type)
james@538 270 {
james@538 271 case WdfSpecialFilePaging:
james@538 272 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
james@538 273 break;
james@538 274 case WdfSpecialFileHibernation:
james@538 275 xppdd->hiber_usage_kludge = is_in_notification_path;
james@538 276 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
james@538 277 break;
james@538 278 case WdfSpecialFileDump:
james@538 279 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
james@538 280 break;
james@538 281 default:
james@538 282 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
james@538 283 break;
james@538 284 }
james@538 285
james@761 286 FUNCTION_EXIT();
james@536 287 }
james@536 288
james@818 289 static VOID
james@803 290 XenPci_EvtDevicePnpStateChange(WDFDEVICE device, PCWDF_DEVICE_PNP_NOTIFICATION_DATA notification_data)
james@803 291 {
james@803 292 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@803 293
james@803 294 //FUNCTION_ENTER();
james@803 295
james@803 296 if (xppdd->backend_initiated_remove
james@803 297 && notification_data->Type == StateNotificationEnterState
james@803 298 && notification_data->Data.EnterState.CurrentState == WdfDevStatePnpQueryRemovePending
james@803 299 && notification_data->Data.EnterState.NewState == WdfDevStatePnpQueryCanceled)
james@803 300 {
james@803 301 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@803 302
james@803 303 KdPrint((__DRIVER_NAME " Eject failed, doing surprise removal\n"));
james@803 304 xppdd->do_not_enumerate = TRUE;
james@803 305 XenPci_EvtChildListScanForChildren(xpdd->child_list);
james@803 306 }
james@803 307
james@803 308 //FUNCTION_EXIT();
james@803 309
james@818 310 //return STATUS_SUCCESS;
james@803 311 }
james@803 312
james@536 313 NTSTATUS
james@536 314 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
james@536 315 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
james@1005 316 PWDFDEVICE_INIT child_init) {
james@536 317 NTSTATUS status = STATUS_SUCCESS;
james@536 318 WDF_OBJECT_ATTRIBUTES child_attributes;
james@536 319 WDFDEVICE child_device;
james@536 320 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
james@536 321 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
james@536 322 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
james@536 323 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
james@536 324 PXENPCI_PDO_DEVICE_DATA xppdd;
james@1005 325 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
james@1005 326 //WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
james@538 327 WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
james@1005 328 //UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
james@538 329 WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
james@536 330
james@536 331 FUNCTION_ENTER();
james@536 332
james@536 333 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
james@536 334
james@536 335 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
james@536 336 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
james@536 337 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
james@538 338 child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
james@536 339 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
james@538 340
james@536 341 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
james@536 342 identification->device, identification->index, identification->path));
james@536 343
james@1005 344 //status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
james@1005 345 // IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
james@1005 346 //if (!NT_SUCCESS(status)) {
james@1005 347 // return status;
james@1005 348 //}
james@536 349
james@1005 350 //WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
james@536 351 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
james@1005 352 //pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
james@536 353 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
james@536 354 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
james@1005 355 //WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
james@536 356
james@536 357 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
james@536 358 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
james@536 359 if (!NT_SUCCESS(status))
james@536 360 {
james@536 361 return status;
james@536 362 }
james@536 363 status = WdfPdoInitAddHardwareID(child_init, &buffer);
james@536 364 if (!NT_SUCCESS(status))
james@536 365 {
james@536 366 return status;
james@536 367 }
james@536 368 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
james@536 369 if (!NT_SUCCESS(status))
james@536 370 {
james@536 371 return status;
james@536 372 }
james@536 373
james@536 374 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
james@536 375 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
james@536 376 if (!NT_SUCCESS(status))
james@536 377 {
james@536 378 return status;
james@536 379 }
james@536 380
james@536 381 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
james@536 382 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
james@536 383 if (!NT_SUCCESS(status))
james@536 384 {
james@536 385 return status;
james@536 386 }
james@536 387 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
james@538 388
james@538 389 WdfDeviceInitSetPowerNotPageable(child_init);
james@803 390
james@803 391 WdfDeviceInitRegisterPnpStateChangeCallback(child_init, WdfDevStatePnpQueryCanceled, XenPci_EvtDevicePnpStateChange, StateNotificationEnterState);
james@536 392
james@536 393 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
james@536 394 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
james@536 395 if (!NT_SUCCESS(status))
james@536 396 {
james@536 397 return status;
james@536 398 }
james@536 399
james@536 400 xppdd = GetXppdd(child_device);
james@536 401
james@536 402 xppdd->wdf_device = child_device;
james@536 403 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
james@1005 404 xppdd->xpdd = xpdd;
james@536 405
james@536 406 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
james@536 407 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
james@536 408 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
james@536 409
james@536 410 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
james@536 411 child_pnp_capabilities.LockSupported = WdfFalse;
james@536 412 child_pnp_capabilities.EjectSupported = WdfTrue;
james@536 413 child_pnp_capabilities.Removable = WdfTrue;
james@536 414 child_pnp_capabilities.DockDevice = WdfFalse;
james@536 415 child_pnp_capabilities.UniqueID = WdfFalse;
james@536 416 child_pnp_capabilities.SilentInstall = WdfTrue;
james@536 417 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
james@536 418 child_pnp_capabilities.HardwareDisabled = WdfFalse;
james@536 419 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
james@536 420
james@538 421 WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
james@538 422 child_power_capabilities.DeviceD1 = WdfTrue;
james@538 423 child_power_capabilities.WakeFromD1 = WdfTrue;
james@538 424 child_power_capabilities.DeviceWake = PowerDeviceD1;
james@912 425 child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD0;
james@538 426 child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
james@538 427 child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
james@538 428 child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
james@538 429 child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
james@538 430 child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
james@538 431 WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
james@536 432
james@536 433 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
james@536 434 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
james@536 435 xppdd->index = identification->index;
james@536 436 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
james@624 437 ExInitializeFastMutex(&xppdd->backend_state_mutex);
james@536 438 xppdd->backend_state = XenbusStateUnknown;
james@538 439 xppdd->frontend_state = XenbusStateUnknown;
james@536 440 xppdd->backend_path[0] = '\0';
james@972 441 xppdd->backend_id = 0;
james@536 442
james@536 443 FUNCTION_EXIT();
james@536 444
james@536 445 return status;
james@1005 446 }