win-pvdrivers

view xenpci/xenpci_dma.c @ 685:c13ccf5a629b

Fixed a bug in the dma routines which was causing memory corruption. In some cases when Windows gave an MDL that was longer than the buffer to be dma'd, the end of the buffer would be overwritten. The only time I am aware of this occuring is on one particular map in Call Of Duty 4.

Split out the dma routines from xenpci_pdo.c into xenpci_dma.c
author James Harper <james.harper@bendigoit.com.au>
date Wed Oct 14 14:46:39 2009 +1100 (2009-10-14)
parents
children c3e410ac288f
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 IO_ALLOCATION_ACTION action;
167 map_register_base_t *map_register_base;
169 UNREFERENCED_PARAMETER(dma_adapter);
171 //FUNCTION_ENTER();
173 map_register_base = ExAllocatePoolWithTag(NonPagedPool,
174 FIELD_OFFSET(map_register_base_t, regs) + NumberOfMapRegisters * sizeof(map_register_t), XENPCI_POOL_TAG);
175 if (!map_register_base)
176 {
177 KdPrint((__DRIVER_NAME " Cannot allocate memory for map_register_base\n"));
178 //FUNCTION_EXIT();
179 return STATUS_INSUFFICIENT_RESOURCES;
180 }
181 /* we should also allocate a single page of memory here for remap purposes as once we allocate the map registers there is no failure allowed */
182 map_register_base->device_object = device_object;
183 map_register_base->total_map_registers = NumberOfMapRegisters;
184 map_register_base->count = 0;
186 action = ExecutionRoutine(device_object, device_object->CurrentIrp, map_register_base, Context);
188 switch (action)
189 {
190 case KeepObject:
191 KdPrint((__DRIVER_NAME " KeepObject\n"));
192 ASSERT(FALSE);
193 break;
194 case DeallocateObject:
195 KdPrint((__DRIVER_NAME " DeallocateObject\n"));
196 ASSERT(FALSE);
197 break;
198 case DeallocateObjectKeepRegisters:
199 //KdPrint((__DRIVER_NAME " DeallocateObjectKeepRegisters\n"));
200 break;
201 default:
202 KdPrint((__DRIVER_NAME " Unknown action %d\n", action));
203 ASSERT(FALSE);
204 break;
205 }
206 //FUNCTION_EXIT();
207 return STATUS_SUCCESS;
208 }
210 static BOOLEAN
211 XenPci_DOP_FlushAdapterBuffers(
212 PDMA_ADAPTER dma_adapter,
213 PMDL mdl,
214 PVOID MapRegisterBase,
215 PVOID CurrentVa,
216 ULONG Length,
217 BOOLEAN write_to_device)
218 {
219 //xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
220 //PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
221 map_register_base_t *map_register_base = MapRegisterBase;
222 map_register_t *map_register;
223 ULONG i;
225 UNREFERENCED_PARAMETER(dma_adapter);
226 UNREFERENCED_PARAMETER(mdl);
227 UNREFERENCED_PARAMETER(CurrentVa);
228 UNREFERENCED_PARAMETER(Length);
230 //FUNCTION_ENTER();
232 for (i = 0; i < map_register_base->count; i++)
233 {
234 map_register = &map_register_base->regs[i];
235 if (map_register->map_type == MAP_TYPE_REMAPPED && !write_to_device)
236 memcpy(map_register->unaligned_buffer, map_register->aligned_buffer, map_register->copy_length);
237 }
238 //FUNCTION_EXIT();
240 return TRUE;
241 }
243 static VOID
244 XenPci_DOP_FreeAdapterChannel(
245 IN PDMA_ADAPTER DmaAdapter
246 )
247 {
248 UNREFERENCED_PARAMETER(DmaAdapter);
250 FUNCTION_ENTER();
251 FUNCTION_EXIT();
252 }
254 static VOID
255 XenPci_DOP_FreeMapRegisters(
256 PDMA_ADAPTER dma_adapter,
257 PVOID MapRegisterBase,
258 ULONG NumberOfMapRegisters)
259 {
260 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
261 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
262 map_register_base_t *map_register_base = MapRegisterBase;
263 map_register_t *map_register;
264 ULONG i;
265 grant_ref_t gref;
267 //FUNCTION_ENTER();
268 if (!map_register_base)
269 {
270 /* i'm not sure if this is ideal here, but NDIS definitely does it */
271 return;
272 }
273 ASSERT(map_register_base->total_map_registers == NumberOfMapRegisters);
275 for (i = 0; i < map_register_base->count; i++)
276 {
277 map_register = &map_register_base->regs[i];
278 switch (map_register->map_type)
279 {
280 case MAP_TYPE_REMAPPED:
281 gref = (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT);
282 GntTbl_EndAccess(xpdd, gref, FALSE);
283 ExFreePoolWithTag(map_register->aligned_buffer, XENPCI_POOL_TAG);
284 break;
285 case MAP_TYPE_MDL:
286 gref = (grant_ref_t)(map_register->logical.QuadPart >> PAGE_SHIFT);
287 GntTbl_EndAccess(xpdd, gref, FALSE);
288 break;
289 case MAP_TYPE_VIRTUAL:
290 break;
291 }
292 }
293 ExFreePoolWithTag(map_register_base, XENPCI_POOL_TAG);
295 //FUNCTION_EXIT();
296 }
298 static PHYSICAL_ADDRESS
299 XenPci_DOP_MapTransfer(
300 PDMA_ADAPTER dma_adapter,
301 PMDL mdl,
302 PVOID MapRegisterBase,
303 PVOID CurrentVa,
304 PULONG Length,
305 BOOLEAN WriteToDevice)
306 {
307 xen_dma_adapter_t *xen_dma_adapter = (xen_dma_adapter_t *)dma_adapter;
308 PXENPCI_DEVICE_DATA xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
309 map_register_base_t *map_register_base = MapRegisterBase;
310 map_register_t *map_register = &map_register_base->regs[map_register_base->count];
311 PDEVICE_OBJECT device_object = map_register_base->device_object;
312 ULONG page_offset;
313 PFN_NUMBER pfn;
314 grant_ref_t gref;
315 PUCHAR ptr;
316 ULONG mdl_offset;
317 ULONG pfn_index;
319 //FUNCTION_ENTER();
321 //KdPrint((__DRIVER_NAME " Mdl = %p, MapRegisterBase = %p, MdlVa = %p, CurrentVa = %p, Length = %d\n",
322 // mdl, MapRegisterBase, MmGetMdlVirtualAddress(mdl), CurrentVa, *Length));
324 ASSERT(mdl);
325 ASSERT(map_register_base);
326 ASSERT(map_register_base->count < map_register_base->total_map_registers);
328 if (xen_dma_adapter->dma_extension)
329 {
330 if (xen_dma_adapter->dma_extension->need_virtual_address && xen_dma_adapter->dma_extension->need_virtual_address(device_object->CurrentIrp))
331 {
332 map_register->map_type = MAP_TYPE_VIRTUAL;
333 }
334 else
335 {
336 if (xen_dma_adapter->dma_extension->get_alignment)
337 {
338 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(device_object->CurrentIrp);
339 if ((MmGetMdlByteOffset(mdl) & (alignment - 1)) || (MmGetMdlByteCount(mdl) & (alignment - 1)))
340 {
341 map_register->map_type = MAP_TYPE_REMAPPED;
342 }
343 else
344 {
345 map_register->map_type = MAP_TYPE_MDL;
346 }
347 }
348 else
349 {
350 map_register->map_type = MAP_TYPE_MDL;
351 }
352 }
353 }
354 else
355 {
356 map_register->map_type = MAP_TYPE_MDL;
357 }
359 switch (map_register->map_type)
360 {
361 case MAP_TYPE_MDL:
362 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL\n"));
363 mdl_offset = (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)MmGetMdlVirtualAddress(mdl));
364 page_offset = PtrToUlong(CurrentVa) & (PAGE_SIZE - 1);
365 *Length = min(*Length, PAGE_SIZE - page_offset);
366 pfn_index = (ULONG)(((UINT_PTR)CurrentVa >> PAGE_SHIFT) - ((UINT_PTR)MmGetMdlVirtualAddress(mdl) >> PAGE_SHIFT));
367 //KdPrint((__DRIVER_NAME " mdl_offset = %d, page_offset = %d, length = %d, pfn_index = %d\n",
368 // mdl_offset, page_offset, *Length, pfn_index));
369 pfn = MmGetMdlPfnArray(mdl)[pfn_index];
370 //KdPrint((__DRIVER_NAME " B Requesting Grant Ref\n"));
371 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
372 //KdPrint((__DRIVER_NAME " B Got Grant Ref %d\n", gref));
373 map_register->logical.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | page_offset;
374 map_register_base->count++;
375 break;
376 case MAP_TYPE_REMAPPED:
377 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED (MapTransfer)\n"));
378 //KdPrint((__DRIVER_NAME " Mdl = %p, MapRegisterBase = %p, MdlVa = %p, CurrentVa = %p, Length = %d\n",
379 // mdl, MapRegisterBase, MmGetMdlVirtualAddress(mdl), CurrentVa, *Length));
380 mdl_offset = (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)MmGetMdlVirtualAddress(mdl));
381 *Length = min(*Length, PAGE_SIZE);
382 map_register->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
383 ASSERT(map_register->aligned_buffer);
384 map_register->unaligned_buffer = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
385 ASSERT(map_register->unaligned_buffer); /* lazy */
386 map_register->unaligned_buffer = (PUCHAR)map_register->unaligned_buffer + mdl_offset;
387 map_register->copy_length = *Length;
388 if (WriteToDevice)
389 memcpy(map_register->aligned_buffer, map_register->unaligned_buffer, map_register->copy_length);
390 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(map_register->aligned_buffer).QuadPart >> PAGE_SHIFT);
391 //KdPrint((__DRIVER_NAME " C Requesting Grant Ref\n"));
392 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
393 //KdPrint((__DRIVER_NAME " C Got Grant Ref %d\n", gref));
394 map_register->logical.QuadPart = (LONGLONG)(gref << PAGE_SHIFT);
395 map_register_base->count++;
396 break;
397 case MAP_TYPE_VIRTUAL:
398 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL\n"));
399 ptr = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
400 ASSERT(ptr); /* lazy */
401 map_register->logical.QuadPart = (ULONGLONG)ptr;
402 map_register_base->count++;
403 break;
404 default:
405 ASSERT(FALSE);
406 break;
407 }
409 //KdPrint((__DRIVER_NAME " logical = %08x:%08x\n", map_register->logical.HighPart, map_register->logical.LowPart));
410 //FUNCTION_EXIT();
411 return map_register->logical;
412 }
414 static ULONG
415 XenPci_DOP_GetDmaAlignment(
416 PDMA_ADAPTER DmaAdapter)
417 {
418 UNREFERENCED_PARAMETER(DmaAdapter);
420 FUNCTION_ENTER();
421 FUNCTION_EXIT();
422 return 0;
423 }
425 static ULONG
426 XenPci_DOP_ReadDmaCounter(
427 PDMA_ADAPTER DmaAdapter)
428 {
429 UNREFERENCED_PARAMETER(DmaAdapter);
431 FUNCTION_ENTER();
432 FUNCTION_EXIT();
433 return 0;
434 }
436 static VOID
437 XenPci_DOP_PutScatterGatherList(
438 IN PDMA_ADAPTER DmaAdapter,
439 IN PSCATTER_GATHER_LIST sg_list,
440 IN BOOLEAN WriteToDevice
441 )
442 {
443 xen_dma_adapter_t *xen_dma_adapter;
444 PXENPCI_DEVICE_DATA xpdd;
445 ULONG i;
446 sg_extra_t *sg_extra;
447 PMDL curr_mdl;
448 ULONG offset;
449 BOOLEAN active;
451 UNREFERENCED_PARAMETER(WriteToDevice);
453 //FUNCTION_ENTER();
455 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
456 ASSERT(xen_dma_adapter);
457 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
459 sg_extra = (sg_extra_t *)((PUCHAR)sg_list + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
460 (sizeof(SCATTER_GATHER_ELEMENT)) * sg_list->NumberOfElements);
462 switch (sg_extra->map_type)
463 {
464 case MAP_TYPE_REMAPPED:
465 for (i = 0; i < sg_list->NumberOfElements; i++)
466 {
467 grant_ref_t gref;
468 gref = (grant_ref_t)(sg_list->Elements[i].Address.QuadPart >> PAGE_SHIFT);
469 GntTbl_EndAccess(xpdd, gref, FALSE);
470 sg_list->Elements[i].Address.QuadPart = -1;
471 }
472 ASSERT(sg_extra->mdl);
473 if (!WriteToDevice)
474 {
475 for (curr_mdl = sg_extra->mdl, offset = 0, active = FALSE; curr_mdl && offset < sg_extra->copy_length; curr_mdl = curr_mdl->Next)
476 {
477 PVOID mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
478 ULONG mdl_byte_count = MmGetMdlByteCount(curr_mdl);
479 ULONG mdl_offset = 0;
480 /* need to use <= va + len - 1 to avoid ptr wraparound */
481 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)
482 {
483 active = TRUE;
484 mdl_byte_count -= (ULONG)((UINT_PTR)sg_extra->currentva - (UINT_PTR)mdl_start_va);
485 if (offset + mdl_byte_count > sg_extra->copy_length)
486 mdl_byte_count = sg_extra->copy_length - offset;
487 mdl_offset = (ULONG)((UINT_PTR)sg_extra->currentva - (UINT_PTR)mdl_start_va);
488 mdl_start_va = sg_extra->currentva;
489 }
490 if (active)
491 {
492 PVOID unaligned_buffer;
493 unaligned_buffer = MmGetSystemAddressForMdlSafe(curr_mdl, NormalPagePriority);
494 ASSERT(unaligned_buffer); /* lazy */
495 memcpy((PUCHAR)unaligned_buffer + mdl_offset, (PUCHAR)sg_extra->aligned_buffer + offset, mdl_byte_count);
496 offset += mdl_byte_count;
497 }
498 }
499 ASSERT(offset == sg_extra->copy_length);
500 }
501 ExFreePoolWithTag(sg_extra->aligned_buffer, XENPCI_POOL_TAG);
502 break;
503 case MAP_TYPE_MDL:
504 for (i = 0; i < sg_list->NumberOfElements; i++)
505 {
506 grant_ref_t gref;
507 gref = (grant_ref_t)(sg_list->Elements[i].Address.QuadPart >> PAGE_SHIFT);
508 GntTbl_EndAccess(xpdd, gref, FALSE);
509 sg_list->Elements[i].Address.QuadPart = -1;
510 }
511 break;
512 case MAP_TYPE_VIRTUAL:
513 break;
514 }
515 if (sg_extra->allocated_by_me)
516 ExFreePoolWithTag(sg_list, XENPCI_POOL_TAG);
517 //FUNCTION_EXIT();
518 }
520 static NTSTATUS
521 XenPci_DOP_CalculateScatterGatherList(
522 PDMA_ADAPTER DmaAdapter,
523 PMDL Mdl,
524 PVOID CurrentVa,
525 ULONG Length,
526 PULONG ScatterGatherListSize,
527 PULONG NumberOfMapRegisters
528 )
529 {
530 xen_dma_adapter_t *xen_dma_adapter;
531 ULONG elements;
532 PMDL curr_mdl;
534 UNREFERENCED_PARAMETER(CurrentVa);
536 //FUNCTION_ENTER();
538 //KdPrint((__DRIVER_NAME " Mdl = %p\n", Mdl));
539 //KdPrint((__DRIVER_NAME " CurrentVa = %p\n", CurrentVa));
540 //KdPrint((__DRIVER_NAME " Length = %d\n", Length));
542 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
544 if (Mdl)
545 {
546 //if (CurrentVa != MmGetMdlVirtualAddress(Mdl))
547 //{
548 // KdPrint((__DRIVER_NAME " CurrentVa (%p) != MdlVa (%p)\n", CurrentVa, MmGetMdlVirtualAddress(Mdl)));
549 //
551 //KdPrint((__DRIVER_NAME " CurrentVa = %p, MdlVa = %p\n", CurrentVa, MmGetMdlVirtualAddress(Mdl)));
553 for (curr_mdl = Mdl, elements = 0; curr_mdl; curr_mdl = curr_mdl->Next)
554 {
555 //KdPrint((__DRIVER_NAME " curr_mdlVa = %p, curr_mdl size = %d\n", MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)));
556 elements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl));
557 }
558 }
559 else
560 {
561 elements = ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, Length); // + 1;
562 }
564 if (elements > xen_dma_adapter->adapter_object.MapRegistersPerChannel)
565 {
566 //KdPrint((__DRIVER_NAME " elements = %d - too many\n", elements));
567 if (NumberOfMapRegisters)
568 *NumberOfMapRegisters = 0;
569 *ScatterGatherListSize = 0;
571 return STATUS_INSUFFICIENT_RESOURCES;
572 }
574 *ScatterGatherListSize = FIELD_OFFSET(SCATTER_GATHER_LIST, Elements)
575 + sizeof(SCATTER_GATHER_ELEMENT) * elements
576 + sizeof(sg_extra_t);
577 if (NumberOfMapRegisters)
578 *NumberOfMapRegisters = elements;
580 //KdPrint((__DRIVER_NAME " ScatterGatherListSize = %d, NumberOfMapRegisters = %d\n", *ScatterGatherListSize, elements));
582 //FUNCTION_EXIT();
583 return STATUS_SUCCESS;
584 }
586 static NTSTATUS
587 XenPci_DOP_BuildScatterGatherListButDontExecute(
588 IN PDMA_ADAPTER DmaAdapter,
589 IN PDEVICE_OBJECT DeviceObject,
590 IN PMDL Mdl,
591 IN PVOID CurrentVa,
592 IN ULONG Length,
593 IN BOOLEAN WriteToDevice,
594 IN PVOID ScatterGatherBuffer,
595 IN ULONG ScatterGatherBufferLength,
596 BOOLEAN allocated_by_me)
597 {
598 ULONG i;
599 PSCATTER_GATHER_LIST sglist = ScatterGatherBuffer;
600 PUCHAR ptr;
601 ULONG remaining = Length;
602 ULONG total_remaining;
603 xen_dma_adapter_t *xen_dma_adapter;
604 PXENPCI_DEVICE_DATA xpdd;
605 sg_extra_t *sg_extra;
606 PMDL curr_mdl;
607 ULONG map_type;
608 ULONG sg_element;
609 ULONG offset;
610 PFN_NUMBER pfn;
611 grant_ref_t gref;
612 BOOLEAN active;
613 PVOID mdl_start_va;
614 ULONG mdl_byte_count;
615 ULONG mdl_offset;
616 ULONG remapped_bytes = 0;
618 //FUNCTION_ENTER();
620 if (!ScatterGatherBuffer)
621 {
622 KdPrint((__DRIVER_NAME " NULL ScatterGatherBuffer\n"));
623 return STATUS_INVALID_PARAMETER;
624 }
625 //if (MmGetMdlVirtualAddress(Mdl) != CurrentVa)
626 //{
627 // KdPrint((__DRIVER_NAME " MmGetMdlVirtualAddress = %p, CurrentVa = %p, Length = %d\n", MmGetMdlVirtualAddress(Mdl), CurrentVa, Length));
628 //}
630 xen_dma_adapter = (xen_dma_adapter_t *)DmaAdapter;
631 xpdd = GetXpdd(xen_dma_adapter->xppdd->wdf_device_bus_fdo);
633 ASSERT(Mdl);
635 if (xen_dma_adapter->dma_extension)
636 {
637 if (xen_dma_adapter->dma_extension->need_virtual_address && xen_dma_adapter->dma_extension->need_virtual_address(DeviceObject->CurrentIrp))
638 {
639 ASSERT(!Mdl->Next); /* can only virtual a single buffer */
640 //ASSERT(MmGetMdlVirtualAddress(Mdl) == CurrentVa);
641 map_type = MAP_TYPE_VIRTUAL;
642 sglist->NumberOfElements = 1;
643 }
644 else
645 {
646 if (xen_dma_adapter->dma_extension->get_alignment)
647 {
648 ULONG alignment = xen_dma_adapter->dma_extension->get_alignment(DeviceObject->CurrentIrp);
650 map_type = MAP_TYPE_MDL;
651 sglist->NumberOfElements = 0;
652 for (curr_mdl = Mdl, remapped_bytes = 0, active = FALSE; remapped_bytes < Length && curr_mdl; curr_mdl = curr_mdl->Next)
653 {
654 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
655 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
656 /* need to use <= va + len - 1 to avoid ptr wraparound */
657 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
658 {
659 active = TRUE;
660 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
661 if (remapped_bytes + mdl_byte_count > Length)
662 mdl_byte_count = Length - remapped_bytes;
663 mdl_start_va = CurrentVa;
664 }
665 if (active)
666 {
667 if (((UINT_PTR)mdl_start_va & (alignment - 1)) || (mdl_byte_count & (alignment - 1)))
668 map_type = MAP_TYPE_REMAPPED;
669 remapped_bytes += mdl_byte_count;
670 if (remapped_bytes > Length)
671 remapped_bytes = Length;
672 }
673 }
674 if (remapped_bytes != Length)
675 {
676 KdPrint((__DRIVER_NAME " remapped_bytes = %d, Length = %d\n", remapped_bytes, Length));
677 }
678 //ASSERT(remapped_bytes == Length);
679 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(NULL, remapped_bytes);
680 }
681 else
682 {
683 map_type = MAP_TYPE_MDL;
684 }
685 }
686 }
687 else
688 {
689 map_type = MAP_TYPE_MDL;
690 }
691 if (map_type == MAP_TYPE_MDL)
692 {
693 for (curr_mdl = Mdl, sglist->NumberOfElements = 0, total_remaining = Length, active = FALSE; total_remaining > 0; curr_mdl = curr_mdl->Next)
694 {
695 ASSERT(curr_mdl);
696 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
697 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
698 /* need to use <= va + len - 1 to avoid ptr wraparound */
699 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
700 {
701 active = TRUE;
702 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
703 mdl_start_va = CurrentVa;
704 }
705 mdl_byte_count = min(mdl_byte_count, total_remaining);
706 if (active && mdl_byte_count)
707 {
708 sglist->NumberOfElements += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
709 mdl_start_va, mdl_byte_count);
710 total_remaining -= mdl_byte_count;
711 }
712 }
713 }
714 if (ScatterGatherBufferLength < FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
715 sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t))
716 {
717 //KdPrint((__DRIVER_NAME " STATUS_BUFFER_TOO_SMALL (%d < %d)\n", ScatterGatherBufferLength, FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
718 // sizeof(SCATTER_GATHER_ELEMENT) * sglist->NumberOfElements + sizeof(sg_extra_t)));
719 return STATUS_BUFFER_TOO_SMALL;
720 }
722 sg_extra = (sg_extra_t *)((PUCHAR)sglist + FIELD_OFFSET(SCATTER_GATHER_LIST, Elements) +
723 (sizeof(SCATTER_GATHER_ELEMENT)) * sglist->NumberOfElements);
725 sg_extra->allocated_by_me = allocated_by_me;
727 sg_extra->map_type = map_type;
728 switch (map_type)
729 {
730 case MAP_TYPE_MDL:
731 //KdPrint((__DRIVER_NAME " MAP_TYPE_MDL - %p\n", MmGetMdlVirtualAddress(Mdl)));
732 total_remaining = Length;
733 for (sg_element = 0, curr_mdl = Mdl, active = FALSE; total_remaining > 0; curr_mdl = curr_mdl->Next)
734 {
735 ASSERT(curr_mdl);
736 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
737 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
738 /* need to use <= va + len - 1 to avoid ptr wraparound */
739 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
740 {
741 active = TRUE;
742 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
743 mdl_start_va = CurrentVa;
744 }
745 if (active && mdl_byte_count)
746 {
747 ULONG pfn_offset;
748 remaining = min(mdl_byte_count, total_remaining);
749 offset = (ULONG)((UINT_PTR)mdl_start_va & (PAGE_SIZE - 1));
750 pfn_offset = (ULONG)(((UINT_PTR)mdl_start_va >> PAGE_SHIFT) - ((UINT_PTR)MmGetMdlVirtualAddress(curr_mdl) >> PAGE_SHIFT));
751 //for (i = 0; i < ADDRESS_AND_SIZE_TO_SPAN_PAGES(mdl_start_va, mdl_byte_count); i++)
752 for (i = 0; remaining > 0; i++)
753 {
754 pfn = MmGetMdlPfnArray(curr_mdl)[pfn_offset + i];
755 ASSERT(pfn);
756 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
757 ASSERT(gref != INVALID_GRANT_REF);
758 sglist->Elements[sg_element].Address.QuadPart = (LONGLONG)(gref << PAGE_SHIFT) | offset;
759 sglist->Elements[sg_element].Length = min(min(PAGE_SIZE - offset, remaining), total_remaining);
760 total_remaining -= sglist->Elements[sg_element].Length;
761 remaining -= sglist->Elements[sg_element].Length;
762 offset = 0;
763 sg_element++;
764 }
765 }
766 }
767 if (sg_element != sglist->NumberOfElements)
768 {
769 KdPrint((__DRIVER_NAME " sg_element = %d, sglist->NumberOfElements = %d\n", sg_element, sglist->NumberOfElements));
770 KdPrint((__DRIVER_NAME " CurrentVa = %p, Length = %d\n", CurrentVa, Length));
771 for (curr_mdl = Mdl; curr_mdl; curr_mdl = curr_mdl->Next)
772 {
773 KdPrint((__DRIVER_NAME " Mdl = %p, VirtualAddress = %p, ByteCount = %d\n", Mdl, MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)));
774 }
775 }
776 ASSERT(sg_element == sglist->NumberOfElements);
777 break;
778 case MAP_TYPE_REMAPPED:
779 sg_extra->aligned_buffer = ExAllocatePoolWithTag(NonPagedPool, max(remapped_bytes, PAGE_SIZE), XENPCI_POOL_TAG);
780 if (!sg_extra->aligned_buffer)
781 {
782 KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED buffer allocation failed - requested va = %p, length = %d\n", MmGetMdlVirtualAddress(Mdl), remapped_bytes));
783 return STATUS_INSUFFICIENT_RESOURCES;
784 }
785 //KdPrint((__DRIVER_NAME " MAP_TYPE_REMAPPED - %p, %d\n", sg_extra->aligned_buffer, remapped_bytes));
786 //KdPrint((__DRIVER_NAME " CurrentVa = %p, Length = %d\n", CurrentVa, Length));
787 //for (curr_mdl = Mdl; curr_mdl; curr_mdl = curr_mdl->Next)
788 //{
789 // KdPrint((__DRIVER_NAME " Mdl = %p, VirtualAddress = %p, ByteCount = %d\n", Mdl, MmGetMdlVirtualAddress(curr_mdl), MmGetMdlByteCount(curr_mdl)));
790 //}
791 sg_extra->mdl = Mdl;
792 sg_extra->currentva = CurrentVa;
793 sg_extra->copy_length = remapped_bytes;
795 if (WriteToDevice)
796 {
797 for (curr_mdl = Mdl, offset = 0, active = FALSE; curr_mdl && offset < Length; curr_mdl = curr_mdl->Next)
798 {
799 mdl_start_va = MmGetMdlVirtualAddress(curr_mdl);
800 mdl_byte_count = MmGetMdlByteCount(curr_mdl);
801 mdl_offset = 0;
802 /* need to use <= va + len - 1 to avoid ptr wraparound */
803 if ((UINT_PTR)CurrentVa >= (UINT_PTR)mdl_start_va && (UINT_PTR)CurrentVa <= (UINT_PTR)mdl_start_va + mdl_byte_count - 1)
804 {
805 active = TRUE;
806 mdl_byte_count -= (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
807 if (offset + mdl_byte_count > Length)
808 mdl_byte_count = Length - offset;
809 mdl_offset = (ULONG)((UINT_PTR)CurrentVa - (UINT_PTR)mdl_start_va);
810 mdl_start_va = CurrentVa;
811 }
812 if (active)
813 {
814 PVOID unaligned_buffer;
815 unaligned_buffer = (PUCHAR)MmGetSystemAddressForMdlSafe(curr_mdl, NormalPagePriority);
816 ASSERT(unaligned_buffer); /* lazy */
817 memcpy((PUCHAR)sg_extra->aligned_buffer + offset, (PUCHAR)unaligned_buffer + mdl_offset, mdl_byte_count);
818 offset += mdl_byte_count;
819 }
820 }
821 }
822 for (sg_element = 0, remaining = remapped_bytes;
823 sg_element < ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_extra->aligned_buffer, remapped_bytes); sg_element++)
824 {
825 pfn = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)sg_extra->aligned_buffer + (sg_element << PAGE_SHIFT)).QuadPart >> PAGE_SHIFT);
826 ASSERT(pfn);
827 gref = (grant_ref_t)GntTbl_GrantAccess(xpdd, 0, (ULONG)pfn, FALSE, INVALID_GRANT_REF);
828 ASSERT(gref != INVALID_GRANT_REF);
829 sglist->Elements[sg_element].Address.QuadPart = (ULONGLONG)gref << PAGE_SHIFT;
830 sglist->Elements[sg_element].Length = min(PAGE_SIZE, remaining);
831 remaining -= sglist->Elements[sg_element].Length;
832 }
833 break;
834 case MAP_TYPE_VIRTUAL:
835 ptr = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
836 ASSERT(ptr); /* lazy */
837 sglist->Elements[0].Address.QuadPart = (ULONGLONG)ptr + ((UINT_PTR)CurrentVa - (UINT_PTR)MmGetMdlVirtualAddress(Mdl));
838 sglist->Elements[0].Length = Length;
839 //KdPrint((__DRIVER_NAME " MAP_TYPE_VIRTUAL - %08x\n", sglist->Elements[0].Address.LowPart));
840 break;
841 default:
842 KdPrint((__DRIVER_NAME " map_type = %d\n", map_type));
843 break;
844 }
845 //FUNCTION_EXIT();
846 return STATUS_SUCCESS;
847 }
849 static NTSTATUS
850 XenPci_DOP_BuildScatterGatherList(
851 IN PDMA_ADAPTER DmaAdapter,
852 IN PDEVICE_OBJECT DeviceObject,
853 IN PMDL Mdl,
854 IN PVOID CurrentVa,
855 IN ULONG Length,
856 IN PDRIVER_LIST_CONTROL ExecutionRoutine,
857 IN PVOID Context,
858 IN BOOLEAN WriteToDevice,
859 IN PVOID ScatterGatherBuffer,
860 IN ULONG ScatterGatherBufferLength)
861 {
862 NTSTATUS status;
864 status = XenPci_DOP_BuildScatterGatherListButDontExecute(DmaAdapter, DeviceObject, Mdl, CurrentVa, Length, WriteToDevice, ScatterGatherBuffer, ScatterGatherBufferLength, FALSE);
866 if (NT_SUCCESS(status))
867 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, ScatterGatherBuffer, Context);
869 //FUNCTION_EXIT();
871 return status;
872 }
874 static NTSTATUS
875 XenPci_DOP_GetScatterGatherList(
876 PDMA_ADAPTER DmaAdapter,
877 PDEVICE_OBJECT DeviceObject,
878 PMDL Mdl,
879 PVOID CurrentVa,
880 ULONG Length,
881 PDRIVER_LIST_CONTROL ExecutionRoutine,
882 PVOID Context,
883 BOOLEAN WriteToDevice)
884 {
885 NTSTATUS status;
886 ULONG list_size;
887 ULONG map_registers;
888 PSCATTER_GATHER_LIST sg_list;
890 //FUNCTION_ENTER();
892 status = XenPci_DOP_CalculateScatterGatherList(DmaAdapter, Mdl, CurrentVa, Length, &list_size, &map_registers);
893 if (!NT_SUCCESS(status))
894 {
895 //FUNCTION_EXIT();
896 return status;
897 }
899 sg_list = ExAllocatePoolWithTag(NonPagedPool, list_size, XENPCI_POOL_TAG);
900 if (!sg_list)
901 {
902 KdPrint((__DRIVER_NAME " Cannot allocate memory for sg_list\n"));
903 //FUNCTION_EXIT();
904 return STATUS_INSUFFICIENT_RESOURCES;
905 }
907 status = XenPci_DOP_BuildScatterGatherListButDontExecute(DmaAdapter, DeviceObject, Mdl, CurrentVa, Length, WriteToDevice, sg_list, list_size, TRUE);
909 if (NT_SUCCESS(status))
910 ExecutionRoutine(DeviceObject, DeviceObject->CurrentIrp, sg_list, Context);
912 //FUNCTION_EXIT();
914 return status;
915 }
917 static NTSTATUS
918 XenPci_DOP_BuildMdlFromScatterGatherList(
919 PDMA_ADAPTER DmaAdapter,
920 PSCATTER_GATHER_LIST ScatterGather,
921 PMDL OriginalMdl,
922 PMDL *TargetMdl)
923 {
924 NTSTATUS status = STATUS_SUCCESS;
925 UNREFERENCED_PARAMETER(DmaAdapter);
926 UNREFERENCED_PARAMETER(ScatterGather);
927 UNREFERENCED_PARAMETER(OriginalMdl);
928 UNREFERENCED_PARAMETER(TargetMdl);
930 FUNCTION_ENTER();
932 if (OriginalMdl)
933 {
934 *TargetMdl = OriginalMdl;
935 }
936 else
937 {
938 *TargetMdl = NULL;
939 status = STATUS_INVALID_PARAMETER;
940 }
942 FUNCTION_EXIT();
944 return status;
945 }
947 PDMA_ADAPTER
948 XenPci_BIS_GetDmaAdapter(PVOID context, PDEVICE_DESCRIPTION device_description, PULONG number_of_map_registers)
949 {
950 xen_dma_adapter_t *xen_dma_adapter;
951 PDEVICE_OBJECT curr, prev;
952 PDRIVER_OBJECT fdo_driver_object;
953 PVOID fdo_driver_extension;
955 UNREFERENCED_PARAMETER(device_description);
957 FUNCTION_ENTER();
959 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
960 KdPrint((__DRIVER_NAME " Device Description = %p:\n", device_description));
961 KdPrint((__DRIVER_NAME " Version = %d\n", device_description->Version));
962 KdPrint((__DRIVER_NAME " Master = %d\n", device_description->Master));
963 KdPrint((__DRIVER_NAME " ScatterGather = %d\n", device_description->ScatterGather));
964 KdPrint((__DRIVER_NAME " DemandMode = %d\n", device_description->DemandMode));
965 KdPrint((__DRIVER_NAME " AutoInitialize = %d\n", device_description->AutoInitialize));
966 KdPrint((__DRIVER_NAME " Dma32BitAddresses = %d\n", device_description->Dma32BitAddresses));
967 KdPrint((__DRIVER_NAME " IgnoreCount = %d\n", device_description->IgnoreCount));
968 KdPrint((__DRIVER_NAME " Dma64BitAddresses = %d\n", device_description->Dma64BitAddresses));
969 KdPrint((__DRIVER_NAME " BusNumber = %d\n", device_description->BusNumber));
970 KdPrint((__DRIVER_NAME " DmaChannel = %d\n", device_description->DmaChannel));
971 KdPrint((__DRIVER_NAME " InterfaceType = %d\n", device_description->InterfaceType));
972 KdPrint((__DRIVER_NAME " DmaWidth = %d\n", device_description->DmaWidth));
973 KdPrint((__DRIVER_NAME " DmaSpeed = %d\n", device_description->DmaSpeed));
974 KdPrint((__DRIVER_NAME " MaximumLength = %d\n", device_description->MaximumLength));
975 KdPrint((__DRIVER_NAME " DmaPort = %d\n", device_description->DmaPort));
977 if (!device_description->Master)
978 return NULL;
979 /*
980 we have to allocate PAGE_SIZE bytes here because Windows thinks this is
981 actually an ADAPTER_OBJECT, and then the verifier crashes because
982 Windows accessed beyond the end of the structure :(
983 */
984 xen_dma_adapter = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
985 ASSERT(xen_dma_adapter);
986 RtlZeroMemory(xen_dma_adapter, PAGE_SIZE);
988 switch(device_description->Version)
989 {
990 case DEVICE_DESCRIPTION_VERSION1:
991 xen_dma_adapter->adapter_object.DmaHeader.Version = 1;
992 break;
993 case DEVICE_DESCRIPTION_VERSION: /* ignore what the docs say here - DEVICE_DESCRIPTION_VERSION appears to mean the latest version */
994 case DEVICE_DESCRIPTION_VERSION2:
995 xen_dma_adapter->adapter_object.DmaHeader.Version = 2;
996 break;
997 default:
998 KdPrint((__DRIVER_NAME " Unsupported device description version %d\n", device_description->Version));
999 ExFreePoolWithTag(xen_dma_adapter, XENPCI_POOL_TAG);
1000 return NULL;
1003 xen_dma_adapter->xppdd = context;
1004 xen_dma_adapter->dma_extension = NULL;
1006 KdPrint((__DRIVER_NAME " About to call IoGetAttachedDeviceReference\n"));
1007 curr = IoGetAttachedDeviceReference(WdfDeviceWdmGetDeviceObject(xen_dma_adapter->xppdd->wdf_device));
1008 KdPrint((__DRIVER_NAME " Before start of loop - curr = %p\n", curr));
1009 while (curr != NULL)
1011 fdo_driver_object = curr->DriverObject;
1012 if (fdo_driver_object)
1014 ObReferenceObject(fdo_driver_object);
1015 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC));
1016 if (fdo_driver_extension)
1018 xen_dma_adapter->dma_extension_driver = fdo_driver_object; /* so we can dereference it on putdmaadapter */
1019 xen_dma_adapter->dma_extension = (dma_driver_extension_t *)fdo_driver_extension;
1020 ObDereferenceObject(curr);
1021 break;
1023 else
1025 ObDereferenceObject(fdo_driver_object);
1028 prev = curr;
1029 curr = IoGetLowerDeviceObject(curr);
1030 ObDereferenceObject(prev);
1032 KdPrint((__DRIVER_NAME " End of loop\n"));
1034 xen_dma_adapter->adapter_object.DmaHeader.Size = sizeof(X_ADAPTER_OBJECT); //xen_dma_adapter_t);
1035 xen_dma_adapter->adapter_object.MasterAdapter = NULL;
1036 if (xen_dma_adapter->dma_extension && xen_dma_adapter->dma_extension->max_sg_elements)
1038 xen_dma_adapter->adapter_object.MapRegistersPerChannel = xen_dma_adapter->dma_extension->max_sg_elements;
1040 else
1042 xen_dma_adapter->adapter_object.MapRegistersPerChannel = 256;
1044 xen_dma_adapter->adapter_object.AdapterBaseVa = NULL;
1045 xen_dma_adapter->adapter_object.MapRegisterBase = NULL;
1046 xen_dma_adapter->adapter_object.NumberOfMapRegisters = 0;
1047 xen_dma_adapter->adapter_object.CommittedMapRegisters = 0;
1048 xen_dma_adapter->adapter_object.CurrentWcb = NULL;
1049 KeInitializeDeviceQueue(&xen_dma_adapter->adapter_object.ChannelWaitQueue);
1050 xen_dma_adapter->adapter_object.RegisterWaitQueue = NULL;
1051 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterQueue);
1052 KeInitializeSpinLock(&xen_dma_adapter->adapter_object.SpinLock);
1053 xen_dma_adapter->adapter_object.MapRegisters = NULL;
1054 xen_dma_adapter->adapter_object.PagePort = NULL;
1055 xen_dma_adapter->adapter_object.ChannelNumber = 0xff;
1056 xen_dma_adapter->adapter_object.AdapterNumber = 0;
1057 xen_dma_adapter->adapter_object.DmaPortAddress = 0;
1058 xen_dma_adapter->adapter_object.AdapterMode = 0;
1059 xen_dma_adapter->adapter_object.NeedsMapRegisters = FALSE; /* when true this causes a crash in the crash dump path */
1060 xen_dma_adapter->adapter_object.MasterDevice = 1;
1061 xen_dma_adapter->adapter_object.Width16Bits = 0;
1062 xen_dma_adapter->adapter_object.ScatterGather = device_description->ScatterGather;
1063 xen_dma_adapter->adapter_object.IgnoreCount = device_description->IgnoreCount;
1064 xen_dma_adapter->adapter_object.Dma32BitAddresses = device_description->Dma32BitAddresses;
1065 xen_dma_adapter->adapter_object.Dma64BitAddresses = device_description->Dma64BitAddresses;
1066 InitializeListHead(&xen_dma_adapter->adapter_object.AdapterList);
1068 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DMA_OPERATIONS), XENPCI_POOL_TAG);
1069 ASSERT(xen_dma_adapter->adapter_object.DmaHeader.DmaOperations);
1070 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 1)
1072 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = FIELD_OFFSET(DMA_OPERATIONS, CalculateScatterGatherList);
1074 else
1076 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->Size = sizeof(DMA_OPERATIONS);
1078 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutDmaAdapter = XenPci_DOP_PutDmaAdapter;
1079 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateCommonBuffer = XenPci_DOP_AllocateCommonBuffer;
1080 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeCommonBuffer = XenPci_DOP_FreeCommonBuffer;
1081 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->AllocateAdapterChannel = XenPci_DOP_AllocateAdapterChannel;
1082 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FlushAdapterBuffers = XenPci_DOP_FlushAdapterBuffers;
1083 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeAdapterChannel = XenPci_DOP_FreeAdapterChannel;
1084 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->FreeMapRegisters = XenPci_DOP_FreeMapRegisters;
1085 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->MapTransfer = XenPci_DOP_MapTransfer;
1086 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetDmaAlignment = XenPci_DOP_GetDmaAlignment;
1087 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->ReadDmaCounter = XenPci_DOP_ReadDmaCounter;
1088 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->GetScatterGatherList = XenPci_DOP_GetScatterGatherList;
1089 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->PutScatterGatherList = XenPci_DOP_PutScatterGatherList;
1090 if (xen_dma_adapter->adapter_object.DmaHeader.Version == 2)
1092 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->CalculateScatterGatherList = XenPci_DOP_CalculateScatterGatherList;
1093 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildScatterGatherList = XenPci_DOP_BuildScatterGatherList;
1094 xen_dma_adapter->adapter_object.DmaHeader.DmaOperations->BuildMdlFromScatterGatherList = XenPci_DOP_BuildMdlFromScatterGatherList;
1097 *number_of_map_registers = xen_dma_adapter->adapter_object.MapRegistersPerChannel; //1024; /* why not... */
1099 FUNCTION_EXIT();
1101 return &xen_dma_adapter->adapter_object.DmaHeader;
1104 ULONG
1105 XenPci_BIS_SetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
1107 UNREFERENCED_PARAMETER(context);
1108 UNREFERENCED_PARAMETER(data_type);
1109 UNREFERENCED_PARAMETER(buffer);
1110 UNREFERENCED_PARAMETER(offset);
1111 UNREFERENCED_PARAMETER(length);
1113 FUNCTION_ENTER();
1114 FUNCTION_EXIT();
1115 return 0;
1118 ULONG
1119 XenPci_BIS_GetBusData(PVOID context, ULONG data_type, PVOID buffer, ULONG offset, ULONG length)
1121 UNREFERENCED_PARAMETER(context);
1122 UNREFERENCED_PARAMETER(data_type);
1123 UNREFERENCED_PARAMETER(buffer);
1124 UNREFERENCED_PARAMETER(offset);
1125 UNREFERENCED_PARAMETER(length);
1127 FUNCTION_ENTER();
1128 FUNCTION_EXIT();
1129 return 0;