win-pvdrivers

annotate xenpci/xenpci_pdo.c @ 1005:4f7d5a8636bd

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