win-pvdrivers

annotate xenpci/xenpci_pdo.c @ 536:1d39de3ab8d6

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