win-pvdrivers

annotate xenpci/xenpci_pdo.c @ 1004:a5d1d333e0e2

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