win-pvdrivers

annotate xenpci/xenpci_pdo.c @ 1022:cd72cd0e1c19

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