ReactOS  0.4.15-dev-449-g64abd9f
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_
91 #endif
93 #ifndef _MINIHAL_
95 #endif
96 
97 static const ULONG_PTR HalpEisaPortPage[8] = {
98  FIELD_OFFSET(DMA_PAGE, Channel0),
99  FIELD_OFFSET(DMA_PAGE, Channel1),
100  FIELD_OFFSET(DMA_PAGE, Channel2),
101  FIELD_OFFSET(DMA_PAGE, Channel3),
102  0,
103  FIELD_OFFSET(DMA_PAGE, Channel5),
104  FIELD_OFFSET(DMA_PAGE, Channel6),
105  FIELD_OFFSET(DMA_PAGE, Channel7)
106 };
107 
108 #ifndef _MINIHAL_
110  sizeof(DMA_OPERATIONS),
114  NULL, /* Initialized in HalpInitDma() */
115  NULL, /* Initialized in HalpInitDma() */
116  NULL, /* Initialized in HalpInitDma() */
117  NULL, /* Initialized in HalpInitDma() */
118  NULL, /* Initialized in HalpInitDma() */
121  /* FIXME: Implement the S/G funtions. */
124  NULL /*(PCALCULATE_SCATTER_GATHER_LIST_SIZE)HalCalculateScatterGatherListSize*/,
125  NULL /*(PBUILD_SCATTER_GATHER_LIST)HalBuildScatterGatherList*/,
126  NULL /*(PBUILD_MDL_FROM_SCATTER_GATHER_LIST)HalBuildMdlFromScatterGatherList*/
127 };
128 #endif
129 
130 #define MAX_MAP_REGISTERS 64
131 
132 #define TAG_DMA ' AMD'
133 
134 /* FUNCTIONS *****************************************************************/
135 
136 #ifndef _MINIHAL_
137 INIT_FUNCTION
138 VOID
140 {
141  /*
142  * Initialize the DMA Operation table
143  */
149 
151  {
152  /*
153  * Check if Extended DMA is available. We're just going to do a random
154  * read and write.
155  */
156  WRITE_PORT_UCHAR(UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2)), 0x2A);
157  if (READ_PORT_UCHAR(UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2))) == 0x2A)
158  {
159  DPRINT1("Machine supports EISA DMA. Bus type: %lu\n", HalpBusType);
160  HalpEisaDma = TRUE;
161  }
162  }
163 
164  /*
165  * Intialize all the global variables and allocate master adapter with
166  * first map buffers.
167  */
172 
173  /*
174  * Setup the HalDispatchTable callback for creating PnP DMA adapters. It's
175  * used by IoGetDmaAdapter in the kernel.
176  */
178 }
179 #endif
180 
188 NTAPI
190 {
191  PHYSICAL_ADDRESS HighestAddress;
192 
193  if (AdapterObject->MasterDevice)
194  {
195  if (AdapterObject->Dma64BitAddresses)
196  {
197  HighestAddress.QuadPart = 0xFFFFFFFFFFFFFFFFULL;
198  return HighestAddress;
199  }
200  else if (AdapterObject->Dma32BitAddresses)
201  {
202  HighestAddress.QuadPart = 0xFFFFFFFF;
203  return HighestAddress;
204  }
205  }
206 
207  HighestAddress.QuadPart = 0xFFFFFF;
208  return HighestAddress;
209 }
210 
211 #ifndef _MINIHAL_
212 
223 BOOLEAN
224 NTAPI
226  IN ULONG SizeOfMapBuffers)
227 {
232  PHYSICAL_ADDRESS BoundryAddressMultiple;
233  KIRQL OldIrql;
234  ULONG MapRegisterCount;
235 
236  /* Check if enough map register slots are available. */
237  MapRegisterCount = BYTES_TO_PAGES(SizeOfMapBuffers);
238  if (MapRegisterCount + AdapterObject->NumberOfMapRegisters > MAX_MAP_REGISTERS)
239  {
240  DPRINT("No more map register slots available! (Current: %d | Requested: %d | Limit: %d)\n",
241  AdapterObject->NumberOfMapRegisters,
242  MapRegisterCount,
244  return FALSE;
245  }
246 
247  /*
248  * Allocate memory for the new map registers. For 32-bit adapters we use
249  * two passes in order not to waste scare resource (low memory).
250  */
253  LowestAcceptableAddress.LowPart = HighestAcceptableAddress.LowPart == 0xFFFFFFFF ? 0x1000000 : 0;
254  BoundryAddressMultiple.QuadPart = 0;
255 
259  BoundryAddressMultiple,
260  MmNonCached);
262  {
267  BoundryAddressMultiple,
268  MmNonCached);
269  }
270 
271  if (!VirtualAddress) return FALSE;
272 
274 
275  /*
276  * All the following must be done with the master adapter lock held
277  * to prevent corruption.
278  */
279  KeAcquireSpinLock(&AdapterObject->SpinLock, &OldIrql);
280 
281  /*
282  * Setup map register entries for the buffer allocated. Each entry has
283  * a virtual and physical address and corresponds to PAGE_SIZE large
284  * buffer.
285  */
286  if (MapRegisterCount > 0)
287  {
288  PROS_MAP_REGISTER_ENTRY CurrentEntry, PreviousEntry;
289 
290  CurrentEntry = AdapterObject->MapRegisterBase + AdapterObject->NumberOfMapRegisters;
291  do
292  {
293  /*
294  * Leave one entry free for every non-contiguous memory region
295  * in the map register bitmap. This ensures that we can search
296  * using RtlFindClearBits for contiguous map register regions.
297  *
298  * Also for non-EISA DMA leave one free entry for every 64Kb
299  * break, because the DMA controller can handle only coniguous
300  * 64Kb regions.
301  */
302  if (CurrentEntry != AdapterObject->MapRegisterBase)
303  {
304  PreviousEntry = CurrentEntry - 1;
305  if ((PreviousEntry->PhysicalAddress.LowPart + PAGE_SIZE) == PhysicalAddress.LowPart)
306  {
307  if (!HalpEisaDma)
308  {
309  if ((PreviousEntry->PhysicalAddress.LowPart ^ PhysicalAddress.LowPart) & 0xFFFF0000)
310  {
311  CurrentEntry++;
312  AdapterObject->NumberOfMapRegisters++;
313  }
314  }
315  }
316  else
317  {
318  CurrentEntry++;
319  AdapterObject->NumberOfMapRegisters++;
320  }
321  }
322 
323  RtlClearBit(AdapterObject->MapRegisters,
324  (ULONG)(CurrentEntry - AdapterObject->MapRegisterBase));
325  CurrentEntry->VirtualAddress = VirtualAddress;
326  CurrentEntry->PhysicalAddress = PhysicalAddress;
327 
330 
331  CurrentEntry++;
332  AdapterObject->NumberOfMapRegisters++;
333  MapRegisterCount--;
334  } while (MapRegisterCount);
335  }
336 
337  KeReleaseSpinLock(&AdapterObject->SpinLock, OldIrql);
338 
339  return TRUE;
340 }
341 
351 NTAPI
353 {
354  PADAPTER_OBJECT MasterAdapter;
355  ULONG Size, SizeOfBitmap;
356 
357  SizeOfBitmap = MAX_MAP_REGISTERS;
358  Size = sizeof(ADAPTER_OBJECT);
359  Size += sizeof(RTL_BITMAP);
360  Size += (SizeOfBitmap + 7) >> 3;
361 
362  MasterAdapter = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_DMA);
363  if (!MasterAdapter) return NULL;
364 
365  RtlZeroMemory(MasterAdapter, Size);
366 
367  KeInitializeSpinLock(&MasterAdapter->SpinLock);
368  InitializeListHead(&MasterAdapter->AdapterQueue);
369 
370  MasterAdapter->MapRegisters = (PVOID)(MasterAdapter + 1);
371  RtlInitializeBitMap(MasterAdapter->MapRegisters,
372  (PULONG)(MasterAdapter->MapRegisters + 1),
373  SizeOfBitmap);
374  RtlSetAllBits(MasterAdapter->MapRegisters);
375  MasterAdapter->NumberOfMapRegisters = 0;
376  MasterAdapter->CommittedMapRegisters = 0;
377 
378  MasterAdapter->MapRegisterBase = ExAllocatePoolWithTag(NonPagedPool,
379  SizeOfBitmap *
380  sizeof(ROS_MAP_REGISTER_ENTRY),
381  TAG_DMA);
382  if (!MasterAdapter->MapRegisterBase)
383  {
384  ExFreePool(MasterAdapter);
385  return NULL;
386  }
387 
388  RtlZeroMemory(MasterAdapter->MapRegisterBase,
389  SizeOfBitmap * sizeof(ROS_MAP_REGISTER_ENTRY));
390  if (!HalpGrowMapBuffers(MasterAdapter, 0x10000))
391  {
392  ExFreePool(MasterAdapter);
393  return NULL;
394  }
395 
396  return MasterAdapter;
397 }
398 
408 NTAPI
411 {
412  PADAPTER_OBJECT AdapterObject;
415  HANDLE Handle;
416 
418  NULL,
420  NULL,
421  NULL);
422 
426  KernelMode,
427  NULL,
428  sizeof(ADAPTER_OBJECT),
429  0,
430  0,
431  (PVOID)&AdapterObject);
432  if (!NT_SUCCESS(Status)) return NULL;
433 
434  Status = ObReferenceObjectByPointer(AdapterObject,
437  KernelMode);
438  if (!NT_SUCCESS(Status)) return NULL;
439 
440  RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT));
441 
442  Status = ObInsertObject(AdapterObject,
443  NULL,
445  0,
446  NULL,
447  &Handle);
448  if (!NT_SUCCESS(Status)) return NULL;
449 
450  ZwClose(Handle);
451 
452  AdapterObject->DmaHeader.Version = (USHORT)DeviceDescription->Version;
453  AdapterObject->DmaHeader.Size = sizeof(ADAPTER_OBJECT);
454  AdapterObject->DmaHeader.DmaOperations = &HalpDmaOperations;
455  AdapterObject->MapRegistersPerChannel = 1;
456  AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
457  AdapterObject->ChannelNumber = 0xFF;
458  AdapterObject->MasterAdapter = HalpMasterAdapter;
459  KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue);
460 
461  return AdapterObject;
462 }
463 #endif
464 
470 BOOLEAN
471 NTAPI
474 {
475  UCHAR Controller;
476  DMA_MODE DmaMode = {{0 }};
477  DMA_EXTENDED_MODE ExtendedMode = {{ 0 }};
478  PVOID AdapterBaseVa;
479 
480  Controller = (DeviceDescription->DmaChannel & 4) ? 2 : 1;
481 
482  if (Controller == 1)
483  {
484  AdapterBaseVa = UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController1));
485  }
486  else
487  {
488  AdapterBaseVa = UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2));
489  }
490 
491  AdapterObject->AdapterNumber = Controller;
492  AdapterObject->ChannelNumber = (UCHAR)(DeviceDescription->DmaChannel & 3);
493  AdapterObject->PagePort = (PUCHAR)HalpEisaPortPage[DeviceDescription->DmaChannel];
494  AdapterObject->Width16Bits = FALSE;
495  AdapterObject->AdapterBaseVa = AdapterBaseVa;
496 
497  if (HalpEisaDma)
498  {
499  ExtendedMode.ChannelNumber = AdapterObject->ChannelNumber;
500 
501  switch (DeviceDescription->DmaSpeed)
502  {
503  case Compatible: ExtendedMode.TimingMode = COMPATIBLE_TIMING; break;
504  case TypeA: ExtendedMode.TimingMode = TYPE_A_TIMING; break;
505  case TypeB: ExtendedMode.TimingMode = TYPE_B_TIMING; break;
506  case TypeC: ExtendedMode.TimingMode = BURST_TIMING; break;
507  default:
508  return FALSE;
509  }
510 
511  switch (DeviceDescription->DmaWidth)
512  {
513  case Width8Bits: ExtendedMode.TransferSize = B_8BITS; break;
514  case Width16Bits: ExtendedMode.TransferSize = B_16BITS; break;
515  case Width32Bits: ExtendedMode.TransferSize = B_32BITS; break;
516  default:
517  return FALSE;
518  }
519 
520  if (Controller == 1)
521  {
523  ExtendedMode.Byte);
524  }
525  else
526  {
528  ExtendedMode.Byte);
529  }
530  }
531  else
532  {
533  /*
534  * Validate setup for non-busmaster DMA adapter. Secondary controller
535  * supports only 16-bit transfers and main controller supports only
536  * 8-bit transfers. Anything else is invalid.
537  */
539  {
540  if ((Controller == 2) && (DeviceDescription->DmaWidth == Width16Bits))
541  {
542  AdapterObject->Width16Bits = TRUE;
543  }
544  else if ((Controller != 1) || (DeviceDescription->DmaWidth != Width8Bits))
545  {
546  return FALSE;
547  }
548  }
549  }
550 
551  DmaMode.Channel = AdapterObject->ChannelNumber;
553 
554  /*
555  * Set the DMA request mode.
556  *
557  * For (E)ISA bus master devices just unmask (enable) the DMA channel
558  * and set it to cascade mode. Otherwise just select the right one
559  * bases on the passed device description.
560  */
562  {
564  if (Controller == 1)
565  {
566  /* Set the Request Data */
568  WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte);
569 
570  /* Unmask DMA Channel */
571  WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->SingleMask,
572  AdapterObject->ChannelNumber | DMA_CLEARMASK);
573  }
574  else
575  {
576  /* Set the Request Data */
577  WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte);
578 
579  /* Unmask DMA Channel */
580  WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->SingleMask,
581  AdapterObject->ChannelNumber | DMA_CLEARMASK);
582  }
583  }
584  else
585  {
587  {
589  }
590  else
591  {
593  }
594  }
595 
596  AdapterObject->AdapterMode = DmaMode;
597 
598  return TRUE;
599 }
600 
601 #ifndef _MINIHAL_
602 
618 NTAPI
621 {
622  PADAPTER_OBJECT AdapterObject = NULL;
624  ULONG MapRegisters;
626  KIRQL OldIrql;
627 
628  /* Validate parameters in device description */
630 
631  /*
632  * See if we're going to use ISA/EISA DMA adapter. These adapters are
633  * special since they're reused.
634  *
635  * Also note that we check for channel number since there are only 8 DMA
636  * channels on ISA, so any request above this requires new adapter.
637  */
638  if (((DeviceDescription->InterfaceType == Eisa) ||
640  {
641  if (((DeviceDescription->InterfaceType == Isa) ||
644  {
645  EisaAdapter = FALSE;
646  }
647  else
648  {
649  EisaAdapter = TRUE;
650  }
651  }
652  else
653  {
654  EisaAdapter = FALSE;
655  }
656 
657  /*
658  * Disallow creating adapter for ISA/EISA DMA channel 4 since it's used
659  * for cascading the controllers and it's not available for software use.
660  */
661  if ((EisaAdapter) && (DeviceDescription->DmaChannel == 4)) return NULL;
662 
663  /*
664  * Calculate the number of map registers.
665  *
666  * - For EISA and PCI scatter/gather no map registers are needed.
667  * - For ISA slave scatter/gather one map register is needed.
668  * - For all other cases the number of map registers depends on
669  * DeviceDescription->MaximumLength.
670  */
675  {
676  MapRegisters = 0;
677  }
679  {
680  MapRegisters = 1;
681  }
682  else
683  {
684  /*
685  * In the equation below the additional map register added by
686  * the "+1" accounts for the case when a transfer does not start
687  * at a page-aligned address.
688  */
689  MapRegisters = BYTES_TO_PAGES(MaximumLength) + 1;
690  if (MapRegisters > 16) MapRegisters = 16;
691  }
692 
693  /*
694  * Acquire the DMA lock that is used to protect the EISA adapter array.
695  */
697 
698  /*
699  * Now we must get ahold of the adapter object. For first eight ISA/EISA
700  * channels there are static adapter objects that are reused and updated
701  * on succesive HalGetAdapter calls. In other cases a new adapter object
702  * is always created and it's to the DMA adapter list (HalpDmaAdapterList).
703  */
704  if (EisaAdapter)
705  {
706  AdapterObject = HalpEisaAdapter[DeviceDescription->DmaChannel];
707  if (AdapterObject)
708  {
709  if ((AdapterObject->NeedsMapRegisters) &&
710  (MapRegisters > AdapterObject->MapRegistersPerChannel))
711  {
712  AdapterObject->MapRegistersPerChannel = MapRegisters;
713  }
714  }
715  }
716 
717  if (AdapterObject == NULL)
718  {
719  AdapterObject = HalpDmaAllocateChildAdapter(MapRegisters, DeviceDescription);
720  if (AdapterObject == NULL)
721  {
722  KeSetEvent(&HalpDmaLock, 0, 0);
723  return NULL;
724  }
725 
726  if (EisaAdapter)
727  {
728  HalpEisaAdapter[DeviceDescription->DmaChannel] = AdapterObject;
729  }
730 
731  if (MapRegisters > 0)
732  {
733  AdapterObject->NeedsMapRegisters = TRUE;
734  AdapterObject->MapRegistersPerChannel = MapRegisters;
735  }
736  else
737  {
738  AdapterObject->NeedsMapRegisters = FALSE;
740  {
741  AdapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(MaximumLength) + 1;
742  }
743  else
744  {
745  AdapterObject->MapRegistersPerChannel = 1;
746  }
747  }
748  }
749 
750  /*
751  * Release the DMA lock. HalpEisaAdapter will no longer be touched,
752  * so we don't need it.
753  */
754  KeSetEvent(&HalpDmaLock, 0, 0);
755 
756  if (!EisaAdapter)
757  {
758  /* If it's not one of the static adapters, add it to the list */
760  InsertTailList(&HalpDmaAdapterList, &AdapterObject->AdapterList);
762  }
763 
764  /*
765  * Setup the values in the adapter object that are common for all
766  * types of buses.
767  */
769  {
770  AdapterObject->IgnoreCount = DeviceDescription->IgnoreCount;
771  }
772  else
773  {
774  AdapterObject->IgnoreCount = 0;
775  }
776 
777  AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
778  AdapterObject->Dma64BitAddresses = DeviceDescription->Dma64BitAddresses;
779  AdapterObject->ScatterGather = DeviceDescription->ScatterGather;
780  AdapterObject->MasterDevice = DeviceDescription->Master;
781  *NumberOfMapRegisters = AdapterObject->MapRegistersPerChannel;
782 
783  /*
784  * For non-(E)ISA adapters we have already done all the work. On the
785  * other hand for (E)ISA adapters we must still setup the DMA modes
786  * and prepare the controller.
787  */
788  if (EisaAdapter)
789  {
790  if (!HalpDmaInitializeEisaAdapter(AdapterObject, DeviceDescription))
791  {
792  ObDereferenceObject(AdapterObject);
793  return NULL;
794  }
795  }
796 
797  return AdapterObject;
798 }
799 
809 NTAPI
813 {
815 }
816 
825 VOID
826 NTAPI
828 {
829  KIRQL OldIrql;
830  if (AdapterObject->ChannelNumber == 0xFF)
831  {
833  RemoveEntryList(&AdapterObject->AdapterList);
835  }
836 
837  ObDereferenceObject(AdapterObject);
838 }
839 
865 PVOID
866 NTAPI
868  IN ULONG Length,
869  IN PPHYSICAL_ADDRESS LogicalAddress,
870  IN BOOLEAN CacheEnabled)
871 {
874  PHYSICAL_ADDRESS BoundryAddressMultiple;
876 
879  BoundryAddressMultiple.QuadPart = 0;
880 
881  /*
882  * For bus-master DMA devices the buffer mustn't cross 4Gb boundary. For
883  * slave DMA devices the 64Kb boundary mustn't be crossed since the
884  * controller wouldn't be able to handle it.
885  */
886  if (AdapterObject->MasterDevice)
887  {
888  BoundryAddressMultiple.HighPart = 1;
889  }
890  else
891  {
892  BoundryAddressMultiple.LowPart = 0x10000;
893  }
894 
898  BoundryAddressMultiple,
899  CacheEnabled ? MmCached :
900  MmNonCached);
901  if (VirtualAddress == NULL) return NULL;
902 
903  *LogicalAddress = MmGetPhysicalAddress(VirtualAddress);
904 
905  return VirtualAddress;
906 }
907 
917 VOID
918 NTAPI
920  IN ULONG Length,
921  IN PHYSICAL_ADDRESS LogicalAddress,
923  IN BOOLEAN CacheEnabled)
924 {
926  Length,
927  CacheEnabled ? MmCached : MmNonCached);
928 }
929 
930 typedef struct _SCATTER_GATHER_CONTEXT {
941 
942 
944 NTAPI
946  IN PIRP Irp,
948  IN PVOID Context)
949 {
950  PSCATTER_GATHER_CONTEXT AdapterControlContext = Context;
951  PADAPTER_OBJECT AdapterObject = AdapterControlContext->AdapterObject;
952  PSCATTER_GATHER_LIST ScatterGatherList;
954  ULONG ElementCount = 0, RemainingLength = AdapterControlContext->Length;
955  PUCHAR CurrentVa = AdapterControlContext->CurrentVa;
956 
957  /* Store the map register base for later in HalPutScatterGatherList */
958  AdapterControlContext->MapRegisterBase = MapRegisterBase;
959 
960  while (RemainingLength > 0 && ElementCount < MAX_SG_ELEMENTS)
961  {
962  TempElements[ElementCount].Length = RemainingLength;
963  TempElements[ElementCount].Reserved = 0;
964  TempElements[ElementCount].Address = IoMapTransfer(AdapterObject,
965  AdapterControlContext->Mdl,
967  CurrentVa + (AdapterControlContext->Length - RemainingLength),
968  &TempElements[ElementCount].Length,
969  AdapterControlContext->WriteToDevice);
970  if (TempElements[ElementCount].Length == 0)
971  break;
972 
973  DPRINT("Allocated one S/G element: 0x%I64u with length: 0x%x\n",
974  TempElements[ElementCount].Address.QuadPart,
975  TempElements[ElementCount].Length);
976 
977  ASSERT(TempElements[ElementCount].Length <= RemainingLength);
978  RemainingLength -= TempElements[ElementCount].Length;
979  ElementCount++;
980  }
981 
982  if (RemainingLength > 0)
983  {
984  DPRINT1("Scatter/gather list construction failed!\n");
985  return DeallocateObject;
986  }
987 
988  ScatterGatherList = ExAllocatePoolWithTag(NonPagedPool,
989  sizeof(SCATTER_GATHER_LIST) + sizeof(SCATTER_GATHER_ELEMENT) * ElementCount,
990  TAG_DMA);
991  ASSERT(ScatterGatherList);
992 
993  ScatterGatherList->NumberOfElements = ElementCount;
994  ScatterGatherList->Reserved = (ULONG_PTR)AdapterControlContext;
995  RtlCopyMemory(ScatterGatherList->Elements,
996  TempElements,
997  sizeof(SCATTER_GATHER_ELEMENT) * ElementCount);
998 
999  DPRINT("Initiating S/G DMA with %d element(s)\n", ElementCount);
1000 
1001  AdapterControlContext->AdapterListControlRoutine(DeviceObject,
1002  Irp,
1003  ScatterGatherList,
1004  AdapterControlContext->AdapterListControlContext);
1005 
1007 }
1008 
1037  NTSTATUS
1038  NTAPI
1041  IN PMDL Mdl,
1042  IN PVOID CurrentVa,
1043  IN ULONG Length,
1045  IN PVOID Context,
1046  IN BOOLEAN WriteToDevice)
1047 {
1048  PSCATTER_GATHER_CONTEXT AdapterControlContext;
1049 
1050  AdapterControlContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCATTER_GATHER_CONTEXT), TAG_DMA);
1051  if (!AdapterControlContext) return STATUS_INSUFFICIENT_RESOURCES;
1052 
1053  AdapterControlContext->AdapterObject = AdapterObject;
1054  AdapterControlContext->Mdl = Mdl;
1055  AdapterControlContext->CurrentVa = CurrentVa;
1056  AdapterControlContext->Length = Length;
1057  AdapterControlContext->MapRegisterCount = PAGE_ROUND_UP(Length) >> PAGE_SHIFT;
1058  AdapterControlContext->AdapterListControlRoutine = ExecutionRoutine;
1059  AdapterControlContext->AdapterListControlContext = Context;
1060  AdapterControlContext->WriteToDevice = WriteToDevice;
1061 
1062  AdapterControlContext->Wcb.DeviceObject = DeviceObject;
1063  AdapterControlContext->Wcb.DeviceContext = AdapterControlContext;
1064  AdapterControlContext->Wcb.CurrentIrp = DeviceObject->CurrentIrp;
1065 
1066  return HalAllocateAdapterChannel(AdapterObject,
1067  &AdapterControlContext->Wcb,
1068  AdapterControlContext->MapRegisterCount,
1070 }
1071 
1090  VOID
1091  NTAPI
1094  IN BOOLEAN WriteToDevice)
1095 {
1096  PSCATTER_GATHER_CONTEXT AdapterControlContext = (PSCATTER_GATHER_CONTEXT)ScatterGather->Reserved;
1097  ULONG i;
1098 
1099  for (i = 0; i < ScatterGather->NumberOfElements; i++)
1100  {
1101  IoFlushAdapterBuffers(AdapterObject,
1102  AdapterControlContext->Mdl,
1103  AdapterControlContext->MapRegisterBase,
1104  AdapterControlContext->CurrentVa,
1105  ScatterGather->Elements[i].Length,
1106  AdapterControlContext->WriteToDevice);
1107  AdapterControlContext->CurrentVa += ScatterGather->Elements[i].Length;
1108  }
1109 
1110  IoFreeMapRegisters(AdapterObject,
1111  AdapterControlContext->MapRegisterBase,
1112  AdapterControlContext->MapRegisterCount);
1113 
1114  DPRINT("S/G DMA has finished!\n");
1115 
1116  ExFreePoolWithTag(AdapterControlContext, TAG_DMA);
1118 }
1119 #endif
1120 
1129 ULONG
1130 NTAPI
1132 {
1133  return 1;
1134 }
1135 
1136 /*
1137  * @name HalReadDmaCounter
1138  *
1139  * Read DMA operation progress counter.
1140  *
1141  * @implemented
1142  */
1143 ULONG
1144 NTAPI
1146 {
1147  KIRQL OldIrql;
1148  ULONG Count, OldCount;
1149 
1150  ASSERT(!AdapterObject->MasterDevice);
1151 
1152  /*
1153  * Acquire the master adapter lock since we're going to mess with the
1154  * system DMA controller registers and we really don't want anyone
1155  * to do the same at the same time.
1156  */
1157  KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
1158 
1159  /* Send the request to the specific controller. */
1160  if (AdapterObject->AdapterNumber == 1)
1161  {
1162  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
1163 
1164  Count = 0xffff00;
1165  do
1166  {
1167  OldCount = Count;
1168 
1169  /* Send Reset */
1170  WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
1171 
1172  /* Read Count */
1173  Count = READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
1174  [AdapterObject->ChannelNumber].DmaBaseCount);
1175  Count |= READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
1176  [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
1177  } while (0xffff00 & (OldCount ^ Count));
1178  }
1179  else
1180  {
1181  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
1182 
1183  Count = 0xffff00;
1184  do
1185  {
1186  OldCount = Count;
1187 
1188  /* Send Reset */
1189  WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
1190 
1191  /* Read Count */
1192  Count = READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
1193  [AdapterObject->ChannelNumber].DmaBaseCount);
1194  Count |= READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
1195  [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
1196  } while (0xffff00 & (OldCount ^ Count));
1197  }
1198 
1199  KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
1200 
1201  Count++;
1202  Count &= 0xffff;
1203  if (AdapterObject->Width16Bits) Count *= 2;
1204 
1205  return Count;
1206 }
1207 
1208 #ifndef _MINIHAL_
1209 
1215 VOID
1216 NTAPI
1218 {
1220  KIRQL OldIrql;
1221  BOOLEAN Succeeded;
1222 
1223  /*
1224  * Try to allocate new map registers for the adapter.
1225  *
1226  * NOTE: The NT implementation actually tries to allocate more map
1227  * registers than needed as an optimization.
1228  */
1230  Succeeded = HalpGrowMapBuffers(WorkItem->AdapterObject->MasterAdapter,
1231  WorkItem->NumberOfMapRegisters << PAGE_SHIFT);
1232  KeSetEvent(&HalpDmaLock, 0, 0);
1233 
1234  if (Succeeded)
1235  {
1236  /*
1237  * Flush the adapter queue now that new map registers are ready. The
1238  * easiest way to do that is to call IoFreeMapRegisters to not free
1239  * any registers. Note that we use the magic (PVOID)2 map register
1240  * base to bypass the parameter checking.
1241  */
1243  IoFreeMapRegisters(WorkItem->AdapterObject, (PVOID)2, 0);
1245  }
1246 
1247  ExFreePool(WorkItem);
1248 }
1249 
1274 NTSTATUS
1275 NTAPI
1277  IN PWAIT_CONTEXT_BLOCK WaitContextBlock,
1280 {
1281  PADAPTER_OBJECT MasterAdapter;
1282  PGROW_WORK_ITEM WorkItem;
1283  ULONG Index = MAXULONG;
1284  ULONG Result;
1285  KIRQL OldIrql;
1286 
1288 
1289  /* Set up the wait context block in case we can't run right away. */
1290  WaitContextBlock->DeviceRoutine = ExecutionRoutine;
1291  WaitContextBlock->NumberOfMapRegisters = NumberOfMapRegisters;
1292 
1293  /* Returns true if queued, else returns false and sets the queue to busy */
1294  if (KeInsertDeviceQueue(&AdapterObject->ChannelWaitQueue,
1295  &WaitContextBlock->WaitQueueEntry))
1296  {
1297  return STATUS_SUCCESS;
1298  }
1299 
1300  MasterAdapter = AdapterObject->MasterAdapter;
1301 
1302  AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
1303  AdapterObject->CurrentWcb = WaitContextBlock;
1304 
1305  if ((NumberOfMapRegisters) && (AdapterObject->NeedsMapRegisters))
1306  {
1307  if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
1308  {
1309  AdapterObject->NumberOfMapRegisters = 0;
1310  IoFreeAdapterChannel(AdapterObject);
1312  }
1313 
1314  /*
1315  * Get the map registers. This is partly complicated by the fact
1316  * that new map registers can only be allocated at PASSIVE_LEVEL
1317  * and we're currently at DISPATCH_LEVEL. The following code has
1318  * two code paths:
1319  *
1320  * - If there is no adapter queued for map register allocation,
1321  * try to see if enough contiguous map registers are present.
1322  * In case they're we can just get them and proceed further.
1323  *
1324  * - If some adapter is already present in the queue we must
1325  * respect the order of adapters asking for map registers and
1326  * so the fast case described above can't take place.
1327  * This case is also entered if not enough coniguous map
1328  * registers are present.
1329  *
1330  * A work queue item is allocated and queued, the adapter is
1331  * also queued into the master adapter queue. The worker
1332  * routine does the job of allocating the map registers at
1333  * PASSIVE_LEVEL and calling the ExecutionRoutine.
1334  */
1335 
1336  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1337 
1338  if (IsListEmpty(&MasterAdapter->AdapterQueue))
1339  {
1340  Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters, NumberOfMapRegisters, 0);
1341  if (Index != MAXULONG)
1342  {
1343  AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1344  if (!AdapterObject->ScatterGather)
1345  {
1346  AdapterObject->MapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1347  }
1348  }
1349  }
1350 
1351  if (Index == MAXULONG)
1352  {
1353  InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
1354 
1356  sizeof(GROW_WORK_ITEM),
1357  TAG_DMA);
1358  if (WorkItem)
1359  {
1361  WorkItem->AdapterObject = AdapterObject;
1363 
1365  }
1366 
1367  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1368 
1369  return STATUS_SUCCESS;
1370  }
1371 
1372  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1373  }
1374  else
1375  {
1376  AdapterObject->MapRegisterBase = NULL;
1377  AdapterObject->NumberOfMapRegisters = 0;
1378  }
1379 
1380  AdapterObject->CurrentWcb = WaitContextBlock;
1381 
1382  Result = ExecutionRoutine(WaitContextBlock->DeviceObject,
1383  WaitContextBlock->CurrentIrp,
1384  AdapterObject->MapRegisterBase,
1385  WaitContextBlock->DeviceContext);
1386 
1387  /*
1388  * Possible return values:
1389  *
1390  * - KeepObject
1391  * Don't free any resources, the ADAPTER_OBJECT is still in use and
1392  * the caller will call IoFreeAdapterChannel later.
1393  *
1394  * - DeallocateObject
1395  * Deallocate the map registers and release the ADAPTER_OBJECT, so
1396  * someone else can use it.
1397  *
1398  * - DeallocateObjectKeepRegisters
1399  * Release the ADAPTER_OBJECT, but hang on to the map registers. The
1400  * client will later call IoFreeMapRegisters.
1401  *
1402  * NOTE:
1403  * IoFreeAdapterChannel runs the queue, so it must be called unless
1404  * the adapter object is not to be freed.
1405  */
1406  if (Result == DeallocateObject)
1407  {
1408  IoFreeAdapterChannel(AdapterObject);
1409  }
1411  {
1412  AdapterObject->NumberOfMapRegisters = 0;
1413  IoFreeAdapterChannel(AdapterObject);
1414  }
1415 
1416  return STATUS_SUCCESS;
1417 }
1418 
1437 VOID
1438 NTAPI
1440 {
1441  PADAPTER_OBJECT MasterAdapter;
1443  PWAIT_CONTEXT_BLOCK WaitContextBlock;
1444  ULONG Index = MAXULONG;
1445  ULONG Result;
1446  KIRQL OldIrql;
1447 
1448  MasterAdapter = AdapterObject->MasterAdapter;
1449 
1450  for (;;)
1451  {
1452  /*
1453  * To keep map registers, call here with AdapterObject->
1454  * NumberOfMapRegisters set to zero. This trick is used in
1455  * HalAllocateAdapterChannel for example.
1456  */
1457  if (AdapterObject->NumberOfMapRegisters)
1458  {
1459  IoFreeMapRegisters(AdapterObject,
1460  AdapterObject->MapRegisterBase,
1461  AdapterObject->NumberOfMapRegisters);
1462  }
1463 
1464  DeviceQueueEntry = KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue);
1465  if (!DeviceQueueEntry) break;
1466 
1467  WaitContextBlock = CONTAINING_RECORD(DeviceQueueEntry,
1469  WaitQueueEntry);
1470 
1471  AdapterObject->CurrentWcb = WaitContextBlock;
1472  AdapterObject->NumberOfMapRegisters = WaitContextBlock->NumberOfMapRegisters;
1473 
1474  if ((WaitContextBlock->NumberOfMapRegisters) && (AdapterObject->MasterAdapter))
1475  {
1476  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1477 
1478  if (IsListEmpty(&MasterAdapter->AdapterQueue))
1479  {
1480  Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
1481  WaitContextBlock->NumberOfMapRegisters,
1482  0);
1483  if (Index != MAXULONG)
1484  {
1485  AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1486  if (!AdapterObject->ScatterGather)
1487  {
1488  AdapterObject->MapRegisterBase =(PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1489  }
1490  }
1491  }
1492 
1493  if (Index == MAXULONG)
1494  {
1495  InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
1496  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1497  break;
1498  }
1499 
1500  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1501  }
1502  else
1503  {
1504  AdapterObject->MapRegisterBase = NULL;
1505  AdapterObject->NumberOfMapRegisters = 0;
1506  }
1507 
1508  /* Call the adapter control routine. */
1509  Result = ((PDRIVER_CONTROL)WaitContextBlock->DeviceRoutine)(WaitContextBlock->DeviceObject,
1510  WaitContextBlock->CurrentIrp,
1511  AdapterObject->MapRegisterBase,
1512  WaitContextBlock->DeviceContext);
1513  switch (Result)
1514  {
1515  case KeepObject:
1516  /*
1517  * We're done until the caller manually calls IoFreeAdapterChannel
1518  * or IoFreeMapRegisters.
1519  */
1520  return;
1521 
1523  /*
1524  * Hide the map registers so they aren't deallocated next time
1525  * around.
1526  */
1527  AdapterObject->NumberOfMapRegisters = 0;
1528  break;
1529 
1530  default:
1531  break;
1532  }
1533  }
1534 }
1535 
1550 VOID
1551 NTAPI
1555 {
1556  PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
1557  PLIST_ENTRY ListEntry;
1558  KIRQL OldIrql;
1559  ULONG Index;
1560  ULONG Result;
1561 
1563 
1564  if (!(MasterAdapter) || !(MapRegisterBase)) return;
1565 
1566  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1567 
1568  if (NumberOfMapRegisters != 0)
1569  {
1570  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1571 
1572  RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1573  RtlClearBits(MasterAdapter->MapRegisters,
1574  (ULONG)(RealMapRegisterBase - MasterAdapter->MapRegisterBase),
1576  }
1577 
1578  /*
1579  * Now that we freed few map registers it's time to look at the master
1580  * adapter queue and see if there is someone waiting for map registers.
1581  */
1582  while (!IsListEmpty(&MasterAdapter->AdapterQueue))
1583  {
1584  ListEntry = RemoveHeadList(&MasterAdapter->AdapterQueue);
1585  AdapterObject = CONTAINING_RECORD(ListEntry, struct _ADAPTER_OBJECT, AdapterQueue);
1586 
1587  Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
1588  AdapterObject->NumberOfMapRegisters,
1589  0);
1590  if (Index == MAXULONG)
1591  {
1592  InsertHeadList(&MasterAdapter->AdapterQueue, ListEntry);
1593  break;
1594  }
1595 
1596  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1597 
1598  AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1599  if (!AdapterObject->ScatterGather)
1600  {
1601  AdapterObject->MapRegisterBase =
1602  (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1603  }
1604 
1605  Result = ((PDRIVER_CONTROL)AdapterObject->CurrentWcb->DeviceRoutine)(AdapterObject->CurrentWcb->DeviceObject,
1606  AdapterObject->CurrentWcb->CurrentIrp,
1607  AdapterObject->MapRegisterBase,
1608  AdapterObject->CurrentWcb->DeviceContext);
1609  switch (Result)
1610  {
1612  AdapterObject->NumberOfMapRegisters = 0;
1613  /* fall through */
1614 
1615  case DeallocateObject:
1616  if (AdapterObject->NumberOfMapRegisters)
1617  {
1618  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1619  RtlClearBits(MasterAdapter->MapRegisters,
1620  (ULONG)(AdapterObject->MapRegisterBase -
1621  MasterAdapter->MapRegisterBase),
1622  AdapterObject->NumberOfMapRegisters);
1623  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1624  }
1625 
1626  IoFreeAdapterChannel(AdapterObject);
1627  break;
1628 
1629  default:
1630  break;
1631  }
1632 
1633  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1634  }
1635 
1636  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1637 }
1638 
1646 VOID
1647 NTAPI
1650  IN PVOID CurrentVa,
1651  IN ULONG Length,
1652  IN BOOLEAN WriteToDevice)
1653 {
1654  ULONG CurrentLength;
1655  ULONG_PTR CurrentAddress;
1656  ULONG ByteOffset;
1658 
1660  if (!VirtualAddress)
1661  {
1662  /*
1663  * NOTE: On real NT a mechanism with reserved pages is implemented
1664  * to handle this case in a slow, but graceful non-fatal way.
1665  */
1666  KeBugCheckEx(HAL_MEMORY_ALLOCATION, PAGE_SIZE, 0, (ULONG_PTR)__FILE__, 0);
1667  }
1668 
1669  CurrentAddress = (ULONG_PTR)VirtualAddress +
1670  (ULONG_PTR)CurrentVa -
1672 
1673  while (Length > 0)
1674  {
1675  ByteOffset = BYTE_OFFSET(CurrentAddress);
1676  CurrentLength = PAGE_SIZE - ByteOffset;
1677  if (CurrentLength > Length) CurrentLength = Length;
1678 
1679  if (WriteToDevice)
1680  {
1681  RtlCopyMemory((PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
1682  (PVOID)CurrentAddress,
1683  CurrentLength);
1684  }
1685  else
1686  {
1687  RtlCopyMemory((PVOID)CurrentAddress,
1688  (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
1689  CurrentLength);
1690  }
1691 
1692  Length -= CurrentLength;
1693  CurrentAddress += CurrentLength;
1694  MapRegisterBase++;
1695  }
1696 }
1697 
1729 BOOLEAN
1730 NTAPI
1732  IN PMDL Mdl,
1734  IN PVOID CurrentVa,
1735  IN ULONG Length,
1736  IN BOOLEAN WriteToDevice)
1737 {
1738  BOOLEAN SlaveDma = FALSE;
1739  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1742  PPFN_NUMBER MdlPagesPtr;
1743 
1744  /* Sanity checks */
1746  ASSERT(AdapterObject);
1747 
1748  if (!AdapterObject->MasterDevice)
1749  {
1750  /* Mask out (disable) the DMA channel. */
1751  if (AdapterObject->AdapterNumber == 1)
1752  {
1753  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
1754  WRITE_PORT_UCHAR(&DmaControl1->SingleMask,
1755  AdapterObject->ChannelNumber | DMA_SETMASK);
1756  }
1757  else
1758  {
1759  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
1760  WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
1761  AdapterObject->ChannelNumber | DMA_SETMASK);
1762  }
1763  SlaveDma = TRUE;
1764  }
1765 
1766  /* This can happen if the device supports hardware scatter/gather. */
1767  if (MapRegisterBase == NULL) return TRUE;
1768 
1769  RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1770 
1771  if (!WriteToDevice)
1772  {
1774  {
1775  if (RealMapRegisterBase->Counter != MAXULONG)
1776  {
1777  if ((SlaveDma) && !(AdapterObject->IgnoreCount))
1778  {
1779  Length -= HalReadDmaCounter(AdapterObject);
1780  }
1781  }
1782  HalpCopyBufferMap(Mdl,
1783  RealMapRegisterBase,
1784  CurrentVa,
1785  Length,
1786  FALSE);
1787  }
1788  else
1789  {
1790  MdlPagesPtr = MmGetMdlPfnArray(Mdl);
1791  MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
1792 
1793  PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
1794  PhysicalAddress.QuadPart += BYTE_OFFSET(CurrentVa);
1795 
1798  {
1799  HalpCopyBufferMap(Mdl,
1800  RealMapRegisterBase,
1801  CurrentVa,
1802  Length,
1803  FALSE);
1804  }
1805  }
1806  }
1807 
1808  RealMapRegisterBase->Counter = 0;
1809 
1810  return TRUE;
1811 }
1812 
1845 NTAPI
1847  IN PMDL Mdl,
1849  IN PVOID CurrentVa,
1850  IN OUT PULONG Length,
1851  IN BOOLEAN WriteToDevice)
1852 {
1853  PPFN_NUMBER MdlPagesPtr;
1854  PFN_NUMBER MdlPage1, MdlPage2;
1855  ULONG ByteOffset;
1856  ULONG TransferOffset;
1857  ULONG TransferLength;
1858  BOOLEAN UseMapRegisters;
1859  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1862  ULONG Counter;
1863  DMA_MODE AdapterMode;
1864  KIRQL OldIrql;
1865 
1866  /*
1867  * Precalculate some values that are used in all cases.
1868  *
1869  * ByteOffset is offset inside the page at which the transfer starts.
1870  * MdlPagesPtr is pointer inside the MDL page chain at the page where the
1871  * transfer start.
1872  * PhysicalAddress is physical address corresponding to the transfer
1873  * start page and offset.
1874  * TransferLength is the initial length of the transfer, which is reminder
1875  * of the first page. The actual value is calculated below.
1876  *
1877  * Note that all the variables can change during the processing which
1878  * takes place below. These are just initial values.
1879  */
1880  ByteOffset = BYTE_OFFSET(CurrentVa);
1881 
1882  MdlPagesPtr = MmGetMdlPfnArray(Mdl);
1883  MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
1884 
1885  PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
1887 
1888  TransferLength = PAGE_SIZE - ByteOffset;
1889 
1890  /*
1891  * Special case for bus master adapters with S/G support. We can directly
1892  * use the buffer specified by the MDL, so not much work has to be done.
1893  *
1894  * Just return the passed VA's corresponding physical address and update
1895  * length to the number of physically contiguous bytes found. Also
1896  * pages crossing the 4Gb boundary aren't considered physically contiguous.
1897  */
1898  if (MapRegisterBase == NULL)
1899  {
1900  while (TransferLength < *Length)
1901  {
1902  MdlPage1 = *MdlPagesPtr;
1903  MdlPage2 = *(MdlPagesPtr + 1);
1904  if (MdlPage1 + 1 != MdlPage2) break;
1905  if ((MdlPage1 ^ MdlPage2) & ~0xFFFFF) break;
1906  TransferLength += PAGE_SIZE;
1907  MdlPagesPtr++;
1908  }
1909 
1910  if (TransferLength < *Length) *Length = TransferLength;
1911 
1912  return PhysicalAddress;
1913  }
1914 
1915  /*
1916  * The code below applies to slave DMA adapters and bus master adapters
1917  * without hardward S/G support.
1918  */
1919  RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1920 
1921  /*
1922  * Try to calculate the size of the transfer. We can only transfer
1923  * pages that are physically contiguous and that don't cross the
1924  * 64Kb boundary (this limitation applies only for ISA controllers).
1925  */
1926  while (TransferLength < *Length)
1927  {
1928  MdlPage1 = *MdlPagesPtr;
1929  MdlPage2 = *(MdlPagesPtr + 1);
1930  if (MdlPage1 + 1 != MdlPage2) break;
1931  if (!HalpEisaDma && ((MdlPage1 ^ MdlPage2) & ~0xF)) break;
1932  TransferLength += PAGE_SIZE;
1933  MdlPagesPtr++;
1934  }
1935 
1936  if (TransferLength > *Length) TransferLength = *Length;
1937 
1938  /*
1939  * If we're about to simulate software S/G and not all the pages are
1940  * physically contiguous then we must use the map registers to store
1941  * the data and allow the whole transfer to proceed at once.
1942  */
1943  if (((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG) && (TransferLength < *Length))
1944  {
1945  UseMapRegisters = TRUE;
1946  PhysicalAddress = RealMapRegisterBase->PhysicalAddress;
1948  TransferLength = *Length;
1949  RealMapRegisterBase->Counter = MAXULONG;
1950  Counter = 0;
1951  }
1952  else
1953  {
1954  /*
1955  * This is ordinary DMA transfer, so just update the progress
1956  * counters. These are used by IoFlushAdapterBuffers to track
1957  * the transfer progress.
1958  */
1959  UseMapRegisters = FALSE;
1960  Counter = RealMapRegisterBase->Counter;
1961  RealMapRegisterBase->Counter += BYTES_TO_PAGES(ByteOffset + TransferLength);
1962 
1963  /*
1964  * Check if the buffer doesn't exceed the highest physical address
1965  * limit of the device. In that case we must use the map registers to
1966  * store the data.
1967  */
1969  if ((PhysicalAddress.QuadPart + TransferLength) > HighestAcceptableAddress.QuadPart)
1970  {
1971  UseMapRegisters = TRUE;
1972  PhysicalAddress = RealMapRegisterBase[Counter].PhysicalAddress;
1975  {
1976  RealMapRegisterBase->Counter = MAXULONG;
1977  Counter = 0;
1978  }
1979  }
1980  }
1981 
1982  /*
1983  * If we decided to use the map registers (see above) and we're about
1984  * to transfer data to the device then copy the buffers into the map
1985  * register memory.
1986  */
1987  if ((UseMapRegisters) && (WriteToDevice))
1988  {
1989  HalpCopyBufferMap(Mdl,
1990  RealMapRegisterBase + Counter,
1991  CurrentVa,
1992  TransferLength,
1993  WriteToDevice);
1994  }
1995 
1996  /*
1997  * Return the length of transfer that actually takes place.
1998  */
1999  *Length = TransferLength;
2000 
2001  /*
2002  * If we're doing slave (system) DMA then program the (E)ISA controller
2003  * to actually start the transfer.
2004  */
2005  if ((AdapterObject) && !(AdapterObject->MasterDevice))
2006  {
2007  AdapterMode = AdapterObject->AdapterMode;
2008 
2009  if (WriteToDevice)
2010  {
2011  AdapterMode.TransferType = WRITE_TRANSFER;
2012  }
2013  else
2014  {
2015  AdapterMode.TransferType = READ_TRANSFER;
2016  if (AdapterObject->IgnoreCount)
2017  {
2018  RtlZeroMemory((PUCHAR)RealMapRegisterBase[Counter].VirtualAddress + ByteOffset,
2019  TransferLength);
2020  }
2021  }
2022 
2023  TransferOffset = PhysicalAddress.LowPart & 0xFFFF;
2024  if (AdapterObject->Width16Bits)
2025  {
2026  TransferLength >>= 1;
2027  TransferOffset >>= 1;
2028  }
2029 
2030  KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
2031 
2032  if (AdapterObject->AdapterNumber == 1)
2033  {
2034  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
2035 
2036  /* Reset Register */
2037  WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
2038 
2039  /* Set the Mode */
2040  WRITE_PORT_UCHAR(&DmaControl1->Mode, AdapterMode.Byte);
2041 
2042  /* Set the Offset Register */
2043  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2044  (UCHAR)(TransferOffset));
2045  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2046  (UCHAR)(TransferOffset >> 8));
2047 
2048  /* Set the Page Register */
2049  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
2050  (UCHAR)(PhysicalAddress.LowPart >> 16));
2051  if (HalpEisaDma)
2052  {
2053  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
2054  0);
2055  }
2056 
2057  /* Set the Length */
2058  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2059  (UCHAR)(TransferLength - 1));
2060  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2061  (UCHAR)((TransferLength - 1) >> 8));
2062 
2063  /* Unmask the Channel */
2064  WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK);
2065  }
2066  else
2067  {
2068  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
2069 
2070  /* Reset Register */
2071  WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
2072 
2073  /* Set the Mode */
2074  WRITE_PORT_UCHAR(&DmaControl2->Mode, AdapterMode.Byte);
2075 
2076  /* Set the Offset Register */
2077  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2078  (UCHAR)(TransferOffset));
2079  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2080  (UCHAR)(TransferOffset >> 8));
2081 
2082  /* Set the Page Register */
2083  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
2084  (UCHAR)(PhysicalAddress.u.LowPart >> 16));
2085  if (HalpEisaDma)
2086  {
2087  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
2088  0);
2089  }
2090 
2091  /* Set the Length */
2092  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2093  (UCHAR)(TransferLength - 1));
2094  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2095  (UCHAR)((TransferLength - 1) >> 8));
2096 
2097  /* Unmask the Channel */
2098  WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
2099  AdapterObject->ChannelNumber | DMA_CLEARMASK);
2100  }
2101 
2102  KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
2103  }
2104 
2105  /*
2106  * Return physical address of the buffer with data that is used for the
2107  * transfer. It can either point inside the Mdl that was passed by the
2108  * caller or into the map registers if the Mdl buffer can't be used
2109  * directly.
2110  */
2111  return PhysicalAddress;
2112 }
2113 #endif
2114 
2120 BOOLEAN
2121 NTAPI
2123  IN ULONG Length,
2124  IN PHYSICAL_ADDRESS LogicalAddress,
2126 {
2127  /* Function always returns true */
2128  return TRUE;
2129 }
2130 
2131 /*
2132  * @implemented
2133  */
2134 PVOID
2135 NTAPI
2138 {
2139  PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
2140  ULONG MapRegisterNumber;
2141 
2142  /* Check if it needs map registers */
2143  if (AdapterObject->NeedsMapRegisters)
2144  {
2145  /* Check if we have enough */
2146  if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
2147  {
2148  /* We don't, fail */
2149  AdapterObject->NumberOfMapRegisters = 0;
2150  return NULL;
2151  }
2152 
2153  /* Try to find free map registers */
2154  MapRegisterNumber = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
2156  0);
2157 
2158  /* Check if nothing was found */
2159  if (MapRegisterNumber == MAXULONG)
2160  {
2161  /* No free registers found, so use the base registers */
2162  RtlSetBits(MasterAdapter->MapRegisters,
2163  0,
2165  MapRegisterNumber = 0;
2166  }
2167 
2168  /* Calculate the new base */
2169  AdapterObject->MapRegisterBase =
2170  (PROS_MAP_REGISTER_ENTRY)(MasterAdapter->MapRegisterBase +
2171  MapRegisterNumber);
2172 
2173  /* Check if scatter gather isn't supported */
2174  if (!AdapterObject->ScatterGather)
2175  {
2176  /* Set the flag */
2177  AdapterObject->MapRegisterBase =
2179  ((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
2180  }
2181  }
2182  else
2183  {
2184  AdapterObject->MapRegisterBase = NULL;
2185  AdapterObject->NumberOfMapRegisters = 0;
2186  }
2187 
2188  /* Return the base */
2189  return AdapterObject->MapRegisterBase;
2190 }
2191 
2192 /* 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:39
#define TYPE_A_TIMING
Definition: haldma.h:150
UCHAR AutoInitialize
Definition: haldma.h:95
PDRIVER_LIST_CONTROL AdapterListControlRoutine
Definition: dma.c:935
#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
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:90
_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
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
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 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:97
UCHAR Byte
Definition: haldma.h:99
#define InsertTailList(ListHead, Entry)
ULONG MapRegisterCount
Definition: dma.c:937
static DMA_OPERATIONS HalpDmaOperations
Definition: dma.c:109
#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
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
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:64
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:1092
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
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:238
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
static WCHAR Address[46]
Definition: ping.c:68
static KSPIN_LOCK HalpDmaAdapterListLock
Definition: dma.c:88
_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
NTSYSAPI ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP, ULONG, ULONG)
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:1039
_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:931
#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
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:790
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
#define OBJ_PERMANENT
Definition: winternl.h:226
_Out_ PNDIS_HANDLE _Out_ PUINT _In_ PNDIS_STRING _In_ NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress
Definition: ndis.h:3227
ULONG LowPart
Definition: typedefs.h:105
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:118
static PADAPTER_OBJECT HalpMasterAdapter
Definition: dma.c:94
_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:361
#define TAG_DMA
Definition: dma.c:132
#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:939
BOOLEAN NTAPI HalpDmaInitializeEisaAdapter(PADAPTER_OBJECT AdapterObject, PDEVICE_DESCRIPTION DeviceDescription)
Definition: dma.c:461
static LIST_ENTRY HalpDmaAdapterList
Definition: dma.c:89
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
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
UnicodeString MaximumLength
Definition: rtlfuncs.h:2982
PVOID MapRegisterBase
Definition: dma.c:936
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1569
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:130
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
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
PKDEVICE_QUEUE_ENTRY NTAPI KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
Definition: devqueue.c:153
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
NTSYSAPI void WINAPI RtlSetBits(PRTL_BITMAP, ULONG, ULONG)
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
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:40
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:936
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:1034
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:685
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
#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:945
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
_Inout_ PKDEVICE_QUEUE_ENTRY DeviceQueueEntry
Definition: kefuncs.h:339
#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:3014
#define CASCADE_REQUEST_MODE
Definition: haldma.h:172
static BOOLEAN HalpEisaDma
Definition: dma.c:92
UCHAR ClearBytePointer
Definition: haldma.h:202
#define BYTE_OFFSET(Va)
struct _LARGE_INTEGER::@2245 u
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:108
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:113
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:725
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:938
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