win-pvdrivers

view xenpci/xenpci_pdo.c @ 607:c2aea3e060a7

Missed a line in cut&paste in previous checksum fix
author James Harper <james.harper@bendigoit.com.au>
date Sun Jul 05 21:06:26 2009 +1000 (2009-07-05)
parents bfcba5547b8e
children 4d777ca3cdd1
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)((ULONGLONG)CurrentVa - (ULONGLONG)MmGetMdlVirtualAddress(mdl));
368 page_offset = PtrToUlong(CurrentVa) & (PAGE_SIZE - 1);
369 *Length = min(*Length, PAGE_SIZE - page_offset);
370 pfn_index = (ULONG)(((ULONGLONG)CurrentVa >> PAGE_SHIFT) - ((ULONGLONG)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)((ULONGLONG)CurrentVa - (ULONGLONG)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 if ((ULONGLONG)sg_extra->currentva >= (ULONGLONG)mdl_start_va && (ULONGLONG)sg_extra->currentva < (ULONGLONG)mdl_start_va + mdl_byte_count)
485 {
486 active = TRUE;
487 mdl_byte_count -= (ULONG)((ULONGLONG)sg_extra->currentva - (ULONGLONG)mdl_start_va);
488 mdl_offset = (ULONG)((ULONGLONG)sg_extra->currentva - (ULONGLONG)mdl_start_va);
489 mdl_start_va = sg_extra->currentva;
490 }
491 if (active)
492 {
493 PVOID unaligned_buffer;
494 unaligned_buffer = MmGetSystemAddressForMdlSafe(curr_mdl, NormalPagePriority);
495 ASSERT(unaligned_buffer); /* lazy */
496 memcpy((PUCHAR)unaligned_buffer + mdl_offset, (PUCHAR)sg_extra->aligned_buffer + offset, mdl_byte_count);
497 offset += mdl_byte_count;
498 }
499 }
500 }
501 ExFreePoolWithTag(sg_extra->aligned_buffer, XENPCI_POOL_TAG);
502 break;
503 case MAP_TYPE_MDL:
504 for (i = 0; i < sg_list->NumberOfElements; i++)
505 {
506 grant_ref_t gref;
507 gref = (grant_ref_t)(sg_list->Elements[i].Address.QuadPart >> PAGE_SHIFT);
508 GntTbl_EndAccess(xpdd, gref, FALSE);
509 sg_list->Elements[i].Address.QuadPart = -1;
510 }
511 break;
512 case MAP_TYPE_VIRTUAL:
513 break;
514 }
515 if (sg_extra->allocated_by_me)
516 ExFreePoolWithTag(sg_list, XENPCI_POOL_TAG);
517 //FUNCTION_EXIT();
518 }
520 static NTSTATUS
521 XenPci_DOP_CalculateScatterGatherList(
522 PDMA_ADAPTER DmaAdapter,
523 PMDL Mdl,
524 PVOID CurrentVa,
525 ULONG Length,
526 PULONG ScatterGatherListSize,
527 PULONG NumberOfMapRegisters
528 )
529 {
530 xen_dma_adapter_t *xen_dma_adapter;
531 ULONG elements;
532 PMDL curr_mdl;
534 //FUNCTION_ENTER();
536 //KdPrint((__DRIVER_NAME " Mdl = %p\n", Mdl));
537 //KdPrint((__DRIVER_NAME " CurrentVa = %p\n", CurrentVa));
538 //KdPrint((__DRIVER_NAME " Length = %d\n", Length));
540 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
542 if (Mdl)
543 {
544 //if (CurrentVa != MmGetMdlVirtualAddress(Mdl))
545 //{
546 // KdPrint((__DRIVER_NAME " CurrentVa (%p) != MdlVa (%p)\n", CurrentVa, MmGetMdlVirtualAddress(Mdl)));
547 //
549 KdPrint((__DRIVER_NAME " CurrentVa = %p, MdlVa = %p\n", CurrentVa, MmGetMdlVirtualAddress(Mdl)));
551 for (curr_mdl = Mdl, elements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
552 {
553 KdPrint((__DRIVER_NAME " curr_mdlVa = %p, curr_mdl size = %d\n", MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)));
554 elements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
555 }
556 }
557 else
558 {
559 elements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, Length); // + 1;
560 }
562 if (elements > xen_dma_adapter->adapter_object.MapRegistersPerChannel)
563 {
564 KdPrint((__DRIVER_NAME " elements = %d - too many\n", elements));
565 if (NumberOfMapRegisters)
566 *NumberOfMapRegisters = 0;
567 *ScatterGatherListSize = 0;
569 return STATUS_INSUFFICIENT_RESOURCES;
570 }
572 *ScatterGatherListSize = FIELD_OFFSET(SCATTER_GATHER_LIST, Elements)
573 + sizeof(SCATTER_GATHER_ELEMENT) * elements
574 + sizeof(sg_extra_t);
575 if (NumberOfMapRegisters)
576 *NumberOfMapRegisters = elements;
578 KdPrint((__DRIVER_NAME " ScatterGatherListSize = %d, NumberOfMapRegisters = %d\n", *ScatterGatherListSize, elements));
580 //FUNCTION_EXIT();
581 return STATUS_SUCCESS;
582 }
584 static NTSTATUS
585 XenPci_DOP_BuildScatterGatherListButDontExecute(
586 IN PDMA_ADAPTER DmaAdapter,
587 IN PDEVICE_OBJECT DeviceObject,
588 IN PMDL Mdl,
589 IN PVOID CurrentVa,
590 IN ULONG Length,
591 IN BOOLEAN WriteToDevice,
592 IN PVOID ScatterGatherBuffer,
593 IN ULONG ScatterGatherBufferLength,
594 BOOLEAN allocated_by_me)
595 {
596 ULONG i;
597 PSCATTER_GATHER_LIST sglist = ScatterGatherBuffer;
598 PUCHAR ptr;
599 ULONG remaining = Length;
600 ULONG total_remaining;
601 xen_dma_adapter_t *xen_dma_adapter;
602 PXENPCI_DEVICE_DATA xpdd;
603 sg_extra_t *sg_extra;
604 PMDL curr_mdl;
605 ULONG map_type;
606 ULONG sg_element;
607 ULONG offset;
608 PFN_NUMBER pfn;
609 grant_ref_t gref;
610 BOOLEAN active;
611 PVOID mdl_start_va;
612 ULONG mdl_byte_count;
613 ULONG mdl_offset;
614 ULONG remapped_bytes = 0;
616 //FUNCTION_ENTER();
618 if (!ScatterGatherBuffer)
619 {
620 KdPrint((__DRIVER_NAME " NULL ScatterGatherBuffer\n"));
621 return STATUS_INVALID_PARAMETER;
622 }
623 if (MmGetMdlVirtualAddress(Mdl) != CurrentVa)
624 {
625 KdPrint((__DRIVER_NAME " MmGetMdlVirtualAddress = %p, CurrentVa = %p, Length = %d\n", MmGetMdlVirtualAddress(Mdl), CurrentVa, Length));
626 }
628 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
629 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
631 ASSERT(Mdl);
633 if (xen_dma_adapter->dma_extension)
634 {
635 if (xen_dma_adapter->dma_extension->need_virtual_address && xen_dma_adapter->dma_extension->need_virtual_address(DeviceObject->CurrentIrp))
636 {
637 ASSERT(!Mdl->Next); /* can only virtual a single buffer */
638 ASSERT(MmGetMdlVirtualAddress(Mdl) == CurrentVa);
639 map_type = MAP_TYPE_VIRTUAL;
640 sglist->NumberOfElements = 1;
641 }
642 else
643 {
644 if (xen_dma_adapter->dma_extension->get_alignment)
645 {
646 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(DeviceObject->CurrentIrp);
648 map_type = MAP_TYPE_MDL;
649 sglist->NumberOfElements = 0;
650 for (curr_mdl = Mdl, remapped_bytes = 0, active = FALSE; curr_mdl; curr_mdl = curr_mdl->Next)
651 {
652 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
653 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
654 if ((ULONGLONG)CurrentVa >= (ULONGLONG)mdl_start_va && (ULONGLONG)CurrentVa < (ULONGLONG)mdl_start_va + mdl_byte_count)
655 {
656 active = TRUE;
657 mdl_byte_count -= (ULONG)((ULONGLONG)CurrentVa - (ULONGLONG)mdl_start_va);
658 mdl_start_va = CurrentVa;
659 }
660 if (active)
661 {
662 if (((ULONGLONG)mdl_start_va & (alignment - 1)) || (mdl_byte_count & (alignment - 1)))
663 map_type = MAP_TYPE_REMAPPED;
664 remapped_bytes += mdl_byte_count;
665 }
666 }
667 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(NULL, remapped_bytes);
668 }
669 else
670 {
671 map_type = MAP_TYPE_MDL;
672 }
673 }
674 }
675 else
676 {
677 map_type = MAP_TYPE_MDL;
678 }
679 if (map_type == MAP_TYPE_MDL)
680 {
681 for (curr_mdl = Mdl, sglist->NumberOfElements = 0, active = FALSE; curr_mdl; curr_mdl = curr_mdl->Next)
682 {
683 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
684 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
685 if ((ULONGLONG)CurrentVa >= (ULONGLONG)mdl_start_va && (ULONGLONG)CurrentVa < (ULONGLONG)mdl_start_va + mdl_byte_count)
686 {
687 active = TRUE;
688 mdl_byte_count -= (ULONG)((ULONGLONG)CurrentVa - (ULONGLONG)mdl_start_va);
689 mdl_start_va = CurrentVa;
690 }
691 if (active)
692 {
693 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
694 MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
695 }
696 }
697 }
698 if (ScatterGatherBufferLength < FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
699 sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t))
700 {
701 //KdPrint((__DRIVER_NAME " STATUS_BUFFER_TOO_SMALL (%d < %d)\n", ScatterGatherBufferLength, FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
702 // sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t)));
703 return STATUS_BUFFER_TOO_SMALL;
704 }
706 sg_extra = (sg_extra_t *)((PUCHAR)sglist + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
707 (sizeof(SCATTER_GATHER_ELEMENT)) * sglist->NumberOfElements);
709 sg_extra->allocated_by_me = allocated_by_me;
711 sg_extra->map_type = map_type;
712 switch (map_type)
713 {
714 case MAP_TYPE_MDL:
715 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL - %p\n", MmGetMdlVirtualAddress(Mdl)));
716 total_remaining = Length;
717 for (sg_element = 0, curr_mdl = Mdl, active = FALSE; curr_mdl; curr_mdl = curr_mdl->Next)
718 {
719 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
720 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
721 if ((ULONGLONG)CurrentVa >= (ULONGLONG)mdl_start_va && (ULONGLONG)CurrentVa < (ULONGLONG)mdl_start_va + mdl_byte_count)
722 {
723 active = TRUE;
724 mdl_byte_count -= (ULONG)((ULONGLONG)CurrentVa - (ULONGLONG)mdl_start_va);
725 mdl_start_va = CurrentVa;
726 }
727 if (active)
728 {
729 ULONG pfn_offset;
730 remaining = mdl_byte_count;
731 offset = (ULONG)((ULONGLONG)mdl_start_va & (PAGE_SIZE - 1));
732 pfn_offset = (ULONG)(((ULONGLONG)mdl_start_va >> PAGE_SHIFT) - ((ULONGLONG)MmGetMdlVirtualAddress(curr_mdl) >> PAGE_SHIFT));
733 for (i = 0; i < ADDRESS_AND_SIZE_TO_SPAN_PAGES(mdl_start_va, mdl_byte_count); i++)
734 {
735 pfn = MmGetMdlPfnArray(curr_mdl)[pfn_offset + i];
736 ASSERT(pfn);
737 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
738 ASSERT(gref != INVALID_GRANT_REF);
739 sglist->Elements[sg_element].Address.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | offset;
740 sglist->Elements[sg_element].Length = min(min(PAGE_SIZE - offset, remaining), total_remaining);
741 total_remaining -= sglist->Elements[sg_element].Length;
742 remaining -= sglist->Elements[sg_element].Length;
743 offset = 0;
744 sg_element++;
745 }
746 }
747 }
748 break;
749 case MAP_TYPE_REMAPPED:
750 sg_extra->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, max(remapped_bytes, PAGE_SIZE), XENPCI_POOL_TAG);
751 if (!sg_extra->aligned_buffer)
752 {
753 KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED buffer allocation failed - requested va = %p, length = %d\n", MmGetMdlVirtualAddress(Mdl), remapped_bytes));
754 return STATUS_INSUFFICIENT_RESOURCES;
755 }
756 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED - %p -> %p\n", MmGetMdlVirtualAddress(Mdl), sg_extra->aligned_buffer));
757 sg_extra->mdl = Mdl;
758 sg_extra->currentva = CurrentVa;
759 sg_extra->copy_length = remapped_bytes;
761 if (WriteToDevice)
762 {
763 for (curr_mdl = Mdl, offset = 0, active = FALSE; curr_mdl; curr_mdl = curr_mdl->Next)
764 {
765 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
766 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
767 mdl_offset = 0;
768 if ((ULONGLONG)CurrentVa >= (ULONGLONG)mdl_start_va && (ULONGLONG)CurrentVa < (ULONGLONG)mdl_start_va + mdl_byte_count)
769 {
770 active = TRUE;
771 mdl_byte_count -= (ULONG)((ULONGLONG)CurrentVa - (ULONGLONG)mdl_start_va);
772 mdl_offset = (ULONG)((ULONGLONG)CurrentVa - (ULONGLONG)mdl_start_va);
773 mdl_start_va = CurrentVa;
774 }
775 if (active)
776 {
777 PVOID unaligned_buffer;
778 unaligned_buffer = (PUCHAR)MmGetSystemAddressForMdlSafe(curr_mdl, NormalPagePriority);
779 ASSERT(unaligned_buffer); /* lazy */
780 memcpy((PUCHAR)sg_extra->aligned_buffer + offset, (PUCHAR)unaligned_buffer + mdl_offset, mdl_byte_count);
781 offset += mdl_byte_count;
782 }
783 }
784 }
785 for (sg_element = 0, remaining = remapped_bytes;
786 sg_element < ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_extra->aligned_buffer, remapped_bytes); sg_element++)
787 {
788 pfn = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)sg_extra->aligned_buffer + (sg_element << PAGE_SHIFT)).QuadPart >> PAGE_SHIFT);
789 ASSERT(pfn);
790 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
791 ASSERT(gref != INVALID_GRANT_REF);
792 sglist->Elements[sg_element].Address.QuadPart = (ULONGLONG)gref << PAGE_SHIFT;
793 sglist->Elements[sg_element].Length = min(PAGE_SIZE, remaining);
794 remaining -= sglist->Elements[sg_element].Length;
795 }
796 break;
797 case MAP_TYPE_VIRTUAL:
798 ptr = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
799 ASSERT(ptr); /* lazy */
800 sglist->Elements[0].Address.QuadPart = (ULONGLONG)ptr;
801 sglist->Elements[0].Length = Length;
802 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL - %08x\n", sglist->Elements[0].Address.LowPart));
803 break;
804 default:
805 KdPrint((__DRIVER_NAME " map_type = %d\n", map_type));
806 break;
807 }
808 //FUNCTION_EXIT();
809 return STATUS_SUCCESS;
810 }
812 static NTSTATUS
813 XenPci_DOP_BuildScatterGatherList(
814 IN PDMA_ADAPTER DmaAdapter,
815 IN PDEVICE_OBJECT DeviceObject,
816 IN PMDL Mdl,
817 IN PVOID CurrentVa,
818 IN ULONG Length,
819 IN PDRIVER_LIST_CONTROL ExecutionRoutine,
820 IN PVOID Context,
821 IN BOOLEAN WriteToDevice,
822 IN PVOID ScatterGatherBuffer,
823 IN ULONG ScatterGatherBufferLength)
824 {
825 NTSTATUS status;
827 status = XenPci_DOP_BuildScatterGatherListButDontExecute(DmaAdapter, DeviceObject, Mdl, CurrentVa, Length, WriteToDevice, ScatterGatherBuffer, ScatterGatherBufferLength, FALSE);
829 if (NT_SUCCESS(status))
830 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, ScatterGatherBuffer, Context);
832 //FUNCTION_EXIT();
834 return status;
835 }
837 static NTSTATUS
838 XenPci_DOP_GetScatterGatherList(
839 PDMA_ADAPTER DmaAdapter,
840 PDEVICE_OBJECT DeviceObject,
841 PMDL Mdl,
842 PVOID CurrentVa,
843 ULONG Length,
844 PDRIVER_LIST_CONTROL ExecutionRoutine,
845 PVOID Context,
846 BOOLEAN WriteToDevice)
847 {
848 NTSTATUS status;
849 ULONG list_size;
850 ULONG map_registers;
851 PSCATTER_GATHER_LIST sg_list;
853 //FUNCTION_ENTER();
855 status = XenPci_DOP_CalculateScatterGatherList(DmaAdapter, Mdl, CurrentVa, Length, &list_size, &map_registers);
856 if (!NT_SUCCESS(status))
857 {
858 //FUNCTION_EXIT();
859 return status;
860 }
862 sg_list = ExAllocatePoolWithTag(NonPagedPool, list_size, XENPCI_POOL_TAG);
863 if (!sg_list)
864 {
865 KdPrint((__DRIVER_NAME " Cannot allocate memory for sg_list\n"));
866 //FUNCTION_EXIT();
867 return STATUS_INSUFFICIENT_RESOURCES;
868 }
870 status = XenPci_DOP_BuildScatterGatherListButDontExecute(DmaAdapter, DeviceObject, Mdl, CurrentVa, Length, WriteToDevice, sg_list, list_size, TRUE);
872 if (NT_SUCCESS(status))
873 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, sg_list, Context);
875 //FUNCTION_EXIT();
877 return status;
878 }
880 static NTSTATUS
881 XenPci_DOP_BuildMdlFromScatterGatherList(
882 PDMA_ADAPTER DmaAdapter,
883 PSCATTER_GATHER_LIST ScatterGather,
884 PMDL OriginalMdl,
885 PMDL *TargetMdl)
886 {
887 NTSTATUS status = STATUS_SUCCESS;
888 UNREFERENCED_PARAMETER(DmaAdapter);
889 UNREFERENCED_PARAMETER(ScatterGather);
890 UNREFERENCED_PARAMETER(OriginalMdl);
891 UNREFERENCED_PARAMETER(TargetMdl);
893 FUNCTION_ENTER();
895 if (OriginalMdl)
896 {
897 *TargetMdl = OriginalMdl;
898 }
899 else
900 {
901 *TargetMdl = NULL;
902 status = STATUS_INVALID_PARAMETER;
903 }
905 FUNCTION_EXIT();
907 return status;
908 }
910 static PDMA_ADAPTER
911 XenPci_BIS_GetDmaAdapter(PVOID context, PDEVICE_DESCRIPTION device_description, PULONG number_of_map_registers)
912 {
913 xen_dma_adapter_t *xen_dma_adapter;
914 PDEVICE_OBJECT curr, prev;
915 PDRIVER_OBJECT fdo_driver_object;
916 PVOID fdo_driver_extension;
918 UNREFERENCED_PARAMETER(device_description);
920 FUNCTION_ENTER();
922 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
923 KdPrint((__DRIVER_NAME " Device Description = %p:\n", device_description));
924 KdPrint((__DRIVER_NAME " Version = %d\n", device_description->Version));
925 KdPrint((__DRIVER_NAME " Master = %d\n", device_description->Master));
926 KdPrint((__DRIVER_NAME " ScatterGather = %d\n", device_description->ScatterGather));
927 KdPrint((__DRIVER_NAME " DemandMode = %d\n", device_description->DemandMode));
928 KdPrint((__DRIVER_NAME " AutoInitialize = %d\n", device_description->AutoInitialize));
929 KdPrint((__DRIVER_NAME " Dma32BitAddresses = %d\n", device_description->Dma32BitAddresses));
930 KdPrint((__DRIVER_NAME " IgnoreCount = %d\n", device_description->IgnoreCount));
931 KdPrint((__DRIVER_NAME " Dma64BitAddresses = %d\n", device_description->Dma64BitAddresses));
932 KdPrint((__DRIVER_NAME " BusNumber = %d\n", device_description->BusNumber));
933 KdPrint((__DRIVER_NAME " DmaChannel = %d\n", device_description->DmaChannel));
934 KdPrint((__DRIVER_NAME " InterfaceType = %d\n", device_description->InterfaceType));
935 KdPrint((__DRIVER_NAME " DmaWidth = %d\n", device_description->DmaWidth));
936 KdPrint((__DRIVER_NAME " DmaSpeed = %d\n", device_description->DmaSpeed));
937 KdPrint((__DRIVER_NAME " MaximumLength = %d\n", device_description->MaximumLength));
938 KdPrint((__DRIVER_NAME " DmaPort = %d\n", device_description->DmaPort));
940 if (!device_description->Master)
941 return NULL;
942 /*
943 we have to allocate PAGE_SIZE bytes here because Windows thinks this is
944 actually an ADAPTER_OBJECT, and then the verifier crashes because
945 Windows accessed beyond the end of the structure :(
946 */
947 xen_dma_adapter = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
948 ASSERT(xen_dma_adapter);
949 RtlZeroMemory(xen_dma_adapter, PAGE_SIZE);
951 switch(device_description->Version)
952 {
953 case DEVICE_DESCRIPTION_VERSION1:
954 xen_dma_adapter->adapter_object.DmaHeader.Version = 1;
955 break;
956 case DEVICE_DESCRIPTION_VERSION: /* ignore what the docs say here - DEVICE_DESCRIPTION_VERSION appears to mean the latest version */
957 case DEVICE_DESCRIPTION_VERSION2:
958 xen_dma_adapter->adapter_object.DmaHeader.Version = 2;
959 break;
960 default:
961 KdPrint((__DRIVER_NAME " Unsupported device description version %d\n", device_description->Version));
962 ExFreePoolWithTag(xen_dma_adapter, XENPCI_POOL_TAG);
963 return NULL;
964 }
966 xen_dma_adapter->xppdd = context;
967 xen_dma_adapter->dma_extension = NULL;
969 KdPrint((__DRIVER_NAME " About to call IoGetAttachedDeviceReference\n"));
970 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(xen_dma_adapter->xppdd->wdf_device));
971 KdPrint((__DRIVER_NAME " Before start of loop - curr = %p\n", curr));
972 while (curr != NULL)
973 {
974 fdo_driver_object = curr->DriverObject;
975 if (fdo_driver_object)
976 {
977 ObReferenceObject(fdo_driver_object);
978 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC));
979 if (fdo_driver_extension)
980 {
981 xen_dma_adapter->dma_extension_driver = fdo_driver_object; /* so we can dereference it on putdmaadapter */
982 xen_dma_adapter->dma_extension = (dma_driver_extension_t *)fdo_driver_extension;
983 ObDereferenceObject(curr);
984 break;
985 }
986 else
987 {
988 ObDereferenceObject(fdo_driver_object);
989 }
990 }
991 prev = curr;
992 curr = IoGetLowerDeviceObject(curr);
993 ObDereferenceObject(prev);
994 }
995 KdPrint((__DRIVER_NAME " End of loop\n"));
997 xen_dma_adapter->adapter_object.DmaHeader.Size = sizeof(X_ADAPTER_OBJECT); //xen_dma_adapter_t);
998 xen_dma_adapter->adapter_object.MasterAdapter = NULL;
999 if (xen_dma_adapter->dma_extension && xen_dma_adapter->dma_extension->max_sg_elements)
1001 xen_dma_adapter->adapter_object.MapRegistersPerChannel = xen_dma_adapter->dma_extension->max_sg_elements;
1003 else
1005 xen_dma_adapter->adapter_object.MapRegistersPerChannel = 256;
1007 xen_dma_adapter->adapter_object.AdapterBaseVa = NULL;
1008 xen_dma_adapter->adapter_object.MapRegisterBase = NULL;
1009 xen_dma_adapter->adapter_object.NumberOfMapRegisters = 0;
1010 xen_dma_adapter->adapter_object.CommittedMapRegisters = 0;
1011 xen_dma_adapter->adapter_object.CurrentWcb = NULL;
1012 KeInitializeDeviceQueue(&xen_dma_adapter->adapter_object.ChannelWaitQueue);
1013 xen_dma_adapter->adapter_object.RegisterWaitQueue = NULL;
1014 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterQueue);
1015 KeInitializeSpinLock(&xen_dma_adapter->adapter_object.SpinLock);
1016 xen_dma_adapter->adapter_object.MapRegisters = NULL;
1017 xen_dma_adapter->adapter_object.PagePort = NULL;
1018 xen_dma_adapter->adapter_object.ChannelNumber = 0xff;
1019 xen_dma_adapter->adapter_object.AdapterNumber = 0;
1020 xen_dma_adapter->adapter_object.DmaPortAddress = 0;
1021 xen_dma_adapter->adapter_object.AdapterMode = 0;
1022 xen_dma_adapter->adapter_object.NeedsMapRegisters = FALSE; /* when true this causes a crash in the crash dump path */
1023 xen_dma_adapter->adapter_object.MasterDevice = 1;
1024 xen_dma_adapter->adapter_object.Width16Bits = 0;
1025 xen_dma_adapter->adapter_object.ScatterGather = device_description->ScatterGather;
1026 xen_dma_adapter->adapter_object.IgnoreCount = device_description->IgnoreCount;
1027 xen_dma_adapter->adapter_object.Dma32BitAddresses = device_description->Dma32BitAddresses;
1028 xen_dma_adapter->adapter_object.Dma64BitAddresses = device_description->Dma64BitAddresses;
1029 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterList);
1031 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DMA_OPERATIONS), XENPCI_POOL_TAG);
1032 ASSERT(xen_dma_adapter->adapter_object.DmaHeader.DmaOperations);
1033 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 1)
1035 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = FIELD_OFFSET(DMA_OPERATIONS, CalculateScatterGatherList);
1037 else
1039 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = sizeof(DMA_OPERATIONS);
1041 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutDmaAdapter = XenPci_DOP_PutDmaAdapter;
1042 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateCommonBuffer = XenPci_DOP_AllocateCommonBuffer;
1043 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeCommonBuffer = XenPci_DOP_FreeCommonBuffer;
1044 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateAdapterChannel = XenPci_DOP_AllocateAdapterChannel;
1045 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FlushAdapterBuffers = XenPci_DOP_FlushAdapterBuffers;
1046 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeAdapterChannel = XenPci_DOP_FreeAdapterChannel;
1047 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeMapRegisters = XenPci_DOP_FreeMapRegisters;
1048 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->MapTransfer = XenPci_DOP_MapTransfer;
1049 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetDmaAlignment = XenPci_DOP_GetDmaAlignment;
1050 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->ReadDmaCounter = XenPci_DOP_ReadDmaCounter;
1051 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetScatterGatherList = XenPci_DOP_GetScatterGatherList;
1052 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutScatterGatherList = XenPci_DOP_PutScatterGatherList;
1053 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 2)
1055 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->CalculateScatterGatherList = XenPci_DOP_CalculateScatterGatherList;
1056 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildScatterGatherList = XenPci_DOP_BuildScatterGatherList;
1057 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildMdlFromScatterGatherList = XenPci_DOP_BuildMdlFromScatterGatherList;
1060 *number_of_map_registers = xen_dma_adapter->adapter_object.MapRegistersPerChannel; //1024; /* why not... */
1062 FUNCTION_EXIT();
1064 return &xen_dma_adapter->adapter_object.DmaHeader;
1067 static ULONG
1068 XenPci_BIS_SetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
1070 UNREFERENCED_PARAMETER(context);
1071 UNREFERENCED_PARAMETER(data_type);
1072 UNREFERENCED_PARAMETER(buffer);
1073 UNREFERENCED_PARAMETER(offset);
1074 UNREFERENCED_PARAMETER(length);
1076 FUNCTION_ENTER();
1077 FUNCTION_EXIT();
1078 return 0;
1081 static ULONG
1082 XenPci_BIS_GetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
1084 UNREFERENCED_PARAMETER(context);
1085 UNREFERENCED_PARAMETER(data_type);
1086 UNREFERENCED_PARAMETER(buffer);
1087 UNREFERENCED_PARAMETER(offset);
1088 UNREFERENCED_PARAMETER(length);
1090 FUNCTION_ENTER();
1091 FUNCTION_EXIT();
1092 return 0;
1095 /*
1096 Called at PASSIVE_LEVEL(?)
1097 Called during restore
1098 */
1100 static ULONG
1101 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
1103 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1104 char path[128];
1105 char *value;
1106 char *err;
1107 ULONG backend_state;
1109 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1110 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
1111 if (err)
1113 XenPci_FreeMem(err);
1114 return XenbusStateUnknown;
1116 else
1118 backend_state = atoi(value);
1119 XenPci_FreeMem(value);
1120 return backend_state;
1124 static VOID
1125 XenPci_BackEndStateHandler(char *path, PVOID context)
1127 WDFDEVICE device = context;
1128 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1129 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1130 ULONG new_backend_state;
1132 #if !DBG
1133 UNREFERENCED_PARAMETER(path);
1134 #endif
1136 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1138 /* check that path == device/id/state */
1139 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
1140 new_backend_state = XenPci_ReadBackendState(xppdd);
1141 if (new_backend_state == XenbusStateUnknown)
1143 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
1144 return;
1145 KdPrint(("Failed to read %s, assuming closed\n", path));
1146 new_backend_state = XenbusStateClosed;
1149 if (xppdd->backend_state == new_backend_state)
1151 KdPrint((__DRIVER_NAME " state unchanged\n"));
1152 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1153 return;
1156 xppdd->backend_state = new_backend_state;
1158 switch (xppdd->backend_state)
1160 case XenbusStateUnknown:
1161 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown (%s)\n", path));
1162 break;
1164 case XenbusStateInitialising:
1165 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising (%s)\n", path));
1166 break;
1168 case XenbusStateInitWait:
1169 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait (%s)\n", path));
1170 break;
1172 case XenbusStateInitialised:
1173 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised (%s)\n", path));
1174 break;
1176 case XenbusStateConnected:
1177 KdPrint((__DRIVER_NAME " Backend State Changed to Connected (%s)\n", path));
1178 break;
1180 case XenbusStateClosing:
1181 KdPrint((__DRIVER_NAME " Backend State Changed to Closing (%s)\n", path));
1182 if (xppdd->frontend_state == XenbusStateConnected)
1184 KdPrint((__DRIVER_NAME " Requesting eject\n"));
1185 WdfPdoRequestEject(device);
1187 break;
1189 case XenbusStateClosed:
1190 KdPrint((__DRIVER_NAME " Backend State Changed to Closed (%s)\n", path));
1191 break;
1193 default:
1194 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d (%s)\n", xppdd->backend_state, path));
1195 break;
1198 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
1200 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1202 return;
1205 static NTSTATUS
1206 XenPci_GetBackendAndAddWatch(WDFDEVICE device)
1208 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1209 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1210 char path[128];
1211 PCHAR res;
1212 PCHAR value;
1214 /* Get backend path */
1215 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
1216 "%s/backend", xppdd->path);
1217 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
1218 if (res)
1220 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
1221 XenPci_FreeMem(res);
1222 return STATUS_UNSUCCESSFUL;
1224 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
1225 XenPci_FreeMem(value);
1227 /* Add watch on backend state */
1228 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1229 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
1231 return STATUS_SUCCESS;
1234 static NTSTATUS
1235 XenConfig_InitConfigPage(WDFDEVICE device)
1237 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1238 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
1239 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
1240 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
1241 PUCHAR ptr;
1242 PDEVICE_OBJECT curr, prev;
1243 PDRIVER_OBJECT fdo_driver_object;
1244 PUCHAR fdo_driver_extension;
1246 FUNCTION_ENTER();
1248 ptr = MmGetMdlVirtualAddress(xppdd->config_page_mdl);
1249 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(device));
1250 //curr = WdfDeviceWdmGetAttachedDevice(device);
1251 while (curr != NULL)
1253 fdo_driver_object = curr->DriverObject;
1254 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
1255 if (fdo_driver_object)
1257 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
1258 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
1259 if (fdo_driver_extension)
1261 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
1262 ObDereferenceObject(curr);
1263 break;
1266 prev = curr;
1267 curr = IoGetLowerDeviceObject(curr);
1268 ObDereferenceObject(prev);
1271 FUNCTION_EXIT();
1273 return STATUS_SUCCESS;
1276 static NTSTATUS
1277 XenPci_EvtChn_Bind(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
1279 WDFDEVICE device = context;
1280 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1281 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1283 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext);
1286 static NTSTATUS
1287 XenPci_EvtChn_BindDpc(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
1289 WDFDEVICE device = context;
1290 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1291 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1293 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext);
1296 static NTSTATUS
1297 XenPci_EvtChn_Unbind(PVOID context, evtchn_port_t Port)
1299 WDFDEVICE device = context;
1300 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1301 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1303 return EvtChn_Unbind(xpdd, Port);
1306 static NTSTATUS
1307 XenPci_EvtChn_Mask(PVOID context, evtchn_port_t Port)
1309 WDFDEVICE device = context;
1310 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1311 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1313 return EvtChn_Mask(xpdd, Port);
1316 static NTSTATUS
1317 XenPci_EvtChn_Unmask(PVOID context, evtchn_port_t Port)
1319 WDFDEVICE device = context;
1320 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1321 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1323 return EvtChn_Unmask(xpdd, Port);
1326 static NTSTATUS
1327 XenPci_EvtChn_Notify(PVOID context, evtchn_port_t Port)
1329 WDFDEVICE device = context;
1330 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1331 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1333 return EvtChn_Notify(xpdd, Port);
1336 static BOOLEAN
1337 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port, BOOLEAN *last_interrupt)
1339 WDFDEVICE device = context;
1340 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1341 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1343 return EvtChn_AckEvent(xpdd, port, last_interrupt);
1346 typedef struct {
1347 PXEN_EVTCHN_SYNC_ROUTINE sync_routine;
1348 PVOID sync_context;
1349 } sync_context_t;
1351 static BOOLEAN
1352 XenPci_EvtChn_Sync_Routine(WDFINTERRUPT interrupt, WDFCONTEXT context)
1354 sync_context_t *wdf_sync_context = context;
1355 UNREFERENCED_PARAMETER(interrupt);
1356 return wdf_sync_context->sync_routine(wdf_sync_context->sync_context);
1359 static BOOLEAN
1360 XenPci_EvtChn_Sync(PVOID context, PXEN_EVTCHN_SYNC_ROUTINE sync_routine, PVOID sync_context)
1362 WDFDEVICE device = context;
1363 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1364 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1365 sync_context_t wdf_sync_context;
1367 wdf_sync_context.sync_routine = sync_routine;
1368 wdf_sync_context.sync_context = sync_context;
1370 return WdfInterruptSynchronize(xpdd->interrupt, XenPci_EvtChn_Sync_Routine, &wdf_sync_context);
1373 static grant_ref_t
1374 XenPci_GntTbl_GrantAccess(PVOID context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref)
1376 WDFDEVICE device = context;
1377 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1378 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1380 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref);
1383 static BOOLEAN
1384 XenPci_GntTbl_EndAccess(PVOID context, grant_ref_t ref, BOOLEAN keepref)
1386 WDFDEVICE device = context;
1387 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1388 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1390 return GntTbl_EndAccess(xpdd, ref, keepref);
1393 static VOID
1394 XenPci_GntTbl_PutRef(PVOID context, grant_ref_t ref)
1396 WDFDEVICE device = context;
1397 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1398 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1400 GntTbl_PutRef(xpdd, ref);
1403 static grant_ref_t
1404 XenPci_GntTbl_GetRef(PVOID context)
1406 WDFDEVICE device = context;
1407 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1408 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1410 return GntTbl_GetRef(xpdd);
1413 PCHAR
1414 XenPci_XenBus_Read(PVOID context, xenbus_transaction_t xbt, char *path, char **value)
1416 WDFDEVICE device = context;
1417 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1418 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1419 return XenBus_Read(xpdd, xbt, path, value);
1422 PCHAR
1423 XenPci_XenBus_Write(PVOID context, xenbus_transaction_t xbt, char *path, char *value)
1425 WDFDEVICE device = context;
1426 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1427 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1428 return XenBus_Write(xpdd, xbt, path, value);
1431 PCHAR
1432 XenPci_XenBus_Printf(PVOID context, xenbus_transaction_t xbt, char *path, char *fmt, ...)
1434 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
1435 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
1436 //return XenBus_Printf(xpdd, xbt, path, value);
1437 UNREFERENCED_PARAMETER(context);
1438 UNREFERENCED_PARAMETER(xbt);
1439 UNREFERENCED_PARAMETER(path);
1440 UNREFERENCED_PARAMETER(fmt);
1441 return NULL;
1444 PCHAR
1445 XenPci_XenBus_StartTransaction(PVOID context, xenbus_transaction_t *xbt)
1447 WDFDEVICE device = context;
1448 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1449 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1450 return XenBus_StartTransaction(xpdd, xbt);
1453 PCHAR
1454 XenPci_XenBus_EndTransaction(PVOID context, xenbus_transaction_t xbt, int abort, int *retry)
1456 WDFDEVICE device = context;
1457 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1458 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1459 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
1462 PCHAR
1463 XenPci_XenBus_List(PVOID context, xenbus_transaction_t xbt, char *prefix, char ***contents)
1465 WDFDEVICE device = context;
1466 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1467 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1468 return XenBus_List(xpdd, xbt, prefix, contents);
1471 PCHAR
1472 XenPci_XenBus_AddWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
1474 WDFDEVICE device = context;
1475 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1476 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1477 PCHAR retval;
1479 FUNCTION_ENTER();
1480 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
1481 if (retval == NULL)
1483 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
1485 else
1487 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
1489 FUNCTION_EXIT();
1490 return retval;
1493 PCHAR
1494 XenPci_XenBus_RemWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
1496 WDFDEVICE device = context;
1497 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1498 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1499 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
1502 /*
1503 Called at PASSIVE_LEVEL
1504 Called during restore
1505 */
1507 static NTSTATUS
1508 XenPci_ChangeFrontendState(WDFDEVICE device, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
1510 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1511 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1512 LARGE_INTEGER timeout;
1513 ULONG remaining;
1514 ULONG thiswait;
1515 char path[128];
1517 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1519 xppdd->frontend_state = frontend_state_set;
1521 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
1522 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
1524 remaining = maximum_wait_ms;
1526 while (xppdd->backend_state != backend_state_response)
1528 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
1529 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
1530 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
1532 remaining -= thiswait;
1533 if (remaining == 0)
1535 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
1536 return STATUS_UNSUCCESSFUL;
1538 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
1541 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1542 return STATUS_SUCCESS;
1545 static NTSTATUS
1546 XenPci_XenConfigDevice(WDFDEVICE device);
1548 static NTSTATUS
1549 XenPci_XenShutdownDevice(PVOID context)
1551 WDFDEVICE device = context;
1552 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1553 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1554 PUCHAR in_ptr;
1555 ULONG i;
1556 UCHAR type;
1557 PVOID setting;
1558 PVOID value;
1559 PVOID value2;
1561 FUNCTION_ENTER();
1563 if (xppdd->backend_state == XenbusStateConnected)
1565 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
1566 if (xppdd->backend_state == XenbusStateClosing)
1567 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
1568 if (xppdd->backend_state == XenbusStateClosed)
1569 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
1571 else
1573 if (xppdd->backend_state == XenbusStateClosing)
1574 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
1577 if (xppdd->assigned_resources_start != NULL)
1579 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1580 in_ptr = xppdd->assigned_resources_start;
1581 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
1583 switch (type)
1585 case XEN_INIT_TYPE_RING: /* frontend ring */
1586 FreePages(value);
1587 break;
1588 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
1589 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
1590 EvtChn_Unbind(xpdd, PtrToUlong(value));
1591 EvtChn_Close(xpdd, PtrToUlong(value));
1592 break;
1593 case XEN_INIT_TYPE_GRANT_ENTRIES:
1594 for (i = 0; i < PtrToUlong(setting); i++)
1595 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value)[i], FALSE);
1596 break;
1599 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
1600 xppdd->assigned_resources_start = NULL;
1603 FUNCTION_EXIT();
1605 return STATUS_SUCCESS;
1608 struct dummy_sring {
1609 RING_IDX req_prod, req_event;
1610 RING_IDX rsp_prod, rsp_event;
1611 uint8_t pad[48];
1612 };
1614 static NTSTATUS
1615 XenPci_XenConfigDeviceSpecifyBuffers(WDFDEVICE device, PUCHAR src, PUCHAR dst)
1617 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1618 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1619 NTSTATUS status = STATUS_SUCCESS;
1620 ULONG i;
1621 char path[128];
1622 PCHAR setting, value;
1623 PCHAR res;
1624 PVOID address;
1625 UCHAR type;
1626 PUCHAR in_ptr;
1627 PUCHAR out_ptr;
1628 XENPCI_VECTORS vectors;
1629 ULONG event_channel;
1630 ULONG run_type = 0;
1631 PMDL ring;
1632 grant_ref_t gref;
1633 BOOLEAN done_xenbus_init = FALSE;
1634 PVOID value2;
1635 BOOLEAN active = TRUE;
1636 BOOLEAN dont_config = FALSE;
1638 FUNCTION_ENTER();
1640 in_ptr = src;
1641 out_ptr = dst;
1643 // always add vectors
1644 vectors.magic = XEN_DATA_MAGIC;
1645 vectors.length = sizeof(XENPCI_VECTORS);
1646 vectors.context = device;
1647 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
1648 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
1649 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
1650 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
1651 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
1652 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
1653 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
1654 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
1655 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
1656 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
1657 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
1658 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
1659 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
1660 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
1661 strncpy(vectors.path, xppdd->path, 128);
1662 strncpy(vectors.backend_path, xppdd->backend_path, 128);
1663 //vectors.pdo_event_channel = xpdd->pdo_event_channel;
1664 vectors.XenBus_Read = XenPci_XenBus_Read;
1665 vectors.XenBus_Write = XenPci_XenBus_Write;
1666 vectors.XenBus_Printf = XenPci_XenBus_Printf;
1667 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
1668 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
1669 vectors.XenBus_List = XenPci_XenBus_List;
1670 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
1671 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
1673 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
1675 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
1676 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
1679 if (!qemu_filtered)
1680 active = FALSE;
1682 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
1684 BOOLEAN condition;
1685 PCHAR xb_value;
1686 switch (type)
1688 case XEN_INIT_TYPE_MATCH_FRONT:
1689 case XEN_INIT_TYPE_MATCH_BACK:
1690 if (type == XEN_INIT_TYPE_MATCH_FRONT)
1692 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1694 else
1696 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
1698 KdPrint((__DRIVER_NAME " testing path = %s\n", path));
1699 res = XenBus_Read(xpdd, XBT_NIL, path, &xb_value);
1700 if (res)
1702 KdPrint((__DRIVER_NAME " read failed (%s)\n", res));
1703 XenPci_FreeMem(res);
1705 else
1707 KdPrint((__DRIVER_NAME " testing %s vs %s\n", xb_value, value));
1708 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_IF_MATCH)
1709 condition = (strcmp(xb_value, value) == 0)?TRUE:FALSE;
1710 else
1711 condition = (strcmp(xb_value, value) != 0)?TRUE:FALSE;
1712 KdPrint((__DRIVER_NAME " condition = %d\n", condition));
1714 if ((PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_ONLY_IF_QEMU_HIDE) && qemu_protocol_version && condition)
1715 condition = FALSE;
1717 if (condition)
1719 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_SET_INACTIVE)
1721 active = FALSE;
1722 KdPrint((__DRIVER_NAME " set inactive\n"));
1724 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_DONT_CONFIG)
1726 dont_config = TRUE;
1727 KdPrint((__DRIVER_NAME " set inactive with dont config\n"));
1730 XenPci_FreeMem(xb_value);
1732 break;
1735 if (dont_config)
1737 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1738 FUNCTION_EXIT();
1739 return status;
1742 // first pass, possibly before state == Connected
1743 in_ptr = src;
1744 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
1747 if (!done_xenbus_init)
1749 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000) != STATUS_SUCCESS)
1751 status = STATUS_UNSUCCESSFUL;
1752 goto error;
1754 done_xenbus_init = TRUE;
1757 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
1759 switch (type)
1761 case XEN_INIT_TYPE_RUN:
1762 run_type++;
1763 break;
1764 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
1765 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
1766 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1767 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
1768 break;
1769 case XEN_INIT_TYPE_RING: /* frontend ring */
1770 /* we only allocate and do the SHARED_RING_INIT here */
1771 if ((ring = AllocatePage()) != 0)
1773 address = MmGetMdlVirtualAddress(ring);
1774 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
1775 SHARED_RING_INIT((struct dummy_sring *)address);
1776 if ((gref = GntTbl_GrantAccess(
1777 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
1779 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1780 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
1781 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
1782 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
1783 // add the grant entry too so it gets freed automatically
1784 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
1785 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
1786 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
1788 else
1790 FreePages(ring);
1791 status = STATUS_UNSUCCESSFUL;
1792 goto error;
1795 else
1797 status = STATUS_UNSUCCESSFUL;
1798 goto error;
1800 break;
1801 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
1802 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
1803 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
1805 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
1806 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1807 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
1808 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
1809 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
1810 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
1812 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
1814 else
1816 #pragma warning(suppress:4055)
1817 EvtChn_Bind(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
1820 else
1822 status = STATUS_UNSUCCESSFUL;
1823 goto error;
1825 break;
1828 if (!NT_SUCCESS(status))
1830 goto error;
1832 // If XEN_INIT_TYPE_RUN was specified more than once then we skip XenbusStateInitialised here and go straight to XenbusStateConnected at the end
1833 if (run_type == 1)
1835 if (XenPci_ChangeFrontendState(device, XenbusStateInitialised, XenbusStateConnected, 2000) != STATUS_SUCCESS)
1837 status = STATUS_UNSUCCESSFUL;
1838 goto error;
1842 // second pass, possibly after state == Connected
1843 in_ptr = src;
1844 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
1846 switch(type)
1848 case XEN_INIT_TYPE_READ_STRING_BACK:
1849 case XEN_INIT_TYPE_READ_STRING_FRONT:
1850 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
1851 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1852 else
1853 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
1854 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
1855 if (res)
1857 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
1858 XenPci_FreeMem(res);
1859 ADD_XEN_INIT_RSP(&out_ptr, type, setting, NULL, NULL);
1861 else
1863 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
1864 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, value2);
1865 XenPci_FreeMem(value);
1867 break;
1868 case XEN_INIT_TYPE_VECTORS:
1869 // this is always done so ignore the request
1870 break;
1871 case XEN_INIT_TYPE_GRANT_ENTRIES:
1872 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
1873 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
1874 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
1875 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
1876 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
1877 for (i = 0; i < PtrToUlong(value); i++)
1879 gref = GntTbl_GetRef(xpdd);
1880 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
1881 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
1883 break;
1886 if (active)
1888 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_ACTIVE, NULL, NULL, NULL);
1890 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1892 if (run_type)
1894 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 2000) != STATUS_SUCCESS)
1896 status = STATUS_UNSUCCESSFUL;
1897 goto error;
1900 FUNCTION_EXIT();
1901 return status;
1903 error:
1904 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000);
1905 FUNCTION_EXIT_STATUS(status);
1906 return status;
1909 static NTSTATUS
1910 XenPci_XenConfigDevice(WDFDEVICE device)
1912 NTSTATUS status;
1913 PUCHAR src, dst;
1914 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1916 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
1917 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
1918 memcpy(src, dst, xppdd->config_page_length);
1920 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
1922 MmUnmapIoSpace(dst, xppdd->config_page_length);
1923 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
1925 return status;
1928 static NTSTATUS
1929 XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp)
1931 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1932 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1933 PIO_STACK_LOCATION stack;
1934 PCM_PARTIAL_RESOURCE_LIST prl;
1935 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
1936 ULONG i;
1937 //char path[128];
1938 //PMDL mdl;
1940 FUNCTION_ENTER();
1941 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
1943 stack = IoGetCurrentIrpStackLocation(irp);
1945 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
1946 for (i = 0; i < prl->Count; i++)
1948 prd = & prl->PartialDescriptors[i];
1949 switch (prd->Type)
1951 case CmResourceTypeMemory:
1952 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
1954 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
1955 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
1957 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
1959 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1960 prd->Type = CmResourceTypeInterrupt;
1961 prd->ShareDisposition = CmResourceShareShared;
1962 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
1963 prd->u.Interrupt.Level = xpdd->irq_number;
1964 prd->u.Interrupt.Vector = xpdd->irq_number;
1965 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
1966 xppdd->irq_number = xpdd->irq_number;
1968 break;
1972 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
1973 for (i = 0; i < prl->Count; i++)
1975 prd = & prl->PartialDescriptors[i];
1976 switch (prd->Type)
1978 case CmResourceTypeMemory:
1979 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
1980 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
1981 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
1983 if (prd->u.Memory.Length == 0)
1985 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0]));
1986 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
1987 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
1988 KdPrint((__DRIVER_NAME " New Start = %08x%08x, Length = %d\n", prd->u.Memory.Start.HighPart, prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
1990 xppdd->config_page_phys = prd->u.Memory.Start;
1991 xppdd->config_page_length = prd->u.Memory.Length;
1992 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
1993 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
1995 #if 0
1996 status = XenPci_XenConfigDevice(device);
1997 if (!NT_SUCCESS(status))
1999 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2000 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
2001 FUNCTION_ERROR_EXIT();
2002 return status;
2004 #endif
2006 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
2008 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
2009 prd->Type = CmResourceTypeInterrupt;
2010 prd->ShareDisposition = CmResourceShareShared;
2011 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
2012 prd->u.Interrupt.Level = xpdd->irq_level;
2013 prd->u.Interrupt.Vector = xpdd->irq_vector;
2014 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
2015 xppdd->irq_vector = xpdd->irq_vector;
2016 xppdd->irq_level = xpdd->irq_level;
2018 break;
2022 IoSkipCurrentIrpStackLocation(irp);
2024 FUNCTION_EXIT();
2026 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
2029 #if 0
2030 static NTSTATUS
2031 XenPciPdo_EvtDeviceResourcesQuery(WDFDEVICE device, WDFCMRESLIST resources)
2034 #endif
2036 static NTSTATUS
2037 XenPciPdo_EvtDeviceResourceRequirementsQuery(WDFDEVICE device, WDFIORESREQLIST requirements_list)
2039 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2040 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2041 WDFIORESLIST res_list;
2042 IO_RESOURCE_DESCRIPTOR ird;
2044 //FUNCTION_ENTER();
2046 WdfIoResourceRequirementsListSetInterfaceType(requirements_list, PNPBus);
2048 WdfIoResourceListCreate(requirements_list, WDF_NO_OBJECT_ATTRIBUTES, &res_list);
2049 ird.Option = 0;
2050 ird.Type = CmResourceTypeMemory;
2051 ird.ShareDisposition = CmResourceShareShared;
2052 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
2053 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
2054 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
2055 ird.u.Memory.Length = 0;
2056 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
2057 WdfIoResourceListAppendDescriptor(res_list, &ird);
2059 ird.Option = 0;
2060 ird.Type = CmResourceTypeMemory;
2061 ird.ShareDisposition = CmResourceShareShared;
2062 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
2063 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
2064 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
2065 ird.u.Memory.Length = 0;
2066 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
2067 WdfIoResourceListAppendDescriptor(res_list, &ird);
2069 WdfIoResourceRequirementsListAppendIoResList(requirements_list, res_list);
2071 //FUNCTION_EXIT();
2073 return STATUS_SUCCESS;
2076 NTSTATUS
2077 XenPciPdo_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
2079 NTSTATUS status = STATUS_SUCCESS;
2080 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2081 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2082 CHAR path[128];
2084 FUNCTION_ENTER();
2086 switch (previous_state)
2088 case WdfPowerDeviceD0:
2089 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
2090 break;
2091 case WdfPowerDeviceD1:
2092 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
2093 break;
2094 case WdfPowerDeviceD2:
2095 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
2096 break;
2097 case WdfPowerDeviceD3:
2098 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
2099 break;
2100 case WdfPowerDeviceD3Final:
2101 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
2102 break;
2103 case WdfPowerDevicePrepareForHibernation:
2104 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
2105 break;
2106 default:
2107 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
2108 break;
2111 if (previous_state == WdfPowerDevicePrepareForHibernation
2112 || (previous_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
2114 KdPrint((__DRIVER_NAME " starting up from hibernation\n"));
2116 else
2120 XenConfig_InitConfigPage(device);
2122 status = XenPci_GetBackendAndAddWatch(device);
2123 if (!NT_SUCCESS(status))
2125 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
2126 FUNCTION_ERROR_EXIT();
2127 return status;
2129 status = XenPci_XenConfigDevice(device);
2130 if (!NT_SUCCESS(status))
2132 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2133 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
2134 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
2135 FUNCTION_ERROR_EXIT();
2136 return status;
2139 FUNCTION_EXIT();
2141 return status;
2144 NTSTATUS
2145 XenPciPdo_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
2147 NTSTATUS status = STATUS_SUCCESS;
2148 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2149 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2150 char path[128];
2152 UNREFERENCED_PARAMETER(device);
2153 UNREFERENCED_PARAMETER(target_state);
2155 FUNCTION_ENTER();
2157 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
2160 switch (target_state)
2162 case WdfPowerDeviceD0:
2163 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
2164 break;
2165 case WdfPowerDeviceD1:
2166 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
2167 break;
2168 case WdfPowerDeviceD2:
2169 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
2170 break;
2171 case WdfPowerDeviceD3:
2172 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
2173 break;
2174 case WdfPowerDeviceD3Final:
2175 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
2176 break;
2177 case WdfPowerDevicePrepareForHibernation:
2178 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
2179 break;
2180 default:
2181 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
2182 break;
2185 if (target_state == WdfPowerDevicePrepareForHibernation
2186 || (target_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
2188 KdPrint((__DRIVER_NAME " not powering down as we are hibernating\n"));
2190 else
2192 status = XenPci_XenShutdownDevice(device);
2193 /* Remove watch on backend state */
2194 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2195 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
2197 FUNCTION_EXIT();
2199 return status;
2202 NTSTATUS
2203 XenPciPdo_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
2205 NTSTATUS status = STATUS_SUCCESS;
2207 UNREFERENCED_PARAMETER(device);
2208 UNREFERENCED_PARAMETER(resources_raw);
2209 UNREFERENCED_PARAMETER(resources_translated);
2211 FUNCTION_ENTER();
2212 FUNCTION_EXIT();
2214 return status;
2217 NTSTATUS
2218 XenPciPdo_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
2220 NTSTATUS status = STATUS_SUCCESS;
2222 UNREFERENCED_PARAMETER(device);
2223 UNREFERENCED_PARAMETER(resources_translated);
2225 FUNCTION_ENTER();
2226 FUNCTION_EXIT();
2228 return status;
2231 static VOID
2232 XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
2234 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2236 FUNCTION_ENTER();
2238 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
2239 switch (notification_type)
2241 case WdfSpecialFilePaging:
2242 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
2243 break;
2244 case WdfSpecialFileHibernation:
2245 xppdd->hiber_usage_kludge = is_in_notification_path;
2246 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
2247 break;
2248 case WdfSpecialFileDump:
2249 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
2250 break;
2251 default:
2252 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
2253 break;
2256 FUNCTION_EXIT();
2259 NTSTATUS
2260 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
2261 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
2262 PWDFDEVICE_INIT child_init)
2264 NTSTATUS status = STATUS_SUCCESS;
2265 WDF_OBJECT_ATTRIBUTES child_attributes;
2266 WDFDEVICE child_device;
2267 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
2268 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
2269 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
2270 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
2271 PXENPCI_PDO_DEVICE_DATA xppdd;
2272 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
2273 WDF_QUERY_INTERFACE_CONFIG interface_config;
2274 BUS_INTERFACE_STANDARD bus_interface;
2275 WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
2276 WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
2277 UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
2278 WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
2280 FUNCTION_ENTER();
2282 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
2284 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
2285 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
2286 //child_pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPciPdo_EvtDeviceD0EntryPostInterruptsEnabled;
2287 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
2288 //child_pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPciPdo_EvtDeviceD0ExitPreInterruptsDisabled;
2289 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenPciPdo_EvtDevicePrepareHardware;
2290 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenPciPdo_EvtDeviceReleaseHardware;
2291 child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
2292 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
2294 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
2295 identification->device, identification->index, identification->path));
2297 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
2298 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
2299 if (!NT_SUCCESS(status))
2301 return status;
2304 WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
2305 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
2306 pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
2307 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
2308 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
2309 WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
2311 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
2312 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
2313 if (!NT_SUCCESS(status))
2315 return status;
2317 status = WdfPdoInitAddHardwareID(child_init, &buffer);
2318 if (!NT_SUCCESS(status))
2320 return status;
2322 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
2323 if (!NT_SUCCESS(status))
2325 return status;
2328 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
2329 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
2330 if (!NT_SUCCESS(status))
2332 return status;
2335 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
2336 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
2337 if (!NT_SUCCESS(status))
2339 return status;
2341 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
2343 WdfDeviceInitSetPowerNotPageable(child_init);
2345 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
2346 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
2347 if (!NT_SUCCESS(status))
2349 return status;
2352 xppdd = GetXppdd(child_device);
2354 xppdd->wdf_device = child_device;
2355 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
2357 xppdd->config_page_mdl = AllocateUncachedPage();
2359 xppdd->device_state.magic = XEN_DEVICE_STATE_MAGIC;
2360 xppdd->device_state.length = sizeof(XENPCI_DEVICE_STATE);
2361 xppdd->device_state.suspend_resume_state_pdo = SR_STATE_RUNNING;
2362 xppdd->device_state.suspend_resume_state_fdo = SR_STATE_RUNNING;
2363 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
2364 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
2365 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
2366 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
2368 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
2369 child_pnp_capabilities.LockSupported = WdfFalse;
2370 child_pnp_capabilities.EjectSupported = WdfTrue;
2371 child_pnp_capabilities.Removable = WdfTrue;
2372 child_pnp_capabilities.DockDevice = WdfFalse;
2373 child_pnp_capabilities.UniqueID = WdfFalse;
2374 child_pnp_capabilities.SilentInstall = WdfTrue;
2375 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
2376 child_pnp_capabilities.HardwareDisabled = WdfFalse;
2377 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
2379 WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
2380 child_power_capabilities.DeviceD1 = WdfTrue;
2381 child_power_capabilities.WakeFromD1 = WdfTrue;
2382 child_power_capabilities.DeviceWake = PowerDeviceD1;
2383 child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
2384 child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
2385 child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
2386 child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
2387 child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
2388 child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
2389 WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
2391 bus_interface.Size = sizeof(BUS_INTERFACE_STANDARD);
2392 bus_interface.Version = 1; //BUS_INTERFACE_STANDARD_VERSION;
2393 bus_interface.Context = xppdd;
2394 bus_interface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
2395 bus_interface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
2396 bus_interface.TranslateBusAddress = XenPci_BIS_TranslateBusAddress;
2397 bus_interface.GetDmaAdapter = XenPci_BIS_GetDmaAdapter;
2398 bus_interface.SetBusData = XenPci_BIS_SetBusData;
2399 bus_interface.GetBusData = XenPci_BIS_GetBusData;
2400 WDF_QUERY_INTERFACE_CONFIG_INIT(&interface_config, (PINTERFACE)&bus_interface, &GUID_BUS_INTERFACE_STANDARD, NULL);
2401 status = WdfDeviceAddQueryInterface(child_device, &interface_config);
2402 if (!NT_SUCCESS(status))
2404 return status;
2407 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
2408 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
2409 xppdd->index = identification->index;
2410 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
2411 xppdd->backend_state = XenbusStateUnknown;
2412 xppdd->frontend_state = XenbusStateUnknown;
2413 xppdd->backend_path[0] = '\0';
2415 FUNCTION_EXIT();
2417 return status;
2420 static __forceinline VOID
2421 XenPci_Pdo_ChangeSuspendState(WDFDEVICE device, ULONG new_state)
2423 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2424 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2426 FUNCTION_ENTER();
2427 KdPrint((__DRIVER_NAME " setting pdo state to %d\n", new_state));
2428 xppdd->device_state.suspend_resume_state_pdo = new_state;
2429 KeMemoryBarrier();
2430 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xpdd->pdo_event_channel));
2431 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
2432 while(xppdd->device_state.suspend_resume_state_fdo != xppdd->device_state.suspend_resume_state_pdo)
2434 KdPrint((__DRIVER_NAME " waiting...\n"));
2435 KeWaitForSingleObject(&xpdd->pdo_suspend_event, Executive, KernelMode, FALSE, NULL);
2437 KdPrint((__DRIVER_NAME " fdo state set to %d\n", new_state));
2438 FUNCTION_EXIT();
2441 /* called at PASSIVE_LEVEL */
2442 NTSTATUS
2443 XenPci_Pdo_Suspend(WDFDEVICE device)
2445 NTSTATUS status = STATUS_SUCCESS;
2446 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2447 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2448 //LARGE_INTEGER wait_time;
2449 char path[128];
2450 PUCHAR in_ptr;
2451 UCHAR type;
2452 PVOID setting;
2453 PVOID value;
2454 PVOID value2;
2456 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
2458 if (xppdd->backend_state == XenbusStateConnected)
2460 xppdd->restart_on_resume = TRUE;
2461 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_SUSPENDING);
2463 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
2464 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
2465 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
2467 if (xppdd->assigned_resources_start != NULL)
2469 in_ptr = xppdd->assigned_resources_ptr;
2470 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
2471 in_ptr = xppdd->assigned_resources_start;
2472 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
2474 switch (type)
2476 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
2477 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
2478 EvtChn_Unbind(xpdd, PtrToUlong(value));
2479 EvtChn_Close(xpdd, PtrToUlong(value));
2480 break;
2485 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2486 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
2488 else
2490 xppdd->restart_on_resume = FALSE;
2493 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
2495 return status;
2498 NTSTATUS
2499 XenPci_Pdo_Resume(WDFDEVICE device)
2501 NTSTATUS status = STATUS_SUCCESS;
2502 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2503 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2504 ULONG old_backend_state;
2505 PUCHAR src, dst;
2507 FUNCTION_ENTER();
2508 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
2510 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
2511 old_backend_state = xppdd->backend_state;
2513 if (xppdd->restart_on_resume)
2515 status = XenPci_GetBackendAndAddWatch(device);
2517 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
2519 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
2520 // this is probably an unrecoverable situation...
2521 FUNCTION_ERROR_EXIT();
2522 return STATUS_UNSUCCESSFUL;
2524 if (xppdd->assigned_resources_ptr)
2526 // reset things - feed the 'requested resources' back in
2527 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
2528 src = xppdd->requested_resources_start;
2529 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
2530 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
2532 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
2534 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
2536 MmUnmapIoSpace(dst, xppdd->config_page_length);
2537 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
2539 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
2541 // this is definitely an unrecoverable situation...
2542 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
2543 FUNCTION_ERROR_EXIT();
2544 return STATUS_UNSUCCESSFUL;
2546 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RESUMING);
2547 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RUNNING);
2550 FUNCTION_EXIT();
2552 return STATUS_SUCCESS;