win-pvdrivers

annotate xenpci/xenpci_pdo.c @ 972:ef1f25e2c281

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