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
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 } |