win-pvdrivers

view xenpci/xenpci_pdo.c @ 654:76b5aefeb46c

turn off some debugging
author James Harper <james.harper@bendigoit.com.au>
date Fri Sep 11 22:21:00 2009 +1000 (2009-09-11)
parents 6a160c1ad6e7
children e5522de3be37
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
20 #include "xenpci.h"
21 #include <stdlib.h>
22 #include <io/ring.h>
24 #pragma warning(disable : 4200) // zero-sized array
25 #pragma warning(disable: 4127) // conditional expression is constant
27 #define MAP_TYPE_VIRTUAL 1
28 #define MAP_TYPE_MDL 2
29 #define MAP_TYPE_REMAPPED 3
31 typedef struct {
32 ULONG map_type;
33 PVOID aligned_buffer;
34 ULONG copy_length;
35 PMDL mdl;
36 PVOID currentva;
37 BOOLEAN allocated_by_me;
38 } sg_extra_t;
40 typedef struct {
41 ULONG map_type;
42 PVOID aligned_buffer;
43 PVOID unaligned_buffer;
44 ULONG copy_length;
45 PHYSICAL_ADDRESS logical;
46 } map_register_t;
48 typedef struct {
49 PDEVICE_OBJECT device_object;
50 ULONG total_map_registers;
51 ULONG count;
52 map_register_t regs[1];
53 } map_register_base_t;
55 static BOOLEAN
56 XenPci_BIS_TranslateBusAddress(PVOID context, PHYSICAL_ADDRESS bus_address, ULONG length, PULONG address_space, PPHYSICAL_ADDRESS translated_address)
57 {
58 UNREFERENCED_PARAMETER(context);
59 UNREFERENCED_PARAMETER(length);
60 /* actually this isn't right - should look up the gref for the physical address and work backwards from that */
61 FUNCTION_ENTER();
62 if (*address_space != 0)
63 {
64 KdPrint((__DRIVER_NAME " Cannot map I/O space\n"));
65 FUNCTION_EXIT();
66 return FALSE;
67 }
68 *translated_address = bus_address;
69 FUNCTION_EXIT();
70 return TRUE;
71 }
73 static VOID
74 XenPci_DOP_PutDmaAdapter(PDMA_ADAPTER dma_adapter)
75 {
76 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
78 FUNCTION_ENTER();
80 if (xen_dma_adapter->dma_extension)
81 ObDereferenceObject(xen_dma_adapter->dma_extension_driver);
82 ExFreePoolWithTag(xen_dma_adapter->adapter_object.DmaHeader.DmaOperations, XENPCI_POOL_TAG);
83 ExFreePoolWithTag(xen_dma_adapter, XENPCI_POOL_TAG);
85 FUNCTION_EXIT();
87 return;
88 }
90 static PVOID
91 XenPci_DOP_AllocateCommonBuffer(
92 PDMA_ADAPTER DmaAdapter,
93 ULONG Length,
94 PPHYSICAL_ADDRESS LogicalAddress,
95 BOOLEAN CacheEnabled
96 )
97 {
98 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
99 PXENPCI_DEVICE_DATA xpdd;
100 PVOID buffer;
101 PFN_NUMBER pfn;
102 grant_ref_t gref;
104 UNREFERENCED_PARAMETER(DmaAdapter);
105 UNREFERENCED_PARAMETER(CacheEnabled);
107 //FUNCTION_ENTER();
109 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
111 //KdPrint((__DRIVER_NAME " Length = %d\n", Length));
113 buffer = ExAllocatePoolWithTag(NonPagedPool, Length, XENPCI_POOL_TAG);
114 ASSERT(buffer); /* lazy */
116 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(buffer).QuadPart >> PAGE_SHIFT);
117 ASSERT(pfn); /* lazy */
118 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
119 ASSERT(gref != INVALID_GRANT_REF); /* lazy */
120 LogicalAddress->QuadPart = (gref << PAGE_SHIFT) | (PtrToUlong(buffer) & (PAGE_SIZE - 1));
122 //FUNCTION_EXIT();
123 return buffer;
124 }
126 static VOID
127 XenPci_DOP_FreeCommonBuffer(
128 PDMA_ADAPTER dma_adapter,
129 ULONG length,
130 PHYSICAL_ADDRESS logical_address,
131 PVOID virtual_address,
132 BOOLEAN cache_enabled
133 )
134 {
135 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
136 PXENPCI_DEVICE_DATA xpdd;
137 grant_ref_t gref;
139 UNREFERENCED_PARAMETER(dma_adapter);
140 UNREFERENCED_PARAMETER(length);
141 UNREFERENCED_PARAMETER(cache_enabled);
143 // FUNCTION_ENTER();
145 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
146 gref = (grant_ref_t)(logical_address.QuadPart >> PAGE_SHIFT);
147 //KdPrint((__DRIVER_NAME " F Releasing Grant Ref %d\n", gref));
148 GntTbl_EndAccess(xpdd, gref, FALSE);
149 //KdPrint((__DRIVER_NAME " F Released Grant Ref\n"));
150 ExFreePoolWithTag(virtual_address, XENPCI_POOL_TAG);
152 // FUNCTION_EXIT();
153 }
155 static NTSTATUS
156 XenPci_DOP_AllocateAdapterChannel(
157 IN PDMA_ADAPTER dma_adapter,
158 IN PDEVICE_OBJECT device_object,
159 IN ULONG NumberOfMapRegisters,
160 IN PDRIVER_CONTROL ExecutionRoutine,
161 IN PVOID Context
162 )
163 {
164 //xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
165 //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
166 IO_ALLOCATION_ACTION action;
167 map_register_base_t *map_register_base;
169 UNREFERENCED_PARAMETER(dma_adapter);
171 //FUNCTION_ENTER();
173 map_register_base = ExAllocatePoolWithTag(NonPagedPool,
174 FIELD_OFFSET(map_register_base_t, regs) + NumberOfMapRegisters * sizeof(map_register_t), XENPCI_POOL_TAG);
175 if (!map_register_base)
176 {
177 KdPrint((__DRIVER_NAME " Cannot allocate memory for map_register_base\n"));
178 //FUNCTION_EXIT();
179 return STATUS_INSUFFICIENT_RESOURCES;
180 }
181 /* we should also allocate a single page of memory here for remap purposes as once we allocate the map registers there is no failure allowed */
182 map_register_base->device_object = device_object;
183 map_register_base->total_map_registers = NumberOfMapRegisters;
184 map_register_base->count = 0;
186 action = ExecutionRoutine(device_object, device_object->CurrentIrp, map_register_base, Context);
188 switch (action)
189 {
190 case KeepObject:
191 KdPrint((__DRIVER_NAME " KeepObject\n"));
192 ASSERT(FALSE);
193 break;
194 case DeallocateObject:
195 KdPrint((__DRIVER_NAME " DeallocateObject\n"));
196 ASSERT(FALSE);
197 break;
198 case DeallocateObjectKeepRegisters:
199 //KdPrint((__DRIVER_NAME " DeallocateObjectKeepRegisters\n"));
200 break;
201 default:
202 KdPrint((__DRIVER_NAME " Unknown action %d\n", action));
203 ASSERT(FALSE);
204 break;
205 }
206 //FUNCTION_EXIT();
207 return STATUS_SUCCESS;
208 }
210 static BOOLEAN
211 XenPci_DOP_FlushAdapterBuffers(
212 PDMA_ADAPTER dma_adapter,
213 PMDL mdl,
214 PVOID MapRegisterBase,
215 PVOID CurrentVa,
216 ULONG Length,
217 BOOLEAN write_to_device)
218 {
219 //xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
220 //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
221 map_register_base_t *map_register_base = MapRegisterBase;
222 map_register_t *map_register;
223 ULONG i;
225 UNREFERENCED_PARAMETER(dma_adapter);
226 UNREFERENCED_PARAMETER(mdl);
227 UNREFERENCED_PARAMETER(CurrentVa);
228 UNREFERENCED_PARAMETER(Length);
230 //FUNCTION_ENTER();
232 for (i = 0; i < map_register_base->count; i++)
233 {
234 map_register = &map_register_base->regs[i];
235 if (map_register->map_type == MAP_TYPE_REMAPPED && !write_to_device)
236 memcpy(map_register->unaligned_buffer, map_register->aligned_buffer, map_register->copy_length);
237 }
238 //FUNCTION_EXIT();
240 return TRUE;
241 }
243 static VOID
244 XenPci_DOP_FreeAdapterChannel(
245 IN PDMA_ADAPTER DmaAdapter
246 )
247 {
248 UNREFERENCED_PARAMETER(DmaAdapter);
250 FUNCTION_ENTER();
251 FUNCTION_EXIT();
252 }
254 static VOID
255 XenPci_DOP_FreeMapRegisters(
256 PDMA_ADAPTER dma_adapter,
257 PVOID MapRegisterBase,
258 ULONG NumberOfMapRegisters)
259 {
260 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
261 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
262 map_register_base_t *map_register_base = MapRegisterBase;
263 map_register_t *map_register;
264 ULONG i;
265 grant_ref_t gref;
267 //FUNCTION_ENTER();
268 if (!map_register_base)
269 {
270 /* i'm not sure if this is ideal here, but NDIS definitely does it */
271 return;
272 }
273 ASSERT(map_register_base->total_map_registers == NumberOfMapRegisters);
275 for (i = 0; i < map_register_base->count; i++)
276 {
277 map_register = &map_register_base->regs[i];
278 switch (map_register->map_type)
279 {
280 case MAP_TYPE_REMAPPED:
281 gref = (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT);
282 //KdPrint((__DRIVER_NAME " D Releasing Grant Ref %d\n", gref));
283 GntTbl_EndAccess(xpdd, gref, FALSE);
284 //KdPrint((__DRIVER_NAME " D Released Grant Ref\n"));
285 ExFreePoolWithTag(map_register->aligned_buffer, XENPCI_POOL_TAG);
286 break;
287 case MAP_TYPE_MDL:
288 gref = (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT);
289 //KdPrint((__DRIVER_NAME " E Releasing Grant Ref %d\n", gref));
290 GntTbl_EndAccess(xpdd, gref, FALSE);
291 //KdPrint((__DRIVER_NAME " E Released Grant Ref\n"));
292 break;
293 case MAP_TYPE_VIRTUAL:
294 break;
295 }
296 }
297 ExFreePoolWithTag(map_register_base, XENPCI_POOL_TAG);
299 //FUNCTION_EXIT();
300 }
302 static PHYSICAL_ADDRESS
303 XenPci_DOP_MapTransfer(
304 PDMA_ADAPTER dma_adapter,
305 PMDL mdl,
306 PVOID MapRegisterBase,
307 PVOID CurrentVa,
308 PULONG Length,
309 BOOLEAN WriteToDevice)
310 {
311 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
312 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
313 map_register_base_t *map_register_base = MapRegisterBase;
314 map_register_t *map_register = &map_register_base->regs[map_register_base->count];
315 PDEVICE_OBJECT device_object = map_register_base->device_object;
316 ULONG page_offset;
317 PFN_NUMBER pfn;
318 grant_ref_t gref;
319 PUCHAR ptr;
320 ULONG mdl_offset;
321 ULONG pfn_index;
323 //FUNCTION_ENTER();
325 //KdPrint((__DRIVER_NAME " Mdl = %p, MapRegisterBase = %p, MdlVa = %p, CurrentVa = %p, Length = %d\n",
326 // mdl, MapRegisterBase, MmGetMdlVirtualAddress(mdl), CurrentVa, *Length));
328 ASSERT(mdl);
329 ASSERT(map_register_base);
330 ASSERT(map_register_base->count < map_register_base->total_map_registers);
332 if (xen_dma_adapter->dma_extension)
333 {
334 if (xen_dma_adapter->dma_extension->need_virtual_address && xen_dma_adapter->dma_extension->need_virtual_address(device_object->CurrentIrp))
335 {
336 map_register->map_type = MAP_TYPE_VIRTUAL;
337 }
338 else
339 {
340 if (xen_dma_adapter->dma_extension->get_alignment)
341 {
342 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(device_object->CurrentIrp);
343 if ((MmGetMdlByteOffset(mdl) & (alignment - 1)) || (MmGetMdlByteCount(mdl) & (alignment - 1)))
344 {
345 map_register->map_type = MAP_TYPE_REMAPPED;
346 }
347 else
348 {
349 map_register->map_type = MAP_TYPE_MDL;
350 }
351 }
352 else
353 {
354 map_register->map_type = MAP_TYPE_MDL;
355 }
356 }
357 }
358 else
359 {
360 map_register->map_type = MAP_TYPE_MDL;
361 }
363 switch (map_register->map_type)
364 {
365 case MAP_TYPE_MDL:
366 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL\n"));
367 mdl_offset = (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)MmGetMdlVirtualAddress(mdl));
368 page_offset = PtrToUlong(CurrentVa) & (PAGE_SIZE - 1);
369 *Length = min(*Length, PAGE_SIZE - page_offset);
370 pfn_index = (ULONG)(((UINT_PTR)CurrentVa >> PAGE_SHIFT) - ((UINT_PTR)MmGetMdlVirtualAddress(mdl) >> PAGE_SHIFT));
371 //KdPrint((__DRIVER_NAME " mdl_offset = %d, page_offset = %d, length = %d, pfn_index = %d\n",
372 // mdl_offset, page_offset, *Length, pfn_index));
373 pfn = MmGetMdlPfnArray(mdl)[pfn_index];
374 //KdPrint((__DRIVER_NAME " B Requesting Grant Ref\n"));
375 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
376 //KdPrint((__DRIVER_NAME " B Got Grant Ref %d\n", gref));
377 map_register->logical.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | page_offset;
378 map_register_base->count++;
379 break;
380 case MAP_TYPE_REMAPPED:
381 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED (MapTransfer)\n"));
382 //KdPrint((__DRIVER_NAME " Mdl = %p, MapRegisterBase = %p, MdlVa = %p, CurrentVa = %p, Length = %d\n",
383 // mdl, MapRegisterBase, MmGetMdlVirtualAddress(mdl), CurrentVa, *Length));
384 mdl_offset = (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)MmGetMdlVirtualAddress(mdl));
385 *Length = min(*Length, PAGE_SIZE);
386 map_register->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
387 ASSERT(map_register->aligned_buffer);
388 map_register->unaligned_buffer = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
389 ASSERT(map_register->unaligned_buffer); /* lazy */
390 map_register->unaligned_buffer = (PUCHAR)map_register->unaligned_buffer + mdl_offset;
391 map_register->copy_length = *Length;
392 if (WriteToDevice)
393 memcpy(map_register->aligned_buffer, map_register->unaligned_buffer, map_register->copy_length);
394 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(map_register->aligned_buffer).QuadPart >> PAGE_SHIFT);
395 //KdPrint((__DRIVER_NAME " C Requesting Grant Ref\n"));
396 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
397 //KdPrint((__DRIVER_NAME " C Got Grant Ref %d\n", gref));
398 map_register->logical.QuadPart = (LONGLONG)(gref << PAGE_SHIFT);
399 map_register_base->count++;
400 break;
401 case MAP_TYPE_VIRTUAL:
402 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL\n"));
403 ptr = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
404 ASSERT(ptr); /* lazy */
405 map_register->logical.QuadPart = (ULONGLONG)ptr;
406 map_register_base->count++;
407 break;
408 default:
409 ASSERT(FALSE);
410 break;
411 }
413 //KdPrint((__DRIVER_NAME " logical = %08x:%08x\n", map_register->logical.HighPart, map_register->logical.LowPart));
414 //FUNCTION_EXIT();
415 return map_register->logical;
416 }
418 static ULONG
419 XenPci_DOP_GetDmaAlignment(
420 PDMA_ADAPTER DmaAdapter)
421 {
422 UNREFERENCED_PARAMETER(DmaAdapter);
424 FUNCTION_ENTER();
425 FUNCTION_EXIT();
426 return 0;
427 }
429 static ULONG
430 XenPci_DOP_ReadDmaCounter(
431 PDMA_ADAPTER DmaAdapter)
432 {
433 UNREFERENCED_PARAMETER(DmaAdapter);
435 FUNCTION_ENTER();
436 FUNCTION_EXIT();
437 return 0;
438 }
440 static VOID
441 XenPci_DOP_PutScatterGatherList(
442 IN PDMA_ADAPTER DmaAdapter,
443 IN PSCATTER_GATHER_LIST sg_list,
444 IN BOOLEAN WriteToDevice
445 )
446 {
447 xen_dma_adapter_t *xen_dma_adapter;
448 PXENPCI_DEVICE_DATA xpdd;
449 ULONG i;
450 sg_extra_t *sg_extra;
451 PMDL curr_mdl;
452 ULONG offset;
453 BOOLEAN active;
455 UNREFERENCED_PARAMETER(WriteToDevice);
457 //FUNCTION_ENTER();
459 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
460 ASSERT(xen_dma_adapter);
461 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
463 sg_extra = (sg_extra_t *)((PUCHAR)sg_list + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
464 (sizeof(SCATTER_GATHER_ELEMENT)) * sg_list->NumberOfElements);
466 switch (sg_extra->map_type)
467 {
468 case MAP_TYPE_REMAPPED:
469 for (i = 0; i < sg_list->NumberOfElements; i++)
470 {
471 grant_ref_t gref;
472 gref = (grant_ref_t)(sg_list->Elements[i].Address.QuadPart >> PAGE_SHIFT);
473 GntTbl_EndAccess(xpdd, gref, FALSE);
474 sg_list->Elements[i].Address.QuadPart = -1;
475 }
476 ASSERT(sg_extra->mdl);
477 if (!WriteToDevice)
478 {
479 for (curr_mdl = sg_extra->mdl, offset = 0, active = FALSE; curr_mdl; curr_mdl = curr_mdl->Next)
480 {
481 PVOID mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
482 ULONG mdl_byte_count = MmGetMdlByteCount(curr_mdl);
483 ULONG mdl_offset = 0;
484 /* need to use <= va + len - 1 to avoid ptr wraparound */
485 if ((UINT_PTR)sg_extra->currentva >= (UINT_PTR)mdl_start_va && (UINT_PTR)sg_extra->currentva <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
486 {
487 active = TRUE;
488 mdl_byte_count -= (ULONG)((UINT_PTR)sg_extra->currentva - (UINT_PTR)mdl_start_va);
489 mdl_offset = (ULONG)((UINT_PTR)sg_extra->currentva - (UINT_PTR)mdl_start_va);
490 mdl_start_va = sg_extra->currentva;
491 }
492 if (active)
493 {
494 PVOID unaligned_buffer;
495 unaligned_buffer = MmGetSystemAddressForMdlSafe(curr_mdl, NormalPagePriority);
496 ASSERT(unaligned_buffer); /* lazy */
497 memcpy((PUCHAR)unaligned_buffer + mdl_offset, (PUCHAR)sg_extra->aligned_buffer + offset, mdl_byte_count);
498 offset += mdl_byte_count;
499 }
500 }
501 }
502 ExFreePoolWithTag(sg_extra->aligned_buffer, XENPCI_POOL_TAG);
503 break;
504 case MAP_TYPE_MDL:
505 for (i = 0; i < sg_list->NumberOfElements; i++)
506 {
507 grant_ref_t gref;
508 gref = (grant_ref_t)(sg_list->Elements[i].Address.QuadPart >> PAGE_SHIFT);
509 GntTbl_EndAccess(xpdd, gref, FALSE);
510 sg_list->Elements[i].Address.QuadPart = -1;
511 }
512 break;
513 case MAP_TYPE_VIRTUAL:
514 break;
515 }
516 if (sg_extra->allocated_by_me)
517 ExFreePoolWithTag(sg_list, XENPCI_POOL_TAG);
518 //FUNCTION_EXIT();
519 }
521 static NTSTATUS
522 XenPci_DOP_CalculateScatterGatherList(
523 PDMA_ADAPTER DmaAdapter,
524 PMDL Mdl,
525 PVOID CurrentVa,
526 ULONG Length,
527 PULONG ScatterGatherListSize,
528 PULONG NumberOfMapRegisters
529 )
530 {
531 xen_dma_adapter_t *xen_dma_adapter;
532 ULONG elements;
533 PMDL curr_mdl;
535 UNREFERENCED_PARAMETER(CurrentVa);
537 //FUNCTION_ENTER();
539 //KdPrint((__DRIVER_NAME " Mdl = %p\n", Mdl));
540 //KdPrint((__DRIVER_NAME " CurrentVa = %p\n", CurrentVa));
541 //KdPrint((__DRIVER_NAME " Length = %d\n", Length));
543 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
545 if (Mdl)
546 {
547 //if (CurrentVa != MmGetMdlVirtualAddress(Mdl))
548 //{
549 // KdPrint((__DRIVER_NAME " CurrentVa (%p) != MdlVa (%p)\n", CurrentVa, MmGetMdlVirtualAddress(Mdl)));
550 //
552 //KdPrint((__DRIVER_NAME " CurrentVa = %p, MdlVa = %p\n", CurrentVa, MmGetMdlVirtualAddress(Mdl)));
554 for (curr_mdl = Mdl, elements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
555 {
556 //KdPrint((__DRIVER_NAME " curr_mdlVa = %p, curr_mdl size = %d\n", MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)));
557 elements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
558 }
559 }
560 else
561 {
562 elements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, Length); // + 1;
563 }
565 if (elements > xen_dma_adapter->adapter_object.MapRegistersPerChannel)
566 {
567 //KdPrint((__DRIVER_NAME " elements = %d - too many\n", elements));
568 if (NumberOfMapRegisters)
569 *NumberOfMapRegisters = 0;
570 *ScatterGatherListSize = 0;
572 return STATUS_INSUFFICIENT_RESOURCES;
573 }
575 *ScatterGatherListSize = FIELD_OFFSET(SCATTER_GATHER_LIST, Elements)
576 + sizeof(SCATTER_GATHER_ELEMENT) * elements
577 + sizeof(sg_extra_t);
578 if (NumberOfMapRegisters)
579 *NumberOfMapRegisters = elements;
581 //KdPrint((__DRIVER_NAME " ScatterGatherListSize = %d, NumberOfMapRegisters = %d\n", *ScatterGatherListSize, elements));
583 //FUNCTION_EXIT();
584 return STATUS_SUCCESS;
585 }
587 static NTSTATUS
588 XenPci_DOP_BuildScatterGatherListButDontExecute(
589 IN PDMA_ADAPTER DmaAdapter,
590 IN PDEVICE_OBJECT DeviceObject,
591 IN PMDL Mdl,
592 IN PVOID CurrentVa,
593 IN ULONG Length,
594 IN BOOLEAN WriteToDevice,
595 IN PVOID ScatterGatherBuffer,
596 IN ULONG ScatterGatherBufferLength,
597 BOOLEAN allocated_by_me)
598 {
599 ULONG i;
600 PSCATTER_GATHER_LIST sglist = ScatterGatherBuffer;
601 PUCHAR ptr;
602 ULONG remaining = Length;
603 ULONG total_remaining;
604 xen_dma_adapter_t *xen_dma_adapter;
605 PXENPCI_DEVICE_DATA xpdd;
606 sg_extra_t *sg_extra;
607 PMDL curr_mdl;
608 ULONG map_type;
609 ULONG sg_element;
610 ULONG offset;
611 PFN_NUMBER pfn;
612 grant_ref_t gref;
613 BOOLEAN active;
614 PVOID mdl_start_va;
615 ULONG mdl_byte_count;
616 ULONG mdl_offset;
617 ULONG remapped_bytes = 0;
619 //FUNCTION_ENTER();
621 if (!ScatterGatherBuffer)
622 {
623 KdPrint((__DRIVER_NAME " NULL ScatterGatherBuffer\n"));
624 return STATUS_INVALID_PARAMETER;
625 }
626 //if (MmGetMdlVirtualAddress(Mdl) != CurrentVa)
627 //{
628 // KdPrint((__DRIVER_NAME " MmGetMdlVirtualAddress = %p, CurrentVa = %p, Length = %d\n", MmGetMdlVirtualAddress(Mdl), CurrentVa, Length));
629 //}
631 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
632 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
634 ASSERT(Mdl);
636 if (xen_dma_adapter->dma_extension)
637 {
638 if (xen_dma_adapter->dma_extension->need_virtual_address && xen_dma_adapter->dma_extension->need_virtual_address(DeviceObject->CurrentIrp))
639 {
640 ASSERT(!Mdl->Next); /* can only virtual a single buffer */
641 //ASSERT(MmGetMdlVirtualAddress(Mdl) == CurrentVa);
642 map_type = MAP_TYPE_VIRTUAL;
643 sglist->NumberOfElements = 1;
644 }
645 else
646 {
647 if (xen_dma_adapter->dma_extension->get_alignment)
648 {
649 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(DeviceObject->CurrentIrp);
651 map_type = MAP_TYPE_MDL;
652 sglist->NumberOfElements = 0;
653 for (curr_mdl = Mdl, remapped_bytes = 0, active = FALSE; curr_mdl; curr_mdl = curr_mdl->Next)
654 {
655 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
656 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
657 /* need to use <= va + len - 1 to avoid ptr wraparound */
658 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
659 {
660 active = TRUE;
661 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
662 mdl_start_va = CurrentVa;
663 }
664 if (active)
665 {
666 if (((UINT_PTR)mdl_start_va & (alignment - 1)) || (mdl_byte_count & (alignment - 1)))
667 map_type = MAP_TYPE_REMAPPED;
668 remapped_bytes += mdl_byte_count;
669 }
670 }
671 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(NULL, remapped_bytes);
672 }
673 else
674 {
675 map_type = MAP_TYPE_MDL;
676 }
677 }
678 }
679 else
680 {
681 map_type = MAP_TYPE_MDL;
682 }
683 if (map_type == MAP_TYPE_MDL)
684 {
685 for (curr_mdl = Mdl, sglist->NumberOfElements = 0, total_remaining = Length, active = FALSE; total_remaining > 0; curr_mdl = curr_mdl->Next)
686 {
687 ASSERT(curr_mdl);
688 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
689 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
690 /* need to use <= va + len - 1 to avoid ptr wraparound */
691 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
692 {
693 active = TRUE;
694 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
695 mdl_start_va = CurrentVa;
696 }
697 mdl_byte_count = min(mdl_byte_count, total_remaining);
698 if (active)
699 {
700 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
701 mdl_start_va, mdl_byte_count);
702 total_remaining -= mdl_byte_count;
703 }
704 }
705 }
706 if (ScatterGatherBufferLength < FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
707 sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t))
708 {
709 //KdPrint((__DRIVER_NAME " STATUS_BUFFER_TOO_SMALL (%d < %d)\n", ScatterGatherBufferLength, FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
710 // sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t)));
711 return STATUS_BUFFER_TOO_SMALL;
712 }
714 sg_extra = (sg_extra_t *)((PUCHAR)sglist + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
715 (sizeof(SCATTER_GATHER_ELEMENT)) * sglist->NumberOfElements);
717 sg_extra->allocated_by_me = allocated_by_me;
719 sg_extra->map_type = map_type;
720 switch (map_type)
721 {
722 case MAP_TYPE_MDL:
723 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL - %p\n", MmGetMdlVirtualAddress(Mdl)));
724 total_remaining = Length;
725 for (sg_element = 0, curr_mdl = Mdl, active = FALSE; total_remaining > 0; curr_mdl = curr_mdl->Next)
726 {
727 ASSERT(curr_mdl);
728 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
729 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
730 /* need to use <= va + len - 1 to avoid ptr wraparound */
731 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
732 {
733 active = TRUE;
734 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
735 mdl_start_va = CurrentVa;
736 }
737 if (active)
738 {
739 ULONG pfn_offset;
740 remaining = min(mdl_byte_count, total_remaining);
741 offset = (ULONG)((UINT_PTR)mdl_start_va & (PAGE_SIZE - 1));
742 pfn_offset = (ULONG)(((UINT_PTR)mdl_start_va >> PAGE_SHIFT) - ((UINT_PTR)MmGetMdlVirtualAddress(curr_mdl) >> PAGE_SHIFT));
743 //for (i = 0; i < ADDRESS_AND_SIZE_TO_SPAN_PAGES(mdl_start_va, mdl_byte_count); i++)
744 for (i = 0; remaining > 0; i++)
745 {
746 pfn = MmGetMdlPfnArray(curr_mdl)[pfn_offset + i];
747 ASSERT(pfn);
748 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
749 ASSERT(gref != INVALID_GRANT_REF);
750 sglist->Elements[sg_element].Address.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | offset;
751 sglist->Elements[sg_element].Length = min(min(PAGE_SIZE - offset, remaining), total_remaining);
752 total_remaining -= sglist->Elements[sg_element].Length;
753 remaining -= sglist->Elements[sg_element].Length;
754 offset = 0;
755 sg_element++;
756 }
757 }
758 }
759 if (sg_element != sglist->NumberOfElements)
760 {
761 KdPrint((__DRIVER_NAME " sg_element = %d, sglist->NumberOfElements = %d\n", sg_element, sglist->NumberOfElements));
762 KdPrint((__DRIVER_NAME " CurrentVa = %p, Length = %d\n", CurrentVa, Length));
763 for (curr_mdl = Mdl; curr_mdl; curr_mdl = curr_mdl->Next)
764 {
765 KdPrint((__DRIVER_NAME " Mdl = %p, VirtualAddress = %p, ByteCount = %d\n", Mdl, MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)));
766 }
767 }
768 ASSERT(sg_element == sglist->NumberOfElements);
769 break;
770 case MAP_TYPE_REMAPPED:
771 sg_extra->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, max(remapped_bytes, PAGE_SIZE), XENPCI_POOL_TAG);
772 if (!sg_extra->aligned_buffer)
773 {
774 KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED buffer allocation failed - requested va = %p, length = %d\n", MmGetMdlVirtualAddress(Mdl), remapped_bytes));
775 return STATUS_INSUFFICIENT_RESOURCES;
776 }
777 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED - %p\n", sg_extra->aligned_buffer));
778 sg_extra->mdl = Mdl;
779 sg_extra->currentva = CurrentVa;
780 sg_extra->copy_length = remapped_bytes;
782 if (WriteToDevice)
783 {
784 for (curr_mdl = Mdl, offset = 0, active = FALSE; curr_mdl; curr_mdl = curr_mdl->Next)
785 {
786 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
787 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
788 mdl_offset = 0;
789 /* need to use <= va + len - 1 to avoid ptr wraparound */
790 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
791 {
792 active = TRUE;
793 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
794 mdl_offset = (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
795 mdl_start_va = CurrentVa;
796 }
797 if (active)
798 {
799 PVOID unaligned_buffer;
800 unaligned_buffer = (PUCHAR)MmGetSystemAddressForMdlSafe(curr_mdl, NormalPagePriority);
801 ASSERT(unaligned_buffer); /* lazy */
802 memcpy((PUCHAR)sg_extra->aligned_buffer + offset, (PUCHAR)unaligned_buffer + mdl_offset, mdl_byte_count);
803 offset += mdl_byte_count;
804 }
805 }
806 }
807 for (sg_element = 0, remaining = remapped_bytes;
808 sg_element < ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_extra->aligned_buffer, remapped_bytes); sg_element++)
809 {
810 pfn = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)sg_extra->aligned_buffer + (sg_element << PAGE_SHIFT)).QuadPart >> PAGE_SHIFT);
811 ASSERT(pfn);
812 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
813 ASSERT(gref != INVALID_GRANT_REF);
814 sglist->Elements[sg_element].Address.QuadPart = (ULONGLONG)gref << PAGE_SHIFT;
815 sglist->Elements[sg_element].Length = min(PAGE_SIZE, remaining);
816 remaining -= sglist->Elements[sg_element].Length;
817 }
818 break;
819 case MAP_TYPE_VIRTUAL:
820 ptr = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
821 ASSERT(ptr); /* lazy */
822 sglist->Elements[0].Address.QuadPart = (ULONGLONG)ptr + ((UINT_PTR)CurrentVa - (UINT_PTR)MmGetMdlVirtualAddress(Mdl));
823 sglist->Elements[0].Length = Length;
824 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL - %08x\n", sglist->Elements[0].Address.LowPart));
825 break;
826 default:
827 KdPrint((__DRIVER_NAME " map_type = %d\n", map_type));
828 break;
829 }
830 //FUNCTION_EXIT();
831 return STATUS_SUCCESS;
832 }
834 static NTSTATUS
835 XenPci_DOP_BuildScatterGatherList(
836 IN PDMA_ADAPTER DmaAdapter,
837 IN PDEVICE_OBJECT DeviceObject,
838 IN PMDL Mdl,
839 IN PVOID CurrentVa,
840 IN ULONG Length,
841 IN PDRIVER_LIST_CONTROL ExecutionRoutine,
842 IN PVOID Context,
843 IN BOOLEAN WriteToDevice,
844 IN PVOID ScatterGatherBuffer,
845 IN ULONG ScatterGatherBufferLength)
846 {
847 NTSTATUS status;
849 status = XenPci_DOP_BuildScatterGatherListButDontExecute(DmaAdapter, DeviceObject, Mdl, CurrentVa, Length, WriteToDevice, ScatterGatherBuffer, ScatterGatherBufferLength, FALSE);
851 if (NT_SUCCESS(status))
852 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, ScatterGatherBuffer, Context);
854 //FUNCTION_EXIT();
856 return status;
857 }
859 static NTSTATUS
860 XenPci_DOP_GetScatterGatherList(
861 PDMA_ADAPTER DmaAdapter,
862 PDEVICE_OBJECT DeviceObject,
863 PMDL Mdl,
864 PVOID CurrentVa,
865 ULONG Length,
866 PDRIVER_LIST_CONTROL ExecutionRoutine,
867 PVOID Context,
868 BOOLEAN WriteToDevice)
869 {
870 NTSTATUS status;
871 ULONG list_size;
872 ULONG map_registers;
873 PSCATTER_GATHER_LIST sg_list;
875 //FUNCTION_ENTER();
877 status = XenPci_DOP_CalculateScatterGatherList(DmaAdapter, Mdl, CurrentVa, Length, &list_size, &map_registers);
878 if (!NT_SUCCESS(status))
879 {
880 //FUNCTION_EXIT();
881 return status;
882 }
884 sg_list = ExAllocatePoolWithTag(NonPagedPool, list_size, XENPCI_POOL_TAG);
885 if (!sg_list)
886 {
887 KdPrint((__DRIVER_NAME " Cannot allocate memory for sg_list\n"));
888 //FUNCTION_EXIT();
889 return STATUS_INSUFFICIENT_RESOURCES;
890 }
892 status = XenPci_DOP_BuildScatterGatherListButDontExecute(DmaAdapter, DeviceObject, Mdl, CurrentVa, Length, WriteToDevice, sg_list, list_size, TRUE);
894 if (NT_SUCCESS(status))
895 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, sg_list, Context);
897 //FUNCTION_EXIT();
899 return status;
900 }
902 static NTSTATUS
903 XenPci_DOP_BuildMdlFromScatterGatherList(
904 PDMA_ADAPTER DmaAdapter,
905 PSCATTER_GATHER_LIST ScatterGather,
906 PMDL OriginalMdl,
907 PMDL *TargetMdl)
908 {
909 NTSTATUS status = STATUS_SUCCESS;
910 UNREFERENCED_PARAMETER(DmaAdapter);
911 UNREFERENCED_PARAMETER(ScatterGather);
912 UNREFERENCED_PARAMETER(OriginalMdl);
913 UNREFERENCED_PARAMETER(TargetMdl);
915 FUNCTION_ENTER();
917 if (OriginalMdl)
918 {
919 *TargetMdl = OriginalMdl;
920 }
921 else
922 {
923 *TargetMdl = NULL;
924 status = STATUS_INVALID_PARAMETER;
925 }
927 FUNCTION_EXIT();
929 return status;
930 }
932 static PDMA_ADAPTER
933 XenPci_BIS_GetDmaAdapter(PVOID context, PDEVICE_DESCRIPTION device_description, PULONG number_of_map_registers)
934 {
935 xen_dma_adapter_t *xen_dma_adapter;
936 PDEVICE_OBJECT curr, prev;
937 PDRIVER_OBJECT fdo_driver_object;
938 PVOID fdo_driver_extension;
940 UNREFERENCED_PARAMETER(device_description);
942 FUNCTION_ENTER();
944 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
945 KdPrint((__DRIVER_NAME " Device Description = %p:\n", device_description));
946 KdPrint((__DRIVER_NAME " Version = %d\n", device_description->Version));
947 KdPrint((__DRIVER_NAME " Master = %d\n", device_description->Master));
948 KdPrint((__DRIVER_NAME " ScatterGather = %d\n", device_description->ScatterGather));
949 KdPrint((__DRIVER_NAME " DemandMode = %d\n", device_description->DemandMode));
950 KdPrint((__DRIVER_NAME " AutoInitialize = %d\n", device_description->AutoInitialize));
951 KdPrint((__DRIVER_NAME " Dma32BitAddresses = %d\n", device_description->Dma32BitAddresses));
952 KdPrint((__DRIVER_NAME " IgnoreCount = %d\n", device_description->IgnoreCount));
953 KdPrint((__DRIVER_NAME " Dma64BitAddresses = %d\n", device_description->Dma64BitAddresses));
954 KdPrint((__DRIVER_NAME " BusNumber = %d\n", device_description->BusNumber));
955 KdPrint((__DRIVER_NAME " DmaChannel = %d\n", device_description->DmaChannel));
956 KdPrint((__DRIVER_NAME " InterfaceType = %d\n", device_description->InterfaceType));
957 KdPrint((__DRIVER_NAME " DmaWidth = %d\n", device_description->DmaWidth));
958 KdPrint((__DRIVER_NAME " DmaSpeed = %d\n", device_description->DmaSpeed));
959 KdPrint((__DRIVER_NAME " MaximumLength = %d\n", device_description->MaximumLength));
960 KdPrint((__DRIVER_NAME " DmaPort = %d\n", device_description->DmaPort));
962 if (!device_description->Master)
963 return NULL;
964 /*
965 we have to allocate PAGE_SIZE bytes here because Windows thinks this is
966 actually an ADAPTER_OBJECT, and then the verifier crashes because
967 Windows accessed beyond the end of the structure :(
968 */
969 xen_dma_adapter = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
970 ASSERT(xen_dma_adapter);
971 RtlZeroMemory(xen_dma_adapter, PAGE_SIZE);
973 switch(device_description->Version)
974 {
975 case DEVICE_DESCRIPTION_VERSION1:
976 xen_dma_adapter->adapter_object.DmaHeader.Version = 1;
977 break;
978 case DEVICE_DESCRIPTION_VERSION: /* ignore what the docs say here - DEVICE_DESCRIPTION_VERSION appears to mean the latest version */
979 case DEVICE_DESCRIPTION_VERSION2:
980 xen_dma_adapter->adapter_object.DmaHeader.Version = 2;
981 break;
982 default:
983 KdPrint((__DRIVER_NAME " Unsupported device description version %d\n", device_description->Version));
984 ExFreePoolWithTag(xen_dma_adapter, XENPCI_POOL_TAG);
985 return NULL;
986 }
988 xen_dma_adapter->xppdd = context;
989 xen_dma_adapter->dma_extension = NULL;
991 KdPrint((__DRIVER_NAME " About to call IoGetAttachedDeviceReference\n"));
992 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(xen_dma_adapter->xppdd->wdf_device));
993 KdPrint((__DRIVER_NAME " Before start of loop - curr = %p\n", curr));
994 while (curr != NULL)
995 {
996 fdo_driver_object = curr->DriverObject;
997 if (fdo_driver_object)
998 {
999 ObReferenceObject(fdo_driver_object);
1000 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC));
1001 if (fdo_driver_extension)
1003 xen_dma_adapter->dma_extension_driver = fdo_driver_object; /* so we can dereference it on putdmaadapter */
1004 xen_dma_adapter->dma_extension = (dma_driver_extension_t *)fdo_driver_extension;
1005 ObDereferenceObject(curr);
1006 break;
1008 else
1010 ObDereferenceObject(fdo_driver_object);
1013 prev = curr;
1014 curr = IoGetLowerDeviceObject(curr);
1015 ObDereferenceObject(prev);
1017 KdPrint((__DRIVER_NAME " End of loop\n"));
1019 xen_dma_adapter->adapter_object.DmaHeader.Size = sizeof(X_ADAPTER_OBJECT); //xen_dma_adapter_t);
1020 xen_dma_adapter->adapter_object.MasterAdapter = NULL;
1021 if (xen_dma_adapter->dma_extension && xen_dma_adapter->dma_extension->max_sg_elements)
1023 xen_dma_adapter->adapter_object.MapRegistersPerChannel = xen_dma_adapter->dma_extension->max_sg_elements;
1025 else
1027 xen_dma_adapter->adapter_object.MapRegistersPerChannel = 256;
1029 xen_dma_adapter->adapter_object.AdapterBaseVa = NULL;
1030 xen_dma_adapter->adapter_object.MapRegisterBase = NULL;
1031 xen_dma_adapter->adapter_object.NumberOfMapRegisters = 0;
1032 xen_dma_adapter->adapter_object.CommittedMapRegisters = 0;
1033 xen_dma_adapter->adapter_object.CurrentWcb = NULL;
1034 KeInitializeDeviceQueue(&xen_dma_adapter->adapter_object.ChannelWaitQueue);
1035 xen_dma_adapter->adapter_object.RegisterWaitQueue = NULL;
1036 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterQueue);
1037 KeInitializeSpinLock(&xen_dma_adapter->adapter_object.SpinLock);
1038 xen_dma_adapter->adapter_object.MapRegisters = NULL;
1039 xen_dma_adapter->adapter_object.PagePort = NULL;
1040 xen_dma_adapter->adapter_object.ChannelNumber = 0xff;
1041 xen_dma_adapter->adapter_object.AdapterNumber = 0;
1042 xen_dma_adapter->adapter_object.DmaPortAddress = 0;
1043 xen_dma_adapter->adapter_object.AdapterMode = 0;
1044 xen_dma_adapter->adapter_object.NeedsMapRegisters = FALSE; /* when true this causes a crash in the crash dump path */
1045 xen_dma_adapter->adapter_object.MasterDevice = 1;
1046 xen_dma_adapter->adapter_object.Width16Bits = 0;
1047 xen_dma_adapter->adapter_object.ScatterGather = device_description->ScatterGather;
1048 xen_dma_adapter->adapter_object.IgnoreCount = device_description->IgnoreCount;
1049 xen_dma_adapter->adapter_object.Dma32BitAddresses = device_description->Dma32BitAddresses;
1050 xen_dma_adapter->adapter_object.Dma64BitAddresses = device_description->Dma64BitAddresses;
1051 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterList);
1053 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DMA_OPERATIONS), XENPCI_POOL_TAG);
1054 ASSERT(xen_dma_adapter->adapter_object.DmaHeader.DmaOperations);
1055 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 1)
1057 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = FIELD_OFFSET(DMA_OPERATIONS, CalculateScatterGatherList);
1059 else
1061 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = sizeof(DMA_OPERATIONS);
1063 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutDmaAdapter = XenPci_DOP_PutDmaAdapter;
1064 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateCommonBuffer = XenPci_DOP_AllocateCommonBuffer;
1065 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeCommonBuffer = XenPci_DOP_FreeCommonBuffer;
1066 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateAdapterChannel = XenPci_DOP_AllocateAdapterChannel;
1067 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FlushAdapterBuffers = XenPci_DOP_FlushAdapterBuffers;
1068 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeAdapterChannel = XenPci_DOP_FreeAdapterChannel;
1069 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeMapRegisters = XenPci_DOP_FreeMapRegisters;
1070 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->MapTransfer = XenPci_DOP_MapTransfer;
1071 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetDmaAlignment = XenPci_DOP_GetDmaAlignment;
1072 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->ReadDmaCounter = XenPci_DOP_ReadDmaCounter;
1073 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetScatterGatherList = XenPci_DOP_GetScatterGatherList;
1074 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutScatterGatherList = XenPci_DOP_PutScatterGatherList;
1075 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 2)
1077 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->CalculateScatterGatherList = XenPci_DOP_CalculateScatterGatherList;
1078 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildScatterGatherList = XenPci_DOP_BuildScatterGatherList;
1079 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildMdlFromScatterGatherList = XenPci_DOP_BuildMdlFromScatterGatherList;
1082 *number_of_map_registers = xen_dma_adapter->adapter_object.MapRegistersPerChannel; //1024; /* why not... */
1084 FUNCTION_EXIT();
1086 return &xen_dma_adapter->adapter_object.DmaHeader;
1089 static ULONG
1090 XenPci_BIS_SetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
1092 UNREFERENCED_PARAMETER(context);
1093 UNREFERENCED_PARAMETER(data_type);
1094 UNREFERENCED_PARAMETER(buffer);
1095 UNREFERENCED_PARAMETER(offset);
1096 UNREFERENCED_PARAMETER(length);
1098 FUNCTION_ENTER();
1099 FUNCTION_EXIT();
1100 return 0;
1103 static ULONG
1104 XenPci_BIS_GetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
1106 UNREFERENCED_PARAMETER(context);
1107 UNREFERENCED_PARAMETER(data_type);
1108 UNREFERENCED_PARAMETER(buffer);
1109 UNREFERENCED_PARAMETER(offset);
1110 UNREFERENCED_PARAMETER(length);
1112 FUNCTION_ENTER();
1113 FUNCTION_EXIT();
1114 return 0;
1117 /*
1118 Called at PASSIVE_LEVEL(?)
1119 Called during restore
1120 */
1121 static ULONG
1122 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
1124 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1125 char path[128];
1126 char *value;
1127 char *err;
1128 ULONG backend_state;
1130 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1131 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
1132 if (err)
1134 XenPci_FreeMem(err);
1135 return XenbusStateUnknown;
1137 else
1139 backend_state = atoi(value);
1140 XenPci_FreeMem(value);
1141 return backend_state;
1145 static NTSTATUS
1146 XenPciPdo_ReconfigureCompletionRoutine(
1147 PDEVICE_OBJECT device_object,
1148 PIRP irp,
1149 PVOID context)
1151 UNREFERENCED_PARAMETER(device_object);
1153 if (irp->PendingReturned)
1155 KeSetEvent ((PKEVENT)context, IO_NO_INCREMENT, FALSE);
1157 return STATUS_MORE_PROCESSING_REQUIRED;
1160 static VOID
1161 XenPci_UpdateBackendState(PVOID context)
1163 WDFDEVICE device = context;
1164 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1165 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1166 ULONG new_backend_state;
1167 CHAR tmp_path[128];
1169 FUNCTION_ENTER();
1171 ExAcquireFastMutex(&xppdd->backend_state_mutex);
1173 new_backend_state = XenPci_ReadBackendState(xppdd);
1174 if (new_backend_state == XenbusStateUnknown)
1176 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
1178 ExReleaseFastMutex(&xppdd->backend_state_mutex);
1179 return;
1181 KdPrint(("Failed to read path, assuming closed\n"));
1182 new_backend_state = XenbusStateClosed;
1185 if (xppdd->backend_state == new_backend_state)
1187 KdPrint((__DRIVER_NAME " state unchanged\n"));
1188 ExReleaseFastMutex(&xppdd->backend_state_mutex);
1189 return;
1192 xppdd->backend_state = new_backend_state;
1194 switch (xppdd->backend_state)
1196 case XenbusStateUnknown:
1197 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
1198 break;
1200 case XenbusStateInitialising:
1201 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
1202 break;
1204 case XenbusStateInitWait:
1205 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
1206 break;
1208 case XenbusStateInitialised:
1209 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
1210 break;
1212 case XenbusStateConnected:
1213 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
1214 break;
1216 case XenbusStateClosing:
1217 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
1218 if (xppdd->frontend_state == XenbusStateConnected)
1220 KdPrint((__DRIVER_NAME " Requesting eject\n"));
1221 WdfPdoRequestEject(device);
1223 break;
1225 case XenbusStateClosed:
1226 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
1227 break;
1229 case XenbusStateReconfiguring:
1230 KdPrint((__DRIVER_NAME " Backend State Changed to Reconfiguring\n"));
1231 RtlStringCbPrintfA(tmp_path, ARRAY_SIZE(tmp_path), "%s/state", xppdd->path);
1232 KdPrint((__DRIVER_NAME " Setting %s to %d\n", tmp_path, XenbusStateReconfiguring));
1233 XenBus_Printf(xpdd, XBT_NIL, tmp_path, "%d", XenbusStateReconfiguring);
1234 break;
1236 case XenbusStateReconfigured:
1237 KdPrint((__DRIVER_NAME " Backend State Changed to Reconfigured\n"));
1239 PDEVICE_OBJECT fdo;
1240 PIRP irp;
1241 PIO_STACK_LOCATION stack;
1242 NTSTATUS status;
1243 KEVENT irp_complete_event;
1245 fdo = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(device));
1246 KeInitializeEvent(&irp_complete_event, NotificationEvent, FALSE);
1247 irp = IoAllocateIrp(fdo->StackSize, FALSE);
1248 stack = IoGetNextIrpStackLocation(irp);
1249 stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
1250 stack->Parameters.DeviceIoControl.IoControlCode = (ULONG)IOCTL_XEN_RECONFIGURE;
1251 IoSetCompletionRoutine(irp, XenPciPdo_ReconfigureCompletionRoutine, &irp_complete_event, TRUE, TRUE, TRUE);
1252 status = IoCallDriver(fdo, irp);
1253 if (status == STATUS_PENDING)
1255 KdPrint((__DRIVER_NAME " Waiting for completion\n"));
1256 status = KeWaitForSingleObject(&irp_complete_event, Executive, KernelMode, FALSE, NULL);
1257 status = irp->IoStatus.Status;
1259 KdPrint((__DRIVER_NAME " IOCTL_XEN_RECONFIGURE status = %08x\n", status));
1260 ObDereferenceObject(fdo);
1261 #if 0
1262 WDFREQUEST request;
1263 WDF_REQUEST_SEND_OPTIONS options;
1264 WDFIOTARGET target;
1265 DEVICE_OBJECT fdo;
1267 WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET);
1268 fdo = IoGetAttachedDevice(WdfDeviceWdmGetDeviceObject(device));
1270 target = WdfDeviceGetIoTarget(xppdd->wdf_device);
1271 WdfRequestCreate(WDF_NO_OBJECT_ATTRIBUTES, target, &request);
1272 WdfIoTargetFormatRequestForInternalIoctl(target, request, IOCTL_XEN_RECONFIGURE, NULL, NULL, NULL, NULL);
1273 WdfRequestSend(request, target, &options);
1274 #endif
1275 RtlStringCbPrintfA(tmp_path, ARRAY_SIZE(tmp_path), "%s/state", xppdd->path);
1276 KdPrint((__DRIVER_NAME " Setting %s to %d\n", tmp_path, XenbusStateConnected));
1277 XenBus_Printf(xpdd, XBT_NIL, tmp_path, "%d", XenbusStateConnected);
1278 break;
1281 default:
1282 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", xppdd->backend_state));
1283 break;
1286 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
1288 ExReleaseFastMutex(&xppdd->backend_state_mutex);
1289 FUNCTION_EXIT();
1291 return;
1294 static VOID
1295 XenPci_BackendStateHandler(char *path, PVOID context)
1297 UNREFERENCED_PARAMETER(path);
1299 /* check that path == device/id/state */
1300 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
1302 XenPci_UpdateBackendState(context);
1305 static NTSTATUS
1306 XenPci_GetBackendAndAddWatch(WDFDEVICE device)
1308 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1309 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1310 char path[128];
1311 PCHAR res;
1312 PCHAR value;
1314 FUNCTION_ENTER();
1315 /* Get backend path */
1316 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
1317 "%s/backend", xppdd->path);
1318 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
1319 if (res)
1321 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
1322 XenPci_FreeMem(res);
1323 return STATUS_UNSUCCESSFUL;
1325 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
1326 XenPci_FreeMem(value);
1328 /* Add watch on backend state */
1329 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1330 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
1332 FUNCTION_EXIT();
1333 return STATUS_SUCCESS;
1336 static NTSTATUS
1337 XenConfig_InitConfigPage(WDFDEVICE device)
1339 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1340 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
1341 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
1342 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
1343 PUCHAR ptr;
1344 PDEVICE_OBJECT curr, prev;
1345 PDRIVER_OBJECT fdo_driver_object;
1346 PUCHAR fdo_driver_extension;
1348 FUNCTION_ENTER();
1350 ptr = MmGetMdlVirtualAddress(xppdd->config_page_mdl);
1351 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(device));
1352 //curr = WdfDeviceWdmGetAttachedDevice(device);
1353 while (curr != NULL)
1355 fdo_driver_object = curr->DriverObject;
1356 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
1357 if (fdo_driver_object)
1359 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
1360 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
1361 if (fdo_driver_extension)
1363 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
1364 ObDereferenceObject(curr);
1365 break;
1368 prev = curr;
1369 curr = IoGetLowerDeviceObject(curr);
1370 ObDereferenceObject(prev);
1373 FUNCTION_EXIT();
1375 return STATUS_SUCCESS;
1378 static NTSTATUS
1379 XenPci_EvtChn_Bind(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
1381 WDFDEVICE device = context;
1382 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1383 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1385 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext);
1388 static NTSTATUS
1389 XenPci_EvtChn_BindDpc(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
1391 WDFDEVICE device = context;
1392 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1393 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1395 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext);
1398 static NTSTATUS
1399 XenPci_EvtChn_Unbind(PVOID context, evtchn_port_t Port)
1401 WDFDEVICE device = context;
1402 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1403 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1405 return EvtChn_Unbind(xpdd, Port);
1408 static NTSTATUS
1409 XenPci_EvtChn_Mask(PVOID context, evtchn_port_t Port)
1411 WDFDEVICE device = context;
1412 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1413 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1415 return EvtChn_Mask(xpdd, Port);
1418 static NTSTATUS
1419 XenPci_EvtChn_Unmask(PVOID context, evtchn_port_t Port)
1421 WDFDEVICE device = context;
1422 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1423 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1425 return EvtChn_Unmask(xpdd, Port);
1428 static NTSTATUS
1429 XenPci_EvtChn_Notify(PVOID context, evtchn_port_t Port)
1431 WDFDEVICE device = context;
1432 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1433 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1435 return EvtChn_Notify(xpdd, Port);
1438 static BOOLEAN
1439 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port, BOOLEAN *last_interrupt)
1441 WDFDEVICE device = context;
1442 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1443 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1445 return EvtChn_AckEvent(xpdd, port, last_interrupt);
1448 typedef struct {
1449 PXEN_EVTCHN_SYNC_ROUTINE sync_routine;
1450 PVOID sync_context;
1451 } sync_context_t;
1453 static BOOLEAN
1454 XenPci_EvtChn_Sync_Routine(WDFINTERRUPT interrupt, WDFCONTEXT context)
1456 sync_context_t *wdf_sync_context = context;
1457 UNREFERENCED_PARAMETER(interrupt);
1458 return wdf_sync_context->sync_routine(wdf_sync_context->sync_context);
1461 static BOOLEAN
1462 XenPci_EvtChn_Sync(PVOID context, PXEN_EVTCHN_SYNC_ROUTINE sync_routine, PVOID sync_context)
1464 WDFDEVICE device = context;
1465 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1466 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1467 sync_context_t wdf_sync_context;
1469 wdf_sync_context.sync_routine = sync_routine;
1470 wdf_sync_context.sync_context = sync_context;
1472 return WdfInterruptSynchronize(xpdd->interrupt, XenPci_EvtChn_Sync_Routine, &wdf_sync_context);
1475 static grant_ref_t
1476 XenPci_GntTbl_GrantAccess(PVOID context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref)
1478 WDFDEVICE device = context;
1479 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1480 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1482 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref);
1485 static BOOLEAN
1486 XenPci_GntTbl_EndAccess(PVOID context, grant_ref_t ref, BOOLEAN keepref)
1488 WDFDEVICE device = context;
1489 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1490 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1492 return GntTbl_EndAccess(xpdd, ref, keepref);
1495 static VOID
1496 XenPci_GntTbl_PutRef(PVOID context, grant_ref_t ref)
1498 WDFDEVICE device = context;
1499 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1500 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1502 GntTbl_PutRef(xpdd, ref);
1505 static grant_ref_t
1506 XenPci_GntTbl_GetRef(PVOID context)
1508 WDFDEVICE device = context;
1509 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1510 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1512 return GntTbl_GetRef(xpdd);
1515 PCHAR
1516 XenPci_XenBus_Read(PVOID context, xenbus_transaction_t xbt, char *path, char **value)
1518 WDFDEVICE device = context;
1519 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1520 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1521 return XenBus_Read(xpdd, xbt, path, value);
1524 PCHAR
1525 XenPci_XenBus_Write(PVOID context, xenbus_transaction_t xbt, char *path, char *value)
1527 WDFDEVICE device = context;
1528 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1529 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1530 return XenBus_Write(xpdd, xbt, path, value);
1533 PCHAR
1534 XenPci_XenBus_Printf(PVOID context, xenbus_transaction_t xbt, char *path, char *fmt, ...)
1536 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
1537 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
1538 //return XenBus_Printf(xpdd, xbt, path, value);
1539 UNREFERENCED_PARAMETER(context);
1540 UNREFERENCED_PARAMETER(xbt);
1541 UNREFERENCED_PARAMETER(path);
1542 UNREFERENCED_PARAMETER(fmt);
1543 return NULL;
1546 PCHAR
1547 XenPci_XenBus_StartTransaction(PVOID context, xenbus_transaction_t *xbt)
1549 WDFDEVICE device = context;
1550 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1551 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1552 return XenBus_StartTransaction(xpdd, xbt);
1555 PCHAR
1556 XenPci_XenBus_EndTransaction(PVOID context, xenbus_transaction_t xbt, int abort, int *retry)
1558 WDFDEVICE device = context;
1559 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1560 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1561 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
1564 PCHAR
1565 XenPci_XenBus_List(PVOID context, xenbus_transaction_t xbt, char *prefix, char ***contents)
1567 WDFDEVICE device = context;
1568 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1569 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1570 return XenBus_List(xpdd, xbt, prefix, contents);
1573 PCHAR
1574 XenPci_XenBus_AddWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
1576 WDFDEVICE device = context;
1577 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1578 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1579 PCHAR retval;
1581 FUNCTION_ENTER();
1582 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
1583 if (retval == NULL)
1585 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
1587 else
1589 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
1591 FUNCTION_EXIT();
1592 return retval;
1595 PCHAR
1596 XenPci_XenBus_RemWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
1598 WDFDEVICE device = context;
1599 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1600 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1601 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
1604 /*
1605 Called at PASSIVE_LEVEL
1606 Called during restore
1607 */
1609 static NTSTATUS
1610 XenPci_ChangeFrontendState(WDFDEVICE device, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
1612 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1613 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1614 LARGE_INTEGER timeout;
1615 ULONG remaining;
1616 ULONG thiswait;
1617 char path[128];
1619 FUNCTION_ENTER();
1621 xppdd->frontend_state = frontend_state_set;
1623 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
1624 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
1626 remaining = maximum_wait_ms;
1628 while (xppdd->backend_state != backend_state_response)
1630 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
1631 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
1632 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
1634 /* it's possible that the workitems are blocked because the pagefile isn't available. Lets just re-read the backend value for now */
1635 XenPci_UpdateBackendState(device);
1636 remaining -= thiswait;
1637 if (remaining == 0)
1639 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
1640 return STATUS_UNSUCCESSFUL;
1642 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
1645 FUNCTION_EXIT();
1646 return STATUS_SUCCESS;
1649 static NTSTATUS
1650 XenPci_XenConfigDevice(WDFDEVICE device);
1652 static NTSTATUS
1653 XenPci_XenShutdownDevice(PVOID context)
1655 WDFDEVICE device = context;
1656 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1657 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1658 PUCHAR in_ptr;
1659 ULONG i;
1660 UCHAR type;
1661 PVOID setting;
1662 PVOID value;
1663 PVOID value2;
1665 FUNCTION_ENTER();
1667 if (xppdd->backend_state == XenbusStateConnected)
1669 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
1670 if (xppdd->backend_state == XenbusStateClosing)
1671 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
1672 if (xppdd->backend_state == XenbusStateClosed)
1673 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
1675 else
1677 if (xppdd->backend_state == XenbusStateClosing)
1678 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
1681 if (xppdd->assigned_resources_start != NULL)
1683 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1684 in_ptr = xppdd->assigned_resources_start;
1685 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
1687 switch (type)
1689 case XEN_INIT_TYPE_RING: /* frontend ring */
1690 FreePages(value);
1691 break;
1692 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
1693 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
1694 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
1695 EvtChn_Unbind(xpdd, PtrToUlong(value));
1696 EvtChn_Close(xpdd, PtrToUlong(value));
1697 break;
1698 case XEN_INIT_TYPE_GRANT_ENTRIES:
1699 for (i = 0; i < PtrToUlong(setting); i++)
1700 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value)[i], FALSE);
1701 break;
1704 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
1705 xppdd->assigned_resources_start = NULL;
1708 FUNCTION_EXIT();
1710 return STATUS_SUCCESS;
1713 struct dummy_sring {
1714 RING_IDX req_prod, req_event;
1715 RING_IDX rsp_prod, rsp_event;
1716 uint8_t pad[48];
1717 };
1719 static NTSTATUS
1720 XenPci_XenConfigDeviceSpecifyBuffers(WDFDEVICE device, PUCHAR src, PUCHAR dst)
1722 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1723 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1724 NTSTATUS status = STATUS_SUCCESS;
1725 ULONG i;
1726 char path[128];
1727 PCHAR setting, value;
1728 PCHAR res;
1729 PVOID address;
1730 UCHAR type;
1731 PUCHAR in_ptr;
1732 PUCHAR out_ptr;
1733 XENPCI_VECTORS vectors;
1734 ULONG event_channel;
1735 ULONG run_type = 0;
1736 PMDL ring;
1737 grant_ref_t gref;
1738 BOOLEAN done_xenbus_init = FALSE;
1739 PVOID value2;
1740 BOOLEAN active = TRUE;
1741 BOOLEAN dont_config = FALSE;
1743 FUNCTION_ENTER();
1745 in_ptr = src;
1746 out_ptr = dst;
1748 // always add vectors
1749 vectors.magic = XEN_DATA_MAGIC;
1750 vectors.length = sizeof(XENPCI_VECTORS);
1751 vectors.context = device;
1752 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
1753 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
1754 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
1755 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
1756 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
1757 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
1758 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
1759 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
1760 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
1761 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
1762 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
1763 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
1764 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
1765 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
1766 strncpy(vectors.path, xppdd->path, 128);
1767 strncpy(vectors.backend_path, xppdd->backend_path, 128);
1768 //vectors.pdo_event_channel = xpdd->pdo_event_channel;
1769 vectors.XenBus_Read = XenPci_XenBus_Read;
1770 vectors.XenBus_Write = XenPci_XenBus_Write;
1771 vectors.XenBus_Printf = XenPci_XenBus_Printf;
1772 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
1773 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
1774 vectors.XenBus_List = XenPci_XenBus_List;
1775 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
1776 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
1778 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
1780 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
1781 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
1783 if (!qemu_filtered)
1784 active = FALSE;
1786 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
1788 BOOLEAN condition;
1789 PCHAR xb_value;
1790 switch (type)
1792 case XEN_INIT_TYPE_MATCH_FRONT:
1793 case XEN_INIT_TYPE_MATCH_BACK:
1794 if (type == XEN_INIT_TYPE_MATCH_FRONT)
1796 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1798 else
1800 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
1802 KdPrint((__DRIVER_NAME " testing path = %s\n", path));
1803 res = XenBus_Read(xpdd, XBT_NIL, path, &xb_value);
1804 if (res)
1806 KdPrint((__DRIVER_NAME " read failed (%s)\n", res));
1807 XenPci_FreeMem(res);
1809 else
1811 KdPrint((__DRIVER_NAME " testing %s vs %s\n", xb_value, value));
1812 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_IF_MATCH)
1813 condition = (strcmp(xb_value, value) == 0)?TRUE:FALSE;
1814 else
1815 condition = (strcmp(xb_value, value) != 0)?TRUE:FALSE;
1816 KdPrint((__DRIVER_NAME " condition = %d\n", condition));
1818 if ((PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_ONLY_IF_QEMU_HIDE) && qemu_protocol_version && condition)
1819 condition = FALSE;
1821 if (condition)
1823 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_SET_INACTIVE)
1825 active = FALSE;
1826 KdPrint((__DRIVER_NAME " set inactive\n"));
1828 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_DONT_CONFIG)
1830 dont_config = TRUE;
1831 KdPrint((__DRIVER_NAME " set inactive with dont config\n"));
1834 XenPci_FreeMem(xb_value);
1836 break;
1839 if (dont_config)
1841 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1842 FUNCTION_EXIT();
1843 return status;
1846 // first pass, possibly before state == Connected
1847 in_ptr = src;
1848 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
1850 if (!done_xenbus_init)
1852 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000) != STATUS_SUCCESS)
1854 status = STATUS_UNSUCCESSFUL;
1855 goto error;
1857 done_xenbus_init = TRUE;
1860 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
1862 switch (type)
1864 case XEN_INIT_TYPE_RUN:
1865 run_type++;
1866 break;
1867 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
1868 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
1869 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1870 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
1871 break;
1872 case XEN_INIT_TYPE_RING: /* frontend ring */
1873 /* we only allocate and do the SHARED_RING_INIT here */
1874 if ((ring = AllocatePage()) != 0)
1876 address = MmGetMdlVirtualAddress(ring);
1877 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
1878 SHARED_RING_INIT((struct dummy_sring *)address);
1879 if ((gref = GntTbl_GrantAccess(
1880 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
1882 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1883 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
1884 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
1885 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
1886 // add the grant entry too so it gets freed automatically
1887 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
1888 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
1889 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
1891 else
1893 FreePages(ring);
1894 status = STATUS_UNSUCCESSFUL;
1895 goto error;
1898 else
1900 status = STATUS_UNSUCCESSFUL;
1901 goto error;
1903 break;
1904 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
1905 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
1906 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
1907 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
1909 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
1910 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1911 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
1912 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
1913 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
1914 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
1916 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
1918 else if (type == XEN_INIT_TYPE_EVENT_CHANNEL_DPC)
1920 #pragma warning(suppress:4055)
1921 EvtChn_BindDpc(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
1923 else
1925 #pragma warning(suppress:4055)
1926 EvtChn_Bind(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
1929 else
1931 status = STATUS_UNSUCCESSFUL;
1932 goto error;
1934 break;
1937 if (!NT_SUCCESS(status))
1939 goto error;
1941 // If XEN_INIT_TYPE_RUN was specified more than once then we skip XenbusStateInitialised here and go straight to XenbusStateConnected at the end
1942 if (run_type == 1)
1944 if (XenPci_ChangeFrontendState(device, XenbusStateInitialised, XenbusStateConnected, 2000) != STATUS_SUCCESS)
1946 status = STATUS_UNSUCCESSFUL;
1947 goto error;
1951 // second pass, possibly after state == Connected
1952 in_ptr = src;
1953 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
1955 switch(type)
1957 case XEN_INIT_TYPE_READ_STRING_BACK:
1958 case XEN_INIT_TYPE_READ_STRING_FRONT:
1959 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
1960 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1961 else
1962 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
1963 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
1964 if (res)
1966 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
1967 XenPci_FreeMem(res);
1968 ADD_XEN_INIT_RSP(&out_ptr, type, setting, "", "");
1970 else
1972 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
1973 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, value2);
1974 XenPci_FreeMem(value);
1976 break;
1977 case XEN_INIT_TYPE_VECTORS:
1978 // this is always done so ignore the request
1979 break;
1980 case XEN_INIT_TYPE_GRANT_ENTRIES:
1981 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
1982 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
1983 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
1984 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
1985 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
1986 for (i = 0; i < PtrToUlong(value); i++)
1988 gref = GntTbl_GetRef(xpdd);
1989 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
1990 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
1992 break;
1995 if (active)
1997 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_ACTIVE, NULL, NULL, NULL);
1999 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
2001 if (run_type)
2003 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 2000) != STATUS_SUCCESS)
2005 status = STATUS_UNSUCCESSFUL;
2006 goto error;
2009 FUNCTION_EXIT();
2010 return status;
2012 error:
2013 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000);
2014 FUNCTION_EXIT_STATUS(status);
2015 return status;
2018 static NTSTATUS
2019 XenPci_XenConfigDevice(WDFDEVICE device)
2021 NTSTATUS status;
2022 PUCHAR src, dst;
2023 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2025 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
2026 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
2027 memcpy(src, dst, xppdd->config_page_length);
2029 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
2031 MmUnmapIoSpace(dst, xppdd->config_page_length);
2032 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
2034 return status;
2037 static NTSTATUS
2038 XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp)
2040 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2041 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2042 PIO_STACK_LOCATION stack;
2043 PCM_PARTIAL_RESOURCE_LIST prl;
2044 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
2045 ULONG i;
2046 //char path[128];
2047 //PMDL mdl;
2049 FUNCTION_ENTER();
2050 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
2052 stack = IoGetCurrentIrpStackLocation(irp);
2054 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
2055 for (i = 0; i < prl->Count; i++)
2057 prd = & prl->PartialDescriptors[i];
2058 switch (prd->Type)
2060 case CmResourceTypeMemory:
2061 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
2063 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
2064 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
2066 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
2068 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
2069 prd->Type = CmResourceTypeInterrupt;
2070 prd->ShareDisposition = CmResourceShareShared;
2071 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
2072 prd->u.Interrupt.Level = 0; // Set group and level to zero (group = upper word)
2073 prd->u.Interrupt.Level = xpdd->irq_number & 0xffff; // Only set the lower word
2074 prd->u.Interrupt.Vector = xpdd->irq_number;
2075 prd->u.Interrupt.Affinity = KeQueryActiveProcessors();
2076 xppdd->irq_number = xpdd->irq_number;
2078 break;
2082 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
2083 for (i = 0; i < prl->Count; i++)
2085 prd = & prl->PartialDescriptors[i];
2086 switch (prd->Type)
2088 case CmResourceTypeMemory:
2089 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
2090 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
2091 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
2093 if (prd->u.Memory.Length == 0)
2095 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0]));
2096 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
2097 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
2098 KdPrint((__DRIVER_NAME " New Start = %08x%08x, Length = %d\n", prd->u.Memory.Start.HighPart, prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
2100 xppdd->config_page_phys = prd->u.Memory.Start;
2101 xppdd->config_page_length = prd->u.Memory.Length;
2102 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
2103 //xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
2105 #if 0
2106 status = XenPci_XenConfigDevice(device);
2107 if (!NT_SUCCESS(status))
2109 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2110 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
2111 FUNCTION_ERROR_EXIT();
2112 return status;
2114 #endif
2116 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
2118 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
2119 prd->Type = CmResourceTypeInterrupt;
2120 prd->ShareDisposition = CmResourceShareShared;
2121 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
2122 prd->u.Interrupt.Level = 0; // Set group and level to zero (group = upper word)
2123 prd->u.Interrupt.Level = xpdd->irq_level & 0xffff; // Only set the lower word
2124 prd->u.Interrupt.Vector = xpdd->irq_vector;
2125 prd->u.Interrupt.Affinity = KeQueryActiveProcessors();
2126 xppdd->irq_vector = xpdd->irq_vector;
2127 xppdd->irq_level = xpdd->irq_level;
2129 break;
2133 IoSkipCurrentIrpStackLocation(irp);
2135 FUNCTION_EXIT();
2137 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
2140 #if 0
2141 static NTSTATUS
2142 XenPciPdo_EvtDeviceResourcesQuery(WDFDEVICE device, WDFCMRESLIST resources)
2145 #endif
2147 static NTSTATUS
2148 XenPciPdo_EvtDeviceResourceRequirementsQuery(WDFDEVICE device, WDFIORESREQLIST requirements_list)
2150 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2151 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2152 WDFIORESLIST res_list;
2153 IO_RESOURCE_DESCRIPTOR ird;
2155 //FUNCTION_ENTER();
2157 WdfIoResourceRequirementsListSetInterfaceType(requirements_list, PNPBus);
2159 WdfIoResourceListCreate(requirements_list, WDF_NO_OBJECT_ATTRIBUTES, &res_list);
2160 ird.Option = 0;
2161 ird.Type = CmResourceTypeMemory;
2162 ird.ShareDisposition = CmResourceShareShared;
2163 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
2164 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
2165 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
2166 ird.u.Memory.Length = 0;
2167 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
2168 WdfIoResourceListAppendDescriptor(res_list, &ird);
2170 ird.Option = 0;
2171 ird.Type = CmResourceTypeMemory;
2172 ird.ShareDisposition = CmResourceShareShared;
2173 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
2174 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
2175 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
2176 ird.u.Memory.Length = 0;
2177 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
2178 WdfIoResourceListAppendDescriptor(res_list, &ird);
2180 WdfIoResourceRequirementsListAppendIoResList(requirements_list, res_list);
2182 //FUNCTION_EXIT();
2184 return STATUS_SUCCESS;
2187 NTSTATUS
2188 XenPciPdo_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
2190 NTSTATUS status = STATUS_SUCCESS;
2191 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2192 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2193 CHAR path[128];
2195 FUNCTION_ENTER();
2197 switch (previous_state)
2199 case WdfPowerDeviceD0:
2200 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
2201 break;
2202 case WdfPowerDeviceD1:
2203 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
2204 break;
2205 case WdfPowerDeviceD2:
2206 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
2207 break;
2208 case WdfPowerDeviceD3:
2209 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
2210 break;
2211 case WdfPowerDeviceD3Final:
2212 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
2213 break;
2214 case WdfPowerDevicePrepareForHibernation:
2215 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
2216 break;
2217 default:
2218 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
2219 break;
2222 if (previous_state == WdfPowerDevicePrepareForHibernation
2223 || (previous_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
2225 KdPrint((__DRIVER_NAME " starting up from hibernation\n"));
2227 else
2231 if (previous_state == WdfPowerDevicePrepareForHibernation || previous_state == WdfPowerDeviceD3 || previous_state == WdfPowerDeviceD3Final)
2233 xppdd->requested_resources_ptr = xppdd->requested_resources_start;
2234 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
2237 XenConfig_InitConfigPage(device);
2239 status = XenPci_GetBackendAndAddWatch(device);
2240 if (!NT_SUCCESS(status))
2242 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
2243 FUNCTION_ERROR_EXIT();
2244 return status;
2246 status = XenPci_XenConfigDevice(device);
2247 if (!NT_SUCCESS(status))
2249 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2250 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
2251 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
2252 FUNCTION_ERROR_EXIT();
2253 return status;
2256 FUNCTION_EXIT();
2258 return status;
2261 NTSTATUS
2262 XenPciPdo_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
2264 NTSTATUS status = STATUS_SUCCESS;
2265 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2266 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2267 char path[128];
2269 UNREFERENCED_PARAMETER(device);
2270 UNREFERENCED_PARAMETER(target_state);
2272 FUNCTION_ENTER();
2274 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
2277 switch (target_state)
2279 case WdfPowerDeviceD0:
2280 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
2281 break;
2282 case WdfPowerDeviceD1:
2283 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
2284 break;
2285 case WdfPowerDeviceD2:
2286 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
2287 break;
2288 case WdfPowerDeviceD3:
2289 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
2290 break;
2291 case WdfPowerDeviceD3Final:
2292 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
2293 break;
2294 case WdfPowerDevicePrepareForHibernation:
2295 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
2296 break;
2297 default:
2298 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
2299 break;
2302 if (target_state == WdfPowerDevicePrepareForHibernation
2303 || (target_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
2305 KdPrint((__DRIVER_NAME " not powering down as we are hibernating\n"));
2307 else
2309 status = XenPci_XenShutdownDevice(device);
2310 /* Remove watch on backend state */
2311 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2312 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
2314 FUNCTION_EXIT();
2316 return status;
2319 NTSTATUS
2320 XenPciPdo_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
2322 NTSTATUS status = STATUS_SUCCESS;
2324 UNREFERENCED_PARAMETER(device);
2325 UNREFERENCED_PARAMETER(resources_raw);
2326 UNREFERENCED_PARAMETER(resources_translated);
2328 FUNCTION_ENTER();
2329 FUNCTION_EXIT();
2331 return status;
2334 NTSTATUS
2335 XenPciPdo_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
2337 NTSTATUS status = STATUS_SUCCESS;
2339 UNREFERENCED_PARAMETER(device);
2340 UNREFERENCED_PARAMETER(resources_translated);
2342 FUNCTION_ENTER();
2343 FUNCTION_EXIT();
2345 return status;
2348 static VOID
2349 XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
2351 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2353 FUNCTION_ENTER();
2355 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
2356 switch (notification_type)
2358 case WdfSpecialFilePaging:
2359 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
2360 break;
2361 case WdfSpecialFileHibernation:
2362 xppdd->hiber_usage_kludge = is_in_notification_path;
2363 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
2364 break;
2365 case WdfSpecialFileDump:
2366 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
2367 break;
2368 default:
2369 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
2370 break;
2373 FUNCTION_EXIT();
2376 NTSTATUS
2377 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
2378 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
2379 PWDFDEVICE_INIT child_init)
2381 NTSTATUS status = STATUS_SUCCESS;
2382 WDF_OBJECT_ATTRIBUTES child_attributes;
2383 WDFDEVICE child_device;
2384 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
2385 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
2386 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
2387 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
2388 PXENPCI_PDO_DEVICE_DATA xppdd;
2389 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
2390 WDF_QUERY_INTERFACE_CONFIG interface_config;
2391 BUS_INTERFACE_STANDARD bus_interface;
2392 WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
2393 WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
2394 UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
2395 WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
2397 FUNCTION_ENTER();
2399 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
2401 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
2402 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
2403 //child_pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPciPdo_EvtDeviceD0EntryPostInterruptsEnabled;
2404 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
2405 //child_pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPciPdo_EvtDeviceD0ExitPreInterruptsDisabled;
2406 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenPciPdo_EvtDevicePrepareHardware;
2407 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenPciPdo_EvtDeviceReleaseHardware;
2408 child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
2409 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
2411 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
2412 identification->device, identification->index, identification->path));
2414 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
2415 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
2416 if (!NT_SUCCESS(status))
2418 return status;
2421 WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
2422 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
2423 pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
2424 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
2425 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
2426 WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
2428 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
2429 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
2430 if (!NT_SUCCESS(status))
2432 return status;
2434 status = WdfPdoInitAddHardwareID(child_init, &buffer);
2435 if (!NT_SUCCESS(status))
2437 return status;
2439 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
2440 if (!NT_SUCCESS(status))
2442 return status;
2445 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
2446 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
2447 if (!NT_SUCCESS(status))
2449 return status;
2452 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
2453 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
2454 if (!NT_SUCCESS(status))
2456 return status;
2458 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
2460 WdfDeviceInitSetPowerNotPageable(child_init);
2462 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
2463 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
2464 if (!NT_SUCCESS(status))
2466 return status;
2469 xppdd = GetXppdd(child_device);
2471 xppdd->wdf_device = child_device;
2472 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
2474 xppdd->config_page_mdl = AllocateUncachedPage();
2476 xppdd->device_state.magic = XEN_DEVICE_STATE_MAGIC;
2477 xppdd->device_state.length = sizeof(XENPCI_DEVICE_STATE);
2478 xppdd->device_state.suspend_resume_state_pdo = SR_STATE_RUNNING;
2479 xppdd->device_state.suspend_resume_state_fdo = SR_STATE_RUNNING;
2480 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
2481 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
2482 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
2483 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
2485 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
2486 child_pnp_capabilities.LockSupported = WdfFalse;
2487 child_pnp_capabilities.EjectSupported = WdfTrue;
2488 child_pnp_capabilities.Removable = WdfTrue;
2489 child_pnp_capabilities.DockDevice = WdfFalse;
2490 child_pnp_capabilities.UniqueID = WdfFalse;
2491 child_pnp_capabilities.SilentInstall = WdfTrue;
2492 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
2493 child_pnp_capabilities.HardwareDisabled = WdfFalse;
2494 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
2496 WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
2497 child_power_capabilities.DeviceD1 = WdfTrue;
2498 child_power_capabilities.WakeFromD1 = WdfTrue;
2499 child_power_capabilities.DeviceWake = PowerDeviceD1;
2500 child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
2501 child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
2502 child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
2503 child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
2504 child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
2505 child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
2506 WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
2508 bus_interface.Size = sizeof(BUS_INTERFACE_STANDARD);
2509 bus_interface.Version = 1; //BUS_INTERFACE_STANDARD_VERSION;
2510 bus_interface.Context = xppdd;
2511 bus_interface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
2512 bus_interface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
2513 bus_interface.TranslateBusAddress = XenPci_BIS_TranslateBusAddress;
2514 bus_interface.GetDmaAdapter = XenPci_BIS_GetDmaAdapter;
2515 bus_interface.SetBusData = XenPci_BIS_SetBusData;
2516 bus_interface.GetBusData = XenPci_BIS_GetBusData;
2517 WDF_QUERY_INTERFACE_CONFIG_INIT(&interface_config, (PINTERFACE)&bus_interface, &GUID_BUS_INTERFACE_STANDARD, NULL);
2518 status = WdfDeviceAddQueryInterface(child_device, &interface_config);
2519 if (!NT_SUCCESS(status))
2521 return status;
2524 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
2525 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
2526 xppdd->index = identification->index;
2527 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
2528 ExInitializeFastMutex(&xppdd->backend_state_mutex);
2529 xppdd->backend_state = XenbusStateUnknown;
2530 xppdd->frontend_state = XenbusStateUnknown;
2531 xppdd->backend_path[0] = '\0';
2533 FUNCTION_EXIT();
2535 return status;
2538 static __forceinline VOID
2539 XenPci_Pdo_ChangeSuspendState(WDFDEVICE device, ULONG new_state)
2541 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2542 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2544 FUNCTION_ENTER();
2545 KdPrint((__DRIVER_NAME " setting pdo state to %d\n", new_state));
2546 xppdd->device_state.suspend_resume_state_pdo = new_state;
2547 KeMemoryBarrier();
2548 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xpdd->pdo_event_channel));
2549 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
2550 while(xppdd->device_state.suspend_resume_state_fdo != xppdd->device_state.suspend_resume_state_pdo)
2552 KdPrint((__DRIVER_NAME " waiting...\n"));
2553 KeWaitForSingleObject(&xpdd->pdo_suspend_event, Executive, KernelMode, FALSE, NULL);
2555 KdPrint((__DRIVER_NAME " fdo state set to %d\n", new_state));
2556 FUNCTION_EXIT();
2559 /* called at PASSIVE_LEVEL */
2560 NTSTATUS
2561 XenPci_Pdo_Suspend(WDFDEVICE device)
2563 NTSTATUS status = STATUS_SUCCESS;
2564 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2565 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2566 //LARGE_INTEGER wait_time;
2567 char path[128];
2568 PUCHAR in_ptr;
2569 UCHAR type;
2570 PVOID setting;
2571 PVOID value;
2572 PVOID value2;
2574 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
2576 if (xppdd->backend_state == XenbusStateConnected)
2578 xppdd->restart_on_resume = TRUE;
2579 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_SUSPENDING);
2581 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
2582 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
2583 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
2585 if (xppdd->assigned_resources_start != NULL)
2587 in_ptr = xppdd->assigned_resources_ptr;
2588 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
2589 in_ptr = xppdd->assigned_resources_start;
2590 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
2592 switch (type)
2594 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
2595 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
2596 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
2597 EvtChn_Unbind(xpdd, PtrToUlong(value));
2598 EvtChn_Close(xpdd, PtrToUlong(value));
2599 break;
2604 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2605 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, xppdd);
2607 else
2609 xppdd->restart_on_resume = FALSE;
2612 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
2614 return status;
2617 NTSTATUS
2618 XenPci_Pdo_Resume(WDFDEVICE device)
2620 NTSTATUS status = STATUS_SUCCESS;
2621 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2622 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2623 ULONG old_backend_state;
2624 PUCHAR src, dst;
2626 FUNCTION_ENTER();
2627 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
2629 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
2630 old_backend_state = xppdd->backend_state;
2632 if (xppdd->restart_on_resume)
2634 status = XenPci_GetBackendAndAddWatch(device);
2636 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
2638 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
2639 // this is probably an unrecoverable situation...
2640 FUNCTION_ERROR_EXIT();
2641 return STATUS_UNSUCCESSFUL;
2643 if (xppdd->assigned_resources_ptr)
2645 // reset things - feed the 'requested resources' back in
2646 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
2647 src = xppdd->requested_resources_start;
2648 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
2649 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
2651 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
2653 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
2655 MmUnmapIoSpace(dst, xppdd->config_page_length);
2656 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
2658 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
2660 // this is definitely an unrecoverable situation...
2661 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
2662 FUNCTION_ERROR_EXIT();
2663 return STATUS_UNSUCCESSFUL;
2665 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RESUMING);
2666 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RUNNING);
2669 FUNCTION_EXIT();
2671 return STATUS_SUCCESS;