win-pvdrivers

view xenpci/xenpci_pdo.c @ 537:2a74ac2f43bb

more big updates
dma now working under xp
author James Harper <james.harper@bendigoit.com.au>
date Wed Feb 18 22:18:23 2009 +1100 (2009-02-18)
parents 1d39de3ab8d6
children e75bb8d68370
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->dma_adapter.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);
113 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(buffer).QuadPart >> PAGE_SHIFT);
114 ASSERT(pfn);
115 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
116 ASSERT(gref);
117 LogicalAddress->QuadPart = (gref << PAGE_SHIFT) | (PtrToUlong(buffer) & (PAGE_SIZE - 1));
119 //FUNCTION_EXIT();
120 return buffer;
121 }
123 static VOID
124 XenPci_DOP_FreeCommonBuffer(
125 PDMA_ADAPTER dma_adapter,
126 ULONG length,
127 PHYSICAL_ADDRESS logical_address,
128 PVOID virtual_address,
129 BOOLEAN cache_enabled
130 )
131 {
132 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
133 PXENPCI_DEVICE_DATA xpdd;
134 grant_ref_t gref;
136 UNREFERENCED_PARAMETER(dma_adapter);
137 UNREFERENCED_PARAMETER(length);
138 UNREFERENCED_PARAMETER(cache_enabled);
140 // FUNCTION_ENTER();
142 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
143 gref = (grant_ref_t)(logical_address.QuadPart >> PAGE_SHIFT);
144 GntTbl_EndAccess(xpdd, gref, FALSE);
145 ExFreePoolWithTag(virtual_address, XENPCI_POOL_TAG);
147 // FUNCTION_EXIT();
148 }
150 static NTSTATUS
151 XenPci_DOP_AllocateAdapterChannel(
152 IN PDMA_ADAPTER dma_adapter,
153 IN PDEVICE_OBJECT device_object,
154 IN ULONG NumberOfMapRegisters,
155 IN PDRIVER_CONTROL ExecutionRoutine,
156 IN PVOID Context
157 )
158 {
159 //xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
160 //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
161 IO_ALLOCATION_ACTION action;
162 map_register_base_t *map_register_base;
164 UNREFERENCED_PARAMETER(dma_adapter);
166 //FUNCTION_ENTER();
168 map_register_base = ExAllocatePoolWithTag(NonPagedPool,
169 FIELD_OFFSET(map_register_base_t, regs) + NumberOfMapRegisters * sizeof(map_register_t), XENPCI_POOL_TAG);
170 if (!map_register_base)
171 {
172 KdPrint((__DRIVER_NAME " Cannot allocate memory for map_register_base\n"));
173 FUNCTION_EXIT();
174 return STATUS_INSUFFICIENT_RESOURCES;
175 }
176 /* 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 */
177 map_register_base->device_object = device_object;
178 map_register_base->total_map_registers = NumberOfMapRegisters;
179 map_register_base->count = 0;
181 action = ExecutionRoutine(device_object, device_object->CurrentIrp, map_register_base, Context);
183 switch (action)
184 {
185 case KeepObject:
186 KdPrint((__DRIVER_NAME " KeepObject\n"));
187 ASSERT(FALSE);
188 break;
189 case DeallocateObject:
190 KdPrint((__DRIVER_NAME " DeallocateObject\n"));
191 ASSERT(FALSE);
192 break;
193 case DeallocateObjectKeepRegisters:
194 //KdPrint((__DRIVER_NAME " DeallocateObjectKeepRegisters\n"));
195 break;
196 default:
197 KdPrint((__DRIVER_NAME " Unknown action %d\n", action));
198 ASSERT(FALSE);
199 break;
200 }
201 //FUNCTION_EXIT();
202 return STATUS_SUCCESS;
203 }
205 static BOOLEAN
206 XenPci_DOP_FlushAdapterBuffers(
207 PDMA_ADAPTER dma_adapter,
208 PMDL mdl,
209 PVOID MapRegisterBase,
210 PVOID CurrentVa,
211 ULONG Length,
212 BOOLEAN write_to_device)
213 {
214 //xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
215 //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
216 map_register_base_t *map_register_base = MapRegisterBase;
217 map_register_t *map_register;
218 ULONG i;
220 UNREFERENCED_PARAMETER(dma_adapter);
221 UNREFERENCED_PARAMETER(mdl);
222 UNREFERENCED_PARAMETER(CurrentVa);
223 UNREFERENCED_PARAMETER(Length);
225 //FUNCTION_ENTER();
227 for (i = 0; i < map_register_base->count; i++)
228 {
229 map_register = &map_register_base->regs[i];
230 if (map_register->map_type == MAP_TYPE_REMAPPED && !write_to_device)
231 memcpy(map_register->unaligned_buffer, map_register->aligned_buffer, map_register->copy_length);
232 }
233 //FUNCTION_EXIT();
235 return TRUE;
236 }
238 static VOID
239 XenPci_DOP_FreeAdapterChannel(
240 IN PDMA_ADAPTER DmaAdapter
241 )
242 {
243 UNREFERENCED_PARAMETER(DmaAdapter);
245 FUNCTION_ENTER();
246 FUNCTION_EXIT();
247 }
249 static VOID
250 XenPci_DOP_FreeMapRegisters(
251 PDMA_ADAPTER dma_adapter,
252 PVOID MapRegisterBase,
253 ULONG NumberOfMapRegisters)
254 {
255 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
256 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
257 map_register_base_t *map_register_base = MapRegisterBase;
258 map_register_t *map_register;
259 ULONG i;
260 grant_ref_t gref;
262 //FUNCTION_ENTER();
263 ASSERT(map_register_base->total_map_registers == NumberOfMapRegisters);
265 for (i = 0; i < map_register_base->count; i++)
266 {
267 map_register = &map_register_base->regs[i];
268 switch (map_register->map_type)
269 {
270 case MAP_TYPE_REMAPPED:
271 gref = (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT);
272 GntTbl_EndAccess(xpdd, gref, FALSE);
273 ExFreePoolWithTag(map_register->aligned_buffer, XENPCI_POOL_TAG);
274 break;
275 case MAP_TYPE_MDL:
276 gref = (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT);
277 GntTbl_EndAccess(xpdd, gref, FALSE);
278 break;
279 case MAP_TYPE_VIRTUAL:
280 break;
281 }
282 }
283 ExFreePoolWithTag(map_register_base, XENPCI_POOL_TAG);
285 //FUNCTION_EXIT();
286 }
288 static PHYSICAL_ADDRESS
289 XenPci_DOP_MapTransfer(
290 PDMA_ADAPTER dma_adapter,
291 PMDL mdl,
292 PVOID MapRegisterBase,
293 PVOID CurrentVa,
294 PULONG Length,
295 BOOLEAN WriteToDevice)
296 {
297 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
298 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
299 map_register_base_t *map_register_base = MapRegisterBase;
300 map_register_t *map_register = &map_register_base->regs[map_register_base->count];
301 PDEVICE_OBJECT device_object = map_register_base->device_object;
302 ULONG page_offset;
303 PFN_NUMBER pfn;
304 grant_ref_t gref;
305 PUCHAR ptr;
306 ULONG mdl_offset;
307 ULONG pfn_index;
309 //FUNCTION_ENTER();
311 //KdPrint((__DRIVER_NAME " Mdl = %p, MapRegisterBase = %p, MdlVa = %p, CurrentVa = %p, Length = %d\n",
312 // mdl, MapRegisterBase, MmGetMdlVirtualAddress(mdl), CurrentVa, *Length));
314 ASSERT(mdl);
315 ASSERT(map_register_base->count < map_register_base->total_map_registers);
317 if (xen_dma_adapter->dma_extension)
318 {
319 if (xen_dma_adapter->dma_extension->need_virtual_address(device_object->CurrentIrp))
320 {
321 map_register->map_type = MAP_TYPE_VIRTUAL;
322 }
323 else
324 {
325 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(device_object->CurrentIrp);
326 if ((MmGetMdlByteOffset(mdl) & (alignment - 1)) || (MmGetMdlByteCount(mdl) & (alignment - 1)))
327 {
328 map_register->map_type = MAP_TYPE_REMAPPED;
329 }
330 else
331 {
332 map_register->map_type = MAP_TYPE_MDL;
333 }
334 }
335 }
336 else
337 {
338 map_register->map_type = MAP_TYPE_MDL;
339 }
341 switch (map_register->map_type)
342 {
343 case MAP_TYPE_MDL:
344 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL\n"));
345 mdl_offset = (ULONG)((ULONGLONG)CurrentVa - (ULONGLONG)MmGetMdlVirtualAddress(mdl));
346 page_offset = PtrToUlong(CurrentVa) & (PAGE_SIZE - 1);
347 *Length = min(*Length, PAGE_SIZE - page_offset);
348 pfn_index = (ULONG)(((ULONGLONG)CurrentVa >> PAGE_SHIFT) - ((ULONGLONG)MmGetMdlVirtualAddress(mdl) >> PAGE_SHIFT));
349 //KdPrint((__DRIVER_NAME " mdl_offset = %d, page_offset = %d, length = %d, pfn_index = %d\n",
350 // mdl_offset, page_offset, *Length, pfn_index));
351 pfn = MmGetMdlPfnArray(mdl)[pfn_index];
352 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
353 map_register->logical.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | page_offset;
354 map_register_base->count++;
355 break;
356 case MAP_TYPE_REMAPPED:
357 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED\n"));
358 *Length = min(*Length, PAGE_SIZE);
359 map_register->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
360 ASSERT(map_register->aligned_buffer);
361 map_register->unaligned_buffer = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
362 ASSERT(map_register->unaligned_buffer); /* lazy */
363 map_register->copy_length = *Length;
364 if (WriteToDevice)
365 memcpy(map_register->aligned_buffer, map_register->unaligned_buffer, map_register->copy_length);
366 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(map_register->aligned_buffer).QuadPart >> PAGE_SHIFT);
367 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
368 map_register->logical.QuadPart = (LONGLONG)(gref << PAGE_SHIFT);
369 map_register_base->count++;
370 break;
371 case MAP_TYPE_VIRTUAL:
372 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL\n"));
373 ptr = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
374 ASSERT(ptr); /* lazy */
375 map_register->logical.QuadPart = (ULONGLONG)ptr;
376 map_register_base->count++;
377 break;
378 default:
379 ASSERT(FALSE);
380 break;
381 }
383 //FUNCTION_EXIT();
384 return map_register->logical;
385 }
387 static ULONG
388 XenPci_DOP_GetDmaAlignment(
389 PDMA_ADAPTER DmaAdapter)
390 {
391 UNREFERENCED_PARAMETER(DmaAdapter);
393 FUNCTION_ENTER();
394 FUNCTION_EXIT();
395 return 0;
396 }
398 static ULONG
399 XenPci_DOP_ReadDmaCounter(
400 PDMA_ADAPTER DmaAdapter)
401 {
402 UNREFERENCED_PARAMETER(DmaAdapter);
404 FUNCTION_ENTER();
405 FUNCTION_EXIT();
406 return 0;
407 }
409 static NTSTATUS
410 XenPci_DOP_GetScatterGatherList(
411 PDMA_ADAPTER DmaAdapter,
412 PDEVICE_OBJECT DeviceObject,
413 PMDL Mdl,
414 PVOID CurrentVa,
415 ULONG Length,
416 PDRIVER_LIST_CONTROL ExecutionRoutine,
417 PVOID Context,
418 BOOLEAN WriteToDevice)
419 {
420 UNREFERENCED_PARAMETER(DmaAdapter);
421 UNREFERENCED_PARAMETER(DeviceObject);
422 UNREFERENCED_PARAMETER(Mdl);
423 UNREFERENCED_PARAMETER(CurrentVa);
424 UNREFERENCED_PARAMETER(Length);
425 UNREFERENCED_PARAMETER(ExecutionRoutine);
426 UNREFERENCED_PARAMETER(Context);
427 UNREFERENCED_PARAMETER(WriteToDevice);
429 FUNCTION_ENTER();
430 FUNCTION_EXIT();
431 return STATUS_SUCCESS;
432 }
434 static VOID
435 XenPci_DOP_PutScatterGatherList(
436 IN PDMA_ADAPTER DmaAdapter,
437 IN PSCATTER_GATHER_LIST ScatterGather,
438 IN BOOLEAN WriteToDevice
439 )
440 {
441 xen_dma_adapter_t *xen_dma_adapter;
442 PXENPCI_DEVICE_DATA xpdd;
443 ULONG i;
444 sg_extra_t *sg_extra;
446 UNREFERENCED_PARAMETER(WriteToDevice);
448 //FUNCTION_ENTER();
450 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
451 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
453 sg_extra = (sg_extra_t *)((PUCHAR)ScatterGather + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
454 (sizeof(SCATTER_GATHER_ELEMENT)) * ScatterGather->NumberOfElements);
456 switch (sg_extra->map_type)
457 {
458 case MAP_TYPE_REMAPPED:
459 for (i = 0; i < ScatterGather->NumberOfElements; i++)
460 {
461 grant_ref_t gref;
462 gref = (grant_ref_t)(ScatterGather->Elements[i].Address.QuadPart >> PAGE_SHIFT);
463 GntTbl_EndAccess(xpdd, gref, FALSE);
464 ScatterGather->Elements[i].Address.QuadPart = -1;
465 }
466 if (!WriteToDevice)
467 memcpy(sg_extra->unaligned_buffer, sg_extra->aligned_buffer, sg_extra->copy_length);
468 ExFreePoolWithTag(sg_extra->aligned_buffer, XENPCI_POOL_TAG);
469 break;
470 case MAP_TYPE_MDL:
471 for (i = 0; i < ScatterGather->NumberOfElements; i++)
472 {
473 grant_ref_t gref;
474 gref = (grant_ref_t)(ScatterGather->Elements[i].Address.QuadPart >> PAGE_SHIFT);
475 GntTbl_EndAccess(xpdd, gref, FALSE);
476 ScatterGather->Elements[i].Address.QuadPart = -1;
477 }
478 break;
479 case MAP_TYPE_VIRTUAL:
480 break;
481 }
482 //FUNCTION_EXIT();
483 }
485 static NTSTATUS
486 XenPci_DOP_CalculateScatterGatherList(
487 PDMA_ADAPTER DmaAdapter,
488 PMDL Mdl,
489 PVOID CurrentVa,
490 ULONG Length,
491 PULONG ScatterGatherListSize,
492 PULONG NumberOfMapRegisters
493 )
494 {
495 ULONG elements;
496 PMDL curr_mdl;
498 UNREFERENCED_PARAMETER(DmaAdapter);
499 UNREFERENCED_PARAMETER(Mdl);
501 FUNCTION_ENTER();
503 KdPrint((__DRIVER_NAME " Mdl = %p\n", Mdl));
504 KdPrint((__DRIVER_NAME " CurrentVa = %p\n", CurrentVa));
505 KdPrint((__DRIVER_NAME " Length = %d\n", Length));
506 if (Mdl)
507 {
508 for (curr_mdl = Mdl, elements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
509 elements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(CurrentVa, Length);
510 }
511 else
512 {
513 elements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, Length) + 1;
514 }
516 *ScatterGatherListSize = FIELD_OFFSET(SCATTER_GATHER_LIST, Elements)
517 + sizeof(SCATTER_GATHER_ELEMENT) * elements
518 + sizeof(sg_extra_t);
519 if (NumberOfMapRegisters)
520 *NumberOfMapRegisters = 1;
522 KdPrint((__DRIVER_NAME " ScatterGatherListSize = %d\n", *ScatterGatherListSize));
524 FUNCTION_EXIT();
525 return STATUS_SUCCESS;
526 }
528 static NTSTATUS
529 XenPci_DOP_BuildScatterGatherList(
530 IN PDMA_ADAPTER DmaAdapter,
531 IN PDEVICE_OBJECT DeviceObject,
532 IN PMDL Mdl,
533 IN PVOID CurrentVa,
534 IN ULONG Length,
535 IN PDRIVER_LIST_CONTROL ExecutionRoutine,
536 IN PVOID Context,
537 IN BOOLEAN WriteToDevice,
538 IN PVOID ScatterGatherBuffer,
539 IN ULONG ScatterGatherBufferLength)
540 {
541 ULONG i;
542 PSCATTER_GATHER_LIST sglist = ScatterGatherBuffer;
543 PUCHAR ptr;
544 ULONG remaining = Length;
545 ULONG total_remaining;
546 xen_dma_adapter_t *xen_dma_adapter;
547 PXENPCI_DEVICE_DATA xpdd;
548 sg_extra_t *sg_extra;
549 PMDL curr_mdl;
550 ULONG map_type;
551 ULONG sg_element;
552 ULONG offset;
553 PFN_NUMBER pfn;
554 grant_ref_t gref;
555 //PUCHAR StartVa;
557 ASSERT(MmGetMdlVirtualAddress(Mdl) == CurrentVa);
559 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
560 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
562 ASSERT(Mdl);
564 if (xen_dma_adapter->dma_extension)
565 {
566 if (xen_dma_adapter->dma_extension->need_virtual_address(DeviceObject->CurrentIrp))
567 {
568 ASSERT(!Mdl->Next); /* can only virtual a single buffer */
569 map_type = MAP_TYPE_VIRTUAL;
570 sglist->NumberOfElements = 1;
571 }
572 else
573 {
574 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(DeviceObject->CurrentIrp);
575 if ((MmGetMdlByteOffset(Mdl) & (alignment - 1)) || (MmGetMdlByteCount(Mdl) & (alignment - 1)))
576 {
577 ASSERT(!Mdl->Next); /* can only remap a single buffer for now - will need to check all Mdl's in the future */
578 map_type = MAP_TYPE_REMAPPED;
579 sglist->NumberOfElements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(NULL, Length);
580 }
581 else
582 {
583 map_type = MAP_TYPE_MDL;
584 for (curr_mdl = Mdl, sglist->NumberOfElements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
585 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
586 MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
587 }
588 }
589 }
590 else
591 {
592 map_type = MAP_TYPE_MDL;
593 for (curr_mdl = Mdl, sglist->NumberOfElements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
594 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
595 MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
596 }
597 if (ScatterGatherBufferLength < FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
598 sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t))
599 {
600 return STATUS_BUFFER_TOO_SMALL;
601 }
603 sg_extra = (sg_extra_t *)((PUCHAR)sglist + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
604 (sizeof(SCATTER_GATHER_ELEMENT)) * sglist->NumberOfElements);
606 sg_extra->map_type = map_type;
607 switch (map_type)
608 {
609 case MAP_TYPE_MDL:
610 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL - %p\n", MmGetMdlVirtualAddress(Mdl)));
611 total_remaining = Length;
612 for (sg_element = 0, curr_mdl = Mdl; curr_mdl; curr_mdl = curr_mdl->Next)
613 {
614 remaining = MmGetMdlByteCount(curr_mdl);
615 offset = MmGetMdlByteOffset(curr_mdl);
616 for (i = 0; i < ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)); i++)
617 {
618 //KdPrint((__DRIVER_NAME " element = %d\n", sg_element));
619 //KdPrint((__DRIVER_NAME " remaining = %d\n", remaining));
620 pfn = MmGetMdlPfnArray(curr_mdl)[i];
621 ASSERT(pfn);
622 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
623 ASSERT(gref != INVALID_GRANT_REF);
624 sglist->Elements[sg_element].Address.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | offset;
625 sglist->Elements[sg_element].Length = min(min(PAGE_SIZE - offset, remaining), total_remaining);
626 total_remaining -= sglist->Elements[sg_element].Length;
627 remaining -= sglist->Elements[sg_element].Length;
628 offset = 0;
629 sg_element++;
630 }
631 }
632 break;
633 case MAP_TYPE_REMAPPED:
634 sg_extra->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, max(Length, PAGE_SIZE), XENPCI_POOL_TAG);
635 if (!sg_extra->aligned_buffer)
636 {
637 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED buffer allocation failed - requested va = %p, length = %d\n", MmGetMdlVirtualAddress(Mdl), Length));
638 return STATUS_INSUFFICIENT_RESOURCES;
639 }
640 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED - %p -> %p\n", MmGetMdlVirtualAddress(Mdl), sg_extra->aligned_buffer));
641 sg_extra->unaligned_buffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
642 ASSERT(sg_extra->unaligned_buffer); /* lazy */
643 sg_extra->copy_length = Length;
644 if (WriteToDevice)
645 memcpy(sg_extra->aligned_buffer, sg_extra->unaligned_buffer, sg_extra->copy_length);
646 for (sg_element = 0, remaining = Length;
647 sg_element < ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_extra->aligned_buffer, Length); sg_element++)
648 {
649 pfn = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)sg_extra->aligned_buffer + (sg_element << PAGE_SHIFT)).QuadPart >> PAGE_SHIFT);
650 ASSERT(pfn);
651 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
652 ASSERT(gref);
653 sglist->Elements[sg_element].Address.QuadPart = (ULONGLONG)gref << PAGE_SHIFT;
654 sglist->Elements[sg_element].Length = min(PAGE_SIZE, remaining);
655 remaining -= sglist->Elements[sg_element].Length;
656 }
657 break;
658 case MAP_TYPE_VIRTUAL:
659 ptr = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
660 ASSERT(ptr); /* lazy */
661 sglist->Elements[0].Address.QuadPart = (ULONGLONG)ptr;
662 sglist->Elements[0].Length = Length;
663 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL - %08x\n", sglist->Elements[0].Address.LowPart));
664 break;
665 }
667 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, ScatterGatherBuffer, Context);
669 //FUNCTION_EXIT();
671 return STATUS_SUCCESS;
672 }
674 static NTSTATUS
675 XenPci_DOP_BuildMdlFromScatterGatherList(
676 PDMA_ADAPTER DmaAdapter,
677 PSCATTER_GATHER_LIST ScatterGather,
678 PMDL OriginalMdl,
679 PMDL *TargetMdl)
680 {
681 UNREFERENCED_PARAMETER(DmaAdapter);
682 UNREFERENCED_PARAMETER(ScatterGather);
683 UNREFERENCED_PARAMETER(OriginalMdl);
684 UNREFERENCED_PARAMETER(TargetMdl);
686 FUNCTION_ENTER();
687 FUNCTION_EXIT();
688 return STATUS_UNSUCCESSFUL;
689 }
691 static PDMA_ADAPTER
692 XenPci_BIS_GetDmaAdapter(PVOID context, PDEVICE_DESCRIPTION device_description, PULONG number_of_map_registers)
693 {
694 xen_dma_adapter_t *xen_dma_adapter;
695 PDEVICE_OBJECT curr, prev;
696 PDRIVER_OBJECT fdo_driver_object;
697 PVOID fdo_driver_extension;
699 UNREFERENCED_PARAMETER(device_description);
701 FUNCTION_ENTER();
703 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
704 KdPrint((__DRIVER_NAME " Device Description = %p:\n", device_description));
705 KdPrint((__DRIVER_NAME " Version = %d\n", device_description->Version));
706 KdPrint((__DRIVER_NAME " Master = %d\n", device_description->Master));
707 KdPrint((__DRIVER_NAME " ScatterGather = %d\n", device_description->ScatterGather));
708 KdPrint((__DRIVER_NAME " DemandMode = %d\n", device_description->DemandMode));
709 KdPrint((__DRIVER_NAME " AutoInitialize = %d\n", device_description->AutoInitialize));
710 KdPrint((__DRIVER_NAME " Dma32BitAddresses = %d\n", device_description->Dma32BitAddresses));
711 KdPrint((__DRIVER_NAME " IgnoreCount = %d\n", device_description->IgnoreCount));
712 KdPrint((__DRIVER_NAME " Dma64BitAddresses = %d\n", device_description->Dma64BitAddresses));
713 KdPrint((__DRIVER_NAME " BusNumber = %d\n", device_description->BusNumber));
714 KdPrint((__DRIVER_NAME " DmaChannel = %d\n", device_description->DmaChannel));
715 KdPrint((__DRIVER_NAME " InterfaceType = %d\n", device_description->InterfaceType));
716 KdPrint((__DRIVER_NAME " DmaWidth = %d\n", device_description->DmaWidth));
717 KdPrint((__DRIVER_NAME " DmaSpeed = %d\n", device_description->DmaSpeed));
718 KdPrint((__DRIVER_NAME " MaximumLength = %d\n", device_description->MaximumLength));
719 KdPrint((__DRIVER_NAME " DmaPort = %d\n", device_description->DmaPort));
721 /*
722 we have to allocate PAGE_SIZE bytes here because Windows thinks this is
723 actually an ADAPTER_OBJECT, and then the verifier crashes because
724 Windows accessed beyond the end of the structure :(
725 */
726 xen_dma_adapter = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
727 RtlZeroMemory(xen_dma_adapter, PAGE_SIZE);
728 xen_dma_adapter->dma_adapter.Version = 2;
729 xen_dma_adapter->dma_adapter.Size = sizeof(DMA_ADAPTER); //xen_dma_adapter_t);
730 xen_dma_adapter->dma_adapter.DmaOperations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DMA_OPERATIONS), XENPCI_POOL_TAG);
731 xen_dma_adapter->dma_adapter.DmaOperations->Size = sizeof(DMA_OPERATIONS);
732 xen_dma_adapter->dma_adapter.DmaOperations->PutDmaAdapter = XenPci_DOP_PutDmaAdapter;
733 xen_dma_adapter->dma_adapter.DmaOperations->AllocateCommonBuffer = XenPci_DOP_AllocateCommonBuffer;
734 xen_dma_adapter->dma_adapter.DmaOperations->FreeCommonBuffer = XenPci_DOP_FreeCommonBuffer;
735 xen_dma_adapter->dma_adapter.DmaOperations->AllocateAdapterChannel = XenPci_DOP_AllocateAdapterChannel;
736 xen_dma_adapter->dma_adapter.DmaOperations->FlushAdapterBuffers = XenPci_DOP_FlushAdapterBuffers;
737 xen_dma_adapter->dma_adapter.DmaOperations->FreeAdapterChannel = XenPci_DOP_FreeAdapterChannel;
738 xen_dma_adapter->dma_adapter.DmaOperations->FreeMapRegisters = XenPci_DOP_FreeMapRegisters;
739 xen_dma_adapter->dma_adapter.DmaOperations->MapTransfer = XenPci_DOP_MapTransfer;
740 xen_dma_adapter->dma_adapter.DmaOperations->GetDmaAlignment = XenPci_DOP_GetDmaAlignment;
741 xen_dma_adapter->dma_adapter.DmaOperations->ReadDmaCounter = XenPci_DOP_ReadDmaCounter;
742 xen_dma_adapter->dma_adapter.DmaOperations->GetScatterGatherList = XenPci_DOP_GetScatterGatherList;
743 xen_dma_adapter->dma_adapter.DmaOperations->PutScatterGatherList = XenPci_DOP_PutScatterGatherList;
744 xen_dma_adapter->dma_adapter.DmaOperations->CalculateScatterGatherList = XenPci_DOP_CalculateScatterGatherList;
745 xen_dma_adapter->dma_adapter.DmaOperations->BuildScatterGatherList = XenPci_DOP_BuildScatterGatherList;
746 xen_dma_adapter->dma_adapter.DmaOperations->BuildMdlFromScatterGatherList = XenPci_DOP_BuildMdlFromScatterGatherList;
747 xen_dma_adapter->xppdd = context;
748 xen_dma_adapter->dma_extension = NULL;
750 KdPrint((__DRIVER_NAME " About to call IoGetAttachedDeviceReference\n"));
751 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(xen_dma_adapter->xppdd->wdf_device));
752 //curr = WdfDeviceWdmGetAttachedDevice(xen_dma_adapter->xppdd->wdf_device);
753 KdPrint((__DRIVER_NAME " Before start of loop - curr = %p\n", curr));
754 while (curr != NULL)
755 {
756 fdo_driver_object = curr->DriverObject;
757 if (fdo_driver_object)
758 {
759 ObReferenceObject(fdo_driver_object);
760 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC));
761 if (fdo_driver_extension)
762 {
763 xen_dma_adapter->dma_extension_driver = fdo_driver_object; /* so we can dereference it on putdmaadapter */
764 xen_dma_adapter->dma_extension = (dma_driver_extension_t *)fdo_driver_extension;
765 ObDereferenceObject(curr);
766 break;
767 }
768 else
769 {
770 ObDereferenceObject(fdo_driver_object);
771 }
772 }
773 prev = curr;
774 curr = IoGetLowerDeviceObject(curr);
775 ObDereferenceObject(prev);
776 }
777 KdPrint((__DRIVER_NAME " End of loop\n"));
779 *number_of_map_registers = 1024; /* why not... */
781 FUNCTION_EXIT();
783 return &xen_dma_adapter->dma_adapter;
784 }
786 static ULONG
787 XenPci_BIS_SetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
788 {
789 UNREFERENCED_PARAMETER(context);
790 UNREFERENCED_PARAMETER(data_type);
791 UNREFERENCED_PARAMETER(buffer);
792 UNREFERENCED_PARAMETER(offset);
793 UNREFERENCED_PARAMETER(length);
795 FUNCTION_ENTER();
796 FUNCTION_EXIT();
797 return 0;
798 }
800 static ULONG
801 XenPci_BIS_GetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
802 {
803 UNREFERENCED_PARAMETER(context);
804 UNREFERENCED_PARAMETER(data_type);
805 UNREFERENCED_PARAMETER(buffer);
806 UNREFERENCED_PARAMETER(offset);
807 UNREFERENCED_PARAMETER(length);
809 FUNCTION_ENTER();
810 FUNCTION_EXIT();
811 return 0;
812 }
814 /*
815 Called at PASSIVE_LEVEL(?)
816 Called during restore
817 */
819 static ULONG
820 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
821 {
822 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
823 char path[128];
824 char *value;
825 char *err;
826 ULONG backend_state;
828 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
829 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
830 if (err)
831 {
832 XenPci_FreeMem(err);
833 return XenbusStateUnknown;
834 }
835 else
836 {
837 backend_state = atoi(value);
838 XenPci_FreeMem(value);
839 return backend_state;
840 }
841 }
843 static VOID
844 XenPci_BackEndStateHandler(char *path, PVOID context)
845 {
846 WDFDEVICE device = context;
847 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
848 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
849 ULONG new_backend_state;
851 #if !DBG
852 UNREFERENCED_PARAMETER(path);
853 #endif
855 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
857 /* check that path == device/id/state */
858 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
859 new_backend_state = XenPci_ReadBackendState(xppdd);
860 if (new_backend_state == XenbusStateUnknown)
861 {
862 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
863 return;
864 KdPrint(("Failed to read %s, assuming closed\n", path));
865 new_backend_state = XenbusStateClosed;
866 }
868 if (xppdd->backend_state == new_backend_state)
869 {
870 KdPrint((__DRIVER_NAME " state unchanged\n"));
871 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
872 return;
873 }
875 xppdd->backend_state = new_backend_state;
877 switch (xppdd->backend_state)
878 {
879 case XenbusStateUnknown:
880 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown (%s)\n", path));
881 break;
883 case XenbusStateInitialising:
884 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising (%s)\n", path));
885 break;
887 case XenbusStateInitWait:
888 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait (%s)\n", path));
889 break;
891 case XenbusStateInitialised:
892 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised (%s)\n", path));
893 break;
895 case XenbusStateConnected:
896 KdPrint((__DRIVER_NAME " Backend State Changed to Connected (%s)\n", path));
897 break;
899 case XenbusStateClosing:
900 KdPrint((__DRIVER_NAME " Backend State Changed to Closing (%s)\n", path));
901 if (xpdd->suspend_state == SUSPEND_STATE_NONE)
902 {
903 WdfPdoRequestEject(device);
904 #if 0
905 if (xppdd->common.device_usage_paging
906 || xppdd->common.device_usage_dump
907 || xppdd->common.device_usage_hibernation)
908 {
909 KdPrint((__DRIVER_NAME " Not closing device because it is in use\n"));
910 /* in use by page file, dump file, or hiber file - can't close */
911 /* we should probably re-check if the device usage changes in the future */
912 }
913 else
914 {
916 if (xppdd->common.current_pnp_state == Started)
917 {
918 KdPrint((__DRIVER_NME " Sending RequestDeviceEject\n"));
919 WdfPdoRequestEject(device);
920 }
921 else
922 {
923 KdPrint((__DRIVER_NAME " Not closing device because it is not started\n"));
924 }
925 }
926 #endif
927 }
928 break;
930 case XenbusStateClosed:
931 KdPrint((__DRIVER_NAME " Backend State Changed to Closed (%s)\n", path));
932 break;
934 default:
935 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d (%s)\n", xppdd->backend_state, path));
936 break;
937 }
939 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
941 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
943 return;
944 }
946 static NTSTATUS
947 XenPci_GetBackendAndAddWatch(WDFDEVICE device)
948 {
949 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
950 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
951 char path[128];
952 PCHAR res;
953 PCHAR value;
955 /* Get backend path */
956 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
957 "%s/backend", xppdd->path);
958 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
959 if (res)
960 {
961 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
962 XenPci_FreeMem(res);
963 return STATUS_UNSUCCESSFUL;
964 }
965 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
966 XenPci_FreeMem(value);
968 /* Add watch on backend state */
969 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
970 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, device);
972 return STATUS_SUCCESS;
973 }
975 static PMDL
976 XenConfig_MakeConfigPage(WDFDEVICE device)
977 {
978 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
979 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
980 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
981 PMDL mdl;
982 PUCHAR ptr;
983 PDEVICE_OBJECT curr, prev;
984 PDRIVER_OBJECT fdo_driver_object;
985 PUCHAR fdo_driver_extension;
987 FUNCTION_ENTER();
989 mdl = AllocateUncachedPage();
990 ptr = MmGetMdlVirtualAddress(mdl);
991 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(device));
992 //curr = WdfDeviceWdmGetAttachedDevice(device);
993 while (curr != NULL)
994 {
995 fdo_driver_object = curr->DriverObject;
996 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
997 if (fdo_driver_object)
998 {
999 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
1000 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
1001 if (fdo_driver_extension)
1003 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
1004 ObDereferenceObject(curr);
1005 break;
1008 prev = curr;
1009 curr = IoGetLowerDeviceObject(curr);
1010 ObDereferenceObject(prev);
1013 FUNCTION_EXIT();
1015 return mdl;
1018 static NTSTATUS
1019 XenPci_EvtChn_Bind(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
1021 WDFDEVICE device = context;
1022 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1023 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1025 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext);
1028 static NTSTATUS
1029 XenPci_EvtChn_BindDpc(PVOID context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
1031 WDFDEVICE device = context;
1032 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1033 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1035 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext);
1038 static NTSTATUS
1039 XenPci_EvtChn_Unbind(PVOID context, evtchn_port_t Port)
1041 WDFDEVICE device = context;
1042 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1043 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1045 return EvtChn_Unbind(xpdd, Port);
1048 static NTSTATUS
1049 XenPci_EvtChn_Mask(PVOID context, evtchn_port_t Port)
1051 WDFDEVICE device = context;
1052 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1053 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1055 return EvtChn_Mask(xpdd, Port);
1058 static NTSTATUS
1059 XenPci_EvtChn_Unmask(PVOID context, evtchn_port_t Port)
1061 WDFDEVICE device = context;
1062 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1063 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1065 return EvtChn_Unmask(xpdd, Port);
1068 static NTSTATUS
1069 XenPci_EvtChn_Notify(PVOID context, evtchn_port_t Port)
1071 WDFDEVICE device = context;
1072 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1073 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1075 return EvtChn_Notify(xpdd, Port);
1078 static BOOLEAN
1079 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port)
1081 WDFDEVICE device = context;
1082 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1083 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1085 return EvtChn_AckEvent(xpdd, port);
1088 typedef struct {
1089 PXEN_EVTCHN_SYNC_ROUTINE sync_routine;
1090 PVOID sync_context;
1091 } sync_context_t;
1093 static BOOLEAN
1094 XenPci_EvtChn_Sync_Routine(WDFINTERRUPT interrupt, WDFCONTEXT context)
1096 sync_context_t *wdf_sync_context = context;
1097 UNREFERENCED_PARAMETER(interrupt);
1098 return wdf_sync_context->sync_routine(wdf_sync_context->sync_context);
1101 static BOOLEAN
1102 XenPci_EvtChn_Sync(PVOID context, PXEN_EVTCHN_SYNC_ROUTINE sync_routine, PVOID sync_context)
1104 WDFDEVICE device = context;
1105 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1106 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1107 sync_context_t wdf_sync_context;
1109 wdf_sync_context.sync_routine = sync_routine;
1110 wdf_sync_context.sync_context = sync_context;
1112 return WdfInterruptSynchronize(xpdd->interrupt, XenPci_EvtChn_Sync_Routine, &wdf_sync_context);
1115 static grant_ref_t
1116 XenPci_GntTbl_GrantAccess(PVOID context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref)
1118 WDFDEVICE device = context;
1119 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1120 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1122 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref);
1125 static BOOLEAN
1126 XenPci_GntTbl_EndAccess(PVOID context, grant_ref_t ref, BOOLEAN keepref)
1128 WDFDEVICE device = context;
1129 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1130 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1132 return GntTbl_EndAccess(xpdd, ref, keepref);
1135 static VOID
1136 XenPci_GntTbl_PutRef(PVOID context, grant_ref_t ref)
1138 WDFDEVICE device = context;
1139 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1140 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1142 GntTbl_PutRef(xpdd, ref);
1145 static grant_ref_t
1146 XenPci_GntTbl_GetRef(PVOID context)
1148 WDFDEVICE device = context;
1149 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1150 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1152 return GntTbl_GetRef(xpdd);
1155 PCHAR
1156 XenPci_XenBus_Read(PVOID context, xenbus_transaction_t xbt, char *path, char **value)
1158 WDFDEVICE device = context;
1159 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1160 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1161 return XenBus_Read(xpdd, xbt, path, value);
1164 PCHAR
1165 XenPci_XenBus_Write(PVOID context, xenbus_transaction_t xbt, char *path, char *value)
1167 WDFDEVICE device = context;
1168 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1169 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1170 return XenBus_Write(xpdd, xbt, path, value);
1173 PCHAR
1174 XenPci_XenBus_Printf(PVOID context, xenbus_transaction_t xbt, char *path, char *fmt, ...)
1176 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
1177 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
1178 //return XenBus_Printf(xpdd, xbt, path, value);
1179 UNREFERENCED_PARAMETER(context);
1180 UNREFERENCED_PARAMETER(xbt);
1181 UNREFERENCED_PARAMETER(path);
1182 UNREFERENCED_PARAMETER(fmt);
1183 return NULL;
1186 PCHAR
1187 XenPci_XenBus_StartTransaction(PVOID context, xenbus_transaction_t *xbt)
1189 WDFDEVICE device = context;
1190 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1191 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1192 return XenBus_StartTransaction(xpdd, xbt);
1195 PCHAR
1196 XenPci_XenBus_EndTransaction(PVOID context, xenbus_transaction_t xbt, int abort, int *retry)
1198 WDFDEVICE device = context;
1199 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1200 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1201 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
1204 PCHAR
1205 XenPci_XenBus_List(PVOID context, xenbus_transaction_t xbt, char *prefix, char ***contents)
1207 WDFDEVICE device = context;
1208 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1209 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1210 return XenBus_List(xpdd, xbt, prefix, contents);
1213 PCHAR
1214 XenPci_XenBus_AddWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
1216 WDFDEVICE device = context;
1217 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1218 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1219 PCHAR retval;
1221 FUNCTION_ENTER();
1222 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
1223 if (retval == NULL)
1225 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
1227 else
1229 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
1231 FUNCTION_EXIT();
1232 return retval;
1235 PCHAR
1236 XenPci_XenBus_RemWatch(PVOID context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
1238 WDFDEVICE device = context;
1239 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1240 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1241 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
1244 /*
1245 Called at PASSIVE_LEVEL
1246 Called during restore
1247 */
1249 static NTSTATUS
1250 XenPci_ChangeFrontendState(WDFDEVICE device, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
1252 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1253 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1254 LARGE_INTEGER timeout;
1255 ULONG remaining;
1256 ULONG thiswait;
1257 char path[128];
1259 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1261 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
1262 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
1264 remaining = maximum_wait_ms;
1266 while (xppdd->backend_state != backend_state_response)
1268 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
1269 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
1270 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
1272 remaining -= thiswait;
1273 if (remaining == 0)
1275 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
1276 return STATUS_UNSUCCESSFUL;
1278 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
1281 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1282 return STATUS_SUCCESS;
1285 static NTSTATUS
1286 XenPci_XenConfigDevice(WDFDEVICE device);
1288 static NTSTATUS
1289 XenPci_XenShutdownDevice(PVOID context)
1291 WDFDEVICE device = context;
1292 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1293 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1294 PUCHAR in_ptr;
1295 ULONG i;
1296 UCHAR type;
1297 PVOID setting;
1298 PVOID value;
1299 PVOID value2;
1301 FUNCTION_ENTER();
1303 if (xppdd->backend_state == XenbusStateConnected)
1305 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
1306 if (xppdd->backend_state == XenbusStateClosing)
1307 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
1308 if (xppdd->backend_state == XenbusStateClosed)
1309 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
1311 else
1313 if (xppdd->backend_state == XenbusStateClosing)
1314 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
1317 if (xppdd->assigned_resources_start != NULL)
1319 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1320 in_ptr = xppdd->assigned_resources_start;
1321 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
1323 switch (type)
1325 case XEN_INIT_TYPE_RING: /* frontend ring */
1326 FreePages(value);
1327 break;
1328 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
1329 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
1330 EvtChn_Unbind(xpdd, PtrToUlong(value));
1331 EvtChn_Close(xpdd, PtrToUlong(value));
1332 break;
1333 case XEN_INIT_TYPE_GRANT_ENTRIES:
1334 for (i = 0; i < PtrToUlong(setting); i++)
1335 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value)[i], FALSE);
1336 break;
1339 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
1340 xppdd->assigned_resources_start = NULL;
1343 FUNCTION_EXIT();
1345 return STATUS_SUCCESS;
1348 struct dummy_sring {
1349 RING_IDX req_prod, req_event;
1350 RING_IDX rsp_prod, rsp_event;
1351 uint8_t pad[48];
1352 };
1354 static NTSTATUS
1355 XenPci_XenConfigDeviceSpecifyBuffers(WDFDEVICE device, PUCHAR src, PUCHAR dst)
1357 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1358 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1359 NTSTATUS status = STATUS_SUCCESS;
1360 ULONG i;
1361 char path[128];
1362 PCHAR setting, value;
1363 PCHAR res;
1364 PVOID address;
1365 UCHAR type;
1366 PUCHAR in_ptr; //, in_start;
1367 PUCHAR out_ptr; //, out_start;
1368 XENPCI_VECTORS vectors;
1369 ULONG event_channel;
1370 ULONG run_type = 0;
1371 PMDL ring;
1372 grant_ref_t gref;
1373 BOOLEAN done_xenbus_init = FALSE;
1374 PVOID value2;
1376 FUNCTION_ENTER();
1378 in_ptr = src;
1379 out_ptr = dst;
1381 // always add vectors
1382 vectors.magic = XEN_DATA_MAGIC;
1383 vectors.length = sizeof(XENPCI_VECTORS);
1384 vectors.context = device;
1385 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
1386 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
1387 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
1388 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
1389 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
1390 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
1391 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
1392 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
1393 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
1394 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
1395 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
1396 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
1397 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
1398 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
1399 strncpy(vectors.path, xppdd->path, 128);
1400 strncpy(vectors.backend_path, xppdd->backend_path, 128);
1401 //vectors.pdo_event_channel = xpdd->pdo_event_channel;
1402 vectors.XenBus_Read = XenPci_XenBus_Read;
1403 vectors.XenBus_Write = XenPci_XenBus_Write;
1404 vectors.XenBus_Printf = XenPci_XenBus_Printf;
1405 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
1406 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
1407 vectors.XenBus_List = XenPci_XenBus_List;
1408 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
1409 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
1411 if (qemu_filtered)
1412 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_ACTIVE, NULL, NULL, NULL);
1414 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
1416 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
1417 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
1419 // first pass, possibly before state == Connected
1420 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
1423 if (!done_xenbus_init)
1425 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
1427 status = STATUS_UNSUCCESSFUL;
1428 goto error;
1430 done_xenbus_init = TRUE;
1433 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
1435 switch (type)
1437 case XEN_INIT_TYPE_RUN:
1438 run_type++;
1439 break;
1440 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
1441 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
1442 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1443 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
1444 break;
1445 case XEN_INIT_TYPE_RING: /* frontend ring */
1446 /* we only allocate and do the SHARED_RING_INIT here */
1447 if ((ring = AllocatePage()) != 0)
1449 address = MmGetMdlVirtualAddress(ring);
1450 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
1451 SHARED_RING_INIT((struct dummy_sring *)address);
1452 if ((gref = GntTbl_GrantAccess(
1453 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
1455 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1456 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
1457 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
1458 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
1459 // add the grant entry too so it gets freed automatically
1460 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
1461 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
1462 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
1464 else
1466 FreePages(ring);
1467 status = STATUS_UNSUCCESSFUL;
1468 goto error;
1471 else
1473 status = STATUS_UNSUCCESSFUL;
1474 goto error;
1476 break;
1477 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
1478 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
1479 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
1481 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
1482 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1483 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
1484 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
1485 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
1486 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
1488 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
1490 else
1492 #pragma warning(suppress:4055)
1493 EvtChn_Bind(xpdd, event_channel, (PXEN_EVTCHN_SERVICE_ROUTINE)value, value2);
1496 else
1498 status = STATUS_UNSUCCESSFUL;
1499 goto error;
1501 break;
1504 if (!NT_SUCCESS(status))
1506 goto error;
1508 // If XEN_INIT_TYPE_RUN was specified more than once then we skip XenbusStateInitialised here and go straight to XenbusStateConnected at the end
1509 if (run_type == 1)
1511 if (XenPci_ChangeFrontendState(device, XenbusStateInitialised, XenbusStateConnected, 30000) != STATUS_SUCCESS)
1513 status = STATUS_UNSUCCESSFUL;
1514 goto error;
1518 // second pass, possibly after state == Connected
1519 in_ptr = src;
1520 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
1522 switch(type)
1524 case XEN_INIT_TYPE_READ_STRING_BACK:
1525 case XEN_INIT_TYPE_READ_STRING_FRONT:
1526 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
1527 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
1528 else
1529 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
1530 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
1531 if (res)
1533 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
1534 XenPci_FreeMem(res);
1535 ADD_XEN_INIT_RSP(&out_ptr, type, setting, NULL, NULL);
1537 else
1539 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
1540 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, value2);
1541 XenPci_FreeMem(value);
1543 break;
1544 case XEN_INIT_TYPE_VECTORS:
1545 // this is always done so ignore the request
1546 break;
1547 case XEN_INIT_TYPE_GRANT_ENTRIES:
1548 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
1549 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
1550 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
1551 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
1552 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
1553 for (i = 0; i < PtrToUlong(value); i++)
1555 gref = GntTbl_GetRef(xpdd);
1556 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
1557 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
1559 break;
1562 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1564 if (run_type)
1566 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
1568 status = STATUS_UNSUCCESSFUL;
1569 goto error;
1572 FUNCTION_EXIT();
1573 return status;
1575 error:
1576 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
1577 FUNCTION_EXIT_STATUS(status);
1579 return status;
1582 static NTSTATUS
1583 XenPci_XenConfigDevice(WDFDEVICE device)
1585 NTSTATUS status;
1586 PUCHAR src, dst;
1587 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1589 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
1590 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
1591 memcpy(src, dst, xppdd->config_page_length);
1593 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
1595 MmUnmapIoSpace(dst, xppdd->config_page_length);
1596 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
1598 return status;
1601 static NTSTATUS
1602 XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp)
1604 NTSTATUS status = STATUS_SUCCESS;
1605 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1606 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1607 PIO_STACK_LOCATION stack;
1608 PCM_PARTIAL_RESOURCE_LIST prl;
1609 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
1610 ULONG i;
1611 char path[128];
1612 PMDL mdl;
1614 FUNCTION_ENTER();
1615 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
1617 stack = IoGetCurrentIrpStackLocation(irp);
1619 status = XenPci_GetBackendAndAddWatch(device);
1620 if (!NT_SUCCESS(status)) {
1621 FUNCTION_ERROR_EXIT();
1622 return status;
1625 mdl = XenConfig_MakeConfigPage(device);
1627 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
1628 for (i = 0; i < prl->Count; i++)
1630 prd = & prl->PartialDescriptors[i];
1631 switch (prd->Type)
1633 case CmResourceTypeMemory:
1634 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
1636 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
1637 prd->u.Memory.Length = MmGetMdlByteCount(mdl);
1639 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
1641 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1642 prd->Type = CmResourceTypeInterrupt;
1643 prd->ShareDisposition = CmResourceShareShared;
1644 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
1645 prd->u.Interrupt.Level = xpdd->irq_number;
1646 prd->u.Interrupt.Vector = xpdd->irq_number;
1647 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
1648 xppdd->irq_number = xpdd->irq_number;
1650 break;
1654 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
1655 for (i = 0; i < prl->Count; i++)
1657 prd = & prl->PartialDescriptors[i];
1658 switch (prd->Type)
1660 case CmResourceTypeMemory:
1661 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
1662 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
1663 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
1665 if (prd->u.Memory.Length == 0)
1667 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(mdl)[0]));
1668 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
1669 prd->u.Memory.Length = MmGetMdlByteCount(mdl);
1670 KdPrint((__DRIVER_NAME " New Start = %08x%08x, Length = %d\n", prd->u.Memory.Start.HighPart, prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
1672 xppdd->config_page_phys = prd->u.Memory.Start;
1673 xppdd->config_page_length = prd->u.Memory.Length;
1674 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
1675 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
1677 status = XenPci_XenConfigDevice(device);
1678 if (!NT_SUCCESS(status))
1680 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1681 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
1682 FUNCTION_ERROR_EXIT();
1683 return status;
1686 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
1688 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1689 prd->Type = CmResourceTypeInterrupt;
1690 prd->ShareDisposition = CmResourceShareShared;
1691 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
1692 prd->u.Interrupt.Level = xpdd->irq_level;
1693 prd->u.Interrupt.Vector = xpdd->irq_vector;
1694 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
1695 xppdd->irq_vector = xpdd->irq_vector;
1696 xppdd->irq_level = xpdd->irq_level;
1698 break;
1702 IoSkipCurrentIrpStackLocation(irp);
1704 FUNCTION_EXIT();
1706 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
1709 #if 0
1710 static NTSTATUS
1711 XenPciPdo_EvtDeviceResourcesQuery(WDFDEVICE device, WDFCMRESLIST resources)
1714 #endif
1716 static NTSTATUS
1717 XenPciPdo_EvtDeviceResourceRequirementsQuery(WDFDEVICE device, WDFIORESREQLIST requirements_list)
1719 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1720 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1721 WDFIORESLIST res_list;
1722 IO_RESOURCE_DESCRIPTOR ird;
1724 FUNCTION_ENTER();
1726 WdfIoResourceRequirementsListSetInterfaceType(requirements_list, PNPBus);
1728 WdfIoResourceListCreate(requirements_list, WDF_NO_OBJECT_ATTRIBUTES, &res_list);
1729 ird.Option = 0;
1730 ird.Type = CmResourceTypeMemory;
1731 ird.ShareDisposition = CmResourceShareShared;
1732 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
1733 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
1734 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
1735 ird.u.Memory.Length = 0;
1736 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
1737 WdfIoResourceListAppendDescriptor(res_list, &ird);
1739 ird.Option = 0;
1740 ird.Type = CmResourceTypeMemory;
1741 ird.ShareDisposition = CmResourceShareShared;
1742 ird.Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
1743 ird.u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
1744 ird.u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
1745 ird.u.Memory.Length = 0;
1746 ird.u.Memory.Alignment = 1; //PAGE_SIZE;
1747 WdfIoResourceListAppendDescriptor(res_list, &ird);
1749 WdfIoResourceRequirementsListAppendIoResList(requirements_list, res_list);
1751 FUNCTION_EXIT();
1753 return STATUS_SUCCESS;
1756 NTSTATUS
1757 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
1758 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
1759 PWDFDEVICE_INIT child_init)
1761 NTSTATUS status = STATUS_SUCCESS;
1762 WDF_OBJECT_ATTRIBUTES child_attributes;
1763 WDFDEVICE child_device;
1764 PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
1765 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
1766 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
1767 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
1768 PXENPCI_PDO_DEVICE_DATA xppdd;
1769 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
1770 WDF_QUERY_INTERFACE_CONFIG interface_config;
1771 BUS_INTERFACE_STANDARD bus_interface;
1772 WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
1773 UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
1775 FUNCTION_ENTER();
1777 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
1779 /*
1780 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
1781 child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
1782 child_pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPciPdo_EvtDeviceD0EntryPostInterruptsEnabled;
1783 child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
1784 child_pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPciPdo_EvtDeviceD0ExitPreInterruptsDisabled;
1785 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenPciPdo_EvtDevicePrepareHardware;
1786 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenPciPdo_EvtDeviceReleaseHardware;
1787 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
1788 */
1789 KdPrint((__DRIVER_NAME " device = '%s', index = '%d', path = '%s'\n",
1790 identification->device, identification->index, identification->path));
1792 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
1793 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
1794 if (!NT_SUCCESS(status))
1796 return status;
1799 WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
1800 //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
1801 pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
1802 //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
1803 //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock;
1804 WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);
1806 RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
1807 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
1808 if (!NT_SUCCESS(status))
1810 return status;
1812 status = WdfPdoInitAddHardwareID(child_init, &buffer);
1813 if (!NT_SUCCESS(status))
1815 return status;
1817 status = WdfPdoInitAddCompatibleID(child_init, &buffer);
1818 if (!NT_SUCCESS(status))
1820 return status;
1823 RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
1824 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
1825 if (!NT_SUCCESS(status))
1827 return status;
1830 RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
1831 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
1832 if (!NT_SUCCESS(status))
1834 return status;
1836 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
1838 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
1839 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
1840 if (!NT_SUCCESS(status))
1842 return status;
1845 xppdd = GetXppdd(child_device);
1847 xppdd->wdf_device = child_device;
1848 xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
1850 xppdd->device_state.magic = XEN_DEVICE_STATE_MAGIC;
1851 xppdd->device_state.length = sizeof(XENPCI_DEVICE_STATE);
1852 xppdd->device_state.suspend_resume_state_pdo = SR_STATE_RUNNING;
1853 xppdd->device_state.suspend_resume_state_fdo = SR_STATE_RUNNING;
1854 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
1855 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
1856 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
1857 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
1859 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
1860 child_pnp_capabilities.LockSupported = WdfFalse;
1861 child_pnp_capabilities.EjectSupported = WdfTrue;
1862 child_pnp_capabilities.Removable = WdfTrue;
1863 child_pnp_capabilities.DockDevice = WdfFalse;
1864 child_pnp_capabilities.UniqueID = WdfFalse;
1865 child_pnp_capabilities.SilentInstall = WdfTrue;
1866 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
1867 child_pnp_capabilities.HardwareDisabled = WdfFalse;
1868 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
1870 //WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
1871 //WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
1873 bus_interface.Size = sizeof(BUS_INTERFACE_STANDARD);
1874 bus_interface.Version = 1; //BUS_INTERFACE_STANDARD_VERSION;
1875 bus_interface.Context = xppdd;
1876 bus_interface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
1877 bus_interface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
1878 bus_interface.TranslateBusAddress = XenPci_BIS_TranslateBusAddress;
1879 bus_interface.GetDmaAdapter = XenPci_BIS_GetDmaAdapter;
1880 bus_interface.SetBusData = XenPci_BIS_SetBusData;
1881 bus_interface.GetBusData = XenPci_BIS_GetBusData;
1882 WDF_QUERY_INTERFACE_CONFIG_INIT(&interface_config, (PINTERFACE)&bus_interface, &GUID_BUS_INTERFACE_STANDARD, NULL);
1883 status = WdfDeviceAddQueryInterface(child_device, &interface_config);
1884 if (!NT_SUCCESS(status))
1886 return status;
1889 RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
1890 RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
1891 xppdd->index = identification->index;
1892 KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
1893 xppdd->backend_state = XenbusStateUnknown;
1894 xppdd->backend_path[0] = '\0';
1896 FUNCTION_EXIT();
1898 return status;
1901 static __forceinline VOID
1902 XenPci_Pdo_ChangeSuspendState(WDFDEVICE device, ULONG new_state)
1904 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1905 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1907 FUNCTION_ENTER();
1908 KdPrint((__DRIVER_NAME " setting pdo state to %d\n", new_state));
1909 xppdd->device_state.suspend_resume_state_pdo = new_state;
1910 KeMemoryBarrier();
1911 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xpdd->pdo_event_channel));
1912 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
1913 while(xppdd->device_state.suspend_resume_state_fdo != xppdd->device_state.suspend_resume_state_pdo)
1915 KdPrint((__DRIVER_NAME " waiting...\n"));
1916 KeWaitForSingleObject(&xpdd->pdo_suspend_event, Executive, KernelMode, FALSE, NULL);
1918 KdPrint((__DRIVER_NAME " fdo state set to %d\n", new_state));
1919 FUNCTION_EXIT();
1922 /* called at PASSIVE_LEVEL */
1923 NTSTATUS
1924 XenPci_Pdo_Suspend(WDFDEVICE device)
1926 NTSTATUS status = STATUS_SUCCESS;
1927 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1928 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1929 //LARGE_INTEGER wait_time;
1930 char path[128];
1931 PUCHAR in_ptr;
1932 UCHAR type;
1933 PVOID setting;
1934 PVOID value;
1935 PVOID value2;
1937 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
1939 if (xppdd->backend_state == XenbusStateConnected)
1941 xppdd->restart_on_resume = TRUE;
1942 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_SUSPENDING);
1944 XenPci_ChangeFrontendState(device, XenbusStateClosing, XenbusStateClosing, 30000);
1945 XenPci_ChangeFrontendState(device, XenbusStateClosed, XenbusStateClosed, 30000);
1946 XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000);
1948 if (xppdd->assigned_resources_start != NULL)
1950 in_ptr = xppdd->assigned_resources_ptr;
1951 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1952 in_ptr = xppdd->assigned_resources_start;
1953 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
1955 switch (type)
1957 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
1958 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
1959 EvtChn_Unbind(xpdd, PtrToUlong(value));
1960 EvtChn_Close(xpdd, PtrToUlong(value));
1961 break;
1966 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1967 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
1969 else
1971 xppdd->restart_on_resume = FALSE;
1974 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1976 return status;
1979 NTSTATUS
1980 XenPci_Pdo_Resume(WDFDEVICE device)
1982 NTSTATUS status = STATUS_SUCCESS;
1983 PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
1984 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
1985 ULONG old_backend_state;
1986 PUCHAR src, dst;
1988 FUNCTION_ENTER();
1989 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
1991 xppdd->device_state.pdo_event_channel = xpdd->pdo_event_channel;
1992 old_backend_state = xppdd->backend_state;
1994 if (xppdd->restart_on_resume)
1996 status = XenPci_GetBackendAndAddWatch(device);
1998 if (XenPci_ChangeFrontendState(device, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
2000 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
2001 // this is probably an unrecoverable situation...
2002 FUNCTION_ERROR_EXIT();
2003 return STATUS_UNSUCCESSFUL;
2005 if (xppdd->assigned_resources_ptr)
2007 // reset things - feed the 'requested resources' back in
2008 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
2009 src = xppdd->requested_resources_start;
2010 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
2011 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
2013 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
2015 status = XenPci_XenConfigDeviceSpecifyBuffers(device, src, dst);
2017 MmUnmapIoSpace(dst, xppdd->config_page_length);
2018 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
2020 if (XenPci_ChangeFrontendState(device, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
2022 // this is definitely an unrecoverable situation...
2023 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
2024 FUNCTION_ERROR_EXIT();
2025 return STATUS_UNSUCCESSFUL;
2027 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RESUMING);
2028 XenPci_Pdo_ChangeSuspendState(device, SR_STATE_RUNNING);
2031 FUNCTION_EXIT();
2033 return STATUS_SUCCESS;
2036 #if 0
2037 NTSTATUS
2038 XenPci_Power_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
2040 NTSTATUS status;
2041 PIO_STACK_LOCATION stack;
2042 POWER_STATE_TYPE power_type;
2043 POWER_STATE power_state;
2044 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
2045 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2047 UNREFERENCED_PARAMETER(device_object);
2049 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
2051 stack = IoGetCurrentIrpStackLocation(irp);
2052 power_type = stack->Parameters.Power.Type;
2053 power_state = stack->Parameters.Power.State;
2055 switch (stack->MinorFunction)
2057 case IRP_MN_POWER_SEQUENCE:
2058 //KdPrint((__DRIVER_NAME " IRP_MN_POWER_SEQUENCE\n"));
2059 status = STATUS_NOT_SUPPORTED;
2060 break;
2061 case IRP_MN_QUERY_POWER:
2062 //KdPrint((__DRIVER_NAME " IRP_MN_QUERY_POWER\n"));
2063 status = STATUS_SUCCESS;
2064 break;
2065 case IRP_MN_SET_POWER:
2066 //KdPrint((__DRIVER_NAME " IRP_MN_SET_POWER\n"));
2067 switch (power_type) {
2068 case DevicePowerState:
2069 PoSetPowerState(device_object, power_type, power_state);
2070 status = STATUS_SUCCESS;
2071 break;
2072 case SystemPowerState:
2073 status = STATUS_SUCCESS;
2074 break;
2075 default:
2076 status = STATUS_NOT_SUPPORTED;
2077 break;
2079 break;
2080 case IRP_MN_WAIT_WAKE:
2081 //KdPrint((__DRIVER_NAME " IRP_MN_WAIT_WAKE\n"));
2082 status = STATUS_NOT_SUPPORTED;
2083 break;
2084 default:
2085 //KdPrint((__DRIVER_NAME " Unknown IRP_MN_%d\n", stack->MinorFunction));
2086 status = STATUS_NOT_SUPPORTED;
2087 break;
2089 if (status != STATUS_NOT_SUPPORTED) {
2090 irp->IoStatus.Status = status;
2093 PoStartNextPowerIrp(irp);
2094 status = irp->IoStatus.Status;
2095 IoCompleteRequest(irp, IO_NO_INCREMENT);
2097 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
2099 return status;
2102 /*
2103 Called at PASSIVE_LEVEL(?)
2104 Called during restore
2105 */
2107 static ULONG
2108 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
2110 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2111 char path[128];
2112 char *value;
2113 char *err;
2114 ULONG backend_state;
2116 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2117 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
2118 if (err)
2120 XenPci_FreeMem(err);
2121 return XenbusStateUnknown;
2123 else
2125 backend_state = atoi(value);
2126 XenPci_FreeMem(value);
2127 return backend_state;
2131 static VOID
2132 XenPci_BackEndStateHandler(char *path, PVOID context)
2134 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)context;
2135 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2136 ULONG new_backend_state;
2138 #if !DBG
2139 UNREFERENCED_PARAMETER(path);
2140 #endif
2142 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
2144 /* check that path == device/id/state */
2145 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
2146 new_backend_state = XenPci_ReadBackendState(xppdd);
2147 if (new_backend_state == XenbusStateUnknown)
2149 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
2150 return;
2151 KdPrint(("Failed to read %s, assuming closed\n", path));
2152 new_backend_state = XenbusStateClosed;
2155 if (xppdd->backend_state == new_backend_state)
2157 KdPrint((__DRIVER_NAME " state unchanged\n"));
2158 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
2159 return;
2162 xppdd->backend_state = new_backend_state;
2164 switch (xppdd->backend_state)
2166 case XenbusStateUnknown:
2167 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown (%s)\n", path));
2168 break;
2170 case XenbusStateInitialising:
2171 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising (%s)\n", path));
2172 break;
2174 case XenbusStateInitWait:
2175 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait (%s)\n", path));
2176 break;
2178 case XenbusStateInitialised:
2179 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised (%s)\n", path));
2180 break;
2182 case XenbusStateConnected:
2183 KdPrint((__DRIVER_NAME " Backend State Changed to Connected (%s)\n", path));
2184 break;
2186 case XenbusStateClosing:
2187 KdPrint((__DRIVER_NAME " Backend State Changed to Closing (%s)\n", path));
2188 if (xpdd->suspend_state == SUSPEND_STATE_NONE)
2190 if (xppdd->common.device_usage_paging
2191 || xppdd->common.device_usage_dump
2192 || xppdd->common.device_usage_hibernation)
2194 KdPrint((__DRIVER_NAME " Not closing device because it is in use\n"));
2195 /* in use by page file, dump file, or hiber file - can't close */
2196 /* we should probably re-check if the device usage changes in the future */
2198 else
2200 if (xppdd->common.current_pnp_state == Started)
2202 KdPrint((__DRIVER_NAME " Sending RequestDeviceEject\n"));
2203 IoRequestDeviceEject(xppdd->common.pdo);
2205 else
2207 KdPrint((__DRIVER_NAME " Not closing device because it is not started\n"));
2211 break;
2213 case XenbusStateClosed:
2214 KdPrint((__DRIVER_NAME " Backend State Changed to Closed (%s)\n", path));
2215 break;
2217 default:
2218 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d (%s)\n", xppdd->backend_state, path));
2219 break;
2222 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
2224 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
2226 return;
2229 struct dummy_sring {
2230 RING_IDX req_prod, req_event;
2231 RING_IDX rsp_prod, rsp_event;
2232 uint8_t pad[48];
2233 };
2235 /*
2236 Called at PASSIVE_LEVEL
2237 Called during restore
2238 */
2240 static NTSTATUS
2241 XenPci_ChangeFrontendState(PXENPCI_PDO_DEVICE_DATA xppdd, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
2243 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2244 LARGE_INTEGER timeout;
2245 ULONG remaining;
2246 ULONG thiswait;
2247 char path[128];
2249 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
2251 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
2252 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
2254 remaining = maximum_wait_ms;
2256 while (xppdd->backend_state != backend_state_response)
2258 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
2259 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
2260 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
2262 remaining -= thiswait;
2263 if (remaining == 0)
2265 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
2266 return STATUS_UNSUCCESSFUL;
2268 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
2271 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
2272 return STATUS_SUCCESS;
2275 static VOID
2276 DUMP_CURRENT_PNP_STATE(PXENPCI_PDO_DEVICE_DATA xppdd)
2278 switch (xppdd->common.current_pnp_state)
2280 case Unknown:
2281 KdPrint((__DRIVER_NAME " pnp_state = Unknown\n"));
2282 break;
2283 case NotStarted:
2284 KdPrint((__DRIVER_NAME " pnp_state = NotStarted\n"));
2285 break;
2286 case Started:
2287 KdPrint((__DRIVER_NAME " pnp_state = Started\n"));
2288 break;
2289 case StopPending:
2290 KdPrint((__DRIVER_NAME " pnp_state = StopPending\n"));
2291 break;
2292 case Stopped:
2293 KdPrint((__DRIVER_NAME " pnp_state = Stopped\n"));
2294 break;
2295 case RemovePending:
2296 KdPrint((__DRIVER_NAME " pnp_state = RemovePending\n"));
2297 break;
2298 case SurpriseRemovePending:
2299 KdPrint((__DRIVER_NAME " pnp_state = SurpriseRemovePending\n"));
2300 break;
2301 case Removed:
2302 KdPrint((__DRIVER_NAME " pnp_state = Removed\n"));
2303 break;
2304 default:
2305 KdPrint((__DRIVER_NAME " pnp_state = ???\n"));
2306 break;
2310 static NTSTATUS
2311 XenPci_EvtChn_Bind(PVOID Context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
2313 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2314 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2316 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext);
2319 static NTSTATUS
2320 XenPci_EvtChn_BindDpc(PVOID Context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
2322 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2323 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2325 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext);
2328 static NTSTATUS
2329 XenPci_EvtChn_Unbind(PVOID Context, evtchn_port_t Port)
2331 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2332 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2334 return EvtChn_Unbind(xpdd, Port);
2337 static NTSTATUS
2338 XenPci_EvtChn_Mask(PVOID Context, evtchn_port_t Port)
2340 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2341 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2343 return EvtChn_Mask(xpdd, Port);
2346 static NTSTATUS
2347 XenPci_EvtChn_Unmask(PVOID Context, evtchn_port_t Port)
2349 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2350 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2352 return EvtChn_Unmask(xpdd, Port);
2355 static NTSTATUS
2356 XenPci_EvtChn_Notify(PVOID Context, evtchn_port_t Port)
2358 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2359 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2361 return EvtChn_Notify(xpdd, Port);
2364 static BOOLEAN
2365 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port)
2367 PXENPCI_PDO_DEVICE_DATA xppdd = context;
2368 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2370 return EvtChn_AckEvent(xpdd, port);
2373 static BOOLEAN
2374 XenPci_EvtChn_Sync(PVOID context, PKSYNCHRONIZE_ROUTINE sync_routine, PVOID sync_context)
2376 PXENPCI_PDO_DEVICE_DATA xppdd = context;
2377 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2379 return KeSynchronizeExecution(xpdd->interrupt, sync_routine, sync_context);
2382 static grant_ref_t
2383 XenPci_GntTbl_GrantAccess(PVOID Context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref)
2385 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2386 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2388 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref);
2391 static BOOLEAN
2392 XenPci_GntTbl_EndAccess(PVOID Context, grant_ref_t ref, BOOLEAN keepref)
2394 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2395 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2397 return GntTbl_EndAccess(xpdd, ref, keepref);
2400 static VOID
2401 XenPci_GntTbl_PutRef(PVOID Context, grant_ref_t ref)
2403 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2404 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2406 GntTbl_PutRef(xpdd, ref);
2409 static grant_ref_t
2410 XenPci_GntTbl_GetRef(PVOID Context)
2412 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2413 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2415 return GntTbl_GetRef(xpdd);
2418 PCHAR
2419 XenPci_XenBus_Read(PVOID Context, xenbus_transaction_t xbt, char *path, char **value)
2421 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2422 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2423 return XenBus_Read(xpdd, xbt, path, value);
2426 PCHAR
2427 XenPci_XenBus_Write(PVOID Context, xenbus_transaction_t xbt, char *path, char *value)
2429 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2430 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2431 return XenBus_Write(xpdd, xbt, path, value);
2434 PCHAR
2435 XenPci_XenBus_Printf(PVOID Context, xenbus_transaction_t xbt, char *path, char *fmt, ...)
2437 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2438 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2439 //return XenBus_Printf(xpdd, xbt, path, value);
2440 UNREFERENCED_PARAMETER(Context);
2441 UNREFERENCED_PARAMETER(xbt);
2442 UNREFERENCED_PARAMETER(path);
2443 UNREFERENCED_PARAMETER(fmt);
2444 return NULL;
2447 PCHAR
2448 XenPci_XenBus_StartTransaction(PVOID Context, xenbus_transaction_t *xbt)
2450 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2451 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2452 return XenBus_StartTransaction(xpdd, xbt);
2455 PCHAR
2456 XenPci_XenBus_EndTransaction(PVOID Context, xenbus_transaction_t xbt, int abort, int *retry)
2458 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2459 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2460 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
2463 PCHAR
2464 XenPci_XenBus_List(PVOID Context, xenbus_transaction_t xbt, char *prefix, char ***contents)
2466 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2467 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2468 return XenBus_List(xpdd, xbt, prefix, contents);
2471 PCHAR
2472 XenPci_XenBus_AddWatch(PVOID Context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
2474 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2475 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2476 PCHAR retval;
2478 FUNCTION_ENTER();
2479 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
2480 if (retval == NULL)
2482 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
2484 else
2486 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
2488 FUNCTION_EXIT();
2489 return retval;
2492 PCHAR
2493 XenPci_XenBus_RemWatch(PVOID Context, xenbus_transaction_t xbt, char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
2495 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2496 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2497 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
2500 static NTSTATUS
2501 XenPci_XenShutdownDevice(PVOID Context)
2503 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
2504 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2505 PUCHAR in_ptr;
2506 ULONG i;
2507 UCHAR type;
2508 PVOID setting;
2509 PVOID value;
2511 FUNCTION_ENTER();
2513 if (xppdd->backend_state == XenbusStateConnected)
2515 XenPci_ChangeFrontendState(xppdd, XenbusStateClosing, XenbusStateClosing, 30000);
2516 if (xppdd->backend_state == XenbusStateClosing)
2517 XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
2518 if (xppdd->backend_state == XenbusStateClosed)
2519 XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
2521 else
2523 if (xppdd->backend_state == XenbusStateClosing)
2524 XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
2527 if (xppdd->assigned_resources_start != NULL)
2529 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
2530 in_ptr = xppdd->assigned_resources_start;
2531 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
2533 switch (type)
2535 case XEN_INIT_TYPE_RING: /* frontend ring */
2536 FreePages(value);
2537 break;
2538 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
2539 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
2540 EvtChn_Unbind(xpdd, PtrToUlong(value));
2541 EvtChn_Close(xpdd, PtrToUlong(value));
2542 break;
2543 case XEN_INIT_TYPE_GRANT_ENTRIES:
2544 for (i = 0; i < PtrToUlong(setting); i++)
2545 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value)[i], FALSE);
2546 break;
2549 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
2550 xppdd->assigned_resources_start = NULL;
2553 FUNCTION_EXIT();
2555 return STATUS_SUCCESS;
2558 static NTSTATUS
2559 XenPci_XenConfigDevice(PVOID context);
2561 static NTSTATUS
2562 XenPci_XenConfigDeviceSpecifyBuffers(PVOID context, PUCHAR src, PUCHAR dst)
2564 PXENPCI_PDO_DEVICE_DATA xppdd = context;
2565 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2566 NTSTATUS status = STATUS_SUCCESS;
2567 ULONG i;
2568 char path[128];
2569 PCHAR setting, value, value2;
2570 PCHAR res;
2571 PVOID address;
2572 UCHAR type;
2573 PUCHAR in_ptr; //, in_start;
2574 PUCHAR out_ptr; //, out_start;
2575 XENPCI_VECTORS vectors;
2576 ULONG event_channel;
2577 ULONG run_type = 0;
2578 PMDL ring;
2579 grant_ref_t gref;
2580 BOOLEAN done_xenbus_init = FALSE;
2582 FUNCTION_ENTER();
2584 in_ptr = src;
2585 out_ptr = dst;
2587 // always add vectors
2588 vectors.magic = XEN_DATA_MAGIC;
2589 vectors.length = sizeof(XENPCI_VECTORS);
2590 vectors.context = xppdd;
2591 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
2592 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
2593 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
2594 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
2595 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
2596 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
2597 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
2598 vectors.EvtChn_Sync = XenPci_EvtChn_Sync;
2599 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
2600 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
2601 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
2602 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
2603 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
2604 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
2605 strncpy(vectors.path, xppdd->path, 128);
2606 strncpy(vectors.backend_path, xppdd->backend_path, 128);
2607 vectors.pdo_event_channel = xpdd->pdo_event_channel;
2608 vectors.XenBus_Read = XenPci_XenBus_Read;
2609 vectors.XenBus_Write = XenPci_XenBus_Write;
2610 vectors.XenBus_Printf = XenPci_XenBus_Printf;
2611 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
2612 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
2613 vectors.XenBus_List = XenPci_XenBus_List;
2614 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
2615 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
2617 if (qemu_filtered)
2618 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_ACTIVE, NULL, NULL, NULL);
2620 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version), NULL);
2622 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors, NULL);
2623 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state, NULL);
2625 // first pass, possibly before state == Connected
2626 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
2629 if (!done_xenbus_init)
2631 if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
2633 status = STATUS_UNSUCCESSFUL;
2634 goto error;
2636 done_xenbus_init = TRUE;
2639 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value, value2);
2641 switch (type)
2643 case XEN_INIT_TYPE_RUN:
2644 run_type++;
2645 break;
2646 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
2647 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
2648 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
2649 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
2650 break;
2651 case XEN_INIT_TYPE_RING: /* frontend ring */
2652 /* we only allocate and do the SHARED_RING_INIT here */
2653 if ((ring = AllocatePage()) != 0)
2655 address = MmGetMdlVirtualAddress(ring);
2656 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
2657 SHARED_RING_INIT((struct dummy_sring *)address);
2658 if ((gref = GntTbl_GrantAccess(
2659 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
2661 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
2662 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
2663 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address, NULL);
2664 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring, NULL);
2665 // add the grant entry too so it gets freed automatically
2666 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
2667 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
2668 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
2670 else
2672 FreePages(ring);
2673 status = STATUS_UNSUCCESSFUL;
2674 goto error;
2677 else
2679 status = STATUS_UNSUCCESSFUL;
2680 goto error;
2682 break;
2683 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
2684 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
2685 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
2687 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
2688 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
2689 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
2690 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel), NULL);
2691 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel), NULL);
2692 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
2693 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
2695 else
2697 status = STATUS_UNSUCCESSFUL;
2698 goto error;
2700 break;
2703 if (!NT_SUCCESS(status))
2705 goto error;
2707 // If XEN_INIT_TYPE_RUN was specified more than once then we skip XenbusStateInitialised here and go straight to XenbusStateConnected at the end
2708 if (run_type == 1)
2710 if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialised, XenbusStateConnected, 30000) != STATUS_SUCCESS)
2712 status = STATUS_UNSUCCESSFUL;
2713 goto error;
2717 // second pass, possibly after state == Connected
2718 in_ptr = src;
2719 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
2721 switch(type)
2723 case XEN_INIT_TYPE_READ_STRING_BACK:
2724 case XEN_INIT_TYPE_READ_STRING_FRONT:
2725 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
2726 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
2727 else
2728 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
2729 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
2730 if (res)
2732 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
2733 XenPci_FreeMem(res);
2734 ADD_XEN_INIT_RSP(&out_ptr, type, setting, NULL, NULL);
2736 else
2738 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
2739 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value, NULL);
2740 XenPci_FreeMem(value);
2742 break;
2743 case XEN_INIT_TYPE_VECTORS:
2744 // this is always done so ignore the request
2745 break;
2746 case XEN_INIT_TYPE_GRANT_ENTRIES:
2747 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
2748 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
2749 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
2750 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
2751 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
2752 for (i = 0; i < PtrToUlong(value); i++)
2754 gref = GntTbl_GetRef(xpdd);
2755 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
2756 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
2758 break;
2761 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL);
2763 if (run_type)
2765 if (XenPci_ChangeFrontendState(xppdd, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
2767 status = STATUS_UNSUCCESSFUL;
2768 goto error;
2771 FUNCTION_EXIT();
2772 return status;
2774 error:
2775 XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
2776 FUNCTION_EXIT_STATUS(status);
2778 return status;
2781 static NTSTATUS
2782 XenPci_XenConfigDevice(PVOID context)
2784 NTSTATUS status;
2785 PUCHAR src, dst;
2786 PXENPCI_PDO_DEVICE_DATA xppdd = context;
2788 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
2789 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
2790 memcpy(src, dst, xppdd->config_page_length);
2792 status = XenPci_XenConfigDeviceSpecifyBuffers(xppdd, src, dst);
2794 MmUnmapIoSpace(dst, xppdd->config_page_length);
2795 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
2797 return status;
2800 static NTSTATUS
2801 XenPci_GetBackendAndAddWatch(PDEVICE_OBJECT device_object)
2803 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
2804 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2805 char path[128];
2806 PCHAR res;
2807 PCHAR value;
2809 /* Get backend path */
2810 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
2811 "%s/backend", xppdd->path);
2812 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
2813 if (res)
2815 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
2816 XenPci_FreeMem(res);
2817 return STATUS_UNSUCCESSFUL;
2819 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
2820 XenPci_FreeMem(value);
2822 /* Add watch on backend state */
2823 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2824 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
2826 return STATUS_SUCCESS;
2829 NTSTATUS
2830 XenPci_Pdo_Resume(PDEVICE_OBJECT device_object)
2832 NTSTATUS status;
2833 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
2834 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2835 ULONG old_backend_state;
2836 PUCHAR src, dst;
2838 FUNCTION_ENTER();
2840 old_backend_state = xppdd->backend_state;
2842 if (xppdd->restart_on_resume)
2844 status = XenPci_GetBackendAndAddWatch(device_object);
2846 if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
2848 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
2849 // this is probably an unrecoverable situation...
2850 FUNCTION_ERROR_EXIT();
2851 return STATUS_UNSUCCESSFUL;
2853 if (xppdd->assigned_resources_ptr)
2855 // reset things - feed the 'requested resources' back in
2856 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL);
2857 src = xppdd->requested_resources_start;
2858 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
2859 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
2861 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
2863 status = XenPci_XenConfigDeviceSpecifyBuffers(xppdd, src, dst);
2865 MmUnmapIoSpace(dst, xppdd->config_page_length);
2866 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
2868 if (XenPci_ChangeFrontendState(xppdd, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
2870 // this is definitely an unrecoverable situation...
2871 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
2872 FUNCTION_ERROR_EXIT();
2873 return STATUS_UNSUCCESSFUL;
2876 else
2878 KdPrint((__DRIVER_NAME " Not resuming - current_pnp_state = %d, old_backend_state = %d\n", xppdd->common.current_pnp_state, old_backend_state));
2880 KeMemoryBarrier();
2881 xppdd->device_state.resume_state = RESUME_STATE_FRONTEND_RESUME;
2882 KeMemoryBarrier();
2883 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
2885 FUNCTION_EXIT();
2887 return STATUS_SUCCESS;
2890 /* called at PASSIVE_LEVEL */
2891 NTSTATUS
2892 XenPci_Pdo_Suspend(PDEVICE_OBJECT device_object)
2894 NTSTATUS status = STATUS_SUCCESS;
2895 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
2896 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2897 LARGE_INTEGER wait_time;
2898 char path[128];
2899 PUCHAR in_ptr;
2900 UCHAR type;
2901 PVOID setting;
2902 PVOID value;
2904 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
2906 if (xppdd->backend_state == XenbusStateConnected)
2908 xppdd->restart_on_resume = TRUE;
2909 xppdd->device_state.resume_state_ack = RESUME_STATE_RUNNING;
2910 KeMemoryBarrier();
2911 xppdd->device_state.resume_state = RESUME_STATE_SUSPENDING;
2912 KeMemoryBarrier();
2913 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
2914 while(xppdd->device_state.resume_state_ack != RESUME_STATE_SUSPENDING)
2916 KdPrint((__DRIVER_NAME " Starting delay - resume_state = %d, resume_state_ack = %d\n", xppdd->device_state.resume_state, xppdd->device_state.resume_state_ack));
2917 wait_time.QuadPart = 100 * (-1 * 10 * 1000);
2918 KeDelayExecutionThread(KernelMode, FALSE, &wait_time);
2919 KdPrint((__DRIVER_NAME " Done with delay\n"));
2921 KdPrint((__DRIVER_NAME " resume_state acknowledged\n"));
2923 XenPci_ChangeFrontendState(xppdd, XenbusStateClosing, XenbusStateClosing, 30000);
2924 XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
2925 XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
2927 if (xppdd->assigned_resources_start != NULL)
2929 in_ptr = xppdd->assigned_resources_ptr;
2930 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL);
2931 in_ptr = xppdd->assigned_resources_start;
2932 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value)) != XEN_INIT_TYPE_END)
2934 switch (type)
2936 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
2937 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
2938 EvtChn_Close(xpdd, PtrToUlong(value));
2939 break;
2944 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
2945 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
2947 else
2949 xppdd->restart_on_resume = FALSE;
2952 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
2954 return status;
2957 VOID
2958 XenPci_DumpPdoConfig(PDEVICE_OBJECT device_object)
2960 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
2962 #if !DBG
2963 UNREFERENCED_PARAMETER(xppdd);
2964 #endif
2966 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
2967 KdPrint((__DRIVER_NAME " backend_path = %s\n", xppdd->backend_path));
2968 KdPrint((__DRIVER_NAME " irq_number = %d\n", xppdd->irq_number));
2969 KdPrint((__DRIVER_NAME " irq_level = %d\n", xppdd->irq_level));
2970 KdPrint((__DRIVER_NAME " irq_vector = %x\n", xppdd->irq_vector));
2973 static PMDL
2974 XenConfig_MakeConfigPage(PDEVICE_OBJECT device_object)
2976 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
2977 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
2978 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
2979 PMDL mdl;
2980 PUCHAR ptr;
2981 PDEVICE_OBJECT curr, prev;
2982 PDRIVER_OBJECT fdo_driver_object;
2983 PUCHAR fdo_driver_extension;
2985 mdl = AllocateUncachedPage();
2986 ptr = MmGetMdlVirtualAddress(mdl);
2987 curr = IoGetAttachedDeviceReference(device_object);
2988 while (curr != NULL)
2990 fdo_driver_object = curr->DriverObject;
2991 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
2992 if (fdo_driver_object)
2994 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
2995 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
2996 if (fdo_driver_extension)
2998 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
2999 ObDereferenceObject(curr);
3000 break;
3003 prev = curr;
3004 curr = IoGetLowerDeviceObject(curr);
3005 ObDereferenceObject(prev);
3007 return mdl;
3010 static NTSTATUS
3011 XenPci_Pnp_StartDevice(PDEVICE_OBJECT device_object, PIRP irp)
3013 NTSTATUS status = STATUS_SUCCESS;
3014 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3015 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
3016 PIO_STACK_LOCATION stack;
3017 PCM_PARTIAL_RESOURCE_LIST prl;
3018 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
3019 ULONG i;
3020 char path[128];
3021 PMDL mdl;
3023 FUNCTION_ENTER();
3024 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
3026 DUMP_CURRENT_PNP_STATE(xppdd);
3028 stack = IoGetCurrentIrpStackLocation(irp);
3030 status = XenPci_GetBackendAndAddWatch(device_object);
3031 if (!NT_SUCCESS(status)) {
3032 FUNCTION_ERROR_EXIT();
3033 return status;
3036 mdl = XenConfig_MakeConfigPage(device_object);
3038 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
3039 for (i = 0; i < prl->Count; i++)
3041 prd = & prl->PartialDescriptors[i];
3042 switch (prd->Type)
3044 #if 0
3045 case CmResourceTypeInterrupt:
3046 KdPrint((__DRIVER_NAME " CmResourceTypeInterrupt\n"));
3047 KdPrint((__DRIVER_NAME " irq_number = %02x\n", prd->u.Interrupt.Vector));
3048 xppdd->irq_number = prd->u.Interrupt.Vector;
3049 break;
3050 #endif
3051 case CmResourceTypeMemory:
3052 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
3054 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
3055 prd->u.Memory.Length = MmGetMdlByteCount(mdl);
3057 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
3059 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
3060 prd->Type = CmResourceTypeInterrupt;
3061 prd->ShareDisposition = CmResourceShareShared;
3062 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
3063 prd->u.Interrupt.Level = xpdd->irq_number;
3064 prd->u.Interrupt.Vector = xpdd->irq_number;
3065 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
3066 xppdd->irq_number = xpdd->irq_number;
3068 break;
3072 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
3073 for (i = 0; i < prl->Count; i++)
3075 prd = & prl->PartialDescriptors[i];
3076 switch (prd->Type)
3078 #if 0
3079 case CmResourceTypeInterrupt:
3080 KdPrint((__DRIVER_NAME " CmResourceTypeInterrupt (%d)\n", i));
3081 KdPrint((__DRIVER_NAME " irq_vector = %02x\n", prd->u.Interrupt.Vector));
3082 KdPrint((__DRIVER_NAME " irq_level = %d\n", prd->u.Interrupt.Level));
3083 xppdd->irq_vector = prd->u.Interrupt.Vector;
3084 xppdd->irq_level = (KIRQL)prd->u.Interrupt.Level;
3085 break;
3086 #endif
3087 case CmResourceTypeMemory:
3088 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
3089 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
3090 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
3092 if (prd->u.Memory.Length == 0)
3094 KdPrint((__DRIVER_NAME " pfn[0] = %08x\n", (ULONG)MmGetMdlPfnArray(mdl)[0]));
3095 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
3096 prd->u.Memory.Length = MmGetMdlByteCount(mdl);
3097 KdPrint((__DRIVER_NAME " New Start = %08x%08x, Length = %d\n", prd->u.Memory.Start.HighPart, prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
3099 xppdd->config_page_phys = prd->u.Memory.Start;
3100 xppdd->config_page_length = prd->u.Memory.Length;
3101 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
3102 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
3104 status = XenPci_XenConfigDevice(xppdd);
3105 if (!NT_SUCCESS(status))
3107 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
3108 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
3109 FUNCTION_ERROR_EXIT();
3110 return status;
3113 else if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart + 1 && prd->u.Memory.Length == 0)
3115 RtlZeroMemory(prd, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
3116 prd->Type = CmResourceTypeInterrupt;
3117 prd->ShareDisposition = CmResourceShareShared;
3118 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
3119 prd->u.Interrupt.Level = xpdd->irq_level;
3120 prd->u.Interrupt.Vector = xpdd->irq_vector;
3121 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
3122 xppdd->irq_vector = xpdd->irq_vector;
3123 xppdd->irq_level = xpdd->irq_level;
3125 break;
3129 SET_PNP_STATE(&xppdd->common, Started);
3131 FUNCTION_EXIT();
3133 return STATUS_SUCCESS;
3136 static NTSTATUS
3137 XenPci_Pnp_RemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
3139 NTSTATUS status = STATUS_SUCCESS;
3140 PXENPCI_PDO_DEVICE_DATA xppdd = device_object->DeviceExtension;
3141 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
3142 char path[128];
3144 UNREFERENCED_PARAMETER(irp);
3146 FUNCTION_ENTER();
3148 DUMP_CURRENT_PNP_STATE(xppdd);
3150 if (xppdd->common.current_pnp_state != Removed)
3152 status = XenPci_XenShutdownDevice(xppdd);
3153 /* Remove watch on backend state */
3154 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
3155 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
3156 SET_PNP_STATE(&xppdd->common, Removed);
3157 IoInvalidateDeviceRelations(xppdd->bus_pdo, BusRelations);
3159 if (xppdd->reported_missing)
3161 IoDeleteDevice(xppdd->common.pdo);
3164 FUNCTION_EXIT_STATUS(status);
3166 return status;
3169 static NTSTATUS
3170 XenPci_QueryResourceRequirements(PDEVICE_OBJECT device_object, PIRP irp)
3172 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3173 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
3174 PIO_RESOURCE_REQUIREMENTS_LIST irrl;
3175 PIO_RESOURCE_DESCRIPTOR ird;
3176 ULONG length;
3178 UNREFERENCED_PARAMETER(device_object);
3180 FUNCTION_ENTER();
3182 length = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List) +
3183 FIELD_OFFSET(IO_RESOURCE_LIST, Descriptors) +
3184 sizeof(IO_RESOURCE_DESCRIPTOR) * 2;
3185 irrl = ExAllocatePoolWithTag(NonPagedPool,
3186 length,
3187 XENPCI_POOL_TAG);
3189 irrl->ListSize = length;
3190 irrl->InterfaceType = PNPBus; //Internal;
3191 irrl->BusNumber = 0;
3192 irrl->SlotNumber = 0;
3193 irrl->AlternativeLists = 1;
3194 irrl->List[0].Version = 1;
3195 irrl->List[0].Revision = 1;
3196 irrl->List[0].Count = 0;
3198 #if 0
3199 ird = &irrl->List[0].Descriptors[irrl->List[0].Count++];
3200 ird->Option = 0;
3201 ird->Type = CmResourceTypeInterrupt;
3202 ird->ShareDisposition = CmResourceShareShared;
3203 ird->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
3204 KdPrint((__DRIVER_NAME " irq type = %s\n", (xpdd->irq_mode == Latched)?"Latched":"Level"));
3205 ird->u.Interrupt.MinimumVector = xpdd->irq_number;
3206 ird->u.Interrupt.MaximumVector = xpdd->irq_number;
3207 #endif
3209 ird = &irrl->List[0].Descriptors[irrl->List[0].Count++];
3210 ird->Option = 0;
3211 ird->Type = CmResourceTypeMemory;
3212 ird->ShareDisposition = CmResourceShareShared;
3213 ird->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
3214 ird->u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
3215 ird->u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart;
3216 ird->u.Memory.Length = 0;
3217 ird->u.Memory.Alignment = PAGE_SIZE;
3219 ird = &irrl->List[0].Descriptors[irrl->List[0].Count++];
3220 ird->Option = 0;
3221 ird->Type = CmResourceTypeMemory;
3222 ird->ShareDisposition = CmResourceShareShared;
3223 ird->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
3224 ird->u.Memory.MinimumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
3225 ird->u.Memory.MaximumAddress.QuadPart = xpdd->platform_mmio_addr.QuadPart + 1;
3226 ird->u.Memory.Length = 0;
3227 ird->u.Memory.Alignment = PAGE_SIZE;
3229 irp->IoStatus.Information = (ULONG_PTR)irrl;
3231 FUNCTION_EXIT();
3233 return STATUS_SUCCESS;
3236 static NTSTATUS
3237 XenPci_Pnp_QueryTargetRelations(PDEVICE_OBJECT device_object, PIRP irp)
3239 PDEVICE_RELATIONS dr;
3240 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3242 dr = (PDEVICE_RELATIONS)ExAllocatePoolWithTag (PagedPool, sizeof(DEVICE_RELATIONS), XENPCI_POOL_TAG);
3243 dr->Count = 1;
3244 dr->Objects[0] = xppdd->common.pdo;
3245 ObReferenceObject(xppdd->common.pdo);
3246 irp->IoStatus.Information = (ULONG_PTR)dr;
3248 return STATUS_SUCCESS;
3251 static NTSTATUS
3252 XenPci_Pnp_QueryCapabilities(PDEVICE_OBJECT device_object, PIRP irp)
3254 PIO_STACK_LOCATION stack;
3255 PDEVICE_CAPABILITIES dc;
3257 UNREFERENCED_PARAMETER(device_object);
3259 stack = IoGetCurrentIrpStackLocation(irp);
3260 dc = stack->Parameters.DeviceCapabilities.Capabilities;
3261 dc->LockSupported = FALSE;
3262 dc->EjectSupported = TRUE;
3263 dc->Removable = TRUE;
3264 dc->DockDevice = FALSE;
3265 dc->UniqueID = FALSE;
3266 dc->SilentInstall = TRUE; //FALSE;
3267 dc->RawDeviceOK = FALSE;
3268 dc->SurpriseRemovalOK = TRUE;
3269 dc->HardwareDisabled = FALSE;
3270 dc->NoDisplayInUI = FALSE;
3271 dc->DeviceWake = PowerDeviceUnspecified;
3272 dc->D1Latency = 0;
3273 dc->D2Latency = 0;
3274 dc->D3Latency = 0;
3275 /* we are really supposed to get the DeviceState entries from the parent... */
3276 dc->DeviceState[PowerSystemWorking] = PowerDeviceD0;
3277 dc->DeviceState[PowerSystemSleeping1] = PowerDeviceUnspecified;
3278 dc->DeviceState[PowerSystemSleeping2] = PowerDeviceUnspecified;
3279 dc->DeviceState[PowerSystemSleeping3] = PowerDeviceUnspecified;
3280 dc->DeviceState[PowerSystemHibernate] = PowerDeviceD3;
3281 dc->DeviceState[PowerSystemShutdown] = PowerDeviceD3;
3282 return STATUS_SUCCESS;
3285 static VOID
3286 XenPci_IS_InterfaceReference(PVOID context)
3288 UNREFERENCED_PARAMETER(context);
3289 FUNCTION_ENTER();
3290 FUNCTION_EXIT();
3293 static VOID
3294 XenPci_IS_InterfaceDereference(PVOID context)
3296 UNREFERENCED_PARAMETER(context);
3297 FUNCTION_ENTER();
3298 FUNCTION_EXIT();
3301 static BOOLEAN
3302 XenPci_BIS_TranslateBusAddress(PVOID context, PHYSICAL_ADDRESS bus_address, ULONG length, PULONG address_space, PPHYSICAL_ADDRESS translated_address)
3304 UNREFERENCED_PARAMETER(context);
3305 UNREFERENCED_PARAMETER(length);
3306 /* actually this isn't right - should look up the gref for the physical address and work backwards from that */
3307 FUNCTION_ENTER();
3308 if (*address_space != 0)
3310 KdPrint((__DRIVER_NAME " Cannot map I/O space\n"));
3311 FUNCTION_EXIT();
3312 return FALSE;
3314 *translated_address = bus_address;
3315 FUNCTION_EXIT();
3316 return TRUE;
3319 static VOID
3320 XenPci_DOP_PutDmaAdapter(PDMA_ADAPTER dma_adapter)
3322 UNREFERENCED_PARAMETER(dma_adapter);
3324 FUNCTION_ENTER();
3325 // decrement ref count
3326 FUNCTION_EXIT();
3328 return;
3331 static PVOID
3332 XenPci_DOP_AllocateCommonBuffer(
3333 PDMA_ADAPTER DmaAdapter,
3334 ULONG Length,
3335 PPHYSICAL_ADDRESS LogicalAddress,
3336 BOOLEAN CacheEnabled
3339 xen_dma_adapter_t *xen_dma_adapter;
3340 PXENPCI_DEVICE_DATA xpdd;
3341 PVOID buffer;
3342 PFN_NUMBER pfn;
3343 grant_ref_t gref;
3345 UNREFERENCED_PARAMETER(DmaAdapter);
3346 UNREFERENCED_PARAMETER(CacheEnabled);
3348 //FUNCTION_ENTER();
3350 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
3351 xpdd = xen_dma_adapter->xppdd->bus_fdo->DeviceExtension;
3353 //KdPrint((__DRIVER_NAME " Length = %d\n", Length));
3355 buffer = ExAllocatePoolWithTag(NonPagedPool, Length, XENPCI_POOL_TAG);
3357 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(buffer).QuadPart >> PAGE_SHIFT);
3358 ASSERT(pfn);
3359 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, pfn, FALSE, INVALID_GRANT_REF);
3360 ASSERT(gref);
3361 LogicalAddress->QuadPart = (gref << PAGE_SHIFT) | (PtrToUlong(buffer) & (PAGE_SIZE - 1));
3363 //FUNCTION_EXIT();
3364 return buffer;
3367 static VOID
3368 XenPci_DOP_FreeCommonBuffer(
3369 PDMA_ADAPTER DmaAdapter,
3370 ULONG Length,
3371 PHYSICAL_ADDRESS LogicalAddress,
3372 PVOID VirtualAddress,
3373 BOOLEAN CacheEnabled
3376 UNREFERENCED_PARAMETER(DmaAdapter);
3377 UNREFERENCED_PARAMETER(Length);
3378 UNREFERENCED_PARAMETER(LogicalAddress);
3379 UNREFERENCED_PARAMETER(CacheEnabled);
3381 FUNCTION_ENTER();
3382 ExFreePoolWithTag(VirtualAddress, XENPCI_POOL_TAG);
3383 // TODO: free the grant ref here
3384 FUNCTION_EXIT();
3387 static NTSTATUS
3388 XenPci_DOP_AllocateAdapterChannel(
3389 IN PDMA_ADAPTER DmaAdapter,
3390 IN PDEVICE_OBJECT DeviceObject,
3391 IN ULONG NumberOfMapRegisters,
3392 IN PDRIVER_CONTROL ExecutionRoutine,
3393 IN PVOID Context
3396 IO_ALLOCATION_ACTION action;
3398 UNREFERENCED_PARAMETER(DmaAdapter);
3399 UNREFERENCED_PARAMETER(NumberOfMapRegisters);
3401 FUNCTION_ENTER();
3402 action = ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, UlongToPtr(64), Context);
3404 switch (action)
3406 case KeepObject:
3407 KdPrint((__DRIVER_NAME " KeepObject\n"));
3408 break;
3409 case DeallocateObject:
3410 KdPrint((__DRIVER_NAME " DeallocateObject\n"));
3411 break;
3412 case DeallocateObjectKeepRegisters:
3413 KdPrint((__DRIVER_NAME " DeallocateObjectKeepRegisters\n"));
3414 break;
3415 default:
3416 KdPrint((__DRIVER_NAME " Unknown action %d\n", action));
3417 break;
3419 FUNCTION_EXIT();
3420 return STATUS_SUCCESS;
3423 static BOOLEAN
3424 XenPci_DOP_FlushAdapterBuffers(
3425 PDMA_ADAPTER DmaAdapter,
3426 PMDL Mdl,
3427 PVOID MapRegisterBase,
3428 PVOID CurrentVa,
3429 ULONG Length,
3430 BOOLEAN WriteToDevice)
3432 UNREFERENCED_PARAMETER(DmaAdapter);
3433 UNREFERENCED_PARAMETER( Mdl);
3434 UNREFERENCED_PARAMETER(MapRegisterBase);
3435 UNREFERENCED_PARAMETER(CurrentVa);
3436 UNREFERENCED_PARAMETER(Length);
3437 UNREFERENCED_PARAMETER(WriteToDevice);
3439 FUNCTION_ENTER();
3440 FUNCTION_EXIT();
3441 return TRUE;
3444 static VOID
3445 XenPci_DOP_FreeAdapterChannel(
3446 IN PDMA_ADAPTER DmaAdapter
3449 UNREFERENCED_PARAMETER(DmaAdapter);
3451 FUNCTION_ENTER();
3452 FUNCTION_EXIT();
3455 static VOID
3456 XenPci_DOP_FreeMapRegisters(
3457 PDMA_ADAPTER DmaAdapter,
3458 PVOID MapRegisterBase,
3459 ULONG NumberOfMapRegisters)
3461 UNREFERENCED_PARAMETER(DmaAdapter);
3462 UNREFERENCED_PARAMETER(MapRegisterBase);
3463 UNREFERENCED_PARAMETER(NumberOfMapRegisters);
3465 FUNCTION_ENTER();
3466 FUNCTION_EXIT();
3469 static PHYSICAL_ADDRESS
3470 XenPci_DOP_MapTransfer(
3471 PDMA_ADAPTER DmaAdapter,
3472 PMDL Mdl,
3473 PVOID MapRegisterBase,
3474 PVOID CurrentVa,
3475 PULONG Length,
3476 BOOLEAN WriteToDevice)
3478 PHYSICAL_ADDRESS physical;
3480 UNREFERENCED_PARAMETER(DmaAdapter);
3481 UNREFERENCED_PARAMETER(Mdl);
3482 UNREFERENCED_PARAMETER(MapRegisterBase);
3483 UNREFERENCED_PARAMETER(CurrentVa);
3484 UNREFERENCED_PARAMETER(Length);
3485 UNREFERENCED_PARAMETER(WriteToDevice);
3487 FUNCTION_ENTER();
3489 physical.QuadPart = 0;
3491 FUNCTION_EXIT();
3492 return physical;
3495 static ULONG
3496 XenPci_DOP_GetDmaAlignment(
3497 PDMA_ADAPTER DmaAdapter)
3499 UNREFERENCED_PARAMETER(DmaAdapter);
3501 FUNCTION_ENTER();
3502 FUNCTION_EXIT();
3503 return 0;
3506 static ULONG
3507 XenPci_DOP_ReadDmaCounter(
3508 PDMA_ADAPTER DmaAdapter)
3510 UNREFERENCED_PARAMETER(DmaAdapter);
3512 FUNCTION_ENTER();
3513 FUNCTION_EXIT();
3514 return 0;
3517 static NTSTATUS
3518 XenPci_DOP_GetScatterGatherList(
3519 PDMA_ADAPTER DmaAdapter,
3520 PDEVICE_OBJECT DeviceObject,
3521 PMDL Mdl,
3522 PVOID CurrentVa,
3523 ULONG Length,
3524 PDRIVER_LIST_CONTROL ExecutionRoutine,
3525 PVOID Context,
3526 BOOLEAN WriteToDevice)
3528 UNREFERENCED_PARAMETER(DmaAdapter);
3529 UNREFERENCED_PARAMETER(DeviceObject);
3530 UNREFERENCED_PARAMETER(Mdl);
3531 UNREFERENCED_PARAMETER(CurrentVa);
3532 UNREFERENCED_PARAMETER(Length);
3533 UNREFERENCED_PARAMETER(ExecutionRoutine);
3534 UNREFERENCED_PARAMETER(Context);
3535 UNREFERENCED_PARAMETER(WriteToDevice);
3537 FUNCTION_ENTER();
3538 FUNCTION_EXIT();
3539 return STATUS_SUCCESS;
3542 #define MAP_TYPE_VIRTUAL 1
3543 #define MAP_TYPE_MDL 2
3544 #define MAP_TYPE_REMAPPED 3
3546 typedef struct {
3547 ULONG map_type;
3548 PVOID aligned_buffer;
3549 PVOID unaligned_buffer;
3550 ULONG copy_length;
3551 } sg_extra_t;
3553 static VOID
3554 XenPci_DOP_PutScatterGatherList(
3555 IN PDMA_ADAPTER DmaAdapter,
3556 IN PSCATTER_GATHER_LIST ScatterGather,
3557 IN BOOLEAN WriteToDevice
3560 xen_dma_adapter_t *xen_dma_adapter;
3561 PXENPCI_DEVICE_DATA xpdd;
3562 ULONG i;
3563 sg_extra_t *sg_extra;
3565 UNREFERENCED_PARAMETER(WriteToDevice);
3567 //FUNCTION_ENTER();
3569 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
3570 xpdd = xen_dma_adapter->xppdd->bus_fdo->DeviceExtension;
3572 sg_extra = (sg_extra_t *)((PUCHAR)ScatterGather + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
3573 (sizeof(SCATTER_GATHER_ELEMENT)) * ScatterGather->NumberOfElements);
3575 switch (sg_extra->map_type)
3577 case MAP_TYPE_REMAPPED:
3578 for (i = 0; i < ScatterGather->NumberOfElements; i++)
3580 grant_ref_t gref;
3581 gref = (grant_ref_t)(ScatterGather->Elements[i].Address.QuadPart >> PAGE_SHIFT);
3582 GntTbl_EndAccess(xpdd, gref, FALSE);
3583 ScatterGather->Elements[i].Address.QuadPart = -1;
3585 if (!WriteToDevice)
3586 memcpy(sg_extra->unaligned_buffer, sg_extra->aligned_buffer, sg_extra->copy_length);
3587 ExFreePoolWithTag(sg_extra->aligned_buffer, XENPCI_POOL_TAG);
3588 break;
3589 case MAP_TYPE_MDL:
3590 for (i = 0; i < ScatterGather->NumberOfElements; i++)
3592 grant_ref_t gref;
3593 gref = (grant_ref_t)(ScatterGather->Elements[i].Address.QuadPart >> PAGE_SHIFT);
3594 GntTbl_EndAccess(xpdd, gref, FALSE);
3595 ScatterGather->Elements[i].Address.QuadPart = -1;
3597 break;
3598 case MAP_TYPE_VIRTUAL:
3599 break;
3601 //FUNCTION_EXIT();
3604 static NTSTATUS
3605 XenPci_DOP_CalculateScatterGatherList(
3606 PDMA_ADAPTER DmaAdapter,
3607 PMDL Mdl,
3608 PVOID CurrentVa,
3609 ULONG Length,
3610 PULONG ScatterGatherListSize,
3611 PULONG NumberOfMapRegisters
3614 ULONG elements;
3615 PMDL curr_mdl;
3617 UNREFERENCED_PARAMETER(DmaAdapter);
3618 UNREFERENCED_PARAMETER(Mdl);
3620 FUNCTION_ENTER();
3622 KdPrint((__DRIVER_NAME " Mdl = %p\n", Mdl));
3623 KdPrint((__DRIVER_NAME " CurrentVa = %p\n", CurrentVa));
3624 KdPrint((__DRIVER_NAME " Length = %d\n", Length));
3625 if (Mdl)
3627 for (curr_mdl = Mdl, elements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
3628 elements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(CurrentVa, Length);
3630 else
3632 elements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, Length) + 1;
3635 *ScatterGatherListSize = FIELD_OFFSET(SCATTER_GATHER_LIST, Elements)
3636 + sizeof(SCATTER_GATHER_ELEMENT) * elements
3637 + sizeof(sg_extra_t);
3638 if (NumberOfMapRegisters)
3639 *NumberOfMapRegisters = 1;
3641 KdPrint((__DRIVER_NAME " ScatterGatherListSize = %d\n", *ScatterGatherListSize));
3643 FUNCTION_EXIT();
3644 return STATUS_SUCCESS;
3647 static NTSTATUS
3648 XenPci_DOP_BuildScatterGatherList(
3649 IN PDMA_ADAPTER DmaAdapter,
3650 IN PDEVICE_OBJECT DeviceObject,
3651 IN PMDL Mdl,
3652 IN PVOID CurrentVa,
3653 IN ULONG Length,
3654 IN PDRIVER_LIST_CONTROL ExecutionRoutine,
3655 IN PVOID Context,
3656 IN BOOLEAN WriteToDevice,
3657 IN PVOID ScatterGatherBuffer,
3658 IN ULONG ScatterGatherBufferLength)
3660 ULONG i;
3661 PSCATTER_GATHER_LIST sglist = ScatterGatherBuffer;
3662 PUCHAR ptr;
3663 ULONG remaining = Length;
3664 ULONG total_remaining;
3665 xen_dma_adapter_t *xen_dma_adapter;
3666 PXENPCI_DEVICE_DATA xpdd;
3667 sg_extra_t *sg_extra;
3668 PMDL curr_mdl;
3669 ULONG map_type;
3670 ULONG sg_element;
3671 ULONG offset;
3672 PFN_NUMBER pfn;
3673 grant_ref_t gref;
3675 UNREFERENCED_PARAMETER(WriteToDevice);
3677 //FUNCTION_ENTER();
3679 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
3680 xpdd = xen_dma_adapter->xppdd->bus_fdo->DeviceExtension;
3682 ASSERT(Mdl);
3683 if (xen_dma_adapter->dma_extension)
3685 if (xen_dma_adapter->dma_extension->need_virtual_address(DeviceObject->CurrentIrp))
3687 ASSERT(!Mdl->Next); /* can only virtual a single buffer */
3688 map_type = MAP_TYPE_VIRTUAL;
3689 sglist->NumberOfElements = 1;
3691 else
3693 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(DeviceObject->CurrentIrp);
3694 if (PtrToUlong(CurrentVa) & (alignment - 1))
3696 ASSERT(!Mdl->Next); /* can only remap a single buffer */
3697 map_type = MAP_TYPE_REMAPPED;
3698 sglist->NumberOfElements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(NULL, Length);
3700 else
3702 map_type = MAP_TYPE_MDL;
3703 for (curr_mdl = Mdl, sglist->NumberOfElements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
3704 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
3705 MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
3709 else
3711 map_type = MAP_TYPE_MDL;
3712 for (curr_mdl = Mdl, sglist->NumberOfElements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
3713 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
3714 MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
3716 if (ScatterGatherBufferLength < FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
3717 sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t))
3719 return STATUS_BUFFER_TOO_SMALL;
3722 sg_extra = (sg_extra_t *)((PUCHAR)sglist + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
3723 (sizeof(SCATTER_GATHER_ELEMENT)) * sglist->NumberOfElements);
3725 sg_extra->map_type = map_type;
3726 switch (map_type)
3728 case MAP_TYPE_MDL:
3729 KdPrint((__DRIVER_NAME " MAP_TYPE_MDL - %p\n", CurrentVa));
3730 total_remaining = Length;
3731 for (sg_element = 0, curr_mdl = Mdl; curr_mdl; curr_mdl = curr_mdl->Next)
3733 remaining = MmGetMdlByteCount(curr_mdl);
3734 if (!MmGetMdlByteOffset(Mdl) && (PtrToUlong(CurrentVa) & (PAGE_SIZE - 1)))
3735 offset = (PtrToUlong(CurrentVa) & (PAGE_SIZE - 1));
3736 else
3737 offset = MmGetMdlByteOffset(curr_mdl);
3738 for (i = 0; i < ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)); i++)
3740 //KdPrint((__DRIVER_NAME " element = %d\n", sg_element));
3741 //KdPrint((__DRIVER_NAME " remaining = %d\n", remaining));
3742 pfn = MmGetMdlPfnArray(curr_mdl)[i];
3743 ASSERT(pfn);
3744 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, pfn, FALSE, INVALID_GRANT_REF);
3745 ASSERT(gref != INVALID_GRANT_REF);
3746 sglist->Elements[sg_element].Address.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | offset;
3747 sglist->Elements[sg_element].Length = min(min(PAGE_SIZE - offset, remaining), total_remaining);
3748 total_remaining -= sglist->Elements[sg_element].Length;
3749 remaining -= sglist->Elements[sg_element].Length;
3750 offset = 0;
3751 sg_element++;
3754 break;
3755 case MAP_TYPE_REMAPPED:
3756 sg_extra->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, max(Length, PAGE_SIZE), XENPCI_POOL_TAG);
3757 ASSERT(sg_extra->aligned_buffer); /* lazy */
3758 KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED - %p -> %p\n", CurrentVa, sg_extra->aligned_buffer));
3759 sg_extra->unaligned_buffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
3760 ASSERT(sg_extra->unaligned_buffer); /* lazy */
3761 if (!MmGetMdlByteOffset(Mdl) && (PtrToUlong(CurrentVa) & (PAGE_SIZE - 1)))
3762 sg_extra->unaligned_buffer = (PUCHAR)sg_extra->unaligned_buffer + (PtrToUlong(CurrentVa) & (PAGE_SIZE - 1));
3763 sg_extra->copy_length = Length;
3764 if (WriteToDevice)
3765 memcpy(sg_extra->aligned_buffer, sg_extra->unaligned_buffer, sg_extra->copy_length);
3766 for (sg_element = 0, remaining = Length;
3767 sg_element < ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_extra->aligned_buffer, Length); sg_element++)
3769 pfn = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)sg_extra->aligned_buffer + (sg_element << PAGE_SHIFT)).QuadPart >> PAGE_SHIFT);
3770 ASSERT(pfn);
3771 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, pfn, FALSE, INVALID_GRANT_REF);
3772 ASSERT(gref);
3773 sglist->Elements[sg_element].Address.QuadPart = (ULONGLONG)gref << PAGE_SHIFT;
3774 sglist->Elements[sg_element].Length = min(PAGE_SIZE, remaining);
3775 remaining -= sglist->Elements[sg_element].Length;
3777 break;
3778 case MAP_TYPE_VIRTUAL:
3779 KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL\n"));
3780 ptr = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
3781 ASSERT(ptr); /* lazy */
3782 if (!MmGetMdlByteOffset(Mdl) && (PtrToUlong(CurrentVa) & (PAGE_SIZE - 1)))
3783 ptr += (PtrToUlong(CurrentVa) & (PAGE_SIZE - 1));
3784 sglist->Elements[0].Address.QuadPart = (ULONGLONG)ptr;
3785 sglist->Elements[0].Length = Length;
3786 break;
3788 #if 0
3789 KdPrint((__DRIVER_NAME " Mdl = %p, CurrentVa = %p, Mdl->Va = %p, Offset = %d, Length = %d\n",
3790 Mdl, CurrentVa, MmGetMdlVirtualAddress(Mdl), MmGetMdlByteOffset(Mdl), Length));
3791 for (i = 0; i < sglist->NumberOfElements; i++)
3793 KdPrint((__DRIVER_NAME " sge[%d]->Address = %08x%08x, Length = %d\n", i, sglist->Elements[i].Address.HighPart,
3794 sglist->Elements[i].Address.LowPart, sglist->Elements[i].Length));
3796 #endif
3797 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, ScatterGatherBuffer, Context);
3799 //FUNCTION_EXIT();
3801 return STATUS_SUCCESS;
3804 static NTSTATUS
3805 XenPci_DOP_BuildMdlFromScatterGatherList(
3806 PDMA_ADAPTER DmaAdapter,
3807 PSCATTER_GATHER_LIST ScatterGather,
3808 PMDL OriginalMdl,
3809 PMDL *TargetMdl)
3811 UNREFERENCED_PARAMETER(DmaAdapter);
3812 UNREFERENCED_PARAMETER(ScatterGather);
3813 UNREFERENCED_PARAMETER(OriginalMdl);
3814 UNREFERENCED_PARAMETER(TargetMdl);
3816 FUNCTION_ENTER();
3817 FUNCTION_EXIT();
3818 return STATUS_UNSUCCESSFUL;
3821 static PDMA_ADAPTER
3822 XenPci_BIS_GetDmaAdapter(PVOID context, PDEVICE_DESCRIPTION device_description, PULONG number_of_map_registers)
3824 xen_dma_adapter_t *xen_dma_adapter;
3825 PDEVICE_OBJECT curr, prev;
3826 PDRIVER_OBJECT fdo_driver_object;
3827 PVOID fdo_driver_extension;
3829 UNREFERENCED_PARAMETER(device_description);
3831 FUNCTION_ENTER();
3833 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
3834 KdPrint((__DRIVER_NAME " Device Description = %p:\n", device_description));
3835 KdPrint((__DRIVER_NAME " Version = %d\n", device_description->Version));
3836 KdPrint((__DRIVER_NAME " Master = %d\n", device_description->Master));
3837 KdPrint((__DRIVER_NAME " ScatterGather = %d\n", device_description->ScatterGather));
3838 KdPrint((__DRIVER_NAME " DemandMode = %d\n", device_description->DemandMode));
3839 KdPrint((__DRIVER_NAME " AutoInitialize = %d\n", device_description->AutoInitialize));
3840 KdPrint((__DRIVER_NAME " Dma32BitAddresses = %d\n", device_description->Dma32BitAddresses));
3841 KdPrint((__DRIVER_NAME " IgnoreCount = %d\n", device_description->IgnoreCount));
3842 KdPrint((__DRIVER_NAME " Dma64BitAddresses = %d\n", device_description->Dma64BitAddresses));
3843 KdPrint((__DRIVER_NAME " BusNumber = %d\n", device_description->BusNumber));
3844 KdPrint((__DRIVER_NAME " DmaChannel = %d\n", device_description->DmaChannel));
3845 KdPrint((__DRIVER_NAME " InterfaceType = %d\n", device_description->InterfaceType));
3846 KdPrint((__DRIVER_NAME " DmaWidth = %d\n", device_description->DmaWidth));
3847 KdPrint((__DRIVER_NAME " DmaSpeed = %d\n", device_description->DmaSpeed));
3848 KdPrint((__DRIVER_NAME " MaximumLength = %d\n", device_description->MaximumLength));
3849 KdPrint((__DRIVER_NAME " DmaPort = %d\n", device_description->DmaPort));
3851 /*
3852 we have to allocate PAGE_SIZE bytes here because Windows thinks this is
3853 actually an ADAPTER_OBJECT, and then the verifier crashes because
3854 Windows accessed beyond the end of the structure :(
3855 */
3856 xen_dma_adapter = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
3857 RtlZeroMemory(xen_dma_adapter, PAGE_SIZE);
3858 xen_dma_adapter->dma_adapter.Version = 2;
3859 xen_dma_adapter->dma_adapter.Size = sizeof(DMA_ADAPTER); //xen_dma_adapter_t);
3860 xen_dma_adapter->dma_adapter.DmaOperations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DMA_OPERATIONS), XENPCI_POOL_TAG);
3861 //xen_dma_adapter->dma_adapter.DmaOperations = &xen_dma_adapter->dma_operations;
3862 xen_dma_adapter->dma_adapter.DmaOperations->Size = sizeof(DMA_OPERATIONS);
3863 xen_dma_adapter->dma_adapter.DmaOperations->PutDmaAdapter = XenPci_DOP_PutDmaAdapter;
3864 xen_dma_adapter->dma_adapter.DmaOperations->AllocateCommonBuffer = XenPci_DOP_AllocateCommonBuffer;
3865 xen_dma_adapter->dma_adapter.DmaOperations->FreeCommonBuffer = XenPci_DOP_FreeCommonBuffer;
3866 xen_dma_adapter->dma_adapter.DmaOperations->AllocateAdapterChannel = XenPci_DOP_AllocateAdapterChannel;
3867 xen_dma_adapter->dma_adapter.DmaOperations->FlushAdapterBuffers = XenPci_DOP_FlushAdapterBuffers;
3868 xen_dma_adapter->dma_adapter.DmaOperations->FreeAdapterChannel = XenPci_DOP_FreeAdapterChannel;
3869 xen_dma_adapter->dma_adapter.DmaOperations->FreeMapRegisters = XenPci_DOP_FreeMapRegisters;
3870 xen_dma_adapter->dma_adapter.DmaOperations->MapTransfer = XenPci_DOP_MapTransfer;
3871 xen_dma_adapter->dma_adapter.DmaOperations->GetDmaAlignment = XenPci_DOP_GetDmaAlignment;
3872 xen_dma_adapter->dma_adapter.DmaOperations->ReadDmaCounter = XenPci_DOP_ReadDmaCounter;
3873 xen_dma_adapter->dma_adapter.DmaOperations->GetScatterGatherList = XenPci_DOP_GetScatterGatherList;
3874 xen_dma_adapter->dma_adapter.DmaOperations->PutScatterGatherList = XenPci_DOP_PutScatterGatherList;
3875 xen_dma_adapter->dma_adapter.DmaOperations->CalculateScatterGatherList = XenPci_DOP_CalculateScatterGatherList;
3876 xen_dma_adapter->dma_adapter.DmaOperations->BuildScatterGatherList = XenPci_DOP_BuildScatterGatherList;
3877 xen_dma_adapter->dma_adapter.DmaOperations->BuildMdlFromScatterGatherList = XenPci_DOP_BuildMdlFromScatterGatherList;
3878 xen_dma_adapter->xppdd = context;
3879 xen_dma_adapter->dma_extension = NULL;
3881 KdPrint((__DRIVER_NAME " About to call IoGetAttachedDeviceReference\n"));
3882 curr = IoGetAttachedDeviceReference(xen_dma_adapter->xppdd->common.pdo);
3883 KdPrint((__DRIVER_NAME " Before start of loop - curr = %p\n", curr));
3884 while (curr != NULL)
3886 fdo_driver_object = curr->DriverObject;
3887 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
3888 if (fdo_driver_object)
3890 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC));
3891 if (fdo_driver_extension)
3893 xen_dma_adapter->dma_extension = (dma_driver_extension_t *)fdo_driver_extension;
3894 ObDereferenceObject(curr);
3895 break;
3898 prev = curr;
3899 curr = IoGetLowerDeviceObject(curr);
3900 ObDereferenceObject(prev);
3902 KdPrint((__DRIVER_NAME " End of loop\n"));
3904 *number_of_map_registers = 1024; //1024; /* why not... */
3906 FUNCTION_EXIT();
3908 return &xen_dma_adapter->dma_adapter;
3911 static ULONG
3912 XenPci_BIS_SetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
3914 UNREFERENCED_PARAMETER(context);
3915 UNREFERENCED_PARAMETER(data_type);
3916 UNREFERENCED_PARAMETER(buffer);
3917 UNREFERENCED_PARAMETER(offset);
3918 UNREFERENCED_PARAMETER(length);
3920 FUNCTION_ENTER();
3921 FUNCTION_EXIT();
3922 return 0;
3925 static ULONG
3926 XenPci_BIS_GetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
3928 UNREFERENCED_PARAMETER(context);
3929 UNREFERENCED_PARAMETER(data_type);
3930 UNREFERENCED_PARAMETER(buffer);
3931 UNREFERENCED_PARAMETER(offset);
3932 UNREFERENCED_PARAMETER(length);
3934 FUNCTION_ENTER();
3935 FUNCTION_EXIT();
3936 return 0;
3939 static NTSTATUS
3940 XenPci_QueryInterface(PDEVICE_OBJECT device_object, PIRP irp)
3942 NTSTATUS status;
3943 PIO_STACK_LOCATION stack;
3944 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
3945 PBUS_INTERFACE_STANDARD bis;
3946 PGUID guid;
3948 FUNCTION_ENTER();
3950 stack = IoGetCurrentIrpStackLocation(irp);
3952 if (memcmp(stack->Parameters.QueryInterface.InterfaceType, &GUID_BUS_INTERFACE_STANDARD, sizeof(GUID_BUS_INTERFACE_STANDARD)) == 0)
3954 KdPrint((__DRIVER_NAME " GUID_BUS_INTERFACE_STANDARD\n"));
3955 if (stack->Parameters.QueryInterface.Size < sizeof(BUS_INTERFACE_STANDARD))
3957 KdPrint((__DRIVER_NAME " buffer too small\n"));
3958 status = STATUS_INVALID_PARAMETER;
3959 FUNCTION_EXIT();
3960 return status;
3962 if (stack->Parameters.QueryInterface.Version != 1)
3964 KdPrint((__DRIVER_NAME " incorrect version %d\n", stack->Parameters.QueryInterface.Version));
3965 status = STATUS_INVALID_PARAMETER;
3966 FUNCTION_EXIT();
3967 return status;
3969 bis = (PBUS_INTERFACE_STANDARD)stack->Parameters.QueryInterface.Interface;
3970 bis->Size = sizeof(BUS_INTERFACE_STANDARD);
3971 bis->Version = 1; //BUS_INTERFACE_STANDARD_VERSION;
3972 bis->Context = xppdd;
3973 bis->InterfaceReference = XenPci_IS_InterfaceReference;
3974 bis->InterfaceDereference = XenPci_IS_InterfaceReference;
3975 bis->TranslateBusAddress = XenPci_BIS_TranslateBusAddress;
3976 bis->GetDmaAdapter = XenPci_BIS_GetDmaAdapter;
3977 bis->SetBusData = XenPci_BIS_SetBusData;
3978 bis->GetBusData = XenPci_BIS_GetBusData;
3979 status = STATUS_SUCCESS;
3980 FUNCTION_EXIT();
3981 return status;
3983 else
3985 guid = (PGUID)stack->Parameters.QueryInterface.InterfaceType;
3986 KdPrint((__DRIVER_NAME " Unknown GUID %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",
3987 guid->Data1, (ULONG)guid->Data2, (ULONG)guid->Data3, (ULONG)guid->Data4[0], (ULONG)guid->Data4[1],
3988 (ULONG)guid->Data4[2], (ULONG)guid->Data4[3], (ULONG)guid->Data4[4], (ULONG)guid->Data4[5],
3989 (ULONG)guid->Data4[6], (ULONG)guid->Data4[7]));
3990 status = irp->IoStatus.Status;
3991 FUNCTION_EXIT();
3992 return status;
3996 NTSTATUS
3997 XenPci_Pnp_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
3999 NTSTATUS status;
4000 PIO_STACK_LOCATION stack;
4001 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
4002 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
4003 LPWSTR buffer;
4004 WCHAR widebuf[256];
4005 unsigned int i;
4006 PPNP_BUS_INFORMATION pbi;
4007 ULONG *usage_type;
4009 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
4011 stack = IoGetCurrentIrpStackLocation(irp);
4013 switch (stack->MinorFunction)
4015 case IRP_MN_START_DEVICE:
4016 KdPrint((__DRIVER_NAME " IRP_MN_START_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4017 status = XenPci_Pnp_StartDevice(device_object, irp);
4018 break;
4020 case IRP_MN_QUERY_STOP_DEVICE:
4021 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_STOP_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4022 SET_PNP_STATE(&xppdd->common, StopPending);
4023 status = STATUS_SUCCESS;
4024 break;
4026 case IRP_MN_STOP_DEVICE:
4027 KdPrint((__DRIVER_NAME " IRP_MN_STOP_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4028 SET_PNP_STATE(&xppdd->common, Stopped);
4029 status = STATUS_SUCCESS;
4030 break;
4032 case IRP_MN_CANCEL_STOP_DEVICE:
4033 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_STOP_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4034 REVERT_PNP_STATE(&xppdd->common);
4035 status = STATUS_SUCCESS;
4036 break;
4038 case IRP_MN_QUERY_REMOVE_DEVICE:
4039 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_REMOVE_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4040 SET_PNP_STATE(&xppdd->common, RemovePending);
4041 status = STATUS_SUCCESS;
4042 break;
4044 case IRP_MN_REMOVE_DEVICE:
4045 KdPrint((__DRIVER_NAME " IRP_MN_REMOVE_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4046 status = XenPci_Pnp_RemoveDevice(device_object, irp);
4047 break;
4049 case IRP_MN_CANCEL_REMOVE_DEVICE:
4050 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_REMOVE_DEVICE (status = %08x)\n", irp->IoStatus.Status));
4051 REVERT_PNP_STATE(&xppdd->common);
4052 status = STATUS_SUCCESS;
4053 break;
4055 case IRP_MN_SURPRISE_REMOVAL:
4056 KdPrint((__DRIVER_NAME " IRP_MN_SURPRISE_REMOVAL (status = %08x)\n", irp->IoStatus.Status));
4057 SET_PNP_STATE(&xppdd->common, SurpriseRemovePending);
4058 status = STATUS_SUCCESS;
4059 break;
4061 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
4062 KdPrint((__DRIVER_NAME " IRP_MN_DEVICE_USAGE_NOTIFICATION (status = %08x)\n", irp->IoStatus.Status));
4064 usage_type = NULL;
4065 switch (stack->Parameters.UsageNotification.Type)
4067 case DeviceUsageTypePaging:
4068 KdPrint((__DRIVER_NAME " type = DeviceUsageTypePaging\n"));
4069 usage_type = &xppdd->common.device_usage_paging;
4070 break;
4071 case DeviceUsageTypeDumpFile:
4072 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeDumpFile\n"));
4073 usage_type = &xppdd->common.device_usage_dump;
4074 break;
4075 case DeviceUsageTypeHibernation:
4076 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeHibernation\n"));
4077 usage_type = &xppdd->common.device_usage_hibernation;
4078 break;
4079 default:
4080 KdPrint((__DRIVER_NAME " Unknown usage type %x\n",
4081 stack->Parameters.UsageNotification.Type));
4082 break;
4084 KdPrint((__DRIVER_NAME " inpath = %d\n", stack->Parameters.UsageNotification.InPath));
4085 if (usage_type)
4087 if (stack->Parameters.UsageNotification.InPath)
4088 (*usage_type)++;
4089 else
4090 (*usage_type)--;
4092 status = STATUS_SUCCESS;
4093 break;
4095 case IRP_MN_QUERY_ID:
4096 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_ID (status = %08x)\n", irp->IoStatus.Status));
4097 switch (stack->Parameters.QueryId.IdType)
4099 case BusQueryDeviceID: /* REG_SZ */
4100 KdPrint((__DRIVER_NAME " BusQueryDeviceID\n"));
4101 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
4102 for (i = 0; i < strlen(xppdd->device); i++)
4103 widebuf[i] = xppdd->device[i];
4104 widebuf[i] = 0;
4105 RtlStringCbPrintfW(buffer, 512, L"Xen\\%ws", widebuf);
4106 KdPrint((__DRIVER_NAME " %ls\n", buffer));
4107 irp->IoStatus.Information = (ULONG_PTR)buffer;
4108 status = STATUS_SUCCESS;
4109 break;
4110 case BusQueryHardwareIDs: /* REG_MULTI_SZ */
4111 KdPrint((__DRIVER_NAME " BusQueryHardwareIDs\n"));
4112 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
4113 for (i = 0; i < strlen(xppdd->device); i++)
4114 widebuf[i] = xppdd->device[i];
4115 widebuf[i] = 0;
4116 RtlStringCbPrintfW(buffer, 512, L"Xen\\%ws", widebuf);
4117 for (i = 0; buffer[i] != 0; i++);
4118 buffer[i + 1] = 0;
4119 // for (i = 0; i < 256; i++)
4120 // KdPrint((__DRIVER_NAME " %04X: %04X %wc\n", i, buffer[i], buffer[i]));
4121 KdPrint((__DRIVER_NAME " %ls\n", buffer));
4122 irp->IoStatus.Information = (ULONG_PTR)buffer;
4123 status = STATUS_SUCCESS;
4124 break;
4125 case BusQueryCompatibleIDs: /* REG_MULTI_SZ */
4126 KdPrint((__DRIVER_NAME " BusQueryCompatibleIDs\n"));
4127 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
4128 for (i = 0; i < strlen(xppdd->device); i++)
4129 widebuf[i] = xppdd->device[i];
4130 widebuf[i] = 0;
4131 RtlStringCbPrintfW(buffer, 512, L"Xen\\%ws", widebuf);
4132 for (i = 0; buffer[i] != 0; i++);
4133 buffer[i + 1] = 0;
4134 KdPrint((__DRIVER_NAME " %ls\n", buffer));
4135 irp->IoStatus.Information = (ULONG_PTR)buffer;
4136 status = STATUS_SUCCESS;
4137 break;
4138 case BusQueryInstanceID: /* REG_SZ */
4139 KdPrint((__DRIVER_NAME " BusQueryInstanceID\n"));
4140 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
4141 RtlStringCbPrintfW(buffer, 512, L"%02d", xppdd->index);
4142 KdPrint((__DRIVER_NAME " %ls\n", buffer));
4143 irp->IoStatus.Information = (ULONG_PTR)buffer;
4144 status = STATUS_SUCCESS;
4145 break;
4146 default:
4147 KdPrint((__DRIVER_NAME " Unhandled IdType = %d\n", stack->Parameters.QueryId.IdType));
4148 irp->IoStatus.Information = 0;
4149 status = STATUS_NOT_SUPPORTED;
4150 break;
4152 break;
4154 case IRP_MN_QUERY_DEVICE_TEXT:
4155 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_TEXT (status = %08x)\n", irp->IoStatus.Status));
4156 switch (stack->Parameters.QueryDeviceText.DeviceTextType)
4158 case DeviceTextDescription:
4159 KdPrint((__DRIVER_NAME " DeviceTextDescription\n"));
4160 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
4161 for (i = 0; i < strlen(xppdd->device); i++)
4162 widebuf[i] = xppdd->device[i];
4163 widebuf[i] = 0;
4164 RtlStringCbPrintfW(buffer, 512, L"Xen %ws device #%d", widebuf, xppdd->index);
4165 KdPrint((__DRIVER_NAME " %ls\n", buffer));
4166 irp->IoStatus.Information = (ULONG_PTR)buffer;
4167 status = STATUS_SUCCESS;
4168 break;
4169 case DeviceTextLocationInformation:
4170 KdPrint((__DRIVER_NAME " DeviceTextLocationInformation\n"));
4171 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
4172 RtlStringCbPrintfW(buffer, 512, L"Xen Bus");
4173 KdPrint((__DRIVER_NAME " %ls\n", buffer));
4174 irp->IoStatus.Information = (ULONG_PTR)buffer;
4175 status = STATUS_SUCCESS;
4176 break;
4177 default:
4178 KdPrint((__DRIVER_NAME " Unhandled IdType = %d\n", stack->Parameters.QueryDeviceText.DeviceTextType));
4179 irp->IoStatus.Information = 0;
4180 status = STATUS_NOT_SUPPORTED;
4181 break;
4183 break;
4185 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
4186 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_RESOURCE_REQUIREMENTS (status = %08x)\n", irp->IoStatus.Status));
4187 status = XenPci_QueryResourceRequirements(device_object, irp);
4188 break;
4190 case IRP_MN_QUERY_CAPABILITIES:
4191 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_CAPABILITIES (status = %08x)\n", irp->IoStatus.Status));
4192 status = XenPci_Pnp_QueryCapabilities(device_object, irp);
4193 break;
4195 case IRP_MN_QUERY_BUS_INFORMATION:
4196 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_BUS_INFORMATION (status = %08x)\n", irp->IoStatus.Status));
4197 pbi = (PPNP_BUS_INFORMATION)ExAllocatePoolWithTag(PagedPool, sizeof(PNP_BUS_INFORMATION), XENPCI_POOL_TAG);
4198 pbi->BusTypeGuid = GUID_BUS_TYPE_XEN;
4199 pbi->LegacyBusType = PNPBus; //Internal;
4200 pbi->BusNumber = 0;
4201 irp->IoStatus.Information = (ULONG_PTR)pbi;
4202 status = STATUS_SUCCESS;
4203 break;
4205 case IRP_MN_QUERY_INTERFACE:
4206 status = XenPci_QueryInterface(device_object, irp);
4207 break;
4209 case IRP_MN_QUERY_RESOURCES:
4210 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_RESOURCES (status = %08x)\n", irp->IoStatus.Status));
4211 status = irp->IoStatus.Status;
4212 #if 0
4213 crl = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(PagedPool, sizeof(CM_RESOURCE_LIST) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 2, XENPCI_POOL_TAG);
4214 crl->Count = 1;
4215 crl->List[0].InterfaceType = PNPBus;
4216 crl->List[0].BusNumber = 0;
4217 crl->List[0].PartialResourceList.Version = 1;
4218 crl->List[0].PartialResourceList.Revision = 1;
4219 crl->List[0].PartialResourceList.Count = 0;
4221 prd = &crl->List[0].PartialResourceList.PartialDescriptors[crl->List[0].PartialResourceList.Count++];
4222 prd->Type = CmResourceTypeInterrupt;
4223 prd->ShareDisposition = CmResourceShareShared;
4224 prd->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
4225 prd->u.Interrupt.Level = xpdd->irq_number;
4226 prd->u.Interrupt.Vector = xpdd->irq_number;
4227 prd->u.Interrupt.Affinity = (KAFFINITY)-1;
4229 prd = &crl->List[0].PartialResourceList.PartialDescriptors[crl->List[0].PartialResourceList.Count++];
4230 prd->Type = CmResourceTypeMemory;
4231 prd->ShareDisposition = CmResourceShareShared;
4232 prd->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
4233 prd->u.Memory.Start = xpdd->platform_mmio_addr;
4234 prd->u.Memory.Length = 0;
4236 irp->IoStatus.Information = (ULONG_PTR)crl;
4237 status = STATUS_SUCCESS;
4238 #endif
4239 break;
4241 case IRP_MN_QUERY_PNP_DEVICE_STATE:
4242 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_PNP_DEVICE_STATE (status = %08x)\n", irp->IoStatus.Status));
4243 irp->IoStatus.Information = 0;
4244 status = STATUS_SUCCESS;
4245 break;
4247 case IRP_MN_QUERY_DEVICE_RELATIONS:
4248 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_RELATIONS (status = %08x)\n", irp->IoStatus.Status));
4249 switch (stack->Parameters.QueryDeviceRelations.Type)
4251 case TargetDeviceRelation:
4252 KdPrint((__DRIVER_NAME " BusRelations\n"));
4253 status = XenPci_Pnp_QueryTargetRelations(device_object, irp);
4254 break;
4255 default:
4256 status = irp->IoStatus.Status;
4257 break;
4259 break;
4261 case IRP_MN_EJECT:
4262 KdPrint((__DRIVER_NAME " IRP_MN_EJECT\n"));
4263 status = STATUS_SUCCESS;
4264 break;
4266 default:
4267 //KdPrint((__DRIVER_NAME " Unhandled Minor = %d, Status = %08x\n", stack->MinorFunction, irp->IoStatus.Status));
4268 status = irp->IoStatus.Status;
4269 break;
4272 irp->IoStatus.Status = status;
4273 IoCompleteRequest(irp, IO_NO_INCREMENT);
4275 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
4277 return status;
4280 NTSTATUS
4281 XenPci_Irp_Create_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4283 NTSTATUS status;
4285 UNREFERENCED_PARAMETER(device_object);
4287 FUNCTION_ENTER();
4289 status = irp->IoStatus.Status;
4290 IoCompleteRequest(irp, IO_NO_INCREMENT);
4292 FUNCTION_EXIT();
4294 return status;
4297 NTSTATUS
4298 XenPci_Irp_Close_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4300 NTSTATUS status;
4302 UNREFERENCED_PARAMETER(device_object);
4304 FUNCTION_ENTER();
4306 status = irp->IoStatus.Status;
4307 IoCompleteRequest(irp, IO_NO_INCREMENT);
4309 FUNCTION_EXIT();
4311 return status;
4314 NTSTATUS
4315 XenPci_Irp_Read_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4317 NTSTATUS status;
4319 UNREFERENCED_PARAMETER(device_object);
4321 FUNCTION_ENTER();
4323 status = irp->IoStatus.Status;
4324 IoCompleteRequest(irp, IO_NO_INCREMENT);
4326 FUNCTION_EXIT();
4328 return status;
4331 NTSTATUS
4332 XenPci_Irp_Write_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4334 NTSTATUS status;
4336 UNREFERENCED_PARAMETER(device_object);
4338 FUNCTION_ENTER();
4340 status = irp->IoStatus.Status;
4341 IoCompleteRequest(irp, IO_NO_INCREMENT);
4343 FUNCTION_EXIT();
4345 return status;
4348 NTSTATUS
4349 XenPci_Irp_Cleanup_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4351 NTSTATUS status;
4353 UNREFERENCED_PARAMETER(device_object);
4355 FUNCTION_ENTER();
4357 status = irp->IoStatus.Status;
4358 IoCompleteRequest(irp, IO_NO_INCREMENT);
4360 FUNCTION_EXIT();
4362 return status;
4365 DDKAPI NTSTATUS
4366 XenPci_SystemControl_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
4368 NTSTATUS status;
4370 UNREFERENCED_PARAMETER(device_object);
4372 FUNCTION_ENTER();
4374 status = irp->IoStatus.Status;
4375 IoCompleteRequest(irp, IO_NO_INCREMENT);
4377 FUNCTION_EXIT();
4379 return status;
4381 #endif