win-pvdrivers

annotate xenpci/xenpci_pdo.c @ 634:743b1f6470d8

fix config page overflow after multiple hibernations
author James Harper <james.harper@bendigoit.com.au>
date Wed Aug 19 16:50:33 2009 +1000 (2009-08-19)
parents 0b55299418ce
children 6a160c1ad6e7
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@600 626 if (MmGetMdlVirtualAddress(Mdl) != CurrentVa)
james@600 627 {
james@600 628 KdPrint((__DRIVER_NAME " MmGetMdlVirtualAddress = %p, CurrentVa = %p, Length = %d\n", MmGetMdlVirtualAddress(Mdl), CurrentVa, Length));
james@600 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@600 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@600 698 if (active)
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@600 737 if (active)
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@536 822 sglist->Elements[0].Address.QuadPart = (ULONGLONG)ptr;
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 /* Remove watch on backend state */
james@538 2311 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@624 2312 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
james@538 2313 }
james@538 2314 FUNCTION_EXIT();
james@538 2315
james@538 2316 return status;
james@538 2317 }
james@538 2318
james@538 2319 NTSTATUS
james@551 2320 XenPciPdo_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
james@538 2321 {
james@538 2322 NTSTATUS status = STATUS_SUCCESS;
james@551 2323
james@538 2324 UNREFERENCED_PARAMETER(device);
james@538 2325 UNREFERENCED_PARAMETER(resources_raw);
james@538 2326 UNREFERENCED_PARAMETER(resources_translated);
james@538 2327
james@538 2328 FUNCTION_ENTER();
james@538 2329 FUNCTION_EXIT();
james@538 2330
james@538 2331 return status;
james@538 2332 }
james@538 2333
james@538 2334 NTSTATUS
james@538 2335 XenPciPdo_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
james@538 2336 {
james@538 2337 NTSTATUS status = STATUS_SUCCESS;
james@538 2338
james@538 2339 UNREFERENCED_PARAMETER(device);
james@538 2340 UNREFERENCED_PARAMETER(resources_translated);
james@538 2341
james@538 2342 FUNCTION_ENTER();
james@538 2343 FUNCTION_EXIT();
james@538 2344
james@538 2345 return status;
james@538 2346 }
james@538 2347
james@538 2348 static VOID
james@538 2349 XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
james@538 2350 {
james@538 2351 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@538 2352
james@538 2353 FUNCTION_ENTER();
james@538 2354
james@538 2355 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@538 2356 switch (notification_type)
james@538 2357 {
james@538 2358 case WdfSpecialFilePaging:
james@538 2359 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
james@538 2360 break;
james@538 2361 case WdfSpecialFileHibernation:
james@538 2362 xppdd->hiber_usage_kludge = is_in_notification_path;
james@538 2363 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
james@538 2364 break;
james@538 2365 case WdfSpecialFileDump:
james@538 2366 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
james@538 2367 break;
james@538 2368 default:
james@538 2369 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
james@538 2370 break;
james@538 2371 }
james@538 2372
james@538 2373 FUNCTION_EXIT();
james@536 2374 }
james@536 2375
james@536 2376 NTSTATUS
james@536 2377 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
james@536 2378 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
james@536 2379 PWDFDEVICE_INIT child_init)
james@536 2380 {
james@536 2381 NTSTATUS status = STATUS_SUCCESS;
james@536 2382 WDF_OBJECT_ATTRIBUTES child_attributes;
james@536 2383 WDFDEVICE child_device;
james@536 2384 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
james@536 2385 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
james@536 2386 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
james@536 2387 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
james@536 2388 PXENPCI_PDO_DEVICE_DATA xppdd;
james@536 2389 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
james@536 2390 WDF_QUERY_INTERFACE_CONFIG interface_config;
james@536 2391 BUS_INTERFACE_STANDARD bus_interface;
james@536 2392 WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
james@538 2393 WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
james@536 2394 UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
james@538 2395 WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
james@536 2396
james@536 2397 FUNCTION_ENTER();
james@536 2398
james@536 2399 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
james@536 2400
james@536 2401 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
james@536 2402 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
james@538 2403 //child_pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPciPdo_EvtDeviceD0EntryPostInterruptsEnabled;
james@536 2404 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
james@538 2405 //child_pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPciPdo_EvtDeviceD0ExitPreInterruptsDisabled;
james@536 2406 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenPciPdo_EvtDevicePrepareHardware;
james@536 2407 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenPciPdo_EvtDeviceReleaseHardware;
james@538 2408 child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
james@536 2409 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
james@538 2410
james@536 2411 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
james@536 2412 identification->device, identification->index, identification->path));
james@536 2413
james@536 2414 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
james@536 2415 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
james@536 2416 if (!NT_SUCCESS(status))
james@536 2417 {
james@536 2418 return status;
james@536 2419 }
james@536 2420
james@536 2421 WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
james@536 2422 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
james@536 2423 pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
james@536 2424 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
james@536 2425 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
james@536 2426 WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
james@536 2427
james@536 2428 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
james@536 2429 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
james@536 2430 if (!NT_SUCCESS(status))
james@536 2431 {
james@536 2432 return status;
james@536 2433 }
james@536 2434 status = WdfPdoInitAddHardwareID(child_init, &buffer);
james@536 2435 if (!NT_SUCCESS(status))
james@536 2436 {
james@536 2437 return status;
james@536 2438 }
james@536 2439 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
james@536 2440 if (!NT_SUCCESS(status))
james@536 2441 {
james@536 2442 return status;
james@536 2443 }
james@536 2444
james@536 2445 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
james@536 2446 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
james@536 2447 if (!NT_SUCCESS(status))
james@536 2448 {
james@536 2449 return status;
james@536 2450 }
james@536 2451
james@536 2452 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
james@536 2453 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
james@536 2454 if (!NT_SUCCESS(status))
james@536 2455 {
james@536 2456 return status;
james@536 2457 }
james@536 2458 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
james@538 2459
james@538 2460 WdfDeviceInitSetPowerNotPageable(child_init);
james@536 2461
james@536 2462 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
james@536 2463 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
james@536 2464 if (!NT_SUCCESS(status))
james@536 2465 {
james@536 2466 return status;
james@536 2467 }
james@536 2468
james@536 2469 xppdd = GetXppdd(child_device);
james@536 2470
james@536 2471 xppdd->wdf_device = child_device;
james@536 2472 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
james@536 2473
james@551 2474 xppdd->config_page_mdl = AllocateUncachedPage();
james@551 2475
james@536 2476 xppdd->device_state.magic = XEN_DEVICE_STATE_MAGIC;
james@536 2477 xppdd->device_state.length = sizeof(XENPCI_DEVICE_STATE);
james@536 2478 xppdd->device_state.suspend_resume_state_pdo = SR_STATE_RUNNING;
james@536 2479 xppdd->device_state.suspend_resume_state_fdo = SR_STATE_RUNNING;
james@536 2480 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
james@536 2481 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
james@536 2482 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
james@536 2483 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
james@536 2484
james@536 2485 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
james@536 2486 child_pnp_capabilities.LockSupported = WdfFalse;
james@536 2487 child_pnp_capabilities.EjectSupported = WdfTrue;
james@536 2488 child_pnp_capabilities.Removable = WdfTrue;
james@536 2489 child_pnp_capabilities.DockDevice = WdfFalse;
james@536 2490 child_pnp_capabilities.UniqueID = WdfFalse;
james@536 2491 child_pnp_capabilities.SilentInstall = WdfTrue;
james@536 2492 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
james@536 2493 child_pnp_capabilities.HardwareDisabled = WdfFalse;
james@536 2494 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
james@536 2495
james@538 2496 WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
james@538 2497 child_power_capabilities.DeviceD1 = WdfTrue;
james@538 2498 child_power_capabilities.WakeFromD1 = WdfTrue;
james@538 2499 child_power_capabilities.DeviceWake = PowerDeviceD1;
james@538 2500 child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
james@538 2501 child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
james@538 2502 child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
james@538 2503 child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
james@538 2504 child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
james@538 2505 child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
james@538 2506 WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
james@536 2507
james@536 2508 bus_interface.Size = sizeof(BUS_INTERFACE_STANDARD);
james@536 2509 bus_interface.Version = 1; //BUS_INTERFACE_STANDARD_VERSION;
james@536 2510 bus_interface.Context = xppdd;
james@537 2511 bus_interface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
james@537 2512 bus_interface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
james@536 2513 bus_interface.TranslateBusAddress = XenPci_BIS_TranslateBusAddress;
james@536 2514 bus_interface.GetDmaAdapter = XenPci_BIS_GetDmaAdapter;
james@536 2515 bus_interface.SetBusData = XenPci_BIS_SetBusData;
james@536 2516 bus_interface.GetBusData = XenPci_BIS_GetBusData;
james@536 2517 WDF_QUERY_INTERFACE_CONFIG_INIT(&interface_config, (PINTERFACE)&bus_interface, &GUID_BUS_INTERFACE_STANDARD, NULL);
james@536 2518 status = WdfDeviceAddQueryInterface(child_device, &interface_config);
james@536 2519 if (!NT_SUCCESS(status))
james@536 2520 {
james@536 2521 return status;
james@536 2522 }
james@536 2523
james@536 2524 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
james@536 2525 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
james@536 2526 xppdd->index = identification->index;
james@536 2527 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
james@624 2528 ExInitializeFastMutex(&xppdd->backend_state_mutex);
james@536 2529 xppdd->backend_state = XenbusStateUnknown;
james@538 2530 xppdd->frontend_state = XenbusStateUnknown;
james@536 2531 xppdd->backend_path[0] = '\0';
james@536 2532
james@536 2533 FUNCTION_EXIT();
james@536 2534
james@536 2535 return status;
james@536 2536 }
james@536 2537
james@536 2538 static __forceinline VOID
james@536 2539 XenPci_Pdo_ChangeSuspendState(WDFDEVICE device, ULONG new_state)
james@536 2540 {
james@536 2541 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2542 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2543
james@536 2544 FUNCTION_ENTER();
james@536 2545 KdPrint((__DRIVER_NAME " setting pdo state to %d\n", new_state));
james@536 2546 xppdd->device_state.suspend_resume_state_pdo = new_state;
james@536 2547 KeMemoryBarrier();
james@536 2548 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xpdd->pdo_event_channel));
james@536 2549 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
james@536 2550 while(xppdd->device_state.suspend_resume_state_fdo != xppdd->device_state.suspend_resume_state_pdo)
james@536 2551 {
james@536 2552 KdPrint((__DRIVER_NAME " waiting...\n"));
james@536 2553 KeWaitForSingleObject(&xpdd->pdo_suspend_event, Executive, KernelMode, FALSE, NULL);
james@536 2554 }
james@536 2555 KdPrint((__DRIVER_NAME " fdo state set to %d\n", new_state));
james@536 2556 FUNCTION_EXIT();
james@536 2557 }
james@536 2558
james@536 2559 /* called at PASSIVE_LEVEL */
james@536 2560 NTSTATUS
james@536 2561 XenPci_Pdo_Suspend(WDFDEVICE device)
james@536 2562 {
james@536 2563 NTSTATUS status = STATUS_SUCCESS;
james@536 2564 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2565 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2566 //LARGE_INTEGER wait_time;
james@536 2567 char path[128];
james@536 2568 PUCHAR in_ptr;
james@536 2569 UCHAR type;
james@536 2570 PVOID setting;
james@536 2571 PVOID value;
james@536 2572 PVOID value2;
james@536 2573
james@536 2574 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
james@536 2575
james@536 2576 if (xppdd->backend_state == XenbusStateConnected)
james@536 2577 {
james@536 2578 xppdd->restart_on_resume = TRUE;
james@536 2579 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_SUSPENDING);
james@536 2580
james@536 2581 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
james@536 2582 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
james@536 2583 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
james@536 2584
james@536 2585 if (xppdd->assigned_resources_start != NULL)
james@536 2586 {
james@536 2587 in_ptr = xppdd->assigned_resources_ptr;
james@536 2588 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 2589 in_ptr = xppdd->assigned_resources_start;
james@536 2590 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
james@536 2591 {
james@536 2592 switch (type)
james@536 2593 {
james@536 2594 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@617 2595 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
james@536 2596 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 2597 EvtChn_Unbind(xpdd, PtrToUlong(value));
james@536 2598 EvtChn_Close(xpdd, PtrToUlong(value));
james@536 2599 break;
james@536 2600 }
james@536 2601 }
james@536 2602 }
james@536 2603
james@536 2604 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@624 2605 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, xppdd);
james@536 2606 }
james@536 2607 else
james@536 2608 {
james@536 2609 xppdd->restart_on_resume = FALSE;
james@536 2610 }
james@536 2611
james@536 2612 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@536 2613
james@536 2614 return status;
james@536 2615 }
james@536 2616
james@536 2617 NTSTATUS
james@536 2618 XenPci_Pdo_Resume(WDFDEVICE device)
james@536 2619 {
james@536 2620 NTSTATUS status = STATUS_SUCCESS;
james@536 2621 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2622 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2623 ULONG old_backend_state;
james@536 2624 PUCHAR src, dst;
james@536 2625
james@536 2626 FUNCTION_ENTER();
james@536 2627 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@536 2628
james@536 2629 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
james@536 2630 old_backend_state = xppdd->backend_state;
james@536 2631
james@536 2632 if (xppdd->restart_on_resume)
james@536 2633 {
james@536 2634 status = XenPci_GetBackendAndAddWatch(device);
james@536 2635
james@536 2636 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
james@536 2637 {
james@536 2638 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
james@536 2639 // this is probably an unrecoverable situation...
james@536 2640 FUNCTION_ERROR_EXIT();
james@536 2641 return STATUS_UNSUCCESSFUL;
james@536 2642 }
james@536 2643 if (xppdd->assigned_resources_ptr)
james@536 2644 {
james@536 2645 // reset things - feed the 'requested resources' back in
james@536 2646 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 2647 src = xppdd->requested_resources_start;
james@536 2648 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
james@536 2649 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
james@536 2650
james@536 2651 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
james@536 2652
james@536 2653 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
james@536 2654
james@536 2655 MmUnmapIoSpace(dst, xppdd->config_page_length);
james@536 2656 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
james@536 2657 }
james@536 2658 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
james@536 2659 {
james@536 2660 // this is definitely an unrecoverable situation...
james@536 2661 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
james@536 2662 FUNCTION_ERROR_EXIT();
james@536 2663 return STATUS_UNSUCCESSFUL;
james@536 2664 }
james@536 2665 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RESUMING);
james@536 2666 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RUNNING);
james@536 2667 }
james@536 2668
james@536 2669 FUNCTION_EXIT();
james@536 2670
james@536 2671 return STATUS_SUCCESS;
james@536 2672 }