win-pvdrivers

annotate xenpci/xenpci_pdo.c @ 537:2a74ac2f43bb

more big updates
dma now working under xp
author James Harper <james.harper@bendigoit.com.au>
date Wed Feb 18 22:18:23 2009 +1100 (2009-02-18)
parents 1d39de3ab8d6
children e75bb8d68370
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@537 27 #define MAP_TYPE_VIRTUAL 1
james@537 28 #define MAP_TYPE_MDL 2
james@537 29 #define MAP_TYPE_REMAPPED 3
james@537 30
james@537 31 typedef struct {
james@537 32 ULONG map_type;
james@537 33 PVOID aligned_buffer;
james@537 34 PVOID unaligned_buffer;
james@537 35 ULONG copy_length;
james@537 36 } sg_extra_t;
james@537 37
james@537 38 typedef struct {
james@537 39 ULONG map_type;
james@537 40 PVOID aligned_buffer;
james@537 41 PVOID unaligned_buffer;
james@537 42 ULONG copy_length;
james@537 43 PHYSICAL_ADDRESS logical;
james@537 44 } map_register_t;
james@537 45
james@537 46 typedef struct {
james@537 47 PDEVICE_OBJECT device_object;
james@537 48 ULONG total_map_registers;
james@537 49 ULONG count;
james@537 50 map_register_t regs[1];
james@537 51 } map_register_base_t;
james@536 52
james@536 53 static BOOLEAN
james@536 54 XenPci_BIS_TranslateBusAddress(PVOID context, PHYSICAL_ADDRESS bus_address, ULONG length, PULONG address_space, PPHYSICAL_ADDRESS translated_address)
james@536 55 {
james@536 56 UNREFERENCED_PARAMETER(context);
james@536 57 UNREFERENCED_PARAMETER(length);
james@536 58 /* actually this isn't right - should look up the gref for the physical address and work backwards from that */
james@536 59 FUNCTION_ENTER();
james@536 60 if (*address_space != 0)
james@536 61 {
james@536 62 KdPrint((__DRIVER_NAME " Cannot map I/O space\n"));
james@536 63 FUNCTION_EXIT();
james@536 64 return FALSE;
james@536 65 }
james@536 66 *translated_address = bus_address;
james@536 67 FUNCTION_EXIT();
james@536 68 return TRUE;
james@536 69 }
james@536 70
james@536 71 static VOID
james@536 72 XenPci_DOP_PutDmaAdapter(PDMA_ADAPTER dma_adapter)
james@536 73 {
james@537 74 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
james@536 75
james@536 76 FUNCTION_ENTER();
james@537 77
james@537 78 if (xen_dma_adapter->dma_extension)
james@537 79 ObDereferenceObject(xen_dma_adapter->dma_extension_driver);
james@537 80 ExFreePoolWithTag(xen_dma_adapter->dma_adapter.DmaOperations, XENPCI_POOL_TAG);
james@537 81 ExFreePoolWithTag(xen_dma_adapter, XENPCI_POOL_TAG);
james@537 82
james@536 83 FUNCTION_EXIT();
james@536 84
james@536 85 return;
james@536 86 }
james@536 87
james@536 88 static PVOID
james@536 89 XenPci_DOP_AllocateCommonBuffer(
james@536 90 PDMA_ADAPTER DmaAdapter,
james@536 91 ULONG Length,
james@536 92 PPHYSICAL_ADDRESS LogicalAddress,
james@536 93 BOOLEAN CacheEnabled
james@536 94 )
james@536 95 {
james@537 96 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
james@536 97 PXENPCI_DEVICE_DATA xpdd;
james@536 98 PVOID buffer;
james@536 99 PFN_NUMBER pfn;
james@536 100 grant_ref_t gref;
james@536 101
james@536 102 UNREFERENCED_PARAMETER(DmaAdapter);
james@536 103 UNREFERENCED_PARAMETER(CacheEnabled);
james@536 104
james@536 105 //FUNCTION_ENTER();
james@536 106
james@536 107 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@536 108
james@536 109 //KdPrint((__DRIVER_NAME " Length = %d\n", Length));
james@536 110
james@536 111 buffer = ExAllocatePoolWithTag(NonPagedPool, Length, XENPCI_POOL_TAG);
james@536 112
james@536 113 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(buffer).QuadPart >> PAGE_SHIFT);
james@536 114 ASSERT(pfn);
james@537 115 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
james@536 116 ASSERT(gref);
james@536 117 LogicalAddress->QuadPart = (gref << PAGE_SHIFT) | (PtrToUlong(buffer) & (PAGE_SIZE - 1));
james@536 118
james@536 119 //FUNCTION_EXIT();
james@536 120 return buffer;
james@536 121 }
james@536 122
james@536 123 static VOID
james@536 124 XenPci_DOP_FreeCommonBuffer(
james@536 125 PDMA_ADAPTER dma_adapter,
james@536 126 ULONG length,
james@536 127 PHYSICAL_ADDRESS logical_address,
james@536 128 PVOID virtual_address,
james@536 129 BOOLEAN cache_enabled
james@536 130 )
james@536 131 {
james@536 132 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
james@536 133 PXENPCI_DEVICE_DATA xpdd;
james@536 134 grant_ref_t gref;
james@536 135
james@536 136 UNREFERENCED_PARAMETER(dma_adapter);
james@536 137 UNREFERENCED_PARAMETER(length);
james@536 138 UNREFERENCED_PARAMETER(cache_enabled);
james@536 139
james@537 140 // FUNCTION_ENTER();
james@536 141
james@536 142 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@536 143 gref = (grant_ref_t)(logical_address.QuadPart >> PAGE_SHIFT);
james@536 144 GntTbl_EndAccess(xpdd, gref, FALSE);
james@536 145 ExFreePoolWithTag(virtual_address, XENPCI_POOL_TAG);
james@536 146
james@537 147 // FUNCTION_EXIT();
james@536 148 }
james@536 149
james@536 150 static NTSTATUS
james@536 151 XenPci_DOP_AllocateAdapterChannel(
james@537 152 IN PDMA_ADAPTER dma_adapter,
james@537 153 IN PDEVICE_OBJECT device_object,
james@537 154 IN ULONG NumberOfMapRegisters,
james@537 155 IN PDRIVER_CONTROL ExecutionRoutine,
james@537 156 IN PVOID Context
james@536 157 )
james@536 158 {
james@537 159 //xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
james@537 160 //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@536 161 IO_ALLOCATION_ACTION action;
james@537 162 map_register_base_t *map_register_base;
james@536 163
james@537 164 UNREFERENCED_PARAMETER(dma_adapter);
james@536 165
james@537 166 //FUNCTION_ENTER();
james@537 167
james@537 168 map_register_base = ExAllocatePoolWithTag(NonPagedPool,
james@537 169 FIELD_OFFSET(map_register_base_t, regs) + NumberOfMapRegisters * sizeof(map_register_t), XENPCI_POOL_TAG);
james@537 170 if (!map_register_base)
james@537 171 {
james@537 172 KdPrint((__DRIVER_NAME " Cannot allocate memory for map_register_base\n"));
james@537 173 FUNCTION_EXIT();
james@537 174 return STATUS_INSUFFICIENT_RESOURCES;
james@537 175 }
james@537 176 /* we should also allocate a single page of memory here for remap purposes as once we allocate the map registers there is no failure allowed */
james@537 177 map_register_base->device_object = device_object;
james@537 178 map_register_base->total_map_registers = NumberOfMapRegisters;
james@537 179 map_register_base->count = 0;
james@537 180
james@537 181 action = ExecutionRoutine(device_object, device_object->CurrentIrp, map_register_base, Context);
james@536 182
james@536 183 switch (action)
james@536 184 {
james@536 185 case KeepObject:
james@536 186 KdPrint((__DRIVER_NAME " KeepObject\n"));
james@537 187 ASSERT(FALSE);
james@536 188 break;
james@536 189 case DeallocateObject:
james@536 190 KdPrint((__DRIVER_NAME " DeallocateObject\n"));
james@537 191 ASSERT(FALSE);
james@536 192 break;
james@536 193 case DeallocateObjectKeepRegisters:
james@537 194 //KdPrint((__DRIVER_NAME " DeallocateObjectKeepRegisters\n"));
james@536 195 break;
james@536 196 default:
james@536 197 KdPrint((__DRIVER_NAME " Unknown action %d\n", action));
james@537 198 ASSERT(FALSE);
james@536 199 break;
james@536 200 }
james@537 201 //FUNCTION_EXIT();
james@536 202 return STATUS_SUCCESS;
james@536 203 }
james@536 204
james@536 205 static BOOLEAN
james@536 206 XenPci_DOP_FlushAdapterBuffers(
james@537 207 PDMA_ADAPTER dma_adapter,
james@537 208 PMDL mdl,
james@536 209 PVOID MapRegisterBase,
james@536 210 PVOID CurrentVa,
james@536 211 ULONG Length,
james@537 212 BOOLEAN write_to_device)
james@536 213 {
james@537 214 //xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
james@537 215 //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@537 216 map_register_base_t *map_register_base = MapRegisterBase;
james@537 217 map_register_t *map_register;
james@537 218 ULONG i;
james@537 219
james@537 220 UNREFERENCED_PARAMETER(dma_adapter);
james@537 221 UNREFERENCED_PARAMETER(mdl);
james@536 222 UNREFERENCED_PARAMETER(CurrentVa);
james@536 223 UNREFERENCED_PARAMETER(Length);
james@537 224
james@537 225 //FUNCTION_ENTER();
james@537 226
james@537 227 for (i = 0; i < map_register_base->count; i++)
james@537 228 {
james@537 229 map_register = &map_register_base->regs[i];
james@537 230 if (map_register->map_type == MAP_TYPE_REMAPPED && !write_to_device)
james@537 231 memcpy(map_register->unaligned_buffer, map_register->aligned_buffer, map_register->copy_length);
james@537 232 }
james@537 233 //FUNCTION_EXIT();
james@537 234
james@536 235 return TRUE;
james@536 236 }
james@536 237
james@536 238 static VOID
james@536 239 XenPci_DOP_FreeAdapterChannel(
james@536 240 IN PDMA_ADAPTER DmaAdapter
james@536 241 )
james@536 242 {
james@536 243 UNREFERENCED_PARAMETER(DmaAdapter);
james@536 244
james@536 245 FUNCTION_ENTER();
james@536 246 FUNCTION_EXIT();
james@536 247 }
james@536 248
james@536 249 static VOID
james@536 250 XenPci_DOP_FreeMapRegisters(
james@537 251 PDMA_ADAPTER dma_adapter,
james@536 252 PVOID MapRegisterBase,
james@536 253 ULONG NumberOfMapRegisters)
james@536 254 {
james@537 255 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
james@537 256 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@537 257 map_register_base_t *map_register_base = MapRegisterBase;
james@537 258 map_register_t *map_register;
james@537 259 ULONG i;
james@537 260 grant_ref_t gref;
james@537 261
james@537 262 //FUNCTION_ENTER();
james@537 263 ASSERT(map_register_base->total_map_registers == NumberOfMapRegisters);
james@537 264
james@537 265 for (i = 0; i < map_register_base->count; i++)
james@537 266 {
james@537 267 map_register = &map_register_base->regs[i];
james@537 268 switch (map_register->map_type)
james@537 269 {
james@537 270 case MAP_TYPE_REMAPPED:
james@537 271 gref = (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT);
james@537 272 GntTbl_EndAccess(xpdd, gref, FALSE);
james@537 273 ExFreePoolWithTag(map_register->aligned_buffer, XENPCI_POOL_TAG);
james@537 274 break;
james@537 275 case MAP_TYPE_MDL:
james@537 276 gref = (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT);
james@537 277 GntTbl_EndAccess(xpdd, gref, FALSE);
james@537 278 break;
james@537 279 case MAP_TYPE_VIRTUAL:
james@537 280 break;
james@537 281 }
james@537 282 }
james@537 283 ExFreePoolWithTag(map_register_base, XENPCI_POOL_TAG);
james@537 284
james@537 285 //FUNCTION_EXIT();
james@536 286 }
james@536 287
james@536 288 static PHYSICAL_ADDRESS
james@536 289 XenPci_DOP_MapTransfer(
james@537 290 PDMA_ADAPTER dma_adapter,
james@537 291 PMDL mdl,
james@536 292 PVOID MapRegisterBase,
james@536 293 PVOID CurrentVa,
james@536 294 PULONG Length,
james@536 295 BOOLEAN WriteToDevice)
james@536 296 {
james@537 297 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
james@537 298 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@537 299 map_register_base_t *map_register_base = MapRegisterBase;
james@537 300 map_register_t *map_register = &map_register_base->regs[map_register_base->count];
james@537 301 PDEVICE_OBJECT device_object = map_register_base->device_object;
james@537 302 ULONG page_offset;
james@537 303 PFN_NUMBER pfn;
james@537 304 grant_ref_t gref;
james@537 305 PUCHAR ptr;
james@537 306 ULONG mdl_offset;
james@537 307 ULONG pfn_index;
james@537 308
james@537 309 //FUNCTION_ENTER();
james@537 310
james@537 311 //KdPrint((__DRIVER_NAME " Mdl = %p, MapRegisterBase = %p, MdlVa = %p, CurrentVa = %p, Length = %d\n",
james@537 312 // mdl, MapRegisterBase, MmGetMdlVirtualAddress(mdl), CurrentVa, *Length));
james@537 313
james@537 314 ASSERT(mdl);
james@537 315 ASSERT(map_register_base->count < map_register_base->total_map_registers);
james@536 316
james@537 317 if (xen_dma_adapter->dma_extension)
james@537 318 {
james@537 319 if (xen_dma_adapter->dma_extension->need_virtual_address(device_object->CurrentIrp))
james@537 320 {
james@537 321 map_register->map_type = MAP_TYPE_VIRTUAL;
james@537 322 }
james@537 323 else
james@537 324 {
james@537 325 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(device_object->CurrentIrp);
james@537 326 if ((MmGetMdlByteOffset(mdl) & (alignment - 1)) || (MmGetMdlByteCount(mdl) & (alignment - 1)))
james@537 327 {
james@537 328 map_register->map_type = MAP_TYPE_REMAPPED;
james@537 329 }
james@537 330 else
james@537 331 {
james@537 332 map_register->map_type = MAP_TYPE_MDL;
james@537 333 }
james@537 334 }
james@537 335 }
james@537 336 else
james@537 337 {
james@537 338 map_register->map_type = MAP_TYPE_MDL;
james@537 339 }
james@537 340
james@537 341 switch (map_register->map_type)
james@537 342 {
james@537 343 case MAP_TYPE_MDL:
james@537 344 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL\n"));
james@537 345 mdl_offset = (ULONG)((ULONGLONG)CurrentVa - (ULONGLONG)MmGetMdlVirtualAddress(mdl));
james@537 346 page_offset = PtrToUlong(CurrentVa) & (PAGE_SIZE - 1);
james@537 347 *Length = min(*Length, PAGE_SIZE - page_offset);
james@537 348 pfn_index = (ULONG)(((ULONGLONG)CurrentVa >> PAGE_SHIFT) - ((ULONGLONG)MmGetMdlVirtualAddress(mdl) >> PAGE_SHIFT));
james@537 349 //KdPrint((__DRIVER_NAME " mdl_offset = %d, page_offset = %d, length = %d, pfn_index = %d\n",
james@537 350 // mdl_offset, page_offset, *Length, pfn_index));
james@537 351 pfn = MmGetMdlPfnArray(mdl)[pfn_index];
james@537 352 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
james@537 353 map_register->logical.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | page_offset;
james@537 354 map_register_base->count++;
james@537 355 break;
james@537 356 case MAP_TYPE_REMAPPED:
james@537 357 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED\n"));
james@537 358 *Length = min(*Length, PAGE_SIZE);
james@537 359 map_register->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@537 360 ASSERT(map_register->aligned_buffer);
james@537 361 map_register->unaligned_buffer = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
james@537 362 ASSERT(map_register->unaligned_buffer); /* lazy */
james@537 363 map_register->copy_length = *Length;
james@537 364 if (WriteToDevice)
james@537 365 memcpy(map_register->aligned_buffer, map_register->unaligned_buffer, map_register->copy_length);
james@537 366 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(map_register->aligned_buffer).QuadPart >> PAGE_SHIFT);
james@537 367 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
james@537 368 map_register->logical.QuadPart = (LONGLONG)(gref << PAGE_SHIFT);
james@537 369 map_register_base->count++;
james@537 370 break;
james@537 371 case MAP_TYPE_VIRTUAL:
james@537 372 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL\n"));
james@537 373 ptr = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
james@537 374 ASSERT(ptr); /* lazy */
james@537 375 map_register->logical.QuadPart = (ULONGLONG)ptr;
james@537 376 map_register_base->count++;
james@537 377 break;
james@537 378 default:
james@537 379 ASSERT(FALSE);
james@537 380 break;
james@537 381 }
james@536 382
james@537 383 //FUNCTION_EXIT();
james@537 384 return map_register->logical;
james@536 385 }
james@536 386
james@536 387 static ULONG
james@536 388 XenPci_DOP_GetDmaAlignment(
james@536 389 PDMA_ADAPTER DmaAdapter)
james@536 390 {
james@536 391 UNREFERENCED_PARAMETER(DmaAdapter);
james@536 392
james@536 393 FUNCTION_ENTER();
james@536 394 FUNCTION_EXIT();
james@536 395 return 0;
james@536 396 }
james@536 397
james@536 398 static ULONG
james@536 399 XenPci_DOP_ReadDmaCounter(
james@536 400 PDMA_ADAPTER DmaAdapter)
james@536 401 {
james@536 402 UNREFERENCED_PARAMETER(DmaAdapter);
james@536 403
james@536 404 FUNCTION_ENTER();
james@536 405 FUNCTION_EXIT();
james@536 406 return 0;
james@536 407 }
james@536 408
james@536 409 static NTSTATUS
james@536 410 XenPci_DOP_GetScatterGatherList(
james@536 411 PDMA_ADAPTER DmaAdapter,
james@536 412 PDEVICE_OBJECT DeviceObject,
james@536 413 PMDL Mdl,
james@536 414 PVOID CurrentVa,
james@536 415 ULONG Length,
james@536 416 PDRIVER_LIST_CONTROL ExecutionRoutine,
james@536 417 PVOID Context,
james@536 418 BOOLEAN WriteToDevice)
james@536 419 {
james@536 420 UNREFERENCED_PARAMETER(DmaAdapter);
james@536 421 UNREFERENCED_PARAMETER(DeviceObject);
james@536 422 UNREFERENCED_PARAMETER(Mdl);
james@536 423 UNREFERENCED_PARAMETER(CurrentVa);
james@536 424 UNREFERENCED_PARAMETER(Length);
james@536 425 UNREFERENCED_PARAMETER(ExecutionRoutine);
james@536 426 UNREFERENCED_PARAMETER(Context);
james@536 427 UNREFERENCED_PARAMETER(WriteToDevice);
james@536 428
james@536 429 FUNCTION_ENTER();
james@536 430 FUNCTION_EXIT();
james@536 431 return STATUS_SUCCESS;
james@536 432 }
james@536 433
james@536 434 static VOID
james@536 435 XenPci_DOP_PutScatterGatherList(
james@536 436 IN PDMA_ADAPTER DmaAdapter,
james@536 437 IN PSCATTER_GATHER_LIST ScatterGather,
james@536 438 IN BOOLEAN WriteToDevice
james@536 439 )
james@536 440 {
james@536 441 xen_dma_adapter_t *xen_dma_adapter;
james@536 442 PXENPCI_DEVICE_DATA xpdd;
james@536 443 ULONG i;
james@536 444 sg_extra_t *sg_extra;
james@536 445
james@536 446 UNREFERENCED_PARAMETER(WriteToDevice);
james@536 447
james@536 448 //FUNCTION_ENTER();
james@536 449
james@536 450 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
james@536 451 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@536 452
james@536 453 sg_extra = (sg_extra_t *)((PUCHAR)ScatterGather + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
james@536 454 (sizeof(SCATTER_GATHER_ELEMENT)) * ScatterGather->NumberOfElements);
james@536 455
james@536 456 switch (sg_extra->map_type)
james@536 457 {
james@536 458 case MAP_TYPE_REMAPPED:
james@536 459 for (i = 0; i < ScatterGather->NumberOfElements; i++)
james@536 460 {
james@536 461 grant_ref_t gref;
james@536 462 gref = (grant_ref_t)(ScatterGather->Elements[i].Address.QuadPart >> PAGE_SHIFT);
james@536 463 GntTbl_EndAccess(xpdd, gref, FALSE);
james@536 464 ScatterGather->Elements[i].Address.QuadPart = -1;
james@536 465 }
james@536 466 if (!WriteToDevice)
james@536 467 memcpy(sg_extra->unaligned_buffer, sg_extra->aligned_buffer, sg_extra->copy_length);
james@536 468 ExFreePoolWithTag(sg_extra->aligned_buffer, XENPCI_POOL_TAG);
james@536 469 break;
james@536 470 case MAP_TYPE_MDL:
james@536 471 for (i = 0; i < ScatterGather->NumberOfElements; i++)
james@536 472 {
james@536 473 grant_ref_t gref;
james@536 474 gref = (grant_ref_t)(ScatterGather->Elements[i].Address.QuadPart >> PAGE_SHIFT);
james@536 475 GntTbl_EndAccess(xpdd, gref, FALSE);
james@536 476 ScatterGather->Elements[i].Address.QuadPart = -1;
james@536 477 }
james@536 478 break;
james@536 479 case MAP_TYPE_VIRTUAL:
james@536 480 break;
james@536 481 }
james@536 482 //FUNCTION_EXIT();
james@536 483 }
james@536 484
james@536 485 static NTSTATUS
james@536 486 XenPci_DOP_CalculateScatterGatherList(
james@536 487 PDMA_ADAPTER DmaAdapter,
james@536 488 PMDL Mdl,
james@536 489 PVOID CurrentVa,
james@536 490 ULONG Length,
james@536 491 PULONG ScatterGatherListSize,
james@536 492 PULONG NumberOfMapRegisters
james@536 493 )
james@536 494 {
james@536 495 ULONG elements;
james@536 496 PMDL curr_mdl;
james@536 497
james@536 498 UNREFERENCED_PARAMETER(DmaAdapter);
james@536 499 UNREFERENCED_PARAMETER(Mdl);
james@536 500
james@536 501 FUNCTION_ENTER();
james@536 502
james@536 503 KdPrint((__DRIVER_NAME " Mdl = %p\n", Mdl));
james@536 504 KdPrint((__DRIVER_NAME " CurrentVa = %p\n", CurrentVa));
james@536 505 KdPrint((__DRIVER_NAME " Length = %d\n", Length));
james@536 506 if (Mdl)
james@536 507 {
james@536 508 for (curr_mdl = Mdl, elements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
james@536 509 elements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(CurrentVa, Length);
james@536 510 }
james@536 511 else
james@536 512 {
james@536 513 elements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, Length) + 1;
james@536 514 }
james@536 515
james@536 516 *ScatterGatherListSize = FIELD_OFFSET(SCATTER_GATHER_LIST, Elements)
james@536 517 + sizeof(SCATTER_GATHER_ELEMENT) * elements
james@536 518 + sizeof(sg_extra_t);
james@536 519 if (NumberOfMapRegisters)
james@536 520 *NumberOfMapRegisters = 1;
james@536 521
james@536 522 KdPrint((__DRIVER_NAME " ScatterGatherListSize = %d\n", *ScatterGatherListSize));
james@536 523
james@536 524 FUNCTION_EXIT();
james@536 525 return STATUS_SUCCESS;
james@536 526 }
james@536 527
james@536 528 static NTSTATUS
james@536 529 XenPci_DOP_BuildScatterGatherList(
james@536 530 IN PDMA_ADAPTER DmaAdapter,
james@536 531 IN PDEVICE_OBJECT DeviceObject,
james@536 532 IN PMDL Mdl,
james@536 533 IN PVOID CurrentVa,
james@536 534 IN ULONG Length,
james@536 535 IN PDRIVER_LIST_CONTROL ExecutionRoutine,
james@536 536 IN PVOID Context,
james@536 537 IN BOOLEAN WriteToDevice,
james@536 538 IN PVOID ScatterGatherBuffer,
james@536 539 IN ULONG ScatterGatherBufferLength)
james@536 540 {
james@536 541 ULONG i;
james@536 542 PSCATTER_GATHER_LIST sglist = ScatterGatherBuffer;
james@536 543 PUCHAR ptr;
james@536 544 ULONG remaining = Length;
james@536 545 ULONG total_remaining;
james@536 546 xen_dma_adapter_t *xen_dma_adapter;
james@536 547 PXENPCI_DEVICE_DATA xpdd;
james@536 548 sg_extra_t *sg_extra;
james@536 549 PMDL curr_mdl;
james@536 550 ULONG map_type;
james@536 551 ULONG sg_element;
james@536 552 ULONG offset;
james@536 553 PFN_NUMBER pfn;
james@536 554 grant_ref_t gref;
james@537 555 //PUCHAR StartVa;
james@536 556
james@537 557 ASSERT(MmGetMdlVirtualAddress(Mdl) == CurrentVa);
james@536 558
james@536 559 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
james@536 560 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@536 561
james@536 562 ASSERT(Mdl);
james@537 563
james@536 564 if (xen_dma_adapter->dma_extension)
james@536 565 {
james@536 566 if (xen_dma_adapter->dma_extension->need_virtual_address(DeviceObject->CurrentIrp))
james@536 567 {
james@536 568 ASSERT(!Mdl->Next); /* can only virtual a single buffer */
james@536 569 map_type = MAP_TYPE_VIRTUAL;
james@536 570 sglist->NumberOfElements = 1;
james@536 571 }
james@536 572 else
james@536 573 {
james@536 574 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(DeviceObject->CurrentIrp);
james@537 575 if ((MmGetMdlByteOffset(Mdl) & (alignment - 1)) || (MmGetMdlByteCount(Mdl) & (alignment - 1)))
james@536 576 {
james@537 577 ASSERT(!Mdl->Next); /* can only remap a single buffer for now - will need to check all Mdl's in the future */
james@536 578 map_type = MAP_TYPE_REMAPPED;
james@536 579 sglist->NumberOfElements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(NULL, Length);
james@536 580 }
james@536 581 else
james@536 582 {
james@536 583 map_type = MAP_TYPE_MDL;
james@536 584 for (curr_mdl = Mdl, sglist->NumberOfElements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
james@536 585 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
james@536 586 MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
james@536 587 }
james@536 588 }
james@536 589 }
james@536 590 else
james@536 591 {
james@536 592 map_type = MAP_TYPE_MDL;
james@536 593 for (curr_mdl = Mdl, sglist->NumberOfElements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
james@536 594 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
james@536 595 MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
james@536 596 }
james@536 597 if (ScatterGatherBufferLength < FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
james@536 598 sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t))
james@536 599 {
james@536 600 return STATUS_BUFFER_TOO_SMALL;
james@536 601 }
james@536 602
james@536 603 sg_extra = (sg_extra_t *)((PUCHAR)sglist + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
james@536 604 (sizeof(SCATTER_GATHER_ELEMENT)) * sglist->NumberOfElements);
james@536 605
james@536 606 sg_extra->map_type = map_type;
james@536 607 switch (map_type)
james@536 608 {
james@536 609 case MAP_TYPE_MDL:
james@537 610 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL - %p\n", MmGetMdlVirtualAddress(Mdl)));
james@536 611 total_remaining = Length;
james@536 612 for (sg_element = 0, curr_mdl = Mdl; curr_mdl; curr_mdl = curr_mdl->Next)
james@536 613 {
james@536 614 remaining = MmGetMdlByteCount(curr_mdl);
james@537 615 offset = MmGetMdlByteOffset(curr_mdl);
james@536 616 for (i = 0; i < ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)); i++)
james@536 617 {
james@536 618 //KdPrint((__DRIVER_NAME " element = %d\n", sg_element));
james@536 619 //KdPrint((__DRIVER_NAME " remaining = %d\n", remaining));
james@536 620 pfn = MmGetMdlPfnArray(curr_mdl)[i];
james@536 621 ASSERT(pfn);
james@537 622 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
james@536 623 ASSERT(gref != INVALID_GRANT_REF);
james@536 624 sglist->Elements[sg_element].Address.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | offset;
james@536 625 sglist->Elements[sg_element].Length = min(min(PAGE_SIZE - offset, remaining), total_remaining);
james@536 626 total_remaining -= sglist->Elements[sg_element].Length;
james@536 627 remaining -= sglist->Elements[sg_element].Length;
james@536 628 offset = 0;
james@536 629 sg_element++;
james@536 630 }
james@536 631 }
james@536 632 break;
james@536 633 case MAP_TYPE_REMAPPED:
james@536 634 sg_extra->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, max(Length, PAGE_SIZE), XENPCI_POOL_TAG);
james@536 635 if (!sg_extra->aligned_buffer)
james@536 636 {
james@537 637 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED buffer allocation failed - requested va = %p, length = %d\n", MmGetMdlVirtualAddress(Mdl), Length));
james@536 638 return STATUS_INSUFFICIENT_RESOURCES;
james@536 639 }
james@537 640 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED - %p -> %p\n", MmGetMdlVirtualAddress(Mdl), sg_extra->aligned_buffer));
james@536 641 sg_extra->unaligned_buffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
james@536 642 ASSERT(sg_extra->unaligned_buffer); /* lazy */
james@536 643 sg_extra->copy_length = Length;
james@536 644 if (WriteToDevice)
james@536 645 memcpy(sg_extra->aligned_buffer, sg_extra->unaligned_buffer, sg_extra->copy_length);
james@536 646 for (sg_element = 0, remaining = Length;
james@536 647 sg_element < ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_extra->aligned_buffer, Length); sg_element++)
james@536 648 {
james@536 649 pfn = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)sg_extra->aligned_buffer + (sg_element << PAGE_SHIFT)).QuadPart >> PAGE_SHIFT);
james@536 650 ASSERT(pfn);
james@537 651 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
james@536 652 ASSERT(gref);
james@536 653 sglist->Elements[sg_element].Address.QuadPart = (ULONGLONG)gref << PAGE_SHIFT;
james@536 654 sglist->Elements[sg_element].Length = min(PAGE_SIZE, remaining);
james@536 655 remaining -= sglist->Elements[sg_element].Length;
james@536 656 }
james@536 657 break;
james@536 658 case MAP_TYPE_VIRTUAL:
james@536 659 ptr = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
james@536 660 ASSERT(ptr); /* lazy */
james@536 661 sglist->Elements[0].Address.QuadPart = (ULONGLONG)ptr;
james@536 662 sglist->Elements[0].Length = Length;
james@537 663 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL - %08x\n", sglist->Elements[0].Address.LowPart));
james@536 664 break;
james@536 665 }
james@537 666
james@536 667 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, ScatterGatherBuffer, Context);
james@536 668
james@536 669 //FUNCTION_EXIT();
james@536 670
james@536 671 return STATUS_SUCCESS;
james@536 672 }
james@536 673
james@536 674 static NTSTATUS
james@536 675 XenPci_DOP_BuildMdlFromScatterGatherList(
james@536 676 PDMA_ADAPTER DmaAdapter,
james@536 677 PSCATTER_GATHER_LIST ScatterGather,
james@536 678 PMDL OriginalMdl,
james@536 679 PMDL *TargetMdl)
james@536 680 {
james@536 681 UNREFERENCED_PARAMETER(DmaAdapter);
james@536 682 UNREFERENCED_PARAMETER(ScatterGather);
james@536 683 UNREFERENCED_PARAMETER(OriginalMdl);
james@536 684 UNREFERENCED_PARAMETER(TargetMdl);
james@536 685
james@536 686 FUNCTION_ENTER();
james@536 687 FUNCTION_EXIT();
james@536 688 return STATUS_UNSUCCESSFUL;
james@536 689 }
james@536 690
james@536 691 static PDMA_ADAPTER
james@536 692 XenPci_BIS_GetDmaAdapter(PVOID context, PDEVICE_DESCRIPTION device_description, PULONG number_of_map_registers)
james@536 693 {
james@536 694 xen_dma_adapter_t *xen_dma_adapter;
james@536 695 PDEVICE_OBJECT curr, prev;
james@536 696 PDRIVER_OBJECT fdo_driver_object;
james@536 697 PVOID fdo_driver_extension;
james@536 698
james@536 699 UNREFERENCED_PARAMETER(device_description);
james@536 700
james@536 701 FUNCTION_ENTER();
james@536 702
james@536 703 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@536 704 KdPrint((__DRIVER_NAME " Device Description = %p:\n", device_description));
james@536 705 KdPrint((__DRIVER_NAME " Version = %d\n", device_description->Version));
james@536 706 KdPrint((__DRIVER_NAME " Master = %d\n", device_description->Master));
james@536 707 KdPrint((__DRIVER_NAME " ScatterGather = %d\n", device_description->ScatterGather));
james@536 708 KdPrint((__DRIVER_NAME " DemandMode = %d\n", device_description->DemandMode));
james@536 709 KdPrint((__DRIVER_NAME " AutoInitialize = %d\n", device_description->AutoInitialize));
james@536 710 KdPrint((__DRIVER_NAME " Dma32BitAddresses = %d\n", device_description->Dma32BitAddresses));
james@536 711 KdPrint((__DRIVER_NAME " IgnoreCount = %d\n", device_description->IgnoreCount));
james@536 712 KdPrint((__DRIVER_NAME " Dma64BitAddresses = %d\n", device_description->Dma64BitAddresses));
james@536 713 KdPrint((__DRIVER_NAME " BusNumber = %d\n", device_description->BusNumber));
james@536 714 KdPrint((__DRIVER_NAME " DmaChannel = %d\n", device_description->DmaChannel));
james@536 715 KdPrint((__DRIVER_NAME " InterfaceType = %d\n", device_description->InterfaceType));
james@536 716 KdPrint((__DRIVER_NAME " DmaWidth = %d\n", device_description->DmaWidth));
james@536 717 KdPrint((__DRIVER_NAME " DmaSpeed = %d\n", device_description->DmaSpeed));
james@536 718 KdPrint((__DRIVER_NAME " MaximumLength = %d\n", device_description->MaximumLength));
james@536 719 KdPrint((__DRIVER_NAME " DmaPort = %d\n", device_description->DmaPort));
james@536 720
james@536 721 /*
james@536 722 we have to allocate PAGE_SIZE bytes here because Windows thinks this is
james@536 723 actually an ADAPTER_OBJECT, and then the verifier crashes because
james@536 724 Windows accessed beyond the end of the structure :(
james@536 725 */
james@536 726 xen_dma_adapter = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@536 727 RtlZeroMemory(xen_dma_adapter, PAGE_SIZE);
james@536 728 xen_dma_adapter->dma_adapter.Version = 2;
james@536 729 xen_dma_adapter->dma_adapter.Size = sizeof(DMA_ADAPTER); //xen_dma_adapter_t);
james@536 730 xen_dma_adapter->dma_adapter.DmaOperations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DMA_OPERATIONS), XENPCI_POOL_TAG);
james@536 731 xen_dma_adapter->dma_adapter.DmaOperations->Size = sizeof(DMA_OPERATIONS);
james@536 732 xen_dma_adapter->dma_adapter.DmaOperations->PutDmaAdapter = XenPci_DOP_PutDmaAdapter;
james@536 733 xen_dma_adapter->dma_adapter.DmaOperations->AllocateCommonBuffer = XenPci_DOP_AllocateCommonBuffer;
james@536 734 xen_dma_adapter->dma_adapter.DmaOperations->FreeCommonBuffer = XenPci_DOP_FreeCommonBuffer;
james@536 735 xen_dma_adapter->dma_adapter.DmaOperations->AllocateAdapterChannel = XenPci_DOP_AllocateAdapterChannel;
james@536 736 xen_dma_adapter->dma_adapter.DmaOperations->FlushAdapterBuffers = XenPci_DOP_FlushAdapterBuffers;
james@536 737 xen_dma_adapter->dma_adapter.DmaOperations->FreeAdapterChannel = XenPci_DOP_FreeAdapterChannel;
james@536 738 xen_dma_adapter->dma_adapter.DmaOperations->FreeMapRegisters = XenPci_DOP_FreeMapRegisters;
james@536 739 xen_dma_adapter->dma_adapter.DmaOperations->MapTransfer = XenPci_DOP_MapTransfer;
james@536 740 xen_dma_adapter->dma_adapter.DmaOperations->GetDmaAlignment = XenPci_DOP_GetDmaAlignment;
james@536 741 xen_dma_adapter->dma_adapter.DmaOperations->ReadDmaCounter = XenPci_DOP_ReadDmaCounter;
james@536 742 xen_dma_adapter->dma_adapter.DmaOperations->GetScatterGatherList = XenPci_DOP_GetScatterGatherList;
james@536 743 xen_dma_adapter->dma_adapter.DmaOperations->PutScatterGatherList = XenPci_DOP_PutScatterGatherList;
james@536 744 xen_dma_adapter->dma_adapter.DmaOperations->CalculateScatterGatherList = XenPci_DOP_CalculateScatterGatherList;
james@536 745 xen_dma_adapter->dma_adapter.DmaOperations->BuildScatterGatherList = XenPci_DOP_BuildScatterGatherList;
james@536 746 xen_dma_adapter->dma_adapter.DmaOperations->BuildMdlFromScatterGatherList = XenPci_DOP_BuildMdlFromScatterGatherList;
james@536 747 xen_dma_adapter->xppdd = context;
james@536 748 xen_dma_adapter->dma_extension = NULL;
james@536 749
james@536 750 KdPrint((__DRIVER_NAME " About to call IoGetAttachedDeviceReference\n"));
james@536 751 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(xen_dma_adapter->xppdd->wdf_device));
james@536 752 //curr = WdfDeviceWdmGetAttachedDevice(xen_dma_adapter->xppdd->wdf_device);
james@536 753 KdPrint((__DRIVER_NAME " Before start of loop - curr = %p\n", curr));
james@536 754 while (curr != NULL)
james@536 755 {
james@536 756 fdo_driver_object = curr->DriverObject;
james@536 757 if (fdo_driver_object)
james@536 758 {
james@537 759 ObReferenceObject(fdo_driver_object);
james@536 760 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC));
james@536 761 if (fdo_driver_extension)
james@536 762 {
james@537 763 xen_dma_adapter->dma_extension_driver = fdo_driver_object; /* so we can dereference it on putdmaadapter */
james@536 764 xen_dma_adapter->dma_extension = (dma_driver_extension_t *)fdo_driver_extension;
james@536 765 ObDereferenceObject(curr);
james@536 766 break;
james@536 767 }
james@537 768 else
james@537 769 {
james@537 770 ObDereferenceObject(fdo_driver_object);
james@537 771 }
james@536 772 }
james@536 773 prev = curr;
james@536 774 curr = IoGetLowerDeviceObject(curr);
james@536 775 ObDereferenceObject(prev);
james@536 776 }
james@536 777 KdPrint((__DRIVER_NAME " End of loop\n"));
james@536 778
james@537 779 *number_of_map_registers = 1024; /* why not... */
james@536 780
james@536 781 FUNCTION_EXIT();
james@536 782
james@536 783 return &xen_dma_adapter->dma_adapter;
james@536 784 }
james@536 785
james@536 786 static ULONG
james@536 787 XenPci_BIS_SetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
james@536 788 {
james@536 789 UNREFERENCED_PARAMETER(context);
james@536 790 UNREFERENCED_PARAMETER(data_type);
james@536 791 UNREFERENCED_PARAMETER(buffer);
james@536 792 UNREFERENCED_PARAMETER(offset);
james@536 793 UNREFERENCED_PARAMETER(length);
james@536 794
james@536 795 FUNCTION_ENTER();
james@536 796 FUNCTION_EXIT();
james@536 797 return 0;
james@536 798 }
james@536 799
james@536 800 static ULONG
james@536 801 XenPci_BIS_GetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
james@536 802 {
james@536 803 UNREFERENCED_PARAMETER(context);
james@536 804 UNREFERENCED_PARAMETER(data_type);
james@536 805 UNREFERENCED_PARAMETER(buffer);
james@536 806 UNREFERENCED_PARAMETER(offset);
james@536 807 UNREFERENCED_PARAMETER(length);
james@536 808
james@536 809 FUNCTION_ENTER();
james@536 810 FUNCTION_EXIT();
james@536 811 return 0;
james@536 812 }
james@536 813
james@536 814 /*
james@536 815 Called at PASSIVE_LEVEL(?)
james@536 816 Called during restore
james@536 817 */
james@536 818
james@536 819 static ULONG
james@536 820 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
james@536 821 {
james@536 822 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 823 char path[128];
james@536 824 char *value;
james@536 825 char *err;
james@536 826 ULONG backend_state;
james@536 827
james@536 828 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@536 829 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@536 830 if (err)
james@536 831 {
james@536 832 XenPci_FreeMem(err);
james@536 833 return XenbusStateUnknown;
james@536 834 }
james@536 835 else
james@536 836 {
james@536 837 backend_state = atoi(value);
james@536 838 XenPci_FreeMem(value);
james@536 839 return backend_state;
james@536 840 }
james@536 841 }
james@536 842
james@536 843 static VOID
james@536 844 XenPci_BackEndStateHandler(char *path, PVOID context)
james@536 845 {
james@536 846 WDFDEVICE device = context;
james@536 847 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 848 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 849 ULONG new_backend_state;
james@536 850
james@536 851 #if !DBG
james@536 852 UNREFERENCED_PARAMETER(path);
james@536 853 #endif
james@536 854
james@536 855 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
james@536 856
james@536 857 /* check that path == device/id/state */
james@536 858 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
james@536 859 new_backend_state = XenPci_ReadBackendState(xppdd);
james@536 860 if (new_backend_state == XenbusStateUnknown)
james@536 861 {
james@536 862 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
james@536 863 return;
james@536 864 KdPrint(("Failed to read %s, assuming closed\n", path));
james@536 865 new_backend_state = XenbusStateClosed;
james@536 866 }
james@536 867
james@536 868 if (xppdd->backend_state == new_backend_state)
james@536 869 {
james@536 870 KdPrint((__DRIVER_NAME " state unchanged\n"));
james@536 871 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@536 872 return;
james@536 873 }
james@536 874
james@536 875 xppdd->backend_state = new_backend_state;
james@536 876
james@536 877 switch (xppdd->backend_state)
james@536 878 {
james@536 879 case XenbusStateUnknown:
james@536 880 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown (%s)\n", path));
james@536 881 break;
james@536 882
james@536 883 case XenbusStateInitialising:
james@536 884 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising (%s)\n", path));
james@536 885 break;
james@536 886
james@536 887 case XenbusStateInitWait:
james@536 888 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait (%s)\n", path));
james@536 889 break;
james@536 890
james@536 891 case XenbusStateInitialised:
james@536 892 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised (%s)\n", path));
james@536 893 break;
james@536 894
james@536 895 case XenbusStateConnected:
james@536 896 KdPrint((__DRIVER_NAME " Backend State Changed to Connected (%s)\n", path));
james@536 897 break;
james@536 898
james@536 899 case XenbusStateClosing:
james@536 900 KdPrint((__DRIVER_NAME " Backend State Changed to Closing (%s)\n", path));
james@536 901 if (xpdd->suspend_state == SUSPEND_STATE_NONE)
james@536 902 {
james@536 903 WdfPdoRequestEject(device);
james@536 904 #if 0
james@536 905 if (xppdd->common.device_usage_paging
james@536 906 || xppdd->common.device_usage_dump
james@536 907 || xppdd->common.device_usage_hibernation)
james@536 908 {
james@536 909 KdPrint((__DRIVER_NAME " Not closing device because it is in use\n"));
james@536 910 /* in use by page file, dump file, or hiber file - can't close */
james@536 911 /* we should probably re-check if the device usage changes in the future */
james@536 912 }
james@536 913 else
james@536 914 {
james@536 915
james@536 916 if (xppdd->common.current_pnp_state == Started)
james@536 917 {
james@536 918 KdPrint((__DRIVER_NME " Sending RequestDeviceEject\n"));
james@536 919 WdfPdoRequestEject(device);
james@536 920 }
james@536 921 else
james@536 922 {
james@536 923 KdPrint((__DRIVER_NAME " Not closing device because it is not started\n"));
james@536 924 }
james@536 925 }
james@536 926 #endif
james@536 927 }
james@536 928 break;
james@536 929
james@536 930 case XenbusStateClosed:
james@536 931 KdPrint((__DRIVER_NAME " Backend State Changed to Closed (%s)\n", path));
james@536 932 break;
james@536 933
james@536 934 default:
james@536 935 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d (%s)\n", xppdd->backend_state, path));
james@536 936 break;
james@536 937 }
james@536 938
james@536 939 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
james@536 940
james@536 941 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@536 942
james@536 943 return;
james@536 944 }
james@536 945
james@536 946 static NTSTATUS
james@536 947 XenPci_GetBackendAndAddWatch(WDFDEVICE device)
james@536 948 {
james@536 949 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 950 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 951 char path[128];
james@536 952 PCHAR res;
james@536 953 PCHAR value;
james@536 954
james@536 955 /* Get backend path */
james@536 956 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
james@536 957 "%s/backend", xppdd->path);
james@536 958 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@536 959 if (res)
james@536 960 {
james@536 961 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
james@536 962 XenPci_FreeMem(res);
james@536 963 return STATUS_UNSUCCESSFUL;
james@536 964 }
james@536 965 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
james@536 966 XenPci_FreeMem(value);
james@536 967
james@536 968 /* Add watch on backend state */
james@536 969 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@536 970 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
james@536 971
james@536 972 return STATUS_SUCCESS;
james@536 973 }
james@536 974
james@536 975 static PMDL
james@536 976 XenConfig_MakeConfigPage(WDFDEVICE device)
james@536 977 {
james@536 978 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
james@536 979 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
james@536 980 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@536 981 PMDL mdl;
james@536 982 PUCHAR ptr;
james@536 983 PDEVICE_OBJECT curr, prev;
james@536 984 PDRIVER_OBJECT fdo_driver_object;
james@536 985 PUCHAR fdo_driver_extension;
james@536 986
james@536 987 FUNCTION_ENTER();
james@536 988
james@536 989 mdl = AllocateUncachedPage();
james@536 990 ptr = MmGetMdlVirtualAddress(mdl);
james@536 991 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(device));
james@536 992 //curr = WdfDeviceWdmGetAttachedDevice(device);
james@536 993 while (curr != NULL)
james@536 994 {
james@536 995 fdo_driver_object = curr->DriverObject;
james@536 996 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
james@536 997 if (fdo_driver_object)
james@536 998 {
james@536 999 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
james@536 1000 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
james@536 1001 if (fdo_driver_extension)
james@536 1002 {
james@536 1003 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
james@536 1004 ObDereferenceObject(curr);
james@536 1005 break;
james@536 1006 }
james@536 1007 }
james@536 1008 prev = curr;
james@536 1009 curr = IoGetLowerDeviceObject(curr);
james@536 1010 ObDereferenceObject(prev);
james@536 1011 }
james@536 1012
james@536 1013 FUNCTION_EXIT();
james@536 1014
james@536 1015 return mdl;
james@536 1016 }
james@536 1017
james@536 1018 static NTSTATUS
james@536 1019 XenPci_EvtChn_Bind(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
james@536 1020 {
james@536 1021 WDFDEVICE device = context;
james@536 1022 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1023 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1024
james@536 1025 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext);
james@536 1026 }
james@536 1027
james@536 1028 static NTSTATUS
james@536 1029 XenPci_EvtChn_BindDpc(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
james@536 1030 {
james@536 1031 WDFDEVICE device = context;
james@536 1032 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1033 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1034
james@536 1035 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext);
james@536 1036 }
james@536 1037
james@536 1038 static NTSTATUS
james@536 1039 XenPci_EvtChn_Unbind(PVOID context, evtchn_port_t Port)
james@536 1040 {
james@536 1041 WDFDEVICE device = context;
james@536 1042 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1043 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1044
james@536 1045 return EvtChn_Unbind(xpdd, Port);
james@536 1046 }
james@536 1047
james@536 1048 static NTSTATUS
james@536 1049 XenPci_EvtChn_Mask(PVOID context, evtchn_port_t Port)
james@536 1050 {
james@536 1051 WDFDEVICE device = context;
james@536 1052 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1053 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1054
james@536 1055 return EvtChn_Mask(xpdd, Port);
james@536 1056 }
james@536 1057
james@536 1058 static NTSTATUS
james@536 1059 XenPci_EvtChn_Unmask(PVOID context, evtchn_port_t Port)
james@536 1060 {
james@536 1061 WDFDEVICE device = context;
james@536 1062 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1063 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1064
james@536 1065 return EvtChn_Unmask(xpdd, Port);
james@536 1066 }
james@536 1067
james@536 1068 static NTSTATUS
james@536 1069 XenPci_EvtChn_Notify(PVOID context, evtchn_port_t Port)
james@536 1070 {
james@536 1071 WDFDEVICE device = context;
james@536 1072 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1073 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1074
james@536 1075 return EvtChn_Notify(xpdd, Port);
james@536 1076 }
james@536 1077
james@536 1078 static BOOLEAN
james@536 1079 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port)
james@536 1080 {
james@536 1081 WDFDEVICE device = context;
james@536 1082 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1083 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1084
james@536 1085 return EvtChn_AckEvent(xpdd, port);
james@536 1086 }
james@536 1087
james@536 1088 typedef struct {
james@536 1089 PXEN_EVTCHN_SYNC_ROUTINE sync_routine;
james@536 1090 PVOID sync_context;
james@536 1091 } sync_context_t;
james@536 1092
james@536 1093 static BOOLEAN
james@536 1094 XenPci_EvtChn_Sync_Routine(WDFINTERRUPT interrupt, WDFCONTEXT context)
james@536 1095 {
james@536 1096 sync_context_t *wdf_sync_context = context;
james@536 1097 UNREFERENCED_PARAMETER(interrupt);
james@536 1098 return wdf_sync_context->sync_routine(wdf_sync_context->sync_context);
james@536 1099 }
james@536 1100
james@536 1101 static BOOLEAN
james@536 1102 XenPci_EvtChn_Sync(PVOID context, PXEN_EVTCHN_SYNC_ROUTINE sync_routine, PVOID sync_context)
james@536 1103 {
james@536 1104 WDFDEVICE device = context;
james@536 1105 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1106 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1107 sync_context_t wdf_sync_context;
james@536 1108
james@536 1109 wdf_sync_context.sync_routine = sync_routine;
james@536 1110 wdf_sync_context.sync_context = sync_context;
james@536 1111
james@536 1112 return WdfInterruptSynchronize(xpdd->interrupt, XenPci_EvtChn_Sync_Routine, &wdf_sync_context);
james@536 1113 }
james@536 1114
james@536 1115 static grant_ref_t
james@536 1116 XenPci_GntTbl_GrantAccess(PVOID context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref)
james@536 1117 {
james@536 1118 WDFDEVICE device = context;
james@536 1119 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1120 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1121
james@536 1122 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref);
james@536 1123 }
james@536 1124
james@536 1125 static BOOLEAN
james@536 1126 XenPci_GntTbl_EndAccess(PVOID context, grant_ref_t ref, BOOLEAN keepref)
james@536 1127 {
james@536 1128 WDFDEVICE device = context;
james@536 1129 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1130 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1131
james@536 1132 return GntTbl_EndAccess(xpdd, ref, keepref);
james@536 1133 }
james@536 1134
james@536 1135 static VOID
james@536 1136 XenPci_GntTbl_PutRef(PVOID context, grant_ref_t ref)
james@536 1137 {
james@536 1138 WDFDEVICE device = context;
james@536 1139 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1140 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1141
james@536 1142 GntTbl_PutRef(xpdd, ref);
james@536 1143 }
james@536 1144
james@536 1145 static grant_ref_t
james@536 1146 XenPci_GntTbl_GetRef(PVOID context)
james@536 1147 {
james@536 1148 WDFDEVICE device = context;
james@536 1149 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1150 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1151
james@536 1152 return GntTbl_GetRef(xpdd);
james@536 1153 }
james@536 1154
james@536 1155 PCHAR
james@536 1156 XenPci_XenBus_Read(PVOID context, xenbus_transaction_t xbt, char *path, char **value)
james@536 1157 {
james@536 1158 WDFDEVICE device = context;
james@536 1159 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1160 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1161 return XenBus_Read(xpdd, xbt, path, value);
james@536 1162 }
james@536 1163
james@536 1164 PCHAR
james@536 1165 XenPci_XenBus_Write(PVOID context, xenbus_transaction_t xbt, char *path, char *value)
james@536 1166 {
james@536 1167 WDFDEVICE device = context;
james@536 1168 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1169 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1170 return XenBus_Write(xpdd, xbt, path, value);
james@536 1171 }
james@536 1172
james@536 1173 PCHAR
james@536 1174 XenPci_XenBus_Printf(PVOID context, xenbus_transaction_t xbt, char *path, char *fmt, ...)
james@536 1175 {
james@536 1176 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@536 1177 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@536 1178 //return XenBus_Printf(xpdd, xbt, path, value);
james@536 1179 UNREFERENCED_PARAMETER(context);
james@536 1180 UNREFERENCED_PARAMETER(xbt);
james@536 1181 UNREFERENCED_PARAMETER(path);
james@536 1182 UNREFERENCED_PARAMETER(fmt);
james@536 1183 return NULL;
james@536 1184 }
james@536 1185
james@536 1186 PCHAR
james@536 1187 XenPci_XenBus_StartTransaction(PVOID context, xenbus_transaction_t *xbt)
james@536 1188 {
james@536 1189 WDFDEVICE device = context;
james@536 1190 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1191 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1192 return XenBus_StartTransaction(xpdd, xbt);
james@536 1193 }
james@536 1194
james@536 1195 PCHAR
james@536 1196 XenPci_XenBus_EndTransaction(PVOID context, xenbus_transaction_t xbt, int abort, int *retry)
james@536 1197 {
james@536 1198 WDFDEVICE device = context;
james@536 1199 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1200 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1201 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
james@536 1202 }
james@536 1203
james@536 1204 PCHAR
james@536 1205 XenPci_XenBus_List(PVOID context, xenbus_transaction_t xbt, char *prefix, char ***contents)
james@536 1206 {
james@536 1207 WDFDEVICE device = context;
james@536 1208 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1209 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1210 return XenBus_List(xpdd, xbt, prefix, contents);
james@536 1211 }
james@536 1212
james@536 1213 PCHAR
james@536 1214 XenPci_XenBus_AddWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
james@536 1215 {
james@536 1216 WDFDEVICE device = context;
james@536 1217 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1218 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1219 PCHAR retval;
james@536 1220
james@536 1221 FUNCTION_ENTER();
james@536 1222 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
james@536 1223 if (retval == NULL)
james@536 1224 {
james@536 1225 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
james@536 1226 }
james@536 1227 else
james@536 1228 {
james@536 1229 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
james@536 1230 }
james@536 1231 FUNCTION_EXIT();
james@536 1232 return retval;
james@536 1233 }
james@536 1234
james@536 1235 PCHAR
james@536 1236 XenPci_XenBus_RemWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
james@536 1237 {
james@536 1238 WDFDEVICE device = context;
james@536 1239 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1240 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1241 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
james@536 1242 }
james@536 1243
james@536 1244 /*
james@536 1245 Called at PASSIVE_LEVEL
james@536 1246 Called during restore
james@536 1247 */
james@536 1248
james@536 1249 static NTSTATUS
james@536 1250 XenPci_ChangeFrontendState(WDFDEVICE device, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
james@536 1251 {
james@536 1252 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1253 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1254 LARGE_INTEGER timeout;
james@536 1255 ULONG remaining;
james@536 1256 ULONG thiswait;
james@536 1257 char path[128];
james@536 1258
james@536 1259 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
james@536 1260
james@536 1261 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
james@536 1262 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
james@536 1263
james@536 1264 remaining = maximum_wait_ms;
james@536 1265
james@536 1266 while (xppdd->backend_state != backend_state_response)
james@536 1267 {
james@536 1268 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
james@536 1269 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
james@536 1270 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
james@536 1271 {
james@536 1272 remaining -= thiswait;
james@536 1273 if (remaining == 0)
james@536 1274 {
james@536 1275 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
james@536 1276 return STATUS_UNSUCCESSFUL;
james@536 1277 }
james@536 1278 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
james@536 1279 }
james@536 1280 }
james@536 1281 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@536 1282 return STATUS_SUCCESS;
james@536 1283 }
james@536 1284
james@536 1285 static NTSTATUS
james@536 1286 XenPci_XenConfigDevice(WDFDEVICE device);
james@536 1287
james@536 1288 static NTSTATUS
james@536 1289 XenPci_XenShutdownDevice(PVOID context)
james@536 1290 {
james@536 1291 WDFDEVICE device = context;
james@536 1292 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1293 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1294 PUCHAR in_ptr;
james@536 1295 ULONG i;
james@536 1296 UCHAR type;
james@536 1297 PVOID setting;
james@536 1298 PVOID value;
james@536 1299 PVOID value2;
james@536 1300
james@536 1301 FUNCTION_ENTER();
james@536 1302
james@536 1303 if (xppdd->backend_state == XenbusStateConnected)
james@536 1304 {
james@536 1305 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
james@536 1306 if (xppdd->backend_state == XenbusStateClosing)
james@536 1307 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
james@536 1308 if (xppdd->backend_state == XenbusStateClosed)
james@536 1309 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
james@536 1310 }
james@536 1311 else
james@536 1312 {
james@536 1313 if (xppdd->backend_state == XenbusStateClosing)
james@536 1314 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
james@536 1315 }
james@536 1316
james@536 1317 if (xppdd->assigned_resources_start != NULL)
james@536 1318 {
james@536 1319 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 1320 in_ptr = xppdd->assigned_resources_start;
james@536 1321 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
james@536 1322 {
james@536 1323 switch (type)
james@536 1324 {
james@536 1325 case XEN_INIT_TYPE_RING: /* frontend ring */
james@536 1326 FreePages(value);
james@536 1327 break;
james@536 1328 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@536 1329 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 1330 EvtChn_Unbind(xpdd, PtrToUlong(value));
james@536 1331 EvtChn_Close(xpdd, PtrToUlong(value));
james@536 1332 break;
james@536 1333 case XEN_INIT_TYPE_GRANT_ENTRIES:
james@536 1334 for (i = 0; i < PtrToUlong(setting); i++)
james@536 1335 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value)[i], FALSE);
james@536 1336 break;
james@536 1337 }
james@536 1338 }
james@536 1339 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
james@536 1340 xppdd->assigned_resources_start = NULL;
james@536 1341 }
james@536 1342
james@536 1343 FUNCTION_EXIT();
james@536 1344
james@536 1345 return STATUS_SUCCESS;
james@536 1346 }
james@536 1347
james@536 1348 struct dummy_sring {
james@536 1349 RING_IDX req_prod, req_event;
james@536 1350 RING_IDX rsp_prod, rsp_event;
james@536 1351 uint8_t pad[48];
james@536 1352 };
james@536 1353
james@536 1354 static NTSTATUS
james@536 1355 XenPci_XenConfigDeviceSpecifyBuffers(WDFDEVICE device, PUCHAR src, PUCHAR dst)
james@536 1356 {
james@536 1357 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1358 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1359 NTSTATUS status = STATUS_SUCCESS;
james@536 1360 ULONG i;
james@536 1361 char path[128];
james@536 1362 PCHAR setting, value;
james@536 1363 PCHAR res;
james@536 1364 PVOID address;
james@536 1365 UCHAR type;
james@536 1366 PUCHAR in_ptr; //, in_start;
james@536 1367 PUCHAR out_ptr; //, out_start;
james@536 1368 XENPCI_VECTORS vectors;
james@536 1369 ULONG event_channel;
james@536 1370 ULONG run_type = 0;
james@536 1371 PMDL ring;
james@536 1372 grant_ref_t gref;
james@536 1373 BOOLEAN done_xenbus_init = FALSE;
james@536 1374 PVOID value2;
james@536 1375
james@536 1376 FUNCTION_ENTER();
james@536 1377
james@536 1378 in_ptr = src;
james@536 1379 out_ptr = dst;
james@536 1380
james@536 1381 // always add vectors
james@536 1382 vectors.magic = XEN_DATA_MAGIC;
james@536 1383 vectors.length = sizeof(XENPCI_VECTORS);
james@536 1384 vectors.context = device;
james@536 1385 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
james@536 1386 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
james@536 1387 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
james@536 1388 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
james@536 1389 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
james@536 1390 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
james@536 1391 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
james@536 1392 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
james@536 1393 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
james@536 1394 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
james@536 1395 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
james@536 1396 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
james@536 1397 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
james@536 1398 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
james@536 1399 strncpy(vectors.path, xppdd->path, 128);
james@536 1400 strncpy(vectors.backend_path, xppdd->backend_path, 128);
james@536 1401 //vectors.pdo_event_channel = xpdd->pdo_event_channel;
james@536 1402 vectors.XenBus_Read = XenPci_XenBus_Read;
james@536 1403 vectors.XenBus_Write = XenPci_XenBus_Write;
james@536 1404 vectors.XenBus_Printf = XenPci_XenBus_Printf;
james@536 1405 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
james@536 1406 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
james@536 1407 vectors.XenBus_List = XenPci_XenBus_List;
james@536 1408 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
james@536 1409 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
james@536 1410
james@536 1411 if (qemu_filtered)
james@536 1412 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_ACTIVE, NULL, NULL, NULL);
james@536 1413
james@536 1414 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
james@536 1415
james@536 1416 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
james@536 1417 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
james@536 1418
james@536 1419 // first pass, possibly before state == Connected
james@536 1420 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@536 1421 {
james@536 1422
james@536 1423 if (!done_xenbus_init)
james@536 1424 {
james@536 1425 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
james@536 1426 {
james@536 1427 status = STATUS_UNSUCCESSFUL;
james@536 1428 goto error;
james@536 1429 }
james@536 1430 done_xenbus_init = TRUE;
james@536 1431 }
james@536 1432
james@536 1433 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
james@536 1434
james@536 1435 switch (type)
james@536 1436 {
james@536 1437 case XEN_INIT_TYPE_RUN:
james@536 1438 run_type++;
james@536 1439 break;
james@536 1440 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
james@536 1441 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
james@536 1442 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 1443 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
james@536 1444 break;
james@536 1445 case XEN_INIT_TYPE_RING: /* frontend ring */
james@536 1446 /* we only allocate and do the SHARED_RING_INIT here */
james@536 1447 if ((ring = AllocatePage()) != 0)
james@536 1448 {
james@536 1449 address = MmGetMdlVirtualAddress(ring);
james@536 1450 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
james@536 1451 SHARED_RING_INIT((struct dummy_sring *)address);
james@536 1452 if ((gref = GntTbl_GrantAccess(
james@536 1453 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
james@536 1454 {
james@536 1455 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 1456 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
james@536 1457 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
james@536 1458 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
james@536 1459 // add the grant entry too so it gets freed automatically
james@536 1460 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
james@536 1461 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
james@536 1462 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
james@536 1463 }
james@536 1464 else
james@536 1465 {
james@536 1466 FreePages(ring);
james@536 1467 status = STATUS_UNSUCCESSFUL;
james@536 1468 goto error;
james@536 1469 }
james@536 1470 }
james@536 1471 else
james@536 1472 {
james@536 1473 status = STATUS_UNSUCCESSFUL;
james@536 1474 goto error;
james@536 1475 }
james@536 1476 break;
james@536 1477 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@536 1478 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 1479 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
james@536 1480 {
james@536 1481 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
james@536 1482 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 1483 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
james@536 1484 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
james@536 1485 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
james@536 1486 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
james@536 1487 {
james@536 1488 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
james@536 1489 }
james@536 1490 else
james@536 1491 {
james@537 1492 #pragma warning(suppress:4055)
james@536 1493 EvtChn_Bind(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
james@536 1494 }
james@536 1495 }
james@536 1496 else
james@536 1497 {
james@536 1498 status = STATUS_UNSUCCESSFUL;
james@536 1499 goto error;
james@536 1500 }
james@536 1501 break;
james@536 1502 }
james@536 1503 }
james@536 1504 if (!NT_SUCCESS(status))
james@536 1505 {
james@536 1506 goto error;
james@536 1507 }
james@536 1508 // If XEN_INIT_TYPE_RUN was specified more than once then we skip XenbusStateInitialised here and go straight to XenbusStateConnected at the end
james@536 1509 if (run_type == 1)
james@536 1510 {
james@536 1511 if (XenPci_ChangeFrontendState(device, XenbusStateInitialised, XenbusStateConnected, 30000) != STATUS_SUCCESS)
james@536 1512 {
james@536 1513 status = STATUS_UNSUCCESSFUL;
james@536 1514 goto error;
james@536 1515 }
james@536 1516 }
james@536 1517
james@536 1518 // second pass, possibly after state == Connected
james@536 1519 in_ptr = src;
james@536 1520 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@536 1521 {
james@536 1522 switch(type)
james@536 1523 {
james@536 1524 case XEN_INIT_TYPE_READ_STRING_BACK:
james@536 1525 case XEN_INIT_TYPE_READ_STRING_FRONT:
james@536 1526 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
james@536 1527 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 1528 else
james@536 1529 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
james@536 1530 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@536 1531 if (res)
james@536 1532 {
james@536 1533 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
james@536 1534 XenPci_FreeMem(res);
james@536 1535 ADD_XEN_INIT_RSP(&out_ptr, type, setting, NULL, NULL);
james@536 1536 }
james@536 1537 else
james@536 1538 {
james@536 1539 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
james@536 1540 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, value2);
james@536 1541 XenPci_FreeMem(value);
james@536 1542 }
james@536 1543 break;
james@536 1544 case XEN_INIT_TYPE_VECTORS:
james@536 1545 // this is always done so ignore the request
james@536 1546 break;
james@536 1547 case XEN_INIT_TYPE_GRANT_ENTRIES:
james@536 1548 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
james@536 1549 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
james@536 1550 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
james@536 1551 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
james@536 1552 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
james@536 1553 for (i = 0; i < PtrToUlong(value); i++)
james@536 1554 {
james@536 1555 gref = GntTbl_GetRef(xpdd);
james@536 1556 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
james@536 1557 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
james@536 1558 }
james@536 1559 break;
james@536 1560 }
james@536 1561 }
james@536 1562 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 1563
james@536 1564 if (run_type)
james@536 1565 {
james@536 1566 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
james@536 1567 {
james@536 1568 status = STATUS_UNSUCCESSFUL;
james@536 1569 goto error;
james@536 1570 }
james@536 1571 }
james@536 1572 FUNCTION_EXIT();
james@536 1573 return status;
james@536 1574
james@536 1575 error:
james@536 1576 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
james@536 1577 FUNCTION_EXIT_STATUS(status);
james@536 1578
james@536 1579 return status;
james@536 1580 }
james@536 1581
james@536 1582 static NTSTATUS
james@536 1583 XenPci_XenConfigDevice(WDFDEVICE device)
james@536 1584 {
james@536 1585 NTSTATUS status;
james@536 1586 PUCHAR src, dst;
james@536 1587 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1588
james@536 1589 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
james@536 1590 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
james@536 1591 memcpy(src, dst, xppdd->config_page_length);
james@536 1592
james@536 1593 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
james@536 1594
james@536 1595 MmUnmapIoSpace(dst, xppdd->config_page_length);
james@536 1596 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
james@536 1597
james@536 1598 return status;
james@536 1599 }
james@536 1600
james@536 1601 static NTSTATUS
james@536 1602 XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp)
james@536 1603 {
james@536 1604 NTSTATUS status = STATUS_SUCCESS;
james@536 1605 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1606 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1607 PIO_STACK_LOCATION stack;
james@536 1608 PCM_PARTIAL_RESOURCE_LIST prl;
james@536 1609 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
james@536 1610 ULONG i;
james@536 1611 char path[128];
james@536 1612 PMDL mdl;
james@536 1613
james@536 1614 FUNCTION_ENTER();
james@536 1615 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
james@536 1616
james@536 1617 stack = IoGetCurrentIrpStackLocation(irp);
james@536 1618
james@536 1619 status = XenPci_GetBackendAndAddWatch(device);
james@536 1620 if (!NT_SUCCESS(status)) {
james@536 1621 FUNCTION_ERROR_EXIT();
james@536 1622 return status;
james@536 1623 }
james@536 1624
james@536 1625 mdl = XenConfig_MakeConfigPage(device);
james@536 1626
james@536 1627 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
james@536 1628 for (i = 0; i < prl->Count; i++)
james@536 1629 {
james@536 1630 prd = & prl->PartialDescriptors[i];
james@536 1631 switch (prd->Type)
james@536 1632 {
james@536 1633 case CmResourceTypeMemory:
james@536 1634 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
james@536 1635 {
james@536 1636 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
james@536 1637 prd->u.Memory.Length = MmGetMdlByteCount(mdl);
james@536 1638 }
james@536 1639 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
james@536 1640 {
james@536 1641 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@536 1642 prd->Type = CmResourceTypeInterrupt;
james@536 1643 prd->ShareDisposition = CmResourceShareShared;
james@536 1644 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
james@536 1645 prd->u.Interrupt.Level = xpdd->irq_number;
james@536 1646 prd->u.Interrupt.Vector = xpdd->irq_number;
james@536 1647 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
james@536 1648 xppdd->irq_number = xpdd->irq_number;
james@536 1649 }
james@536 1650 break;
james@536 1651 }
james@536 1652 }
james@536 1653
james@536 1654 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
james@536 1655 for (i = 0; i < prl->Count; i++)
james@536 1656 {
james@536 1657 prd = & prl->PartialDescriptors[i];
james@536 1658 switch (prd->Type)
james@536 1659 {
james@536 1660 case CmResourceTypeMemory:
james@536 1661 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
james@536 1662 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
james@536 1663 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
james@536 1664 {
james@536 1665 if (prd->u.Memory.Length == 0)
james@536 1666 {
james@536 1667 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(mdl)[0]));
james@536 1668 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
james@536 1669 prd->u.Memory.Length = MmGetMdlByteCount(mdl);
james@536 1670 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 1671 }
james@536 1672 xppdd->config_page_phys = prd->u.Memory.Start;
james@536 1673 xppdd->config_page_length = prd->u.Memory.Length;
james@536 1674 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@536 1675 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@536 1676
james@536 1677 status = XenPci_XenConfigDevice(device);
james@536 1678 if (!NT_SUCCESS(status))
james@536 1679 {
james@536 1680 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@536 1681 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
james@536 1682 FUNCTION_ERROR_EXIT();
james@536 1683 return status;
james@536 1684 }
james@536 1685 }
james@536 1686 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
james@536 1687 {
james@536 1688 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@536 1689 prd->Type = CmResourceTypeInterrupt;
james@536 1690 prd->ShareDisposition = CmResourceShareShared;
james@536 1691 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
james@536 1692 prd->u.Interrupt.Level = xpdd->irq_level;
james@536 1693 prd->u.Interrupt.Vector = xpdd->irq_vector;
james@536 1694 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
james@536 1695 xppdd->irq_vector = xpdd->irq_vector;
james@536 1696 xppdd->irq_level = xpdd->irq_level;
james@536 1697 }
james@536 1698 break;
james@536 1699 }
james@536 1700 }
james@536 1701
james@536 1702 IoSkipCurrentIrpStackLocation(irp);
james@536 1703
james@536 1704 FUNCTION_EXIT();
james@536 1705
james@536 1706 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
james@536 1707 }
james@536 1708
james@536 1709 #if 0
james@536 1710 static NTSTATUS
james@536 1711 XenPciPdo_EvtDeviceResourcesQuery(WDFDEVICE device, WDFCMRESLIST resources)
james@536 1712 {
james@536 1713 }
james@536 1714 #endif
james@536 1715
james@536 1716 static NTSTATUS
james@536 1717 XenPciPdo_EvtDeviceResourceRequirementsQuery(WDFDEVICE device, WDFIORESREQLIST requirements_list)
james@536 1718 {
james@536 1719 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1720 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1721 WDFIORESLIST res_list;
james@536 1722 IO_RESOURCE_DESCRIPTOR ird;
james@536 1723
james@536 1724 FUNCTION_ENTER();
james@536 1725
james@536 1726 WdfIoResourceRequirementsListSetInterfaceType(requirements_list, PNPBus);
james@536 1727
james@536 1728 WdfIoResourceListCreate(requirements_list, WDF_NO_OBJECT_ATTRIBUTES, &res_list);
james@536 1729 ird.Option = 0;
james@536 1730 ird.Type = CmResourceTypeMemory;
james@536 1731 ird.ShareDisposition = CmResourceShareShared;
james@536 1732 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
james@536 1733 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
james@536 1734 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
james@536 1735 ird.u.Memory.Length = 0;
james@536 1736 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
james@536 1737 WdfIoResourceListAppendDescriptor(res_list, &ird);
james@536 1738
james@536 1739 ird.Option = 0;
james@536 1740 ird.Type = CmResourceTypeMemory;
james@536 1741 ird.ShareDisposition = CmResourceShareShared;
james@536 1742 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
james@536 1743 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
james@536 1744 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
james@536 1745 ird.u.Memory.Length = 0;
james@536 1746 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
james@536 1747 WdfIoResourceListAppendDescriptor(res_list, &ird);
james@536 1748
james@536 1749 WdfIoResourceRequirementsListAppendIoResList(requirements_list, res_list);
james@536 1750
james@536 1751 FUNCTION_EXIT();
james@536 1752
james@536 1753 return STATUS_SUCCESS;
james@536 1754 }
james@536 1755
james@536 1756 NTSTATUS
james@536 1757 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
james@536 1758 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
james@536 1759 PWDFDEVICE_INIT child_init)
james@536 1760 {
james@536 1761 NTSTATUS status = STATUS_SUCCESS;
james@536 1762 WDF_OBJECT_ATTRIBUTES child_attributes;
james@536 1763 WDFDEVICE child_device;
james@536 1764 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
james@536 1765 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
james@536 1766 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
james@536 1767 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
james@536 1768 PXENPCI_PDO_DEVICE_DATA xppdd;
james@536 1769 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
james@536 1770 WDF_QUERY_INTERFACE_CONFIG interface_config;
james@536 1771 BUS_INTERFACE_STANDARD bus_interface;
james@536 1772 WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
james@536 1773 UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
james@536 1774
james@536 1775 FUNCTION_ENTER();
james@536 1776
james@536 1777 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
james@536 1778
james@536 1779 /*
james@536 1780 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
james@536 1781 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
james@536 1782 child_pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPciPdo_EvtDeviceD0EntryPostInterruptsEnabled;
james@536 1783 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
james@536 1784 child_pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPciPdo_EvtDeviceD0ExitPreInterruptsDisabled;
james@536 1785 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenPciPdo_EvtDevicePrepareHardware;
james@536 1786 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenPciPdo_EvtDeviceReleaseHardware;
james@536 1787 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
james@536 1788 */
james@536 1789 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
james@536 1790 identification->device, identification->index, identification->path));
james@536 1791
james@536 1792 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
james@536 1793 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
james@536 1794 if (!NT_SUCCESS(status))
james@536 1795 {
james@536 1796 return status;
james@536 1797 }
james@536 1798
james@536 1799 WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
james@536 1800 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
james@536 1801 pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
james@536 1802 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
james@536 1803 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
james@536 1804 WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
james@536 1805
james@536 1806 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
james@536 1807 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
james@536 1808 if (!NT_SUCCESS(status))
james@536 1809 {
james@536 1810 return status;
james@536 1811 }
james@536 1812 status = WdfPdoInitAddHardwareID(child_init, &buffer);
james@536 1813 if (!NT_SUCCESS(status))
james@536 1814 {
james@536 1815 return status;
james@536 1816 }
james@536 1817 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
james@536 1818 if (!NT_SUCCESS(status))
james@536 1819 {
james@536 1820 return status;
james@536 1821 }
james@536 1822
james@536 1823 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
james@536 1824 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
james@536 1825 if (!NT_SUCCESS(status))
james@536 1826 {
james@536 1827 return status;
james@536 1828 }
james@536 1829
james@536 1830 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
james@536 1831 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
james@536 1832 if (!NT_SUCCESS(status))
james@536 1833 {
james@536 1834 return status;
james@536 1835 }
james@536 1836 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
james@536 1837
james@536 1838 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
james@536 1839 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
james@536 1840 if (!NT_SUCCESS(status))
james@536 1841 {
james@536 1842 return status;
james@536 1843 }
james@536 1844
james@536 1845 xppdd = GetXppdd(child_device);
james@536 1846
james@536 1847 xppdd->wdf_device = child_device;
james@536 1848 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
james@536 1849
james@536 1850 xppdd->device_state.magic = XEN_DEVICE_STATE_MAGIC;
james@536 1851 xppdd->device_state.length = sizeof(XENPCI_DEVICE_STATE);
james@536 1852 xppdd->device_state.suspend_resume_state_pdo = SR_STATE_RUNNING;
james@536 1853 xppdd->device_state.suspend_resume_state_fdo = SR_STATE_RUNNING;
james@536 1854 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
james@536 1855 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
james@536 1856 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
james@536 1857 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
james@536 1858
james@536 1859 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
james@536 1860 child_pnp_capabilities.LockSupported = WdfFalse;
james@536 1861 child_pnp_capabilities.EjectSupported = WdfTrue;
james@536 1862 child_pnp_capabilities.Removable = WdfTrue;
james@536 1863 child_pnp_capabilities.DockDevice = WdfFalse;
james@536 1864 child_pnp_capabilities.UniqueID = WdfFalse;
james@536 1865 child_pnp_capabilities.SilentInstall = WdfTrue;
james@536 1866 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
james@536 1867 child_pnp_capabilities.HardwareDisabled = WdfFalse;
james@536 1868 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
james@536 1869
james@536 1870 //WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
james@536 1871 //WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
james@536 1872
james@536 1873 bus_interface.Size = sizeof(BUS_INTERFACE_STANDARD);
james@536 1874 bus_interface.Version = 1; //BUS_INTERFACE_STANDARD_VERSION;
james@536 1875 bus_interface.Context = xppdd;
james@537 1876 bus_interface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
james@537 1877 bus_interface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
james@536 1878 bus_interface.TranslateBusAddress = XenPci_BIS_TranslateBusAddress;
james@536 1879 bus_interface.GetDmaAdapter = XenPci_BIS_GetDmaAdapter;
james@536 1880 bus_interface.SetBusData = XenPci_BIS_SetBusData;
james@536 1881 bus_interface.GetBusData = XenPci_BIS_GetBusData;
james@536 1882 WDF_QUERY_INTERFACE_CONFIG_INIT(&interface_config, (PINTERFACE)&bus_interface, &GUID_BUS_INTERFACE_STANDARD, NULL);
james@536 1883 status = WdfDeviceAddQueryInterface(child_device, &interface_config);
james@536 1884 if (!NT_SUCCESS(status))
james@536 1885 {
james@536 1886 return status;
james@536 1887 }
james@536 1888
james@536 1889 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
james@536 1890 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
james@536 1891 xppdd->index = identification->index;
james@536 1892 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
james@536 1893 xppdd->backend_state = XenbusStateUnknown;
james@536 1894 xppdd->backend_path[0] = '\0';
james@536 1895
james@536 1896 FUNCTION_EXIT();
james@536 1897
james@536 1898 return status;
james@536 1899 }
james@536 1900
james@536 1901 static __forceinline VOID
james@536 1902 XenPci_Pdo_ChangeSuspendState(WDFDEVICE device, ULONG new_state)
james@536 1903 {
james@536 1904 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1905 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1906
james@536 1907 FUNCTION_ENTER();
james@536 1908 KdPrint((__DRIVER_NAME " setting pdo state to %d\n", new_state));
james@536 1909 xppdd->device_state.suspend_resume_state_pdo = new_state;
james@536 1910 KeMemoryBarrier();
james@536 1911 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xpdd->pdo_event_channel));
james@536 1912 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
james@536 1913 while(xppdd->device_state.suspend_resume_state_fdo != xppdd->device_state.suspend_resume_state_pdo)
james@536 1914 {
james@536 1915 KdPrint((__DRIVER_NAME " waiting...\n"));
james@536 1916 KeWaitForSingleObject(&xpdd->pdo_suspend_event, Executive, KernelMode, FALSE, NULL);
james@536 1917 }
james@536 1918 KdPrint((__DRIVER_NAME " fdo state set to %d\n", new_state));
james@536 1919 FUNCTION_EXIT();
james@536 1920 }
james@536 1921
james@536 1922 /* called at PASSIVE_LEVEL */
james@536 1923 NTSTATUS
james@536 1924 XenPci_Pdo_Suspend(WDFDEVICE device)
james@536 1925 {
james@536 1926 NTSTATUS status = STATUS_SUCCESS;
james@536 1927 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1928 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1929 //LARGE_INTEGER wait_time;
james@536 1930 char path[128];
james@536 1931 PUCHAR in_ptr;
james@536 1932 UCHAR type;
james@536 1933 PVOID setting;
james@536 1934 PVOID value;
james@536 1935 PVOID value2;
james@536 1936
james@536 1937 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
james@536 1938
james@536 1939 if (xppdd->backend_state == XenbusStateConnected)
james@536 1940 {
james@536 1941 xppdd->restart_on_resume = TRUE;
james@536 1942 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_SUSPENDING);
james@536 1943
james@536 1944 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
james@536 1945 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
james@536 1946 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
james@536 1947
james@536 1948 if (xppdd->assigned_resources_start != NULL)
james@536 1949 {
james@536 1950 in_ptr = xppdd->assigned_resources_ptr;
james@536 1951 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 1952 in_ptr = xppdd->assigned_resources_start;
james@536 1953 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
james@536 1954 {
james@536 1955 switch (type)
james@536 1956 {
james@536 1957 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@536 1958 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 1959 EvtChn_Unbind(xpdd, PtrToUlong(value));
james@536 1960 EvtChn_Close(xpdd, PtrToUlong(value));
james@536 1961 break;
james@536 1962 }
james@536 1963 }
james@536 1964 }
james@536 1965
james@536 1966 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@536 1967 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
james@536 1968 }
james@536 1969 else
james@536 1970 {
james@536 1971 xppdd->restart_on_resume = FALSE;
james@536 1972 }
james@536 1973
james@536 1974 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@536 1975
james@536 1976 return status;
james@536 1977 }
james@536 1978
james@536 1979 NTSTATUS
james@536 1980 XenPci_Pdo_Resume(WDFDEVICE device)
james@536 1981 {
james@536 1982 NTSTATUS status = STATUS_SUCCESS;
james@536 1983 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1984 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1985 ULONG old_backend_state;
james@536 1986 PUCHAR src, dst;
james@536 1987
james@536 1988 FUNCTION_ENTER();
james@536 1989 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@536 1990
james@536 1991 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
james@536 1992 old_backend_state = xppdd->backend_state;
james@536 1993
james@536 1994 if (xppdd->restart_on_resume)
james@536 1995 {
james@536 1996 status = XenPci_GetBackendAndAddWatch(device);
james@536 1997
james@536 1998 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
james@536 1999 {
james@536 2000 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
james@536 2001 // this is probably an unrecoverable situation...
james@536 2002 FUNCTION_ERROR_EXIT();
james@536 2003 return STATUS_UNSUCCESSFUL;
james@536 2004 }
james@536 2005 if (xppdd->assigned_resources_ptr)
james@536 2006 {
james@536 2007 // reset things - feed the 'requested resources' back in
james@536 2008 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 2009 src = xppdd->requested_resources_start;
james@536 2010 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
james@536 2011 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
james@536 2012
james@536 2013 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
james@536 2014
james@536 2015 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
james@536 2016
james@536 2017 MmUnmapIoSpace(dst, xppdd->config_page_length);
james@536 2018 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
james@536 2019 }
james@536 2020 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
james@536 2021 {
james@536 2022 // this is definitely an unrecoverable situation...
james@536 2023 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
james@536 2024 FUNCTION_ERROR_EXIT();
james@536 2025 return STATUS_UNSUCCESSFUL;
james@536 2026 }
james@536 2027 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RESUMING);
james@536 2028 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RUNNING);
james@536 2029 }
james@536 2030
james@536 2031 FUNCTION_EXIT();
james@536 2032
james@536 2033 return STATUS_SUCCESS;
james@536 2034 }
james@536 2035
james@536 2036 #if 0
james@259 2037 NTSTATUS
james@259 2038 XenPci_Power_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
james@259 2039 {
james@272 2040 NTSTATUS status;
james@272 2041 PIO_STACK_LOCATION stack;
james@272 2042 POWER_STATE_TYPE power_type;
james@272 2043 POWER_STATE power_state;
james@272 2044 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
james@272 2045 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@272 2046
james@259 2047 UNREFERENCED_PARAMETER(device_object);
james@259 2048
james@289 2049 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
james@259 2050
james@272 2051 stack = IoGetCurrentIrpStackLocation(irp);
james@272 2052 power_type = stack->Parameters.Power.Type;
james@272 2053 power_state = stack->Parameters.Power.State;
james@272 2054
james@272 2055 switch (stack->MinorFunction)
james@272 2056 {
james@272 2057 case IRP_MN_POWER_SEQUENCE:
james@289 2058 //KdPrint((__DRIVER_NAME " IRP_MN_POWER_SEQUENCE\n"));
james@272 2059 status = STATUS_NOT_SUPPORTED;
james@272 2060 break;
james@272 2061 case IRP_MN_QUERY_POWER:
james@289 2062 //KdPrint((__DRIVER_NAME " IRP_MN_QUERY_POWER\n"));
james@272 2063 status = STATUS_SUCCESS;
james@272 2064 break;
james@272 2065 case IRP_MN_SET_POWER:
james@289 2066 //KdPrint((__DRIVER_NAME " IRP_MN_SET_POWER\n"));
james@272 2067 switch (power_type) {
james@272 2068 case DevicePowerState:
james@272 2069 PoSetPowerState(device_object, power_type, power_state);
james@272 2070 status = STATUS_SUCCESS;
james@272 2071 break;
james@272 2072 case SystemPowerState:
james@272 2073 status = STATUS_SUCCESS;
james@272 2074 break;
james@272 2075 default:
james@272 2076 status = STATUS_NOT_SUPPORTED;
james@272 2077 break;
james@272 2078 }
james@272 2079 break;
james@272 2080 case IRP_MN_WAIT_WAKE:
james@289 2081 //KdPrint((__DRIVER_NAME " IRP_MN_WAIT_WAKE\n"));
james@272 2082 status = STATUS_NOT_SUPPORTED;
james@272 2083 break;
james@272 2084 default:
james@272 2085 //KdPrint((__DRIVER_NAME " Unknown IRP_MN_%d\n", stack->MinorFunction));
james@272 2086 status = STATUS_NOT_SUPPORTED;
james@272 2087 break;
james@272 2088 }
james@272 2089 if (status != STATUS_NOT_SUPPORTED) {
james@272 2090 irp->IoStatus.Status = status;
james@272 2091 }
james@272 2092
james@272 2093 PoStartNextPowerIrp(irp);
james@272 2094 status = irp->IoStatus.Status;
james@259 2095 IoCompleteRequest(irp, IO_NO_INCREMENT);
james@259 2096
james@289 2097 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@259 2098
james@272 2099 return status;
james@259 2100 }
james@259 2101
james@394 2102 /*
james@394 2103 Called at PASSIVE_LEVEL(?)
james@394 2104 Called during restore
james@394 2105 */
james@403 2106
james@403 2107 static ULONG
james@403 2108 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
james@267 2109 {
james@267 2110 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@403 2111 char path[128];
james@267 2112 char *value;
james@267 2113 char *err;
james@403 2114 ULONG backend_state;
james@403 2115
james@403 2116 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@403 2117 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@403 2118 if (err)
james@403 2119 {
james@403 2120 XenPci_FreeMem(err);
james@403 2121 return XenbusStateUnknown;
james@403 2122 }
james@403 2123 else
james@403 2124 {
james@403 2125 backend_state = atoi(value);
james@403 2126 XenPci_FreeMem(value);
james@403 2127 return backend_state;
james@403 2128 }
james@403 2129 }
james@403 2130
james@403 2131 static VOID
james@403 2132 XenPci_BackEndStateHandler(char *path, PVOID context)
james@403 2133 {
james@403 2134 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)context;
james@403 2135 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@267 2136 ULONG new_backend_state;
james@267 2137
steve@461 2138 #if !DBG
steve@461 2139 UNREFERENCED_PARAMETER(path);
steve@461 2140 #endif
steve@461 2141
steve@461 2142 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
james@267 2143
james@267 2144 /* check that path == device/id/state */
james@403 2145 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
james@403 2146 new_backend_state = XenPci_ReadBackendState(xppdd);
james@403 2147 if (new_backend_state == XenbusStateUnknown)
james@267 2148 {
james@385 2149 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
james@360 2150 return;
james@403 2151 KdPrint(("Failed to read %s, assuming closed\n", path));
james@291 2152 new_backend_state = XenbusStateClosed;
james@291 2153 }
james@267 2154
james@267 2155 if (xppdd->backend_state == new_backend_state)
james@267 2156 {
james@267 2157 KdPrint((__DRIVER_NAME " state unchanged\n"));
james@289 2158 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@267 2159 return;
andy@346 2160 }
james@267 2161
james@267 2162 xppdd->backend_state = new_backend_state;
james@267 2163
james@267 2164 switch (xppdd->backend_state)
james@267 2165 {
james@267 2166 case XenbusStateUnknown:
james@406 2167 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown (%s)\n", path));
james@267 2168 break;
james@267 2169
james@267 2170 case XenbusStateInitialising:
james@406 2171 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising (%s)\n", path));
james@267 2172 break;
james@267 2173
james@267 2174 case XenbusStateInitWait:
james@406 2175 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait (%s)\n", path));
james@267 2176 break;
james@267 2177
james@267 2178 case XenbusStateInitialised:
james@406 2179 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised (%s)\n", path));
james@267 2180 break;
james@267 2181
james@267 2182 case XenbusStateConnected:
james@406 2183 KdPrint((__DRIVER_NAME " Backend State Changed to Connected (%s)\n", path));
james@267 2184 break;
james@267 2185
james@267 2186 case XenbusStateClosing:
james@406 2187 KdPrint((__DRIVER_NAME " Backend State Changed to Closing (%s)\n", path));
james@401 2188 if (xpdd->suspend_state == SUSPEND_STATE_NONE)
james@289 2189 {
james@401 2190 if (xppdd->common.device_usage_paging
james@401 2191 || xppdd->common.device_usage_dump
james@401 2192 || xppdd->common.device_usage_hibernation)
james@289 2193 {
james@401 2194 KdPrint((__DRIVER_NAME " Not closing device because it is in use\n"));
james@401 2195 /* in use by page file, dump file, or hiber file - can't close */
james@401 2196 /* we should probably re-check if the device usage changes in the future */
james@289 2197 }
james@289 2198 else
james@289 2199 {
james@401 2200 if (xppdd->common.current_pnp_state == Started)
james@401 2201 {
james@401 2202 KdPrint((__DRIVER_NAME " Sending RequestDeviceEject\n"));
james@401 2203 IoRequestDeviceEject(xppdd->common.pdo);
james@401 2204 }
james@401 2205 else
james@401 2206 {
james@401 2207 KdPrint((__DRIVER_NAME " Not closing device because it is not started\n"));
james@401 2208 }
james@289 2209 }
james@289 2210 }
james@267 2211 break;
james@267 2212
james@267 2213 case XenbusStateClosed:
james@406 2214 KdPrint((__DRIVER_NAME " Backend State Changed to Closed (%s)\n", path));
james@267 2215 break;
james@267 2216
james@267 2217 default:
james@406 2218 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d (%s)\n", xppdd->backend_state, path));
james@267 2219 break;
james@267 2220 }
james@267 2221
james@267 2222 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
james@267 2223
james@267 2224 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@267 2225
james@267 2226 return;
james@267 2227 }
james@267 2228
james@267 2229 struct dummy_sring {
james@267 2230 RING_IDX req_prod, req_event;
james@267 2231 RING_IDX rsp_prod, rsp_event;
james@267 2232 uint8_t pad[48];
james@267 2233 };
james@267 2234
james@394 2235 /*
james@394 2236 Called at PASSIVE_LEVEL
james@394 2237 Called during restore
james@394 2238 */
james@450 2239
james@260 2240 static NTSTATUS
james@274 2241 XenPci_ChangeFrontendState(PXENPCI_PDO_DEVICE_DATA xppdd, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
james@274 2242 {
james@274 2243 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@274 2244 LARGE_INTEGER timeout;
james@274 2245 ULONG remaining;
james@274 2246 ULONG thiswait;
james@274 2247 char path[128];
james@274 2248
james@401 2249 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
james@401 2250
james@274 2251 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
james@274 2252 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
james@274 2253
james@274 2254 remaining = maximum_wait_ms;
james@406 2255
james@406 2256 while (xppdd->backend_state != backend_state_response)
james@274 2257 {
james@274 2258 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
james@274 2259 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
james@274 2260 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
james@274 2261 {
james@274 2262 remaining -= thiswait;
james@274 2263 if (remaining == 0)
james@274 2264 {
james@274 2265 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
james@274 2266 return STATUS_UNSUCCESSFUL;
james@274 2267 }
james@274 2268 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
james@274 2269 }
james@274 2270 }
james@401 2271 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@274 2272 return STATUS_SUCCESS;
james@274 2273 }
james@274 2274
james@274 2275 static VOID
james@274 2276 DUMP_CURRENT_PNP_STATE(PXENPCI_PDO_DEVICE_DATA xppdd)
james@274 2277 {
james@284 2278 switch (xppdd->common.current_pnp_state)
james@274 2279 {
james@274 2280 case Unknown:
james@274 2281 KdPrint((__DRIVER_NAME " pnp_state = Unknown\n"));
james@274 2282 break;
james@274 2283 case NotStarted:
james@274 2284 KdPrint((__DRIVER_NAME " pnp_state = NotStarted\n"));
james@274 2285 break;
james@274 2286 case Started:
james@274 2287 KdPrint((__DRIVER_NAME " pnp_state = Started\n"));
james@274 2288 break;
james@274 2289 case StopPending:
james@274 2290 KdPrint((__DRIVER_NAME " pnp_state = StopPending\n"));
james@274 2291 break;
james@274 2292 case Stopped:
james@274 2293 KdPrint((__DRIVER_NAME " pnp_state = Stopped\n"));
james@274 2294 break;
james@274 2295 case RemovePending:
james@274 2296 KdPrint((__DRIVER_NAME " pnp_state = RemovePending\n"));
james@274 2297 break;
james@274 2298 case SurpriseRemovePending:
james@274 2299 KdPrint((__DRIVER_NAME " pnp_state = SurpriseRemovePending\n"));
james@274 2300 break;
james@274 2301 case Removed:
james@274 2302 KdPrint((__DRIVER_NAME " pnp_state = Removed\n"));
james@274 2303 break;
james@274 2304 default:
james@274 2305 KdPrint((__DRIVER_NAME " pnp_state = ???\n"));
james@274 2306 break;
james@274 2307 }
james@274 2308 }
james@274 2309
james@274 2310 static NTSTATUS
james@515 2311 XenPci_EvtChn_Bind(PVOID Context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
james@274 2312 {
james@274 2313 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@274 2314 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@274 2315
james@274 2316 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext);
james@274 2317 }
james@274 2318
james@274 2319 static NTSTATUS
james@515 2320 XenPci_EvtChn_BindDpc(PVOID Context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
james@274 2321 {
james@274 2322 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@274 2323 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@274 2324
james@274 2325 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext);
james@274 2326 }
james@274 2327
james@274 2328 static NTSTATUS
james@274 2329 XenPci_EvtChn_Unbind(PVOID Context, evtchn_port_t Port)
james@274 2330 {
james@274 2331 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@274 2332 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@274 2333
james@274 2334 return EvtChn_Unbind(xpdd, Port);
james@274 2335 }
james@274 2336
james@274 2337 static NTSTATUS
james@274 2338 XenPci_EvtChn_Mask(PVOID Context, evtchn_port_t Port)
james@274 2339 {
james@274 2340 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@274 2341 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@274 2342
james@274 2343 return EvtChn_Mask(xpdd, Port);
james@274 2344 }
james@274 2345
james@274 2346 static NTSTATUS
james@274 2347 XenPci_EvtChn_Unmask(PVOID Context, evtchn_port_t Port)
james@274 2348 {
james@274 2349 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@274 2350 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@274 2351
james@274 2352 return EvtChn_Unmask(xpdd, Port);
james@274 2353 }
james@274 2354
james@274 2355 static NTSTATUS
james@274 2356 XenPci_EvtChn_Notify(PVOID Context, evtchn_port_t Port)
james@274 2357 {
james@274 2358 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@274 2359 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@274 2360
james@274 2361 return EvtChn_Notify(xpdd, Port);
james@274 2362 }
james@274 2363
james@416 2364 static BOOLEAN
james@416 2365 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port)
james@416 2366 {
james@416 2367 PXENPCI_PDO_DEVICE_DATA xppdd = context;
james@416 2368 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@416 2369
james@416 2370 return EvtChn_AckEvent(xpdd, port);
james@416 2371 }
james@416 2372
james@521 2373 static BOOLEAN
james@521 2374 XenPci_EvtChn_Sync(PVOID context, PKSYNCHRONIZE_ROUTINE sync_routine, PVOID sync_context)
james@521 2375 {
james@521 2376 PXENPCI_PDO_DEVICE_DATA xppdd = context;
james@521 2377 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@521 2378
james@521 2379 return KeSynchronizeExecution(xpdd->interrupt, sync_routine, sync_context);
james@521 2380 }
james@521 2381
james@274 2382 static grant_ref_t
james@274 2383 XenPci_GntTbl_GrantAccess(PVOID Context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref)
james@274 2384 {
james@274 2385 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@274 2386 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@274 2387
james@274 2388 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref);
james@274 2389 }
james@274 2390
james@274 2391 static BOOLEAN
james@274 2392 XenPci_GntTbl_EndAccess(PVOID Context, grant_ref_t ref, BOOLEAN keepref)
james@274 2393 {
james@274 2394 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@274 2395 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@274 2396
james@274 2397 return GntTbl_EndAccess(xpdd, ref, keepref);
james@274 2398 }
james@274 2399
james@274 2400 static VOID
james@274 2401 XenPci_GntTbl_PutRef(PVOID Context, grant_ref_t ref)
james@274 2402 {
james@274 2403 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@274 2404 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@274 2405
james@274 2406 GntTbl_PutRef(xpdd, ref);
james@274 2407 }
james@274 2408
james@274 2409 static grant_ref_t
james@274 2410 XenPci_GntTbl_GetRef(PVOID Context)
james@274 2411 {
james@274 2412 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@274 2413 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@274 2414
james@274 2415 return GntTbl_GetRef(xpdd);
james@274 2416 }
james@274 2417
james@474 2418 PCHAR
james@504 2419 XenPci_XenBus_Read(PVOID Context, xenbus_transaction_t xbt, char *path, char **value)
james@474 2420 {
james@474 2421 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@474 2422 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@474 2423 return XenBus_Read(xpdd, xbt, path, value);
james@474 2424 }
james@474 2425
james@474 2426 PCHAR
james@504 2427 XenPci_XenBus_Write(PVOID Context, xenbus_transaction_t xbt, char *path, char *value)
james@474 2428 {
james@474 2429 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@474 2430 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@474 2431 return XenBus_Write(xpdd, xbt, path, value);
james@474 2432 }
james@474 2433
james@474 2434 PCHAR
james@504 2435 XenPci_XenBus_Printf(PVOID Context, xenbus_transaction_t xbt, char *path, char *fmt, ...)
james@474 2436 {
james@474 2437 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@474 2438 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@474 2439 //return XenBus_Printf(xpdd, xbt, path, value);
james@474 2440 UNREFERENCED_PARAMETER(Context);
james@474 2441 UNREFERENCED_PARAMETER(xbt);
james@474 2442 UNREFERENCED_PARAMETER(path);
james@474 2443 UNREFERENCED_PARAMETER(fmt);
james@474 2444 return NULL;
james@474 2445 }
james@474 2446
james@474 2447 PCHAR
james@474 2448 XenPci_XenBus_StartTransaction(PVOID Context, xenbus_transaction_t *xbt)
james@474 2449 {
james@474 2450 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@474 2451 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@474 2452 return XenBus_StartTransaction(xpdd, xbt);
james@474 2453 }
james@474 2454
james@474 2455 PCHAR
james@474 2456 XenPci_XenBus_EndTransaction(PVOID Context, xenbus_transaction_t xbt, int abort, int *retry)
james@474 2457 {
james@474 2458 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@474 2459 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@474 2460 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
james@474 2461 }
james@474 2462
james@474 2463 PCHAR
james@504 2464 XenPci_XenBus_List(PVOID Context, xenbus_transaction_t xbt, char *prefix, char ***contents)
james@474 2465 {
james@474 2466 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@474 2467 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@474 2468 return XenBus_List(xpdd, xbt, prefix, contents);
james@474 2469 }
james@474 2470
james@474 2471 PCHAR
james@504 2472 XenPci_XenBus_AddWatch(PVOID Context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
james@474 2473 {
james@474 2474 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@474 2475 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@474 2476 PCHAR retval;
james@474 2477
james@474 2478 FUNCTION_ENTER();
james@474 2479 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
james@474 2480 if (retval == NULL)
james@474 2481 {
james@474 2482 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
james@474 2483 }
james@474 2484 else
james@474 2485 {
james@474 2486 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
james@474 2487 }
james@474 2488 FUNCTION_EXIT();
james@474 2489 return retval;
james@474 2490 }
james@474 2491
james@474 2492 PCHAR
james@504 2493 XenPci_XenBus_RemWatch(PVOID Context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
james@474 2494 {
james@474 2495 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@474 2496 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@474 2497 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
james@474 2498 }
james@474 2499
james@274 2500 static NTSTATUS
james@314 2501 XenPci_XenShutdownDevice(PVOID Context)
james@274 2502 {
james@274 2503 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@314 2504 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@314 2505 PUCHAR in_ptr;
james@314 2506 ULONG i;
james@314 2507 UCHAR type;
james@314 2508 PVOID setting;
james@314 2509 PVOID value;
james@274 2510
andy@398 2511 FUNCTION_ENTER();
james@274 2512
james@274 2513 if (xppdd->backend_state == XenbusStateConnected)
james@289 2514 {
james@274 2515 XenPci_ChangeFrontendState(xppdd, XenbusStateClosing, XenbusStateClosing, 30000);
james@289 2516 if (xppdd->backend_state == XenbusStateClosing)
james@289 2517 XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
james@289 2518 if (xppdd->backend_state == XenbusStateClosed)
james@289 2519 XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
james@289 2520 }
james@289 2521 else
james@289 2522 {
james@289 2523 if (xppdd->backend_state == XenbusStateClosing)
james@289 2524 XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
james@289 2525 }
james@314 2526
james@314 2527 if (xppdd->assigned_resources_start != NULL)
james@314 2528 {
james@536 2529 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@314 2530 in_ptr = xppdd->assigned_resources_start;
james@536 2531 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
james@314 2532 {
james@314 2533 switch (type)
james@314 2534 {
james@314 2535 case XEN_INIT_TYPE_RING: /* frontend ring */
james@314 2536 FreePages(value);
james@314 2537 break;
james@314 2538 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@314 2539 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@314 2540 EvtChn_Unbind(xpdd, PtrToUlong(value));
james@409 2541 EvtChn_Close(xpdd, PtrToUlong(value));
james@314 2542 break;
james@314 2543 case XEN_INIT_TYPE_GRANT_ENTRIES:
james@314 2544 for (i = 0; i < PtrToUlong(setting); i++)
james@314 2545 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value)[i], FALSE);
james@314 2546 break;
james@314 2547 }
james@314 2548 }
james@314 2549 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
james@314 2550 xppdd->assigned_resources_start = NULL;
james@314 2551 }
james@314 2552
andy@398 2553 FUNCTION_EXIT();
james@274 2554
james@274 2555 return STATUS_SUCCESS;
james@274 2556 }
james@274 2557
james@305 2558 static NTSTATUS
james@342 2559 XenPci_XenConfigDevice(PVOID context);
james@342 2560
james@342 2561 static NTSTATUS
james@342 2562 XenPci_XenConfigDeviceSpecifyBuffers(PVOID context, PUCHAR src, PUCHAR dst)
james@305 2563 {
james@314 2564 PXENPCI_PDO_DEVICE_DATA xppdd = context;
james@314 2565 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@314 2566 NTSTATUS status = STATUS_SUCCESS;
james@314 2567 ULONG i;
james@314 2568 char path[128];
james@536 2569 PCHAR setting, value, value2;
james@314 2570 PCHAR res;
james@314 2571 PVOID address;
james@314 2572 UCHAR type;
james@342 2573 PUCHAR in_ptr; //, in_start;
james@342 2574 PUCHAR out_ptr; //, out_start;
james@314 2575 XENPCI_VECTORS vectors;
james@314 2576 ULONG event_channel;
james@450 2577 ULONG run_type = 0;
james@314 2578 PMDL ring;
james@314 2579 grant_ref_t gref;
james@342 2580 BOOLEAN done_xenbus_init = FALSE;
james@314 2581
andy@398 2582 FUNCTION_ENTER();
james@305 2583
james@342 2584 in_ptr = src;
james@342 2585 out_ptr = dst;
james@342 2586
james@314 2587 // always add vectors
james@314 2588 vectors.magic = XEN_DATA_MAGIC;
james@314 2589 vectors.length = sizeof(XENPCI_VECTORS);
james@314 2590 vectors.context = xppdd;
james@314 2591 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
james@314 2592 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
james@314 2593 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
james@314 2594 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
james@314 2595 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
james@314 2596 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
james@416 2597 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
james@521 2598 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
james@314 2599 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
james@314 2600 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
james@314 2601 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
james@314 2602 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
james@314 2603 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
james@314 2604 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
james@474 2605 strncpy(vectors.path, xppdd->path, 128);
james@474 2606 strncpy(vectors.backend_path, xppdd->backend_path, 128);
james@480 2607 vectors.pdo_event_channel = xpdd->pdo_event_channel;
james@474 2608 vectors.XenBus_Read = XenPci_XenBus_Read;
james@474 2609 vectors.XenBus_Write = XenPci_XenBus_Write;
james@474 2610 vectors.XenBus_Printf = XenPci_XenBus_Printf;
james@474 2611 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
james@474 2612 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
james@474 2613 vectors.XenBus_List = XenPci_XenBus_List;
james@474 2614 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
james@474 2615 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
james@495 2616
james@497 2617 if (qemu_filtered)
james@536 2618 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_ACTIVE, NULL, NULL, NULL);
james@536 2619
james@536 2620 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
james@495 2621
james@536 2622 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
james@536 2623 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
james@314 2624
james@314 2625 // first pass, possibly before state == Connected
james@536 2626 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@314 2627 {
james@359 2628
james@342 2629 if (!done_xenbus_init)
james@342 2630 {
james@342 2631 if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
james@342 2632 {
james@342 2633 status = STATUS_UNSUCCESSFUL;
james@342 2634 goto error;
james@342 2635 }
james@342 2636 done_xenbus_init = TRUE;
james@342 2637 }
james@342 2638
james@536 2639 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
james@342 2640
james@314 2641 switch (type)
james@314 2642 {
james@314 2643 case XEN_INIT_TYPE_RUN:
james@450 2644 run_type++;
james@450 2645 break;
james@314 2646 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
james@409 2647 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
james@314 2648 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@314 2649 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
james@314 2650 break;
james@314 2651 case XEN_INIT_TYPE_RING: /* frontend ring */
james@314 2652 /* we only allocate and do the SHARED_RING_INIT here */
james@314 2653 if ((ring = AllocatePage()) != 0)
james@314 2654 {
james@314 2655 address = MmGetMdlVirtualAddress(ring);
james@409 2656 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
james@314 2657 SHARED_RING_INIT((struct dummy_sring *)address);
james@314 2658 if ((gref = GntTbl_GrantAccess(
james@415 2659 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
james@314 2660 {
james@314 2661 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@314 2662 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
james@536 2663 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
james@536 2664 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
james@314 2665 // add the grant entry too so it gets freed automatically
james@314 2666 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
james@359 2667 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
james@314 2668 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
james@314 2669 }
james@314 2670 else
james@314 2671 {
james@314 2672 FreePages(ring);
james@314 2673 status = STATUS_UNSUCCESSFUL;
james@314 2674 goto error;
james@314 2675 }
james@314 2676 }
james@314 2677 else
james@314 2678 {
james@314 2679 status = STATUS_UNSUCCESSFUL;
james@314 2680 goto error;
james@314 2681 }
james@314 2682 break;
james@314 2683 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@314 2684 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@314 2685 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
james@314 2686 {
james@409 2687 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
james@314 2688 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@314 2689 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
james@536 2690 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
james@536 2691 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
james@314 2692 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
james@416 2693 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
james@314 2694 }
james@314 2695 else
james@314 2696 {
james@314 2697 status = STATUS_UNSUCCESSFUL;
james@314 2698 goto error;
james@314 2699 }
james@314 2700 break;
james@314 2701 }
james@314 2702 }
james@314 2703 if (!NT_SUCCESS(status))
james@314 2704 {
james@314 2705 goto error;
james@314 2706 }
james@450 2707 // If XEN_INIT_TYPE_RUN was specified more than once then we skip XenbusStateInitialised here and go straight to XenbusStateConnected at the end
james@450 2708 if (run_type == 1)
james@314 2709 {
james@450 2710 if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialised, XenbusStateConnected, 30000) != STATUS_SUCCESS)
james@342 2711 {
james@342 2712 status = STATUS_UNSUCCESSFUL;
james@342 2713 goto error;
james@342 2714 }
james@314 2715 }
james@314 2716
james@314 2717 // second pass, possibly after state == Connected
james@342 2718 in_ptr = src;
james@536 2719 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@314 2720 {
james@314 2721 switch(type)
james@314 2722 {
james@314 2723 case XEN_INIT_TYPE_READ_STRING_BACK:
james@314 2724 case XEN_INIT_TYPE_READ_STRING_FRONT:
james@314 2725 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
james@314 2726 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@314 2727 else
james@314 2728 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
james@314 2729 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@314 2730 if (res)
james@314 2731 {
james@409 2732 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
james@314 2733 XenPci_FreeMem(res);
james@536 2734 ADD_XEN_INIT_RSP(&out_ptr, type, setting, NULL, NULL);
james@314 2735 }
james@314 2736 else
james@314 2737 {
james@409 2738 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
james@536 2739 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, NULL);
james@314 2740 XenPci_FreeMem(value);
james@314 2741 }
james@314 2742 break;
james@314 2743 case XEN_INIT_TYPE_VECTORS:
james@314 2744 // this is always done so ignore the request
james@314 2745 break;
james@314 2746 case XEN_INIT_TYPE_GRANT_ENTRIES:
james@409 2747 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
james@314 2748 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
james@314 2749 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
james@314 2750 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
james@314 2751 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
james@314 2752 for (i = 0; i < PtrToUlong(value); i++)
james@314 2753 {
james@415 2754 gref = GntTbl_GetRef(xpdd);
james@415 2755 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
james@415 2756 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
james@314 2757 }
james@314 2758 break;
james@314 2759 }
james@314 2760 }
james@353 2761 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL);
james@450 2762
james@450 2763 if (run_type)
james@450 2764 {
james@450 2765 if (XenPci_ChangeFrontendState(xppdd, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
james@450 2766 {
james@450 2767 status = STATUS_UNSUCCESSFUL;
james@450 2768 goto error;
james@450 2769 }
james@450 2770 }
james@450 2771 FUNCTION_EXIT();
james@450 2772 return status;
james@353 2773
james@314 2774 error:
james@450 2775 XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
andy@398 2776 FUNCTION_EXIT_STATUS(status);
james@314 2777
james@314 2778 return status;
james@305 2779 }
james@305 2780
james@274 2781 static NTSTATUS
james@342 2782 XenPci_XenConfigDevice(PVOID context)
james@266 2783 {
james@342 2784 NTSTATUS status;
james@342 2785 PUCHAR src, dst;
james@342 2786 PXENPCI_PDO_DEVICE_DATA xppdd = context;
james@342 2787
james@394 2788 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
james@342 2789 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
james@342 2790 memcpy(src, dst, xppdd->config_page_length);
james@342 2791
james@342 2792 status = XenPci_XenConfigDeviceSpecifyBuffers(xppdd, src, dst);
james@342 2793
james@342 2794 MmUnmapIoSpace(dst, xppdd->config_page_length);
james@342 2795 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
james@342 2796
james@342 2797 return status;
james@342 2798 }
james@342 2799
james@342 2800 static NTSTATUS
james@342 2801 XenPci_GetBackendAndAddWatch(PDEVICE_OBJECT device_object)
james@342 2802 {
james@267 2803 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
james@267 2804 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@267 2805 char path[128];
james@267 2806 PCHAR res;
james@342 2807 PCHAR value;
james@266 2808
james@267 2809 /* Get backend path */
james@267 2810 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
james@267 2811 "%s/backend", xppdd->path);
james@267 2812 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@267 2813 if (res)
james@267 2814 {
james@267 2815 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
james@267 2816 XenPci_FreeMem(res);
james@274 2817 return STATUS_UNSUCCESSFUL;
james@267 2818 }
james@267 2819 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
james@267 2820 XenPci_FreeMem(value);
james@267 2821
james@267 2822 /* Add watch on backend state */
james@267 2823 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@267 2824 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
james@403 2825
james@342 2826 return STATUS_SUCCESS;
james@342 2827 }
james@342 2828
james@342 2829 NTSTATUS
james@401 2830 XenPci_Pdo_Resume(PDEVICE_OBJECT device_object)
james@342 2831 {
james@342 2832 NTSTATUS status;
james@342 2833 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
james@422 2834 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@342 2835 ULONG old_backend_state;
james@342 2836 PUCHAR src, dst;
james@342 2837
andy@398 2838 FUNCTION_ENTER();
james@342 2839
james@342 2840 old_backend_state = xppdd->backend_state;
james@409 2841
james@409 2842 if (xppdd->restart_on_resume)
james@409 2843 {
james@409 2844 status = XenPci_GetBackendAndAddWatch(device_object);
james@342 2845
james@342 2846 if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
james@342 2847 {
james@406 2848 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
james@342 2849 // this is probably an unrecoverable situation...
andy@398 2850 FUNCTION_ERROR_EXIT();
james@342 2851 return STATUS_UNSUCCESSFUL;
james@342 2852 }
james@342 2853 if (xppdd->assigned_resources_ptr)
james@342 2854 {
james@342 2855 // reset things - feed the 'requested resources' back in
james@343 2856 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL);
james@342 2857 src = xppdd->requested_resources_start;
james@394 2858 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
james@342 2859 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
james@342 2860
james@342 2861 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
james@342 2862
james@342 2863 status = XenPci_XenConfigDeviceSpecifyBuffers(xppdd, src, dst);
james@342 2864
james@342 2865 MmUnmapIoSpace(dst, xppdd->config_page_length);
james@342 2866 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
james@342 2867 }
james@342 2868 if (XenPci_ChangeFrontendState(xppdd, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
james@342 2869 {
james@342 2870 // this is definitely an unrecoverable situation...
james@406 2871 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
andy@398 2872 FUNCTION_ERROR_EXIT();
james@342 2873 return STATUS_UNSUCCESSFUL;
james@342 2874 }
james@266 2875 }
james@406 2876 else
james@406 2877 {
james@406 2878 KdPrint((__DRIVER_NAME " Not resuming - current_pnp_state = %d, old_backend_state = %d\n", xppdd->common.current_pnp_state, old_backend_state));
james@406 2879 }
james@406 2880 KeMemoryBarrier();
james@406 2881 xppdd->device_state.resume_state = RESUME_STATE_FRONTEND_RESUME;
james@422 2882 KeMemoryBarrier();
james@480 2883 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
andy@398 2884
andy@398 2885 FUNCTION_EXIT();
andy@398 2886
james@342 2887 return STATUS_SUCCESS;
james@342 2888 }
james@342 2889
james@406 2890 /* called at PASSIVE_LEVEL */
james@401 2891 NTSTATUS
james@401 2892 XenPci_Pdo_Suspend(PDEVICE_OBJECT device_object)
james@401 2893 {
james@401 2894 NTSTATUS status = STATUS_SUCCESS;
james@401 2895 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
james@409 2896 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@401 2897 LARGE_INTEGER wait_time;
james@409 2898 char path[128];
james@409 2899 PUCHAR in_ptr;
james@409 2900 UCHAR type;
james@409 2901 PVOID setting;
james@409 2902 PVOID value;
james@401 2903
james@409 2904 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
james@401 2905
james@401 2906 if (xppdd->backend_state == XenbusStateConnected)
james@401 2907 {
james@409 2908 xppdd->restart_on_resume = TRUE;
james@401 2909 xppdd->device_state.resume_state_ack = RESUME_STATE_RUNNING;
james@401 2910 KeMemoryBarrier();
james@401 2911 xppdd->device_state.resume_state = RESUME_STATE_SUSPENDING;
james@401 2912 KeMemoryBarrier();
james@480 2913 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
james@401 2914 while(xppdd->device_state.resume_state_ack != RESUME_STATE_SUSPENDING)
james@401 2915 {
james@401 2916 KdPrint((__DRIVER_NAME " Starting delay - resume_state = %d, resume_state_ack = %d\n", xppdd->device_state.resume_state, xppdd->device_state.resume_state_ack));
james@403 2917 wait_time.QuadPart = 100 * (-1 * 10 * 1000);
james@401 2918 KeDelayExecutionThread(KernelMode, FALSE, &wait_time);
james@401 2919 KdPrint((__DRIVER_NAME " Done with delay\n"));
james@401 2920 }
james@401 2921 KdPrint((__DRIVER_NAME " resume_state acknowledged\n"));
james@401 2922
james@401 2923 XenPci_ChangeFrontendState(xppdd, XenbusStateClosing, XenbusStateClosing, 30000);
james@401 2924 XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
james@409 2925 XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
james@409 2926
james@409 2927 if (xppdd->assigned_resources_start != NULL)
james@409 2928 {
james@409 2929 in_ptr = xppdd->assigned_resources_ptr;
james@409 2930 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL);
james@409 2931 in_ptr = xppdd->assigned_resources_start;
james@409 2932 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value)) != XEN_INIT_TYPE_END)
james@409 2933 {
james@409 2934 switch (type)
james@409 2935 {
james@409 2936 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@409 2937 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@409 2938 EvtChn_Close(xpdd, PtrToUlong(value));
james@409 2939 break;
james@409 2940 }
james@409 2941 }
james@409 2942 }
james@409 2943
james@409 2944 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@409 2945 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
james@401 2946 }
james@409 2947 else
james@409 2948 {
james@409 2949 xppdd->restart_on_resume = FALSE;
james@409 2950 }
james@409 2951
james@401 2952 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@401 2953
james@401 2954 return status;
james@401 2955 }
james@401 2956
james@411 2957 VOID
james@411 2958 XenPci_DumpPdoConfig(PDEVICE_OBJECT device_object)
james@411 2959 {
james@411 2960 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
james@411 2961
steve@461 2962 #if !DBG
steve@461 2963 UNREFERENCED_PARAMETER(xppdd);
steve@461 2964 #endif
steve@461 2965
james@411 2966 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@411 2967 KdPrint((__DRIVER_NAME " backend_path = %s\n", xppdd->backend_path));
james@411 2968 KdPrint((__DRIVER_NAME " irq_number = %d\n", xppdd->irq_number));
james@411 2969 KdPrint((__DRIVER_NAME " irq_level = %d\n", xppdd->irq_level));
james@411 2970 KdPrint((__DRIVER_NAME " irq_vector = %x\n", xppdd->irq_vector));
james@411 2971 }
james@411 2972
james@485 2973 static PMDL
james@485 2974 XenConfig_MakeConfigPage(PDEVICE_OBJECT device_object)
james@485 2975 {
james@485 2976 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
james@485 2977 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
james@485 2978 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@485 2979 PMDL mdl;
james@485 2980 PUCHAR ptr;
james@522 2981 PDEVICE_OBJECT curr, prev;
james@486 2982 PDRIVER_OBJECT fdo_driver_object;
james@486 2983 PUCHAR fdo_driver_extension;
james@486 2984
james@485 2985 mdl = AllocateUncachedPage();
james@485 2986 ptr = MmGetMdlVirtualAddress(mdl);
james@495 2987 curr = IoGetAttachedDeviceReference(device_object);
james@495 2988 while (curr != NULL)
james@485 2989 {
james@495 2990 fdo_driver_object = curr->DriverObject;
james@486 2991 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
james@495 2992 if (fdo_driver_object)
james@486 2993 {
james@495 2994 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
james@495 2995 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
james@495 2996 if (fdo_driver_extension)
james@485 2997 {
james@495 2998 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
james@522 2999 ObDereferenceObject(curr);
james@485 3000 break;
james@485 3001 }
james@485 3002 }
james@522 3003 prev = curr;
james@495 3004 curr = IoGetLowerDeviceObject(curr);
james@522 3005 ObDereferenceObject(prev);
james@485 3006 }
james@485 3007 return mdl;
james@485 3008 }
james@485 3009
james@342 3010 static NTSTATUS
james@342 3011 XenPci_Pnp_StartDevice(PDEVICE_OBJECT device_object, PIRP irp)
james@342 3012 {
james@342 3013 NTSTATUS status = STATUS_SUCCESS;
james@342 3014 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
james@342 3015 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@342 3016 PIO_STACK_LOCATION stack;
james@342 3017 PCM_PARTIAL_RESOURCE_LIST prl;
james@342 3018 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
james@342 3019 ULONG i;
james@342 3020 char path[128];
james@485 3021 PMDL mdl;
james@342 3022
andy@398 3023 FUNCTION_ENTER();
james@495 3024 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
james@342 3025
james@342 3026 DUMP_CURRENT_PNP_STATE(xppdd);
james@342 3027
james@342 3028 stack = IoGetCurrentIrpStackLocation(irp);
james@342 3029
james@342 3030 status = XenPci_GetBackendAndAddWatch(device_object);
andy@398 3031 if (!NT_SUCCESS(status)) {
andy@398 3032 FUNCTION_ERROR_EXIT();
james@342 3033 return status;
andy@398 3034 }
james@266 3035
james@485 3036 mdl = XenConfig_MakeConfigPage(device_object);
james@485 3037
james@411 3038 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
james@411 3039 for (i = 0; i < prl->Count; i++)
james@411 3040 {
james@411 3041 prd = & prl->PartialDescriptors[i];
james@411 3042 switch (prd->Type)
james@411 3043 {
james@529 3044 #if 0
james@411 3045 case CmResourceTypeInterrupt:
james@411 3046 KdPrint((__DRIVER_NAME " CmResourceTypeInterrupt\n"));
james@411 3047 KdPrint((__DRIVER_NAME " irq_number = %02x\n", prd->u.Interrupt.Vector));
james@411 3048 xppdd->irq_number = prd->u.Interrupt.Vector;
james@411 3049 break;
james@529 3050 #endif
james@485 3051 case CmResourceTypeMemory:
james@495 3052 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
james@485 3053 {
james@485 3054 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
james@485 3055 prd->u.Memory.Length = MmGetMdlByteCount(mdl);
james@485 3056 }
james@529 3057 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
james@529 3058 {
james@529 3059 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@529 3060 prd->Type = CmResourceTypeInterrupt;
james@529 3061 prd->ShareDisposition = CmResourceShareShared;
james@529 3062 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
james@529 3063 prd->u.Interrupt.Level = xpdd->irq_number;
james@529 3064 prd->u.Interrupt.Vector = xpdd->irq_number;
james@529 3065 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
james@529 3066 xppdd->irq_number = xpdd->irq_number;
james@529 3067 }
james@485 3068 break;
james@411 3069 }
james@411 3070 }
james@411 3071
james@314 3072 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
james@314 3073 for (i = 0; i < prl->Count; i++)
james@266 3074 {
james@314 3075 prd = & prl->PartialDescriptors[i];
james@314 3076 switch (prd->Type)
james@305 3077 {
james@529 3078 #if 0
james@266 3079 case CmResourceTypeInterrupt:
james@495 3080 KdPrint((__DRIVER_NAME " CmResourceTypeInterrupt (%d)\n", i));
james@362 3081 KdPrint((__DRIVER_NAME " irq_vector = %02x\n", prd->u.Interrupt.Vector));
james@314 3082 KdPrint((__DRIVER_NAME " irq_level = %d\n", prd->u.Interrupt.Level));
james@314 3083 xppdd->irq_vector = prd->u.Interrupt.Vector;
james@314 3084 xppdd->irq_level = (KIRQL)prd->u.Interrupt.Level;
james@266 3085 break;
james@529 3086 #endif
james@267 3087 case CmResourceTypeMemory:
james@495 3088 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
james@485 3089 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
james@495 3090 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
james@485 3091 {
james@495 3092 if (prd->u.Memory.Length == 0)
james@495 3093 {
james@507 3094 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(mdl)[0]));
james@507 3095 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
james@495 3096 prd->u.Memory.Length = MmGetMdlByteCount(mdl);
james@507 3097 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@495 3098 }
james@495 3099 xppdd->config_page_phys = prd->u.Memory.Start;
james@495 3100 xppdd->config_page_length = prd->u.Memory.Length;
james@495 3101 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@495 3102 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@495 3103
james@495 3104 status = XenPci_XenConfigDevice(xppdd);
james@495 3105 if (!NT_SUCCESS(status))
james@495 3106 {
james@495 3107 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@495 3108 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
james@495 3109 FUNCTION_ERROR_EXIT();
james@495 3110 return status;
james@495 3111 }
james@485 3112 }
james@529 3113 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
james@529 3114 {
james@529 3115 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@529 3116 prd->Type = CmResourceTypeInterrupt;
james@529 3117 prd->ShareDisposition = CmResourceShareShared;
james@529 3118 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
james@529 3119 prd->u.Interrupt.Level = xpdd->irq_level;
james@529 3120 prd->u.Interrupt.Vector = xpdd->irq_vector;
james@529 3121 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
james@529 3122 xppdd->irq_vector = xpdd->irq_vector;
james@529 3123 xppdd->irq_level = xpdd->irq_level;
james@529 3124 }
james@485 3125 break;
james@267 3126 }
james@267 3127 }
james@485 3128
james@314 3129 SET_PNP_STATE(&xppdd->common, Started);
james@314 3130
andy@398 3131 FUNCTION_EXIT();
james@274 3132
james@274 3133 return STATUS_SUCCESS;
james@274 3134 }
james@274 3135
james@274 3136 static NTSTATUS
james@274 3137 XenPci_Pnp_RemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
james@274 3138 {
james@305 3139 NTSTATUS status = STATUS_SUCCESS;
james@274 3140 PXENPCI_PDO_DEVICE_DATA xppdd = device_object->DeviceExtension;
james@274 3141 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@274 3142 char path[128];
james@274 3143
james@274 3144 UNREFERENCED_PARAMETER(irp);
james@274 3145
andy@398 3146 FUNCTION_ENTER();
james@274 3147
james@274 3148 DUMP_CURRENT_PNP_STATE(xppdd);
james@274 3149
james@291 3150 if (xppdd->common.current_pnp_state != Removed)
james@274 3151 {
james@314 3152 status = XenPci_XenShutdownDevice(xppdd);
james@291 3153 /* Remove watch on backend state */
james@291 3154 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@291 3155 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
james@291 3156 SET_PNP_STATE(&xppdd->common, Removed);
james@291 3157 IoInvalidateDeviceRelations(xppdd->bus_pdo, BusRelations);
james@274 3158 }
james@312 3159 if (xppdd->reported_missing)
james@291 3160 {
james@291 3161 IoDeleteDevice(xppdd->common.pdo);
james@291 3162 }
james@266 3163
andy@398 3164 FUNCTION_EXIT_STATUS(status);
james@266 3165
james@274 3166 return status;
james@266 3167 }
james@266 3168
james@266 3169 static NTSTATUS
james@260 3170 XenPci_QueryResourceRequirements(PDEVICE_OBJECT device_object, PIRP irp)
james@260 3171 {
james@364 3172 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
james@364 3173 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@260 3174 PIO_RESOURCE_REQUIREMENTS_LIST irrl;
james@260 3175 PIO_RESOURCE_DESCRIPTOR ird;
james@260 3176 ULONG length;
james@305 3177
james@267 3178 UNREFERENCED_PARAMETER(device_object);
james@305 3179
james@529 3180 FUNCTION_ENTER();
james@529 3181
james@260 3182 length = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List) +
james@260 3183 FIELD_OFFSET(IO_RESOURCE_LIST, Descriptors) +
james@485 3184 sizeof(IO_RESOURCE_DESCRIPTOR) * 2;
james@394 3185 irrl = ExAllocatePoolWithTag(NonPagedPool,
james@260 3186 length,
james@260 3187 XENPCI_POOL_TAG);
james@260 3188
james@260 3189 irrl->ListSize = length;
james@529 3190 irrl->InterfaceType = PNPBus; //Internal;
james@260 3191 irrl->BusNumber = 0;
james@260 3192 irrl->SlotNumber = 0;
james@260 3193 irrl->AlternativeLists = 1;
james@260 3194 irrl->List[0].Version = 1;
james@260 3195 irrl->List[0].Revision = 1;
james@267 3196 irrl->List[0].Count = 0;
james@260 3197
james@529 3198 #if 0
james@416 3199 ird = &irrl->List[0].Descriptors[irrl->List[0].Count++];
james@416 3200 ird->Option = 0;
james@416 3201 ird->Type = CmResourceTypeInterrupt;
james@416 3202 ird->ShareDisposition = CmResourceShareShared;
james@432 3203 ird->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
james@529 3204 KdPrint((__DRIVER_NAME " irq type = %s\n", (xpdd->irq_mode == Latched)?"Latched":"Level"));
james@416 3205 ird->u.Interrupt.MinimumVector = xpdd->irq_number;
james@416 3206 ird->u.Interrupt.MaximumVector = xpdd->irq_number;
james@529 3207 #endif
james@529 3208
james@529 3209 ird = &irrl->List[0].Descriptors[irrl->List[0].Count++];
james@529 3210 ird->Option = 0;
james@529 3211 ird->Type = CmResourceTypeMemory;
james@529 3212 ird->ShareDisposition = CmResourceShareShared;
james@529 3213 ird->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
james@529 3214 ird->u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
james@529 3215 ird->u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
james@529 3216 ird->u.Memory.Length = 0;
james@529 3217 ird->u.Memory.Alignment = PAGE_SIZE;
james@485 3218
james@485 3219 ird = &irrl->List[0].Descriptors[irrl->List[0].Count++];
james@485 3220 ird->Option = 0;
james@485 3221 ird->Type = CmResourceTypeMemory;
james@485 3222 ird->ShareDisposition = CmResourceShareShared;
james@485 3223 ird->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
james@529 3224 ird->u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
james@529 3225 ird->u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
james@485 3226 ird->u.Memory.Length = 0;
james@485 3227 ird->u.Memory.Alignment = PAGE_SIZE;
james@529 3228
james@529 3229 irp->IoStatus.Information = (ULONG_PTR)irrl;
james@529 3230
james@529 3231 FUNCTION_EXIT();
james@305 3232
james@260 3233 return STATUS_SUCCESS;
james@260 3234 }
james@260 3235
james@261 3236 static NTSTATUS
james@261 3237 XenPci_Pnp_QueryTargetRelations(PDEVICE_OBJECT device_object, PIRP irp)
james@261 3238 {
james@261 3239 PDEVICE_RELATIONS dr;
james@261 3240 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
james@261 3241
james@261 3242 dr = (PDEVICE_RELATIONS)ExAllocatePoolWithTag (PagedPool, sizeof(DEVICE_RELATIONS), XENPCI_POOL_TAG);
james@261 3243 dr->Count = 1;
james@261 3244 dr->Objects[0] = xppdd->common.pdo;
james@261 3245 ObReferenceObject(xppdd->common.pdo);
james@261 3246 irp->IoStatus.Information = (ULONG_PTR)dr;
james@261 3247
james@261 3248 return STATUS_SUCCESS;
james@261 3249 }
james@261 3250
james@261 3251 static NTSTATUS
james@261 3252 XenPci_Pnp_QueryCapabilities(PDEVICE_OBJECT device_object, PIRP irp)
james@261 3253 {
james@261 3254 PIO_STACK_LOCATION stack;
james@261 3255 PDEVICE_CAPABILITIES dc;
james@261 3256
james@261 3257 UNREFERENCED_PARAMETER(device_object);
james@261 3258
james@261 3259 stack = IoGetCurrentIrpStackLocation(irp);
james@261 3260 dc = stack->Parameters.DeviceCapabilities.Capabilities;
james@261 3261 dc->LockSupported = FALSE;
james@312 3262 dc->EjectSupported = TRUE;
james@289 3263 dc->Removable = TRUE;
james@261 3264 dc->DockDevice = FALSE;
james@261 3265 dc->UniqueID = FALSE;
james@289 3266 dc->SilentInstall = TRUE; //FALSE;
james@261 3267 dc->RawDeviceOK = FALSE;
james@289 3268 dc->SurpriseRemovalOK = TRUE;
james@261 3269 dc->HardwareDisabled = FALSE;
james@261 3270 dc->NoDisplayInUI = FALSE;
james@261 3271 dc->DeviceWake = PowerDeviceUnspecified;
james@261 3272 dc->D1Latency = 0;
james@261 3273 dc->D2Latency = 0;
james@261 3274 dc->D3Latency = 0;
james@261 3275 /* we are really supposed to get the DeviceState entries from the parent... */
james@261 3276 dc->DeviceState[PowerSystemWorking] = PowerDeviceD0;
james@261 3277 dc->DeviceState[PowerSystemSleeping1] = PowerDeviceUnspecified;
james@261 3278 dc->DeviceState[PowerSystemSleeping2] = PowerDeviceUnspecified;
james@261 3279 dc->DeviceState[PowerSystemSleeping3] = PowerDeviceUnspecified;
james@261 3280 dc->DeviceState[PowerSystemHibernate] = PowerDeviceD3;
james@261 3281 dc->DeviceState[PowerSystemShutdown] = PowerDeviceD3;
james@261 3282 return STATUS_SUCCESS;
james@261 3283 }
james@261 3284
james@529 3285 static VOID
james@529 3286 XenPci_IS_InterfaceReference(PVOID context)
james@529 3287 {
james@529 3288 UNREFERENCED_PARAMETER(context);
james@536 3289 FUNCTION_ENTER();
james@536 3290 FUNCTION_EXIT();
james@529 3291 }
james@529 3292
james@529 3293 static VOID
james@529 3294 XenPci_IS_InterfaceDereference(PVOID context)
james@529 3295 {
james@529 3296 UNREFERENCED_PARAMETER(context);
james@536 3297 FUNCTION_ENTER();
james@536 3298 FUNCTION_EXIT();
james@529 3299 }
james@529 3300