win-pvdrivers

annotate xenpci/xenpci_pdo.c @ 617:1478103c6ef5

Added DPC call in config page and Reconfiguring callback
author James Harper <james.harper@bendigoit.com.au>
date Sun Jul 26 23:06:45 2009 +1000 (2009-07-26)
parents 227085ff4ffd
children 9c7b7fbacd7f
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 if (!curr_mdl)
james@612 688 {
james@612 689 KdPrint((__DRIVER_NAME " CurrentVa = %p, Length = %d\n", CurrentVa, Length));
james@612 690 for (curr_mdl = Mdl; curr_mdl; curr_mdl = curr_mdl->Next)
james@612 691 {
james@612 692 KdPrint((__DRIVER_NAME " Mdl = %p, VirtualAddress = %p, ByteCount = %d\n", Mdl, MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)));
james@612 693 }
james@612 694 }
james@612 695 ASSERT(curr_mdl);
james@600 696 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
james@600 697 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
james@612 698 /* need to use <= va + len - 1 to avoid ptr wraparound */
james@612 699 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
james@600 700 {
james@600 701 active = TRUE;
james@612 702 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
james@600 703 mdl_start_va = CurrentVa;
james@600 704 }
james@612 705 mdl_byte_count = min(mdl_byte_count, total_remaining);
james@600 706 if (active)
james@600 707 {
james@600 708 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
james@612 709 mdl_start_va, mdl_byte_count);
james@612 710 total_remaining -= mdl_byte_count;
james@600 711 }
james@600 712 }
james@536 713 }
james@536 714 if (ScatterGatherBufferLength < FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
james@536 715 sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t))
james@536 716 {
james@561 717 //KdPrint((__DRIVER_NAME " STATUS_BUFFER_TOO_SMALL (%d < %d)\n", ScatterGatherBufferLength, FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
james@561 718 // sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t)));
james@536 719 return STATUS_BUFFER_TOO_SMALL;
james@536 720 }
james@536 721
james@536 722 sg_extra = (sg_extra_t *)((PUCHAR)sglist + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
james@536 723 (sizeof(SCATTER_GATHER_ELEMENT)) * sglist->NumberOfElements);
james@558 724
james@558 725 sg_extra->allocated_by_me = allocated_by_me;
james@536 726
james@536 727 sg_extra->map_type = map_type;
james@536 728 switch (map_type)
james@536 729 {
james@536 730 case MAP_TYPE_MDL:
james@537 731 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL - %p\n", MmGetMdlVirtualAddress(Mdl)));
james@536 732 total_remaining = Length;
james@612 733 for (sg_element = 0, curr_mdl = Mdl, active = FALSE; total_remaining > 0; curr_mdl = curr_mdl->Next)
james@536 734 {
james@612 735 ASSERT(curr_mdl);
james@600 736 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
james@600 737 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
james@612 738 /* need to use <= va + len - 1 to avoid ptr wraparound */
james@612 739 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
james@536 740 {
james@600 741 active = TRUE;
james@612 742 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
james@600 743 mdl_start_va = CurrentVa;
james@600 744 }
james@600 745 if (active)
james@600 746 {
james@600 747 ULONG pfn_offset;
james@612 748 remaining = min(mdl_byte_count, total_remaining);
james@612 749 offset = (ULONG)((UINT_PTR)mdl_start_va & (PAGE_SIZE - 1));
james@612 750 pfn_offset = (ULONG)(((UINT_PTR)mdl_start_va >> PAGE_SHIFT) - ((UINT_PTR)MmGetMdlVirtualAddress(curr_mdl) >> PAGE_SHIFT));
james@612 751 //for (i = 0; i < ADDRESS_AND_SIZE_TO_SPAN_PAGES(mdl_start_va, mdl_byte_count); i++)
james@612 752 for (i = 0; remaining > 0; i++)
james@600 753 {
james@600 754 pfn = MmGetMdlPfnArray(curr_mdl)[pfn_offset + i];
james@600 755 ASSERT(pfn);
james@600 756 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
james@600 757 ASSERT(gref != INVALID_GRANT_REF);
james@600 758 sglist->Elements[sg_element].Address.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | offset;
james@600 759 sglist->Elements[sg_element].Length = min(min(PAGE_SIZE - offset, remaining), total_remaining);
james@600 760 total_remaining -= sglist->Elements[sg_element].Length;
james@600 761 remaining -= sglist->Elements[sg_element].Length;
james@600 762 offset = 0;
james@600 763 sg_element++;
james@600 764 }
james@536 765 }
james@536 766 }
james@612 767 if (sg_element != sglist->NumberOfElements)
james@612 768 {
james@612 769 KdPrint((__DRIVER_NAME " sg_element = %d, sglist->NumberOfElements = %d\n", sg_element, sglist->NumberOfElements));
james@612 770 KdPrint((__DRIVER_NAME " CurrentVa = %p, Length = %d\n", CurrentVa, Length));
james@612 771 for (curr_mdl = Mdl; curr_mdl; curr_mdl = curr_mdl->Next)
james@612 772 {
james@612 773 KdPrint((__DRIVER_NAME " Mdl = %p, VirtualAddress = %p, ByteCount = %d\n", Mdl, MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)));
james@612 774 }
james@612 775 }
james@612 776 ASSERT(sg_element == sglist->NumberOfElements);
james@536 777 break;
james@536 778 case MAP_TYPE_REMAPPED:
james@600 779 sg_extra->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, max(remapped_bytes, PAGE_SIZE), XENPCI_POOL_TAG);
james@536 780 if (!sg_extra->aligned_buffer)
james@536 781 {
james@600 782 KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED buffer allocation failed - requested va = %p, length = %d\n", MmGetMdlVirtualAddress(Mdl), remapped_bytes));
james@536 783 return STATUS_INSUFFICIENT_RESOURCES;
james@536 784 }
james@612 785 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED - %p\n", sg_extra->aligned_buffer));
james@600 786 sg_extra->mdl = Mdl;
james@600 787 sg_extra->currentva = CurrentVa;
james@600 788 sg_extra->copy_length = remapped_bytes;
james@600 789
james@536 790 if (WriteToDevice)
james@600 791 {
james@600 792 for (curr_mdl = Mdl, offset = 0, active = FALSE; curr_mdl; curr_mdl = curr_mdl->Next)
james@600 793 {
james@600 794 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
james@600 795 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
james@600 796 mdl_offset = 0;
james@612 797 /* need to use <= va + len - 1 to avoid ptr wraparound */
james@612 798 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
james@600 799 {
james@600 800 active = TRUE;
james@612 801 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
james@612 802 mdl_offset = (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
james@600 803 mdl_start_va = CurrentVa;
james@600 804 }
james@600 805 if (active)
james@600 806 {
james@600 807 PVOID unaligned_buffer;
james@600 808 unaligned_buffer = (PUCHAR)MmGetSystemAddressForMdlSafe(curr_mdl, NormalPagePriority);
james@600 809 ASSERT(unaligned_buffer); /* lazy */
james@600 810 memcpy((PUCHAR)sg_extra->aligned_buffer + offset, (PUCHAR)unaligned_buffer + mdl_offset, mdl_byte_count);
james@600 811 offset += mdl_byte_count;
james@600 812 }
james@600 813 }
james@600 814 }
james@600 815 for (sg_element = 0, remaining = remapped_bytes;
james@600 816 sg_element < ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_extra->aligned_buffer, remapped_bytes); sg_element++)
james@536 817 {
james@536 818 pfn = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)sg_extra->aligned_buffer + (sg_element << PAGE_SHIFT)).QuadPart >> PAGE_SHIFT);
james@536 819 ASSERT(pfn);
james@537 820 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
james@600 821 ASSERT(gref != INVALID_GRANT_REF);
james@536 822 sglist->Elements[sg_element].Address.QuadPart = (ULONGLONG)gref << PAGE_SHIFT;
james@536 823 sglist->Elements[sg_element].Length = min(PAGE_SIZE, remaining);
james@536 824 remaining -= sglist->Elements[sg_element].Length;
james@536 825 }
james@536 826 break;
james@536 827 case MAP_TYPE_VIRTUAL:
james@536 828 ptr = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
james@536 829 ASSERT(ptr); /* lazy */
james@536 830 sglist->Elements[0].Address.QuadPart = (ULONGLONG)ptr;
james@536 831 sglist->Elements[0].Length = Length;
james@537 832 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL - %08x\n", sglist->Elements[0].Address.LowPart));
james@536 833 break;
james@555 834 default:
james@555 835 KdPrint((__DRIVER_NAME " map_type = %d\n", map_type));
james@555 836 break;
james@536 837 }
james@600 838 //FUNCTION_EXIT();
james@558 839 return STATUS_SUCCESS;
james@558 840 }
james@537 841
james@558 842 static NTSTATUS
james@558 843 XenPci_DOP_BuildScatterGatherList(
james@558 844 IN PDMA_ADAPTER DmaAdapter,
james@558 845 IN PDEVICE_OBJECT DeviceObject,
james@558 846 IN PMDL Mdl,
james@558 847 IN PVOID CurrentVa,
james@558 848 IN ULONG Length,
james@558 849 IN PDRIVER_LIST_CONTROL ExecutionRoutine,
james@558 850 IN PVOID Context,
james@558 851 IN BOOLEAN WriteToDevice,
james@558 852 IN PVOID ScatterGatherBuffer,
james@558 853 IN ULONG ScatterGatherBufferLength)
james@558 854 {
james@558 855 NTSTATUS status;
james@558 856
james@558 857 status = XenPci_DOP_BuildScatterGatherListButDontExecute(DmaAdapter, DeviceObject, Mdl, CurrentVa, Length, WriteToDevice, ScatterGatherBuffer, ScatterGatherBufferLength, FALSE);
james@558 858
james@558 859 if (NT_SUCCESS(status))
james@558 860 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, ScatterGatherBuffer, Context);
james@536 861
james@536 862 //FUNCTION_EXIT();
james@536 863
james@558 864 return status;
james@558 865 }
james@558 866
james@558 867 static NTSTATUS
james@558 868 XenPci_DOP_GetScatterGatherList(
james@558 869 PDMA_ADAPTER DmaAdapter,
james@558 870 PDEVICE_OBJECT DeviceObject,
james@558 871 PMDL Mdl,
james@558 872 PVOID CurrentVa,
james@558 873 ULONG Length,
james@558 874 PDRIVER_LIST_CONTROL ExecutionRoutine,
james@558 875 PVOID Context,
james@558 876 BOOLEAN WriteToDevice)
james@558 877 {
james@558 878 NTSTATUS status;
james@558 879 ULONG list_size;
james@558 880 ULONG map_registers;
james@558 881 PSCATTER_GATHER_LIST sg_list;
james@558 882
james@561 883 //FUNCTION_ENTER();
james@558 884
james@558 885 status = XenPci_DOP_CalculateScatterGatherList(DmaAdapter, Mdl, CurrentVa, Length, &list_size, &map_registers);
james@558 886 if (!NT_SUCCESS(status))
james@558 887 {
james@561 888 //FUNCTION_EXIT();
james@558 889 return status;
james@558 890 }
james@558 891
james@558 892 sg_list = ExAllocatePoolWithTag(NonPagedPool, list_size, XENPCI_POOL_TAG);
james@558 893 if (!sg_list)
james@558 894 {
james@558 895 KdPrint((__DRIVER_NAME " Cannot allocate memory for sg_list\n"));
james@561 896 //FUNCTION_EXIT();
james@558 897 return STATUS_INSUFFICIENT_RESOURCES;
james@558 898 }
james@558 899
james@558 900 status = XenPci_DOP_BuildScatterGatherListButDontExecute(DmaAdapter, DeviceObject, Mdl, CurrentVa, Length, WriteToDevice, sg_list, list_size, TRUE);
james@558 901
james@558 902 if (NT_SUCCESS(status))
james@558 903 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, sg_list, Context);
james@558 904
james@561 905 //FUNCTION_EXIT();
james@558 906
james@558 907 return status;
james@536 908 }
james@536 909
james@536 910 static NTSTATUS
james@536 911 XenPci_DOP_BuildMdlFromScatterGatherList(
james@536 912 PDMA_ADAPTER DmaAdapter,
james@536 913 PSCATTER_GATHER_LIST ScatterGather,
james@536 914 PMDL OriginalMdl,
james@536 915 PMDL *TargetMdl)
james@536 916 {
james@561 917 NTSTATUS status = STATUS_SUCCESS;
james@536 918 UNREFERENCED_PARAMETER(DmaAdapter);
james@536 919 UNREFERENCED_PARAMETER(ScatterGather);
james@536 920 UNREFERENCED_PARAMETER(OriginalMdl);
james@536 921 UNREFERENCED_PARAMETER(TargetMdl);
james@536 922
james@536 923 FUNCTION_ENTER();
james@561 924
james@561 925 if (OriginalMdl)
james@561 926 {
james@561 927 *TargetMdl = OriginalMdl;
james@561 928 }
james@561 929 else
james@561 930 {
james@561 931 *TargetMdl = NULL;
james@561 932 status = STATUS_INVALID_PARAMETER;
james@561 933 }
james@561 934
james@536 935 FUNCTION_EXIT();
james@561 936
james@561 937 return status;
james@536 938 }
james@536 939
james@536 940 static PDMA_ADAPTER
james@536 941 XenPci_BIS_GetDmaAdapter(PVOID context, PDEVICE_DESCRIPTION device_description, PULONG number_of_map_registers)
james@536 942 {
james@536 943 xen_dma_adapter_t *xen_dma_adapter;
james@536 944 PDEVICE_OBJECT curr, prev;
james@536 945 PDRIVER_OBJECT fdo_driver_object;
james@536 946 PVOID fdo_driver_extension;
james@536 947
james@536 948 UNREFERENCED_PARAMETER(device_description);
james@536 949
james@536 950 FUNCTION_ENTER();
james@536 951
james@536 952 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@536 953 KdPrint((__DRIVER_NAME " Device Description = %p:\n", device_description));
james@536 954 KdPrint((__DRIVER_NAME " Version = %d\n", device_description->Version));
james@536 955 KdPrint((__DRIVER_NAME " Master = %d\n", device_description->Master));
james@536 956 KdPrint((__DRIVER_NAME " ScatterGather = %d\n", device_description->ScatterGather));
james@536 957 KdPrint((__DRIVER_NAME " DemandMode = %d\n", device_description->DemandMode));
james@536 958 KdPrint((__DRIVER_NAME " AutoInitialize = %d\n", device_description->AutoInitialize));
james@536 959 KdPrint((__DRIVER_NAME " Dma32BitAddresses = %d\n", device_description->Dma32BitAddresses));
james@536 960 KdPrint((__DRIVER_NAME " IgnoreCount = %d\n", device_description->IgnoreCount));
james@536 961 KdPrint((__DRIVER_NAME " Dma64BitAddresses = %d\n", device_description->Dma64BitAddresses));
james@536 962 KdPrint((__DRIVER_NAME " BusNumber = %d\n", device_description->BusNumber));
james@536 963 KdPrint((__DRIVER_NAME " DmaChannel = %d\n", device_description->DmaChannel));
james@536 964 KdPrint((__DRIVER_NAME " InterfaceType = %d\n", device_description->InterfaceType));
james@536 965 KdPrint((__DRIVER_NAME " DmaWidth = %d\n", device_description->DmaWidth));
james@536 966 KdPrint((__DRIVER_NAME " DmaSpeed = %d\n", device_description->DmaSpeed));
james@536 967 KdPrint((__DRIVER_NAME " MaximumLength = %d\n", device_description->MaximumLength));
james@536 968 KdPrint((__DRIVER_NAME " DmaPort = %d\n", device_description->DmaPort));
james@536 969
james@538 970 if (!device_description->Master)
james@538 971 return NULL;
james@536 972 /*
james@536 973 we have to allocate PAGE_SIZE bytes here because Windows thinks this is
james@536 974 actually an ADAPTER_OBJECT, and then the verifier crashes because
james@536 975 Windows accessed beyond the end of the structure :(
james@536 976 */
james@536 977 xen_dma_adapter = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@538 978 ASSERT(xen_dma_adapter);
james@536 979 RtlZeroMemory(xen_dma_adapter, PAGE_SIZE);
james@538 980
james@538 981 switch(device_description->Version)
james@538 982 {
james@538 983 case DEVICE_DESCRIPTION_VERSION1:
james@538 984 xen_dma_adapter->adapter_object.DmaHeader.Version = 1;
james@538 985 break;
james@538 986 case DEVICE_DESCRIPTION_VERSION: /* ignore what the docs say here - DEVICE_DESCRIPTION_VERSION appears to mean the latest version */
james@538 987 case DEVICE_DESCRIPTION_VERSION2:
james@538 988 xen_dma_adapter->adapter_object.DmaHeader.Version = 2;
james@538 989 break;
james@538 990 default:
james@538 991 KdPrint((__DRIVER_NAME " Unsupported device description version %d\n", device_description->Version));
james@538 992 ExFreePoolWithTag(xen_dma_adapter, XENPCI_POOL_TAG);
james@538 993 return NULL;
james@538 994 }
james@538 995
james@558 996 xen_dma_adapter->xppdd = context;
james@558 997 xen_dma_adapter->dma_extension = NULL;
james@558 998
james@558 999 KdPrint((__DRIVER_NAME " About to call IoGetAttachedDeviceReference\n"));
james@558 1000 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(xen_dma_adapter->xppdd->wdf_device));
james@558 1001 KdPrint((__DRIVER_NAME " Before start of loop - curr = %p\n", curr));
james@558 1002 while (curr != NULL)
james@558 1003 {
james@558 1004 fdo_driver_object = curr->DriverObject;
james@558 1005 if (fdo_driver_object)
james@558 1006 {
james@558 1007 ObReferenceObject(fdo_driver_object);
james@558 1008 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC));
james@558 1009 if (fdo_driver_extension)
james@558 1010 {
james@558 1011 xen_dma_adapter->dma_extension_driver = fdo_driver_object; /* so we can dereference it on putdmaadapter */
james@558 1012 xen_dma_adapter->dma_extension = (dma_driver_extension_t *)fdo_driver_extension;
james@558 1013 ObDereferenceObject(curr);
james@558 1014 break;
james@558 1015 }
james@558 1016 else
james@558 1017 {
james@558 1018 ObDereferenceObject(fdo_driver_object);
james@558 1019 }
james@558 1020 }
james@558 1021 prev = curr;
james@558 1022 curr = IoGetLowerDeviceObject(curr);
james@558 1023 ObDereferenceObject(prev);
james@558 1024 }
james@558 1025 KdPrint((__DRIVER_NAME " End of loop\n"));
james@538 1026
james@538 1027 xen_dma_adapter->adapter_object.DmaHeader.Size = sizeof(X_ADAPTER_OBJECT); //xen_dma_adapter_t);
james@538 1028 xen_dma_adapter->adapter_object.MasterAdapter = NULL;
james@558 1029 if (xen_dma_adapter->dma_extension && xen_dma_adapter->dma_extension->max_sg_elements)
james@558 1030 {
james@558 1031 xen_dma_adapter->adapter_object.MapRegistersPerChannel = xen_dma_adapter->dma_extension->max_sg_elements;
james@558 1032 }
james@558 1033 else
james@558 1034 {
james@558 1035 xen_dma_adapter->adapter_object.MapRegistersPerChannel = 256;
james@558 1036 }
james@538 1037 xen_dma_adapter->adapter_object.AdapterBaseVa = NULL;
james@538 1038 xen_dma_adapter->adapter_object.MapRegisterBase = NULL;
james@538 1039 xen_dma_adapter->adapter_object.NumberOfMapRegisters = 0;
james@538 1040 xen_dma_adapter->adapter_object.CommittedMapRegisters = 0;
james@538 1041 xen_dma_adapter->adapter_object.CurrentWcb = NULL;
james@538 1042 KeInitializeDeviceQueue(&xen_dma_adapter->adapter_object.ChannelWaitQueue);
james@538 1043 xen_dma_adapter->adapter_object.RegisterWaitQueue = NULL;
james@538 1044 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterQueue);
james@538 1045 KeInitializeSpinLock(&xen_dma_adapter->adapter_object.SpinLock);
james@538 1046 xen_dma_adapter->adapter_object.MapRegisters = NULL;
james@538 1047 xen_dma_adapter->adapter_object.PagePort = NULL;
james@538 1048 xen_dma_adapter->adapter_object.ChannelNumber = 0xff;
james@538 1049 xen_dma_adapter->adapter_object.AdapterNumber = 0;
james@538 1050 xen_dma_adapter->adapter_object.DmaPortAddress = 0;
james@538 1051 xen_dma_adapter->adapter_object.AdapterMode = 0;
james@538 1052 xen_dma_adapter->adapter_object.NeedsMapRegisters = FALSE; /* when true this causes a crash in the crash dump path */
james@538 1053 xen_dma_adapter->adapter_object.MasterDevice = 1;
james@538 1054 xen_dma_adapter->adapter_object.Width16Bits = 0;
james@538 1055 xen_dma_adapter->adapter_object.ScatterGather = device_description->ScatterGather;
james@538 1056 xen_dma_adapter->adapter_object.IgnoreCount = device_description->IgnoreCount;
james@538 1057 xen_dma_adapter->adapter_object.Dma32BitAddresses = device_description->Dma32BitAddresses;
james@538 1058 xen_dma_adapter->adapter_object.Dma64BitAddresses = device_description->Dma64BitAddresses;
james@538 1059 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterList);
james@538 1060
james@538 1061 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DMA_OPERATIONS), XENPCI_POOL_TAG);
james@538 1062 ASSERT(xen_dma_adapter->adapter_object.DmaHeader.DmaOperations);
james@538 1063 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 1)
james@538 1064 {
james@538 1065 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = FIELD_OFFSET(DMA_OPERATIONS, CalculateScatterGatherList);
james@538 1066 }
james@538 1067 else
james@538 1068 {
james@538 1069 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = sizeof(DMA_OPERATIONS);
james@538 1070 }
james@538 1071 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutDmaAdapter = XenPci_DOP_PutDmaAdapter;
james@538 1072 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateCommonBuffer = XenPci_DOP_AllocateCommonBuffer;
james@538 1073 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeCommonBuffer = XenPci_DOP_FreeCommonBuffer;
james@538 1074 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateAdapterChannel = XenPci_DOP_AllocateAdapterChannel;
james@538 1075 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FlushAdapterBuffers = XenPci_DOP_FlushAdapterBuffers;
james@538 1076 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeAdapterChannel = XenPci_DOP_FreeAdapterChannel;
james@538 1077 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeMapRegisters = XenPci_DOP_FreeMapRegisters;
james@538 1078 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->MapTransfer = XenPci_DOP_MapTransfer;
james@538 1079 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetDmaAlignment = XenPci_DOP_GetDmaAlignment;
james@538 1080 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->ReadDmaCounter = XenPci_DOP_ReadDmaCounter;
james@538 1081 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetScatterGatherList = XenPci_DOP_GetScatterGatherList;
james@538 1082 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutScatterGatherList = XenPci_DOP_PutScatterGatherList;
james@538 1083 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 2)
james@538 1084 {
james@538 1085 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->CalculateScatterGatherList = XenPci_DOP_CalculateScatterGatherList;
james@538 1086 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildScatterGatherList = XenPci_DOP_BuildScatterGatherList;
james@538 1087 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildMdlFromScatterGatherList = XenPci_DOP_BuildMdlFromScatterGatherList;
james@538 1088 }
james@536 1089
james@558 1090 *number_of_map_registers = xen_dma_adapter->adapter_object.MapRegistersPerChannel; //1024; /* why not... */
james@536 1091
james@536 1092 FUNCTION_EXIT();
james@536 1093
james@538 1094 return &xen_dma_adapter->adapter_object.DmaHeader;
james@536 1095 }
james@536 1096
james@536 1097 static ULONG
james@536 1098 XenPci_BIS_SetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
james@536 1099 {
james@536 1100 UNREFERENCED_PARAMETER(context);
james@536 1101 UNREFERENCED_PARAMETER(data_type);
james@536 1102 UNREFERENCED_PARAMETER(buffer);
james@536 1103 UNREFERENCED_PARAMETER(offset);
james@536 1104 UNREFERENCED_PARAMETER(length);
james@536 1105
james@536 1106 FUNCTION_ENTER();
james@536 1107 FUNCTION_EXIT();
james@536 1108 return 0;
james@536 1109 }
james@536 1110
james@536 1111 static ULONG
james@536 1112 XenPci_BIS_GetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
james@536 1113 {
james@536 1114 UNREFERENCED_PARAMETER(context);
james@536 1115 UNREFERENCED_PARAMETER(data_type);
james@536 1116 UNREFERENCED_PARAMETER(buffer);
james@536 1117 UNREFERENCED_PARAMETER(offset);
james@536 1118 UNREFERENCED_PARAMETER(length);
james@536 1119
james@536 1120 FUNCTION_ENTER();
james@536 1121 FUNCTION_EXIT();
james@536 1122 return 0;
james@536 1123 }
james@536 1124
james@536 1125 /*
james@536 1126 Called at PASSIVE_LEVEL(?)
james@536 1127 Called during restore
james@536 1128 */
james@536 1129
james@536 1130 static ULONG
james@536 1131 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
james@536 1132 {
james@536 1133 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1134 char path[128];
james@536 1135 char *value;
james@536 1136 char *err;
james@536 1137 ULONG backend_state;
james@536 1138
james@536 1139 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@536 1140 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@536 1141 if (err)
james@536 1142 {
james@536 1143 XenPci_FreeMem(err);
james@536 1144 return XenbusStateUnknown;
james@536 1145 }
james@536 1146 else
james@536 1147 {
james@536 1148 backend_state = atoi(value);
james@536 1149 XenPci_FreeMem(value);
james@536 1150 return backend_state;
james@536 1151 }
james@536 1152 }
james@536 1153
james@617 1154 static NTSTATUS
james@617 1155 XenPciPdo_ReconfigureCompletionRoutine(
james@617 1156 PDEVICE_OBJECT device_object,
james@617 1157 PIRP irp,
james@617 1158 PVOID context)
james@617 1159 {
james@617 1160 UNREFERENCED_PARAMETER(device_object);
james@617 1161
james@617 1162 if (irp->PendingReturned)
james@617 1163 {
james@617 1164 KeSetEvent ((PKEVENT)context, IO_NO_INCREMENT, FALSE);
james@617 1165 }
james@617 1166 return STATUS_MORE_PROCESSING_REQUIRED;
james@617 1167 }
james@617 1168
james@536 1169 static VOID
james@536 1170 XenPci_BackEndStateHandler(char *path, PVOID context)
james@536 1171 {
james@536 1172 WDFDEVICE device = context;
james@536 1173 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1174 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1175 ULONG new_backend_state;
james@617 1176 CHAR tmp_path[128];
james@536 1177
james@536 1178 #if !DBG
james@536 1179 UNREFERENCED_PARAMETER(path);
james@536 1180 #endif
james@536 1181
james@536 1182 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
james@536 1183
james@536 1184 /* check that path == device/id/state */
james@536 1185 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
james@536 1186 new_backend_state = XenPci_ReadBackendState(xppdd);
james@536 1187 if (new_backend_state == XenbusStateUnknown)
james@536 1188 {
james@536 1189 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
james@536 1190 return;
james@536 1191 KdPrint(("Failed to read %s, assuming closed\n", path));
james@536 1192 new_backend_state = XenbusStateClosed;
james@536 1193 }
james@536 1194
james@536 1195 if (xppdd->backend_state == new_backend_state)
james@536 1196 {
james@536 1197 KdPrint((__DRIVER_NAME " state unchanged\n"));
james@536 1198 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@536 1199 return;
james@536 1200 }
james@536 1201
james@536 1202 xppdd->backend_state = new_backend_state;
james@536 1203
james@536 1204 switch (xppdd->backend_state)
james@536 1205 {
james@536 1206 case XenbusStateUnknown:
james@536 1207 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown (%s)\n", path));
james@536 1208 break;
james@536 1209
james@536 1210 case XenbusStateInitialising:
james@536 1211 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising (%s)\n", path));
james@536 1212 break;
james@536 1213
james@536 1214 case XenbusStateInitWait:
james@536 1215 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait (%s)\n", path));
james@536 1216 break;
james@536 1217
james@536 1218 case XenbusStateInitialised:
james@536 1219 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised (%s)\n", path));
james@536 1220 break;
james@536 1221
james@536 1222 case XenbusStateConnected:
james@536 1223 KdPrint((__DRIVER_NAME " Backend State Changed to Connected (%s)\n", path));
james@536 1224 break;
james@536 1225
james@536 1226 case XenbusStateClosing:
james@538 1227 KdPrint((__DRIVER_NAME " Backend State Changed to Closing (%s)\n", path));
james@538 1228 if (xppdd->frontend_state == XenbusStateConnected)
james@536 1229 {
james@538 1230 KdPrint((__DRIVER_NAME " Requesting eject\n"));
james@536 1231 WdfPdoRequestEject(device);
james@536 1232 }
james@536 1233 break;
james@536 1234
james@536 1235 case XenbusStateClosed:
james@536 1236 KdPrint((__DRIVER_NAME " Backend State Changed to Closed (%s)\n", path));
james@536 1237 break;
james@536 1238
james@617 1239 case XenbusStateReconfiguring:
james@617 1240 KdPrint((__DRIVER_NAME " Backend State Changed to Reconfiguring (%s)\n", path));
james@617 1241 RtlStringCbPrintfA(tmp_path, ARRAY_SIZE(tmp_path), "%s/state", xppdd->path);
james@617 1242 KdPrint((__DRIVER_NAME " Setting %s to %d\n", tmp_path, XenbusStateReconfiguring));
james@617 1243 XenBus_Printf(xpdd, XBT_NIL, tmp_path, "%d", XenbusStateReconfiguring);
james@617 1244 break;
james@617 1245
james@617 1246 case XenbusStateReconfigured:
james@617 1247 KdPrint((__DRIVER_NAME " Backend State Changed to Reconfigured (%s)\n", path));
james@617 1248 {
james@617 1249 PDEVICE_OBJECT fdo;
james@617 1250 PIRP irp;
james@617 1251 PIO_STACK_LOCATION stack;
james@617 1252 NTSTATUS status;
james@617 1253 KEVENT irp_complete_event;
james@617 1254
james@617 1255 fdo = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(device));
james@617 1256 KeInitializeEvent(&irp_complete_event, NotificationEvent, FALSE);
james@617 1257 irp = IoAllocateIrp(fdo->StackSize, FALSE);
james@617 1258 stack = IoGetNextIrpStackLocation(irp);
james@617 1259 stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
james@617 1260 stack->Parameters.DeviceIoControl.IoControlCode = (ULONG)IOCTL_XEN_RECONFIGURE;
james@617 1261 IoSetCompletionRoutine(irp, XenPciPdo_ReconfigureCompletionRoutine, &irp_complete_event, TRUE, TRUE, TRUE);
james@617 1262 status = IoCallDriver(fdo, irp);
james@617 1263 if (status == STATUS_PENDING)
james@617 1264 {
james@617 1265 KdPrint((__DRIVER_NAME " Waiting for completion\n"));
james@617 1266 status = KeWaitForSingleObject(&irp_complete_event, Executive, KernelMode, FALSE, NULL);
james@617 1267 status = irp->IoStatus.Status;
james@617 1268 }
james@617 1269 KdPrint((__DRIVER_NAME " IOCTL_XEN_RECONFIGURE status = %08x\n", status));
james@617 1270 ObDereferenceObject(fdo);
james@617 1271 #if 0
james@617 1272 WDFREQUEST request;
james@617 1273 WDF_REQUEST_SEND_OPTIONS options;
james@617 1274 WDFIOTARGET target;
james@617 1275 DEVICE_OBJECT fdo;
james@617 1276
james@617 1277 WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET);
james@617 1278 fdo = IoGetAttachedDevice(WdfDeviceWdmGetDeviceObject(device));
james@617 1279
james@617 1280 target = WdfDeviceGetIoTarget(xppdd->wdf_device);
james@617 1281 WdfRequestCreate(WDF_NO_OBJECT_ATTRIBUTES, target, &request);
james@617 1282 WdfIoTargetFormatRequestForInternalIoctl(target, request, IOCTL_XEN_RECONFIGURE, NULL, NULL, NULL, NULL);
james@617 1283 WdfRequestSend(request, target, &options);
james@617 1284 #endif
james@617 1285 RtlStringCbPrintfA(tmp_path, ARRAY_SIZE(tmp_path), "%s/state", xppdd->path);
james@617 1286 KdPrint((__DRIVER_NAME " Setting %s to %d\n", tmp_path, XenbusStateConnected));
james@617 1287 XenBus_Printf(xpdd, XBT_NIL, tmp_path, "%d", XenbusStateConnected);
james@617 1288 break;
james@617 1289 }
james@617 1290
james@536 1291 default:
james@536 1292 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d (%s)\n", xppdd->backend_state, path));
james@536 1293 break;
james@536 1294 }
james@536 1295
james@536 1296 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
james@536 1297
james@536 1298 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@536 1299
james@536 1300 return;
james@536 1301 }
james@536 1302
james@536 1303 static NTSTATUS
james@536 1304 XenPci_GetBackendAndAddWatch(WDFDEVICE device)
james@536 1305 {
james@536 1306 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1307 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1308 char path[128];
james@536 1309 PCHAR res;
james@536 1310 PCHAR value;
james@536 1311
james@536 1312 /* Get backend path */
james@536 1313 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
james@536 1314 "%s/backend", xppdd->path);
james@536 1315 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@536 1316 if (res)
james@536 1317 {
james@536 1318 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
james@536 1319 XenPci_FreeMem(res);
james@536 1320 return STATUS_UNSUCCESSFUL;
james@536 1321 }
james@536 1322 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
james@536 1323 XenPci_FreeMem(value);
james@536 1324
james@536 1325 /* Add watch on backend state */
james@536 1326 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@536 1327 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
james@536 1328
james@536 1329 return STATUS_SUCCESS;
james@536 1330 }
james@536 1331
james@551 1332 static NTSTATUS
james@551 1333 XenConfig_InitConfigPage(WDFDEVICE device)
james@536 1334 {
james@551 1335 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1336 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
james@536 1337 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
james@536 1338 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@536 1339 PUCHAR ptr;
james@536 1340 PDEVICE_OBJECT curr, prev;
james@536 1341 PDRIVER_OBJECT fdo_driver_object;
james@536 1342 PUCHAR fdo_driver_extension;
james@536 1343
james@536 1344 FUNCTION_ENTER();
james@536 1345
james@551 1346 ptr = MmGetMdlVirtualAddress(xppdd->config_page_mdl);
james@536 1347 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(device));
james@536 1348 //curr = WdfDeviceWdmGetAttachedDevice(device);
james@536 1349 while (curr != NULL)
james@536 1350 {
james@536 1351 fdo_driver_object = curr->DriverObject;
james@536 1352 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
james@536 1353 if (fdo_driver_object)
james@536 1354 {
james@536 1355 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
james@536 1356 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
james@536 1357 if (fdo_driver_extension)
james@536 1358 {
james@536 1359 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
james@536 1360 ObDereferenceObject(curr);
james@536 1361 break;
james@536 1362 }
james@536 1363 }
james@536 1364 prev = curr;
james@536 1365 curr = IoGetLowerDeviceObject(curr);
james@536 1366 ObDereferenceObject(prev);
james@536 1367 }
james@536 1368
james@536 1369 FUNCTION_EXIT();
james@536 1370
james@551 1371 return STATUS_SUCCESS;
james@536 1372 }
james@536 1373
james@536 1374 static NTSTATUS
james@536 1375 XenPci_EvtChn_Bind(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
james@536 1376 {
james@536 1377 WDFDEVICE device = context;
james@536 1378 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1379 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1380
james@536 1381 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext);
james@536 1382 }
james@536 1383
james@536 1384 static NTSTATUS
james@536 1385 XenPci_EvtChn_BindDpc(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
james@536 1386 {
james@536 1387 WDFDEVICE device = context;
james@536 1388 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1389 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1390
james@536 1391 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext);
james@536 1392 }
james@536 1393
james@536 1394 static NTSTATUS
james@536 1395 XenPci_EvtChn_Unbind(PVOID context, evtchn_port_t Port)
james@536 1396 {
james@536 1397 WDFDEVICE device = context;
james@536 1398 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1399 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1400
james@536 1401 return EvtChn_Unbind(xpdd, Port);
james@536 1402 }
james@536 1403
james@536 1404 static NTSTATUS
james@536 1405 XenPci_EvtChn_Mask(PVOID context, evtchn_port_t Port)
james@536 1406 {
james@536 1407 WDFDEVICE device = context;
james@536 1408 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1409 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1410
james@536 1411 return EvtChn_Mask(xpdd, Port);
james@536 1412 }
james@536 1413
james@536 1414 static NTSTATUS
james@536 1415 XenPci_EvtChn_Unmask(PVOID context, evtchn_port_t Port)
james@536 1416 {
james@536 1417 WDFDEVICE device = context;
james@536 1418 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1419 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1420
james@536 1421 return EvtChn_Unmask(xpdd, Port);
james@536 1422 }
james@536 1423
james@536 1424 static NTSTATUS
james@536 1425 XenPci_EvtChn_Notify(PVOID context, evtchn_port_t Port)
james@536 1426 {
james@536 1427 WDFDEVICE device = context;
james@536 1428 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1429 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1430
james@536 1431 return EvtChn_Notify(xpdd, Port);
james@536 1432 }
james@536 1433
james@536 1434 static BOOLEAN
james@561 1435 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port, BOOLEAN *last_interrupt)
james@536 1436 {
james@536 1437 WDFDEVICE device = context;
james@536 1438 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1439 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1440
james@561 1441 return EvtChn_AckEvent(xpdd, port, last_interrupt);
james@536 1442 }
james@536 1443
james@536 1444 typedef struct {
james@536 1445 PXEN_EVTCHN_SYNC_ROUTINE sync_routine;
james@536 1446 PVOID sync_context;
james@536 1447 } sync_context_t;
james@536 1448
james@536 1449 static BOOLEAN
james@536 1450 XenPci_EvtChn_Sync_Routine(WDFINTERRUPT interrupt, WDFCONTEXT context)
james@536 1451 {
james@536 1452 sync_context_t *wdf_sync_context = context;
james@536 1453 UNREFERENCED_PARAMETER(interrupt);
james@536 1454 return wdf_sync_context->sync_routine(wdf_sync_context->sync_context);
james@536 1455 }
james@536 1456
james@536 1457 static BOOLEAN
james@536 1458 XenPci_EvtChn_Sync(PVOID context, PXEN_EVTCHN_SYNC_ROUTINE sync_routine, PVOID sync_context)
james@536 1459 {
james@536 1460 WDFDEVICE device = context;
james@536 1461 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1462 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1463 sync_context_t wdf_sync_context;
james@536 1464
james@536 1465 wdf_sync_context.sync_routine = sync_routine;
james@536 1466 wdf_sync_context.sync_context = sync_context;
james@536 1467
james@536 1468 return WdfInterruptSynchronize(xpdd->interrupt, XenPci_EvtChn_Sync_Routine, &wdf_sync_context);
james@536 1469 }
james@536 1470
james@536 1471 static grant_ref_t
james@536 1472 XenPci_GntTbl_GrantAccess(PVOID context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref)
james@536 1473 {
james@536 1474 WDFDEVICE device = context;
james@536 1475 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1476 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1477
james@536 1478 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref);
james@536 1479 }
james@536 1480
james@536 1481 static BOOLEAN
james@536 1482 XenPci_GntTbl_EndAccess(PVOID context, grant_ref_t ref, BOOLEAN keepref)
james@536 1483 {
james@536 1484 WDFDEVICE device = context;
james@536 1485 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1486 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1487
james@536 1488 return GntTbl_EndAccess(xpdd, ref, keepref);
james@536 1489 }
james@536 1490
james@536 1491 static VOID
james@536 1492 XenPci_GntTbl_PutRef(PVOID context, grant_ref_t ref)
james@536 1493 {
james@536 1494 WDFDEVICE device = context;
james@536 1495 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1496 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1497
james@536 1498 GntTbl_PutRef(xpdd, ref);
james@536 1499 }
james@536 1500
james@536 1501 static grant_ref_t
james@536 1502 XenPci_GntTbl_GetRef(PVOID context)
james@536 1503 {
james@536 1504 WDFDEVICE device = context;
james@536 1505 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1506 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1507
james@536 1508 return GntTbl_GetRef(xpdd);
james@536 1509 }
james@536 1510
james@536 1511 PCHAR
james@536 1512 XenPci_XenBus_Read(PVOID context, xenbus_transaction_t xbt, char *path, char **value)
james@536 1513 {
james@536 1514 WDFDEVICE device = context;
james@536 1515 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1516 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1517 return XenBus_Read(xpdd, xbt, path, value);
james@536 1518 }
james@536 1519
james@536 1520 PCHAR
james@536 1521 XenPci_XenBus_Write(PVOID context, xenbus_transaction_t xbt, char *path, char *value)
james@536 1522 {
james@536 1523 WDFDEVICE device = context;
james@536 1524 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1525 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1526 return XenBus_Write(xpdd, xbt, path, value);
james@536 1527 }
james@536 1528
james@536 1529 PCHAR
james@536 1530 XenPci_XenBus_Printf(PVOID context, xenbus_transaction_t xbt, char *path, char *fmt, ...)
james@536 1531 {
james@536 1532 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@536 1533 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@536 1534 //return XenBus_Printf(xpdd, xbt, path, value);
james@536 1535 UNREFERENCED_PARAMETER(context);
james@536 1536 UNREFERENCED_PARAMETER(xbt);
james@536 1537 UNREFERENCED_PARAMETER(path);
james@536 1538 UNREFERENCED_PARAMETER(fmt);
james@536 1539 return NULL;
james@536 1540 }
james@536 1541
james@536 1542 PCHAR
james@536 1543 XenPci_XenBus_StartTransaction(PVOID context, xenbus_transaction_t *xbt)
james@536 1544 {
james@536 1545 WDFDEVICE device = context;
james@536 1546 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1547 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1548 return XenBus_StartTransaction(xpdd, xbt);
james@536 1549 }
james@536 1550
james@536 1551 PCHAR
james@536 1552 XenPci_XenBus_EndTransaction(PVOID context, xenbus_transaction_t xbt, int abort, int *retry)
james@536 1553 {
james@536 1554 WDFDEVICE device = context;
james@536 1555 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1556 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1557 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
james@536 1558 }
james@536 1559
james@536 1560 PCHAR
james@536 1561 XenPci_XenBus_List(PVOID context, xenbus_transaction_t xbt, char *prefix, char ***contents)
james@536 1562 {
james@536 1563 WDFDEVICE device = context;
james@536 1564 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1565 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1566 return XenBus_List(xpdd, xbt, prefix, contents);
james@536 1567 }
james@536 1568
james@536 1569 PCHAR
james@536 1570 XenPci_XenBus_AddWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
james@536 1571 {
james@536 1572 WDFDEVICE device = context;
james@536 1573 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1574 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1575 PCHAR retval;
james@536 1576
james@536 1577 FUNCTION_ENTER();
james@536 1578 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
james@536 1579 if (retval == NULL)
james@536 1580 {
james@536 1581 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
james@536 1582 }
james@536 1583 else
james@536 1584 {
james@536 1585 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
james@536 1586 }
james@536 1587 FUNCTION_EXIT();
james@536 1588 return retval;
james@536 1589 }
james@536 1590
james@536 1591 PCHAR
james@536 1592 XenPci_XenBus_RemWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
james@536 1593 {
james@536 1594 WDFDEVICE device = context;
james@536 1595 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1596 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1597 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
james@536 1598 }
james@536 1599
james@536 1600 /*
james@536 1601 Called at PASSIVE_LEVEL
james@536 1602 Called during restore
james@536 1603 */
james@536 1604
james@536 1605 static NTSTATUS
james@536 1606 XenPci_ChangeFrontendState(WDFDEVICE device, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
james@536 1607 {
james@536 1608 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1609 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1610 LARGE_INTEGER timeout;
james@536 1611 ULONG remaining;
james@536 1612 ULONG thiswait;
james@536 1613 char path[128];
james@536 1614
james@536 1615 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
james@538 1616
james@538 1617 xppdd->frontend_state = frontend_state_set;
james@536 1618
james@536 1619 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
james@536 1620 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
james@536 1621
james@536 1622 remaining = maximum_wait_ms;
james@536 1623
james@536 1624 while (xppdd->backend_state != backend_state_response)
james@536 1625 {
james@536 1626 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
james@536 1627 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
james@536 1628 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
james@536 1629 {
james@536 1630 remaining -= thiswait;
james@536 1631 if (remaining == 0)
james@536 1632 {
james@536 1633 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
james@536 1634 return STATUS_UNSUCCESSFUL;
james@536 1635 }
james@536 1636 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
james@536 1637 }
james@536 1638 }
james@536 1639 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@536 1640 return STATUS_SUCCESS;
james@536 1641 }
james@536 1642
james@536 1643 static NTSTATUS
james@536 1644 XenPci_XenConfigDevice(WDFDEVICE device);
james@536 1645
james@536 1646 static NTSTATUS
james@536 1647 XenPci_XenShutdownDevice(PVOID context)
james@536 1648 {
james@536 1649 WDFDEVICE device = context;
james@536 1650 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1651 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1652 PUCHAR in_ptr;
james@536 1653 ULONG i;
james@536 1654 UCHAR type;
james@536 1655 PVOID setting;
james@536 1656 PVOID value;
james@536 1657 PVOID value2;
james@536 1658
james@536 1659 FUNCTION_ENTER();
james@536 1660
james@536 1661 if (xppdd->backend_state == XenbusStateConnected)
james@536 1662 {
james@536 1663 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
james@536 1664 if (xppdd->backend_state == XenbusStateClosing)
james@536 1665 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
james@536 1666 if (xppdd->backend_state == XenbusStateClosed)
james@536 1667 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
james@536 1668 }
james@536 1669 else
james@536 1670 {
james@536 1671 if (xppdd->backend_state == XenbusStateClosing)
james@536 1672 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
james@536 1673 }
james@536 1674
james@536 1675 if (xppdd->assigned_resources_start != NULL)
james@536 1676 {
james@536 1677 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 1678 in_ptr = xppdd->assigned_resources_start;
james@536 1679 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
james@536 1680 {
james@536 1681 switch (type)
james@536 1682 {
james@536 1683 case XEN_INIT_TYPE_RING: /* frontend ring */
james@536 1684 FreePages(value);
james@536 1685 break;
james@536 1686 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@617 1687 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
james@536 1688 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 1689 EvtChn_Unbind(xpdd, PtrToUlong(value));
james@536 1690 EvtChn_Close(xpdd, PtrToUlong(value));
james@536 1691 break;
james@536 1692 case XEN_INIT_TYPE_GRANT_ENTRIES:
james@536 1693 for (i = 0; i < PtrToUlong(setting); i++)
james@536 1694 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value)[i], FALSE);
james@536 1695 break;
james@536 1696 }
james@536 1697 }
james@536 1698 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
james@536 1699 xppdd->assigned_resources_start = NULL;
james@536 1700 }
james@536 1701
james@536 1702 FUNCTION_EXIT();
james@536 1703
james@536 1704 return STATUS_SUCCESS;
james@536 1705 }
james@536 1706
james@536 1707 struct dummy_sring {
james@536 1708 RING_IDX req_prod, req_event;
james@536 1709 RING_IDX rsp_prod, rsp_event;
james@536 1710 uint8_t pad[48];
james@536 1711 };
james@536 1712
james@536 1713 static NTSTATUS
james@536 1714 XenPci_XenConfigDeviceSpecifyBuffers(WDFDEVICE device, PUCHAR src, PUCHAR dst)
james@536 1715 {
james@536 1716 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1717 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1718 NTSTATUS status = STATUS_SUCCESS;
james@536 1719 ULONG i;
james@536 1720 char path[128];
james@536 1721 PCHAR setting, value;
james@536 1722 PCHAR res;
james@536 1723 PVOID address;
james@536 1724 UCHAR type;
james@551 1725 PUCHAR in_ptr;
james@551 1726 PUCHAR out_ptr;
james@536 1727 XENPCI_VECTORS vectors;
james@536 1728 ULONG event_channel;
james@536 1729 ULONG run_type = 0;
james@536 1730 PMDL ring;
james@536 1731 grant_ref_t gref;
james@536 1732 BOOLEAN done_xenbus_init = FALSE;
james@536 1733 PVOID value2;
james@551 1734 BOOLEAN active = TRUE;
james@551 1735 BOOLEAN dont_config = FALSE;
james@536 1736
james@536 1737 FUNCTION_ENTER();
james@536 1738
james@536 1739 in_ptr = src;
james@536 1740 out_ptr = dst;
james@536 1741
james@536 1742 // always add vectors
james@536 1743 vectors.magic = XEN_DATA_MAGIC;
james@536 1744 vectors.length = sizeof(XENPCI_VECTORS);
james@536 1745 vectors.context = device;
james@536 1746 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
james@536 1747 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
james@536 1748 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
james@536 1749 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
james@536 1750 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
james@536 1751 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
james@536 1752 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
james@536 1753 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
james@536 1754 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
james@536 1755 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
james@536 1756 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
james@536 1757 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
james@536 1758 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
james@536 1759 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
james@536 1760 strncpy(vectors.path, xppdd->path, 128);
james@536 1761 strncpy(vectors.backend_path, xppdd->backend_path, 128);
james@536 1762 //vectors.pdo_event_channel = xpdd->pdo_event_channel;
james@536 1763 vectors.XenBus_Read = XenPci_XenBus_Read;
james@536 1764 vectors.XenBus_Write = XenPci_XenBus_Write;
james@536 1765 vectors.XenBus_Printf = XenPci_XenBus_Printf;
james@536 1766 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
james@536 1767 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
james@536 1768 vectors.XenBus_List = XenPci_XenBus_List;
james@536 1769 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
james@536 1770 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
james@536 1771
james@536 1772 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
james@536 1773
james@536 1774 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
james@536 1775 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
james@536 1776
james@551 1777
james@551 1778 if (!qemu_filtered)
james@551 1779 active = FALSE;
james@551 1780
james@551 1781 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@551 1782 {
james@551 1783 BOOLEAN condition;
james@551 1784 PCHAR xb_value;
james@551 1785 switch (type)
james@551 1786 {
james@551 1787 case XEN_INIT_TYPE_MATCH_FRONT:
james@551 1788 case XEN_INIT_TYPE_MATCH_BACK:
james@551 1789 if (type == XEN_INIT_TYPE_MATCH_FRONT)
james@551 1790 {
james@551 1791 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@551 1792 }
james@551 1793 else
james@551 1794 {
james@551 1795 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
james@551 1796 }
james@551 1797 KdPrint((__DRIVER_NAME " testing path = %s\n", path));
james@551 1798 res = XenBus_Read(xpdd, XBT_NIL, path, &xb_value);
james@551 1799 if (res)
james@551 1800 {
james@551 1801 KdPrint((__DRIVER_NAME " read failed (%s)\n", res));
james@551 1802 XenPci_FreeMem(res);
james@551 1803 }
james@551 1804 else
james@551 1805 {
james@551 1806 KdPrint((__DRIVER_NAME " testing %s vs %s\n", xb_value, value));
james@551 1807 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_IF_MATCH)
james@551 1808 condition = (strcmp(xb_value, value) == 0)?TRUE:FALSE;
james@551 1809 else
james@551 1810 condition = (strcmp(xb_value, value) != 0)?TRUE:FALSE;
james@551 1811 KdPrint((__DRIVER_NAME " condition = %d\n", condition));
james@551 1812
james@551 1813 if ((PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_ONLY_IF_QEMU_HIDE) && qemu_protocol_version && condition)
james@551 1814 condition = FALSE;
james@551 1815
james@551 1816 if (condition)
james@551 1817 {
james@551 1818 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_SET_INACTIVE)
james@551 1819 {
james@551 1820 active = FALSE;
james@551 1821 KdPrint((__DRIVER_NAME " set inactive\n"));
james@551 1822 }
james@551 1823 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_DONT_CONFIG)
james@551 1824 {
james@551 1825 dont_config = TRUE;
james@551 1826 KdPrint((__DRIVER_NAME " set inactive with dont config\n"));
james@551 1827 }
james@551 1828 }
james@551 1829 XenPci_FreeMem(xb_value);
james@551 1830 }
james@551 1831 break;
james@551 1832 }
james@551 1833 }
james@551 1834 if (dont_config)
james@551 1835 {
james@551 1836 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@551 1837 FUNCTION_EXIT();
james@551 1838 return status;
james@551 1839 }
james@551 1840
james@536 1841 // first pass, possibly before state == Connected
james@551 1842 in_ptr = src;
james@536 1843 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@536 1844 {
james@536 1845
james@536 1846 if (!done_xenbus_init)
james@536 1847 {
james@551 1848 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000) != STATUS_SUCCESS)
james@536 1849 {
james@536 1850 status = STATUS_UNSUCCESSFUL;
james@536 1851 goto error;
james@536 1852 }
james@536 1853 done_xenbus_init = TRUE;
james@536 1854 }
james@536 1855
james@536 1856 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
james@536 1857
james@536 1858 switch (type)
james@536 1859 {
james@536 1860 case XEN_INIT_TYPE_RUN:
james@536 1861 run_type++;
james@536 1862 break;
james@536 1863 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
james@536 1864 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
james@536 1865 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 1866 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
james@536 1867 break;
james@536 1868 case XEN_INIT_TYPE_RING: /* frontend ring */
james@536 1869 /* we only allocate and do the SHARED_RING_INIT here */
james@536 1870 if ((ring = AllocatePage()) != 0)
james@536 1871 {
james@536 1872 address = MmGetMdlVirtualAddress(ring);
james@536 1873 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
james@536 1874 SHARED_RING_INIT((struct dummy_sring *)address);
james@536 1875 if ((gref = GntTbl_GrantAccess(
james@536 1876 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
james@536 1877 {
james@536 1878 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 1879 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
james@536 1880 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
james@536 1881 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
james@536 1882 // add the grant entry too so it gets freed automatically
james@536 1883 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
james@536 1884 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
james@536 1885 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
james@536 1886 }
james@536 1887 else
james@536 1888 {
james@536 1889 FreePages(ring);
james@536 1890 status = STATUS_UNSUCCESSFUL;
james@536 1891 goto error;
james@536 1892 }
james@536 1893 }
james@536 1894 else
james@536 1895 {
james@536 1896 status = STATUS_UNSUCCESSFUL;
james@536 1897 goto error;
james@536 1898 }
james@536 1899 break;
james@536 1900 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@617 1901 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
james@536 1902 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 1903 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
james@536 1904 {
james@617 1905 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
james@536 1906 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 1907 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
james@536 1908 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
james@536 1909 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
james@536 1910 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
james@536 1911 {
james@536 1912 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
james@536 1913 }
james@617 1914 else if (type == XEN_INIT_TYPE_EVENT_CHANNEL_DPC)
james@617 1915 {
james@617 1916 #pragma warning(suppress:4055)
james@617 1917 EvtChn_BindDpc(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
james@617 1918 }
james@536 1919 else
james@536 1920 {
james@537 1921 #pragma warning(suppress:4055)
james@536 1922 EvtChn_Bind(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
james@536 1923 }
james@536 1924 }
james@536 1925 else
james@536 1926 {
james@536 1927 status = STATUS_UNSUCCESSFUL;
james@536 1928 goto error;
james@536 1929 }
james@536 1930 break;
james@536 1931 }
james@536 1932 }
james@536 1933 if (!NT_SUCCESS(status))
james@536 1934 {
james@536 1935 goto error;
james@536 1936 }
james@536 1937 // 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 1938 if (run_type == 1)
james@536 1939 {
james@551 1940 if (XenPci_ChangeFrontendState(device, XenbusStateInitialised, XenbusStateConnected, 2000) != STATUS_SUCCESS)
james@536 1941 {
james@536 1942 status = STATUS_UNSUCCESSFUL;
james@536 1943 goto error;
james@536 1944 }
james@536 1945 }
james@536 1946
james@536 1947 // second pass, possibly after state == Connected
james@536 1948 in_ptr = src;
james@536 1949 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@536 1950 {
james@536 1951 switch(type)
james@536 1952 {
james@536 1953 case XEN_INIT_TYPE_READ_STRING_BACK:
james@536 1954 case XEN_INIT_TYPE_READ_STRING_FRONT:
james@536 1955 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
james@536 1956 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 1957 else
james@536 1958 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
james@536 1959 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@536 1960 if (res)
james@536 1961 {
james@617 1962 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
james@536 1963 XenPci_FreeMem(res);
james@617 1964 ADD_XEN_INIT_RSP(&out_ptr, type, setting, "", "");
james@536 1965 }
james@536 1966 else
james@536 1967 {
james@536 1968 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
james@536 1969 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, value2);
james@536 1970 XenPci_FreeMem(value);
james@536 1971 }
james@536 1972 break;
james@536 1973 case XEN_INIT_TYPE_VECTORS:
james@536 1974 // this is always done so ignore the request
james@536 1975 break;
james@536 1976 case XEN_INIT_TYPE_GRANT_ENTRIES:
james@536 1977 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
james@536 1978 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
james@536 1979 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
james@536 1980 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
james@536 1981 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
james@536 1982 for (i = 0; i < PtrToUlong(value); i++)
james@536 1983 {
james@536 1984 gref = GntTbl_GetRef(xpdd);
james@536 1985 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
james@536 1986 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
james@536 1987 }
james@536 1988 break;
james@536 1989 }
james@536 1990 }
james@551 1991 if (active)
james@551 1992 {
james@551 1993 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_ACTIVE, NULL, NULL, NULL);
james@551 1994 }
james@536 1995 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 1996
james@536 1997 if (run_type)
james@536 1998 {
james@551 1999 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 2000) != STATUS_SUCCESS)
james@536 2000 {
james@536 2001 status = STATUS_UNSUCCESSFUL;
james@536 2002 goto error;
james@536 2003 }
james@536 2004 }
james@536 2005 FUNCTION_EXIT();
james@536 2006 return status;
james@551 2007
james@536 2008 error:
james@551 2009 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000);
james@536 2010 FUNCTION_EXIT_STATUS(status);
james@536 2011 return status;
james@536 2012 }
james@536 2013
james@536 2014 static NTSTATUS
james@536 2015 XenPci_XenConfigDevice(WDFDEVICE device)
james@536 2016 {
james@536 2017 NTSTATUS status;
james@536 2018 PUCHAR src, dst;
james@536 2019 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2020
james@536 2021 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
james@536 2022 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
james@536 2023 memcpy(src, dst, xppdd->config_page_length);
james@536 2024
james@536 2025 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
james@536 2026
james@536 2027 MmUnmapIoSpace(dst, xppdd->config_page_length);
james@536 2028 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
james@536 2029
james@536 2030 return status;
james@536 2031 }
james@536 2032
james@536 2033 static NTSTATUS
james@536 2034 XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp)
james@536 2035 {
james@536 2036 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2037 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2038 PIO_STACK_LOCATION stack;
james@536 2039 PCM_PARTIAL_RESOURCE_LIST prl;
james@536 2040 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
james@536 2041 ULONG i;
james@551 2042 //char path[128];
james@551 2043 //PMDL mdl;
james@536 2044
james@536 2045 FUNCTION_ENTER();
james@536 2046 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
james@536 2047
james@536 2048 stack = IoGetCurrentIrpStackLocation(irp);
james@536 2049
james@536 2050 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
james@536 2051 for (i = 0; i < prl->Count; i++)
james@536 2052 {
james@536 2053 prd = & prl->PartialDescriptors[i];
james@536 2054 switch (prd->Type)
james@536 2055 {
james@536 2056 case CmResourceTypeMemory:
james@536 2057 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
james@536 2058 {
james@551 2059 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
james@551 2060 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
james@536 2061 }
james@536 2062 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
james@536 2063 {
james@536 2064 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@536 2065 prd->Type = CmResourceTypeInterrupt;
james@536 2066 prd->ShareDisposition = CmResourceShareShared;
james@536 2067 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
james@536 2068 prd->u.Interrupt.Level = xpdd->irq_number;
james@536 2069 prd->u.Interrupt.Vector = xpdd->irq_number;
james@536 2070 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
james@536 2071 xppdd->irq_number = xpdd->irq_number;
james@536 2072 }
james@536 2073 break;
james@536 2074 }
james@536 2075 }
james@536 2076
james@536 2077 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
james@536 2078 for (i = 0; i < prl->Count; i++)
james@536 2079 {
james@536 2080 prd = & prl->PartialDescriptors[i];
james@536 2081 switch (prd->Type)
james@536 2082 {
james@536 2083 case CmResourceTypeMemory:
james@536 2084 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
james@536 2085 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
james@536 2086 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
james@536 2087 {
james@536 2088 if (prd->u.Memory.Length == 0)
james@536 2089 {
james@551 2090 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0]));
james@551 2091 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
james@551 2092 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
james@536 2093 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 2094 }
james@536 2095 xppdd->config_page_phys = prd->u.Memory.Start;
james@536 2096 xppdd->config_page_length = prd->u.Memory.Length;
james@536 2097 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@536 2098 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@536 2099
james@551 2100 #if 0
james@536 2101 status = XenPci_XenConfigDevice(device);
james@536 2102 if (!NT_SUCCESS(status))
james@536 2103 {
james@536 2104 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@538 2105 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
james@536 2106 FUNCTION_ERROR_EXIT();
james@536 2107 return status;
james@536 2108 }
james@551 2109 #endif
james@536 2110 }
james@536 2111 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
james@536 2112 {
james@536 2113 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@536 2114 prd->Type = CmResourceTypeInterrupt;
james@536 2115 prd->ShareDisposition = CmResourceShareShared;
james@536 2116 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
james@536 2117 prd->u.Interrupt.Level = xpdd->irq_level;
james@536 2118 prd->u.Interrupt.Vector = xpdd->irq_vector;
james@536 2119 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
james@536 2120 xppdd->irq_vector = xpdd->irq_vector;
james@536 2121 xppdd->irq_level = xpdd->irq_level;
james@536 2122 }
james@536 2123 break;
james@536 2124 }
james@536 2125 }
james@536 2126
james@536 2127 IoSkipCurrentIrpStackLocation(irp);
james@536 2128
james@536 2129 FUNCTION_EXIT();
james@536 2130
james@536 2131 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
james@536 2132 }
james@536 2133
james@536 2134 #if 0
james@536 2135 static NTSTATUS
james@536 2136 XenPciPdo_EvtDeviceResourcesQuery(WDFDEVICE device, WDFCMRESLIST resources)
james@536 2137 {
james@536 2138 }
james@536 2139 #endif
james@536 2140
james@536 2141 static NTSTATUS
james@536 2142 XenPciPdo_EvtDeviceResourceRequirementsQuery(WDFDEVICE device, WDFIORESREQLIST requirements_list)
james@536 2143 {
james@536 2144 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2145 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2146 WDFIORESLIST res_list;
james@536 2147 IO_RESOURCE_DESCRIPTOR ird;
james@536 2148
james@538 2149 //FUNCTION_ENTER();
james@536 2150
james@536 2151 WdfIoResourceRequirementsListSetInterfaceType(requirements_list, PNPBus);
james@536 2152
james@536 2153 WdfIoResourceListCreate(requirements_list, WDF_NO_OBJECT_ATTRIBUTES, &res_list);
james@536 2154 ird.Option = 0;
james@536 2155 ird.Type = CmResourceTypeMemory;
james@536 2156 ird.ShareDisposition = CmResourceShareShared;
james@536 2157 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
james@536 2158 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
james@536 2159 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
james@536 2160 ird.u.Memory.Length = 0;
james@536 2161 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
james@536 2162 WdfIoResourceListAppendDescriptor(res_list, &ird);
james@536 2163
james@536 2164 ird.Option = 0;
james@536 2165 ird.Type = CmResourceTypeMemory;
james@536 2166 ird.ShareDisposition = CmResourceShareShared;
james@536 2167 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
james@536 2168 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
james@536 2169 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
james@536 2170 ird.u.Memory.Length = 0;
james@536 2171 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
james@536 2172 WdfIoResourceListAppendDescriptor(res_list, &ird);
james@536 2173
james@536 2174 WdfIoResourceRequirementsListAppendIoResList(requirements_list, res_list);
james@536 2175
james@538 2176 //FUNCTION_EXIT();
james@538 2177
james@538 2178 return STATUS_SUCCESS;
james@538 2179 }
james@538 2180
james@538 2181 NTSTATUS
james@538 2182 XenPciPdo_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
james@538 2183 {
james@538 2184 NTSTATUS status = STATUS_SUCCESS;
james@551 2185 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@551 2186 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@551 2187 CHAR path[128];
james@538 2188
james@538 2189 FUNCTION_ENTER();
james@538 2190
james@538 2191 switch (previous_state)
james@538 2192 {
james@538 2193 case WdfPowerDeviceD0:
james@538 2194 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 2195 break;
james@538 2196 case WdfPowerDeviceD1:
james@538 2197 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 2198 break;
james@538 2199 case WdfPowerDeviceD2:
james@538 2200 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
james@538 2201 break;
james@538 2202 case WdfPowerDeviceD3:
james@538 2203 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
james@538 2204 break;
james@538 2205 case WdfPowerDeviceD3Final:
james@538 2206 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
james@538 2207 break;
james@538 2208 case WdfPowerDevicePrepareForHibernation:
james@538 2209 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
james@538 2210 break;
james@538 2211 default:
james@538 2212 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
james@538 2213 break;
james@538 2214 }
james@551 2215
james@551 2216 if (previous_state == WdfPowerDevicePrepareForHibernation
james@551 2217 || (previous_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
james@551 2218 {
james@551 2219 KdPrint((__DRIVER_NAME " starting up from hibernation\n"));
james@551 2220 }
james@551 2221 else
james@551 2222 {
james@551 2223 }
james@551 2224
james@551 2225 XenConfig_InitConfigPage(device);
james@551 2226
james@551 2227 status = XenPci_GetBackendAndAddWatch(device);
james@551 2228 if (!NT_SUCCESS(status))
james@551 2229 {
james@551 2230 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
james@551 2231 FUNCTION_ERROR_EXIT();
james@551 2232 return status;
james@551 2233 }
james@551 2234 status = XenPci_XenConfigDevice(device);
james@551 2235 if (!NT_SUCCESS(status))
james@551 2236 {
james@551 2237 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@551 2238 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
james@551 2239 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
james@551 2240 FUNCTION_ERROR_EXIT();
james@551 2241 return status;
james@551 2242 }
james@538 2243
james@536 2244 FUNCTION_EXIT();
james@536 2245
james@538 2246 return status;
james@538 2247 }
james@538 2248
james@538 2249 NTSTATUS
james@538 2250 XenPciPdo_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
james@538 2251 {
james@538 2252 NTSTATUS status = STATUS_SUCCESS;
james@538 2253 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@538 2254 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@538 2255 char path[128];
james@538 2256
james@538 2257 UNREFERENCED_PARAMETER(device);
james@538 2258 UNREFERENCED_PARAMETER(target_state);
james@538 2259
james@538 2260 FUNCTION_ENTER();
james@538 2261
james@538 2262 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@538 2263
james@538 2264
james@538 2265 switch (target_state)
james@538 2266 {
james@538 2267 case WdfPowerDeviceD0:
james@538 2268 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 2269 break;
james@538 2270 case WdfPowerDeviceD1:
james@538 2271 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 2272 break;
james@538 2273 case WdfPowerDeviceD2:
james@538 2274 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
james@538 2275 break;
james@538 2276 case WdfPowerDeviceD3:
james@538 2277 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
james@538 2278 break;
james@538 2279 case WdfPowerDeviceD3Final:
james@538 2280 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
james@538 2281 break;
james@538 2282 case WdfPowerDevicePrepareForHibernation:
james@538 2283 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
james@538 2284 break;
james@538 2285 default:
james@538 2286 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
james@538 2287 break;
james@538 2288 }
james@617 2289
james@538 2290 if (target_state == WdfPowerDevicePrepareForHibernation
james@538 2291 || (target_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
james@538 2292 {
james@538 2293 KdPrint((__DRIVER_NAME " not powering down as we are hibernating\n"));
james@538 2294 }
james@538 2295 else
james@538 2296 {
james@538 2297 status = XenPci_XenShutdownDevice(device);
james@538 2298 /* Remove watch on backend state */
james@538 2299 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@538 2300 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
james@538 2301 }
james@538 2302 FUNCTION_EXIT();
james@538 2303
james@538 2304 return status;
james@538 2305 }
james@538 2306
james@538 2307 NTSTATUS
james@551 2308 XenPciPdo_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
james@538 2309 {
james@538 2310 NTSTATUS status = STATUS_SUCCESS;
james@551 2311
james@538 2312 UNREFERENCED_PARAMETER(device);
james@538 2313 UNREFERENCED_PARAMETER(resources_raw);
james@538 2314 UNREFERENCED_PARAMETER(resources_translated);
james@538 2315
james@538 2316 FUNCTION_ENTER();
james@538 2317 FUNCTION_EXIT();
james@538 2318
james@538 2319 return status;
james@538 2320 }
james@538 2321
james@538 2322 NTSTATUS
james@538 2323 XenPciPdo_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
james@538 2324 {
james@538 2325 NTSTATUS status = STATUS_SUCCESS;
james@538 2326
james@538 2327 UNREFERENCED_PARAMETER(device);
james@538 2328 UNREFERENCED_PARAMETER(resources_translated);
james@538 2329
james@538 2330 FUNCTION_ENTER();
james@538 2331 FUNCTION_EXIT();
james@538 2332
james@538 2333 return status;
james@538 2334 }
james@538 2335
james@538 2336 static VOID
james@538 2337 XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
james@538 2338 {
james@538 2339 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@538 2340
james@538 2341 FUNCTION_ENTER();
james@538 2342
james@538 2343 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@538 2344 switch (notification_type)
james@538 2345 {
james@538 2346 case WdfSpecialFilePaging:
james@538 2347 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
james@538 2348 break;
james@538 2349 case WdfSpecialFileHibernation:
james@538 2350 xppdd->hiber_usage_kludge = is_in_notification_path;
james@538 2351 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
james@538 2352 break;
james@538 2353 case WdfSpecialFileDump:
james@538 2354 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
james@538 2355 break;
james@538 2356 default:
james@538 2357 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
james@538 2358 break;
james@538 2359 }
james@538 2360
james@538 2361 FUNCTION_EXIT();
james@536 2362 }
james@536 2363
james@536 2364 NTSTATUS
james@536 2365 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
james@536 2366 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
james@536 2367 PWDFDEVICE_INIT child_init)
james@536 2368 {
james@536 2369 NTSTATUS status = STATUS_SUCCESS;
james@536 2370 WDF_OBJECT_ATTRIBUTES child_attributes;
james@536 2371 WDFDEVICE child_device;
james@536 2372 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
james@536 2373 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
james@536 2374 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
james@536 2375 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
james@536 2376 PXENPCI_PDO_DEVICE_DATA xppdd;
james@536 2377 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
james@536 2378 WDF_QUERY_INTERFACE_CONFIG interface_config;
james@536 2379 BUS_INTERFACE_STANDARD bus_interface;
james@536 2380 WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
james@538 2381 WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
james@536 2382 UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
james@538 2383 WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
james@536 2384
james@536 2385 FUNCTION_ENTER();
james@536 2386
james@536 2387 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
james@536 2388
james@536 2389 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
james@536 2390 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
james@538 2391 //child_pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPciPdo_EvtDeviceD0EntryPostInterruptsEnabled;
james@536 2392 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
james@538 2393 //child_pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPciPdo_EvtDeviceD0ExitPreInterruptsDisabled;
james@536 2394 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenPciPdo_EvtDevicePrepareHardware;
james@536 2395 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenPciPdo_EvtDeviceReleaseHardware;
james@538 2396 child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
james@536 2397 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
james@538 2398
james@536 2399 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
james@536 2400 identification->device, identification->index, identification->path));
james@536 2401
james@536 2402 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
james@536 2403 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
james@536 2404 if (!NT_SUCCESS(status))
james@536 2405 {
james@536 2406 return status;
james@536 2407 }
james@536 2408
james@536 2409 WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
james@536 2410 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
james@536 2411 pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
james@536 2412 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
james@536 2413 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
james@536 2414 WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
james@536 2415
james@536 2416 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
james@536 2417 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
james@536 2418 if (!NT_SUCCESS(status))
james@536 2419 {
james@536 2420 return status;
james@536 2421 }
james@536 2422 status = WdfPdoInitAddHardwareID(child_init, &buffer);
james@536 2423 if (!NT_SUCCESS(status))
james@536 2424 {
james@536 2425 return status;
james@536 2426 }
james@536 2427 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
james@536 2428 if (!NT_SUCCESS(status))
james@536 2429 {
james@536 2430 return status;
james@536 2431 }
james@536 2432
james@536 2433 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
james@536 2434 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
james@536 2435 if (!NT_SUCCESS(status))
james@536 2436 {
james@536 2437 return status;
james@536 2438 }
james@536 2439
james@536 2440 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
james@536 2441 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
james@536 2442 if (!NT_SUCCESS(status))
james@536 2443 {
james@536 2444 return status;
james@536 2445 }
james@536 2446 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
james@538 2447
james@538 2448 WdfDeviceInitSetPowerNotPageable(child_init);
james@536 2449
james@536 2450 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
james@536 2451 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
james@536 2452 if (!NT_SUCCESS(status))
james@536 2453 {
james@536 2454 return status;
james@536 2455 }
james@536 2456
james@536 2457 xppdd = GetXppdd(child_device);
james@536 2458
james@536 2459 xppdd->wdf_device = child_device;
james@536 2460 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
james@536 2461
james@551 2462 xppdd->config_page_mdl = AllocateUncachedPage();
james@551 2463
james@536 2464 xppdd->device_state.magic = XEN_DEVICE_STATE_MAGIC;
james@536 2465 xppdd->device_state.length = sizeof(XENPCI_DEVICE_STATE);
james@536 2466 xppdd->device_state.suspend_resume_state_pdo = SR_STATE_RUNNING;
james@536 2467 xppdd->device_state.suspend_resume_state_fdo = SR_STATE_RUNNING;
james@536 2468 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
james@536 2469 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
james@536 2470 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
james@536 2471 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
james@536 2472
james@536 2473 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
james@536 2474 child_pnp_capabilities.LockSupported = WdfFalse;
james@536 2475 child_pnp_capabilities.EjectSupported = WdfTrue;
james@536 2476 child_pnp_capabilities.Removable = WdfTrue;
james@536 2477 child_pnp_capabilities.DockDevice = WdfFalse;
james@536 2478 child_pnp_capabilities.UniqueID = WdfFalse;
james@536 2479 child_pnp_capabilities.SilentInstall = WdfTrue;
james@536 2480 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
james@536 2481 child_pnp_capabilities.HardwareDisabled = WdfFalse;
james@536 2482 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
james@536 2483
james@538 2484 WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
james@538 2485 child_power_capabilities.DeviceD1 = WdfTrue;
james@538 2486 child_power_capabilities.WakeFromD1 = WdfTrue;
james@538 2487 child_power_capabilities.DeviceWake = PowerDeviceD1;
james@538 2488 child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
james@538 2489 child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
james@538 2490 child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
james@538 2491 child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
james@538 2492 child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
james@538 2493 child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
james@538 2494 WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
james@536 2495
james@536 2496 bus_interface.Size = sizeof(BUS_INTERFACE_STANDARD);
james@536 2497 bus_interface.Version = 1; //BUS_INTERFACE_STANDARD_VERSION;
james@536 2498 bus_interface.Context = xppdd;
james@537 2499 bus_interface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
james@537 2500 bus_interface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
james@536 2501 bus_interface.TranslateBusAddress = XenPci_BIS_TranslateBusAddress;
james@536 2502 bus_interface.GetDmaAdapter = XenPci_BIS_GetDmaAdapter;
james@536 2503 bus_interface.SetBusData = XenPci_BIS_SetBusData;
james@536 2504 bus_interface.GetBusData = XenPci_BIS_GetBusData;
james@536 2505 WDF_QUERY_INTERFACE_CONFIG_INIT(&interface_config, (PINTERFACE)&bus_interface, &GUID_BUS_INTERFACE_STANDARD, NULL);
james@536 2506 status = WdfDeviceAddQueryInterface(child_device, &interface_config);
james@536 2507 if (!NT_SUCCESS(status))
james@536 2508 {
james@536 2509 return status;
james@536 2510 }
james@536 2511
james@536 2512 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
james@536 2513 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
james@536 2514 xppdd->index = identification->index;
james@536 2515 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
james@536 2516 xppdd->backend_state = XenbusStateUnknown;
james@538 2517 xppdd->frontend_state = XenbusStateUnknown;
james@536 2518 xppdd->backend_path[0] = '\0';
james@536 2519
james@536 2520 FUNCTION_EXIT();
james@536 2521
james@536 2522 return status;
james@536 2523 }
james@536 2524
james@536 2525 static __forceinline VOID
james@536 2526 XenPci_Pdo_ChangeSuspendState(WDFDEVICE device, ULONG new_state)
james@536 2527 {
james@536 2528 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2529 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2530
james@536 2531 FUNCTION_ENTER();
james@536 2532 KdPrint((__DRIVER_NAME " setting pdo state to %d\n", new_state));
james@536 2533 xppdd->device_state.suspend_resume_state_pdo = new_state;
james@536 2534 KeMemoryBarrier();
james@536 2535 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xpdd->pdo_event_channel));
james@536 2536 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
james@536 2537 while(xppdd->device_state.suspend_resume_state_fdo != xppdd->device_state.suspend_resume_state_pdo)
james@536 2538 {
james@536 2539 KdPrint((__DRIVER_NAME " waiting...\n"));
james@536 2540 KeWaitForSingleObject(&xpdd->pdo_suspend_event, Executive, KernelMode, FALSE, NULL);
james@536 2541 }
james@536 2542 KdPrint((__DRIVER_NAME " fdo state set to %d\n", new_state));
james@536 2543 FUNCTION_EXIT();
james@536 2544 }
james@536 2545
james@536 2546 /* called at PASSIVE_LEVEL */
james@536 2547 NTSTATUS
james@536 2548 XenPci_Pdo_Suspend(WDFDEVICE device)
james@536 2549 {
james@536 2550 NTSTATUS status = STATUS_SUCCESS;
james@536 2551 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2552 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2553 //LARGE_INTEGER wait_time;
james@536 2554 char path[128];
james@536 2555 PUCHAR in_ptr;
james@536 2556 UCHAR type;
james@536 2557 PVOID setting;
james@536 2558 PVOID value;
james@536 2559 PVOID value2;
james@536 2560
james@536 2561 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
james@536 2562
james@536 2563 if (xppdd->backend_state == XenbusStateConnected)
james@536 2564 {
james@536 2565 xppdd->restart_on_resume = TRUE;
james@536 2566 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_SUSPENDING);
james@536 2567
james@536 2568 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
james@536 2569 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
james@536 2570 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
james@536 2571
james@536 2572 if (xppdd->assigned_resources_start != NULL)
james@536 2573 {
james@536 2574 in_ptr = xppdd->assigned_resources_ptr;
james@536 2575 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 2576 in_ptr = xppdd->assigned_resources_start;
james@536 2577 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
james@536 2578 {
james@536 2579 switch (type)
james@536 2580 {
james@536 2581 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@617 2582 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
james@536 2583 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 2584 EvtChn_Unbind(xpdd, PtrToUlong(value));
james@536 2585 EvtChn_Close(xpdd, PtrToUlong(value));
james@536 2586 break;
james@536 2587 }
james@536 2588 }
james@536 2589 }
james@536 2590
james@536 2591 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@536 2592 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
james@536 2593 }
james@536 2594 else
james@536 2595 {
james@536 2596 xppdd->restart_on_resume = FALSE;
james@536 2597 }
james@536 2598
james@536 2599 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@536 2600
james@536 2601 return status;
james@536 2602 }
james@536 2603
james@536 2604 NTSTATUS
james@536 2605 XenPci_Pdo_Resume(WDFDEVICE device)
james@536 2606 {
james@536 2607 NTSTATUS status = STATUS_SUCCESS;
james@536 2608 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2609 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2610 ULONG old_backend_state;
james@536 2611 PUCHAR src, dst;
james@536 2612
james@536 2613 FUNCTION_ENTER();
james@536 2614 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@536 2615
james@536 2616 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
james@536 2617 old_backend_state = xppdd->backend_state;
james@536 2618
james@536 2619 if (xppdd->restart_on_resume)
james@536 2620 {
james@536 2621 status = XenPci_GetBackendAndAddWatch(device);
james@536 2622
james@536 2623 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
james@536 2624 {
james@536 2625 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
james@536 2626 // this is probably an unrecoverable situation...
james@536 2627 FUNCTION_ERROR_EXIT();
james@536 2628 return STATUS_UNSUCCESSFUL;
james@536 2629 }
james@536 2630 if (xppdd->assigned_resources_ptr)
james@536 2631 {
james@536 2632 // reset things - feed the 'requested resources' back in
james@536 2633 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 2634 src = xppdd->requested_resources_start;
james@536 2635 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
james@536 2636 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
james@536 2637
james@536 2638 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
james@536 2639
james@536 2640 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
james@536 2641
james@536 2642 MmUnmapIoSpace(dst, xppdd->config_page_length);
james@536 2643 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
james@536 2644 }
james@536 2645 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
james@536 2646 {
james@536 2647 // this is definitely an unrecoverable situation...
james@536 2648 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
james@536 2649 FUNCTION_ERROR_EXIT();
james@536 2650 return STATUS_UNSUCCESSFUL;
james@536 2651 }
james@536 2652 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RESUMING);
james@536 2653 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RUNNING);
james@536 2654 }
james@536 2655
james@536 2656 FUNCTION_EXIT();
james@536 2657
james@536 2658 return STATUS_SUCCESS;
james@536 2659 }