win-pvdrivers

annotate xenpci/xenpci_pdo.c @ 561:d56ecda9e61f

Interrupt delivery updates.
SG updates
Removed XenHide and made XenPci also function as a filter device
author James Harper <james.harper@bendigoit.com.au>
date Sun May 10 20:17:05 2009 +1000 (2009-05-10)
parents bbac251831a8
children 1ca6f17ebc47
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@558 36 BOOLEAN allocated_by_me;
james@537 37 } sg_extra_t;
james@537 38
james@537 39 typedef struct {
james@537 40 ULONG map_type;
james@537 41 PVOID aligned_buffer;
james@537 42 PVOID unaligned_buffer;
james@537 43 ULONG copy_length;
james@537 44 PHYSICAL_ADDRESS logical;
james@537 45 } map_register_t;
james@537 46
james@537 47 typedef struct {
james@537 48 PDEVICE_OBJECT device_object;
james@537 49 ULONG total_map_registers;
james@537 50 ULONG count;
james@537 51 map_register_t regs[1];
james@537 52 } map_register_base_t;
james@536 53
james@536 54 static BOOLEAN
james@536 55 XenPci_BIS_TranslateBusAddress(PVOID context, PHYSICAL_ADDRESS bus_address, ULONG length, PULONG address_space, PPHYSICAL_ADDRESS translated_address)
james@536 56 {
james@536 57 UNREFERENCED_PARAMETER(context);
james@536 58 UNREFERENCED_PARAMETER(length);
james@536 59 /* actually this isn't right - should look up the gref for the physical address and work backwards from that */
james@536 60 FUNCTION_ENTER();
james@536 61 if (*address_space != 0)
james@536 62 {
james@536 63 KdPrint((__DRIVER_NAME " Cannot map I/O space\n"));
james@536 64 FUNCTION_EXIT();
james@536 65 return FALSE;
james@536 66 }
james@536 67 *translated_address = bus_address;
james@536 68 FUNCTION_EXIT();
james@536 69 return TRUE;
james@536 70 }
james@536 71
james@536 72 static VOID
james@536 73 XenPci_DOP_PutDmaAdapter(PDMA_ADAPTER dma_adapter)
james@536 74 {
james@537 75 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
james@536 76
james@536 77 FUNCTION_ENTER();
james@537 78
james@537 79 if (xen_dma_adapter->dma_extension)
james@537 80 ObDereferenceObject(xen_dma_adapter->dma_extension_driver);
james@538 81 ExFreePoolWithTag(xen_dma_adapter->adapter_object.DmaHeader.DmaOperations, XENPCI_POOL_TAG);
james@537 82 ExFreePoolWithTag(xen_dma_adapter, XENPCI_POOL_TAG);
james@537 83
james@536 84 FUNCTION_EXIT();
james@536 85
james@536 86 return;
james@536 87 }
james@536 88
james@536 89 static PVOID
james@536 90 XenPci_DOP_AllocateCommonBuffer(
james@536 91 PDMA_ADAPTER DmaAdapter,
james@536 92 ULONG Length,
james@536 93 PPHYSICAL_ADDRESS LogicalAddress,
james@536 94 BOOLEAN CacheEnabled
james@536 95 )
james@536 96 {
james@537 97 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
james@536 98 PXENPCI_DEVICE_DATA xpdd;
james@536 99 PVOID buffer;
james@536 100 PFN_NUMBER pfn;
james@536 101 grant_ref_t gref;
james@536 102
james@536 103 UNREFERENCED_PARAMETER(DmaAdapter);
james@536 104 UNREFERENCED_PARAMETER(CacheEnabled);
james@536 105
james@536 106 //FUNCTION_ENTER();
james@536 107
james@536 108 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@536 109
james@536 110 //KdPrint((__DRIVER_NAME " Length = %d\n", Length));
james@536 111
james@536 112 buffer = ExAllocatePoolWithTag(NonPagedPool, Length, XENPCI_POOL_TAG);
james@538 113 ASSERT(buffer); /* lazy */
james@536 114
james@536 115 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(buffer).QuadPart >> PAGE_SHIFT);
james@538 116 ASSERT(pfn); /* lazy */
james@551 117 //KdPrint((__DRIVER_NAME " A Requesting Grant Ref\n"));
james@537 118 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
james@551 119 //KdPrint((__DRIVER_NAME " A Got Grant Ref %d\n", gref));
james@538 120 ASSERT(gref); /* lazy */
james@536 121 LogicalAddress->QuadPart = (gref << PAGE_SHIFT) | (PtrToUlong(buffer) & (PAGE_SIZE - 1));
james@536 122
james@536 123 //FUNCTION_EXIT();
james@536 124 return buffer;
james@536 125 }
james@536 126
james@536 127 static VOID
james@536 128 XenPci_DOP_FreeCommonBuffer(
james@536 129 PDMA_ADAPTER dma_adapter,
james@536 130 ULONG length,
james@536 131 PHYSICAL_ADDRESS logical_address,
james@536 132 PVOID virtual_address,
james@536 133 BOOLEAN cache_enabled
james@536 134 )
james@536 135 {
james@536 136 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
james@536 137 PXENPCI_DEVICE_DATA xpdd;
james@536 138 grant_ref_t gref;
james@536 139
james@536 140 UNREFERENCED_PARAMETER(dma_adapter);
james@536 141 UNREFERENCED_PARAMETER(length);
james@536 142 UNREFERENCED_PARAMETER(cache_enabled);
james@536 143
james@537 144 // FUNCTION_ENTER();
james@536 145
james@536 146 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@536 147 gref = (grant_ref_t)(logical_address.QuadPart >> PAGE_SHIFT);
james@551 148 //KdPrint((__DRIVER_NAME " F Releasing Grant Ref %d\n", gref));
james@536 149 GntTbl_EndAccess(xpdd, gref, FALSE);
james@551 150 //KdPrint((__DRIVER_NAME " F Released Grant Ref\n"));
james@536 151 ExFreePoolWithTag(virtual_address, XENPCI_POOL_TAG);
james@536 152
james@537 153 // FUNCTION_EXIT();
james@536 154 }
james@536 155
james@536 156 static NTSTATUS
james@536 157 XenPci_DOP_AllocateAdapterChannel(
james@537 158 IN PDMA_ADAPTER dma_adapter,
james@537 159 IN PDEVICE_OBJECT device_object,
james@537 160 IN ULONG NumberOfMapRegisters,
james@537 161 IN PDRIVER_CONTROL ExecutionRoutine,
james@537 162 IN PVOID Context
james@536 163 )
james@536 164 {
james@537 165 //xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
james@537 166 //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@536 167 IO_ALLOCATION_ACTION action;
james@537 168 map_register_base_t *map_register_base;
james@536 169
james@537 170 UNREFERENCED_PARAMETER(dma_adapter);
james@536 171
james@537 172 //FUNCTION_ENTER();
james@537 173
james@537 174 map_register_base = ExAllocatePoolWithTag(NonPagedPool,
james@537 175 FIELD_OFFSET(map_register_base_t, regs) + NumberOfMapRegisters * sizeof(map_register_t), XENPCI_POOL_TAG);
james@537 176 if (!map_register_base)
james@537 177 {
james@537 178 KdPrint((__DRIVER_NAME " Cannot allocate memory for map_register_base\n"));
james@538 179 //FUNCTION_EXIT();
james@537 180 return STATUS_INSUFFICIENT_RESOURCES;
james@537 181 }
james@537 182 /* 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 183 map_register_base->device_object = device_object;
james@537 184 map_register_base->total_map_registers = NumberOfMapRegisters;
james@537 185 map_register_base->count = 0;
james@537 186
james@537 187 action = ExecutionRoutine(device_object, device_object->CurrentIrp, map_register_base, Context);
james@536 188
james@536 189 switch (action)
james@536 190 {
james@536 191 case KeepObject:
james@536 192 KdPrint((__DRIVER_NAME " KeepObject\n"));
james@537 193 ASSERT(FALSE);
james@536 194 break;
james@536 195 case DeallocateObject:
james@536 196 KdPrint((__DRIVER_NAME " DeallocateObject\n"));
james@537 197 ASSERT(FALSE);
james@536 198 break;
james@536 199 case DeallocateObjectKeepRegisters:
james@537 200 //KdPrint((__DRIVER_NAME " DeallocateObjectKeepRegisters\n"));
james@536 201 break;
james@536 202 default:
james@536 203 KdPrint((__DRIVER_NAME " Unknown action %d\n", action));
james@537 204 ASSERT(FALSE);
james@536 205 break;
james@536 206 }
james@537 207 //FUNCTION_EXIT();
james@536 208 return STATUS_SUCCESS;
james@536 209 }
james@536 210
james@536 211 static BOOLEAN
james@536 212 XenPci_DOP_FlushAdapterBuffers(
james@537 213 PDMA_ADAPTER dma_adapter,
james@537 214 PMDL mdl,
james@536 215 PVOID MapRegisterBase,
james@536 216 PVOID CurrentVa,
james@536 217 ULONG Length,
james@537 218 BOOLEAN write_to_device)
james@536 219 {
james@537 220 //xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
james@537 221 //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@537 222 map_register_base_t *map_register_base = MapRegisterBase;
james@537 223 map_register_t *map_register;
james@537 224 ULONG i;
james@537 225
james@537 226 UNREFERENCED_PARAMETER(dma_adapter);
james@537 227 UNREFERENCED_PARAMETER(mdl);
james@536 228 UNREFERENCED_PARAMETER(CurrentVa);
james@536 229 UNREFERENCED_PARAMETER(Length);
james@537 230
james@537 231 //FUNCTION_ENTER();
james@537 232
james@537 233 for (i = 0; i < map_register_base->count; i++)
james@537 234 {
james@537 235 map_register = &map_register_base->regs[i];
james@537 236 if (map_register->map_type == MAP_TYPE_REMAPPED && !write_to_device)
james@537 237 memcpy(map_register->unaligned_buffer, map_register->aligned_buffer, map_register->copy_length);
james@537 238 }
james@537 239 //FUNCTION_EXIT();
james@537 240
james@536 241 return TRUE;
james@536 242 }
james@536 243
james@536 244 static VOID
james@536 245 XenPci_DOP_FreeAdapterChannel(
james@536 246 IN PDMA_ADAPTER DmaAdapter
james@536 247 )
james@536 248 {
james@536 249 UNREFERENCED_PARAMETER(DmaAdapter);
james@536 250
james@536 251 FUNCTION_ENTER();
james@536 252 FUNCTION_EXIT();
james@536 253 }
james@536 254
james@536 255 static VOID
james@536 256 XenPci_DOP_FreeMapRegisters(
james@537 257 PDMA_ADAPTER dma_adapter,
james@536 258 PVOID MapRegisterBase,
james@536 259 ULONG NumberOfMapRegisters)
james@536 260 {
james@537 261 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
james@537 262 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@537 263 map_register_base_t *map_register_base = MapRegisterBase;
james@537 264 map_register_t *map_register;
james@537 265 ULONG i;
james@537 266 grant_ref_t gref;
james@537 267
james@537 268 //FUNCTION_ENTER();
james@537 269 ASSERT(map_register_base->total_map_registers == NumberOfMapRegisters);
james@537 270
james@537 271 for (i = 0; i < map_register_base->count; i++)
james@537 272 {
james@537 273 map_register = &map_register_base->regs[i];
james@537 274 switch (map_register->map_type)
james@537 275 {
james@537 276 case MAP_TYPE_REMAPPED:
james@537 277 gref = (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT);
james@551 278 //KdPrint((__DRIVER_NAME " D Releasing Grant Ref %d\n", gref));
james@537 279 GntTbl_EndAccess(xpdd, gref, FALSE);
james@551 280 //KdPrint((__DRIVER_NAME " D Released Grant Ref\n"));
james@537 281 ExFreePoolWithTag(map_register->aligned_buffer, XENPCI_POOL_TAG);
james@537 282 break;
james@537 283 case MAP_TYPE_MDL:
james@537 284 gref = (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT);
james@551 285 //KdPrint((__DRIVER_NAME " E Releasing Grant Ref %d\n", gref));
james@537 286 GntTbl_EndAccess(xpdd, gref, FALSE);
james@551 287 //KdPrint((__DRIVER_NAME " E Released Grant Ref\n"));
james@537 288 break;
james@537 289 case MAP_TYPE_VIRTUAL:
james@537 290 break;
james@537 291 }
james@537 292 }
james@537 293 ExFreePoolWithTag(map_register_base, XENPCI_POOL_TAG);
james@537 294
james@537 295 //FUNCTION_EXIT();
james@536 296 }
james@536 297
james@536 298 static PHYSICAL_ADDRESS
james@536 299 XenPci_DOP_MapTransfer(
james@537 300 PDMA_ADAPTER dma_adapter,
james@537 301 PMDL mdl,
james@536 302 PVOID MapRegisterBase,
james@536 303 PVOID CurrentVa,
james@536 304 PULONG Length,
james@536 305 BOOLEAN WriteToDevice)
james@536 306 {
james@537 307 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
james@537 308 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@537 309 map_register_base_t *map_register_base = MapRegisterBase;
james@537 310 map_register_t *map_register = &map_register_base->regs[map_register_base->count];
james@537 311 PDEVICE_OBJECT device_object = map_register_base->device_object;
james@537 312 ULONG page_offset;
james@537 313 PFN_NUMBER pfn;
james@537 314 grant_ref_t gref;
james@537 315 PUCHAR ptr;
james@537 316 ULONG mdl_offset;
james@537 317 ULONG pfn_index;
james@537 318
james@537 319 //FUNCTION_ENTER();
james@537 320
james@537 321 //KdPrint((__DRIVER_NAME " Mdl = %p, MapRegisterBase = %p, MdlVa = %p, CurrentVa = %p, Length = %d\n",
james@537 322 // mdl, MapRegisterBase, MmGetMdlVirtualAddress(mdl), CurrentVa, *Length));
james@537 323
james@537 324 ASSERT(mdl);
james@537 325 ASSERT(map_register_base->count < map_register_base->total_map_registers);
james@536 326
james@537 327 if (xen_dma_adapter->dma_extension)
james@537 328 {
james@558 329 if (xen_dma_adapter->dma_extension->need_virtual_address && xen_dma_adapter->dma_extension->need_virtual_address(device_object->CurrentIrp))
james@537 330 {
james@537 331 map_register->map_type = MAP_TYPE_VIRTUAL;
james@537 332 }
james@537 333 else
james@537 334 {
james@558 335 if (xen_dma_adapter->dma_extension->get_alignment)
james@537 336 {
james@558 337 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(device_object->CurrentIrp);
james@558 338 if ((MmGetMdlByteOffset(mdl) & (alignment - 1)) || (MmGetMdlByteCount(mdl) & (alignment - 1)))
james@558 339 {
james@558 340 map_register->map_type = MAP_TYPE_REMAPPED;
james@558 341 }
james@558 342 else
james@558 343 {
james@558 344 map_register->map_type = MAP_TYPE_MDL;
james@558 345 }
james@537 346 }
james@537 347 else
james@537 348 {
james@537 349 map_register->map_type = MAP_TYPE_MDL;
james@537 350 }
james@537 351 }
james@537 352 }
james@537 353 else
james@537 354 {
james@537 355 map_register->map_type = MAP_TYPE_MDL;
james@537 356 }
james@537 357
james@537 358 switch (map_register->map_type)
james@537 359 {
james@537 360 case MAP_TYPE_MDL:
james@537 361 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL\n"));
james@537 362 mdl_offset = (ULONG)((ULONGLONG)CurrentVa - (ULONGLONG)MmGetMdlVirtualAddress(mdl));
james@537 363 page_offset = PtrToUlong(CurrentVa) & (PAGE_SIZE - 1);
james@537 364 *Length = min(*Length, PAGE_SIZE - page_offset);
james@537 365 pfn_index = (ULONG)(((ULONGLONG)CurrentVa >> PAGE_SHIFT) - ((ULONGLONG)MmGetMdlVirtualAddress(mdl) >> PAGE_SHIFT));
james@537 366 //KdPrint((__DRIVER_NAME " mdl_offset = %d, page_offset = %d, length = %d, pfn_index = %d\n",
james@537 367 // mdl_offset, page_offset, *Length, pfn_index));
james@537 368 pfn = MmGetMdlPfnArray(mdl)[pfn_index];
james@551 369 //KdPrint((__DRIVER_NAME " B Requesting Grant Ref\n"));
james@537 370 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
james@551 371 //KdPrint((__DRIVER_NAME " B Got Grant Ref %d\n", gref));
james@537 372 map_register->logical.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | page_offset;
james@537 373 map_register_base->count++;
james@537 374 break;
james@537 375 case MAP_TYPE_REMAPPED:
james@551 376 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED (MapTransfer)\n"));
james@551 377 //KdPrint((__DRIVER_NAME " Mdl = %p, MapRegisterBase = %p, MdlVa = %p, CurrentVa = %p, Length = %d\n",
james@551 378 // mdl, MapRegisterBase, MmGetMdlVirtualAddress(mdl), CurrentVa, *Length));
james@551 379 mdl_offset = (ULONG)((ULONGLONG)CurrentVa - (ULONGLONG)MmGetMdlVirtualAddress(mdl));
james@537 380 *Length = min(*Length, PAGE_SIZE);
james@537 381 map_register->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@537 382 ASSERT(map_register->aligned_buffer);
james@537 383 map_register->unaligned_buffer = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
james@537 384 ASSERT(map_register->unaligned_buffer); /* lazy */
james@551 385 map_register->unaligned_buffer = (PUCHAR)map_register->unaligned_buffer + mdl_offset;
james@537 386 map_register->copy_length = *Length;
james@537 387 if (WriteToDevice)
james@537 388 memcpy(map_register->aligned_buffer, map_register->unaligned_buffer, map_register->copy_length);
james@537 389 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(map_register->aligned_buffer).QuadPart >> PAGE_SHIFT);
james@551 390 //KdPrint((__DRIVER_NAME " C Requesting Grant Ref\n"));
james@537 391 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
james@551 392 //KdPrint((__DRIVER_NAME " C Got Grant Ref %d\n", gref));
james@537 393 map_register->logical.QuadPart = (LONGLONG)(gref << PAGE_SHIFT);
james@537 394 map_register_base->count++;
james@537 395 break;
james@537 396 case MAP_TYPE_VIRTUAL:
james@537 397 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL\n"));
james@537 398 ptr = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
james@537 399 ASSERT(ptr); /* lazy */
james@537 400 map_register->logical.QuadPart = (ULONGLONG)ptr;
james@537 401 map_register_base->count++;
james@537 402 break;
james@537 403 default:
james@537 404 ASSERT(FALSE);
james@537 405 break;
james@537 406 }
james@536 407
james@538 408 //KdPrint((__DRIVER_NAME " logical = %08x:%08x\n", map_register->logical.HighPart, map_register->logical.LowPart));
james@537 409 //FUNCTION_EXIT();
james@537 410 return map_register->logical;
james@536 411 }
james@536 412
james@536 413 static ULONG
james@536 414 XenPci_DOP_GetDmaAlignment(
james@536 415 PDMA_ADAPTER DmaAdapter)
james@536 416 {
james@536 417 UNREFERENCED_PARAMETER(DmaAdapter);
james@536 418
james@536 419 FUNCTION_ENTER();
james@536 420 FUNCTION_EXIT();
james@536 421 return 0;
james@536 422 }
james@536 423
james@536 424 static ULONG
james@536 425 XenPci_DOP_ReadDmaCounter(
james@536 426 PDMA_ADAPTER DmaAdapter)
james@536 427 {
james@536 428 UNREFERENCED_PARAMETER(DmaAdapter);
james@536 429
james@536 430 FUNCTION_ENTER();
james@536 431 FUNCTION_EXIT();
james@536 432 return 0;
james@536 433 }
james@536 434
james@536 435 static VOID
james@536 436 XenPci_DOP_PutScatterGatherList(
james@536 437 IN PDMA_ADAPTER DmaAdapter,
james@558 438 IN PSCATTER_GATHER_LIST sg_list,
james@536 439 IN BOOLEAN WriteToDevice
james@536 440 )
james@536 441 {
james@536 442 xen_dma_adapter_t *xen_dma_adapter;
james@536 443 PXENPCI_DEVICE_DATA xpdd;
james@536 444 ULONG i;
james@536 445 sg_extra_t *sg_extra;
james@536 446
james@536 447 UNREFERENCED_PARAMETER(WriteToDevice);
james@536 448
james@536 449 //FUNCTION_ENTER();
james@536 450
james@536 451 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
james@536 452 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@536 453
james@558 454 sg_extra = (sg_extra_t *)((PUCHAR)sg_list + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
james@558 455 (sizeof(SCATTER_GATHER_ELEMENT)) * sg_list->NumberOfElements);
james@536 456
james@536 457 switch (sg_extra->map_type)
james@536 458 {
james@536 459 case MAP_TYPE_REMAPPED:
james@558 460 for (i = 0; i < sg_list->NumberOfElements; i++)
james@536 461 {
james@536 462 grant_ref_t gref;
james@558 463 gref = (grant_ref_t)(sg_list->Elements[i].Address.QuadPart >> PAGE_SHIFT);
james@536 464 GntTbl_EndAccess(xpdd, gref, FALSE);
james@558 465 sg_list->Elements[i].Address.QuadPart = -1;
james@536 466 }
james@536 467 if (!WriteToDevice)
james@536 468 memcpy(sg_extra->unaligned_buffer, sg_extra->aligned_buffer, sg_extra->copy_length);
james@536 469 ExFreePoolWithTag(sg_extra->aligned_buffer, XENPCI_POOL_TAG);
james@536 470 break;
james@536 471 case MAP_TYPE_MDL:
james@558 472 for (i = 0; i < sg_list->NumberOfElements; i++)
james@536 473 {
james@536 474 grant_ref_t gref;
james@558 475 gref = (grant_ref_t)(sg_list->Elements[i].Address.QuadPart >> PAGE_SHIFT);
james@536 476 GntTbl_EndAccess(xpdd, gref, FALSE);
james@558 477 sg_list->Elements[i].Address.QuadPart = -1;
james@536 478 }
james@536 479 break;
james@536 480 case MAP_TYPE_VIRTUAL:
james@536 481 break;
james@536 482 }
james@558 483 if (sg_extra->allocated_by_me)
james@558 484 ExFreePoolWithTag(sg_list, XENPCI_POOL_TAG);
james@536 485 //FUNCTION_EXIT();
james@536 486 }
james@536 487
james@536 488 static NTSTATUS
james@536 489 XenPci_DOP_CalculateScatterGatherList(
james@536 490 PDMA_ADAPTER DmaAdapter,
james@536 491 PMDL Mdl,
james@536 492 PVOID CurrentVa,
james@536 493 ULONG Length,
james@536 494 PULONG ScatterGatherListSize,
james@536 495 PULONG NumberOfMapRegisters
james@536 496 )
james@536 497 {
james@558 498 xen_dma_adapter_t *xen_dma_adapter;
james@536 499 ULONG elements;
james@536 500 PMDL curr_mdl;
james@558 501
james@561 502 //FUNCTION_ENTER();
james@536 503
james@561 504 //KdPrint((__DRIVER_NAME " Mdl = %p\n", Mdl));
james@561 505 //KdPrint((__DRIVER_NAME " CurrentVa = %p\n", CurrentVa));
james@561 506 //KdPrint((__DRIVER_NAME " Length = %d\n", Length));
james@558 507
james@558 508 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
james@558 509
james@536 510 if (Mdl)
james@536 511 {
james@561 512 //if (CurrentVa != MmGetMdlVirtualAddress(Mdl))
james@561 513 //{
james@561 514 // KdPrint((__DRIVER_NAME " CurrentVa (%p) != MdlVa (%p)\n", CurrentVa, MmGetMdlVirtualAddress(Mdl)));
james@561 515 //
james@561 516
james@561 517 KdPrint((__DRIVER_NAME " CurrentVa = %p, MdlVa = %p\n", CurrentVa, MmGetMdlVirtualAddress(Mdl)));
james@561 518
james@536 519 for (curr_mdl = Mdl, elements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
james@561 520 {
james@561 521 KdPrint((__DRIVER_NAME " curr_mdlVa = %p, curr_mdl size = %d\n", MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)));
james@561 522 elements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
james@561 523 }
james@536 524 }
james@536 525 else
james@536 526 {
james@558 527 elements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, Length); // + 1;
james@558 528 }
james@558 529
james@558 530 if (elements > xen_dma_adapter->adapter_object.MapRegistersPerChannel)
james@558 531 {
james@558 532 KdPrint((__DRIVER_NAME " elements = %d - too many\n", elements));
james@558 533 if (NumberOfMapRegisters)
james@558 534 *NumberOfMapRegisters = 0;
james@558 535 *ScatterGatherListSize = 0;
james@558 536
james@558 537 return STATUS_INSUFFICIENT_RESOURCES;
james@536 538 }
james@536 539
james@536 540 *ScatterGatherListSize = FIELD_OFFSET(SCATTER_GATHER_LIST, Elements)
james@536 541 + sizeof(SCATTER_GATHER_ELEMENT) * elements
james@536 542 + sizeof(sg_extra_t);
james@536 543 if (NumberOfMapRegisters)
james@558 544 *NumberOfMapRegisters = elements;
james@536 545
james@558 546 KdPrint((__DRIVER_NAME " ScatterGatherListSize = %d, NumberOfMapRegisters = %d\n", *ScatterGatherListSize, elements));
james@536 547
james@561 548 //FUNCTION_EXIT();
james@536 549 return STATUS_SUCCESS;
james@536 550 }
james@536 551
james@536 552 static NTSTATUS
james@558 553 XenPci_DOP_BuildScatterGatherListButDontExecute(
james@536 554 IN PDMA_ADAPTER DmaAdapter,
james@536 555 IN PDEVICE_OBJECT DeviceObject,
james@536 556 IN PMDL Mdl,
james@536 557 IN PVOID CurrentVa,
james@536 558 IN ULONG Length,
james@536 559 IN BOOLEAN WriteToDevice,
james@536 560 IN PVOID ScatterGatherBuffer,
james@558 561 IN ULONG ScatterGatherBufferLength,
james@558 562 BOOLEAN allocated_by_me)
james@536 563 {
james@536 564 ULONG i;
james@536 565 PSCATTER_GATHER_LIST sglist = ScatterGatherBuffer;
james@536 566 PUCHAR ptr;
james@536 567 ULONG remaining = Length;
james@536 568 ULONG total_remaining;
james@536 569 xen_dma_adapter_t *xen_dma_adapter;
james@536 570 PXENPCI_DEVICE_DATA xpdd;
james@536 571 sg_extra_t *sg_extra;
james@536 572 PMDL curr_mdl;
james@536 573 ULONG map_type;
james@536 574 ULONG sg_element;
james@536 575 ULONG offset;
james@536 576 PFN_NUMBER pfn;
james@536 577 grant_ref_t gref;
james@537 578 //PUCHAR StartVa;
james@536 579
james@538 580 //FUNCTION_ENTER();
james@538 581
james@555 582 if (!ScatterGatherBuffer)
james@555 583 {
james@555 584 KdPrint((__DRIVER_NAME " NULL ScatterGatherBuffer\n"));
james@555 585 return STATUS_INVALID_PARAMETER;
james@555 586 }
james@537 587 ASSERT(MmGetMdlVirtualAddress(Mdl) == CurrentVa);
james@536 588
james@536 589 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
james@536 590 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
james@536 591
james@536 592 ASSERT(Mdl);
james@537 593
james@536 594 if (xen_dma_adapter->dma_extension)
james@536 595 {
james@558 596 if (xen_dma_adapter->dma_extension->need_virtual_address && xen_dma_adapter->dma_extension->need_virtual_address(DeviceObject->CurrentIrp))
james@536 597 {
james@536 598 ASSERT(!Mdl->Next); /* can only virtual a single buffer */
james@536 599 map_type = MAP_TYPE_VIRTUAL;
james@536 600 sglist->NumberOfElements = 1;
james@536 601 }
james@536 602 else
james@536 603 {
james@558 604 if (xen_dma_adapter->dma_extension->get_alignment)
james@536 605 {
james@558 606 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(DeviceObject->CurrentIrp);
james@558 607 if ((MmGetMdlByteOffset(Mdl) & (alignment - 1)) || (MmGetMdlByteCount(Mdl) & (alignment - 1)))
james@558 608 {
james@558 609 ASSERT(!Mdl->Next); /* can only remap a single buffer for now - will need to check all Mdl's in the future */
james@558 610 map_type = MAP_TYPE_REMAPPED;
james@558 611 sglist->NumberOfElements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(NULL, Length);
james@558 612 }
james@558 613 else
james@558 614 {
james@558 615 map_type = MAP_TYPE_MDL;
james@558 616 }
james@536 617 }
james@536 618 else
james@536 619 {
james@536 620 map_type = MAP_TYPE_MDL;
james@536 621 }
james@536 622 }
james@536 623 }
james@536 624 else
james@536 625 {
james@536 626 map_type = MAP_TYPE_MDL;
james@558 627 }
james@558 628 if (map_type == MAP_TYPE_MDL)
james@558 629 {
james@536 630 for (curr_mdl = Mdl, sglist->NumberOfElements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
james@536 631 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
james@536 632 MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
james@536 633 }
james@536 634 if (ScatterGatherBufferLength < FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
james@536 635 sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t))
james@536 636 {
james@561 637 //KdPrint((__DRIVER_NAME " STATUS_BUFFER_TOO_SMALL (%d < %d)\n", ScatterGatherBufferLength, FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
james@561 638 // sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t)));
james@536 639 return STATUS_BUFFER_TOO_SMALL;
james@536 640 }
james@536 641
james@536 642 sg_extra = (sg_extra_t *)((PUCHAR)sglist + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
james@536 643 (sizeof(SCATTER_GATHER_ELEMENT)) * sglist->NumberOfElements);
james@558 644
james@558 645 sg_extra->allocated_by_me = allocated_by_me;
james@536 646
james@536 647 sg_extra->map_type = map_type;
james@536 648 switch (map_type)
james@536 649 {
james@536 650 case MAP_TYPE_MDL:
james@537 651 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL - %p\n", MmGetMdlVirtualAddress(Mdl)));
james@536 652 total_remaining = Length;
james@536 653 for (sg_element = 0, curr_mdl = Mdl; curr_mdl; curr_mdl = curr_mdl->Next)
james@536 654 {
james@536 655 remaining = MmGetMdlByteCount(curr_mdl);
james@537 656 offset = MmGetMdlByteOffset(curr_mdl);
james@555 657 if (!remaining)
james@555 658 {
james@555 659 KdPrint((__DRIVER_NAME " zero length MDL\n"));
james@555 660 }
james@536 661 for (i = 0; i < ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)); i++)
james@536 662 {
james@536 663 //KdPrint((__DRIVER_NAME " element = %d\n", sg_element));
james@536 664 //KdPrint((__DRIVER_NAME " remaining = %d\n", remaining));
james@536 665 pfn = MmGetMdlPfnArray(curr_mdl)[i];
james@536 666 ASSERT(pfn);
james@537 667 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
james@536 668 ASSERT(gref != INVALID_GRANT_REF);
james@536 669 sglist->Elements[sg_element].Address.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | offset;
james@536 670 sglist->Elements[sg_element].Length = min(min(PAGE_SIZE - offset, remaining), total_remaining);
james@536 671 total_remaining -= sglist->Elements[sg_element].Length;
james@536 672 remaining -= sglist->Elements[sg_element].Length;
james@536 673 offset = 0;
james@536 674 sg_element++;
james@536 675 }
james@536 676 }
james@536 677 break;
james@536 678 case MAP_TYPE_REMAPPED:
james@536 679 sg_extra->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, max(Length, PAGE_SIZE), XENPCI_POOL_TAG);
james@536 680 if (!sg_extra->aligned_buffer)
james@536 681 {
james@555 682 KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED buffer allocation failed - requested va = %p, length = %d\n", MmGetMdlVirtualAddress(Mdl), Length));
james@536 683 return STATUS_INSUFFICIENT_RESOURCES;
james@536 684 }
james@537 685 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED - %p -> %p\n", MmGetMdlVirtualAddress(Mdl), sg_extra->aligned_buffer));
james@536 686 sg_extra->unaligned_buffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
james@536 687 ASSERT(sg_extra->unaligned_buffer); /* lazy */
james@536 688 sg_extra->copy_length = Length;
james@536 689 if (WriteToDevice)
james@536 690 memcpy(sg_extra->aligned_buffer, sg_extra->unaligned_buffer, sg_extra->copy_length);
james@536 691 for (sg_element = 0, remaining = Length;
james@536 692 sg_element < ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_extra->aligned_buffer, Length); sg_element++)
james@536 693 {
james@536 694 pfn = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)sg_extra->aligned_buffer + (sg_element << PAGE_SHIFT)).QuadPart >> PAGE_SHIFT);
james@536 695 ASSERT(pfn);
james@537 696 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
james@536 697 ASSERT(gref);
james@536 698 sglist->Elements[sg_element].Address.QuadPart = (ULONGLONG)gref << PAGE_SHIFT;
james@536 699 sglist->Elements[sg_element].Length = min(PAGE_SIZE, remaining);
james@536 700 remaining -= sglist->Elements[sg_element].Length;
james@536 701 }
james@536 702 break;
james@536 703 case MAP_TYPE_VIRTUAL:
james@536 704 ptr = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
james@536 705 ASSERT(ptr); /* lazy */
james@536 706 sglist->Elements[0].Address.QuadPart = (ULONGLONG)ptr;
james@536 707 sglist->Elements[0].Length = Length;
james@537 708 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL - %08x\n", sglist->Elements[0].Address.LowPart));
james@536 709 break;
james@555 710 default:
james@555 711 KdPrint((__DRIVER_NAME " map_type = %d\n", map_type));
james@555 712 break;
james@536 713 }
james@558 714 return STATUS_SUCCESS;
james@558 715 }
james@537 716
james@558 717 static NTSTATUS
james@558 718 XenPci_DOP_BuildScatterGatherList(
james@558 719 IN PDMA_ADAPTER DmaAdapter,
james@558 720 IN PDEVICE_OBJECT DeviceObject,
james@558 721 IN PMDL Mdl,
james@558 722 IN PVOID CurrentVa,
james@558 723 IN ULONG Length,
james@558 724 IN PDRIVER_LIST_CONTROL ExecutionRoutine,
james@558 725 IN PVOID Context,
james@558 726 IN BOOLEAN WriteToDevice,
james@558 727 IN PVOID ScatterGatherBuffer,
james@558 728 IN ULONG ScatterGatherBufferLength)
james@558 729 {
james@558 730 NTSTATUS status;
james@558 731
james@558 732 status = XenPci_DOP_BuildScatterGatherListButDontExecute(DmaAdapter, DeviceObject, Mdl, CurrentVa, Length, WriteToDevice, ScatterGatherBuffer, ScatterGatherBufferLength, FALSE);
james@558 733
james@558 734 if (NT_SUCCESS(status))
james@558 735 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, ScatterGatherBuffer, Context);
james@536 736
james@536 737 //FUNCTION_EXIT();
james@536 738
james@558 739 return status;
james@558 740 }
james@558 741
james@558 742 static NTSTATUS
james@558 743 XenPci_DOP_GetScatterGatherList(
james@558 744 PDMA_ADAPTER DmaAdapter,
james@558 745 PDEVICE_OBJECT DeviceObject,
james@558 746 PMDL Mdl,
james@558 747 PVOID CurrentVa,
james@558 748 ULONG Length,
james@558 749 PDRIVER_LIST_CONTROL ExecutionRoutine,
james@558 750 PVOID Context,
james@558 751 BOOLEAN WriteToDevice)
james@558 752 {
james@558 753 NTSTATUS status;
james@558 754 ULONG list_size;
james@558 755 ULONG map_registers;
james@558 756 PSCATTER_GATHER_LIST sg_list;
james@558 757
james@561 758 //FUNCTION_ENTER();
james@558 759
james@558 760 status = XenPci_DOP_CalculateScatterGatherList(DmaAdapter, Mdl, CurrentVa, Length, &list_size, &map_registers);
james@558 761 if (!NT_SUCCESS(status))
james@558 762 {
james@561 763 //FUNCTION_EXIT();
james@558 764 return status;
james@558 765 }
james@558 766
james@558 767 sg_list = ExAllocatePoolWithTag(NonPagedPool, list_size, XENPCI_POOL_TAG);
james@558 768 if (!sg_list)
james@558 769 {
james@558 770 KdPrint((__DRIVER_NAME " Cannot allocate memory for sg_list\n"));
james@561 771 //FUNCTION_EXIT();
james@558 772 return STATUS_INSUFFICIENT_RESOURCES;
james@558 773 }
james@558 774
james@558 775 status = XenPci_DOP_BuildScatterGatherListButDontExecute(DmaAdapter, DeviceObject, Mdl, CurrentVa, Length, WriteToDevice, sg_list, list_size, TRUE);
james@558 776
james@558 777 if (NT_SUCCESS(status))
james@558 778 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, sg_list, Context);
james@558 779
james@561 780 //FUNCTION_EXIT();
james@558 781
james@558 782 return status;
james@536 783 }
james@536 784
james@536 785 static NTSTATUS
james@536 786 XenPci_DOP_BuildMdlFromScatterGatherList(
james@536 787 PDMA_ADAPTER DmaAdapter,
james@536 788 PSCATTER_GATHER_LIST ScatterGather,
james@536 789 PMDL OriginalMdl,
james@536 790 PMDL *TargetMdl)
james@536 791 {
james@561 792 NTSTATUS status = STATUS_SUCCESS;
james@536 793 UNREFERENCED_PARAMETER(DmaAdapter);
james@536 794 UNREFERENCED_PARAMETER(ScatterGather);
james@536 795 UNREFERENCED_PARAMETER(OriginalMdl);
james@536 796 UNREFERENCED_PARAMETER(TargetMdl);
james@536 797
james@536 798 FUNCTION_ENTER();
james@561 799
james@561 800 if (OriginalMdl)
james@561 801 {
james@561 802 *TargetMdl = OriginalMdl;
james@561 803 }
james@561 804 else
james@561 805 {
james@561 806 *TargetMdl = NULL;
james@561 807 status = STATUS_INVALID_PARAMETER;
james@561 808 }
james@561 809
james@536 810 FUNCTION_EXIT();
james@561 811
james@561 812 return status;
james@536 813 }
james@536 814
james@536 815 static PDMA_ADAPTER
james@536 816 XenPci_BIS_GetDmaAdapter(PVOID context, PDEVICE_DESCRIPTION device_description, PULONG number_of_map_registers)
james@536 817 {
james@536 818 xen_dma_adapter_t *xen_dma_adapter;
james@536 819 PDEVICE_OBJECT curr, prev;
james@536 820 PDRIVER_OBJECT fdo_driver_object;
james@536 821 PVOID fdo_driver_extension;
james@536 822
james@536 823 UNREFERENCED_PARAMETER(device_description);
james@536 824
james@536 825 FUNCTION_ENTER();
james@536 826
james@536 827 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@536 828 KdPrint((__DRIVER_NAME " Device Description = %p:\n", device_description));
james@536 829 KdPrint((__DRIVER_NAME " Version = %d\n", device_description->Version));
james@536 830 KdPrint((__DRIVER_NAME " Master = %d\n", device_description->Master));
james@536 831 KdPrint((__DRIVER_NAME " ScatterGather = %d\n", device_description->ScatterGather));
james@536 832 KdPrint((__DRIVER_NAME " DemandMode = %d\n", device_description->DemandMode));
james@536 833 KdPrint((__DRIVER_NAME " AutoInitialize = %d\n", device_description->AutoInitialize));
james@536 834 KdPrint((__DRIVER_NAME " Dma32BitAddresses = %d\n", device_description->Dma32BitAddresses));
james@536 835 KdPrint((__DRIVER_NAME " IgnoreCount = %d\n", device_description->IgnoreCount));
james@536 836 KdPrint((__DRIVER_NAME " Dma64BitAddresses = %d\n", device_description->Dma64BitAddresses));
james@536 837 KdPrint((__DRIVER_NAME " BusNumber = %d\n", device_description->BusNumber));
james@536 838 KdPrint((__DRIVER_NAME " DmaChannel = %d\n", device_description->DmaChannel));
james@536 839 KdPrint((__DRIVER_NAME " InterfaceType = %d\n", device_description->InterfaceType));
james@536 840 KdPrint((__DRIVER_NAME " DmaWidth = %d\n", device_description->DmaWidth));
james@536 841 KdPrint((__DRIVER_NAME " DmaSpeed = %d\n", device_description->DmaSpeed));
james@536 842 KdPrint((__DRIVER_NAME " MaximumLength = %d\n", device_description->MaximumLength));
james@536 843 KdPrint((__DRIVER_NAME " DmaPort = %d\n", device_description->DmaPort));
james@536 844
james@538 845 if (!device_description->Master)
james@538 846 return NULL;
james@536 847 /*
james@536 848 we have to allocate PAGE_SIZE bytes here because Windows thinks this is
james@536 849 actually an ADAPTER_OBJECT, and then the verifier crashes because
james@536 850 Windows accessed beyond the end of the structure :(
james@536 851 */
james@536 852 xen_dma_adapter = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@538 853 ASSERT(xen_dma_adapter);
james@536 854 RtlZeroMemory(xen_dma_adapter, PAGE_SIZE);
james@538 855
james@538 856 switch(device_description->Version)
james@538 857 {
james@538 858 case DEVICE_DESCRIPTION_VERSION1:
james@538 859 xen_dma_adapter->adapter_object.DmaHeader.Version = 1;
james@538 860 break;
james@538 861 case DEVICE_DESCRIPTION_VERSION: /* ignore what the docs say here - DEVICE_DESCRIPTION_VERSION appears to mean the latest version */
james@538 862 case DEVICE_DESCRIPTION_VERSION2:
james@538 863 xen_dma_adapter->adapter_object.DmaHeader.Version = 2;
james@538 864 break;
james@538 865 default:
james@538 866 KdPrint((__DRIVER_NAME " Unsupported device description version %d\n", device_description->Version));
james@538 867 ExFreePoolWithTag(xen_dma_adapter, XENPCI_POOL_TAG);
james@538 868 return NULL;
james@538 869 }
james@538 870
james@558 871 xen_dma_adapter->xppdd = context;
james@558 872 xen_dma_adapter->dma_extension = NULL;
james@558 873
james@558 874 KdPrint((__DRIVER_NAME " About to call IoGetAttachedDeviceReference\n"));
james@558 875 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(xen_dma_adapter->xppdd->wdf_device));
james@558 876 KdPrint((__DRIVER_NAME " Before start of loop - curr = %p\n", curr));
james@558 877 while (curr != NULL)
james@558 878 {
james@558 879 fdo_driver_object = curr->DriverObject;
james@558 880 if (fdo_driver_object)
james@558 881 {
james@558 882 ObReferenceObject(fdo_driver_object);
james@558 883 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC));
james@558 884 if (fdo_driver_extension)
james@558 885 {
james@558 886 xen_dma_adapter->dma_extension_driver = fdo_driver_object; /* so we can dereference it on putdmaadapter */
james@558 887 xen_dma_adapter->dma_extension = (dma_driver_extension_t *)fdo_driver_extension;
james@558 888 ObDereferenceObject(curr);
james@558 889 break;
james@558 890 }
james@558 891 else
james@558 892 {
james@558 893 ObDereferenceObject(fdo_driver_object);
james@558 894 }
james@558 895 }
james@558 896 prev = curr;
james@558 897 curr = IoGetLowerDeviceObject(curr);
james@558 898 ObDereferenceObject(prev);
james@558 899 }
james@558 900 KdPrint((__DRIVER_NAME " End of loop\n"));
james@538 901
james@538 902 xen_dma_adapter->adapter_object.DmaHeader.Size = sizeof(X_ADAPTER_OBJECT); //xen_dma_adapter_t);
james@538 903 xen_dma_adapter->adapter_object.MasterAdapter = NULL;
james@558 904 if (xen_dma_adapter->dma_extension && xen_dma_adapter->dma_extension->max_sg_elements)
james@558 905 {
james@558 906 xen_dma_adapter->adapter_object.MapRegistersPerChannel = xen_dma_adapter->dma_extension->max_sg_elements;
james@558 907 }
james@558 908 else
james@558 909 {
james@558 910 xen_dma_adapter->adapter_object.MapRegistersPerChannel = 256;
james@558 911 }
james@538 912 xen_dma_adapter->adapter_object.AdapterBaseVa = NULL;
james@538 913 xen_dma_adapter->adapter_object.MapRegisterBase = NULL;
james@538 914 xen_dma_adapter->adapter_object.NumberOfMapRegisters = 0;
james@538 915 xen_dma_adapter->adapter_object.CommittedMapRegisters = 0;
james@538 916 xen_dma_adapter->adapter_object.CurrentWcb = NULL;
james@538 917 KeInitializeDeviceQueue(&xen_dma_adapter->adapter_object.ChannelWaitQueue);
james@538 918 xen_dma_adapter->adapter_object.RegisterWaitQueue = NULL;
james@538 919 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterQueue);
james@538 920 KeInitializeSpinLock(&xen_dma_adapter->adapter_object.SpinLock);
james@538 921 xen_dma_adapter->adapter_object.MapRegisters = NULL;
james@538 922 xen_dma_adapter->adapter_object.PagePort = NULL;
james@538 923 xen_dma_adapter->adapter_object.ChannelNumber = 0xff;
james@538 924 xen_dma_adapter->adapter_object.AdapterNumber = 0;
james@538 925 xen_dma_adapter->adapter_object.DmaPortAddress = 0;
james@538 926 xen_dma_adapter->adapter_object.AdapterMode = 0;
james@538 927 xen_dma_adapter->adapter_object.NeedsMapRegisters = FALSE; /* when true this causes a crash in the crash dump path */
james@538 928 xen_dma_adapter->adapter_object.MasterDevice = 1;
james@538 929 xen_dma_adapter->adapter_object.Width16Bits = 0;
james@538 930 xen_dma_adapter->adapter_object.ScatterGather = device_description->ScatterGather;
james@538 931 xen_dma_adapter->adapter_object.IgnoreCount = device_description->IgnoreCount;
james@538 932 xen_dma_adapter->adapter_object.Dma32BitAddresses = device_description->Dma32BitAddresses;
james@538 933 xen_dma_adapter->adapter_object.Dma64BitAddresses = device_description->Dma64BitAddresses;
james@538 934 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterList);
james@538 935
james@538 936 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DMA_OPERATIONS), XENPCI_POOL_TAG);
james@538 937 ASSERT(xen_dma_adapter->adapter_object.DmaHeader.DmaOperations);
james@538 938 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 1)
james@538 939 {
james@538 940 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = FIELD_OFFSET(DMA_OPERATIONS, CalculateScatterGatherList);
james@538 941 }
james@538 942 else
james@538 943 {
james@538 944 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = sizeof(DMA_OPERATIONS);
james@538 945 }
james@538 946 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutDmaAdapter = XenPci_DOP_PutDmaAdapter;
james@538 947 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateCommonBuffer = XenPci_DOP_AllocateCommonBuffer;
james@538 948 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeCommonBuffer = XenPci_DOP_FreeCommonBuffer;
james@538 949 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateAdapterChannel = XenPci_DOP_AllocateAdapterChannel;
james@538 950 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FlushAdapterBuffers = XenPci_DOP_FlushAdapterBuffers;
james@538 951 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeAdapterChannel = XenPci_DOP_FreeAdapterChannel;
james@538 952 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeMapRegisters = XenPci_DOP_FreeMapRegisters;
james@538 953 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->MapTransfer = XenPci_DOP_MapTransfer;
james@538 954 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetDmaAlignment = XenPci_DOP_GetDmaAlignment;
james@538 955 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->ReadDmaCounter = XenPci_DOP_ReadDmaCounter;
james@538 956 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetScatterGatherList = XenPci_DOP_GetScatterGatherList;
james@538 957 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutScatterGatherList = XenPci_DOP_PutScatterGatherList;
james@538 958 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 2)
james@538 959 {
james@538 960 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->CalculateScatterGatherList = XenPci_DOP_CalculateScatterGatherList;
james@538 961 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildScatterGatherList = XenPci_DOP_BuildScatterGatherList;
james@538 962 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildMdlFromScatterGatherList = XenPci_DOP_BuildMdlFromScatterGatherList;
james@538 963 }
james@536 964
james@558 965 *number_of_map_registers = xen_dma_adapter->adapter_object.MapRegistersPerChannel; //1024; /* why not... */
james@536 966
james@536 967 FUNCTION_EXIT();
james@536 968
james@538 969 return &xen_dma_adapter->adapter_object.DmaHeader;
james@536 970 }
james@536 971
james@536 972 static ULONG
james@536 973 XenPci_BIS_SetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
james@536 974 {
james@536 975 UNREFERENCED_PARAMETER(context);
james@536 976 UNREFERENCED_PARAMETER(data_type);
james@536 977 UNREFERENCED_PARAMETER(buffer);
james@536 978 UNREFERENCED_PARAMETER(offset);
james@536 979 UNREFERENCED_PARAMETER(length);
james@536 980
james@536 981 FUNCTION_ENTER();
james@536 982 FUNCTION_EXIT();
james@536 983 return 0;
james@536 984 }
james@536 985
james@536 986 static ULONG
james@536 987 XenPci_BIS_GetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
james@536 988 {
james@536 989 UNREFERENCED_PARAMETER(context);
james@536 990 UNREFERENCED_PARAMETER(data_type);
james@536 991 UNREFERENCED_PARAMETER(buffer);
james@536 992 UNREFERENCED_PARAMETER(offset);
james@536 993 UNREFERENCED_PARAMETER(length);
james@536 994
james@536 995 FUNCTION_ENTER();
james@536 996 FUNCTION_EXIT();
james@536 997 return 0;
james@536 998 }
james@536 999
james@536 1000 /*
james@536 1001 Called at PASSIVE_LEVEL(?)
james@536 1002 Called during restore
james@536 1003 */
james@536 1004
james@536 1005 static ULONG
james@536 1006 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
james@536 1007 {
james@536 1008 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1009 char path[128];
james@536 1010 char *value;
james@536 1011 char *err;
james@536 1012 ULONG backend_state;
james@536 1013
james@536 1014 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@536 1015 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@536 1016 if (err)
james@536 1017 {
james@536 1018 XenPci_FreeMem(err);
james@536 1019 return XenbusStateUnknown;
james@536 1020 }
james@536 1021 else
james@536 1022 {
james@536 1023 backend_state = atoi(value);
james@536 1024 XenPci_FreeMem(value);
james@536 1025 return backend_state;
james@536 1026 }
james@536 1027 }
james@536 1028
james@536 1029 static VOID
james@536 1030 XenPci_BackEndStateHandler(char *path, PVOID context)
james@536 1031 {
james@536 1032 WDFDEVICE device = context;
james@536 1033 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1034 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1035 ULONG new_backend_state;
james@536 1036
james@536 1037 #if !DBG
james@536 1038 UNREFERENCED_PARAMETER(path);
james@536 1039 #endif
james@536 1040
james@536 1041 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
james@536 1042
james@536 1043 /* check that path == device/id/state */
james@536 1044 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
james@536 1045 new_backend_state = XenPci_ReadBackendState(xppdd);
james@536 1046 if (new_backend_state == XenbusStateUnknown)
james@536 1047 {
james@536 1048 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
james@536 1049 return;
james@536 1050 KdPrint(("Failed to read %s, assuming closed\n", path));
james@536 1051 new_backend_state = XenbusStateClosed;
james@536 1052 }
james@536 1053
james@536 1054 if (xppdd->backend_state == new_backend_state)
james@536 1055 {
james@536 1056 KdPrint((__DRIVER_NAME " state unchanged\n"));
james@536 1057 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@536 1058 return;
james@536 1059 }
james@536 1060
james@536 1061 xppdd->backend_state = new_backend_state;
james@536 1062
james@536 1063 switch (xppdd->backend_state)
james@536 1064 {
james@536 1065 case XenbusStateUnknown:
james@536 1066 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown (%s)\n", path));
james@536 1067 break;
james@536 1068
james@536 1069 case XenbusStateInitialising:
james@536 1070 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising (%s)\n", path));
james@536 1071 break;
james@536 1072
james@536 1073 case XenbusStateInitWait:
james@536 1074 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait (%s)\n", path));
james@536 1075 break;
james@536 1076
james@536 1077 case XenbusStateInitialised:
james@536 1078 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised (%s)\n", path));
james@536 1079 break;
james@536 1080
james@536 1081 case XenbusStateConnected:
james@536 1082 KdPrint((__DRIVER_NAME " Backend State Changed to Connected (%s)\n", path));
james@536 1083 break;
james@536 1084
james@536 1085 case XenbusStateClosing:
james@538 1086 KdPrint((__DRIVER_NAME " Backend State Changed to Closing (%s)\n", path));
james@538 1087 if (xppdd->frontend_state == XenbusStateConnected)
james@536 1088 {
james@538 1089 KdPrint((__DRIVER_NAME " Requesting eject\n"));
james@536 1090 WdfPdoRequestEject(device);
james@536 1091 }
james@536 1092 break;
james@536 1093
james@536 1094 case XenbusStateClosed:
james@536 1095 KdPrint((__DRIVER_NAME " Backend State Changed to Closed (%s)\n", path));
james@536 1096 break;
james@536 1097
james@536 1098 default:
james@536 1099 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d (%s)\n", xppdd->backend_state, path));
james@536 1100 break;
james@536 1101 }
james@536 1102
james@536 1103 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
james@536 1104
james@536 1105 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@536 1106
james@536 1107 return;
james@536 1108 }
james@536 1109
james@536 1110 static NTSTATUS
james@536 1111 XenPci_GetBackendAndAddWatch(WDFDEVICE device)
james@536 1112 {
james@536 1113 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1114 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1115 char path[128];
james@536 1116 PCHAR res;
james@536 1117 PCHAR value;
james@536 1118
james@536 1119 /* Get backend path */
james@536 1120 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
james@536 1121 "%s/backend", xppdd->path);
james@536 1122 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@536 1123 if (res)
james@536 1124 {
james@536 1125 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
james@536 1126 XenPci_FreeMem(res);
james@536 1127 return STATUS_UNSUCCESSFUL;
james@536 1128 }
james@536 1129 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
james@536 1130 XenPci_FreeMem(value);
james@536 1131
james@536 1132 /* Add watch on backend state */
james@536 1133 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@536 1134 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
james@536 1135
james@536 1136 return STATUS_SUCCESS;
james@536 1137 }
james@536 1138
james@551 1139 static NTSTATUS
james@551 1140 XenConfig_InitConfigPage(WDFDEVICE device)
james@536 1141 {
james@551 1142 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1143 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
james@536 1144 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
james@536 1145 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@536 1146 PUCHAR ptr;
james@536 1147 PDEVICE_OBJECT curr, prev;
james@536 1148 PDRIVER_OBJECT fdo_driver_object;
james@536 1149 PUCHAR fdo_driver_extension;
james@536 1150
james@536 1151 FUNCTION_ENTER();
james@536 1152
james@551 1153 ptr = MmGetMdlVirtualAddress(xppdd->config_page_mdl);
james@536 1154 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(device));
james@536 1155 //curr = WdfDeviceWdmGetAttachedDevice(device);
james@536 1156 while (curr != NULL)
james@536 1157 {
james@536 1158 fdo_driver_object = curr->DriverObject;
james@536 1159 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
james@536 1160 if (fdo_driver_object)
james@536 1161 {
james@536 1162 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
james@536 1163 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
james@536 1164 if (fdo_driver_extension)
james@536 1165 {
james@536 1166 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
james@536 1167 ObDereferenceObject(curr);
james@536 1168 break;
james@536 1169 }
james@536 1170 }
james@536 1171 prev = curr;
james@536 1172 curr = IoGetLowerDeviceObject(curr);
james@536 1173 ObDereferenceObject(prev);
james@536 1174 }
james@536 1175
james@536 1176 FUNCTION_EXIT();
james@536 1177
james@551 1178 return STATUS_SUCCESS;
james@536 1179 }
james@536 1180
james@536 1181 static NTSTATUS
james@536 1182 XenPci_EvtChn_Bind(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
james@536 1183 {
james@536 1184 WDFDEVICE device = context;
james@536 1185 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1186 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1187
james@536 1188 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext);
james@536 1189 }
james@536 1190
james@536 1191 static NTSTATUS
james@536 1192 XenPci_EvtChn_BindDpc(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
james@536 1193 {
james@536 1194 WDFDEVICE device = context;
james@536 1195 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1196 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1197
james@536 1198 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext);
james@536 1199 }
james@536 1200
james@536 1201 static NTSTATUS
james@536 1202 XenPci_EvtChn_Unbind(PVOID context, evtchn_port_t Port)
james@536 1203 {
james@536 1204 WDFDEVICE device = context;
james@536 1205 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1206 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1207
james@536 1208 return EvtChn_Unbind(xpdd, Port);
james@536 1209 }
james@536 1210
james@536 1211 static NTSTATUS
james@536 1212 XenPci_EvtChn_Mask(PVOID context, evtchn_port_t Port)
james@536 1213 {
james@536 1214 WDFDEVICE device = context;
james@536 1215 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1216 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1217
james@536 1218 return EvtChn_Mask(xpdd, Port);
james@536 1219 }
james@536 1220
james@536 1221 static NTSTATUS
james@536 1222 XenPci_EvtChn_Unmask(PVOID context, evtchn_port_t Port)
james@536 1223 {
james@536 1224 WDFDEVICE device = context;
james@536 1225 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1226 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1227
james@536 1228 return EvtChn_Unmask(xpdd, Port);
james@536 1229 }
james@536 1230
james@536 1231 static NTSTATUS
james@536 1232 XenPci_EvtChn_Notify(PVOID context, evtchn_port_t Port)
james@536 1233 {
james@536 1234 WDFDEVICE device = context;
james@536 1235 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1236 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1237
james@536 1238 return EvtChn_Notify(xpdd, Port);
james@536 1239 }
james@536 1240
james@536 1241 static BOOLEAN
james@561 1242 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port, BOOLEAN *last_interrupt)
james@536 1243 {
james@536 1244 WDFDEVICE device = context;
james@536 1245 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1246 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1247
james@561 1248 return EvtChn_AckEvent(xpdd, port, last_interrupt);
james@536 1249 }
james@536 1250
james@536 1251 typedef struct {
james@536 1252 PXEN_EVTCHN_SYNC_ROUTINE sync_routine;
james@536 1253 PVOID sync_context;
james@536 1254 } sync_context_t;
james@536 1255
james@536 1256 static BOOLEAN
james@536 1257 XenPci_EvtChn_Sync_Routine(WDFINTERRUPT interrupt, WDFCONTEXT context)
james@536 1258 {
james@536 1259 sync_context_t *wdf_sync_context = context;
james@536 1260 UNREFERENCED_PARAMETER(interrupt);
james@536 1261 return wdf_sync_context->sync_routine(wdf_sync_context->sync_context);
james@536 1262 }
james@536 1263
james@536 1264 static BOOLEAN
james@536 1265 XenPci_EvtChn_Sync(PVOID context, PXEN_EVTCHN_SYNC_ROUTINE sync_routine, PVOID sync_context)
james@536 1266 {
james@536 1267 WDFDEVICE device = context;
james@536 1268 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1269 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1270 sync_context_t wdf_sync_context;
james@536 1271
james@536 1272 wdf_sync_context.sync_routine = sync_routine;
james@536 1273 wdf_sync_context.sync_context = sync_context;
james@536 1274
james@536 1275 return WdfInterruptSynchronize(xpdd->interrupt, XenPci_EvtChn_Sync_Routine, &wdf_sync_context);
james@536 1276 }
james@536 1277
james@536 1278 static grant_ref_t
james@536 1279 XenPci_GntTbl_GrantAccess(PVOID context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref)
james@536 1280 {
james@536 1281 WDFDEVICE device = context;
james@536 1282 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1283 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1284
james@536 1285 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref);
james@536 1286 }
james@536 1287
james@536 1288 static BOOLEAN
james@536 1289 XenPci_GntTbl_EndAccess(PVOID context, grant_ref_t ref, BOOLEAN keepref)
james@536 1290 {
james@536 1291 WDFDEVICE device = context;
james@536 1292 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1293 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1294
james@536 1295 return GntTbl_EndAccess(xpdd, ref, keepref);
james@536 1296 }
james@536 1297
james@536 1298 static VOID
james@536 1299 XenPci_GntTbl_PutRef(PVOID context, grant_ref_t ref)
james@536 1300 {
james@536 1301 WDFDEVICE device = context;
james@536 1302 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1303 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1304
james@536 1305 GntTbl_PutRef(xpdd, ref);
james@536 1306 }
james@536 1307
james@536 1308 static grant_ref_t
james@536 1309 XenPci_GntTbl_GetRef(PVOID context)
james@536 1310 {
james@536 1311 WDFDEVICE device = context;
james@536 1312 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1313 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1314
james@536 1315 return GntTbl_GetRef(xpdd);
james@536 1316 }
james@536 1317
james@536 1318 PCHAR
james@536 1319 XenPci_XenBus_Read(PVOID context, xenbus_transaction_t xbt, char *path, char **value)
james@536 1320 {
james@536 1321 WDFDEVICE device = context;
james@536 1322 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1323 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1324 return XenBus_Read(xpdd, xbt, path, value);
james@536 1325 }
james@536 1326
james@536 1327 PCHAR
james@536 1328 XenPci_XenBus_Write(PVOID context, xenbus_transaction_t xbt, char *path, char *value)
james@536 1329 {
james@536 1330 WDFDEVICE device = context;
james@536 1331 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1332 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1333 return XenBus_Write(xpdd, xbt, path, value);
james@536 1334 }
james@536 1335
james@536 1336 PCHAR
james@536 1337 XenPci_XenBus_Printf(PVOID context, xenbus_transaction_t xbt, char *path, char *fmt, ...)
james@536 1338 {
james@536 1339 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
james@536 1340 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
james@536 1341 //return XenBus_Printf(xpdd, xbt, path, value);
james@536 1342 UNREFERENCED_PARAMETER(context);
james@536 1343 UNREFERENCED_PARAMETER(xbt);
james@536 1344 UNREFERENCED_PARAMETER(path);
james@536 1345 UNREFERENCED_PARAMETER(fmt);
james@536 1346 return NULL;
james@536 1347 }
james@536 1348
james@536 1349 PCHAR
james@536 1350 XenPci_XenBus_StartTransaction(PVOID context, xenbus_transaction_t *xbt)
james@536 1351 {
james@536 1352 WDFDEVICE device = context;
james@536 1353 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1354 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1355 return XenBus_StartTransaction(xpdd, xbt);
james@536 1356 }
james@536 1357
james@536 1358 PCHAR
james@536 1359 XenPci_XenBus_EndTransaction(PVOID context, xenbus_transaction_t xbt, int abort, int *retry)
james@536 1360 {
james@536 1361 WDFDEVICE device = context;
james@536 1362 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1363 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1364 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
james@536 1365 }
james@536 1366
james@536 1367 PCHAR
james@536 1368 XenPci_XenBus_List(PVOID context, xenbus_transaction_t xbt, char *prefix, char ***contents)
james@536 1369 {
james@536 1370 WDFDEVICE device = context;
james@536 1371 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1372 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1373 return XenBus_List(xpdd, xbt, prefix, contents);
james@536 1374 }
james@536 1375
james@536 1376 PCHAR
james@536 1377 XenPci_XenBus_AddWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
james@536 1378 {
james@536 1379 WDFDEVICE device = context;
james@536 1380 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1381 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1382 PCHAR retval;
james@536 1383
james@536 1384 FUNCTION_ENTER();
james@536 1385 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
james@536 1386 if (retval == NULL)
james@536 1387 {
james@536 1388 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
james@536 1389 }
james@536 1390 else
james@536 1391 {
james@536 1392 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
james@536 1393 }
james@536 1394 FUNCTION_EXIT();
james@536 1395 return retval;
james@536 1396 }
james@536 1397
james@536 1398 PCHAR
james@536 1399 XenPci_XenBus_RemWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
james@536 1400 {
james@536 1401 WDFDEVICE device = context;
james@536 1402 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1403 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1404 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
james@536 1405 }
james@536 1406
james@536 1407 /*
james@536 1408 Called at PASSIVE_LEVEL
james@536 1409 Called during restore
james@536 1410 */
james@536 1411
james@536 1412 static NTSTATUS
james@536 1413 XenPci_ChangeFrontendState(WDFDEVICE device, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
james@536 1414 {
james@536 1415 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1416 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1417 LARGE_INTEGER timeout;
james@536 1418 ULONG remaining;
james@536 1419 ULONG thiswait;
james@536 1420 char path[128];
james@536 1421
james@536 1422 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
james@538 1423
james@538 1424 xppdd->frontend_state = frontend_state_set;
james@536 1425
james@536 1426 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
james@536 1427 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
james@536 1428
james@536 1429 remaining = maximum_wait_ms;
james@536 1430
james@536 1431 while (xppdd->backend_state != backend_state_response)
james@536 1432 {
james@536 1433 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
james@536 1434 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
james@536 1435 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
james@536 1436 {
james@536 1437 remaining -= thiswait;
james@536 1438 if (remaining == 0)
james@536 1439 {
james@536 1440 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
james@536 1441 return STATUS_UNSUCCESSFUL;
james@536 1442 }
james@536 1443 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
james@536 1444 }
james@536 1445 }
james@536 1446 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@536 1447 return STATUS_SUCCESS;
james@536 1448 }
james@536 1449
james@536 1450 static NTSTATUS
james@536 1451 XenPci_XenConfigDevice(WDFDEVICE device);
james@536 1452
james@536 1453 static NTSTATUS
james@536 1454 XenPci_XenShutdownDevice(PVOID context)
james@536 1455 {
james@536 1456 WDFDEVICE device = context;
james@536 1457 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1458 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1459 PUCHAR in_ptr;
james@536 1460 ULONG i;
james@536 1461 UCHAR type;
james@536 1462 PVOID setting;
james@536 1463 PVOID value;
james@536 1464 PVOID value2;
james@536 1465
james@536 1466 FUNCTION_ENTER();
james@536 1467
james@536 1468 if (xppdd->backend_state == XenbusStateConnected)
james@536 1469 {
james@536 1470 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
james@536 1471 if (xppdd->backend_state == XenbusStateClosing)
james@536 1472 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
james@536 1473 if (xppdd->backend_state == XenbusStateClosed)
james@536 1474 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
james@536 1475 }
james@536 1476 else
james@536 1477 {
james@536 1478 if (xppdd->backend_state == XenbusStateClosing)
james@536 1479 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
james@536 1480 }
james@536 1481
james@536 1482 if (xppdd->assigned_resources_start != NULL)
james@536 1483 {
james@536 1484 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 1485 in_ptr = xppdd->assigned_resources_start;
james@536 1486 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
james@536 1487 {
james@536 1488 switch (type)
james@536 1489 {
james@536 1490 case XEN_INIT_TYPE_RING: /* frontend ring */
james@536 1491 FreePages(value);
james@536 1492 break;
james@536 1493 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@536 1494 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 1495 EvtChn_Unbind(xpdd, PtrToUlong(value));
james@536 1496 EvtChn_Close(xpdd, PtrToUlong(value));
james@536 1497 break;
james@536 1498 case XEN_INIT_TYPE_GRANT_ENTRIES:
james@536 1499 for (i = 0; i < PtrToUlong(setting); i++)
james@536 1500 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value)[i], FALSE);
james@536 1501 break;
james@536 1502 }
james@536 1503 }
james@536 1504 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
james@536 1505 xppdd->assigned_resources_start = NULL;
james@536 1506 }
james@536 1507
james@536 1508 FUNCTION_EXIT();
james@536 1509
james@536 1510 return STATUS_SUCCESS;
james@536 1511 }
james@536 1512
james@536 1513 struct dummy_sring {
james@536 1514 RING_IDX req_prod, req_event;
james@536 1515 RING_IDX rsp_prod, rsp_event;
james@536 1516 uint8_t pad[48];
james@536 1517 };
james@536 1518
james@536 1519 static NTSTATUS
james@536 1520 XenPci_XenConfigDeviceSpecifyBuffers(WDFDEVICE device, PUCHAR src, PUCHAR dst)
james@536 1521 {
james@536 1522 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1523 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1524 NTSTATUS status = STATUS_SUCCESS;
james@536 1525 ULONG i;
james@536 1526 char path[128];
james@536 1527 PCHAR setting, value;
james@536 1528 PCHAR res;
james@536 1529 PVOID address;
james@536 1530 UCHAR type;
james@551 1531 PUCHAR in_ptr;
james@551 1532 PUCHAR out_ptr;
james@536 1533 XENPCI_VECTORS vectors;
james@536 1534 ULONG event_channel;
james@536 1535 ULONG run_type = 0;
james@536 1536 PMDL ring;
james@536 1537 grant_ref_t gref;
james@536 1538 BOOLEAN done_xenbus_init = FALSE;
james@536 1539 PVOID value2;
james@551 1540 BOOLEAN active = TRUE;
james@551 1541 BOOLEAN dont_config = FALSE;
james@536 1542
james@536 1543 FUNCTION_ENTER();
james@536 1544
james@536 1545 in_ptr = src;
james@536 1546 out_ptr = dst;
james@536 1547
james@536 1548 // always add vectors
james@536 1549 vectors.magic = XEN_DATA_MAGIC;
james@536 1550 vectors.length = sizeof(XENPCI_VECTORS);
james@536 1551 vectors.context = device;
james@536 1552 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
james@536 1553 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
james@536 1554 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
james@536 1555 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
james@536 1556 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
james@536 1557 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
james@536 1558 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
james@536 1559 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
james@536 1560 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
james@536 1561 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
james@536 1562 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
james@536 1563 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
james@536 1564 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
james@536 1565 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
james@536 1566 strncpy(vectors.path, xppdd->path, 128);
james@536 1567 strncpy(vectors.backend_path, xppdd->backend_path, 128);
james@536 1568 //vectors.pdo_event_channel = xpdd->pdo_event_channel;
james@536 1569 vectors.XenBus_Read = XenPci_XenBus_Read;
james@536 1570 vectors.XenBus_Write = XenPci_XenBus_Write;
james@536 1571 vectors.XenBus_Printf = XenPci_XenBus_Printf;
james@536 1572 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
james@536 1573 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
james@536 1574 vectors.XenBus_List = XenPci_XenBus_List;
james@536 1575 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
james@536 1576 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
james@536 1577
james@536 1578 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
james@536 1579
james@536 1580 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
james@536 1581 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
james@536 1582
james@551 1583
james@551 1584 if (!qemu_filtered)
james@551 1585 active = FALSE;
james@551 1586
james@551 1587 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@551 1588 {
james@551 1589 BOOLEAN condition;
james@551 1590 PCHAR xb_value;
james@551 1591 switch (type)
james@551 1592 {
james@551 1593 case XEN_INIT_TYPE_MATCH_FRONT:
james@551 1594 case XEN_INIT_TYPE_MATCH_BACK:
james@551 1595 if (type == XEN_INIT_TYPE_MATCH_FRONT)
james@551 1596 {
james@551 1597 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@551 1598 }
james@551 1599 else
james@551 1600 {
james@551 1601 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
james@551 1602 }
james@551 1603 KdPrint((__DRIVER_NAME " testing path = %s\n", path));
james@551 1604 res = XenBus_Read(xpdd, XBT_NIL, path, &xb_value);
james@551 1605 if (res)
james@551 1606 {
james@551 1607 KdPrint((__DRIVER_NAME " read failed (%s)\n", res));
james@551 1608 XenPci_FreeMem(res);
james@551 1609 }
james@551 1610 else
james@551 1611 {
james@551 1612 KdPrint((__DRIVER_NAME " testing %s vs %s\n", xb_value, value));
james@551 1613 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_IF_MATCH)
james@551 1614 condition = (strcmp(xb_value, value) == 0)?TRUE:FALSE;
james@551 1615 else
james@551 1616 condition = (strcmp(xb_value, value) != 0)?TRUE:FALSE;
james@551 1617 KdPrint((__DRIVER_NAME " condition = %d\n", condition));
james@551 1618
james@551 1619 if ((PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_ONLY_IF_QEMU_HIDE) && qemu_protocol_version && condition)
james@551 1620 condition = FALSE;
james@551 1621
james@551 1622 if (condition)
james@551 1623 {
james@551 1624 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_SET_INACTIVE)
james@551 1625 {
james@551 1626 active = FALSE;
james@551 1627 KdPrint((__DRIVER_NAME " set inactive\n"));
james@551 1628 }
james@551 1629 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_DONT_CONFIG)
james@551 1630 {
james@551 1631 dont_config = TRUE;
james@551 1632 KdPrint((__DRIVER_NAME " set inactive with dont config\n"));
james@551 1633 }
james@551 1634 }
james@551 1635 XenPci_FreeMem(xb_value);
james@551 1636 }
james@551 1637 break;
james@551 1638 }
james@551 1639 }
james@551 1640 if (dont_config)
james@551 1641 {
james@551 1642 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@551 1643 FUNCTION_EXIT();
james@551 1644 return status;
james@551 1645 }
james@551 1646
james@536 1647 // first pass, possibly before state == Connected
james@551 1648 in_ptr = src;
james@536 1649 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@536 1650 {
james@536 1651
james@536 1652 if (!done_xenbus_init)
james@536 1653 {
james@551 1654 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000) != STATUS_SUCCESS)
james@536 1655 {
james@536 1656 status = STATUS_UNSUCCESSFUL;
james@536 1657 goto error;
james@536 1658 }
james@536 1659 done_xenbus_init = TRUE;
james@536 1660 }
james@536 1661
james@536 1662 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
james@536 1663
james@536 1664 switch (type)
james@536 1665 {
james@536 1666 case XEN_INIT_TYPE_RUN:
james@536 1667 run_type++;
james@536 1668 break;
james@536 1669 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
james@536 1670 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
james@536 1671 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 1672 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
james@536 1673 break;
james@536 1674 case XEN_INIT_TYPE_RING: /* frontend ring */
james@536 1675 /* we only allocate and do the SHARED_RING_INIT here */
james@536 1676 if ((ring = AllocatePage()) != 0)
james@536 1677 {
james@536 1678 address = MmGetMdlVirtualAddress(ring);
james@536 1679 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
james@536 1680 SHARED_RING_INIT((struct dummy_sring *)address);
james@536 1681 if ((gref = GntTbl_GrantAccess(
james@536 1682 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
james@536 1683 {
james@536 1684 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 1685 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
james@536 1686 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
james@536 1687 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
james@536 1688 // add the grant entry too so it gets freed automatically
james@536 1689 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
james@536 1690 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
james@536 1691 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
james@536 1692 }
james@536 1693 else
james@536 1694 {
james@536 1695 FreePages(ring);
james@536 1696 status = STATUS_UNSUCCESSFUL;
james@536 1697 goto error;
james@536 1698 }
james@536 1699 }
james@536 1700 else
james@536 1701 {
james@536 1702 status = STATUS_UNSUCCESSFUL;
james@536 1703 goto error;
james@536 1704 }
james@536 1705 break;
james@536 1706 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@536 1707 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 1708 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
james@536 1709 {
james@536 1710 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
james@536 1711 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 1712 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
james@536 1713 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
james@536 1714 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
james@536 1715 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
james@536 1716 {
james@536 1717 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
james@536 1718 }
james@536 1719 else
james@536 1720 {
james@537 1721 #pragma warning(suppress:4055)
james@536 1722 EvtChn_Bind(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
james@536 1723 }
james@536 1724 }
james@536 1725 else
james@536 1726 {
james@536 1727 status = STATUS_UNSUCCESSFUL;
james@536 1728 goto error;
james@536 1729 }
james@536 1730 break;
james@536 1731 }
james@536 1732 }
james@536 1733 if (!NT_SUCCESS(status))
james@536 1734 {
james@536 1735 goto error;
james@536 1736 }
james@536 1737 // 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 1738 if (run_type == 1)
james@536 1739 {
james@551 1740 if (XenPci_ChangeFrontendState(device, XenbusStateInitialised, XenbusStateConnected, 2000) != STATUS_SUCCESS)
james@536 1741 {
james@536 1742 status = STATUS_UNSUCCESSFUL;
james@536 1743 goto error;
james@536 1744 }
james@536 1745 }
james@536 1746
james@536 1747 // second pass, possibly after state == Connected
james@536 1748 in_ptr = src;
james@536 1749 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@536 1750 {
james@536 1751 switch(type)
james@536 1752 {
james@536 1753 case XEN_INIT_TYPE_READ_STRING_BACK:
james@536 1754 case XEN_INIT_TYPE_READ_STRING_FRONT:
james@536 1755 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
james@536 1756 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
james@536 1757 else
james@536 1758 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
james@536 1759 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
james@536 1760 if (res)
james@536 1761 {
james@536 1762 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
james@536 1763 XenPci_FreeMem(res);
james@536 1764 ADD_XEN_INIT_RSP(&out_ptr, type, setting, NULL, NULL);
james@536 1765 }
james@536 1766 else
james@536 1767 {
james@536 1768 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
james@536 1769 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, value2);
james@536 1770 XenPci_FreeMem(value);
james@536 1771 }
james@536 1772 break;
james@536 1773 case XEN_INIT_TYPE_VECTORS:
james@536 1774 // this is always done so ignore the request
james@536 1775 break;
james@536 1776 case XEN_INIT_TYPE_GRANT_ENTRIES:
james@536 1777 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
james@536 1778 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
james@536 1779 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
james@536 1780 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
james@536 1781 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
james@536 1782 for (i = 0; i < PtrToUlong(value); i++)
james@536 1783 {
james@536 1784 gref = GntTbl_GetRef(xpdd);
james@536 1785 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
james@536 1786 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
james@536 1787 }
james@536 1788 break;
james@536 1789 }
james@536 1790 }
james@551 1791 if (active)
james@551 1792 {
james@551 1793 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_ACTIVE, NULL, NULL, NULL);
james@551 1794 }
james@536 1795 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 1796
james@536 1797 if (run_type)
james@536 1798 {
james@551 1799 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 2000) != STATUS_SUCCESS)
james@536 1800 {
james@536 1801 status = STATUS_UNSUCCESSFUL;
james@536 1802 goto error;
james@536 1803 }
james@536 1804 }
james@536 1805 FUNCTION_EXIT();
james@536 1806 return status;
james@551 1807
james@536 1808 error:
james@551 1809 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000);
james@536 1810 FUNCTION_EXIT_STATUS(status);
james@536 1811 return status;
james@536 1812 }
james@536 1813
james@536 1814 static NTSTATUS
james@536 1815 XenPci_XenConfigDevice(WDFDEVICE device)
james@536 1816 {
james@536 1817 NTSTATUS status;
james@536 1818 PUCHAR src, dst;
james@536 1819 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1820
james@536 1821 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
james@536 1822 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
james@536 1823 memcpy(src, dst, xppdd->config_page_length);
james@536 1824
james@536 1825 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
james@536 1826
james@536 1827 MmUnmapIoSpace(dst, xppdd->config_page_length);
james@536 1828 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
james@536 1829
james@536 1830 return status;
james@536 1831 }
james@536 1832
james@536 1833 static NTSTATUS
james@536 1834 XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp)
james@536 1835 {
james@536 1836 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1837 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1838 PIO_STACK_LOCATION stack;
james@536 1839 PCM_PARTIAL_RESOURCE_LIST prl;
james@536 1840 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
james@536 1841 ULONG i;
james@551 1842 //char path[128];
james@551 1843 //PMDL mdl;
james@536 1844
james@536 1845 FUNCTION_ENTER();
james@536 1846 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
james@536 1847
james@536 1848 stack = IoGetCurrentIrpStackLocation(irp);
james@536 1849
james@536 1850 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
james@536 1851 for (i = 0; i < prl->Count; i++)
james@536 1852 {
james@536 1853 prd = & prl->PartialDescriptors[i];
james@536 1854 switch (prd->Type)
james@536 1855 {
james@536 1856 case CmResourceTypeMemory:
james@536 1857 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
james@536 1858 {
james@551 1859 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
james@551 1860 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
james@536 1861 }
james@536 1862 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
james@536 1863 {
james@536 1864 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@536 1865 prd->Type = CmResourceTypeInterrupt;
james@536 1866 prd->ShareDisposition = CmResourceShareShared;
james@536 1867 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
james@536 1868 prd->u.Interrupt.Level = xpdd->irq_number;
james@536 1869 prd->u.Interrupt.Vector = xpdd->irq_number;
james@536 1870 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
james@536 1871 xppdd->irq_number = xpdd->irq_number;
james@536 1872 }
james@536 1873 break;
james@536 1874 }
james@536 1875 }
james@536 1876
james@536 1877 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
james@536 1878 for (i = 0; i < prl->Count; i++)
james@536 1879 {
james@536 1880 prd = & prl->PartialDescriptors[i];
james@536 1881 switch (prd->Type)
james@536 1882 {
james@536 1883 case CmResourceTypeMemory:
james@536 1884 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
james@536 1885 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
james@536 1886 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
james@536 1887 {
james@536 1888 if (prd->u.Memory.Length == 0)
james@536 1889 {
james@551 1890 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0]));
james@551 1891 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
james@551 1892 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
james@536 1893 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 1894 }
james@536 1895 xppdd->config_page_phys = prd->u.Memory.Start;
james@536 1896 xppdd->config_page_length = prd->u.Memory.Length;
james@536 1897 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@536 1898 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
james@536 1899
james@551 1900 #if 0
james@536 1901 status = XenPci_XenConfigDevice(device);
james@536 1902 if (!NT_SUCCESS(status))
james@536 1903 {
james@536 1904 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@538 1905 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
james@536 1906 FUNCTION_ERROR_EXIT();
james@536 1907 return status;
james@536 1908 }
james@551 1909 #endif
james@536 1910 }
james@536 1911 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
james@536 1912 {
james@536 1913 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@536 1914 prd->Type = CmResourceTypeInterrupt;
james@536 1915 prd->ShareDisposition = CmResourceShareShared;
james@536 1916 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
james@536 1917 prd->u.Interrupt.Level = xpdd->irq_level;
james@536 1918 prd->u.Interrupt.Vector = xpdd->irq_vector;
james@536 1919 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
james@536 1920 xppdd->irq_vector = xpdd->irq_vector;
james@536 1921 xppdd->irq_level = xpdd->irq_level;
james@536 1922 }
james@536 1923 break;
james@536 1924 }
james@536 1925 }
james@536 1926
james@536 1927 IoSkipCurrentIrpStackLocation(irp);
james@536 1928
james@536 1929 FUNCTION_EXIT();
james@536 1930
james@536 1931 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
james@536 1932 }
james@536 1933
james@536 1934 #if 0
james@536 1935 static NTSTATUS
james@536 1936 XenPciPdo_EvtDeviceResourcesQuery(WDFDEVICE device, WDFCMRESLIST resources)
james@536 1937 {
james@536 1938 }
james@536 1939 #endif
james@536 1940
james@536 1941 static NTSTATUS
james@536 1942 XenPciPdo_EvtDeviceResourceRequirementsQuery(WDFDEVICE device, WDFIORESREQLIST requirements_list)
james@536 1943 {
james@536 1944 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 1945 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 1946 WDFIORESLIST res_list;
james@536 1947 IO_RESOURCE_DESCRIPTOR ird;
james@536 1948
james@538 1949 //FUNCTION_ENTER();
james@536 1950
james@536 1951 WdfIoResourceRequirementsListSetInterfaceType(requirements_list, PNPBus);
james@536 1952
james@536 1953 WdfIoResourceListCreate(requirements_list, WDF_NO_OBJECT_ATTRIBUTES, &res_list);
james@536 1954 ird.Option = 0;
james@536 1955 ird.Type = CmResourceTypeMemory;
james@536 1956 ird.ShareDisposition = CmResourceShareShared;
james@536 1957 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
james@536 1958 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
james@536 1959 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
james@536 1960 ird.u.Memory.Length = 0;
james@536 1961 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
james@536 1962 WdfIoResourceListAppendDescriptor(res_list, &ird);
james@536 1963
james@536 1964 ird.Option = 0;
james@536 1965 ird.Type = CmResourceTypeMemory;
james@536 1966 ird.ShareDisposition = CmResourceShareShared;
james@536 1967 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
james@536 1968 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
james@536 1969 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
james@536 1970 ird.u.Memory.Length = 0;
james@536 1971 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
james@536 1972 WdfIoResourceListAppendDescriptor(res_list, &ird);
james@536 1973
james@536 1974 WdfIoResourceRequirementsListAppendIoResList(requirements_list, res_list);
james@536 1975
james@538 1976 //FUNCTION_EXIT();
james@538 1977
james@538 1978 return STATUS_SUCCESS;
james@538 1979 }
james@538 1980
james@538 1981 NTSTATUS
james@538 1982 XenPciPdo_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
james@538 1983 {
james@538 1984 NTSTATUS status = STATUS_SUCCESS;
james@551 1985 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@551 1986 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@551 1987 CHAR path[128];
james@538 1988
james@538 1989 FUNCTION_ENTER();
james@538 1990
james@538 1991 switch (previous_state)
james@538 1992 {
james@538 1993 case WdfPowerDeviceD0:
james@538 1994 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 1995 break;
james@538 1996 case WdfPowerDeviceD1:
james@538 1997 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 1998 break;
james@538 1999 case WdfPowerDeviceD2:
james@538 2000 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
james@538 2001 break;
james@538 2002 case WdfPowerDeviceD3:
james@538 2003 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
james@538 2004 break;
james@538 2005 case WdfPowerDeviceD3Final:
james@538 2006 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
james@538 2007 break;
james@538 2008 case WdfPowerDevicePrepareForHibernation:
james@538 2009 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
james@538 2010 break;
james@538 2011 default:
james@538 2012 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
james@538 2013 break;
james@538 2014 }
james@551 2015
james@551 2016 if (previous_state == WdfPowerDevicePrepareForHibernation
james@551 2017 || (previous_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
james@551 2018 {
james@551 2019 KdPrint((__DRIVER_NAME " starting up from hibernation\n"));
james@551 2020 }
james@551 2021 else
james@551 2022 {
james@551 2023 }
james@551 2024
james@551 2025 XenConfig_InitConfigPage(device);
james@551 2026
james@551 2027 status = XenPci_GetBackendAndAddWatch(device);
james@551 2028 if (!NT_SUCCESS(status))
james@551 2029 {
james@551 2030 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
james@551 2031 FUNCTION_ERROR_EXIT();
james@551 2032 return status;
james@551 2033 }
james@551 2034 status = XenPci_XenConfigDevice(device);
james@551 2035 if (!NT_SUCCESS(status))
james@551 2036 {
james@551 2037 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@551 2038 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
james@551 2039 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
james@551 2040 FUNCTION_ERROR_EXIT();
james@551 2041 return status;
james@551 2042 }
james@538 2043
james@536 2044 FUNCTION_EXIT();
james@536 2045
james@538 2046 return status;
james@538 2047 }
james@538 2048
james@538 2049 NTSTATUS
james@538 2050 XenPciPdo_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
james@538 2051 {
james@538 2052 NTSTATUS status = STATUS_SUCCESS;
james@538 2053 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@538 2054 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@538 2055 char path[128];
james@538 2056
james@538 2057 UNREFERENCED_PARAMETER(device);
james@538 2058 UNREFERENCED_PARAMETER(target_state);
james@538 2059
james@538 2060 FUNCTION_ENTER();
james@538 2061
james@538 2062 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@538 2063
james@538 2064
james@538 2065 switch (target_state)
james@538 2066 {
james@538 2067 case WdfPowerDeviceD0:
james@538 2068 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 2069 break;
james@538 2070 case WdfPowerDeviceD1:
james@538 2071 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
james@538 2072 break;
james@538 2073 case WdfPowerDeviceD2:
james@538 2074 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
james@538 2075 break;
james@538 2076 case WdfPowerDeviceD3:
james@538 2077 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
james@538 2078 break;
james@538 2079 case WdfPowerDeviceD3Final:
james@538 2080 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
james@538 2081 break;
james@538 2082 case WdfPowerDevicePrepareForHibernation:
james@538 2083 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
james@538 2084 break;
james@538 2085 default:
james@538 2086 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
james@538 2087 break;
james@538 2088 }
james@538 2089
james@538 2090 if (target_state == WdfPowerDevicePrepareForHibernation
james@538 2091 || (target_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
james@538 2092 {
james@538 2093 KdPrint((__DRIVER_NAME " not powering down as we are hibernating\n"));
james@538 2094 }
james@538 2095 else
james@538 2096 {
james@538 2097 status = XenPci_XenShutdownDevice(device);
james@538 2098 /* Remove watch on backend state */
james@538 2099 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@538 2100 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
james@538 2101 }
james@538 2102 FUNCTION_EXIT();
james@538 2103
james@538 2104 return status;
james@538 2105 }
james@538 2106
james@538 2107 NTSTATUS
james@551 2108 XenPciPdo_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
james@538 2109 {
james@538 2110 NTSTATUS status = STATUS_SUCCESS;
james@551 2111
james@538 2112 UNREFERENCED_PARAMETER(device);
james@538 2113 UNREFERENCED_PARAMETER(resources_raw);
james@538 2114 UNREFERENCED_PARAMETER(resources_translated);
james@538 2115
james@538 2116 FUNCTION_ENTER();
james@538 2117 FUNCTION_EXIT();
james@538 2118
james@538 2119 return status;
james@538 2120 }
james@538 2121
james@538 2122 NTSTATUS
james@538 2123 XenPciPdo_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
james@538 2124 {
james@538 2125 NTSTATUS status = STATUS_SUCCESS;
james@538 2126
james@538 2127 UNREFERENCED_PARAMETER(device);
james@538 2128 UNREFERENCED_PARAMETER(resources_translated);
james@538 2129
james@538 2130 FUNCTION_ENTER();
james@538 2131 FUNCTION_EXIT();
james@538 2132
james@538 2133 return status;
james@538 2134 }
james@538 2135
james@538 2136 static VOID
james@538 2137 XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
james@538 2138 {
james@538 2139 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@538 2140
james@538 2141 FUNCTION_ENTER();
james@538 2142
james@538 2143 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@538 2144 switch (notification_type)
james@538 2145 {
james@538 2146 case WdfSpecialFilePaging:
james@538 2147 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
james@538 2148 break;
james@538 2149 case WdfSpecialFileHibernation:
james@538 2150 xppdd->hiber_usage_kludge = is_in_notification_path;
james@538 2151 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
james@538 2152 break;
james@538 2153 case WdfSpecialFileDump:
james@538 2154 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
james@538 2155 break;
james@538 2156 default:
james@538 2157 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
james@538 2158 break;
james@538 2159 }
james@538 2160
james@538 2161 FUNCTION_EXIT();
james@536 2162 }
james@536 2163
james@536 2164 NTSTATUS
james@536 2165 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
james@536 2166 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
james@536 2167 PWDFDEVICE_INIT child_init)
james@536 2168 {
james@536 2169 NTSTATUS status = STATUS_SUCCESS;
james@536 2170 WDF_OBJECT_ATTRIBUTES child_attributes;
james@536 2171 WDFDEVICE child_device;
james@536 2172 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
james@536 2173 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
james@536 2174 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
james@536 2175 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
james@536 2176 PXENPCI_PDO_DEVICE_DATA xppdd;
james@536 2177 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
james@536 2178 WDF_QUERY_INTERFACE_CONFIG interface_config;
james@536 2179 BUS_INTERFACE_STANDARD bus_interface;
james@536 2180 WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
james@538 2181 WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
james@536 2182 UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
james@538 2183 WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
james@536 2184
james@536 2185 FUNCTION_ENTER();
james@536 2186
james@536 2187 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
james@536 2188
james@536 2189 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
james@536 2190 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
james@538 2191 //child_pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPciPdo_EvtDeviceD0EntryPostInterruptsEnabled;
james@536 2192 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
james@538 2193 //child_pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPciPdo_EvtDeviceD0ExitPreInterruptsDisabled;
james@536 2194 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenPciPdo_EvtDevicePrepareHardware;
james@536 2195 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenPciPdo_EvtDeviceReleaseHardware;
james@538 2196 child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
james@536 2197 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
james@538 2198
james@536 2199 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
james@536 2200 identification->device, identification->index, identification->path));
james@536 2201
james@536 2202 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
james@536 2203 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
james@536 2204 if (!NT_SUCCESS(status))
james@536 2205 {
james@536 2206 return status;
james@536 2207 }
james@536 2208
james@536 2209 WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
james@536 2210 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
james@536 2211 pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
james@536 2212 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
james@536 2213 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
james@536 2214 WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
james@536 2215
james@536 2216 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
james@536 2217 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
james@536 2218 if (!NT_SUCCESS(status))
james@536 2219 {
james@536 2220 return status;
james@536 2221 }
james@536 2222 status = WdfPdoInitAddHardwareID(child_init, &buffer);
james@536 2223 if (!NT_SUCCESS(status))
james@536 2224 {
james@536 2225 return status;
james@536 2226 }
james@536 2227 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
james@536 2228 if (!NT_SUCCESS(status))
james@536 2229 {
james@536 2230 return status;
james@536 2231 }
james@536 2232
james@536 2233 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
james@536 2234 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
james@536 2235 if (!NT_SUCCESS(status))
james@536 2236 {
james@536 2237 return status;
james@536 2238 }
james@536 2239
james@536 2240 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
james@536 2241 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
james@536 2242 if (!NT_SUCCESS(status))
james@536 2243 {
james@536 2244 return status;
james@536 2245 }
james@536 2246 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
james@538 2247
james@538 2248 WdfDeviceInitSetPowerNotPageable(child_init);
james@536 2249
james@536 2250 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
james@536 2251 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
james@536 2252 if (!NT_SUCCESS(status))
james@536 2253 {
james@536 2254 return status;
james@536 2255 }
james@536 2256
james@536 2257 xppdd = GetXppdd(child_device);
james@536 2258
james@536 2259 xppdd->wdf_device = child_device;
james@536 2260 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
james@536 2261
james@551 2262 xppdd->config_page_mdl = AllocateUncachedPage();
james@551 2263
james@536 2264 xppdd->device_state.magic = XEN_DEVICE_STATE_MAGIC;
james@536 2265 xppdd->device_state.length = sizeof(XENPCI_DEVICE_STATE);
james@536 2266 xppdd->device_state.suspend_resume_state_pdo = SR_STATE_RUNNING;
james@536 2267 xppdd->device_state.suspend_resume_state_fdo = SR_STATE_RUNNING;
james@536 2268 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
james@536 2269 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
james@536 2270 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
james@536 2271 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
james@536 2272
james@536 2273 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
james@536 2274 child_pnp_capabilities.LockSupported = WdfFalse;
james@536 2275 child_pnp_capabilities.EjectSupported = WdfTrue;
james@536 2276 child_pnp_capabilities.Removable = WdfTrue;
james@536 2277 child_pnp_capabilities.DockDevice = WdfFalse;
james@536 2278 child_pnp_capabilities.UniqueID = WdfFalse;
james@536 2279 child_pnp_capabilities.SilentInstall = WdfTrue;
james@536 2280 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
james@536 2281 child_pnp_capabilities.HardwareDisabled = WdfFalse;
james@536 2282 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
james@536 2283
james@538 2284 WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
james@538 2285 child_power_capabilities.DeviceD1 = WdfTrue;
james@538 2286 child_power_capabilities.WakeFromD1 = WdfTrue;
james@538 2287 child_power_capabilities.DeviceWake = PowerDeviceD1;
james@538 2288 child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
james@538 2289 child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
james@538 2290 child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
james@538 2291 child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
james@538 2292 child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
james@538 2293 child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
james@538 2294 WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
james@536 2295
james@536 2296 bus_interface.Size = sizeof(BUS_INTERFACE_STANDARD);
james@536 2297 bus_interface.Version = 1; //BUS_INTERFACE_STANDARD_VERSION;
james@536 2298 bus_interface.Context = xppdd;
james@537 2299 bus_interface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
james@537 2300 bus_interface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
james@536 2301 bus_interface.TranslateBusAddress = XenPci_BIS_TranslateBusAddress;
james@536 2302 bus_interface.GetDmaAdapter = XenPci_BIS_GetDmaAdapter;
james@536 2303 bus_interface.SetBusData = XenPci_BIS_SetBusData;
james@536 2304 bus_interface.GetBusData = XenPci_BIS_GetBusData;
james@536 2305 WDF_QUERY_INTERFACE_CONFIG_INIT(&interface_config, (PINTERFACE)&bus_interface, &GUID_BUS_INTERFACE_STANDARD, NULL);
james@536 2306 status = WdfDeviceAddQueryInterface(child_device, &interface_config);
james@536 2307 if (!NT_SUCCESS(status))
james@536 2308 {
james@536 2309 return status;
james@536 2310 }
james@536 2311
james@536 2312 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
james@536 2313 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
james@536 2314 xppdd->index = identification->index;
james@536 2315 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
james@536 2316 xppdd->backend_state = XenbusStateUnknown;
james@538 2317 xppdd->frontend_state = XenbusStateUnknown;
james@536 2318 xppdd->backend_path[0] = '\0';
james@536 2319
james@536 2320 FUNCTION_EXIT();
james@536 2321
james@536 2322 return status;
james@536 2323 }
james@536 2324
james@536 2325 static __forceinline VOID
james@536 2326 XenPci_Pdo_ChangeSuspendState(WDFDEVICE device, ULONG new_state)
james@536 2327 {
james@536 2328 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2329 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2330
james@536 2331 FUNCTION_ENTER();
james@536 2332 KdPrint((__DRIVER_NAME " setting pdo state to %d\n", new_state));
james@536 2333 xppdd->device_state.suspend_resume_state_pdo = new_state;
james@536 2334 KeMemoryBarrier();
james@536 2335 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xpdd->pdo_event_channel));
james@536 2336 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
james@536 2337 while(xppdd->device_state.suspend_resume_state_fdo != xppdd->device_state.suspend_resume_state_pdo)
james@536 2338 {
james@536 2339 KdPrint((__DRIVER_NAME " waiting...\n"));
james@536 2340 KeWaitForSingleObject(&xpdd->pdo_suspend_event, Executive, KernelMode, FALSE, NULL);
james@536 2341 }
james@536 2342 KdPrint((__DRIVER_NAME " fdo state set to %d\n", new_state));
james@536 2343 FUNCTION_EXIT();
james@536 2344 }
james@536 2345
james@536 2346 /* called at PASSIVE_LEVEL */
james@536 2347 NTSTATUS
james@536 2348 XenPci_Pdo_Suspend(WDFDEVICE device)
james@536 2349 {
james@536 2350 NTSTATUS status = STATUS_SUCCESS;
james@536 2351 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2352 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2353 //LARGE_INTEGER wait_time;
james@536 2354 char path[128];
james@536 2355 PUCHAR in_ptr;
james@536 2356 UCHAR type;
james@536 2357 PVOID setting;
james@536 2358 PVOID value;
james@536 2359 PVOID value2;
james@536 2360
james@536 2361 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
james@536 2362
james@536 2363 if (xppdd->backend_state == XenbusStateConnected)
james@536 2364 {
james@536 2365 xppdd->restart_on_resume = TRUE;
james@536 2366 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_SUSPENDING);
james@536 2367
james@536 2368 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
james@536 2369 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
james@536 2370 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
james@536 2371
james@536 2372 if (xppdd->assigned_resources_start != NULL)
james@536 2373 {
james@536 2374 in_ptr = xppdd->assigned_resources_ptr;
james@536 2375 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 2376 in_ptr = xppdd->assigned_resources_start;
james@536 2377 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
james@536 2378 {
james@536 2379 switch (type)
james@536 2380 {
james@536 2381 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@536 2382 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
james@536 2383 EvtChn_Unbind(xpdd, PtrToUlong(value));
james@536 2384 EvtChn_Close(xpdd, PtrToUlong(value));
james@536 2385 break;
james@536 2386 }
james@536 2387 }
james@536 2388 }
james@536 2389
james@536 2390 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
james@536 2391 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
james@536 2392 }
james@536 2393 else
james@536 2394 {
james@536 2395 xppdd->restart_on_resume = FALSE;
james@536 2396 }
james@536 2397
james@536 2398 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@536 2399
james@536 2400 return status;
james@536 2401 }
james@536 2402
james@536 2403 NTSTATUS
james@536 2404 XenPci_Pdo_Resume(WDFDEVICE device)
james@536 2405 {
james@536 2406 NTSTATUS status = STATUS_SUCCESS;
james@536 2407 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
james@536 2408 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
james@536 2409 ULONG old_backend_state;
james@536 2410 PUCHAR src, dst;
james@536 2411
james@536 2412 FUNCTION_ENTER();
james@536 2413 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
james@536 2414
james@536 2415 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
james@536 2416 old_backend_state = xppdd->backend_state;
james@536 2417
james@536 2418 if (xppdd->restart_on_resume)
james@536 2419 {
james@536 2420 status = XenPci_GetBackendAndAddWatch(device);
james@536 2421
james@536 2422 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
james@536 2423 {
james@536 2424 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
james@536 2425 // this is probably an unrecoverable situation...
james@536 2426 FUNCTION_ERROR_EXIT();
james@536 2427 return STATUS_UNSUCCESSFUL;
james@536 2428 }
james@536 2429 if (xppdd->assigned_resources_ptr)
james@536 2430 {
james@536 2431 // reset things - feed the 'requested resources' back in
james@536 2432 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@536 2433 src = xppdd->requested_resources_start;
james@536 2434 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
james@536 2435 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
james@536 2436
james@536 2437 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
james@536 2438
james@536 2439 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
james@536 2440
james@536 2441 MmUnmapIoSpace(dst, xppdd->config_page_length);
james@536 2442 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
james@536 2443 }
james@536 2444 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
james@536 2445 {
james@536 2446 // this is definitely an unrecoverable situation...
james@536 2447 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
james@536 2448 FUNCTION_ERROR_EXIT();
james@536 2449 return STATUS_UNSUCCESSFUL;
james@536 2450 }
james@536 2451 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RESUMING);
james@536 2452 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RUNNING);
james@536 2453 }
james@536 2454
james@536 2455 FUNCTION_EXIT();
james@536 2456
james@536 2457 return STATUS_SUCCESS;
james@536 2458 }