ReactOS  0.4.14-dev-815-ge410a12
dma.c
Go to the documentation of this file.
1 /*
2  *
3  * COPYRIGHT: See COPYING in the top level directory
4  * PROJECT: ReactOS kernel
5  * FILE: hal/halx86/generic/dma.c
6  * PURPOSE: DMA functions
7  * PROGRAMMERS: David Welch (welch@mcmail.com)
8  * Filip Navara (navaraf@reactos.com)
9  * UPDATE HISTORY:
10  * Created 22/05/98
11  */
12 
72 /* INCLUDES *****************************************************************/
73 
74 #include <hal.h>
75 #include <suppress.h>
76 
77 #define NDEBUG
78 #include <debug.h>
79 
80 #if defined(ALLOC_PRAGMA) && !defined(_MINIHAL_)
81 #pragma alloc_text(INIT, HalpInitDma)
82 #endif
83 
84 #define MAX_SG_ELEMENTS 0x10
85 
86 #ifndef _MINIHAL_
90 #endif
92 #ifndef _MINIHAL_
94 #endif
95 
96 static const ULONG_PTR HalpEisaPortPage[8] = {
97  FIELD_OFFSET(DMA_PAGE, Channel0),
98  FIELD_OFFSET(DMA_PAGE, Channel1),
99  FIELD_OFFSET(DMA_PAGE, Channel2),
100  FIELD_OFFSET(DMA_PAGE, Channel3),
101  0,
102  FIELD_OFFSET(DMA_PAGE, Channel5),
103  FIELD_OFFSET(DMA_PAGE, Channel6),
104  FIELD_OFFSET(DMA_PAGE, Channel7)
105 };
106 
107 #ifndef _MINIHAL_
109  sizeof(DMA_OPERATIONS),
113  NULL, /* Initialized in HalpInitDma() */
114  NULL, /* Initialized in HalpInitDma() */
115  NULL, /* Initialized in HalpInitDma() */
116  NULL, /* Initialized in HalpInitDma() */
117  NULL, /* Initialized in HalpInitDma() */
120  /* FIXME: Implement the S/G funtions. */
123  NULL /*(PCALCULATE_SCATTER_GATHER_LIST_SIZE)HalCalculateScatterGatherListSize*/,
124  NULL /*(PBUILD_SCATTER_GATHER_LIST)HalBuildScatterGatherList*/,
125  NULL /*(PBUILD_MDL_FROM_SCATTER_GATHER_LIST)HalBuildMdlFromScatterGatherList*/
126 };
127 #endif
128 
129 #define MAX_MAP_REGISTERS 64
130 
131 #define TAG_DMA ' AMD'
132 
133 /* FUNCTIONS *****************************************************************/
134 
135 #ifndef _MINIHAL_
136 INIT_FUNCTION
137 VOID
139 {
140  /*
141  * Initialize the DMA Operation table
142  */
148 
150  {
151  /*
152  * Check if Extended DMA is available. We're just going to do a random
153  * read and write.
154  */
155  WRITE_PORT_UCHAR(UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2)), 0x2A);
156  if (READ_PORT_UCHAR(UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2))) == 0x2A)
157  {
158  DPRINT1("Machine supports EISA DMA. Bus type: %lu\n", HalpBusType);
159  HalpEisaDma = TRUE;
160  }
161  }
162 
163  /*
164  * Intialize all the global variables and allocate master adapter with
165  * first map buffers.
166  */
170 
171  /*
172  * Setup the HalDispatchTable callback for creating PnP DMA adapters. It's
173  * used by IoGetDmaAdapter in the kernel.
174  */
176 }
177 #endif
178 
186 NTAPI
188 {
189  PHYSICAL_ADDRESS HighestAddress;
190 
191  if (AdapterObject->MasterDevice)
192  {
193  if (AdapterObject->Dma64BitAddresses)
194  {
195  HighestAddress.QuadPart = 0xFFFFFFFFFFFFFFFFULL;
196  return HighestAddress;
197  }
198  else if (AdapterObject->Dma32BitAddresses)
199  {
200  HighestAddress.QuadPart = 0xFFFFFFFF;
201  return HighestAddress;
202  }
203  }
204 
205  HighestAddress.QuadPart = 0xFFFFFF;
206  return HighestAddress;
207 }
208 
209 #ifndef _MINIHAL_
210 
221 BOOLEAN
222 NTAPI
224  IN ULONG SizeOfMapBuffers)
225 {
230  PHYSICAL_ADDRESS BoundryAddressMultiple;
231  KIRQL OldIrql;
232  ULONG MapRegisterCount;
233 
234  /* Check if enough map register slots are available. */
235  MapRegisterCount = BYTES_TO_PAGES(SizeOfMapBuffers);
236  if (MapRegisterCount + AdapterObject->NumberOfMapRegisters > MAX_MAP_REGISTERS)
237  {
238  DPRINT("No more map register slots available! (Current: %d | Requested: %d | Limit: %d)\n",
239  AdapterObject->NumberOfMapRegisters,
240  MapRegisterCount,
242  return FALSE;
243  }
244 
245  /*
246  * Allocate memory for the new map registers. For 32-bit adapters we use
247  * two passes in order not to waste scare resource (low memory).
248  */
251  LowestAcceptableAddress.LowPart = HighestAcceptableAddress.LowPart == 0xFFFFFFFF ? 0x1000000 : 0;
252  BoundryAddressMultiple.QuadPart = 0;
253 
257  BoundryAddressMultiple,
258  MmNonCached);
260  {
265  BoundryAddressMultiple,
266  MmNonCached);
267  }
268 
269  if (!VirtualAddress) return FALSE;
270 
272 
273  /*
274  * All the following must be done with the master adapter lock held
275  * to prevent corruption.
276  */
277  KeAcquireSpinLock(&AdapterObject->SpinLock, &OldIrql);
278 
279  /*
280  * Setup map register entries for the buffer allocated. Each entry has
281  * a virtual and physical address and corresponds to PAGE_SIZE large
282  * buffer.
283  */
284  if (MapRegisterCount > 0)
285  {
286  PROS_MAP_REGISTER_ENTRY CurrentEntry, PreviousEntry;
287 
288  CurrentEntry = AdapterObject->MapRegisterBase + AdapterObject->NumberOfMapRegisters;
289  do
290  {
291  /*
292  * Leave one entry free for every non-contiguous memory region
293  * in the map register bitmap. This ensures that we can search
294  * using RtlFindClearBits for contiguous map register regions.
295  *
296  * Also for non-EISA DMA leave one free entry for every 64Kb
297  * break, because the DMA controller can handle only coniguous
298  * 64Kb regions.
299  */
300  if (CurrentEntry != AdapterObject->MapRegisterBase)
301  {
302  PreviousEntry = CurrentEntry - 1;
303  if ((PreviousEntry->PhysicalAddress.LowPart + PAGE_SIZE) == PhysicalAddress.LowPart)
304  {
305  if (!HalpEisaDma)
306  {
307  if ((PreviousEntry->PhysicalAddress.LowPart ^ PhysicalAddress.LowPart) & 0xFFFF0000)
308  {
309  CurrentEntry++;
310  AdapterObject->NumberOfMapRegisters++;
311  }
312  }
313  }
314  else
315  {
316  CurrentEntry++;
317  AdapterObject->NumberOfMapRegisters++;
318  }
319  }
320 
321  RtlClearBit(AdapterObject->MapRegisters,
322  (ULONG)(CurrentEntry - AdapterObject->MapRegisterBase));
323  CurrentEntry->VirtualAddress = VirtualAddress;
324  CurrentEntry->PhysicalAddress = PhysicalAddress;
325 
328 
329  CurrentEntry++;
330  AdapterObject->NumberOfMapRegisters++;
331  MapRegisterCount--;
332  } while (MapRegisterCount);
333  }
334 
335  KeReleaseSpinLock(&AdapterObject->SpinLock, OldIrql);
336 
337  return TRUE;
338 }
339 
349 NTAPI
351 {
352  PADAPTER_OBJECT MasterAdapter;
353  ULONG Size, SizeOfBitmap;
354 
355  SizeOfBitmap = MAX_MAP_REGISTERS;
356  Size = sizeof(ADAPTER_OBJECT);
357  Size += sizeof(RTL_BITMAP);
358  Size += (SizeOfBitmap + 7) >> 3;
359 
360  MasterAdapter = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_DMA);
361  if (!MasterAdapter) return NULL;
362 
363  RtlZeroMemory(MasterAdapter, Size);
364 
365  KeInitializeSpinLock(&MasterAdapter->SpinLock);
366  InitializeListHead(&MasterAdapter->AdapterQueue);
367 
368  MasterAdapter->MapRegisters = (PVOID)(MasterAdapter + 1);
369  RtlInitializeBitMap(MasterAdapter->MapRegisters,
370  (PULONG)(MasterAdapter->MapRegisters + 1),
371  SizeOfBitmap);
372  RtlSetAllBits(MasterAdapter->MapRegisters);
373  MasterAdapter->NumberOfMapRegisters = 0;
374  MasterAdapter->CommittedMapRegisters = 0;
375 
376  MasterAdapter->MapRegisterBase = ExAllocatePoolWithTag(NonPagedPool,
377  SizeOfBitmap *
378  sizeof(ROS_MAP_REGISTER_ENTRY),
379  TAG_DMA);
380  if (!MasterAdapter->MapRegisterBase)
381  {
382  ExFreePool(MasterAdapter);
383  return NULL;
384  }
385 
386  RtlZeroMemory(MasterAdapter->MapRegisterBase,
387  SizeOfBitmap * sizeof(ROS_MAP_REGISTER_ENTRY));
388  if (!HalpGrowMapBuffers(MasterAdapter, 0x10000))
389  {
390  ExFreePool(MasterAdapter);
391  return NULL;
392  }
393 
394  return MasterAdapter;
395 }
396 
406 NTAPI
409 {
410  PADAPTER_OBJECT AdapterObject;
413  HANDLE Handle;
414 
416  NULL,
418  NULL,
419  NULL);
420 
424  KernelMode,
425  NULL,
426  sizeof(ADAPTER_OBJECT),
427  0,
428  0,
429  (PVOID)&AdapterObject);
430  if (!NT_SUCCESS(Status)) return NULL;
431 
432  Status = ObReferenceObjectByPointer(AdapterObject,
435  KernelMode);
436  if (!NT_SUCCESS(Status)) return NULL;
437 
438  RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT));
439 
440  Status = ObInsertObject(AdapterObject,
441  NULL,
443  0,
444  NULL,
445  &Handle);
446  if (!NT_SUCCESS(Status)) return NULL;
447 
448  ZwClose(Handle);
449 
450  AdapterObject->DmaHeader.Version = (USHORT)DeviceDescription->Version;
451  AdapterObject->DmaHeader.Size = sizeof(ADAPTER_OBJECT);
452  AdapterObject->DmaHeader.DmaOperations = &HalpDmaOperations;
453  AdapterObject->MapRegistersPerChannel = 1;
454  AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
455  AdapterObject->ChannelNumber = 0xFF;
456  AdapterObject->MasterAdapter = HalpMasterAdapter;
457  KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue);
458 
459  return AdapterObject;
460 }
461 #endif
462 
468 BOOLEAN
469 NTAPI
472 {
473  UCHAR Controller;
474  DMA_MODE DmaMode = {{0 }};
475  DMA_EXTENDED_MODE ExtendedMode = {{ 0 }};
476  PVOID AdapterBaseVa;
477 
478  Controller = (DeviceDescription->DmaChannel & 4) ? 2 : 1;
479 
480  if (Controller == 1)
481  {
482  AdapterBaseVa = UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController1));
483  }
484  else
485  {
486  AdapterBaseVa = UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2));
487  }
488 
489  AdapterObject->AdapterNumber = Controller;
490  AdapterObject->ChannelNumber = (UCHAR)(DeviceDescription->DmaChannel & 3);
491  AdapterObject->PagePort = (PUCHAR)HalpEisaPortPage[DeviceDescription->DmaChannel];
492  AdapterObject->Width16Bits = FALSE;
493  AdapterObject->AdapterBaseVa = AdapterBaseVa;
494 
495  if (HalpEisaDma)
496  {
497  ExtendedMode.ChannelNumber = AdapterObject->ChannelNumber;
498 
499  switch (DeviceDescription->DmaSpeed)
500  {
501  case Compatible: ExtendedMode.TimingMode = COMPATIBLE_TIMING; break;
502  case TypeA: ExtendedMode.TimingMode = TYPE_A_TIMING; break;
503  case TypeB: ExtendedMode.TimingMode = TYPE_B_TIMING; break;
504  case TypeC: ExtendedMode.TimingMode = BURST_TIMING; break;
505  default:
506  return FALSE;
507  }
508 
509  switch (DeviceDescription->DmaWidth)
510  {
511  case Width8Bits: ExtendedMode.TransferSize = B_8BITS; break;
512  case Width16Bits: ExtendedMode.TransferSize = B_16BITS; break;
513  case Width32Bits: ExtendedMode.TransferSize = B_32BITS; break;
514  default:
515  return FALSE;
516  }
517 
518  if (Controller == 1)
519  {
521  ExtendedMode.Byte);
522  }
523  else
524  {
526  ExtendedMode.Byte);
527  }
528  }
529  else
530  {
531  /*
532  * Validate setup for non-busmaster DMA adapter. Secondary controller
533  * supports only 16-bit transfers and main controller supports only
534  * 8-bit transfers. Anything else is invalid.
535  */
537  {
538  if ((Controller == 2) && (DeviceDescription->DmaWidth == Width16Bits))
539  {
540  AdapterObject->Width16Bits = TRUE;
541  }
542  else if ((Controller != 1) || (DeviceDescription->DmaWidth != Width8Bits))
543  {
544  return FALSE;
545  }
546  }
547  }
548 
549  DmaMode.Channel = AdapterObject->ChannelNumber;
551 
552  /*
553  * Set the DMA request mode.
554  *
555  * For (E)ISA bus master devices just unmask (enable) the DMA channel
556  * and set it to cascade mode. Otherwise just select the right one
557  * bases on the passed device description.
558  */
560  {
562  if (Controller == 1)
563  {
564  /* Set the Request Data */
566  WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte);
567 
568  /* Unmask DMA Channel */
569  WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->SingleMask,
570  AdapterObject->ChannelNumber | DMA_CLEARMASK);
571  }
572  else
573  {
574  /* Set the Request Data */
575  WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte);
576 
577  /* Unmask DMA Channel */
578  WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->SingleMask,
579  AdapterObject->ChannelNumber | DMA_CLEARMASK);
580  }
581  }
582  else
583  {
585  {
587  }
588  else
589  {
591  }
592  }
593 
594  AdapterObject->AdapterMode = DmaMode;
595 
596  return TRUE;
597 }
598 
599 #ifndef _MINIHAL_
600 
616 NTAPI
619 {
620  PADAPTER_OBJECT AdapterObject = NULL;
622  ULONG MapRegisters;
624 
625  /* Validate parameters in device description */
627 
628  /*
629  * See if we're going to use ISA/EISA DMA adapter. These adapters are
630  * special since they're reused.
631  *
632  * Also note that we check for channel number since there are only 8 DMA
633  * channels on ISA, so any request above this requires new adapter.
634  */
635  if (((DeviceDescription->InterfaceType == Eisa) ||
637  {
638  if (((DeviceDescription->InterfaceType == Isa) ||
641  {
642  EisaAdapter = FALSE;
643  }
644  else
645  {
646  EisaAdapter = TRUE;
647  }
648  }
649  else
650  {
651  EisaAdapter = FALSE;
652  }
653 
654  /*
655  * Disallow creating adapter for ISA/EISA DMA channel 4 since it's used
656  * for cascading the controllers and it's not available for software use.
657  */
658  if ((EisaAdapter) && (DeviceDescription->DmaChannel == 4)) return NULL;
659 
660  /*
661  * Calculate the number of map registers.
662  *
663  * - For EISA and PCI scatter/gather no map registers are needed.
664  * - For ISA slave scatter/gather one map register is needed.
665  * - For all other cases the number of map registers depends on
666  * DeviceDescription->MaximumLength.
667  */
672  {
673  MapRegisters = 0;
674  }
676  {
677  MapRegisters = 1;
678  }
679  else
680  {
681  /*
682  * In the equation below the additional map register added by
683  * the "+1" accounts for the case when a transfer does not start
684  * at a page-aligned address.
685  */
686  MapRegisters = BYTES_TO_PAGES(MaximumLength) + 1;
687  if (MapRegisters > 16) MapRegisters = 16;
688  }
689 
690  /*
691  * Acquire the DMA lock that is used to protect adapter lists and
692  * EISA adapter array.
693  */
695 
696  /*
697  * Now we must get ahold of the adapter object. For first eight ISA/EISA
698  * channels there are static adapter objects that are reused and updated
699  * on succesive HalGetAdapter calls. In other cases a new adapter object
700  * is always created and it's to the DMA adapter list (HalpDmaAdapterList).
701  */
702  if (EisaAdapter)
703  {
704  AdapterObject = HalpEisaAdapter[DeviceDescription->DmaChannel];
705  if (AdapterObject)
706  {
707  if ((AdapterObject->NeedsMapRegisters) &&
708  (MapRegisters > AdapterObject->MapRegistersPerChannel))
709  {
710  AdapterObject->MapRegistersPerChannel = MapRegisters;
711  }
712  }
713  }
714 
715  if (AdapterObject == NULL)
716  {
717  AdapterObject = HalpDmaAllocateChildAdapter(MapRegisters, DeviceDescription);
718  if (AdapterObject == NULL)
719  {
720  KeSetEvent(&HalpDmaLock, 0, 0);
721  return NULL;
722  }
723 
724  if (EisaAdapter)
725  {
726  HalpEisaAdapter[DeviceDescription->DmaChannel] = AdapterObject;
727  }
728 
729  if (MapRegisters > 0)
730  {
731  AdapterObject->NeedsMapRegisters = TRUE;
732  AdapterObject->MapRegistersPerChannel = MapRegisters;
733  }
734  else
735  {
736  AdapterObject->NeedsMapRegisters = FALSE;
738  {
739  AdapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(MaximumLength) + 1;
740  }
741  else
742  {
743  AdapterObject->MapRegistersPerChannel = 1;
744  }
745  }
746  }
747 
748  if (!EisaAdapter) InsertTailList(&HalpDmaAdapterList, &AdapterObject->AdapterList);
749 
750  /*
751  * Release the DMA lock. HalpDmaAdapterList and HalpEisaAdapter will
752  * no longer be touched, so we don't need it.
753  */
754  KeSetEvent(&HalpDmaLock, 0, 0);
755 
756  /*
757  * Setup the values in the adapter object that are common for all
758  * types of buses.
759  */
761  {
762  AdapterObject->IgnoreCount = DeviceDescription->IgnoreCount;
763  }
764  else
765  {
766  AdapterObject->IgnoreCount = 0;
767  }
768 
769  AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
770  AdapterObject->Dma64BitAddresses = DeviceDescription->Dma64BitAddresses;
771  AdapterObject->ScatterGather = DeviceDescription->ScatterGather;
772  AdapterObject->MasterDevice = DeviceDescription->Master;
773  *NumberOfMapRegisters = AdapterObject->MapRegistersPerChannel;
774 
775  /*
776  * For non-(E)ISA adapters we have already done all the work. On the
777  * other hand for (E)ISA adapters we must still setup the DMA modes
778  * and prepare the controller.
779  */
780  if (EisaAdapter)
781  {
782  if (!HalpDmaInitializeEisaAdapter(AdapterObject, DeviceDescription))
783  {
784  ObDereferenceObject(AdapterObject);
785  return NULL;
786  }
787  }
788 
789  return AdapterObject;
790 }
791 
801 NTAPI
805 {
807 }
808 
817 VOID
818 NTAPI
820 {
821  if (AdapterObject->ChannelNumber == 0xFF)
822  {
824  RemoveEntryList(&AdapterObject->AdapterList);
825  KeSetEvent(&HalpDmaLock, 0, 0);
826  }
827 
828  ObDereferenceObject(AdapterObject);
829 }
830 
856 PVOID
857 NTAPI
859  IN ULONG Length,
860  IN PPHYSICAL_ADDRESS LogicalAddress,
861  IN BOOLEAN CacheEnabled)
862 {
865  PHYSICAL_ADDRESS BoundryAddressMultiple;
867 
870  BoundryAddressMultiple.QuadPart = 0;
871 
872  /*
873  * For bus-master DMA devices the buffer mustn't cross 4Gb boundary. For
874  * slave DMA devices the 64Kb boundary mustn't be crossed since the
875  * controller wouldn't be able to handle it.
876  */
877  if (AdapterObject->MasterDevice)
878  {
879  BoundryAddressMultiple.HighPart = 1;
880  }
881  else
882  {
883  BoundryAddressMultiple.LowPart = 0x10000;
884  }
885 
889  BoundryAddressMultiple,
890  CacheEnabled ? MmCached :
891  MmNonCached);
892  if (VirtualAddress == NULL) return NULL;
893 
894  *LogicalAddress = MmGetPhysicalAddress(VirtualAddress);
895 
896  return VirtualAddress;
897 }
898 
908 VOID
909 NTAPI
911  IN ULONG Length,
912  IN PHYSICAL_ADDRESS LogicalAddress,
914  IN BOOLEAN CacheEnabled)
915 {
917  Length,
918  CacheEnabled ? MmCached : MmNonCached);
919 }
920 
921 typedef struct _SCATTER_GATHER_CONTEXT {
932 
933 
935 NTAPI
937  IN PIRP Irp,
939  IN PVOID Context)
940 {
941  PSCATTER_GATHER_CONTEXT AdapterControlContext = Context;
942  PADAPTER_OBJECT AdapterObject = AdapterControlContext->AdapterObject;
943  PSCATTER_GATHER_LIST ScatterGatherList;
945  ULONG ElementCount = 0, RemainingLength = AdapterControlContext->Length;
946  PUCHAR CurrentVa = AdapterControlContext->CurrentVa;
947 
948  /* Store the map register base for later in HalPutScatterGatherList */
949  AdapterControlContext->MapRegisterBase = MapRegisterBase;
950 
951  while (RemainingLength > 0 && ElementCount < MAX_SG_ELEMENTS)
952  {
953  TempElements[ElementCount].Length = RemainingLength;
954  TempElements[ElementCount].Reserved = 0;
955  TempElements[ElementCount].Address = IoMapTransfer(AdapterObject,
956  AdapterControlContext->Mdl,
958  CurrentVa + (AdapterControlContext->Length - RemainingLength),
959  &TempElements[ElementCount].Length,
960  AdapterControlContext->WriteToDevice);
961  if (TempElements[ElementCount].Length == 0)
962  break;
963 
964  DPRINT("Allocated one S/G element: 0x%I64u with length: 0x%x\n",
965  TempElements[ElementCount].Address.QuadPart,
966  TempElements[ElementCount].Length);
967 
968  ASSERT(TempElements[ElementCount].Length <= RemainingLength);
969  RemainingLength -= TempElements[ElementCount].Length;
970  ElementCount++;
971  }
972 
973  if (RemainingLength > 0)
974  {
975  DPRINT1("Scatter/gather list construction failed!\n");
976  return DeallocateObject;
977  }
978 
979  ScatterGatherList = ExAllocatePoolWithTag(NonPagedPool,
980  sizeof(SCATTER_GATHER_LIST) + sizeof(SCATTER_GATHER_ELEMENT) * ElementCount,
981  TAG_DMA);
982  ASSERT(ScatterGatherList);
983 
984  ScatterGatherList->NumberOfElements = ElementCount;
985  ScatterGatherList->Reserved = (ULONG_PTR)AdapterControlContext;
986  RtlCopyMemory(ScatterGatherList->Elements,
987  TempElements,
988  sizeof(SCATTER_GATHER_ELEMENT) * ElementCount);
989 
990  DPRINT("Initiating S/G DMA with %d element(s)\n", ElementCount);
991 
992  AdapterControlContext->AdapterListControlRoutine(DeviceObject,
993  Irp,
994  ScatterGatherList,
995  AdapterControlContext->AdapterListControlContext);
996 
998 }
999 
1028  NTSTATUS
1029  NTAPI
1032  IN PMDL Mdl,
1033  IN PVOID CurrentVa,
1034  IN ULONG Length,
1036  IN PVOID Context,
1037  IN BOOLEAN WriteToDevice)
1038 {
1039  PSCATTER_GATHER_CONTEXT AdapterControlContext;
1040 
1041  AdapterControlContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCATTER_GATHER_CONTEXT), TAG_DMA);
1042  if (!AdapterControlContext) return STATUS_INSUFFICIENT_RESOURCES;
1043 
1044  AdapterControlContext->AdapterObject = AdapterObject;
1045  AdapterControlContext->Mdl = Mdl;
1046  AdapterControlContext->CurrentVa = CurrentVa;
1047  AdapterControlContext->Length = Length;
1048  AdapterControlContext->MapRegisterCount = PAGE_ROUND_UP(Length) >> PAGE_SHIFT;
1049  AdapterControlContext->AdapterListControlRoutine = ExecutionRoutine;
1050  AdapterControlContext->AdapterListControlContext = Context;
1051  AdapterControlContext->WriteToDevice = WriteToDevice;
1052 
1053  AdapterControlContext->Wcb.DeviceObject = DeviceObject;
1054  AdapterControlContext->Wcb.DeviceContext = AdapterControlContext;
1055  AdapterControlContext->Wcb.CurrentIrp = DeviceObject->CurrentIrp;
1056 
1057  return HalAllocateAdapterChannel(AdapterObject,
1058  &AdapterControlContext->Wcb,
1059  AdapterControlContext->MapRegisterCount,
1061 }
1062 
1081  VOID
1082  NTAPI
1085  IN BOOLEAN WriteToDevice)
1086 {
1087  PSCATTER_GATHER_CONTEXT AdapterControlContext = (PSCATTER_GATHER_CONTEXT)ScatterGather->Reserved;
1088  ULONG i;
1089 
1090  for (i = 0; i < ScatterGather->NumberOfElements; i++)
1091  {
1092  IoFlushAdapterBuffers(AdapterObject,
1093  AdapterControlContext->Mdl,
1094  AdapterControlContext->MapRegisterBase,
1095  AdapterControlContext->CurrentVa,
1096  ScatterGather->Elements[i].Length,
1097  AdapterControlContext->WriteToDevice);
1098  AdapterControlContext->CurrentVa += ScatterGather->Elements[i].Length;
1099  }
1100 
1101  IoFreeMapRegisters(AdapterObject,
1102  AdapterControlContext->MapRegisterBase,
1103  AdapterControlContext->MapRegisterCount);
1104 
1105  DPRINT("S/G DMA has finished!\n");
1106 
1107  ExFreePoolWithTag(AdapterControlContext, TAG_DMA);
1109 }
1110 #endif
1111 
1120 ULONG
1121 NTAPI
1123 {
1124  return 1;
1125 }
1126 
1127 /*
1128  * @name HalReadDmaCounter
1129  *
1130  * Read DMA operation progress counter.
1131  *
1132  * @implemented
1133  */
1134 ULONG
1135 NTAPI
1137 {
1138  KIRQL OldIrql;
1139  ULONG Count, OldCount;
1140 
1141  ASSERT(!AdapterObject->MasterDevice);
1142 
1143  /*
1144  * Acquire the master adapter lock since we're going to mess with the
1145  * system DMA controller registers and we really don't want anyone
1146  * to do the same at the same time.
1147  */
1148  KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
1149 
1150  /* Send the request to the specific controller. */
1151  if (AdapterObject->AdapterNumber == 1)
1152  {
1153  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
1154 
1155  Count = 0xffff00;
1156  do
1157  {
1158  OldCount = Count;
1159 
1160  /* Send Reset */
1161  WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
1162 
1163  /* Read Count */
1164  Count = READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
1165  [AdapterObject->ChannelNumber].DmaBaseCount);
1166  Count |= READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
1167  [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
1168  } while (0xffff00 & (OldCount ^ Count));
1169  }
1170  else
1171  {
1172  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
1173 
1174  Count = 0xffff00;
1175  do
1176  {
1177  OldCount = Count;
1178 
1179  /* Send Reset */
1180  WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
1181 
1182  /* Read Count */
1183  Count = READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
1184  [AdapterObject->ChannelNumber].DmaBaseCount);
1185  Count |= READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
1186  [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
1187  } while (0xffff00 & (OldCount ^ Count));
1188  }
1189 
1190  KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
1191 
1192  Count++;
1193  Count &= 0xffff;
1194  if (AdapterObject->Width16Bits) Count *= 2;
1195 
1196  return Count;
1197 }
1198 
1199 #ifndef _MINIHAL_
1200 
1206 VOID
1207 NTAPI
1209 {
1211  KIRQL OldIrql;
1212  BOOLEAN Succeeded;
1213 
1214  /*
1215  * Try to allocate new map registers for the adapter.
1216  *
1217  * NOTE: The NT implementation actually tries to allocate more map
1218  * registers than needed as an optimization.
1219  */
1221  Succeeded = HalpGrowMapBuffers(WorkItem->AdapterObject->MasterAdapter,
1222  WorkItem->NumberOfMapRegisters << PAGE_SHIFT);
1223  KeSetEvent(&HalpDmaLock, 0, 0);
1224 
1225  if (Succeeded)
1226  {
1227  /*
1228  * Flush the adapter queue now that new map registers are ready. The
1229  * easiest way to do that is to call IoFreeMapRegisters to not free
1230  * any registers. Note that we use the magic (PVOID)2 map register
1231  * base to bypass the parameter checking.
1232  */
1234  IoFreeMapRegisters(WorkItem->AdapterObject, (PVOID)2, 0);
1236  }
1237 
1238  ExFreePool(WorkItem);
1239 }
1240 
1265 NTSTATUS
1266 NTAPI
1268  IN PWAIT_CONTEXT_BLOCK WaitContextBlock,
1271 {
1272  PADAPTER_OBJECT MasterAdapter;
1273  PGROW_WORK_ITEM WorkItem;
1274  ULONG Index = MAXULONG;
1275  ULONG Result;
1276  KIRQL OldIrql;
1277 
1279 
1280  /* Set up the wait context block in case we can't run right away. */
1281  WaitContextBlock->DeviceRoutine = ExecutionRoutine;
1282  WaitContextBlock->NumberOfMapRegisters = NumberOfMapRegisters;
1283 
1284  /* Returns true if queued, else returns false and sets the queue to busy */
1285  if (KeInsertDeviceQueue(&AdapterObject->ChannelWaitQueue,
1286  &WaitContextBlock->WaitQueueEntry))
1287  {
1288  return STATUS_SUCCESS;
1289  }
1290 
1291  MasterAdapter = AdapterObject->MasterAdapter;
1292 
1293  AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
1294  AdapterObject->CurrentWcb = WaitContextBlock;
1295 
1296  if ((NumberOfMapRegisters) && (AdapterObject->NeedsMapRegisters))
1297  {
1298  if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
1299  {
1300  AdapterObject->NumberOfMapRegisters = 0;
1301  IoFreeAdapterChannel(AdapterObject);
1303  }
1304 
1305  /*
1306  * Get the map registers. This is partly complicated by the fact
1307  * that new map registers can only be allocated at PASSIVE_LEVEL
1308  * and we're currently at DISPATCH_LEVEL. The following code has
1309  * two code paths:
1310  *
1311  * - If there is no adapter queued for map register allocation,
1312  * try to see if enough contiguous map registers are present.
1313  * In case they're we can just get them and proceed further.
1314  *
1315  * - If some adapter is already present in the queue we must
1316  * respect the order of adapters asking for map registers and
1317  * so the fast case described above can't take place.
1318  * This case is also entered if not enough coniguous map
1319  * registers are present.
1320  *
1321  * A work queue item is allocated and queued, the adapter is
1322  * also queued into the master adapter queue. The worker
1323  * routine does the job of allocating the map registers at
1324  * PASSIVE_LEVEL and calling the ExecutionRoutine.
1325  */
1326 
1327  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1328 
1329  if (IsListEmpty(&MasterAdapter->AdapterQueue))
1330  {
1331  Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters, NumberOfMapRegisters, 0);
1332  if (Index != MAXULONG)
1333  {
1334  AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1335  if (!AdapterObject->ScatterGather)
1336  {
1337  AdapterObject->MapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1338  }
1339  }
1340  }
1341 
1342  if (Index == MAXULONG)
1343  {
1344  InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
1345 
1347  sizeof(GROW_WORK_ITEM),
1348  TAG_DMA);
1349  if (WorkItem)
1350  {
1352  WorkItem->AdapterObject = AdapterObject;
1354 
1356  }
1357 
1358  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1359 
1360  return STATUS_SUCCESS;
1361  }
1362 
1363  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1364  }
1365  else
1366  {
1367  AdapterObject->MapRegisterBase = NULL;
1368  AdapterObject->NumberOfMapRegisters = 0;
1369  }
1370 
1371  AdapterObject->CurrentWcb = WaitContextBlock;
1372 
1373  Result = ExecutionRoutine(WaitContextBlock->DeviceObject,
1374  WaitContextBlock->CurrentIrp,
1375  AdapterObject->MapRegisterBase,
1376  WaitContextBlock->DeviceContext);
1377 
1378  /*
1379  * Possible return values:
1380  *
1381  * - KeepObject
1382  * Don't free any resources, the ADAPTER_OBJECT is still in use and
1383  * the caller will call IoFreeAdapterChannel later.
1384  *
1385  * - DeallocateObject
1386  * Deallocate the map registers and release the ADAPTER_OBJECT, so
1387  * someone else can use it.
1388  *
1389  * - DeallocateObjectKeepRegisters
1390  * Release the ADAPTER_OBJECT, but hang on to the map registers. The
1391  * client will later call IoFreeMapRegisters.
1392  *
1393  * NOTE:
1394  * IoFreeAdapterChannel runs the queue, so it must be called unless
1395  * the adapter object is not to be freed.
1396  */
1397  if (Result == DeallocateObject)
1398  {
1399  IoFreeAdapterChannel(AdapterObject);
1400  }
1402  {
1403  AdapterObject->NumberOfMapRegisters = 0;
1404  IoFreeAdapterChannel(AdapterObject);
1405  }
1406 
1407  return STATUS_SUCCESS;
1408 }
1409 
1428 VOID
1429 NTAPI
1431 {
1432  PADAPTER_OBJECT MasterAdapter;
1434  PWAIT_CONTEXT_BLOCK WaitContextBlock;
1435  ULONG Index = MAXULONG;
1436  ULONG Result;
1437  KIRQL OldIrql;
1438 
1439  MasterAdapter = AdapterObject->MasterAdapter;
1440 
1441  for (;;)
1442  {
1443  /*
1444  * To keep map registers, call here with AdapterObject->
1445  * NumberOfMapRegisters set to zero. This trick is used in
1446  * HalAllocateAdapterChannel for example.
1447  */
1448  if (AdapterObject->NumberOfMapRegisters)
1449  {
1450  IoFreeMapRegisters(AdapterObject,
1451  AdapterObject->MapRegisterBase,
1452  AdapterObject->NumberOfMapRegisters);
1453  }
1454 
1455  DeviceQueueEntry = KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue);
1456  if (!DeviceQueueEntry) break;
1457 
1458  WaitContextBlock = CONTAINING_RECORD(DeviceQueueEntry,
1460  WaitQueueEntry);
1461 
1462  AdapterObject->CurrentWcb = WaitContextBlock;
1463  AdapterObject->NumberOfMapRegisters = WaitContextBlock->NumberOfMapRegisters;
1464 
1465  if ((WaitContextBlock->NumberOfMapRegisters) && (AdapterObject->MasterAdapter))
1466  {
1467  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1468 
1469  if (IsListEmpty(&MasterAdapter->AdapterQueue))
1470  {
1471  Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
1472  WaitContextBlock->NumberOfMapRegisters,
1473  0);
1474  if (Index != MAXULONG)
1475  {
1476  AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1477  if (!AdapterObject->ScatterGather)
1478  {
1479  AdapterObject->MapRegisterBase =(PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1480  }
1481  }
1482  }
1483 
1484  if (Index == MAXULONG)
1485  {
1486  InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
1487  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1488  break;
1489  }
1490 
1491  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1492  }
1493  else
1494  {
1495  AdapterObject->MapRegisterBase = NULL;
1496  AdapterObject->NumberOfMapRegisters = 0;
1497  }
1498 
1499  /* Call the adapter control routine. */
1500  Result = ((PDRIVER_CONTROL)WaitContextBlock->DeviceRoutine)(WaitContextBlock->DeviceObject,
1501  WaitContextBlock->CurrentIrp,
1502  AdapterObject->MapRegisterBase,
1503  WaitContextBlock->DeviceContext);
1504  switch (Result)
1505  {
1506  case KeepObject:
1507  /*
1508  * We're done until the caller manually calls IoFreeAdapterChannel
1509  * or IoFreeMapRegisters.
1510  */
1511  return;
1512 
1514  /*
1515  * Hide the map registers so they aren't deallocated next time
1516  * around.
1517  */
1518  AdapterObject->NumberOfMapRegisters = 0;
1519  break;
1520 
1521  default:
1522  break;
1523  }
1524  }
1525 }
1526 
1541 VOID
1542 NTAPI
1546 {
1547  PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
1548  PLIST_ENTRY ListEntry;
1549  KIRQL OldIrql;
1550  ULONG Index;
1551  ULONG Result;
1552 
1554 
1555  if (!(MasterAdapter) || !(MapRegisterBase)) return;
1556 
1557  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1558 
1559  if (NumberOfMapRegisters != 0)
1560  {
1561  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1562 
1563  RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1564  RtlClearBits(MasterAdapter->MapRegisters,
1565  (ULONG)(RealMapRegisterBase - MasterAdapter->MapRegisterBase),
1567  }
1568 
1569  /*
1570  * Now that we freed few map registers it's time to look at the master
1571  * adapter queue and see if there is someone waiting for map registers.
1572  */
1573  while (!IsListEmpty(&MasterAdapter->AdapterQueue))
1574  {
1575  ListEntry = RemoveHeadList(&MasterAdapter->AdapterQueue);
1576  AdapterObject = CONTAINING_RECORD(ListEntry, struct _ADAPTER_OBJECT, AdapterQueue);
1577 
1578  Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
1579  AdapterObject->NumberOfMapRegisters,
1580  0);
1581  if (Index == MAXULONG)
1582  {
1583  InsertHeadList(&MasterAdapter->AdapterQueue, ListEntry);
1584  break;
1585  }
1586 
1587  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1588 
1589  AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1590  if (!AdapterObject->ScatterGather)
1591  {
1592  AdapterObject->MapRegisterBase =
1593  (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1594  }
1595 
1596  Result = ((PDRIVER_CONTROL)AdapterObject->CurrentWcb->DeviceRoutine)(AdapterObject->CurrentWcb->DeviceObject,
1597  AdapterObject->CurrentWcb->CurrentIrp,
1598  AdapterObject->MapRegisterBase,
1599  AdapterObject->CurrentWcb->DeviceContext);
1600  switch (Result)
1601  {
1603  AdapterObject->NumberOfMapRegisters = 0;
1604  /* fall through */
1605 
1606  case DeallocateObject:
1607  if (AdapterObject->NumberOfMapRegisters)
1608  {
1609  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1610  RtlClearBits(MasterAdapter->MapRegisters,
1611  (ULONG)(AdapterObject->MapRegisterBase -
1612  MasterAdapter->MapRegisterBase),
1613  AdapterObject->NumberOfMapRegisters);
1614  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1615  }
1616 
1617  IoFreeAdapterChannel(AdapterObject);
1618  break;
1619 
1620  default:
1621  break;
1622  }
1623 
1624  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1625  }
1626 
1627  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1628 }
1629 
1637 VOID
1638 NTAPI
1641  IN PVOID CurrentVa,
1642  IN ULONG Length,
1643  IN BOOLEAN WriteToDevice)
1644 {
1645  ULONG CurrentLength;
1646  ULONG_PTR CurrentAddress;
1647  ULONG ByteOffset;
1649 
1651  if (!VirtualAddress)
1652  {
1653  /*
1654  * NOTE: On real NT a mechanism with reserved pages is implemented
1655  * to handle this case in a slow, but graceful non-fatal way.
1656  */
1657  KeBugCheckEx(HAL_MEMORY_ALLOCATION, PAGE_SIZE, 0, (ULONG_PTR)__FILE__, 0);
1658  }
1659 
1660  CurrentAddress = (ULONG_PTR)VirtualAddress +
1661  (ULONG_PTR)CurrentVa -
1663 
1664  while (Length > 0)
1665  {
1666  ByteOffset = BYTE_OFFSET(CurrentAddress);
1667  CurrentLength = PAGE_SIZE - ByteOffset;
1668  if (CurrentLength > Length) CurrentLength = Length;
1669 
1670  if (WriteToDevice)
1671  {
1672  RtlCopyMemory((PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
1673  (PVOID)CurrentAddress,
1674  CurrentLength);
1675  }
1676  else
1677  {
1678  RtlCopyMemory((PVOID)CurrentAddress,
1679  (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
1680  CurrentLength);
1681  }
1682 
1683  Length -= CurrentLength;
1684  CurrentAddress += CurrentLength;
1685  MapRegisterBase++;
1686  }
1687 }
1688 
1720 BOOLEAN
1721 NTAPI
1723  IN PMDL Mdl,
1725  IN PVOID CurrentVa,
1726  IN ULONG Length,
1727  IN BOOLEAN WriteToDevice)
1728 {
1729  BOOLEAN SlaveDma = FALSE;
1730  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1733  PPFN_NUMBER MdlPagesPtr;
1734 
1735  /* Sanity checks */
1737  ASSERT(AdapterObject);
1738 
1739  if (!AdapterObject->MasterDevice)
1740  {
1741  /* Mask out (disable) the DMA channel. */
1742  if (AdapterObject->AdapterNumber == 1)
1743  {
1744  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
1745  WRITE_PORT_UCHAR(&DmaControl1->SingleMask,
1746  AdapterObject->ChannelNumber | DMA_SETMASK);
1747  }
1748  else
1749  {
1750  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
1751  WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
1752  AdapterObject->ChannelNumber | DMA_SETMASK);
1753  }
1754  SlaveDma = TRUE;
1755  }
1756 
1757  /* This can happen if the device supports hardware scatter/gather. */
1758  if (MapRegisterBase == NULL) return TRUE;
1759 
1760  RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1761 
1762  if (!WriteToDevice)
1763  {
1765  {
1766  if (RealMapRegisterBase->Counter != MAXULONG)
1767  {
1768  if ((SlaveDma) && !(AdapterObject->IgnoreCount))
1769  {
1770  Length -= HalReadDmaCounter(AdapterObject);
1771  }
1772  }
1773  HalpCopyBufferMap(Mdl,
1774  RealMapRegisterBase,
1775  CurrentVa,
1776  Length,
1777  FALSE);
1778  }
1779  else
1780  {
1781  MdlPagesPtr = MmGetMdlPfnArray(Mdl);
1782  MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
1783 
1784  PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
1785  PhysicalAddress.QuadPart += BYTE_OFFSET(CurrentVa);
1786 
1789  {
1790  HalpCopyBufferMap(Mdl,
1791  RealMapRegisterBase,
1792  CurrentVa,
1793  Length,
1794  FALSE);
1795  }
1796  }
1797  }
1798 
1799  RealMapRegisterBase->Counter = 0;
1800 
1801  return TRUE;
1802 }
1803 
1836 NTAPI
1838  IN PMDL Mdl,
1840  IN PVOID CurrentVa,
1841  IN OUT PULONG Length,
1842  IN BOOLEAN WriteToDevice)
1843 {
1844  PPFN_NUMBER MdlPagesPtr;
1845  PFN_NUMBER MdlPage1, MdlPage2;
1846  ULONG ByteOffset;
1847  ULONG TransferOffset;
1848  ULONG TransferLength;
1849  BOOLEAN UseMapRegisters;
1850  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1853  ULONG Counter;
1854  DMA_MODE AdapterMode;
1855  KIRQL OldIrql;
1856 
1857  /*
1858  * Precalculate some values that are used in all cases.
1859  *
1860  * ByteOffset is offset inside the page at which the transfer starts.
1861  * MdlPagesPtr is pointer inside the MDL page chain at the page where the
1862  * transfer start.
1863  * PhysicalAddress is physical address corresponding to the transfer
1864  * start page and offset.
1865  * TransferLength is the initial length of the transfer, which is reminder
1866  * of the first page. The actual value is calculated below.
1867  *
1868  * Note that all the variables can change during the processing which
1869  * takes place below. These are just initial values.
1870  */
1871  ByteOffset = BYTE_OFFSET(CurrentVa);
1872 
1873  MdlPagesPtr = MmGetMdlPfnArray(Mdl);
1874  MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
1875 
1876  PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
1878 
1879  TransferLength = PAGE_SIZE - ByteOffset;
1880 
1881  /*
1882  * Special case for bus master adapters with S/G support. We can directly
1883  * use the buffer specified by the MDL, so not much work has to be done.
1884  *
1885  * Just return the passed VA's corresponding physical address and update
1886  * length to the number of physically contiguous bytes found. Also
1887  * pages crossing the 4Gb boundary aren't considered physically contiguous.
1888  */
1889  if (MapRegisterBase == NULL)
1890  {
1891  while (TransferLength < *Length)
1892  {
1893  MdlPage1 = *MdlPagesPtr;
1894  MdlPage2 = *(MdlPagesPtr + 1);
1895  if (MdlPage1 + 1 != MdlPage2) break;
1896  if ((MdlPage1 ^ MdlPage2) & ~0xFFFFF) break;
1897  TransferLength += PAGE_SIZE;
1898  MdlPagesPtr++;
1899  }
1900 
1901  if (TransferLength < *Length) *Length = TransferLength;
1902 
1903  return PhysicalAddress;
1904  }
1905 
1906  /*
1907  * The code below applies to slave DMA adapters and bus master adapters
1908  * without hardward S/G support.
1909  */
1910  RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1911 
1912  /*
1913  * Try to calculate the size of the transfer. We can only transfer
1914  * pages that are physically contiguous and that don't cross the
1915  * 64Kb boundary (this limitation applies only for ISA controllers).
1916  */
1917  while (TransferLength < *Length)
1918  {
1919  MdlPage1 = *MdlPagesPtr;
1920  MdlPage2 = *(MdlPagesPtr + 1);
1921  if (MdlPage1 + 1 != MdlPage2) break;
1922  if (!HalpEisaDma && ((MdlPage1 ^ MdlPage2) & ~0xF)) break;
1923  TransferLength += PAGE_SIZE;
1924  MdlPagesPtr++;
1925  }
1926 
1927  if (TransferLength > *Length) TransferLength = *Length;
1928 
1929  /*
1930  * If we're about to simulate software S/G and not all the pages are
1931  * physically contiguous then we must use the map registers to store
1932  * the data and allow the whole transfer to proceed at once.
1933  */
1934  if (((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG) && (TransferLength < *Length))
1935  {
1936  UseMapRegisters = TRUE;
1937  PhysicalAddress = RealMapRegisterBase->PhysicalAddress;
1939  TransferLength = *Length;
1940  RealMapRegisterBase->Counter = MAXULONG;
1941  Counter = 0;
1942  }
1943  else
1944  {
1945  /*
1946  * This is ordinary DMA transfer, so just update the progress
1947  * counters. These are used by IoFlushAdapterBuffers to track
1948  * the transfer progress.
1949  */
1950  UseMapRegisters = FALSE;
1951  Counter = RealMapRegisterBase->Counter;
1952  RealMapRegisterBase->Counter += BYTES_TO_PAGES(ByteOffset + TransferLength);
1953 
1954  /*
1955  * Check if the buffer doesn't exceed the highest physical address
1956  * limit of the device. In that case we must use the map registers to
1957  * store the data.
1958  */
1960  if ((PhysicalAddress.QuadPart + TransferLength) > HighestAcceptableAddress.QuadPart)
1961  {
1962  UseMapRegisters = TRUE;
1963  PhysicalAddress = RealMapRegisterBase[Counter].PhysicalAddress;
1966  {
1967  RealMapRegisterBase->Counter = MAXULONG;
1968  Counter = 0;
1969  }
1970  }
1971  }
1972 
1973  /*
1974  * If we decided to use the map registers (see above) and we're about
1975  * to transfer data to the device then copy the buffers into the map
1976  * register memory.
1977  */
1978  if ((UseMapRegisters) && (WriteToDevice))
1979  {
1980  HalpCopyBufferMap(Mdl,
1981  RealMapRegisterBase + Counter,
1982  CurrentVa,
1983  TransferLength,
1984  WriteToDevice);
1985  }
1986 
1987  /*
1988  * Return the length of transfer that actually takes place.
1989  */
1990  *Length = TransferLength;
1991 
1992  /*
1993  * If we're doing slave (system) DMA then program the (E)ISA controller
1994  * to actually start the transfer.
1995  */
1996  if ((AdapterObject) && !(AdapterObject->MasterDevice))
1997  {
1998  AdapterMode = AdapterObject->AdapterMode;
1999 
2000  if (WriteToDevice)
2001  {
2002  AdapterMode.TransferType = WRITE_TRANSFER;
2003  }
2004  else
2005  {
2006  AdapterMode.TransferType = READ_TRANSFER;
2007  if (AdapterObject->IgnoreCount)
2008  {
2009  RtlZeroMemory((PUCHAR)RealMapRegisterBase[Counter].VirtualAddress + ByteOffset,
2010  TransferLength);
2011  }
2012  }
2013 
2014  TransferOffset = PhysicalAddress.LowPart & 0xFFFF;
2015  if (AdapterObject->Width16Bits)
2016  {
2017  TransferLength >>= 1;
2018  TransferOffset >>= 1;
2019  }
2020 
2021  KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
2022 
2023  if (AdapterObject->AdapterNumber == 1)
2024  {
2025  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
2026 
2027  /* Reset Register */
2028  WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
2029 
2030  /* Set the Mode */
2031  WRITE_PORT_UCHAR(&DmaControl1->Mode, AdapterMode.Byte);
2032 
2033  /* Set the Offset Register */
2034  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2035  (UCHAR)(TransferOffset));
2036  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2037  (UCHAR)(TransferOffset >> 8));
2038 
2039  /* Set the Page Register */
2040  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
2041  (UCHAR)(PhysicalAddress.LowPart >> 16));
2042  if (HalpEisaDma)
2043  {
2044  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
2045  0);
2046  }
2047 
2048  /* Set the Length */
2049  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2050  (UCHAR)(TransferLength - 1));
2051  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2052  (UCHAR)((TransferLength - 1) >> 8));
2053 
2054  /* Unmask the Channel */
2055  WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK);
2056  }
2057  else
2058  {
2059  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
2060 
2061  /* Reset Register */
2062  WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
2063 
2064  /* Set the Mode */
2065  WRITE_PORT_UCHAR(&DmaControl2->Mode, AdapterMode.Byte);
2066 
2067  /* Set the Offset Register */
2068  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2069  (UCHAR)(TransferOffset));
2070  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2071  (UCHAR)(TransferOffset >> 8));
2072 
2073  /* Set the Page Register */
2074  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
2075  (UCHAR)(PhysicalAddress.u.LowPart >> 16));
2076  if (HalpEisaDma)
2077  {
2078  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
2079  0);
2080  }
2081 
2082  /* Set the Length */
2083  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2084  (UCHAR)(TransferLength - 1));
2085  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2086  (UCHAR)((TransferLength - 1) >> 8));
2087 
2088  /* Unmask the Channel */
2089  WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
2090  AdapterObject->ChannelNumber | DMA_CLEARMASK);
2091  }
2092 
2093  KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
2094  }
2095 
2096  /*
2097  * Return physical address of the buffer with data that is used for the
2098  * transfer. It can either point inside the Mdl that was passed by the
2099  * caller or into the map registers if the Mdl buffer can't be used
2100  * directly.
2101  */
2102  return PhysicalAddress;
2103 }
2104 #endif
2105 
2111 BOOLEAN
2112 NTAPI
2114  IN ULONG Length,
2115  IN PHYSICAL_ADDRESS LogicalAddress,
2117 {
2118  /* Function always returns true */
2119  return TRUE;
2120 }
2121 
2122 /*
2123  * @implemented
2124  */
2125 PVOID
2126 NTAPI
2129 {
2130  PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
2131  ULONG MapRegisterNumber;
2132 
2133  /* Check if it needs map registers */
2134  if (AdapterObject->NeedsMapRegisters)
2135  {
2136  /* Check if we have enough */
2137  if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
2138  {
2139  /* We don't, fail */
2140  AdapterObject->NumberOfMapRegisters = 0;
2141  return NULL;
2142  }
2143 
2144  /* Try to find free map registers */
2145  MapRegisterNumber = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
2147  0);
2148 
2149  /* Check if nothing was found */
2150  if (MapRegisterNumber == MAXULONG)
2151  {
2152  /* No free registers found, so use the base registers */
2153  RtlSetBits(MasterAdapter->MapRegisters,
2154  0,
2156  MapRegisterNumber = 0;
2157  }
2158 
2159  /* Calculate the new base */
2160  AdapterObject->MapRegisterBase =
2161  (PROS_MAP_REGISTER_ENTRY)(MasterAdapter->MapRegisterBase +
2162  MapRegisterNumber);
2163 
2164  /* Check if scatter gather isn't supported */
2165  if (!AdapterObject->ScatterGather)
2166  {
2167  /* Set the flag */
2168  AdapterObject->MapRegisterBase =
2170  ((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
2171  }
2172  }
2173  else
2174  {
2175  AdapterObject->MapRegisterBase = NULL;
2176  AdapterObject->NumberOfMapRegisters = 0;
2177  }
2178 
2179  /* Return the base */
2180  return AdapterObject->MapRegisterBase;
2181 }
2182 
2183 /* EOF */
#define DMA_SETMASK
Definition: haldma.h:174
UCHAR DmaBaseCount
Definition: haldma.h:184
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
enum _IO_ALLOCATION_ACTION IO_ALLOCATION_ACTION
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define ASSERT_IRQL_LESS_OR_EQUAL(x)
Definition: debug.h:251
PVOID(NTAPI * PALLOCATE_COMMON_BUFFER)(_In_ PDMA_ADAPTER DmaAdapter, _In_ ULONG Length, _Out_ PPHYSICAL_ADDRESS LogicalAddress, _In_ BOOLEAN CacheEnabled)
Definition: iotypes.h:2195
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define HalGetDmaAdapter
Definition: haltypes.h:291
#define IN
Definition: typedefs.h:38
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
#define TYPE_A_TIMING
Definition: haldma.h:150
UCHAR AutoInitialize
Definition: haldma.h:95
PDRIVER_LIST_CONTROL AdapterListControlRoutine
Definition: dma.c:926
#define MAX_SG_ELEMENTS
Definition: dma.c:84
UCHAR DmaBaseAddress
Definition: haldma.h:183
DMA1_ADDRESS_COUNT DmaAddressCount[4]
Definition: haldma.h:197
#define TRUE
Definition: types.h:120
#define B_32BITS
Definition: haldma.h:145
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
ULONG NTAPI HalReadDmaCounter(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:76
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:717
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
VOID(NTAPI * PPUT_SCATTER_GATHER_LIST)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PSCATTER_GATHER_LIST ScatterGather, _In_ BOOLEAN WriteToDevice)
Definition: iotypes.h:2275
struct _RTL_BITMAP RTL_BITMAP
_Out_ PULONG NumberOfMapRegisters
Definition: halfuncs.h:209
#define MmGetMdlPfnArray(_Mdl)
UCHAR SingleMask
Definition: haldma.h:215
_In_ ULONG Mode
Definition: hubbusif.h:303
#define MAXLONG
Definition: umtypes.h:116
#define MmGetMdlVirtualAddress(_Mdl)
static PADAPTER_OBJECT HalpEisaAdapter[8]
Definition: dma.c:89
_In_ PIRP Irp
Definition: csq.h:116
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
PHYSICAL_ADDRESS NTAPI IoMapTransfer(IN PADAPTER_OBJECT AdapterObject, IN PMDL Mdl, IN PVOID MapRegisterBase, IN PVOID CurrentVa, IN OUT PULONG Length, IN BOOLEAN WriteToDevice)
Definition: dma.c:144
UCHAR Mode
Definition: haldma.h:217
PFREE_MAP_REGISTERS FreeMapRegisters
Definition: iotypes.h:2317
ULONG NTAPI HalpDmaGetDmaAlignment(PADAPTER_OBJECT AdapterObject)
Definition: dma.c:918
unsigned char * PUCHAR
Definition: retypes.h:3
UCHAR NTAPI READ_PORT_UCHAR(PUCHAR Address)
Definition: mach.c:528
UCHAR DmaBaseAddress
Definition: haldma.h:189
struct _ADAPTER_OBJECT ADAPTER_OBJECT
LONG NTSTATUS
Definition: precomp.h:26
DMA_SPEED DmaSpeed
Definition: iotypes.h:2038
Definition: haldma.h:312
DMA2_ADDRESS_COUNT DmaAddressCount[4]
Definition: haldma.h:210
BOOLEAN(NTAPI * PFLUSH_ADAPTER_BUFFERS)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PMDL Mdl, _In_ PVOID MapRegisterBase, _In_ PVOID CurrentVa, _In_ ULONG Length, _In_ BOOLEAN WriteToDevice)
Definition: iotypes.h:2218
PVOID VirtualAddress
Definition: haldma.h:314
PHYSICAL_ADDRESS Address
Definition: iotypes.h:2065
VOID NTAPI KeInitializeDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
Definition: devqueue.c:22
#define TypeA
Definition: nslookup.h:13
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
PDRIVER_CONTROL DeviceRoutine
Definition: iotypes.h:196
#define OBJ_PERMANENT
Definition: winternl.h:226
#define BURST_TIMING
Definition: haldma.h:152
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
#define DMA_CLEARMASK
Definition: haldma.h:175
static const ULONG_PTR HalpEisaPortPage[8]
Definition: dma.c:96
UCHAR Byte
Definition: haldma.h:99
#define InsertTailList(ListHead, Entry)
ULONG MapRegisterCount
Definition: dma.c:928
static DMA_OPERATIONS HalpDmaOperations
Definition: dma.c:108
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
VOID NTAPI IoFreeMapRegisters(IN PADAPTER_OBJECT AdapterObject, IN PVOID MapRegisterBase, IN ULONG NumberOfMapRegisters)
Definition: dma.c:114
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
#define PAGE_ROUND_UP(x)
Definition: scsiport_int.h:13
VOID NTAPI HalpCopyBufferMap(PMDL Mdl, PROS_MAP_REGISTER_ENTRY MapRegisterBase, PVOID CurrentVa, ULONG Length, BOOLEAN WriteToDevice)
Definition: dma.c:1468
VOID(NTAPI * PFREE_ADAPTER_CHANNEL)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2227
static KEVENT HalpDmaLock
Definition: dma.c:87
WORK_QUEUE_ITEM WorkQueueItem
Definition: haldma.h:362
uint32_t ULONG_PTR
Definition: typedefs.h:63
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
VOID NTAPI HalPutScatterGatherList(IN PADAPTER_OBJECT AdapterObject, IN PSCATTER_GATHER_LIST ScatterGather, IN BOOLEAN WriteToDevice)
Definition: dma.c:1083
struct _SCATTER_GATHER_CONTEXT SCATTER_GATHER_CONTEXT
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define __WARNING_DEREF_NULL_PTR
Definition: suppress.h:32
ULONG * PPFN_NUMBER
Definition: ke.h:8
ULONG(NTAPI * PGET_DMA_ALIGNMENT)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2246
NTSTATUS(NTAPI * PALLOCATE_ADAPTER_CHANNEL)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PDEVICE_OBJECT DeviceObject, _In_ ULONG NumberOfMapRegisters, _In_ PDRIVER_CONTROL ExecutionRoutine, _In_ PVOID Context)
Definition: iotypes.h:2210
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
UCHAR SingleMask
Definition: haldma.h:200
PADAPTER_OBJECT AdapterObject
Definition: haldma.h:363
PVOID NTAPI HalAllocateCrashDumpRegisters(IN PADAPTER_OBJECT AdapterObject, IN OUT PULONG NumberOfMapRegisters)
Definition: dma.c:180
ULONG PFN_NUMBER
Definition: ke.h:8
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
struct _GROW_WORK_ITEM * PGROW_WORK_ITEM
NTSTATUS NTAPI HalAllocateAdapterChannel(IN PADAPTER_OBJECT AdapterObject, IN PWAIT_CONTEXT_BLOCK WaitContextBlock, IN ULONG NumberOfMapRegisters, IN PDRIVER_CONTROL ExecutionRoutine)
Definition: dma.c:88
UCHAR Channel
Definition: haldma.h:93
PMAP_TRANSFER MapTransfer
Definition: iotypes.h:2318
PHYSICAL_ADDRESS NTAPI HalpGetAdapterMaximumPhysicalAddress(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:167
BOOLEAN NTAPI HalpGrowMapBuffers(IN PADAPTER_OBJECT AdapterObject, IN ULONG SizeOfMapBuffers)
Definition: dma.c:203
#define FILE_READ_DATA
Definition: nt_native.h:628
BOOLEAN IgnoreCount
Definition: iotypes.h:2031
VOID HalpInitDma(VOID)
Definition: dma.c:121
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:251
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
static WCHAR Address[46]
Definition: ping.c:68
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
void DPRINT(...)
Definition: polytest.cpp:61
struct _ROS_MAP_REGISTER_ENTRY * PROS_MAP_REGISTER_ENTRY
NTSTATUS NTAPI ObReferenceObjectByPointer(IN PVOID Object, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode)
Definition: obref.c:383
UCHAR ClearBytePointer
Definition: haldma.h:219
void * PVOID
Definition: retypes.h:9
struct _SCATTER_GATHER_LIST SCATTER_GATHER_LIST
Definition: iotypes.h:2096
#define FILE_WRITE_DATA
Definition: nt_native.h:631
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define ULL(a, b)
Definition: format_msg.c:27
#define UlongToPtr(u)
Definition: config.h:106
VOID NTAPI IoFreeAdapterChannel(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:103
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:952
BOOLEAN Dma32BitAddresses
Definition: iotypes.h:2030
VOID NTAPI HalpGrowMapBufferWorker(PVOID DeferredContext)
Definition: dma.c:1005
#define B_16BITS
Definition: haldma.h:146
PFLUSH_ADAPTER_BUFFERS FlushAdapterBuffers
Definition: iotypes.h:2315
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
BOOLEAN Dma64BitAddresses
Definition: iotypes.h:2033
NTSTATUS NTAPI HalGetScatterGatherList(IN PADAPTER_OBJECT AdapterObject, IN PDEVICE_OBJECT DeviceObject, IN PMDL Mdl, IN PVOID CurrentVa, IN ULONG Length, IN PDRIVER_LIST_CONTROL ExecutionRoutine, IN PVOID Context, IN BOOLEAN WriteToDevice)
Definition: dma.c:1030
_Must_inspect_result_ _In_ PDEVICE_DESCRIPTION DeviceDescription
Definition: iofuncs.h:1015
_In_ HANDLE Handle
Definition: extypes.h:390
PHYSICAL_ADDRESS(NTAPI * PMAP_TRANSFER)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PMDL Mdl, _In_ PVOID MapRegisterBase, _In_ PVOID CurrentVa, _Inout_ PULONG Length, _In_ BOOLEAN WriteToDevice)
Definition: iotypes.h:2237
PADAPTER_OBJECT AdapterObject
Definition: dma.c:922
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
NTSTATUS NTAPI IoAllocateAdapterChannel(IN PADAPTER_OBJECT AdapterObject, IN PDEVICE_OBJECT DeviceObject, IN ULONG NumberOfMapRegisters, IN PDRIVER_CONTROL ExecutionRoutine, IN PVOID Context)
Definition: adapter.c:30
ULONG HalpBusType
Definition: bus.c:17
PFREE_ADAPTER_CHANNEL FreeAdapterChannel
Definition: iotypes.h:2316
#define COMPATIBLE_TIMING
Definition: haldma.h:149
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
BOOLEAN DemandMode
Definition: iotypes.h:2028
struct _LARGE_INTEGER::@2216 u
BOOLEAN ScatterGather
Definition: iotypes.h:2027
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
static const UCHAR Index[8]
Definition: usbohci.c:18
BOOLEAN NTAPI KeInsertDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue, IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)
Definition: devqueue.c:41
VOID NTAPI RtlClearBit(_In_ PRTL_BITMAP BitMapHeader, _In_ BITMAP_INDEX BitNumber)
Definition: bitmap.c:294
#define for
Definition: utility.h:88
BOOLEAN NTAPI IoFlushAdapterBuffers(IN PADAPTER_OBJECT AdapterObject, IN PMDL Mdl, IN PVOID MapRegisterBase, IN PVOID CurrentVa, IN ULONG Length, IN BOOLEAN WriteToDevice)
Definition: dma.c:127
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
DMA_WIDTH DmaWidth
Definition: iotypes.h:2037
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define BYTES_TO_PAGES(Size)
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS PhysicalAddress
Definition: iotypes.h:1061
unsigned char UCHAR
Definition: xmlstorage.h:181
UCHAR TransferType
Definition: haldma.h:94
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
UCHAR DmaBaseCount
Definition: haldma.h:191
POBJECT_TYPE IoAdapterObjectType
Definition: adapter.c:18
PHYSICAL_ADDRESS PhysicalAddress
Definition: haldma.h:315
UCHAR ChannelNumber
Definition: haldma.h:133
_Out_ PNDIS_HANDLE _Out_ PUINT _In_ PNDIS_STRING _In_ NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress
Definition: ndis.h:3227
ULONG LowPart
Definition: typedefs.h:104
VOID(NTAPI * PFREE_COMMON_BUFFER)(_In_ PDMA_ADAPTER DmaAdapter, _In_ ULONG Length, _In_ PHYSICAL_ADDRESS LogicalAddress, _In_ PVOID VirtualAddress, _In_ BOOLEAN CacheEnabled)
Definition: iotypes.h:2202
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:117
static PADAPTER_OBJECT HalpMasterAdapter
Definition: dma.c:93
_In_ ULONG _In_ BOOLEAN _Must_inspect_result_ PVOID * VirtualAddress
Definition: ndis.h:3791
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
#define TAG_DMA
Definition: dma.c:131
NTSYSAPI ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP, ULONG, ULONG)
#define READ_TRANSFER
Definition: haldma.h:165
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS LowestAcceptableAddress
Definition: mmfuncs.h:214
VOID(NTAPI * PPUT_DMA_ADAPTER)(PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2191
WAIT_CONTEXT_BLOCK Wcb
Definition: dma.c:930
BOOLEAN NTAPI HalpDmaInitializeEisaAdapter(PADAPTER_OBJECT AdapterObject, PDEVICE_DESCRIPTION DeviceDescription)
Definition: dma.c:461
static LIST_ENTRY HalpDmaAdapterList
Definition: dma.c:88
Status
Definition: gdiplustypes.h:24
struct _DMA_OPERATIONS DMA_OPERATIONS
VOID NTAPI HalPutDmaAdapter(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:35
#define MAXULONG
Definition: typedefs.h:250
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
UnicodeString MaximumLength
Definition: rtlfuncs.h:2982
PVOID MapRegisterBase
Definition: dma.c:927
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
UCHAR RequestMode
Definition: haldma.h:97
VOID FASTCALL KfLowerIrql(IN KIRQL NewIrql)
Definition: pic.c:232
_Inout_ struct _IRP _In_ PVOID MapRegisterBase
Definition: iotypes.h:189
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2932
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
PALLOCATE_ADAPTER_CHANNEL AllocateAdapterChannel
Definition: iotypes.h:2314
#define MAX_MAP_REGISTERS
Definition: dma.c:129
PDMA_ADAPTER NTAPI HalpGetDmaAdapter(IN PVOID Context, IN PDEVICE_DESCRIPTION DeviceDescription, OUT PULONG NumberOfMapRegisters)
Definition: dma.c:790
UCHAR TransferSize
Definition: haldma.h:134
Definition: ketypes.h:566
unsigned short USHORT
Definition: pedump.c:61
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
DRIVER_LIST_CONTROL * PDRIVER_LIST_CONTROL
Definition: iotypes.h:2261
ULONG(NTAPI * PREAD_DMA_COUNTER)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2250
PKDEVICE_QUEUE_ENTRY NTAPI KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
Definition: devqueue.c:153
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
unsigned int * PULONG
Definition: retypes.h:1
_In_ struct _IRP _In_ struct _SCATTER_GATHER_LIST * ScatterGather
Definition: iotypes.h:2259
VOID(NTAPI * PFREE_MAP_REGISTERS)(_In_ PDMA_ADAPTER DmaAdapter, PVOID MapRegisterBase, ULONG NumberOfMapRegisters)
Definition: iotypes.h:2231
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define DPRINT1
Definition: precomp.h:8
BOOLEAN NTAPI HalFlushCommonBuffer(IN PADAPTER_OBJECT AdapterObject, IN ULONG Length, IN PHYSICAL_ADDRESS LogicalAddress, IN PVOID VirtualAddress)
Definition: dma.c:165
static LARGE_INTEGER Counter
Definition: clock.c:43
#define DEVICE_DESCRIPTION_VERSION2
Definition: iotypes.h:2022
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
VOID NTAPI MmFreeContiguousMemorySpecifyCache(IN PVOID BaseAddress, IN SIZE_T NumberOfBytes, IN MEMORY_CACHING_TYPE CacheType)
Definition: contmem.c:666
#define SINGLE_REQUEST_MODE
Definition: haldma.h:170
#define OUT
Definition: typedefs.h:39
INTERFACE_TYPE InterfaceType
Definition: iotypes.h:2036
_In_ PDEVICE_OBJECT _In_ ULONG _In_ PDRIVER_CONTROL ExecutionRoutine
Definition: iofuncs.h:1393
PVOID AdapterListControlContext
Definition: dma.c:927
struct _SCATTER_GATHER_LIST * PSCATTER_GATHER_LIST
Definition: iotypes.h:2096
#define TYPE_B_TIMING
Definition: haldma.h:151
struct tagContext Context
Definition: acpixf.h:1030
unsigned int ULONG
Definition: retypes.h:1
#define DEMAND_REQUEST_MODE
Definition: haldma.h:169
void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value)
Definition: mach.c:532
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ULONG_PTR
Definition: config.h:101
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
PHYSICAL_ADDRESS NTAPI MmGetPhysicalAddress(IN PVOID Address)
Definition: stubs.c:682
DRIVER_CONTROL * PDRIVER_CONTROL
Definition: iotypes.h:192
UCHAR Mode
Definition: haldma.h:201
PADAPTER_OBJECT NTAPI HalpDmaAllocateChildAdapter(ULONG NumberOfMapRegisters, PDEVICE_DESCRIPTION DeviceDescription)
Definition: dma.c:391
NTSYSAPI void WINAPI RtlSetBits(PRTL_BITMAP, ULONG, ULONG)
#define WRITE_TRANSFER
Definition: haldma.h:166
IO_ALLOCATION_ACTION NTAPI HalpScatterGatherAdapterControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID MapRegisterBase, IN PVOID Context)
Definition: dma.c:936
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
_Inout_ PKDEVICE_QUEUE_ENTRY DeviceQueueEntry
Definition: kefuncs.h:352
#define DEVICE_DESCRIPTION_VERSION1
Definition: iotypes.h:2021
ULONG NumberOfMapRegisters
Definition: haldma.h:364
#define B_8BITS
Definition: haldma.h:143
#define MAP_BASE_SW_SG
Definition: haldma.h:367
PVOID NTAPI HalAllocateCommonBuffer(IN PADAPTER_OBJECT AdapterObject, IN ULONG Length, IN PPHYSICAL_ADDRESS LogicalAddress, IN BOOLEAN CacheEnabled)
Definition: dma.c:46
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define CASCADE_REQUEST_MODE
Definition: haldma.h:172
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
static BOOLEAN HalpEisaDma
Definition: dma.c:91
UCHAR ClearBytePointer
Definition: haldma.h:202
#define BYTE_OFFSET(Va)
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:107
VOID NTAPI HalFreeCommonBuffer(IN PADAPTER_OBJECT AdapterObject, IN ULONG Length, IN PHYSICAL_ADDRESS LogicalAddress, IN PVOID VirtualAddress, IN BOOLEAN CacheEnabled)
Definition: dma.c:61
#define MACHINE_TYPE_EISA
Definition: ketypes.h:53
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS(NTAPI * PGET_SCATTER_GATHER_LIST)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PDEVICE_OBJECT DeviceObject, _In_ PMDL Mdl, _In_ PVOID CurrentVa, _In_ ULONG Length, _In_ PDRIVER_LIST_CONTROL ExecutionRoutine, _In_ PVOID Context, _In_ BOOLEAN WriteToDevice)
Definition: iotypes.h:2264
PADAPTER_OBJECT NTAPI HalpDmaAllocateMasterAdapter(VOID)
Definition: dma.c:332
BOOLEAN AutoInitialize
Definition: iotypes.h:2029
struct _SCATTER_GATHER_CONTEXT * PSCATTER_GATHER_CONTEXT
LONGLONG QuadPart
Definition: typedefs.h:112
ULONG Counter
Definition: haldma.h:316
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:716
ULONG NumberOfMapRegisters
Definition: iotypes.h:198
PADAPTER_OBJECT NTAPI HalGetAdapter(IN PDEVICE_DESCRIPTION DeviceDescription, OUT PULONG NumberOfMapRegisters)
Definition: dma.c:22
#define _PRAGMA_WARNING_SUPPRESS(x)
Definition: suppress.h:28
BOOLEAN WriteToDevice
Definition: dma.c:929
PVOID NTAPI MmAllocateContiguousMemorySpecifyCache(IN SIZE_T NumberOfBytes, IN PHYSICAL_ADDRESS LowestAcceptableAddress OPTIONAL, IN PHYSICAL_ADDRESS HighestAcceptableAddress, IN PHYSICAL_ADDRESS BoundaryAddressMultiple OPTIONAL, IN MEMORY_CACHING_TYPE CacheType OPTIONAL)
Definition: contmem.c:574
UCHAR TimingMode
Definition: haldma.h:135
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:675