win-pvdrivers

annotate xenpci/xenpci_pdo.c @ 621:9c7b7fbacd7f

Windows 7 fix. Interrupt affinity cannot be set to -1 anymore (this is the affinity returned in the resource list). A proper fix that works across multiple Windows OS was implemented. Also, the interrupt level had to be set properly (as outlined in the new Microsoft Windows DDK docs).
author Steve Meisner <steve.meisner@virtualcomputer.com>
date Wed Jul 29 12:43:36 2009 -0400 (2009-07-29)
parents 1478103c6ef5
children 0b55299418ce
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;
steve@621 2068 prd->u.Interrupt.Level = 0; // Set group and level to zero (group = upper word)
steve@621 2069 prd->u.Interrupt.Level = xpdd->irq_number & 0xffff; // Only set the lower word
james@536 2070 prd->u.Interrupt.Vector = xpdd->irq_number;
steve@621 2071 prd->u.Interrupt.Affinity = KeQueryActiveProcessors();
james@536 2072 xppdd->irq_number = xpdd->irq_number;
james@536 2073 }
james@536 2074 break;
james@536 2075 }
james@536 2076 }
james@536 2077
james@536 2078 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
james@536 2079 for (i = 0; i < prl->Count; i++)
james@536 2080 {
james@536 2081 prd = & prl->PartialDescriptors[i];
james@536 2082 switch (prd->Type)
james@536 2083 {
james@536 2084 case CmResourceTypeMemory:
james@536 2085 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
james@536 2086 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
james@536 2087 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
james@536 2088 {
james@536 2089 if (prd->u.Memory.Length == 0)
james@536 2090 {
james@551 2091 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0]));
james@551 2092 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
james@551 2093 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
james@536 2094 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 2095 }
james@536 2096 xppdd->config_page_phys = prd->u.Memory.Start;
james@536 2097 xppdd->config_page_length = prd->u.Memory.Length;
james@536 2098 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@536 2099 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@536 2100
james@551 2101 #if 0
james@536 2102 status = XenPci_XenConfigDevice(device);
james@536 2103 if (!NT_SUCCESS(status))
james@536 2104 {
james@536 2105 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@538 2106 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
james@536 2107 FUNCTION_ERROR_EXIT();
james@536 2108 return status;
james@536 2109 }
james@551 2110 #endif
james@536 2111 }
james@536 2112 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
james@536 2113 {
james@536 2114 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@536 2115 prd->Type = CmResourceTypeInterrupt;
james@536 2116 prd->ShareDisposition = CmResourceShareShared;
james@536 2117 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
steve@621 2118 prd->u.Interrupt.Level = 0; // Set group and level to zero (group = upper word)
steve@621 2119 prd->u.Interrupt.Level = xpdd->irq_level & 0xffff; // Only set the lower word
james@536 2120 prd->u.Interrupt.Vector = xpdd->irq_vector;
steve@621 2121 prd->u.Interrupt.Affinity = KeQueryActiveProcessors();
james@536 2122 xppdd->irq_vector = xpdd->irq_vector;
james@536 2123 xppdd->irq_level = xpdd->irq_level;
james@536 2124 }
james@536 2125 break;
james@536 2126 }
james@536 2127 }
james@536 2128
james@536 2129 IoSkipCurrentIrpStackLocation(irp);
james@536 2130
james@536 2131 FUNCTION_EXIT();
james@536 2132
james@536 2133 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
james@536 2134 }
james@536 2135
james@536 2136 #if 0
james@536 2137 static NTSTATUS
james@536 2138 XenPciPdo_EvtDeviceResourcesQuery(WDFDEVICE device, WDFCMRESLIST resources)
james@536 2139 {
james@536 2140 }
james@536 2141 #endif
james@536 2142
james@536 2143 static NTSTATUS
james@536 2144 XenPciPdo_EvtDeviceResourceRequirementsQuery(WDFDEVICE device, WDFIORESREQLIST requirements_list)
james@536 2145 {
james@536 2146 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2147 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2148 WDFIORESLIST res_list;
james@536 2149 IO_RESOURCE_DESCRIPTOR ird;
james@536 2150
james@538 2151 //FUNCTION_ENTER();
james@536 2152
james@536 2153 WdfIoResourceRequirementsListSetInterfaceType(requirements_list, PNPBus);
james@536 2154
james@536 2155 WdfIoResourceListCreate(requirements_list, WDF_NO_OBJECT_ATTRIBUTES, &res_list);
james@536 2156 ird.Option = 0;
james@536 2157 ird.Type = CmResourceTypeMemory;
james@536 2158 ird.ShareDisposition = CmResourceShareShared;
james@536 2159 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
james@536 2160 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
james@536 2161 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
james@536 2162 ird.u.Memory.Length = 0;
james@536 2163 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
james@536 2164 WdfIoResourceListAppendDescriptor(res_list, &ird);
james@536 2165
james@536 2166 ird.Option = 0;
james@536 2167 ird.Type = CmResourceTypeMemory;
james@536 2168 ird.ShareDisposition = CmResourceShareShared;
james@536 2169 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
james@536 2170 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
james@536 2171 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
james@536 2172 ird.u.Memory.Length = 0;
james@536 2173 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
james@536 2174 WdfIoResourceListAppendDescriptor(res_list, &ird);
james@536 2175
james@536 2176 WdfIoResourceRequirementsListAppendIoResList(requirements_list, res_list);
james@536 2177
james@538 2178 //FUNCTION_EXIT();
james@538 2179
james@538 2180 return STATUS_SUCCESS;
james@538 2181 }
james@538 2182
james@538 2183 NTSTATUS
james@538 2184 XenPciPdo_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
james@538 2185 {
james@538 2186 NTSTATUS status = STATUS_SUCCESS;
james@551 2187 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@551 2188 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@551 2189 CHAR path[128];
james@538 2190
james@538 2191 FUNCTION_ENTER();
james@538 2192
james@538 2193 switch (previous_state)
james@538 2194 {
james@538 2195 case WdfPowerDeviceD0:
james@538 2196 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 2197 break;
james@538 2198 case WdfPowerDeviceD1:
james@538 2199 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 2200 break;
james@538 2201 case WdfPowerDeviceD2:
james@538 2202 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
james@538 2203 break;
james@538 2204 case WdfPowerDeviceD3:
james@538 2205 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
james@538 2206 break;
james@538 2207 case WdfPowerDeviceD3Final:
james@538 2208 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
james@538 2209 break;
james@538 2210 case WdfPowerDevicePrepareForHibernation:
james@538 2211 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
james@538 2212 break;
james@538 2213 default:
james@538 2214 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
james@538 2215 break;
james@538 2216 }
james@551 2217
james@551 2218 if (previous_state == WdfPowerDevicePrepareForHibernation
james@551 2219 || (previous_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
james@551 2220 {
james@551 2221 KdPrint((__DRIVER_NAME " starting up from hibernation\n"));
james@551 2222 }
james@551 2223 else
james@551 2224 {
james@551 2225 }
james@551 2226
james@551 2227 XenConfig_InitConfigPage(device);
james@551 2228
james@551 2229 status = XenPci_GetBackendAndAddWatch(device);
james@551 2230 if (!NT_SUCCESS(status))
james@551 2231 {
james@551 2232 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
james@551 2233 FUNCTION_ERROR_EXIT();
james@551 2234 return status;
james@551 2235 }
james@551 2236 status = XenPci_XenConfigDevice(device);
james@551 2237 if (!NT_SUCCESS(status))
james@551 2238 {
james@551 2239 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@551 2240 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
james@551 2241 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
james@551 2242 FUNCTION_ERROR_EXIT();
james@551 2243 return status;
james@551 2244 }
james@538 2245
james@536 2246 FUNCTION_EXIT();
james@536 2247
james@538 2248 return status;
james@538 2249 }
james@538 2250
james@538 2251 NTSTATUS
james@538 2252 XenPciPdo_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
james@538 2253 {
james@538 2254 NTSTATUS status = STATUS_SUCCESS;
james@538 2255 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@538 2256 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@538 2257 char path[128];
james@538 2258
james@538 2259 UNREFERENCED_PARAMETER(device);
james@538 2260 UNREFERENCED_PARAMETER(target_state);
james@538 2261
james@538 2262 FUNCTION_ENTER();
james@538 2263
james@538 2264 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@538 2265
james@538 2266
james@538 2267 switch (target_state)
james@538 2268 {
james@538 2269 case WdfPowerDeviceD0:
james@538 2270 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 2271 break;
james@538 2272 case WdfPowerDeviceD1:
james@538 2273 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 2274 break;
james@538 2275 case WdfPowerDeviceD2:
james@538 2276 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
james@538 2277 break;
james@538 2278 case WdfPowerDeviceD3:
james@538 2279 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
james@538 2280 break;
james@538 2281 case WdfPowerDeviceD3Final:
james@538 2282 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
james@538 2283 break;
james@538 2284 case WdfPowerDevicePrepareForHibernation:
james@538 2285 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
james@538 2286 break;
james@538 2287 default:
james@538 2288 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
james@538 2289 break;
james@538 2290 }
james@617 2291
james@538 2292 if (target_state == WdfPowerDevicePrepareForHibernation
james@538 2293 || (target_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
james@538 2294 {
james@538 2295 KdPrint((__DRIVER_NAME " not powering down as we are hibernating\n"));
james@538 2296 }
james@538 2297 else
james@538 2298 {
james@538 2299 status = XenPci_XenShutdownDevice(device);
james@538 2300 /* Remove watch on backend state */
james@538 2301 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@538 2302 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
james@538 2303 }
james@538 2304 FUNCTION_EXIT();
james@538 2305
james@538 2306 return status;
james@538 2307 }
james@538 2308
james@538 2309 NTSTATUS
james@551 2310 XenPciPdo_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
james@538 2311 {
james@538 2312 NTSTATUS status = STATUS_SUCCESS;
james@551 2313
james@538 2314 UNREFERENCED_PARAMETER(device);
james@538 2315 UNREFERENCED_PARAMETER(resources_raw);
james@538 2316 UNREFERENCED_PARAMETER(resources_translated);
james@538 2317
james@538 2318 FUNCTION_ENTER();
james@538 2319 FUNCTION_EXIT();
james@538 2320
james@538 2321 return status;
james@538 2322 }
james@538 2323
james@538 2324 NTSTATUS
james@538 2325 XenPciPdo_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
james@538 2326 {
james@538 2327 NTSTATUS status = STATUS_SUCCESS;
james@538 2328
james@538 2329 UNREFERENCED_PARAMETER(device);
james@538 2330 UNREFERENCED_PARAMETER(resources_translated);
james@538 2331
james@538 2332 FUNCTION_ENTER();
james@538 2333 FUNCTION_EXIT();
james@538 2334
james@538 2335 return status;
james@538 2336 }
james@538 2337
james@538 2338 static VOID
james@538 2339 XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
james@538 2340 {
james@538 2341 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@538 2342
james@538 2343 FUNCTION_ENTER();
james@538 2344
james@538 2345 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@538 2346 switch (notification_type)
james@538 2347 {
james@538 2348 case WdfSpecialFilePaging:
james@538 2349 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
james@538 2350 break;
james@538 2351 case WdfSpecialFileHibernation:
james@538 2352 xppdd->hiber_usage_kludge = is_in_notification_path;
james@538 2353 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
james@538 2354 break;
james@538 2355 case WdfSpecialFileDump:
james@538 2356 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
james@538 2357 break;
james@538 2358 default:
james@538 2359 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
james@538 2360 break;
james@538 2361 }
james@538 2362
james@538 2363 FUNCTION_EXIT();
james@536 2364 }
james@536 2365
james@536 2366 NTSTATUS
james@536 2367 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
james@536 2368 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
james@536 2369 PWDFDEVICE_INIT child_init)
james@536 2370 {
james@536 2371 NTSTATUS status = STATUS_SUCCESS;
james@536 2372 WDF_OBJECT_ATTRIBUTES child_attributes;
james@536 2373 WDFDEVICE child_device;
james@536 2374 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
james@536 2375 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
james@536 2376 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
james@536 2377 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
james@536 2378 PXENPCI_PDO_DEVICE_DATA xppdd;
james@536 2379 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
james@536 2380 WDF_QUERY_INTERFACE_CONFIG interface_config;
james@536 2381 BUS_INTERFACE_STANDARD bus_interface;
james@536 2382 WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
james@538 2383 WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
james@536 2384 UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
james@538 2385 WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
james@536 2386
james@536 2387 FUNCTION_ENTER();
james@536 2388
james@536 2389 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
james@536 2390
james@536 2391 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
james@536 2392 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
james@538 2393 //child_pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPciPdo_EvtDeviceD0EntryPostInterruptsEnabled;
james@536 2394 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
james@538 2395 //child_pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPciPdo_EvtDeviceD0ExitPreInterruptsDisabled;
james@536 2396 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenPciPdo_EvtDevicePrepareHardware;
james@536 2397 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenPciPdo_EvtDeviceReleaseHardware;
james@538 2398 child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
james@536 2399 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
james@538 2400
james@536 2401 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
james@536 2402 identification->device, identification->index, identification->path));
james@536 2403
james@536 2404 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
james@536 2405 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
james@536 2406 if (!NT_SUCCESS(status))
james@536 2407 {
james@536 2408 return status;
james@536 2409 }
james@536 2410
james@536 2411 WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
james@536 2412 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
james@536 2413 pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
james@536 2414 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
james@536 2415 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
james@536 2416 WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
james@536 2417
james@536 2418 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
james@536 2419 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
james@536 2420 if (!NT_SUCCESS(status))
james@536 2421 {
james@536 2422 return status;
james@536 2423 }
james@536 2424 status = WdfPdoInitAddHardwareID(child_init, &buffer);
james@536 2425 if (!NT_SUCCESS(status))
james@536 2426 {
james@536 2427 return status;
james@536 2428 }
james@536 2429 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
james@536 2430 if (!NT_SUCCESS(status))
james@536 2431 {
james@536 2432 return status;
james@536 2433 }
james@536 2434
james@536 2435 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
james@536 2436 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
james@536 2437 if (!NT_SUCCESS(status))
james@536 2438 {
james@536 2439 return status;
james@536 2440 }
james@536 2441
james@536 2442 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
james@536 2443 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
james@536 2444 if (!NT_SUCCESS(status))
james@536 2445 {
james@536 2446 return status;
james@536 2447 }
james@536 2448 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
james@538 2449
james@538 2450 WdfDeviceInitSetPowerNotPageable(child_init);
james@536 2451
james@536 2452 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
james@536 2453 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
james@536 2454 if (!NT_SUCCESS(status))
james@536 2455 {
james@536 2456 return status;
james@536 2457 }
james@536 2458
james@536 2459 xppdd = GetXppdd(child_device);
james@536 2460
james@536 2461 xppdd->wdf_device = child_device;
james@536 2462 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
james@536 2463
james@551 2464 xppdd->config_page_mdl = AllocateUncachedPage();
james@551 2465
james@536 2466 xppdd->device_state.magic = XEN_DEVICE_STATE_MAGIC;
james@536 2467 xppdd->device_state.length = sizeof(XENPCI_DEVICE_STATE);
james@536 2468 xppdd->device_state.suspend_resume_state_pdo = SR_STATE_RUNNING;
james@536 2469 xppdd->device_state.suspend_resume_state_fdo = SR_STATE_RUNNING;
james@536 2470 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
james@536 2471 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
james@536 2472 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
james@536 2473 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
james@536 2474
james@536 2475 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
james@536 2476 child_pnp_capabilities.LockSupported = WdfFalse;
james@536 2477 child_pnp_capabilities.EjectSupported = WdfTrue;
james@536 2478 child_pnp_capabilities.Removable = WdfTrue;
james@536 2479 child_pnp_capabilities.DockDevice = WdfFalse;
james@536 2480 child_pnp_capabilities.UniqueID = WdfFalse;
james@536 2481 child_pnp_capabilities.SilentInstall = WdfTrue;
james@536 2482 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
james@536 2483 child_pnp_capabilities.HardwareDisabled = WdfFalse;
james@536 2484 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
james@536 2485
james@538 2486 WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
james@538 2487 child_power_capabilities.DeviceD1 = WdfTrue;
james@538 2488 child_power_capabilities.WakeFromD1 = WdfTrue;
james@538 2489 child_power_capabilities.DeviceWake = PowerDeviceD1;
james@538 2490 child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
james@538 2491 child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
james@538 2492 child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
james@538 2493 child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
james@538 2494 child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
james@538 2495 child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
james@538 2496 WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
james@536 2497
james@536 2498 bus_interface.Size = sizeof(BUS_INTERFACE_STANDARD);
james@536 2499 bus_interface.Version = 1; //BUS_INTERFACE_STANDARD_VERSION;
james@536 2500 bus_interface.Context = xppdd;
james@537 2501 bus_interface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
james@537 2502 bus_interface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
james@536 2503 bus_interface.TranslateBusAddress = XenPci_BIS_TranslateBusAddress;
james@536 2504 bus_interface.GetDmaAdapter = XenPci_BIS_GetDmaAdapter;
james@536 2505 bus_interface.SetBusData = XenPci_BIS_SetBusData;
james@536 2506 bus_interface.GetBusData = XenPci_BIS_GetBusData;
james@536 2507 WDF_QUERY_INTERFACE_CONFIG_INIT(&interface_config, (PINTERFACE)&bus_interface, &GUID_BUS_INTERFACE_STANDARD, NULL);
james@536 2508 status = WdfDeviceAddQueryInterface(child_device, &interface_config);
james@536 2509 if (!NT_SUCCESS(status))
james@536 2510 {
james@536 2511 return status;
james@536 2512 }
james@536 2513
james@536 2514 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
james@536 2515 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
james@536 2516 xppdd->index = identification->index;
james@536 2517 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
james@536 2518 xppdd->backend_state = XenbusStateUnknown;
james@538 2519 xppdd->frontend_state = XenbusStateUnknown;
james@536 2520 xppdd->backend_path[0] = '\0';
james@536 2521
james@536 2522 FUNCTION_EXIT();
james@536 2523
james@536 2524 return status;
james@536 2525 }
james@536 2526
james@536 2527 static __forceinline VOID
james@536 2528 XenPci_Pdo_ChangeSuspendState(WDFDEVICE device, ULONG new_state)
james@536 2529 {
james@536 2530 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2531 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2532
james@536 2533 FUNCTION_ENTER();
james@536 2534 KdPrint((__DRIVER_NAME " setting pdo state to %d\n", new_state));
james@536 2535 xppdd->device_state.suspend_resume_state_pdo = new_state;
james@536 2536 KeMemoryBarrier();
james@536 2537 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xpdd->pdo_event_channel));
james@536 2538 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
james@536 2539 while(xppdd->device_state.suspend_resume_state_fdo != xppdd->device_state.suspend_resume_state_pdo)
james@536 2540 {
james@536 2541 KdPrint((__DRIVER_NAME " waiting...\n"));
james@536 2542 KeWaitForSingleObject(&xpdd->pdo_suspend_event, Executive, KernelMode, FALSE, NULL);
james@536 2543 }
james@536 2544 KdPrint((__DRIVER_NAME " fdo state set to %d\n", new_state));
james@536 2545 FUNCTION_EXIT();
james@536 2546 }
james@536 2547
james@536 2548 /* called at PASSIVE_LEVEL */
james@536 2549 NTSTATUS
james@536 2550 XenPci_Pdo_Suspend(WDFDEVICE device)
james@536 2551 {
james@536 2552 NTSTATUS status = STATUS_SUCCESS;
james@536 2553 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2554 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2555 //LARGE_INTEGER wait_time;
james@536 2556 char path[128];
james@536 2557 PUCHAR in_ptr;
james@536 2558 UCHAR type;
james@536 2559 PVOID setting;
james@536 2560 PVOID value;
james@536 2561 PVOID value2;
james@536 2562
james@536 2563 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
james@536 2564
james@536 2565 if (xppdd->backend_state == XenbusStateConnected)
james@536 2566 {
james@536 2567 xppdd->restart_on_resume = TRUE;
james@536 2568 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_SUSPENDING);
james@536 2569
james@536 2570 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
james@536 2571 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
james@536 2572 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
james@536 2573
james@536 2574 if (xppdd->assigned_resources_start != NULL)
james@536 2575 {
james@536 2576 in_ptr = xppdd->assigned_resources_ptr;
james@536 2577 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 2578 in_ptr = xppdd->assigned_resources_start;
james@536 2579 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
james@536 2580 {
james@536 2581 switch (type)
james@536 2582 {
james@536 2583 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@617 2584 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
james@536 2585 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 2586 EvtChn_Unbind(xpdd, PtrToUlong(value));
james@536 2587 EvtChn_Close(xpdd, PtrToUlong(value));
james@536 2588 break;
james@536 2589 }
james@536 2590 }
james@536 2591 }
james@536 2592
james@536 2593 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@536 2594 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
james@536 2595 }
james@536 2596 else
james@536 2597 {
james@536 2598 xppdd->restart_on_resume = FALSE;
james@536 2599 }
james@536 2600
james@536 2601 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@536 2602
james@536 2603 return status;
james@536 2604 }
james@536 2605
james@536 2606 NTSTATUS
james@536 2607 XenPci_Pdo_Resume(WDFDEVICE device)
james@536 2608 {
james@536 2609 NTSTATUS status = STATUS_SUCCESS;
james@536 2610 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2611 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2612 ULONG old_backend_state;
james@536 2613 PUCHAR src, dst;
james@536 2614
james@536 2615 FUNCTION_ENTER();
james@536 2616 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@536 2617
james@536 2618 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
james@536 2619 old_backend_state = xppdd->backend_state;
james@536 2620
james@536 2621 if (xppdd->restart_on_resume)
james@536 2622 {
james@536 2623 status = XenPci_GetBackendAndAddWatch(device);
james@536 2624
james@536 2625 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
james@536 2626 {
james@536 2627 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
james@536 2628 // this is probably an unrecoverable situation...
james@536 2629 FUNCTION_ERROR_EXIT();
james@536 2630 return STATUS_UNSUCCESSFUL;
james@536 2631 }
james@536 2632 if (xppdd->assigned_resources_ptr)
james@536 2633 {
james@536 2634 // reset things - feed the 'requested resources' back in
james@536 2635 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 2636 src = xppdd->requested_resources_start;
james@536 2637 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
james@536 2638 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
james@536 2639
james@536 2640 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
james@536 2641
james@536 2642 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
james@536 2643
james@536 2644 MmUnmapIoSpace(dst, xppdd->config_page_length);
james@536 2645 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
james@536 2646 }
james@536 2647 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
james@536 2648 {
james@536 2649 // this is definitely an unrecoverable situation...
james@536 2650 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
james@536 2651 FUNCTION_ERROR_EXIT();
james@536 2652 return STATUS_UNSUCCESSFUL;
james@536 2653 }
james@536 2654 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RESUMING);
james@536 2655 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RUNNING);
james@536 2656 }
james@536 2657
james@536 2658 FUNCTION_EXIT();
james@536 2659
james@536 2660 return STATUS_SUCCESS;
james@536 2661 }