win-pvdrivers

annotate xenpci/xenpci_pdo.c @ 716:5bdb7251370c

Use WinDDK 7600.16385.0
Update userspace binaries to build for XP not 2K (2K not supported in new DDK)
Fix lots of PREfast errors
Make build and installer less dependant on DDK version
Fix IRQL crash in DpgPrint hooking
author James Harper <james.harper@bendigoit.com.au>
date Tue Dec 22 22:44:07 2009 +1100 (2009-12-22)
parents b620a1b82e0b
children f43c89df09b2
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@551 607 BOOLEAN active = TRUE;
james@551 608 BOOLEAN dont_config = FALSE;
james@536 609
james@536 610 FUNCTION_ENTER();
james@536 611
james@536 612 in_ptr = src;
james@536 613 out_ptr = dst;
james@536 614
james@536 615 // always add vectors
james@536 616 vectors.magic = XEN_DATA_MAGIC;
james@536 617 vectors.length = sizeof(XENPCI_VECTORS);
james@536 618 vectors.context = device;
james@536 619 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
james@536 620 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
james@536 621 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
james@536 622 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
james@536 623 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
james@536 624 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
james@536 625 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
james@536 626 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
james@536 627 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
james@536 628 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
james@536 629 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
james@536 630 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
james@536 631 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
james@536 632 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
james@716 633 RtlStringCbCopyA(vectors.path, 128, xppdd->path);
james@716 634 RtlStringCbCopyA(vectors.backend_path, 128, xppdd->backend_path);
james@536 635 //vectors.pdo_event_channel = xpdd->pdo_event_channel;
james@536 636 vectors.XenBus_Read = XenPci_XenBus_Read;
james@536 637 vectors.XenBus_Write = XenPci_XenBus_Write;
james@536 638 vectors.XenBus_Printf = XenPci_XenBus_Printf;
james@536 639 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
james@536 640 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
james@536 641 vectors.XenBus_List = XenPci_XenBus_List;
james@536 642 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
james@536 643 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
james@536 644
james@536 645 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
james@536 646
james@536 647 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
james@536 648 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
james@536 649
james@551 650 if (!qemu_filtered)
james@551 651 active = FALSE;
james@551 652
james@551 653 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@551 654 {
james@551 655 BOOLEAN condition;
james@551 656 PCHAR xb_value;
james@551 657 switch (type)
james@551 658 {
james@551 659 case XEN_INIT_TYPE_MATCH_FRONT:
james@551 660 case XEN_INIT_TYPE_MATCH_BACK:
james@551 661 if (type == XEN_INIT_TYPE_MATCH_FRONT)
james@551 662 {
james@551 663 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@551 664 }
james@551 665 else
james@551 666 {
james@551 667 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
james@551 668 }
james@551 669 KdPrint((__DRIVER_NAME " testing path = %s\n", path));
james@551 670 res = XenBus_Read(xpdd, XBT_NIL, path, &xb_value);
james@551 671 if (res)
james@551 672 {
james@551 673 KdPrint((__DRIVER_NAME " read failed (%s)\n", res));
james@551 674 XenPci_FreeMem(res);
james@551 675 }
james@551 676 else
james@551 677 {
james@551 678 KdPrint((__DRIVER_NAME " testing %s vs %s\n", xb_value, value));
james@551 679 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_IF_MATCH)
james@551 680 condition = (strcmp(xb_value, value) == 0)?TRUE:FALSE;
james@551 681 else
james@551 682 condition = (strcmp(xb_value, value) != 0)?TRUE:FALSE;
james@551 683 KdPrint((__DRIVER_NAME " condition = %d\n", condition));
james@551 684
james@551 685 if ((PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_ONLY_IF_QEMU_HIDE) && qemu_protocol_version && condition)
james@551 686 condition = FALSE;
james@551 687
james@551 688 if (condition)
james@551 689 {
james@551 690 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_SET_INACTIVE)
james@551 691 {
james@551 692 active = FALSE;
james@551 693 KdPrint((__DRIVER_NAME " set inactive\n"));
james@551 694 }
james@551 695 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_DONT_CONFIG)
james@551 696 {
james@551 697 dont_config = TRUE;
james@551 698 KdPrint((__DRIVER_NAME " set inactive with dont config\n"));
james@551 699 }
james@551 700 }
james@551 701 XenPci_FreeMem(xb_value);
james@551 702 }
james@551 703 break;
james@551 704 }
james@551 705 }
james@551 706 if (dont_config)
james@551 707 {
james@551 708 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@551 709 FUNCTION_EXIT();
james@551 710 return status;
james@551 711 }
james@551 712
james@536 713 // first pass, possibly before state == Connected
james@551 714 in_ptr = src;
james@536 715 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@536 716 {
james@536 717 if (!done_xenbus_init)
james@536 718 {
james@551 719 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000) != STATUS_SUCCESS)
james@536 720 {
james@536 721 status = STATUS_UNSUCCESSFUL;
james@536 722 goto error;
james@536 723 }
james@536 724 done_xenbus_init = TRUE;
james@536 725 }
james@536 726
james@536 727 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
james@536 728
james@536 729 switch (type)
james@536 730 {
james@536 731 case XEN_INIT_TYPE_RUN:
james@536 732 run_type++;
james@536 733 break;
james@536 734 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
james@536 735 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
james@536 736 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 737 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
james@536 738 break;
james@536 739 case XEN_INIT_TYPE_RING: /* frontend ring */
james@536 740 /* we only allocate and do the SHARED_RING_INIT here */
james@536 741 if ((ring = AllocatePage()) != 0)
james@536 742 {
james@536 743 address = MmGetMdlVirtualAddress(ring);
james@536 744 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
james@536 745 SHARED_RING_INIT((struct dummy_sring *)address);
james@536 746 if ((gref = GntTbl_GrantAccess(
james@536 747 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
james@536 748 {
james@536 749 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 750 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
james@536 751 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
james@536 752 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
james@536 753 // add the grant entry too so it gets freed automatically
james@536 754 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
james@536 755 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
james@536 756 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
james@536 757 }
james@536 758 else
james@536 759 {
james@536 760 FreePages(ring);
james@536 761 status = STATUS_UNSUCCESSFUL;
james@536 762 goto error;
james@536 763 }
james@536 764 }
james@536 765 else
james@536 766 {
james@536 767 status = STATUS_UNSUCCESSFUL;
james@536 768 goto error;
james@536 769 }
james@536 770 break;
james@536 771 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@617 772 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
james@536 773 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 774 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
james@536 775 {
james@617 776 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
james@536 777 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 778 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
james@536 779 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
james@536 780 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
james@536 781 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
james@536 782 {
james@536 783 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
james@536 784 }
james@617 785 else if (type == XEN_INIT_TYPE_EVENT_CHANNEL_DPC)
james@617 786 {
james@617 787 #pragma warning(suppress:4055)
james@617 788 EvtChn_BindDpc(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
james@617 789 }
james@536 790 else
james@536 791 {
james@537 792 #pragma warning(suppress:4055)
james@536 793 EvtChn_Bind(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
james@536 794 }
james@536 795 }
james@536 796 else
james@536 797 {
james@536 798 status = STATUS_UNSUCCESSFUL;
james@536 799 goto error;
james@536 800 }
james@536 801 break;
james@536 802 }
james@536 803 }
james@536 804 if (!NT_SUCCESS(status))
james@536 805 {
james@536 806 goto error;
james@536 807 }
james@536 808 // 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 809 if (run_type == 1)
james@536 810 {
james@551 811 if (XenPci_ChangeFrontendState(device, XenbusStateInitialised, XenbusStateConnected, 2000) != STATUS_SUCCESS)
james@536 812 {
james@536 813 status = STATUS_UNSUCCESSFUL;
james@536 814 goto error;
james@536 815 }
james@536 816 }
james@536 817
james@536 818 // second pass, possibly after state == Connected
james@536 819 in_ptr = src;
james@536 820 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@536 821 {
james@536 822 switch(type)
james@536 823 {
james@536 824 case XEN_INIT_TYPE_READ_STRING_BACK:
james@536 825 case XEN_INIT_TYPE_READ_STRING_FRONT:
james@536 826 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
james@536 827 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 828 else
james@536 829 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
james@536 830 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@536 831 if (res)
james@536 832 {
james@617 833 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
james@536 834 XenPci_FreeMem(res);
james@617 835 ADD_XEN_INIT_RSP(&out_ptr, type, setting, "", "");
james@536 836 }
james@536 837 else
james@536 838 {
james@536 839 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
james@536 840 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, value2);
james@536 841 XenPci_FreeMem(value);
james@536 842 }
james@536 843 break;
james@536 844 case XEN_INIT_TYPE_VECTORS:
james@536 845 // this is always done so ignore the request
james@536 846 break;
james@536 847 case XEN_INIT_TYPE_GRANT_ENTRIES:
james@536 848 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
james@536 849 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
james@536 850 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
james@536 851 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
james@536 852 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
james@536 853 for (i = 0; i < PtrToUlong(value); i++)
james@536 854 {
james@536 855 gref = GntTbl_GetRef(xpdd);
james@536 856 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
james@536 857 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
james@536 858 }
james@536 859 break;
james@536 860 }
james@536 861 }
james@551 862 if (active)
james@551 863 {
james@551 864 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_ACTIVE, NULL, NULL, NULL);
james@551 865 }
james@536 866 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 867
james@536 868 if (run_type)
james@536 869 {
james@551 870 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 2000) != STATUS_SUCCESS)
james@536 871 {
james@536 872 status = STATUS_UNSUCCESSFUL;
james@536 873 goto error;
james@536 874 }
james@536 875 }
james@536 876 FUNCTION_EXIT();
james@536 877 return status;
james@551 878
james@536 879 error:
james@551 880 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000);
james@536 881 FUNCTION_EXIT_STATUS(status);
james@536 882 return status;
james@536 883 }
james@536 884
james@536 885 static NTSTATUS
james@536 886 XenPci_XenConfigDevice(WDFDEVICE device)
james@536 887 {
james@536 888 NTSTATUS status;
james@536 889 PUCHAR src, dst;
james@536 890 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 891
james@536 892 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
james@536 893 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
james@536 894 memcpy(src, dst, xppdd->config_page_length);
james@536 895
james@536 896 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
james@536 897
james@536 898 MmUnmapIoSpace(dst, xppdd->config_page_length);
james@536 899 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
james@536 900
james@536 901 return status;
james@536 902 }
james@536 903
james@536 904 static NTSTATUS
james@536 905 XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp)
james@536 906 {
james@536 907 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 908 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 909 PIO_STACK_LOCATION stack;
james@536 910 PCM_PARTIAL_RESOURCE_LIST prl;
james@536 911 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
james@536 912 ULONG i;
james@551 913 //char path[128];
james@551 914 //PMDL mdl;
james@536 915
james@536 916 FUNCTION_ENTER();
james@536 917 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
james@536 918
james@536 919 stack = IoGetCurrentIrpStackLocation(irp);
james@536 920
james@536 921 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
james@536 922 for (i = 0; i < prl->Count; i++)
james@536 923 {
james@536 924 prd = & prl->PartialDescriptors[i];
james@536 925 switch (prd->Type)
james@536 926 {
james@536 927 case CmResourceTypeMemory:
james@536 928 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
james@536 929 {
james@551 930 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
james@551 931 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
james@536 932 }
james@536 933 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
james@536 934 {
james@536 935 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@536 936 prd->Type = CmResourceTypeInterrupt;
james@536 937 prd->ShareDisposition = CmResourceShareShared;
james@536 938 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
steve@621 939 prd->u.Interrupt.Level = 0; // Set group and level to zero (group = upper word)
steve@621 940 prd->u.Interrupt.Level = xpdd->irq_number & 0xffff; // Only set the lower word
james@536 941 prd->u.Interrupt.Vector = xpdd->irq_number;
james@705 942 prd->u.Interrupt.Affinity = xpdd->irq_affinity; //KeQueryActiveProcessors();
james@536 943 xppdd->irq_number = xpdd->irq_number;
james@536 944 }
james@536 945 break;
james@536 946 }
james@536 947 }
james@536 948
james@536 949 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
james@536 950 for (i = 0; i < prl->Count; i++)
james@536 951 {
james@536 952 prd = & prl->PartialDescriptors[i];
james@536 953 switch (prd->Type)
james@536 954 {
james@536 955 case CmResourceTypeMemory:
james@536 956 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
james@536 957 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
james@536 958 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
james@536 959 {
james@536 960 if (prd->u.Memory.Length == 0)
james@536 961 {
james@551 962 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0]));
james@551 963 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
james@551 964 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
james@536 965 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 966 }
james@536 967 xppdd->config_page_phys = prd->u.Memory.Start;
james@536 968 xppdd->config_page_length = prd->u.Memory.Length;
james@536 969 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@634 970 //xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@536 971
james@551 972 #if 0
james@536 973 status = XenPci_XenConfigDevice(device);
james@536 974 if (!NT_SUCCESS(status))
james@536 975 {
james@536 976 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@624 977 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
james@702 978 FUNCTION_EXIT_STATUS(status);
james@536 979 return status;
james@536 980 }
james@551 981 #endif
james@536 982 }
james@536 983 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
james@536 984 {
james@536 985 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@536 986 prd->Type = CmResourceTypeInterrupt;
james@536 987 prd->ShareDisposition = CmResourceShareShared;
james@536 988 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
steve@621 989 prd->u.Interrupt.Level = 0; // Set group and level to zero (group = upper word)
steve@621 990 prd->u.Interrupt.Level = xpdd->irq_level & 0xffff; // Only set the lower word
james@536 991 prd->u.Interrupt.Vector = xpdd->irq_vector;
james@705 992 prd->u.Interrupt.Affinity = xpdd->irq_affinity; //KeQueryActiveProcessors();
james@536 993 xppdd->irq_vector = xpdd->irq_vector;
james@536 994 xppdd->irq_level = xpdd->irq_level;
james@536 995 }
james@536 996 break;
james@536 997 }
james@536 998 }
james@536 999
james@536 1000 IoSkipCurrentIrpStackLocation(irp);
james@536 1001
james@536 1002 FUNCTION_EXIT();
james@536 1003
james@536 1004 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
james@536 1005 }
james@536 1006
james@536 1007 #if 0
james@536 1008 static NTSTATUS
james@536 1009 XenPciPdo_EvtDeviceResourcesQuery(WDFDEVICE device, WDFCMRESLIST resources)
james@536 1010 {
james@536 1011 }
james@536 1012 #endif
james@536 1013
james@536 1014 static NTSTATUS
james@536 1015 XenPciPdo_EvtDeviceResourceRequirementsQuery(WDFDEVICE device, WDFIORESREQLIST requirements_list)
james@536 1016 {
james@536 1017 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1018 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1019 WDFIORESLIST res_list;
james@536 1020 IO_RESOURCE_DESCRIPTOR ird;
james@536 1021
james@538 1022 //FUNCTION_ENTER();
james@536 1023
james@536 1024 WdfIoResourceRequirementsListSetInterfaceType(requirements_list, PNPBus);
james@536 1025
james@536 1026 WdfIoResourceListCreate(requirements_list, WDF_NO_OBJECT_ATTRIBUTES, &res_list);
james@536 1027 ird.Option = 0;
james@536 1028 ird.Type = CmResourceTypeMemory;
james@536 1029 ird.ShareDisposition = CmResourceShareShared;
james@536 1030 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
james@536 1031 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
james@536 1032 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
james@536 1033 ird.u.Memory.Length = 0;
james@536 1034 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
james@536 1035 WdfIoResourceListAppendDescriptor(res_list, &ird);
james@536 1036
james@536 1037 ird.Option = 0;
james@536 1038 ird.Type = CmResourceTypeMemory;
james@536 1039 ird.ShareDisposition = CmResourceShareShared;
james@536 1040 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
james@536 1041 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
james@536 1042 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
james@536 1043 ird.u.Memory.Length = 0;
james@536 1044 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
james@536 1045 WdfIoResourceListAppendDescriptor(res_list, &ird);
james@536 1046
james@536 1047 WdfIoResourceRequirementsListAppendIoResList(requirements_list, res_list);
james@536 1048
james@538 1049 //FUNCTION_EXIT();
james@538 1050
james@538 1051 return STATUS_SUCCESS;
james@538 1052 }
james@538 1053
james@538 1054 NTSTATUS
james@538 1055 XenPciPdo_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
james@538 1056 {
james@538 1057 NTSTATUS status = STATUS_SUCCESS;
james@551 1058 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@551 1059 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@551 1060 CHAR path[128];
james@538 1061
james@538 1062 FUNCTION_ENTER();
james@538 1063
james@538 1064 switch (previous_state)
james@538 1065 {
james@538 1066 case WdfPowerDeviceD0:
james@538 1067 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 1068 break;
james@538 1069 case WdfPowerDeviceD1:
james@538 1070 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 1071 break;
james@538 1072 case WdfPowerDeviceD2:
james@538 1073 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
james@538 1074 break;
james@538 1075 case WdfPowerDeviceD3:
james@538 1076 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
james@538 1077 break;
james@538 1078 case WdfPowerDeviceD3Final:
james@538 1079 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
james@538 1080 break;
james@538 1081 case WdfPowerDevicePrepareForHibernation:
james@538 1082 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
james@538 1083 break;
james@538 1084 default:
james@538 1085 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
james@538 1086 break;
james@538 1087 }
james@634 1088
james@551 1089 if (previous_state == WdfPowerDevicePrepareForHibernation
james@551 1090 || (previous_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
james@551 1091 {
james@551 1092 KdPrint((__DRIVER_NAME " starting up from hibernation\n"));
james@551 1093 }
james@551 1094 else
james@551 1095 {
james@551 1096 }
james@551 1097
james@634 1098 if (previous_state == WdfPowerDevicePrepareForHibernation || previous_state == WdfPowerDeviceD3 || previous_state == WdfPowerDeviceD3Final)
james@634 1099 {
james@634 1100 xppdd->requested_resources_ptr = xppdd->requested_resources_start;
james@634 1101 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@634 1102 }
james@634 1103
james@551 1104 XenConfig_InitConfigPage(device);
james@551 1105
james@551 1106 status = XenPci_GetBackendAndAddWatch(device);
james@551 1107 if (!NT_SUCCESS(status))
james@551 1108 {
james@551 1109 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
james@702 1110 FUNCTION_EXIT_STATUS(status);
james@551 1111 return status;
james@551 1112 }
james@551 1113 status = XenPci_XenConfigDevice(device);
james@551 1114 if (!NT_SUCCESS(status))
james@551 1115 {
james@551 1116 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@624 1117 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
james@551 1118 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
james@702 1119 FUNCTION_EXIT_STATUS(status);
james@551 1120 return status;
james@551 1121 }
james@538 1122
james@536 1123 FUNCTION_EXIT();
james@536 1124
james@538 1125 return status;
james@538 1126 }
james@538 1127
james@538 1128 NTSTATUS
james@538 1129 XenPciPdo_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
james@538 1130 {
james@538 1131 NTSTATUS status = STATUS_SUCCESS;
james@538 1132 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@538 1133 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@538 1134 char path[128];
james@538 1135
james@538 1136 UNREFERENCED_PARAMETER(device);
james@538 1137 UNREFERENCED_PARAMETER(target_state);
james@538 1138
james@538 1139 FUNCTION_ENTER();
james@538 1140
james@538 1141 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@538 1142
james@538 1143
james@538 1144 switch (target_state)
james@538 1145 {
james@538 1146 case WdfPowerDeviceD0:
james@538 1147 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 1148 break;
james@538 1149 case WdfPowerDeviceD1:
james@538 1150 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 1151 break;
james@538 1152 case WdfPowerDeviceD2:
james@538 1153 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
james@538 1154 break;
james@538 1155 case WdfPowerDeviceD3:
james@538 1156 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
james@538 1157 break;
james@538 1158 case WdfPowerDeviceD3Final:
james@538 1159 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
james@538 1160 break;
james@538 1161 case WdfPowerDevicePrepareForHibernation:
james@538 1162 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
james@538 1163 break;
james@538 1164 default:
james@538 1165 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
james@538 1166 break;
james@538 1167 }
james@692 1168
james@538 1169 if (target_state == WdfPowerDevicePrepareForHibernation
james@538 1170 || (target_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
james@538 1171 {
james@538 1172 KdPrint((__DRIVER_NAME " not powering down as we are hibernating\n"));
james@538 1173 }
james@538 1174 else
james@538 1175 {
james@538 1176 status = XenPci_XenShutdownDevice(device);
james@538 1177 }
amir@679 1178
amir@679 1179 /* Remove watch on backend state */
amir@679 1180 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
amir@679 1181 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
amir@679 1182
james@538 1183 FUNCTION_EXIT();
james@538 1184
james@538 1185 return status;
james@538 1186 }
james@538 1187
james@538 1188 NTSTATUS
james@551 1189 XenPciPdo_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
james@538 1190 {
james@538 1191 NTSTATUS status = STATUS_SUCCESS;
james@551 1192
james@538 1193 UNREFERENCED_PARAMETER(device);
james@538 1194 UNREFERENCED_PARAMETER(resources_raw);
james@538 1195 UNREFERENCED_PARAMETER(resources_translated);
james@538 1196
james@538 1197 FUNCTION_ENTER();
james@538 1198 FUNCTION_EXIT();
james@538 1199
james@538 1200 return status;
james@538 1201 }
james@538 1202
james@538 1203 NTSTATUS
james@538 1204 XenPciPdo_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
james@538 1205 {
james@538 1206 NTSTATUS status = STATUS_SUCCESS;
james@538 1207
james@538 1208 UNREFERENCED_PARAMETER(device);
james@538 1209 UNREFERENCED_PARAMETER(resources_translated);
james@538 1210
james@538 1211 FUNCTION_ENTER();
james@538 1212 FUNCTION_EXIT();
james@538 1213
james@538 1214 return status;
james@538 1215 }
james@538 1216
james@538 1217 static VOID
james@538 1218 XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
james@538 1219 {
james@538 1220 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@538 1221
james@538 1222 FUNCTION_ENTER();
james@538 1223
james@538 1224 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@538 1225 switch (notification_type)
james@538 1226 {
james@538 1227 case WdfSpecialFilePaging:
james@538 1228 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
james@538 1229 break;
james@538 1230 case WdfSpecialFileHibernation:
james@538 1231 xppdd->hiber_usage_kludge = is_in_notification_path;
james@538 1232 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
james@538 1233 break;
james@538 1234 case WdfSpecialFileDump:
james@538 1235 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
james@538 1236 break;
james@538 1237 default:
james@538 1238 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
james@538 1239 break;
james@538 1240 }
james@538 1241
james@538 1242 FUNCTION_EXIT();
james@536 1243 }
james@536 1244
james@536 1245 NTSTATUS
james@536 1246 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
james@536 1247 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
james@536 1248 PWDFDEVICE_INIT child_init)
james@536 1249 {
james@536 1250 NTSTATUS status = STATUS_SUCCESS;
james@536 1251 WDF_OBJECT_ATTRIBUTES child_attributes;
james@536 1252 WDFDEVICE child_device;
james@536 1253 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
james@536 1254 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
james@536 1255 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
james@536 1256 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
james@536 1257 PXENPCI_PDO_DEVICE_DATA xppdd;
james@536 1258 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
james@536 1259 WDF_QUERY_INTERFACE_CONFIG interface_config;
james@536 1260 BUS_INTERFACE_STANDARD bus_interface;
james@536 1261 WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
james@538 1262 WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
james@536 1263 UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
james@538 1264 WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
james@536 1265
james@536 1266 FUNCTION_ENTER();
james@536 1267
james@536 1268 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
james@536 1269
james@536 1270 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
james@536 1271 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
james@538 1272 //child_pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPciPdo_EvtDeviceD0EntryPostInterruptsEnabled;
james@536 1273 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
james@538 1274 //child_pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPciPdo_EvtDeviceD0ExitPreInterruptsDisabled;
james@536 1275 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenPciPdo_EvtDevicePrepareHardware;
james@536 1276 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenPciPdo_EvtDeviceReleaseHardware;
james@538 1277 child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
james@536 1278 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
james@538 1279
james@536 1280 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
james@536 1281 identification->device, identification->index, identification->path));
james@536 1282
james@536 1283 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
james@536 1284 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
james@536 1285 if (!NT_SUCCESS(status))
james@536 1286 {
james@536 1287 return status;
james@536 1288 }
james@536 1289
james@536 1290 WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
james@536 1291 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
james@536 1292 pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
james@536 1293 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
james@536 1294 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
james@536 1295 WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
james@536 1296
james@536 1297 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
james@536 1298 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
james@536 1299 if (!NT_SUCCESS(status))
james@536 1300 {
james@536 1301 return status;
james@536 1302 }
james@536 1303 status = WdfPdoInitAddHardwareID(child_init, &buffer);
james@536 1304 if (!NT_SUCCESS(status))
james@536 1305 {
james@536 1306 return status;
james@536 1307 }
james@536 1308 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
james@536 1309 if (!NT_SUCCESS(status))
james@536 1310 {
james@536 1311 return status;
james@536 1312 }
james@536 1313
james@536 1314 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
james@536 1315 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
james@536 1316 if (!NT_SUCCESS(status))
james@536 1317 {
james@536 1318 return status;
james@536 1319 }
james@536 1320
james@536 1321 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
james@536 1322 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
james@536 1323 if (!NT_SUCCESS(status))
james@536 1324 {
james@536 1325 return status;
james@536 1326 }
james@536 1327 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
james@538 1328
james@538 1329 WdfDeviceInitSetPowerNotPageable(child_init);
james@536 1330
james@536 1331 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
james@536 1332 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
james@536 1333 if (!NT_SUCCESS(status))
james@536 1334 {
james@536 1335 return status;
james@536 1336 }
james@536 1337
james@536 1338 xppdd = GetXppdd(child_device);
james@536 1339
james@536 1340 xppdd->wdf_device = child_device;
james@536 1341 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
james@536 1342
james@551 1343 xppdd->config_page_mdl = AllocateUncachedPage();
james@551 1344
james@536 1345 xppdd->device_state.magic = XEN_DEVICE_STATE_MAGIC;
james@536 1346 xppdd->device_state.length = sizeof(XENPCI_DEVICE_STATE);
james@536 1347 xppdd->device_state.suspend_resume_state_pdo = SR_STATE_RUNNING;
james@536 1348 xppdd->device_state.suspend_resume_state_fdo = SR_STATE_RUNNING;
james@536 1349 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
james@536 1350 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
james@536 1351 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
james@536 1352 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
james@536 1353
james@536 1354 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
james@536 1355 child_pnp_capabilities.LockSupported = WdfFalse;
james@536 1356 child_pnp_capabilities.EjectSupported = WdfTrue;
james@536 1357 child_pnp_capabilities.Removable = WdfTrue;
james@536 1358 child_pnp_capabilities.DockDevice = WdfFalse;
james@536 1359 child_pnp_capabilities.UniqueID = WdfFalse;
james@536 1360 child_pnp_capabilities.SilentInstall = WdfTrue;
james@536 1361 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
james@536 1362 child_pnp_capabilities.HardwareDisabled = WdfFalse;
james@536 1363 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
james@536 1364
james@538 1365 WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
james@538 1366 child_power_capabilities.DeviceD1 = WdfTrue;
james@538 1367 child_power_capabilities.WakeFromD1 = WdfTrue;
james@538 1368 child_power_capabilities.DeviceWake = PowerDeviceD1;
james@538 1369 child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
james@538 1370 child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
james@538 1371 child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
james@538 1372 child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
james@538 1373 child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
james@538 1374 child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
james@538 1375 WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
james@536 1376
james@536 1377 bus_interface.Size = sizeof(BUS_INTERFACE_STANDARD);
james@536 1378 bus_interface.Version = 1; //BUS_INTERFACE_STANDARD_VERSION;
james@536 1379 bus_interface.Context = xppdd;
james@537 1380 bus_interface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
james@537 1381 bus_interface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
james@536 1382 bus_interface.TranslateBusAddress = XenPci_BIS_TranslateBusAddress;
james@536 1383 bus_interface.GetDmaAdapter = XenPci_BIS_GetDmaAdapter;
james@536 1384 bus_interface.SetBusData = XenPci_BIS_SetBusData;
james@536 1385 bus_interface.GetBusData = XenPci_BIS_GetBusData;
james@536 1386 WDF_QUERY_INTERFACE_CONFIG_INIT(&interface_config, (PINTERFACE)&bus_interface, &GUID_BUS_INTERFACE_STANDARD, NULL);
james@536 1387 status = WdfDeviceAddQueryInterface(child_device, &interface_config);
james@536 1388 if (!NT_SUCCESS(status))
james@536 1389 {
james@536 1390 return status;
james@536 1391 }
james@536 1392
james@536 1393 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
james@536 1394 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
james@536 1395 xppdd->index = identification->index;
james@536 1396 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
james@624 1397 ExInitializeFastMutex(&xppdd->backend_state_mutex);
james@536 1398 xppdd->backend_state = XenbusStateUnknown;
james@538 1399 xppdd->frontend_state = XenbusStateUnknown;
james@536 1400 xppdd->backend_path[0] = '\0';
james@536 1401
james@536 1402 FUNCTION_EXIT();
james@536 1403
james@536 1404 return status;
james@536 1405 }
james@536 1406
james@536 1407 static __forceinline VOID
james@536 1408 XenPci_Pdo_ChangeSuspendState(WDFDEVICE device, ULONG new_state)
james@536 1409 {
james@536 1410 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1411 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1412
james@536 1413 FUNCTION_ENTER();
james@536 1414 KdPrint((__DRIVER_NAME " setting pdo state to %d\n", new_state));
james@536 1415 xppdd->device_state.suspend_resume_state_pdo = new_state;
james@536 1416 KeMemoryBarrier();
james@536 1417 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xpdd->pdo_event_channel));
james@536 1418 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
james@536 1419 while(xppdd->device_state.suspend_resume_state_fdo != xppdd->device_state.suspend_resume_state_pdo)
james@536 1420 {
james@536 1421 KdPrint((__DRIVER_NAME " waiting...\n"));
james@536 1422 KeWaitForSingleObject(&xpdd->pdo_suspend_event, Executive, KernelMode, FALSE, NULL);
james@536 1423 }
james@536 1424 KdPrint((__DRIVER_NAME " fdo state set to %d\n", new_state));
james@536 1425 FUNCTION_EXIT();
james@536 1426 }
james@536 1427
james@536 1428 /* called at PASSIVE_LEVEL */
james@536 1429 NTSTATUS
james@536 1430 XenPci_Pdo_Suspend(WDFDEVICE device)
james@536 1431 {
james@536 1432 NTSTATUS status = STATUS_SUCCESS;
james@536 1433 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1434 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1435 //LARGE_INTEGER wait_time;
james@536 1436 char path[128];
james@536 1437 PUCHAR in_ptr;
james@536 1438 UCHAR type;
james@536 1439 PVOID setting;
james@536 1440 PVOID value;
james@536 1441 PVOID value2;
james@536 1442
james@536 1443 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
james@536 1444
james@536 1445 if (xppdd->backend_state == XenbusStateConnected)
james@536 1446 {
james@536 1447 xppdd->restart_on_resume = TRUE;
james@536 1448 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_SUSPENDING);
james@536 1449
james@536 1450 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
james@536 1451 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
james@536 1452 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
james@536 1453
james@536 1454 if (xppdd->assigned_resources_start != NULL)
james@536 1455 {
james@536 1456 in_ptr = xppdd->assigned_resources_ptr;
james@536 1457 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 1458 in_ptr = xppdd->assigned_resources_start;
james@536 1459 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
james@536 1460 {
james@536 1461 switch (type)
james@536 1462 {
james@536 1463 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@617 1464 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
james@536 1465 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 1466 EvtChn_Unbind(xpdd, PtrToUlong(value));
james@536 1467 EvtChn_Close(xpdd, PtrToUlong(value));
james@536 1468 break;
james@536 1469 }
james@536 1470 }
james@536 1471 }
james@536 1472
james@536 1473 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@624 1474 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, xppdd);
james@536 1475 }
james@536 1476 else
james@536 1477 {
james@536 1478 xppdd->restart_on_resume = FALSE;
james@536 1479 }
james@536 1480
james@536 1481 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@536 1482
james@536 1483 return status;
james@536 1484 }
james@536 1485
james@536 1486 NTSTATUS
james@536 1487 XenPci_Pdo_Resume(WDFDEVICE device)
james@536 1488 {
james@536 1489 NTSTATUS status = STATUS_SUCCESS;
james@536 1490 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1491 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1492 ULONG old_backend_state;
james@536 1493 PUCHAR src, dst;
james@536 1494
james@536 1495 FUNCTION_ENTER();
james@536 1496 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@536 1497
james@536 1498 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
james@536 1499 old_backend_state = xppdd->backend_state;
james@536 1500
james@536 1501 if (xppdd->restart_on_resume)
james@536 1502 {
james@536 1503 status = XenPci_GetBackendAndAddWatch(device);
james@536 1504
james@536 1505 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
james@536 1506 {
james@536 1507 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
james@536 1508 // this is probably an unrecoverable situation...
james@702 1509 FUNCTION_EXIT();
james@536 1510 return STATUS_UNSUCCESSFUL;
james@536 1511 }
james@536 1512 if (xppdd->assigned_resources_ptr)
james@536 1513 {
james@536 1514 // reset things - feed the 'requested resources' back in
james@536 1515 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 1516 src = xppdd->requested_resources_start;
james@536 1517 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
james@536 1518 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
james@536 1519
james@536 1520 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
james@536 1521
james@536 1522 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
james@536 1523
james@536 1524 MmUnmapIoSpace(dst, xppdd->config_page_length);
james@536 1525 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
james@536 1526 }
james@536 1527 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
james@536 1528 {
james@536 1529 // this is definitely an unrecoverable situation...
james@536 1530 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
james@702 1531 FUNCTION_EXIT();
james@536 1532 return STATUS_UNSUCCESSFUL;
james@536 1533 }
james@536 1534 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RESUMING);
james@536 1535 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RUNNING);
james@536 1536 }
james@536 1537
james@536 1538 FUNCTION_EXIT();
james@536 1539
james@536 1540 return STATUS_SUCCESS;
james@536 1541 }