win-pvdrivers

annotate xenpci/xenpci_pdo.c @ 835:e5651aba4e03

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