ReactOS  0.4.15-dev-1018-g0695ecb
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 #if defined(SARCH_PC98)
137 /*
138  * Disable I/O for safety.
139  * FIXME: Add support for PC-98 DMA controllers.
140  */
141 #undef WRITE_PORT_UCHAR
142 #undef READ_PORT_UCHAR
143 
144 #define WRITE_PORT_UCHAR(Port, Data) \
145  do { \
146  UNIMPLEMENTED; \
147  (Port); \
148  (Data); \
149  } while (0)
150 
151 #define READ_PORT_UCHAR(Port) 0x00
152 #endif
153 
154 #ifndef _MINIHAL_
155 INIT_FUNCTION
156 VOID
158 {
159  /*
160  * Initialize the DMA Operation table
161  */
167 
169  {
170  /*
171  * Check if Extended DMA is available. We're just going to do a random
172  * read and write.
173  */
174  WRITE_PORT_UCHAR(UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2)), 0x2A);
175  if (READ_PORT_UCHAR(UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2))) == 0x2A)
176  {
177  DPRINT1("Machine supports EISA DMA. Bus type: %lu\n", HalpBusType);
178  HalpEisaDma = TRUE;
179  }
180  }
181 
182  /*
183  * Intialize all the global variables and allocate master adapter with
184  * first map buffers.
185  */
190 
191  /*
192  * Setup the HalDispatchTable callback for creating PnP DMA adapters. It's
193  * used by IoGetDmaAdapter in the kernel.
194  */
196 }
197 #endif
198 
206 NTAPI
208 {
209  PHYSICAL_ADDRESS HighestAddress;
210 
211  if (AdapterObject->MasterDevice)
212  {
213  if (AdapterObject->Dma64BitAddresses)
214  {
215  HighestAddress.QuadPart = 0xFFFFFFFFFFFFFFFFULL;
216  return HighestAddress;
217  }
218  else if (AdapterObject->Dma32BitAddresses)
219  {
220  HighestAddress.QuadPart = 0xFFFFFFFF;
221  return HighestAddress;
222  }
223  }
224 
225  HighestAddress.QuadPart = 0xFFFFFF;
226  return HighestAddress;
227 }
228 
229 #ifndef _MINIHAL_
230 
241 BOOLEAN
242 NTAPI
244  IN ULONG SizeOfMapBuffers)
245 {
250  PHYSICAL_ADDRESS BoundryAddressMultiple;
251  KIRQL OldIrql;
252  ULONG MapRegisterCount;
253 
254  /* Check if enough map register slots are available. */
255  MapRegisterCount = BYTES_TO_PAGES(SizeOfMapBuffers);
256  if (MapRegisterCount + AdapterObject->NumberOfMapRegisters > MAX_MAP_REGISTERS)
257  {
258  DPRINT("No more map register slots available! (Current: %d | Requested: %d | Limit: %d)\n",
259  AdapterObject->NumberOfMapRegisters,
260  MapRegisterCount,
262  return FALSE;
263  }
264 
265  /*
266  * Allocate memory for the new map registers. For 32-bit adapters we use
267  * two passes in order not to waste scare resource (low memory).
268  */
271  LowestAcceptableAddress.LowPart = HighestAcceptableAddress.LowPart == 0xFFFFFFFF ? 0x1000000 : 0;
272  BoundryAddressMultiple.QuadPart = 0;
273 
277  BoundryAddressMultiple,
278  MmNonCached);
280  {
285  BoundryAddressMultiple,
286  MmNonCached);
287  }
288 
289  if (!VirtualAddress) return FALSE;
290 
292 
293  /*
294  * All the following must be done with the master adapter lock held
295  * to prevent corruption.
296  */
297  KeAcquireSpinLock(&AdapterObject->SpinLock, &OldIrql);
298 
299  /*
300  * Setup map register entries for the buffer allocated. Each entry has
301  * a virtual and physical address and corresponds to PAGE_SIZE large
302  * buffer.
303  */
304  if (MapRegisterCount > 0)
305  {
306  PROS_MAP_REGISTER_ENTRY CurrentEntry, PreviousEntry;
307 
308  CurrentEntry = AdapterObject->MapRegisterBase + AdapterObject->NumberOfMapRegisters;
309  do
310  {
311  /*
312  * Leave one entry free for every non-contiguous memory region
313  * in the map register bitmap. This ensures that we can search
314  * using RtlFindClearBits for contiguous map register regions.
315  *
316  * Also for non-EISA DMA leave one free entry for every 64Kb
317  * break, because the DMA controller can handle only coniguous
318  * 64Kb regions.
319  */
320  if (CurrentEntry != AdapterObject->MapRegisterBase)
321  {
322  PreviousEntry = CurrentEntry - 1;
323  if ((PreviousEntry->PhysicalAddress.LowPart + PAGE_SIZE) == PhysicalAddress.LowPart)
324  {
325  if (!HalpEisaDma)
326  {
327  if ((PreviousEntry->PhysicalAddress.LowPart ^ PhysicalAddress.LowPart) & 0xFFFF0000)
328  {
329  CurrentEntry++;
330  AdapterObject->NumberOfMapRegisters++;
331  }
332  }
333  }
334  else
335  {
336  CurrentEntry++;
337  AdapterObject->NumberOfMapRegisters++;
338  }
339  }
340 
341  RtlClearBit(AdapterObject->MapRegisters,
342  (ULONG)(CurrentEntry - AdapterObject->MapRegisterBase));
343  CurrentEntry->VirtualAddress = VirtualAddress;
344  CurrentEntry->PhysicalAddress = PhysicalAddress;
345 
348 
349  CurrentEntry++;
350  AdapterObject->NumberOfMapRegisters++;
351  MapRegisterCount--;
352  } while (MapRegisterCount);
353  }
354 
355  KeReleaseSpinLock(&AdapterObject->SpinLock, OldIrql);
356 
357  return TRUE;
358 }
359 
369 NTAPI
371 {
372  PADAPTER_OBJECT MasterAdapter;
373  ULONG Size, SizeOfBitmap;
374 
375  SizeOfBitmap = MAX_MAP_REGISTERS;
376  Size = sizeof(ADAPTER_OBJECT);
377  Size += sizeof(RTL_BITMAP);
378  Size += (SizeOfBitmap + 7) >> 3;
379 
380  MasterAdapter = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_DMA);
381  if (!MasterAdapter) return NULL;
382 
383  RtlZeroMemory(MasterAdapter, Size);
384 
385  KeInitializeSpinLock(&MasterAdapter->SpinLock);
386  InitializeListHead(&MasterAdapter->AdapterQueue);
387 
388  MasterAdapter->MapRegisters = (PVOID)(MasterAdapter + 1);
389  RtlInitializeBitMap(MasterAdapter->MapRegisters,
390  (PULONG)(MasterAdapter->MapRegisters + 1),
391  SizeOfBitmap);
392  RtlSetAllBits(MasterAdapter->MapRegisters);
393  MasterAdapter->NumberOfMapRegisters = 0;
394  MasterAdapter->CommittedMapRegisters = 0;
395 
396  MasterAdapter->MapRegisterBase = ExAllocatePoolWithTag(NonPagedPool,
397  SizeOfBitmap *
398  sizeof(ROS_MAP_REGISTER_ENTRY),
399  TAG_DMA);
400  if (!MasterAdapter->MapRegisterBase)
401  {
402  ExFreePool(MasterAdapter);
403  return NULL;
404  }
405 
406  RtlZeroMemory(MasterAdapter->MapRegisterBase,
407  SizeOfBitmap * sizeof(ROS_MAP_REGISTER_ENTRY));
408  if (!HalpGrowMapBuffers(MasterAdapter, 0x10000))
409  {
410  ExFreePool(MasterAdapter);
411  return NULL;
412  }
413 
414  return MasterAdapter;
415 }
416 
426 NTAPI
429 {
430  PADAPTER_OBJECT AdapterObject;
433  HANDLE Handle;
434 
436  NULL,
438  NULL,
439  NULL);
440 
444  KernelMode,
445  NULL,
446  sizeof(ADAPTER_OBJECT),
447  0,
448  0,
449  (PVOID)&AdapterObject);
450  if (!NT_SUCCESS(Status)) return NULL;
451 
452  Status = ObReferenceObjectByPointer(AdapterObject,
455  KernelMode);
456  if (!NT_SUCCESS(Status)) return NULL;
457 
458  RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT));
459 
460  Status = ObInsertObject(AdapterObject,
461  NULL,
463  0,
464  NULL,
465  &Handle);
466  if (!NT_SUCCESS(Status)) return NULL;
467 
468  ZwClose(Handle);
469 
470  AdapterObject->DmaHeader.Version = (USHORT)DeviceDescription->Version;
471  AdapterObject->DmaHeader.Size = sizeof(ADAPTER_OBJECT);
472  AdapterObject->DmaHeader.DmaOperations = &HalpDmaOperations;
473  AdapterObject->MapRegistersPerChannel = 1;
474  AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
475  AdapterObject->ChannelNumber = 0xFF;
476  AdapterObject->MasterAdapter = HalpMasterAdapter;
477  KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue);
478 
479  return AdapterObject;
480 }
481 #endif
482 
488 BOOLEAN
489 NTAPI
492 {
493  UCHAR Controller;
494  DMA_MODE DmaMode = {{0 }};
495  DMA_EXTENDED_MODE ExtendedMode = {{ 0 }};
496  PVOID AdapterBaseVa;
497 
498  Controller = (DeviceDescription->DmaChannel & 4) ? 2 : 1;
499 
500  if (Controller == 1)
501  {
502  AdapterBaseVa = UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController1));
503  }
504  else
505  {
506  AdapterBaseVa = UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2));
507  }
508 
509  AdapterObject->AdapterNumber = Controller;
510  AdapterObject->ChannelNumber = (UCHAR)(DeviceDescription->DmaChannel & 3);
511  AdapterObject->PagePort = (PUCHAR)HalpEisaPortPage[DeviceDescription->DmaChannel];
512  AdapterObject->Width16Bits = FALSE;
513  AdapterObject->AdapterBaseVa = AdapterBaseVa;
514 
515  if (HalpEisaDma)
516  {
517  ExtendedMode.ChannelNumber = AdapterObject->ChannelNumber;
518 
519  switch (DeviceDescription->DmaSpeed)
520  {
521  case Compatible: ExtendedMode.TimingMode = COMPATIBLE_TIMING; break;
522  case TypeA: ExtendedMode.TimingMode = TYPE_A_TIMING; break;
523  case TypeB: ExtendedMode.TimingMode = TYPE_B_TIMING; break;
524  case TypeC: ExtendedMode.TimingMode = BURST_TIMING; break;
525  default:
526  return FALSE;
527  }
528 
529  switch (DeviceDescription->DmaWidth)
530  {
531  case Width8Bits: ExtendedMode.TransferSize = B_8BITS; break;
532  case Width16Bits: ExtendedMode.TransferSize = B_16BITS; break;
533  case Width32Bits: ExtendedMode.TransferSize = B_32BITS; break;
534  default:
535  return FALSE;
536  }
537 
538  if (Controller == 1)
539  {
541  ExtendedMode.Byte);
542  }
543  else
544  {
546  ExtendedMode.Byte);
547  }
548  }
549  else
550  {
551  /*
552  * Validate setup for non-busmaster DMA adapter. Secondary controller
553  * supports only 16-bit transfers and main controller supports only
554  * 8-bit transfers. Anything else is invalid.
555  */
557  {
558  if ((Controller == 2) && (DeviceDescription->DmaWidth == Width16Bits))
559  {
560  AdapterObject->Width16Bits = TRUE;
561  }
562  else if ((Controller != 1) || (DeviceDescription->DmaWidth != Width8Bits))
563  {
564  return FALSE;
565  }
566  }
567  }
568 
569  DmaMode.Channel = AdapterObject->ChannelNumber;
571 
572  /*
573  * Set the DMA request mode.
574  *
575  * For (E)ISA bus master devices just unmask (enable) the DMA channel
576  * and set it to cascade mode. Otherwise just select the right one
577  * bases on the passed device description.
578  */
580  {
582  if (Controller == 1)
583  {
584  /* Set the Request Data */
586  WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte);
587 
588  /* Unmask DMA Channel */
589  WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->SingleMask,
590  AdapterObject->ChannelNumber | DMA_CLEARMASK);
591  }
592  else
593  {
594  /* Set the Request Data */
595  WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte);
596 
597  /* Unmask DMA Channel */
598  WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->SingleMask,
599  AdapterObject->ChannelNumber | DMA_CLEARMASK);
600  }
601  }
602  else
603  {
605  {
607  }
608  else
609  {
611  }
612  }
613 
614  AdapterObject->AdapterMode = DmaMode;
615 
616  return TRUE;
617 }
618 
619 #ifndef _MINIHAL_
620 
636 NTAPI
639 {
640  PADAPTER_OBJECT AdapterObject = NULL;
642  ULONG MapRegisters;
644  KIRQL OldIrql;
645 
646  /* Validate parameters in device description */
648 
649  /*
650  * See if we're going to use ISA/EISA DMA adapter. These adapters are
651  * special since they're reused.
652  *
653  * Also note that we check for channel number since there are only 8 DMA
654  * channels on ISA, so any request above this requires new adapter.
655  */
656  if (((DeviceDescription->InterfaceType == Eisa) ||
658  {
659  if (((DeviceDescription->InterfaceType == Isa) ||
662  {
663  EisaAdapter = FALSE;
664  }
665  else
666  {
667  EisaAdapter = TRUE;
668  }
669  }
670  else
671  {
672  EisaAdapter = FALSE;
673  }
674 
675  /*
676  * Disallow creating adapter for ISA/EISA DMA channel 4 since it's used
677  * for cascading the controllers and it's not available for software use.
678  */
679  if ((EisaAdapter) && (DeviceDescription->DmaChannel == 4)) return NULL;
680 
681  /*
682  * Calculate the number of map registers.
683  *
684  * - For EISA and PCI scatter/gather no map registers are needed.
685  * - For ISA slave scatter/gather one map register is needed.
686  * - For all other cases the number of map registers depends on
687  * DeviceDescription->MaximumLength.
688  */
693  {
694  MapRegisters = 0;
695  }
697  {
698  MapRegisters = 1;
699  }
700  else
701  {
702  /*
703  * In the equation below the additional map register added by
704  * the "+1" accounts for the case when a transfer does not start
705  * at a page-aligned address.
706  */
707  MapRegisters = BYTES_TO_PAGES(MaximumLength) + 1;
708  if (MapRegisters > 16) MapRegisters = 16;
709  }
710 
711  /*
712  * Acquire the DMA lock that is used to protect the EISA adapter array.
713  */
715 
716  /*
717  * Now we must get ahold of the adapter object. For first eight ISA/EISA
718  * channels there are static adapter objects that are reused and updated
719  * on succesive HalGetAdapter calls. In other cases a new adapter object
720  * is always created and it's to the DMA adapter list (HalpDmaAdapterList).
721  */
722  if (EisaAdapter)
723  {
724  AdapterObject = HalpEisaAdapter[DeviceDescription->DmaChannel];
725  if (AdapterObject)
726  {
727  if ((AdapterObject->NeedsMapRegisters) &&
728  (MapRegisters > AdapterObject->MapRegistersPerChannel))
729  {
730  AdapterObject->MapRegistersPerChannel = MapRegisters;
731  }
732  }
733  }
734 
735  if (AdapterObject == NULL)
736  {
737  AdapterObject = HalpDmaAllocateChildAdapter(MapRegisters, DeviceDescription);
738  if (AdapterObject == NULL)
739  {
740  KeSetEvent(&HalpDmaLock, 0, 0);
741  return NULL;
742  }
743 
744  if (EisaAdapter)
745  {
746  HalpEisaAdapter[DeviceDescription->DmaChannel] = AdapterObject;
747  }
748 
749  if (MapRegisters > 0)
750  {
751  AdapterObject->NeedsMapRegisters = TRUE;
752  AdapterObject->MapRegistersPerChannel = MapRegisters;
753  }
754  else
755  {
756  AdapterObject->NeedsMapRegisters = FALSE;
758  {
759  AdapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(MaximumLength) + 1;
760  }
761  else
762  {
763  AdapterObject->MapRegistersPerChannel = 1;
764  }
765  }
766  }
767 
768  /*
769  * Release the DMA lock. HalpEisaAdapter will no longer be touched,
770  * so we don't need it.
771  */
772  KeSetEvent(&HalpDmaLock, 0, 0);
773 
774  if (!EisaAdapter)
775  {
776  /* If it's not one of the static adapters, add it to the list */
778  InsertTailList(&HalpDmaAdapterList, &AdapterObject->AdapterList);
780  }
781 
782  /*
783  * Setup the values in the adapter object that are common for all
784  * types of buses.
785  */
787  {
788  AdapterObject->IgnoreCount = DeviceDescription->IgnoreCount;
789  }
790  else
791  {
792  AdapterObject->IgnoreCount = 0;
793  }
794 
795  AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
796  AdapterObject->Dma64BitAddresses = DeviceDescription->Dma64BitAddresses;
797  AdapterObject->ScatterGather = DeviceDescription->ScatterGather;
798  AdapterObject->MasterDevice = DeviceDescription->Master;
799  *NumberOfMapRegisters = AdapterObject->MapRegistersPerChannel;
800 
801  /*
802  * For non-(E)ISA adapters we have already done all the work. On the
803  * other hand for (E)ISA adapters we must still setup the DMA modes
804  * and prepare the controller.
805  */
806  if (EisaAdapter)
807  {
808  if (!HalpDmaInitializeEisaAdapter(AdapterObject, DeviceDescription))
809  {
810  ObDereferenceObject(AdapterObject);
811  return NULL;
812  }
813  }
814 
815  return AdapterObject;
816 }
817 
827 NTAPI
831 {
833 }
834 
843 VOID
844 NTAPI
846 {
847  KIRQL OldIrql;
848  if (AdapterObject->ChannelNumber == 0xFF)
849  {
851  RemoveEntryList(&AdapterObject->AdapterList);
853  }
854 
855  ObDereferenceObject(AdapterObject);
856 }
857 
883 PVOID
884 NTAPI
886  IN ULONG Length,
887  IN PPHYSICAL_ADDRESS LogicalAddress,
888  IN BOOLEAN CacheEnabled)
889 {
892  PHYSICAL_ADDRESS BoundryAddressMultiple;
894 
897  BoundryAddressMultiple.QuadPart = 0;
898 
899  /*
900  * For bus-master DMA devices the buffer mustn't cross 4Gb boundary. For
901  * slave DMA devices the 64Kb boundary mustn't be crossed since the
902  * controller wouldn't be able to handle it.
903  */
904  if (AdapterObject->MasterDevice)
905  {
906  BoundryAddressMultiple.HighPart = 1;
907  }
908  else
909  {
910  BoundryAddressMultiple.LowPart = 0x10000;
911  }
912 
916  BoundryAddressMultiple,
917  CacheEnabled ? MmCached :
918  MmNonCached);
919  if (VirtualAddress == NULL) return NULL;
920 
921  *LogicalAddress = MmGetPhysicalAddress(VirtualAddress);
922 
923  return VirtualAddress;
924 }
925 
935 VOID
936 NTAPI
938  IN ULONG Length,
939  IN PHYSICAL_ADDRESS LogicalAddress,
941  IN BOOLEAN CacheEnabled)
942 {
944  Length,
945  CacheEnabled ? MmCached : MmNonCached);
946 }
947 
948 typedef struct _SCATTER_GATHER_CONTEXT {
959 
960 
962 NTAPI
964  IN PIRP Irp,
966  IN PVOID Context)
967 {
968  PSCATTER_GATHER_CONTEXT AdapterControlContext = Context;
969  PADAPTER_OBJECT AdapterObject = AdapterControlContext->AdapterObject;
970  PSCATTER_GATHER_LIST ScatterGatherList;
972  ULONG ElementCount = 0, RemainingLength = AdapterControlContext->Length;
973  PUCHAR CurrentVa = AdapterControlContext->CurrentVa;
974 
975  /* Store the map register base for later in HalPutScatterGatherList */
976  AdapterControlContext->MapRegisterBase = MapRegisterBase;
977 
978  while (RemainingLength > 0 && ElementCount < MAX_SG_ELEMENTS)
979  {
980  TempElements[ElementCount].Length = RemainingLength;
981  TempElements[ElementCount].Reserved = 0;
982  TempElements[ElementCount].Address = IoMapTransfer(AdapterObject,
983  AdapterControlContext->Mdl,
985  CurrentVa + (AdapterControlContext->Length - RemainingLength),
986  &TempElements[ElementCount].Length,
987  AdapterControlContext->WriteToDevice);
988  if (TempElements[ElementCount].Length == 0)
989  break;
990 
991  DPRINT("Allocated one S/G element: 0x%I64u with length: 0x%x\n",
992  TempElements[ElementCount].Address.QuadPart,
993  TempElements[ElementCount].Length);
994 
995  ASSERT(TempElements[ElementCount].Length <= RemainingLength);
996  RemainingLength -= TempElements[ElementCount].Length;
997  ElementCount++;
998  }
999 
1000  if (RemainingLength > 0)
1001  {
1002  DPRINT1("Scatter/gather list construction failed!\n");
1003  return DeallocateObject;
1004  }
1005 
1006  ScatterGatherList = ExAllocatePoolWithTag(NonPagedPool,
1007  sizeof(SCATTER_GATHER_LIST) + sizeof(SCATTER_GATHER_ELEMENT) * ElementCount,
1008  TAG_DMA);
1009  ASSERT(ScatterGatherList);
1010 
1011  ScatterGatherList->NumberOfElements = ElementCount;
1012  ScatterGatherList->Reserved = (ULONG_PTR)AdapterControlContext;
1013  RtlCopyMemory(ScatterGatherList->Elements,
1014  TempElements,
1015  sizeof(SCATTER_GATHER_ELEMENT) * ElementCount);
1016 
1017  DPRINT("Initiating S/G DMA with %d element(s)\n", ElementCount);
1018 
1019  AdapterControlContext->AdapterListControlRoutine(DeviceObject,
1020  Irp,
1021  ScatterGatherList,
1022  AdapterControlContext->AdapterListControlContext);
1023 
1025 }
1026 
1055  NTSTATUS
1056  NTAPI
1059  IN PMDL Mdl,
1060  IN PVOID CurrentVa,
1061  IN ULONG Length,
1063  IN PVOID Context,
1064  IN BOOLEAN WriteToDevice)
1065 {
1066  PSCATTER_GATHER_CONTEXT AdapterControlContext;
1067 
1068  AdapterControlContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCATTER_GATHER_CONTEXT), TAG_DMA);
1069  if (!AdapterControlContext) return STATUS_INSUFFICIENT_RESOURCES;
1070 
1071  AdapterControlContext->AdapterObject = AdapterObject;
1072  AdapterControlContext->Mdl = Mdl;
1073  AdapterControlContext->CurrentVa = CurrentVa;
1074  AdapterControlContext->Length = Length;
1075  AdapterControlContext->MapRegisterCount = PAGE_ROUND_UP(Length) >> PAGE_SHIFT;
1076  AdapterControlContext->AdapterListControlRoutine = ExecutionRoutine;
1077  AdapterControlContext->AdapterListControlContext = Context;
1078  AdapterControlContext->WriteToDevice = WriteToDevice;
1079 
1080  AdapterControlContext->Wcb.DeviceObject = DeviceObject;
1081  AdapterControlContext->Wcb.DeviceContext = AdapterControlContext;
1082  AdapterControlContext->Wcb.CurrentIrp = DeviceObject->CurrentIrp;
1083 
1084  return HalAllocateAdapterChannel(AdapterObject,
1085  &AdapterControlContext->Wcb,
1086  AdapterControlContext->MapRegisterCount,
1088 }
1089 
1108  VOID
1109  NTAPI
1112  IN BOOLEAN WriteToDevice)
1113 {
1114  PSCATTER_GATHER_CONTEXT AdapterControlContext = (PSCATTER_GATHER_CONTEXT)ScatterGather->Reserved;
1115  ULONG i;
1116 
1117  for (i = 0; i < ScatterGather->NumberOfElements; i++)
1118  {
1119  IoFlushAdapterBuffers(AdapterObject,
1120  AdapterControlContext->Mdl,
1121  AdapterControlContext->MapRegisterBase,
1122  AdapterControlContext->CurrentVa,
1123  ScatterGather->Elements[i].Length,
1124  AdapterControlContext->WriteToDevice);
1125  AdapterControlContext->CurrentVa += ScatterGather->Elements[i].Length;
1126  }
1127 
1128  IoFreeMapRegisters(AdapterObject,
1129  AdapterControlContext->MapRegisterBase,
1130  AdapterControlContext->MapRegisterCount);
1131 
1132  DPRINT("S/G DMA has finished!\n");
1133 
1134  ExFreePoolWithTag(AdapterControlContext, TAG_DMA);
1136 }
1137 #endif
1138 
1147 ULONG
1148 NTAPI
1150 {
1151  return 1;
1152 }
1153 
1154 /*
1155  * @name HalReadDmaCounter
1156  *
1157  * Read DMA operation progress counter.
1158  *
1159  * @implemented
1160  */
1161 ULONG
1162 NTAPI
1164 {
1165  KIRQL OldIrql;
1166  ULONG Count, OldCount;
1167 
1168  ASSERT(!AdapterObject->MasterDevice);
1169 
1170  /*
1171  * Acquire the master adapter lock since we're going to mess with the
1172  * system DMA controller registers and we really don't want anyone
1173  * to do the same at the same time.
1174  */
1175  KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
1176 
1177  /* Send the request to the specific controller. */
1178  if (AdapterObject->AdapterNumber == 1)
1179  {
1180  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
1181 
1182  Count = 0xffff00;
1183  do
1184  {
1185  OldCount = Count;
1186 
1187  /* Send Reset */
1188  WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
1189 
1190  /* Read Count */
1191  Count = READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
1192  [AdapterObject->ChannelNumber].DmaBaseCount);
1193  Count |= READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
1194  [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
1195  } while (0xffff00 & (OldCount ^ Count));
1196  }
1197  else
1198  {
1199  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
1200 
1201  Count = 0xffff00;
1202  do
1203  {
1204  OldCount = Count;
1205 
1206  /* Send Reset */
1207  WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
1208 
1209  /* Read Count */
1210  Count = READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
1211  [AdapterObject->ChannelNumber].DmaBaseCount);
1212  Count |= READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
1213  [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
1214  } while (0xffff00 & (OldCount ^ Count));
1215  }
1216 
1217  KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
1218 
1219  Count++;
1220  Count &= 0xffff;
1221  if (AdapterObject->Width16Bits) Count *= 2;
1222 
1223  return Count;
1224 }
1225 
1226 #ifndef _MINIHAL_
1227 
1233 VOID
1234 NTAPI
1236 {
1238  KIRQL OldIrql;
1239  BOOLEAN Succeeded;
1240 
1241  /*
1242  * Try to allocate new map registers for the adapter.
1243  *
1244  * NOTE: The NT implementation actually tries to allocate more map
1245  * registers than needed as an optimization.
1246  */
1248  Succeeded = HalpGrowMapBuffers(WorkItem->AdapterObject->MasterAdapter,
1249  WorkItem->NumberOfMapRegisters << PAGE_SHIFT);
1250  KeSetEvent(&HalpDmaLock, 0, 0);
1251 
1252  if (Succeeded)
1253  {
1254  /*
1255  * Flush the adapter queue now that new map registers are ready. The
1256  * easiest way to do that is to call IoFreeMapRegisters to not free
1257  * any registers. Note that we use the magic (PVOID)2 map register
1258  * base to bypass the parameter checking.
1259  */
1261  IoFreeMapRegisters(WorkItem->AdapterObject, (PVOID)2, 0);
1263  }
1264 
1265  ExFreePool(WorkItem);
1266 }
1267 
1292 NTSTATUS
1293 NTAPI
1295  IN PWAIT_CONTEXT_BLOCK WaitContextBlock,
1298 {
1299  PADAPTER_OBJECT MasterAdapter;
1300  PGROW_WORK_ITEM WorkItem;
1301  ULONG Index = MAXULONG;
1302  ULONG Result;
1303  KIRQL OldIrql;
1304 
1306 
1307  /* Set up the wait context block in case we can't run right away. */
1308  WaitContextBlock->DeviceRoutine = ExecutionRoutine;
1309  WaitContextBlock->NumberOfMapRegisters = NumberOfMapRegisters;
1310 
1311  /* Returns true if queued, else returns false and sets the queue to busy */
1312  if (KeInsertDeviceQueue(&AdapterObject->ChannelWaitQueue,
1313  &WaitContextBlock->WaitQueueEntry))
1314  {
1315  return STATUS_SUCCESS;
1316  }
1317 
1318  MasterAdapter = AdapterObject->MasterAdapter;
1319 
1320  AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
1321  AdapterObject->CurrentWcb = WaitContextBlock;
1322 
1323  if ((NumberOfMapRegisters) && (AdapterObject->NeedsMapRegisters))
1324  {
1325  if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
1326  {
1327  AdapterObject->NumberOfMapRegisters = 0;
1328  IoFreeAdapterChannel(AdapterObject);
1330  }
1331 
1332  /*
1333  * Get the map registers. This is partly complicated by the fact
1334  * that new map registers can only be allocated at PASSIVE_LEVEL
1335  * and we're currently at DISPATCH_LEVEL. The following code has
1336  * two code paths:
1337  *
1338  * - If there is no adapter queued for map register allocation,
1339  * try to see if enough contiguous map registers are present.
1340  * In case they're we can just get them and proceed further.
1341  *
1342  * - If some adapter is already present in the queue we must
1343  * respect the order of adapters asking for map registers and
1344  * so the fast case described above can't take place.
1345  * This case is also entered if not enough coniguous map
1346  * registers are present.
1347  *
1348  * A work queue item is allocated and queued, the adapter is
1349  * also queued into the master adapter queue. The worker
1350  * routine does the job of allocating the map registers at
1351  * PASSIVE_LEVEL and calling the ExecutionRoutine.
1352  */
1353 
1354  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1355 
1356  if (IsListEmpty(&MasterAdapter->AdapterQueue))
1357  {
1358  Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters, NumberOfMapRegisters, 0);
1359  if (Index != MAXULONG)
1360  {
1361  AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1362  if (!AdapterObject->ScatterGather)
1363  {
1364  AdapterObject->MapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1365  }
1366  }
1367  }
1368 
1369  if (Index == MAXULONG)
1370  {
1371  InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
1372 
1374  sizeof(GROW_WORK_ITEM),
1375  TAG_DMA);
1376  if (WorkItem)
1377  {
1379  WorkItem->AdapterObject = AdapterObject;
1381 
1383  }
1384 
1385  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1386 
1387  return STATUS_SUCCESS;
1388  }
1389 
1390  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1391  }
1392  else
1393  {
1394  AdapterObject->MapRegisterBase = NULL;
1395  AdapterObject->NumberOfMapRegisters = 0;
1396  }
1397 
1398  AdapterObject->CurrentWcb = WaitContextBlock;
1399 
1400  Result = ExecutionRoutine(WaitContextBlock->DeviceObject,
1401  WaitContextBlock->CurrentIrp,
1402  AdapterObject->MapRegisterBase,
1403  WaitContextBlock->DeviceContext);
1404 
1405  /*
1406  * Possible return values:
1407  *
1408  * - KeepObject
1409  * Don't free any resources, the ADAPTER_OBJECT is still in use and
1410  * the caller will call IoFreeAdapterChannel later.
1411  *
1412  * - DeallocateObject
1413  * Deallocate the map registers and release the ADAPTER_OBJECT, so
1414  * someone else can use it.
1415  *
1416  * - DeallocateObjectKeepRegisters
1417  * Release the ADAPTER_OBJECT, but hang on to the map registers. The
1418  * client will later call IoFreeMapRegisters.
1419  *
1420  * NOTE:
1421  * IoFreeAdapterChannel runs the queue, so it must be called unless
1422  * the adapter object is not to be freed.
1423  */
1424  if (Result == DeallocateObject)
1425  {
1426  IoFreeAdapterChannel(AdapterObject);
1427  }
1429  {
1430  AdapterObject->NumberOfMapRegisters = 0;
1431  IoFreeAdapterChannel(AdapterObject);
1432  }
1433 
1434  return STATUS_SUCCESS;
1435 }
1436 
1455 VOID
1456 NTAPI
1458 {
1459  PADAPTER_OBJECT MasterAdapter;
1461  PWAIT_CONTEXT_BLOCK WaitContextBlock;
1462  ULONG Index = MAXULONG;
1463  ULONG Result;
1464  KIRQL OldIrql;
1465 
1466  MasterAdapter = AdapterObject->MasterAdapter;
1467 
1468  for (;;)
1469  {
1470  /*
1471  * To keep map registers, call here with AdapterObject->
1472  * NumberOfMapRegisters set to zero. This trick is used in
1473  * HalAllocateAdapterChannel for example.
1474  */
1475  if (AdapterObject->NumberOfMapRegisters)
1476  {
1477  IoFreeMapRegisters(AdapterObject,
1478  AdapterObject->MapRegisterBase,
1479  AdapterObject->NumberOfMapRegisters);
1480  }
1481 
1482  DeviceQueueEntry = KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue);
1483  if (!DeviceQueueEntry) break;
1484 
1485  WaitContextBlock = CONTAINING_RECORD(DeviceQueueEntry,
1487  WaitQueueEntry);
1488 
1489  AdapterObject->CurrentWcb = WaitContextBlock;
1490  AdapterObject->NumberOfMapRegisters = WaitContextBlock->NumberOfMapRegisters;
1491 
1492  if ((WaitContextBlock->NumberOfMapRegisters) && (AdapterObject->MasterAdapter))
1493  {
1494  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1495 
1496  if (IsListEmpty(&MasterAdapter->AdapterQueue))
1497  {
1498  Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
1499  WaitContextBlock->NumberOfMapRegisters,
1500  0);
1501  if (Index != MAXULONG)
1502  {
1503  AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1504  if (!AdapterObject->ScatterGather)
1505  {
1506  AdapterObject->MapRegisterBase =(PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1507  }
1508  }
1509  }
1510 
1511  if (Index == MAXULONG)
1512  {
1513  InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
1514  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1515  break;
1516  }
1517 
1518  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1519  }
1520  else
1521  {
1522  AdapterObject->MapRegisterBase = NULL;
1523  AdapterObject->NumberOfMapRegisters = 0;
1524  }
1525 
1526  /* Call the adapter control routine. */
1527  Result = ((PDRIVER_CONTROL)WaitContextBlock->DeviceRoutine)(WaitContextBlock->DeviceObject,
1528  WaitContextBlock->CurrentIrp,
1529  AdapterObject->MapRegisterBase,
1530  WaitContextBlock->DeviceContext);
1531  switch (Result)
1532  {
1533  case KeepObject:
1534  /*
1535  * We're done until the caller manually calls IoFreeAdapterChannel
1536  * or IoFreeMapRegisters.
1537  */
1538  return;
1539 
1541  /*
1542  * Hide the map registers so they aren't deallocated next time
1543  * around.
1544  */
1545  AdapterObject->NumberOfMapRegisters = 0;
1546  break;
1547 
1548  default:
1549  break;
1550  }
1551  }
1552 }
1553 
1568 VOID
1569 NTAPI
1573 {
1574  PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
1575  PLIST_ENTRY ListEntry;
1576  KIRQL OldIrql;
1577  ULONG Index;
1578  ULONG Result;
1579 
1581 
1582  if (!(MasterAdapter) || !(MapRegisterBase)) return;
1583 
1584  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1585 
1586  if (NumberOfMapRegisters != 0)
1587  {
1588  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1589 
1590  RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1591  RtlClearBits(MasterAdapter->MapRegisters,
1592  (ULONG)(RealMapRegisterBase - MasterAdapter->MapRegisterBase),
1594  }
1595 
1596  /*
1597  * Now that we freed few map registers it's time to look at the master
1598  * adapter queue and see if there is someone waiting for map registers.
1599  */
1600  while (!IsListEmpty(&MasterAdapter->AdapterQueue))
1601  {
1602  ListEntry = RemoveHeadList(&MasterAdapter->AdapterQueue);
1603  AdapterObject = CONTAINING_RECORD(ListEntry, struct _ADAPTER_OBJECT, AdapterQueue);
1604 
1605  Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
1606  AdapterObject->NumberOfMapRegisters,
1607  0);
1608  if (Index == MAXULONG)
1609  {
1610  InsertHeadList(&MasterAdapter->AdapterQueue, ListEntry);
1611  break;
1612  }
1613 
1614  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1615 
1616  AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1617  if (!AdapterObject->ScatterGather)
1618  {
1619  AdapterObject->MapRegisterBase =
1620  (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1621  }
1622 
1623  Result = ((PDRIVER_CONTROL)AdapterObject->CurrentWcb->DeviceRoutine)(AdapterObject->CurrentWcb->DeviceObject,
1624  AdapterObject->CurrentWcb->CurrentIrp,
1625  AdapterObject->MapRegisterBase,
1626  AdapterObject->CurrentWcb->DeviceContext);
1627  switch (Result)
1628  {
1630  AdapterObject->NumberOfMapRegisters = 0;
1631  /* fall through */
1632 
1633  case DeallocateObject:
1634  if (AdapterObject->NumberOfMapRegisters)
1635  {
1636  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1637  RtlClearBits(MasterAdapter->MapRegisters,
1638  (ULONG)(AdapterObject->MapRegisterBase -
1639  MasterAdapter->MapRegisterBase),
1640  AdapterObject->NumberOfMapRegisters);
1641  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1642  }
1643 
1644  IoFreeAdapterChannel(AdapterObject);
1645  break;
1646 
1647  default:
1648  break;
1649  }
1650 
1651  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1652  }
1653 
1654  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1655 }
1656 
1664 VOID
1665 NTAPI
1668  IN PVOID CurrentVa,
1669  IN ULONG Length,
1670  IN BOOLEAN WriteToDevice)
1671 {
1672  ULONG CurrentLength;
1673  ULONG_PTR CurrentAddress;
1674  ULONG ByteOffset;
1676 
1678  if (!VirtualAddress)
1679  {
1680  /*
1681  * NOTE: On real NT a mechanism with reserved pages is implemented
1682  * to handle this case in a slow, but graceful non-fatal way.
1683  */
1684  KeBugCheckEx(HAL_MEMORY_ALLOCATION, PAGE_SIZE, 0, (ULONG_PTR)__FILE__, 0);
1685  }
1686 
1687  CurrentAddress = (ULONG_PTR)VirtualAddress +
1688  (ULONG_PTR)CurrentVa -
1690 
1691  while (Length > 0)
1692  {
1693  ByteOffset = BYTE_OFFSET(CurrentAddress);
1694  CurrentLength = PAGE_SIZE - ByteOffset;
1695  if (CurrentLength > Length) CurrentLength = Length;
1696 
1697  if (WriteToDevice)
1698  {
1699  RtlCopyMemory((PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
1700  (PVOID)CurrentAddress,
1701  CurrentLength);
1702  }
1703  else
1704  {
1705  RtlCopyMemory((PVOID)CurrentAddress,
1706  (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
1707  CurrentLength);
1708  }
1709 
1710  Length -= CurrentLength;
1711  CurrentAddress += CurrentLength;
1712  MapRegisterBase++;
1713  }
1714 }
1715 
1747 BOOLEAN
1748 NTAPI
1750  IN PMDL Mdl,
1752  IN PVOID CurrentVa,
1753  IN ULONG Length,
1754  IN BOOLEAN WriteToDevice)
1755 {
1756  BOOLEAN SlaveDma = FALSE;
1757  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1760  PPFN_NUMBER MdlPagesPtr;
1761 
1762  /* Sanity checks */
1764  ASSERT(AdapterObject);
1765 
1766  if (!AdapterObject->MasterDevice)
1767  {
1768  /* Mask out (disable) the DMA channel. */
1769  if (AdapterObject->AdapterNumber == 1)
1770  {
1771  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
1772  WRITE_PORT_UCHAR(&DmaControl1->SingleMask,
1773  AdapterObject->ChannelNumber | DMA_SETMASK);
1774  }
1775  else
1776  {
1777  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
1778  WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
1779  AdapterObject->ChannelNumber | DMA_SETMASK);
1780  }
1781  SlaveDma = TRUE;
1782  }
1783 
1784  /* This can happen if the device supports hardware scatter/gather. */
1785  if (MapRegisterBase == NULL) return TRUE;
1786 
1787  RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1788 
1789  if (!WriteToDevice)
1790  {
1792  {
1793  if (RealMapRegisterBase->Counter != MAXULONG)
1794  {
1795  if ((SlaveDma) && !(AdapterObject->IgnoreCount))
1796  {
1797  Length -= HalReadDmaCounter(AdapterObject);
1798  }
1799  }
1800  HalpCopyBufferMap(Mdl,
1801  RealMapRegisterBase,
1802  CurrentVa,
1803  Length,
1804  FALSE);
1805  }
1806  else
1807  {
1808  MdlPagesPtr = MmGetMdlPfnArray(Mdl);
1809  MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
1810 
1811  PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
1812  PhysicalAddress.QuadPart += BYTE_OFFSET(CurrentVa);
1813 
1816  {
1817  HalpCopyBufferMap(Mdl,
1818  RealMapRegisterBase,
1819  CurrentVa,
1820  Length,
1821  FALSE);
1822  }
1823  }
1824  }
1825 
1826  RealMapRegisterBase->Counter = 0;
1827 
1828  return TRUE;
1829 }
1830 
1863 NTAPI
1865  IN PMDL Mdl,
1867  IN PVOID CurrentVa,
1868  IN OUT PULONG Length,
1869  IN BOOLEAN WriteToDevice)
1870 {
1871  PPFN_NUMBER MdlPagesPtr;
1872  PFN_NUMBER MdlPage1, MdlPage2;
1873  ULONG ByteOffset;
1874  ULONG TransferOffset;
1875  ULONG TransferLength;
1876  BOOLEAN UseMapRegisters;
1877  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1880  ULONG Counter;
1881  DMA_MODE AdapterMode;
1882  KIRQL OldIrql;
1883 
1884  /*
1885  * Precalculate some values that are used in all cases.
1886  *
1887  * ByteOffset is offset inside the page at which the transfer starts.
1888  * MdlPagesPtr is pointer inside the MDL page chain at the page where the
1889  * transfer start.
1890  * PhysicalAddress is physical address corresponding to the transfer
1891  * start page and offset.
1892  * TransferLength is the initial length of the transfer, which is reminder
1893  * of the first page. The actual value is calculated below.
1894  *
1895  * Note that all the variables can change during the processing which
1896  * takes place below. These are just initial values.
1897  */
1898  ByteOffset = BYTE_OFFSET(CurrentVa);
1899 
1900  MdlPagesPtr = MmGetMdlPfnArray(Mdl);
1901  MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
1902 
1903  PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
1905 
1906  TransferLength = PAGE_SIZE - ByteOffset;
1907 
1908  /*
1909  * Special case for bus master adapters with S/G support. We can directly
1910  * use the buffer specified by the MDL, so not much work has to be done.
1911  *
1912  * Just return the passed VA's corresponding physical address and update
1913  * length to the number of physically contiguous bytes found. Also
1914  * pages crossing the 4Gb boundary aren't considered physically contiguous.
1915  */
1916  if (MapRegisterBase == NULL)
1917  {
1918  while (TransferLength < *Length)
1919  {
1920  MdlPage1 = *MdlPagesPtr;
1921  MdlPage2 = *(MdlPagesPtr + 1);
1922  if (MdlPage1 + 1 != MdlPage2) break;
1923  if ((MdlPage1 ^ MdlPage2) & ~0xFFFFF) break;
1924  TransferLength += PAGE_SIZE;
1925  MdlPagesPtr++;
1926  }
1927 
1928  if (TransferLength < *Length) *Length = TransferLength;
1929 
1930  return PhysicalAddress;
1931  }
1932 
1933  /*
1934  * The code below applies to slave DMA adapters and bus master adapters
1935  * without hardward S/G support.
1936  */
1937  RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1938 
1939  /*
1940  * Try to calculate the size of the transfer. We can only transfer
1941  * pages that are physically contiguous and that don't cross the
1942  * 64Kb boundary (this limitation applies only for ISA controllers).
1943  */
1944  while (TransferLength < *Length)
1945  {
1946  MdlPage1 = *MdlPagesPtr;
1947  MdlPage2 = *(MdlPagesPtr + 1);
1948  if (MdlPage1 + 1 != MdlPage2) break;
1949  if (!HalpEisaDma && ((MdlPage1 ^ MdlPage2) & ~0xF)) break;
1950  TransferLength += PAGE_SIZE;
1951  MdlPagesPtr++;
1952  }
1953 
1954  if (TransferLength > *Length) TransferLength = *Length;
1955 
1956  /*
1957  * If we're about to simulate software S/G and not all the pages are
1958  * physically contiguous then we must use the map registers to store
1959  * the data and allow the whole transfer to proceed at once.
1960  */
1961  if (((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG) && (TransferLength < *Length))
1962  {
1963  UseMapRegisters = TRUE;
1964  PhysicalAddress = RealMapRegisterBase->PhysicalAddress;
1966  TransferLength = *Length;
1967  RealMapRegisterBase->Counter = MAXULONG;
1968  Counter = 0;
1969  }
1970  else
1971  {
1972  /*
1973  * This is ordinary DMA transfer, so just update the progress
1974  * counters. These are used by IoFlushAdapterBuffers to track
1975  * the transfer progress.
1976  */
1977  UseMapRegisters = FALSE;
1978  Counter = RealMapRegisterBase->Counter;
1979  RealMapRegisterBase->Counter += BYTES_TO_PAGES(ByteOffset + TransferLength);
1980 
1981  /*
1982  * Check if the buffer doesn't exceed the highest physical address
1983  * limit of the device. In that case we must use the map registers to
1984  * store the data.
1985  */
1987  if ((PhysicalAddress.QuadPart + TransferLength) > HighestAcceptableAddress.QuadPart)
1988  {
1989  UseMapRegisters = TRUE;
1990  PhysicalAddress = RealMapRegisterBase[Counter].PhysicalAddress;
1993  {
1994  RealMapRegisterBase->Counter = MAXULONG;
1995  Counter = 0;
1996  }
1997  }
1998  }
1999 
2000  /*
2001  * If we decided to use the map registers (see above) and we're about
2002  * to transfer data to the device then copy the buffers into the map
2003  * register memory.
2004  */
2005  if ((UseMapRegisters) && (WriteToDevice))
2006  {
2007  HalpCopyBufferMap(Mdl,
2008  RealMapRegisterBase + Counter,
2009  CurrentVa,
2010  TransferLength,
2011  WriteToDevice);
2012  }
2013 
2014  /*
2015  * Return the length of transfer that actually takes place.
2016  */
2017  *Length = TransferLength;
2018 
2019  /*
2020  * If we're doing slave (system) DMA then program the (E)ISA controller
2021  * to actually start the transfer.
2022  */
2023  if ((AdapterObject) && !(AdapterObject->MasterDevice))
2024  {
2025  AdapterMode = AdapterObject->AdapterMode;
2026 
2027  if (WriteToDevice)
2028  {
2029  AdapterMode.TransferType = WRITE_TRANSFER;
2030  }
2031  else
2032  {
2033  AdapterMode.TransferType = READ_TRANSFER;
2034  if (AdapterObject->IgnoreCount)
2035  {
2036  RtlZeroMemory((PUCHAR)RealMapRegisterBase[Counter].VirtualAddress + ByteOffset,
2037  TransferLength);
2038  }
2039  }
2040 
2041  TransferOffset = PhysicalAddress.LowPart & 0xFFFF;
2042  if (AdapterObject->Width16Bits)
2043  {
2044  TransferLength >>= 1;
2045  TransferOffset >>= 1;
2046  }
2047 
2048  KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
2049 
2050  if (AdapterObject->AdapterNumber == 1)
2051  {
2052  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
2053 
2054  /* Reset Register */
2055  WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
2056 
2057  /* Set the Mode */
2058  WRITE_PORT_UCHAR(&DmaControl1->Mode, AdapterMode.Byte);
2059 
2060  /* Set the Offset Register */
2061  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2062  (UCHAR)(TransferOffset));
2063  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2064  (UCHAR)(TransferOffset >> 8));
2065 
2066  /* Set the Page Register */
2067  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
2068  (UCHAR)(PhysicalAddress.LowPart >> 16));
2069  if (HalpEisaDma)
2070  {
2071  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
2072  0);
2073  }
2074 
2075  /* Set the Length */
2076  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2077  (UCHAR)(TransferLength - 1));
2078  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2079  (UCHAR)((TransferLength - 1) >> 8));
2080 
2081  /* Unmask the Channel */
2082  WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK);
2083  }
2084  else
2085  {
2086  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
2087 
2088  /* Reset Register */
2089  WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
2090 
2091  /* Set the Mode */
2092  WRITE_PORT_UCHAR(&DmaControl2->Mode, AdapterMode.Byte);
2093 
2094  /* Set the Offset Register */
2095  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2096  (UCHAR)(TransferOffset));
2097  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2098  (UCHAR)(TransferOffset >> 8));
2099 
2100  /* Set the Page Register */
2101  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
2102  (UCHAR)(PhysicalAddress.u.LowPart >> 16));
2103  if (HalpEisaDma)
2104  {
2105  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
2106  0);
2107  }
2108 
2109  /* Set the Length */
2110  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2111  (UCHAR)(TransferLength - 1));
2112  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2113  (UCHAR)((TransferLength - 1) >> 8));
2114 
2115  /* Unmask the Channel */
2116  WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
2117  AdapterObject->ChannelNumber | DMA_CLEARMASK);
2118  }
2119 
2120  KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
2121  }
2122 
2123  /*
2124  * Return physical address of the buffer with data that is used for the
2125  * transfer. It can either point inside the Mdl that was passed by the
2126  * caller or into the map registers if the Mdl buffer can't be used
2127  * directly.
2128  */
2129  return PhysicalAddress;
2130 }
2131 #endif
2132 
2138 BOOLEAN
2139 NTAPI
2141  IN ULONG Length,
2142  IN PHYSICAL_ADDRESS LogicalAddress,
2144 {
2145  /* Function always returns true */
2146  return TRUE;
2147 }
2148 
2149 /*
2150  * @implemented
2151  */
2152 PVOID
2153 NTAPI
2156 {
2157  PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
2158  ULONG MapRegisterNumber;
2159 
2160  /* Check if it needs map registers */
2161  if (AdapterObject->NeedsMapRegisters)
2162  {
2163  /* Check if we have enough */
2164  if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
2165  {
2166  /* We don't, fail */
2167  AdapterObject->NumberOfMapRegisters = 0;
2168  return NULL;
2169  }
2170 
2171  /* Try to find free map registers */
2172  MapRegisterNumber = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
2174  0);
2175 
2176  /* Check if nothing was found */
2177  if (MapRegisterNumber == MAXULONG)
2178  {
2179  /* No free registers found, so use the base registers */
2180  RtlSetBits(MasterAdapter->MapRegisters,
2181  0,
2183  MapRegisterNumber = 0;
2184  }
2185 
2186  /* Calculate the new base */
2187  AdapterObject->MapRegisterBase =
2188  (PROS_MAP_REGISTER_ENTRY)(MasterAdapter->MapRegisterBase +
2189  MapRegisterNumber);
2190 
2191  /* Check if scatter gather isn't supported */
2192  if (!AdapterObject->ScatterGather)
2193  {
2194  /* Set the flag */
2195  AdapterObject->MapRegisterBase =
2197  ((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
2198  }
2199  }
2200  else
2201  {
2202  AdapterObject->MapRegisterBase = NULL;
2203  AdapterObject->NumberOfMapRegisters = 0;
2204  }
2205 
2206  /* Return the base */
2207  return AdapterObject->MapRegisterBase;
2208 }
2209 
2210 /* 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:2202
#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:953
#define MAX_SG_ELEMENTS
Definition: dma.c:84
UCHAR DmaBaseAddress
Definition: haldma.h:183
DMA1_ADDRESS_COUNT DmaAddressCount[4]
Definition: haldma.h:197
#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:2282
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
#define READ_PORT_UCHAR(p)
Definition: pc98vid.h:21
_In_ PIRP Irp
Definition: csq.h:116
#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
PFREE_MAP_REGISTERS FreeMapRegisters
Definition: iotypes.h:2324
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)
DMA_SPEED DmaSpeed
Definition: iotypes.h:2045
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:2225
PVOID VirtualAddress
Definition: haldma.h:314
PHYSICAL_ADDRESS Address
Definition: iotypes.h:2072
VOID NTAPI KeInitializeDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
Definition: devqueue.c:22
#define TypeA
Definition: nslookup.h:13
struct _LARGE_INTEGER::@2263 u
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1173
PDRIVER_CONTROL DeviceRoutine
Definition: iotypes.h:198
#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:955
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:2234
static KEVENT HalpDmaLock
Definition: dma.c:87
WORK_QUEUE_ITEM WorkQueueItem
Definition: haldma.h:362
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:1110
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:2253
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:2217
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
#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
UCHAR Channel
Definition: haldma.h:93
PMAP_TRANSFER MapTransfer
Definition: iotypes.h:2325
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:2038
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:2103
#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:2037
VOID NTAPI HalpGrowMapBufferWorker(PVOID DeferredContext)
Definition: dma.c:1005
#define B_16BITS
Definition: haldma.h:146
PFLUSH_ADAPTER_BUFFERS FlushAdapterBuffers
Definition: iotypes.h:2322
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
BOOLEAN Dma64BitAddresses
Definition: iotypes.h:2040
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:1057
_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:2244
PADAPTER_OBJECT AdapterObject
Definition: dma.c:949
#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:2323
#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:2035
BOOLEAN ScatterGather
Definition: iotypes.h:2034
#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:2044
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:1065
unsigned char UCHAR
Definition: xmlstorage.h:181
Status
Definition: gdiplustypes.h:24
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:20
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
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:2209
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:119
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:2198
WAIT_CONTEXT_BLOCK Wcb
Definition: dma.c:957
BOOLEAN NTAPI HalpDmaInitializeEisaAdapter(PADAPTER_OBJECT AdapterObject, PDEVICE_DESCRIPTION DeviceDescription)
Definition: dma.c:461
static LIST_ENTRY HalpDmaAdapterList
Definition: dma.c:89
struct _DMA_OPERATIONS DMA_OPERATIONS
VOID NTAPI HalPutDmaAdapter(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:35
#define MAXULONG
Definition: typedefs.h:251
#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:954
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: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:2321
#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:2268
ULONG(NTAPI * PREAD_DMA_COUNTER)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2257
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:2266
VOID(NTAPI * PFREE_MAP_REGISTERS)(_In_ PDMA_ADAPTER DmaAdapter, PVOID MapRegisterBase, ULONG NumberOfMapRegisters)
Definition: iotypes.h:2238
#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:2029
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:2043
_In_ PDEVICE_OBJECT _In_ ULONG _In_ PDRIVER_CONTROL ExecutionRoutine
Definition: iofuncs.h:1393
PVOID AdapterListControlContext
Definition: dma.c:954
struct _SCATTER_GATHER_LIST * PSCATTER_GATHER_LIST
Definition: iotypes.h:2103
#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
#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:685
DRIVER_CONTROL * PDRIVER_CONTROL
Definition: iotypes.h:194
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:963
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
_Inout_ PKDEVICE_QUEUE_ENTRY DeviceQueueEntry
Definition: kefuncs.h:339
#define DEVICE_DESCRIPTION_VERSION1
Definition: iotypes.h:2028
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)
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:2271
PADAPTER_OBJECT NTAPI HalpDmaAllocateMasterAdapter(VOID)
Definition: dma.c:332
BOOLEAN AutoInitialize
Definition: iotypes.h:2036
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:956
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