win-pvdrivers

annotate xenpci/xenpci_pdo.c @ 551:a88fe72e3597

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