win-pvdrivers

view xenpci/xenpci_dma.c @ 701:c3e410ac288f

Fix a few cases where a failure to allocate a gref did not result in the expected outcome.
Allocate gref's in AllocateAdapterChannel not in MapTransfer. This may have been causing a leak of grefs with a slowdown and eventual crash over time
author James Harper <james.harper@bendigoit.com.au>
date Wed Nov 25 21:41:03 2009 +1100 (2009-11-25)
parents c13ccf5a629b
children 5bdb7251370c
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2009 James Harper
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
20 #include "xenpci.h"
21 #include <stdlib.h>
22 #include <io/ring.h>
24 #pragma warning(disable : 4200) // zero-sized array
25 #pragma warning(disable: 4127) // conditional expression is constant
27 #define MAP_TYPE_VIRTUAL 1
28 #define MAP_TYPE_MDL 2
29 #define MAP_TYPE_REMAPPED 3
31 typedef struct {
32 ULONG map_type;
33 PVOID aligned_buffer;
34 ULONG copy_length;
35 PMDL mdl;
36 PVOID currentva;
37 BOOLEAN allocated_by_me;
38 } sg_extra_t;
40 typedef struct {
41 ULONG map_type;
42 PVOID aligned_buffer;
43 PVOID unaligned_buffer;
44 ULONG copy_length;
45 PHYSICAL_ADDRESS logical;
46 } map_register_t;
48 typedef struct {
49 PDEVICE_OBJECT device_object;
50 ULONG total_map_registers;
51 ULONG count;
52 map_register_t regs[1];
53 } map_register_base_t;
55 BOOLEAN
56 XenPci_BIS_TranslateBusAddress(PVOID context, PHYSICAL_ADDRESS bus_address, ULONG length, PULONG address_space, PPHYSICAL_ADDRESS translated_address)
57 {
58 UNREFERENCED_PARAMETER(context);
59 UNREFERENCED_PARAMETER(length);
60 /* actually this isn't right - should look up the gref for the physical address and work backwards from that */
61 FUNCTION_ENTER();
62 if (*address_space != 0)
63 {
64 KdPrint((__DRIVER_NAME " Cannot map I/O space\n"));
65 FUNCTION_EXIT();
66 return FALSE;
67 }
68 *translated_address = bus_address;
69 FUNCTION_EXIT();
70 return TRUE;
71 }
73 static VOID
74 XenPci_DOP_PutDmaAdapter(PDMA_ADAPTER dma_adapter)
75 {
76 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
78 FUNCTION_ENTER();
80 if (xen_dma_adapter->dma_extension)
81 ObDereferenceObject(xen_dma_adapter->dma_extension_driver);
82 ExFreePoolWithTag(xen_dma_adapter->adapter_object.DmaHeader.DmaOperations, XENPCI_POOL_TAG);
83 ExFreePoolWithTag(xen_dma_adapter, XENPCI_POOL_TAG);
85 FUNCTION_EXIT();
87 return;
88 }
90 static PVOID
91 XenPci_DOP_AllocateCommonBuffer(
92 PDMA_ADAPTER DmaAdapter,
93 ULONG Length,
94 PPHYSICAL_ADDRESS LogicalAddress,
95 BOOLEAN CacheEnabled
96 )
97 {
98 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
99 PXENPCI_DEVICE_DATA xpdd;
100 PVOID buffer;
101 PFN_NUMBER pfn;
102 grant_ref_t gref;
104 UNREFERENCED_PARAMETER(DmaAdapter);
105 UNREFERENCED_PARAMETER(CacheEnabled);
107 //FUNCTION_ENTER();
109 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
111 //KdPrint((__DRIVER_NAME " Length = %d\n", Length));
113 buffer = ExAllocatePoolWithTag(NonPagedPool, Length, XENPCI_POOL_TAG);
114 ASSERT(buffer); /* lazy */
116 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(buffer).QuadPart >> PAGE_SHIFT);
117 ASSERT(pfn); /* lazy */
118 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
119 ASSERT(gref != INVALID_GRANT_REF); /* lazy */
120 LogicalAddress->QuadPart = (gref << PAGE_SHIFT) | (PtrToUlong(buffer) & (PAGE_SIZE - 1));
122 //FUNCTION_EXIT();
123 return buffer;
124 }
126 static VOID
127 XenPci_DOP_FreeCommonBuffer(
128 PDMA_ADAPTER dma_adapter,
129 ULONG length,
130 PHYSICAL_ADDRESS logical_address,
131 PVOID virtual_address,
132 BOOLEAN cache_enabled
133 )
134 {
135 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
136 PXENPCI_DEVICE_DATA xpdd;
137 grant_ref_t gref;
139 UNREFERENCED_PARAMETER(dma_adapter);
140 UNREFERENCED_PARAMETER(length);
141 UNREFERENCED_PARAMETER(cache_enabled);
143 // FUNCTION_ENTER();
145 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
146 gref = (grant_ref_t)(logical_address.QuadPart >> PAGE_SHIFT);
147 //KdPrint((__DRIVER_NAME " F Releasing Grant Ref %d\n", gref));
148 GntTbl_EndAccess(xpdd, gref, FALSE);
149 //KdPrint((__DRIVER_NAME " F Released Grant Ref\n"));
150 ExFreePoolWithTag(virtual_address, XENPCI_POOL_TAG);
152 // FUNCTION_EXIT();
153 }
155 static NTSTATUS
156 XenPci_DOP_AllocateAdapterChannel(
157 IN PDMA_ADAPTER dma_adapter,
158 IN PDEVICE_OBJECT device_object,
159 IN ULONG NumberOfMapRegisters,
160 IN PDRIVER_CONTROL ExecutionRoutine,
161 IN PVOID Context
162 )
163 {
164 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
165 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
166 ULONG i;
167 IO_ALLOCATION_ACTION action;
168 map_register_base_t *map_register_base;
169 grant_ref_t gref;
171 UNREFERENCED_PARAMETER(dma_adapter);
173 //FUNCTION_ENTER();
175 map_register_base = ExAllocatePoolWithTag(NonPagedPool,
176 FIELD_OFFSET(map_register_base_t, regs) + NumberOfMapRegisters * sizeof(map_register_t), XENPCI_POOL_TAG);
177 if (!map_register_base)
178 {
179 KdPrint((__DRIVER_NAME " Cannot allocate memory for map_register_base\n"));
180 //FUNCTION_EXIT();
181 return STATUS_INSUFFICIENT_RESOURCES;
182 }
183 /* 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 */
184 map_register_base->device_object = device_object;
185 map_register_base->total_map_registers = NumberOfMapRegisters;
186 map_register_base->count = 0;
188 for (i = 0; i < NumberOfMapRegisters; i++)
189 {
190 gref = GntTbl_GetRef(xpdd);
191 if (gref == INVALID_GRANT_REF)
192 {
193 /* go back through the list and free the ones we allocated */
194 NumberOfMapRegisters = i;
195 for (i = 0; i < NumberOfMapRegisters; i++)
196 {
197 gref = (grant_ref_t)(map_register_base->regs[i].logical.QuadPart >> PAGE_SHIFT);
198 GntTbl_PutRef(xpdd, gref);
199 }
200 ExFreePoolWithTag(map_register_base, XENPCI_POOL_TAG);
201 return STATUS_INSUFFICIENT_RESOURCES;
202 }
203 map_register_base->regs[i].logical.QuadPart = ((LONGLONG)gref << PAGE_SHIFT);
204 }
206 action = ExecutionRoutine(device_object, device_object->CurrentIrp, map_register_base, Context);
208 switch (action)
209 {
210 case KeepObject:
211 KdPrint((__DRIVER_NAME " KeepObject\n"));
212 ASSERT(FALSE);
213 break;
214 case DeallocateObject:
215 KdPrint((__DRIVER_NAME " DeallocateObject\n"));
216 ASSERT(FALSE);
217 break;
218 case DeallocateObjectKeepRegisters:
219 //KdPrint((__DRIVER_NAME " DeallocateObjectKeepRegisters\n"));
220 break;
221 default:
222 KdPrint((__DRIVER_NAME " Unknown action %d\n", action));
223 ASSERT(FALSE);
224 break;
225 }
226 //FUNCTION_EXIT();
227 return STATUS_SUCCESS;
228 }
230 static BOOLEAN
231 XenPci_DOP_FlushAdapterBuffers(
232 PDMA_ADAPTER dma_adapter,
233 PMDL mdl,
234 PVOID MapRegisterBase,
235 PVOID CurrentVa,
236 ULONG Length,
237 BOOLEAN write_to_device)
238 {
239 //xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
240 //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
241 map_register_base_t *map_register_base = MapRegisterBase;
242 map_register_t *map_register;
243 ULONG i;
245 UNREFERENCED_PARAMETER(dma_adapter);
246 UNREFERENCED_PARAMETER(mdl);
247 UNREFERENCED_PARAMETER(CurrentVa);
248 UNREFERENCED_PARAMETER(Length);
250 //FUNCTION_ENTER();
252 for (i = 0; i < map_register_base->count; i++)
253 {
254 map_register = &map_register_base->regs[i];
255 if (map_register->map_type == MAP_TYPE_REMAPPED && !write_to_device)
256 memcpy(map_register->unaligned_buffer, map_register->aligned_buffer, map_register->copy_length);
257 }
258 //FUNCTION_EXIT();
260 return TRUE;
261 }
263 static VOID
264 XenPci_DOP_FreeAdapterChannel(
265 IN PDMA_ADAPTER DmaAdapter
266 )
267 {
268 UNREFERENCED_PARAMETER(DmaAdapter);
270 FUNCTION_ENTER();
271 FUNCTION_EXIT();
272 }
274 static VOID
275 XenPci_DOP_FreeMapRegisters(
276 PDMA_ADAPTER dma_adapter,
277 PVOID MapRegisterBase,
278 ULONG NumberOfMapRegisters)
279 {
280 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
281 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
282 map_register_base_t *map_register_base = MapRegisterBase;
283 map_register_t *map_register;
284 ULONG i;
285 grant_ref_t gref;
287 UNREFERENCED_PARAMETER(NumberOfMapRegisters);
289 //FUNCTION_ENTER();
290 if (!map_register_base)
291 {
292 /* i'm not sure if this is ideal here, but NDIS definitely does it */
293 return;
294 }
295 ASSERT(map_register_base->total_map_registers == NumberOfMapRegisters);
297 for (i = 0; i < map_register_base->count; i++)
298 {
299 map_register = &map_register_base->regs[i];
300 switch (map_register->map_type)
301 {
302 case MAP_TYPE_REMAPPED:
303 gref = (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT);
304 GntTbl_EndAccess(xpdd, gref, FALSE);
305 ExFreePoolWithTag(map_register->aligned_buffer, XENPCI_POOL_TAG);
306 break;
307 case MAP_TYPE_MDL:
308 gref = (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT);
309 GntTbl_EndAccess(xpdd, gref, FALSE);
310 break;
311 case MAP_TYPE_VIRTUAL:
312 break;
313 }
314 }
315 ExFreePoolWithTag(map_register_base, XENPCI_POOL_TAG);
317 //FUNCTION_EXIT();
318 }
320 static PHYSICAL_ADDRESS
321 XenPci_DOP_MapTransfer(
322 PDMA_ADAPTER dma_adapter,
323 PMDL mdl,
324 PVOID MapRegisterBase,
325 PVOID CurrentVa,
326 PULONG Length,
327 BOOLEAN WriteToDevice)
328 {
329 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
330 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
331 map_register_base_t *map_register_base = MapRegisterBase;
332 map_register_t *map_register = &map_register_base->regs[map_register_base->count];
333 PDEVICE_OBJECT device_object = map_register_base->device_object;
334 ULONG page_offset;
335 PFN_NUMBER pfn;
336 //grant_ref_t gref;
337 PUCHAR ptr;
338 ULONG mdl_offset;
339 ULONG pfn_index;
341 //FUNCTION_ENTER();
343 //KdPrint((__DRIVER_NAME " Mdl = %p, MapRegisterBase = %p, MdlVa = %p, CurrentVa = %p, Length = %d\n",
344 // mdl, MapRegisterBase, MmGetMdlVirtualAddress(mdl), CurrentVa, *Length));
346 ASSERT(mdl);
347 ASSERT(map_register_base);
348 ASSERT(map_register_base->count < map_register_base->total_map_registers);
350 if (xen_dma_adapter->dma_extension)
351 {
352 if (xen_dma_adapter->dma_extension->need_virtual_address && xen_dma_adapter->dma_extension->need_virtual_address(device_object->CurrentIrp))
353 {
354 map_register->map_type = MAP_TYPE_VIRTUAL;
355 }
356 else
357 {
358 if (xen_dma_adapter->dma_extension->get_alignment)
359 {
360 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(device_object->CurrentIrp);
361 if ((MmGetMdlByteOffset(mdl) & (alignment - 1)) || (MmGetMdlByteCount(mdl) & (alignment - 1)))
362 {
363 map_register->map_type = MAP_TYPE_REMAPPED;
364 }
365 else
366 {
367 map_register->map_type = MAP_TYPE_MDL;
368 }
369 }
370 else
371 {
372 map_register->map_type = MAP_TYPE_MDL;
373 }
374 }
375 }
376 else
377 {
378 map_register->map_type = MAP_TYPE_MDL;
379 }
381 switch (map_register->map_type)
382 {
383 case MAP_TYPE_MDL:
384 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL\n"));
385 mdl_offset = (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)MmGetMdlVirtualAddress(mdl));
386 page_offset = PtrToUlong(CurrentVa) & (PAGE_SIZE - 1);
387 *Length = min(*Length, PAGE_SIZE - page_offset);
388 pfn_index = (ULONG)(((UINT_PTR)CurrentVa >> PAGE_SHIFT) - ((UINT_PTR)MmGetMdlVirtualAddress(mdl) >> PAGE_SHIFT));
389 //KdPrint((__DRIVER_NAME " mdl_offset = %d, page_offset = %d, length = %d, pfn_index = %d\n",
390 // mdl_offset, page_offset, *Length, pfn_index));
391 pfn = MmGetMdlPfnArray(mdl)[pfn_index];
392 //KdPrint((__DRIVER_NAME " B Requesting Grant Ref\n"));
393 GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT));
394 //KdPrint((__DRIVER_NAME " B Got Grant Ref %d\n", gref));
395 map_register->logical.QuadPart &= ~(LONGLONG)(PAGE_SIZE - 1);
396 map_register->logical.QuadPart |= page_offset;
397 map_register_base->count++;
398 break;
399 case MAP_TYPE_REMAPPED:
400 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED (MapTransfer)\n"));
401 //KdPrint((__DRIVER_NAME " Mdl = %p, MapRegisterBase = %p, MdlVa = %p, CurrentVa = %p, Length = %d\n",
402 // mdl, MapRegisterBase, MmGetMdlVirtualAddress(mdl), CurrentVa, *Length));
403 mdl_offset = (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)MmGetMdlVirtualAddress(mdl));
404 *Length = min(*Length, PAGE_SIZE);
405 map_register->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
406 ASSERT(map_register->aligned_buffer);
407 map_register->unaligned_buffer = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
408 ASSERT(map_register->unaligned_buffer); /* lazy */
409 map_register->unaligned_buffer = (PUCHAR)map_register->unaligned_buffer + mdl_offset;
410 map_register->copy_length = *Length;
411 if (WriteToDevice)
412 memcpy(map_register->aligned_buffer, map_register->unaligned_buffer, map_register->copy_length);
413 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(map_register->aligned_buffer).QuadPart >> PAGE_SHIFT);
414 //KdPrint((__DRIVER_NAME " C Requesting Grant Ref\n"));
415 GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT));
416 //KdPrint((__DRIVER_NAME " C Got Grant Ref %d\n", gref));
417 map_register->logical.QuadPart &= ~(LONGLONG)(PAGE_SIZE - 1);
418 map_register_base->count++;
419 break;
420 case MAP_TYPE_VIRTUAL:
421 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL\n"));
422 ptr = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
423 ASSERT(ptr); /* lazy */
424 map_register->logical.QuadPart = (ULONGLONG)ptr;
425 map_register_base->count++;
426 break;
427 default:
428 ASSERT(FALSE);
429 break;
430 }
432 //KdPrint((__DRIVER_NAME " logical = %08x:%08x\n", map_register->logical.HighPart, map_register->logical.LowPart));
433 //FUNCTION_EXIT();
434 return map_register->logical;
435 }
437 static ULONG
438 XenPci_DOP_GetDmaAlignment(
439 PDMA_ADAPTER DmaAdapter)
440 {
441 UNREFERENCED_PARAMETER(DmaAdapter);
443 FUNCTION_ENTER();
444 FUNCTION_EXIT();
445 return 0;
446 }
448 static ULONG
449 XenPci_DOP_ReadDmaCounter(
450 PDMA_ADAPTER DmaAdapter)
451 {
452 UNREFERENCED_PARAMETER(DmaAdapter);
454 FUNCTION_ENTER();
455 FUNCTION_EXIT();
456 return 0;
457 }
459 static VOID
460 XenPci_DOP_PutScatterGatherList(
461 IN PDMA_ADAPTER DmaAdapter,
462 IN PSCATTER_GATHER_LIST sg_list,
463 IN BOOLEAN WriteToDevice
464 )
465 {
466 xen_dma_adapter_t *xen_dma_adapter;
467 PXENPCI_DEVICE_DATA xpdd;
468 ULONG i;
469 sg_extra_t *sg_extra;
470 PMDL curr_mdl;
471 ULONG offset;
472 BOOLEAN active;
474 UNREFERENCED_PARAMETER(WriteToDevice);
476 //FUNCTION_ENTER();
478 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
479 ASSERT(xen_dma_adapter);
480 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
482 sg_extra = (sg_extra_t *)((PUCHAR)sg_list + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
483 (sizeof(SCATTER_GATHER_ELEMENT)) * sg_list->NumberOfElements);
485 switch (sg_extra->map_type)
486 {
487 case MAP_TYPE_REMAPPED:
488 for (i = 0; i < sg_list->NumberOfElements; i++)
489 {
490 grant_ref_t gref;
491 gref = (grant_ref_t)(sg_list->Elements[i].Address.QuadPart >> PAGE_SHIFT);
492 GntTbl_EndAccess(xpdd, gref, FALSE);
493 sg_list->Elements[i].Address.QuadPart = -1;
494 }
495 ASSERT(sg_extra->mdl);
496 if (!WriteToDevice)
497 {
498 for (curr_mdl = sg_extra->mdl, offset = 0, active = FALSE; curr_mdl && offset < sg_extra->copy_length; curr_mdl = curr_mdl->Next)
499 {
500 PVOID mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
501 ULONG mdl_byte_count = MmGetMdlByteCount(curr_mdl);
502 ULONG mdl_offset = 0;
503 /* need to use <= va + len - 1 to avoid ptr wraparound */
504 if ((UINT_PTR)sg_extra->currentva >= (UINT_PTR)mdl_start_va && (UINT_PTR)sg_extra->currentva <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
505 {
506 active = TRUE;
507 mdl_byte_count -= (ULONG)((UINT_PTR)sg_extra->currentva - (UINT_PTR)mdl_start_va);
508 if (offset + mdl_byte_count > sg_extra->copy_length)
509 mdl_byte_count = sg_extra->copy_length - offset;
510 mdl_offset = (ULONG)((UINT_PTR)sg_extra->currentva - (UINT_PTR)mdl_start_va);
511 mdl_start_va = sg_extra->currentva;
512 }
513 if (active)
514 {
515 PVOID unaligned_buffer;
516 unaligned_buffer = MmGetSystemAddressForMdlSafe(curr_mdl, NormalPagePriority);
517 ASSERT(unaligned_buffer); /* lazy */
518 memcpy((PUCHAR)unaligned_buffer + mdl_offset, (PUCHAR)sg_extra->aligned_buffer + offset, mdl_byte_count);
519 offset += mdl_byte_count;
520 }
521 }
522 ASSERT(offset == sg_extra->copy_length);
523 }
524 ExFreePoolWithTag(sg_extra->aligned_buffer, XENPCI_POOL_TAG);
525 break;
526 case MAP_TYPE_MDL:
527 for (i = 0; i < sg_list->NumberOfElements; i++)
528 {
529 grant_ref_t gref;
530 gref = (grant_ref_t)(sg_list->Elements[i].Address.QuadPart >> PAGE_SHIFT);
531 GntTbl_EndAccess(xpdd, gref, FALSE);
532 sg_list->Elements[i].Address.QuadPart = -1;
533 }
534 break;
535 case MAP_TYPE_VIRTUAL:
536 break;
537 }
538 if (sg_extra->allocated_by_me)
539 ExFreePoolWithTag(sg_list, XENPCI_POOL_TAG);
540 //FUNCTION_EXIT();
541 }
543 static NTSTATUS
544 XenPci_DOP_CalculateScatterGatherList(
545 PDMA_ADAPTER DmaAdapter,
546 PMDL Mdl,
547 PVOID CurrentVa,
548 ULONG Length,
549 PULONG ScatterGatherListSize,
550 PULONG NumberOfMapRegisters
551 )
552 {
553 xen_dma_adapter_t *xen_dma_adapter;
554 ULONG elements;
555 PMDL curr_mdl;
557 UNREFERENCED_PARAMETER(CurrentVa);
559 //FUNCTION_ENTER();
561 //KdPrint((__DRIVER_NAME " Mdl = %p\n", Mdl));
562 //KdPrint((__DRIVER_NAME " CurrentVa = %p\n", CurrentVa));
563 //KdPrint((__DRIVER_NAME " Length = %d\n", Length));
565 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
567 if (Mdl)
568 {
569 //if (CurrentVa != MmGetMdlVirtualAddress(Mdl))
570 //{
571 // KdPrint((__DRIVER_NAME " CurrentVa (%p) != MdlVa (%p)\n", CurrentVa, MmGetMdlVirtualAddress(Mdl)));
572 //
574 //KdPrint((__DRIVER_NAME " CurrentVa = %p, MdlVa = %p\n", CurrentVa, MmGetMdlVirtualAddress(Mdl)));
576 for (curr_mdl = Mdl, elements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
577 {
578 //KdPrint((__DRIVER_NAME " curr_mdlVa = %p, curr_mdl size = %d\n", MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)));
579 elements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
580 }
581 }
582 else
583 {
584 elements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, Length); // + 1;
585 }
587 if (elements > xen_dma_adapter->adapter_object.MapRegistersPerChannel)
588 {
589 //KdPrint((__DRIVER_NAME " elements = %d - too many\n", elements));
590 if (NumberOfMapRegisters)
591 *NumberOfMapRegisters = 0;
592 *ScatterGatherListSize = 0;
594 return STATUS_INSUFFICIENT_RESOURCES;
595 }
597 *ScatterGatherListSize = FIELD_OFFSET(SCATTER_GATHER_LIST, Elements)
598 + sizeof(SCATTER_GATHER_ELEMENT) * elements
599 + sizeof(sg_extra_t);
600 if (NumberOfMapRegisters)
601 *NumberOfMapRegisters = elements;
603 //KdPrint((__DRIVER_NAME " ScatterGatherListSize = %d, NumberOfMapRegisters = %d\n", *ScatterGatherListSize, elements));
605 //FUNCTION_EXIT();
606 return STATUS_SUCCESS;
607 }
609 static NTSTATUS
610 XenPci_DOP_BuildScatterGatherListButDontExecute(
611 IN PDMA_ADAPTER DmaAdapter,
612 IN PDEVICE_OBJECT DeviceObject,
613 IN PMDL Mdl,
614 IN PVOID CurrentVa,
615 IN ULONG Length,
616 IN BOOLEAN WriteToDevice,
617 IN PVOID ScatterGatherBuffer,
618 IN ULONG ScatterGatherBufferLength,
619 BOOLEAN allocated_by_me)
620 {
621 ULONG i;
622 PSCATTER_GATHER_LIST sglist = ScatterGatherBuffer;
623 PUCHAR ptr;
624 ULONG remaining = Length;
625 ULONG total_remaining;
626 xen_dma_adapter_t *xen_dma_adapter;
627 PXENPCI_DEVICE_DATA xpdd;
628 sg_extra_t *sg_extra;
629 PMDL curr_mdl;
630 ULONG map_type;
631 ULONG sg_element;
632 ULONG offset;
633 PFN_NUMBER pfn;
634 grant_ref_t gref;
635 BOOLEAN active;
636 PVOID mdl_start_va;
637 ULONG mdl_byte_count;
638 ULONG mdl_offset;
639 ULONG remapped_bytes = 0;
641 //FUNCTION_ENTER();
643 if (!ScatterGatherBuffer)
644 {
645 KdPrint((__DRIVER_NAME " NULL ScatterGatherBuffer\n"));
646 return STATUS_INVALID_PARAMETER;
647 }
648 //if (MmGetMdlVirtualAddress(Mdl) != CurrentVa)
649 //{
650 // KdPrint((__DRIVER_NAME " MmGetMdlVirtualAddress = %p, CurrentVa = %p, Length = %d\n", MmGetMdlVirtualAddress(Mdl), CurrentVa, Length));
651 //}
653 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
654 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
656 ASSERT(Mdl);
658 if (xen_dma_adapter->dma_extension)
659 {
660 if (xen_dma_adapter->dma_extension->need_virtual_address && xen_dma_adapter->dma_extension->need_virtual_address(DeviceObject->CurrentIrp))
661 {
662 ASSERT(!Mdl->Next); /* can only virtual a single buffer */
663 //ASSERT(MmGetMdlVirtualAddress(Mdl) == CurrentVa);
664 map_type = MAP_TYPE_VIRTUAL;
665 sglist->NumberOfElements = 1;
666 }
667 else
668 {
669 if (xen_dma_adapter->dma_extension->get_alignment)
670 {
671 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(DeviceObject->CurrentIrp);
673 map_type = MAP_TYPE_MDL;
674 sglist->NumberOfElements = 0;
675 for (curr_mdl = Mdl, remapped_bytes = 0, active = FALSE; remapped_bytes < Length && curr_mdl; curr_mdl = curr_mdl->Next)
676 {
677 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
678 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
679 /* need to use <= va + len - 1 to avoid ptr wraparound */
680 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
681 {
682 active = TRUE;
683 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
684 if (remapped_bytes + mdl_byte_count > Length)
685 mdl_byte_count = Length - remapped_bytes;
686 mdl_start_va = CurrentVa;
687 }
688 if (active)
689 {
690 if (((UINT_PTR)mdl_start_va & (alignment - 1)) || (mdl_byte_count & (alignment - 1)))
691 map_type = MAP_TYPE_REMAPPED;
692 remapped_bytes += mdl_byte_count;
693 if (remapped_bytes > Length)
694 remapped_bytes = Length;
695 }
696 }
697 if (remapped_bytes != Length)
698 {
699 KdPrint((__DRIVER_NAME " remapped_bytes = %d, Length = %d\n", remapped_bytes, Length));
700 }
701 //ASSERT(remapped_bytes == Length);
702 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(NULL, remapped_bytes);
703 }
704 else
705 {
706 map_type = MAP_TYPE_MDL;
707 }
708 }
709 }
710 else
711 {
712 map_type = MAP_TYPE_MDL;
713 }
714 if (map_type == MAP_TYPE_MDL)
715 {
716 for (curr_mdl = Mdl, sglist->NumberOfElements = 0, total_remaining = Length, active = FALSE; total_remaining > 0; curr_mdl = curr_mdl->Next)
717 {
718 ASSERT(curr_mdl);
719 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
720 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
721 /* need to use <= va + len - 1 to avoid ptr wraparound */
722 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
723 {
724 active = TRUE;
725 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
726 mdl_start_va = CurrentVa;
727 }
728 mdl_byte_count = min(mdl_byte_count, total_remaining);
729 if (active && mdl_byte_count)
730 {
731 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
732 mdl_start_va, mdl_byte_count);
733 total_remaining -= mdl_byte_count;
734 }
735 }
736 }
737 if (ScatterGatherBufferLength < FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
738 sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t))
739 {
740 //KdPrint((__DRIVER_NAME " STATUS_BUFFER_TOO_SMALL (%d < %d)\n", ScatterGatherBufferLength, FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
741 // sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t)));
742 return STATUS_BUFFER_TOO_SMALL;
743 }
745 if (map_type != MAP_TYPE_VIRTUAL)
746 {
747 for (sg_element = 0; sg_element < sglist->NumberOfElements; sg_element++)
748 {
749 gref = GntTbl_GetRef(xpdd);
750 if (gref == INVALID_GRANT_REF)
751 {
752 /* go back through the list and free the ones we allocated */
753 sglist->NumberOfElements = sg_element;
754 for (sg_element = 0; sg_element < sglist->NumberOfElements; sg_element++)
755 {
756 gref = (grant_ref_t)(sglist->Elements[sg_element].Address.QuadPart >> PAGE_SHIFT);
757 GntTbl_PutRef(xpdd, gref);
758 }
759 return STATUS_INSUFFICIENT_RESOURCES;
760 }
761 sglist->Elements[sg_element].Address.QuadPart = ((LONGLONG)gref << PAGE_SHIFT);
762 }
763 }
765 sg_extra = (sg_extra_t *)((PUCHAR)sglist + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
766 (sizeof(SCATTER_GATHER_ELEMENT)) * sglist->NumberOfElements);
768 sg_extra->allocated_by_me = allocated_by_me;
770 sg_extra->map_type = map_type;
771 switch (map_type)
772 {
773 case MAP_TYPE_MDL:
774 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL - %p\n", MmGetMdlVirtualAddress(Mdl)));
775 total_remaining = Length;
776 for (sg_element = 0, curr_mdl = Mdl, active = FALSE; total_remaining > 0; curr_mdl = curr_mdl->Next)
777 {
778 ASSERT(curr_mdl);
779 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
780 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
781 /* need to use <= va + len - 1 to avoid ptr wraparound */
782 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
783 {
784 active = TRUE;
785 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
786 mdl_start_va = CurrentVa;
787 }
788 if (active && mdl_byte_count)
789 {
790 ULONG pfn_offset;
791 remaining = min(mdl_byte_count, total_remaining);
792 offset = (ULONG)((UINT_PTR)mdl_start_va & (PAGE_SIZE - 1));
793 pfn_offset = (ULONG)(((UINT_PTR)mdl_start_va >> PAGE_SHIFT) - ((UINT_PTR)MmGetMdlVirtualAddress(curr_mdl) >> PAGE_SHIFT));
794 //for (i = 0; i < ADDRESS_AND_SIZE_TO_SPAN_PAGES(mdl_start_va, mdl_byte_count); i++)
795 for (i = 0; remaining > 0; i++)
796 {
797 pfn = MmGetMdlPfnArray(curr_mdl)[pfn_offset + i];
798 GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE,
799 (grant_ref_t)(sglist->Elements[sg_element].Address.QuadPart >> PAGE_SHIFT));
800 sglist->Elements[sg_element].Address.QuadPart |= (LONGLONG)offset;
801 sglist->Elements[sg_element].Length = min(min(PAGE_SIZE - offset, remaining), total_remaining);
802 total_remaining -= sglist->Elements[sg_element].Length;
803 remaining -= sglist->Elements[sg_element].Length;
804 offset = 0;
805 sg_element++;
806 }
807 }
808 }
809 if (sg_element != sglist->NumberOfElements)
810 {
811 KdPrint((__DRIVER_NAME " sg_element = %d, sglist->NumberOfElements = %d\n", sg_element, sglist->NumberOfElements));
812 KdPrint((__DRIVER_NAME " CurrentVa = %p, Length = %d\n", CurrentVa, Length));
813 for (curr_mdl = Mdl; curr_mdl; curr_mdl = curr_mdl->Next)
814 {
815 KdPrint((__DRIVER_NAME " Mdl = %p, VirtualAddress = %p, ByteCount = %d\n", Mdl, MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)));
816 }
817 }
818 ASSERT(sg_element == sglist->NumberOfElements);
819 break;
820 case MAP_TYPE_REMAPPED:
821 sg_extra->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, max(remapped_bytes, PAGE_SIZE), XENPCI_POOL_TAG);
822 if (!sg_extra->aligned_buffer)
823 {
824 KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED buffer allocation failed - requested va = %p, length = %d\n", MmGetMdlVirtualAddress(Mdl), remapped_bytes));
825 return STATUS_INSUFFICIENT_RESOURCES;
826 }
827 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED - %p, %d\n", sg_extra->aligned_buffer, remapped_bytes));
828 //KdPrint((__DRIVER_NAME " CurrentVa = %p, Length = %d\n", CurrentVa, Length));
829 //for (curr_mdl = Mdl; curr_mdl; curr_mdl = curr_mdl->Next)
830 //{
831 // KdPrint((__DRIVER_NAME " Mdl = %p, VirtualAddress = %p, ByteCount = %d\n", Mdl, MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)));
832 //}
833 sg_extra->mdl = Mdl;
834 sg_extra->currentva = CurrentVa;
835 sg_extra->copy_length = remapped_bytes;
837 if (WriteToDevice)
838 {
839 for (curr_mdl = Mdl, offset = 0, active = FALSE; curr_mdl && offset < Length; curr_mdl = curr_mdl->Next)
840 {
841 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
842 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
843 mdl_offset = 0;
844 /* need to use <= va + len - 1 to avoid ptr wraparound */
845 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
846 {
847 active = TRUE;
848 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
849 if (offset + mdl_byte_count > Length)
850 mdl_byte_count = Length - offset;
851 mdl_offset = (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
852 mdl_start_va = CurrentVa;
853 }
854 if (active)
855 {
856 PVOID unaligned_buffer;
857 unaligned_buffer = (PUCHAR)MmGetSystemAddressForMdlSafe(curr_mdl, NormalPagePriority);
858 ASSERT(unaligned_buffer); /* lazy */
859 memcpy((PUCHAR)sg_extra->aligned_buffer + offset, (PUCHAR)unaligned_buffer + mdl_offset, mdl_byte_count);
860 offset += mdl_byte_count;
861 }
862 }
863 }
864 for (sg_element = 0, remaining = remapped_bytes;
865 sg_element < ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_extra->aligned_buffer, remapped_bytes); sg_element++)
866 {
867 pfn = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)sg_extra->aligned_buffer + (sg_element << PAGE_SHIFT)).QuadPart >> PAGE_SHIFT);
868 GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE,
869 (grant_ref_t)(sglist->Elements[sg_element].Address.QuadPart >> PAGE_SHIFT));
870 sglist->Elements[sg_element].Length = min(PAGE_SIZE, remaining);
871 remaining -= sglist->Elements[sg_element].Length;
872 }
873 break;
874 case MAP_TYPE_VIRTUAL:
875 ptr = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
876 ASSERT(ptr); /* lazy */
877 sglist->Elements[0].Address.QuadPart = (ULONGLONG)ptr + ((UINT_PTR)CurrentVa - (UINT_PTR)MmGetMdlVirtualAddress(Mdl));
878 sglist->Elements[0].Length = Length;
879 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL - %08x\n", sglist->Elements[0].Address.LowPart));
880 break;
881 default:
882 KdPrint((__DRIVER_NAME " map_type = %d\n", map_type));
883 break;
884 }
885 //FUNCTION_EXIT();
886 return STATUS_SUCCESS;
887 }
889 static NTSTATUS
890 XenPci_DOP_BuildScatterGatherList(
891 IN PDMA_ADAPTER DmaAdapter,
892 IN PDEVICE_OBJECT DeviceObject,
893 IN PMDL Mdl,
894 IN PVOID CurrentVa,
895 IN ULONG Length,
896 IN PDRIVER_LIST_CONTROL ExecutionRoutine,
897 IN PVOID Context,
898 IN BOOLEAN WriteToDevice,
899 IN PVOID ScatterGatherBuffer,
900 IN ULONG ScatterGatherBufferLength)
901 {
902 NTSTATUS status;
904 status = XenPci_DOP_BuildScatterGatherListButDontExecute(DmaAdapter, DeviceObject, Mdl, CurrentVa, Length, WriteToDevice, ScatterGatherBuffer, ScatterGatherBufferLength, FALSE);
906 if (NT_SUCCESS(status))
907 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, ScatterGatherBuffer, Context);
909 //FUNCTION_EXIT();
911 return status;
912 }
914 static NTSTATUS
915 XenPci_DOP_GetScatterGatherList(
916 PDMA_ADAPTER DmaAdapter,
917 PDEVICE_OBJECT DeviceObject,
918 PMDL Mdl,
919 PVOID CurrentVa,
920 ULONG Length,
921 PDRIVER_LIST_CONTROL ExecutionRoutine,
922 PVOID Context,
923 BOOLEAN WriteToDevice)
924 {
925 NTSTATUS status;
926 ULONG list_size;
927 ULONG map_registers;
928 PSCATTER_GATHER_LIST sg_list;
930 //FUNCTION_ENTER();
932 status = XenPci_DOP_CalculateScatterGatherList(DmaAdapter, Mdl, CurrentVa, Length, &list_size, &map_registers);
933 if (!NT_SUCCESS(status))
934 {
935 //FUNCTION_EXIT();
936 return status;
937 }
939 sg_list = ExAllocatePoolWithTag(NonPagedPool, list_size, XENPCI_POOL_TAG);
940 if (!sg_list)
941 {
942 KdPrint((__DRIVER_NAME " Cannot allocate memory for sg_list\n"));
943 //FUNCTION_EXIT();
944 return STATUS_INSUFFICIENT_RESOURCES;
945 }
947 status = XenPci_DOP_BuildScatterGatherListButDontExecute(DmaAdapter, DeviceObject, Mdl, CurrentVa, Length, WriteToDevice, sg_list, list_size, TRUE);
949 if (NT_SUCCESS(status))
950 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, sg_list, Context);
951 else
952 ExFreePoolWithTag(sg_list, XENPCI_POOL_TAG);
954 //FUNCTION_EXIT();
956 return status;
957 }
959 static NTSTATUS
960 XenPci_DOP_BuildMdlFromScatterGatherList(
961 PDMA_ADAPTER DmaAdapter,
962 PSCATTER_GATHER_LIST ScatterGather,
963 PMDL OriginalMdl,
964 PMDL *TargetMdl)
965 {
966 NTSTATUS status = STATUS_SUCCESS;
967 UNREFERENCED_PARAMETER(DmaAdapter);
968 UNREFERENCED_PARAMETER(ScatterGather);
969 UNREFERENCED_PARAMETER(OriginalMdl);
970 UNREFERENCED_PARAMETER(TargetMdl);
972 FUNCTION_ENTER();
974 if (OriginalMdl)
975 {
976 *TargetMdl = OriginalMdl;
977 }
978 else
979 {
980 *TargetMdl = NULL;
981 status = STATUS_INVALID_PARAMETER;
982 }
984 FUNCTION_EXIT();
986 return status;
987 }
989 PDMA_ADAPTER
990 XenPci_BIS_GetDmaAdapter(PVOID context, PDEVICE_DESCRIPTION device_description, PULONG number_of_map_registers)
991 {
992 xen_dma_adapter_t *xen_dma_adapter;
993 PDEVICE_OBJECT curr, prev;
994 PDRIVER_OBJECT fdo_driver_object;
995 PVOID fdo_driver_extension;
997 UNREFERENCED_PARAMETER(device_description);
999 FUNCTION_ENTER();
1001 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1002 KdPrint((__DRIVER_NAME " Device Description = %p:\n", device_description));
1003 KdPrint((__DRIVER_NAME " Version = %d\n", device_description->Version));
1004 KdPrint((__DRIVER_NAME " Master = %d\n", device_description->Master));
1005 KdPrint((__DRIVER_NAME " ScatterGather = %d\n", device_description->ScatterGather));
1006 KdPrint((__DRIVER_NAME " DemandMode = %d\n", device_description->DemandMode));
1007 KdPrint((__DRIVER_NAME " AutoInitialize = %d\n", device_description->AutoInitialize));
1008 KdPrint((__DRIVER_NAME " Dma32BitAddresses = %d\n", device_description->Dma32BitAddresses));
1009 KdPrint((__DRIVER_NAME " IgnoreCount = %d\n", device_description->IgnoreCount));
1010 KdPrint((__DRIVER_NAME " Dma64BitAddresses = %d\n", device_description->Dma64BitAddresses));
1011 KdPrint((__DRIVER_NAME " BusNumber = %d\n", device_description->BusNumber));
1012 KdPrint((__DRIVER_NAME " DmaChannel = %d\n", device_description->DmaChannel));
1013 KdPrint((__DRIVER_NAME " InterfaceType = %d\n", device_description->InterfaceType));
1014 KdPrint((__DRIVER_NAME " DmaWidth = %d\n", device_description->DmaWidth));
1015 KdPrint((__DRIVER_NAME " DmaSpeed = %d\n", device_description->DmaSpeed));
1016 KdPrint((__DRIVER_NAME " MaximumLength = %d\n", device_description->MaximumLength));
1017 KdPrint((__DRIVER_NAME " DmaPort = %d\n", device_description->DmaPort));
1019 if (!device_description->Master)
1020 return NULL;
1021 /*
1022 we have to allocate PAGE_SIZE bytes here because Windows thinks this is
1023 actually an ADAPTER_OBJECT, and then the verifier crashes because
1024 Windows accessed beyond the end of the structure :(
1025 */
1026 xen_dma_adapter = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
1027 ASSERT(xen_dma_adapter);
1028 RtlZeroMemory(xen_dma_adapter, PAGE_SIZE);
1030 switch(device_description->Version)
1032 case DEVICE_DESCRIPTION_VERSION1:
1033 xen_dma_adapter->adapter_object.DmaHeader.Version = 1;
1034 break;
1035 case DEVICE_DESCRIPTION_VERSION: /* ignore what the docs say here - DEVICE_DESCRIPTION_VERSION appears to mean the latest version */
1036 case DEVICE_DESCRIPTION_VERSION2:
1037 xen_dma_adapter->adapter_object.DmaHeader.Version = 2;
1038 break;
1039 default:
1040 KdPrint((__DRIVER_NAME " Unsupported device description version %d\n", device_description->Version));
1041 ExFreePoolWithTag(xen_dma_adapter, XENPCI_POOL_TAG);
1042 return NULL;
1045 xen_dma_adapter->xppdd = context;
1046 xen_dma_adapter->dma_extension = NULL;
1048 KdPrint((__DRIVER_NAME " About to call IoGetAttachedDeviceReference\n"));
1049 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(xen_dma_adapter->xppdd->wdf_device));
1050 KdPrint((__DRIVER_NAME " Before start of loop - curr = %p\n", curr));
1051 while (curr != NULL)
1053 fdo_driver_object = curr->DriverObject;
1054 if (fdo_driver_object)
1056 ObReferenceObject(fdo_driver_object);
1057 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC));
1058 if (fdo_driver_extension)
1060 xen_dma_adapter->dma_extension_driver = fdo_driver_object; /* so we can dereference it on putdmaadapter */
1061 xen_dma_adapter->dma_extension = (dma_driver_extension_t *)fdo_driver_extension;
1062 ObDereferenceObject(curr);
1063 break;
1065 else
1067 ObDereferenceObject(fdo_driver_object);
1070 prev = curr;
1071 curr = IoGetLowerDeviceObject(curr);
1072 ObDereferenceObject(prev);
1074 KdPrint((__DRIVER_NAME " End of loop\n"));
1076 xen_dma_adapter->adapter_object.DmaHeader.Size = sizeof(X_ADAPTER_OBJECT); //xen_dma_adapter_t);
1077 xen_dma_adapter->adapter_object.MasterAdapter = NULL;
1078 if (xen_dma_adapter->dma_extension && xen_dma_adapter->dma_extension->max_sg_elements)
1080 xen_dma_adapter->adapter_object.MapRegistersPerChannel = xen_dma_adapter->dma_extension->max_sg_elements;
1082 else
1084 xen_dma_adapter->adapter_object.MapRegistersPerChannel = 256;
1086 xen_dma_adapter->adapter_object.AdapterBaseVa = NULL;
1087 xen_dma_adapter->adapter_object.MapRegisterBase = NULL;
1088 xen_dma_adapter->adapter_object.NumberOfMapRegisters = 0;
1089 xen_dma_adapter->adapter_object.CommittedMapRegisters = 0;
1090 xen_dma_adapter->adapter_object.CurrentWcb = NULL;
1091 KeInitializeDeviceQueue(&xen_dma_adapter->adapter_object.ChannelWaitQueue);
1092 xen_dma_adapter->adapter_object.RegisterWaitQueue = NULL;
1093 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterQueue);
1094 KeInitializeSpinLock(&xen_dma_adapter->adapter_object.SpinLock);
1095 xen_dma_adapter->adapter_object.MapRegisters = NULL;
1096 xen_dma_adapter->adapter_object.PagePort = NULL;
1097 xen_dma_adapter->adapter_object.ChannelNumber = 0xff;
1098 xen_dma_adapter->adapter_object.AdapterNumber = 0;
1099 xen_dma_adapter->adapter_object.DmaPortAddress = 0;
1100 xen_dma_adapter->adapter_object.AdapterMode = 0;
1101 xen_dma_adapter->adapter_object.NeedsMapRegisters = FALSE; /* when true this causes a crash in the crash dump path */
1102 xen_dma_adapter->adapter_object.MasterDevice = 1;
1103 xen_dma_adapter->adapter_object.Width16Bits = 0;
1104 xen_dma_adapter->adapter_object.ScatterGather = device_description->ScatterGather;
1105 xen_dma_adapter->adapter_object.IgnoreCount = device_description->IgnoreCount;
1106 xen_dma_adapter->adapter_object.Dma32BitAddresses = device_description->Dma32BitAddresses;
1107 xen_dma_adapter->adapter_object.Dma64BitAddresses = device_description->Dma64BitAddresses;
1108 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterList);
1110 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DMA_OPERATIONS), XENPCI_POOL_TAG);
1111 ASSERT(xen_dma_adapter->adapter_object.DmaHeader.DmaOperations);
1112 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 1)
1114 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = FIELD_OFFSET(DMA_OPERATIONS, CalculateScatterGatherList);
1116 else
1118 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = sizeof(DMA_OPERATIONS);
1120 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutDmaAdapter = XenPci_DOP_PutDmaAdapter;
1121 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateCommonBuffer = XenPci_DOP_AllocateCommonBuffer;
1122 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeCommonBuffer = XenPci_DOP_FreeCommonBuffer;
1123 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateAdapterChannel = XenPci_DOP_AllocateAdapterChannel;
1124 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FlushAdapterBuffers = XenPci_DOP_FlushAdapterBuffers;
1125 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeAdapterChannel = XenPci_DOP_FreeAdapterChannel;
1126 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeMapRegisters = XenPci_DOP_FreeMapRegisters;
1127 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->MapTransfer = XenPci_DOP_MapTransfer;
1128 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetDmaAlignment = XenPci_DOP_GetDmaAlignment;
1129 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->ReadDmaCounter = XenPci_DOP_ReadDmaCounter;
1130 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetScatterGatherList = XenPci_DOP_GetScatterGatherList;
1131 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutScatterGatherList = XenPci_DOP_PutScatterGatherList;
1132 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 2)
1134 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->CalculateScatterGatherList = XenPci_DOP_CalculateScatterGatherList;
1135 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildScatterGatherList = XenPci_DOP_BuildScatterGatherList;
1136 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildMdlFromScatterGatherList = XenPci_DOP_BuildMdlFromScatterGatherList;
1139 *number_of_map_registers = xen_dma_adapter->adapter_object.MapRegistersPerChannel; //1024; /* why not... */
1141 FUNCTION_EXIT();
1143 return &xen_dma_adapter->adapter_object.DmaHeader;
1146 ULONG
1147 XenPci_BIS_SetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
1149 UNREFERENCED_PARAMETER(context);
1150 UNREFERENCED_PARAMETER(data_type);
1151 UNREFERENCED_PARAMETER(buffer);
1152 UNREFERENCED_PARAMETER(offset);
1153 UNREFERENCED_PARAMETER(length);
1155 FUNCTION_ENTER();
1156 FUNCTION_EXIT();
1157 return 0;
1160 ULONG
1161 XenPci_BIS_GetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
1163 UNREFERENCED_PARAMETER(context);
1164 UNREFERENCED_PARAMETER(data_type);
1165 UNREFERENCED_PARAMETER(buffer);
1166 UNREFERENCED_PARAMETER(offset);
1167 UNREFERENCED_PARAMETER(length);
1169 FUNCTION_ENTER();
1170 FUNCTION_EXIT();
1171 return 0;