win-pvdrivers

annotate xenpci/xenpci_pdo.c @ 747:f43c89df09b2

Big changes to the way the device hiding works. Should fix the way Vista and above need a reboot into safe mode after install.
author James Harper <james.harper@bendigoit.com.au>
date Sun Jan 10 10:07:32 2010 +1100 (2010-01-10)
parents 5bdb7251370c
children acc551273d8b
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@716 34 static EVT_WDFDEVICE_WDM_IRP_PREPROCESS XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE;
james@716 35 static EVT_WDF_DEVICE_RESOURCE_REQUIREMENTS_QUERY XenPciPdo_EvtDeviceResourceRequirementsQuery;
james@716 36
james@536 37 /*
james@536 38 Called at PASSIVE_LEVEL(?)
james@536 39 Called during restore
james@536 40 */
james@536 41 static ULONG
james@536 42 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
james@536 43 {
james@536 44 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 45 char path[128];
james@536 46 char *value;
james@536 47 char *err;
james@536 48 ULONG backend_state;
james@536 49
james@536 50 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@536 51 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@536 52 if (err)
james@536 53 {
james@536 54 XenPci_FreeMem(err);
james@536 55 return XenbusStateUnknown;
james@536 56 }
james@536 57 else
james@536 58 {
james@536 59 backend_state = atoi(value);
james@536 60 XenPci_FreeMem(value);
james@536 61 return backend_state;
james@536 62 }
james@536 63 }
james@536 64
james@617 65 static NTSTATUS
james@617 66 XenPciPdo_ReconfigureCompletionRoutine(
james@617 67 PDEVICE_OBJECT device_object,
james@617 68 PIRP irp,
james@617 69 PVOID context)
james@617 70 {
james@617 71 UNREFERENCED_PARAMETER(device_object);
james@617 72
james@617 73 if (irp->PendingReturned)
james@617 74 {
james@617 75 KeSetEvent ((PKEVENT)context, IO_NO_INCREMENT, FALSE);
james@617 76 }
james@617 77 return STATUS_MORE_PROCESSING_REQUIRED;
james@617 78 }
james@617 79
james@536 80 static VOID
james@624 81 XenPci_UpdateBackendState(PVOID context)
james@536 82 {
james@536 83 WDFDEVICE device = context;
james@536 84 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 85 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 86 ULONG new_backend_state;
james@536 87
james@624 88 FUNCTION_ENTER();
james@536 89
james@624 90 ExAcquireFastMutex(&xppdd->backend_state_mutex);
james@624 91
james@536 92 new_backend_state = XenPci_ReadBackendState(xppdd);
james@536 93 if (new_backend_state == XenbusStateUnknown)
james@536 94 {
james@536 95 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
james@624 96 {
james@624 97 ExReleaseFastMutex(&xppdd->backend_state_mutex);
james@536 98 return;
james@624 99 }
james@624 100 KdPrint(("Failed to read path, assuming closed\n"));
james@536 101 new_backend_state = XenbusStateClosed;
james@536 102 }
james@536 103
james@536 104 if (xppdd->backend_state == new_backend_state)
james@536 105 {
james@536 106 KdPrint((__DRIVER_NAME " state unchanged\n"));
james@624 107 ExReleaseFastMutex(&xppdd->backend_state_mutex);
james@536 108 return;
james@536 109 }
james@536 110
james@536 111 xppdd->backend_state = new_backend_state;
james@536 112
james@536 113 switch (xppdd->backend_state)
james@536 114 {
james@536 115 case XenbusStateUnknown:
james@624 116 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
james@536 117 break;
james@536 118
james@536 119 case XenbusStateInitialising:
james@624 120 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
james@536 121 break;
james@536 122
james@536 123 case XenbusStateInitWait:
james@624 124 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
james@536 125 break;
james@536 126
james@536 127 case XenbusStateInitialised:
james@624 128 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
james@536 129 break;
james@536 130
james@536 131 case XenbusStateConnected:
james@624 132 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
james@536 133 break;
james@536 134
james@536 135 case XenbusStateClosing:
james@624 136 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
james@692 137 if (xppdd->frontend_state != XenbusStateClosing)
james@692 138 {
james@692 139 KdPrint((__DRIVER_NAME " Requesting eject\n"));
james@692 140 WdfPdoRequestEject(device);
james@692 141 }
james@536 142 break;
james@536 143
james@536 144 case XenbusStateClosed:
james@624 145 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
james@536 146 break;
james@617 147
james@536 148 default:
james@624 149 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", xppdd->backend_state));
james@536 150 break;
james@536 151 }
james@536 152
james@536 153 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
james@536 154
james@624 155 ExReleaseFastMutex(&xppdd->backend_state_mutex);
james@624 156 FUNCTION_EXIT();
james@536 157
james@536 158 return;
james@536 159 }
james@536 160
james@624 161 static VOID
james@624 162 XenPci_BackendStateHandler(char *path, PVOID context)
james@624 163 {
james@624 164 UNREFERENCED_PARAMETER(path);
james@624 165
james@624 166 /* check that path == device/id/state */
james@624 167 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
james@624 168
james@624 169 XenPci_UpdateBackendState(context);
james@624 170 }
james@624 171
james@536 172 static NTSTATUS
james@536 173 XenPci_GetBackendAndAddWatch(WDFDEVICE device)
james@536 174 {
james@536 175 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 176 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 177 char path[128];
james@536 178 PCHAR res;
james@536 179 PCHAR value;
james@536 180
james@624 181 FUNCTION_ENTER();
james@536 182 /* Get backend path */
james@536 183 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
james@536 184 "%s/backend", xppdd->path);
james@536 185 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@536 186 if (res)
james@536 187 {
james@536 188 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
james@536 189 XenPci_FreeMem(res);
james@536 190 return STATUS_UNSUCCESSFUL;
james@536 191 }
james@536 192 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
james@536 193 XenPci_FreeMem(value);
james@536 194
james@536 195 /* Add watch on backend state */
james@536 196 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@624 197 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
james@624 198
james@624 199 FUNCTION_EXIT();
james@536 200 return STATUS_SUCCESS;
james@536 201 }
james@536 202
james@551 203 static NTSTATUS
james@551 204 XenConfig_InitConfigPage(WDFDEVICE device)
james@536 205 {
james@551 206 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 207 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
james@536 208 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
james@536 209 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@536 210 PUCHAR ptr;
james@536 211 PDEVICE_OBJECT curr, prev;
james@536 212 PDRIVER_OBJECT fdo_driver_object;
james@536 213 PUCHAR fdo_driver_extension;
james@536 214
james@536 215 FUNCTION_ENTER();
james@536 216
james@551 217 ptr = MmGetMdlVirtualAddress(xppdd->config_page_mdl);
james@536 218 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(device));
james@536 219 //curr = WdfDeviceWdmGetAttachedDevice(device);
james@536 220 while (curr != NULL)
james@536 221 {
james@536 222 fdo_driver_object = curr->DriverObject;
james@536 223 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
james@536 224 if (fdo_driver_object)
james@536 225 {
james@536 226 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
james@536 227 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
james@536 228 if (fdo_driver_extension)
james@536 229 {
james@536 230 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
james@536 231 ObDereferenceObject(curr);
james@536 232 break;
james@536 233 }
james@536 234 }
james@536 235 prev = curr;
james@536 236 curr = IoGetLowerDeviceObject(curr);
james@536 237 ObDereferenceObject(prev);
james@536 238 }
james@536 239
james@536 240 FUNCTION_EXIT();
james@536 241
james@551 242 return STATUS_SUCCESS;
james@536 243 }
james@536 244
james@536 245 static NTSTATUS
james@536 246 XenPci_EvtChn_Bind(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
james@536 247 {
james@536 248 WDFDEVICE device = context;
james@536 249 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 250 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 251
james@536 252 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext);
james@536 253 }
james@536 254
james@536 255 static NTSTATUS
james@536 256 XenPci_EvtChn_BindDpc(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
james@536 257 {
james@536 258 WDFDEVICE device = context;
james@536 259 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 260 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 261
james@536 262 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext);
james@536 263 }
james@536 264
james@536 265 static NTSTATUS
james@536 266 XenPci_EvtChn_Unbind(PVOID context, evtchn_port_t Port)
james@536 267 {
james@536 268 WDFDEVICE device = context;
james@536 269 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 270 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 271
james@536 272 return EvtChn_Unbind(xpdd, Port);
james@536 273 }
james@536 274
james@536 275 static NTSTATUS
james@536 276 XenPci_EvtChn_Mask(PVOID context, evtchn_port_t Port)
james@536 277 {
james@536 278 WDFDEVICE device = context;
james@536 279 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 280 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 281
james@536 282 return EvtChn_Mask(xpdd, Port);
james@536 283 }
james@536 284
james@536 285 static NTSTATUS
james@536 286 XenPci_EvtChn_Unmask(PVOID context, evtchn_port_t Port)
james@536 287 {
james@536 288 WDFDEVICE device = context;
james@536 289 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 290 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 291
james@536 292 return EvtChn_Unmask(xpdd, Port);
james@536 293 }
james@536 294
james@536 295 static NTSTATUS
james@536 296 XenPci_EvtChn_Notify(PVOID context, evtchn_port_t Port)
james@536 297 {
james@536 298 WDFDEVICE device = context;
james@536 299 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 300 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 301
james@536 302 return EvtChn_Notify(xpdd, Port);
james@536 303 }
james@536 304
james@536 305 static BOOLEAN
james@561 306 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port, BOOLEAN *last_interrupt)
james@536 307 {
james@536 308 WDFDEVICE device = context;
james@536 309 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 310 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 311
james@561 312 return EvtChn_AckEvent(xpdd, port, last_interrupt);
james@536 313 }
james@536 314
james@536 315 typedef struct {
james@536 316 PXEN_EVTCHN_SYNC_ROUTINE sync_routine;
james@536 317 PVOID sync_context;
james@536 318 } sync_context_t;
james@536 319
james@536 320 static BOOLEAN
james@536 321 XenPci_EvtChn_Sync_Routine(WDFINTERRUPT interrupt, WDFCONTEXT context)
james@536 322 {
james@536 323 sync_context_t *wdf_sync_context = context;
james@536 324 UNREFERENCED_PARAMETER(interrupt);
james@536 325 return wdf_sync_context->sync_routine(wdf_sync_context->sync_context);
james@536 326 }
james@536 327
james@536 328 static BOOLEAN
james@536 329 XenPci_EvtChn_Sync(PVOID context, PXEN_EVTCHN_SYNC_ROUTINE sync_routine, PVOID sync_context)
james@536 330 {
james@536 331 WDFDEVICE device = context;
james@536 332 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 333 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 334 sync_context_t wdf_sync_context;
james@536 335
james@536 336 wdf_sync_context.sync_routine = sync_routine;
james@536 337 wdf_sync_context.sync_context = sync_context;
james@536 338
james@536 339 return WdfInterruptSynchronize(xpdd->interrupt, XenPci_EvtChn_Sync_Routine, &wdf_sync_context);
james@536 340 }
james@536 341
james@536 342 static grant_ref_t
james@536 343 XenPci_GntTbl_GrantAccess(PVOID context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref)
james@536 344 {
james@536 345 WDFDEVICE device = context;
james@536 346 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 347 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 348
james@536 349 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref);
james@536 350 }
james@536 351
james@536 352 static BOOLEAN
james@536 353 XenPci_GntTbl_EndAccess(PVOID context, grant_ref_t ref, BOOLEAN keepref)
james@536 354 {
james@536 355 WDFDEVICE device = context;
james@536 356 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 357 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 358
james@536 359 return GntTbl_EndAccess(xpdd, ref, keepref);
james@536 360 }
james@536 361
james@536 362 static VOID
james@536 363 XenPci_GntTbl_PutRef(PVOID context, grant_ref_t ref)
james@536 364 {
james@536 365 WDFDEVICE device = context;
james@536 366 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 367 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 368
james@536 369 GntTbl_PutRef(xpdd, ref);
james@536 370 }
james@536 371
james@536 372 static grant_ref_t
james@536 373 XenPci_GntTbl_GetRef(PVOID context)
james@536 374 {
james@536 375 WDFDEVICE device = context;
james@536 376 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 377 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 378
james@536 379 return GntTbl_GetRef(xpdd);
james@536 380 }
james@536 381
james@536 382 PCHAR
james@536 383 XenPci_XenBus_Read(PVOID context, xenbus_transaction_t xbt, char *path, char **value)
james@536 384 {
james@536 385 WDFDEVICE device = context;
james@536 386 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 387 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 388 return XenBus_Read(xpdd, xbt, path, value);
james@536 389 }
james@536 390
james@536 391 PCHAR
james@536 392 XenPci_XenBus_Write(PVOID context, xenbus_transaction_t xbt, char *path, char *value)
james@536 393 {
james@536 394 WDFDEVICE device = context;
james@536 395 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 396 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 397 return XenBus_Write(xpdd, xbt, path, value);
james@536 398 }
james@536 399
james@536 400 PCHAR
james@536 401 XenPci_XenBus_Printf(PVOID context, xenbus_transaction_t xbt, char *path, char *fmt, ...)
james@536 402 {
james@536 403 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@536 404 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@536 405 //return XenBus_Printf(xpdd, xbt, path, value);
james@536 406 UNREFERENCED_PARAMETER(context);
james@536 407 UNREFERENCED_PARAMETER(xbt);
james@536 408 UNREFERENCED_PARAMETER(path);
james@536 409 UNREFERENCED_PARAMETER(fmt);
james@536 410 return NULL;
james@536 411 }
james@536 412
james@536 413 PCHAR
james@536 414 XenPci_XenBus_StartTransaction(PVOID context, xenbus_transaction_t *xbt)
james@536 415 {
james@536 416 WDFDEVICE device = context;
james@536 417 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 418 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 419 return XenBus_StartTransaction(xpdd, xbt);
james@536 420 }
james@536 421
james@536 422 PCHAR
james@536 423 XenPci_XenBus_EndTransaction(PVOID context, xenbus_transaction_t xbt, int abort, int *retry)
james@536 424 {
james@536 425 WDFDEVICE device = context;
james@536 426 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 427 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 428 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
james@536 429 }
james@536 430
james@536 431 PCHAR
james@536 432 XenPci_XenBus_List(PVOID context, xenbus_transaction_t xbt, char *prefix, char ***contents)
james@536 433 {
james@536 434 WDFDEVICE device = context;
james@536 435 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 436 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 437 return XenBus_List(xpdd, xbt, prefix, contents);
james@536 438 }
james@536 439
james@536 440 PCHAR
james@536 441 XenPci_XenBus_AddWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
james@536 442 {
james@536 443 WDFDEVICE device = context;
james@536 444 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 445 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 446 PCHAR retval;
james@536 447
james@536 448 FUNCTION_ENTER();
james@536 449 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
james@536 450 if (retval == NULL)
james@536 451 {
james@536 452 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
james@536 453 }
james@536 454 else
james@536 455 {
james@536 456 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
james@536 457 }
james@536 458 FUNCTION_EXIT();
james@536 459 return retval;
james@536 460 }
james@536 461
james@536 462 PCHAR
james@536 463 XenPci_XenBus_RemWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
james@536 464 {
james@536 465 WDFDEVICE device = context;
james@536 466 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 467 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 468 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
james@536 469 }
james@536 470
james@536 471 /*
james@536 472 Called at PASSIVE_LEVEL
james@536 473 Called during restore
james@536 474 */
james@536 475
james@536 476 static NTSTATUS
james@536 477 XenPci_ChangeFrontendState(WDFDEVICE device, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
james@536 478 {
james@536 479 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 480 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 481 LARGE_INTEGER timeout;
james@536 482 ULONG remaining;
james@536 483 ULONG thiswait;
james@536 484 char path[128];
james@536 485
james@624 486 FUNCTION_ENTER();
james@538 487
james@538 488 xppdd->frontend_state = frontend_state_set;
james@536 489
james@536 490 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
james@536 491 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
james@536 492
james@536 493 remaining = maximum_wait_ms;
james@536 494
james@536 495 while (xppdd->backend_state != backend_state_response)
james@536 496 {
james@536 497 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
james@536 498 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
james@536 499 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
james@536 500 {
james@624 501 /* it's possible that the workitems are blocked because the pagefile isn't available. Lets just re-read the backend value for now */
james@624 502 XenPci_UpdateBackendState(device);
james@536 503 remaining -= thiswait;
james@536 504 if (remaining == 0)
james@536 505 {
james@536 506 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
james@536 507 return STATUS_UNSUCCESSFUL;
james@536 508 }
james@536 509 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
james@536 510 }
james@536 511 }
james@624 512 FUNCTION_EXIT();
james@536 513 return STATUS_SUCCESS;
james@536 514 }
james@536 515
james@536 516 static NTSTATUS
james@536 517 XenPci_XenConfigDevice(WDFDEVICE device);
james@536 518
james@536 519 static NTSTATUS
james@536 520 XenPci_XenShutdownDevice(PVOID context)
james@536 521 {
james@536 522 WDFDEVICE device = context;
james@536 523 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 524 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 525 PUCHAR in_ptr;
james@536 526 ULONG i;
james@536 527 UCHAR type;
james@536 528 PVOID setting;
james@536 529 PVOID value;
james@536 530 PVOID value2;
james@536 531
james@536 532 FUNCTION_ENTER();
james@536 533
james@536 534 if (xppdd->backend_state == XenbusStateConnected)
james@536 535 {
james@536 536 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
james@536 537 if (xppdd->backend_state == XenbusStateClosing)
james@536 538 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
james@536 539 if (xppdd->backend_state == XenbusStateClosed)
james@536 540 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
james@536 541 }
james@536 542 else
james@536 543 {
james@536 544 if (xppdd->backend_state == XenbusStateClosing)
james@536 545 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
james@536 546 }
james@536 547
james@536 548 if (xppdd->assigned_resources_start != NULL)
james@536 549 {
james@536 550 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 551 in_ptr = xppdd->assigned_resources_start;
james@536 552 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
james@536 553 {
james@536 554 switch (type)
james@536 555 {
james@536 556 case XEN_INIT_TYPE_RING: /* frontend ring */
james@536 557 FreePages(value);
james@536 558 break;
james@536 559 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@617 560 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
james@536 561 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 562 EvtChn_Unbind(xpdd, PtrToUlong(value));
james@536 563 EvtChn_Close(xpdd, PtrToUlong(value));
james@536 564 break;
james@536 565 case XEN_INIT_TYPE_GRANT_ENTRIES:
james@536 566 for (i = 0; i < PtrToUlong(setting); i++)
james@536 567 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value)[i], FALSE);
james@536 568 break;
james@536 569 }
james@536 570 }
james@536 571 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
james@536 572 xppdd->assigned_resources_start = NULL;
james@536 573 }
james@536 574
james@536 575 FUNCTION_EXIT();
james@536 576
james@536 577 return STATUS_SUCCESS;
james@536 578 }
james@536 579
james@536 580 struct dummy_sring {
james@536 581 RING_IDX req_prod, req_event;
james@536 582 RING_IDX rsp_prod, rsp_event;
james@536 583 uint8_t pad[48];
james@536 584 };
james@536 585
james@536 586 static NTSTATUS
james@536 587 XenPci_XenConfigDeviceSpecifyBuffers(WDFDEVICE device, PUCHAR src, PUCHAR dst)
james@536 588 {
james@536 589 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 590 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 591 NTSTATUS status = STATUS_SUCCESS;
james@536 592 ULONG i;
james@536 593 char path[128];
james@536 594 PCHAR setting, value;
james@536 595 PCHAR res;
james@536 596 PVOID address;
james@536 597 UCHAR type;
james@551 598 PUCHAR in_ptr;
james@551 599 PUCHAR out_ptr;
james@536 600 XENPCI_VECTORS vectors;
james@536 601 ULONG event_channel;
james@536 602 ULONG run_type = 0;
james@536 603 PMDL ring;
james@536 604 grant_ref_t gref;
james@536 605 BOOLEAN done_xenbus_init = FALSE;
james@536 606 PVOID value2;
james@536 607
james@536 608 FUNCTION_ENTER();
james@536 609
james@536 610 in_ptr = src;
james@536 611 out_ptr = dst;
james@536 612
james@536 613 // always add vectors
james@536 614 vectors.magic = XEN_DATA_MAGIC;
james@536 615 vectors.length = sizeof(XENPCI_VECTORS);
james@536 616 vectors.context = device;
james@536 617 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
james@536 618 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
james@536 619 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
james@536 620 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
james@536 621 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
james@536 622 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
james@536 623 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
james@536 624 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
james@536 625 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
james@536 626 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
james@536 627 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
james@536 628 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
james@536 629 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
james@536 630 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
james@716 631 RtlStringCbCopyA(vectors.path, 128, xppdd->path);
james@716 632 RtlStringCbCopyA(vectors.backend_path, 128, xppdd->backend_path);
james@536 633 //vectors.pdo_event_channel = xpdd->pdo_event_channel;
james@536 634 vectors.XenBus_Read = XenPci_XenBus_Read;
james@536 635 vectors.XenBus_Write = XenPci_XenBus_Write;
james@536 636 vectors.XenBus_Printf = XenPci_XenBus_Printf;
james@536 637 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
james@536 638 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
james@536 639 vectors.XenBus_List = XenPci_XenBus_List;
james@536 640 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
james@536 641 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
james@536 642
james@536 643 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
james@536 644
james@536 645 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
james@536 646 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
james@536 647
james@747 648 #if 0
james@551 649 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@551 650 {
james@551 651 BOOLEAN condition;
james@551 652 PCHAR xb_value;
james@551 653 switch (type)
james@551 654 {
james@551 655 case XEN_INIT_TYPE_MATCH_FRONT:
james@551 656 case XEN_INIT_TYPE_MATCH_BACK:
james@551 657 if (type == XEN_INIT_TYPE_MATCH_FRONT)
james@551 658 {
james@551 659 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@551 660 }
james@551 661 else
james@551 662 {
james@551 663 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
james@551 664 }
james@551 665 KdPrint((__DRIVER_NAME " testing path = %s\n", path));
james@551 666 res = XenBus_Read(xpdd, XBT_NIL, path, &xb_value);
james@551 667 if (res)
james@551 668 {
james@551 669 KdPrint((__DRIVER_NAME " read failed (%s)\n", res));
james@551 670 XenPci_FreeMem(res);
james@551 671 }
james@551 672 else
james@551 673 {
james@551 674 KdPrint((__DRIVER_NAME " testing %s vs %s\n", xb_value, value));
james@551 675 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_IF_MATCH)
james@551 676 condition = (strcmp(xb_value, value) == 0)?TRUE:FALSE;
james@551 677 else
james@551 678 condition = (strcmp(xb_value, value) != 0)?TRUE:FALSE;
james@551 679 KdPrint((__DRIVER_NAME " condition = %d\n", condition));
james@551 680
james@551 681 if ((PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_ONLY_IF_QEMU_HIDE) && qemu_protocol_version && condition)
james@551 682 condition = FALSE;
james@551 683
james@551 684 if (condition)
james@551 685 {
james@551 686 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_SET_INACTIVE)
james@551 687 {
james@551 688 active = FALSE;
james@551 689 KdPrint((__DRIVER_NAME " set inactive\n"));
james@551 690 }
james@551 691 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_DONT_CONFIG)
james@551 692 {
james@551 693 dont_config = TRUE;
james@551 694 KdPrint((__DRIVER_NAME " set inactive with dont config\n"));
james@551 695 }
james@551 696 }
james@551 697 XenPci_FreeMem(xb_value);
james@551 698 }
james@551 699 break;
james@551 700 }
james@551 701 }
james@551 702 if (dont_config)
james@551 703 {
james@551 704 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@551 705 FUNCTION_EXIT();
james@551 706 return status;
james@551 707 }
james@747 708 #endif
james@551 709
james@536 710 // first pass, possibly before state == Connected
james@551 711 in_ptr = src;
james@536 712 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@536 713 {
james@536 714 if (!done_xenbus_init)
james@536 715 {
james@551 716 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000) != STATUS_SUCCESS)
james@536 717 {
james@536 718 status = STATUS_UNSUCCESSFUL;
james@536 719 goto error;
james@536 720 }
james@536 721 done_xenbus_init = TRUE;
james@536 722 }
james@536 723
james@536 724 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
james@536 725
james@536 726 switch (type)
james@536 727 {
james@536 728 case XEN_INIT_TYPE_RUN:
james@536 729 run_type++;
james@536 730 break;
james@536 731 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
james@536 732 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
james@536 733 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 734 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
james@536 735 break;
james@536 736 case XEN_INIT_TYPE_RING: /* frontend ring */
james@536 737 /* we only allocate and do the SHARED_RING_INIT here */
james@536 738 if ((ring = AllocatePage()) != 0)
james@536 739 {
james@536 740 address = MmGetMdlVirtualAddress(ring);
james@536 741 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
james@536 742 SHARED_RING_INIT((struct dummy_sring *)address);
james@536 743 if ((gref = GntTbl_GrantAccess(
james@536 744 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
james@536 745 {
james@536 746 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 747 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
james@536 748 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
james@536 749 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
james@536 750 // add the grant entry too so it gets freed automatically
james@536 751 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
james@536 752 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
james@536 753 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
james@536 754 }
james@536 755 else
james@536 756 {
james@536 757 FreePages(ring);
james@536 758 status = STATUS_UNSUCCESSFUL;
james@536 759 goto error;
james@536 760 }
james@536 761 }
james@536 762 else
james@536 763 {
james@536 764 status = STATUS_UNSUCCESSFUL;
james@536 765 goto error;
james@536 766 }
james@536 767 break;
james@536 768 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@617 769 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
james@536 770 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 771 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
james@536 772 {
james@617 773 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
james@536 774 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 775 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
james@536 776 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
james@536 777 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
james@536 778 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
james@536 779 {
james@536 780 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
james@536 781 }
james@617 782 else if (type == XEN_INIT_TYPE_EVENT_CHANNEL_DPC)
james@617 783 {
james@617 784 #pragma warning(suppress:4055)
james@617 785 EvtChn_BindDpc(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
james@617 786 }
james@536 787 else
james@536 788 {
james@537 789 #pragma warning(suppress:4055)
james@536 790 EvtChn_Bind(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
james@536 791 }
james@536 792 }
james@536 793 else
james@536 794 {
james@536 795 status = STATUS_UNSUCCESSFUL;
james@536 796 goto error;
james@536 797 }
james@536 798 break;
james@536 799 }
james@536 800 }
james@536 801 if (!NT_SUCCESS(status))
james@536 802 {
james@536 803 goto error;
james@536 804 }
james@536 805 // If XEN_INIT_TYPE_RUN was specified more than once then we skip XenbusStateInitialised here and go straight to XenbusStateConnected at the end
james@536 806 if (run_type == 1)
james@536 807 {
james@551 808 if (XenPci_ChangeFrontendState(device, XenbusStateInitialised, XenbusStateConnected, 2000) != STATUS_SUCCESS)
james@536 809 {
james@536 810 status = STATUS_UNSUCCESSFUL;
james@536 811 goto error;
james@536 812 }
james@536 813 }
james@536 814
james@536 815 // second pass, possibly after state == Connected
james@536 816 in_ptr = src;
james@536 817 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@536 818 {
james@536 819 switch(type)
james@536 820 {
james@536 821 case XEN_INIT_TYPE_READ_STRING_BACK:
james@536 822 case XEN_INIT_TYPE_READ_STRING_FRONT:
james@536 823 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
james@536 824 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 825 else
james@536 826 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
james@536 827 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@536 828 if (res)
james@536 829 {
james@617 830 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
james@536 831 XenPci_FreeMem(res);
james@617 832 ADD_XEN_INIT_RSP(&out_ptr, type, setting, "", "");
james@536 833 }
james@536 834 else
james@536 835 {
james@536 836 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
james@536 837 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, value2);
james@536 838 XenPci_FreeMem(value);
james@536 839 }
james@536 840 break;
james@536 841 case XEN_INIT_TYPE_VECTORS:
james@536 842 // this is always done so ignore the request
james@536 843 break;
james@536 844 case XEN_INIT_TYPE_GRANT_ENTRIES:
james@536 845 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
james@536 846 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
james@536 847 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
james@536 848 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
james@536 849 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
james@536 850 for (i = 0; i < PtrToUlong(value); i++)
james@536 851 {
james@536 852 gref = GntTbl_GetRef(xpdd);
james@536 853 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
james@536 854 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
james@536 855 }
james@536 856 break;
james@536 857 }
james@536 858 }
james@747 859 if (qemu_hide_flags_value)
james@551 860 {
james@747 861 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_HIDE_FLAGS, NULL, UlongToPtr(qemu_hide_flags_value), NULL);
james@551 862 }
james@747 863 else
james@747 864 {
james@747 865 DECLARE_UNICODE_STRING_SIZE(my_device_name, 128);
james@747 866
james@747 867 RtlUnicodeStringPrintf(&my_device_name, L"#%S#", xppdd->device);
james@747 868
james@747 869 for (i = 0; i < WdfCollectionGetCount(qemu_hide_devices); i++)
james@747 870 {
james@747 871 WDFSTRING wdf_string = WdfCollectionGetItem(qemu_hide_devices, i);
james@747 872 UNICODE_STRING hide_device_name;
james@747 873
james@747 874 WdfStringGetUnicodeString(wdf_string, &hide_device_name);
james@747 875
james@747 876 if (RtlCompareUnicodeString(&hide_device_name, &my_device_name, TRUE) != 0)
james@747 877 {
james@747 878 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_HIDE_FILTER, NULL, NULL, NULL);
james@747 879 break;
james@747 880 }
james@747 881 }
james@747 882 }
james@747 883
james@536 884 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 885
james@536 886 if (run_type)
james@536 887 {
james@551 888 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 2000) != STATUS_SUCCESS)
james@536 889 {
james@536 890 status = STATUS_UNSUCCESSFUL;
james@536 891 goto error;
james@536 892 }
james@536 893 }
james@536 894 FUNCTION_EXIT();
james@536 895 return status;
james@551 896
james@536 897 error:
james@551 898 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000);
james@536 899 FUNCTION_EXIT_STATUS(status);
james@536 900 return status;
james@536 901 }
james@536 902
james@536 903 static NTSTATUS
james@536 904 XenPci_XenConfigDevice(WDFDEVICE device)
james@536 905 {
james@536 906 NTSTATUS status;
james@536 907 PUCHAR src, dst;
james@536 908 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 909
james@536 910 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
james@536 911 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
james@536 912 memcpy(src, dst, xppdd->config_page_length);
james@536 913
james@536 914 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
james@536 915
james@536 916 MmUnmapIoSpace(dst, xppdd->config_page_length);
james@536 917 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
james@536 918
james@536 919 return status;
james@536 920 }
james@536 921
james@536 922 static NTSTATUS
james@536 923 XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp)
james@536 924 {
james@536 925 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 926 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 927 PIO_STACK_LOCATION stack;
james@536 928 PCM_PARTIAL_RESOURCE_LIST prl;
james@536 929 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
james@536 930 ULONG i;
james@551 931 //char path[128];
james@551 932 //PMDL mdl;
james@536 933
james@536 934 FUNCTION_ENTER();
james@536 935 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
james@536 936
james@536 937 stack = IoGetCurrentIrpStackLocation(irp);
james@536 938
james@536 939 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
james@536 940 for (i = 0; i < prl->Count; i++)
james@536 941 {
james@536 942 prd = & prl->PartialDescriptors[i];
james@536 943 switch (prd->Type)
james@536 944 {
james@536 945 case CmResourceTypeMemory:
james@536 946 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
james@536 947 {
james@551 948 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
james@551 949 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
james@536 950 }
james@536 951 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
james@536 952 {
james@536 953 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@536 954 prd->Type = CmResourceTypeInterrupt;
james@536 955 prd->ShareDisposition = CmResourceShareShared;
james@536 956 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
steve@621 957 prd->u.Interrupt.Level = 0; // Set group and level to zero (group = upper word)
steve@621 958 prd->u.Interrupt.Level = xpdd->irq_number & 0xffff; // Only set the lower word
james@536 959 prd->u.Interrupt.Vector = xpdd->irq_number;
james@705 960 prd->u.Interrupt.Affinity = xpdd->irq_affinity; //KeQueryActiveProcessors();
james@536 961 xppdd->irq_number = xpdd->irq_number;
james@536 962 }
james@536 963 break;
james@536 964 }
james@536 965 }
james@536 966
james@536 967 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
james@536 968 for (i = 0; i < prl->Count; i++)
james@536 969 {
james@536 970 prd = & prl->PartialDescriptors[i];
james@536 971 switch (prd->Type)
james@536 972 {
james@536 973 case CmResourceTypeMemory:
james@536 974 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
james@536 975 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
james@536 976 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
james@536 977 {
james@536 978 if (prd->u.Memory.Length == 0)
james@536 979 {
james@551 980 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0]));
james@551 981 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
james@551 982 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
james@536 983 KdPrint((__DRIVER_NAME " New Start = %08x%08x, Length = %d\n", prd->u.Memory.Start.HighPart, prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
james@536 984 }
james@536 985 xppdd->config_page_phys = prd->u.Memory.Start;
james@536 986 xppdd->config_page_length = prd->u.Memory.Length;
james@536 987 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@634 988 //xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@536 989
james@551 990 #if 0
james@536 991 status = XenPci_XenConfigDevice(device);
james@536 992 if (!NT_SUCCESS(status))
james@536 993 {
james@536 994 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@624 995 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
james@702 996 FUNCTION_EXIT_STATUS(status);
james@536 997 return status;
james@536 998 }
james@551 999 #endif
james@536 1000 }
james@536 1001 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
james@536 1002 {
james@536 1003 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@536 1004 prd->Type = CmResourceTypeInterrupt;
james@536 1005 prd->ShareDisposition = CmResourceShareShared;
james@536 1006 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
steve@621 1007 prd->u.Interrupt.Level = 0; // Set group and level to zero (group = upper word)
steve@621 1008 prd->u.Interrupt.Level = xpdd->irq_level & 0xffff; // Only set the lower word
james@536 1009 prd->u.Interrupt.Vector = xpdd->irq_vector;
james@705 1010 prd->u.Interrupt.Affinity = xpdd->irq_affinity; //KeQueryActiveProcessors();
james@536 1011 xppdd->irq_vector = xpdd->irq_vector;
james@536 1012 xppdd->irq_level = xpdd->irq_level;
james@536 1013 }
james@536 1014 break;
james@536 1015 }
james@536 1016 }
james@536 1017
james@536 1018 IoSkipCurrentIrpStackLocation(irp);
james@536 1019
james@536 1020 FUNCTION_EXIT();
james@536 1021
james@536 1022 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
james@536 1023 }
james@536 1024
james@536 1025 #if 0
james@536 1026 static NTSTATUS
james@536 1027 XenPciPdo_EvtDeviceResourcesQuery(WDFDEVICE device, WDFCMRESLIST resources)
james@536 1028 {
james@536 1029 }
james@536 1030 #endif
james@536 1031
james@536 1032 static NTSTATUS
james@536 1033 XenPciPdo_EvtDeviceResourceRequirementsQuery(WDFDEVICE device, WDFIORESREQLIST requirements_list)
james@536 1034 {
james@536 1035 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1036 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1037 WDFIORESLIST res_list;
james@536 1038 IO_RESOURCE_DESCRIPTOR ird;
james@536 1039
james@538 1040 //FUNCTION_ENTER();
james@536 1041
james@536 1042 WdfIoResourceRequirementsListSetInterfaceType(requirements_list, PNPBus);
james@536 1043
james@536 1044 WdfIoResourceListCreate(requirements_list, WDF_NO_OBJECT_ATTRIBUTES, &res_list);
james@536 1045 ird.Option = 0;
james@536 1046 ird.Type = CmResourceTypeMemory;
james@536 1047 ird.ShareDisposition = CmResourceShareShared;
james@536 1048 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
james@536 1049 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
james@536 1050 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
james@536 1051 ird.u.Memory.Length = 0;
james@536 1052 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
james@536 1053 WdfIoResourceListAppendDescriptor(res_list, &ird);
james@536 1054
james@536 1055 ird.Option = 0;
james@536 1056 ird.Type = CmResourceTypeMemory;
james@536 1057 ird.ShareDisposition = CmResourceShareShared;
james@536 1058 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
james@536 1059 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
james@536 1060 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
james@536 1061 ird.u.Memory.Length = 0;
james@536 1062 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
james@536 1063 WdfIoResourceListAppendDescriptor(res_list, &ird);
james@536 1064
james@536 1065 WdfIoResourceRequirementsListAppendIoResList(requirements_list, res_list);
james@536 1066
james@538 1067 //FUNCTION_EXIT();
james@538 1068
james@538 1069 return STATUS_SUCCESS;
james@538 1070 }
james@538 1071
james@538 1072 NTSTATUS
james@538 1073 XenPciPdo_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
james@538 1074 {
james@538 1075 NTSTATUS status = STATUS_SUCCESS;
james@551 1076 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@551 1077 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@551 1078 CHAR path[128];
james@538 1079
james@538 1080 FUNCTION_ENTER();
james@538 1081
james@538 1082 switch (previous_state)
james@538 1083 {
james@538 1084 case WdfPowerDeviceD0:
james@538 1085 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 1086 break;
james@538 1087 case WdfPowerDeviceD1:
james@538 1088 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 1089 break;
james@538 1090 case WdfPowerDeviceD2:
james@538 1091 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
james@538 1092 break;
james@538 1093 case WdfPowerDeviceD3:
james@538 1094 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
james@538 1095 break;
james@538 1096 case WdfPowerDeviceD3Final:
james@538 1097 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
james@538 1098 break;
james@538 1099 case WdfPowerDevicePrepareForHibernation:
james@538 1100 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
james@538 1101 break;
james@538 1102 default:
james@538 1103 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
james@538 1104 break;
james@538 1105 }
james@634 1106
james@551 1107 if (previous_state == WdfPowerDevicePrepareForHibernation
james@551 1108 || (previous_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
james@551 1109 {
james@551 1110 KdPrint((__DRIVER_NAME " starting up from hibernation\n"));
james@551 1111 }
james@551 1112 else
james@551 1113 {
james@551 1114 }
james@551 1115
james@634 1116 if (previous_state == WdfPowerDevicePrepareForHibernation || previous_state == WdfPowerDeviceD3 || previous_state == WdfPowerDeviceD3Final)
james@634 1117 {
james@634 1118 xppdd->requested_resources_ptr = xppdd->requested_resources_start;
james@634 1119 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@634 1120 }
james@634 1121
james@551 1122 XenConfig_InitConfigPage(device);
james@551 1123
james@551 1124 status = XenPci_GetBackendAndAddWatch(device);
james@551 1125 if (!NT_SUCCESS(status))
james@551 1126 {
james@551 1127 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
james@702 1128 FUNCTION_EXIT_STATUS(status);
james@551 1129 return status;
james@551 1130 }
james@551 1131 status = XenPci_XenConfigDevice(device);
james@551 1132 if (!NT_SUCCESS(status))
james@551 1133 {
james@551 1134 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@624 1135 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
james@551 1136 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
james@702 1137 FUNCTION_EXIT_STATUS(status);
james@551 1138 return status;
james@551 1139 }
james@538 1140
james@536 1141 FUNCTION_EXIT();
james@536 1142
james@538 1143 return status;
james@538 1144 }
james@538 1145
james@538 1146 NTSTATUS
james@538 1147 XenPciPdo_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
james@538 1148 {
james@538 1149 NTSTATUS status = STATUS_SUCCESS;
james@538 1150 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@538 1151 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@538 1152 char path[128];
james@538 1153
james@538 1154 UNREFERENCED_PARAMETER(device);
james@538 1155 UNREFERENCED_PARAMETER(target_state);
james@538 1156
james@538 1157 FUNCTION_ENTER();
james@538 1158
james@538 1159 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@538 1160
james@538 1161
james@538 1162 switch (target_state)
james@538 1163 {
james@538 1164 case WdfPowerDeviceD0:
james@538 1165 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 1166 break;
james@538 1167 case WdfPowerDeviceD1:
james@538 1168 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 1169 break;
james@538 1170 case WdfPowerDeviceD2:
james@538 1171 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
james@538 1172 break;
james@538 1173 case WdfPowerDeviceD3:
james@538 1174 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
james@538 1175 break;
james@538 1176 case WdfPowerDeviceD3Final:
james@538 1177 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
james@538 1178 break;
james@538 1179 case WdfPowerDevicePrepareForHibernation:
james@538 1180 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
james@538 1181 break;
james@538 1182 default:
james@538 1183 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
james@538 1184 break;
james@538 1185 }
james@692 1186
james@538 1187 if (target_state == WdfPowerDevicePrepareForHibernation
james@538 1188 || (target_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
james@538 1189 {
james@538 1190 KdPrint((__DRIVER_NAME " not powering down as we are hibernating\n"));
james@538 1191 }
james@538 1192 else
james@538 1193 {
james@538 1194 status = XenPci_XenShutdownDevice(device);
james@538 1195 }
amir@679 1196
amir@679 1197 /* Remove watch on backend state */
amir@679 1198 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
amir@679 1199 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
amir@679 1200
james@538 1201 FUNCTION_EXIT();
james@538 1202
james@538 1203 return status;
james@538 1204 }
james@538 1205
james@538 1206 NTSTATUS
james@551 1207 XenPciPdo_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
james@538 1208 {
james@538 1209 NTSTATUS status = STATUS_SUCCESS;
james@551 1210
james@538 1211 UNREFERENCED_PARAMETER(device);
james@538 1212 UNREFERENCED_PARAMETER(resources_raw);
james@538 1213 UNREFERENCED_PARAMETER(resources_translated);
james@538 1214
james@538 1215 FUNCTION_ENTER();
james@538 1216 FUNCTION_EXIT();
james@538 1217
james@538 1218 return status;
james@538 1219 }
james@538 1220
james@538 1221 NTSTATUS
james@538 1222 XenPciPdo_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
james@538 1223 {
james@538 1224 NTSTATUS status = STATUS_SUCCESS;
james@538 1225
james@538 1226 UNREFERENCED_PARAMETER(device);
james@538 1227 UNREFERENCED_PARAMETER(resources_translated);
james@538 1228
james@538 1229 FUNCTION_ENTER();
james@538 1230 FUNCTION_EXIT();
james@538 1231
james@538 1232 return status;
james@538 1233 }
james@538 1234
james@538 1235 static VOID
james@538 1236 XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
james@538 1237 {
james@538 1238 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@538 1239
james@538 1240 FUNCTION_ENTER();
james@538 1241
james@538 1242 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@538 1243 switch (notification_type)
james@538 1244 {
james@538 1245 case WdfSpecialFilePaging:
james@538 1246 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
james@538 1247 break;
james@538 1248 case WdfSpecialFileHibernation:
james@538 1249 xppdd->hiber_usage_kludge = is_in_notification_path;
james@538 1250 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
james@538 1251 break;
james@538 1252 case WdfSpecialFileDump:
james@538 1253 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
james@538 1254 break;
james@538 1255 default:
james@538 1256 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
james@538 1257 break;
james@538 1258 }
james@538 1259
james@538 1260 FUNCTION_EXIT();
james@536 1261 }
james@536 1262
james@536 1263 NTSTATUS
james@536 1264 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
james@536 1265 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
james@536 1266 PWDFDEVICE_INIT child_init)
james@536 1267 {
james@536 1268 NTSTATUS status = STATUS_SUCCESS;
james@536 1269 WDF_OBJECT_ATTRIBUTES child_attributes;
james@536 1270 WDFDEVICE child_device;
james@536 1271 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
james@536 1272 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
james@536 1273 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
james@536 1274 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
james@536 1275 PXENPCI_PDO_DEVICE_DATA xppdd;
james@536 1276 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
james@536 1277 WDF_QUERY_INTERFACE_CONFIG interface_config;
james@536 1278 BUS_INTERFACE_STANDARD bus_interface;
james@536 1279 WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
james@538 1280 WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
james@536 1281 UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
james@538 1282 WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
james@536 1283
james@536 1284 FUNCTION_ENTER();
james@536 1285
james@536 1286 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
james@536 1287
james@536 1288 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
james@536 1289 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
james@538 1290 //child_pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPciPdo_EvtDeviceD0EntryPostInterruptsEnabled;
james@536 1291 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
james@538 1292 //child_pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPciPdo_EvtDeviceD0ExitPreInterruptsDisabled;
james@536 1293 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenPciPdo_EvtDevicePrepareHardware;
james@536 1294 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenPciPdo_EvtDeviceReleaseHardware;
james@538 1295 child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
james@536 1296 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
james@538 1297
james@536 1298 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
james@536 1299 identification->device, identification->index, identification->path));
james@536 1300
james@536 1301 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
james@536 1302 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
james@536 1303 if (!NT_SUCCESS(status))
james@536 1304 {
james@536 1305 return status;
james@536 1306 }
james@536 1307
james@536 1308 WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
james@536 1309 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
james@536 1310 pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
james@536 1311 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
james@536 1312 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
james@536 1313 WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
james@536 1314
james@536 1315 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
james@536 1316 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
james@536 1317 if (!NT_SUCCESS(status))
james@536 1318 {
james@536 1319 return status;
james@536 1320 }
james@536 1321 status = WdfPdoInitAddHardwareID(child_init, &buffer);
james@536 1322 if (!NT_SUCCESS(status))
james@536 1323 {
james@536 1324 return status;
james@536 1325 }
james@536 1326 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
james@536 1327 if (!NT_SUCCESS(status))
james@536 1328 {
james@536 1329 return status;
james@536 1330 }
james@536 1331
james@536 1332 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
james@536 1333 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
james@536 1334 if (!NT_SUCCESS(status))
james@536 1335 {
james@536 1336 return status;
james@536 1337 }
james@536 1338
james@536 1339 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
james@536 1340 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
james@536 1341 if (!NT_SUCCESS(status))
james@536 1342 {
james@536 1343 return status;
james@536 1344 }
james@536 1345 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
james@538 1346
james@538 1347 WdfDeviceInitSetPowerNotPageable(child_init);
james@536 1348
james@536 1349 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
james@536 1350 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
james@536 1351 if (!NT_SUCCESS(status))
james@536 1352 {
james@536 1353 return status;
james@536 1354 }
james@536 1355
james@536 1356 xppdd = GetXppdd(child_device);
james@536 1357
james@536 1358 xppdd->wdf_device = child_device;
james@536 1359 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
james@536 1360
james@551 1361 xppdd->config_page_mdl = AllocateUncachedPage();
james@551 1362
james@536 1363 xppdd->device_state.magic = XEN_DEVICE_STATE_MAGIC;
james@536 1364 xppdd->device_state.length = sizeof(XENPCI_DEVICE_STATE);
james@536 1365 xppdd->device_state.suspend_resume_state_pdo = SR_STATE_RUNNING;
james@536 1366 xppdd->device_state.suspend_resume_state_fdo = SR_STATE_RUNNING;
james@536 1367 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
james@536 1368 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
james@536 1369 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
james@536 1370 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
james@536 1371
james@536 1372 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
james@536 1373 child_pnp_capabilities.LockSupported = WdfFalse;
james@536 1374 child_pnp_capabilities.EjectSupported = WdfTrue;
james@536 1375 child_pnp_capabilities.Removable = WdfTrue;
james@536 1376 child_pnp_capabilities.DockDevice = WdfFalse;
james@536 1377 child_pnp_capabilities.UniqueID = WdfFalse;
james@536 1378 child_pnp_capabilities.SilentInstall = WdfTrue;
james@536 1379 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
james@536 1380 child_pnp_capabilities.HardwareDisabled = WdfFalse;
james@536 1381 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
james@536 1382
james@538 1383 WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
james@538 1384 child_power_capabilities.DeviceD1 = WdfTrue;
james@538 1385 child_power_capabilities.WakeFromD1 = WdfTrue;
james@538 1386 child_power_capabilities.DeviceWake = PowerDeviceD1;
james@538 1387 child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
james@538 1388 child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
james@538 1389 child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
james@538 1390 child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
james@538 1391 child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
james@538 1392 child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
james@538 1393 WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
james@536 1394
james@536 1395 bus_interface.Size = sizeof(BUS_INTERFACE_STANDARD);
james@536 1396 bus_interface.Version = 1; //BUS_INTERFACE_STANDARD_VERSION;
james@536 1397 bus_interface.Context = xppdd;
james@537 1398 bus_interface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
james@537 1399 bus_interface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
james@536 1400 bus_interface.TranslateBusAddress = XenPci_BIS_TranslateBusAddress;
james@536 1401 bus_interface.GetDmaAdapter = XenPci_BIS_GetDmaAdapter;
james@536 1402 bus_interface.SetBusData = XenPci_BIS_SetBusData;
james@536 1403 bus_interface.GetBusData = XenPci_BIS_GetBusData;
james@536 1404 WDF_QUERY_INTERFACE_CONFIG_INIT(&interface_config, (PINTERFACE)&bus_interface, &GUID_BUS_INTERFACE_STANDARD, NULL);
james@536 1405 status = WdfDeviceAddQueryInterface(child_device, &interface_config);
james@536 1406 if (!NT_SUCCESS(status))
james@536 1407 {
james@536 1408 return status;
james@536 1409 }
james@536 1410
james@536 1411 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
james@536 1412 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
james@536 1413 xppdd->index = identification->index;
james@536 1414 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
james@624 1415 ExInitializeFastMutex(&xppdd->backend_state_mutex);
james@536 1416 xppdd->backend_state = XenbusStateUnknown;
james@538 1417 xppdd->frontend_state = XenbusStateUnknown;
james@536 1418 xppdd->backend_path[0] = '\0';
james@536 1419
james@536 1420 FUNCTION_EXIT();
james@536 1421
james@536 1422 return status;
james@536 1423 }
james@536 1424
james@536 1425 static __forceinline VOID
james@536 1426 XenPci_Pdo_ChangeSuspendState(WDFDEVICE device, ULONG new_state)
james@536 1427 {
james@536 1428 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1429 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1430
james@536 1431 FUNCTION_ENTER();
james@536 1432 KdPrint((__DRIVER_NAME " setting pdo state to %d\n", new_state));
james@536 1433 xppdd->device_state.suspend_resume_state_pdo = new_state;
james@536 1434 KeMemoryBarrier();
james@536 1435 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xpdd->pdo_event_channel));
james@536 1436 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
james@536 1437 while(xppdd->device_state.suspend_resume_state_fdo != xppdd->device_state.suspend_resume_state_pdo)
james@536 1438 {
james@536 1439 KdPrint((__DRIVER_NAME " waiting...\n"));
james@536 1440 KeWaitForSingleObject(&xpdd->pdo_suspend_event, Executive, KernelMode, FALSE, NULL);
james@536 1441 }
james@536 1442 KdPrint((__DRIVER_NAME " fdo state set to %d\n", new_state));
james@536 1443 FUNCTION_EXIT();
james@536 1444 }
james@536 1445
james@536 1446 /* called at PASSIVE_LEVEL */
james@536 1447 NTSTATUS
james@536 1448 XenPci_Pdo_Suspend(WDFDEVICE device)
james@536 1449 {
james@536 1450 NTSTATUS status = STATUS_SUCCESS;
james@536 1451 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1452 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1453 //LARGE_INTEGER wait_time;
james@536 1454 char path[128];
james@536 1455 PUCHAR in_ptr;
james@536 1456 UCHAR type;
james@536 1457 PVOID setting;
james@536 1458 PVOID value;
james@536 1459 PVOID value2;
james@536 1460
james@536 1461 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
james@536 1462
james@536 1463 if (xppdd->backend_state == XenbusStateConnected)
james@536 1464 {
james@536 1465 xppdd->restart_on_resume = TRUE;
james@536 1466 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_SUSPENDING);
james@536 1467
james@536 1468 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
james@536 1469 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
james@536 1470 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
james@536 1471
james@536 1472 if (xppdd->assigned_resources_start != NULL)
james@536 1473 {
james@536 1474 in_ptr = xppdd->assigned_resources_ptr;
james@536 1475 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 1476 in_ptr = xppdd->assigned_resources_start;
james@536 1477 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
james@536 1478 {
james@536 1479 switch (type)
james@536 1480 {
james@536 1481 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@617 1482 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
james@536 1483 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 1484 EvtChn_Unbind(xpdd, PtrToUlong(value));
james@536 1485 EvtChn_Close(xpdd, PtrToUlong(value));
james@536 1486 break;
james@536 1487 }
james@536 1488 }
james@536 1489 }
james@536 1490
james@536 1491 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@624 1492 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, xppdd);
james@536 1493 }
james@536 1494 else
james@536 1495 {
james@536 1496 xppdd->restart_on_resume = FALSE;
james@536 1497 }
james@536 1498
james@536 1499 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@536 1500
james@536 1501 return status;
james@536 1502 }
james@536 1503
james@536 1504 NTSTATUS
james@536 1505 XenPci_Pdo_Resume(WDFDEVICE device)
james@536 1506 {
james@536 1507 NTSTATUS status = STATUS_SUCCESS;
james@536 1508 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1509 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1510 ULONG old_backend_state;
james@536 1511 PUCHAR src, dst;
james@536 1512
james@536 1513 FUNCTION_ENTER();
james@536 1514 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@536 1515
james@536 1516 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
james@536 1517 old_backend_state = xppdd->backend_state;
james@536 1518
james@536 1519 if (xppdd->restart_on_resume)
james@536 1520 {
james@536 1521 status = XenPci_GetBackendAndAddWatch(device);
james@536 1522
james@536 1523 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
james@536 1524 {
james@536 1525 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
james@536 1526 // this is probably an unrecoverable situation...
james@702 1527 FUNCTION_EXIT();
james@536 1528 return STATUS_UNSUCCESSFUL;
james@536 1529 }
james@536 1530 if (xppdd->assigned_resources_ptr)
james@536 1531 {
james@536 1532 // reset things - feed the 'requested resources' back in
james@536 1533 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 1534 src = xppdd->requested_resources_start;
james@536 1535 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
james@536 1536 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
james@536 1537
james@536 1538 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
james@536 1539
james@536 1540 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
james@536 1541
james@536 1542 MmUnmapIoSpace(dst, xppdd->config_page_length);
james@536 1543 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
james@536 1544 }
james@536 1545 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
james@536 1546 {
james@536 1547 // this is definitely an unrecoverable situation...
james@536 1548 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
james@702 1549 FUNCTION_EXIT();
james@536 1550 return STATUS_UNSUCCESSFUL;
james@536 1551 }
james@536 1552 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RESUMING);
james@536 1553 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RUNNING);
james@536 1554 }
james@536 1555
james@536 1556 FUNCTION_EXIT();
james@536 1557
james@536 1558 return STATUS_SUCCESS;
james@536 1559 }