win-pvdrivers

view xenpci/xenpci_pdo.c @ 621:9c7b7fbacd7f

Windows 7 fix. Interrupt affinity cannot be set to -1 anymore (this is the affinity returned in the resource list). A proper fix that works across multiple Windows OS was implemented. Also, the interrupt level had to be set properly (as outlined in the new Microsoft Windows DDK docs).
author Steve Meisner <steve.meisner@virtualcomputer.com>
date Wed Jul 29 12:43:36 2009 -0400 (2009-07-29)
parents 1478103c6ef5
children 0b55299418ce
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 if (!curr_mdl)
688 {
689 KdPrint((__DRIVER_NAME " CurrentVa = %p, Length = %d\n", CurrentVa, Length));
690 for (curr_mdl = Mdl; curr_mdl; curr_mdl = curr_mdl->Next)
691 {
692 KdPrint((__DRIVER_NAME " Mdl = %p, VirtualAddress = %p, ByteCount = %d\n", Mdl, MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)));
693 }
694 }
695 ASSERT(curr_mdl);
696 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
697 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
698 /* need to use <= va + len - 1 to avoid ptr wraparound */
699 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
700 {
701 active = TRUE;
702 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
703 mdl_start_va = CurrentVa;
704 }
705 mdl_byte_count = min(mdl_byte_count, total_remaining);
706 if (active)
707 {
708 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
709 mdl_start_va, mdl_byte_count);
710 total_remaining -= mdl_byte_count;
711 }
712 }
713 }
714 if (ScatterGatherBufferLength < FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
715 sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t))
716 {
717 //KdPrint((__DRIVER_NAME " STATUS_BUFFER_TOO_SMALL (%d < %d)\n", ScatterGatherBufferLength, FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
718 // sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t)));
719 return STATUS_BUFFER_TOO_SMALL;
720 }
722 sg_extra = (sg_extra_t *)((PUCHAR)sglist + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
723 (sizeof(SCATTER_GATHER_ELEMENT)) * sglist->NumberOfElements);
725 sg_extra->allocated_by_me = allocated_by_me;
727 sg_extra->map_type = map_type;
728 switch (map_type)
729 {
730 case MAP_TYPE_MDL:
731 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL - %p\n", MmGetMdlVirtualAddress(Mdl)));
732 total_remaining = Length;
733 for (sg_element = 0, curr_mdl = Mdl, active = FALSE; total_remaining > 0; curr_mdl = curr_mdl->Next)
734 {
735 ASSERT(curr_mdl);
736 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
737 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
738 /* need to use <= va + len - 1 to avoid ptr wraparound */
739 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
740 {
741 active = TRUE;
742 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
743 mdl_start_va = CurrentVa;
744 }
745 if (active)
746 {
747 ULONG pfn_offset;
748 remaining = min(mdl_byte_count, total_remaining);
749 offset = (ULONG)((UINT_PTR)mdl_start_va & (PAGE_SIZE - 1));
750 pfn_offset = (ULONG)(((UINT_PTR)mdl_start_va >> PAGE_SHIFT) - ((UINT_PTR)MmGetMdlVirtualAddress(curr_mdl) >> PAGE_SHIFT));
751 //for (i = 0; i < ADDRESS_AND_SIZE_TO_SPAN_PAGES(mdl_start_va, mdl_byte_count); i++)
752 for (i = 0; remaining > 0; i++)
753 {
754 pfn = MmGetMdlPfnArray(curr_mdl)[pfn_offset + i];
755 ASSERT(pfn);
756 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
757 ASSERT(gref != INVALID_GRANT_REF);
758 sglist->Elements[sg_element].Address.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | offset;
759 sglist->Elements[sg_element].Length = min(min(PAGE_SIZE - offset, remaining), total_remaining);
760 total_remaining -= sglist->Elements[sg_element].Length;
761 remaining -= sglist->Elements[sg_element].Length;
762 offset = 0;
763 sg_element++;
764 }
765 }
766 }
767 if (sg_element != sglist->NumberOfElements)
768 {
769 KdPrint((__DRIVER_NAME " sg_element = %d, sglist->NumberOfElements = %d\n", sg_element, sglist->NumberOfElements));
770 KdPrint((__DRIVER_NAME " CurrentVa = %p, Length = %d\n", CurrentVa, Length));
771 for (curr_mdl = Mdl; curr_mdl; curr_mdl = curr_mdl->Next)
772 {
773 KdPrint((__DRIVER_NAME " Mdl = %p, VirtualAddress = %p, ByteCount = %d\n", Mdl, MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)));
774 }
775 }
776 ASSERT(sg_element == sglist->NumberOfElements);
777 break;
778 case MAP_TYPE_REMAPPED:
779 sg_extra->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, max(remapped_bytes, PAGE_SIZE), XENPCI_POOL_TAG);
780 if (!sg_extra->aligned_buffer)
781 {
782 KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED buffer allocation failed - requested va = %p, length = %d\n", MmGetMdlVirtualAddress(Mdl), remapped_bytes));
783 return STATUS_INSUFFICIENT_RESOURCES;
784 }
785 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED - %p\n", sg_extra->aligned_buffer));
786 sg_extra->mdl = Mdl;
787 sg_extra->currentva = CurrentVa;
788 sg_extra->copy_length = remapped_bytes;
790 if (WriteToDevice)
791 {
792 for (curr_mdl = Mdl, offset = 0, active = FALSE; curr_mdl; curr_mdl = curr_mdl->Next)
793 {
794 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
795 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
796 mdl_offset = 0;
797 /* need to use <= va + len - 1 to avoid ptr wraparound */
798 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
799 {
800 active = TRUE;
801 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
802 mdl_offset = (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
803 mdl_start_va = CurrentVa;
804 }
805 if (active)
806 {
807 PVOID unaligned_buffer;
808 unaligned_buffer = (PUCHAR)MmGetSystemAddressForMdlSafe(curr_mdl, NormalPagePriority);
809 ASSERT(unaligned_buffer); /* lazy */
810 memcpy((PUCHAR)sg_extra->aligned_buffer + offset, (PUCHAR)unaligned_buffer + mdl_offset, mdl_byte_count);
811 offset += mdl_byte_count;
812 }
813 }
814 }
815 for (sg_element = 0, remaining = remapped_bytes;
816 sg_element < ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_extra->aligned_buffer, remapped_bytes); sg_element++)
817 {
818 pfn = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)sg_extra->aligned_buffer + (sg_element << PAGE_SHIFT)).QuadPart >> PAGE_SHIFT);
819 ASSERT(pfn);
820 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
821 ASSERT(gref != INVALID_GRANT_REF);
822 sglist->Elements[sg_element].Address.QuadPart = (ULONGLONG)gref << PAGE_SHIFT;
823 sglist->Elements[sg_element].Length = min(PAGE_SIZE, remaining);
824 remaining -= sglist->Elements[sg_element].Length;
825 }
826 break;
827 case MAP_TYPE_VIRTUAL:
828 ptr = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
829 ASSERT(ptr); /* lazy */
830 sglist->Elements[0].Address.QuadPart = (ULONGLONG)ptr;
831 sglist->Elements[0].Length = Length;
832 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL - %08x\n", sglist->Elements[0].Address.LowPart));
833 break;
834 default:
835 KdPrint((__DRIVER_NAME " map_type = %d\n", map_type));
836 break;
837 }
838 //FUNCTION_EXIT();
839 return STATUS_SUCCESS;
840 }
842 static NTSTATUS
843 XenPci_DOP_BuildScatterGatherList(
844 IN PDMA_ADAPTER DmaAdapter,
845 IN PDEVICE_OBJECT DeviceObject,
846 IN PMDL Mdl,
847 IN PVOID CurrentVa,
848 IN ULONG Length,
849 IN PDRIVER_LIST_CONTROL ExecutionRoutine,
850 IN PVOID Context,
851 IN BOOLEAN WriteToDevice,
852 IN PVOID ScatterGatherBuffer,
853 IN ULONG ScatterGatherBufferLength)
854 {
855 NTSTATUS status;
857 status = XenPci_DOP_BuildScatterGatherListButDontExecute(DmaAdapter, DeviceObject, Mdl, CurrentVa, Length, WriteToDevice, ScatterGatherBuffer, ScatterGatherBufferLength, FALSE);
859 if (NT_SUCCESS(status))
860 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, ScatterGatherBuffer, Context);
862 //FUNCTION_EXIT();
864 return status;
865 }
867 static NTSTATUS
868 XenPci_DOP_GetScatterGatherList(
869 PDMA_ADAPTER DmaAdapter,
870 PDEVICE_OBJECT DeviceObject,
871 PMDL Mdl,
872 PVOID CurrentVa,
873 ULONG Length,
874 PDRIVER_LIST_CONTROL ExecutionRoutine,
875 PVOID Context,
876 BOOLEAN WriteToDevice)
877 {
878 NTSTATUS status;
879 ULONG list_size;
880 ULONG map_registers;
881 PSCATTER_GATHER_LIST sg_list;
883 //FUNCTION_ENTER();
885 status = XenPci_DOP_CalculateScatterGatherList(DmaAdapter, Mdl, CurrentVa, Length, &list_size, &map_registers);
886 if (!NT_SUCCESS(status))
887 {
888 //FUNCTION_EXIT();
889 return status;
890 }
892 sg_list = ExAllocatePoolWithTag(NonPagedPool, list_size, XENPCI_POOL_TAG);
893 if (!sg_list)
894 {
895 KdPrint((__DRIVER_NAME " Cannot allocate memory for sg_list\n"));
896 //FUNCTION_EXIT();
897 return STATUS_INSUFFICIENT_RESOURCES;
898 }
900 status = XenPci_DOP_BuildScatterGatherListButDontExecute(DmaAdapter, DeviceObject, Mdl, CurrentVa, Length, WriteToDevice, sg_list, list_size, TRUE);
902 if (NT_SUCCESS(status))
903 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, sg_list, Context);
905 //FUNCTION_EXIT();
907 return status;
908 }
910 static NTSTATUS
911 XenPci_DOP_BuildMdlFromScatterGatherList(
912 PDMA_ADAPTER DmaAdapter,
913 PSCATTER_GATHER_LIST ScatterGather,
914 PMDL OriginalMdl,
915 PMDL *TargetMdl)
916 {
917 NTSTATUS status = STATUS_SUCCESS;
918 UNREFERENCED_PARAMETER(DmaAdapter);
919 UNREFERENCED_PARAMETER(ScatterGather);
920 UNREFERENCED_PARAMETER(OriginalMdl);
921 UNREFERENCED_PARAMETER(TargetMdl);
923 FUNCTION_ENTER();
925 if (OriginalMdl)
926 {
927 *TargetMdl = OriginalMdl;
928 }
929 else
930 {
931 *TargetMdl = NULL;
932 status = STATUS_INVALID_PARAMETER;
933 }
935 FUNCTION_EXIT();
937 return status;
938 }
940 static PDMA_ADAPTER
941 XenPci_BIS_GetDmaAdapter(PVOID context, PDEVICE_DESCRIPTION device_description, PULONG number_of_map_registers)
942 {
943 xen_dma_adapter_t *xen_dma_adapter;
944 PDEVICE_OBJECT curr, prev;
945 PDRIVER_OBJECT fdo_driver_object;
946 PVOID fdo_driver_extension;
948 UNREFERENCED_PARAMETER(device_description);
950 FUNCTION_ENTER();
952 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
953 KdPrint((__DRIVER_NAME " Device Description = %p:\n", device_description));
954 KdPrint((__DRIVER_NAME " Version = %d\n", device_description->Version));
955 KdPrint((__DRIVER_NAME " Master = %d\n", device_description->Master));
956 KdPrint((__DRIVER_NAME " ScatterGather = %d\n", device_description->ScatterGather));
957 KdPrint((__DRIVER_NAME " DemandMode = %d\n", device_description->DemandMode));
958 KdPrint((__DRIVER_NAME " AutoInitialize = %d\n", device_description->AutoInitialize));
959 KdPrint((__DRIVER_NAME " Dma32BitAddresses = %d\n", device_description->Dma32BitAddresses));
960 KdPrint((__DRIVER_NAME " IgnoreCount = %d\n", device_description->IgnoreCount));
961 KdPrint((__DRIVER_NAME " Dma64BitAddresses = %d\n", device_description->Dma64BitAddresses));
962 KdPrint((__DRIVER_NAME " BusNumber = %d\n", device_description->BusNumber));
963 KdPrint((__DRIVER_NAME " DmaChannel = %d\n", device_description->DmaChannel));
964 KdPrint((__DRIVER_NAME " InterfaceType = %d\n", device_description->InterfaceType));
965 KdPrint((__DRIVER_NAME " DmaWidth = %d\n", device_description->DmaWidth));
966 KdPrint((__DRIVER_NAME " DmaSpeed = %d\n", device_description->DmaSpeed));
967 KdPrint((__DRIVER_NAME " MaximumLength = %d\n", device_description->MaximumLength));
968 KdPrint((__DRIVER_NAME " DmaPort = %d\n", device_description->DmaPort));
970 if (!device_description->Master)
971 return NULL;
972 /*
973 we have to allocate PAGE_SIZE bytes here because Windows thinks this is
974 actually an ADAPTER_OBJECT, and then the verifier crashes because
975 Windows accessed beyond the end of the structure :(
976 */
977 xen_dma_adapter = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
978 ASSERT(xen_dma_adapter);
979 RtlZeroMemory(xen_dma_adapter, PAGE_SIZE);
981 switch(device_description->Version)
982 {
983 case DEVICE_DESCRIPTION_VERSION1:
984 xen_dma_adapter->adapter_object.DmaHeader.Version = 1;
985 break;
986 case DEVICE_DESCRIPTION_VERSION: /* ignore what the docs say here - DEVICE_DESCRIPTION_VERSION appears to mean the latest version */
987 case DEVICE_DESCRIPTION_VERSION2:
988 xen_dma_adapter->adapter_object.DmaHeader.Version = 2;
989 break;
990 default:
991 KdPrint((__DRIVER_NAME " Unsupported device description version %d\n", device_description->Version));
992 ExFreePoolWithTag(xen_dma_adapter, XENPCI_POOL_TAG);
993 return NULL;
994 }
996 xen_dma_adapter->xppdd = context;
997 xen_dma_adapter->dma_extension = NULL;
999 KdPrint((__DRIVER_NAME " About to call IoGetAttachedDeviceReference\n"));
1000 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(xen_dma_adapter->xppdd->wdf_device));
1001 KdPrint((__DRIVER_NAME " Before start of loop - curr = %p\n", curr));
1002 while (curr != NULL)
1004 fdo_driver_object = curr->DriverObject;
1005 if (fdo_driver_object)
1007 ObReferenceObject(fdo_driver_object);
1008 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC));
1009 if (fdo_driver_extension)
1011 xen_dma_adapter->dma_extension_driver = fdo_driver_object; /* so we can dereference it on putdmaadapter */
1012 xen_dma_adapter->dma_extension = (dma_driver_extension_t *)fdo_driver_extension;
1013 ObDereferenceObject(curr);
1014 break;
1016 else
1018 ObDereferenceObject(fdo_driver_object);
1021 prev = curr;
1022 curr = IoGetLowerDeviceObject(curr);
1023 ObDereferenceObject(prev);
1025 KdPrint((__DRIVER_NAME " End of loop\n"));
1027 xen_dma_adapter->adapter_object.DmaHeader.Size = sizeof(X_ADAPTER_OBJECT); //xen_dma_adapter_t);
1028 xen_dma_adapter->adapter_object.MasterAdapter = NULL;
1029 if (xen_dma_adapter->dma_extension && xen_dma_adapter->dma_extension->max_sg_elements)
1031 xen_dma_adapter->adapter_object.MapRegistersPerChannel = xen_dma_adapter->dma_extension->max_sg_elements;
1033 else
1035 xen_dma_adapter->adapter_object.MapRegistersPerChannel = 256;
1037 xen_dma_adapter->adapter_object.AdapterBaseVa = NULL;
1038 xen_dma_adapter->adapter_object.MapRegisterBase = NULL;
1039 xen_dma_adapter->adapter_object.NumberOfMapRegisters = 0;
1040 xen_dma_adapter->adapter_object.CommittedMapRegisters = 0;
1041 xen_dma_adapter->adapter_object.CurrentWcb = NULL;
1042 KeInitializeDeviceQueue(&xen_dma_adapter->adapter_object.ChannelWaitQueue);
1043 xen_dma_adapter->adapter_object.RegisterWaitQueue = NULL;
1044 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterQueue);
1045 KeInitializeSpinLock(&xen_dma_adapter->adapter_object.SpinLock);
1046 xen_dma_adapter->adapter_object.MapRegisters = NULL;
1047 xen_dma_adapter->adapter_object.PagePort = NULL;
1048 xen_dma_adapter->adapter_object.ChannelNumber = 0xff;
1049 xen_dma_adapter->adapter_object.AdapterNumber = 0;
1050 xen_dma_adapter->adapter_object.DmaPortAddress = 0;
1051 xen_dma_adapter->adapter_object.AdapterMode = 0;
1052 xen_dma_adapter->adapter_object.NeedsMapRegisters = FALSE; /* when true this causes a crash in the crash dump path */
1053 xen_dma_adapter->adapter_object.MasterDevice = 1;
1054 xen_dma_adapter->adapter_object.Width16Bits = 0;
1055 xen_dma_adapter->adapter_object.ScatterGather = device_description->ScatterGather;
1056 xen_dma_adapter->adapter_object.IgnoreCount = device_description->IgnoreCount;
1057 xen_dma_adapter->adapter_object.Dma32BitAddresses = device_description->Dma32BitAddresses;
1058 xen_dma_adapter->adapter_object.Dma64BitAddresses = device_description->Dma64BitAddresses;
1059 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterList);
1061 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DMA_OPERATIONS), XENPCI_POOL_TAG);
1062 ASSERT(xen_dma_adapter->adapter_object.DmaHeader.DmaOperations);
1063 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 1)
1065 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = FIELD_OFFSET(DMA_OPERATIONS, CalculateScatterGatherList);
1067 else
1069 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = sizeof(DMA_OPERATIONS);
1071 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutDmaAdapter = XenPci_DOP_PutDmaAdapter;
1072 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateCommonBuffer = XenPci_DOP_AllocateCommonBuffer;
1073 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeCommonBuffer = XenPci_DOP_FreeCommonBuffer;
1074 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateAdapterChannel = XenPci_DOP_AllocateAdapterChannel;
1075 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FlushAdapterBuffers = XenPci_DOP_FlushAdapterBuffers;
1076 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeAdapterChannel = XenPci_DOP_FreeAdapterChannel;
1077 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeMapRegisters = XenPci_DOP_FreeMapRegisters;
1078 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->MapTransfer = XenPci_DOP_MapTransfer;
1079 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetDmaAlignment = XenPci_DOP_GetDmaAlignment;
1080 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->ReadDmaCounter = XenPci_DOP_ReadDmaCounter;
1081 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetScatterGatherList = XenPci_DOP_GetScatterGatherList;
1082 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutScatterGatherList = XenPci_DOP_PutScatterGatherList;
1083 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 2)
1085 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->CalculateScatterGatherList = XenPci_DOP_CalculateScatterGatherList;
1086 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildScatterGatherList = XenPci_DOP_BuildScatterGatherList;
1087 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildMdlFromScatterGatherList = XenPci_DOP_BuildMdlFromScatterGatherList;
1090 *number_of_map_registers = xen_dma_adapter->adapter_object.MapRegistersPerChannel; //1024; /* why not... */
1092 FUNCTION_EXIT();
1094 return &xen_dma_adapter->adapter_object.DmaHeader;
1097 static ULONG
1098 XenPci_BIS_SetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
1100 UNREFERENCED_PARAMETER(context);
1101 UNREFERENCED_PARAMETER(data_type);
1102 UNREFERENCED_PARAMETER(buffer);
1103 UNREFERENCED_PARAMETER(offset);
1104 UNREFERENCED_PARAMETER(length);
1106 FUNCTION_ENTER();
1107 FUNCTION_EXIT();
1108 return 0;
1111 static ULONG
1112 XenPci_BIS_GetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
1114 UNREFERENCED_PARAMETER(context);
1115 UNREFERENCED_PARAMETER(data_type);
1116 UNREFERENCED_PARAMETER(buffer);
1117 UNREFERENCED_PARAMETER(offset);
1118 UNREFERENCED_PARAMETER(length);
1120 FUNCTION_ENTER();
1121 FUNCTION_EXIT();
1122 return 0;
1125 /*
1126 Called at PASSIVE_LEVEL(?)
1127 Called during restore
1128 */
1130 static ULONG
1131 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
1133 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1134 char path[128];
1135 char *value;
1136 char *err;
1137 ULONG backend_state;
1139 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1140 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
1141 if (err)
1143 XenPci_FreeMem(err);
1144 return XenbusStateUnknown;
1146 else
1148 backend_state = atoi(value);
1149 XenPci_FreeMem(value);
1150 return backend_state;
1154 static NTSTATUS
1155 XenPciPdo_ReconfigureCompletionRoutine(
1156 PDEVICE_OBJECT device_object,
1157 PIRP irp,
1158 PVOID context)
1160 UNREFERENCED_PARAMETER(device_object);
1162 if (irp->PendingReturned)
1164 KeSetEvent ((PKEVENT)context, IO_NO_INCREMENT, FALSE);
1166 return STATUS_MORE_PROCESSING_REQUIRED;
1169 static VOID
1170 XenPci_BackEndStateHandler(char *path, PVOID context)
1172 WDFDEVICE device = context;
1173 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1174 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1175 ULONG new_backend_state;
1176 CHAR tmp_path[128];
1178 #if !DBG
1179 UNREFERENCED_PARAMETER(path);
1180 #endif
1182 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1184 /* check that path == device/id/state */
1185 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
1186 new_backend_state = XenPci_ReadBackendState(xppdd);
1187 if (new_backend_state == XenbusStateUnknown)
1189 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
1190 return;
1191 KdPrint(("Failed to read %s, assuming closed\n", path));
1192 new_backend_state = XenbusStateClosed;
1195 if (xppdd->backend_state == new_backend_state)
1197 KdPrint((__DRIVER_NAME " state unchanged\n"));
1198 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1199 return;
1202 xppdd->backend_state = new_backend_state;
1204 switch (xppdd->backend_state)
1206 case XenbusStateUnknown:
1207 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown (%s)\n", path));
1208 break;
1210 case XenbusStateInitialising:
1211 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising (%s)\n", path));
1212 break;
1214 case XenbusStateInitWait:
1215 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait (%s)\n", path));
1216 break;
1218 case XenbusStateInitialised:
1219 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised (%s)\n", path));
1220 break;
1222 case XenbusStateConnected:
1223 KdPrint((__DRIVER_NAME " Backend State Changed to Connected (%s)\n", path));
1224 break;
1226 case XenbusStateClosing:
1227 KdPrint((__DRIVER_NAME " Backend State Changed to Closing (%s)\n", path));
1228 if (xppdd->frontend_state == XenbusStateConnected)
1230 KdPrint((__DRIVER_NAME " Requesting eject\n"));
1231 WdfPdoRequestEject(device);
1233 break;
1235 case XenbusStateClosed:
1236 KdPrint((__DRIVER_NAME " Backend State Changed to Closed (%s)\n", path));
1237 break;
1239 case XenbusStateReconfiguring:
1240 KdPrint((__DRIVER_NAME " Backend State Changed to Reconfiguring (%s)\n", path));
1241 RtlStringCbPrintfA(tmp_path, ARRAY_SIZE(tmp_path), "%s/state", xppdd->path);
1242 KdPrint((__DRIVER_NAME " Setting %s to %d\n", tmp_path, XenbusStateReconfiguring));
1243 XenBus_Printf(xpdd, XBT_NIL, tmp_path, "%d", XenbusStateReconfiguring);
1244 break;
1246 case XenbusStateReconfigured:
1247 KdPrint((__DRIVER_NAME " Backend State Changed to Reconfigured (%s)\n", path));
1249 PDEVICE_OBJECT fdo;
1250 PIRP irp;
1251 PIO_STACK_LOCATION stack;
1252 NTSTATUS status;
1253 KEVENT irp_complete_event;
1255 fdo = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(device));
1256 KeInitializeEvent(&irp_complete_event, NotificationEvent, FALSE);
1257 irp = IoAllocateIrp(fdo->StackSize, FALSE);
1258 stack = IoGetNextIrpStackLocation(irp);
1259 stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
1260 stack->Parameters.DeviceIoControl.IoControlCode = (ULONG)IOCTL_XEN_RECONFIGURE;
1261 IoSetCompletionRoutine(irp, XenPciPdo_ReconfigureCompletionRoutine, &irp_complete_event, TRUE, TRUE, TRUE);
1262 status = IoCallDriver(fdo, irp);
1263 if (status == STATUS_PENDING)
1265 KdPrint((__DRIVER_NAME " Waiting for completion\n"));
1266 status = KeWaitForSingleObject(&irp_complete_event, Executive, KernelMode, FALSE, NULL);
1267 status = irp->IoStatus.Status;
1269 KdPrint((__DRIVER_NAME " IOCTL_XEN_RECONFIGURE status = %08x\n", status));
1270 ObDereferenceObject(fdo);
1271 #if 0
1272 WDFREQUEST request;
1273 WDF_REQUEST_SEND_OPTIONS options;
1274 WDFIOTARGET target;
1275 DEVICE_OBJECT fdo;
1277 WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET);
1278 fdo = IoGetAttachedDevice(WdfDeviceWdmGetDeviceObject(device));
1280 target = WdfDeviceGetIoTarget(xppdd->wdf_device);
1281 WdfRequestCreate(WDF_NO_OBJECT_ATTRIBUTES, target, &request);
1282 WdfIoTargetFormatRequestForInternalIoctl(target, request, IOCTL_XEN_RECONFIGURE, NULL, NULL, NULL, NULL);
1283 WdfRequestSend(request, target, &options);
1284 #endif
1285 RtlStringCbPrintfA(tmp_path, ARRAY_SIZE(tmp_path), "%s/state", xppdd->path);
1286 KdPrint((__DRIVER_NAME " Setting %s to %d\n", tmp_path, XenbusStateConnected));
1287 XenBus_Printf(xpdd, XBT_NIL, tmp_path, "%d", XenbusStateConnected);
1288 break;
1291 default:
1292 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d (%s)\n", xppdd->backend_state, path));
1293 break;
1296 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
1298 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1300 return;
1303 static NTSTATUS
1304 XenPci_GetBackendAndAddWatch(WDFDEVICE device)
1306 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1307 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1308 char path[128];
1309 PCHAR res;
1310 PCHAR value;
1312 /* Get backend path */
1313 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
1314 "%s/backend", xppdd->path);
1315 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
1316 if (res)
1318 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
1319 XenPci_FreeMem(res);
1320 return STATUS_UNSUCCESSFUL;
1322 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
1323 XenPci_FreeMem(value);
1325 /* Add watch on backend state */
1326 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1327 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
1329 return STATUS_SUCCESS;
1332 static NTSTATUS
1333 XenConfig_InitConfigPage(WDFDEVICE device)
1335 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1336 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
1337 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
1338 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
1339 PUCHAR ptr;
1340 PDEVICE_OBJECT curr, prev;
1341 PDRIVER_OBJECT fdo_driver_object;
1342 PUCHAR fdo_driver_extension;
1344 FUNCTION_ENTER();
1346 ptr = MmGetMdlVirtualAddress(xppdd->config_page_mdl);
1347 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(device));
1348 //curr = WdfDeviceWdmGetAttachedDevice(device);
1349 while (curr != NULL)
1351 fdo_driver_object = curr->DriverObject;
1352 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
1353 if (fdo_driver_object)
1355 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
1356 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
1357 if (fdo_driver_extension)
1359 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
1360 ObDereferenceObject(curr);
1361 break;
1364 prev = curr;
1365 curr = IoGetLowerDeviceObject(curr);
1366 ObDereferenceObject(prev);
1369 FUNCTION_EXIT();
1371 return STATUS_SUCCESS;
1374 static NTSTATUS
1375 XenPci_EvtChn_Bind(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
1377 WDFDEVICE device = context;
1378 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1379 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1381 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext);
1384 static NTSTATUS
1385 XenPci_EvtChn_BindDpc(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
1387 WDFDEVICE device = context;
1388 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1389 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1391 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext);
1394 static NTSTATUS
1395 XenPci_EvtChn_Unbind(PVOID context, evtchn_port_t Port)
1397 WDFDEVICE device = context;
1398 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1399 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1401 return EvtChn_Unbind(xpdd, Port);
1404 static NTSTATUS
1405 XenPci_EvtChn_Mask(PVOID context, evtchn_port_t Port)
1407 WDFDEVICE device = context;
1408 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1409 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1411 return EvtChn_Mask(xpdd, Port);
1414 static NTSTATUS
1415 XenPci_EvtChn_Unmask(PVOID context, evtchn_port_t Port)
1417 WDFDEVICE device = context;
1418 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1419 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1421 return EvtChn_Unmask(xpdd, Port);
1424 static NTSTATUS
1425 XenPci_EvtChn_Notify(PVOID context, evtchn_port_t Port)
1427 WDFDEVICE device = context;
1428 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1429 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1431 return EvtChn_Notify(xpdd, Port);
1434 static BOOLEAN
1435 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port, BOOLEAN *last_interrupt)
1437 WDFDEVICE device = context;
1438 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1439 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1441 return EvtChn_AckEvent(xpdd, port, last_interrupt);
1444 typedef struct {
1445 PXEN_EVTCHN_SYNC_ROUTINE sync_routine;
1446 PVOID sync_context;
1447 } sync_context_t;
1449 static BOOLEAN
1450 XenPci_EvtChn_Sync_Routine(WDFINTERRUPT interrupt, WDFCONTEXT context)
1452 sync_context_t *wdf_sync_context = context;
1453 UNREFERENCED_PARAMETER(interrupt);
1454 return wdf_sync_context->sync_routine(wdf_sync_context->sync_context);
1457 static BOOLEAN
1458 XenPci_EvtChn_Sync(PVOID context, PXEN_EVTCHN_SYNC_ROUTINE sync_routine, PVOID sync_context)
1460 WDFDEVICE device = context;
1461 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1462 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1463 sync_context_t wdf_sync_context;
1465 wdf_sync_context.sync_routine = sync_routine;
1466 wdf_sync_context.sync_context = sync_context;
1468 return WdfInterruptSynchronize(xpdd->interrupt, XenPci_EvtChn_Sync_Routine, &wdf_sync_context);
1471 static grant_ref_t
1472 XenPci_GntTbl_GrantAccess(PVOID context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref)
1474 WDFDEVICE device = context;
1475 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1476 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1478 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref);
1481 static BOOLEAN
1482 XenPci_GntTbl_EndAccess(PVOID context, grant_ref_t ref, BOOLEAN keepref)
1484 WDFDEVICE device = context;
1485 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1486 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1488 return GntTbl_EndAccess(xpdd, ref, keepref);
1491 static VOID
1492 XenPci_GntTbl_PutRef(PVOID context, grant_ref_t ref)
1494 WDFDEVICE device = context;
1495 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1496 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1498 GntTbl_PutRef(xpdd, ref);
1501 static grant_ref_t
1502 XenPci_GntTbl_GetRef(PVOID context)
1504 WDFDEVICE device = context;
1505 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1506 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1508 return GntTbl_GetRef(xpdd);
1511 PCHAR
1512 XenPci_XenBus_Read(PVOID context, xenbus_transaction_t xbt, char *path, char **value)
1514 WDFDEVICE device = context;
1515 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1516 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1517 return XenBus_Read(xpdd, xbt, path, value);
1520 PCHAR
1521 XenPci_XenBus_Write(PVOID context, xenbus_transaction_t xbt, char *path, char *value)
1523 WDFDEVICE device = context;
1524 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1525 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1526 return XenBus_Write(xpdd, xbt, path, value);
1529 PCHAR
1530 XenPci_XenBus_Printf(PVOID context, xenbus_transaction_t xbt, char *path, char *fmt, ...)
1532 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
1533 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
1534 //return XenBus_Printf(xpdd, xbt, path, value);
1535 UNREFERENCED_PARAMETER(context);
1536 UNREFERENCED_PARAMETER(xbt);
1537 UNREFERENCED_PARAMETER(path);
1538 UNREFERENCED_PARAMETER(fmt);
1539 return NULL;
1542 PCHAR
1543 XenPci_XenBus_StartTransaction(PVOID context, xenbus_transaction_t *xbt)
1545 WDFDEVICE device = context;
1546 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1547 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1548 return XenBus_StartTransaction(xpdd, xbt);
1551 PCHAR
1552 XenPci_XenBus_EndTransaction(PVOID context, xenbus_transaction_t xbt, int abort, int *retry)
1554 WDFDEVICE device = context;
1555 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1556 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1557 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
1560 PCHAR
1561 XenPci_XenBus_List(PVOID context, xenbus_transaction_t xbt, char *prefix, char ***contents)
1563 WDFDEVICE device = context;
1564 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1565 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1566 return XenBus_List(xpdd, xbt, prefix, contents);
1569 PCHAR
1570 XenPci_XenBus_AddWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
1572 WDFDEVICE device = context;
1573 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1574 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1575 PCHAR retval;
1577 FUNCTION_ENTER();
1578 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
1579 if (retval == NULL)
1581 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
1583 else
1585 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
1587 FUNCTION_EXIT();
1588 return retval;
1591 PCHAR
1592 XenPci_XenBus_RemWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
1594 WDFDEVICE device = context;
1595 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1596 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1597 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
1600 /*
1601 Called at PASSIVE_LEVEL
1602 Called during restore
1603 */
1605 static NTSTATUS
1606 XenPci_ChangeFrontendState(WDFDEVICE device, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
1608 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1609 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1610 LARGE_INTEGER timeout;
1611 ULONG remaining;
1612 ULONG thiswait;
1613 char path[128];
1615 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1617 xppdd->frontend_state = frontend_state_set;
1619 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
1620 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
1622 remaining = maximum_wait_ms;
1624 while (xppdd->backend_state != backend_state_response)
1626 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
1627 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
1628 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
1630 remaining -= thiswait;
1631 if (remaining == 0)
1633 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
1634 return STATUS_UNSUCCESSFUL;
1636 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
1639 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1640 return STATUS_SUCCESS;
1643 static NTSTATUS
1644 XenPci_XenConfigDevice(WDFDEVICE device);
1646 static NTSTATUS
1647 XenPci_XenShutdownDevice(PVOID context)
1649 WDFDEVICE device = context;
1650 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1651 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1652 PUCHAR in_ptr;
1653 ULONG i;
1654 UCHAR type;
1655 PVOID setting;
1656 PVOID value;
1657 PVOID value2;
1659 FUNCTION_ENTER();
1661 if (xppdd->backend_state == XenbusStateConnected)
1663 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
1664 if (xppdd->backend_state == XenbusStateClosing)
1665 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
1666 if (xppdd->backend_state == XenbusStateClosed)
1667 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
1669 else
1671 if (xppdd->backend_state == XenbusStateClosing)
1672 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
1675 if (xppdd->assigned_resources_start != NULL)
1677 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1678 in_ptr = xppdd->assigned_resources_start;
1679 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
1681 switch (type)
1683 case XEN_INIT_TYPE_RING: /* frontend ring */
1684 FreePages(value);
1685 break;
1686 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
1687 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
1688 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
1689 EvtChn_Unbind(xpdd, PtrToUlong(value));
1690 EvtChn_Close(xpdd, PtrToUlong(value));
1691 break;
1692 case XEN_INIT_TYPE_GRANT_ENTRIES:
1693 for (i = 0; i < PtrToUlong(setting); i++)
1694 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value)[i], FALSE);
1695 break;
1698 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
1699 xppdd->assigned_resources_start = NULL;
1702 FUNCTION_EXIT();
1704 return STATUS_SUCCESS;
1707 struct dummy_sring {
1708 RING_IDX req_prod, req_event;
1709 RING_IDX rsp_prod, rsp_event;
1710 uint8_t pad[48];
1711 };
1713 static NTSTATUS
1714 XenPci_XenConfigDeviceSpecifyBuffers(WDFDEVICE device, PUCHAR src, PUCHAR dst)
1716 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1717 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1718 NTSTATUS status = STATUS_SUCCESS;
1719 ULONG i;
1720 char path[128];
1721 PCHAR setting, value;
1722 PCHAR res;
1723 PVOID address;
1724 UCHAR type;
1725 PUCHAR in_ptr;
1726 PUCHAR out_ptr;
1727 XENPCI_VECTORS vectors;
1728 ULONG event_channel;
1729 ULONG run_type = 0;
1730 PMDL ring;
1731 grant_ref_t gref;
1732 BOOLEAN done_xenbus_init = FALSE;
1733 PVOID value2;
1734 BOOLEAN active = TRUE;
1735 BOOLEAN dont_config = FALSE;
1737 FUNCTION_ENTER();
1739 in_ptr = src;
1740 out_ptr = dst;
1742 // always add vectors
1743 vectors.magic = XEN_DATA_MAGIC;
1744 vectors.length = sizeof(XENPCI_VECTORS);
1745 vectors.context = device;
1746 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
1747 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
1748 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
1749 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
1750 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
1751 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
1752 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
1753 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
1754 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
1755 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
1756 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
1757 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
1758 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
1759 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
1760 strncpy(vectors.path, xppdd->path, 128);
1761 strncpy(vectors.backend_path, xppdd->backend_path, 128);
1762 //vectors.pdo_event_channel = xpdd->pdo_event_channel;
1763 vectors.XenBus_Read = XenPci_XenBus_Read;
1764 vectors.XenBus_Write = XenPci_XenBus_Write;
1765 vectors.XenBus_Printf = XenPci_XenBus_Printf;
1766 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
1767 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
1768 vectors.XenBus_List = XenPci_XenBus_List;
1769 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
1770 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
1772 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
1774 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
1775 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
1778 if (!qemu_filtered)
1779 active = FALSE;
1781 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
1783 BOOLEAN condition;
1784 PCHAR xb_value;
1785 switch (type)
1787 case XEN_INIT_TYPE_MATCH_FRONT:
1788 case XEN_INIT_TYPE_MATCH_BACK:
1789 if (type == XEN_INIT_TYPE_MATCH_FRONT)
1791 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1793 else
1795 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
1797 KdPrint((__DRIVER_NAME " testing path = %s\n", path));
1798 res = XenBus_Read(xpdd, XBT_NIL, path, &xb_value);
1799 if (res)
1801 KdPrint((__DRIVER_NAME " read failed (%s)\n", res));
1802 XenPci_FreeMem(res);
1804 else
1806 KdPrint((__DRIVER_NAME " testing %s vs %s\n", xb_value, value));
1807 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_IF_MATCH)
1808 condition = (strcmp(xb_value, value) == 0)?TRUE:FALSE;
1809 else
1810 condition = (strcmp(xb_value, value) != 0)?TRUE:FALSE;
1811 KdPrint((__DRIVER_NAME " condition = %d\n", condition));
1813 if ((PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_ONLY_IF_QEMU_HIDE) && qemu_protocol_version && condition)
1814 condition = FALSE;
1816 if (condition)
1818 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_SET_INACTIVE)
1820 active = FALSE;
1821 KdPrint((__DRIVER_NAME " set inactive\n"));
1823 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_DONT_CONFIG)
1825 dont_config = TRUE;
1826 KdPrint((__DRIVER_NAME " set inactive with dont config\n"));
1829 XenPci_FreeMem(xb_value);
1831 break;
1834 if (dont_config)
1836 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1837 FUNCTION_EXIT();
1838 return status;
1841 // first pass, possibly before state == Connected
1842 in_ptr = src;
1843 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
1846 if (!done_xenbus_init)
1848 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000) != STATUS_SUCCESS)
1850 status = STATUS_UNSUCCESSFUL;
1851 goto error;
1853 done_xenbus_init = TRUE;
1856 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
1858 switch (type)
1860 case XEN_INIT_TYPE_RUN:
1861 run_type++;
1862 break;
1863 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
1864 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
1865 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1866 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
1867 break;
1868 case XEN_INIT_TYPE_RING: /* frontend ring */
1869 /* we only allocate and do the SHARED_RING_INIT here */
1870 if ((ring = AllocatePage()) != 0)
1872 address = MmGetMdlVirtualAddress(ring);
1873 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
1874 SHARED_RING_INIT((struct dummy_sring *)address);
1875 if ((gref = GntTbl_GrantAccess(
1876 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
1878 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1879 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
1880 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
1881 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
1882 // add the grant entry too so it gets freed automatically
1883 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
1884 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
1885 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
1887 else
1889 FreePages(ring);
1890 status = STATUS_UNSUCCESSFUL;
1891 goto error;
1894 else
1896 status = STATUS_UNSUCCESSFUL;
1897 goto error;
1899 break;
1900 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
1901 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
1902 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
1903 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
1905 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
1906 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1907 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
1908 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
1909 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
1910 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
1912 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
1914 else if (type == XEN_INIT_TYPE_EVENT_CHANNEL_DPC)
1916 #pragma warning(suppress:4055)
1917 EvtChn_BindDpc(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
1919 else
1921 #pragma warning(suppress:4055)
1922 EvtChn_Bind(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
1925 else
1927 status = STATUS_UNSUCCESSFUL;
1928 goto error;
1930 break;
1933 if (!NT_SUCCESS(status))
1935 goto error;
1937 // If XEN_INIT_TYPE_RUN was specified more than once then we skip XenbusStateInitialised here and go straight to XenbusStateConnected at the end
1938 if (run_type == 1)
1940 if (XenPci_ChangeFrontendState(device, XenbusStateInitialised, XenbusStateConnected, 2000) != STATUS_SUCCESS)
1942 status = STATUS_UNSUCCESSFUL;
1943 goto error;
1947 // second pass, possibly after state == Connected
1948 in_ptr = src;
1949 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
1951 switch(type)
1953 case XEN_INIT_TYPE_READ_STRING_BACK:
1954 case XEN_INIT_TYPE_READ_STRING_FRONT:
1955 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
1956 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1957 else
1958 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
1959 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
1960 if (res)
1962 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
1963 XenPci_FreeMem(res);
1964 ADD_XEN_INIT_RSP(&out_ptr, type, setting, "", "");
1966 else
1968 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
1969 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, value2);
1970 XenPci_FreeMem(value);
1972 break;
1973 case XEN_INIT_TYPE_VECTORS:
1974 // this is always done so ignore the request
1975 break;
1976 case XEN_INIT_TYPE_GRANT_ENTRIES:
1977 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
1978 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
1979 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
1980 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
1981 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
1982 for (i = 0; i < PtrToUlong(value); i++)
1984 gref = GntTbl_GetRef(xpdd);
1985 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
1986 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
1988 break;
1991 if (active)
1993 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_ACTIVE, NULL, NULL, NULL);
1995 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1997 if (run_type)
1999 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 2000) != STATUS_SUCCESS)
2001 status = STATUS_UNSUCCESSFUL;
2002 goto error;
2005 FUNCTION_EXIT();
2006 return status;
2008 error:
2009 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000);
2010 FUNCTION_EXIT_STATUS(status);
2011 return status;
2014 static NTSTATUS
2015 XenPci_XenConfigDevice(WDFDEVICE device)
2017 NTSTATUS status;
2018 PUCHAR src, dst;
2019 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2021 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
2022 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
2023 memcpy(src, dst, xppdd->config_page_length);
2025 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
2027 MmUnmapIoSpace(dst, xppdd->config_page_length);
2028 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
2030 return status;
2033 static NTSTATUS
2034 XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp)
2036 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2037 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2038 PIO_STACK_LOCATION stack;
2039 PCM_PARTIAL_RESOURCE_LIST prl;
2040 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
2041 ULONG i;
2042 //char path[128];
2043 //PMDL mdl;
2045 FUNCTION_ENTER();
2046 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
2048 stack = IoGetCurrentIrpStackLocation(irp);
2050 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
2051 for (i = 0; i < prl->Count; i++)
2053 prd = & prl->PartialDescriptors[i];
2054 switch (prd->Type)
2056 case CmResourceTypeMemory:
2057 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
2059 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
2060 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
2062 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
2064 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
2065 prd->Type = CmResourceTypeInterrupt;
2066 prd->ShareDisposition = CmResourceShareShared;
2067 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
2068 prd->u.Interrupt.Level = 0; // Set group and level to zero (group = upper word)
2069 prd->u.Interrupt.Level = xpdd->irq_number & 0xffff; // Only set the lower word
2070 prd->u.Interrupt.Vector = xpdd->irq_number;
2071 prd->u.Interrupt.Affinity = KeQueryActiveProcessors();
2072 xppdd->irq_number = xpdd->irq_number;
2074 break;
2078 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
2079 for (i = 0; i < prl->Count; i++)
2081 prd = & prl->PartialDescriptors[i];
2082 switch (prd->Type)
2084 case CmResourceTypeMemory:
2085 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
2086 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
2087 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
2089 if (prd->u.Memory.Length == 0)
2091 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0]));
2092 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
2093 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
2094 KdPrint((__DRIVER_NAME " New Start = %08x%08x, Length = %d\n", prd->u.Memory.Start.HighPart, prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
2096 xppdd->config_page_phys = prd->u.Memory.Start;
2097 xppdd->config_page_length = prd->u.Memory.Length;
2098 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
2099 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
2101 #if 0
2102 status = XenPci_XenConfigDevice(device);
2103 if (!NT_SUCCESS(status))
2105 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2106 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
2107 FUNCTION_ERROR_EXIT();
2108 return status;
2110 #endif
2112 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
2114 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
2115 prd->Type = CmResourceTypeInterrupt;
2116 prd->ShareDisposition = CmResourceShareShared;
2117 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
2118 prd->u.Interrupt.Level = 0; // Set group and level to zero (group = upper word)
2119 prd->u.Interrupt.Level = xpdd->irq_level & 0xffff; // Only set the lower word
2120 prd->u.Interrupt.Vector = xpdd->irq_vector;
2121 prd->u.Interrupt.Affinity = KeQueryActiveProcessors();
2122 xppdd->irq_vector = xpdd->irq_vector;
2123 xppdd->irq_level = xpdd->irq_level;
2125 break;
2129 IoSkipCurrentIrpStackLocation(irp);
2131 FUNCTION_EXIT();
2133 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
2136 #if 0
2137 static NTSTATUS
2138 XenPciPdo_EvtDeviceResourcesQuery(WDFDEVICE device, WDFCMRESLIST resources)
2141 #endif
2143 static NTSTATUS
2144 XenPciPdo_EvtDeviceResourceRequirementsQuery(WDFDEVICE device, WDFIORESREQLIST requirements_list)
2146 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2147 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2148 WDFIORESLIST res_list;
2149 IO_RESOURCE_DESCRIPTOR ird;
2151 //FUNCTION_ENTER();
2153 WdfIoResourceRequirementsListSetInterfaceType(requirements_list, PNPBus);
2155 WdfIoResourceListCreate(requirements_list, WDF_NO_OBJECT_ATTRIBUTES, &res_list);
2156 ird.Option = 0;
2157 ird.Type = CmResourceTypeMemory;
2158 ird.ShareDisposition = CmResourceShareShared;
2159 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
2160 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
2161 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
2162 ird.u.Memory.Length = 0;
2163 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
2164 WdfIoResourceListAppendDescriptor(res_list, &ird);
2166 ird.Option = 0;
2167 ird.Type = CmResourceTypeMemory;
2168 ird.ShareDisposition = CmResourceShareShared;
2169 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
2170 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
2171 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
2172 ird.u.Memory.Length = 0;
2173 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
2174 WdfIoResourceListAppendDescriptor(res_list, &ird);
2176 WdfIoResourceRequirementsListAppendIoResList(requirements_list, res_list);
2178 //FUNCTION_EXIT();
2180 return STATUS_SUCCESS;
2183 NTSTATUS
2184 XenPciPdo_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
2186 NTSTATUS status = STATUS_SUCCESS;
2187 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2188 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2189 CHAR path[128];
2191 FUNCTION_ENTER();
2193 switch (previous_state)
2195 case WdfPowerDeviceD0:
2196 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
2197 break;
2198 case WdfPowerDeviceD1:
2199 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
2200 break;
2201 case WdfPowerDeviceD2:
2202 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
2203 break;
2204 case WdfPowerDeviceD3:
2205 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
2206 break;
2207 case WdfPowerDeviceD3Final:
2208 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
2209 break;
2210 case WdfPowerDevicePrepareForHibernation:
2211 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
2212 break;
2213 default:
2214 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
2215 break;
2218 if (previous_state == WdfPowerDevicePrepareForHibernation
2219 || (previous_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
2221 KdPrint((__DRIVER_NAME " starting up from hibernation\n"));
2223 else
2227 XenConfig_InitConfigPage(device);
2229 status = XenPci_GetBackendAndAddWatch(device);
2230 if (!NT_SUCCESS(status))
2232 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
2233 FUNCTION_ERROR_EXIT();
2234 return status;
2236 status = XenPci_XenConfigDevice(device);
2237 if (!NT_SUCCESS(status))
2239 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2240 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
2241 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
2242 FUNCTION_ERROR_EXIT();
2243 return status;
2246 FUNCTION_EXIT();
2248 return status;
2251 NTSTATUS
2252 XenPciPdo_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
2254 NTSTATUS status = STATUS_SUCCESS;
2255 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2256 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2257 char path[128];
2259 UNREFERENCED_PARAMETER(device);
2260 UNREFERENCED_PARAMETER(target_state);
2262 FUNCTION_ENTER();
2264 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
2267 switch (target_state)
2269 case WdfPowerDeviceD0:
2270 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
2271 break;
2272 case WdfPowerDeviceD1:
2273 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
2274 break;
2275 case WdfPowerDeviceD2:
2276 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
2277 break;
2278 case WdfPowerDeviceD3:
2279 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
2280 break;
2281 case WdfPowerDeviceD3Final:
2282 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
2283 break;
2284 case WdfPowerDevicePrepareForHibernation:
2285 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
2286 break;
2287 default:
2288 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
2289 break;
2292 if (target_state == WdfPowerDevicePrepareForHibernation
2293 || (target_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
2295 KdPrint((__DRIVER_NAME " not powering down as we are hibernating\n"));
2297 else
2299 status = XenPci_XenShutdownDevice(device);
2300 /* Remove watch on backend state */
2301 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2302 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
2304 FUNCTION_EXIT();
2306 return status;
2309 NTSTATUS
2310 XenPciPdo_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
2312 NTSTATUS status = STATUS_SUCCESS;
2314 UNREFERENCED_PARAMETER(device);
2315 UNREFERENCED_PARAMETER(resources_raw);
2316 UNREFERENCED_PARAMETER(resources_translated);
2318 FUNCTION_ENTER();
2319 FUNCTION_EXIT();
2321 return status;
2324 NTSTATUS
2325 XenPciPdo_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
2327 NTSTATUS status = STATUS_SUCCESS;
2329 UNREFERENCED_PARAMETER(device);
2330 UNREFERENCED_PARAMETER(resources_translated);
2332 FUNCTION_ENTER();
2333 FUNCTION_EXIT();
2335 return status;
2338 static VOID
2339 XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
2341 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2343 FUNCTION_ENTER();
2345 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
2346 switch (notification_type)
2348 case WdfSpecialFilePaging:
2349 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
2350 break;
2351 case WdfSpecialFileHibernation:
2352 xppdd->hiber_usage_kludge = is_in_notification_path;
2353 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
2354 break;
2355 case WdfSpecialFileDump:
2356 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
2357 break;
2358 default:
2359 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
2360 break;
2363 FUNCTION_EXIT();
2366 NTSTATUS
2367 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
2368 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
2369 PWDFDEVICE_INIT child_init)
2371 NTSTATUS status = STATUS_SUCCESS;
2372 WDF_OBJECT_ATTRIBUTES child_attributes;
2373 WDFDEVICE child_device;
2374 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
2375 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
2376 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
2377 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
2378 PXENPCI_PDO_DEVICE_DATA xppdd;
2379 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
2380 WDF_QUERY_INTERFACE_CONFIG interface_config;
2381 BUS_INTERFACE_STANDARD bus_interface;
2382 WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
2383 WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
2384 UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
2385 WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
2387 FUNCTION_ENTER();
2389 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
2391 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
2392 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
2393 //child_pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPciPdo_EvtDeviceD0EntryPostInterruptsEnabled;
2394 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
2395 //child_pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPciPdo_EvtDeviceD0ExitPreInterruptsDisabled;
2396 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenPciPdo_EvtDevicePrepareHardware;
2397 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenPciPdo_EvtDeviceReleaseHardware;
2398 child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
2399 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
2401 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
2402 identification->device, identification->index, identification->path));
2404 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
2405 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
2406 if (!NT_SUCCESS(status))
2408 return status;
2411 WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
2412 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
2413 pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
2414 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
2415 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
2416 WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
2418 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
2419 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
2420 if (!NT_SUCCESS(status))
2422 return status;
2424 status = WdfPdoInitAddHardwareID(child_init, &buffer);
2425 if (!NT_SUCCESS(status))
2427 return status;
2429 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
2430 if (!NT_SUCCESS(status))
2432 return status;
2435 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
2436 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
2437 if (!NT_SUCCESS(status))
2439 return status;
2442 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
2443 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
2444 if (!NT_SUCCESS(status))
2446 return status;
2448 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
2450 WdfDeviceInitSetPowerNotPageable(child_init);
2452 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
2453 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
2454 if (!NT_SUCCESS(status))
2456 return status;
2459 xppdd = GetXppdd(child_device);
2461 xppdd->wdf_device = child_device;
2462 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
2464 xppdd->config_page_mdl = AllocateUncachedPage();
2466 xppdd->device_state.magic = XEN_DEVICE_STATE_MAGIC;
2467 xppdd->device_state.length = sizeof(XENPCI_DEVICE_STATE);
2468 xppdd->device_state.suspend_resume_state_pdo = SR_STATE_RUNNING;
2469 xppdd->device_state.suspend_resume_state_fdo = SR_STATE_RUNNING;
2470 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
2471 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
2472 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
2473 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
2475 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
2476 child_pnp_capabilities.LockSupported = WdfFalse;
2477 child_pnp_capabilities.EjectSupported = WdfTrue;
2478 child_pnp_capabilities.Removable = WdfTrue;
2479 child_pnp_capabilities.DockDevice = WdfFalse;
2480 child_pnp_capabilities.UniqueID = WdfFalse;
2481 child_pnp_capabilities.SilentInstall = WdfTrue;
2482 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
2483 child_pnp_capabilities.HardwareDisabled = WdfFalse;
2484 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
2486 WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
2487 child_power_capabilities.DeviceD1 = WdfTrue;
2488 child_power_capabilities.WakeFromD1 = WdfTrue;
2489 child_power_capabilities.DeviceWake = PowerDeviceD1;
2490 child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
2491 child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
2492 child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
2493 child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
2494 child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
2495 child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
2496 WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
2498 bus_interface.Size = sizeof(BUS_INTERFACE_STANDARD);
2499 bus_interface.Version = 1; //BUS_INTERFACE_STANDARD_VERSION;
2500 bus_interface.Context = xppdd;
2501 bus_interface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
2502 bus_interface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
2503 bus_interface.TranslateBusAddress = XenPci_BIS_TranslateBusAddress;
2504 bus_interface.GetDmaAdapter = XenPci_BIS_GetDmaAdapter;
2505 bus_interface.SetBusData = XenPci_BIS_SetBusData;
2506 bus_interface.GetBusData = XenPci_BIS_GetBusData;
2507 WDF_QUERY_INTERFACE_CONFIG_INIT(&interface_config, (PINTERFACE)&bus_interface, &GUID_BUS_INTERFACE_STANDARD, NULL);
2508 status = WdfDeviceAddQueryInterface(child_device, &interface_config);
2509 if (!NT_SUCCESS(status))
2511 return status;
2514 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
2515 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
2516 xppdd->index = identification->index;
2517 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
2518 xppdd->backend_state = XenbusStateUnknown;
2519 xppdd->frontend_state = XenbusStateUnknown;
2520 xppdd->backend_path[0] = '\0';
2522 FUNCTION_EXIT();
2524 return status;
2527 static __forceinline VOID
2528 XenPci_Pdo_ChangeSuspendState(WDFDEVICE device, ULONG new_state)
2530 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2531 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2533 FUNCTION_ENTER();
2534 KdPrint((__DRIVER_NAME " setting pdo state to %d\n", new_state));
2535 xppdd->device_state.suspend_resume_state_pdo = new_state;
2536 KeMemoryBarrier();
2537 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xpdd->pdo_event_channel));
2538 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
2539 while(xppdd->device_state.suspend_resume_state_fdo != xppdd->device_state.suspend_resume_state_pdo)
2541 KdPrint((__DRIVER_NAME " waiting...\n"));
2542 KeWaitForSingleObject(&xpdd->pdo_suspend_event, Executive, KernelMode, FALSE, NULL);
2544 KdPrint((__DRIVER_NAME " fdo state set to %d\n", new_state));
2545 FUNCTION_EXIT();
2548 /* called at PASSIVE_LEVEL */
2549 NTSTATUS
2550 XenPci_Pdo_Suspend(WDFDEVICE device)
2552 NTSTATUS status = STATUS_SUCCESS;
2553 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2554 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2555 //LARGE_INTEGER wait_time;
2556 char path[128];
2557 PUCHAR in_ptr;
2558 UCHAR type;
2559 PVOID setting;
2560 PVOID value;
2561 PVOID value2;
2563 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
2565 if (xppdd->backend_state == XenbusStateConnected)
2567 xppdd->restart_on_resume = TRUE;
2568 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_SUSPENDING);
2570 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
2571 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
2572 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
2574 if (xppdd->assigned_resources_start != NULL)
2576 in_ptr = xppdd->assigned_resources_ptr;
2577 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
2578 in_ptr = xppdd->assigned_resources_start;
2579 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
2581 switch (type)
2583 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
2584 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel bound to dpc */
2585 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
2586 EvtChn_Unbind(xpdd, PtrToUlong(value));
2587 EvtChn_Close(xpdd, PtrToUlong(value));
2588 break;
2593 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2594 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
2596 else
2598 xppdd->restart_on_resume = FALSE;
2601 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
2603 return status;
2606 NTSTATUS
2607 XenPci_Pdo_Resume(WDFDEVICE device)
2609 NTSTATUS status = STATUS_SUCCESS;
2610 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2611 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2612 ULONG old_backend_state;
2613 PUCHAR src, dst;
2615 FUNCTION_ENTER();
2616 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
2618 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
2619 old_backend_state = xppdd->backend_state;
2621 if (xppdd->restart_on_resume)
2623 status = XenPci_GetBackendAndAddWatch(device);
2625 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
2627 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
2628 // this is probably an unrecoverable situation...
2629 FUNCTION_ERROR_EXIT();
2630 return STATUS_UNSUCCESSFUL;
2632 if (xppdd->assigned_resources_ptr)
2634 // reset things - feed the 'requested resources' back in
2635 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
2636 src = xppdd->requested_resources_start;
2637 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
2638 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
2640 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
2642 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
2644 MmUnmapIoSpace(dst, xppdd->config_page_length);
2645 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
2647 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
2649 // this is definitely an unrecoverable situation...
2650 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
2651 FUNCTION_ERROR_EXIT();
2652 return STATUS_UNSUCCESSFUL;
2654 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RESUMING);
2655 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RUNNING);
2658 FUNCTION_EXIT();
2660 return STATUS_SUCCESS;