win-pvdrivers

annotate xenpci/xenpci_pdo.c @ 679:bccfedce08ea

remove xenstore watches on hibernation too
without this, the watches keep on stacking and might exceed the limit, preventing addition of any more watches

this can also cause 0x10d BSOD for reasons yet unclear
it probably has to do with xenstore ring-buffer getting corrupt and discarding responses
wdf power opretaion times out because XenPci_UpdateBackendState() can't get a response
author Amir Szekely <amir@neocleus.com>
date Sat Sep 26 01:19:29 2009 +0300 (2009-09-26)
parents e5522de3be37
children 38fd04771db8
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 ULONG copy_length;
james@600 35 PMDL mdl;
james@600 36 PVOID currentva;
james@558 37 BOOLEAN allocated_by_me;
james@537 38 } sg_extra_t;
james@537 39
james@537 40 typedef struct {
james@537 41 ULONG map_type;
james@537 42 PVOID aligned_buffer;
james@537 43 PVOID unaligned_buffer;
james@537 44 ULONG copy_length;
james@537 45 PHYSICAL_ADDRESS logical;
james@537 46 } map_register_t;
james@537 47
james@537 48 typedef struct {
james@537 49 PDEVICE_OBJECT device_object;
james@537 50 ULONG total_map_registers;
james@537 51 ULONG count;
james@537 52 map_register_t regs[1];
james@537 53 } map_register_base_t;
james@536 54
james@536 55 static BOOLEAN
james@536 56 XenPci_BIS_TranslateBusAddress(PVOID context, PHYSICAL_ADDRESS bus_address, ULONG length, PULONG address_space, PPHYSICAL_ADDRESS translated_address)
james@536 57 {
james@536 58 UNREFERENCED_PARAMETER(context);
james@536 59 UNREFERENCED_PARAMETER(length);
james@536 60 /* actually this isn't right - should look up the gref for the physical address and work backwards from that */
james@536 61 FUNCTION_ENTER();
james@536 62 if (*address_space != 0)
james@536 63 {
james@536 64 KdPrint((__DRIVER_NAME " Cannot map I/O space\n"));
james@536 65 FUNCTION_EXIT();
james@536 66 return FALSE;
james@536 67 }
james@536 68 *translated_address = bus_address;
james@536 69 FUNCTION_EXIT();
james@536 70 return TRUE;
james@536 71 }
james@536 72
james@536 73 static VOID
james@536 74 XenPci_DOP_PutDmaAdapter(PDMA_ADAPTER dma_adapter)
james@536 75 {
james@537 76 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
james@536 77
james@536 78 FUNCTION_ENTER();
james@537 79
james@537 80 if (xen_dma_adapter->dma_extension)
james@537 81 ObDereferenceObject(xen_dma_adapter->dma_extension_driver);
james@538 82 ExFreePoolWithTag(xen_dma_adapter->adapter_object.DmaHeader.DmaOperations, XENPCI_POOL_TAG);
james@537 83 ExFreePoolWithTag(xen_dma_adapter, XENPCI_POOL_TAG);
james@537 84
james@536 85 FUNCTION_EXIT();
james@536 86
james@536 87 return;
james@536 88 }
james@536 89
james@536 90 static PVOID
james@536 91 XenPci_DOP_AllocateCommonBuffer(
james@536 92 PDMA_ADAPTER DmaAdapter,
james@536 93 ULONG Length,
james@536 94 PPHYSICAL_ADDRESS LogicalAddress,
james@536 95 BOOLEAN CacheEnabled
james@536 96 )
james@536 97 {
james@537 98 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
james@536 99 PXENPCI_DEVICE_DATA xpdd;
james@536 100 PVOID buffer;
james@536 101 PFN_NUMBER pfn;
james@536 102 grant_ref_t gref;
james@536 103
james@536 104 UNREFERENCED_PARAMETER(DmaAdapter);
james@536 105 UNREFERENCED_PARAMETER(CacheEnabled);
james@536 106
james@536 107 //FUNCTION_ENTER();
james@536 108
james@536 109 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@536 110
james@536 111 //KdPrint((__DRIVER_NAME " Length = %d\n", Length));
james@536 112
james@536 113 buffer = ExAllocatePoolWithTag(NonPagedPool, Length, XENPCI_POOL_TAG);
james@538 114 ASSERT(buffer); /* lazy */
james@536 115
james@536 116 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(buffer).QuadPart >> PAGE_SHIFT);
james@538 117 ASSERT(pfn); /* lazy */
james@537 118 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
james@600 119 ASSERT(gref != INVALID_GRANT_REF); /* lazy */
james@536 120 LogicalAddress->QuadPart = (gref << PAGE_SHIFT) | (PtrToUlong(buffer) & (PAGE_SIZE - 1));
james@536 121
james@536 122 //FUNCTION_EXIT();
james@536 123 return buffer;
james@536 124 }
james@536 125
james@536 126 static VOID
james@536 127 XenPci_DOP_FreeCommonBuffer(
james@536 128 PDMA_ADAPTER dma_adapter,
james@536 129 ULONG length,
james@536 130 PHYSICAL_ADDRESS logical_address,
james@536 131 PVOID virtual_address,
james@536 132 BOOLEAN cache_enabled
james@536 133 )
james@536 134 {
james@536 135 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
james@536 136 PXENPCI_DEVICE_DATA xpdd;
james@536 137 grant_ref_t gref;
james@536 138
james@536 139 UNREFERENCED_PARAMETER(dma_adapter);
james@536 140 UNREFERENCED_PARAMETER(length);
james@536 141 UNREFERENCED_PARAMETER(cache_enabled);
james@536 142
james@537 143 // FUNCTION_ENTER();
james@536 144
james@536 145 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@536 146 gref = (grant_ref_t)(logical_address.QuadPart >> PAGE_SHIFT);
james@551 147 //KdPrint((__DRIVER_NAME " F Releasing Grant Ref %d\n", gref));
james@536 148 GntTbl_EndAccess(xpdd, gref, FALSE);
james@551 149 //KdPrint((__DRIVER_NAME " F Released Grant Ref\n"));
james@536 150 ExFreePoolWithTag(virtual_address, XENPCI_POOL_TAG);
james@536 151
james@537 152 // FUNCTION_EXIT();
james@536 153 }
james@536 154
james@536 155 static NTSTATUS
james@536 156 XenPci_DOP_AllocateAdapterChannel(
james@537 157 IN PDMA_ADAPTER dma_adapter,
james@537 158 IN PDEVICE_OBJECT device_object,
james@537 159 IN ULONG NumberOfMapRegisters,
james@537 160 IN PDRIVER_CONTROL ExecutionRoutine,
james@537 161 IN PVOID Context
james@536 162 )
james@536 163 {
james@537 164 //xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
james@537 165 //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@536 166 IO_ALLOCATION_ACTION action;
james@537 167 map_register_base_t *map_register_base;
james@536 168
james@537 169 UNREFERENCED_PARAMETER(dma_adapter);
james@536 170
james@537 171 //FUNCTION_ENTER();
james@537 172
james@537 173 map_register_base = ExAllocatePoolWithTag(NonPagedPool,
james@537 174 FIELD_OFFSET(map_register_base_t, regs) + NumberOfMapRegisters * sizeof(map_register_t), XENPCI_POOL_TAG);
james@537 175 if (!map_register_base)
james@537 176 {
james@537 177 KdPrint((__DRIVER_NAME " Cannot allocate memory for map_register_base\n"));
james@538 178 //FUNCTION_EXIT();
james@537 179 return STATUS_INSUFFICIENT_RESOURCES;
james@537 180 }
james@537 181 /* 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 182 map_register_base->device_object = device_object;
james@537 183 map_register_base->total_map_registers = NumberOfMapRegisters;
james@537 184 map_register_base->count = 0;
james@537 185
james@537 186 action = ExecutionRoutine(device_object, device_object->CurrentIrp, map_register_base, Context);
james@536 187
james@536 188 switch (action)
james@536 189 {
james@536 190 case KeepObject:
james@536 191 KdPrint((__DRIVER_NAME " KeepObject\n"));
james@537 192 ASSERT(FALSE);
james@536 193 break;
james@536 194 case DeallocateObject:
james@536 195 KdPrint((__DRIVER_NAME " DeallocateObject\n"));
james@537 196 ASSERT(FALSE);
james@536 197 break;
james@536 198 case DeallocateObjectKeepRegisters:
james@537 199 //KdPrint((__DRIVER_NAME " DeallocateObjectKeepRegisters\n"));
james@536 200 break;
james@536 201 default:
james@536 202 KdPrint((__DRIVER_NAME " Unknown action %d\n", action));
james@537 203 ASSERT(FALSE);
james@536 204 break;
james@536 205 }
james@537 206 //FUNCTION_EXIT();
james@536 207 return STATUS_SUCCESS;
james@536 208 }
james@536 209
james@536 210 static BOOLEAN
james@536 211 XenPci_DOP_FlushAdapterBuffers(
james@537 212 PDMA_ADAPTER dma_adapter,
james@537 213 PMDL mdl,
james@536 214 PVOID MapRegisterBase,
james@536 215 PVOID CurrentVa,
james@536 216 ULONG Length,
james@537 217 BOOLEAN write_to_device)
james@536 218 {
james@537 219 //xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
james@537 220 //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@537 221 map_register_base_t *map_register_base = MapRegisterBase;
james@537 222 map_register_t *map_register;
james@537 223 ULONG i;
james@537 224
james@537 225 UNREFERENCED_PARAMETER(dma_adapter);
james@537 226 UNREFERENCED_PARAMETER(mdl);
james@536 227 UNREFERENCED_PARAMETER(CurrentVa);
james@536 228 UNREFERENCED_PARAMETER(Length);
james@537 229
james@537 230 //FUNCTION_ENTER();
james@537 231
james@537 232 for (i = 0; i < map_register_base->count; i++)
james@537 233 {
james@537 234 map_register = &map_register_base->regs[i];
james@537 235 if (map_register->map_type == MAP_TYPE_REMAPPED && !write_to_device)
james@537 236 memcpy(map_register->unaligned_buffer, map_register->aligned_buffer, map_register->copy_length);
james@537 237 }
james@537 238 //FUNCTION_EXIT();
james@537 239
james@536 240 return TRUE;
james@536 241 }
james@536 242
james@536 243 static VOID
james@536 244 XenPci_DOP_FreeAdapterChannel(
james@536 245 IN PDMA_ADAPTER DmaAdapter
james@536 246 )
james@536 247 {
james@536 248 UNREFERENCED_PARAMETER(DmaAdapter);
james@536 249
james@536 250 FUNCTION_ENTER();
james@536 251 FUNCTION_EXIT();
james@536 252 }
james@536 253
james@536 254 static VOID
james@536 255 XenPci_DOP_FreeMapRegisters(
james@537 256 PDMA_ADAPTER dma_adapter,
james@536 257 PVOID MapRegisterBase,
james@536 258 ULONG NumberOfMapRegisters)
james@536 259 {
james@537 260 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
james@537 261 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@537 262 map_register_base_t *map_register_base = MapRegisterBase;
james@537 263 map_register_t *map_register;
james@537 264 ULONG i;
james@537 265 grant_ref_t gref;
james@537 266
james@537 267 //FUNCTION_ENTER();
james@597 268 if (!map_register_base)
james@597 269 {
james@597 270 /* i'm not sure if this is ideal here, but NDIS definitely does it */
james@597 271 return;
james@597 272 }
james@537 273 ASSERT(map_register_base->total_map_registers == NumberOfMapRegisters);
james@537 274
james@537 275 for (i = 0; i < map_register_base->count; i++)
james@537 276 {
james@537 277 map_register = &map_register_base->regs[i];
james@537 278 switch (map_register->map_type)
james@537 279 {
james@537 280 case MAP_TYPE_REMAPPED:
james@537 281 gref = (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT);
james@551 282 //KdPrint((__DRIVER_NAME " D Releasing Grant Ref %d\n", gref));
james@537 283 GntTbl_EndAccess(xpdd, gref, FALSE);
james@551 284 //KdPrint((__DRIVER_NAME " D Released Grant Ref\n"));
james@537 285 ExFreePoolWithTag(map_register->aligned_buffer, XENPCI_POOL_TAG);
james@537 286 break;
james@537 287 case MAP_TYPE_MDL:
james@537 288 gref = (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT);
james@551 289 //KdPrint((__DRIVER_NAME " E Releasing Grant Ref %d\n", gref));
james@537 290 GntTbl_EndAccess(xpdd, gref, FALSE);
james@551 291 //KdPrint((__DRIVER_NAME " E Released Grant Ref\n"));
james@537 292 break;
james@537 293 case MAP_TYPE_VIRTUAL:
james@537 294 break;
james@537 295 }
james@537 296 }
james@537 297 ExFreePoolWithTag(map_register_base, XENPCI_POOL_TAG);
james@537 298
james@537 299 //FUNCTION_EXIT();
james@536 300 }
james@536 301
james@536 302 static PHYSICAL_ADDRESS
james@536 303 XenPci_DOP_MapTransfer(
james@537 304 PDMA_ADAPTER dma_adapter,
james@537 305 PMDL mdl,
james@536 306 PVOID MapRegisterBase,
james@536 307 PVOID CurrentVa,
james@536 308 PULONG Length,
james@536 309 BOOLEAN WriteToDevice)
james@536 310 {
james@537 311 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
james@537 312 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@537 313 map_register_base_t *map_register_base = MapRegisterBase;
james@537 314 map_register_t *map_register = &map_register_base->regs[map_register_base->count];
james@537 315 PDEVICE_OBJECT device_object = map_register_base->device_object;
james@537 316 ULONG page_offset;
james@537 317 PFN_NUMBER pfn;
james@537 318 grant_ref_t gref;
james@537 319 PUCHAR ptr;
james@537 320 ULONG mdl_offset;
james@537 321 ULONG pfn_index;
james@537 322
james@537 323 //FUNCTION_ENTER();
james@537 324
james@537 325 //KdPrint((__DRIVER_NAME " Mdl = %p, MapRegisterBase = %p, MdlVa = %p, CurrentVa = %p, Length = %d\n",
james@537 326 // mdl, MapRegisterBase, MmGetMdlVirtualAddress(mdl), CurrentVa, *Length));
james@537 327
james@537 328 ASSERT(mdl);
james@597 329 ASSERT(map_register_base);
james@537 330 ASSERT(map_register_base->count < map_register_base->total_map_registers);
james@536 331
james@537 332 if (xen_dma_adapter->dma_extension)
james@537 333 {
james@558 334 if (xen_dma_adapter->dma_extension->need_virtual_address && xen_dma_adapter->dma_extension->need_virtual_address(device_object->CurrentIrp))
james@537 335 {
james@537 336 map_register->map_type = MAP_TYPE_VIRTUAL;
james@537 337 }
james@537 338 else
james@537 339 {
james@558 340 if (xen_dma_adapter->dma_extension->get_alignment)
james@537 341 {
james@558 342 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(device_object->CurrentIrp);
james@558 343 if ((MmGetMdlByteOffset(mdl) & (alignment - 1)) || (MmGetMdlByteCount(mdl) & (alignment - 1)))
james@558 344 {
james@558 345 map_register->map_type = MAP_TYPE_REMAPPED;
james@558 346 }
james@558 347 else
james@558 348 {
james@558 349 map_register->map_type = MAP_TYPE_MDL;
james@558 350 }
james@537 351 }
james@537 352 else
james@537 353 {
james@537 354 map_register->map_type = MAP_TYPE_MDL;
james@537 355 }
james@537 356 }
james@537 357 }
james@537 358 else
james@537 359 {
james@537 360 map_register->map_type = MAP_TYPE_MDL;
james@537 361 }
james@537 362
james@537 363 switch (map_register->map_type)
james@537 364 {
james@537 365 case MAP_TYPE_MDL:
james@537 366 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL\n"));
james@612 367 mdl_offset = (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)MmGetMdlVirtualAddress(mdl));
james@537 368 page_offset = PtrToUlong(CurrentVa) & (PAGE_SIZE - 1);
james@537 369 *Length = min(*Length, PAGE_SIZE - page_offset);
james@612 370 pfn_index = (ULONG)(((UINT_PTR)CurrentVa >> PAGE_SHIFT) - ((UINT_PTR)MmGetMdlVirtualAddress(mdl) >> PAGE_SHIFT));
james@537 371 //KdPrint((__DRIVER_NAME " mdl_offset = %d, page_offset = %d, length = %d, pfn_index = %d\n",
james@537 372 // mdl_offset, page_offset, *Length, pfn_index));
james@537 373 pfn = MmGetMdlPfnArray(mdl)[pfn_index];
james@551 374 //KdPrint((__DRIVER_NAME " B Requesting Grant Ref\n"));
james@537 375 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
james@551 376 //KdPrint((__DRIVER_NAME " B Got Grant Ref %d\n", gref));
james@537 377 map_register->logical.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | page_offset;
james@537 378 map_register_base->count++;
james@537 379 break;
james@537 380 case MAP_TYPE_REMAPPED:
james@551 381 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED (MapTransfer)\n"));
james@551 382 //KdPrint((__DRIVER_NAME " Mdl = %p, MapRegisterBase = %p, MdlVa = %p, CurrentVa = %p, Length = %d\n",
james@551 383 // mdl, MapRegisterBase, MmGetMdlVirtualAddress(mdl), CurrentVa, *Length));
james@612 384 mdl_offset = (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)MmGetMdlVirtualAddress(mdl));
james@537 385 *Length = min(*Length, PAGE_SIZE);
james@537 386 map_register->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@537 387 ASSERT(map_register->aligned_buffer);
james@537 388 map_register->unaligned_buffer = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
james@537 389 ASSERT(map_register->unaligned_buffer); /* lazy */
james@551 390 map_register->unaligned_buffer = (PUCHAR)map_register->unaligned_buffer + mdl_offset;
james@537 391 map_register->copy_length = *Length;
james@537 392 if (WriteToDevice)
james@537 393 memcpy(map_register->aligned_buffer, map_register->unaligned_buffer, map_register->copy_length);
james@537 394 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(map_register->aligned_buffer).QuadPart >> PAGE_SHIFT);
james@551 395 //KdPrint((__DRIVER_NAME " C Requesting Grant Ref\n"));
james@537 396 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
james@551 397 //KdPrint((__DRIVER_NAME " C Got Grant Ref %d\n", gref));
james@537 398 map_register->logical.QuadPart = (LONGLONG)(gref << PAGE_SHIFT);
james@537 399 map_register_base->count++;
james@537 400 break;
james@537 401 case MAP_TYPE_VIRTUAL:
james@537 402 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL\n"));
james@537 403 ptr = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
james@537 404 ASSERT(ptr); /* lazy */
james@537 405 map_register->logical.QuadPart = (ULONGLONG)ptr;
james@537 406 map_register_base->count++;
james@537 407 break;
james@537 408 default:
james@537 409 ASSERT(FALSE);
james@537 410 break;
james@537 411 }
james@536 412
james@538 413 //KdPrint((__DRIVER_NAME " logical = %08x:%08x\n", map_register->logical.HighPart, map_register->logical.LowPart));
james@537 414 //FUNCTION_EXIT();
james@537 415 return map_register->logical;
james@536 416 }
james@536 417
james@536 418 static ULONG
james@536 419 XenPci_DOP_GetDmaAlignment(
james@536 420 PDMA_ADAPTER DmaAdapter)
james@536 421 {
james@536 422 UNREFERENCED_PARAMETER(DmaAdapter);
james@536 423
james@536 424 FUNCTION_ENTER();
james@536 425 FUNCTION_EXIT();
james@536 426 return 0;
james@536 427 }
james@536 428
james@536 429 static ULONG
james@536 430 XenPci_DOP_ReadDmaCounter(
james@536 431 PDMA_ADAPTER DmaAdapter)
james@536 432 {
james@536 433 UNREFERENCED_PARAMETER(DmaAdapter);
james@536 434
james@536 435 FUNCTION_ENTER();
james@536 436 FUNCTION_EXIT();
james@536 437 return 0;
james@536 438 }
james@536 439
james@536 440 static VOID
james@536 441 XenPci_DOP_PutScatterGatherList(
james@536 442 IN PDMA_ADAPTER DmaAdapter,
james@558 443 IN PSCATTER_GATHER_LIST sg_list,
james@536 444 IN BOOLEAN WriteToDevice
james@536 445 )
james@536 446 {
james@536 447 xen_dma_adapter_t *xen_dma_adapter;
james@536 448 PXENPCI_DEVICE_DATA xpdd;
james@536 449 ULONG i;
james@536 450 sg_extra_t *sg_extra;
james@600 451 PMDL curr_mdl;
james@600 452 ULONG offset;
james@600 453 BOOLEAN active;
james@536 454
james@536 455 UNREFERENCED_PARAMETER(WriteToDevice);
james@536 456
james@536 457 //FUNCTION_ENTER();
james@536 458
james@536 459 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
james@600 460 ASSERT(xen_dma_adapter);
james@536 461 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@536 462
james@558 463 sg_extra = (sg_extra_t *)((PUCHAR)sg_list + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
james@558 464 (sizeof(SCATTER_GATHER_ELEMENT)) * sg_list->NumberOfElements);
james@536 465
james@536 466 switch (sg_extra->map_type)
james@536 467 {
james@536 468 case MAP_TYPE_REMAPPED:
james@558 469 for (i = 0; i < sg_list->NumberOfElements; i++)
james@536 470 {
james@536 471 grant_ref_t gref;
james@558 472 gref = (grant_ref_t)(sg_list->Elements[i].Address.QuadPart >> PAGE_SHIFT);
james@536 473 GntTbl_EndAccess(xpdd, gref, FALSE);
james@558 474 sg_list->Elements[i].Address.QuadPart = -1;
james@536 475 }
james@600 476 ASSERT(sg_extra->mdl);
james@536 477 if (!WriteToDevice)
james@600 478 {
james@600 479 for (curr_mdl = sg_extra->mdl, offset = 0, active = FALSE; curr_mdl; curr_mdl = curr_mdl->Next)
james@600 480 {
james@600 481 PVOID mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
james@600 482 ULONG mdl_byte_count = MmGetMdlByteCount(curr_mdl);
james@600 483 ULONG mdl_offset = 0;
james@612 484 /* need to use <= va + len - 1 to avoid ptr wraparound */
james@612 485 if ((UINT_PTR)sg_extra->currentva >= (UINT_PTR)mdl_start_va && (UINT_PTR)sg_extra->currentva <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
james@600 486 {
james@600 487 active = TRUE;
james@612 488 mdl_byte_count -= (ULONG)((UINT_PTR)sg_extra->currentva - (UINT_PTR)mdl_start_va);
james@612 489 mdl_offset = (ULONG)((UINT_PTR)sg_extra->currentva - (UINT_PTR)mdl_start_va);
james@600 490 mdl_start_va = sg_extra->currentva;
james@600 491 }
james@600 492 if (active)
james@600 493 {
james@600 494 PVOID unaligned_buffer;
james@600 495 unaligned_buffer = MmGetSystemAddressForMdlSafe(curr_mdl, NormalPagePriority);
james@600 496 ASSERT(unaligned_buffer); /* lazy */
james@600 497 memcpy((PUCHAR)unaligned_buffer + mdl_offset, (PUCHAR)sg_extra->aligned_buffer + offset, mdl_byte_count);
james@600 498 offset += mdl_byte_count;
james@600 499 }
james@600 500 }
james@600 501 }
james@536 502 ExFreePoolWithTag(sg_extra->aligned_buffer, XENPCI_POOL_TAG);
james@536 503 break;
james@536 504 case MAP_TYPE_MDL:
james@558 505 for (i = 0; i < sg_list->NumberOfElements; i++)
james@536 506 {
james@536 507 grant_ref_t gref;
james@558 508 gref = (grant_ref_t)(sg_list->Elements[i].Address.QuadPart >> PAGE_SHIFT);
james@536 509 GntTbl_EndAccess(xpdd, gref, FALSE);
james@558 510 sg_list->Elements[i].Address.QuadPart = -1;
james@536 511 }
james@536 512 break;
james@536 513 case MAP_TYPE_VIRTUAL:
james@536 514 break;
james@536 515 }
james@558 516 if (sg_extra->allocated_by_me)
james@558 517 ExFreePoolWithTag(sg_list, XENPCI_POOL_TAG);
james@536 518 //FUNCTION_EXIT();
james@536 519 }
james@536 520
james@536 521 static NTSTATUS
james@536 522 XenPci_DOP_CalculateScatterGatherList(
james@536 523 PDMA_ADAPTER DmaAdapter,
james@536 524 PMDL Mdl,
james@536 525 PVOID CurrentVa,
james@536 526 ULONG Length,
james@536 527 PULONG ScatterGatherListSize,
james@536 528 PULONG NumberOfMapRegisters
james@536 529 )
james@536 530 {
james@558 531 xen_dma_adapter_t *xen_dma_adapter;
james@536 532 ULONG elements;
james@536 533 PMDL curr_mdl;
james@613 534
james@613 535 UNREFERENCED_PARAMETER(CurrentVa);
james@558 536
james@561 537 //FUNCTION_ENTER();
james@536 538
james@561 539 //KdPrint((__DRIVER_NAME " Mdl = %p\n", Mdl));
james@561 540 //KdPrint((__DRIVER_NAME " CurrentVa = %p\n", CurrentVa));
james@561 541 //KdPrint((__DRIVER_NAME " Length = %d\n", Length));
james@558 542
james@558 543 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
james@558 544
james@536 545 if (Mdl)
james@536 546 {
james@561 547 //if (CurrentVa != MmGetMdlVirtualAddress(Mdl))
james@561 548 //{
james@561 549 // KdPrint((__DRIVER_NAME " CurrentVa (%p) != MdlVa (%p)\n", CurrentVa, MmGetMdlVirtualAddress(Mdl)));
james@561 550 //
james@561 551
james@612 552 //KdPrint((__DRIVER_NAME " CurrentVa = %p, MdlVa = %p\n", CurrentVa, MmGetMdlVirtualAddress(Mdl)));
james@561 553
james@536 554 for (curr_mdl = Mdl, elements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
james@561 555 {
james@612 556 //KdPrint((__DRIVER_NAME " curr_mdlVa = %p, curr_mdl size = %d\n", MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)));
james@561 557 elements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
james@561 558 }
james@536 559 }
james@536 560 else
james@536 561 {
james@558 562 elements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, Length); // + 1;
james@558 563 }
james@558 564
james@558 565 if (elements > xen_dma_adapter->adapter_object.MapRegistersPerChannel)
james@558 566 {
james@612 567 //KdPrint((__DRIVER_NAME " elements = %d - too many\n", elements));
james@558 568 if (NumberOfMapRegisters)
james@558 569 *NumberOfMapRegisters = 0;
james@558 570 *ScatterGatherListSize = 0;
james@558 571
james@558 572 return STATUS_INSUFFICIENT_RESOURCES;
james@536 573 }
james@536 574
james@536 575 *ScatterGatherListSize = FIELD_OFFSET(SCATTER_GATHER_LIST, Elements)
james@536 576 + sizeof(SCATTER_GATHER_ELEMENT) * elements
james@536 577 + sizeof(sg_extra_t);
james@536 578 if (NumberOfMapRegisters)
james@558 579 *NumberOfMapRegisters = elements;
james@536 580
james@612 581 //KdPrint((__DRIVER_NAME " ScatterGatherListSize = %d, NumberOfMapRegisters = %d\n", *ScatterGatherListSize, elements));
james@536 582
james@561 583 //FUNCTION_EXIT();
james@536 584 return STATUS_SUCCESS;
james@536 585 }
james@536 586
james@536 587 static NTSTATUS
james@558 588 XenPci_DOP_BuildScatterGatherListButDontExecute(
james@536 589 IN PDMA_ADAPTER DmaAdapter,
james@536 590 IN PDEVICE_OBJECT DeviceObject,
james@536 591 IN PMDL Mdl,
james@536 592 IN PVOID CurrentVa,
james@536 593 IN ULONG Length,
james@536 594 IN BOOLEAN WriteToDevice,
james@536 595 IN PVOID ScatterGatherBuffer,
james@558 596 IN ULONG ScatterGatherBufferLength,
james@558 597 BOOLEAN allocated_by_me)
james@536 598 {
james@536 599 ULONG i;
james@536 600 PSCATTER_GATHER_LIST sglist = ScatterGatherBuffer;
james@536 601 PUCHAR ptr;
james@536 602 ULONG remaining = Length;
james@536 603 ULONG total_remaining;
james@536 604 xen_dma_adapter_t *xen_dma_adapter;
james@536 605 PXENPCI_DEVICE_DATA xpdd;
james@536 606 sg_extra_t *sg_extra;
james@536 607 PMDL curr_mdl;
james@536 608 ULONG map_type;
james@536 609 ULONG sg_element;
james@536 610 ULONG offset;
james@536 611 PFN_NUMBER pfn;
james@536 612 grant_ref_t gref;
james@600 613 BOOLEAN active;
james@600 614 PVOID mdl_start_va;
james@600 615 ULONG mdl_byte_count;
james@600 616 ULONG mdl_offset;
james@600 617 ULONG remapped_bytes = 0;
james@536 618
james@538 619 //FUNCTION_ENTER();
james@538 620
james@555 621 if (!ScatterGatherBuffer)
james@555 622 {
james@555 623 KdPrint((__DRIVER_NAME " NULL ScatterGatherBuffer\n"));
james@555 624 return STATUS_INVALID_PARAMETER;
james@555 625 }
james@654 626 //if (MmGetMdlVirtualAddress(Mdl) != CurrentVa)
james@654 627 //{
james@654 628 // KdPrint((__DRIVER_NAME " MmGetMdlVirtualAddress = %p, CurrentVa = %p, Length = %d\n", MmGetMdlVirtualAddress(Mdl), CurrentVa, Length));
james@654 629 //}
james@536 630
james@536 631 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
james@536 632 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@536 633
james@536 634 ASSERT(Mdl);
james@537 635
james@536 636 if (xen_dma_adapter->dma_extension)
james@536 637 {
james@558 638 if (xen_dma_adapter->dma_extension->need_virtual_address && xen_dma_adapter->dma_extension->need_virtual_address(DeviceObject->CurrentIrp))
james@536 639 {
james@536 640 ASSERT(!Mdl->Next); /* can only virtual a single buffer */
james@653 641 //ASSERT(MmGetMdlVirtualAddress(Mdl) == CurrentVa);
james@536 642 map_type = MAP_TYPE_VIRTUAL;
james@536 643 sglist->NumberOfElements = 1;
james@536 644 }
james@536 645 else
james@536 646 {
james@558 647 if (xen_dma_adapter->dma_extension->get_alignment)
james@536 648 {
james@558 649 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(DeviceObject->CurrentIrp);
james@600 650
james@600 651 map_type = MAP_TYPE_MDL;
james@600 652 sglist->NumberOfElements = 0;
james@600 653 for (curr_mdl = Mdl, remapped_bytes = 0, active = FALSE; curr_mdl; curr_mdl = curr_mdl->Next)
james@558 654 {
james@600 655 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
james@600 656 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
james@612 657 /* need to use <= va + len - 1 to avoid ptr wraparound */
james@612 658 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
james@600 659 {
james@600 660 active = TRUE;
james@612 661 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
james@600 662 mdl_start_va = CurrentVa;
james@600 663 }
james@600 664 if (active)
james@600 665 {
james@612 666 if (((UINT_PTR)mdl_start_va & (alignment - 1)) || (mdl_byte_count & (alignment - 1)))
james@600 667 map_type = MAP_TYPE_REMAPPED;
james@600 668 remapped_bytes += mdl_byte_count;
james@600 669 }
james@558 670 }
james@600 671 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(NULL, remapped_bytes);
james@536 672 }
james@536 673 else
james@536 674 {
james@536 675 map_type = MAP_TYPE_MDL;
james@536 676 }
james@536 677 }
james@536 678 }
james@536 679 else
james@536 680 {
james@536 681 map_type = MAP_TYPE_MDL;
james@558 682 }
james@558 683 if (map_type == MAP_TYPE_MDL)
james@612 684 {
james@612 685 for (curr_mdl = Mdl, sglist->NumberOfElements = 0, total_remaining = Length, active = FALSE; total_remaining > 0; curr_mdl = curr_mdl->Next)
james@600 686 {
james@612 687 ASSERT(curr_mdl);
james@600 688 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
james@600 689 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
james@612 690 /* need to use <= va + len - 1 to avoid ptr wraparound */
james@612 691 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
james@600 692 {
james@600 693 active = TRUE;
james@612 694 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
james@600 695 mdl_start_va = CurrentVa;
james@600 696 }
james@612 697 mdl_byte_count = min(mdl_byte_count, total_remaining);
james@673 698 if (active && mdl_byte_count)
james@600 699 {
james@600 700 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
james@612 701 mdl_start_va, mdl_byte_count);
james@612 702 total_remaining -= mdl_byte_count;
james@600 703 }
james@600 704 }
james@536 705 }
james@536 706 if (ScatterGatherBufferLength < FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
james@536 707 sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t))
james@536 708 {
james@561 709 //KdPrint((__DRIVER_NAME " STATUS_BUFFER_TOO_SMALL (%d < %d)\n", ScatterGatherBufferLength, FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
james@561 710 // sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t)));
james@536 711 return STATUS_BUFFER_TOO_SMALL;
james@536 712 }
james@536 713
james@536 714 sg_extra = (sg_extra_t *)((PUCHAR)sglist + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
james@536 715 (sizeof(SCATTER_GATHER_ELEMENT)) * sglist->NumberOfElements);
james@558 716
james@558 717 sg_extra->allocated_by_me = allocated_by_me;
james@536 718
james@536 719 sg_extra->map_type = map_type;
james@536 720 switch (map_type)
james@536 721 {
james@536 722 case MAP_TYPE_MDL:
james@537 723 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL - %p\n", MmGetMdlVirtualAddress(Mdl)));
james@536 724 total_remaining = Length;
james@612 725 for (sg_element = 0, curr_mdl = Mdl, active = FALSE; total_remaining > 0; curr_mdl = curr_mdl->Next)
james@536 726 {
james@612 727 ASSERT(curr_mdl);
james@600 728 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
james@600 729 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
james@612 730 /* need to use <= va + len - 1 to avoid ptr wraparound */
james@612 731 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
james@536 732 {
james@600 733 active = TRUE;
james@612 734 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
james@600 735 mdl_start_va = CurrentVa;
james@600 736 }
james@673 737 if (active && mdl_byte_count)
james@600 738 {
james@600 739 ULONG pfn_offset;
james@612 740 remaining = min(mdl_byte_count, total_remaining);
james@612 741 offset = (ULONG)((UINT_PTR)mdl_start_va & (PAGE_SIZE - 1));
james@612 742 pfn_offset = (ULONG)(((UINT_PTR)mdl_start_va >> PAGE_SHIFT) - ((UINT_PTR)MmGetMdlVirtualAddress(curr_mdl) >> PAGE_SHIFT));
james@612 743 //for (i = 0; i < ADDRESS_AND_SIZE_TO_SPAN_PAGES(mdl_start_va, mdl_byte_count); i++)
james@612 744 for (i = 0; remaining > 0; i++)
james@600 745 {
james@600 746 pfn = MmGetMdlPfnArray(curr_mdl)[pfn_offset + i];
james@600 747 ASSERT(pfn);
james@600 748 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
james@600 749 ASSERT(gref != INVALID_GRANT_REF);
james@600 750 sglist->Elements[sg_element].Address.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | offset;
james@600 751 sglist->Elements[sg_element].Length = min(min(PAGE_SIZE - offset, remaining), total_remaining);
james@600 752 total_remaining -= sglist->Elements[sg_element].Length;
james@600 753 remaining -= sglist->Elements[sg_element].Length;
james@600 754 offset = 0;
james@600 755 sg_element++;
james@600 756 }
james@536 757 }
james@536 758 }
james@612 759 if (sg_element != sglist->NumberOfElements)
james@612 760 {
james@612 761 KdPrint((__DRIVER_NAME " sg_element = %d, sglist->NumberOfElements = %d\n", sg_element, sglist->NumberOfElements));
james@612 762 KdPrint((__DRIVER_NAME " CurrentVa = %p, Length = %d\n", CurrentVa, Length));
james@612 763 for (curr_mdl = Mdl; curr_mdl; curr_mdl = curr_mdl->Next)
james@612 764 {
james@612 765 KdPrint((__DRIVER_NAME " Mdl = %p, VirtualAddress = %p, ByteCount = %d\n", Mdl, MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)));
james@612 766 }
james@612 767 }
james@612 768 ASSERT(sg_element == sglist->NumberOfElements);
james@536 769 break;
james@536 770 case MAP_TYPE_REMAPPED:
james@600 771 sg_extra->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, max(remapped_bytes, PAGE_SIZE), XENPCI_POOL_TAG);
james@536 772 if (!sg_extra->aligned_buffer)
james@536 773 {
james@600 774 KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED buffer allocation failed - requested va = %p, length = %d\n", MmGetMdlVirtualAddress(Mdl), remapped_bytes));
james@536 775 return STATUS_INSUFFICIENT_RESOURCES;
james@536 776 }
james@612 777 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED - %p\n", sg_extra->aligned_buffer));
james@600 778 sg_extra->mdl = Mdl;
james@600 779 sg_extra->currentva = CurrentVa;
james@600 780 sg_extra->copy_length = remapped_bytes;
james@600 781
james@536 782 if (WriteToDevice)
james@600 783 {
james@600 784 for (curr_mdl = Mdl, offset = 0, active = FALSE; curr_mdl; curr_mdl = curr_mdl->Next)
james@600 785 {
james@600 786 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
james@600 787 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
james@600 788 mdl_offset = 0;
james@612 789 /* need to use <= va + len - 1 to avoid ptr wraparound */
james@612 790 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
james@600 791 {
james@600 792 active = TRUE;
james@612 793 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
james@612 794 mdl_offset = (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
james@600 795 mdl_start_va = CurrentVa;
james@600 796 }
james@600 797 if (active)
james@600 798 {
james@600 799 PVOID unaligned_buffer;
james@600 800 unaligned_buffer = (PUCHAR)MmGetSystemAddressForMdlSafe(curr_mdl, NormalPagePriority);
james@600 801 ASSERT(unaligned_buffer); /* lazy */
james@600 802 memcpy((PUCHAR)sg_extra->aligned_buffer + offset, (PUCHAR)unaligned_buffer + mdl_offset, mdl_byte_count);
james@600 803 offset += mdl_byte_count;
james@600 804 }
james@600 805 }
james@600 806 }
james@600 807 for (sg_element = 0, remaining = remapped_bytes;
james@600 808 sg_element < ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_extra->aligned_buffer, remapped_bytes); sg_element++)
james@536 809 {
james@536 810 pfn = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)sg_extra->aligned_buffer + (sg_element << PAGE_SHIFT)).QuadPart >> PAGE_SHIFT);
james@536 811 ASSERT(pfn);
james@537 812 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
james@600 813 ASSERT(gref != INVALID_GRANT_REF);
james@536 814 sglist->Elements[sg_element].Address.QuadPart = (ULONGLONG)gref << PAGE_SHIFT;
james@536 815 sglist->Elements[sg_element].Length = min(PAGE_SIZE, remaining);
james@536 816 remaining -= sglist->Elements[sg_element].Length;
james@536 817 }
james@536 818 break;
james@536 819 case MAP_TYPE_VIRTUAL:
james@536 820 ptr = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
james@536 821 ASSERT(ptr); /* lazy */
james@653 822 sglist->Elements[0].Address.QuadPart = (ULONGLONG)ptr + ((UINT_PTR)CurrentVa - (UINT_PTR)MmGetMdlVirtualAddress(Mdl));
james@536 823 sglist->Elements[0].Length = Length;
james@537 824 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL - %08x\n", sglist->Elements[0].Address.LowPart));
james@536 825 break;
james@555 826 default:
james@555 827 KdPrint((__DRIVER_NAME " map_type = %d\n", map_type));
james@555 828 break;
james@536 829 }
james@600 830 //FUNCTION_EXIT();
james@558 831 return STATUS_SUCCESS;
james@558 832 }
james@537 833
james@558 834 static NTSTATUS
james@558 835 XenPci_DOP_BuildScatterGatherList(
james@558 836 IN PDMA_ADAPTER DmaAdapter,
james@558 837 IN PDEVICE_OBJECT DeviceObject,
james@558 838 IN PMDL Mdl,
james@558 839 IN PVOID CurrentVa,
james@558 840 IN ULONG Length,
james@558 841 IN PDRIVER_LIST_CONTROL ExecutionRoutine,
james@558 842 IN PVOID Context,
james@558 843 IN BOOLEAN WriteToDevice,
james@558 844 IN PVOID ScatterGatherBuffer,
james@558 845 IN ULONG ScatterGatherBufferLength)
james@558 846 {
james@558 847 NTSTATUS status;
james@558 848
james@558 849 status = XenPci_DOP_BuildScatterGatherListButDontExecute(DmaAdapter, DeviceObject, Mdl, CurrentVa, Length, WriteToDevice, ScatterGatherBuffer, ScatterGatherBufferLength, FALSE);
james@558 850
james@558 851 if (NT_SUCCESS(status))
james@558 852 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, ScatterGatherBuffer, Context);
james@536 853
james@536 854 //FUNCTION_EXIT();
james@536 855
james@558 856 return status;
james@558 857 }
james@558 858
james@558 859 static NTSTATUS
james@558 860 XenPci_DOP_GetScatterGatherList(
james@558 861 PDMA_ADAPTER DmaAdapter,
james@558 862 PDEVICE_OBJECT DeviceObject,
james@558 863 PMDL Mdl,
james@558 864 PVOID CurrentVa,
james@558 865 ULONG Length,
james@558 866 PDRIVER_LIST_CONTROL ExecutionRoutine,
james@558 867 PVOID Context,
james@558 868 BOOLEAN WriteToDevice)
james@558 869 {
james@558 870 NTSTATUS status;
james@558 871 ULONG list_size;
james@558 872 ULONG map_registers;
james@558 873 PSCATTER_GATHER_LIST sg_list;
james@558 874
james@561 875 //FUNCTION_ENTER();
james@558 876
james@558 877 status = XenPci_DOP_CalculateScatterGatherList(DmaAdapter, Mdl, CurrentVa, Length, &list_size, &map_registers);
james@558 878 if (!NT_SUCCESS(status))
james@558 879 {
james@561 880 //FUNCTION_EXIT();
james@558 881 return status;
james@558 882 }
james@558 883
james@558 884 sg_list = ExAllocatePoolWithTag(NonPagedPool, list_size, XENPCI_POOL_TAG);
james@558 885 if (!sg_list)
james@558 886 {
james@558 887 KdPrint((__DRIVER_NAME " Cannot allocate memory for sg_list\n"));
james@561 888 //FUNCTION_EXIT();
james@558 889 return STATUS_INSUFFICIENT_RESOURCES;
james@558 890 }
james@558 891
james@558 892 status = XenPci_DOP_BuildScatterGatherListButDontExecute(DmaAdapter, DeviceObject, Mdl, CurrentVa, Length, WriteToDevice, sg_list, list_size, TRUE);
james@558 893
james@558 894 if (NT_SUCCESS(status))
james@558 895 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, sg_list, Context);
james@558 896
james@561 897 //FUNCTION_EXIT();
james@558 898
james@558 899 return status;
james@536 900 }
james@536 901
james@536 902 static NTSTATUS
james@536 903 XenPci_DOP_BuildMdlFromScatterGatherList(
james@536 904 PDMA_ADAPTER DmaAdapter,
james@536 905 PSCATTER_GATHER_LIST ScatterGather,
james@536 906 PMDL OriginalMdl,
james@536 907 PMDL *TargetMdl)
james@536 908 {
james@561 909 NTSTATUS status = STATUS_SUCCESS;
james@536 910 UNREFERENCED_PARAMETER(DmaAdapter);
james@536 911 UNREFERENCED_PARAMETER(ScatterGather);
james@536 912 UNREFERENCED_PARAMETER(OriginalMdl);
james@536 913 UNREFERENCED_PARAMETER(TargetMdl);
james@536 914
james@536 915 FUNCTION_ENTER();
james@561 916
james@561 917 if (OriginalMdl)
james@561 918 {
james@561 919 *TargetMdl = OriginalMdl;
james@561 920 }
james@561 921 else
james@561 922 {
james@561 923 *TargetMdl = NULL;
james@561 924 status = STATUS_INVALID_PARAMETER;
james@561 925 }
james@561 926
james@536 927 FUNCTION_EXIT();
james@561 928
james@561 929 return status;
james@536 930 }
james@536 931
james@536 932 static PDMA_ADAPTER
james@536 933 XenPci_BIS_GetDmaAdapter(PVOID context, PDEVICE_DESCRIPTION device_description, PULONG number_of_map_registers)
james@536 934 {
james@536 935 xen_dma_adapter_t *xen_dma_adapter;
james@536 936 PDEVICE_OBJECT curr, prev;
james@536 937 PDRIVER_OBJECT fdo_driver_object;
james@536 938 PVOID fdo_driver_extension;
james@536 939
james@536 940 UNREFERENCED_PARAMETER(device_description);
james@536 941
james@536 942 FUNCTION_ENTER();
james@536 943
james@536 944 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@536 945 KdPrint((__DRIVER_NAME " Device Description = %p:\n", device_description));
james@536 946 KdPrint((__DRIVER_NAME " Version = %d\n", device_description->Version));
james@536 947 KdPrint((__DRIVER_NAME " Master = %d\n", device_description->Master));
james@536 948 KdPrint((__DRIVER_NAME " ScatterGather = %d\n", device_description->ScatterGather));
james@536 949 KdPrint((__DRIVER_NAME " DemandMode = %d\n", device_description->DemandMode));
james@536 950 KdPrint((__DRIVER_NAME " AutoInitialize = %d\n", device_description->AutoInitialize));
james@536 951 KdPrint((__DRIVER_NAME " Dma32BitAddresses = %d\n", device_description->Dma32BitAddresses));
james@536 952 KdPrint((__DRIVER_NAME " IgnoreCount = %d\n", device_description->IgnoreCount));
james@536 953 KdPrint((__DRIVER_NAME " Dma64BitAddresses = %d\n", device_description->Dma64BitAddresses));
james@536 954 KdPrint((__DRIVER_NAME " BusNumber = %d\n", device_description->BusNumber));
james@536 955 KdPrint((__DRIVER_NAME " DmaChannel = %d\n", device_description->DmaChannel));
james@536 956 KdPrint((__DRIVER_NAME " InterfaceType = %d\n", device_description->InterfaceType));
james@536 957 KdPrint((__DRIVER_NAME " DmaWidth = %d\n", device_description->DmaWidth));
james@536 958 KdPrint((__DRIVER_NAME " DmaSpeed = %d\n", device_description->DmaSpeed));
james@536 959 KdPrint((__DRIVER_NAME " MaximumLength = %d\n", device_description->MaximumLength));
james@536 960 KdPrint((__DRIVER_NAME " DmaPort = %d\n", device_description->DmaPort));
james@536 961
james@538 962 if (!device_description->Master)
james@538 963 return NULL;
james@536 964 /*
james@536 965 we have to allocate PAGE_SIZE bytes here because Windows thinks this is
james@536 966 actually an ADAPTER_OBJECT, and then the verifier crashes because
james@536 967 Windows accessed beyond the end of the structure :(
james@536 968 */
james@536 969 xen_dma_adapter = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@538 970 ASSERT(xen_dma_adapter);
james@536 971 RtlZeroMemory(xen_dma_adapter, PAGE_SIZE);
james@538 972
james@538 973 switch(device_description->Version)
james@538 974 {
james@538 975 case DEVICE_DESCRIPTION_VERSION1:
james@538 976 xen_dma_adapter->adapter_object.DmaHeader.Version = 1;
james@538 977 break;
james@538 978 case DEVICE_DESCRIPTION_VERSION: /* ignore what the docs say here - DEVICE_DESCRIPTION_VERSION appears to mean the latest version */
james@538 979 case DEVICE_DESCRIPTION_VERSION2:
james@538 980 xen_dma_adapter->adapter_object.DmaHeader.Version = 2;
james@538 981 break;
james@538 982 default:
james@538 983 KdPrint((__DRIVER_NAME " Unsupported device description version %d\n", device_description->Version));
james@538 984 ExFreePoolWithTag(xen_dma_adapter, XENPCI_POOL_TAG);
james@538 985 return NULL;
james@538 986 }
james@538 987
james@558 988 xen_dma_adapter->xppdd = context;
james@558 989 xen_dma_adapter->dma_extension = NULL;
james@558 990
james@558 991 KdPrint((__DRIVER_NAME " About to call IoGetAttachedDeviceReference\n"));
james@558 992 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(xen_dma_adapter->xppdd->wdf_device));
james@558 993 KdPrint((__DRIVER_NAME " Before start of loop - curr = %p\n", curr));
james@558 994 while (curr != NULL)
james@558 995 {
james@558 996 fdo_driver_object = curr->DriverObject;
james@558 997 if (fdo_driver_object)
james@558 998 {
james@558 999 ObReferenceObject(fdo_driver_object);
james@558 1000 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC));
james@558 1001 if (fdo_driver_extension)
james@558 1002 {
james@558 1003 xen_dma_adapter->dma_extension_driver = fdo_driver_object; /* so we can dereference it on putdmaadapter */
james@558 1004 xen_dma_adapter->dma_extension = (dma_driver_extension_t *)fdo_driver_extension;
james@558 1005 ObDereferenceObject(curr);
james@558 1006 break;
james@558 1007 }
james@558 1008 else
james@558 1009 {
james@558 1010 ObDereferenceObject(fdo_driver_object);
james@558 1011 }
james@558 1012 }
james@558 1013 prev = curr;
james@558 1014 curr = IoGetLowerDeviceObject(curr);
james@558 1015 ObDereferenceObject(prev);
james@558 1016 }
james@558 1017 KdPrint((__DRIVER_NAME " End of loop\n"));
james@538 1018
james@538 1019 xen_dma_adapter->adapter_object.DmaHeader.Size = sizeof(X_ADAPTER_OBJECT); //xen_dma_adapter_t);
james@538 1020 xen_dma_adapter->adapter_object.MasterAdapter = NULL;
james@558 1021 if (xen_dma_adapter->dma_extension && xen_dma_adapter->dma_extension->max_sg_elements)
james@558 1022 {
james@558 1023 xen_dma_adapter->adapter_object.MapRegistersPerChannel = xen_dma_adapter->dma_extension->max_sg_elements;
james@558 1024 }
james@558 1025 else
james@558 1026 {
james@558 1027 xen_dma_adapter->adapter_object.MapRegistersPerChannel = 256;
james@558 1028 }
james@538 1029 xen_dma_adapter->adapter_object.AdapterBaseVa = NULL;
james@538 1030 xen_dma_adapter->adapter_object.MapRegisterBase = NULL;
james@538 1031 xen_dma_adapter->adapter_object.NumberOfMapRegisters = 0;
james@538 1032 xen_dma_adapter->adapter_object.CommittedMapRegisters = 0;
james@538 1033 xen_dma_adapter->adapter_object.CurrentWcb = NULL;
james@538 1034 KeInitializeDeviceQueue(&xen_dma_adapter->adapter_object.ChannelWaitQueue);
james@538 1035 xen_dma_adapter->adapter_object.RegisterWaitQueue = NULL;
james@538 1036 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterQueue);
james@538 1037 KeInitializeSpinLock(&xen_dma_adapter->adapter_object.SpinLock);
james@538 1038 xen_dma_adapter->adapter_object.MapRegisters = NULL;
james@538 1039 xen_dma_adapter->adapter_object.PagePort = NULL;
james@538 1040 xen_dma_adapter->adapter_object.ChannelNumber = 0xff;
james@538 1041 xen_dma_adapter->adapter_object.AdapterNumber = 0;
james@538 1042 xen_dma_adapter->adapter_object.DmaPortAddress = 0;
james@538 1043 xen_dma_adapter->adapter_object.AdapterMode = 0;
james@538 1044 xen_dma_adapter->adapter_object.NeedsMapRegisters = FALSE; /* when true this causes a crash in the crash dump path */
james@538 1045 xen_dma_adapter->adapter_object.MasterDevice = 1;
james@538 1046 xen_dma_adapter->adapter_object.Width16Bits = 0;
james@538 1047 xen_dma_adapter->adapter_object.ScatterGather = device_description->ScatterGather;
james@538 1048 xen_dma_adapter->adapter_object.IgnoreCount = device_description->IgnoreCount;
james@538 1049 xen_dma_adapter->adapter_object.Dma32BitAddresses = device_description->Dma32BitAddresses;
james@538 1050 xen_dma_adapter->adapter_object.Dma64BitAddresses = device_description->Dma64BitAddresses;
james@538 1051 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterList);
james@538 1052
james@538 1053 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DMA_OPERATIONS), XENPCI_POOL_TAG);
james@538 1054 ASSERT(xen_dma_adapter->adapter_object.DmaHeader.DmaOperations);
james@538 1055 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 1)
james@538 1056 {
james@538 1057 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = FIELD_OFFSET(DMA_OPERATIONS, CalculateScatterGatherList);
james@538 1058 }
james@538 1059 else
james@538 1060 {
james@538 1061 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = sizeof(DMA_OPERATIONS);
james@538 1062 }
james@538 1063 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutDmaAdapter = XenPci_DOP_PutDmaAdapter;
james@538 1064 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateCommonBuffer = XenPci_DOP_AllocateCommonBuffer;
james@538 1065 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeCommonBuffer = XenPci_DOP_FreeCommonBuffer;
james@538 1066 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateAdapterChannel = XenPci_DOP_AllocateAdapterChannel;
james@538 1067 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FlushAdapterBuffers = XenPci_DOP_FlushAdapterBuffers;
james@538 1068 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeAdapterChannel = XenPci_DOP_FreeAdapterChannel;
james@538 1069 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeMapRegisters = XenPci_DOP_FreeMapRegisters;
james@538 1070 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->MapTransfer = XenPci_DOP_MapTransfer;
james@538 1071 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetDmaAlignment = XenPci_DOP_GetDmaAlignment;
james@538 1072 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->ReadDmaCounter = XenPci_DOP_ReadDmaCounter;
james@538 1073 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetScatterGatherList = XenPci_DOP_GetScatterGatherList;
james@538 1074 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutScatterGatherList = XenPci_DOP_PutScatterGatherList;
james@538 1075 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 2)
james@538 1076 {
james@538 1077 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->CalculateScatterGatherList = XenPci_DOP_CalculateScatterGatherList;
james@538 1078 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildScatterGatherList = XenPci_DOP_BuildScatterGatherList;
james@538 1079 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildMdlFromScatterGatherList = XenPci_DOP_BuildMdlFromScatterGatherList;
james@538 1080 }
james@536 1081
james@558 1082 *number_of_map_registers = xen_dma_adapter->adapter_object.MapRegistersPerChannel; //1024; /* why not... */
james@536 1083
james@536 1084 FUNCTION_EXIT();
james@536 1085
james@538 1086 return &xen_dma_adapter->adapter_object.DmaHeader;
james@536 1087 }
james@536 1088
james@536 1089 static ULONG
james@536 1090 XenPci_BIS_SetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
james@536 1091 {
james@536 1092 UNREFERENCED_PARAMETER(context);
james@536 1093 UNREFERENCED_PARAMETER(data_type);
james@536 1094 UNREFERENCED_PARAMETER(buffer);
james@536 1095 UNREFERENCED_PARAMETER(offset);
james@536 1096 UNREFERENCED_PARAMETER(length);
james@536 1097
james@536 1098 FUNCTION_ENTER();
james@536 1099 FUNCTION_EXIT();
james@536 1100 return 0;
james@536 1101 }
james@536 1102
james@536 1103 static ULONG
james@536 1104 XenPci_BIS_GetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
james@536 1105 {
james@536 1106 UNREFERENCED_PARAMETER(context);
james@536 1107 UNREFERENCED_PARAMETER(data_type);
james@536 1108 UNREFERENCED_PARAMETER(buffer);
james@536 1109 UNREFERENCED_PARAMETER(offset);
james@536 1110 UNREFERENCED_PARAMETER(length);
james@536 1111
james@536 1112 FUNCTION_ENTER();
james@536 1113 FUNCTION_EXIT();
james@536 1114 return 0;
james@536 1115 }
james@536 1116
james@536 1117 /*
james@536 1118 Called at PASSIVE_LEVEL(?)
james@536 1119 Called during restore
james@536 1120 */
james@536 1121 static ULONG
james@536 1122 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
james@536 1123 {
james@536 1124 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1125 char path[128];
james@536 1126 char *value;
james@536 1127 char *err;
james@536 1128 ULONG backend_state;
james@536 1129
james@536 1130 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@536 1131 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@536 1132 if (err)
james@536 1133 {
james@536 1134 XenPci_FreeMem(err);
james@536 1135 return XenbusStateUnknown;
james@536 1136 }
james@536 1137 else
james@536 1138 {
james@536 1139 backend_state = atoi(value);
james@536 1140 XenPci_FreeMem(value);
james@536 1141 return backend_state;
james@536 1142 }
james@536 1143 }
james@536 1144
james@617 1145 static NTSTATUS
james@617 1146 XenPciPdo_ReconfigureCompletionRoutine(
james@617 1147 PDEVICE_OBJECT device_object,
james@617 1148 PIRP irp,
james@617 1149 PVOID context)
james@617 1150 {
james@617 1151 UNREFERENCED_PARAMETER(device_object);
james@617 1152
james@617 1153 if (irp->PendingReturned)
james@617 1154 {
james@617 1155 KeSetEvent ((PKEVENT)context, IO_NO_INCREMENT, FALSE);
james@617 1156 }
james@617 1157 return STATUS_MORE_PROCESSING_REQUIRED;
james@617 1158 }
james@617 1159
james@536 1160 static VOID
james@624 1161 XenPci_UpdateBackendState(PVOID context)
james@536 1162 {
james@536 1163 WDFDEVICE device = context;
james@536 1164 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1165 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1166 ULONG new_backend_state;
james@617 1167 CHAR tmp_path[128];
james@536 1168
james@624 1169 FUNCTION_ENTER();
james@536 1170
james@624 1171 ExAcquireFastMutex(&xppdd->backend_state_mutex);
james@624 1172
james@536 1173 new_backend_state = XenPci_ReadBackendState(xppdd);
james@536 1174 if (new_backend_state == XenbusStateUnknown)
james@536 1175 {
james@536 1176 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
james@624 1177 {
james@624 1178 ExReleaseFastMutex(&xppdd->backend_state_mutex);
james@536 1179 return;
james@624 1180 }
james@624 1181 KdPrint(("Failed to read path, assuming closed\n"));
james@536 1182 new_backend_state = XenbusStateClosed;
james@536 1183 }
james@536 1184
james@536 1185 if (xppdd->backend_state == new_backend_state)
james@536 1186 {
james@536 1187 KdPrint((__DRIVER_NAME " state unchanged\n"));
james@624 1188 ExReleaseFastMutex(&xppdd->backend_state_mutex);
james@536 1189 return;
james@536 1190 }
james@536 1191
james@536 1192 xppdd->backend_state = new_backend_state;
james@536 1193
james@536 1194 switch (xppdd->backend_state)
james@536 1195 {
james@536 1196 case XenbusStateUnknown:
james@624 1197 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
james@536 1198 break;
james@536 1199
james@536 1200 case XenbusStateInitialising:
james@624 1201 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
james@536 1202 break;
james@536 1203
james@536 1204 case XenbusStateInitWait:
james@624 1205 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
james@536 1206 break;
james@536 1207
james@536 1208 case XenbusStateInitialised:
james@624 1209 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
james@536 1210 break;
james@536 1211
james@536 1212 case XenbusStateConnected:
james@624 1213 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
james@536 1214 break;
james@536 1215
james@536 1216 case XenbusStateClosing:
james@624 1217 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
james@538 1218 if (xppdd->frontend_state == XenbusStateConnected)
james@536 1219 {
james@538 1220 KdPrint((__DRIVER_NAME " Requesting eject\n"));
james@536 1221 WdfPdoRequestEject(device);
james@536 1222 }
james@536 1223 break;
james@536 1224
james@536 1225 case XenbusStateClosed:
james@624 1226 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
james@536 1227 break;
james@536 1228
james@617 1229 case XenbusStateReconfiguring:
james@624 1230 KdPrint((__DRIVER_NAME " Backend State Changed to Reconfiguring\n"));
james@617 1231 RtlStringCbPrintfA(tmp_path, ARRAY_SIZE(tmp_path), "%s/state", xppdd->path);
james@617 1232 KdPrint((__DRIVER_NAME " Setting %s to %d\n", tmp_path, XenbusStateReconfiguring));
james@617 1233 XenBus_Printf(xpdd, XBT_NIL, tmp_path, "%d", XenbusStateReconfiguring);
james@617 1234 break;
james@617 1235
james@617 1236 case XenbusStateReconfigured:
james@624 1237 KdPrint((__DRIVER_NAME " Backend State Changed to Reconfigured\n"));
james@617 1238 {
james@617 1239 PDEVICE_OBJECT fdo;
james@617 1240 PIRP irp;
james@617 1241 PIO_STACK_LOCATION stack;
james@617 1242 NTSTATUS status;
james@617 1243 KEVENT irp_complete_event;
james@617 1244
james@617 1245 fdo = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(device));
james@617 1246 KeInitializeEvent(&irp_complete_event, NotificationEvent, FALSE);
james@617 1247 irp = IoAllocateIrp(fdo->StackSize, FALSE);
james@617 1248 stack = IoGetNextIrpStackLocation(irp);
james@617 1249 stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
james@617 1250 stack->Parameters.DeviceIoControl.IoControlCode = (ULONG)IOCTL_XEN_RECONFIGURE;
james@617 1251 IoSetCompletionRoutine(irp, XenPciPdo_ReconfigureCompletionRoutine, &irp_complete_event, TRUE, TRUE, TRUE);
james@617 1252 status = IoCallDriver(fdo, irp);
james@617 1253 if (status == STATUS_PENDING)
james@617 1254 {
james@617 1255 KdPrint((__DRIVER_NAME " Waiting for completion\n"));
james@617 1256 status = KeWaitForSingleObject(&irp_complete_event, Executive, KernelMode, FALSE, NULL);
james@617 1257 status = irp->IoStatus.Status;
james@617 1258 }
james@617 1259 KdPrint((__DRIVER_NAME " IOCTL_XEN_RECONFIGURE status = %08x\n", status));
james@617 1260 ObDereferenceObject(fdo);
james@617 1261 #if 0
james@617 1262 WDFREQUEST request;
james@617 1263 WDF_REQUEST_SEND_OPTIONS options;
james@617 1264 WDFIOTARGET target;
james@617 1265 DEVICE_OBJECT fdo;
james@617 1266
james@617 1267 WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET);
james@617 1268 fdo = IoGetAttachedDevice(WdfDeviceWdmGetDeviceObject(device));
james@617 1269
james@617 1270 target = WdfDeviceGetIoTarget(xppdd->wdf_device);
james@617 1271 WdfRequestCreate(WDF_NO_OBJECT_ATTRIBUTES, target, &request);
james@617 1272 WdfIoTargetFormatRequestForInternalIoctl(target, request, IOCTL_XEN_RECONFIGURE, NULL, NULL, NULL, NULL);
james@617 1273 WdfRequestSend(request, target, &options);
james@617 1274 #endif
james@617 1275 RtlStringCbPrintfA(tmp_path, ARRAY_SIZE(tmp_path), "%s/state", xppdd->path);
james@617 1276 KdPrint((__DRIVER_NAME " Setting %s to %d\n", tmp_path, XenbusStateConnected));
james@617 1277 XenBus_Printf(xpdd, XBT_NIL, tmp_path, "%d", XenbusStateConnected);
james@617 1278 break;
james@617 1279 }
james@617 1280
james@536 1281 default:
james@624 1282 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", xppdd->backend_state));
james@536 1283 break;
james@536 1284 }
james@536 1285
james@536 1286 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
james@536 1287
james@624 1288 ExReleaseFastMutex(&xppdd->backend_state_mutex);
james@624 1289 FUNCTION_EXIT();
james@536 1290
james@536 1291 return;
james@536 1292 }
james@536 1293
james@624 1294 static VOID
james@624 1295 XenPci_BackendStateHandler(char *path, PVOID context)
james@624 1296 {
james@624 1297 UNREFERENCED_PARAMETER(path);
james@624 1298
james@624 1299 /* check that path == device/id/state */
james@624 1300 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
james@624 1301
james@624 1302 XenPci_UpdateBackendState(context);
james@624 1303 }
james@624 1304
james@536 1305 static NTSTATUS
james@536 1306 XenPci_GetBackendAndAddWatch(WDFDEVICE device)
james@536 1307 {
james@536 1308 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1309 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1310 char path[128];
james@536 1311 PCHAR res;
james@536 1312 PCHAR value;
james@536 1313
james@624 1314 FUNCTION_ENTER();
james@536 1315 /* Get backend path */
james@536 1316 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
james@536 1317 "%s/backend", xppdd->path);
james@536 1318 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@536 1319 if (res)
james@536 1320 {
james@536 1321 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
james@536 1322 XenPci_FreeMem(res);
james@536 1323 return STATUS_UNSUCCESSFUL;
james@536 1324 }
james@536 1325 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
james@536 1326 XenPci_FreeMem(value);
james@536 1327
james@536 1328 /* Add watch on backend state */
james@536 1329 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@624 1330 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
james@624 1331
james@624 1332 FUNCTION_EXIT();
james@536 1333 return STATUS_SUCCESS;
james@536 1334 }
james@536 1335
james@551 1336 static NTSTATUS
james@551 1337 XenConfig_InitConfigPage(WDFDEVICE device)
james@536 1338 {
james@551 1339 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1340 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
james@536 1341 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
james@536 1342 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@536 1343 PUCHAR ptr;
james@536 1344 PDEVICE_OBJECT curr, prev;
james@536 1345 PDRIVER_OBJECT fdo_driver_object;
james@536 1346 PUCHAR fdo_driver_extension;
james@536 1347
james@536 1348 FUNCTION_ENTER();
james@536 1349
james@551 1350 ptr = MmGetMdlVirtualAddress(xppdd->config_page_mdl);
james@536 1351 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(device));
james@536 1352 //curr = WdfDeviceWdmGetAttachedDevice(device);
james@536 1353 while (curr != NULL)
james@536 1354 {
james@536 1355 fdo_driver_object = curr->DriverObject;
james@536 1356 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
james@536 1357 if (fdo_driver_object)
james@536 1358 {
james@536 1359 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
james@536 1360 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
james@536 1361 if (fdo_driver_extension)
james@536 1362 {
james@536 1363 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
james@536 1364 ObDereferenceObject(curr);
james@536 1365 break;
james@536 1366 }
james@536 1367 }
james@536 1368 prev = curr;
james@536 1369 curr = IoGetLowerDeviceObject(curr);
james@536 1370 ObDereferenceObject(prev);
james@536 1371 }
james@536 1372
james@536 1373 FUNCTION_EXIT();
james@536 1374
james@551 1375 return STATUS_SUCCESS;
james@536 1376 }
james@536 1377
james@536 1378 static NTSTATUS
james@536 1379 XenPci_EvtChn_Bind(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
james@536 1380 {
james@536 1381 WDFDEVICE device = context;
james@536 1382 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1383 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1384
james@536 1385 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext);
james@536 1386 }
james@536 1387
james@536 1388 static NTSTATUS
james@536 1389 XenPci_EvtChn_BindDpc(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
james@536 1390 {
james@536 1391 WDFDEVICE device = context;
james@536 1392 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1393 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1394
james@536 1395 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext);
james@536 1396 }
james@536 1397
james@536 1398 static NTSTATUS
james@536 1399 XenPci_EvtChn_Unbind(PVOID context, evtchn_port_t Port)
james@536 1400 {
james@536 1401 WDFDEVICE device = context;
james@536 1402 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1403 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1404
james@536 1405 return EvtChn_Unbind(xpdd, Port);
james@536 1406 }
james@536 1407
james@536 1408 static NTSTATUS
james@536 1409 XenPci_EvtChn_Mask(PVOID context, evtchn_port_t Port)
james@536 1410 {
james@536 1411 WDFDEVICE device = context;
james@536 1412 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1413 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1414
james@536 1415 return EvtChn_Mask(xpdd, Port);
james@536 1416 }
james@536 1417
james@536 1418 static NTSTATUS
james@536 1419 XenPci_EvtChn_Unmask(PVOID context, evtchn_port_t Port)
james@536 1420 {
james@536 1421 WDFDEVICE device = context;
james@536 1422 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1423 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1424
james@536 1425 return EvtChn_Unmask(xpdd, Port);
james@536 1426 }
james@536 1427
james@536 1428 static NTSTATUS
james@536 1429 XenPci_EvtChn_Notify(PVOID context, evtchn_port_t Port)
james@536 1430 {
james@536 1431 WDFDEVICE device = context;
james@536 1432 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1433 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1434
james@536 1435 return EvtChn_Notify(xpdd, Port);
james@536 1436 }
james@536 1437
james@536 1438 static BOOLEAN
james@561 1439 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port, BOOLEAN *last_interrupt)
james@536 1440 {
james@536 1441 WDFDEVICE device = context;
james@536 1442 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1443 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1444
james@561 1445 return EvtChn_AckEvent(xpdd, port, last_interrupt);
james@536 1446 }
james@536 1447
james@536 1448 typedef struct {
james@536 1449 PXEN_EVTCHN_SYNC_ROUTINE sync_routine;
james@536 1450 PVOID sync_context;
james@536 1451 } sync_context_t;
james@536 1452
james@536 1453 static BOOLEAN
james@536 1454 XenPci_EvtChn_Sync_Routine(WDFINTERRUPT interrupt, WDFCONTEXT context)
james@536 1455 {
james@536 1456 sync_context_t *wdf_sync_context = context;
james@536 1457 UNREFERENCED_PARAMETER(interrupt);
james@536 1458 return wdf_sync_context->sync_routine(wdf_sync_context->sync_context);
james@536 1459 }
james@536 1460
james@536 1461 static BOOLEAN
james@536 1462 XenPci_EvtChn_Sync(PVOID context, PXEN_EVTCHN_SYNC_ROUTINE sync_routine, PVOID sync_context)
james@536 1463 {
james@536 1464 WDFDEVICE device = context;
james@536 1465 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1466 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1467 sync_context_t wdf_sync_context;
james@536 1468
james@536 1469 wdf_sync_context.sync_routine = sync_routine;
james@536 1470 wdf_sync_context.sync_context = sync_context;
james@536 1471
james@536 1472 return WdfInterruptSynchronize(xpdd->interrupt, XenPci_EvtChn_Sync_Routine, &wdf_sync_context);
james@536 1473 }
james@536 1474
james@536 1475 static grant_ref_t
james@536 1476 XenPci_GntTbl_GrantAccess(PVOID context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref)
james@536 1477 {
james@536 1478 WDFDEVICE device = context;
james@536 1479 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1480 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1481
james@536 1482 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref);
james@536 1483 }
james@536 1484
james@536 1485 static BOOLEAN
james@536 1486 XenPci_GntTbl_EndAccess(PVOID context, grant_ref_t ref, BOOLEAN keepref)
james@536 1487 {
james@536 1488 WDFDEVICE device = context;
james@536 1489 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1490 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1491
james@536 1492 return GntTbl_EndAccess(xpdd, ref, keepref);
james@536 1493 }
james@536 1494
james@536 1495 static VOID
james@536 1496 XenPci_GntTbl_PutRef(PVOID context, grant_ref_t ref)
james@536 1497 {
james@536 1498 WDFDEVICE device = context;
james@536 1499 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1500 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1501
james@536 1502 GntTbl_PutRef(xpdd, ref);
james@536 1503 }
james@536 1504
james@536 1505 static grant_ref_t
james@536 1506 XenPci_GntTbl_GetRef(PVOID context)
james@536 1507 {
james@536 1508 WDFDEVICE device = context;
james@536 1509 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1510 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1511
james@536 1512 return GntTbl_GetRef(xpdd);
james@536 1513 }
james@536 1514
james@536 1515 PCHAR
james@536 1516 XenPci_XenBus_Read(PVOID context, xenbus_transaction_t xbt, char *path, char **value)
james@536 1517 {
james@536 1518 WDFDEVICE device = context;
james@536 1519 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1520 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1521 return XenBus_Read(xpdd, xbt, path, value);
james@536 1522 }
james@536 1523
james@536 1524 PCHAR
james@536 1525 XenPci_XenBus_Write(PVOID context, xenbus_transaction_t xbt, char *path, char *value)
james@536 1526 {
james@536 1527 WDFDEVICE device = context;
james@536 1528 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1529 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1530 return XenBus_Write(xpdd, xbt, path, value);
james@536 1531 }
james@536 1532
james@536 1533 PCHAR
james@536 1534 XenPci_XenBus_Printf(PVOID context, xenbus_transaction_t xbt, char *path, char *fmt, ...)
james@536 1535 {
james@536 1536 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@536 1537 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@536 1538 //return XenBus_Printf(xpdd, xbt, path, value);
james@536 1539 UNREFERENCED_PARAMETER(context);
james@536 1540 UNREFERENCED_PARAMETER(xbt);
james@536 1541 UNREFERENCED_PARAMETER(path);
james@536 1542 UNREFERENCED_PARAMETER(fmt);
james@536 1543 return NULL;
james@536 1544 }
james@536 1545
james@536 1546 PCHAR
james@536 1547 XenPci_XenBus_StartTransaction(PVOID context, xenbus_transaction_t *xbt)
james@536 1548 {
james@536 1549 WDFDEVICE device = context;
james@536 1550 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1551 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1552 return XenBus_StartTransaction(xpdd, xbt);
james@536 1553 }
james@536 1554
james@536 1555 PCHAR
james@536 1556 XenPci_XenBus_EndTransaction(PVOID context, xenbus_transaction_t xbt, int abort, int *retry)
james@536 1557 {
james@536 1558 WDFDEVICE device = context;
james@536 1559 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1560 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1561 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
james@536 1562 }
james@536 1563
james@536 1564 PCHAR
james@536 1565 XenPci_XenBus_List(PVOID context, xenbus_transaction_t xbt, char *prefix, char ***contents)
james@536 1566 {
james@536 1567 WDFDEVICE device = context;
james@536 1568 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1569 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1570 return XenBus_List(xpdd, xbt, prefix, contents);
james@536 1571 }
james@536 1572
james@536 1573 PCHAR
james@536 1574 XenPci_XenBus_AddWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
james@536 1575 {
james@536 1576 WDFDEVICE device = context;
james@536 1577 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1578 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1579 PCHAR retval;
james@536 1580
james@536 1581 FUNCTION_ENTER();
james@536 1582 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
james@536 1583 if (retval == NULL)
james@536 1584 {
james@536 1585 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
james@536 1586 }
james@536 1587 else
james@536 1588 {
james@536 1589 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
james@536 1590 }
james@536 1591 FUNCTION_EXIT();
james@536 1592 return retval;
james@536 1593 }
james@536 1594
james@536 1595 PCHAR
james@536 1596 XenPci_XenBus_RemWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
james@536 1597 {
james@536 1598 WDFDEVICE device = context;
james@536 1599 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1600 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1601 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
james@536 1602 }
james@536 1603
james@536 1604 /*
james@536 1605 Called at PASSIVE_LEVEL
james@536 1606 Called during restore
james@536 1607 */
james@536 1608
james@536 1609 static NTSTATUS
james@536 1610 XenPci_ChangeFrontendState(WDFDEVICE device, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
james@536 1611 {
james@536 1612 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1613 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1614 LARGE_INTEGER timeout;
james@536 1615 ULONG remaining;
james@536 1616 ULONG thiswait;
james@536 1617 char path[128];
james@536 1618
james@624 1619 FUNCTION_ENTER();
james@538 1620
james@538 1621 xppdd->frontend_state = frontend_state_set;
james@536 1622
james@536 1623 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
james@536 1624 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
james@536 1625
james@536 1626 remaining = maximum_wait_ms;
james@536 1627
james@536 1628 while (xppdd->backend_state != backend_state_response)
james@536 1629 {
james@536 1630 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
james@536 1631 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
james@536 1632 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
james@536 1633 {
james@624 1634 /* it's possible that the workitems are blocked because the pagefile isn't available. Lets just re-read the backend value for now */
james@624 1635 XenPci_UpdateBackendState(device);
james@536 1636 remaining -= thiswait;
james@536 1637 if (remaining == 0)
james@536 1638 {
james@536 1639 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
james@536 1640 return STATUS_UNSUCCESSFUL;
james@536 1641 }
james@536 1642 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
james@536 1643 }
james@536 1644 }
james@624 1645 FUNCTION_EXIT();
james@536 1646 return STATUS_SUCCESS;
james@536 1647 }
james@536 1648
james@536 1649 static NTSTATUS
james@536 1650 XenPci_XenConfigDevice(WDFDEVICE device);
james@536 1651
james@536 1652 static NTSTATUS
james@536 1653 XenPci_XenShutdownDevice(PVOID context)
james@536 1654 {
james@536 1655 WDFDEVICE device = context;
james@536 1656 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1657 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1658 PUCHAR in_ptr;
james@536 1659 ULONG i;
james@536 1660 UCHAR type;
james@536 1661 PVOID setting;
james@536 1662 PVOID value;
james@536 1663 PVOID value2;
james@536 1664
james@536 1665 FUNCTION_ENTER();
james@536 1666
james@536 1667 if (xppdd->backend_state == XenbusStateConnected)
james@536 1668 {
james@536 1669 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
james@536 1670 if (xppdd->backend_state == XenbusStateClosing)
james@536 1671 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
james@536 1672 if (xppdd->backend_state == XenbusStateClosed)
james@536 1673 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
james@536 1674 }
james@536 1675 else
james@536 1676 {
james@536 1677 if (xppdd->backend_state == XenbusStateClosing)
james@536 1678 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
james@536 1679 }
james@536 1680
james@536 1681 if (xppdd->assigned_resources_start != NULL)
james@536 1682 {
james@536 1683 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 1684 in_ptr = xppdd->assigned_resources_start;
james@536 1685 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
james@536 1686 {
james@536 1687 switch (type)
james@536 1688 {
james@536 1689 case XEN_INIT_TYPE_RING: /* frontend ring */
james@536 1690 FreePages(value);
james@536 1691 break;
james@536 1692 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@617 1693 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
james@536 1694 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 1695 EvtChn_Unbind(xpdd, PtrToUlong(value));
james@536 1696 EvtChn_Close(xpdd, PtrToUlong(value));
james@536 1697 break;
james@536 1698 case XEN_INIT_TYPE_GRANT_ENTRIES:
james@536 1699 for (i = 0; i < PtrToUlong(setting); i++)
james@536 1700 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value)[i], FALSE);
james@536 1701 break;
james@536 1702 }
james@536 1703 }
james@536 1704 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
james@536 1705 xppdd->assigned_resources_start = NULL;
james@536 1706 }
james@536 1707
james@536 1708 FUNCTION_EXIT();
james@536 1709
james@536 1710 return STATUS_SUCCESS;
james@536 1711 }
james@536 1712
james@536 1713 struct dummy_sring {
james@536 1714 RING_IDX req_prod, req_event;
james@536 1715 RING_IDX rsp_prod, rsp_event;
james@536 1716 uint8_t pad[48];
james@536 1717 };
james@536 1718
james@536 1719 static NTSTATUS
james@536 1720 XenPci_XenConfigDeviceSpecifyBuffers(WDFDEVICE device, PUCHAR src, PUCHAR dst)
james@536 1721 {
james@536 1722 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1723 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1724 NTSTATUS status = STATUS_SUCCESS;
james@536 1725 ULONG i;
james@536 1726 char path[128];
james@536 1727 PCHAR setting, value;
james@536 1728 PCHAR res;
james@536 1729 PVOID address;
james@536 1730 UCHAR type;
james@551 1731 PUCHAR in_ptr;
james@551 1732 PUCHAR out_ptr;
james@536 1733 XENPCI_VECTORS vectors;
james@536 1734 ULONG event_channel;
james@536 1735 ULONG run_type = 0;
james@536 1736 PMDL ring;
james@536 1737 grant_ref_t gref;
james@536 1738 BOOLEAN done_xenbus_init = FALSE;
james@536 1739 PVOID value2;
james@551 1740 BOOLEAN active = TRUE;
james@551 1741 BOOLEAN dont_config = FALSE;
james@536 1742
james@536 1743 FUNCTION_ENTER();
james@536 1744
james@536 1745 in_ptr = src;
james@536 1746 out_ptr = dst;
james@536 1747
james@536 1748 // always add vectors
james@536 1749 vectors.magic = XEN_DATA_MAGIC;
james@536 1750 vectors.length = sizeof(XENPCI_VECTORS);
james@536 1751 vectors.context = device;
james@536 1752 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
james@536 1753 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
james@536 1754 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
james@536 1755 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
james@536 1756 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
james@536 1757 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
james@536 1758 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
james@536 1759 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
james@536 1760 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
james@536 1761 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
james@536 1762 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
james@536 1763 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
james@536 1764 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
james@536 1765 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
james@536 1766 strncpy(vectors.path, xppdd->path, 128);
james@536 1767 strncpy(vectors.backend_path, xppdd->backend_path, 128);
james@536 1768 //vectors.pdo_event_channel = xpdd->pdo_event_channel;
james@536 1769 vectors.XenBus_Read = XenPci_XenBus_Read;
james@536 1770 vectors.XenBus_Write = XenPci_XenBus_Write;
james@536 1771 vectors.XenBus_Printf = XenPci_XenBus_Printf;
james@536 1772 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
james@536 1773 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
james@536 1774 vectors.XenBus_List = XenPci_XenBus_List;
james@536 1775 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
james@536 1776 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
james@536 1777
james@536 1778 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
james@536 1779
james@536 1780 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
james@536 1781 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
james@536 1782
james@551 1783 if (!qemu_filtered)
james@551 1784 active = FALSE;
james@551 1785
james@551 1786 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@551 1787 {
james@551 1788 BOOLEAN condition;
james@551 1789 PCHAR xb_value;
james@551 1790 switch (type)
james@551 1791 {
james@551 1792 case XEN_INIT_TYPE_MATCH_FRONT:
james@551 1793 case XEN_INIT_TYPE_MATCH_BACK:
james@551 1794 if (type == XEN_INIT_TYPE_MATCH_FRONT)
james@551 1795 {
james@551 1796 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@551 1797 }
james@551 1798 else
james@551 1799 {
james@551 1800 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
james@551 1801 }
james@551 1802 KdPrint((__DRIVER_NAME " testing path = %s\n", path));
james@551 1803 res = XenBus_Read(xpdd, XBT_NIL, path, &xb_value);
james@551 1804 if (res)
james@551 1805 {
james@551 1806 KdPrint((__DRIVER_NAME " read failed (%s)\n", res));
james@551 1807 XenPci_FreeMem(res);
james@551 1808 }
james@551 1809 else
james@551 1810 {
james@551 1811 KdPrint((__DRIVER_NAME " testing %s vs %s\n", xb_value, value));
james@551 1812 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_IF_MATCH)
james@551 1813 condition = (strcmp(xb_value, value) == 0)?TRUE:FALSE;
james@551 1814 else
james@551 1815 condition = (strcmp(xb_value, value) != 0)?TRUE:FALSE;
james@551 1816 KdPrint((__DRIVER_NAME " condition = %d\n", condition));
james@551 1817
james@551 1818 if ((PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_ONLY_IF_QEMU_HIDE) && qemu_protocol_version && condition)
james@551 1819 condition = FALSE;
james@551 1820
james@551 1821 if (condition)
james@551 1822 {
james@551 1823 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_SET_INACTIVE)
james@551 1824 {
james@551 1825 active = FALSE;
james@551 1826 KdPrint((__DRIVER_NAME " set inactive\n"));
james@551 1827 }
james@551 1828 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_DONT_CONFIG)
james@551 1829 {
james@551 1830 dont_config = TRUE;
james@551 1831 KdPrint((__DRIVER_NAME " set inactive with dont config\n"));
james@551 1832 }
james@551 1833 }
james@551 1834 XenPci_FreeMem(xb_value);
james@551 1835 }
james@551 1836 break;
james@551 1837 }
james@551 1838 }
james@551 1839 if (dont_config)
james@551 1840 {
james@551 1841 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@551 1842 FUNCTION_EXIT();
james@551 1843 return status;
james@551 1844 }
james@551 1845
james@536 1846 // first pass, possibly before state == Connected
james@551 1847 in_ptr = src;
james@536 1848 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@536 1849 {
james@536 1850 if (!done_xenbus_init)
james@536 1851 {
james@551 1852 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000) != STATUS_SUCCESS)
james@536 1853 {
james@536 1854 status = STATUS_UNSUCCESSFUL;
james@536 1855 goto error;
james@536 1856 }
james@536 1857 done_xenbus_init = TRUE;
james@536 1858 }
james@536 1859
james@536 1860 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
james@536 1861
james@536 1862 switch (type)
james@536 1863 {
james@536 1864 case XEN_INIT_TYPE_RUN:
james@536 1865 run_type++;
james@536 1866 break;
james@536 1867 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
james@536 1868 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
james@536 1869 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 1870 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
james@536 1871 break;
james@536 1872 case XEN_INIT_TYPE_RING: /* frontend ring */
james@536 1873 /* we only allocate and do the SHARED_RING_INIT here */
james@536 1874 if ((ring = AllocatePage()) != 0)
james@536 1875 {
james@536 1876 address = MmGetMdlVirtualAddress(ring);
james@536 1877 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
james@536 1878 SHARED_RING_INIT((struct dummy_sring *)address);
james@536 1879 if ((gref = GntTbl_GrantAccess(
james@536 1880 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
james@536 1881 {
james@536 1882 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 1883 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
james@536 1884 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
james@536 1885 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
james@536 1886 // add the grant entry too so it gets freed automatically
james@536 1887 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
james@536 1888 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
james@536 1889 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
james@536 1890 }
james@536 1891 else
james@536 1892 {
james@536 1893 FreePages(ring);
james@536 1894 status = STATUS_UNSUCCESSFUL;
james@536 1895 goto error;
james@536 1896 }
james@536 1897 }
james@536 1898 else
james@536 1899 {
james@536 1900 status = STATUS_UNSUCCESSFUL;
james@536 1901 goto error;
james@536 1902 }
james@536 1903 break;
james@536 1904 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@617 1905 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
james@536 1906 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 1907 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
james@536 1908 {
james@617 1909 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
james@536 1910 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 1911 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
james@536 1912 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
james@536 1913 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
james@536 1914 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
james@536 1915 {
james@536 1916 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
james@536 1917 }
james@617 1918 else if (type == XEN_INIT_TYPE_EVENT_CHANNEL_DPC)
james@617 1919 {
james@617 1920 #pragma warning(suppress:4055)
james@617 1921 EvtChn_BindDpc(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
james@617 1922 }
james@536 1923 else
james@536 1924 {
james@537 1925 #pragma warning(suppress:4055)
james@536 1926 EvtChn_Bind(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
james@536 1927 }
james@536 1928 }
james@536 1929 else
james@536 1930 {
james@536 1931 status = STATUS_UNSUCCESSFUL;
james@536 1932 goto error;
james@536 1933 }
james@536 1934 break;
james@536 1935 }
james@536 1936 }
james@536 1937 if (!NT_SUCCESS(status))
james@536 1938 {
james@536 1939 goto error;
james@536 1940 }
james@536 1941 // 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 1942 if (run_type == 1)
james@536 1943 {
james@551 1944 if (XenPci_ChangeFrontendState(device, XenbusStateInitialised, XenbusStateConnected, 2000) != STATUS_SUCCESS)
james@536 1945 {
james@536 1946 status = STATUS_UNSUCCESSFUL;
james@536 1947 goto error;
james@536 1948 }
james@536 1949 }
james@536 1950
james@536 1951 // second pass, possibly after state == Connected
james@536 1952 in_ptr = src;
james@536 1953 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@536 1954 {
james@536 1955 switch(type)
james@536 1956 {
james@536 1957 case XEN_INIT_TYPE_READ_STRING_BACK:
james@536 1958 case XEN_INIT_TYPE_READ_STRING_FRONT:
james@536 1959 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
james@536 1960 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 1961 else
james@536 1962 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
james@536 1963 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@536 1964 if (res)
james@536 1965 {
james@617 1966 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
james@536 1967 XenPci_FreeMem(res);
james@617 1968 ADD_XEN_INIT_RSP(&out_ptr, type, setting, "", "");
james@536 1969 }
james@536 1970 else
james@536 1971 {
james@536 1972 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
james@536 1973 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, value2);
james@536 1974 XenPci_FreeMem(value);
james@536 1975 }
james@536 1976 break;
james@536 1977 case XEN_INIT_TYPE_VECTORS:
james@536 1978 // this is always done so ignore the request
james@536 1979 break;
james@536 1980 case XEN_INIT_TYPE_GRANT_ENTRIES:
james@536 1981 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
james@536 1982 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
james@536 1983 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
james@536 1984 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
james@536 1985 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
james@536 1986 for (i = 0; i < PtrToUlong(value); i++)
james@536 1987 {
james@536 1988 gref = GntTbl_GetRef(xpdd);
james@536 1989 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
james@536 1990 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
james@536 1991 }
james@536 1992 break;
james@536 1993 }
james@536 1994 }
james@551 1995 if (active)
james@551 1996 {
james@551 1997 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_ACTIVE, NULL, NULL, NULL);
james@551 1998 }
james@536 1999 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 2000
james@536 2001 if (run_type)
james@536 2002 {
james@551 2003 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 2000) != STATUS_SUCCESS)
james@536 2004 {
james@536 2005 status = STATUS_UNSUCCESSFUL;
james@536 2006 goto error;
james@536 2007 }
james@536 2008 }
james@536 2009 FUNCTION_EXIT();
james@536 2010 return status;
james@551 2011
james@536 2012 error:
james@551 2013 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000);
james@536 2014 FUNCTION_EXIT_STATUS(status);
james@536 2015 return status;
james@536 2016 }
james@536 2017
james@536 2018 static NTSTATUS
james@536 2019 XenPci_XenConfigDevice(WDFDEVICE device)
james@536 2020 {
james@536 2021 NTSTATUS status;
james@536 2022 PUCHAR src, dst;
james@536 2023 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2024
james@536 2025 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
james@536 2026 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
james@536 2027 memcpy(src, dst, xppdd->config_page_length);
james@536 2028
james@536 2029 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
james@536 2030
james@536 2031 MmUnmapIoSpace(dst, xppdd->config_page_length);
james@536 2032 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
james@536 2033
james@536 2034 return status;
james@536 2035 }
james@536 2036
james@536 2037 static NTSTATUS
james@536 2038 XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp)
james@536 2039 {
james@536 2040 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2041 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2042 PIO_STACK_LOCATION stack;
james@536 2043 PCM_PARTIAL_RESOURCE_LIST prl;
james@536 2044 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
james@536 2045 ULONG i;
james@551 2046 //char path[128];
james@551 2047 //PMDL mdl;
james@536 2048
james@536 2049 FUNCTION_ENTER();
james@536 2050 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
james@536 2051
james@536 2052 stack = IoGetCurrentIrpStackLocation(irp);
james@536 2053
james@536 2054 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
james@536 2055 for (i = 0; i < prl->Count; i++)
james@536 2056 {
james@536 2057 prd = & prl->PartialDescriptors[i];
james@536 2058 switch (prd->Type)
james@536 2059 {
james@536 2060 case CmResourceTypeMemory:
james@536 2061 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
james@536 2062 {
james@551 2063 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
james@551 2064 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
james@536 2065 }
james@536 2066 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
james@536 2067 {
james@536 2068 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@536 2069 prd->Type = CmResourceTypeInterrupt;
james@536 2070 prd->ShareDisposition = CmResourceShareShared;
james@536 2071 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
steve@621 2072 prd->u.Interrupt.Level = 0; // Set group and level to zero (group = upper word)
steve@621 2073 prd->u.Interrupt.Level = xpdd->irq_number & 0xffff; // Only set the lower word
james@536 2074 prd->u.Interrupt.Vector = xpdd->irq_number;
steve@621 2075 prd->u.Interrupt.Affinity = KeQueryActiveProcessors();
james@536 2076 xppdd->irq_number = xpdd->irq_number;
james@536 2077 }
james@536 2078 break;
james@536 2079 }
james@536 2080 }
james@536 2081
james@536 2082 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
james@536 2083 for (i = 0; i < prl->Count; i++)
james@536 2084 {
james@536 2085 prd = & prl->PartialDescriptors[i];
james@536 2086 switch (prd->Type)
james@536 2087 {
james@536 2088 case CmResourceTypeMemory:
james@536 2089 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
james@536 2090 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
james@536 2091 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
james@536 2092 {
james@536 2093 if (prd->u.Memory.Length == 0)
james@536 2094 {
james@551 2095 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0]));
james@551 2096 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
james@551 2097 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
james@536 2098 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 2099 }
james@536 2100 xppdd->config_page_phys = prd->u.Memory.Start;
james@536 2101 xppdd->config_page_length = prd->u.Memory.Length;
james@536 2102 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@634 2103 //xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@536 2104
james@551 2105 #if 0
james@536 2106 status = XenPci_XenConfigDevice(device);
james@536 2107 if (!NT_SUCCESS(status))
james@536 2108 {
james@536 2109 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@624 2110 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
james@536 2111 FUNCTION_ERROR_EXIT();
james@536 2112 return status;
james@536 2113 }
james@551 2114 #endif
james@536 2115 }
james@536 2116 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
james@536 2117 {
james@536 2118 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@536 2119 prd->Type = CmResourceTypeInterrupt;
james@536 2120 prd->ShareDisposition = CmResourceShareShared;
james@536 2121 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
steve@621 2122 prd->u.Interrupt.Level = 0; // Set group and level to zero (group = upper word)
steve@621 2123 prd->u.Interrupt.Level = xpdd->irq_level & 0xffff; // Only set the lower word
james@536 2124 prd->u.Interrupt.Vector = xpdd->irq_vector;
steve@621 2125 prd->u.Interrupt.Affinity = KeQueryActiveProcessors();
james@536 2126 xppdd->irq_vector = xpdd->irq_vector;
james@536 2127 xppdd->irq_level = xpdd->irq_level;
james@536 2128 }
james@536 2129 break;
james@536 2130 }
james@536 2131 }
james@536 2132
james@536 2133 IoSkipCurrentIrpStackLocation(irp);
james@536 2134
james@536 2135 FUNCTION_EXIT();
james@536 2136
james@536 2137 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
james@536 2138 }
james@536 2139
james@536 2140 #if 0
james@536 2141 static NTSTATUS
james@536 2142 XenPciPdo_EvtDeviceResourcesQuery(WDFDEVICE device, WDFCMRESLIST resources)
james@536 2143 {
james@536 2144 }
james@536 2145 #endif
james@536 2146
james@536 2147 static NTSTATUS
james@536 2148 XenPciPdo_EvtDeviceResourceRequirementsQuery(WDFDEVICE device, WDFIORESREQLIST requirements_list)
james@536 2149 {
james@536 2150 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2151 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2152 WDFIORESLIST res_list;
james@536 2153 IO_RESOURCE_DESCRIPTOR ird;
james@536 2154
james@538 2155 //FUNCTION_ENTER();
james@536 2156
james@536 2157 WdfIoResourceRequirementsListSetInterfaceType(requirements_list, PNPBus);
james@536 2158
james@536 2159 WdfIoResourceListCreate(requirements_list, WDF_NO_OBJECT_ATTRIBUTES, &res_list);
james@536 2160 ird.Option = 0;
james@536 2161 ird.Type = CmResourceTypeMemory;
james@536 2162 ird.ShareDisposition = CmResourceShareShared;
james@536 2163 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
james@536 2164 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
james@536 2165 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
james@536 2166 ird.u.Memory.Length = 0;
james@536 2167 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
james@536 2168 WdfIoResourceListAppendDescriptor(res_list, &ird);
james@536 2169
james@536 2170 ird.Option = 0;
james@536 2171 ird.Type = CmResourceTypeMemory;
james@536 2172 ird.ShareDisposition = CmResourceShareShared;
james@536 2173 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
james@536 2174 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
james@536 2175 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
james@536 2176 ird.u.Memory.Length = 0;
james@536 2177 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
james@536 2178 WdfIoResourceListAppendDescriptor(res_list, &ird);
james@536 2179
james@536 2180 WdfIoResourceRequirementsListAppendIoResList(requirements_list, res_list);
james@536 2181
james@538 2182 //FUNCTION_EXIT();
james@538 2183
james@538 2184 return STATUS_SUCCESS;
james@538 2185 }
james@538 2186
james@538 2187 NTSTATUS
james@538 2188 XenPciPdo_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
james@538 2189 {
james@538 2190 NTSTATUS status = STATUS_SUCCESS;
james@551 2191 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@551 2192 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@551 2193 CHAR path[128];
james@538 2194
james@538 2195 FUNCTION_ENTER();
james@538 2196
james@538 2197 switch (previous_state)
james@538 2198 {
james@538 2199 case WdfPowerDeviceD0:
james@538 2200 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 2201 break;
james@538 2202 case WdfPowerDeviceD1:
james@538 2203 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 2204 break;
james@538 2205 case WdfPowerDeviceD2:
james@538 2206 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
james@538 2207 break;
james@538 2208 case WdfPowerDeviceD3:
james@538 2209 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
james@538 2210 break;
james@538 2211 case WdfPowerDeviceD3Final:
james@538 2212 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
james@538 2213 break;
james@538 2214 case WdfPowerDevicePrepareForHibernation:
james@538 2215 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
james@538 2216 break;
james@538 2217 default:
james@538 2218 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
james@538 2219 break;
james@538 2220 }
james@634 2221
james@551 2222 if (previous_state == WdfPowerDevicePrepareForHibernation
james@551 2223 || (previous_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
james@551 2224 {
james@551 2225 KdPrint((__DRIVER_NAME " starting up from hibernation\n"));
james@551 2226 }
james@551 2227 else
james@551 2228 {
james@551 2229 }
james@551 2230
james@634 2231 if (previous_state == WdfPowerDevicePrepareForHibernation || previous_state == WdfPowerDeviceD3 || previous_state == WdfPowerDeviceD3Final)
james@634 2232 {
james@634 2233 xppdd->requested_resources_ptr = xppdd->requested_resources_start;
james@634 2234 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@634 2235 }
james@634 2236
james@551 2237 XenConfig_InitConfigPage(device);
james@551 2238
james@551 2239 status = XenPci_GetBackendAndAddWatch(device);
james@551 2240 if (!NT_SUCCESS(status))
james@551 2241 {
james@551 2242 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
james@551 2243 FUNCTION_ERROR_EXIT();
james@551 2244 return status;
james@551 2245 }
james@551 2246 status = XenPci_XenConfigDevice(device);
james@551 2247 if (!NT_SUCCESS(status))
james@551 2248 {
james@551 2249 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@624 2250 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
james@551 2251 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
james@551 2252 FUNCTION_ERROR_EXIT();
james@551 2253 return status;
james@551 2254 }
james@538 2255
james@536 2256 FUNCTION_EXIT();
james@536 2257
james@538 2258 return status;
james@538 2259 }
james@538 2260
james@538 2261 NTSTATUS
james@538 2262 XenPciPdo_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
james@538 2263 {
james@538 2264 NTSTATUS status = STATUS_SUCCESS;
james@538 2265 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@538 2266 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@538 2267 char path[128];
james@538 2268
james@538 2269 UNREFERENCED_PARAMETER(device);
james@538 2270 UNREFERENCED_PARAMETER(target_state);
james@538 2271
james@538 2272 FUNCTION_ENTER();
james@538 2273
james@538 2274 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@538 2275
james@538 2276
james@538 2277 switch (target_state)
james@538 2278 {
james@538 2279 case WdfPowerDeviceD0:
james@538 2280 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 2281 break;
james@538 2282 case WdfPowerDeviceD1:
james@538 2283 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 2284 break;
james@538 2285 case WdfPowerDeviceD2:
james@538 2286 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
james@538 2287 break;
james@538 2288 case WdfPowerDeviceD3:
james@538 2289 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
james@538 2290 break;
james@538 2291 case WdfPowerDeviceD3Final:
james@538 2292 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
james@538 2293 break;
james@538 2294 case WdfPowerDevicePrepareForHibernation:
james@538 2295 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
james@538 2296 break;
james@538 2297 default:
james@538 2298 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
james@538 2299 break;
james@538 2300 }
james@617 2301
james@538 2302 if (target_state == WdfPowerDevicePrepareForHibernation
james@538 2303 || (target_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
james@538 2304 {
james@538 2305 KdPrint((__DRIVER_NAME " not powering down as we are hibernating\n"));
james@538 2306 }
james@538 2307 else
james@538 2308 {
james@538 2309 status = XenPci_XenShutdownDevice(device);
james@538 2310 }
amir@679 2311
amir@679 2312 /* Remove watch on backend state */
amir@679 2313 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
amir@679 2314 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
amir@679 2315
james@538 2316 FUNCTION_EXIT();
james@538 2317
james@538 2318 return status;
james@538 2319 }
james@538 2320
james@538 2321 NTSTATUS
james@551 2322 XenPciPdo_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
james@538 2323 {
james@538 2324 NTSTATUS status = STATUS_SUCCESS;
james@551 2325
james@538 2326 UNREFERENCED_PARAMETER(device);
james@538 2327 UNREFERENCED_PARAMETER(resources_raw);
james@538 2328 UNREFERENCED_PARAMETER(resources_translated);
james@538 2329
james@538 2330 FUNCTION_ENTER();
james@538 2331 FUNCTION_EXIT();
james@538 2332
james@538 2333 return status;
james@538 2334 }
james@538 2335
james@538 2336 NTSTATUS
james@538 2337 XenPciPdo_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
james@538 2338 {
james@538 2339 NTSTATUS status = STATUS_SUCCESS;
james@538 2340
james@538 2341 UNREFERENCED_PARAMETER(device);
james@538 2342 UNREFERENCED_PARAMETER(resources_translated);
james@538 2343
james@538 2344 FUNCTION_ENTER();
james@538 2345 FUNCTION_EXIT();
james@538 2346
james@538 2347 return status;
james@538 2348 }
james@538 2349
james@538 2350 static VOID
james@538 2351 XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
james@538 2352 {
james@538 2353 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@538 2354
james@538 2355 FUNCTION_ENTER();
james@538 2356
james@538 2357 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@538 2358 switch (notification_type)
james@538 2359 {
james@538 2360 case WdfSpecialFilePaging:
james@538 2361 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
james@538 2362 break;
james@538 2363 case WdfSpecialFileHibernation:
james@538 2364 xppdd->hiber_usage_kludge = is_in_notification_path;
james@538 2365 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
james@538 2366 break;
james@538 2367 case WdfSpecialFileDump:
james@538 2368 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
james@538 2369 break;
james@538 2370 default:
james@538 2371 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
james@538 2372 break;
james@538 2373 }
james@538 2374
james@538 2375 FUNCTION_EXIT();
james@536 2376 }
james@536 2377
james@536 2378 NTSTATUS
james@536 2379 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
james@536 2380 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
james@536 2381 PWDFDEVICE_INIT child_init)
james@536 2382 {
james@536 2383 NTSTATUS status = STATUS_SUCCESS;
james@536 2384 WDF_OBJECT_ATTRIBUTES child_attributes;
james@536 2385 WDFDEVICE child_device;
james@536 2386 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
james@536 2387 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
james@536 2388 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
james@536 2389 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
james@536 2390 PXENPCI_PDO_DEVICE_DATA xppdd;
james@536 2391 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
james@536 2392 WDF_QUERY_INTERFACE_CONFIG interface_config;
james@536 2393 BUS_INTERFACE_STANDARD bus_interface;
james@536 2394 WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
james@538 2395 WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
james@536 2396 UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
james@538 2397 WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
james@536 2398
james@536 2399 FUNCTION_ENTER();
james@536 2400
james@536 2401 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
james@536 2402
james@536 2403 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
james@536 2404 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
james@538 2405 //child_pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPciPdo_EvtDeviceD0EntryPostInterruptsEnabled;
james@536 2406 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
james@538 2407 //child_pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPciPdo_EvtDeviceD0ExitPreInterruptsDisabled;
james@536 2408 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenPciPdo_EvtDevicePrepareHardware;
james@536 2409 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenPciPdo_EvtDeviceReleaseHardware;
james@538 2410 child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
james@536 2411 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
james@538 2412
james@536 2413 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
james@536 2414 identification->device, identification->index, identification->path));
james@536 2415
james@536 2416 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
james@536 2417 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
james@536 2418 if (!NT_SUCCESS(status))
james@536 2419 {
james@536 2420 return status;
james@536 2421 }
james@536 2422
james@536 2423 WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
james@536 2424 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
james@536 2425 pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
james@536 2426 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
james@536 2427 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
james@536 2428 WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
james@536 2429
james@536 2430 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
james@536 2431 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
james@536 2432 if (!NT_SUCCESS(status))
james@536 2433 {
james@536 2434 return status;
james@536 2435 }
james@536 2436 status = WdfPdoInitAddHardwareID(child_init, &buffer);
james@536 2437 if (!NT_SUCCESS(status))
james@536 2438 {
james@536 2439 return status;
james@536 2440 }
james@536 2441 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
james@536 2442 if (!NT_SUCCESS(status))
james@536 2443 {
james@536 2444 return status;
james@536 2445 }
james@536 2446
james@536 2447 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
james@536 2448 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
james@536 2449 if (!NT_SUCCESS(status))
james@536 2450 {
james@536 2451 return status;
james@536 2452 }
james@536 2453
james@536 2454 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
james@536 2455 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
james@536 2456 if (!NT_SUCCESS(status))
james@536 2457 {
james@536 2458 return status;
james@536 2459 }
james@536 2460 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
james@538 2461
james@538 2462 WdfDeviceInitSetPowerNotPageable(child_init);
james@536 2463
james@536 2464 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
james@536 2465 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
james@536 2466 if (!NT_SUCCESS(status))
james@536 2467 {
james@536 2468 return status;
james@536 2469 }
james@536 2470
james@536 2471 xppdd = GetXppdd(child_device);
james@536 2472
james@536 2473 xppdd->wdf_device = child_device;
james@536 2474 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
james@536 2475
james@551 2476 xppdd->config_page_mdl = AllocateUncachedPage();
james@551 2477
james@536 2478 xppdd->device_state.magic = XEN_DEVICE_STATE_MAGIC;
james@536 2479 xppdd->device_state.length = sizeof(XENPCI_DEVICE_STATE);
james@536 2480 xppdd->device_state.suspend_resume_state_pdo = SR_STATE_RUNNING;
james@536 2481 xppdd->device_state.suspend_resume_state_fdo = SR_STATE_RUNNING;
james@536 2482 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
james@536 2483 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
james@536 2484 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
james@536 2485 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
james@536 2486
james@536 2487 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
james@536 2488 child_pnp_capabilities.LockSupported = WdfFalse;
james@536 2489 child_pnp_capabilities.EjectSupported = WdfTrue;
james@536 2490 child_pnp_capabilities.Removable = WdfTrue;
james@536 2491 child_pnp_capabilities.DockDevice = WdfFalse;
james@536 2492 child_pnp_capabilities.UniqueID = WdfFalse;
james@536 2493 child_pnp_capabilities.SilentInstall = WdfTrue;
james@536 2494 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
james@536 2495 child_pnp_capabilities.HardwareDisabled = WdfFalse;
james@536 2496 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
james@536 2497
james@538 2498 WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
james@538 2499 child_power_capabilities.DeviceD1 = WdfTrue;
james@538 2500 child_power_capabilities.WakeFromD1 = WdfTrue;
james@538 2501 child_power_capabilities.DeviceWake = PowerDeviceD1;
james@538 2502 child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
james@538 2503 child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
james@538 2504 child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
james@538 2505 child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
james@538 2506 child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
james@538 2507 child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
james@538 2508 WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
james@536 2509
james@536 2510 bus_interface.Size = sizeof(BUS_INTERFACE_STANDARD);
james@536 2511 bus_interface.Version = 1; //BUS_INTERFACE_STANDARD_VERSION;
james@536 2512 bus_interface.Context = xppdd;
james@537 2513 bus_interface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
james@537 2514 bus_interface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
james@536 2515 bus_interface.TranslateBusAddress = XenPci_BIS_TranslateBusAddress;
james@536 2516 bus_interface.GetDmaAdapter = XenPci_BIS_GetDmaAdapter;
james@536 2517 bus_interface.SetBusData = XenPci_BIS_SetBusData;
james@536 2518 bus_interface.GetBusData = XenPci_BIS_GetBusData;
james@536 2519 WDF_QUERY_INTERFACE_CONFIG_INIT(&interface_config, (PINTERFACE)&bus_interface, &GUID_BUS_INTERFACE_STANDARD, NULL);
james@536 2520 status = WdfDeviceAddQueryInterface(child_device, &interface_config);
james@536 2521 if (!NT_SUCCESS(status))
james@536 2522 {
james@536 2523 return status;
james@536 2524 }
james@536 2525
james@536 2526 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
james@536 2527 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
james@536 2528 xppdd->index = identification->index;
james@536 2529 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
james@624 2530 ExInitializeFastMutex(&xppdd->backend_state_mutex);
james@536 2531 xppdd->backend_state = XenbusStateUnknown;
james@538 2532 xppdd->frontend_state = XenbusStateUnknown;
james@536 2533 xppdd->backend_path[0] = '\0';
james@536 2534
james@536 2535 FUNCTION_EXIT();
james@536 2536
james@536 2537 return status;
james@536 2538 }
james@536 2539
james@536 2540 static __forceinline VOID
james@536 2541 XenPci_Pdo_ChangeSuspendState(WDFDEVICE device, ULONG new_state)
james@536 2542 {
james@536 2543 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2544 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2545
james@536 2546 FUNCTION_ENTER();
james@536 2547 KdPrint((__DRIVER_NAME " setting pdo state to %d\n", new_state));
james@536 2548 xppdd->device_state.suspend_resume_state_pdo = new_state;
james@536 2549 KeMemoryBarrier();
james@536 2550 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xpdd->pdo_event_channel));
james@536 2551 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
james@536 2552 while(xppdd->device_state.suspend_resume_state_fdo != xppdd->device_state.suspend_resume_state_pdo)
james@536 2553 {
james@536 2554 KdPrint((__DRIVER_NAME " waiting...\n"));
james@536 2555 KeWaitForSingleObject(&xpdd->pdo_suspend_event, Executive, KernelMode, FALSE, NULL);
james@536 2556 }
james@536 2557 KdPrint((__DRIVER_NAME " fdo state set to %d\n", new_state));
james@536 2558 FUNCTION_EXIT();
james@536 2559 }
james@536 2560
james@536 2561 /* called at PASSIVE_LEVEL */
james@536 2562 NTSTATUS
james@536 2563 XenPci_Pdo_Suspend(WDFDEVICE device)
james@536 2564 {
james@536 2565 NTSTATUS status = STATUS_SUCCESS;
james@536 2566 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2567 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2568 //LARGE_INTEGER wait_time;
james@536 2569 char path[128];
james@536 2570 PUCHAR in_ptr;
james@536 2571 UCHAR type;
james@536 2572 PVOID setting;
james@536 2573 PVOID value;
james@536 2574 PVOID value2;
james@536 2575
james@536 2576 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
james@536 2577
james@536 2578 if (xppdd->backend_state == XenbusStateConnected)
james@536 2579 {
james@536 2580 xppdd->restart_on_resume = TRUE;
james@536 2581 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_SUSPENDING);
james@536 2582
james@536 2583 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
james@536 2584 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
james@536 2585 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
james@536 2586
james@536 2587 if (xppdd->assigned_resources_start != NULL)
james@536 2588 {
james@536 2589 in_ptr = xppdd->assigned_resources_ptr;
james@536 2590 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 2591 in_ptr = xppdd->assigned_resources_start;
james@536 2592 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
james@536 2593 {
james@536 2594 switch (type)
james@536 2595 {
james@536 2596 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@617 2597 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
james@536 2598 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 2599 EvtChn_Unbind(xpdd, PtrToUlong(value));
james@536 2600 EvtChn_Close(xpdd, PtrToUlong(value));
james@536 2601 break;
james@536 2602 }
james@536 2603 }
james@536 2604 }
james@536 2605
james@536 2606 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@624 2607 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, xppdd);
james@536 2608 }
james@536 2609 else
james@536 2610 {
james@536 2611 xppdd->restart_on_resume = FALSE;
james@536 2612 }
james@536 2613
james@536 2614 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@536 2615
james@536 2616 return status;
james@536 2617 }
james@536 2618
james@536 2619 NTSTATUS
james@536 2620 XenPci_Pdo_Resume(WDFDEVICE device)
james@536 2621 {
james@536 2622 NTSTATUS status = STATUS_SUCCESS;
james@536 2623 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2624 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2625 ULONG old_backend_state;
james@536 2626 PUCHAR src, dst;
james@536 2627
james@536 2628 FUNCTION_ENTER();
james@536 2629 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@536 2630
james@536 2631 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
james@536 2632 old_backend_state = xppdd->backend_state;
james@536 2633
james@536 2634 if (xppdd->restart_on_resume)
james@536 2635 {
james@536 2636 status = XenPci_GetBackendAndAddWatch(device);
james@536 2637
james@536 2638 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
james@536 2639 {
james@536 2640 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
james@536 2641 // this is probably an unrecoverable situation...
james@536 2642 FUNCTION_ERROR_EXIT();
james@536 2643 return STATUS_UNSUCCESSFUL;
james@536 2644 }
james@536 2645 if (xppdd->assigned_resources_ptr)
james@536 2646 {
james@536 2647 // reset things - feed the 'requested resources' back in
james@536 2648 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 2649 src = xppdd->requested_resources_start;
james@536 2650 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
james@536 2651 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
james@536 2652
james@536 2653 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
james@536 2654
james@536 2655 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
james@536 2656
james@536 2657 MmUnmapIoSpace(dst, xppdd->config_page_length);
james@536 2658 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
james@536 2659 }
james@536 2660 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
james@536 2661 {
james@536 2662 // this is definitely an unrecoverable situation...
james@536 2663 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
james@536 2664 FUNCTION_ERROR_EXIT();
james@536 2665 return STATUS_UNSUCCESSFUL;
james@536 2666 }
james@536 2667 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RESUMING);
james@536 2668 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RUNNING);
james@536 2669 }
james@536 2670
james@536 2671 FUNCTION_EXIT();
james@536 2672
james@536 2673 return STATUS_SUCCESS;
james@536 2674 }