ReactOS  0.4.15-dev-1392-g3014417
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 #define MAX_SG_ELEMENTS 0x10
81 
82 #ifndef _MINIHAL_
87 #endif
89 #ifndef _MINIHAL_
91 #endif
92 
93 static const ULONG_PTR HalpEisaPortPage[8] = {
94  FIELD_OFFSET(DMA_PAGE, Channel0),
95  FIELD_OFFSET(DMA_PAGE, Channel1),
96  FIELD_OFFSET(DMA_PAGE, Channel2),
97  FIELD_OFFSET(DMA_PAGE, Channel3),
98  0,
99  FIELD_OFFSET(DMA_PAGE, Channel5),
100  FIELD_OFFSET(DMA_PAGE, Channel6),
101  FIELD_OFFSET(DMA_PAGE, Channel7)
102 };
103 
104 #ifndef _MINIHAL_
106  sizeof(DMA_OPERATIONS),
110  NULL, /* Initialized in HalpInitDma() */
111  NULL, /* Initialized in HalpInitDma() */
112  NULL, /* Initialized in HalpInitDma() */
113  NULL, /* Initialized in HalpInitDma() */
114  NULL, /* Initialized in HalpInitDma() */
117  /* FIXME: Implement the S/G funtions. */
120  NULL /*(PCALCULATE_SCATTER_GATHER_LIST_SIZE)HalCalculateScatterGatherListSize*/,
121  NULL /*(PBUILD_SCATTER_GATHER_LIST)HalBuildScatterGatherList*/,
122  NULL /*(PBUILD_MDL_FROM_SCATTER_GATHER_LIST)HalBuildMdlFromScatterGatherList*/
123 };
124 #endif
125 
126 #define MAX_MAP_REGISTERS 64
127 
128 #define TAG_DMA ' AMD'
129 
130 /* FUNCTIONS *****************************************************************/
131 
132 #if defined(SARCH_PC98)
133 /*
134  * Disable I/O for safety.
135  * FIXME: Add support for PC-98 DMA controllers.
136  */
137 #undef WRITE_PORT_UCHAR
138 #undef READ_PORT_UCHAR
139 
140 #define WRITE_PORT_UCHAR(Port, Data) \
141  do { \
142  UNIMPLEMENTED; \
143  (Port); \
144  (Data); \
145  } while (0)
146 
147 #define READ_PORT_UCHAR(Port) 0x00
148 #endif
149 
150 #ifndef _MINIHAL_
151 CODE_SEG("INIT")
152 VOID
154 {
155  /*
156  * Initialize the DMA Operation table
157  */
163 
165  {
166  /*
167  * Check if Extended DMA is available. We're just going to do a random
168  * read and write.
169  */
170  WRITE_PORT_UCHAR(UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2)), 0x2A);
171  if (READ_PORT_UCHAR(UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2))) == 0x2A)
172  {
173  DPRINT1("Machine supports EISA DMA. Bus type: %lu\n", HalpBusType);
174  HalpEisaDma = TRUE;
175  }
176  }
177 
178  /*
179  * Intialize all the global variables and allocate master adapter with
180  * first map buffers.
181  */
186 
187  /*
188  * Setup the HalDispatchTable callback for creating PnP DMA adapters. It's
189  * used by IoGetDmaAdapter in the kernel.
190  */
192 }
193 #endif
194 
202 NTAPI
204 {
205  PHYSICAL_ADDRESS HighestAddress;
206 
207  if (AdapterObject->MasterDevice)
208  {
209  if (AdapterObject->Dma64BitAddresses)
210  {
211  HighestAddress.QuadPart = 0xFFFFFFFFFFFFFFFFULL;
212  return HighestAddress;
213  }
214  else if (AdapterObject->Dma32BitAddresses)
215  {
216  HighestAddress.QuadPart = 0xFFFFFFFF;
217  return HighestAddress;
218  }
219  }
220 
221  HighestAddress.QuadPart = 0xFFFFFF;
222  return HighestAddress;
223 }
224 
225 #ifndef _MINIHAL_
226 
237 BOOLEAN
238 NTAPI
240  IN ULONG SizeOfMapBuffers)
241 {
246  PHYSICAL_ADDRESS BoundryAddressMultiple;
247  KIRQL OldIrql;
249 
250  /* Check if enough map register slots are available. */
251  MapRegisterCount = BYTES_TO_PAGES(SizeOfMapBuffers);
252  if (MapRegisterCount + AdapterObject->NumberOfMapRegisters > MAX_MAP_REGISTERS)
253  {
254  DPRINT("No more map register slots available! (Current: %d | Requested: %d | Limit: %d)\n",
255  AdapterObject->NumberOfMapRegisters,
258  return FALSE;
259  }
260 
261  /*
262  * Allocate memory for the new map registers. For 32-bit adapters we use
263  * two passes in order not to waste scare resource (low memory).
264  */
267  LowestAcceptableAddress.LowPart = HighestAcceptableAddress.LowPart == 0xFFFFFFFF ? 0x1000000 : 0;
268  BoundryAddressMultiple.QuadPart = 0;
269 
273  BoundryAddressMultiple,
274  MmNonCached);
276  {
281  BoundryAddressMultiple,
282  MmNonCached);
283  }
284 
285  if (!VirtualAddress) return FALSE;
286 
288 
289  /*
290  * All the following must be done with the master adapter lock held
291  * to prevent corruption.
292  */
293  KeAcquireSpinLock(&AdapterObject->SpinLock, &OldIrql);
294 
295  /*
296  * Setup map register entries for the buffer allocated. Each entry has
297  * a virtual and physical address and corresponds to PAGE_SIZE large
298  * buffer.
299  */
300  if (MapRegisterCount > 0)
301  {
302  PROS_MAP_REGISTER_ENTRY CurrentEntry, PreviousEntry;
303 
304  CurrentEntry = AdapterObject->MapRegisterBase + AdapterObject->NumberOfMapRegisters;
305  do
306  {
307  /*
308  * Leave one entry free for every non-contiguous memory region
309  * in the map register bitmap. This ensures that we can search
310  * using RtlFindClearBits for contiguous map register regions.
311  *
312  * Also for non-EISA DMA leave one free entry for every 64Kb
313  * break, because the DMA controller can handle only coniguous
314  * 64Kb regions.
315  */
316  if (CurrentEntry != AdapterObject->MapRegisterBase)
317  {
318  PreviousEntry = CurrentEntry - 1;
319  if ((PreviousEntry->PhysicalAddress.LowPart + PAGE_SIZE) == PhysicalAddress.LowPart)
320  {
321  if (!HalpEisaDma)
322  {
323  if ((PreviousEntry->PhysicalAddress.LowPart ^ PhysicalAddress.LowPart) & 0xFFFF0000)
324  {
325  CurrentEntry++;
326  AdapterObject->NumberOfMapRegisters++;
327  }
328  }
329  }
330  else
331  {
332  CurrentEntry++;
333  AdapterObject->NumberOfMapRegisters++;
334  }
335  }
336 
337  RtlClearBit(AdapterObject->MapRegisters,
338  (ULONG)(CurrentEntry - AdapterObject->MapRegisterBase));
339  CurrentEntry->VirtualAddress = VirtualAddress;
340  CurrentEntry->PhysicalAddress = PhysicalAddress;
341 
344 
345  CurrentEntry++;
346  AdapterObject->NumberOfMapRegisters++;
348  } while (MapRegisterCount);
349  }
350 
351  KeReleaseSpinLock(&AdapterObject->SpinLock, OldIrql);
352 
353  return TRUE;
354 }
355 
365 NTAPI
367 {
368  PADAPTER_OBJECT MasterAdapter;
369  ULONG Size, SizeOfBitmap;
370 
371  SizeOfBitmap = MAX_MAP_REGISTERS;
372  Size = sizeof(ADAPTER_OBJECT);
373  Size += sizeof(RTL_BITMAP);
374  Size += (SizeOfBitmap + 7) >> 3;
375 
376  MasterAdapter = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_DMA);
377  if (!MasterAdapter) return NULL;
378 
379  RtlZeroMemory(MasterAdapter, Size);
380 
381  KeInitializeSpinLock(&MasterAdapter->SpinLock);
382  InitializeListHead(&MasterAdapter->AdapterQueue);
383 
384  MasterAdapter->MapRegisters = (PVOID)(MasterAdapter + 1);
385  RtlInitializeBitMap(MasterAdapter->MapRegisters,
386  (PULONG)(MasterAdapter->MapRegisters + 1),
387  SizeOfBitmap);
388  RtlSetAllBits(MasterAdapter->MapRegisters);
389  MasterAdapter->NumberOfMapRegisters = 0;
390  MasterAdapter->CommittedMapRegisters = 0;
391 
392  MasterAdapter->MapRegisterBase = ExAllocatePoolWithTag(NonPagedPool,
393  SizeOfBitmap *
394  sizeof(ROS_MAP_REGISTER_ENTRY),
395  TAG_DMA);
396  if (!MasterAdapter->MapRegisterBase)
397  {
398  ExFreePool(MasterAdapter);
399  return NULL;
400  }
401 
402  RtlZeroMemory(MasterAdapter->MapRegisterBase,
403  SizeOfBitmap * sizeof(ROS_MAP_REGISTER_ENTRY));
404  if (!HalpGrowMapBuffers(MasterAdapter, 0x10000))
405  {
406  ExFreePool(MasterAdapter);
407  return NULL;
408  }
409 
410  return MasterAdapter;
411 }
412 
422 NTAPI
425 {
426  PADAPTER_OBJECT AdapterObject;
429  HANDLE Handle;
430 
432  NULL,
434  NULL,
435  NULL);
436 
440  KernelMode,
441  NULL,
442  sizeof(ADAPTER_OBJECT),
443  0,
444  0,
445  (PVOID)&AdapterObject);
446  if (!NT_SUCCESS(Status)) return NULL;
447 
448  Status = ObReferenceObjectByPointer(AdapterObject,
451  KernelMode);
452  if (!NT_SUCCESS(Status)) return NULL;
453 
454  RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT));
455 
456  Status = ObInsertObject(AdapterObject,
457  NULL,
459  0,
460  NULL,
461  &Handle);
462  if (!NT_SUCCESS(Status)) return NULL;
463 
464  ZwClose(Handle);
465 
466  AdapterObject->DmaHeader.Version = (USHORT)DeviceDescription->Version;
467  AdapterObject->DmaHeader.Size = sizeof(ADAPTER_OBJECT);
468  AdapterObject->DmaHeader.DmaOperations = &HalpDmaOperations;
469  AdapterObject->MapRegistersPerChannel = 1;
470  AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
471  AdapterObject->ChannelNumber = 0xFF;
472  AdapterObject->MasterAdapter = HalpMasterAdapter;
473  KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue);
474 
475  return AdapterObject;
476 }
477 #endif
478 
484 BOOLEAN
485 NTAPI
488 {
489  UCHAR Controller;
490  DMA_MODE DmaMode = {{0 }};
491  DMA_EXTENDED_MODE ExtendedMode = {{ 0 }};
492  PVOID AdapterBaseVa;
493 
494  Controller = (DeviceDescription->DmaChannel & 4) ? 2 : 1;
495 
496  if (Controller == 1)
497  {
498  AdapterBaseVa = UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController1));
499  }
500  else
501  {
502  AdapterBaseVa = UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2));
503  }
504 
505  AdapterObject->AdapterNumber = Controller;
506  AdapterObject->ChannelNumber = (UCHAR)(DeviceDescription->DmaChannel & 3);
507  AdapterObject->PagePort = (PUCHAR)HalpEisaPortPage[DeviceDescription->DmaChannel];
508  AdapterObject->Width16Bits = FALSE;
509  AdapterObject->AdapterBaseVa = AdapterBaseVa;
510 
511  if (HalpEisaDma)
512  {
513  ExtendedMode.ChannelNumber = AdapterObject->ChannelNumber;
514 
515  switch (DeviceDescription->DmaSpeed)
516  {
517  case Compatible: ExtendedMode.TimingMode = COMPATIBLE_TIMING; break;
518  case TypeA: ExtendedMode.TimingMode = TYPE_A_TIMING; break;
519  case TypeB: ExtendedMode.TimingMode = TYPE_B_TIMING; break;
520  case TypeC: ExtendedMode.TimingMode = BURST_TIMING; break;
521  default:
522  return FALSE;
523  }
524 
525  switch (DeviceDescription->DmaWidth)
526  {
527  case Width8Bits: ExtendedMode.TransferSize = B_8BITS; break;
528  case Width16Bits: ExtendedMode.TransferSize = B_16BITS; break;
529  case Width32Bits: ExtendedMode.TransferSize = B_32BITS; break;
530  default:
531  return FALSE;
532  }
533 
534  if (Controller == 1)
535  {
537  ExtendedMode.Byte);
538  }
539  else
540  {
542  ExtendedMode.Byte);
543  }
544  }
545  else
546  {
547  /*
548  * Validate setup for non-busmaster DMA adapter. Secondary controller
549  * supports only 16-bit transfers and main controller supports only
550  * 8-bit transfers. Anything else is invalid.
551  */
552  if (!DeviceDescription->Master)
553  {
554  if ((Controller == 2) && (DeviceDescription->DmaWidth == Width16Bits))
555  {
556  AdapterObject->Width16Bits = TRUE;
557  }
558  else if ((Controller != 1) || (DeviceDescription->DmaWidth != Width8Bits))
559  {
560  return FALSE;
561  }
562  }
563  }
564 
565  DmaMode.Channel = AdapterObject->ChannelNumber;
566  DmaMode.AutoInitialize = DeviceDescription->AutoInitialize;
567 
568  /*
569  * Set the DMA request mode.
570  *
571  * For (E)ISA bus master devices just unmask (enable) the DMA channel
572  * and set it to cascade mode. Otherwise just select the right one
573  * bases on the passed device description.
574  */
575  if (DeviceDescription->Master)
576  {
578  if (Controller == 1)
579  {
580  /* Set the Request Data */
582  WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte);
583 
584  /* Unmask DMA Channel */
585  WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->SingleMask,
586  AdapterObject->ChannelNumber | DMA_CLEARMASK);
587  }
588  else
589  {
590  /* Set the Request Data */
591  WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte);
592 
593  /* Unmask DMA Channel */
594  WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->SingleMask,
595  AdapterObject->ChannelNumber | DMA_CLEARMASK);
596  }
597  }
598  else
599  {
600  if (DeviceDescription->DemandMode)
601  {
603  }
604  else
605  {
607  }
608  }
609 
610  AdapterObject->AdapterMode = DmaMode;
611 
612  return TRUE;
613 }
614 
615 #ifndef _MINIHAL_
616 
632 NTAPI
635 {
636  PADAPTER_OBJECT AdapterObject = NULL;
638  ULONG MapRegisters;
640  KIRQL OldIrql;
641 
642  /* Validate parameters in device description */
643  if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION2) return NULL;
644 
645  /*
646  * See if we're going to use ISA/EISA DMA adapter. These adapters are
647  * special since they're reused.
648  *
649  * Also note that we check for channel number since there are only 8 DMA
650  * channels on ISA, so any request above this requires new adapter.
651  */
652  if (((DeviceDescription->InterfaceType == Eisa) ||
653  (DeviceDescription->InterfaceType == Isa)) || !(DeviceDescription->Master))
654  {
655  if (((DeviceDescription->InterfaceType == Isa) ||
656  (DeviceDescription->InterfaceType == Eisa)) &&
657  (DeviceDescription->DmaChannel >= 8))
658  {
659  EisaAdapter = FALSE;
660  }
661  else
662  {
663  EisaAdapter = TRUE;
664  }
665  }
666  else
667  {
668  EisaAdapter = FALSE;
669  }
670 
671  /*
672  * Disallow creating adapter for ISA/EISA DMA channel 4 since it's used
673  * for cascading the controllers and it's not available for software use.
674  */
675  if ((EisaAdapter) && (DeviceDescription->DmaChannel == 4)) return NULL;
676 
677  /*
678  * Calculate the number of map registers.
679  *
680  * - For EISA and PCI scatter/gather no map registers are needed.
681  * - For ISA slave scatter/gather one map register is needed.
682  * - For all other cases the number of map registers depends on
683  * DeviceDescription->MaximumLength.
684  */
685  MaximumLength = DeviceDescription->MaximumLength & MAXLONG;
686  if ((DeviceDescription->ScatterGather) &&
687  ((DeviceDescription->InterfaceType == Eisa) ||
688  (DeviceDescription->InterfaceType == PCIBus)))
689  {
690  MapRegisters = 0;
691  }
692  else if ((DeviceDescription->ScatterGather) && !(DeviceDescription->Master))
693  {
694  MapRegisters = 1;
695  }
696  else
697  {
698  /*
699  * In the equation below the additional map register added by
700  * the "+1" accounts for the case when a transfer does not start
701  * at a page-aligned address.
702  */
703  MapRegisters = BYTES_TO_PAGES(MaximumLength) + 1;
704  if (MapRegisters > 16) MapRegisters = 16;
705  }
706 
707  /*
708  * Acquire the DMA lock that is used to protect the EISA adapter array.
709  */
711 
712  /*
713  * Now we must get ahold of the adapter object. For first eight ISA/EISA
714  * channels there are static adapter objects that are reused and updated
715  * on succesive HalGetAdapter calls. In other cases a new adapter object
716  * is always created and it's to the DMA adapter list (HalpDmaAdapterList).
717  */
718  if (EisaAdapter)
719  {
720  AdapterObject = HalpEisaAdapter[DeviceDescription->DmaChannel];
721  if (AdapterObject)
722  {
723  if ((AdapterObject->NeedsMapRegisters) &&
724  (MapRegisters > AdapterObject->MapRegistersPerChannel))
725  {
726  AdapterObject->MapRegistersPerChannel = MapRegisters;
727  }
728  }
729  }
730 
731  if (AdapterObject == NULL)
732  {
733  AdapterObject = HalpDmaAllocateChildAdapter(MapRegisters, DeviceDescription);
734  if (AdapterObject == NULL)
735  {
736  KeSetEvent(&HalpDmaLock, 0, 0);
737  return NULL;
738  }
739 
740  if (EisaAdapter)
741  {
742  HalpEisaAdapter[DeviceDescription->DmaChannel] = AdapterObject;
743  }
744 
745  if (MapRegisters > 0)
746  {
747  AdapterObject->NeedsMapRegisters = TRUE;
748  AdapterObject->MapRegistersPerChannel = MapRegisters;
749  }
750  else
751  {
752  AdapterObject->NeedsMapRegisters = FALSE;
753  if (DeviceDescription->Master)
754  {
755  AdapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(MaximumLength) + 1;
756  }
757  else
758  {
759  AdapterObject->MapRegistersPerChannel = 1;
760  }
761  }
762  }
763 
764  /*
765  * Release the DMA lock. HalpEisaAdapter will no longer be touched,
766  * so we don't need it.
767  */
768  KeSetEvent(&HalpDmaLock, 0, 0);
769 
770  if (!EisaAdapter)
771  {
772  /* If it's not one of the static adapters, add it to the list */
774  InsertTailList(&HalpDmaAdapterList, &AdapterObject->AdapterList);
776  }
777 
778  /*
779  * Setup the values in the adapter object that are common for all
780  * types of buses.
781  */
783  {
784  AdapterObject->IgnoreCount = DeviceDescription->IgnoreCount;
785  }
786  else
787  {
788  AdapterObject->IgnoreCount = 0;
789  }
790 
791  AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
792  AdapterObject->Dma64BitAddresses = DeviceDescription->Dma64BitAddresses;
793  AdapterObject->ScatterGather = DeviceDescription->ScatterGather;
794  AdapterObject->MasterDevice = DeviceDescription->Master;
795  *NumberOfMapRegisters = AdapterObject->MapRegistersPerChannel;
796 
797  /*
798  * For non-(E)ISA adapters we have already done all the work. On the
799  * other hand for (E)ISA adapters we must still setup the DMA modes
800  * and prepare the controller.
801  */
802  if (EisaAdapter)
803  {
804  if (!HalpDmaInitializeEisaAdapter(AdapterObject, DeviceDescription))
805  {
806  ObDereferenceObject(AdapterObject);
807  return NULL;
808  }
809  }
810 
811  return AdapterObject;
812 }
813 
823 NTAPI
827 {
829 }
830 
839 VOID
840 NTAPI
842 {
843  KIRQL OldIrql;
844  if (AdapterObject->ChannelNumber == 0xFF)
845  {
847  RemoveEntryList(&AdapterObject->AdapterList);
849  }
850 
851  ObDereferenceObject(AdapterObject);
852 }
853 
879 PVOID
880 NTAPI
882  IN ULONG Length,
883  IN PPHYSICAL_ADDRESS LogicalAddress,
884  IN BOOLEAN CacheEnabled)
885 {
888  PHYSICAL_ADDRESS BoundryAddressMultiple;
890 
893  BoundryAddressMultiple.QuadPart = 0;
894 
895  /*
896  * For bus-master DMA devices the buffer mustn't cross 4Gb boundary. For
897  * slave DMA devices the 64Kb boundary mustn't be crossed since the
898  * controller wouldn't be able to handle it.
899  */
900  if (AdapterObject->MasterDevice)
901  {
902  BoundryAddressMultiple.HighPart = 1;
903  }
904  else
905  {
906  BoundryAddressMultiple.LowPart = 0x10000;
907  }
908 
912  BoundryAddressMultiple,
913  CacheEnabled ? MmCached :
914  MmNonCached);
915  if (VirtualAddress == NULL) return NULL;
916 
917  *LogicalAddress = MmGetPhysicalAddress(VirtualAddress);
918 
919  return VirtualAddress;
920 }
921 
931 VOID
932 NTAPI
934  IN ULONG Length,
935  IN PHYSICAL_ADDRESS LogicalAddress,
937  IN BOOLEAN CacheEnabled)
938 {
940  Length,
941  CacheEnabled ? MmCached : MmNonCached);
942 }
943 
944 typedef struct _SCATTER_GATHER_CONTEXT {
955 
956 
958 NTAPI
960  IN PIRP Irp,
962  IN PVOID Context)
963 {
964  PSCATTER_GATHER_CONTEXT AdapterControlContext = Context;
965  PADAPTER_OBJECT AdapterObject = AdapterControlContext->AdapterObject;
966  PSCATTER_GATHER_LIST ScatterGatherList;
968  ULONG ElementCount = 0, RemainingLength = AdapterControlContext->Length;
969  PUCHAR CurrentVa = AdapterControlContext->CurrentVa;
970 
971  /* Store the map register base for later in HalPutScatterGatherList */
972  AdapterControlContext->MapRegisterBase = MapRegisterBase;
973 
974  while (RemainingLength > 0 && ElementCount < MAX_SG_ELEMENTS)
975  {
976  TempElements[ElementCount].Length = RemainingLength;
977  TempElements[ElementCount].Reserved = 0;
978  TempElements[ElementCount].Address = IoMapTransfer(AdapterObject,
979  AdapterControlContext->Mdl,
981  CurrentVa + (AdapterControlContext->Length - RemainingLength),
982  &TempElements[ElementCount].Length,
983  AdapterControlContext->WriteToDevice);
984  if (TempElements[ElementCount].Length == 0)
985  break;
986 
987  DPRINT("Allocated one S/G element: 0x%I64u with length: 0x%x\n",
988  TempElements[ElementCount].Address.QuadPart,
989  TempElements[ElementCount].Length);
990 
991  ASSERT(TempElements[ElementCount].Length <= RemainingLength);
992  RemainingLength -= TempElements[ElementCount].Length;
993  ElementCount++;
994  }
995 
996  if (RemainingLength > 0)
997  {
998  DPRINT1("Scatter/gather list construction failed!\n");
999  return DeallocateObject;
1000  }
1001 
1002  ScatterGatherList = ExAllocatePoolWithTag(NonPagedPool,
1003  sizeof(SCATTER_GATHER_LIST) + sizeof(SCATTER_GATHER_ELEMENT) * ElementCount,
1004  TAG_DMA);
1005  ASSERT(ScatterGatherList);
1006 
1007  ScatterGatherList->NumberOfElements = ElementCount;
1008  ScatterGatherList->Reserved = (ULONG_PTR)AdapterControlContext;
1009  RtlCopyMemory(ScatterGatherList->Elements,
1010  TempElements,
1011  sizeof(SCATTER_GATHER_ELEMENT) * ElementCount);
1012 
1013  DPRINT("Initiating S/G DMA with %d element(s)\n", ElementCount);
1014 
1015  AdapterControlContext->AdapterListControlRoutine(DeviceObject,
1016  Irp,
1017  ScatterGatherList,
1018  AdapterControlContext->AdapterListControlContext);
1019 
1021 }
1022 
1051  NTSTATUS
1052  NTAPI
1055  IN PMDL Mdl,
1056  IN PVOID CurrentVa,
1057  IN ULONG Length,
1059  IN PVOID Context,
1061 {
1062  PSCATTER_GATHER_CONTEXT AdapterControlContext;
1063 
1064  AdapterControlContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCATTER_GATHER_CONTEXT), TAG_DMA);
1065  if (!AdapterControlContext) return STATUS_INSUFFICIENT_RESOURCES;
1066 
1067  AdapterControlContext->AdapterObject = AdapterObject;
1068  AdapterControlContext->Mdl = Mdl;
1069  AdapterControlContext->CurrentVa = CurrentVa;
1070  AdapterControlContext->Length = Length;
1071  AdapterControlContext->MapRegisterCount = PAGE_ROUND_UP(Length) >> PAGE_SHIFT;
1072  AdapterControlContext->AdapterListControlRoutine = ExecutionRoutine;
1073  AdapterControlContext->AdapterListControlContext = Context;
1074  AdapterControlContext->WriteToDevice = WriteToDevice;
1075 
1076  AdapterControlContext->Wcb.DeviceObject = DeviceObject;
1077  AdapterControlContext->Wcb.DeviceContext = AdapterControlContext;
1078  AdapterControlContext->Wcb.CurrentIrp = DeviceObject->CurrentIrp;
1079 
1080  return HalAllocateAdapterChannel(AdapterObject,
1081  &AdapterControlContext->Wcb,
1082  AdapterControlContext->MapRegisterCount,
1084 }
1085 
1104  VOID
1105  NTAPI
1109 {
1110  PSCATTER_GATHER_CONTEXT AdapterControlContext = (PSCATTER_GATHER_CONTEXT)ScatterGather->Reserved;
1111  ULONG i;
1112 
1113  for (i = 0; i < ScatterGather->NumberOfElements; i++)
1114  {
1115  IoFlushAdapterBuffers(AdapterObject,
1116  AdapterControlContext->Mdl,
1117  AdapterControlContext->MapRegisterBase,
1118  AdapterControlContext->CurrentVa,
1119  ScatterGather->Elements[i].Length,
1120  AdapterControlContext->WriteToDevice);
1121  AdapterControlContext->CurrentVa += ScatterGather->Elements[i].Length;
1122  }
1123 
1124  IoFreeMapRegisters(AdapterObject,
1125  AdapterControlContext->MapRegisterBase,
1126  AdapterControlContext->MapRegisterCount);
1127 
1128  DPRINT("S/G DMA has finished!\n");
1129 
1130  ExFreePoolWithTag(AdapterControlContext, TAG_DMA);
1132 }
1133 #endif
1134 
1143 ULONG
1144 NTAPI
1146 {
1147  return 1;
1148 }
1149 
1150 /*
1151  * @name HalReadDmaCounter
1152  *
1153  * Read DMA operation progress counter.
1154  *
1155  * @implemented
1156  */
1157 ULONG
1158 NTAPI
1160 {
1161  KIRQL OldIrql;
1162  ULONG Count, OldCount;
1163 
1164  ASSERT(!AdapterObject->MasterDevice);
1165 
1166  /*
1167  * Acquire the master adapter lock since we're going to mess with the
1168  * system DMA controller registers and we really don't want anyone
1169  * to do the same at the same time.
1170  */
1171  KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
1172 
1173  /* Send the request to the specific controller. */
1174  if (AdapterObject->AdapterNumber == 1)
1175  {
1176  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
1177 
1178  Count = 0xffff00;
1179  do
1180  {
1181  OldCount = Count;
1182 
1183  /* Send Reset */
1184  WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
1185 
1186  /* Read Count */
1187  Count = READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
1188  [AdapterObject->ChannelNumber].DmaBaseCount);
1189  Count |= READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
1190  [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
1191  } while (0xffff00 & (OldCount ^ Count));
1192  }
1193  else
1194  {
1195  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
1196 
1197  Count = 0xffff00;
1198  do
1199  {
1200  OldCount = Count;
1201 
1202  /* Send Reset */
1203  WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
1204 
1205  /* Read Count */
1206  Count = READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
1207  [AdapterObject->ChannelNumber].DmaBaseCount);
1208  Count |= READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
1209  [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
1210  } while (0xffff00 & (OldCount ^ Count));
1211  }
1212 
1213  KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
1214 
1215  Count++;
1216  Count &= 0xffff;
1217  if (AdapterObject->Width16Bits) Count *= 2;
1218 
1219  return Count;
1220 }
1221 
1222 #ifndef _MINIHAL_
1223 
1229 VOID
1230 NTAPI
1232 {
1234  KIRQL OldIrql;
1235  BOOLEAN Succeeded;
1236 
1237  /*
1238  * Try to allocate new map registers for the adapter.
1239  *
1240  * NOTE: The NT implementation actually tries to allocate more map
1241  * registers than needed as an optimization.
1242  */
1244  Succeeded = HalpGrowMapBuffers(WorkItem->AdapterObject->MasterAdapter,
1245  WorkItem->NumberOfMapRegisters << PAGE_SHIFT);
1246  KeSetEvent(&HalpDmaLock, 0, 0);
1247 
1248  if (Succeeded)
1249  {
1250  /*
1251  * Flush the adapter queue now that new map registers are ready. The
1252  * easiest way to do that is to call IoFreeMapRegisters to not free
1253  * any registers. Note that we use the magic (PVOID)2 map register
1254  * base to bypass the parameter checking.
1255  */
1257  IoFreeMapRegisters(WorkItem->AdapterObject, (PVOID)2, 0);
1259  }
1260 
1262 }
1263 
1288 NTSTATUS
1289 NTAPI
1291  IN PWAIT_CONTEXT_BLOCK WaitContextBlock,
1294 {
1295  PADAPTER_OBJECT MasterAdapter;
1297  ULONG Index = MAXULONG;
1298  ULONG Result;
1299  KIRQL OldIrql;
1300 
1302 
1303  /* Set up the wait context block in case we can't run right away. */
1304  WaitContextBlock->DeviceRoutine = ExecutionRoutine;
1305  WaitContextBlock->NumberOfMapRegisters = NumberOfMapRegisters;
1306 
1307  /* Returns true if queued, else returns false and sets the queue to busy */
1308  if (KeInsertDeviceQueue(&AdapterObject->ChannelWaitQueue,
1309  &WaitContextBlock->WaitQueueEntry))
1310  {
1311  return STATUS_SUCCESS;
1312  }
1313 
1314  MasterAdapter = AdapterObject->MasterAdapter;
1315 
1316  AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
1317  AdapterObject->CurrentWcb = WaitContextBlock;
1318 
1319  if ((NumberOfMapRegisters) && (AdapterObject->NeedsMapRegisters))
1320  {
1321  if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
1322  {
1323  AdapterObject->NumberOfMapRegisters = 0;
1324  IoFreeAdapterChannel(AdapterObject);
1326  }
1327 
1328  /*
1329  * Get the map registers. This is partly complicated by the fact
1330  * that new map registers can only be allocated at PASSIVE_LEVEL
1331  * and we're currently at DISPATCH_LEVEL. The following code has
1332  * two code paths:
1333  *
1334  * - If there is no adapter queued for map register allocation,
1335  * try to see if enough contiguous map registers are present.
1336  * In case they're we can just get them and proceed further.
1337  *
1338  * - If some adapter is already present in the queue we must
1339  * respect the order of adapters asking for map registers and
1340  * so the fast case described above can't take place.
1341  * This case is also entered if not enough coniguous map
1342  * registers are present.
1343  *
1344  * A work queue item is allocated and queued, the adapter is
1345  * also queued into the master adapter queue. The worker
1346  * routine does the job of allocating the map registers at
1347  * PASSIVE_LEVEL and calling the ExecutionRoutine.
1348  */
1349 
1350  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1351 
1352  if (IsListEmpty(&MasterAdapter->AdapterQueue))
1353  {
1354  Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters, NumberOfMapRegisters, 0);
1355  if (Index != MAXULONG)
1356  {
1357  AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1358  if (!AdapterObject->ScatterGather)
1359  {
1360  AdapterObject->MapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1361  }
1362  }
1363  }
1364 
1365  if (Index == MAXULONG)
1366  {
1367  InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
1368 
1370  sizeof(GROW_WORK_ITEM),
1371  TAG_DMA);
1372  if (WorkItem)
1373  {
1375  WorkItem->AdapterObject = AdapterObject;
1376  WorkItem->NumberOfMapRegisters = NumberOfMapRegisters;
1377 
1378  ExQueueWorkItem(&WorkItem->WorkQueueItem, DelayedWorkQueue);
1379  }
1380 
1381  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1382 
1383  return STATUS_SUCCESS;
1384  }
1385 
1386  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1387  }
1388  else
1389  {
1390  AdapterObject->MapRegisterBase = NULL;
1391  AdapterObject->NumberOfMapRegisters = 0;
1392  }
1393 
1394  AdapterObject->CurrentWcb = WaitContextBlock;
1395 
1396  Result = ExecutionRoutine(WaitContextBlock->DeviceObject,
1397  WaitContextBlock->CurrentIrp,
1398  AdapterObject->MapRegisterBase,
1399  WaitContextBlock->DeviceContext);
1400 
1401  /*
1402  * Possible return values:
1403  *
1404  * - KeepObject
1405  * Don't free any resources, the ADAPTER_OBJECT is still in use and
1406  * the caller will call IoFreeAdapterChannel later.
1407  *
1408  * - DeallocateObject
1409  * Deallocate the map registers and release the ADAPTER_OBJECT, so
1410  * someone else can use it.
1411  *
1412  * - DeallocateObjectKeepRegisters
1413  * Release the ADAPTER_OBJECT, but hang on to the map registers. The
1414  * client will later call IoFreeMapRegisters.
1415  *
1416  * NOTE:
1417  * IoFreeAdapterChannel runs the queue, so it must be called unless
1418  * the adapter object is not to be freed.
1419  */
1420  if (Result == DeallocateObject)
1421  {
1422  IoFreeAdapterChannel(AdapterObject);
1423  }
1425  {
1426  AdapterObject->NumberOfMapRegisters = 0;
1427  IoFreeAdapterChannel(AdapterObject);
1428  }
1429 
1430  return STATUS_SUCCESS;
1431 }
1432 
1451 VOID
1452 NTAPI
1454 {
1455  PADAPTER_OBJECT MasterAdapter;
1457  PWAIT_CONTEXT_BLOCK WaitContextBlock;
1458  ULONG Index = MAXULONG;
1459  ULONG Result;
1460  KIRQL OldIrql;
1461 
1462  MasterAdapter = AdapterObject->MasterAdapter;
1463 
1464  for (;;)
1465  {
1466  /*
1467  * To keep map registers, call here with AdapterObject->
1468  * NumberOfMapRegisters set to zero. This trick is used in
1469  * HalAllocateAdapterChannel for example.
1470  */
1471  if (AdapterObject->NumberOfMapRegisters)
1472  {
1473  IoFreeMapRegisters(AdapterObject,
1474  AdapterObject->MapRegisterBase,
1475  AdapterObject->NumberOfMapRegisters);
1476  }
1477 
1478  DeviceQueueEntry = KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue);
1479  if (!DeviceQueueEntry) break;
1480 
1481  WaitContextBlock = CONTAINING_RECORD(DeviceQueueEntry,
1483  WaitQueueEntry);
1484 
1485  AdapterObject->CurrentWcb = WaitContextBlock;
1486  AdapterObject->NumberOfMapRegisters = WaitContextBlock->NumberOfMapRegisters;
1487 
1488  if ((WaitContextBlock->NumberOfMapRegisters) && (AdapterObject->MasterAdapter))
1489  {
1490  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1491 
1492  if (IsListEmpty(&MasterAdapter->AdapterQueue))
1493  {
1494  Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
1495  WaitContextBlock->NumberOfMapRegisters,
1496  0);
1497  if (Index != MAXULONG)
1498  {
1499  AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1500  if (!AdapterObject->ScatterGather)
1501  {
1502  AdapterObject->MapRegisterBase =(PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1503  }
1504  }
1505  }
1506 
1507  if (Index == MAXULONG)
1508  {
1509  InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
1510  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1511  break;
1512  }
1513 
1514  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1515  }
1516  else
1517  {
1518  AdapterObject->MapRegisterBase = NULL;
1519  AdapterObject->NumberOfMapRegisters = 0;
1520  }
1521 
1522  /* Call the adapter control routine. */
1523  Result = ((PDRIVER_CONTROL)WaitContextBlock->DeviceRoutine)(WaitContextBlock->DeviceObject,
1524  WaitContextBlock->CurrentIrp,
1525  AdapterObject->MapRegisterBase,
1526  WaitContextBlock->DeviceContext);
1527  switch (Result)
1528  {
1529  case KeepObject:
1530  /*
1531  * We're done until the caller manually calls IoFreeAdapterChannel
1532  * or IoFreeMapRegisters.
1533  */
1534  return;
1535 
1537  /*
1538  * Hide the map registers so they aren't deallocated next time
1539  * around.
1540  */
1541  AdapterObject->NumberOfMapRegisters = 0;
1542  break;
1543 
1544  default:
1545  break;
1546  }
1547  }
1548 }
1549 
1564 VOID
1565 NTAPI
1569 {
1570  PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
1571  PLIST_ENTRY ListEntry;
1572  KIRQL OldIrql;
1573  ULONG Index;
1574  ULONG Result;
1575 
1577 
1578  if (!(MasterAdapter) || !(MapRegisterBase)) return;
1579 
1580  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1581 
1582  if (NumberOfMapRegisters != 0)
1583  {
1584  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1585 
1586  RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1587  RtlClearBits(MasterAdapter->MapRegisters,
1588  (ULONG)(RealMapRegisterBase - MasterAdapter->MapRegisterBase),
1590  }
1591 
1592  /*
1593  * Now that we freed few map registers it's time to look at the master
1594  * adapter queue and see if there is someone waiting for map registers.
1595  */
1596  while (!IsListEmpty(&MasterAdapter->AdapterQueue))
1597  {
1598  ListEntry = RemoveHeadList(&MasterAdapter->AdapterQueue);
1599  AdapterObject = CONTAINING_RECORD(ListEntry, struct _ADAPTER_OBJECT, AdapterQueue);
1600 
1601  Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
1602  AdapterObject->NumberOfMapRegisters,
1603  0);
1604  if (Index == MAXULONG)
1605  {
1606  InsertHeadList(&MasterAdapter->AdapterQueue, ListEntry);
1607  break;
1608  }
1609 
1610  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1611 
1612  AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1613  if (!AdapterObject->ScatterGather)
1614  {
1615  AdapterObject->MapRegisterBase =
1616  (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1617  }
1618 
1619  Result = ((PDRIVER_CONTROL)AdapterObject->CurrentWcb->DeviceRoutine)(AdapterObject->CurrentWcb->DeviceObject,
1620  AdapterObject->CurrentWcb->CurrentIrp,
1621  AdapterObject->MapRegisterBase,
1622  AdapterObject->CurrentWcb->DeviceContext);
1623  switch (Result)
1624  {
1626  AdapterObject->NumberOfMapRegisters = 0;
1627  /* fall through */
1628 
1629  case DeallocateObject:
1630  if (AdapterObject->NumberOfMapRegisters)
1631  {
1632  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1633  RtlClearBits(MasterAdapter->MapRegisters,
1634  (ULONG)(AdapterObject->MapRegisterBase -
1635  MasterAdapter->MapRegisterBase),
1636  AdapterObject->NumberOfMapRegisters);
1637  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1638  }
1639 
1640  IoFreeAdapterChannel(AdapterObject);
1641  break;
1642 
1643  default:
1644  break;
1645  }
1646 
1647  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1648  }
1649 
1650  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1651 }
1652 
1660 VOID
1661 NTAPI
1664  IN PVOID CurrentVa,
1665  IN ULONG Length,
1667 {
1668  ULONG CurrentLength;
1669  ULONG_PTR CurrentAddress;
1670  ULONG ByteOffset;
1672 
1674  if (!VirtualAddress)
1675  {
1676  /*
1677  * NOTE: On real NT a mechanism with reserved pages is implemented
1678  * to handle this case in a slow, but graceful non-fatal way.
1679  */
1680  KeBugCheckEx(HAL_MEMORY_ALLOCATION, PAGE_SIZE, 0, (ULONG_PTR)__FILE__, 0);
1681  }
1682 
1683  CurrentAddress = (ULONG_PTR)VirtualAddress +
1684  (ULONG_PTR)CurrentVa -
1686 
1687  while (Length > 0)
1688  {
1689  ByteOffset = BYTE_OFFSET(CurrentAddress);
1690  CurrentLength = PAGE_SIZE - ByteOffset;
1691  if (CurrentLength > Length) CurrentLength = Length;
1692 
1693  if (WriteToDevice)
1694  {
1695  RtlCopyMemory((PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
1696  (PVOID)CurrentAddress,
1697  CurrentLength);
1698  }
1699  else
1700  {
1701  RtlCopyMemory((PVOID)CurrentAddress,
1702  (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
1703  CurrentLength);
1704  }
1705 
1706  Length -= CurrentLength;
1707  CurrentAddress += CurrentLength;
1708  MapRegisterBase++;
1709  }
1710 }
1711 
1743 BOOLEAN
1744 NTAPI
1746  IN PMDL Mdl,
1748  IN PVOID CurrentVa,
1749  IN ULONG Length,
1751 {
1752  BOOLEAN SlaveDma = FALSE;
1753  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1756  PPFN_NUMBER MdlPagesPtr;
1757 
1758  /* Sanity checks */
1760  ASSERT(AdapterObject);
1761 
1762  if (!AdapterObject->MasterDevice)
1763  {
1764  /* Mask out (disable) the DMA channel. */
1765  if (AdapterObject->AdapterNumber == 1)
1766  {
1767  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
1768  WRITE_PORT_UCHAR(&DmaControl1->SingleMask,
1769  AdapterObject->ChannelNumber | DMA_SETMASK);
1770  }
1771  else
1772  {
1773  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
1774  WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
1775  AdapterObject->ChannelNumber | DMA_SETMASK);
1776  }
1777  SlaveDma = TRUE;
1778  }
1779 
1780  /* This can happen if the device supports hardware scatter/gather. */
1781  if (MapRegisterBase == NULL) return TRUE;
1782 
1783  RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1784 
1785  if (!WriteToDevice)
1786  {
1788  {
1789  if (RealMapRegisterBase->Counter != MAXULONG)
1790  {
1791  if ((SlaveDma) && !(AdapterObject->IgnoreCount))
1792  {
1793  Length -= HalReadDmaCounter(AdapterObject);
1794  }
1795  }
1797  RealMapRegisterBase,
1798  CurrentVa,
1799  Length,
1800  FALSE);
1801  }
1802  else
1803  {
1804  MdlPagesPtr = MmGetMdlPfnArray(Mdl);
1805  MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
1806 
1807  PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
1808  PhysicalAddress.QuadPart += BYTE_OFFSET(CurrentVa);
1809 
1812  {
1814  RealMapRegisterBase,
1815  CurrentVa,
1816  Length,
1817  FALSE);
1818  }
1819  }
1820  }
1821 
1822  RealMapRegisterBase->Counter = 0;
1823 
1824  return TRUE;
1825 }
1826 
1859 NTAPI
1861  IN PMDL Mdl,
1863  IN PVOID CurrentVa,
1864  IN OUT PULONG Length,
1866 {
1867  PPFN_NUMBER MdlPagesPtr;
1868  PFN_NUMBER MdlPage1, MdlPage2;
1869  ULONG ByteOffset;
1871  ULONG TransferLength;
1872  BOOLEAN UseMapRegisters;
1873  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1876  ULONG Counter;
1877  DMA_MODE AdapterMode;
1878  KIRQL OldIrql;
1879 
1880  /*
1881  * Precalculate some values that are used in all cases.
1882  *
1883  * ByteOffset is offset inside the page at which the transfer starts.
1884  * MdlPagesPtr is pointer inside the MDL page chain at the page where the
1885  * transfer start.
1886  * PhysicalAddress is physical address corresponding to the transfer
1887  * start page and offset.
1888  * TransferLength is the initial length of the transfer, which is reminder
1889  * of the first page. The actual value is calculated below.
1890  *
1891  * Note that all the variables can change during the processing which
1892  * takes place below. These are just initial values.
1893  */
1894  ByteOffset = BYTE_OFFSET(CurrentVa);
1895 
1896  MdlPagesPtr = MmGetMdlPfnArray(Mdl);
1897  MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
1898 
1899  PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
1901 
1902  TransferLength = PAGE_SIZE - ByteOffset;
1903 
1904  /*
1905  * Special case for bus master adapters with S/G support. We can directly
1906  * use the buffer specified by the MDL, so not much work has to be done.
1907  *
1908  * Just return the passed VA's corresponding physical address and update
1909  * length to the number of physically contiguous bytes found. Also
1910  * pages crossing the 4Gb boundary aren't considered physically contiguous.
1911  */
1912  if (MapRegisterBase == NULL)
1913  {
1914  while (TransferLength < *Length)
1915  {
1916  MdlPage1 = *MdlPagesPtr;
1917  MdlPage2 = *(MdlPagesPtr + 1);
1918  if (MdlPage1 + 1 != MdlPage2) break;
1919  if ((MdlPage1 ^ MdlPage2) & ~0xFFFFF) break;
1920  TransferLength += PAGE_SIZE;
1921  MdlPagesPtr++;
1922  }
1923 
1924  if (TransferLength < *Length) *Length = TransferLength;
1925 
1926  return PhysicalAddress;
1927  }
1928 
1929  /*
1930  * The code below applies to slave DMA adapters and bus master adapters
1931  * without hardward S/G support.
1932  */
1933  RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1934 
1935  /*
1936  * Try to calculate the size of the transfer. We can only transfer
1937  * pages that are physically contiguous and that don't cross the
1938  * 64Kb boundary (this limitation applies only for ISA controllers).
1939  */
1940  while (TransferLength < *Length)
1941  {
1942  MdlPage1 = *MdlPagesPtr;
1943  MdlPage2 = *(MdlPagesPtr + 1);
1944  if (MdlPage1 + 1 != MdlPage2) break;
1945  if (!HalpEisaDma && ((MdlPage1 ^ MdlPage2) & ~0xF)) break;
1946  TransferLength += PAGE_SIZE;
1947  MdlPagesPtr++;
1948  }
1949 
1950  if (TransferLength > *Length) TransferLength = *Length;
1951 
1952  /*
1953  * If we're about to simulate software S/G and not all the pages are
1954  * physically contiguous then we must use the map registers to store
1955  * the data and allow the whole transfer to proceed at once.
1956  */
1957  if (((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG) && (TransferLength < *Length))
1958  {
1959  UseMapRegisters = TRUE;
1960  PhysicalAddress = RealMapRegisterBase->PhysicalAddress;
1962  TransferLength = *Length;
1963  RealMapRegisterBase->Counter = MAXULONG;
1964  Counter = 0;
1965  }
1966  else
1967  {
1968  /*
1969  * This is ordinary DMA transfer, so just update the progress
1970  * counters. These are used by IoFlushAdapterBuffers to track
1971  * the transfer progress.
1972  */
1973  UseMapRegisters = FALSE;
1974  Counter = RealMapRegisterBase->Counter;
1975  RealMapRegisterBase->Counter += BYTES_TO_PAGES(ByteOffset + TransferLength);
1976 
1977  /*
1978  * Check if the buffer doesn't exceed the highest physical address
1979  * limit of the device. In that case we must use the map registers to
1980  * store the data.
1981  */
1983  if ((PhysicalAddress.QuadPart + TransferLength) > HighestAcceptableAddress.QuadPart)
1984  {
1985  UseMapRegisters = TRUE;
1986  PhysicalAddress = RealMapRegisterBase[Counter].PhysicalAddress;
1989  {
1990  RealMapRegisterBase->Counter = MAXULONG;
1991  Counter = 0;
1992  }
1993  }
1994  }
1995 
1996  /*
1997  * If we decided to use the map registers (see above) and we're about
1998  * to transfer data to the device then copy the buffers into the map
1999  * register memory.
2000  */
2001  if ((UseMapRegisters) && (WriteToDevice))
2002  {
2004  RealMapRegisterBase + Counter,
2005  CurrentVa,
2006  TransferLength,
2007  WriteToDevice);
2008  }
2009 
2010  /*
2011  * Return the length of transfer that actually takes place.
2012  */
2013  *Length = TransferLength;
2014 
2015  /*
2016  * If we're doing slave (system) DMA then program the (E)ISA controller
2017  * to actually start the transfer.
2018  */
2019  if ((AdapterObject) && !(AdapterObject->MasterDevice))
2020  {
2021  AdapterMode = AdapterObject->AdapterMode;
2022 
2023  if (WriteToDevice)
2024  {
2025  AdapterMode.TransferType = WRITE_TRANSFER;
2026  }
2027  else
2028  {
2029  AdapterMode.TransferType = READ_TRANSFER;
2030  if (AdapterObject->IgnoreCount)
2031  {
2032  RtlZeroMemory((PUCHAR)RealMapRegisterBase[Counter].VirtualAddress + ByteOffset,
2033  TransferLength);
2034  }
2035  }
2036 
2038  if (AdapterObject->Width16Bits)
2039  {
2040  TransferLength >>= 1;
2041  TransferOffset >>= 1;
2042  }
2043 
2044  KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
2045 
2046  if (AdapterObject->AdapterNumber == 1)
2047  {
2048  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
2049 
2050  /* Reset Register */
2051  WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
2052 
2053  /* Set the Mode */
2054  WRITE_PORT_UCHAR(&DmaControl1->Mode, AdapterMode.Byte);
2055 
2056  /* Set the Offset Register */
2057  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2058  (UCHAR)(TransferOffset));
2059  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2060  (UCHAR)(TransferOffset >> 8));
2061 
2062  /* Set the Page Register */
2063  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
2064  (UCHAR)(PhysicalAddress.LowPart >> 16));
2065  if (HalpEisaDma)
2066  {
2067  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
2068  0);
2069  }
2070 
2071  /* Set the Length */
2072  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2073  (UCHAR)(TransferLength - 1));
2074  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2075  (UCHAR)((TransferLength - 1) >> 8));
2076 
2077  /* Unmask the Channel */
2078  WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK);
2079  }
2080  else
2081  {
2082  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
2083 
2084  /* Reset Register */
2085  WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
2086 
2087  /* Set the Mode */
2088  WRITE_PORT_UCHAR(&DmaControl2->Mode, AdapterMode.Byte);
2089 
2090  /* Set the Offset Register */
2091  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2092  (UCHAR)(TransferOffset));
2093  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2094  (UCHAR)(TransferOffset >> 8));
2095 
2096  /* Set the Page Register */
2097  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
2098  (UCHAR)(PhysicalAddress.u.LowPart >> 16));
2099  if (HalpEisaDma)
2100  {
2101  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
2102  0);
2103  }
2104 
2105  /* Set the Length */
2106  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2107  (UCHAR)(TransferLength - 1));
2108  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2109  (UCHAR)((TransferLength - 1) >> 8));
2110 
2111  /* Unmask the Channel */
2112  WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
2113  AdapterObject->ChannelNumber | DMA_CLEARMASK);
2114  }
2115 
2116  KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
2117  }
2118 
2119  /*
2120  * Return physical address of the buffer with data that is used for the
2121  * transfer. It can either point inside the Mdl that was passed by the
2122  * caller or into the map registers if the Mdl buffer can't be used
2123  * directly.
2124  */
2125  return PhysicalAddress;
2126 }
2127 #endif
2128 
2134 BOOLEAN
2135 NTAPI
2137  IN ULONG Length,
2138  IN PHYSICAL_ADDRESS LogicalAddress,
2140 {
2141  /* Function always returns true */
2142  return TRUE;
2143 }
2144 
2145 /*
2146  * @implemented
2147  */
2148 PVOID
2149 NTAPI
2152 {
2153  PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
2154  ULONG MapRegisterNumber;
2155 
2156  /* Check if it needs map registers */
2157  if (AdapterObject->NeedsMapRegisters)
2158  {
2159  /* Check if we have enough */
2160  if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
2161  {
2162  /* We don't, fail */
2163  AdapterObject->NumberOfMapRegisters = 0;
2164  return NULL;
2165  }
2166 
2167  /* Try to find free map registers */
2168  MapRegisterNumber = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
2170  0);
2171 
2172  /* Check if nothing was found */
2173  if (MapRegisterNumber == MAXULONG)
2174  {
2175  /* No free registers found, so use the base registers */
2176  RtlSetBits(MasterAdapter->MapRegisters,
2177  0,
2179  MapRegisterNumber = 0;
2180  }
2181 
2182  /* Calculate the new base */
2183  AdapterObject->MapRegisterBase =
2184  (PROS_MAP_REGISTER_ENTRY)(MasterAdapter->MapRegisterBase +
2185  MapRegisterNumber);
2186 
2187  /* Check if scatter gather isn't supported */
2188  if (!AdapterObject->ScatterGather)
2189  {
2190  /* Set the flag */
2191  AdapterObject->MapRegisterBase =
2193  ((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
2194  }
2195  }
2196  else
2197  {
2198  AdapterObject->MapRegisterBase = NULL;
2199  AdapterObject->NumberOfMapRegisters = 0;
2200  }
2201 
2202  /* Return the base */
2203  return AdapterObject->MapRegisterBase;
2204 }
2205 
2206 /* 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:2291
#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:949
#define MAX_SG_ELEMENTS
Definition: dma.c:80
UCHAR DmaBaseAddress
Definition: haldma.h:183
DMA1_ADDRESS_COUNT DmaAddressCount[4]
Definition: haldma.h:197
#define B_32BITS
Definition: haldma.h:145
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:711
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
VOID(NTAPI * PPUT_SCATTER_GATHER_LIST)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PSCATTER_GATHER_LIST ScatterGather, _In_ BOOLEAN WriteToDevice)
Definition: iotypes.h:2371
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:86
#define READ_PORT_UCHAR(p)
Definition: pc98vid.h:22
#define TRUE
Definition: types.h:120
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
_Must_inspect_result_ _In_ WDFUSBDEVICE _In_ WDFREQUEST _In_ PWDF_USB_CONTROL_SETUP_PACKET _In_opt_ WDFMEMORY _In_opt_ PWDFMEMORY_OFFSET TransferOffset
Definition: wdfusb.h:1378
PFREE_MAP_REGISTERS FreeMapRegisters
Definition: iotypes.h:2620
ULONG NTAPI HalpDmaGetDmaAlignment(PADAPTER_OBJECT AdapterObject)
Definition: dma.c:918
unsigned char * PUCHAR
Definition: retypes.h:3
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)
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:2314
PVOID VirtualAddress
Definition: haldma.h:314
PHYSICAL_ADDRESS Address
Definition: iotypes.h:2153
VOID NTAPI KeInitializeDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
Definition: devqueue.c:22
#define TypeA
Definition: nslookup.h:13
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
PDRIVER_CONTROL DeviceRoutine
Definition: iotypes.h:198
#define BURST_TIMING
Definition: haldma.h:152
#define DMA_CLEARMASK
Definition: haldma.h:175
static const ULONG_PTR HalpEisaPortPage[8]
Definition: dma.c:93
UCHAR Byte
Definition: haldma.h:99
#define InsertTailList(ListHead, Entry)
ULONG MapRegisterCount
Definition: dma.c:951
static DMA_OPERATIONS HalpDmaOperations
Definition: dma.c:105
#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
_In_ WDFDMATRANSACTION _Out_opt_ ULONG * MapRegisterCount
#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
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:2323
static KEVENT HalpDmaLock
Definition: dma.c:83
uint32_t ULONG_PTR
Definition: typedefs.h:65
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:1106
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:9
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
ULONG(NTAPI * PGET_DMA_ALIGNMENT)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2342
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:2306
UCHAR SingleMask
Definition: haldma.h:200
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_ PCUNICODE_STRING DeviceDescription
Definition: wdfpdo.h:430
PVOID NTAPI HalAllocateCrashDumpRegisters(IN PADAPTER_OBJECT AdapterObject, IN OUT PULONG NumberOfMapRegisters)
Definition: dma.c:180
ULONG PFN_NUMBER
Definition: ke.h:9
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
#define FALSE
Definition: types.h:117
NTSTATUS NTAPI HalAllocateAdapterChannel(IN PADAPTER_OBJECT AdapterObject, IN PWAIT_CONTEXT_BLOCK WaitContextBlock, IN ULONG NumberOfMapRegisters, IN PDRIVER_CONTROL ExecutionRoutine)
Definition: dma.c:88
_In_ PIRP Irp
Definition: csq.h:116
UCHAR Channel
Definition: haldma.h:93
PMAP_TRANSFER MapTransfer
Definition: iotypes.h:2621
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
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
static WCHAR Address[46]
Definition: ping.c:68
static KSPIN_LOCK HalpDmaAdapterListLock
Definition: dma.c:84
_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
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
void * PVOID
Definition: retypes.h:9
struct _SCATTER_GATHER_LIST SCATTER_GATHER_LIST
Definition: iotypes.h:2184
#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
VOID NTAPI HalpGrowMapBufferWorker(PVOID DeferredContext)
Definition: dma.c:1005
#define B_16BITS
Definition: haldma.h:146
PFLUSH_ADAPTER_BUFFERS FlushAdapterBuffers
Definition: iotypes.h:2618
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
Status
Definition: gdiplustypes.h:24
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:1053
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:2333
int Count
Definition: noreturn.cpp:7
PADAPTER_OBJECT AdapterObject
Definition: dma.c:945
#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
_In_ WDFDMATRANSACTION _In_ size_t MaximumLength
PFREE_ADAPTER_CHANNEL FreeAdapterChannel
Definition: iotypes.h:2619
#define COMPATIBLE_TIMING
Definition: haldma.h:149
#define ASSERT(a)
Definition: mode.c:45
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_In_ WDFCOLLECTION _In_ ULONG Index
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define ObDereferenceObject
Definition: obfuncs.h:203
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
CODE_SEG("INIT")
Definition: fsrtlpc.c:19
#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:1081
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
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
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:106
struct _LARGE_INTEGER::@2277 u
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:2298
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:119
static PADAPTER_OBJECT HalpMasterAdapter
Definition: dma.c:90
#define TAG_DMA
Definition: dma.c:128
#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:2287
WAIT_CONTEXT_BLOCK Wcb
Definition: dma.c:953
BOOLEAN NTAPI HalpDmaInitializeEisaAdapter(PADAPTER_OBJECT AdapterObject, PDEVICE_DESCRIPTION DeviceDescription)
Definition: dma.c:461
static LIST_ENTRY HalpDmaAdapterList
Definition: dma.c:85
struct _DMA_OPERATIONS DMA_OPERATIONS
VOID NTAPI HalPutDmaAdapter(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:35
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN WriteToDevice
Definition: cdrom.h:989
#define MAXULONG
Definition: typedefs.h:251
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
PVOID MapRegisterBase
Definition: dma.c:950
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:191
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:2617
#define MAX_MAP_REGISTERS
Definition: dma.c:126
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
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:2357
ULONG(NTAPI * PREAD_DMA_COUNTER)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2346
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:255
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:2355
#define NULL
Definition: types.h:112
VOID(NTAPI * PFREE_MAP_REGISTERS)(_In_ PDMA_ADAPTER DmaAdapter, PVOID MapRegisterBase, ULONG NumberOfMapRegisters)
Definition: iotypes.h:2327
#define PAGE_ROUND_UP(x)
Definition: mmtypes.h:38
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
#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:2045
VOID NTAPI MmFreeContiguousMemorySpecifyCache(IN PVOID BaseAddress, IN SIZE_T NumberOfBytes, IN MEMORY_CACHING_TYPE CacheType)
Definition: contmem.c:666
_In_ HANDLE Handle
Definition: extypes.h:390
struct tagContext Context
Definition: acpixf.h:1034
#define SINGLE_REQUEST_MODE
Definition: haldma.h:170
#define OUT
Definition: typedefs.h:40
_In_ PDEVICE_OBJECT _In_ ULONG _In_ PDRIVER_CONTROL ExecutionRoutine
Definition: iofuncs.h:1393
PVOID AdapterListControlContext
Definition: dma.c:950
struct _SCATTER_GATHER_LIST * PSCATTER_GATHER_LIST
Definition: iotypes.h:2184
#define TYPE_B_TIMING
Definition: haldma.h:151
unsigned int ULONG
Definition: retypes.h:1
#define DEMAND_REQUEST_MODE
Definition: haldma.h:169
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#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:686
DRIVER_CONTROL * PDRIVER_CONTROL
Definition: iotypes.h:194
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
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:959
#define STATUS_SUCCESS
Definition: shellext.h:65
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:110
_Inout_ PKDEVICE_QUEUE_ENTRY DeviceQueueEntry
Definition: kefuncs.h:339
#define DEVICE_DESCRIPTION_VERSION1
Definition: iotypes.h:2044
#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
#define CASCADE_REQUEST_MODE
Definition: haldma.h:172
static BOOLEAN HalpEisaDma
Definition: dma.c:88
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: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:2360
PADAPTER_OBJECT NTAPI HalpDmaAllocateMasterAdapter(VOID)
Definition: dma.c:332
struct _SCATTER_GATHER_CONTEXT * PSCATTER_GATHER_CONTEXT
LONGLONG QuadPart
Definition: typedefs.h:114
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:200
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:952
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