win-pvdrivers

annotate xenpci/xenpci_pdo.c @ 538:e75bb8d68370

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