win-pvdrivers

view xenpci/xenpci_pdo.c @ 547:ac614e49832c

Fixed another typo
author James Harper <james.harper@bendigoit.com.au>
date Sun Mar 08 14:37:45 2009 +1100 (2009-03-08)
parents e75bb8d68370
children a88fe72e3597
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 } sg_extra_t;
38 typedef struct {
39 ULONG map_type;
40 PVOID aligned_buffer;
41 PVOID unaligned_buffer;
42 ULONG copy_length;
43 PHYSICAL_ADDRESS logical;
44 } map_register_t;
46 typedef struct {
47 PDEVICE_OBJECT device_object;
48 ULONG total_map_registers;
49 ULONG count;
50 map_register_t regs[1];
51 } map_register_base_t;
53 static BOOLEAN
54 XenPci_BIS_TranslateBusAddress(PVOID context, PHYSICAL_ADDRESS bus_address, ULONG length, PULONG address_space, PPHYSICAL_ADDRESS translated_address)
55 {
56 UNREFERENCED_PARAMETER(context);
57 UNREFERENCED_PARAMETER(length);
58 /* actually this isn't right - should look up the gref for the physical address and work backwards from that */
59 FUNCTION_ENTER();
60 if (*address_space != 0)
61 {
62 KdPrint((__DRIVER_NAME " Cannot map I/O space\n"));
63 FUNCTION_EXIT();
64 return FALSE;
65 }
66 *translated_address = bus_address;
67 FUNCTION_EXIT();
68 return TRUE;
69 }
71 static VOID
72 XenPci_DOP_PutDmaAdapter(PDMA_ADAPTER dma_adapter)
73 {
74 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
76 FUNCTION_ENTER();
78 if (xen_dma_adapter->dma_extension)
79 ObDereferenceObject(xen_dma_adapter->dma_extension_driver);
80 ExFreePoolWithTag(xen_dma_adapter->adapter_object.DmaHeader.DmaOperations, XENPCI_POOL_TAG);
81 ExFreePoolWithTag(xen_dma_adapter, XENPCI_POOL_TAG);
83 FUNCTION_EXIT();
85 return;
86 }
88 static PVOID
89 XenPci_DOP_AllocateCommonBuffer(
90 PDMA_ADAPTER DmaAdapter,
91 ULONG Length,
92 PPHYSICAL_ADDRESS LogicalAddress,
93 BOOLEAN CacheEnabled
94 )
95 {
96 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
97 PXENPCI_DEVICE_DATA xpdd;
98 PVOID buffer;
99 PFN_NUMBER pfn;
100 grant_ref_t gref;
102 UNREFERENCED_PARAMETER(DmaAdapter);
103 UNREFERENCED_PARAMETER(CacheEnabled);
105 //FUNCTION_ENTER();
107 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
109 //KdPrint((__DRIVER_NAME " Length = %d\n", Length));
111 buffer = ExAllocatePoolWithTag(NonPagedPool, Length, XENPCI_POOL_TAG);
112 ASSERT(buffer); /* lazy */
114 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(buffer).QuadPart >> PAGE_SHIFT);
115 ASSERT(pfn); /* lazy */
116 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
117 ASSERT(gref); /* lazy */
118 LogicalAddress->QuadPart = (gref << PAGE_SHIFT) | (PtrToUlong(buffer) & (PAGE_SIZE - 1));
120 //FUNCTION_EXIT();
121 return buffer;
122 }
124 static VOID
125 XenPci_DOP_FreeCommonBuffer(
126 PDMA_ADAPTER dma_adapter,
127 ULONG length,
128 PHYSICAL_ADDRESS logical_address,
129 PVOID virtual_address,
130 BOOLEAN cache_enabled
131 )
132 {
133 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
134 PXENPCI_DEVICE_DATA xpdd;
135 grant_ref_t gref;
137 UNREFERENCED_PARAMETER(dma_adapter);
138 UNREFERENCED_PARAMETER(length);
139 UNREFERENCED_PARAMETER(cache_enabled);
141 // FUNCTION_ENTER();
143 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
144 gref = (grant_ref_t)(logical_address.QuadPart >> PAGE_SHIFT);
145 GntTbl_EndAccess(xpdd, gref, FALSE);
146 ExFreePoolWithTag(virtual_address, XENPCI_POOL_TAG);
148 // FUNCTION_EXIT();
149 }
151 static NTSTATUS
152 XenPci_DOP_AllocateAdapterChannel(
153 IN PDMA_ADAPTER dma_adapter,
154 IN PDEVICE_OBJECT device_object,
155 IN ULONG NumberOfMapRegisters,
156 IN PDRIVER_CONTROL ExecutionRoutine,
157 IN PVOID Context
158 )
159 {
160 //xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
161 //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
162 IO_ALLOCATION_ACTION action;
163 map_register_base_t *map_register_base;
165 UNREFERENCED_PARAMETER(dma_adapter);
167 //FUNCTION_ENTER();
169 map_register_base = ExAllocatePoolWithTag(NonPagedPool,
170 FIELD_OFFSET(map_register_base_t, regs) + NumberOfMapRegisters * sizeof(map_register_t), XENPCI_POOL_TAG);
171 if (!map_register_base)
172 {
173 KdPrint((__DRIVER_NAME " Cannot allocate memory for map_register_base\n"));
174 //FUNCTION_EXIT();
175 return STATUS_INSUFFICIENT_RESOURCES;
176 }
177 /* 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 */
178 map_register_base->device_object = device_object;
179 map_register_base->total_map_registers = NumberOfMapRegisters;
180 map_register_base->count = 0;
182 action = ExecutionRoutine(device_object, device_object->CurrentIrp, map_register_base, Context);
184 switch (action)
185 {
186 case KeepObject:
187 KdPrint((__DRIVER_NAME " KeepObject\n"));
188 ASSERT(FALSE);
189 break;
190 case DeallocateObject:
191 KdPrint((__DRIVER_NAME " DeallocateObject\n"));
192 ASSERT(FALSE);
193 break;
194 case DeallocateObjectKeepRegisters:
195 //KdPrint((__DRIVER_NAME " DeallocateObjectKeepRegisters\n"));
196 break;
197 default:
198 KdPrint((__DRIVER_NAME " Unknown action %d\n", action));
199 ASSERT(FALSE);
200 break;
201 }
202 //FUNCTION_EXIT();
203 return STATUS_SUCCESS;
204 }
206 static BOOLEAN
207 XenPci_DOP_FlushAdapterBuffers(
208 PDMA_ADAPTER dma_adapter,
209 PMDL mdl,
210 PVOID MapRegisterBase,
211 PVOID CurrentVa,
212 ULONG Length,
213 BOOLEAN write_to_device)
214 {
215 //xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
216 //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
217 map_register_base_t *map_register_base = MapRegisterBase;
218 map_register_t *map_register;
219 ULONG i;
221 UNREFERENCED_PARAMETER(dma_adapter);
222 UNREFERENCED_PARAMETER(mdl);
223 UNREFERENCED_PARAMETER(CurrentVa);
224 UNREFERENCED_PARAMETER(Length);
226 //FUNCTION_ENTER();
228 for (i = 0; i < map_register_base->count; i++)
229 {
230 map_register = &map_register_base->regs[i];
231 if (map_register->map_type == MAP_TYPE_REMAPPED && !write_to_device)
232 memcpy(map_register->unaligned_buffer, map_register->aligned_buffer, map_register->copy_length);
233 }
234 //FUNCTION_EXIT();
236 return TRUE;
237 }
239 static VOID
240 XenPci_DOP_FreeAdapterChannel(
241 IN PDMA_ADAPTER DmaAdapter
242 )
243 {
244 UNREFERENCED_PARAMETER(DmaAdapter);
246 FUNCTION_ENTER();
247 FUNCTION_EXIT();
248 }
250 static VOID
251 XenPci_DOP_FreeMapRegisters(
252 PDMA_ADAPTER dma_adapter,
253 PVOID MapRegisterBase,
254 ULONG NumberOfMapRegisters)
255 {
256 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
257 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
258 map_register_base_t *map_register_base = MapRegisterBase;
259 map_register_t *map_register;
260 ULONG i;
261 grant_ref_t gref;
263 //FUNCTION_ENTER();
264 ASSERT(map_register_base->total_map_registers == NumberOfMapRegisters);
266 for (i = 0; i < map_register_base->count; i++)
267 {
268 map_register = &map_register_base->regs[i];
269 switch (map_register->map_type)
270 {
271 case MAP_TYPE_REMAPPED:
272 gref = (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT);
273 GntTbl_EndAccess(xpdd, gref, FALSE);
274 ExFreePoolWithTag(map_register->aligned_buffer, XENPCI_POOL_TAG);
275 break;
276 case MAP_TYPE_MDL:
277 gref = (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT);
278 GntTbl_EndAccess(xpdd, gref, FALSE);
279 break;
280 case MAP_TYPE_VIRTUAL:
281 break;
282 }
283 }
284 ExFreePoolWithTag(map_register_base, XENPCI_POOL_TAG);
286 //FUNCTION_EXIT();
287 }
289 static PHYSICAL_ADDRESS
290 XenPci_DOP_MapTransfer(
291 PDMA_ADAPTER dma_adapter,
292 PMDL mdl,
293 PVOID MapRegisterBase,
294 PVOID CurrentVa,
295 PULONG Length,
296 BOOLEAN WriteToDevice)
297 {
298 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
299 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
300 map_register_base_t *map_register_base = MapRegisterBase;
301 map_register_t *map_register = &map_register_base->regs[map_register_base->count];
302 PDEVICE_OBJECT device_object = map_register_base->device_object;
303 ULONG page_offset;
304 PFN_NUMBER pfn;
305 grant_ref_t gref;
306 PUCHAR ptr;
307 ULONG mdl_offset;
308 ULONG pfn_index;
310 //FUNCTION_ENTER();
312 //KdPrint((__DRIVER_NAME " Mdl = %p, MapRegisterBase = %p, MdlVa = %p, CurrentVa = %p, Length = %d\n",
313 // mdl, MapRegisterBase, MmGetMdlVirtualAddress(mdl), CurrentVa, *Length));
315 ASSERT(mdl);
316 ASSERT(map_register_base->count < map_register_base->total_map_registers);
318 if (xen_dma_adapter->dma_extension)
319 {
320 if (xen_dma_adapter->dma_extension->need_virtual_address(device_object->CurrentIrp))
321 {
322 map_register->map_type = MAP_TYPE_VIRTUAL;
323 }
324 else
325 {
326 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(device_object->CurrentIrp);
327 if ((MmGetMdlByteOffset(mdl) & (alignment - 1)) || (MmGetMdlByteCount(mdl) & (alignment - 1)))
328 {
329 map_register->map_type = MAP_TYPE_REMAPPED;
330 }
331 else
332 {
333 map_register->map_type = MAP_TYPE_MDL;
334 }
335 }
336 }
337 else
338 {
339 map_register->map_type = MAP_TYPE_MDL;
340 }
342 switch (map_register->map_type)
343 {
344 case MAP_TYPE_MDL:
345 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL\n"));
346 mdl_offset = (ULONG)((ULONGLONG)CurrentVa - (ULONGLONG)MmGetMdlVirtualAddress(mdl));
347 page_offset = PtrToUlong(CurrentVa) & (PAGE_SIZE - 1);
348 *Length = min(*Length, PAGE_SIZE - page_offset);
349 pfn_index = (ULONG)(((ULONGLONG)CurrentVa >> PAGE_SHIFT) - ((ULONGLONG)MmGetMdlVirtualAddress(mdl) >> PAGE_SHIFT));
350 //KdPrint((__DRIVER_NAME " mdl_offset = %d, page_offset = %d, length = %d, pfn_index = %d\n",
351 // mdl_offset, page_offset, *Length, pfn_index));
352 pfn = MmGetMdlPfnArray(mdl)[pfn_index];
353 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
354 map_register->logical.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | page_offset;
355 map_register_base->count++;
356 break;
357 case MAP_TYPE_REMAPPED:
358 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED\n"));
359 *Length = min(*Length, PAGE_SIZE);
360 map_register->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
361 ASSERT(map_register->aligned_buffer);
362 map_register->unaligned_buffer = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
363 ASSERT(map_register->unaligned_buffer); /* lazy */
364 map_register->copy_length = *Length;
365 if (WriteToDevice)
366 memcpy(map_register->aligned_buffer, map_register->unaligned_buffer, map_register->copy_length);
367 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(map_register->aligned_buffer).QuadPart >> PAGE_SHIFT);
368 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
369 map_register->logical.QuadPart = (LONGLONG)(gref << PAGE_SHIFT);
370 map_register_base->count++;
371 break;
372 case MAP_TYPE_VIRTUAL:
373 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL\n"));
374 ptr = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
375 ASSERT(ptr); /* lazy */
376 map_register->logical.QuadPart = (ULONGLONG)ptr;
377 map_register_base->count++;
378 break;
379 default:
380 ASSERT(FALSE);
381 break;
382 }
384 //KdPrint((__DRIVER_NAME " logical = %08x:%08x\n", map_register->logical.HighPart, map_register->logical.LowPart));
385 //FUNCTION_EXIT();
386 return map_register->logical;
387 }
389 static ULONG
390 XenPci_DOP_GetDmaAlignment(
391 PDMA_ADAPTER DmaAdapter)
392 {
393 UNREFERENCED_PARAMETER(DmaAdapter);
395 FUNCTION_ENTER();
396 FUNCTION_EXIT();
397 return 0;
398 }
400 static ULONG
401 XenPci_DOP_ReadDmaCounter(
402 PDMA_ADAPTER DmaAdapter)
403 {
404 UNREFERENCED_PARAMETER(DmaAdapter);
406 FUNCTION_ENTER();
407 FUNCTION_EXIT();
408 return 0;
409 }
411 static NTSTATUS
412 XenPci_DOP_GetScatterGatherList(
413 PDMA_ADAPTER DmaAdapter,
414 PDEVICE_OBJECT DeviceObject,
415 PMDL Mdl,
416 PVOID CurrentVa,
417 ULONG Length,
418 PDRIVER_LIST_CONTROL ExecutionRoutine,
419 PVOID Context,
420 BOOLEAN WriteToDevice)
421 {
422 UNREFERENCED_PARAMETER(DmaAdapter);
423 UNREFERENCED_PARAMETER(DeviceObject);
424 UNREFERENCED_PARAMETER(Mdl);
425 UNREFERENCED_PARAMETER(CurrentVa);
426 UNREFERENCED_PARAMETER(Length);
427 UNREFERENCED_PARAMETER(ExecutionRoutine);
428 UNREFERENCED_PARAMETER(Context);
429 UNREFERENCED_PARAMETER(WriteToDevice);
431 FUNCTION_ENTER();
432 FUNCTION_EXIT();
433 return STATUS_SUCCESS;
434 }
436 static VOID
437 XenPci_DOP_PutScatterGatherList(
438 IN PDMA_ADAPTER DmaAdapter,
439 IN PSCATTER_GATHER_LIST ScatterGather,
440 IN BOOLEAN WriteToDevice
441 )
442 {
443 xen_dma_adapter_t *xen_dma_adapter;
444 PXENPCI_DEVICE_DATA xpdd;
445 ULONG i;
446 sg_extra_t *sg_extra;
448 UNREFERENCED_PARAMETER(WriteToDevice);
450 //FUNCTION_ENTER();
452 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
453 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
455 sg_extra = (sg_extra_t *)((PUCHAR)ScatterGather + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
456 (sizeof(SCATTER_GATHER_ELEMENT)) * ScatterGather->NumberOfElements);
458 switch (sg_extra->map_type)
459 {
460 case MAP_TYPE_REMAPPED:
461 for (i = 0; i < ScatterGather->NumberOfElements; i++)
462 {
463 grant_ref_t gref;
464 gref = (grant_ref_t)(ScatterGather->Elements[i].Address.QuadPart >> PAGE_SHIFT);
465 GntTbl_EndAccess(xpdd, gref, FALSE);
466 ScatterGather->Elements[i].Address.QuadPart = -1;
467 }
468 if (!WriteToDevice)
469 memcpy(sg_extra->unaligned_buffer, sg_extra->aligned_buffer, sg_extra->copy_length);
470 ExFreePoolWithTag(sg_extra->aligned_buffer, XENPCI_POOL_TAG);
471 break;
472 case MAP_TYPE_MDL:
473 for (i = 0; i < ScatterGather->NumberOfElements; i++)
474 {
475 grant_ref_t gref;
476 gref = (grant_ref_t)(ScatterGather->Elements[i].Address.QuadPart >> PAGE_SHIFT);
477 GntTbl_EndAccess(xpdd, gref, FALSE);
478 ScatterGather->Elements[i].Address.QuadPart = -1;
479 }
480 break;
481 case MAP_TYPE_VIRTUAL:
482 break;
483 }
484 //FUNCTION_EXIT();
485 }
487 static NTSTATUS
488 XenPci_DOP_CalculateScatterGatherList(
489 PDMA_ADAPTER DmaAdapter,
490 PMDL Mdl,
491 PVOID CurrentVa,
492 ULONG Length,
493 PULONG ScatterGatherListSize,
494 PULONG NumberOfMapRegisters
495 )
496 {
497 ULONG elements;
498 PMDL curr_mdl;
500 UNREFERENCED_PARAMETER(DmaAdapter);
501 UNREFERENCED_PARAMETER(Mdl);
503 FUNCTION_ENTER();
505 KdPrint((__DRIVER_NAME " Mdl = %p\n", Mdl));
506 KdPrint((__DRIVER_NAME " CurrentVa = %p\n", CurrentVa));
507 KdPrint((__DRIVER_NAME " Length = %d\n", Length));
508 if (Mdl)
509 {
510 for (curr_mdl = Mdl, elements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
511 elements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(CurrentVa, Length);
512 }
513 else
514 {
515 elements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, Length) + 1;
516 }
518 *ScatterGatherListSize = FIELD_OFFSET(SCATTER_GATHER_LIST, Elements)
519 + sizeof(SCATTER_GATHER_ELEMENT) * elements
520 + sizeof(sg_extra_t);
521 if (NumberOfMapRegisters)
522 *NumberOfMapRegisters = 1;
524 KdPrint((__DRIVER_NAME " ScatterGatherListSize = %d\n", *ScatterGatherListSize));
526 FUNCTION_EXIT();
527 return STATUS_SUCCESS;
528 }
530 static NTSTATUS
531 XenPci_DOP_BuildScatterGatherList(
532 IN PDMA_ADAPTER DmaAdapter,
533 IN PDEVICE_OBJECT DeviceObject,
534 IN PMDL Mdl,
535 IN PVOID CurrentVa,
536 IN ULONG Length,
537 IN PDRIVER_LIST_CONTROL ExecutionRoutine,
538 IN PVOID Context,
539 IN BOOLEAN WriteToDevice,
540 IN PVOID ScatterGatherBuffer,
541 IN ULONG ScatterGatherBufferLength)
542 {
543 ULONG i;
544 PSCATTER_GATHER_LIST sglist = ScatterGatherBuffer;
545 PUCHAR ptr;
546 ULONG remaining = Length;
547 ULONG total_remaining;
548 xen_dma_adapter_t *xen_dma_adapter;
549 PXENPCI_DEVICE_DATA xpdd;
550 sg_extra_t *sg_extra;
551 PMDL curr_mdl;
552 ULONG map_type;
553 ULONG sg_element;
554 ULONG offset;
555 PFN_NUMBER pfn;
556 grant_ref_t gref;
557 //PUCHAR StartVa;
559 //FUNCTION_ENTER();
561 ASSERT(MmGetMdlVirtualAddress(Mdl) == CurrentVa);
563 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
564 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
566 ASSERT(Mdl);
568 if (xen_dma_adapter->dma_extension)
569 {
570 if (xen_dma_adapter->dma_extension->need_virtual_address(DeviceObject->CurrentIrp))
571 {
572 ASSERT(!Mdl->Next); /* can only virtual a single buffer */
573 map_type = MAP_TYPE_VIRTUAL;
574 sglist->NumberOfElements = 1;
575 }
576 else
577 {
578 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(DeviceObject->CurrentIrp);
579 if ((MmGetMdlByteOffset(Mdl) & (alignment - 1)) || (MmGetMdlByteCount(Mdl) & (alignment - 1)))
580 {
581 ASSERT(!Mdl->Next); /* can only remap a single buffer for now - will need to check all Mdl's in the future */
582 map_type = MAP_TYPE_REMAPPED;
583 sglist->NumberOfElements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(NULL, Length);
584 }
585 else
586 {
587 map_type = MAP_TYPE_MDL;
588 for (curr_mdl = Mdl, sglist->NumberOfElements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
589 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
590 MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
591 }
592 }
593 }
594 else
595 {
596 map_type = MAP_TYPE_MDL;
597 for (curr_mdl = Mdl, sglist->NumberOfElements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
598 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
599 MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
600 }
601 if (ScatterGatherBufferLength < FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
602 sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t))
603 {
604 return STATUS_BUFFER_TOO_SMALL;
605 }
607 sg_extra = (sg_extra_t *)((PUCHAR)sglist + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
608 (sizeof(SCATTER_GATHER_ELEMENT)) * sglist->NumberOfElements);
610 sg_extra->map_type = map_type;
611 switch (map_type)
612 {
613 case MAP_TYPE_MDL:
614 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL - %p\n", MmGetMdlVirtualAddress(Mdl)));
615 total_remaining = Length;
616 for (sg_element = 0, curr_mdl = Mdl; curr_mdl; curr_mdl = curr_mdl->Next)
617 {
618 remaining = MmGetMdlByteCount(curr_mdl);
619 offset = MmGetMdlByteOffset(curr_mdl);
620 for (i = 0; i < ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)); i++)
621 {
622 //KdPrint((__DRIVER_NAME " element = %d\n", sg_element));
623 //KdPrint((__DRIVER_NAME " remaining = %d\n", remaining));
624 pfn = MmGetMdlPfnArray(curr_mdl)[i];
625 ASSERT(pfn);
626 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
627 ASSERT(gref != INVALID_GRANT_REF);
628 sglist->Elements[sg_element].Address.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | offset;
629 sglist->Elements[sg_element].Length = min(min(PAGE_SIZE - offset, remaining), total_remaining);
630 total_remaining -= sglist->Elements[sg_element].Length;
631 remaining -= sglist->Elements[sg_element].Length;
632 offset = 0;
633 sg_element++;
634 }
635 }
636 break;
637 case MAP_TYPE_REMAPPED:
638 sg_extra->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, max(Length, PAGE_SIZE), XENPCI_POOL_TAG);
639 if (!sg_extra->aligned_buffer)
640 {
641 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED buffer allocation failed - requested va = %p, length = %d\n", MmGetMdlVirtualAddress(Mdl), Length));
642 return STATUS_INSUFFICIENT_RESOURCES;
643 }
644 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED - %p -> %p\n", MmGetMdlVirtualAddress(Mdl), sg_extra->aligned_buffer));
645 sg_extra->unaligned_buffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
646 ASSERT(sg_extra->unaligned_buffer); /* lazy */
647 sg_extra->copy_length = Length;
648 if (WriteToDevice)
649 memcpy(sg_extra->aligned_buffer, sg_extra->unaligned_buffer, sg_extra->copy_length);
650 for (sg_element = 0, remaining = Length;
651 sg_element < ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_extra->aligned_buffer, Length); sg_element++)
652 {
653 pfn = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)sg_extra->aligned_buffer + (sg_element << PAGE_SHIFT)).QuadPart >> PAGE_SHIFT);
654 ASSERT(pfn);
655 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
656 ASSERT(gref);
657 sglist->Elements[sg_element].Address.QuadPart = (ULONGLONG)gref << PAGE_SHIFT;
658 sglist->Elements[sg_element].Length = min(PAGE_SIZE, remaining);
659 remaining -= sglist->Elements[sg_element].Length;
660 }
661 break;
662 case MAP_TYPE_VIRTUAL:
663 ptr = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
664 ASSERT(ptr); /* lazy */
665 sglist->Elements[0].Address.QuadPart = (ULONGLONG)ptr;
666 sglist->Elements[0].Length = Length;
667 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL - %08x\n", sglist->Elements[0].Address.LowPart));
668 break;
669 }
671 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, ScatterGatherBuffer, Context);
673 //FUNCTION_EXIT();
675 return STATUS_SUCCESS;
676 }
678 static NTSTATUS
679 XenPci_DOP_BuildMdlFromScatterGatherList(
680 PDMA_ADAPTER DmaAdapter,
681 PSCATTER_GATHER_LIST ScatterGather,
682 PMDL OriginalMdl,
683 PMDL *TargetMdl)
684 {
685 UNREFERENCED_PARAMETER(DmaAdapter);
686 UNREFERENCED_PARAMETER(ScatterGather);
687 UNREFERENCED_PARAMETER(OriginalMdl);
688 UNREFERENCED_PARAMETER(TargetMdl);
690 FUNCTION_ENTER();
691 FUNCTION_EXIT();
692 return STATUS_UNSUCCESSFUL;
693 }
695 static PDMA_ADAPTER
696 XenPci_BIS_GetDmaAdapter(PVOID context, PDEVICE_DESCRIPTION device_description, PULONG number_of_map_registers)
697 {
698 xen_dma_adapter_t *xen_dma_adapter;
699 PDEVICE_OBJECT curr, prev;
700 PDRIVER_OBJECT fdo_driver_object;
701 PVOID fdo_driver_extension;
703 UNREFERENCED_PARAMETER(device_description);
705 FUNCTION_ENTER();
707 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
708 KdPrint((__DRIVER_NAME " Device Description = %p:\n", device_description));
709 KdPrint((__DRIVER_NAME " Version = %d\n", device_description->Version));
710 KdPrint((__DRIVER_NAME " Master = %d\n", device_description->Master));
711 KdPrint((__DRIVER_NAME " ScatterGather = %d\n", device_description->ScatterGather));
712 KdPrint((__DRIVER_NAME " DemandMode = %d\n", device_description->DemandMode));
713 KdPrint((__DRIVER_NAME " AutoInitialize = %d\n", device_description->AutoInitialize));
714 KdPrint((__DRIVER_NAME " Dma32BitAddresses = %d\n", device_description->Dma32BitAddresses));
715 KdPrint((__DRIVER_NAME " IgnoreCount = %d\n", device_description->IgnoreCount));
716 KdPrint((__DRIVER_NAME " Dma64BitAddresses = %d\n", device_description->Dma64BitAddresses));
717 KdPrint((__DRIVER_NAME " BusNumber = %d\n", device_description->BusNumber));
718 KdPrint((__DRIVER_NAME " DmaChannel = %d\n", device_description->DmaChannel));
719 KdPrint((__DRIVER_NAME " InterfaceType = %d\n", device_description->InterfaceType));
720 KdPrint((__DRIVER_NAME " DmaWidth = %d\n", device_description->DmaWidth));
721 KdPrint((__DRIVER_NAME " DmaSpeed = %d\n", device_description->DmaSpeed));
722 KdPrint((__DRIVER_NAME " MaximumLength = %d\n", device_description->MaximumLength));
723 KdPrint((__DRIVER_NAME " DmaPort = %d\n", device_description->DmaPort));
725 if (!device_description->Master)
726 return NULL;
727 /*
728 we have to allocate PAGE_SIZE bytes here because Windows thinks this is
729 actually an ADAPTER_OBJECT, and then the verifier crashes because
730 Windows accessed beyond the end of the structure :(
731 */
732 xen_dma_adapter = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
733 ASSERT(xen_dma_adapter);
734 RtlZeroMemory(xen_dma_adapter, PAGE_SIZE);
736 switch(device_description->Version)
737 {
738 case DEVICE_DESCRIPTION_VERSION1:
739 xen_dma_adapter->adapter_object.DmaHeader.Version = 1;
740 break;
741 case DEVICE_DESCRIPTION_VERSION: /* ignore what the docs say here - DEVICE_DESCRIPTION_VERSION appears to mean the latest version */
742 case DEVICE_DESCRIPTION_VERSION2:
743 xen_dma_adapter->adapter_object.DmaHeader.Version = 2;
744 break;
745 default:
746 KdPrint((__DRIVER_NAME " Unsupported device description version %d\n", device_description->Version));
747 ExFreePoolWithTag(xen_dma_adapter, XENPCI_POOL_TAG);
748 return NULL;
749 }
752 xen_dma_adapter->adapter_object.DmaHeader.Size = sizeof(X_ADAPTER_OBJECT); //xen_dma_adapter_t);
753 xen_dma_adapter->adapter_object.MasterAdapter = NULL;
754 xen_dma_adapter->adapter_object.MapRegistersPerChannel = 1024;
755 xen_dma_adapter->adapter_object.AdapterBaseVa = NULL;
756 xen_dma_adapter->adapter_object.MapRegisterBase = NULL;
757 xen_dma_adapter->adapter_object.NumberOfMapRegisters = 0;
758 xen_dma_adapter->adapter_object.CommittedMapRegisters = 0;
759 xen_dma_adapter->adapter_object.CurrentWcb = NULL;
760 KeInitializeDeviceQueue(&xen_dma_adapter->adapter_object.ChannelWaitQueue);
761 xen_dma_adapter->adapter_object.RegisterWaitQueue = NULL;
762 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterQueue);
763 KeInitializeSpinLock(&xen_dma_adapter->adapter_object.SpinLock);
764 xen_dma_adapter->adapter_object.MapRegisters = NULL;
765 xen_dma_adapter->adapter_object.PagePort = NULL;
766 xen_dma_adapter->adapter_object.ChannelNumber = 0xff;
767 xen_dma_adapter->adapter_object.AdapterNumber = 0;
768 xen_dma_adapter->adapter_object.DmaPortAddress = 0;
769 xen_dma_adapter->adapter_object.AdapterMode = 0;
770 xen_dma_adapter->adapter_object.NeedsMapRegisters = FALSE; /* when true this causes a crash in the crash dump path */
771 xen_dma_adapter->adapter_object.MasterDevice = 1;
772 xen_dma_adapter->adapter_object.Width16Bits = 0;
773 xen_dma_adapter->adapter_object.ScatterGather = device_description->ScatterGather;
774 xen_dma_adapter->adapter_object.IgnoreCount = device_description->IgnoreCount;
775 xen_dma_adapter->adapter_object.Dma32BitAddresses = device_description->Dma32BitAddresses;
776 xen_dma_adapter->adapter_object.Dma64BitAddresses = device_description->Dma64BitAddresses;
777 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterList);
779 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DMA_OPERATIONS), XENPCI_POOL_TAG);
780 ASSERT(xen_dma_adapter->adapter_object.DmaHeader.DmaOperations);
781 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 1)
782 {
783 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = FIELD_OFFSET(DMA_OPERATIONS, CalculateScatterGatherList);
784 }
785 else
786 {
787 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = sizeof(DMA_OPERATIONS);
788 }
789 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutDmaAdapter = XenPci_DOP_PutDmaAdapter;
790 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateCommonBuffer = XenPci_DOP_AllocateCommonBuffer;
791 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeCommonBuffer = XenPci_DOP_FreeCommonBuffer;
792 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateAdapterChannel = XenPci_DOP_AllocateAdapterChannel;
793 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FlushAdapterBuffers = XenPci_DOP_FlushAdapterBuffers;
794 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeAdapterChannel = XenPci_DOP_FreeAdapterChannel;
795 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeMapRegisters = XenPci_DOP_FreeMapRegisters;
796 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->MapTransfer = XenPci_DOP_MapTransfer;
797 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetDmaAlignment = XenPci_DOP_GetDmaAlignment;
798 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->ReadDmaCounter = XenPci_DOP_ReadDmaCounter;
799 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetScatterGatherList = XenPci_DOP_GetScatterGatherList;
800 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutScatterGatherList = XenPci_DOP_PutScatterGatherList;
801 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 2)
802 {
803 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->CalculateScatterGatherList = XenPci_DOP_CalculateScatterGatherList;
804 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildScatterGatherList = XenPci_DOP_BuildScatterGatherList;
805 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildMdlFromScatterGatherList = XenPci_DOP_BuildMdlFromScatterGatherList;
806 }
807 xen_dma_adapter->xppdd = context;
808 xen_dma_adapter->dma_extension = NULL;
810 KdPrint((__DRIVER_NAME " About to call IoGetAttachedDeviceReference\n"));
811 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(xen_dma_adapter->xppdd->wdf_device));
812 KdPrint((__DRIVER_NAME " Before start of loop - curr = %p\n", curr));
813 while (curr != NULL)
814 {
815 fdo_driver_object = curr->DriverObject;
816 if (fdo_driver_object)
817 {
818 ObReferenceObject(fdo_driver_object);
819 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC));
820 if (fdo_driver_extension)
821 {
822 xen_dma_adapter->dma_extension_driver = fdo_driver_object; /* so we can dereference it on putdmaadapter */
823 xen_dma_adapter->dma_extension = (dma_driver_extension_t *)fdo_driver_extension;
824 ObDereferenceObject(curr);
825 break;
826 }
827 else
828 {
829 ObDereferenceObject(fdo_driver_object);
830 }
831 }
832 prev = curr;
833 curr = IoGetLowerDeviceObject(curr);
834 ObDereferenceObject(prev);
835 }
836 KdPrint((__DRIVER_NAME " End of loop\n"));
838 *number_of_map_registers = 1024; /* why not... */
840 FUNCTION_EXIT();
842 return &xen_dma_adapter->adapter_object.DmaHeader;
843 }
845 static ULONG
846 XenPci_BIS_SetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
847 {
848 UNREFERENCED_PARAMETER(context);
849 UNREFERENCED_PARAMETER(data_type);
850 UNREFERENCED_PARAMETER(buffer);
851 UNREFERENCED_PARAMETER(offset);
852 UNREFERENCED_PARAMETER(length);
854 FUNCTION_ENTER();
855 FUNCTION_EXIT();
856 return 0;
857 }
859 static ULONG
860 XenPci_BIS_GetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
861 {
862 UNREFERENCED_PARAMETER(context);
863 UNREFERENCED_PARAMETER(data_type);
864 UNREFERENCED_PARAMETER(buffer);
865 UNREFERENCED_PARAMETER(offset);
866 UNREFERENCED_PARAMETER(length);
868 FUNCTION_ENTER();
869 FUNCTION_EXIT();
870 return 0;
871 }
873 /*
874 Called at PASSIVE_LEVEL(?)
875 Called during restore
876 */
878 static ULONG
879 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
880 {
881 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
882 char path[128];
883 char *value;
884 char *err;
885 ULONG backend_state;
887 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
888 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
889 if (err)
890 {
891 XenPci_FreeMem(err);
892 return XenbusStateUnknown;
893 }
894 else
895 {
896 backend_state = atoi(value);
897 XenPci_FreeMem(value);
898 return backend_state;
899 }
900 }
902 static VOID
903 XenPci_BackEndStateHandler(char *path, PVOID context)
904 {
905 WDFDEVICE device = context;
906 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
907 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
908 ULONG new_backend_state;
910 #if !DBG
911 UNREFERENCED_PARAMETER(path);
912 #endif
914 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
916 /* check that path == device/id/state */
917 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
918 new_backend_state = XenPci_ReadBackendState(xppdd);
919 if (new_backend_state == XenbusStateUnknown)
920 {
921 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
922 return;
923 KdPrint(("Failed to read %s, assuming closed\n", path));
924 new_backend_state = XenbusStateClosed;
925 }
927 if (xppdd->backend_state == new_backend_state)
928 {
929 KdPrint((__DRIVER_NAME " state unchanged\n"));
930 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
931 return;
932 }
934 xppdd->backend_state = new_backend_state;
936 switch (xppdd->backend_state)
937 {
938 case XenbusStateUnknown:
939 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown (%s)\n", path));
940 break;
942 case XenbusStateInitialising:
943 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising (%s)\n", path));
944 break;
946 case XenbusStateInitWait:
947 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait (%s)\n", path));
948 break;
950 case XenbusStateInitialised:
951 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised (%s)\n", path));
952 break;
954 case XenbusStateConnected:
955 KdPrint((__DRIVER_NAME " Backend State Changed to Connected (%s)\n", path));
956 break;
958 case XenbusStateClosing:
959 KdPrint((__DRIVER_NAME " Backend State Changed to Closing (%s)\n", path));
960 if (xppdd->frontend_state == XenbusStateConnected)
961 {
962 KdPrint((__DRIVER_NAME " Requesting eject\n"));
963 WdfPdoRequestEject(device);
964 }
965 break;
967 case XenbusStateClosed:
968 KdPrint((__DRIVER_NAME " Backend State Changed to Closed (%s)\n", path));
969 break;
971 default:
972 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d (%s)\n", xppdd->backend_state, path));
973 break;
974 }
976 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
978 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
980 return;
981 }
983 static NTSTATUS
984 XenPci_GetBackendAndAddWatch(WDFDEVICE device)
985 {
986 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
987 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
988 char path[128];
989 PCHAR res;
990 PCHAR value;
992 /* Get backend path */
993 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
994 "%s/backend", xppdd->path);
995 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
996 if (res)
997 {
998 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
999 XenPci_FreeMem(res);
1000 return STATUS_UNSUCCESSFUL;
1002 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
1003 XenPci_FreeMem(value);
1005 /* Add watch on backend state */
1006 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1007 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
1009 return STATUS_SUCCESS;
1012 static PMDL
1013 XenConfig_MakeConfigPage(WDFDEVICE device)
1015 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
1016 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
1017 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
1018 PMDL mdl;
1019 PUCHAR ptr;
1020 PDEVICE_OBJECT curr, prev;
1021 PDRIVER_OBJECT fdo_driver_object;
1022 PUCHAR fdo_driver_extension;
1024 FUNCTION_ENTER();
1026 mdl = AllocateUncachedPage();
1027 ptr = MmGetMdlVirtualAddress(mdl);
1028 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(device));
1029 //curr = WdfDeviceWdmGetAttachedDevice(device);
1030 while (curr != NULL)
1032 fdo_driver_object = curr->DriverObject;
1033 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
1034 if (fdo_driver_object)
1036 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
1037 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
1038 if (fdo_driver_extension)
1040 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
1041 ObDereferenceObject(curr);
1042 break;
1045 prev = curr;
1046 curr = IoGetLowerDeviceObject(curr);
1047 ObDereferenceObject(prev);
1050 FUNCTION_EXIT();
1052 return mdl;
1055 static NTSTATUS
1056 XenPci_EvtChn_Bind(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
1058 WDFDEVICE device = context;
1059 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1060 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1062 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext);
1065 static NTSTATUS
1066 XenPci_EvtChn_BindDpc(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
1068 WDFDEVICE device = context;
1069 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1070 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1072 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext);
1075 static NTSTATUS
1076 XenPci_EvtChn_Unbind(PVOID context, evtchn_port_t Port)
1078 WDFDEVICE device = context;
1079 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1080 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1082 return EvtChn_Unbind(xpdd, Port);
1085 static NTSTATUS
1086 XenPci_EvtChn_Mask(PVOID context, evtchn_port_t Port)
1088 WDFDEVICE device = context;
1089 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1090 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1092 return EvtChn_Mask(xpdd, Port);
1095 static NTSTATUS
1096 XenPci_EvtChn_Unmask(PVOID context, evtchn_port_t Port)
1098 WDFDEVICE device = context;
1099 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1100 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1102 return EvtChn_Unmask(xpdd, Port);
1105 static NTSTATUS
1106 XenPci_EvtChn_Notify(PVOID context, evtchn_port_t Port)
1108 WDFDEVICE device = context;
1109 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1110 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1112 return EvtChn_Notify(xpdd, Port);
1115 static BOOLEAN
1116 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port)
1118 WDFDEVICE device = context;
1119 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1120 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1122 return EvtChn_AckEvent(xpdd, port);
1125 typedef struct {
1126 PXEN_EVTCHN_SYNC_ROUTINE sync_routine;
1127 PVOID sync_context;
1128 } sync_context_t;
1130 static BOOLEAN
1131 XenPci_EvtChn_Sync_Routine(WDFINTERRUPT interrupt, WDFCONTEXT context)
1133 sync_context_t *wdf_sync_context = context;
1134 UNREFERENCED_PARAMETER(interrupt);
1135 return wdf_sync_context->sync_routine(wdf_sync_context->sync_context);
1138 static BOOLEAN
1139 XenPci_EvtChn_Sync(PVOID context, PXEN_EVTCHN_SYNC_ROUTINE sync_routine, PVOID sync_context)
1141 WDFDEVICE device = context;
1142 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1143 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1144 sync_context_t wdf_sync_context;
1146 wdf_sync_context.sync_routine = sync_routine;
1147 wdf_sync_context.sync_context = sync_context;
1149 return WdfInterruptSynchronize(xpdd->interrupt, XenPci_EvtChn_Sync_Routine, &wdf_sync_context);
1152 static grant_ref_t
1153 XenPci_GntTbl_GrantAccess(PVOID context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref)
1155 WDFDEVICE device = context;
1156 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1157 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1159 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref);
1162 static BOOLEAN
1163 XenPci_GntTbl_EndAccess(PVOID context, grant_ref_t ref, BOOLEAN keepref)
1165 WDFDEVICE device = context;
1166 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1167 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1169 return GntTbl_EndAccess(xpdd, ref, keepref);
1172 static VOID
1173 XenPci_GntTbl_PutRef(PVOID context, grant_ref_t ref)
1175 WDFDEVICE device = context;
1176 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1177 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1179 GntTbl_PutRef(xpdd, ref);
1182 static grant_ref_t
1183 XenPci_GntTbl_GetRef(PVOID context)
1185 WDFDEVICE device = context;
1186 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1187 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1189 return GntTbl_GetRef(xpdd);
1192 PCHAR
1193 XenPci_XenBus_Read(PVOID context, xenbus_transaction_t xbt, char *path, char **value)
1195 WDFDEVICE device = context;
1196 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1197 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1198 return XenBus_Read(xpdd, xbt, path, value);
1201 PCHAR
1202 XenPci_XenBus_Write(PVOID context, xenbus_transaction_t xbt, char *path, char *value)
1204 WDFDEVICE device = context;
1205 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1206 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1207 return XenBus_Write(xpdd, xbt, path, value);
1210 PCHAR
1211 XenPci_XenBus_Printf(PVOID context, xenbus_transaction_t xbt, char *path, char *fmt, ...)
1213 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
1214 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
1215 //return XenBus_Printf(xpdd, xbt, path, value);
1216 UNREFERENCED_PARAMETER(context);
1217 UNREFERENCED_PARAMETER(xbt);
1218 UNREFERENCED_PARAMETER(path);
1219 UNREFERENCED_PARAMETER(fmt);
1220 return NULL;
1223 PCHAR
1224 XenPci_XenBus_StartTransaction(PVOID context, xenbus_transaction_t *xbt)
1226 WDFDEVICE device = context;
1227 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1228 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1229 return XenBus_StartTransaction(xpdd, xbt);
1232 PCHAR
1233 XenPci_XenBus_EndTransaction(PVOID context, xenbus_transaction_t xbt, int abort, int *retry)
1235 WDFDEVICE device = context;
1236 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1237 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1238 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
1241 PCHAR
1242 XenPci_XenBus_List(PVOID context, xenbus_transaction_t xbt, char *prefix, char ***contents)
1244 WDFDEVICE device = context;
1245 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1246 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1247 return XenBus_List(xpdd, xbt, prefix, contents);
1250 PCHAR
1251 XenPci_XenBus_AddWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
1253 WDFDEVICE device = context;
1254 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1255 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1256 PCHAR retval;
1258 FUNCTION_ENTER();
1259 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
1260 if (retval == NULL)
1262 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
1264 else
1266 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
1268 FUNCTION_EXIT();
1269 return retval;
1272 PCHAR
1273 XenPci_XenBus_RemWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
1275 WDFDEVICE device = context;
1276 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1277 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1278 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
1281 /*
1282 Called at PASSIVE_LEVEL
1283 Called during restore
1284 */
1286 static NTSTATUS
1287 XenPci_ChangeFrontendState(WDFDEVICE device, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
1289 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1290 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1291 LARGE_INTEGER timeout;
1292 ULONG remaining;
1293 ULONG thiswait;
1294 char path[128];
1296 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1298 xppdd->frontend_state = frontend_state_set;
1300 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
1301 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
1303 remaining = maximum_wait_ms;
1305 while (xppdd->backend_state != backend_state_response)
1307 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
1308 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
1309 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
1311 remaining -= thiswait;
1312 if (remaining == 0)
1314 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
1315 return STATUS_UNSUCCESSFUL;
1317 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
1320 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1321 return STATUS_SUCCESS;
1324 static NTSTATUS
1325 XenPci_XenConfigDevice(WDFDEVICE device);
1327 static NTSTATUS
1328 XenPci_XenShutdownDevice(PVOID context)
1330 WDFDEVICE device = context;
1331 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1332 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1333 PUCHAR in_ptr;
1334 ULONG i;
1335 UCHAR type;
1336 PVOID setting;
1337 PVOID value;
1338 PVOID value2;
1340 FUNCTION_ENTER();
1342 if (xppdd->backend_state == XenbusStateConnected)
1344 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
1345 if (xppdd->backend_state == XenbusStateClosing)
1346 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
1347 if (xppdd->backend_state == XenbusStateClosed)
1348 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
1350 else
1352 if (xppdd->backend_state == XenbusStateClosing)
1353 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
1356 if (xppdd->assigned_resources_start != NULL)
1358 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1359 in_ptr = xppdd->assigned_resources_start;
1360 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
1362 switch (type)
1364 case XEN_INIT_TYPE_RING: /* frontend ring */
1365 FreePages(value);
1366 break;
1367 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
1368 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
1369 EvtChn_Unbind(xpdd, PtrToUlong(value));
1370 EvtChn_Close(xpdd, PtrToUlong(value));
1371 break;
1372 case XEN_INIT_TYPE_GRANT_ENTRIES:
1373 for (i = 0; i < PtrToUlong(setting); i++)
1374 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value)[i], FALSE);
1375 break;
1378 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
1379 xppdd->assigned_resources_start = NULL;
1382 FUNCTION_EXIT();
1384 return STATUS_SUCCESS;
1387 struct dummy_sring {
1388 RING_IDX req_prod, req_event;
1389 RING_IDX rsp_prod, rsp_event;
1390 uint8_t pad[48];
1391 };
1393 static NTSTATUS
1394 XenPci_XenConfigDeviceSpecifyBuffers(WDFDEVICE device, PUCHAR src, PUCHAR dst)
1396 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1397 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1398 NTSTATUS status = STATUS_SUCCESS;
1399 ULONG i;
1400 char path[128];
1401 PCHAR setting, value;
1402 PCHAR res;
1403 PVOID address;
1404 UCHAR type;
1405 PUCHAR in_ptr; //, in_start;
1406 PUCHAR out_ptr; //, out_start;
1407 XENPCI_VECTORS vectors;
1408 ULONG event_channel;
1409 ULONG run_type = 0;
1410 PMDL ring;
1411 grant_ref_t gref;
1412 BOOLEAN done_xenbus_init = FALSE;
1413 PVOID value2;
1415 FUNCTION_ENTER();
1417 in_ptr = src;
1418 out_ptr = dst;
1420 // always add vectors
1421 vectors.magic = XEN_DATA_MAGIC;
1422 vectors.length = sizeof(XENPCI_VECTORS);
1423 vectors.context = device;
1424 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
1425 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
1426 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
1427 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
1428 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
1429 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
1430 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
1431 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
1432 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
1433 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
1434 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
1435 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
1436 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
1437 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
1438 strncpy(vectors.path, xppdd->path, 128);
1439 strncpy(vectors.backend_path, xppdd->backend_path, 128);
1440 //vectors.pdo_event_channel = xpdd->pdo_event_channel;
1441 vectors.XenBus_Read = XenPci_XenBus_Read;
1442 vectors.XenBus_Write = XenPci_XenBus_Write;
1443 vectors.XenBus_Printf = XenPci_XenBus_Printf;
1444 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
1445 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
1446 vectors.XenBus_List = XenPci_XenBus_List;
1447 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
1448 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
1450 if (qemu_filtered)
1451 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_ACTIVE, NULL, NULL, NULL);
1453 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
1455 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
1456 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
1458 // first pass, possibly before state == Connected
1459 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
1462 if (!done_xenbus_init)
1464 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
1466 status = STATUS_UNSUCCESSFUL;
1467 goto error;
1469 done_xenbus_init = TRUE;
1472 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
1474 switch (type)
1476 case XEN_INIT_TYPE_RUN:
1477 run_type++;
1478 break;
1479 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
1480 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
1481 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1482 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
1483 break;
1484 case XEN_INIT_TYPE_RING: /* frontend ring */
1485 /* we only allocate and do the SHARED_RING_INIT here */
1486 if ((ring = AllocatePage()) != 0)
1488 address = MmGetMdlVirtualAddress(ring);
1489 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
1490 SHARED_RING_INIT((struct dummy_sring *)address);
1491 if ((gref = GntTbl_GrantAccess(
1492 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
1494 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1495 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
1496 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
1497 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
1498 // add the grant entry too so it gets freed automatically
1499 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
1500 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
1501 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
1503 else
1505 FreePages(ring);
1506 status = STATUS_UNSUCCESSFUL;
1507 goto error;
1510 else
1512 status = STATUS_UNSUCCESSFUL;
1513 goto error;
1515 break;
1516 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
1517 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
1518 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
1520 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
1521 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1522 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
1523 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
1524 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
1525 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
1527 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
1529 else
1531 #pragma warning(suppress:4055)
1532 EvtChn_Bind(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
1535 else
1537 status = STATUS_UNSUCCESSFUL;
1538 goto error;
1540 break;
1543 if (!NT_SUCCESS(status))
1545 goto error;
1547 // If XEN_INIT_TYPE_RUN was specified more than once then we skip XenbusStateInitialised here and go straight to XenbusStateConnected at the end
1548 if (run_type == 1)
1550 if (XenPci_ChangeFrontendState(device, XenbusStateInitialised, XenbusStateConnected, 30000) != STATUS_SUCCESS)
1552 status = STATUS_UNSUCCESSFUL;
1553 goto error;
1557 // second pass, possibly after state == Connected
1558 in_ptr = src;
1559 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
1561 switch(type)
1563 case XEN_INIT_TYPE_READ_STRING_BACK:
1564 case XEN_INIT_TYPE_READ_STRING_FRONT:
1565 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
1566 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1567 else
1568 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
1569 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
1570 if (res)
1572 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
1573 XenPci_FreeMem(res);
1574 ADD_XEN_INIT_RSP(&out_ptr, type, setting, NULL, NULL);
1576 else
1578 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
1579 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, value2);
1580 XenPci_FreeMem(value);
1582 break;
1583 case XEN_INIT_TYPE_VECTORS:
1584 // this is always done so ignore the request
1585 break;
1586 case XEN_INIT_TYPE_GRANT_ENTRIES:
1587 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
1588 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
1589 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
1590 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
1591 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
1592 for (i = 0; i < PtrToUlong(value); i++)
1594 gref = GntTbl_GetRef(xpdd);
1595 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
1596 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
1598 break;
1601 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1603 if (run_type)
1605 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
1607 status = STATUS_UNSUCCESSFUL;
1608 goto error;
1611 FUNCTION_EXIT();
1612 return status;
1614 error:
1615 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
1616 FUNCTION_EXIT_STATUS(status);
1618 return status;
1621 static NTSTATUS
1622 XenPci_XenConfigDevice(WDFDEVICE device)
1624 NTSTATUS status;
1625 PUCHAR src, dst;
1626 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1628 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
1629 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
1630 memcpy(src, dst, xppdd->config_page_length);
1632 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
1634 MmUnmapIoSpace(dst, xppdd->config_page_length);
1635 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
1637 return status;
1640 static NTSTATUS
1641 XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp)
1643 NTSTATUS status = STATUS_SUCCESS;
1644 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1645 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1646 PIO_STACK_LOCATION stack;
1647 PCM_PARTIAL_RESOURCE_LIST prl;
1648 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
1649 ULONG i;
1650 char path[128];
1651 PMDL mdl;
1653 FUNCTION_ENTER();
1654 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
1656 stack = IoGetCurrentIrpStackLocation(irp);
1658 status = XenPci_GetBackendAndAddWatch(device);
1659 if (!NT_SUCCESS(status)) {
1660 FUNCTION_ERROR_EXIT();
1661 return status;
1664 mdl = XenConfig_MakeConfigPage(device);
1666 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
1667 for (i = 0; i < prl->Count; i++)
1669 prd = & prl->PartialDescriptors[i];
1670 switch (prd->Type)
1672 case CmResourceTypeMemory:
1673 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
1675 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
1676 prd->u.Memory.Length = MmGetMdlByteCount(mdl);
1678 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
1680 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1681 prd->Type = CmResourceTypeInterrupt;
1682 prd->ShareDisposition = CmResourceShareShared;
1683 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
1684 prd->u.Interrupt.Level = xpdd->irq_number;
1685 prd->u.Interrupt.Vector = xpdd->irq_number;
1686 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
1687 xppdd->irq_number = xpdd->irq_number;
1689 break;
1693 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
1694 for (i = 0; i < prl->Count; i++)
1696 prd = & prl->PartialDescriptors[i];
1697 switch (prd->Type)
1699 case CmResourceTypeMemory:
1700 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
1701 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
1702 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
1704 if (prd->u.Memory.Length == 0)
1706 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(mdl)[0]));
1707 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
1708 prd->u.Memory.Length = MmGetMdlByteCount(mdl);
1709 KdPrint((__DRIVER_NAME " New Start = %08x%08x, Length = %d\n", prd->u.Memory.Start.HighPart, prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
1711 xppdd->config_page_phys = prd->u.Memory.Start;
1712 xppdd->config_page_length = prd->u.Memory.Length;
1713 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
1714 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
1716 status = XenPci_XenConfigDevice(device);
1717 if (!NT_SUCCESS(status))
1719 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1720 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
1721 FUNCTION_ERROR_EXIT();
1722 return status;
1725 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
1727 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1728 prd->Type = CmResourceTypeInterrupt;
1729 prd->ShareDisposition = CmResourceShareShared;
1730 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
1731 prd->u.Interrupt.Level = xpdd->irq_level;
1732 prd->u.Interrupt.Vector = xpdd->irq_vector;
1733 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
1734 xppdd->irq_vector = xpdd->irq_vector;
1735 xppdd->irq_level = xpdd->irq_level;
1737 break;
1741 IoSkipCurrentIrpStackLocation(irp);
1743 FUNCTION_EXIT();
1745 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
1748 #if 0
1749 static NTSTATUS
1750 XenPciPdo_EvtDeviceResourcesQuery(WDFDEVICE device, WDFCMRESLIST resources)
1753 #endif
1755 static NTSTATUS
1756 XenPciPdo_EvtDeviceResourceRequirementsQuery(WDFDEVICE device, WDFIORESREQLIST requirements_list)
1758 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1759 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1760 WDFIORESLIST res_list;
1761 IO_RESOURCE_DESCRIPTOR ird;
1763 //FUNCTION_ENTER();
1765 WdfIoResourceRequirementsListSetInterfaceType(requirements_list, PNPBus);
1767 WdfIoResourceListCreate(requirements_list, WDF_NO_OBJECT_ATTRIBUTES, &res_list);
1768 ird.Option = 0;
1769 ird.Type = CmResourceTypeMemory;
1770 ird.ShareDisposition = CmResourceShareShared;
1771 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
1772 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
1773 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
1774 ird.u.Memory.Length = 0;
1775 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
1776 WdfIoResourceListAppendDescriptor(res_list, &ird);
1778 ird.Option = 0;
1779 ird.Type = CmResourceTypeMemory;
1780 ird.ShareDisposition = CmResourceShareShared;
1781 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
1782 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
1783 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
1784 ird.u.Memory.Length = 0;
1785 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
1786 WdfIoResourceListAppendDescriptor(res_list, &ird);
1788 WdfIoResourceRequirementsListAppendIoResList(requirements_list, res_list);
1790 //FUNCTION_EXIT();
1792 return STATUS_SUCCESS;
1795 NTSTATUS
1796 XenPciPdo_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
1798 NTSTATUS status = STATUS_SUCCESS;
1800 UNREFERENCED_PARAMETER(device);
1801 UNREFERENCED_PARAMETER(previous_state);
1803 FUNCTION_ENTER();
1805 switch (previous_state)
1807 case WdfPowerDeviceD0:
1808 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1809 break;
1810 case WdfPowerDeviceD1:
1811 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1812 break;
1813 case WdfPowerDeviceD2:
1814 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
1815 break;
1816 case WdfPowerDeviceD3:
1817 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
1818 break;
1819 case WdfPowerDeviceD3Final:
1820 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
1821 break;
1822 case WdfPowerDevicePrepareForHibernation:
1823 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
1824 break;
1825 default:
1826 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
1827 break;
1830 FUNCTION_EXIT();
1832 return status;
1835 NTSTATUS
1836 XenPciPdo_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
1838 NTSTATUS status = STATUS_SUCCESS;
1839 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1840 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1841 char path[128];
1843 UNREFERENCED_PARAMETER(device);
1844 UNREFERENCED_PARAMETER(target_state);
1846 FUNCTION_ENTER();
1848 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
1851 switch (target_state)
1853 case WdfPowerDeviceD0:
1854 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1855 break;
1856 case WdfPowerDeviceD1:
1857 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1858 break;
1859 case WdfPowerDeviceD2:
1860 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
1861 break;
1862 case WdfPowerDeviceD3:
1863 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
1864 break;
1865 case WdfPowerDeviceD3Final:
1866 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
1867 break;
1868 case WdfPowerDevicePrepareForHibernation:
1869 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
1870 break;
1871 default:
1872 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
1873 break;
1876 if (target_state == WdfPowerDevicePrepareForHibernation
1877 || (target_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
1879 KdPrint((__DRIVER_NAME " not powering down as we are hibernating\n"));
1881 else
1883 status = XenPci_XenShutdownDevice(device);
1884 /* Remove watch on backend state */
1885 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1886 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
1888 FUNCTION_EXIT();
1890 return status;
1893 NTSTATUS
1894 XenPciPdo_EvtDevicePrepareHardware (WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
1896 NTSTATUS status = STATUS_SUCCESS;
1898 UNREFERENCED_PARAMETER(device);
1899 UNREFERENCED_PARAMETER(resources_raw);
1900 UNREFERENCED_PARAMETER(resources_translated);
1902 FUNCTION_ENTER();
1903 FUNCTION_EXIT();
1905 return status;
1908 NTSTATUS
1909 XenPciPdo_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
1911 NTSTATUS status = STATUS_SUCCESS;
1913 UNREFERENCED_PARAMETER(device);
1914 UNREFERENCED_PARAMETER(resources_translated);
1916 FUNCTION_ENTER();
1917 FUNCTION_EXIT();
1919 return status;
1922 static VOID
1923 XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
1925 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1927 FUNCTION_ENTER();
1929 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
1930 switch (notification_type)
1932 case WdfSpecialFilePaging:
1933 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
1934 break;
1935 case WdfSpecialFileHibernation:
1936 xppdd->hiber_usage_kludge = is_in_notification_path;
1937 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
1938 break;
1939 case WdfSpecialFileDump:
1940 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
1941 break;
1942 default:
1943 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
1944 break;
1947 FUNCTION_EXIT();
1950 NTSTATUS
1951 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
1952 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
1953 PWDFDEVICE_INIT child_init)
1955 NTSTATUS status = STATUS_SUCCESS;
1956 WDF_OBJECT_ATTRIBUTES child_attributes;
1957 WDFDEVICE child_device;
1958 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
1959 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
1960 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
1961 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
1962 PXENPCI_PDO_DEVICE_DATA xppdd;
1963 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
1964 WDF_QUERY_INTERFACE_CONFIG interface_config;
1965 BUS_INTERFACE_STANDARD bus_interface;
1966 WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
1967 WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
1968 UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
1969 WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
1971 FUNCTION_ENTER();
1973 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
1975 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
1976 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
1977 //child_pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPciPdo_EvtDeviceD0EntryPostInterruptsEnabled;
1978 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
1979 //child_pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPciPdo_EvtDeviceD0ExitPreInterruptsDisabled;
1980 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenPciPdo_EvtDevicePrepareHardware;
1981 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenPciPdo_EvtDeviceReleaseHardware;
1982 child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
1983 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
1985 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
1986 identification->device, identification->index, identification->path));
1988 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
1989 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
1990 if (!NT_SUCCESS(status))
1992 return status;
1995 WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
1996 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
1997 pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
1998 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
1999 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
2000 WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
2002 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
2003 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
2004 if (!NT_SUCCESS(status))
2006 return status;
2008 status = WdfPdoInitAddHardwareID(child_init, &buffer);
2009 if (!NT_SUCCESS(status))
2011 return status;
2013 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
2014 if (!NT_SUCCESS(status))
2016 return status;
2019 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
2020 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
2021 if (!NT_SUCCESS(status))
2023 return status;
2026 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
2027 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
2028 if (!NT_SUCCESS(status))
2030 return status;
2032 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
2034 WdfDeviceInitSetPowerNotPageable(child_init);
2036 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
2037 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
2038 if (!NT_SUCCESS(status))
2040 return status;
2043 xppdd = GetXppdd(child_device);
2045 xppdd->wdf_device = child_device;
2046 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
2048 xppdd->device_state.magic = XEN_DEVICE_STATE_MAGIC;
2049 xppdd->device_state.length = sizeof(XENPCI_DEVICE_STATE);
2050 xppdd->device_state.suspend_resume_state_pdo = SR_STATE_RUNNING;
2051 xppdd->device_state.suspend_resume_state_fdo = SR_STATE_RUNNING;
2052 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
2053 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
2054 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
2055 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
2057 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
2058 child_pnp_capabilities.LockSupported = WdfFalse;
2059 child_pnp_capabilities.EjectSupported = WdfTrue;
2060 child_pnp_capabilities.Removable = WdfTrue;
2061 child_pnp_capabilities.DockDevice = WdfFalse;
2062 child_pnp_capabilities.UniqueID = WdfFalse;
2063 child_pnp_capabilities.SilentInstall = WdfTrue;
2064 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
2065 child_pnp_capabilities.HardwareDisabled = WdfFalse;
2066 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
2068 WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
2069 child_power_capabilities.DeviceD1 = WdfTrue;
2070 child_power_capabilities.WakeFromD1 = WdfTrue;
2071 child_power_capabilities.DeviceWake = PowerDeviceD1;
2072 child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
2073 child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
2074 child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
2075 child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
2076 child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
2077 child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
2078 WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
2080 bus_interface.Size = sizeof(BUS_INTERFACE_STANDARD);
2081 bus_interface.Version = 1; //BUS_INTERFACE_STANDARD_VERSION;
2082 bus_interface.Context = xppdd;
2083 bus_interface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
2084 bus_interface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
2085 bus_interface.TranslateBusAddress = XenPci_BIS_TranslateBusAddress;
2086 bus_interface.GetDmaAdapter = XenPci_BIS_GetDmaAdapter;
2087 bus_interface.SetBusData = XenPci_BIS_SetBusData;
2088 bus_interface.GetBusData = XenPci_BIS_GetBusData;
2089 WDF_QUERY_INTERFACE_CONFIG_INIT(&interface_config, (PINTERFACE)&bus_interface, &GUID_BUS_INTERFACE_STANDARD, NULL);
2090 status = WdfDeviceAddQueryInterface(child_device, &interface_config);
2091 if (!NT_SUCCESS(status))
2093 return status;
2096 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
2097 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
2098 xppdd->index = identification->index;
2099 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
2100 xppdd->backend_state = XenbusStateUnknown;
2101 xppdd->frontend_state = XenbusStateUnknown;
2102 xppdd->backend_path[0] = '\0';
2104 FUNCTION_EXIT();
2106 return status;
2109 static __forceinline VOID
2110 XenPci_Pdo_ChangeSuspendState(WDFDEVICE device, ULONG new_state)
2112 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2113 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2115 FUNCTION_ENTER();
2116 KdPrint((__DRIVER_NAME " setting pdo state to %d\n", new_state));
2117 xppdd->device_state.suspend_resume_state_pdo = new_state;
2118 KeMemoryBarrier();
2119 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xpdd->pdo_event_channel));
2120 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
2121 while(xppdd->device_state.suspend_resume_state_fdo != xppdd->device_state.suspend_resume_state_pdo)
2123 KdPrint((__DRIVER_NAME " waiting...\n"));
2124 KeWaitForSingleObject(&xpdd->pdo_suspend_event, Executive, KernelMode, FALSE, NULL);
2126 KdPrint((__DRIVER_NAME " fdo state set to %d\n", new_state));
2127 FUNCTION_EXIT();
2130 /* called at PASSIVE_LEVEL */
2131 NTSTATUS
2132 XenPci_Pdo_Suspend(WDFDEVICE device)
2134 NTSTATUS status = STATUS_SUCCESS;
2135 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2136 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2137 //LARGE_INTEGER wait_time;
2138 char path[128];
2139 PUCHAR in_ptr;
2140 UCHAR type;
2141 PVOID setting;
2142 PVOID value;
2143 PVOID value2;
2145 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
2147 if (xppdd->backend_state == XenbusStateConnected)
2149 xppdd->restart_on_resume = TRUE;
2150 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_SUSPENDING);
2152 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
2153 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
2154 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
2156 if (xppdd->assigned_resources_start != NULL)
2158 in_ptr = xppdd->assigned_resources_ptr;
2159 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
2160 in_ptr = xppdd->assigned_resources_start;
2161 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
2163 switch (type)
2165 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
2166 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
2167 EvtChn_Unbind(xpdd, PtrToUlong(value));
2168 EvtChn_Close(xpdd, PtrToUlong(value));
2169 break;
2174 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2175 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
2177 else
2179 xppdd->restart_on_resume = FALSE;
2182 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
2184 return status;
2187 NTSTATUS
2188 XenPci_Pdo_Resume(WDFDEVICE device)
2190 NTSTATUS status = STATUS_SUCCESS;
2191 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2192 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2193 ULONG old_backend_state;
2194 PUCHAR src, dst;
2196 FUNCTION_ENTER();
2197 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
2199 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
2200 old_backend_state = xppdd->backend_state;
2202 if (xppdd->restart_on_resume)
2204 status = XenPci_GetBackendAndAddWatch(device);
2206 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
2208 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
2209 // this is probably an unrecoverable situation...
2210 FUNCTION_ERROR_EXIT();
2211 return STATUS_UNSUCCESSFUL;
2213 if (xppdd->assigned_resources_ptr)
2215 // reset things - feed the 'requested resources' back in
2216 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
2217 src = xppdd->requested_resources_start;
2218 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
2219 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
2221 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
2223 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
2225 MmUnmapIoSpace(dst, xppdd->config_page_length);
2226 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
2228 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
2230 // this is definitely an unrecoverable situation...
2231 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
2232 FUNCTION_ERROR_EXIT();
2233 return STATUS_UNSUCCESSFUL;
2235 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RESUMING);
2236 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RUNNING);
2239 FUNCTION_EXIT();
2241 return STATUS_SUCCESS;
2244 #if 0
2245 NTSTATUS
2246 XenPci_Power_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
2248 NTSTATUS status;
2249 PIO_STACK_LOCATION stack;
2250 POWER_STATE_TYPE power_type;
2251 POWER_STATE power_state;
2252 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
2253 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2255 UNREFERENCED_PARAMETER(device_object);
2257 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
2259 stack = IoGetCurrentIrpStackLocation(irp);
2260 power_type = stack->Parameters.Power.Type;
2261 power_state = stack->Parameters.Power.State;
2263 switch (stack->MinorFunction)
2265 case IRP_MN_POWER_SEQUENCE:
2266 //KdPrint((__DRIVER_NAME " IRP_MN_POWER_SEQUENCE\n"));
2267 status = STATUS_NOT_SUPPORTED;
2268 break;
2269 case IRP_MN_QUERY_POWER:
2270 //KdPrint((__DRIVER_NAME " IRP_MN_QUERY_POWER\n"));
2271 status = STATUS_SUCCESS;
2272 break;
2273 case IRP_MN_SET_POWER:
2274 //KdPrint((__DRIVER_NAME " IRP_MN_SET_POWER\n"));
2275 switch (power_type) {
2276 case DevicePowerState:
2277 PoSetPowerState(device_object, power_type, power_state);
2278 status = STATUS_SUCCESS;
2279 break;
2280 case SystemPowerState:
2281 status = STATUS_SUCCESS;
2282 break;
2283 default:
2284 status = STATUS_NOT_SUPPORTED;
2285 break;
2287 break;
2288 case IRP_MN_WAIT_WAKE:
2289 //KdPrint((__DRIVER_NAME " IRP_MN_WAIT_WAKE\n"));
2290 status = STATUS_NOT_SUPPORTED;
2291 break;
2292 default:
2293 //KdPrint((__DRIVER_NAME " Unknown IRP_MN_%d\n", stack->MinorFunction));
2294 status = STATUS_NOT_SUPPORTED;
2295 break;
2297 if (status != STATUS_NOT_SUPPORTED) {
2298 irp->IoStatus.Status = status;
2301 PoStartNextPowerIrp(irp);
2302 status = irp->IoStatus.Status;
2303 IoCompleteRequest(irp, IO_NO_INCREMENT);
2305 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
2307 return status;
2310 /*
2311 Called at PASSIVE_LEVEL(?)
2312 Called during restore
2313 */
2315 static ULONG
2316 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
2318 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2319 char path[128];
2320 char *value;
2321 char *err;
2322 ULONG backend_state;
2324 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2325 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
2326 if (err)
2328 XenPci_FreeMem(err);
2329 return XenbusStateUnknown;
2331 else
2333 backend_state = atoi(value);
2334 XenPci_FreeMem(value);
2335 return backend_state;
2339 static VOID
2340 XenPci_BackEndStateHandler(char *path, PVOID context)
2342 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)context;
2343 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2344 ULONG new_backend_state;
2346 #if !DBG
2347 UNREFERENCED_PARAMETER(path);
2348 #endif
2350 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
2352 /* check that path == device/id/state */
2353 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
2354 new_backend_state = XenPci_ReadBackendState(xppdd);
2355 if (new_backend_state == XenbusStateUnknown)
2357 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
2358 return;
2359 KdPrint(("Failed to read %s, assuming closed\n", path));
2360 new_backend_state = XenbusStateClosed;
2363 if (xppdd->backend_state == new_backend_state)
2365 KdPrint((__DRIVER_NAME " state unchanged\n"));
2366 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
2367 return;
2370 xppdd->backend_state = new_backend_state;
2372 switch (xppdd->backend_state)
2374 case XenbusStateUnknown:
2375 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown (%s)\n", path));
2376 break;
2378 case XenbusStateInitialising:
2379 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising (%s)\n", path));
2380 break;
2382 case XenbusStateInitWait:
2383 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait (%s)\n", path));
2384 break;
2386 case XenbusStateInitialised:
2387 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised (%s)\n", path));
2388 break;
2390 case XenbusStateConnected:
2391 KdPrint((__DRIVER_NAME " Backend State Changed to Connected (%s)\n", path));
2392 break;
2394 case XenbusStateClosing:
2395 KdPrint((__DRIVER_NAME " Backend State Changed to Closing (%s)\n", path));
2396 if (xpdd->suspend_state == SUSPEND_STATE_NONE)
2398 if (xppdd->common.device_usage_paging
2399 || xppdd->common.device_usage_dump
2400 || xppdd->common.device_usage_hibernation)
2402 KdPrint((__DRIVER_NAME " Not closing device because it is in use\n"));
2403 /* in use by page file, dump file, or hiber file - can't close */
2404 /* we should probably re-check if the device usage changes in the future */
2406 else
2408 if (xppdd->common.current_pnp_state == Started)
2410 KdPrint((__DRIVER_NAME " Sending RequestDeviceEject\n"));
2411 IoRequestDeviceEject(xppdd->common.pdo);
2413 else
2415 KdPrint((__DRIVER_NAME " Not closing device because it is not started\n"));
2419 break;
2421 case XenbusStateClosed:
2422 KdPrint((__DRIVER_NAME " Backend State Changed to Closed (%s)\n", path));
2423 break;
2425 default:
2426 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d (%s)\n", xppdd->backend_state, path));
2427 break;
2430 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
2432 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
2434 return;
2437 struct dummy_sring {
2438 RING_IDX req_prod, req_event;
2439 RING_IDX rsp_prod, rsp_event;
2440 uint8_t pad[48];
2441 };
2443 /*
2444 Called at PASSIVE_LEVEL
2445 Called during restore
2446 */
2448 static NTSTATUS
2449 XenPci_ChangeFrontendState(PXENPCI_PDO_DEVICE_DATA xppdd, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
2451 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2452 LARGE_INTEGER timeout;
2453 ULONG remaining;
2454 ULONG thiswait;
2455 char path[128];
2457 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
2459 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
2460 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
2462 remaining = maximum_wait_ms;
2464 while (xppdd->backend_state != backend_state_response)
2466 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
2467 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
2468 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
2470 remaining -= thiswait;
2471 if (remaining == 0)
2473 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
2474 return STATUS_UNSUCCESSFUL;
2476 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
2479 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
2480 return STATUS_SUCCESS;
2483 static VOID
2484 DUMP_CURRENT_PNP_STATE(PXENPCI_PDO_DEVICE_DATA xppdd)
2486 switch (xppdd->common.current_pnp_state)
2488 case Unknown:
2489 KdPrint((__DRIVER_NAME " pnp_state = Unknown\n"));
2490 break;
2491 case NotStarted:
2492 KdPrint((__DRIVER_NAME " pnp_state = NotStarted\n"));
2493 break;
2494 case Started:
2495 KdPrint((__DRIVER_NAME " pnp_state = Started\n"));
2496 break;
2497 case StopPending:
2498 KdPrint((__DRIVER_NAME " pnp_state = StopPending\n"));
2499 break;
2500 case Stopped:
2501 KdPrint((__DRIVER_NAME " pnp_state = Stopped\n"));
2502 break;
2503 case RemovePending:
2504 KdPrint((__DRIVER_NAME " pnp_state = RemovePending\n"));
2505 break;
2506 case SurpriseRemovePending:
2507 KdPrint((__DRIVER_NAME " pnp_state = SurpriseRemovePending\n"));
2508 break;
2509 case Removed:
2510 KdPrint((__DRIVER_NAME " pnp_state = Removed\n"));
2511 break;
2512 default:
2513 KdPrint((__DRIVER_NAME " pnp_state = ???\n"));
2514 break;
2518 static NTSTATUS
2519 XenPci_EvtChn_Bind(PVOID Context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
2521 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2522 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2524 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext);
2527 static NTSTATUS
2528 XenPci_EvtChn_BindDpc(PVOID Context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
2530 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2531 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2533 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext);
2536 static NTSTATUS
2537 XenPci_EvtChn_Unbind(PVOID Context, evtchn_port_t Port)
2539 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2540 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2542 return EvtChn_Unbind(xpdd, Port);
2545 static NTSTATUS
2546 XenPci_EvtChn_Mask(PVOID Context, evtchn_port_t Port)
2548 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2549 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2551 return EvtChn_Mask(xpdd, Port);
2554 static NTSTATUS
2555 XenPci_EvtChn_Unmask(PVOID Context, evtchn_port_t Port)
2557 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2558 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2560 return EvtChn_Unmask(xpdd, Port);
2563 static NTSTATUS
2564 XenPci_EvtChn_Notify(PVOID Context, evtchn_port_t Port)
2566 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2567 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2569 return EvtChn_Notify(xpdd, Port);
2572 static BOOLEAN
2573 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port)
2575 PXENPCI_PDO_DEVICE_DATA xppdd = context;
2576 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2578 return EvtChn_AckEvent(xpdd, port);
2581 static BOOLEAN
2582 XenPci_EvtChn_Sync(PVOID context, PKSYNCHRONIZE_ROUTINE sync_routine, PVOID sync_context)
2584 PXENPCI_PDO_DEVICE_DATA xppdd = context;
2585 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2587 return KeSynchronizeExecution(xpdd->interrupt, sync_routine, sync_context);
2590 static grant_ref_t
2591 XenPci_GntTbl_GrantAccess(PVOID Context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref)
2593 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2594 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2596 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref);
2599 static BOOLEAN
2600 XenPci_GntTbl_EndAccess(PVOID Context, grant_ref_t ref, BOOLEAN keepref)
2602 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2603 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2605 return GntTbl_EndAccess(xpdd, ref, keepref);
2608 static VOID
2609 XenPci_GntTbl_PutRef(PVOID Context, grant_ref_t ref)
2611 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2612 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2614 GntTbl_PutRef(xpdd, ref);
2617 static grant_ref_t
2618 XenPci_GntTbl_GetRef(PVOID Context)
2620 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2621 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2623 return GntTbl_GetRef(xpdd);
2626 PCHAR
2627 XenPci_XenBus_Read(PVOID Context, xenbus_transaction_t xbt, char *path, char **value)
2629 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2630 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2631 return XenBus_Read(xpdd, xbt, path, value);
2634 PCHAR
2635 XenPci_XenBus_Write(PVOID Context, xenbus_transaction_t xbt, char *path, char *value)
2637 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2638 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2639 return XenBus_Write(xpdd, xbt, path, value);
2642 PCHAR
2643 XenPci_XenBus_Printf(PVOID Context, xenbus_transaction_t xbt, char *path, char *fmt, ...)
2645 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2646 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2647 //return XenBus_Printf(xpdd, xbt, path, value);
2648 UNREFERENCED_PARAMETER(Context);
2649 UNREFERENCED_PARAMETER(xbt);
2650 UNREFERENCED_PARAMETER(path);
2651 UNREFERENCED_PARAMETER(fmt);
2652 return NULL;
2655 PCHAR
2656 XenPci_XenBus_StartTransaction(PVOID Context, xenbus_transaction_t *xbt)
2658 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2659 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2660 return XenBus_StartTransaction(xpdd, xbt);
2663 PCHAR
2664 XenPci_XenBus_EndTransaction(PVOID Context, xenbus_transaction_t xbt, int abort, int *retry)
2666 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2667 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2668 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
2671 PCHAR
2672 XenPci_XenBus_List(PVOID Context, xenbus_transaction_t xbt, char *prefix, char ***contents)
2674 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2675 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2676 return XenBus_List(xpdd, xbt, prefix, contents);
2679 PCHAR
2680 XenPci_XenBus_AddWatch(PVOID Context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
2682 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2683 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2684 PCHAR retval;
2686 FUNCTION_ENTER();
2687 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
2688 if (retval == NULL)
2690 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
2692 else
2694 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
2696 FUNCTION_EXIT();
2697 return retval;
2700 PCHAR
2701 XenPci_XenBus_RemWatch(PVOID Context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
2703 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2704 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2705 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
2708 static NTSTATUS
2709 XenPci_XenShutdownDevice(PVOID Context)
2711 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2712 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2713 PUCHAR in_ptr;
2714 ULONG i;
2715 UCHAR type;
2716 PVOID setting;
2717 PVOID value;
2719 FUNCTION_ENTER();
2721 if (xppdd->backend_state == XenbusStateConnected)
2723 XenPci_ChangeFrontendState(xppdd, XenbusStateClosing, XenbusStateClosing, 30000);
2724 if (xppdd->backend_state == XenbusStateClosing)
2725 XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
2726 if (xppdd->backend_state == XenbusStateClosed)
2727 XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
2729 else
2731 if (xppdd->backend_state == XenbusStateClosing)
2732 XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
2735 if (xppdd->assigned_resources_start != NULL)
2737 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
2738 in_ptr = xppdd->assigned_resources_start;
2739 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
2741 switch (type)
2743 case XEN_INIT_TYPE_RING: /* frontend ring */
2744 FreePages(value);
2745 break;
2746 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
2747 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
2748 EvtChn_Unbind(xpdd, PtrToUlong(value));
2749 EvtChn_Close(xpdd, PtrToUlong(value));
2750 break;
2751 case XEN_INIT_TYPE_GRANT_ENTRIES:
2752 for (i = 0; i < PtrToUlong(setting); i++)
2753 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value)[i], FALSE);
2754 break;
2757 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
2758 xppdd->assigned_resources_start = NULL;
2761 FUNCTION_EXIT();
2763 return STATUS_SUCCESS;
2766 static NTSTATUS
2767 XenPci_XenConfigDevice(PVOID context);
2769 static NTSTATUS
2770 XenPci_XenConfigDeviceSpecifyBuffers(PVOID context, PUCHAR src, PUCHAR dst)
2772 PXENPCI_PDO_DEVICE_DATA xppdd = context;
2773 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2774 NTSTATUS status = STATUS_SUCCESS;
2775 ULONG i;
2776 char path[128];
2777 PCHAR setting, value, value2;
2778 PCHAR res;
2779 PVOID address;
2780 UCHAR type;
2781 PUCHAR in_ptr; //, in_start;
2782 PUCHAR out_ptr; //, out_start;
2783 XENPCI_VECTORS vectors;
2784 ULONG event_channel;
2785 ULONG run_type = 0;
2786 PMDL ring;
2787 grant_ref_t gref;
2788 BOOLEAN done_xenbus_init = FALSE;
2790 FUNCTION_ENTER();
2792 in_ptr = src;
2793 out_ptr = dst;
2795 // always add vectors
2796 vectors.magic = XEN_DATA_MAGIC;
2797 vectors.length = sizeof(XENPCI_VECTORS);
2798 vectors.context = xppdd;
2799 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
2800 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
2801 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
2802 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
2803 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
2804 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
2805 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
2806 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
2807 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
2808 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
2809 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
2810 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
2811 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
2812 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
2813 strncpy(vectors.path, xppdd->path, 128);
2814 strncpy(vectors.backend_path, xppdd->backend_path, 128);
2815 vectors.pdo_event_channel = xpdd->pdo_event_channel;
2816 vectors.XenBus_Read = XenPci_XenBus_Read;
2817 vectors.XenBus_Write = XenPci_XenBus_Write;
2818 vectors.XenBus_Printf = XenPci_XenBus_Printf;
2819 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
2820 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
2821 vectors.XenBus_List = XenPci_XenBus_List;
2822 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
2823 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
2825 if (qemu_filtered)
2826 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_ACTIVE, NULL, NULL, NULL);
2828 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
2830 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
2831 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
2833 // first pass, possibly before state == Connected
2834 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
2837 if (!done_xenbus_init)
2839 if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
2841 status = STATUS_UNSUCCESSFUL;
2842 goto error;
2844 done_xenbus_init = TRUE;
2847 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
2849 switch (type)
2851 case XEN_INIT_TYPE_RUN:
2852 run_type++;
2853 break;
2854 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
2855 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
2856 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
2857 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
2858 break;
2859 case XEN_INIT_TYPE_RING: /* frontend ring */
2860 /* we only allocate and do the SHARED_RING_INIT here */
2861 if ((ring = AllocatePage()) != 0)
2863 address = MmGetMdlVirtualAddress(ring);
2864 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
2865 SHARED_RING_INIT((struct dummy_sring *)address);
2866 if ((gref = GntTbl_GrantAccess(
2867 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
2869 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
2870 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
2871 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
2872 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
2873 // add the grant entry too so it gets freed automatically
2874 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
2875 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
2876 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
2878 else
2880 FreePages(ring);
2881 status = STATUS_UNSUCCESSFUL;
2882 goto error;
2885 else
2887 status = STATUS_UNSUCCESSFUL;
2888 goto error;
2890 break;
2891 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
2892 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
2893 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
2895 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
2896 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
2897 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
2898 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
2899 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
2900 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
2901 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
2903 else
2905 status = STATUS_UNSUCCESSFUL;
2906 goto error;
2908 break;
2911 if (!NT_SUCCESS(status))
2913 goto error;
2915 // If XEN_INIT_TYPE_RUN was specified more than once then we skip XenbusStateInitialised here and go straight to XenbusStateConnected at the end
2916 if (run_type == 1)
2918 if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialised, XenbusStateConnected, 30000) != STATUS_SUCCESS)
2920 status = STATUS_UNSUCCESSFUL;
2921 goto error;
2925 // second pass, possibly after state == Connected
2926 in_ptr = src;
2927 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
2929 switch(type)
2931 case XEN_INIT_TYPE_READ_STRING_BACK:
2932 case XEN_INIT_TYPE_READ_STRING_FRONT:
2933 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
2934 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
2935 else
2936 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
2937 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
2938 if (res)
2940 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
2941 XenPci_FreeMem(res);
2942 ADD_XEN_INIT_RSP(&out_ptr, type, setting, NULL, NULL);
2944 else
2946 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
2947 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, NULL);
2948 XenPci_FreeMem(value);
2950 break;
2951 case XEN_INIT_TYPE_VECTORS:
2952 // this is always done so ignore the request
2953 break;
2954 case XEN_INIT_TYPE_GRANT_ENTRIES:
2955 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
2956 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
2957 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
2958 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
2959 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
2960 for (i = 0; i < PtrToUlong(value); i++)
2962 gref = GntTbl_GetRef(xpdd);
2963 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
2964 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
2966 break;
2969 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL);
2971 if (run_type)
2973 if (XenPci_ChangeFrontendState(xppdd, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
2975 status = STATUS_UNSUCCESSFUL;
2976 goto error;
2979 FUNCTION_EXIT();
2980 return status;
2982 error:
2983 XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
2984 FUNCTION_EXIT_STATUS(status);
2986 return status;
2989 static NTSTATUS
2990 XenPci_XenConfigDevice(PVOID context)
2992 NTSTATUS status;
2993 PUCHAR src, dst;
2994 PXENPCI_PDO_DEVICE_DATA xppdd = context;
2996 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
2997 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
2998 memcpy(src, dst, xppdd->config_page_length);
3000 status = XenPci_XenConfigDeviceSpecifyBuffers(xppdd, src, dst);
3002 MmUnmapIoSpace(dst, xppdd->config_page_length);
3003 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
3005 return status;
3008 static NTSTATUS
3009 XenPci_GetBackendAndAddWatch(PDEVICE_OBJECT device_object)
3011 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3012 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
3013 char path[128];
3014 PCHAR res;
3015 PCHAR value;
3017 /* Get backend path */
3018 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
3019 "%s/backend", xppdd->path);
3020 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
3021 if (res)
3023 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
3024 XenPci_FreeMem(res);
3025 return STATUS_UNSUCCESSFUL;
3027 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
3028 XenPci_FreeMem(value);
3030 /* Add watch on backend state */
3031 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
3032 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
3034 return STATUS_SUCCESS;
3037 NTSTATUS
3038 XenPci_Pdo_Resume(PDEVICE_OBJECT device_object)
3040 NTSTATUS status;
3041 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3042 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
3043 ULONG old_backend_state;
3044 PUCHAR src, dst;
3046 FUNCTION_ENTER();
3048 old_backend_state = xppdd->backend_state;
3050 if (xppdd->restart_on_resume)
3052 status = XenPci_GetBackendAndAddWatch(device_object);
3054 if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
3056 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
3057 // this is probably an unrecoverable situation...
3058 FUNCTION_ERROR_EXIT();
3059 return STATUS_UNSUCCESSFUL;
3061 if (xppdd->assigned_resources_ptr)
3063 // reset things - feed the 'requested resources' back in
3064 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL);
3065 src = xppdd->requested_resources_start;
3066 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
3067 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
3069 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
3071 status = XenPci_XenConfigDeviceSpecifyBuffers(xppdd, src, dst);
3073 MmUnmapIoSpace(dst, xppdd->config_page_length);
3074 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
3076 if (XenPci_ChangeFrontendState(xppdd, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
3078 // this is definitely an unrecoverable situation...
3079 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
3080 FUNCTION_ERROR_EXIT();
3081 return STATUS_UNSUCCESSFUL;
3084 else
3086 KdPrint((__DRIVER_NAME " Not resuming - current_pnp_state = %d, old_backend_state = %d\n", xppdd->common.current_pnp_state, old_backend_state));
3088 KeMemoryBarrier();
3089 xppdd->device_state.resume_state = RESUME_STATE_FRONTEND_RESUME;
3090 KeMemoryBarrier();
3091 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
3093 FUNCTION_EXIT();
3095 return STATUS_SUCCESS;
3098 /* called at PASSIVE_LEVEL */
3099 NTSTATUS
3100 XenPci_Pdo_Suspend(PDEVICE_OBJECT device_object)
3102 NTSTATUS status = STATUS_SUCCESS;
3103 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3104 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
3105 LARGE_INTEGER wait_time;
3106 char path[128];
3107 PUCHAR in_ptr;
3108 UCHAR type;
3109 PVOID setting;
3110 PVOID value;
3112 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
3114 if (xppdd->backend_state == XenbusStateConnected)
3116 xppdd->restart_on_resume = TRUE;
3117 xppdd->device_state.resume_state_ack = RESUME_STATE_RUNNING;
3118 KeMemoryBarrier();
3119 xppdd->device_state.resume_state = RESUME_STATE_SUSPENDING;
3120 KeMemoryBarrier();
3121 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
3122 while(xppdd->device_state.resume_state_ack != RESUME_STATE_SUSPENDING)
3124 KdPrint((__DRIVER_NAME " Starting delay - resume_state = %d, resume_state_ack = %d\n", xppdd->device_state.resume_state, xppdd->device_state.resume_state_ack));
3125 wait_time.QuadPart = 100 * (-1 * 10 * 1000);
3126 KeDelayExecutionThread(KernelMode, FALSE, &wait_time);
3127 KdPrint((__DRIVER_NAME " Done with delay\n"));
3129 KdPrint((__DRIVER_NAME " resume_state acknowledged\n"));
3131 XenPci_ChangeFrontendState(xppdd, XenbusStateClosing, XenbusStateClosing, 30000);
3132 XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
3133 XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
3135 if (xppdd->assigned_resources_start != NULL)
3137 in_ptr = xppdd->assigned_resources_ptr;
3138 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL);
3139 in_ptr = xppdd->assigned_resources_start;
3140 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value)) != XEN_INIT_TYPE_END)
3142 switch (type)
3144 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
3145 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
3146 EvtChn_Close(xpdd, PtrToUlong(value));
3147 break;
3152 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
3153 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
3155 else
3157 xppdd->restart_on_resume = FALSE;
3160 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
3162 return status;
3165 VOID
3166 XenPci_DumpPdoConfig(PDEVICE_OBJECT device_object)
3168 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3170 #if !DBG
3171 UNREFERENCED_PARAMETER(xppdd);
3172 #endif
3174 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
3175 KdPrint((__DRIVER_NAME " backend_path = %s\n", xppdd->backend_path));
3176 KdPrint((__DRIVER_NAME " irq_number = %d\n", xppdd->irq_number));
3177 KdPrint((__DRIVER_NAME " irq_level = %d\n", xppdd->irq_level));
3178 KdPrint((__DRIVER_NAME " irq_vector = %x\n", xppdd->irq_vector));
3181 static PMDL
3182 XenConfig_MakeConfigPage(PDEVICE_OBJECT device_object)
3184 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
3185 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3186 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
3187 PMDL mdl;
3188 PUCHAR ptr;
3189 PDEVICE_OBJECT curr, prev;
3190 PDRIVER_OBJECT fdo_driver_object;
3191 PUCHAR fdo_driver_extension;
3193 mdl = AllocateUncachedPage();
3194 ptr = MmGetMdlVirtualAddress(mdl);
3195 curr = IoGetAttachedDeviceReference(device_object);
3196 while (curr != NULL)
3198 fdo_driver_object = curr->DriverObject;
3199 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
3200 if (fdo_driver_object)
3202 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
3203 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
3204 if (fdo_driver_extension)
3206 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
3207 ObDereferenceObject(curr);
3208 break;
3211 prev = curr;
3212 curr = IoGetLowerDeviceObject(curr);
3213 ObDereferenceObject(prev);
3215 return mdl;
3218 static NTSTATUS
3219 XenPci_Pnp_StartDevice(PDEVICE_OBJECT device_object, PIRP irp)
3221 NTSTATUS status = STATUS_SUCCESS;
3222 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3223 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
3224 PIO_STACK_LOCATION stack;
3225 PCM_PARTIAL_RESOURCE_LIST prl;
3226 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
3227 ULONG i;
3228 char path[128];
3229 PMDL mdl;
3231 FUNCTION_ENTER();
3232 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
3234 DUMP_CURRENT_PNP_STATE(xppdd);
3236 stack = IoGetCurrentIrpStackLocation(irp);
3238 status = XenPci_GetBackendAndAddWatch(device_object);
3239 if (!NT_SUCCESS(status)) {
3240 FUNCTION_ERROR_EXIT();
3241 return status;
3244 mdl = XenConfig_MakeConfigPage(device_object);
3246 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
3247 for (i = 0; i < prl->Count; i++)
3249 prd = & prl->PartialDescriptors[i];
3250 switch (prd->Type)
3252 #if 0
3253 case CmResourceTypeInterrupt:
3254 KdPrint((__DRIVER_NAME " CmResourceTypeInterrupt\n"));
3255 KdPrint((__DRIVER_NAME " irq_number = %02x\n", prd->u.Interrupt.Vector));
3256 xppdd->irq_number = prd->u.Interrupt.Vector;
3257 break;
3258 #endif
3259 case CmResourceTypeMemory:
3260 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
3262 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
3263 prd->u.Memory.Length = MmGetMdlByteCount(mdl);
3265 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
3267 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
3268 prd->Type = CmResourceTypeInterrupt;
3269 prd->ShareDisposition = CmResourceShareShared;
3270 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
3271 prd->u.Interrupt.Level = xpdd->irq_number;
3272 prd->u.Interrupt.Vector = xpdd->irq_number;
3273 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
3274 xppdd->irq_number = xpdd->irq_number;
3276 break;
3280 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
3281 for (i = 0; i < prl->Count; i++)
3283 prd = & prl->PartialDescriptors[i];
3284 switch (prd->Type)
3286 #if 0
3287 case CmResourceTypeInterrupt:
3288 KdPrint((__DRIVER_NAME " CmResourceTypeInterrupt (%d)\n", i));
3289 KdPrint((__DRIVER_NAME " irq_vector = %02x\n", prd->u.Interrupt.Vector));
3290 KdPrint((__DRIVER_NAME " irq_level = %d\n", prd->u.Interrupt.Level));
3291 xppdd->irq_vector = prd->u.Interrupt.Vector;
3292 xppdd->irq_level = (KIRQL)prd->u.Interrupt.Level;
3293 break;
3294 #endif
3295 case CmResourceTypeMemory:
3296 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
3297 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
3298 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
3300 if (prd->u.Memory.Length == 0)
3302 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(mdl)[0]));
3303 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
3304 prd->u.Memory.Length = MmGetMdlByteCount(mdl);
3305 KdPrint((__DRIVER_NAME " New Start = %08x%08x, Length = %d\n", prd->u.Memory.Start.HighPart, prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
3307 xppdd->config_page_phys = prd->u.Memory.Start;
3308 xppdd->config_page_length = prd->u.Memory.Length;
3309 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
3310 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
3312 status = XenPci_XenConfigDevice(xppdd);
3313 if (!NT_SUCCESS(status))
3315 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
3316 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
3317 FUNCTION_ERROR_EXIT();
3318 return status;
3321 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
3323 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
3324 prd->Type = CmResourceTypeInterrupt;
3325 prd->ShareDisposition = CmResourceShareShared;
3326 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
3327 prd->u.Interrupt.Level = xpdd->irq_level;
3328 prd->u.Interrupt.Vector = xpdd->irq_vector;
3329 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
3330 xppdd->irq_vector = xpdd->irq_vector;
3331 xppdd->irq_level = xpdd->irq_level;
3333 break;
3337 SET_PNP_STATE(&xppdd->common, Started);
3339 FUNCTION_EXIT();
3341 return STATUS_SUCCESS;
3344 static NTSTATUS
3345 XenPci_Pnp_RemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
3347 NTSTATUS status = STATUS_SUCCESS;
3348 PXENPCI_PDO_DEVICE_DATA xppdd = device_object->DeviceExtension;
3349 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
3350 char path[128];
3352 UNREFERENCED_PARAMETER(irp);
3354 FUNCTION_ENTER();
3356 DUMP_CURRENT_PNP_STATE(xppdd);
3358 if (xppdd->common.current_pnp_state != Removed)
3360 status = XenPci_XenShutdownDevice(xppdd);
3361 /* Remove watch on backend state */
3362 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
3363 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
3364 SET_PNP_STATE(&xppdd->common, Removed);
3365 IoInvalidateDeviceRelations(xppdd->bus_pdo, BusRelations);
3367 if (xppdd->reported_missing)
3369 IoDeleteDevice(xppdd->common.pdo);
3372 FUNCTION_EXIT_STATUS(status);
3374 return status;
3377 static NTSTATUS
3378 XenPci_QueryResourceRequirements(PDEVICE_OBJECT device_object, PIRP irp)
3380 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3381 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
3382 PIO_RESOURCE_REQUIREMENTS_LIST irrl;
3383 PIO_RESOURCE_DESCRIPTOR ird;
3384 ULONG length;
3386 UNREFERENCED_PARAMETER(device_object);
3388 FUNCTION_ENTER();
3390 length = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List) +
3391 FIELD_OFFSET(IO_RESOURCE_LIST, Descriptors) +
3392 sizeof(IO_RESOURCE_DESCRIPTOR) * 2;
3393 irrl = ExAllocatePoolWithTag(NonPagedPool,
3394 length,
3395 XENPCI_POOL_TAG);
3397 irrl->ListSize = length;
3398 irrl->InterfaceType = PNPBus; //Internal;
3399 irrl->BusNumber = 0;
3400 irrl->SlotNumber = 0;
3401 irrl->AlternativeLists = 1;
3402 irrl->List[0].Version = 1;
3403 irrl->List[0].Revision = 1;
3404 irrl->List[0].Count = 0;
3406 #if 0
3407 ird = &irrl->List[0].Descriptors[irrl->List[0].Count++];
3408 ird->Option = 0;
3409 ird->Type = CmResourceTypeInterrupt;
3410 ird->ShareDisposition = CmResourceShareShared;
3411 ird->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
3412 KdPrint((__DRIVER_NAME " irq type = %s\n", (xpdd->irq_mode == Latched)?"Latched":"Level"));
3413 ird->u.Interrupt.MinimumVector = xpdd->irq_number;
3414 ird->u.Interrupt.MaximumVector = xpdd->irq_number;
3415 #endif
3417 ird = &irrl->List[0].Descriptors[irrl->List[0].Count++];
3418 ird->Option = 0;
3419 ird->Type = CmResourceTypeMemory;
3420 ird->ShareDisposition = CmResourceShareShared;
3421 ird->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
3422 ird->u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
3423 ird->u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
3424 ird->u.Memory.Length = 0;
3425 ird->u.Memory.Alignment = PAGE_SIZE;
3427 ird = &irrl->List[0].Descriptors[irrl->List[0].Count++];
3428 ird->Option = 0;
3429 ird->Type = CmResourceTypeMemory;
3430 ird->ShareDisposition = CmResourceShareShared;
3431 ird->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
3432 ird->u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
3433 ird->u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
3434 ird->u.Memory.Length = 0;
3435 ird->u.Memory.Alignment = PAGE_SIZE;
3437 irp->IoStatus.Information = (ULONG_PTR)irrl;
3439 FUNCTION_EXIT();
3441 return STATUS_SUCCESS;
3444 static NTSTATUS
3445 XenPci_Pnp_QueryTargetRelations(PDEVICE_OBJECT device_object, PIRP irp)
3447 PDEVICE_RELATIONS dr;
3448 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3450 dr = (PDEVICE_RELATIONS)ExAllocatePoolWithTag (PagedPool, sizeof(DEVICE_RELATIONS), XENPCI_POOL_TAG);
3451 dr->Count = 1;
3452 dr->Objects[0] = xppdd->common.pdo;
3453 ObReferenceObject(xppdd->common.pdo);
3454 irp->IoStatus.Information = (ULONG_PTR)dr;
3456 return STATUS_SUCCESS;
3459 static NTSTATUS
3460 XenPci_Pnp_QueryCapabilities(PDEVICE_OBJECT device_object, PIRP irp)
3462 PIO_STACK_LOCATION stack;
3463 PDEVICE_CAPABILITIES dc;
3465 UNREFERENCED_PARAMETER(device_object);
3467 stack = IoGetCurrentIrpStackLocation(irp);
3468 dc = stack->Parameters.DeviceCapabilities.Capabilities;
3469 dc->LockSupported = FALSE;
3470 dc->EjectSupported = TRUE;
3471 dc->Removable = TRUE;
3472 dc->DockDevice = FALSE;
3473 dc->UniqueID = FALSE;
3474 dc->SilentInstall = TRUE; //FALSE;
3475 dc->RawDeviceOK = FALSE;
3476 dc->SurpriseRemovalOK = TRUE;
3477 dc->HardwareDisabled = FALSE;
3478 dc->NoDisplayInUI = FALSE;
3479 dc->DeviceWake = PowerDeviceUnspecified;
3480 dc->D1Latency = 0;
3481 dc->D2Latency = 0;
3482 dc->D3Latency = 0;
3483 /* we are really supposed to get the DeviceState entries from the parent... */
3484 dc->DeviceState[PowerSystemWorking] = PowerDeviceD0;
3485 dc->DeviceState[PowerSystemSleeping1] = PowerDeviceUnspecified;
3486 dc->DeviceState[PowerSystemSleeping2] = PowerDeviceUnspecified;
3487 dc->DeviceState[PowerSystemSleeping3] = PowerDeviceUnspecified;
3488 dc->DeviceState[PowerSystemHibernate] = PowerDeviceD3;
3489 dc->DeviceState[PowerSystemShutdown] = PowerDeviceD3;
3490 return STATUS_SUCCESS;
3493 static VOID
3494 XenPci_IS_InterfaceReference(PVOID context)
3496 UNREFERENCED_PARAMETER(context);
3497 FUNCTION_ENTER();
3498 FUNCTION_EXIT();
3501 static VOID
3502 XenPci_IS_InterfaceDereference(PVOID context)
3504 UNREFERENCED_PARAMETER(context);
3505 FUNCTION_ENTER();
3506 FUNCTION_EXIT();
3509 static BOOLEAN
3510 XenPci_BIS_TranslateBusAddress(PVOID context, PHYSICAL_ADDRESS bus_address, ULONG length, PULONG address_space, PPHYSICAL_ADDRESS translated_address)
3512 UNREFERENCED_PARAMETER(context);
3513 UNREFERENCED_PARAMETER(length);
3514 /* actually this isn't right - should look up the gref for the physical address and work backwards from that */
3515 FUNCTION_ENTER();
3516 if (*address_space != 0)
3518 KdPrint((__DRIVER_NAME " Cannot map I/O space\n"));
3519 FUNCTION_EXIT();
3520 return FALSE;
3522 *translated_address = bus_address;
3523 FUNCTION_EXIT();
3524 return TRUE;
3527 static VOID
3528 XenPci_DOP_PutDmaAdapter(PDMA_ADAPTER dma_adapter)
3530 UNREFERENCED_PARAMETER(dma_adapter);
3532 FUNCTION_ENTER();
3533 // decrement ref count
3534 FUNCTION_EXIT();
3536 return;
3539 static PVOID
3540 XenPci_DOP_AllocateCommonBuffer(
3541 PDMA_ADAPTER DmaAdapter,
3542 ULONG Length,
3543 PPHYSICAL_ADDRESS LogicalAddress,
3544 BOOLEAN CacheEnabled
3547 xen_dma_adapter_t *xen_dma_adapter;
3548 PXENPCI_DEVICE_DATA xpdd;
3549 PVOID buffer;
3550 PFN_NUMBER pfn;
3551 grant_ref_t gref;
3553 UNREFERENCED_PARAMETER(DmaAdapter);
3554 UNREFERENCED_PARAMETER(CacheEnabled);
3556 //FUNCTION_ENTER();
3558 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
3559 xpdd = xen_dma_adapter->xppdd->bus_fdo->DeviceExtension;
3561 //KdPrint((__DRIVER_NAME " Length = %d\n", Length));
3563 buffer = ExAllocatePoolWithTag(NonPagedPool, Length, XENPCI_POOL_TAG);
3565 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(buffer).QuadPart >> PAGE_SHIFT);
3566 ASSERT(pfn);
3567 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, pfn, FALSE, INVALID_GRANT_REF);
3568 ASSERT(gref);
3569 LogicalAddress->QuadPart = (gref << PAGE_SHIFT) | (PtrToUlong(buffer) & (PAGE_SIZE - 1));
3571 //FUNCTION_EXIT();
3572 return buffer;
3575 static VOID
3576 XenPci_DOP_FreeCommonBuffer(
3577 PDMA_ADAPTER DmaAdapter,
3578 ULONG Length,
3579 PHYSICAL_ADDRESS LogicalAddress,
3580 PVOID VirtualAddress,
3581 BOOLEAN CacheEnabled
3584 UNREFERENCED_PARAMETER(DmaAdapter);
3585 UNREFERENCED_PARAMETER(Length);
3586 UNREFERENCED_PARAMETER(LogicalAddress);
3587 UNREFERENCED_PARAMETER(CacheEnabled);
3589 FUNCTION_ENTER();
3590 ExFreePoolWithTag(VirtualAddress, XENPCI_POOL_TAG);
3591 // TODO: free the grant ref here
3592 FUNCTION_EXIT();
3595 static NTSTATUS
3596 XenPci_DOP_AllocateAdapterChannel(
3597 IN PDMA_ADAPTER DmaAdapter,
3598 IN PDEVICE_OBJECT DeviceObject,
3599 IN ULONG NumberOfMapRegisters,
3600 IN PDRIVER_CONTROL ExecutionRoutine,
3601 IN PVOID Context
3604 IO_ALLOCATION_ACTION action;
3606 UNREFERENCED_PARAMETER(DmaAdapter);
3607 UNREFERENCED_PARAMETER(NumberOfMapRegisters);
3609 FUNCTION_ENTER();
3610 action = ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, UlongToPtr(64), Context);
3612 switch (action)
3614 case KeepObject:
3615 KdPrint((__DRIVER_NAME " KeepObject\n"));
3616 break;
3617 case DeallocateObject:
3618 KdPrint((__DRIVER_NAME " DeallocateObject\n"));
3619 break;
3620 case DeallocateObjectKeepRegisters:
3621 KdPrint((__DRIVER_NAME " DeallocateObjectKeepRegisters\n"));
3622 break;
3623 default:
3624 KdPrint((__DRIVER_NAME " Unknown action %d\n", action));
3625 break;
3627 FUNCTION_EXIT();
3628 return STATUS_SUCCESS;
3631 static BOOLEAN
3632 XenPci_DOP_FlushAdapterBuffers(
3633 PDMA_ADAPTER DmaAdapter,
3634 PMDL Mdl,
3635 PVOID MapRegisterBase,
3636 PVOID CurrentVa,
3637 ULONG Length,
3638 BOOLEAN WriteToDevice)
3640 UNREFERENCED_PARAMETER(DmaAdapter);
3641 UNREFERENCED_PARAMETER( Mdl);
3642 UNREFERENCED_PARAMETER(MapRegisterBase);
3643 UNREFERENCED_PARAMETER(CurrentVa);
3644 UNREFERENCED_PARAMETER(Length);
3645 UNREFERENCED_PARAMETER(WriteToDevice);
3647 FUNCTION_ENTER();
3648 FUNCTION_EXIT();
3649 return TRUE;
3652 static VOID
3653 XenPci_DOP_FreeAdapterChannel(
3654 IN PDMA_ADAPTER DmaAdapter
3657 UNREFERENCED_PARAMETER(DmaAdapter);
3659 FUNCTION_ENTER();
3660 FUNCTION_EXIT();
3663 static VOID
3664 XenPci_DOP_FreeMapRegisters(
3665 PDMA_ADAPTER DmaAdapter,
3666 PVOID MapRegisterBase,
3667 ULONG NumberOfMapRegisters)
3669 UNREFERENCED_PARAMETER(DmaAdapter);
3670 UNREFERENCED_PARAMETER(MapRegisterBase);
3671 UNREFERENCED_PARAMETER(NumberOfMapRegisters);
3673 FUNCTION_ENTER();
3674 FUNCTION_EXIT();
3677 static PHYSICAL_ADDRESS
3678 XenPci_DOP_MapTransfer(
3679 PDMA_ADAPTER DmaAdapter,
3680 PMDL Mdl,
3681 PVOID MapRegisterBase,
3682 PVOID CurrentVa,
3683 PULONG Length,
3684 BOOLEAN WriteToDevice)
3686 PHYSICAL_ADDRESS physical;
3688 UNREFERENCED_PARAMETER(DmaAdapter);
3689 UNREFERENCED_PARAMETER(Mdl);
3690 UNREFERENCED_PARAMETER(MapRegisterBase);
3691 UNREFERENCED_PARAMETER(CurrentVa);
3692 UNREFERENCED_PARAMETER(Length);
3693 UNREFERENCED_PARAMETER(WriteToDevice);
3695 FUNCTION_ENTER();
3697 physical.QuadPart = 0;
3699 FUNCTION_EXIT();
3700 return physical;
3703 static ULONG
3704 XenPci_DOP_GetDmaAlignment(
3705 PDMA_ADAPTER DmaAdapter)
3707 UNREFERENCED_PARAMETER(DmaAdapter);
3709 FUNCTION_ENTER();
3710 FUNCTION_EXIT();
3711 return 0;
3714 static ULONG
3715 XenPci_DOP_ReadDmaCounter(
3716 PDMA_ADAPTER DmaAdapter)
3718 UNREFERENCED_PARAMETER(DmaAdapter);
3720 FUNCTION_ENTER();
3721 FUNCTION_EXIT();
3722 return 0;
3725 static NTSTATUS
3726 XenPci_DOP_GetScatterGatherList(
3727 PDMA_ADAPTER DmaAdapter,
3728 PDEVICE_OBJECT DeviceObject,
3729 PMDL Mdl,
3730 PVOID CurrentVa,
3731 ULONG Length,
3732 PDRIVER_LIST_CONTROL ExecutionRoutine,
3733 PVOID Context,
3734 BOOLEAN WriteToDevice)
3736 UNREFERENCED_PARAMETER(DmaAdapter);
3737 UNREFERENCED_PARAMETER(DeviceObject);
3738 UNREFERENCED_PARAMETER(Mdl);
3739 UNREFERENCED_PARAMETER(CurrentVa);
3740 UNREFERENCED_PARAMETER(Length);
3741 UNREFERENCED_PARAMETER(ExecutionRoutine);
3742 UNREFERENCED_PARAMETER(Context);
3743 UNREFERENCED_PARAMETER(WriteToDevice);
3745 FUNCTION_ENTER();
3746 FUNCTION_EXIT();
3747 return STATUS_SUCCESS;
3750 #define MAP_TYPE_VIRTUAL 1
3751 #define MAP_TYPE_MDL 2
3752 #define MAP_TYPE_REMAPPED 3
3754 typedef struct {
3755 ULONG map_type;
3756 PVOID aligned_buffer;
3757 PVOID unaligned_buffer;
3758 ULONG copy_length;
3759 } sg_extra_t;
3761 static VOID
3762 XenPci_DOP_PutScatterGatherList(
3763 IN PDMA_ADAPTER DmaAdapter,
3764 IN PSCATTER_GATHER_LIST ScatterGather,
3765 IN BOOLEAN WriteToDevice
3768 xen_dma_adapter_t *xen_dma_adapter;
3769 PXENPCI_DEVICE_DATA xpdd;
3770 ULONG i;
3771 sg_extra_t *sg_extra;
3773 UNREFERENCED_PARAMETER(WriteToDevice);
3775 //FUNCTION_ENTER();
3777 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
3778 xpdd = xen_dma_adapter->xppdd->bus_fdo->DeviceExtension;
3780 sg_extra = (sg_extra_t *)((PUCHAR)ScatterGather + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
3781 (sizeof(SCATTER_GATHER_ELEMENT)) * ScatterGather->NumberOfElements);
3783 switch (sg_extra->map_type)
3785 case MAP_TYPE_REMAPPED:
3786 for (i = 0; i < ScatterGather->NumberOfElements; i++)
3788 grant_ref_t gref;
3789 gref = (grant_ref_t)(ScatterGather->Elements[i].Address.QuadPart >> PAGE_SHIFT);
3790 GntTbl_EndAccess(xpdd, gref, FALSE);
3791 ScatterGather->Elements[i].Address.QuadPart = -1;
3793 if (!WriteToDevice)
3794 memcpy(sg_extra->unaligned_buffer, sg_extra->aligned_buffer, sg_extra->copy_length);
3795 ExFreePoolWithTag(sg_extra->aligned_buffer, XENPCI_POOL_TAG);
3796 break;
3797 case MAP_TYPE_MDL:
3798 for (i = 0; i < ScatterGather->NumberOfElements; i++)
3800 grant_ref_t gref;
3801 gref = (grant_ref_t)(ScatterGather->Elements[i].Address.QuadPart >> PAGE_SHIFT);
3802 GntTbl_EndAccess(xpdd, gref, FALSE);
3803 ScatterGather->Elements[i].Address.QuadPart = -1;
3805 break;
3806 case MAP_TYPE_VIRTUAL:
3807 break;
3809 //FUNCTION_EXIT();
3812 static NTSTATUS
3813 XenPci_DOP_CalculateScatterGatherList(
3814 PDMA_ADAPTER DmaAdapter,
3815 PMDL Mdl,
3816 PVOID CurrentVa,
3817 ULONG Length,
3818 PULONG ScatterGatherListSize,
3819 PULONG NumberOfMapRegisters
3822 ULONG elements;
3823 PMDL curr_mdl;
3825 UNREFERENCED_PARAMETER(DmaAdapter);
3826 UNREFERENCED_PARAMETER(Mdl);
3828 FUNCTION_ENTER();
3830 KdPrint((__DRIVER_NAME " Mdl = %p\n", Mdl));
3831 KdPrint((__DRIVER_NAME " CurrentVa = %p\n", CurrentVa));
3832 KdPrint((__DRIVER_NAME " Length = %d\n", Length));
3833 if (Mdl)
3835 for (curr_mdl = Mdl, elements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
3836 elements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(CurrentVa, Length);
3838 else
3840 elements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, Length) + 1;
3843 *ScatterGatherListSize = FIELD_OFFSET(SCATTER_GATHER_LIST, Elements)
3844 + sizeof(SCATTER_GATHER_ELEMENT) * elements
3845 + sizeof(sg_extra_t);
3846 if (NumberOfMapRegisters)
3847 *NumberOfMapRegisters = 1;
3849 KdPrint((__DRIVER_NAME " ScatterGatherListSize = %d\n", *ScatterGatherListSize));
3851 FUNCTION_EXIT();
3852 return STATUS_SUCCESS;
3855 static NTSTATUS
3856 XenPci_DOP_BuildScatterGatherList(
3857 IN PDMA_ADAPTER DmaAdapter,
3858 IN PDEVICE_OBJECT DeviceObject,
3859 IN PMDL Mdl,
3860 IN PVOID CurrentVa,
3861 IN ULONG Length,
3862 IN PDRIVER_LIST_CONTROL ExecutionRoutine,
3863 IN PVOID Context,
3864 IN BOOLEAN WriteToDevice,
3865 IN PVOID ScatterGatherBuffer,
3866 IN ULONG ScatterGatherBufferLength)
3868 ULONG i;
3869 PSCATTER_GATHER_LIST sglist = ScatterGatherBuffer;
3870 PUCHAR ptr;
3871 ULONG remaining = Length;
3872 ULONG total_remaining;
3873 xen_dma_adapter_t *xen_dma_adapter;
3874 PXENPCI_DEVICE_DATA xpdd;
3875 sg_extra_t *sg_extra;
3876 PMDL curr_mdl;
3877 ULONG map_type;
3878 ULONG sg_element;
3879 ULONG offset;
3880 PFN_NUMBER pfn;
3881 grant_ref_t gref;
3883 UNREFERENCED_PARAMETER(WriteToDevice);
3885 //FUNCTION_ENTER();
3887 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
3888 xpdd = xen_dma_adapter->xppdd->bus_fdo->DeviceExtension;
3890 ASSERT(Mdl);
3891 if (xen_dma_adapter->dma_extension)
3893 if (xen_dma_adapter->dma_extension->need_virtual_address(DeviceObject->CurrentIrp))
3895 ASSERT(!Mdl->Next); /* can only virtual a single buffer */
3896 map_type = MAP_TYPE_VIRTUAL;
3897 sglist->NumberOfElements = 1;
3899 else
3901 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(DeviceObject->CurrentIrp);
3902 if (PtrToUlong(CurrentVa) & (alignment - 1))
3904 ASSERT(!Mdl->Next); /* can only remap a single buffer */
3905 map_type = MAP_TYPE_REMAPPED;
3906 sglist->NumberOfElements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(NULL, Length);
3908 else
3910 map_type = MAP_TYPE_MDL;
3911 for (curr_mdl = Mdl, sglist->NumberOfElements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
3912 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
3913 MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
3917 else
3919 map_type = MAP_TYPE_MDL;
3920 for (curr_mdl = Mdl, sglist->NumberOfElements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
3921 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
3922 MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
3924 if (ScatterGatherBufferLength < FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
3925 sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t))
3927 return STATUS_BUFFER_TOO_SMALL;
3930 sg_extra = (sg_extra_t *)((PUCHAR)sglist + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
3931 (sizeof(SCATTER_GATHER_ELEMENT)) * sglist->NumberOfElements);
3933 sg_extra->map_type = map_type;
3934 switch (map_type)
3936 case MAP_TYPE_MDL:
3937 KdPrint((__DRIVER_NAME " MAP_TYPE_MDL - %p\n", CurrentVa));
3938 total_remaining = Length;
3939 for (sg_element = 0, curr_mdl = Mdl; curr_mdl; curr_mdl = curr_mdl->Next)
3941 remaining = MmGetMdlByteCount(curr_mdl);
3942 if (!MmGetMdlByteOffset(Mdl) && (PtrToUlong(CurrentVa) & (PAGE_SIZE - 1)))
3943 offset = (PtrToUlong(CurrentVa) & (PAGE_SIZE - 1));
3944 else
3945 offset = MmGetMdlByteOffset(curr_mdl);
3946 for (i = 0; i < ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)); i++)
3948 //KdPrint((__DRIVER_NAME " element = %d\n", sg_element));
3949 //KdPrint((__DRIVER_NAME " remaining = %d\n", remaining));
3950 pfn = MmGetMdlPfnArray(curr_mdl)[i];
3951 ASSERT(pfn);
3952 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, pfn, FALSE, INVALID_GRANT_REF);
3953 ASSERT(gref != INVALID_GRANT_REF);
3954 sglist->Elements[sg_element].Address.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | offset;
3955 sglist->Elements[sg_element].Length = min(min(PAGE_SIZE - offset, remaining), total_remaining);
3956 total_remaining -= sglist->Elements[sg_element].Length;
3957 remaining -= sglist->Elements[sg_element].Length;
3958 offset = 0;
3959 sg_element++;
3962 break;
3963 case MAP_TYPE_REMAPPED:
3964 sg_extra->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, max(Length, PAGE_SIZE), XENPCI_POOL_TAG);
3965 ASSERT(sg_extra->aligned_buffer); /* lazy */
3966 KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED - %p -> %p\n", CurrentVa, sg_extra->aligned_buffer));
3967 sg_extra->unaligned_buffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
3968 ASSERT(sg_extra->unaligned_buffer); /* lazy */
3969 if (!MmGetMdlByteOffset(Mdl) && (PtrToUlong(CurrentVa) & (PAGE_SIZE - 1)))
3970 sg_extra->unaligned_buffer = (PUCHAR)sg_extra->unaligned_buffer + (PtrToUlong(CurrentVa) & (PAGE_SIZE - 1));
3971 sg_extra->copy_length = Length;
3972 if (WriteToDevice)
3973 memcpy(sg_extra->aligned_buffer, sg_extra->unaligned_buffer, sg_extra->copy_length);
3974 for (sg_element = 0, remaining = Length;
3975 sg_element < ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_extra->aligned_buffer, Length); sg_element++)
3977 pfn = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)sg_extra->aligned_buffer + (sg_element << PAGE_SHIFT)).QuadPart >> PAGE_SHIFT);
3978 ASSERT(pfn);
3979 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, pfn, FALSE, INVALID_GRANT_REF);
3980 ASSERT(gref);
3981 sglist->Elements[sg_element].Address.QuadPart = (ULONGLONG)gref << PAGE_SHIFT;
3982 sglist->Elements[sg_element].Length = min(PAGE_SIZE, remaining);
3983 remaining -= sglist->Elements[sg_element].Length;
3985 break;
3986 case MAP_TYPE_VIRTUAL:
3987 KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL\n"));
3988 ptr = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
3989 ASSERT(ptr); /* lazy */
3990 if (!MmGetMdlByteOffset(Mdl) && (PtrToUlong(CurrentVa) & (PAGE_SIZE - 1)))
3991 ptr += (PtrToUlong(CurrentVa) & (PAGE_SIZE - 1));
3992 sglist->Elements[0].Address.QuadPart = (ULONGLONG)ptr;
3993 sglist->Elements[0].Length = Length;
3994 break;
3996 #if 0
3997 KdPrint((__DRIVER_NAME " Mdl = %p, CurrentVa = %p, Mdl->Va = %p, Offset = %d, Length = %d\n",
3998 Mdl, CurrentVa, MmGetMdlVirtualAddress(Mdl), MmGetMdlByteOffset(Mdl), Length));
3999 for (i = 0; i < sglist->NumberOfElements; i++)
4001 KdPrint((__DRIVER_NAME " sge[%d]->Address = %08x%08x, Length = %d\n", i, sglist->Elements[i].Address.HighPart,
4002 sglist->Elements[i].Address.LowPart, sglist->Elements[i].Length));
4004 #endif
4005 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, ScatterGatherBuffer, Context);
4007 //FUNCTION_EXIT();
4009 return STATUS_SUCCESS;
4012 static NTSTATUS
4013 XenPci_DOP_BuildMdlFromScatterGatherList(
4014 PDMA_ADAPTER DmaAdapter,
4015 PSCATTER_GATHER_LIST ScatterGather,
4016 PMDL OriginalMdl,
4017 PMDL *TargetMdl)
4019 UNREFERENCED_PARAMETER(DmaAdapter);
4020 UNREFERENCED_PARAMETER(ScatterGather);
4021 UNREFERENCED_PARAMETER(OriginalMdl);
4022 UNREFERENCED_PARAMETER(TargetMdl);
4024 FUNCTION_ENTER();
4025 FUNCTION_EXIT();
4026 return STATUS_UNSUCCESSFUL;
4029 static PDMA_ADAPTER
4030 XenPci_BIS_GetDmaAdapter(PVOID context, PDEVICE_DESCRIPTION device_description, PULONG number_of_map_registers)
4032 xen_dma_adapter_t *xen_dma_adapter;
4033 PDEVICE_OBJECT curr, prev;
4034 PDRIVER_OBJECT fdo_driver_object;
4035 PVOID fdo_driver_extension;
4037 UNREFERENCED_PARAMETER(device_description);
4039 FUNCTION_ENTER();
4041 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
4042 KdPrint((__DRIVER_NAME " Device Description = %p:\n", device_description));
4043 KdPrint((__DRIVER_NAME " Version = %d\n", device_description->Version));
4044 KdPrint((__DRIVER_NAME " Master = %d\n", device_description->Master));
4045 KdPrint((__DRIVER_NAME " ScatterGather = %d\n", device_description->ScatterGather));
4046 KdPrint((__DRIVER_NAME " DemandMode = %d\n", device_description->DemandMode));
4047 KdPrint((__DRIVER_NAME " AutoInitialize = %d\n", device_description->AutoInitialize));
4048 KdPrint((__DRIVER_NAME " Dma32BitAddresses = %d\n", device_description->Dma32BitAddresses));
4049 KdPrint((__DRIVER_NAME " IgnoreCount = %d\n", device_description->IgnoreCount));
4050 KdPrint((__DRIVER_NAME " Dma64BitAddresses = %d\n", device_description->Dma64BitAddresses));
4051 KdPrint((__DRIVER_NAME " BusNumber = %d\n", device_description->BusNumber));
4052 KdPrint((__DRIVER_NAME " DmaChannel = %d\n", device_description->DmaChannel));
4053 KdPrint((__DRIVER_NAME " InterfaceType = %d\n", device_description->InterfaceType));
4054 KdPrint((__DRIVER_NAME " DmaWidth = %d\n", device_description->DmaWidth));
4055 KdPrint((__DRIVER_NAME " DmaSpeed = %d\n", device_description->DmaSpeed));
4056 KdPrint((__DRIVER_NAME " MaximumLength = %d\n", device_description->MaximumLength));
4057 KdPrint((__DRIVER_NAME " DmaPort = %d\n", device_description->DmaPort));
4059 /*
4060 we have to allocate PAGE_SIZE bytes here because Windows thinks this is
4061 actually an ADAPTER_OBJECT, and then the verifier crashes because
4062 Windows accessed beyond the end of the structure :(
4063 */
4064 xen_dma_adapter = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
4065 RtlZeroMemory(xen_dma_adapter, PAGE_SIZE);
4066 xen_dma_adapter->dma_adapter.Version = 2;
4067 xen_dma_adapter->dma_adapter.Size = sizeof(DMA_ADAPTER); //xen_dma_adapter_t);
4068 xen_dma_adapter->dma_adapter.DmaOperations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DMA_OPERATIONS), XENPCI_POOL_TAG);
4069 //xen_dma_adapter->dma_adapter.DmaOperations = &xen_dma_adapter->dma_operations;
4070 xen_dma_adapter->dma_adapter.DmaOperations->Size = sizeof(DMA_OPERATIONS);
4071 xen_dma_adapter->dma_adapter.DmaOperations->PutDmaAdapter = XenPci_DOP_PutDmaAdapter;
4072 xen_dma_adapter->dma_adapter.DmaOperations->AllocateCommonBuffer = XenPci_DOP_AllocateCommonBuffer;
4073 xen_dma_adapter->dma_adapter.DmaOperations->FreeCommonBuffer = XenPci_DOP_FreeCommonBuffer;
4074 xen_dma_adapter->dma_adapter.DmaOperations->AllocateAdapterChannel = XenPci_DOP_AllocateAdapterChannel;
4075 xen_dma_adapter->dma_adapter.DmaOperations->FlushAdapterBuffers = XenPci_DOP_FlushAdapterBuffers;
4076 xen_dma_adapter->dma_adapter.DmaOperations->FreeAdapterChannel = XenPci_DOP_FreeAdapterChannel;
4077 xen_dma_adapter->dma_adapter.DmaOperations->FreeMapRegisters = XenPci_DOP_FreeMapRegisters;
4078 xen_dma_adapter->dma_adapter.DmaOperations->MapTransfer = XenPci_DOP_MapTransfer;
4079 xen_dma_adapter->dma_adapter.DmaOperations->GetDmaAlignment = XenPci_DOP_GetDmaAlignment;
4080 xen_dma_adapter->dma_adapter.DmaOperations->ReadDmaCounter = XenPci_DOP_ReadDmaCounter;
4081 xen_dma_adapter->dma_adapter.DmaOperations->GetScatterGatherList = XenPci_DOP_GetScatterGatherList;
4082 xen_dma_adapter->dma_adapter.DmaOperations->PutScatterGatherList = XenPci_DOP_PutScatterGatherList;
4083 xen_dma_adapter->dma_adapter.DmaOperations->CalculateScatterGatherList = XenPci_DOP_CalculateScatterGatherList;
4084 xen_dma_adapter->dma_adapter.DmaOperations->BuildScatterGatherList = XenPci_DOP_BuildScatterGatherList;
4085 xen_dma_adapter->dma_adapter.DmaOperations->BuildMdlFromScatterGatherList = XenPci_DOP_BuildMdlFromScatterGatherList;
4086 xen_dma_adapter->xppdd = context;
4087 xen_dma_adapter->dma_extension = NULL;
4089 KdPrint((__DRIVER_NAME " About to call IoGetAttachedDeviceReference\n"));
4090 curr = IoGetAttachedDeviceReference(xen_dma_adapter->xppdd->common.pdo);
4091 KdPrint((__DRIVER_NAME " Before start of loop - curr = %p\n", curr));
4092 while (curr != NULL)
4094 fdo_driver_object = curr->DriverObject;
4095 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
4096 if (fdo_driver_object)
4098 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC));
4099 if (fdo_driver_extension)
4101 xen_dma_adapter->dma_extension = (dma_driver_extension_t *)fdo_driver_extension;
4102 ObDereferenceObject(curr);
4103 break;
4106 prev = curr;
4107 curr = IoGetLowerDeviceObject(curr);
4108 ObDereferenceObject(prev);
4110 KdPrint((__DRIVER_NAME " End of loop\n"));
4112 *number_of_map_registers = 1024; //1024; /* why not... */
4114 FUNCTION_EXIT();
4116 return &xen_dma_adapter->dma_adapter;
4119 static ULONG
4120 XenPci_BIS_SetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
4122 UNREFERENCED_PARAMETER(context);
4123 UNREFERENCED_PARAMETER(data_type);
4124 UNREFERENCED_PARAMETER(buffer);
4125 UNREFERENCED_PARAMETER(offset);
4126 UNREFERENCED_PARAMETER(length);
4128 FUNCTION_ENTER();
4129 FUNCTION_EXIT();
4130 return 0;
4133 static ULONG
4134 XenPci_BIS_GetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
4136 UNREFERENCED_PARAMETER(context);
4137 UNREFERENCED_PARAMETER(data_type);
4138 UNREFERENCED_PARAMETER(buffer);
4139 UNREFERENCED_PARAMETER(offset);
4140 UNREFERENCED_PARAMETER(length);
4142 FUNCTION_ENTER();
4143 FUNCTION_EXIT();
4144 return 0;
4147 static NTSTATUS
4148 XenPci_QueryInterface(PDEVICE_OBJECT device_object, PIRP irp)
4150 NTSTATUS status;
4151 PIO_STACK_LOCATION stack;
4152 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
4153 PBUS_INTERFACE_STANDARD bis;
4154 PGUID guid;
4156 FUNCTION_ENTER();
4158 stack = IoGetCurrentIrpStackLocation(irp);
4160 if (memcmp(stack->Parameters.QueryInterface.InterfaceType, &GUID_BUS_INTERFACE_STANDARD, sizeof(GUID_BUS_INTERFACE_STANDARD)) == 0)
4162 KdPrint((__DRIVER_NAME " GUID_BUS_INTERFACE_STANDARD\n"));
4163 if (stack->Parameters.QueryInterface.Size < sizeof(BUS_INTERFACE_STANDARD))
4165 KdPrint((__DRIVER_NAME " buffer too small\n"));
4166 status = STATUS_INVALID_PARAMETER;
4167 FUNCTION_EXIT();
4168 return status;
4170 if (stack->Parameters.QueryInterface.Version != 1)
4172 KdPrint((__DRIVER_NAME " incorrect version %d\n", stack->Parameters.QueryInterface.Version));
4173 status = STATUS_INVALID_PARAMETER;
4174 FUNCTION_EXIT();
4175 return status;
4177 bis = (PBUS_INTERFACE_STANDARD)stack->Parameters.QueryInterface.Interface;
4178 bis->Size = sizeof(BUS_INTERFACE_STANDARD);
4179 bis->Version = 1; //BUS_INTERFACE_STANDARD_VERSION;
4180 bis->Context = xppdd;
4181 bis->InterfaceReference = XenPci_IS_InterfaceReference;
4182 bis->InterfaceDereference = XenPci_IS_InterfaceReference;
4183 bis->TranslateBusAddress = XenPci_BIS_TranslateBusAddress;
4184 bis->GetDmaAdapter = XenPci_BIS_GetDmaAdapter;
4185 bis->SetBusData = XenPci_BIS_SetBusData;
4186 bis->GetBusData = XenPci_BIS_GetBusData;
4187 status = STATUS_SUCCESS;
4188 FUNCTION_EXIT();
4189 return status;
4191 else
4193 guid = (PGUID)stack->Parameters.QueryInterface.InterfaceType;
4194 KdPrint((__DRIVER_NAME " Unknown GUID %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",
4195 guid->Data1, (ULONG)guid->Data2, (ULONG)guid->Data3, (ULONG)guid->Data4[0], (ULONG)guid->Data4[1],
4196 (ULONG)guid->Data4[2], (ULONG)guid->Data4[3], (ULONG)guid->Data4[4], (ULONG)guid->Data4[5],
4197 (ULONG)guid->Data4[6], (ULONG)guid->Data4[7]));
4198 status = irp->IoStatus.Status;
4199 FUNCTION_EXIT();
4200 return status;
4204 NTSTATUS
4205 XenPci_Pnp_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4207 NTSTATUS status;
4208 PIO_STACK_LOCATION stack;
4209 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
4210 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
4211 LPWSTR buffer;
4212 WCHAR widebuf[256];
4213 unsigned int i;
4214 PPNP_BUS_INFORMATION pbi;
4215 ULONG *usage_type;
4217 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
4219 stack = IoGetCurrentIrpStackLocation(irp);
4221 switch (stack->MinorFunction)
4223 case IRP_MN_START_DEVICE:
4224 KdPrint((__DRIVER_NAME " IRP_MN_START_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4225 status = XenPci_Pnp_StartDevice(device_object, irp);
4226 break;
4228 case IRP_MN_QUERY_STOP_DEVICE:
4229 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_STOP_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4230 SET_PNP_STATE(&xppdd->common, StopPending);
4231 status = STATUS_SUCCESS;
4232 break;
4234 case IRP_MN_STOP_DEVICE:
4235 KdPrint((__DRIVER_NAME " IRP_MN_STOP_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4236 SET_PNP_STATE(&xppdd->common, Stopped);
4237 status = STATUS_SUCCESS;
4238 break;
4240 case IRP_MN_CANCEL_STOP_DEVICE:
4241 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_STOP_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4242 REVERT_PNP_STATE(&xppdd->common);
4243 status = STATUS_SUCCESS;
4244 break;
4246 case IRP_MN_QUERY_REMOVE_DEVICE:
4247 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_REMOVE_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4248 SET_PNP_STATE(&xppdd->common, RemovePending);
4249 status = STATUS_SUCCESS;
4250 break;
4252 case IRP_MN_REMOVE_DEVICE:
4253 KdPrint((__DRIVER_NAME " IRP_MN_REMOVE_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4254 status = XenPci_Pnp_RemoveDevice(device_object, irp);
4255 break;
4257 case IRP_MN_CANCEL_REMOVE_DEVICE:
4258 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_REMOVE_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4259 REVERT_PNP_STATE(&xppdd->common);
4260 status = STATUS_SUCCESS;
4261 break;
4263 case IRP_MN_SURPRISE_REMOVAL:
4264 KdPrint((__DRIVER_NAME " IRP_MN_SURPRISE_REMOVAL (status = %08x)\n", irp->IoStatus.Status));
4265 SET_PNP_STATE(&xppdd->common, SurpriseRemovePending);
4266 status = STATUS_SUCCESS;
4267 break;
4269 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
4270 KdPrint((__DRIVER_NAME " IRP_MN_DEVICE_USAGE_NOTIFICATION (status = %08x)\n", irp->IoStatus.Status));
4272 usage_type = NULL;
4273 switch (stack->Parameters.UsageNotification.Type)
4275 case DeviceUsageTypePaging:
4276 KdPrint((__DRIVER_NAME " type = DeviceUsageTypePaging\n"));
4277 usage_type = &xppdd->common.device_usage_paging;
4278 break;
4279 case DeviceUsageTypeDumpFile:
4280 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeDumpFile\n"));
4281 usage_type = &xppdd->common.device_usage_dump;
4282 break;
4283 case DeviceUsageTypeHibernation:
4284 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeHibernation\n"));
4285 usage_type = &xppdd->common.device_usage_hibernation;
4286 break;
4287 default:
4288 KdPrint((__DRIVER_NAME " Unknown usage type %x\n",
4289 stack->Parameters.UsageNotification.Type));
4290 break;
4292 KdPrint((__DRIVER_NAME " inpath = %d\n", stack->Parameters.UsageNotification.InPath));
4293 if (usage_type)
4295 if (stack->Parameters.UsageNotification.InPath)
4296 (*usage_type)++;
4297 else
4298 (*usage_type)--;
4300 status = STATUS_SUCCESS;
4301 break;
4303 case IRP_MN_QUERY_ID:
4304 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_ID (status = %08x)\n", irp->IoStatus.Status));
4305 switch (stack->Parameters.QueryId.IdType)
4307 case BusQueryDeviceID: /* REG_SZ */
4308 KdPrint((__DRIVER_NAME " BusQueryDeviceID\n"));
4309 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
4310 for (i = 0; i < strlen(xppdd->device); i++)
4311 widebuf[i] = xppdd->device[i];
4312 widebuf[i] = 0;
4313 RtlStringCbPrintfW(buffer, 512, L"Xen\\%ws", widebuf);
4314 KdPrint((__DRIVER_NAME " %ls\n", buffer));
4315 irp->IoStatus.Information = (ULONG_PTR)buffer;
4316 status = STATUS_SUCCESS;
4317 break;
4318 case BusQueryHardwareIDs: /* REG_MULTI_SZ */
4319 KdPrint((__DRIVER_NAME " BusQueryHardwareIDs\n"));
4320 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
4321 for (i = 0; i < strlen(xppdd->device); i++)
4322 widebuf[i] = xppdd->device[i];
4323 widebuf[i] = 0;
4324 RtlStringCbPrintfW(buffer, 512, L"Xen\\%ws", widebuf);
4325 for (i = 0; buffer[i] != 0; i++);
4326 buffer[i + 1] = 0;
4327 // for (i = 0; i < 256; i++)
4328 // KdPrint((__DRIVER_NAME " %04X: %04X %wc\n", i, buffer[i], buffer[i]));
4329 KdPrint((__DRIVER_NAME " %ls\n", buffer));
4330 irp->IoStatus.Information = (ULONG_PTR)buffer;
4331 status = STATUS_SUCCESS;
4332 break;
4333 case BusQueryCompatibleIDs: /* REG_MULTI_SZ */
4334 KdPrint((__DRIVER_NAME " BusQueryCompatibleIDs\n"));
4335 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
4336 for (i = 0; i < strlen(xppdd->device); i++)
4337 widebuf[i] = xppdd->device[i];
4338 widebuf[i] = 0;
4339 RtlStringCbPrintfW(buffer, 512, L"Xen\\%ws", widebuf);
4340 for (i = 0; buffer[i] != 0; i++);
4341 buffer[i + 1] = 0;
4342 KdPrint((__DRIVER_NAME " %ls\n", buffer));
4343 irp->IoStatus.Information = (ULONG_PTR)buffer;
4344 status = STATUS_SUCCESS;
4345 break;
4346 case BusQueryInstanceID: /* REG_SZ */
4347 KdPrint((__DRIVER_NAME " BusQueryInstanceID\n"));
4348 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
4349 RtlStringCbPrintfW(buffer, 512, L"%02d", xppdd->index);
4350 KdPrint((__DRIVER_NAME " %ls\n", buffer));
4351 irp->IoStatus.Information = (ULONG_PTR)buffer;
4352 status = STATUS_SUCCESS;
4353 break;
4354 default:
4355 KdPrint((__DRIVER_NAME " Unhandled IdType = %d\n", stack->Parameters.QueryId.IdType));
4356 irp->IoStatus.Information = 0;
4357 status = STATUS_NOT_SUPPORTED;
4358 break;
4360 break;
4362 case IRP_MN_QUERY_DEVICE_TEXT:
4363 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_TEXT (status = %08x)\n", irp->IoStatus.Status));
4364 switch (stack->Parameters.QueryDeviceText.DeviceTextType)
4366 case DeviceTextDescription:
4367 KdPrint((__DRIVER_NAME " DeviceTextDescription\n"));
4368 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
4369 for (i = 0; i < strlen(xppdd->device); i++)
4370 widebuf[i] = xppdd->device[i];
4371 widebuf[i] = 0;
4372 RtlStringCbPrintfW(buffer, 512, L"Xen %ws device #%d", widebuf, xppdd->index);
4373 KdPrint((__DRIVER_NAME " %ls\n", buffer));
4374 irp->IoStatus.Information = (ULONG_PTR)buffer;
4375 status = STATUS_SUCCESS;
4376 break;
4377 case DeviceTextLocationInformation:
4378 KdPrint((__DRIVER_NAME " DeviceTextLocationInformation\n"));
4379 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
4380 RtlStringCbPrintfW(buffer, 512, L"Xen Bus");
4381 KdPrint((__DRIVER_NAME " %ls\n", buffer));
4382 irp->IoStatus.Information = (ULONG_PTR)buffer;
4383 status = STATUS_SUCCESS;
4384 break;
4385 default:
4386 KdPrint((__DRIVER_NAME " Unhandled IdType = %d\n", stack->Parameters.QueryDeviceText.DeviceTextType));
4387 irp->IoStatus.Information = 0;
4388 status = STATUS_NOT_SUPPORTED;
4389 break;
4391 break;
4393 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
4394 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_RESOURCE_REQUIREMENTS (status = %08x)\n", irp->IoStatus.Status));
4395 status = XenPci_QueryResourceRequirements(device_object, irp);
4396 break;
4398 case IRP_MN_QUERY_CAPABILITIES:
4399 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_CAPABILITIES (status = %08x)\n", irp->IoStatus.Status));
4400 status = XenPci_Pnp_QueryCapabilities(device_object, irp);
4401 break;
4403 case IRP_MN_QUERY_BUS_INFORMATION:
4404 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_BUS_INFORMATION (status = %08x)\n", irp->IoStatus.Status));
4405 pbi = (PPNP_BUS_INFORMATION)ExAllocatePoolWithTag(PagedPool, sizeof(PNP_BUS_INFORMATION), XENPCI_POOL_TAG);
4406 pbi->BusTypeGuid = GUID_BUS_TYPE_XEN;
4407 pbi->LegacyBusType = PNPBus; //Internal;
4408 pbi->BusNumber = 0;
4409 irp->IoStatus.Information = (ULONG_PTR)pbi;
4410 status = STATUS_SUCCESS;
4411 break;
4413 case IRP_MN_QUERY_INTERFACE:
4414 status = XenPci_QueryInterface(device_object, irp);
4415 break;
4417 case IRP_MN_QUERY_RESOURCES:
4418 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_RESOURCES (status = %08x)\n", irp->IoStatus.Status));
4419 status = irp->IoStatus.Status;
4420 #if 0
4421 crl = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(PagedPool, sizeof(CM_RESOURCE_LIST) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 2, XENPCI_POOL_TAG);
4422 crl->Count = 1;
4423 crl->List[0].InterfaceType = PNPBus;
4424 crl->List[0].BusNumber = 0;
4425 crl->List[0].PartialResourceList.Version = 1;
4426 crl->List[0].PartialResourceList.Revision = 1;
4427 crl->List[0].PartialResourceList.Count = 0;
4429 prd = &crl->List[0].PartialResourceList.PartialDescriptors[crl->List[0].PartialResourceList.Count++];
4430 prd->Type = CmResourceTypeInterrupt;
4431 prd->ShareDisposition = CmResourceShareShared;
4432 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
4433 prd->u.Interrupt.Level = xpdd->irq_number;
4434 prd->u.Interrupt.Vector = xpdd->irq_number;
4435 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
4437 prd = &crl->List[0].PartialResourceList.PartialDescriptors[crl->List[0].PartialResourceList.Count++];
4438 prd->Type = CmResourceTypeMemory;
4439 prd->ShareDisposition = CmResourceShareShared;
4440 prd->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
4441 prd->u.Memory.Start = xpdd->platform_mmio_addr;
4442 prd->u.Memory.Length = 0;
4444 irp->IoStatus.Information = (ULONG_PTR)crl;
4445 status = STATUS_SUCCESS;
4446 #endif
4447 break;
4449 case IRP_MN_QUERY_PNP_DEVICE_STATE:
4450 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_PNP_DEVICE_STATE (status = %08x)\n", irp->IoStatus.Status));
4451 irp->IoStatus.Information = 0;
4452 status = STATUS_SUCCESS;
4453 break;
4455 case IRP_MN_QUERY_DEVICE_RELATIONS:
4456 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_RELATIONS (status = %08x)\n", irp->IoStatus.Status));
4457 switch (stack->Parameters.QueryDeviceRelations.Type)
4459 case TargetDeviceRelation:
4460 KdPrint((__DRIVER_NAME " BusRelations\n"));
4461 status = XenPci_Pnp_QueryTargetRelations(device_object, irp);
4462 break;
4463 default:
4464 status = irp->IoStatus.Status;
4465 break;
4467 break;
4469 case IRP_MN_EJECT:
4470 KdPrint((__DRIVER_NAME " IRP_MN_EJECT\n"));
4471 status = STATUS_SUCCESS;
4472 break;
4474 default:
4475 //KdPrint((__DRIVER_NAME " Unhandled Minor = %d, Status = %08x\n", stack->MinorFunction, irp->IoStatus.Status));
4476 status = irp->IoStatus.Status;
4477 break;
4480 irp->IoStatus.Status = status;
4481 IoCompleteRequest(irp, IO_NO_INCREMENT);
4483 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
4485 return status;
4488 NTSTATUS
4489 XenPci_Irp_Create_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4491 NTSTATUS status;
4493 UNREFERENCED_PARAMETER(device_object);
4495 FUNCTION_ENTER();
4497 status = irp->IoStatus.Status;
4498 IoCompleteRequest(irp, IO_NO_INCREMENT);
4500 FUNCTION_EXIT();
4502 return status;
4505 NTSTATUS
4506 XenPci_Irp_Close_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4508 NTSTATUS status;
4510 UNREFERENCED_PARAMETER(device_object);
4512 FUNCTION_ENTER();
4514 status = irp->IoStatus.Status;
4515 IoCompleteRequest(irp, IO_NO_INCREMENT);
4517 FUNCTION_EXIT();
4519 return status;
4522 NTSTATUS
4523 XenPci_Irp_Read_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4525 NTSTATUS status;
4527 UNREFERENCED_PARAMETER(device_object);
4529 FUNCTION_ENTER();
4531 status = irp->IoStatus.Status;
4532 IoCompleteRequest(irp, IO_NO_INCREMENT);
4534 FUNCTION_EXIT();
4536 return status;
4539 NTSTATUS
4540 XenPci_Irp_Write_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4542 NTSTATUS status;
4544 UNREFERENCED_PARAMETER(device_object);
4546 FUNCTION_ENTER();
4548 status = irp->IoStatus.Status;
4549 IoCompleteRequest(irp, IO_NO_INCREMENT);
4551 FUNCTION_EXIT();
4553 return status;
4556 NTSTATUS
4557 XenPci_Irp_Cleanup_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4559 NTSTATUS status;
4561 UNREFERENCED_PARAMETER(device_object);
4563 FUNCTION_ENTER();
4565 status = irp->IoStatus.Status;
4566 IoCompleteRequest(irp, IO_NO_INCREMENT);
4568 FUNCTION_EXIT();
4570 return status;
4573 DDKAPI NTSTATUS
4574 XenPci_SystemControl_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4576 NTSTATUS status;
4578 UNREFERENCED_PARAMETER(device_object);
4580 FUNCTION_ENTER();
4582 status = irp->IoStatus.Status;
4583 IoCompleteRequest(irp, IO_NO_INCREMENT);
4585 FUNCTION_EXIT();
4587 return status;
4589 #endif