win-pvdrivers

view xenpci/xenpci_pdo.c @ 551:a88fe72e3597

Tidied up gnttbl code. Better detection of crash dumps. Better behaviour when qemu hiding doesn't work.
author James Harper <james.harper@bendigoit.com.au>
date Sat Mar 28 10:07:53 2009 +1100 (2009-03-28)
parents e75bb8d68370
children 9d6c46298386
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 //KdPrint((__DRIVER_NAME " A Requesting Grant Ref\n"));
117 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
118 //KdPrint((__DRIVER_NAME " A Got Grant Ref %d\n", gref));
119 ASSERT(gref); /* lazy */
120 LogicalAddress->QuadPart = (gref << PAGE_SHIFT) | (PtrToUlong(buffer) & (PAGE_SIZE - 1));
122 //FUNCTION_EXIT();
123 return buffer;
124 }
126 static VOID
127 XenPci_DOP_FreeCommonBuffer(
128 PDMA_ADAPTER dma_adapter,
129 ULONG length,
130 PHYSICAL_ADDRESS logical_address,
131 PVOID virtual_address,
132 BOOLEAN cache_enabled
133 )
134 {
135 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
136 PXENPCI_DEVICE_DATA xpdd;
137 grant_ref_t gref;
139 UNREFERENCED_PARAMETER(dma_adapter);
140 UNREFERENCED_PARAMETER(length);
141 UNREFERENCED_PARAMETER(cache_enabled);
143 // FUNCTION_ENTER();
145 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
146 gref = (grant_ref_t)(logical_address.QuadPart >> PAGE_SHIFT);
147 //KdPrint((__DRIVER_NAME " F Releasing Grant Ref %d\n", gref));
148 GntTbl_EndAccess(xpdd, gref, FALSE);
149 //KdPrint((__DRIVER_NAME " F Released Grant Ref\n"));
150 ExFreePoolWithTag(virtual_address, XENPCI_POOL_TAG);
152 // FUNCTION_EXIT();
153 }
155 static NTSTATUS
156 XenPci_DOP_AllocateAdapterChannel(
157 IN PDMA_ADAPTER dma_adapter,
158 IN PDEVICE_OBJECT device_object,
159 IN ULONG NumberOfMapRegisters,
160 IN PDRIVER_CONTROL ExecutionRoutine,
161 IN PVOID Context
162 )
163 {
164 //xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
165 //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
166 IO_ALLOCATION_ACTION action;
167 map_register_base_t *map_register_base;
169 UNREFERENCED_PARAMETER(dma_adapter);
171 //FUNCTION_ENTER();
173 map_register_base = ExAllocatePoolWithTag(NonPagedPool,
174 FIELD_OFFSET(map_register_base_t, regs) + NumberOfMapRegisters * sizeof(map_register_t), XENPCI_POOL_TAG);
175 if (!map_register_base)
176 {
177 KdPrint((__DRIVER_NAME " Cannot allocate memory for map_register_base\n"));
178 //FUNCTION_EXIT();
179 return STATUS_INSUFFICIENT_RESOURCES;
180 }
181 /* we should also allocate a single page of memory here for remap purposes as once we allocate the map registers there is no failure allowed */
182 map_register_base->device_object = device_object;
183 map_register_base->total_map_registers = NumberOfMapRegisters;
184 map_register_base->count = 0;
186 action = ExecutionRoutine(device_object, device_object->CurrentIrp, map_register_base, Context);
188 switch (action)
189 {
190 case KeepObject:
191 KdPrint((__DRIVER_NAME " KeepObject\n"));
192 ASSERT(FALSE);
193 break;
194 case DeallocateObject:
195 KdPrint((__DRIVER_NAME " DeallocateObject\n"));
196 ASSERT(FALSE);
197 break;
198 case DeallocateObjectKeepRegisters:
199 //KdPrint((__DRIVER_NAME " DeallocateObjectKeepRegisters\n"));
200 break;
201 default:
202 KdPrint((__DRIVER_NAME " Unknown action %d\n", action));
203 ASSERT(FALSE);
204 break;
205 }
206 //FUNCTION_EXIT();
207 return STATUS_SUCCESS;
208 }
210 static BOOLEAN
211 XenPci_DOP_FlushAdapterBuffers(
212 PDMA_ADAPTER dma_adapter,
213 PMDL mdl,
214 PVOID MapRegisterBase,
215 PVOID CurrentVa,
216 ULONG Length,
217 BOOLEAN write_to_device)
218 {
219 //xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
220 //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
221 map_register_base_t *map_register_base = MapRegisterBase;
222 map_register_t *map_register;
223 ULONG i;
225 UNREFERENCED_PARAMETER(dma_adapter);
226 UNREFERENCED_PARAMETER(mdl);
227 UNREFERENCED_PARAMETER(CurrentVa);
228 UNREFERENCED_PARAMETER(Length);
230 //FUNCTION_ENTER();
232 for (i = 0; i < map_register_base->count; i++)
233 {
234 map_register = &map_register_base->regs[i];
235 if (map_register->map_type == MAP_TYPE_REMAPPED && !write_to_device)
236 memcpy(map_register->unaligned_buffer, map_register->aligned_buffer, map_register->copy_length);
237 }
238 //FUNCTION_EXIT();
240 return TRUE;
241 }
243 static VOID
244 XenPci_DOP_FreeAdapterChannel(
245 IN PDMA_ADAPTER DmaAdapter
246 )
247 {
248 UNREFERENCED_PARAMETER(DmaAdapter);
250 FUNCTION_ENTER();
251 FUNCTION_EXIT();
252 }
254 static VOID
255 XenPci_DOP_FreeMapRegisters(
256 PDMA_ADAPTER dma_adapter,
257 PVOID MapRegisterBase,
258 ULONG NumberOfMapRegisters)
259 {
260 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
261 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
262 map_register_base_t *map_register_base = MapRegisterBase;
263 map_register_t *map_register;
264 ULONG i;
265 grant_ref_t gref;
267 //FUNCTION_ENTER();
268 ASSERT(map_register_base->total_map_registers == NumberOfMapRegisters);
270 for (i = 0; i < map_register_base->count; i++)
271 {
272 map_register = &map_register_base->regs[i];
273 switch (map_register->map_type)
274 {
275 case MAP_TYPE_REMAPPED:
276 gref = (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT);
277 //KdPrint((__DRIVER_NAME " D Releasing Grant Ref %d\n", gref));
278 GntTbl_EndAccess(xpdd, gref, FALSE);
279 //KdPrint((__DRIVER_NAME " D Released Grant Ref\n"));
280 ExFreePoolWithTag(map_register->aligned_buffer, XENPCI_POOL_TAG);
281 break;
282 case MAP_TYPE_MDL:
283 gref = (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT);
284 //KdPrint((__DRIVER_NAME " E Releasing Grant Ref %d\n", gref));
285 GntTbl_EndAccess(xpdd, gref, FALSE);
286 //KdPrint((__DRIVER_NAME " E Released Grant Ref\n"));
287 break;
288 case MAP_TYPE_VIRTUAL:
289 break;
290 }
291 }
292 ExFreePoolWithTag(map_register_base, XENPCI_POOL_TAG);
294 //FUNCTION_EXIT();
295 }
297 static PHYSICAL_ADDRESS
298 XenPci_DOP_MapTransfer(
299 PDMA_ADAPTER dma_adapter,
300 PMDL mdl,
301 PVOID MapRegisterBase,
302 PVOID CurrentVa,
303 PULONG Length,
304 BOOLEAN WriteToDevice)
305 {
306 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
307 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
308 map_register_base_t *map_register_base = MapRegisterBase;
309 map_register_t *map_register = &map_register_base->regs[map_register_base->count];
310 PDEVICE_OBJECT device_object = map_register_base->device_object;
311 ULONG page_offset;
312 PFN_NUMBER pfn;
313 grant_ref_t gref;
314 PUCHAR ptr;
315 ULONG mdl_offset;
316 ULONG pfn_index;
318 //FUNCTION_ENTER();
320 //KdPrint((__DRIVER_NAME " Mdl = %p, MapRegisterBase = %p, MdlVa = %p, CurrentVa = %p, Length = %d\n",
321 // mdl, MapRegisterBase, MmGetMdlVirtualAddress(mdl), CurrentVa, *Length));
323 ASSERT(mdl);
324 ASSERT(map_register_base->count < map_register_base->total_map_registers);
326 if (xen_dma_adapter->dma_extension)
327 {
328 if (xen_dma_adapter->dma_extension->need_virtual_address(device_object->CurrentIrp))
329 {
330 map_register->map_type = MAP_TYPE_VIRTUAL;
331 }
332 else
333 {
334 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(device_object->CurrentIrp);
335 if ((MmGetMdlByteOffset(mdl) & (alignment - 1)) || (MmGetMdlByteCount(mdl) & (alignment - 1)))
336 {
337 map_register->map_type = MAP_TYPE_REMAPPED;
338 }
339 else
340 {
341 map_register->map_type = MAP_TYPE_MDL;
342 }
343 }
344 }
345 else
346 {
347 map_register->map_type = MAP_TYPE_MDL;
348 }
350 switch (map_register->map_type)
351 {
352 case MAP_TYPE_MDL:
353 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL\n"));
354 mdl_offset = (ULONG)((ULONGLONG)CurrentVa - (ULONGLONG)MmGetMdlVirtualAddress(mdl));
355 page_offset = PtrToUlong(CurrentVa) & (PAGE_SIZE - 1);
356 *Length = min(*Length, PAGE_SIZE - page_offset);
357 pfn_index = (ULONG)(((ULONGLONG)CurrentVa >> PAGE_SHIFT) - ((ULONGLONG)MmGetMdlVirtualAddress(mdl) >> PAGE_SHIFT));
358 //KdPrint((__DRIVER_NAME " mdl_offset = %d, page_offset = %d, length = %d, pfn_index = %d\n",
359 // mdl_offset, page_offset, *Length, pfn_index));
360 pfn = MmGetMdlPfnArray(mdl)[pfn_index];
361 //KdPrint((__DRIVER_NAME " B Requesting Grant Ref\n"));
362 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
363 //KdPrint((__DRIVER_NAME " B Got Grant Ref %d\n", gref));
364 map_register->logical.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | page_offset;
365 map_register_base->count++;
366 break;
367 case MAP_TYPE_REMAPPED:
368 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED (MapTransfer)\n"));
369 //KdPrint((__DRIVER_NAME " Mdl = %p, MapRegisterBase = %p, MdlVa = %p, CurrentVa = %p, Length = %d\n",
370 // mdl, MapRegisterBase, MmGetMdlVirtualAddress(mdl), CurrentVa, *Length));
371 mdl_offset = (ULONG)((ULONGLONG)CurrentVa - (ULONGLONG)MmGetMdlVirtualAddress(mdl));
372 *Length = min(*Length, PAGE_SIZE);
373 map_register->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
374 ASSERT(map_register->aligned_buffer);
375 map_register->unaligned_buffer = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
376 ASSERT(map_register->unaligned_buffer); /* lazy */
377 map_register->unaligned_buffer = (PUCHAR)map_register->unaligned_buffer + mdl_offset;
378 map_register->copy_length = *Length;
379 if (WriteToDevice)
380 memcpy(map_register->aligned_buffer, map_register->unaligned_buffer, map_register->copy_length);
381 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(map_register->aligned_buffer).QuadPart >> PAGE_SHIFT);
382 //KdPrint((__DRIVER_NAME " C Requesting Grant Ref\n"));
383 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
384 //KdPrint((__DRIVER_NAME " C Got Grant Ref %d\n", gref));
385 map_register->logical.QuadPart = (LONGLONG)(gref << PAGE_SHIFT);
386 map_register_base->count++;
387 break;
388 case MAP_TYPE_VIRTUAL:
389 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL\n"));
390 ptr = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
391 ASSERT(ptr); /* lazy */
392 map_register->logical.QuadPart = (ULONGLONG)ptr;
393 map_register_base->count++;
394 break;
395 default:
396 ASSERT(FALSE);
397 break;
398 }
400 //KdPrint((__DRIVER_NAME " logical = %08x:%08x\n", map_register->logical.HighPart, map_register->logical.LowPart));
401 //FUNCTION_EXIT();
402 return map_register->logical;
403 }
405 static ULONG
406 XenPci_DOP_GetDmaAlignment(
407 PDMA_ADAPTER DmaAdapter)
408 {
409 UNREFERENCED_PARAMETER(DmaAdapter);
411 FUNCTION_ENTER();
412 FUNCTION_EXIT();
413 return 0;
414 }
416 static ULONG
417 XenPci_DOP_ReadDmaCounter(
418 PDMA_ADAPTER DmaAdapter)
419 {
420 UNREFERENCED_PARAMETER(DmaAdapter);
422 FUNCTION_ENTER();
423 FUNCTION_EXIT();
424 return 0;
425 }
427 static NTSTATUS
428 XenPci_DOP_GetScatterGatherList(
429 PDMA_ADAPTER DmaAdapter,
430 PDEVICE_OBJECT DeviceObject,
431 PMDL Mdl,
432 PVOID CurrentVa,
433 ULONG Length,
434 PDRIVER_LIST_CONTROL ExecutionRoutine,
435 PVOID Context,
436 BOOLEAN WriteToDevice)
437 {
438 UNREFERENCED_PARAMETER(DmaAdapter);
439 UNREFERENCED_PARAMETER(DeviceObject);
440 UNREFERENCED_PARAMETER(Mdl);
441 UNREFERENCED_PARAMETER(CurrentVa);
442 UNREFERENCED_PARAMETER(Length);
443 UNREFERENCED_PARAMETER(ExecutionRoutine);
444 UNREFERENCED_PARAMETER(Context);
445 UNREFERENCED_PARAMETER(WriteToDevice);
447 FUNCTION_ENTER();
448 FUNCTION_EXIT();
449 return STATUS_UNSUCCESSFUL;
450 }
452 static VOID
453 XenPci_DOP_PutScatterGatherList(
454 IN PDMA_ADAPTER DmaAdapter,
455 IN PSCATTER_GATHER_LIST ScatterGather,
456 IN BOOLEAN WriteToDevice
457 )
458 {
459 xen_dma_adapter_t *xen_dma_adapter;
460 PXENPCI_DEVICE_DATA xpdd;
461 ULONG i;
462 sg_extra_t *sg_extra;
464 UNREFERENCED_PARAMETER(WriteToDevice);
466 //FUNCTION_ENTER();
468 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
469 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
471 sg_extra = (sg_extra_t *)((PUCHAR)ScatterGather + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
472 (sizeof(SCATTER_GATHER_ELEMENT)) * ScatterGather->NumberOfElements);
474 switch (sg_extra->map_type)
475 {
476 case MAP_TYPE_REMAPPED:
477 for (i = 0; i < ScatterGather->NumberOfElements; i++)
478 {
479 grant_ref_t gref;
480 gref = (grant_ref_t)(ScatterGather->Elements[i].Address.QuadPart >> PAGE_SHIFT);
481 GntTbl_EndAccess(xpdd, gref, FALSE);
482 ScatterGather->Elements[i].Address.QuadPart = -1;
483 }
484 if (!WriteToDevice)
485 memcpy(sg_extra->unaligned_buffer, sg_extra->aligned_buffer, sg_extra->copy_length);
486 ExFreePoolWithTag(sg_extra->aligned_buffer, XENPCI_POOL_TAG);
487 break;
488 case MAP_TYPE_MDL:
489 for (i = 0; i < ScatterGather->NumberOfElements; i++)
490 {
491 grant_ref_t gref;
492 gref = (grant_ref_t)(ScatterGather->Elements[i].Address.QuadPart >> PAGE_SHIFT);
493 GntTbl_EndAccess(xpdd, gref, FALSE);
494 ScatterGather->Elements[i].Address.QuadPart = -1;
495 }
496 break;
497 case MAP_TYPE_VIRTUAL:
498 break;
499 }
500 //FUNCTION_EXIT();
501 }
503 static NTSTATUS
504 XenPci_DOP_CalculateScatterGatherList(
505 PDMA_ADAPTER DmaAdapter,
506 PMDL Mdl,
507 PVOID CurrentVa,
508 ULONG Length,
509 PULONG ScatterGatherListSize,
510 PULONG NumberOfMapRegisters
511 )
512 {
513 ULONG elements;
514 PMDL curr_mdl;
516 UNREFERENCED_PARAMETER(DmaAdapter);
517 UNREFERENCED_PARAMETER(Mdl);
519 FUNCTION_ENTER();
521 KdPrint((__DRIVER_NAME " Mdl = %p\n", Mdl));
522 KdPrint((__DRIVER_NAME " CurrentVa = %p\n", CurrentVa));
523 KdPrint((__DRIVER_NAME " Length = %d\n", Length));
524 if (Mdl)
525 {
526 for (curr_mdl = Mdl, elements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
527 elements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(CurrentVa, Length);
528 }
529 else
530 {
531 elements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, Length) + 1;
532 }
534 *ScatterGatherListSize = FIELD_OFFSET(SCATTER_GATHER_LIST, Elements)
535 + sizeof(SCATTER_GATHER_ELEMENT) * elements
536 + sizeof(sg_extra_t);
537 if (NumberOfMapRegisters)
538 *NumberOfMapRegisters = 1;
540 KdPrint((__DRIVER_NAME " ScatterGatherListSize = %d\n", *ScatterGatherListSize));
542 FUNCTION_EXIT();
543 return STATUS_SUCCESS;
544 }
546 static NTSTATUS
547 XenPci_DOP_BuildScatterGatherList(
548 IN PDMA_ADAPTER DmaAdapter,
549 IN PDEVICE_OBJECT DeviceObject,
550 IN PMDL Mdl,
551 IN PVOID CurrentVa,
552 IN ULONG Length,
553 IN PDRIVER_LIST_CONTROL ExecutionRoutine,
554 IN PVOID Context,
555 IN BOOLEAN WriteToDevice,
556 IN PVOID ScatterGatherBuffer,
557 IN ULONG ScatterGatherBufferLength)
558 {
559 ULONG i;
560 PSCATTER_GATHER_LIST sglist = ScatterGatherBuffer;
561 PUCHAR ptr;
562 ULONG remaining = Length;
563 ULONG total_remaining;
564 xen_dma_adapter_t *xen_dma_adapter;
565 PXENPCI_DEVICE_DATA xpdd;
566 sg_extra_t *sg_extra;
567 PMDL curr_mdl;
568 ULONG map_type;
569 ULONG sg_element;
570 ULONG offset;
571 PFN_NUMBER pfn;
572 grant_ref_t gref;
573 //PUCHAR StartVa;
575 //FUNCTION_ENTER();
577 ASSERT(MmGetMdlVirtualAddress(Mdl) == CurrentVa);
579 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
580 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
582 ASSERT(Mdl);
584 if (xen_dma_adapter->dma_extension)
585 {
586 if (xen_dma_adapter->dma_extension->need_virtual_address(DeviceObject->CurrentIrp))
587 {
588 ASSERT(!Mdl->Next); /* can only virtual a single buffer */
589 map_type = MAP_TYPE_VIRTUAL;
590 sglist->NumberOfElements = 1;
591 }
592 else
593 {
594 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(DeviceObject->CurrentIrp);
595 if ((MmGetMdlByteOffset(Mdl) & (alignment - 1)) || (MmGetMdlByteCount(Mdl) & (alignment - 1)))
596 {
597 ASSERT(!Mdl->Next); /* can only remap a single buffer for now - will need to check all Mdl's in the future */
598 map_type = MAP_TYPE_REMAPPED;
599 sglist->NumberOfElements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(NULL, Length);
600 }
601 else
602 {
603 map_type = MAP_TYPE_MDL;
604 for (curr_mdl = Mdl, sglist->NumberOfElements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
605 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
606 MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
607 }
608 }
609 }
610 else
611 {
612 map_type = MAP_TYPE_MDL;
613 for (curr_mdl = Mdl, sglist->NumberOfElements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
614 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
615 MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
616 }
617 if (ScatterGatherBufferLength < FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
618 sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t))
619 {
620 return STATUS_BUFFER_TOO_SMALL;
621 }
623 sg_extra = (sg_extra_t *)((PUCHAR)sglist + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
624 (sizeof(SCATTER_GATHER_ELEMENT)) * sglist->NumberOfElements);
626 sg_extra->map_type = map_type;
627 switch (map_type)
628 {
629 case MAP_TYPE_MDL:
630 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL - %p\n", MmGetMdlVirtualAddress(Mdl)));
631 total_remaining = Length;
632 for (sg_element = 0, curr_mdl = Mdl; curr_mdl; curr_mdl = curr_mdl->Next)
633 {
634 remaining = MmGetMdlByteCount(curr_mdl);
635 offset = MmGetMdlByteOffset(curr_mdl);
636 for (i = 0; i < ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)); i++)
637 {
638 //KdPrint((__DRIVER_NAME " element = %d\n", sg_element));
639 //KdPrint((__DRIVER_NAME " remaining = %d\n", remaining));
640 pfn = MmGetMdlPfnArray(curr_mdl)[i];
641 ASSERT(pfn);
642 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
643 ASSERT(gref != INVALID_GRANT_REF);
644 sglist->Elements[sg_element].Address.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | offset;
645 sglist->Elements[sg_element].Length = min(min(PAGE_SIZE - offset, remaining), total_remaining);
646 total_remaining -= sglist->Elements[sg_element].Length;
647 remaining -= sglist->Elements[sg_element].Length;
648 offset = 0;
649 sg_element++;
650 }
651 }
652 break;
653 case MAP_TYPE_REMAPPED:
654 sg_extra->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, max(Length, PAGE_SIZE), XENPCI_POOL_TAG);
655 if (!sg_extra->aligned_buffer)
656 {
657 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED buffer allocation failed - requested va = %p, length = %d\n", MmGetMdlVirtualAddress(Mdl), Length));
658 return STATUS_INSUFFICIENT_RESOURCES;
659 }
660 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED - %p -> %p\n", MmGetMdlVirtualAddress(Mdl), sg_extra->aligned_buffer));
661 sg_extra->unaligned_buffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
662 ASSERT(sg_extra->unaligned_buffer); /* lazy */
663 sg_extra->copy_length = Length;
664 if (WriteToDevice)
665 memcpy(sg_extra->aligned_buffer, sg_extra->unaligned_buffer, sg_extra->copy_length);
666 for (sg_element = 0, remaining = Length;
667 sg_element < ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_extra->aligned_buffer, Length); sg_element++)
668 {
669 pfn = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)sg_extra->aligned_buffer + (sg_element << PAGE_SHIFT)).QuadPart >> PAGE_SHIFT);
670 ASSERT(pfn);
671 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
672 ASSERT(gref);
673 sglist->Elements[sg_element].Address.QuadPart = (ULONGLONG)gref << PAGE_SHIFT;
674 sglist->Elements[sg_element].Length = min(PAGE_SIZE, remaining);
675 remaining -= sglist->Elements[sg_element].Length;
676 }
677 break;
678 case MAP_TYPE_VIRTUAL:
679 ptr = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
680 ASSERT(ptr); /* lazy */
681 sglist->Elements[0].Address.QuadPart = (ULONGLONG)ptr;
682 sglist->Elements[0].Length = Length;
683 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL - %08x\n", sglist->Elements[0].Address.LowPart));
684 break;
685 }
687 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, ScatterGatherBuffer, Context);
689 //FUNCTION_EXIT();
691 return STATUS_SUCCESS;
692 }
694 static NTSTATUS
695 XenPci_DOP_BuildMdlFromScatterGatherList(
696 PDMA_ADAPTER DmaAdapter,
697 PSCATTER_GATHER_LIST ScatterGather,
698 PMDL OriginalMdl,
699 PMDL *TargetMdl)
700 {
701 UNREFERENCED_PARAMETER(DmaAdapter);
702 UNREFERENCED_PARAMETER(ScatterGather);
703 UNREFERENCED_PARAMETER(OriginalMdl);
704 UNREFERENCED_PARAMETER(TargetMdl);
706 FUNCTION_ENTER();
707 FUNCTION_EXIT();
708 return STATUS_UNSUCCESSFUL;
709 }
711 static PDMA_ADAPTER
712 XenPci_BIS_GetDmaAdapter(PVOID context, PDEVICE_DESCRIPTION device_description, PULONG number_of_map_registers)
713 {
714 xen_dma_adapter_t *xen_dma_adapter;
715 PDEVICE_OBJECT curr, prev;
716 PDRIVER_OBJECT fdo_driver_object;
717 PVOID fdo_driver_extension;
719 UNREFERENCED_PARAMETER(device_description);
721 FUNCTION_ENTER();
723 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
724 KdPrint((__DRIVER_NAME " Device Description = %p:\n", device_description));
725 KdPrint((__DRIVER_NAME " Version = %d\n", device_description->Version));
726 KdPrint((__DRIVER_NAME " Master = %d\n", device_description->Master));
727 KdPrint((__DRIVER_NAME " ScatterGather = %d\n", device_description->ScatterGather));
728 KdPrint((__DRIVER_NAME " DemandMode = %d\n", device_description->DemandMode));
729 KdPrint((__DRIVER_NAME " AutoInitialize = %d\n", device_description->AutoInitialize));
730 KdPrint((__DRIVER_NAME " Dma32BitAddresses = %d\n", device_description->Dma32BitAddresses));
731 KdPrint((__DRIVER_NAME " IgnoreCount = %d\n", device_description->IgnoreCount));
732 KdPrint((__DRIVER_NAME " Dma64BitAddresses = %d\n", device_description->Dma64BitAddresses));
733 KdPrint((__DRIVER_NAME " BusNumber = %d\n", device_description->BusNumber));
734 KdPrint((__DRIVER_NAME " DmaChannel = %d\n", device_description->DmaChannel));
735 KdPrint((__DRIVER_NAME " InterfaceType = %d\n", device_description->InterfaceType));
736 KdPrint((__DRIVER_NAME " DmaWidth = %d\n", device_description->DmaWidth));
737 KdPrint((__DRIVER_NAME " DmaSpeed = %d\n", device_description->DmaSpeed));
738 KdPrint((__DRIVER_NAME " MaximumLength = %d\n", device_description->MaximumLength));
739 KdPrint((__DRIVER_NAME " DmaPort = %d\n", device_description->DmaPort));
741 if (!device_description->Master)
742 return NULL;
743 /*
744 we have to allocate PAGE_SIZE bytes here because Windows thinks this is
745 actually an ADAPTER_OBJECT, and then the verifier crashes because
746 Windows accessed beyond the end of the structure :(
747 */
748 xen_dma_adapter = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
749 ASSERT(xen_dma_adapter);
750 RtlZeroMemory(xen_dma_adapter, PAGE_SIZE);
752 switch(device_description->Version)
753 {
754 case DEVICE_DESCRIPTION_VERSION1:
755 xen_dma_adapter->adapter_object.DmaHeader.Version = 1;
756 break;
757 case DEVICE_DESCRIPTION_VERSION: /* ignore what the docs say here - DEVICE_DESCRIPTION_VERSION appears to mean the latest version */
758 case DEVICE_DESCRIPTION_VERSION2:
759 xen_dma_adapter->adapter_object.DmaHeader.Version = 2;
760 break;
761 default:
762 KdPrint((__DRIVER_NAME " Unsupported device description version %d\n", device_description->Version));
763 ExFreePoolWithTag(xen_dma_adapter, XENPCI_POOL_TAG);
764 return NULL;
765 }
768 xen_dma_adapter->adapter_object.DmaHeader.Size = sizeof(X_ADAPTER_OBJECT); //xen_dma_adapter_t);
769 xen_dma_adapter->adapter_object.MasterAdapter = NULL;
770 xen_dma_adapter->adapter_object.MapRegistersPerChannel = 1024;
771 xen_dma_adapter->adapter_object.AdapterBaseVa = NULL;
772 xen_dma_adapter->adapter_object.MapRegisterBase = NULL;
773 xen_dma_adapter->adapter_object.NumberOfMapRegisters = 0;
774 xen_dma_adapter->adapter_object.CommittedMapRegisters = 0;
775 xen_dma_adapter->adapter_object.CurrentWcb = NULL;
776 KeInitializeDeviceQueue(&xen_dma_adapter->adapter_object.ChannelWaitQueue);
777 xen_dma_adapter->adapter_object.RegisterWaitQueue = NULL;
778 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterQueue);
779 KeInitializeSpinLock(&xen_dma_adapter->adapter_object.SpinLock);
780 xen_dma_adapter->adapter_object.MapRegisters = NULL;
781 xen_dma_adapter->adapter_object.PagePort = NULL;
782 xen_dma_adapter->adapter_object.ChannelNumber = 0xff;
783 xen_dma_adapter->adapter_object.AdapterNumber = 0;
784 xen_dma_adapter->adapter_object.DmaPortAddress = 0;
785 xen_dma_adapter->adapter_object.AdapterMode = 0;
786 xen_dma_adapter->adapter_object.NeedsMapRegisters = FALSE; /* when true this causes a crash in the crash dump path */
787 xen_dma_adapter->adapter_object.MasterDevice = 1;
788 xen_dma_adapter->adapter_object.Width16Bits = 0;
789 xen_dma_adapter->adapter_object.ScatterGather = device_description->ScatterGather;
790 xen_dma_adapter->adapter_object.IgnoreCount = device_description->IgnoreCount;
791 xen_dma_adapter->adapter_object.Dma32BitAddresses = device_description->Dma32BitAddresses;
792 xen_dma_adapter->adapter_object.Dma64BitAddresses = device_description->Dma64BitAddresses;
793 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterList);
795 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DMA_OPERATIONS), XENPCI_POOL_TAG);
796 ASSERT(xen_dma_adapter->adapter_object.DmaHeader.DmaOperations);
797 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 1)
798 {
799 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = FIELD_OFFSET(DMA_OPERATIONS, CalculateScatterGatherList);
800 }
801 else
802 {
803 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = sizeof(DMA_OPERATIONS);
804 }
805 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutDmaAdapter = XenPci_DOP_PutDmaAdapter;
806 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateCommonBuffer = XenPci_DOP_AllocateCommonBuffer;
807 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeCommonBuffer = XenPci_DOP_FreeCommonBuffer;
808 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateAdapterChannel = XenPci_DOP_AllocateAdapterChannel;
809 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FlushAdapterBuffers = XenPci_DOP_FlushAdapterBuffers;
810 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeAdapterChannel = XenPci_DOP_FreeAdapterChannel;
811 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeMapRegisters = XenPci_DOP_FreeMapRegisters;
812 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->MapTransfer = XenPci_DOP_MapTransfer;
813 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetDmaAlignment = XenPci_DOP_GetDmaAlignment;
814 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->ReadDmaCounter = XenPci_DOP_ReadDmaCounter;
815 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetScatterGatherList = XenPci_DOP_GetScatterGatherList;
816 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutScatterGatherList = XenPci_DOP_PutScatterGatherList;
817 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 2)
818 {
819 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->CalculateScatterGatherList = XenPci_DOP_CalculateScatterGatherList;
820 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildScatterGatherList = XenPci_DOP_BuildScatterGatherList;
821 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildMdlFromScatterGatherList = XenPci_DOP_BuildMdlFromScatterGatherList;
822 }
823 xen_dma_adapter->xppdd = context;
824 xen_dma_adapter->dma_extension = NULL;
826 KdPrint((__DRIVER_NAME " About to call IoGetAttachedDeviceReference\n"));
827 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(xen_dma_adapter->xppdd->wdf_device));
828 KdPrint((__DRIVER_NAME " Before start of loop - curr = %p\n", curr));
829 while (curr != NULL)
830 {
831 fdo_driver_object = curr->DriverObject;
832 if (fdo_driver_object)
833 {
834 ObReferenceObject(fdo_driver_object);
835 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC));
836 if (fdo_driver_extension)
837 {
838 xen_dma_adapter->dma_extension_driver = fdo_driver_object; /* so we can dereference it on putdmaadapter */
839 xen_dma_adapter->dma_extension = (dma_driver_extension_t *)fdo_driver_extension;
840 ObDereferenceObject(curr);
841 break;
842 }
843 else
844 {
845 ObDereferenceObject(fdo_driver_object);
846 }
847 }
848 prev = curr;
849 curr = IoGetLowerDeviceObject(curr);
850 ObDereferenceObject(prev);
851 }
852 KdPrint((__DRIVER_NAME " End of loop\n"));
854 *number_of_map_registers = 1024; /* why not... */
856 FUNCTION_EXIT();
858 return &xen_dma_adapter->adapter_object.DmaHeader;
859 }
861 static ULONG
862 XenPci_BIS_SetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
863 {
864 UNREFERENCED_PARAMETER(context);
865 UNREFERENCED_PARAMETER(data_type);
866 UNREFERENCED_PARAMETER(buffer);
867 UNREFERENCED_PARAMETER(offset);
868 UNREFERENCED_PARAMETER(length);
870 FUNCTION_ENTER();
871 FUNCTION_EXIT();
872 return 0;
873 }
875 static ULONG
876 XenPci_BIS_GetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
877 {
878 UNREFERENCED_PARAMETER(context);
879 UNREFERENCED_PARAMETER(data_type);
880 UNREFERENCED_PARAMETER(buffer);
881 UNREFERENCED_PARAMETER(offset);
882 UNREFERENCED_PARAMETER(length);
884 FUNCTION_ENTER();
885 FUNCTION_EXIT();
886 return 0;
887 }
889 /*
890 Called at PASSIVE_LEVEL(?)
891 Called during restore
892 */
894 static ULONG
895 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
896 {
897 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
898 char path[128];
899 char *value;
900 char *err;
901 ULONG backend_state;
903 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
904 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
905 if (err)
906 {
907 XenPci_FreeMem(err);
908 return XenbusStateUnknown;
909 }
910 else
911 {
912 backend_state = atoi(value);
913 XenPci_FreeMem(value);
914 return backend_state;
915 }
916 }
918 static VOID
919 XenPci_BackEndStateHandler(char *path, PVOID context)
920 {
921 WDFDEVICE device = context;
922 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
923 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
924 ULONG new_backend_state;
926 #if !DBG
927 UNREFERENCED_PARAMETER(path);
928 #endif
930 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
932 /* check that path == device/id/state */
933 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
934 new_backend_state = XenPci_ReadBackendState(xppdd);
935 if (new_backend_state == XenbusStateUnknown)
936 {
937 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
938 return;
939 KdPrint(("Failed to read %s, assuming closed\n", path));
940 new_backend_state = XenbusStateClosed;
941 }
943 if (xppdd->backend_state == new_backend_state)
944 {
945 KdPrint((__DRIVER_NAME " state unchanged\n"));
946 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
947 return;
948 }
950 xppdd->backend_state = new_backend_state;
952 switch (xppdd->backend_state)
953 {
954 case XenbusStateUnknown:
955 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown (%s)\n", path));
956 break;
958 case XenbusStateInitialising:
959 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising (%s)\n", path));
960 break;
962 case XenbusStateInitWait:
963 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait (%s)\n", path));
964 break;
966 case XenbusStateInitialised:
967 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised (%s)\n", path));
968 break;
970 case XenbusStateConnected:
971 KdPrint((__DRIVER_NAME " Backend State Changed to Connected (%s)\n", path));
972 break;
974 case XenbusStateClosing:
975 KdPrint((__DRIVER_NAME " Backend State Changed to Closing (%s)\n", path));
976 if (xppdd->frontend_state == XenbusStateConnected)
977 {
978 KdPrint((__DRIVER_NAME " Requesting eject\n"));
979 WdfPdoRequestEject(device);
980 }
981 break;
983 case XenbusStateClosed:
984 KdPrint((__DRIVER_NAME " Backend State Changed to Closed (%s)\n", path));
985 break;
987 default:
988 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d (%s)\n", xppdd->backend_state, path));
989 break;
990 }
992 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
994 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
996 return;
997 }
999 static NTSTATUS
1000 XenPci_GetBackendAndAddWatch(WDFDEVICE device)
1002 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1003 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1004 char path[128];
1005 PCHAR res;
1006 PCHAR value;
1008 /* Get backend path */
1009 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
1010 "%s/backend", xppdd->path);
1011 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
1012 if (res)
1014 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
1015 XenPci_FreeMem(res);
1016 return STATUS_UNSUCCESSFUL;
1018 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
1019 XenPci_FreeMem(value);
1021 /* Add watch on backend state */
1022 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1023 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
1025 return STATUS_SUCCESS;
1028 static NTSTATUS
1029 XenConfig_InitConfigPage(WDFDEVICE device)
1031 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1032 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
1033 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
1034 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
1035 PUCHAR ptr;
1036 PDEVICE_OBJECT curr, prev;
1037 PDRIVER_OBJECT fdo_driver_object;
1038 PUCHAR fdo_driver_extension;
1040 FUNCTION_ENTER();
1042 ptr = MmGetMdlVirtualAddress(xppdd->config_page_mdl);
1043 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(device));
1044 //curr = WdfDeviceWdmGetAttachedDevice(device);
1045 while (curr != NULL)
1047 fdo_driver_object = curr->DriverObject;
1048 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
1049 if (fdo_driver_object)
1051 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
1052 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
1053 if (fdo_driver_extension)
1055 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
1056 ObDereferenceObject(curr);
1057 break;
1060 prev = curr;
1061 curr = IoGetLowerDeviceObject(curr);
1062 ObDereferenceObject(prev);
1065 FUNCTION_EXIT();
1067 return STATUS_SUCCESS;
1070 static NTSTATUS
1071 XenPci_EvtChn_Bind(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
1073 WDFDEVICE device = context;
1074 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1075 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1077 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext);
1080 static NTSTATUS
1081 XenPci_EvtChn_BindDpc(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
1083 WDFDEVICE device = context;
1084 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1085 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1087 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext);
1090 static NTSTATUS
1091 XenPci_EvtChn_Unbind(PVOID context, evtchn_port_t Port)
1093 WDFDEVICE device = context;
1094 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1095 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1097 return EvtChn_Unbind(xpdd, Port);
1100 static NTSTATUS
1101 XenPci_EvtChn_Mask(PVOID context, evtchn_port_t Port)
1103 WDFDEVICE device = context;
1104 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1105 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1107 return EvtChn_Mask(xpdd, Port);
1110 static NTSTATUS
1111 XenPci_EvtChn_Unmask(PVOID context, evtchn_port_t Port)
1113 WDFDEVICE device = context;
1114 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1115 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1117 return EvtChn_Unmask(xpdd, Port);
1120 static NTSTATUS
1121 XenPci_EvtChn_Notify(PVOID context, evtchn_port_t Port)
1123 WDFDEVICE device = context;
1124 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1125 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1127 return EvtChn_Notify(xpdd, Port);
1130 static BOOLEAN
1131 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port)
1133 WDFDEVICE device = context;
1134 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1135 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1137 return EvtChn_AckEvent(xpdd, port);
1140 typedef struct {
1141 PXEN_EVTCHN_SYNC_ROUTINE sync_routine;
1142 PVOID sync_context;
1143 } sync_context_t;
1145 static BOOLEAN
1146 XenPci_EvtChn_Sync_Routine(WDFINTERRUPT interrupt, WDFCONTEXT context)
1148 sync_context_t *wdf_sync_context = context;
1149 UNREFERENCED_PARAMETER(interrupt);
1150 return wdf_sync_context->sync_routine(wdf_sync_context->sync_context);
1153 static BOOLEAN
1154 XenPci_EvtChn_Sync(PVOID context, PXEN_EVTCHN_SYNC_ROUTINE sync_routine, PVOID sync_context)
1156 WDFDEVICE device = context;
1157 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1158 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1159 sync_context_t wdf_sync_context;
1161 wdf_sync_context.sync_routine = sync_routine;
1162 wdf_sync_context.sync_context = sync_context;
1164 return WdfInterruptSynchronize(xpdd->interrupt, XenPci_EvtChn_Sync_Routine, &wdf_sync_context);
1167 static grant_ref_t
1168 XenPci_GntTbl_GrantAccess(PVOID context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref)
1170 WDFDEVICE device = context;
1171 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1172 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1174 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref);
1177 static BOOLEAN
1178 XenPci_GntTbl_EndAccess(PVOID context, grant_ref_t ref, BOOLEAN keepref)
1180 WDFDEVICE device = context;
1181 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1182 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1184 return GntTbl_EndAccess(xpdd, ref, keepref);
1187 static VOID
1188 XenPci_GntTbl_PutRef(PVOID context, grant_ref_t ref)
1190 WDFDEVICE device = context;
1191 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1192 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1194 GntTbl_PutRef(xpdd, ref);
1197 static grant_ref_t
1198 XenPci_GntTbl_GetRef(PVOID context)
1200 WDFDEVICE device = context;
1201 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1202 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1204 return GntTbl_GetRef(xpdd);
1207 PCHAR
1208 XenPci_XenBus_Read(PVOID context, xenbus_transaction_t xbt, char *path, char **value)
1210 WDFDEVICE device = context;
1211 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1212 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1213 return XenBus_Read(xpdd, xbt, path, value);
1216 PCHAR
1217 XenPci_XenBus_Write(PVOID context, xenbus_transaction_t xbt, char *path, char *value)
1219 WDFDEVICE device = context;
1220 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1221 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1222 return XenBus_Write(xpdd, xbt, path, value);
1225 PCHAR
1226 XenPci_XenBus_Printf(PVOID context, xenbus_transaction_t xbt, char *path, char *fmt, ...)
1228 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
1229 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
1230 //return XenBus_Printf(xpdd, xbt, path, value);
1231 UNREFERENCED_PARAMETER(context);
1232 UNREFERENCED_PARAMETER(xbt);
1233 UNREFERENCED_PARAMETER(path);
1234 UNREFERENCED_PARAMETER(fmt);
1235 return NULL;
1238 PCHAR
1239 XenPci_XenBus_StartTransaction(PVOID context, xenbus_transaction_t *xbt)
1241 WDFDEVICE device = context;
1242 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1243 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1244 return XenBus_StartTransaction(xpdd, xbt);
1247 PCHAR
1248 XenPci_XenBus_EndTransaction(PVOID context, xenbus_transaction_t xbt, int abort, int *retry)
1250 WDFDEVICE device = context;
1251 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1252 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1253 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
1256 PCHAR
1257 XenPci_XenBus_List(PVOID context, xenbus_transaction_t xbt, char *prefix, char ***contents)
1259 WDFDEVICE device = context;
1260 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1261 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1262 return XenBus_List(xpdd, xbt, prefix, contents);
1265 PCHAR
1266 XenPci_XenBus_AddWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
1268 WDFDEVICE device = context;
1269 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1270 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1271 PCHAR retval;
1273 FUNCTION_ENTER();
1274 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
1275 if (retval == NULL)
1277 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
1279 else
1281 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
1283 FUNCTION_EXIT();
1284 return retval;
1287 PCHAR
1288 XenPci_XenBus_RemWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
1290 WDFDEVICE device = context;
1291 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1292 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1293 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
1296 /*
1297 Called at PASSIVE_LEVEL
1298 Called during restore
1299 */
1301 static NTSTATUS
1302 XenPci_ChangeFrontendState(WDFDEVICE device, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
1304 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1305 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1306 LARGE_INTEGER timeout;
1307 ULONG remaining;
1308 ULONG thiswait;
1309 char path[128];
1311 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1313 xppdd->frontend_state = frontend_state_set;
1315 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
1316 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
1318 remaining = maximum_wait_ms;
1320 while (xppdd->backend_state != backend_state_response)
1322 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
1323 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
1324 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
1326 remaining -= thiswait;
1327 if (remaining == 0)
1329 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
1330 return STATUS_UNSUCCESSFUL;
1332 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
1335 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1336 return STATUS_SUCCESS;
1339 static NTSTATUS
1340 XenPci_XenConfigDevice(WDFDEVICE device);
1342 static NTSTATUS
1343 XenPci_XenShutdownDevice(PVOID context)
1345 WDFDEVICE device = context;
1346 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1347 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1348 PUCHAR in_ptr;
1349 ULONG i;
1350 UCHAR type;
1351 PVOID setting;
1352 PVOID value;
1353 PVOID value2;
1355 FUNCTION_ENTER();
1357 if (xppdd->backend_state == XenbusStateConnected)
1359 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
1360 if (xppdd->backend_state == XenbusStateClosing)
1361 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
1362 if (xppdd->backend_state == XenbusStateClosed)
1363 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
1365 else
1367 if (xppdd->backend_state == XenbusStateClosing)
1368 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
1371 if (xppdd->assigned_resources_start != NULL)
1373 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1374 in_ptr = xppdd->assigned_resources_start;
1375 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
1377 switch (type)
1379 case XEN_INIT_TYPE_RING: /* frontend ring */
1380 FreePages(value);
1381 break;
1382 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
1383 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
1384 EvtChn_Unbind(xpdd, PtrToUlong(value));
1385 EvtChn_Close(xpdd, PtrToUlong(value));
1386 break;
1387 case XEN_INIT_TYPE_GRANT_ENTRIES:
1388 for (i = 0; i < PtrToUlong(setting); i++)
1389 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value)[i], FALSE);
1390 break;
1393 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
1394 xppdd->assigned_resources_start = NULL;
1397 FUNCTION_EXIT();
1399 return STATUS_SUCCESS;
1402 struct dummy_sring {
1403 RING_IDX req_prod, req_event;
1404 RING_IDX rsp_prod, rsp_event;
1405 uint8_t pad[48];
1406 };
1408 static NTSTATUS
1409 XenPci_XenConfigDeviceSpecifyBuffers(WDFDEVICE device, PUCHAR src, PUCHAR dst)
1411 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1412 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1413 NTSTATUS status = STATUS_SUCCESS;
1414 ULONG i;
1415 char path[128];
1416 PCHAR setting, value;
1417 PCHAR res;
1418 PVOID address;
1419 UCHAR type;
1420 PUCHAR in_ptr;
1421 PUCHAR out_ptr;
1422 XENPCI_VECTORS vectors;
1423 ULONG event_channel;
1424 ULONG run_type = 0;
1425 PMDL ring;
1426 grant_ref_t gref;
1427 BOOLEAN done_xenbus_init = FALSE;
1428 PVOID value2;
1429 BOOLEAN active = TRUE;
1430 BOOLEAN dont_config = FALSE;
1432 FUNCTION_ENTER();
1434 in_ptr = src;
1435 out_ptr = dst;
1437 // always add vectors
1438 vectors.magic = XEN_DATA_MAGIC;
1439 vectors.length = sizeof(XENPCI_VECTORS);
1440 vectors.context = device;
1441 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
1442 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
1443 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
1444 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
1445 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
1446 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
1447 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
1448 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
1449 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
1450 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
1451 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
1452 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
1453 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
1454 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
1455 strncpy(vectors.path, xppdd->path, 128);
1456 strncpy(vectors.backend_path, xppdd->backend_path, 128);
1457 //vectors.pdo_event_channel = xpdd->pdo_event_channel;
1458 vectors.XenBus_Read = XenPci_XenBus_Read;
1459 vectors.XenBus_Write = XenPci_XenBus_Write;
1460 vectors.XenBus_Printf = XenPci_XenBus_Printf;
1461 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
1462 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
1463 vectors.XenBus_List = XenPci_XenBus_List;
1464 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
1465 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
1467 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
1469 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
1470 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
1473 if (!qemu_filtered)
1474 active = FALSE;
1476 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
1478 BOOLEAN condition;
1479 PCHAR xb_value;
1480 switch (type)
1482 case XEN_INIT_TYPE_MATCH_FRONT:
1483 case XEN_INIT_TYPE_MATCH_BACK:
1484 if (type == XEN_INIT_TYPE_MATCH_FRONT)
1486 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1488 else
1490 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
1492 KdPrint((__DRIVER_NAME " testing path = %s\n", path));
1493 res = XenBus_Read(xpdd, XBT_NIL, path, &xb_value);
1494 if (res)
1496 KdPrint((__DRIVER_NAME " read failed (%s)\n", res));
1497 XenPci_FreeMem(res);
1499 else
1501 KdPrint((__DRIVER_NAME " testing %s vs %s\n", xb_value, value));
1502 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_IF_MATCH)
1503 condition = (strcmp(xb_value, value) == 0)?TRUE:FALSE;
1504 else
1505 condition = (strcmp(xb_value, value) != 0)?TRUE:FALSE;
1506 KdPrint((__DRIVER_NAME " condition = %d\n", condition));
1508 if ((PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_ONLY_IF_QEMU_HIDE) && qemu_protocol_version && condition)
1509 condition = FALSE;
1511 if (condition)
1513 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_SET_INACTIVE)
1515 active = FALSE;
1516 KdPrint((__DRIVER_NAME " set inactive\n"));
1518 if (PtrToUlong(value2) & XEN_INIT_MATCH_TYPE_DONT_CONFIG)
1520 dont_config = TRUE;
1521 KdPrint((__DRIVER_NAME " set inactive with dont config\n"));
1524 XenPci_FreeMem(xb_value);
1526 break;
1529 if (dont_config)
1531 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1532 FUNCTION_EXIT();
1533 return status;
1536 // first pass, possibly before state == Connected
1537 in_ptr = src;
1538 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
1541 if (!done_xenbus_init)
1543 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000) != STATUS_SUCCESS)
1545 status = STATUS_UNSUCCESSFUL;
1546 goto error;
1548 done_xenbus_init = TRUE;
1551 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
1553 switch (type)
1555 case XEN_INIT_TYPE_RUN:
1556 run_type++;
1557 break;
1558 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
1559 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
1560 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1561 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
1562 break;
1563 case XEN_INIT_TYPE_RING: /* frontend ring */
1564 /* we only allocate and do the SHARED_RING_INIT here */
1565 if ((ring = AllocatePage()) != 0)
1567 address = MmGetMdlVirtualAddress(ring);
1568 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
1569 SHARED_RING_INIT((struct dummy_sring *)address);
1570 if ((gref = GntTbl_GrantAccess(
1571 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
1573 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1574 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
1575 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
1576 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
1577 // add the grant entry too so it gets freed automatically
1578 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
1579 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
1580 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
1582 else
1584 FreePages(ring);
1585 status = STATUS_UNSUCCESSFUL;
1586 goto error;
1589 else
1591 status = STATUS_UNSUCCESSFUL;
1592 goto error;
1594 break;
1595 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
1596 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
1597 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
1599 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
1600 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1601 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
1602 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
1603 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
1604 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
1606 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
1608 else
1610 #pragma warning(suppress:4055)
1611 EvtChn_Bind(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
1614 else
1616 status = STATUS_UNSUCCESSFUL;
1617 goto error;
1619 break;
1622 if (!NT_SUCCESS(status))
1624 goto error;
1626 // If XEN_INIT_TYPE_RUN was specified more than once then we skip XenbusStateInitialised here and go straight to XenbusStateConnected at the end
1627 if (run_type == 1)
1629 if (XenPci_ChangeFrontendState(device, XenbusStateInitialised, XenbusStateConnected, 2000) != STATUS_SUCCESS)
1631 status = STATUS_UNSUCCESSFUL;
1632 goto error;
1636 // second pass, possibly after state == Connected
1637 in_ptr = src;
1638 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
1640 switch(type)
1642 case XEN_INIT_TYPE_READ_STRING_BACK:
1643 case XEN_INIT_TYPE_READ_STRING_FRONT:
1644 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
1645 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1646 else
1647 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
1648 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
1649 if (res)
1651 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
1652 XenPci_FreeMem(res);
1653 ADD_XEN_INIT_RSP(&out_ptr, type, setting, NULL, NULL);
1655 else
1657 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
1658 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, value2);
1659 XenPci_FreeMem(value);
1661 break;
1662 case XEN_INIT_TYPE_VECTORS:
1663 // this is always done so ignore the request
1664 break;
1665 case XEN_INIT_TYPE_GRANT_ENTRIES:
1666 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
1667 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
1668 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
1669 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
1670 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
1671 for (i = 0; i < PtrToUlong(value); i++)
1673 gref = GntTbl_GetRef(xpdd);
1674 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
1675 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
1677 break;
1680 if (active)
1682 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_ACTIVE, NULL, NULL, NULL);
1684 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1686 if (run_type)
1688 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 2000) != STATUS_SUCCESS)
1690 status = STATUS_UNSUCCESSFUL;
1691 goto error;
1694 FUNCTION_EXIT();
1695 return status;
1697 error:
1698 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 2000);
1699 FUNCTION_EXIT_STATUS(status);
1700 return status;
1703 static NTSTATUS
1704 XenPci_XenConfigDevice(WDFDEVICE device)
1706 NTSTATUS status;
1707 PUCHAR src, dst;
1708 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1710 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
1711 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
1712 memcpy(src, dst, xppdd->config_page_length);
1714 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
1716 MmUnmapIoSpace(dst, xppdd->config_page_length);
1717 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
1719 return status;
1722 static NTSTATUS
1723 XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp)
1725 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1726 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1727 PIO_STACK_LOCATION stack;
1728 PCM_PARTIAL_RESOURCE_LIST prl;
1729 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
1730 ULONG i;
1731 //char path[128];
1732 //PMDL mdl;
1734 FUNCTION_ENTER();
1735 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
1737 stack = IoGetCurrentIrpStackLocation(irp);
1739 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
1740 for (i = 0; i < prl->Count; i++)
1742 prd = & prl->PartialDescriptors[i];
1743 switch (prd->Type)
1745 case CmResourceTypeMemory:
1746 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
1748 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
1749 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
1751 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
1753 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1754 prd->Type = CmResourceTypeInterrupt;
1755 prd->ShareDisposition = CmResourceShareShared;
1756 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
1757 prd->u.Interrupt.Level = xpdd->irq_number;
1758 prd->u.Interrupt.Vector = xpdd->irq_number;
1759 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
1760 xppdd->irq_number = xpdd->irq_number;
1762 break;
1766 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
1767 for (i = 0; i < prl->Count; i++)
1769 prd = & prl->PartialDescriptors[i];
1770 switch (prd->Type)
1772 case CmResourceTypeMemory:
1773 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
1774 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
1775 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
1777 if (prd->u.Memory.Length == 0)
1779 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0]));
1780 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(xppdd->config_page_mdl)[0] << PAGE_SHIFT;
1781 prd->u.Memory.Length = MmGetMdlByteCount(xppdd->config_page_mdl);
1782 KdPrint((__DRIVER_NAME " New Start = %08x%08x, Length = %d\n", prd->u.Memory.Start.HighPart, prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
1784 xppdd->config_page_phys = prd->u.Memory.Start;
1785 xppdd->config_page_length = prd->u.Memory.Length;
1786 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
1787 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
1789 #if 0
1790 status = XenPci_XenConfigDevice(device);
1791 if (!NT_SUCCESS(status))
1793 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1794 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
1795 FUNCTION_ERROR_EXIT();
1796 return status;
1798 #endif
1800 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
1802 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1803 prd->Type = CmResourceTypeInterrupt;
1804 prd->ShareDisposition = CmResourceShareShared;
1805 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
1806 prd->u.Interrupt.Level = xpdd->irq_level;
1807 prd->u.Interrupt.Vector = xpdd->irq_vector;
1808 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
1809 xppdd->irq_vector = xpdd->irq_vector;
1810 xppdd->irq_level = xpdd->irq_level;
1812 break;
1816 IoSkipCurrentIrpStackLocation(irp);
1818 FUNCTION_EXIT();
1820 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
1823 #if 0
1824 static NTSTATUS
1825 XenPciPdo_EvtDeviceResourcesQuery(WDFDEVICE device, WDFCMRESLIST resources)
1828 #endif
1830 static NTSTATUS
1831 XenPciPdo_EvtDeviceResourceRequirementsQuery(WDFDEVICE device, WDFIORESREQLIST requirements_list)
1833 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1834 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1835 WDFIORESLIST res_list;
1836 IO_RESOURCE_DESCRIPTOR ird;
1838 //FUNCTION_ENTER();
1840 WdfIoResourceRequirementsListSetInterfaceType(requirements_list, PNPBus);
1842 WdfIoResourceListCreate(requirements_list, WDF_NO_OBJECT_ATTRIBUTES, &res_list);
1843 ird.Option = 0;
1844 ird.Type = CmResourceTypeMemory;
1845 ird.ShareDisposition = CmResourceShareShared;
1846 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
1847 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
1848 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
1849 ird.u.Memory.Length = 0;
1850 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
1851 WdfIoResourceListAppendDescriptor(res_list, &ird);
1853 ird.Option = 0;
1854 ird.Type = CmResourceTypeMemory;
1855 ird.ShareDisposition = CmResourceShareShared;
1856 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
1857 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
1858 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
1859 ird.u.Memory.Length = 0;
1860 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
1861 WdfIoResourceListAppendDescriptor(res_list, &ird);
1863 WdfIoResourceRequirementsListAppendIoResList(requirements_list, res_list);
1865 //FUNCTION_EXIT();
1867 return STATUS_SUCCESS;
1870 NTSTATUS
1871 XenPciPdo_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
1873 NTSTATUS status = STATUS_SUCCESS;
1874 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1875 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1876 CHAR path[128];
1878 FUNCTION_ENTER();
1880 switch (previous_state)
1882 case WdfPowerDeviceD0:
1883 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1884 break;
1885 case WdfPowerDeviceD1:
1886 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1887 break;
1888 case WdfPowerDeviceD2:
1889 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
1890 break;
1891 case WdfPowerDeviceD3:
1892 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
1893 break;
1894 case WdfPowerDeviceD3Final:
1895 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
1896 break;
1897 case WdfPowerDevicePrepareForHibernation:
1898 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
1899 break;
1900 default:
1901 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
1902 break;
1905 if (previous_state == WdfPowerDevicePrepareForHibernation
1906 || (previous_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
1908 KdPrint((__DRIVER_NAME " starting up from hibernation\n"));
1910 else
1914 XenConfig_InitConfigPage(device);
1916 status = XenPci_GetBackendAndAddWatch(device);
1917 if (!NT_SUCCESS(status))
1919 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
1920 FUNCTION_ERROR_EXIT();
1921 return status;
1923 status = XenPci_XenConfigDevice(device);
1924 if (!NT_SUCCESS(status))
1926 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1927 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
1928 WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
1929 FUNCTION_ERROR_EXIT();
1930 return status;
1933 FUNCTION_EXIT();
1935 return status;
1938 NTSTATUS
1939 XenPciPdo_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
1941 NTSTATUS status = STATUS_SUCCESS;
1942 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1943 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1944 char path[128];
1946 UNREFERENCED_PARAMETER(device);
1947 UNREFERENCED_PARAMETER(target_state);
1949 FUNCTION_ENTER();
1951 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
1954 switch (target_state)
1956 case WdfPowerDeviceD0:
1957 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1958 break;
1959 case WdfPowerDeviceD1:
1960 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
1961 break;
1962 case WdfPowerDeviceD2:
1963 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
1964 break;
1965 case WdfPowerDeviceD3:
1966 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
1967 break;
1968 case WdfPowerDeviceD3Final:
1969 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
1970 break;
1971 case WdfPowerDevicePrepareForHibernation:
1972 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
1973 break;
1974 default:
1975 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
1976 break;
1979 if (target_state == WdfPowerDevicePrepareForHibernation
1980 || (target_state == WdfPowerDeviceD3 && xppdd->hiber_usage_kludge))
1982 KdPrint((__DRIVER_NAME " not powering down as we are hibernating\n"));
1984 else
1986 status = XenPci_XenShutdownDevice(device);
1987 /* Remove watch on backend state */
1988 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1989 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
1991 FUNCTION_EXIT();
1993 return status;
1996 NTSTATUS
1997 XenPciPdo_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
1999 NTSTATUS status = STATUS_SUCCESS;
2001 UNREFERENCED_PARAMETER(device);
2002 UNREFERENCED_PARAMETER(resources_raw);
2003 UNREFERENCED_PARAMETER(resources_translated);
2005 FUNCTION_ENTER();
2006 FUNCTION_EXIT();
2008 return status;
2011 NTSTATUS
2012 XenPciPdo_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
2014 NTSTATUS status = STATUS_SUCCESS;
2016 UNREFERENCED_PARAMETER(device);
2017 UNREFERENCED_PARAMETER(resources_translated);
2019 FUNCTION_ENTER();
2020 FUNCTION_EXIT();
2022 return status;
2025 static VOID
2026 XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
2028 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2030 FUNCTION_ENTER();
2032 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
2033 switch (notification_type)
2035 case WdfSpecialFilePaging:
2036 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
2037 break;
2038 case WdfSpecialFileHibernation:
2039 xppdd->hiber_usage_kludge = is_in_notification_path;
2040 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
2041 break;
2042 case WdfSpecialFileDump:
2043 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
2044 break;
2045 default:
2046 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
2047 break;
2050 FUNCTION_EXIT();
2053 NTSTATUS
2054 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
2055 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
2056 PWDFDEVICE_INIT child_init)
2058 NTSTATUS status = STATUS_SUCCESS;
2059 WDF_OBJECT_ATTRIBUTES child_attributes;
2060 WDFDEVICE child_device;
2061 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
2062 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
2063 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
2064 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
2065 PXENPCI_PDO_DEVICE_DATA xppdd;
2066 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
2067 WDF_QUERY_INTERFACE_CONFIG interface_config;
2068 BUS_INTERFACE_STANDARD bus_interface;
2069 WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
2070 WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
2071 UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
2072 WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
2074 FUNCTION_ENTER();
2076 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
2078 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
2079 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
2080 //child_pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPciPdo_EvtDeviceD0EntryPostInterruptsEnabled;
2081 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
2082 //child_pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPciPdo_EvtDeviceD0ExitPreInterruptsDisabled;
2083 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenPciPdo_EvtDevicePrepareHardware;
2084 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenPciPdo_EvtDeviceReleaseHardware;
2085 child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
2086 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
2088 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
2089 identification->device, identification->index, identification->path));
2091 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
2092 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
2093 if (!NT_SUCCESS(status))
2095 return status;
2098 WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
2099 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
2100 pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
2101 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
2102 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
2103 WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
2105 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
2106 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
2107 if (!NT_SUCCESS(status))
2109 return status;
2111 status = WdfPdoInitAddHardwareID(child_init, &buffer);
2112 if (!NT_SUCCESS(status))
2114 return status;
2116 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
2117 if (!NT_SUCCESS(status))
2119 return status;
2122 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
2123 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
2124 if (!NT_SUCCESS(status))
2126 return status;
2129 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
2130 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
2131 if (!NT_SUCCESS(status))
2133 return status;
2135 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
2137 WdfDeviceInitSetPowerNotPageable(child_init);
2139 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
2140 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
2141 if (!NT_SUCCESS(status))
2143 return status;
2146 xppdd = GetXppdd(child_device);
2148 xppdd->wdf_device = child_device;
2149 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
2151 xppdd->config_page_mdl = AllocateUncachedPage();
2153 xppdd->device_state.magic = XEN_DEVICE_STATE_MAGIC;
2154 xppdd->device_state.length = sizeof(XENPCI_DEVICE_STATE);
2155 xppdd->device_state.suspend_resume_state_pdo = SR_STATE_RUNNING;
2156 xppdd->device_state.suspend_resume_state_fdo = SR_STATE_RUNNING;
2157 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
2158 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
2159 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
2160 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
2162 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
2163 child_pnp_capabilities.LockSupported = WdfFalse;
2164 child_pnp_capabilities.EjectSupported = WdfTrue;
2165 child_pnp_capabilities.Removable = WdfTrue;
2166 child_pnp_capabilities.DockDevice = WdfFalse;
2167 child_pnp_capabilities.UniqueID = WdfFalse;
2168 child_pnp_capabilities.SilentInstall = WdfTrue;
2169 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
2170 child_pnp_capabilities.HardwareDisabled = WdfFalse;
2171 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
2173 WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
2174 child_power_capabilities.DeviceD1 = WdfTrue;
2175 child_power_capabilities.WakeFromD1 = WdfTrue;
2176 child_power_capabilities.DeviceWake = PowerDeviceD1;
2177 child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
2178 child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
2179 child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
2180 child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
2181 child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
2182 child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
2183 WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
2185 bus_interface.Size = sizeof(BUS_INTERFACE_STANDARD);
2186 bus_interface.Version = 1; //BUS_INTERFACE_STANDARD_VERSION;
2187 bus_interface.Context = xppdd;
2188 bus_interface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
2189 bus_interface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
2190 bus_interface.TranslateBusAddress = XenPci_BIS_TranslateBusAddress;
2191 bus_interface.GetDmaAdapter = XenPci_BIS_GetDmaAdapter;
2192 bus_interface.SetBusData = XenPci_BIS_SetBusData;
2193 bus_interface.GetBusData = XenPci_BIS_GetBusData;
2194 WDF_QUERY_INTERFACE_CONFIG_INIT(&interface_config, (PINTERFACE)&bus_interface, &GUID_BUS_INTERFACE_STANDARD, NULL);
2195 status = WdfDeviceAddQueryInterface(child_device, &interface_config);
2196 if (!NT_SUCCESS(status))
2198 return status;
2201 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
2202 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
2203 xppdd->index = identification->index;
2204 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
2205 xppdd->backend_state = XenbusStateUnknown;
2206 xppdd->frontend_state = XenbusStateUnknown;
2207 xppdd->backend_path[0] = '\0';
2209 FUNCTION_EXIT();
2211 return status;
2214 static __forceinline VOID
2215 XenPci_Pdo_ChangeSuspendState(WDFDEVICE device, ULONG new_state)
2217 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2218 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2220 FUNCTION_ENTER();
2221 KdPrint((__DRIVER_NAME " setting pdo state to %d\n", new_state));
2222 xppdd->device_state.suspend_resume_state_pdo = new_state;
2223 KeMemoryBarrier();
2224 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xpdd->pdo_event_channel));
2225 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
2226 while(xppdd->device_state.suspend_resume_state_fdo != xppdd->device_state.suspend_resume_state_pdo)
2228 KdPrint((__DRIVER_NAME " waiting...\n"));
2229 KeWaitForSingleObject(&xpdd->pdo_suspend_event, Executive, KernelMode, FALSE, NULL);
2231 KdPrint((__DRIVER_NAME " fdo state set to %d\n", new_state));
2232 FUNCTION_EXIT();
2235 /* called at PASSIVE_LEVEL */
2236 NTSTATUS
2237 XenPci_Pdo_Suspend(WDFDEVICE device)
2239 NTSTATUS status = STATUS_SUCCESS;
2240 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2241 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2242 //LARGE_INTEGER wait_time;
2243 char path[128];
2244 PUCHAR in_ptr;
2245 UCHAR type;
2246 PVOID setting;
2247 PVOID value;
2248 PVOID value2;
2250 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
2252 if (xppdd->backend_state == XenbusStateConnected)
2254 xppdd->restart_on_resume = TRUE;
2255 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_SUSPENDING);
2257 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
2258 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
2259 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
2261 if (xppdd->assigned_resources_start != NULL)
2263 in_ptr = xppdd->assigned_resources_ptr;
2264 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
2265 in_ptr = xppdd->assigned_resources_start;
2266 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
2268 switch (type)
2270 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
2271 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
2272 EvtChn_Unbind(xpdd, PtrToUlong(value));
2273 EvtChn_Close(xpdd, PtrToUlong(value));
2274 break;
2279 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2280 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
2282 else
2284 xppdd->restart_on_resume = FALSE;
2287 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
2289 return status;
2292 NTSTATUS
2293 XenPci_Pdo_Resume(WDFDEVICE device)
2295 NTSTATUS status = STATUS_SUCCESS;
2296 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
2297 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
2298 ULONG old_backend_state;
2299 PUCHAR src, dst;
2301 FUNCTION_ENTER();
2302 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
2304 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
2305 old_backend_state = xppdd->backend_state;
2307 if (xppdd->restart_on_resume)
2309 status = XenPci_GetBackendAndAddWatch(device);
2311 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
2313 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
2314 // this is probably an unrecoverable situation...
2315 FUNCTION_ERROR_EXIT();
2316 return STATUS_UNSUCCESSFUL;
2318 if (xppdd->assigned_resources_ptr)
2320 // reset things - feed the 'requested resources' back in
2321 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
2322 src = xppdd->requested_resources_start;
2323 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
2324 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
2326 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
2328 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
2330 MmUnmapIoSpace(dst, xppdd->config_page_length);
2331 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
2333 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
2335 // this is definitely an unrecoverable situation...
2336 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
2337 FUNCTION_ERROR_EXIT();
2338 return STATUS_UNSUCCESSFUL;
2340 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RESUMING);
2341 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RUNNING);
2344 FUNCTION_EXIT();
2346 return STATUS_SUCCESS;
2349 #if 0
2350 NTSTATUS
2351 XenPci_Power_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
2353 NTSTATUS status;
2354 PIO_STACK_LOCATION stack;
2355 POWER_STATE_TYPE power_type;
2356 POWER_STATE power_state;
2357 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
2358 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2360 UNREFERENCED_PARAMETER(device_object);
2362 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
2364 stack = IoGetCurrentIrpStackLocation(irp);
2365 power_type = stack->Parameters.Power.Type;
2366 power_state = stack->Parameters.Power.State;
2368 switch (stack->MinorFunction)
2370 case IRP_MN_POWER_SEQUENCE:
2371 //KdPrint((__DRIVER_NAME " IRP_MN_POWER_SEQUENCE\n"));
2372 status = STATUS_NOT_SUPPORTED;
2373 break;
2374 case IRP_MN_QUERY_POWER:
2375 //KdPrint((__DRIVER_NAME " IRP_MN_QUERY_POWER\n"));
2376 status = STATUS_SUCCESS;
2377 break;
2378 case IRP_MN_SET_POWER:
2379 //KdPrint((__DRIVER_NAME " IRP_MN_SET_POWER\n"));
2380 switch (power_type) {
2381 case DevicePowerState:
2382 PoSetPowerState(device_object, power_type, power_state);
2383 status = STATUS_SUCCESS;
2384 break;
2385 case SystemPowerState:
2386 status = STATUS_SUCCESS;
2387 break;
2388 default:
2389 status = STATUS_NOT_SUPPORTED;
2390 break;
2392 break;
2393 case IRP_MN_WAIT_WAKE:
2394 //KdPrint((__DRIVER_NAME " IRP_MN_WAIT_WAKE\n"));
2395 status = STATUS_NOT_SUPPORTED;
2396 break;
2397 default:
2398 //KdPrint((__DRIVER_NAME " Unknown IRP_MN_%d\n", stack->MinorFunction));
2399 status = STATUS_NOT_SUPPORTED;
2400 break;
2402 if (status != STATUS_NOT_SUPPORTED) {
2403 irp->IoStatus.Status = status;
2406 PoStartNextPowerIrp(irp);
2407 status = irp->IoStatus.Status;
2408 IoCompleteRequest(irp, IO_NO_INCREMENT);
2410 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
2412 return status;
2415 /*
2416 Called at PASSIVE_LEVEL(?)
2417 Called during restore
2418 */
2420 static ULONG
2421 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
2423 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2424 char path[128];
2425 char *value;
2426 char *err;
2427 ULONG backend_state;
2429 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2430 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
2431 if (err)
2433 XenPci_FreeMem(err);
2434 return XenbusStateUnknown;
2436 else
2438 backend_state = atoi(value);
2439 XenPci_FreeMem(value);
2440 return backend_state;
2444 static VOID
2445 XenPci_BackEndStateHandler(char *path, PVOID context)
2447 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)context;
2448 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2449 ULONG new_backend_state;
2451 #if !DBG
2452 UNREFERENCED_PARAMETER(path);
2453 #endif
2455 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
2457 /* check that path == device/id/state */
2458 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
2459 new_backend_state = XenPci_ReadBackendState(xppdd);
2460 if (new_backend_state == XenbusStateUnknown)
2462 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
2463 return;
2464 KdPrint(("Failed to read %s, assuming closed\n", path));
2465 new_backend_state = XenbusStateClosed;
2468 if (xppdd->backend_state == new_backend_state)
2470 KdPrint((__DRIVER_NAME " state unchanged\n"));
2471 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
2472 return;
2475 xppdd->backend_state = new_backend_state;
2477 switch (xppdd->backend_state)
2479 case XenbusStateUnknown:
2480 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown (%s)\n", path));
2481 break;
2483 case XenbusStateInitialising:
2484 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising (%s)\n", path));
2485 break;
2487 case XenbusStateInitWait:
2488 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait (%s)\n", path));
2489 break;
2491 case XenbusStateInitialised:
2492 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised (%s)\n", path));
2493 break;
2495 case XenbusStateConnected:
2496 KdPrint((__DRIVER_NAME " Backend State Changed to Connected (%s)\n", path));
2497 break;
2499 case XenbusStateClosing:
2500 KdPrint((__DRIVER_NAME " Backend State Changed to Closing (%s)\n", path));
2501 if (xpdd->suspend_state == SUSPEND_STATE_NONE)
2503 if (xppdd->common.device_usage_paging
2504 || xppdd->common.device_usage_dump
2505 || xppdd->common.device_usage_hibernation)
2507 KdPrint((__DRIVER_NAME " Not closing device because it is in use\n"));
2508 /* in use by page file, dump file, or hiber file - can't close */
2509 /* we should probably re-check if the device usage changes in the future */
2511 else
2513 if (xppdd->common.current_pnp_state == Started)
2515 KdPrint((__DRIVER_NAME " Sending RequestDeviceEject\n"));
2516 IoRequestDeviceEject(xppdd->common.pdo);
2518 else
2520 KdPrint((__DRIVER_NAME " Not closing device because it is not started\n"));
2524 break;
2526 case XenbusStateClosed:
2527 KdPrint((__DRIVER_NAME " Backend State Changed to Closed (%s)\n", path));
2528 break;
2530 default:
2531 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d (%s)\n", xppdd->backend_state, path));
2532 break;
2535 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
2537 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
2539 return;
2542 struct dummy_sring {
2543 RING_IDX req_prod, req_event;
2544 RING_IDX rsp_prod, rsp_event;
2545 uint8_t pad[48];
2546 };
2548 /*
2549 Called at PASSIVE_LEVEL
2550 Called during restore
2551 */
2553 static NTSTATUS
2554 XenPci_ChangeFrontendState(PXENPCI_PDO_DEVICE_DATA xppdd, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
2556 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2557 LARGE_INTEGER timeout;
2558 ULONG remaining;
2559 ULONG thiswait;
2560 char path[128];
2562 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
2564 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
2565 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
2567 remaining = maximum_wait_ms;
2569 while (xppdd->backend_state != backend_state_response)
2571 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
2572 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
2573 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
2575 remaining -= thiswait;
2576 if (remaining == 0)
2578 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
2579 return STATUS_UNSUCCESSFUL;
2581 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
2584 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
2585 return STATUS_SUCCESS;
2588 static VOID
2589 DUMP_CURRENT_PNP_STATE(PXENPCI_PDO_DEVICE_DATA xppdd)
2591 switch (xppdd->common.current_pnp_state)
2593 case Unknown:
2594 KdPrint((__DRIVER_NAME " pnp_state = Unknown\n"));
2595 break;
2596 case NotStarted:
2597 KdPrint((__DRIVER_NAME " pnp_state = NotStarted\n"));
2598 break;
2599 case Started:
2600 KdPrint((__DRIVER_NAME " pnp_state = Started\n"));
2601 break;
2602 case StopPending:
2603 KdPrint((__DRIVER_NAME " pnp_state = StopPending\n"));
2604 break;
2605 case Stopped:
2606 KdPrint((__DRIVER_NAME " pnp_state = Stopped\n"));
2607 break;
2608 case RemovePending:
2609 KdPrint((__DRIVER_NAME " pnp_state = RemovePending\n"));
2610 break;
2611 case SurpriseRemovePending:
2612 KdPrint((__DRIVER_NAME " pnp_state = SurpriseRemovePending\n"));
2613 break;
2614 case Removed:
2615 KdPrint((__DRIVER_NAME " pnp_state = Removed\n"));
2616 break;
2617 default:
2618 KdPrint((__DRIVER_NAME " pnp_state = ???\n"));
2619 break;
2623 static NTSTATUS
2624 XenPci_EvtChn_Bind(PVOID Context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
2626 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2627 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2629 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext);
2632 static NTSTATUS
2633 XenPci_EvtChn_BindDpc(PVOID Context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
2635 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2636 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2638 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext);
2641 static NTSTATUS
2642 XenPci_EvtChn_Unbind(PVOID Context, evtchn_port_t Port)
2644 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2645 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2647 return EvtChn_Unbind(xpdd, Port);
2650 static NTSTATUS
2651 XenPci_EvtChn_Mask(PVOID Context, evtchn_port_t Port)
2653 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2654 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2656 return EvtChn_Mask(xpdd, Port);
2659 static NTSTATUS
2660 XenPci_EvtChn_Unmask(PVOID Context, evtchn_port_t Port)
2662 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2663 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2665 return EvtChn_Unmask(xpdd, Port);
2668 static NTSTATUS
2669 XenPci_EvtChn_Notify(PVOID Context, evtchn_port_t Port)
2671 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2672 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2674 return EvtChn_Notify(xpdd, Port);
2677 static BOOLEAN
2678 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port)
2680 PXENPCI_PDO_DEVICE_DATA xppdd = context;
2681 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2683 return EvtChn_AckEvent(xpdd, port);
2686 static BOOLEAN
2687 XenPci_EvtChn_Sync(PVOID context, PKSYNCHRONIZE_ROUTINE sync_routine, PVOID sync_context)
2689 PXENPCI_PDO_DEVICE_DATA xppdd = context;
2690 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2692 return KeSynchronizeExecution(xpdd->interrupt, sync_routine, sync_context);
2695 static grant_ref_t
2696 XenPci_GntTbl_GrantAccess(PVOID Context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref)
2698 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2699 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2701 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref);
2704 static BOOLEAN
2705 XenPci_GntTbl_EndAccess(PVOID Context, grant_ref_t ref, BOOLEAN keepref)
2707 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2708 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2710 return GntTbl_EndAccess(xpdd, ref, keepref);
2713 static VOID
2714 XenPci_GntTbl_PutRef(PVOID Context, grant_ref_t ref)
2716 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2717 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2719 GntTbl_PutRef(xpdd, ref);
2722 static grant_ref_t
2723 XenPci_GntTbl_GetRef(PVOID Context)
2725 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2726 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2728 return GntTbl_GetRef(xpdd);
2731 PCHAR
2732 XenPci_XenBus_Read(PVOID Context, xenbus_transaction_t xbt, char *path, char **value)
2734 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2735 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2736 return XenBus_Read(xpdd, xbt, path, value);
2739 PCHAR
2740 XenPci_XenBus_Write(PVOID Context, xenbus_transaction_t xbt, char *path, char *value)
2742 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2743 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2744 return XenBus_Write(xpdd, xbt, path, value);
2747 PCHAR
2748 XenPci_XenBus_Printf(PVOID Context, xenbus_transaction_t xbt, char *path, char *fmt, ...)
2750 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2751 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2752 //return XenBus_Printf(xpdd, xbt, path, value);
2753 UNREFERENCED_PARAMETER(Context);
2754 UNREFERENCED_PARAMETER(xbt);
2755 UNREFERENCED_PARAMETER(path);
2756 UNREFERENCED_PARAMETER(fmt);
2757 return NULL;
2760 PCHAR
2761 XenPci_XenBus_StartTransaction(PVOID Context, xenbus_transaction_t *xbt)
2763 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2764 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2765 return XenBus_StartTransaction(xpdd, xbt);
2768 PCHAR
2769 XenPci_XenBus_EndTransaction(PVOID Context, xenbus_transaction_t xbt, int abort, int *retry)
2771 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2772 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2773 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
2776 PCHAR
2777 XenPci_XenBus_List(PVOID Context, xenbus_transaction_t xbt, char *prefix, char ***contents)
2779 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2780 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2781 return XenBus_List(xpdd, xbt, prefix, contents);
2784 PCHAR
2785 XenPci_XenBus_AddWatch(PVOID Context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
2787 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2788 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2789 PCHAR retval;
2791 FUNCTION_ENTER();
2792 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
2793 if (retval == NULL)
2795 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
2797 else
2799 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
2801 FUNCTION_EXIT();
2802 return retval;
2805 PCHAR
2806 XenPci_XenBus_RemWatch(PVOID Context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
2808 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2809 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2810 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
2813 static NTSTATUS
2814 XenPci_XenShutdownDevice(PVOID Context)
2816 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2817 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2818 PUCHAR in_ptr;
2819 ULONG i;
2820 UCHAR type;
2821 PVOID setting;
2822 PVOID value;
2824 FUNCTION_ENTER();
2826 if (xppdd->backend_state == XenbusStateConnected)
2828 XenPci_ChangeFrontendState(xppdd, XenbusStateClosing, XenbusStateClosing, 30000);
2829 if (xppdd->backend_state == XenbusStateClosing)
2830 XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
2831 if (xppdd->backend_state == XenbusStateClosed)
2832 XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
2834 else
2836 if (xppdd->backend_state == XenbusStateClosing)
2837 XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
2840 if (xppdd->assigned_resources_start != NULL)
2842 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
2843 in_ptr = xppdd->assigned_resources_start;
2844 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
2846 switch (type)
2848 case XEN_INIT_TYPE_RING: /* frontend ring */
2849 FreePages(value);
2850 break;
2851 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
2852 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
2853 EvtChn_Unbind(xpdd, PtrToUlong(value));
2854 EvtChn_Close(xpdd, PtrToUlong(value));
2855 break;
2856 case XEN_INIT_TYPE_GRANT_ENTRIES:
2857 for (i = 0; i < PtrToUlong(setting); i++)
2858 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value)[i], FALSE);
2859 break;
2862 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
2863 xppdd->assigned_resources_start = NULL;
2866 FUNCTION_EXIT();
2868 return STATUS_SUCCESS;
2871 static NTSTATUS
2872 XenPci_XenConfigDevice(PVOID context);
2874 static NTSTATUS
2875 XenPci_XenConfigDeviceSpecifyBuffers(PVOID context, PUCHAR src, PUCHAR dst)
2877 PXENPCI_PDO_DEVICE_DATA xppdd = context;
2878 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2879 NTSTATUS status = STATUS_SUCCESS;
2880 ULONG i;
2881 char path[128];
2882 PCHAR setting, value, value2;
2883 PCHAR res;
2884 PVOID address;
2885 UCHAR type;
2886 PUCHAR in_ptr; //, in_start;
2887 PUCHAR out_ptr; //, out_start;
2888 XENPCI_VECTORS vectors;
2889 ULONG event_channel;
2890 ULONG run_type = 0;
2891 PMDL ring;
2892 grant_ref_t gref;
2893 BOOLEAN done_xenbus_init = FALSE;
2895 FUNCTION_ENTER();
2897 in_ptr = src;
2898 out_ptr = dst;
2900 // always add vectors
2901 vectors.magic = XEN_DATA_MAGIC;
2902 vectors.length = sizeof(XENPCI_VECTORS);
2903 vectors.context = xppdd;
2904 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
2905 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
2906 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
2907 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
2908 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
2909 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
2910 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
2911 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
2912 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
2913 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
2914 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
2915 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
2916 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
2917 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
2918 strncpy(vectors.path, xppdd->path, 128);
2919 strncpy(vectors.backend_path, xppdd->backend_path, 128);
2920 vectors.pdo_event_channel = xpdd->pdo_event_channel;
2921 vectors.XenBus_Read = XenPci_XenBus_Read;
2922 vectors.XenBus_Write = XenPci_XenBus_Write;
2923 vectors.XenBus_Printf = XenPci_XenBus_Printf;
2924 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
2925 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
2926 vectors.XenBus_List = XenPci_XenBus_List;
2927 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
2928 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
2930 if (qemu_filtered)
2931 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_ACTIVE, NULL, NULL, NULL);
2933 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
2935 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
2936 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
2938 // first pass, possibly before state == Connected
2939 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
2942 if (!done_xenbus_init)
2944 if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
2946 status = STATUS_UNSUCCESSFUL;
2947 goto error;
2949 done_xenbus_init = TRUE;
2952 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
2954 switch (type)
2956 case XEN_INIT_TYPE_RUN:
2957 run_type++;
2958 break;
2959 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
2960 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
2961 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
2962 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
2963 break;
2964 case XEN_INIT_TYPE_RING: /* frontend ring */
2965 /* we only allocate and do the SHARED_RING_INIT here */
2966 if ((ring = AllocatePage()) != 0)
2968 address = MmGetMdlVirtualAddress(ring);
2969 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
2970 SHARED_RING_INIT((struct dummy_sring *)address);
2971 if ((gref = GntTbl_GrantAccess(
2972 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
2974 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
2975 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
2976 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
2977 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
2978 // add the grant entry too so it gets freed automatically
2979 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
2980 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
2981 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
2983 else
2985 FreePages(ring);
2986 status = STATUS_UNSUCCESSFUL;
2987 goto error;
2990 else
2992 status = STATUS_UNSUCCESSFUL;
2993 goto error;
2995 break;
2996 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
2997 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
2998 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
3000 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
3001 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
3002 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
3003 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
3004 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
3005 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
3006 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
3008 else
3010 status = STATUS_UNSUCCESSFUL;
3011 goto error;
3013 break;
3016 if (!NT_SUCCESS(status))
3018 goto error;
3020 // If XEN_INIT_TYPE_RUN was specified more than once then we skip XenbusStateInitialised here and go straight to XenbusStateConnected at the end
3021 if (run_type == 1)
3023 if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialised, XenbusStateConnected, 30000) != STATUS_SUCCESS)
3025 status = STATUS_UNSUCCESSFUL;
3026 goto error;
3030 // second pass, possibly after state == Connected
3031 in_ptr = src;
3032 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
3034 switch(type)
3036 case XEN_INIT_TYPE_READ_STRING_BACK:
3037 case XEN_INIT_TYPE_READ_STRING_FRONT:
3038 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
3039 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
3040 else
3041 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
3042 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
3043 if (res)
3045 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
3046 XenPci_FreeMem(res);
3047 ADD_XEN_INIT_RSP(&out_ptr, type, setting, NULL, NULL);
3049 else
3051 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
3052 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, NULL);
3053 XenPci_FreeMem(value);
3055 break;
3056 case XEN_INIT_TYPE_VECTORS:
3057 // this is always done so ignore the request
3058 break;
3059 case XEN_INIT_TYPE_GRANT_ENTRIES:
3060 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
3061 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
3062 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
3063 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
3064 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
3065 for (i = 0; i < PtrToUlong(value); i++)
3067 gref = GntTbl_GetRef(xpdd);
3068 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
3069 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
3071 break;
3074 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL);
3076 if (run_type)
3078 if (XenPci_ChangeFrontendState(xppdd, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
3080 status = STATUS_UNSUCCESSFUL;
3081 goto error;
3084 FUNCTION_EXIT();
3085 return status;
3087 error:
3088 XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
3089 FUNCTION_EXIT_STATUS(status);
3091 return status;
3094 static NTSTATUS
3095 XenPci_XenConfigDevice(PVOID context)
3097 NTSTATUS status;
3098 PUCHAR src, dst;
3099 PXENPCI_PDO_DEVICE_DATA xppdd = context;
3101 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
3102 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
3103 memcpy(src, dst, xppdd->config_page_length);
3105 status = XenPci_XenConfigDeviceSpecifyBuffers(xppdd, src, dst);
3107 MmUnmapIoSpace(dst, xppdd->config_page_length);
3108 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
3110 return status;
3113 static NTSTATUS
3114 XenPci_GetBackendAndAddWatch(PDEVICE_OBJECT device_object)
3116 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3117 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
3118 char path[128];
3119 PCHAR res;
3120 PCHAR value;
3122 /* Get backend path */
3123 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
3124 "%s/backend", xppdd->path);
3125 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
3126 if (res)
3128 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
3129 XenPci_FreeMem(res);
3130 return STATUS_UNSUCCESSFUL;
3132 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
3133 XenPci_FreeMem(value);
3135 /* Add watch on backend state */
3136 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
3137 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
3139 return STATUS_SUCCESS;
3142 NTSTATUS
3143 XenPci_Pdo_Resume(PDEVICE_OBJECT device_object)
3145 NTSTATUS status;
3146 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3147 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
3148 ULONG old_backend_state;
3149 PUCHAR src, dst;
3151 FUNCTION_ENTER();
3153 old_backend_state = xppdd->backend_state;
3155 if (xppdd->restart_on_resume)
3157 status = XenPci_GetBackendAndAddWatch(device_object);
3159 if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
3161 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
3162 // this is probably an unrecoverable situation...
3163 FUNCTION_ERROR_EXIT();
3164 return STATUS_UNSUCCESSFUL;
3166 if (xppdd->assigned_resources_ptr)
3168 // reset things - feed the 'requested resources' back in
3169 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL);
3170 src = xppdd->requested_resources_start;
3171 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
3172 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
3174 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
3176 status = XenPci_XenConfigDeviceSpecifyBuffers(xppdd, src, dst);
3178 MmUnmapIoSpace(dst, xppdd->config_page_length);
3179 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
3181 if (XenPci_ChangeFrontendState(xppdd, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
3183 // this is definitely an unrecoverable situation...
3184 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
3185 FUNCTION_ERROR_EXIT();
3186 return STATUS_UNSUCCESSFUL;
3189 else
3191 KdPrint((__DRIVER_NAME " Not resuming - current_pnp_state = %d, old_backend_state = %d\n", xppdd->common.current_pnp_state, old_backend_state));
3193 KeMemoryBarrier();
3194 xppdd->device_state.resume_state = RESUME_STATE_FRONTEND_RESUME;
3195 KeMemoryBarrier();
3196 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
3198 FUNCTION_EXIT();
3200 return STATUS_SUCCESS;
3203 /* called at PASSIVE_LEVEL */
3204 NTSTATUS
3205 XenPci_Pdo_Suspend(PDEVICE_OBJECT device_object)
3207 NTSTATUS status = STATUS_SUCCESS;
3208 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3209 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
3210 LARGE_INTEGER wait_time;
3211 char path[128];
3212 PUCHAR in_ptr;
3213 UCHAR type;
3214 PVOID setting;
3215 PVOID value;
3217 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
3219 if (xppdd->backend_state == XenbusStateConnected)
3221 xppdd->restart_on_resume = TRUE;
3222 xppdd->device_state.resume_state_ack = RESUME_STATE_RUNNING;
3223 KeMemoryBarrier();
3224 xppdd->device_state.resume_state = RESUME_STATE_SUSPENDING;
3225 KeMemoryBarrier();
3226 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
3227 while(xppdd->device_state.resume_state_ack != RESUME_STATE_SUSPENDING)
3229 KdPrint((__DRIVER_NAME " Starting delay - resume_state = %d, resume_state_ack = %d\n", xppdd->device_state.resume_state, xppdd->device_state.resume_state_ack));
3230 wait_time.QuadPart = 100 * (-1 * 10 * 1000);
3231 KeDelayExecutionThread(KernelMode, FALSE, &wait_time);
3232 KdPrint((__DRIVER_NAME " Done with delay\n"));
3234 KdPrint((__DRIVER_NAME " resume_state acknowledged\n"));
3236 XenPci_ChangeFrontendState(xppdd, XenbusStateClosing, XenbusStateClosing, 30000);
3237 XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
3238 XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
3240 if (xppdd->assigned_resources_start != NULL)
3242 in_ptr = xppdd->assigned_resources_ptr;
3243 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL);
3244 in_ptr = xppdd->assigned_resources_start;
3245 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value)) != XEN_INIT_TYPE_END)
3247 switch (type)
3249 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
3250 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
3251 EvtChn_Close(xpdd, PtrToUlong(value));
3252 break;
3257 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
3258 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
3260 else
3262 xppdd->restart_on_resume = FALSE;
3265 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
3267 return status;
3270 VOID
3271 XenPci_DumpPdoConfig(PDEVICE_OBJECT device_object)
3273 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3275 #if !DBG
3276 UNREFERENCED_PARAMETER(xppdd);
3277 #endif
3279 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
3280 KdPrint((__DRIVER_NAME " backend_path = %s\n", xppdd->backend_path));
3281 KdPrint((__DRIVER_NAME " irq_number = %d\n", xppdd->irq_number));
3282 KdPrint((__DRIVER_NAME " irq_level = %d\n", xppdd->irq_level));
3283 KdPrint((__DRIVER_NAME " irq_vector = %x\n", xppdd->irq_vector));
3286 static PMDL
3287 XenConfig_MakeConfigPage(PDEVICE_OBJECT device_object, PMDL mdl)
3289 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
3290 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3291 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
3292 PMDL mdl;
3293 PUCHAR ptr;
3294 PDEVICE_OBJECT curr, prev;
3295 PDRIVER_OBJECT fdo_driver_object;
3296 PUCHAR fdo_driver_extension;
3298 ptr = MmGetMdlVirtualAddress(mdl);
3299 curr = IoGetAttachedDeviceReference(device_object);
3300 while (curr != NULL)
3302 fdo_driver_object = curr->DriverObject;
3303 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
3304 if (fdo_driver_object)
3306 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
3307 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
3308 if (fdo_driver_extension)
3310 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
3311 ObDereferenceObject(curr);
3312 break;
3315 prev = curr;
3316 curr = IoGetLowerDeviceObject(curr);
3317 ObDereferenceObject(prev);
3319 return mdl;
3322 static NTSTATUS
3323 XenPci_Pnp_StartDevice(PDEVICE_OBJECT device_object, PIRP irp)
3325 NTSTATUS status = STATUS_SUCCESS;
3326 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3327 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
3328 PIO_STACK_LOCATION stack;
3329 PCM_PARTIAL_RESOURCE_LIST prl;
3330 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
3331 ULONG i;
3332 char path[128];
3333 PMDL mdl;
3335 FUNCTION_ENTER();
3336 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
3338 DUMP_CURRENT_PNP_STATE(xppdd);
3340 stack = IoGetCurrentIrpStackLocation(irp);
3342 status = XenPci_GetBackendAndAddWatch(device_object);
3343 if (!NT_SUCCESS(status)) {
3344 FUNCTION_ERROR_EXIT();
3345 return status;
3348 mdl = XenConfig_MakeConfigPage(device_object);
3350 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
3351 for (i = 0; i < prl->Count; i++)
3353 prd = & prl->PartialDescriptors[i];
3354 switch (prd->Type)
3356 #if 0
3357 case CmResourceTypeInterrupt:
3358 KdPrint((__DRIVER_NAME " CmResourceTypeInterrupt\n"));
3359 KdPrint((__DRIVER_NAME " irq_number = %02x\n", prd->u.Interrupt.Vector));
3360 xppdd->irq_number = prd->u.Interrupt.Vector;
3361 break;
3362 #endif
3363 case CmResourceTypeMemory:
3364 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
3366 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
3367 prd->u.Memory.Length = MmGetMdlByteCount(mdl);
3369 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
3371 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
3372 prd->Type = CmResourceTypeInterrupt;
3373 prd->ShareDisposition = CmResourceShareShared;
3374 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
3375 prd->u.Interrupt.Level = xpdd->irq_number;
3376 prd->u.Interrupt.Vector = xpdd->irq_number;
3377 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
3378 xppdd->irq_number = xpdd->irq_number;
3380 break;
3384 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
3385 for (i = 0; i < prl->Count; i++)
3387 prd = & prl->PartialDescriptors[i];
3388 switch (prd->Type)
3390 #if 0
3391 case CmResourceTypeInterrupt:
3392 KdPrint((__DRIVER_NAME " CmResourceTypeInterrupt (%d)\n", i));
3393 KdPrint((__DRIVER_NAME " irq_vector = %02x\n", prd->u.Interrupt.Vector));
3394 KdPrint((__DRIVER_NAME " irq_level = %d\n", prd->u.Interrupt.Level));
3395 xppdd->irq_vector = prd->u.Interrupt.Vector;
3396 xppdd->irq_level = (KIRQL)prd->u.Interrupt.Level;
3397 break;
3398 #endif
3399 case CmResourceTypeMemory:
3400 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
3401 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
3402 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
3404 if (prd->u.Memory.Length == 0)
3406 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(mdl)[0]));
3407 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
3408 prd->u.Memory.Length = MmGetMdlByteCount(mdl);
3409 KdPrint((__DRIVER_NAME " New Start = %08x%08x, Length = %d\n", prd->u.Memory.Start.HighPart, prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
3411 xppdd->config_page_phys = prd->u.Memory.Start;
3412 xppdd->config_page_length = prd->u.Memory.Length;
3413 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
3414 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
3416 status = XenPci_XenConfigDevice(xppdd);
3417 if (!NT_SUCCESS(status))
3419 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
3420 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
3421 FUNCTION_ERROR_EXIT();
3422 return status;
3425 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
3427 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
3428 prd->Type = CmResourceTypeInterrupt;
3429 prd->ShareDisposition = CmResourceShareShared;
3430 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
3431 prd->u.Interrupt.Level = xpdd->irq_level;
3432 prd->u.Interrupt.Vector = xpdd->irq_vector;
3433 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
3434 xppdd->irq_vector = xpdd->irq_vector;
3435 xppdd->irq_level = xpdd->irq_level;
3437 break;
3441 SET_PNP_STATE(&xppdd->common, Started);
3443 FUNCTION_EXIT();
3445 return STATUS_SUCCESS;
3448 static NTSTATUS
3449 XenPci_Pnp_RemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
3451 NTSTATUS status = STATUS_SUCCESS;
3452 PXENPCI_PDO_DEVICE_DATA xppdd = device_object->DeviceExtension;
3453 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
3454 char path[128];
3456 UNREFERENCED_PARAMETER(irp);
3458 FUNCTION_ENTER();
3460 DUMP_CURRENT_PNP_STATE(xppdd);
3462 if (xppdd->common.current_pnp_state != Removed)
3464 status = XenPci_XenShutdownDevice(xppdd);
3465 /* Remove watch on backend state */
3466 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
3467 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
3468 SET_PNP_STATE(&xppdd->common, Removed);
3469 IoInvalidateDeviceRelations(xppdd->bus_pdo, BusRelations);
3471 if (xppdd->reported_missing)
3473 IoDeleteDevice(xppdd->common.pdo);
3476 FUNCTION_EXIT_STATUS(status);
3478 return status;
3481 static NTSTATUS
3482 XenPci_QueryResourceRequirements(PDEVICE_OBJECT device_object, PIRP irp)
3484 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3485 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
3486 PIO_RESOURCE_REQUIREMENTS_LIST irrl;
3487 PIO_RESOURCE_DESCRIPTOR ird;
3488 ULONG length;
3490 UNREFERENCED_PARAMETER(device_object);
3492 FUNCTION_ENTER();
3494 length = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List) +
3495 FIELD_OFFSET(IO_RESOURCE_LIST, Descriptors) +
3496 sizeof(IO_RESOURCE_DESCRIPTOR) * 2;
3497 irrl = ExAllocatePoolWithTag(NonPagedPool,
3498 length,
3499 XENPCI_POOL_TAG);
3501 irrl->ListSize = length;
3502 irrl->InterfaceType = PNPBus; //Internal;
3503 irrl->BusNumber = 0;
3504 irrl->SlotNumber = 0;
3505 irrl->AlternativeLists = 1;
3506 irrl->List[0].Version = 1;
3507 irrl->List[0].Revision = 1;
3508 irrl->List[0].Count = 0;
3510 #if 0
3511 ird = &irrl->List[0].Descriptors[irrl->List[0].Count++];
3512 ird->Option = 0;
3513 ird->Type = CmResourceTypeInterrupt;
3514 ird->ShareDisposition = CmResourceShareShared;
3515 ird->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
3516 KdPrint((__DRIVER_NAME " irq type = %s\n", (xpdd->irq_mode == Latched)?"Latched":"Level"));
3517 ird->u.Interrupt.MinimumVector = xpdd->irq_number;
3518 ird->u.Interrupt.MaximumVector = xpdd->irq_number;
3519 #endif
3521 ird = &irrl->List[0].Descriptors[irrl->List[0].Count++];
3522 ird->Option = 0;
3523 ird->Type = CmResourceTypeMemory;
3524 ird->ShareDisposition = CmResourceShareShared;
3525 ird->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
3526 ird->u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
3527 ird->u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
3528 ird->u.Memory.Length = 0;
3529 ird->u.Memory.Alignment = PAGE_SIZE;
3531 ird = &irrl->List[0].Descriptors[irrl->List[0].Count++];
3532 ird->Option = 0;
3533 ird->Type = CmResourceTypeMemory;
3534 ird->ShareDisposition = CmResourceShareShared;
3535 ird->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
3536 ird->u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
3537 ird->u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
3538 ird->u.Memory.Length = 0;
3539 ird->u.Memory.Alignment = PAGE_SIZE;
3541 irp->IoStatus.Information = (ULONG_PTR)irrl;
3543 FUNCTION_EXIT();
3545 return STATUS_SUCCESS;
3548 static NTSTATUS
3549 XenPci_Pnp_QueryTargetRelations(PDEVICE_OBJECT device_object, PIRP irp)
3551 PDEVICE_RELATIONS dr;
3552 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3554 dr = (PDEVICE_RELATIONS)ExAllocatePoolWithTag (PagedPool, sizeof(DEVICE_RELATIONS), XENPCI_POOL_TAG);
3555 dr->Count = 1;
3556 dr->Objects[0] = xppdd->common.pdo;
3557 ObReferenceObject(xppdd->common.pdo);
3558 irp->IoStatus.Information = (ULONG_PTR)dr;
3560 return STATUS_SUCCESS;
3563 static NTSTATUS
3564 XenPci_Pnp_QueryCapabilities(PDEVICE_OBJECT device_object, PIRP irp)
3566 PIO_STACK_LOCATION stack;
3567 PDEVICE_CAPABILITIES dc;
3569 UNREFERENCED_PARAMETER(device_object);
3571 stack = IoGetCurrentIrpStackLocation(irp);
3572 dc = stack->Parameters.DeviceCapabilities.Capabilities;
3573 dc->LockSupported = FALSE;
3574 dc->EjectSupported = TRUE;
3575 dc->Removable = TRUE;
3576 dc->DockDevice = FALSE;
3577 dc->UniqueID = FALSE;
3578 dc->SilentInstall = TRUE; //FALSE;
3579 dc->RawDeviceOK = FALSE;
3580 dc->SurpriseRemovalOK = TRUE;
3581 dc->HardwareDisabled = FALSE;
3582 dc->NoDisplayInUI = FALSE;
3583 dc->DeviceWake = PowerDeviceUnspecified;
3584 dc->D1Latency = 0;
3585 dc->D2Latency = 0;
3586 dc->D3Latency = 0;
3587 /* we are really supposed to get the DeviceState entries from the parent... */
3588 dc->DeviceState[PowerSystemWorking] = PowerDeviceD0;
3589 dc->DeviceState[PowerSystemSleeping1] = PowerDeviceUnspecified;
3590 dc->DeviceState[PowerSystemSleeping2] = PowerDeviceUnspecified;
3591 dc->DeviceState[PowerSystemSleeping3] = PowerDeviceUnspecified;
3592 dc->DeviceState[PowerSystemHibernate] = PowerDeviceD3;
3593 dc->DeviceState[PowerSystemShutdown] = PowerDeviceD3;
3594 return STATUS_SUCCESS;
3597 static VOID
3598 XenPci_IS_InterfaceReference(PVOID context)
3600 UNREFERENCED_PARAMETER(context);
3601 FUNCTION_ENTER();
3602 FUNCTION_EXIT();
3605 static VOID
3606 XenPci_IS_InterfaceDereference(PVOID context)
3608 UNREFERENCED_PARAMETER(context);
3609 FUNCTION_ENTER();
3610 FUNCTION_EXIT();
3613 static BOOLEAN
3614 XenPci_BIS_TranslateBusAddress(PVOID context, PHYSICAL_ADDRESS bus_address, ULONG length, PULONG address_space, PPHYSICAL_ADDRESS translated_address)
3616 UNREFERENCED_PARAMETER(context);
3617 UNREFERENCED_PARAMETER(length);
3618 /* actually this isn't right - should look up the gref for the physical address and work backwards from that */
3619 FUNCTION_ENTER();
3620 if (*address_space != 0)
3622 KdPrint((__DRIVER_NAME " Cannot map I/O space\n"));
3623 FUNCTION_EXIT();
3624 return FALSE;
3626 *translated_address = bus_address;
3627 FUNCTION_EXIT();
3628 return TRUE;
3631 static VOID
3632 XenPci_DOP_PutDmaAdapter(PDMA_ADAPTER dma_adapter)
3634 UNREFERENCED_PARAMETER(dma_adapter);
3636 FUNCTION_ENTER();
3637 // decrement ref count
3638 FUNCTION_EXIT();
3640 return;
3643 static PVOID
3644 XenPci_DOP_AllocateCommonBuffer(
3645 PDMA_ADAPTER DmaAdapter,
3646 ULONG Length,
3647 PPHYSICAL_ADDRESS LogicalAddress,
3648 BOOLEAN CacheEnabled
3651 xen_dma_adapter_t *xen_dma_adapter;
3652 PXENPCI_DEVICE_DATA xpdd;
3653 PVOID buffer;
3654 PFN_NUMBER pfn;
3655 grant_ref_t gref;
3657 UNREFERENCED_PARAMETER(DmaAdapter);
3658 UNREFERENCED_PARAMETER(CacheEnabled);
3660 //FUNCTION_ENTER();
3662 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
3663 xpdd = xen_dma_adapter->xppdd->bus_fdo->DeviceExtension;
3665 //KdPrint((__DRIVER_NAME " Length = %d\n", Length));
3667 buffer = ExAllocatePoolWithTag(NonPagedPool, Length, XENPCI_POOL_TAG);
3669 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(buffer).QuadPart >> PAGE_SHIFT);
3670 ASSERT(pfn);
3671 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, pfn, FALSE, INVALID_GRANT_REF);
3672 ASSERT(gref);
3673 LogicalAddress->QuadPart = (gref << PAGE_SHIFT) | (PtrToUlong(buffer) & (PAGE_SIZE - 1));
3675 //FUNCTION_EXIT();
3676 return buffer;
3679 static VOID
3680 XenPci_DOP_FreeCommonBuffer(
3681 PDMA_ADAPTER DmaAdapter,
3682 ULONG Length,
3683 PHYSICAL_ADDRESS LogicalAddress,
3684 PVOID VirtualAddress,
3685 BOOLEAN CacheEnabled
3688 UNREFERENCED_PARAMETER(DmaAdapter);
3689 UNREFERENCED_PARAMETER(Length);
3690 UNREFERENCED_PARAMETER(LogicalAddress);
3691 UNREFERENCED_PARAMETER(CacheEnabled);
3693 FUNCTION_ENTER();
3694 ExFreePoolWithTag(VirtualAddress, XENPCI_POOL_TAG);
3695 // TODO: free the grant ref here
3696 FUNCTION_EXIT();
3699 static NTSTATUS
3700 XenPci_DOP_AllocateAdapterChannel(
3701 IN PDMA_ADAPTER DmaAdapter,
3702 IN PDEVICE_OBJECT DeviceObject,
3703 IN ULONG NumberOfMapRegisters,
3704 IN PDRIVER_CONTROL ExecutionRoutine,
3705 IN PVOID Context
3708 IO_ALLOCATION_ACTION action;
3710 UNREFERENCED_PARAMETER(DmaAdapter);
3711 UNREFERENCED_PARAMETER(NumberOfMapRegisters);
3713 FUNCTION_ENTER();
3714 action = ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, UlongToPtr(64), Context);
3716 switch (action)
3718 case KeepObject:
3719 KdPrint((__DRIVER_NAME " KeepObject\n"));
3720 break;
3721 case DeallocateObject:
3722 KdPrint((__DRIVER_NAME " DeallocateObject\n"));
3723 break;
3724 case DeallocateObjectKeepRegisters:
3725 KdPrint((__DRIVER_NAME " DeallocateObjectKeepRegisters\n"));
3726 break;
3727 default:
3728 KdPrint((__DRIVER_NAME " Unknown action %d\n", action));
3729 break;
3731 FUNCTION_EXIT();
3732 return STATUS_SUCCESS;
3735 static BOOLEAN
3736 XenPci_DOP_FlushAdapterBuffers(
3737 PDMA_ADAPTER DmaAdapter,
3738 PMDL Mdl,
3739 PVOID MapRegisterBase,
3740 PVOID CurrentVa,
3741 ULONG Length,
3742 BOOLEAN WriteToDevice)
3744 UNREFERENCED_PARAMETER(DmaAdapter);
3745 UNREFERENCED_PARAMETER( Mdl);
3746 UNREFERENCED_PARAMETER(MapRegisterBase);
3747 UNREFERENCED_PARAMETER(CurrentVa);
3748 UNREFERENCED_PARAMETER(Length);
3749 UNREFERENCED_PARAMETER(WriteToDevice);
3751 FUNCTION_ENTER();
3752 FUNCTION_EXIT();
3753 return TRUE;
3756 static VOID
3757 XenPci_DOP_FreeAdapterChannel(
3758 IN PDMA_ADAPTER DmaAdapter
3761 UNREFERENCED_PARAMETER(DmaAdapter);
3763 FUNCTION_ENTER();
3764 FUNCTION_EXIT();
3767 static VOID
3768 XenPci_DOP_FreeMapRegisters(
3769 PDMA_ADAPTER DmaAdapter,
3770 PVOID MapRegisterBase,
3771 ULONG NumberOfMapRegisters)
3773 UNREFERENCED_PARAMETER(DmaAdapter);
3774 UNREFERENCED_PARAMETER(MapRegisterBase);
3775 UNREFERENCED_PARAMETER(NumberOfMapRegisters);
3777 FUNCTION_ENTER();
3778 FUNCTION_EXIT();
3781 static PHYSICAL_ADDRESS
3782 XenPci_DOP_MapTransfer(
3783 PDMA_ADAPTER DmaAdapter,
3784 PMDL Mdl,
3785 PVOID MapRegisterBase,
3786 PVOID CurrentVa,
3787 PULONG Length,
3788 BOOLEAN WriteToDevice)
3790 PHYSICAL_ADDRESS physical;
3792 UNREFERENCED_PARAMETER(DmaAdapter);
3793 UNREFERENCED_PARAMETER(Mdl);
3794 UNREFERENCED_PARAMETER(MapRegisterBase);
3795 UNREFERENCED_PARAMETER(CurrentVa);
3796 UNREFERENCED_PARAMETER(Length);
3797 UNREFERENCED_PARAMETER(WriteToDevice);
3799 FUNCTION_ENTER();
3801 physical.QuadPart = 0;
3803 FUNCTION_EXIT();
3804 return physical;
3807 static ULONG
3808 XenPci_DOP_GetDmaAlignment(
3809 PDMA_ADAPTER DmaAdapter)
3811 UNREFERENCED_PARAMETER(DmaAdapter);
3813 FUNCTION_ENTER();
3814 FUNCTION_EXIT();
3815 return 0;
3818 static ULONG
3819 XenPci_DOP_ReadDmaCounter(
3820 PDMA_ADAPTER DmaAdapter)
3822 UNREFERENCED_PARAMETER(DmaAdapter);
3824 FUNCTION_ENTER();
3825 FUNCTION_EXIT();
3826 return 0;
3829 static NTSTATUS
3830 XenPci_DOP_GetScatterGatherList(
3831 PDMA_ADAPTER DmaAdapter,
3832 PDEVICE_OBJECT DeviceObject,
3833 PMDL Mdl,
3834 PVOID CurrentVa,
3835 ULONG Length,
3836 PDRIVER_LIST_CONTROL ExecutionRoutine,
3837 PVOID Context,
3838 BOOLEAN WriteToDevice)
3840 UNREFERENCED_PARAMETER(DmaAdapter);
3841 UNREFERENCED_PARAMETER(DeviceObject);
3842 UNREFERENCED_PARAMETER(Mdl);
3843 UNREFERENCED_PARAMETER(CurrentVa);
3844 UNREFERENCED_PARAMETER(Length);
3845 UNREFERENCED_PARAMETER(ExecutionRoutine);
3846 UNREFERENCED_PARAMETER(Context);
3847 UNREFERENCED_PARAMETER(WriteToDevice);
3849 FUNCTION_ENTER();
3850 FUNCTION_EXIT();
3851 return STATUS_SUCCESS;
3854 #define MAP_TYPE_VIRTUAL 1
3855 #define MAP_TYPE_MDL 2
3856 #define MAP_TYPE_REMAPPED 3
3858 typedef struct {
3859 ULONG map_type;
3860 PVOID aligned_buffer;
3861 PVOID unaligned_buffer;
3862 ULONG copy_length;
3863 } sg_extra_t;
3865 static VOID
3866 XenPci_DOP_PutScatterGatherList(
3867 IN PDMA_ADAPTER DmaAdapter,
3868 IN PSCATTER_GATHER_LIST ScatterGather,
3869 IN BOOLEAN WriteToDevice
3872 xen_dma_adapter_t *xen_dma_adapter;
3873 PXENPCI_DEVICE_DATA xpdd;
3874 ULONG i;
3875 sg_extra_t *sg_extra;
3877 UNREFERENCED_PARAMETER(WriteToDevice);
3879 //FUNCTION_ENTER();
3881 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
3882 xpdd = xen_dma_adapter->xppdd->bus_fdo->DeviceExtension;
3884 sg_extra = (sg_extra_t *)((PUCHAR)ScatterGather + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
3885 (sizeof(SCATTER_GATHER_ELEMENT)) * ScatterGather->NumberOfElements);
3887 switch (sg_extra->map_type)
3889 case MAP_TYPE_REMAPPED:
3890 for (i = 0; i < ScatterGather->NumberOfElements; i++)
3892 grant_ref_t gref;
3893 gref = (grant_ref_t)(ScatterGather->Elements[i].Address.QuadPart >> PAGE_SHIFT);
3894 GntTbl_EndAccess(xpdd, gref, FALSE);
3895 ScatterGather->Elements[i].Address.QuadPart = -1;
3897 if (!WriteToDevice)
3898 memcpy(sg_extra->unaligned_buffer, sg_extra->aligned_buffer, sg_extra->copy_length);
3899 ExFreePoolWithTag(sg_extra->aligned_buffer, XENPCI_POOL_TAG);
3900 break;
3901 case MAP_TYPE_MDL:
3902 for (i = 0; i < ScatterGather->NumberOfElements; i++)
3904 grant_ref_t gref;
3905 gref = (grant_ref_t)(ScatterGather->Elements[i].Address.QuadPart >> PAGE_SHIFT);
3906 GntTbl_EndAccess(xpdd, gref, FALSE);
3907 ScatterGather->Elements[i].Address.QuadPart = -1;
3909 break;
3910 case MAP_TYPE_VIRTUAL:
3911 break;
3913 //FUNCTION_EXIT();
3916 static NTSTATUS
3917 XenPci_DOP_CalculateScatterGatherList(
3918 PDMA_ADAPTER DmaAdapter,
3919 PMDL Mdl,
3920 PVOID CurrentVa,
3921 ULONG Length,
3922 PULONG ScatterGatherListSize,
3923 PULONG NumberOfMapRegisters
3926 ULONG elements;
3927 PMDL curr_mdl;
3929 UNREFERENCED_PARAMETER(DmaAdapter);
3930 UNREFERENCED_PARAMETER(Mdl);
3932 FUNCTION_ENTER();
3934 KdPrint((__DRIVER_NAME " Mdl = %p\n", Mdl));
3935 KdPrint((__DRIVER_NAME " CurrentVa = %p\n", CurrentVa));
3936 KdPrint((__DRIVER_NAME " Length = %d\n", Length));
3937 if (Mdl)
3939 for (curr_mdl = Mdl, elements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
3940 elements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(CurrentVa, Length);
3942 else
3944 elements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, Length) + 1;
3947 *ScatterGatherListSize = FIELD_OFFSET(SCATTER_GATHER_LIST, Elements)
3948 + sizeof(SCATTER_GATHER_ELEMENT) * elements
3949 + sizeof(sg_extra_t);
3950 if (NumberOfMapRegisters)
3951 *NumberOfMapRegisters = 1;
3953 KdPrint((__DRIVER_NAME " ScatterGatherListSize = %d\n", *ScatterGatherListSize));
3955 FUNCTION_EXIT();
3956 return STATUS_SUCCESS;
3959 static NTSTATUS
3960 XenPci_DOP_BuildScatterGatherList(
3961 IN PDMA_ADAPTER DmaAdapter,
3962 IN PDEVICE_OBJECT DeviceObject,
3963 IN PMDL Mdl,
3964 IN PVOID CurrentVa,
3965 IN ULONG Length,
3966 IN PDRIVER_LIST_CONTROL ExecutionRoutine,
3967 IN PVOID Context,
3968 IN BOOLEAN WriteToDevice,
3969 IN PVOID ScatterGatherBuffer,
3970 IN ULONG ScatterGatherBufferLength)
3972 ULONG i;
3973 PSCATTER_GATHER_LIST sglist = ScatterGatherBuffer;
3974 PUCHAR ptr;
3975 ULONG remaining = Length;
3976 ULONG total_remaining;
3977 xen_dma_adapter_t *xen_dma_adapter;
3978 PXENPCI_DEVICE_DATA xpdd;
3979 sg_extra_t *sg_extra;
3980 PMDL curr_mdl;
3981 ULONG map_type;
3982 ULONG sg_element;
3983 ULONG offset;
3984 PFN_NUMBER pfn;
3985 grant_ref_t gref;
3987 UNREFERENCED_PARAMETER(WriteToDevice);
3989 //FUNCTION_ENTER();
3991 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
3992 xpdd = xen_dma_adapter->xppdd->bus_fdo->DeviceExtension;
3994 ASSERT(Mdl);
3995 if (xen_dma_adapter->dma_extension)
3997 if (xen_dma_adapter->dma_extension->need_virtual_address(DeviceObject->CurrentIrp))
3999 ASSERT(!Mdl->Next); /* can only virtual a single buffer */
4000 map_type = MAP_TYPE_VIRTUAL;
4001 sglist->NumberOfElements = 1;
4003 else
4005 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(DeviceObject->CurrentIrp);
4006 if (PtrToUlong(CurrentVa) & (alignment - 1))
4008 ASSERT(!Mdl->Next); /* can only remap a single buffer */
4009 map_type = MAP_TYPE_REMAPPED;
4010 sglist->NumberOfElements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(NULL, Length);
4012 else
4014 map_type = MAP_TYPE_MDL;
4015 for (curr_mdl = Mdl, sglist->NumberOfElements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
4016 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
4017 MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
4021 else
4023 map_type = MAP_TYPE_MDL;
4024 for (curr_mdl = Mdl, sglist->NumberOfElements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
4025 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
4026 MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
4028 if (ScatterGatherBufferLength < FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
4029 sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t))
4031 return STATUS_BUFFER_TOO_SMALL;
4034 sg_extra = (sg_extra_t *)((PUCHAR)sglist + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
4035 (sizeof(SCATTER_GATHER_ELEMENT)) * sglist->NumberOfElements);
4037 sg_extra->map_type = map_type;
4038 switch (map_type)
4040 case MAP_TYPE_MDL:
4041 KdPrint((__DRIVER_NAME " MAP_TYPE_MDL - %p\n", CurrentVa));
4042 total_remaining = Length;
4043 for (sg_element = 0, curr_mdl = Mdl; curr_mdl; curr_mdl = curr_mdl->Next)
4045 remaining = MmGetMdlByteCount(curr_mdl);
4046 if (!MmGetMdlByteOffset(Mdl) && (PtrToUlong(CurrentVa) & (PAGE_SIZE - 1)))
4047 offset = (PtrToUlong(CurrentVa) & (PAGE_SIZE - 1));
4048 else
4049 offset = MmGetMdlByteOffset(curr_mdl);
4050 for (i = 0; i < ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)); i++)
4052 //KdPrint((__DRIVER_NAME " element = %d\n", sg_element));
4053 //KdPrint((__DRIVER_NAME " remaining = %d\n", remaining));
4054 pfn = MmGetMdlPfnArray(curr_mdl)[i];
4055 ASSERT(pfn);
4056 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, pfn, FALSE, INVALID_GRANT_REF);
4057 ASSERT(gref != INVALID_GRANT_REF);
4058 sglist->Elements[sg_element].Address.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | offset;
4059 sglist->Elements[sg_element].Length = min(min(PAGE_SIZE - offset, remaining), total_remaining);
4060 total_remaining -= sglist->Elements[sg_element].Length;
4061 remaining -= sglist->Elements[sg_element].Length;
4062 offset = 0;
4063 sg_element++;
4066 break;
4067 case MAP_TYPE_REMAPPED:
4068 sg_extra->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, max(Length, PAGE_SIZE), XENPCI_POOL_TAG);
4069 ASSERT(sg_extra->aligned_buffer); /* lazy */
4070 KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED - %p -> %p\n", CurrentVa, sg_extra->aligned_buffer));
4071 sg_extra->unaligned_buffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
4072 ASSERT(sg_extra->unaligned_buffer); /* lazy */
4073 if (!MmGetMdlByteOffset(Mdl) && (PtrToUlong(CurrentVa) & (PAGE_SIZE - 1)))
4074 sg_extra->unaligned_buffer = (PUCHAR)sg_extra->unaligned_buffer + (PtrToUlong(CurrentVa) & (PAGE_SIZE - 1));
4075 sg_extra->copy_length = Length;
4076 if (WriteToDevice)
4077 memcpy(sg_extra->aligned_buffer, sg_extra->unaligned_buffer, sg_extra->copy_length);
4078 for (sg_element = 0, remaining = Length;
4079 sg_element < ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_extra->aligned_buffer, Length); sg_element++)
4081 pfn = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)sg_extra->aligned_buffer + (sg_element << PAGE_SHIFT)).QuadPart >> PAGE_SHIFT);
4082 ASSERT(pfn);
4083 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, pfn, FALSE, INVALID_GRANT_REF);
4084 ASSERT(gref);
4085 sglist->Elements[sg_element].Address.QuadPart = (ULONGLONG)gref << PAGE_SHIFT;
4086 sglist->Elements[sg_element].Length = min(PAGE_SIZE, remaining);
4087 remaining -= sglist->Elements[sg_element].Length;
4089 break;
4090 case MAP_TYPE_VIRTUAL:
4091 KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL\n"));
4092 ptr = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
4093 ASSERT(ptr); /* lazy */
4094 if (!MmGetMdlByteOffset(Mdl) && (PtrToUlong(CurrentVa) & (PAGE_SIZE - 1)))
4095 ptr += (PtrToUlong(CurrentVa) & (PAGE_SIZE - 1));
4096 sglist->Elements[0].Address.QuadPart = (ULONGLONG)ptr;
4097 sglist->Elements[0].Length = Length;
4098 break;
4100 #if 0
4101 KdPrint((__DRIVER_NAME " Mdl = %p, CurrentVa = %p, Mdl->Va = %p, Offset = %d, Length = %d\n",
4102 Mdl, CurrentVa, MmGetMdlVirtualAddress(Mdl), MmGetMdlByteOffset(Mdl), Length));
4103 for (i = 0; i < sglist->NumberOfElements; i++)
4105 KdPrint((__DRIVER_NAME " sge[%d]->Address = %08x%08x, Length = %d\n", i, sglist->Elements[i].Address.HighPart,
4106 sglist->Elements[i].Address.LowPart, sglist->Elements[i].Length));
4108 #endif
4109 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, ScatterGatherBuffer, Context);
4111 //FUNCTION_EXIT();
4113 return STATUS_SUCCESS;
4116 static NTSTATUS
4117 XenPci_DOP_BuildMdlFromScatterGatherList(
4118 PDMA_ADAPTER DmaAdapter,
4119 PSCATTER_GATHER_LIST ScatterGather,
4120 PMDL OriginalMdl,
4121 PMDL *TargetMdl)
4123 UNREFERENCED_PARAMETER(DmaAdapter);
4124 UNREFERENCED_PARAMETER(ScatterGather);
4125 UNREFERENCED_PARAMETER(OriginalMdl);
4126 UNREFERENCED_PARAMETER(TargetMdl);
4128 FUNCTION_ENTER();
4129 FUNCTION_EXIT();
4130 return STATUS_UNSUCCESSFUL;
4133 static PDMA_ADAPTER
4134 XenPci_BIS_GetDmaAdapter(PVOID context, PDEVICE_DESCRIPTION device_description, PULONG number_of_map_registers)
4136 xen_dma_adapter_t *xen_dma_adapter;
4137 PDEVICE_OBJECT curr, prev;
4138 PDRIVER_OBJECT fdo_driver_object;
4139 PVOID fdo_driver_extension;
4141 UNREFERENCED_PARAMETER(device_description);
4143 FUNCTION_ENTER();
4145 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
4146 KdPrint((__DRIVER_NAME " Device Description = %p:\n", device_description));
4147 KdPrint((__DRIVER_NAME " Version = %d\n", device_description->Version));
4148 KdPrint((__DRIVER_NAME " Master = %d\n", device_description->Master));
4149 KdPrint((__DRIVER_NAME " ScatterGather = %d\n", device_description->ScatterGather));
4150 KdPrint((__DRIVER_NAME " DemandMode = %d\n", device_description->DemandMode));
4151 KdPrint((__DRIVER_NAME " AutoInitialize = %d\n", device_description->AutoInitialize));
4152 KdPrint((__DRIVER_NAME " Dma32BitAddresses = %d\n", device_description->Dma32BitAddresses));
4153 KdPrint((__DRIVER_NAME " IgnoreCount = %d\n", device_description->IgnoreCount));
4154 KdPrint((__DRIVER_NAME " Dma64BitAddresses = %d\n", device_description->Dma64BitAddresses));
4155 KdPrint((__DRIVER_NAME " BusNumber = %d\n", device_description->BusNumber));
4156 KdPrint((__DRIVER_NAME " DmaChannel = %d\n", device_description->DmaChannel));
4157 KdPrint((__DRIVER_NAME " InterfaceType = %d\n", device_description->InterfaceType));
4158 KdPrint((__DRIVER_NAME " DmaWidth = %d\n", device_description->DmaWidth));
4159 KdPrint((__DRIVER_NAME " DmaSpeed = %d\n", device_description->DmaSpeed));
4160 KdPrint((__DRIVER_NAME " MaximumLength = %d\n", device_description->MaximumLength));
4161 KdPrint((__DRIVER_NAME " DmaPort = %d\n", device_description->DmaPort));
4163 /*
4164 we have to allocate PAGE_SIZE bytes here because Windows thinks this is
4165 actually an ADAPTER_OBJECT, and then the verifier crashes because
4166 Windows accessed beyond the end of the structure :(
4167 */
4168 xen_dma_adapter = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
4169 RtlZeroMemory(xen_dma_adapter, PAGE_SIZE);
4170 xen_dma_adapter->dma_adapter.Version = 2;
4171 xen_dma_adapter->dma_adapter.Size = sizeof(DMA_ADAPTER); //xen_dma_adapter_t);
4172 xen_dma_adapter->dma_adapter.DmaOperations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DMA_OPERATIONS), XENPCI_POOL_TAG);
4173 //xen_dma_adapter->dma_adapter.DmaOperations = &xen_dma_adapter->dma_operations;
4174 xen_dma_adapter->dma_adapter.DmaOperations->Size = sizeof(DMA_OPERATIONS);
4175 xen_dma_adapter->dma_adapter.DmaOperations->PutDmaAdapter = XenPci_DOP_PutDmaAdapter;
4176 xen_dma_adapter->dma_adapter.DmaOperations->AllocateCommonBuffer = XenPci_DOP_AllocateCommonBuffer;
4177 xen_dma_adapter->dma_adapter.DmaOperations->FreeCommonBuffer = XenPci_DOP_FreeCommonBuffer;
4178 xen_dma_adapter->dma_adapter.DmaOperations->AllocateAdapterChannel = XenPci_DOP_AllocateAdapterChannel;
4179 xen_dma_adapter->dma_adapter.DmaOperations->FlushAdapterBuffers = XenPci_DOP_FlushAdapterBuffers;
4180 xen_dma_adapter->dma_adapter.DmaOperations->FreeAdapterChannel = XenPci_DOP_FreeAdapterChannel;
4181 xen_dma_adapter->dma_adapter.DmaOperations->FreeMapRegisters = XenPci_DOP_FreeMapRegisters;
4182 xen_dma_adapter->dma_adapter.DmaOperations->MapTransfer = XenPci_DOP_MapTransfer;
4183 xen_dma_adapter->dma_adapter.DmaOperations->GetDmaAlignment = XenPci_DOP_GetDmaAlignment;
4184 xen_dma_adapter->dma_adapter.DmaOperations->ReadDmaCounter = XenPci_DOP_ReadDmaCounter;
4185 xen_dma_adapter->dma_adapter.DmaOperations->GetScatterGatherList = XenPci_DOP_GetScatterGatherList;
4186 xen_dma_adapter->dma_adapter.DmaOperations->PutScatterGatherList = XenPci_DOP_PutScatterGatherList;
4187 xen_dma_adapter->dma_adapter.DmaOperations->CalculateScatterGatherList = XenPci_DOP_CalculateScatterGatherList;
4188 xen_dma_adapter->dma_adapter.DmaOperations->BuildScatterGatherList = XenPci_DOP_BuildScatterGatherList;
4189 xen_dma_adapter->dma_adapter.DmaOperations->BuildMdlFromScatterGatherList = XenPci_DOP_BuildMdlFromScatterGatherList;
4190 xen_dma_adapter->xppdd = context;
4191 xen_dma_adapter->dma_extension = NULL;
4193 KdPrint((__DRIVER_NAME " About to call IoGetAttachedDeviceReference\n"));
4194 curr = IoGetAttachedDeviceReference(xen_dma_adapter->xppdd->common.pdo);
4195 KdPrint((__DRIVER_NAME " Before start of loop - curr = %p\n", curr));
4196 while (curr != NULL)
4198 fdo_driver_object = curr->DriverObject;
4199 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
4200 if (fdo_driver_object)
4202 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC));
4203 if (fdo_driver_extension)
4205 xen_dma_adapter->dma_extension = (dma_driver_extension_t *)fdo_driver_extension;
4206 ObDereferenceObject(curr);
4207 break;
4210 prev = curr;
4211 curr = IoGetLowerDeviceObject(curr);
4212 ObDereferenceObject(prev);
4214 KdPrint((__DRIVER_NAME " End of loop\n"));
4216 *number_of_map_registers = 1024; //1024; /* why not... */
4218 FUNCTION_EXIT();
4220 return &xen_dma_adapter->dma_adapter;
4223 static ULONG
4224 XenPci_BIS_SetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
4226 UNREFERENCED_PARAMETER(context);
4227 UNREFERENCED_PARAMETER(data_type);
4228 UNREFERENCED_PARAMETER(buffer);
4229 UNREFERENCED_PARAMETER(offset);
4230 UNREFERENCED_PARAMETER(length);
4232 FUNCTION_ENTER();
4233 FUNCTION_EXIT();
4234 return 0;
4237 static ULONG
4238 XenPci_BIS_GetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
4240 UNREFERENCED_PARAMETER(context);
4241 UNREFERENCED_PARAMETER(data_type);
4242 UNREFERENCED_PARAMETER(buffer);
4243 UNREFERENCED_PARAMETER(offset);
4244 UNREFERENCED_PARAMETER(length);
4246 FUNCTION_ENTER();
4247 FUNCTION_EXIT();
4248 return 0;
4251 static NTSTATUS
4252 XenPci_QueryInterface(PDEVICE_OBJECT device_object, PIRP irp)
4254 NTSTATUS status;
4255 PIO_STACK_LOCATION stack;
4256 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
4257 PBUS_INTERFACE_STANDARD bis;
4258 PGUID guid;
4260 FUNCTION_ENTER();
4262 stack = IoGetCurrentIrpStackLocation(irp);
4264 if (memcmp(stack->Parameters.QueryInterface.InterfaceType, &GUID_BUS_INTERFACE_STANDARD, sizeof(GUID_BUS_INTERFACE_STANDARD)) == 0)
4266 KdPrint((__DRIVER_NAME " GUID_BUS_INTERFACE_STANDARD\n"));
4267 if (stack->Parameters.QueryInterface.Size < sizeof(BUS_INTERFACE_STANDARD))
4269 KdPrint((__DRIVER_NAME " buffer too small\n"));
4270 status = STATUS_INVALID_PARAMETER;
4271 FUNCTION_EXIT();
4272 return status;
4274 if (stack->Parameters.QueryInterface.Version != 1)
4276 KdPrint((__DRIVER_NAME " incorrect version %d\n", stack->Parameters.QueryInterface.Version));
4277 status = STATUS_INVALID_PARAMETER;
4278 FUNCTION_EXIT();
4279 return status;
4281 bis = (PBUS_INTERFACE_STANDARD)stack->Parameters.QueryInterface.Interface;
4282 bis->Size = sizeof(BUS_INTERFACE_STANDARD);
4283 bis->Version = 1; //BUS_INTERFACE_STANDARD_VERSION;
4284 bis->Context = xppdd;
4285 bis->InterfaceReference = XenPci_IS_InterfaceReference;
4286 bis->InterfaceDereference = XenPci_IS_InterfaceReference;
4287 bis->TranslateBusAddress = XenPci_BIS_TranslateBusAddress;
4288 bis->GetDmaAdapter = XenPci_BIS_GetDmaAdapter;
4289 bis->SetBusData = XenPci_BIS_SetBusData;
4290 bis->GetBusData = XenPci_BIS_GetBusData;
4291 status = STATUS_SUCCESS;
4292 FUNCTION_EXIT();
4293 return status;
4295 else
4297 guid = (PGUID)stack->Parameters.QueryInterface.InterfaceType;
4298 KdPrint((__DRIVER_NAME " Unknown GUID %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",
4299 guid->Data1, (ULONG)guid->Data2, (ULONG)guid->Data3, (ULONG)guid->Data4[0], (ULONG)guid->Data4[1],
4300 (ULONG)guid->Data4[2], (ULONG)guid->Data4[3], (ULONG)guid->Data4[4], (ULONG)guid->Data4[5],
4301 (ULONG)guid->Data4[6], (ULONG)guid->Data4[7]));
4302 status = irp->IoStatus.Status;
4303 FUNCTION_EXIT();
4304 return status;
4308 NTSTATUS
4309 XenPci_Pnp_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4311 NTSTATUS status;
4312 PIO_STACK_LOCATION stack;
4313 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
4314 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
4315 LPWSTR buffer;
4316 WCHAR widebuf[256];
4317 unsigned int i;
4318 PPNP_BUS_INFORMATION pbi;
4319 ULONG *usage_type;
4321 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
4323 stack = IoGetCurrentIrpStackLocation(irp);
4325 switch (stack->MinorFunction)
4327 case IRP_MN_START_DEVICE:
4328 KdPrint((__DRIVER_NAME " IRP_MN_START_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4329 status = XenPci_Pnp_StartDevice(device_object, irp);
4330 break;
4332 case IRP_MN_QUERY_STOP_DEVICE:
4333 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_STOP_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4334 SET_PNP_STATE(&xppdd->common, StopPending);
4335 status = STATUS_SUCCESS;
4336 break;
4338 case IRP_MN_STOP_DEVICE:
4339 KdPrint((__DRIVER_NAME " IRP_MN_STOP_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4340 SET_PNP_STATE(&xppdd->common, Stopped);
4341 status = STATUS_SUCCESS;
4342 break;
4344 case IRP_MN_CANCEL_STOP_DEVICE:
4345 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_STOP_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4346 REVERT_PNP_STATE(&xppdd->common);
4347 status = STATUS_SUCCESS;
4348 break;
4350 case IRP_MN_QUERY_REMOVE_DEVICE:
4351 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_REMOVE_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4352 SET_PNP_STATE(&xppdd->common, RemovePending);
4353 status = STATUS_SUCCESS;
4354 break;
4356 case IRP_MN_REMOVE_DEVICE:
4357 KdPrint((__DRIVER_NAME " IRP_MN_REMOVE_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4358 status = XenPci_Pnp_RemoveDevice(device_object, irp);
4359 break;
4361 case IRP_MN_CANCEL_REMOVE_DEVICE:
4362 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_REMOVE_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4363 REVERT_PNP_STATE(&xppdd->common);
4364 status = STATUS_SUCCESS;
4365 break;
4367 case IRP_MN_SURPRISE_REMOVAL:
4368 KdPrint((__DRIVER_NAME " IRP_MN_SURPRISE_REMOVAL (status = %08x)\n", irp->IoStatus.Status));
4369 SET_PNP_STATE(&xppdd->common, SurpriseRemovePending);
4370 status = STATUS_SUCCESS;
4371 break;
4373 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
4374 KdPrint((__DRIVER_NAME " IRP_MN_DEVICE_USAGE_NOTIFICATION (status = %08x)\n", irp->IoStatus.Status));
4376 usage_type = NULL;
4377 switch (stack->Parameters.UsageNotification.Type)
4379 case DeviceUsageTypePaging:
4380 KdPrint((__DRIVER_NAME " type = DeviceUsageTypePaging\n"));
4381 usage_type = &xppdd->common.device_usage_paging;
4382 break;
4383 case DeviceUsageTypeDumpFile:
4384 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeDumpFile\n"));
4385 usage_type = &xppdd->common.device_usage_dump;
4386 break;
4387 case DeviceUsageTypeHibernation:
4388 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeHibernation\n"));
4389 usage_type = &xppdd->common.device_usage_hibernation;
4390 break;
4391 default:
4392 KdPrint((__DRIVER_NAME " Unknown usage type %x\n",
4393 stack->Parameters.UsageNotification.Type));
4394 break;
4396 KdPrint((__DRIVER_NAME " inpath = %d\n", stack->Parameters.UsageNotification.InPath));
4397 if (usage_type)
4399 if (stack->Parameters.UsageNotification.InPath)
4400 (*usage_type)++;
4401 else
4402 (*usage_type)--;
4404 status = STATUS_SUCCESS;
4405 break;
4407 case IRP_MN_QUERY_ID:
4408 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_ID (status = %08x)\n", irp->IoStatus.Status));
4409 switch (stack->Parameters.QueryId.IdType)
4411 case BusQueryDeviceID: /* REG_SZ */
4412 KdPrint((__DRIVER_NAME " BusQueryDeviceID\n"));
4413 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
4414 for (i = 0; i < strlen(xppdd->device); i++)
4415 widebuf[i] = xppdd->device[i];
4416 widebuf[i] = 0;
4417 RtlStringCbPrintfW(buffer, 512, L"Xen\\%ws", widebuf);
4418 KdPrint((__DRIVER_NAME " %ls\n", buffer));
4419 irp->IoStatus.Information = (ULONG_PTR)buffer;
4420 status = STATUS_SUCCESS;
4421 break;
4422 case BusQueryHardwareIDs: /* REG_MULTI_SZ */
4423 KdPrint((__DRIVER_NAME " BusQueryHardwareIDs\n"));
4424 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
4425 for (i = 0; i < strlen(xppdd->device); i++)
4426 widebuf[i] = xppdd->device[i];
4427 widebuf[i] = 0;
4428 RtlStringCbPrintfW(buffer, 512, L"Xen\\%ws", widebuf);
4429 for (i = 0; buffer[i] != 0; i++);
4430 buffer[i + 1] = 0;
4431 // for (i = 0; i < 256; i++)
4432 // KdPrint((__DRIVER_NAME " %04X: %04X %wc\n", i, buffer[i], buffer[i]));
4433 KdPrint((__DRIVER_NAME " %ls\n", buffer));
4434 irp->IoStatus.Information = (ULONG_PTR)buffer;
4435 status = STATUS_SUCCESS;
4436 break;
4437 case BusQueryCompatibleIDs: /* REG_MULTI_SZ */
4438 KdPrint((__DRIVER_NAME " BusQueryCompatibleIDs\n"));
4439 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
4440 for (i = 0; i < strlen(xppdd->device); i++)
4441 widebuf[i] = xppdd->device[i];
4442 widebuf[i] = 0;
4443 RtlStringCbPrintfW(buffer, 512, L"Xen\\%ws", widebuf);
4444 for (i = 0; buffer[i] != 0; i++);
4445 buffer[i + 1] = 0;
4446 KdPrint((__DRIVER_NAME " %ls\n", buffer));
4447 irp->IoStatus.Information = (ULONG_PTR)buffer;
4448 status = STATUS_SUCCESS;
4449 break;
4450 case BusQueryInstanceID: /* REG_SZ */
4451 KdPrint((__DRIVER_NAME " BusQueryInstanceID\n"));
4452 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
4453 RtlStringCbPrintfW(buffer, 512, L"%02d", xppdd->index);
4454 KdPrint((__DRIVER_NAME " %ls\n", buffer));
4455 irp->IoStatus.Information = (ULONG_PTR)buffer;
4456 status = STATUS_SUCCESS;
4457 break;
4458 default:
4459 KdPrint((__DRIVER_NAME " Unhandled IdType = %d\n", stack->Parameters.QueryId.IdType));
4460 irp->IoStatus.Information = 0;
4461 status = STATUS_NOT_SUPPORTED;
4462 break;
4464 break;
4466 case IRP_MN_QUERY_DEVICE_TEXT:
4467 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_TEXT (status = %08x)\n", irp->IoStatus.Status));
4468 switch (stack->Parameters.QueryDeviceText.DeviceTextType)
4470 case DeviceTextDescription:
4471 KdPrint((__DRIVER_NAME " DeviceTextDescription\n"));
4472 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
4473 for (i = 0; i < strlen(xppdd->device); i++)
4474 widebuf[i] = xppdd->device[i];
4475 widebuf[i] = 0;
4476 RtlStringCbPrintfW(buffer, 512, L"Xen %ws device #%d", widebuf, xppdd->index);
4477 KdPrint((__DRIVER_NAME " %ls\n", buffer));
4478 irp->IoStatus.Information = (ULONG_PTR)buffer;
4479 status = STATUS_SUCCESS;
4480 break;
4481 case DeviceTextLocationInformation:
4482 KdPrint((__DRIVER_NAME " DeviceTextLocationInformation\n"));
4483 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
4484 RtlStringCbPrintfW(buffer, 512, L"Xen Bus");
4485 KdPrint((__DRIVER_NAME " %ls\n", buffer));
4486 irp->IoStatus.Information = (ULONG_PTR)buffer;
4487 status = STATUS_SUCCESS;
4488 break;
4489 default:
4490 KdPrint((__DRIVER_NAME " Unhandled IdType = %d\n", stack->Parameters.QueryDeviceText.DeviceTextType));
4491 irp->IoStatus.Information = 0;
4492 status = STATUS_NOT_SUPPORTED;
4493 break;
4495 break;
4497 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
4498 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_RESOURCE_REQUIREMENTS (status = %08x)\n", irp->IoStatus.Status));
4499 status = XenPci_QueryResourceRequirements(device_object, irp);
4500 break;
4502 case IRP_MN_QUERY_CAPABILITIES:
4503 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_CAPABILITIES (status = %08x)\n", irp->IoStatus.Status));
4504 status = XenPci_Pnp_QueryCapabilities(device_object, irp);
4505 break;
4507 case IRP_MN_QUERY_BUS_INFORMATION:
4508 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_BUS_INFORMATION (status = %08x)\n", irp->IoStatus.Status));
4509 pbi = (PPNP_BUS_INFORMATION)ExAllocatePoolWithTag(PagedPool, sizeof(PNP_BUS_INFORMATION), XENPCI_POOL_TAG);
4510 pbi->BusTypeGuid = GUID_BUS_TYPE_XEN;
4511 pbi->LegacyBusType = PNPBus; //Internal;
4512 pbi->BusNumber = 0;
4513 irp->IoStatus.Information = (ULONG_PTR)pbi;
4514 status = STATUS_SUCCESS;
4515 break;
4517 case IRP_MN_QUERY_INTERFACE:
4518 status = XenPci_QueryInterface(device_object, irp);
4519 break;
4521 case IRP_MN_QUERY_RESOURCES:
4522 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_RESOURCES (status = %08x)\n", irp->IoStatus.Status));
4523 status = irp->IoStatus.Status;
4524 #if 0
4525 crl = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(PagedPool, sizeof(CM_RESOURCE_LIST) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 2, XENPCI_POOL_TAG);
4526 crl->Count = 1;
4527 crl->List[0].InterfaceType = PNPBus;
4528 crl->List[0].BusNumber = 0;
4529 crl->List[0].PartialResourceList.Version = 1;
4530 crl->List[0].PartialResourceList.Revision = 1;
4531 crl->List[0].PartialResourceList.Count = 0;
4533 prd = &crl->List[0].PartialResourceList.PartialDescriptors[crl->List[0].PartialResourceList.Count++];
4534 prd->Type = CmResourceTypeInterrupt;
4535 prd->ShareDisposition = CmResourceShareShared;
4536 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
4537 prd->u.Interrupt.Level = xpdd->irq_number;
4538 prd->u.Interrupt.Vector = xpdd->irq_number;
4539 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
4541 prd = &crl->List[0].PartialResourceList.PartialDescriptors[crl->List[0].PartialResourceList.Count++];
4542 prd->Type = CmResourceTypeMemory;
4543 prd->ShareDisposition = CmResourceShareShared;
4544 prd->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
4545 prd->u.Memory.Start = xpdd->platform_mmio_addr;
4546 prd->u.Memory.Length = 0;
4548 irp->IoStatus.Information = (ULONG_PTR)crl;
4549 status = STATUS_SUCCESS;
4550 #endif
4551 break;
4553 case IRP_MN_QUERY_PNP_DEVICE_STATE:
4554 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_PNP_DEVICE_STATE (status = %08x)\n", irp->IoStatus.Status));
4555 irp->IoStatus.Information = 0;
4556 status = STATUS_SUCCESS;
4557 break;
4559 case IRP_MN_QUERY_DEVICE_RELATIONS:
4560 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_RELATIONS (status = %08x)\n", irp->IoStatus.Status));
4561 switch (stack->Parameters.QueryDeviceRelations.Type)
4563 case TargetDeviceRelation:
4564 KdPrint((__DRIVER_NAME " BusRelations\n"));
4565 status = XenPci_Pnp_QueryTargetRelations(device_object, irp);
4566 break;
4567 default:
4568 status = irp->IoStatus.Status;
4569 break;
4571 break;
4573 case IRP_MN_EJECT:
4574 KdPrint((__DRIVER_NAME " IRP_MN_EJECT\n"));
4575 status = STATUS_SUCCESS;
4576 break;
4578 default:
4579 //KdPrint((__DRIVER_NAME " Unhandled Minor = %d, Status = %08x\n", stack->MinorFunction, irp->IoStatus.Status));
4580 status = irp->IoStatus.Status;
4581 break;
4584 irp->IoStatus.Status = status;
4585 IoCompleteRequest(irp, IO_NO_INCREMENT);
4587 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
4589 return status;
4592 NTSTATUS
4593 XenPci_Irp_Create_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4595 NTSTATUS status;
4597 UNREFERENCED_PARAMETER(device_object);
4599 FUNCTION_ENTER();
4601 status = irp->IoStatus.Status;
4602 IoCompleteRequest(irp, IO_NO_INCREMENT);
4604 FUNCTION_EXIT();
4606 return status;
4609 NTSTATUS
4610 XenPci_Irp_Close_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4612 NTSTATUS status;
4614 UNREFERENCED_PARAMETER(device_object);
4616 FUNCTION_ENTER();
4618 status = irp->IoStatus.Status;
4619 IoCompleteRequest(irp, IO_NO_INCREMENT);
4621 FUNCTION_EXIT();
4623 return status;
4626 NTSTATUS
4627 XenPci_Irp_Read_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4629 NTSTATUS status;
4631 UNREFERENCED_PARAMETER(device_object);
4633 FUNCTION_ENTER();
4635 status = irp->IoStatus.Status;
4636 IoCompleteRequest(irp, IO_NO_INCREMENT);
4638 FUNCTION_EXIT();
4640 return status;
4643 NTSTATUS
4644 XenPci_Irp_Write_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4646 NTSTATUS status;
4648 UNREFERENCED_PARAMETER(device_object);
4650 FUNCTION_ENTER();
4652 status = irp->IoStatus.Status;
4653 IoCompleteRequest(irp, IO_NO_INCREMENT);
4655 FUNCTION_EXIT();
4657 return status;
4660 NTSTATUS
4661 XenPci_Irp_Cleanup_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4663 NTSTATUS status;
4665 UNREFERENCED_PARAMETER(device_object);
4667 FUNCTION_ENTER();
4669 status = irp->IoStatus.Status;
4670 IoCompleteRequest(irp, IO_NO_INCREMENT);
4672 FUNCTION_EXIT();
4674 return status;
4677 DDKAPI NTSTATUS
4678 XenPci_SystemControl_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4680 NTSTATUS status;
4682 UNREFERENCED_PARAMETER(device_object);
4684 FUNCTION_ENTER();
4686 status = irp->IoStatus.Status;
4687 IoCompleteRequest(irp, IO_NO_INCREMENT);
4689 FUNCTION_EXIT();
4691 return status;
4693 #endif