win-pvdrivers

view xenpci/xenpci_pdo.c @ 597:1ca6f17ebc47

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