ReactOS 0.4.15-dev-7788-g1ad9096
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
93static 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_
106NTAPI
108 IN PADAPTER_OBJECT AdapterObject,
110 IN PVOID CurrentVa,
112 OUT PULONG ScatterGatherListSize,
113 OUT PULONG pNumberOfMapRegisters);
114
116NTAPI
118 IN PADAPTER_OBJECT AdapterObject,
120 IN PMDL Mdl,
121 IN PVOID CurrentVa,
126 IN PVOID ScatterGatherBuffer,
127 IN ULONG ScatterGatherLength);
128
130NTAPI
132 IN PDMA_ADAPTER DmaAdapter,
134 IN PMDL OriginalMdl,
136
137
139 sizeof(DMA_OPERATIONS),
143 NULL, /* Initialized in HalpInitDma() */
144 NULL, /* Initialized in HalpInitDma() */
145 NULL, /* Initialized in HalpInitDma() */
146 NULL, /* Initialized in HalpInitDma() */
147 NULL, /* Initialized in HalpInitDma() */
155};
156#endif
157
158#define MAX_MAP_REGISTERS 64
159
160#define TAG_DMA ' AMD'
161
162/* FUNCTIONS *****************************************************************/
163
164#if defined(SARCH_PC98)
165/*
166 * Disable I/O for safety.
167 * FIXME: Add support for PC-98 DMA controllers.
168 */
169#undef WRITE_PORT_UCHAR
170#undef READ_PORT_UCHAR
171
172#define WRITE_PORT_UCHAR(Port, Data) \
173 do { \
174 UNIMPLEMENTED; \
175 (Port); \
176 (Data); \
177 } while (0)
178
179#define READ_PORT_UCHAR(Port) 0x00
180#endif
181
182#ifndef _MINIHAL_
183CODE_SEG("INIT")
184VOID
186{
187 /*
188 * Initialize the DMA Operation table
189 */
195
197 {
198 /*
199 * Check if Extended DMA is available. We're just going to do a random
200 * read and write.
201 */
202 WRITE_PORT_UCHAR(UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2)), 0x2A);
203 if (READ_PORT_UCHAR(UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2))) == 0x2A)
204 {
205 DPRINT1("Machine supports EISA DMA. Bus type: %lu\n", HalpBusType);
207 }
208 }
209
210 /*
211 * Intialize all the global variables and allocate master adapter with
212 * first map buffers.
213 */
218
219 /*
220 * Setup the HalDispatchTable callback for creating PnP DMA adapters. It's
221 * used by IoGetDmaAdapter in the kernel.
222 */
224}
225#endif
226
234NTAPI
236{
237 PHYSICAL_ADDRESS HighestAddress;
238
239 if (AdapterObject->MasterDevice)
240 {
241 if (AdapterObject->Dma64BitAddresses)
242 {
243 HighestAddress.QuadPart = 0xFFFFFFFFFFFFFFFFULL;
244 return HighestAddress;
245 }
246 else if (AdapterObject->Dma32BitAddresses)
247 {
248 HighestAddress.QuadPart = 0xFFFFFFFF;
249 return HighestAddress;
250 }
251 }
252
253 HighestAddress.QuadPart = 0xFFFFFF;
254 return HighestAddress;
255}
256
257#ifndef _MINIHAL_
270NTAPI
272 IN ULONG SizeOfMapBuffers)
273{
278 PHYSICAL_ADDRESS BoundryAddressMultiple;
281
282 /* Check if enough map register slots are available. */
283 MapRegisterCount = BYTES_TO_PAGES(SizeOfMapBuffers);
284 if (MapRegisterCount + AdapterObject->NumberOfMapRegisters > MAX_MAP_REGISTERS)
285 {
286 DPRINT("No more map register slots available! (Current: %d | Requested: %d | Limit: %d)\n",
287 AdapterObject->NumberOfMapRegisters,
290 return FALSE;
291 }
292
293 /*
294 * Allocate memory for the new map registers. For 32-bit adapters we use
295 * two passes in order not to waste scare resource (low memory).
296 */
299 LowestAcceptableAddress.LowPart = HighestAcceptableAddress.LowPart == 0xFFFFFFFF ? 0x1000000 : 0;
300 BoundryAddressMultiple.QuadPart = 0;
301
305 BoundryAddressMultiple,
308 {
313 BoundryAddressMultiple,
315 }
316
317 if (!VirtualAddress) return FALSE;
318
320
321 /*
322 * All the following must be done with the master adapter lock held
323 * to prevent corruption.
324 */
325 KeAcquireSpinLock(&AdapterObject->SpinLock, &OldIrql);
326
327 /*
328 * Setup map register entries for the buffer allocated. Each entry has
329 * a virtual and physical address and corresponds to PAGE_SIZE large
330 * buffer.
331 */
332 if (MapRegisterCount > 0)
333 {
334 PROS_MAP_REGISTER_ENTRY CurrentEntry, PreviousEntry;
335
336 CurrentEntry = AdapterObject->MapRegisterBase + AdapterObject->NumberOfMapRegisters;
337 do
338 {
339 /*
340 * Leave one entry free for every non-contiguous memory region
341 * in the map register bitmap. This ensures that we can search
342 * using RtlFindClearBits for contiguous map register regions.
343 *
344 * Also for non-EISA DMA leave one free entry for every 64Kb
345 * break, because the DMA controller can handle only coniguous
346 * 64Kb regions.
347 */
348 if (CurrentEntry != AdapterObject->MapRegisterBase)
349 {
350 PreviousEntry = CurrentEntry - 1;
351 if ((PreviousEntry->PhysicalAddress.LowPart + PAGE_SIZE) == PhysicalAddress.LowPart)
352 {
353 if (!HalpEisaDma)
354 {
355 if ((PreviousEntry->PhysicalAddress.LowPart ^ PhysicalAddress.LowPart) & 0xFFFF0000)
356 {
357 CurrentEntry++;
358 AdapterObject->NumberOfMapRegisters++;
359 }
360 }
361 }
362 else
363 {
364 CurrentEntry++;
365 AdapterObject->NumberOfMapRegisters++;
366 }
367 }
368
369 RtlClearBit(AdapterObject->MapRegisters,
370 (ULONG)(CurrentEntry - AdapterObject->MapRegisterBase));
371 CurrentEntry->VirtualAddress = VirtualAddress;
372 CurrentEntry->PhysicalAddress = PhysicalAddress;
373
376
377 CurrentEntry++;
378 AdapterObject->NumberOfMapRegisters++;
380 } while (MapRegisterCount);
381 }
382
383 KeReleaseSpinLock(&AdapterObject->SpinLock, OldIrql);
384
385 return TRUE;
386}
387
397NTAPI
399{
400 PADAPTER_OBJECT MasterAdapter;
401 ULONG Size, SizeOfBitmap;
402
403 SizeOfBitmap = MAX_MAP_REGISTERS;
404 Size = sizeof(ADAPTER_OBJECT);
405 Size += sizeof(RTL_BITMAP);
406 Size += (SizeOfBitmap + 7) >> 3;
407
409 if (!MasterAdapter) return NULL;
410
411 RtlZeroMemory(MasterAdapter, Size);
412
413 KeInitializeSpinLock(&MasterAdapter->SpinLock);
414 InitializeListHead(&MasterAdapter->AdapterQueue);
415
416 MasterAdapter->MapRegisters = (PVOID)(MasterAdapter + 1);
417 RtlInitializeBitMap(MasterAdapter->MapRegisters,
418 (PULONG)(MasterAdapter->MapRegisters + 1),
419 SizeOfBitmap);
420 RtlSetAllBits(MasterAdapter->MapRegisters);
421 MasterAdapter->NumberOfMapRegisters = 0;
422 MasterAdapter->CommittedMapRegisters = 0;
423
424 MasterAdapter->MapRegisterBase = ExAllocatePoolWithTag(NonPagedPool,
425 SizeOfBitmap *
427 TAG_DMA);
428 if (!MasterAdapter->MapRegisterBase)
429 {
430 ExFreePool(MasterAdapter);
431 return NULL;
432 }
433
434 RtlZeroMemory(MasterAdapter->MapRegisterBase,
435 SizeOfBitmap * sizeof(ROS_MAP_REGISTER_ENTRY));
436 if (!HalpGrowMapBuffers(MasterAdapter, 0x10000))
437 {
438 ExFreePool(MasterAdapter);
439 return NULL;
440 }
441
442 return MasterAdapter;
443}
444
454NTAPI
457{
458 PADAPTER_OBJECT AdapterObject;
462
464 NULL,
466 NULL,
467 NULL);
468
473 NULL,
474 sizeof(ADAPTER_OBJECT),
475 0,
476 0,
477 (PVOID)&AdapterObject);
478 if (!NT_SUCCESS(Status)) return NULL;
479
480 RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT));
481
482 Status = ObInsertObject(AdapterObject,
483 NULL,
485 0,
486 NULL,
487 &Handle);
488 if (!NT_SUCCESS(Status)) return NULL;
489
490 ObReferenceObject(AdapterObject);
491
493
494 AdapterObject->DmaHeader.Version = (USHORT)DeviceDescription->Version;
495 AdapterObject->DmaHeader.Size = sizeof(ADAPTER_OBJECT);
496 AdapterObject->DmaHeader.DmaOperations = &HalpDmaOperations;
497 AdapterObject->MapRegistersPerChannel = 1;
498 AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
499 AdapterObject->ChannelNumber = 0xFF;
500 AdapterObject->MasterAdapter = HalpMasterAdapter;
501 KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue);
502
503 return AdapterObject;
504}
505#endif
506
513NTAPI
516{
517 UCHAR Controller;
518 DMA_MODE DmaMode = {{0 }};
519 DMA_EXTENDED_MODE ExtendedMode = {{ 0 }};
520 PVOID AdapterBaseVa;
521
522 Controller = (DeviceDescription->DmaChannel & 4) ? 2 : 1;
523
524 if (Controller == 1)
525 {
526 AdapterBaseVa = UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController1));
527 }
528 else
529 {
530 AdapterBaseVa = UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2));
531 }
532
533 AdapterObject->AdapterNumber = Controller;
534 AdapterObject->ChannelNumber = (UCHAR)(DeviceDescription->DmaChannel & 3);
535 AdapterObject->PagePort = (PUCHAR)HalpEisaPortPage[DeviceDescription->DmaChannel];
536 AdapterObject->Width16Bits = FALSE;
537 AdapterObject->AdapterBaseVa = AdapterBaseVa;
538
540 {
541 ExtendedMode.ChannelNumber = AdapterObject->ChannelNumber;
542
543 switch (DeviceDescription->DmaSpeed)
544 {
545 case Compatible: ExtendedMode.TimingMode = COMPATIBLE_TIMING; break;
546 case TypeA: ExtendedMode.TimingMode = TYPE_A_TIMING; break;
547 case TypeB: ExtendedMode.TimingMode = TYPE_B_TIMING; break;
548 case TypeC: ExtendedMode.TimingMode = BURST_TIMING; break;
549 default:
550 return FALSE;
551 }
552
553 switch (DeviceDescription->DmaWidth)
554 {
555 case Width8Bits: ExtendedMode.TransferSize = B_8BITS; break;
556 case Width16Bits: ExtendedMode.TransferSize = B_16BITS; break;
557 case Width32Bits: ExtendedMode.TransferSize = B_32BITS; break;
558 default:
559 return FALSE;
560 }
561
562 if (Controller == 1)
563 {
565 ExtendedMode.Byte);
566 }
567 else
568 {
570 ExtendedMode.Byte);
571 }
572 }
573 else
574 {
575 /*
576 * Validate setup for non-busmaster DMA adapter. Secondary controller
577 * supports only 16-bit transfers and main controller supports only
578 * 8-bit transfers. Anything else is invalid.
579 */
580 if (!DeviceDescription->Master)
581 {
582 if ((Controller == 2) && (DeviceDescription->DmaWidth == Width16Bits))
583 {
584 AdapterObject->Width16Bits = TRUE;
585 }
586 else if ((Controller != 1) || (DeviceDescription->DmaWidth != Width8Bits))
587 {
588 return FALSE;
589 }
590 }
591 }
592
593 DmaMode.Channel = AdapterObject->ChannelNumber;
594 DmaMode.AutoInitialize = DeviceDescription->AutoInitialize;
595
596 /*
597 * Set the DMA request mode.
598 *
599 * For (E)ISA bus master devices just unmask (enable) the DMA channel
600 * and set it to cascade mode. Otherwise just select the right one
601 * bases on the passed device description.
602 */
603 if (DeviceDescription->Master)
604 {
606 if (Controller == 1)
607 {
608 /* Set the Request Data */
610 WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte);
611
612 /* Unmask DMA Channel */
613 WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->SingleMask,
614 AdapterObject->ChannelNumber | DMA_CLEARMASK);
615 }
616 else
617 {
618 /* Set the Request Data */
619 WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte);
620
621 /* Unmask DMA Channel */
622 WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->SingleMask,
623 AdapterObject->ChannelNumber | DMA_CLEARMASK);
624 }
625 }
626 else
627 {
628 if (DeviceDescription->DemandMode)
629 {
631 }
632 else
633 {
635 }
636 }
637
638 AdapterObject->AdapterMode = DmaMode;
639
640 return TRUE;
641}
642
643#ifndef _MINIHAL_
660NTAPI
663{
664 PADAPTER_OBJECT AdapterObject = NULL;
666 ULONG MapRegisters;
669
670 /* Validate parameters in device description */
672
673 /*
674 * See if we're going to use ISA/EISA DMA adapter. These adapters are
675 * special since they're reused.
676 *
677 * Also note that we check for channel number since there are only 8 DMA
678 * channels on ISA, so any request above this requires new adapter.
679 */
680 if (((DeviceDescription->InterfaceType == Eisa) ||
681 (DeviceDescription->InterfaceType == Isa)) || !(DeviceDescription->Master))
682 {
683 if (((DeviceDescription->InterfaceType == Isa) ||
684 (DeviceDescription->InterfaceType == Eisa)) &&
685 (DeviceDescription->DmaChannel >= 8))
686 {
688 }
689 else
690 {
692 }
693 }
694 else
695 {
697 }
698
699 /*
700 * Disallow creating adapter for ISA/EISA DMA channel 4 since it's used
701 * for cascading the controllers and it's not available for software use.
702 */
703 if ((EisaAdapter) && (DeviceDescription->DmaChannel == 4)) return NULL;
704
705 /*
706 * Calculate the number of map registers.
707 *
708 * - For EISA and PCI scatter/gather no map registers are needed.
709 * - For ISA slave scatter/gather one map register is needed.
710 * - For all other cases the number of map registers depends on
711 * DeviceDescription->MaximumLength.
712 */
713 MaximumLength = DeviceDescription->MaximumLength & MAXLONG;
714 if ((DeviceDescription->ScatterGather) &&
715 ((DeviceDescription->InterfaceType == Eisa) ||
716 (DeviceDescription->InterfaceType == PCIBus)))
717 {
718 MapRegisters = 0;
719 }
720 else if ((DeviceDescription->ScatterGather) && !(DeviceDescription->Master))
721 {
722 MapRegisters = 1;
723 }
724 else
725 {
726 /*
727 * In the equation below the additional map register added by
728 * the "+1" accounts for the case when a transfer does not start
729 * at a page-aligned address.
730 */
731 MapRegisters = BYTES_TO_PAGES(MaximumLength) + 1;
732 if (MapRegisters > 16) MapRegisters = 16;
733 }
734
735 /*
736 * Acquire the DMA lock that is used to protect the EISA adapter array.
737 */
739
740 /*
741 * Now we must get ahold of the adapter object. For first eight ISA/EISA
742 * channels there are static adapter objects that are reused and updated
743 * on succesive HalGetAdapter calls. In other cases a new adapter object
744 * is always created and it's to the DMA adapter list (HalpDmaAdapterList).
745 */
746 if (EisaAdapter)
747 {
748 AdapterObject = HalpEisaAdapter[DeviceDescription->DmaChannel];
749 if (AdapterObject)
750 {
751 if ((AdapterObject->NeedsMapRegisters) &&
752 (MapRegisters > AdapterObject->MapRegistersPerChannel))
753 {
754 AdapterObject->MapRegistersPerChannel = MapRegisters;
755 }
756 }
757 }
758
759 if (AdapterObject == NULL)
760 {
761 AdapterObject = HalpDmaAllocateChildAdapter(MapRegisters, DeviceDescription);
762 if (AdapterObject == NULL)
763 {
764 KeSetEvent(&HalpDmaLock, 0, 0);
765 return NULL;
766 }
767
768 if (EisaAdapter)
769 {
770 HalpEisaAdapter[DeviceDescription->DmaChannel] = AdapterObject;
771 }
772
773 if (MapRegisters > 0)
774 {
775 AdapterObject->NeedsMapRegisters = TRUE;
776 AdapterObject->MapRegistersPerChannel = MapRegisters;
777 }
778 else
779 {
780 AdapterObject->NeedsMapRegisters = FALSE;
781 if (DeviceDescription->Master)
782 {
783 AdapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(MaximumLength) + 1;
784 }
785 else
786 {
787 AdapterObject->MapRegistersPerChannel = 1;
788 }
789 }
790 }
791
792 /*
793 * Release the DMA lock. HalpEisaAdapter will no longer be touched,
794 * so we don't need it.
795 */
796 KeSetEvent(&HalpDmaLock, 0, 0);
797
798 if (!EisaAdapter)
799 {
800 /* If it's not one of the static adapters, add it to the list */
802 InsertTailList(&HalpDmaAdapterList, &AdapterObject->AdapterList);
804 }
805
806 /*
807 * Setup the values in the adapter object that are common for all
808 * types of buses.
809 */
811 {
812 AdapterObject->IgnoreCount = DeviceDescription->IgnoreCount;
813 }
814 else
815 {
816 AdapterObject->IgnoreCount = 0;
817 }
818
819 AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
820 AdapterObject->Dma64BitAddresses = DeviceDescription->Dma64BitAddresses;
821 AdapterObject->ScatterGather = DeviceDescription->ScatterGather;
822 AdapterObject->MasterDevice = DeviceDescription->Master;
823 *NumberOfMapRegisters = AdapterObject->MapRegistersPerChannel;
824
825 /*
826 * For non-(E)ISA adapters we have already done all the work. On the
827 * other hand for (E)ISA adapters we must still setup the DMA modes
828 * and prepare the controller.
829 */
830 if (EisaAdapter)
831 {
833 {
834 ObDereferenceObject(AdapterObject);
835 return NULL;
836 }
837 }
838
839 return AdapterObject;
840}
841
851NTAPI
855{
857}
858
867VOID
868NTAPI
870{
872 if (AdapterObject->ChannelNumber == 0xFF)
873 {
875 RemoveEntryList(&AdapterObject->AdapterList);
877 }
878
879 ObDereferenceObject(AdapterObject);
880}
881
907PVOID
908NTAPI
911 IN PPHYSICAL_ADDRESS LogicalAddress,
912 IN BOOLEAN CacheEnabled)
913{
916 PHYSICAL_ADDRESS BoundryAddressMultiple;
918
921 BoundryAddressMultiple.QuadPart = 0;
922
923 /*
924 * For bus-master DMA devices the buffer mustn't cross 4Gb boundary. For
925 * slave DMA devices the 64Kb boundary mustn't be crossed since the
926 * controller wouldn't be able to handle it.
927 */
928 if (AdapterObject->MasterDevice)
929 {
930 BoundryAddressMultiple.HighPart = 1;
931 }
932 else
933 {
934 BoundryAddressMultiple.LowPart = 0x10000;
935 }
936
940 BoundryAddressMultiple,
941 CacheEnabled ? MmCached :
943 if (VirtualAddress == NULL) return NULL;
944
945 *LogicalAddress = MmGetPhysicalAddress(VirtualAddress);
946
947 return VirtualAddress;
948}
949
959VOID
960NTAPI
963 IN PHYSICAL_ADDRESS LogicalAddress,
965 IN BOOLEAN CacheEnabled)
966{
968 Length,
969 CacheEnabled ? MmCached : MmNonCached);
970}
971
984
985
987NTAPI
989 IN PIRP Irp,
992{
993 PSCATTER_GATHER_CONTEXT AdapterControlContext = Context;
994 PADAPTER_OBJECT AdapterObject = AdapterControlContext->AdapterObject;
995 PSCATTER_GATHER_LIST ScatterGatherList;
997 ULONG ElementCount = 0, RemainingLength = AdapterControlContext->Length;
998 PUCHAR CurrentVa = AdapterControlContext->CurrentVa;
999
1000 /* Store the map register base for later in HalPutScatterGatherList */
1001 AdapterControlContext->MapRegisterBase = MapRegisterBase;
1002
1003 while (RemainingLength > 0 && ElementCount < MAX_SG_ELEMENTS)
1004 {
1005 TempElements[ElementCount].Length = RemainingLength;
1006 TempElements[ElementCount].Reserved = 0;
1007 TempElements[ElementCount].Address = IoMapTransfer(AdapterObject,
1008 AdapterControlContext->Mdl,
1010 CurrentVa + (AdapterControlContext->Length - RemainingLength),
1011 &TempElements[ElementCount].Length,
1012 AdapterControlContext->WriteToDevice);
1013 if (TempElements[ElementCount].Length == 0)
1014 break;
1015
1016 DPRINT("Allocated one S/G element: 0x%I64u with length: 0x%x\n",
1017 TempElements[ElementCount].Address.QuadPart,
1018 TempElements[ElementCount].Length);
1019
1020 ASSERT(TempElements[ElementCount].Length <= RemainingLength);
1021 RemainingLength -= TempElements[ElementCount].Length;
1022 ElementCount++;
1023 }
1024
1025 if (RemainingLength > 0)
1026 {
1027 DPRINT1("Scatter/gather list construction failed!\n");
1028 return DeallocateObject;
1029 }
1030
1031 ScatterGatherList = ExAllocatePoolWithTag(NonPagedPool,
1032 sizeof(SCATTER_GATHER_LIST) + sizeof(SCATTER_GATHER_ELEMENT) * ElementCount,
1033 TAG_DMA);
1034 ASSERT(ScatterGatherList);
1035
1036 ScatterGatherList->NumberOfElements = ElementCount;
1037 ScatterGatherList->Reserved = (ULONG_PTR)AdapterControlContext;
1038 RtlCopyMemory(ScatterGatherList->Elements,
1039 TempElements,
1040 sizeof(SCATTER_GATHER_ELEMENT) * ElementCount);
1041
1042 DPRINT("Initiating S/G DMA with %d element(s)\n", ElementCount);
1043
1044 AdapterControlContext->AdapterListControlRoutine(DeviceObject,
1045 Irp,
1046 ScatterGatherList,
1047 AdapterControlContext->AdapterListControlContext);
1048
1050}
1051
1080 NTSTATUS
1081 NTAPI
1084 IN PMDL Mdl,
1085 IN PVOID CurrentVa,
1086 IN ULONG Length,
1090{
1091 return HalBuildScatterGatherList(AdapterObject,
1093 Mdl,
1094 CurrentVa,
1095 Length,
1097 Context,
1099 NULL,
1100 0);
1101}
1102
1121 VOID
1122 NTAPI
1126{
1127 PSCATTER_GATHER_CONTEXT AdapterControlContext = (PSCATTER_GATHER_CONTEXT)ScatterGather->Reserved;
1128 ULONG i;
1129
1130 for (i = 0; i < ScatterGather->NumberOfElements; i++)
1131 {
1132 IoFlushAdapterBuffers(AdapterObject,
1133 AdapterControlContext->Mdl,
1134 AdapterControlContext->MapRegisterBase,
1135 AdapterControlContext->CurrentVa,
1136 ScatterGather->Elements[i].Length,
1137 AdapterControlContext->WriteToDevice);
1138 AdapterControlContext->CurrentVa += ScatterGather->Elements[i].Length;
1139 }
1140
1141 IoFreeMapRegisters(AdapterObject,
1142 AdapterControlContext->MapRegisterBase,
1143 AdapterControlContext->MapRegisterCount);
1144
1145
1147
1148 /* If this is our buffer, release it */
1149 if (!AdapterControlContext->UsingUserBuffer)
1150 ExFreePoolWithTag(AdapterControlContext, TAG_DMA);
1151
1152 DPRINT("S/G DMA has finished!\n");
1153}
1154
1156NTAPI
1158 IN PADAPTER_OBJECT AdapterObject,
1160 IN PVOID CurrentVa,
1161 IN ULONG Length,
1162 OUT PULONG ScatterGatherListSize,
1163 OUT PULONG pNumberOfMapRegisters)
1164{
1166 ULONG SgSize;
1167
1169
1171 SgSize = sizeof(SCATTER_GATHER_CONTEXT);
1172
1173 *ScatterGatherListSize = SgSize;
1174 if (pNumberOfMapRegisters) *pNumberOfMapRegisters = NumberOfMapRegisters;
1175
1176 return STATUS_SUCCESS;
1177}
1178
1214NTAPI
1216 IN PADAPTER_OBJECT AdapterObject,
1218 IN PMDL Mdl,
1219 IN PVOID CurrentVa,
1220 IN ULONG Length,
1224 IN PVOID ScatterGatherBuffer,
1225 IN ULONG ScatterGatherBufferLength)
1226{
1229 PSCATTER_GATHER_CONTEXT ScatterGatherContext;
1230 BOOLEAN UsingUserBuffer;
1231
1233 Mdl,
1234 CurrentVa,
1235 Length,
1236 &SgSize,
1238 if (!NT_SUCCESS(Status)) return Status;
1239
1240 if (ScatterGatherBuffer)
1241 {
1242 /* Checking if user buffer is enough */
1243 if (ScatterGatherBufferLength < SgSize)
1244 {
1246 }
1247 UsingUserBuffer = TRUE;
1248 }
1249 else
1250 {
1251 ScatterGatherBuffer = ExAllocatePoolWithTag(NonPagedPool, SgSize, TAG_DMA);
1252 if (!ScatterGatherBuffer)
1253 {
1255 }
1256 UsingUserBuffer = FALSE;
1257 }
1258
1259 {
1260 ScatterGatherContext = (PSCATTER_GATHER_CONTEXT)ScatterGatherBuffer;
1261
1262 /* Fill the scatter-gather context */
1263 ScatterGatherContext->UsingUserBuffer = UsingUserBuffer;
1264 ScatterGatherContext->AdapterObject = AdapterObject;
1265 ScatterGatherContext->Mdl = Mdl;
1266 ScatterGatherContext->CurrentVa = CurrentVa;
1267 ScatterGatherContext->Length = Length;
1268 ScatterGatherContext->MapRegisterCount = NumberOfMapRegisters;
1269 ScatterGatherContext->AdapterListControlRoutine = ExecutionRoutine;
1270 ScatterGatherContext->AdapterListControlContext = Context;
1271 ScatterGatherContext->WriteToDevice = WriteToDevice;
1272
1273 ScatterGatherContext->Wcb.DeviceObject = DeviceObject;
1274 ScatterGatherContext->Wcb.DeviceContext = (PVOID)ScatterGatherContext;
1275 ScatterGatherContext->Wcb.CurrentIrp = DeviceObject->CurrentIrp;
1276
1277 Status = HalAllocateAdapterChannel(AdapterObject,
1278 &ScatterGatherContext->Wcb,
1281
1282 if (!NT_SUCCESS(Status))
1283 {
1284 if (!UsingUserBuffer)
1285 ExFreePoolWithTag(ScatterGatherBuffer, TAG_DMA);
1286 return Status;
1287 }
1288 }
1289
1290 return STATUS_SUCCESS;
1291}
1292
1294NTAPI
1296 IN PDMA_ADAPTER DmaAdapter,
1298 IN PMDL OriginalMdl,
1300{
1303}
1304#endif
1305
1314ULONG
1315NTAPI
1317{
1318 return 1;
1319}
1320
1321/*
1322 * @name HalReadDmaCounter
1323 *
1324 * Read DMA operation progress counter.
1325 *
1326 * @implemented
1327 */
1328ULONG
1329NTAPI
1331{
1332 KIRQL OldIrql;
1333 ULONG Count, OldCount;
1334
1335 ASSERT(!AdapterObject->MasterDevice);
1336
1337 /*
1338 * Acquire the master adapter lock since we're going to mess with the
1339 * system DMA controller registers and we really don't want anyone
1340 * to do the same at the same time.
1341 */
1342 KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
1343
1344 /* Send the request to the specific controller. */
1345 if (AdapterObject->AdapterNumber == 1)
1346 {
1347 PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
1348
1349 Count = 0xffff00;
1350 do
1351 {
1352 OldCount = Count;
1353
1354 /* Send Reset */
1355 WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
1356
1357 /* Read Count */
1358 Count = READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
1359 [AdapterObject->ChannelNumber].DmaBaseCount);
1360 Count |= READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
1361 [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
1362 } while (0xffff00 & (OldCount ^ Count));
1363 }
1364 else
1365 {
1366 PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
1367
1368 Count = 0xffff00;
1369 do
1370 {
1371 OldCount = Count;
1372
1373 /* Send Reset */
1374 WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
1375
1376 /* Read Count */
1377 Count = READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
1378 [AdapterObject->ChannelNumber].DmaBaseCount);
1379 Count |= READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
1380 [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
1381 } while (0xffff00 & (OldCount ^ Count));
1382 }
1383
1384 KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
1385
1386 Count++;
1387 Count &= 0xffff;
1388 if (AdapterObject->Width16Bits) Count *= 2;
1389
1390 return Count;
1391}
1392
1393#ifndef _MINIHAL_
1400VOID
1401NTAPI
1403{
1405 KIRQL OldIrql;
1406 BOOLEAN Succeeded;
1407
1408 /*
1409 * Try to allocate new map registers for the adapter.
1410 *
1411 * NOTE: The NT implementation actually tries to allocate more map
1412 * registers than needed as an optimization.
1413 */
1415 Succeeded = HalpGrowMapBuffers(WorkItem->AdapterObject->MasterAdapter,
1416 WorkItem->NumberOfMapRegisters << PAGE_SHIFT);
1417 KeSetEvent(&HalpDmaLock, 0, 0);
1418
1419 if (Succeeded)
1420 {
1421 /*
1422 * Flush the adapter queue now that new map registers are ready. The
1423 * easiest way to do that is to call IoFreeMapRegisters to not free
1424 * any registers. Note that we use the magic (PVOID)2 map register
1425 * base to bypass the parameter checking.
1426 */
1428 IoFreeMapRegisters(WorkItem->AdapterObject, (PVOID)2, 0);
1430 }
1431
1433}
1434
1460NTAPI
1462 IN PWAIT_CONTEXT_BLOCK WaitContextBlock,
1465{
1466 PADAPTER_OBJECT MasterAdapter;
1469 ULONG Result;
1470 KIRQL OldIrql;
1471
1473
1474 /* Set up the wait context block in case we can't run right away. */
1475 WaitContextBlock->DeviceRoutine = ExecutionRoutine;
1476 WaitContextBlock->NumberOfMapRegisters = NumberOfMapRegisters;
1477
1478 /* Returns true if queued, else returns false and sets the queue to busy */
1479 if (KeInsertDeviceQueue(&AdapterObject->ChannelWaitQueue,
1480 &WaitContextBlock->WaitQueueEntry))
1481 {
1482 return STATUS_SUCCESS;
1483 }
1484
1485 MasterAdapter = AdapterObject->MasterAdapter;
1486
1487 AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
1488 AdapterObject->CurrentWcb = WaitContextBlock;
1489
1490 if ((NumberOfMapRegisters) && (AdapterObject->NeedsMapRegisters))
1491 {
1492 if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
1493 {
1494 AdapterObject->NumberOfMapRegisters = 0;
1495 IoFreeAdapterChannel(AdapterObject);
1497 }
1498
1499 /*
1500 * Get the map registers. This is partly complicated by the fact
1501 * that new map registers can only be allocated at PASSIVE_LEVEL
1502 * and we're currently at DISPATCH_LEVEL. The following code has
1503 * two code paths:
1504 *
1505 * - If there is no adapter queued for map register allocation,
1506 * try to see if enough contiguous map registers are present.
1507 * In case they're we can just get them and proceed further.
1508 *
1509 * - If some adapter is already present in the queue we must
1510 * respect the order of adapters asking for map registers and
1511 * so the fast case described above can't take place.
1512 * This case is also entered if not enough coniguous map
1513 * registers are present.
1514 *
1515 * A work queue item is allocated and queued, the adapter is
1516 * also queued into the master adapter queue. The worker
1517 * routine does the job of allocating the map registers at
1518 * PASSIVE_LEVEL and calling the ExecutionRoutine.
1519 */
1520
1521 KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1522
1523 if (IsListEmpty(&MasterAdapter->AdapterQueue))
1524 {
1525 Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters, NumberOfMapRegisters, 0);
1526 if (Index != MAXULONG)
1527 {
1528 AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1529 if (!AdapterObject->ScatterGather)
1530 {
1531 AdapterObject->MapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1532 }
1533 }
1534 }
1535
1536 if (Index == MAXULONG)
1537 {
1538 InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
1539
1541 sizeof(GROW_WORK_ITEM),
1542 TAG_DMA);
1543 if (WorkItem)
1544 {
1546 WorkItem->AdapterObject = AdapterObject;
1547 WorkItem->NumberOfMapRegisters = NumberOfMapRegisters;
1548
1549 ExQueueWorkItem(&WorkItem->WorkQueueItem, DelayedWorkQueue);
1550 }
1551
1552 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1553
1554 return STATUS_SUCCESS;
1555 }
1556
1557 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1558 }
1559 else
1560 {
1561 AdapterObject->MapRegisterBase = NULL;
1562 AdapterObject->NumberOfMapRegisters = 0;
1563 }
1564
1565 AdapterObject->CurrentWcb = WaitContextBlock;
1566
1567 Result = ExecutionRoutine(WaitContextBlock->DeviceObject,
1568 WaitContextBlock->CurrentIrp,
1569 AdapterObject->MapRegisterBase,
1570 WaitContextBlock->DeviceContext);
1571
1572 /*
1573 * Possible return values:
1574 *
1575 * - KeepObject
1576 * Don't free any resources, the ADAPTER_OBJECT is still in use and
1577 * the caller will call IoFreeAdapterChannel later.
1578 *
1579 * - DeallocateObject
1580 * Deallocate the map registers and release the ADAPTER_OBJECT, so
1581 * someone else can use it.
1582 *
1583 * - DeallocateObjectKeepRegisters
1584 * Release the ADAPTER_OBJECT, but hang on to the map registers. The
1585 * client will later call IoFreeMapRegisters.
1586 *
1587 * NOTE:
1588 * IoFreeAdapterChannel runs the queue, so it must be called unless
1589 * the adapter object is not to be freed.
1590 */
1591 if (Result == DeallocateObject)
1592 {
1593 IoFreeAdapterChannel(AdapterObject);
1594 }
1596 {
1597 AdapterObject->NumberOfMapRegisters = 0;
1598 IoFreeAdapterChannel(AdapterObject);
1599 }
1600
1601 return STATUS_SUCCESS;
1602}
1603
1622VOID
1623NTAPI
1625{
1626 PADAPTER_OBJECT MasterAdapter;
1628 PWAIT_CONTEXT_BLOCK WaitContextBlock;
1630 ULONG Result;
1631 KIRQL OldIrql;
1632
1633 MasterAdapter = AdapterObject->MasterAdapter;
1634
1635 for (;;)
1636 {
1637 /*
1638 * To keep map registers, call here with AdapterObject->
1639 * NumberOfMapRegisters set to zero. This trick is used in
1640 * HalAllocateAdapterChannel for example.
1641 */
1642 if (AdapterObject->NumberOfMapRegisters)
1643 {
1644 IoFreeMapRegisters(AdapterObject,
1645 AdapterObject->MapRegisterBase,
1646 AdapterObject->NumberOfMapRegisters);
1647 }
1648
1649 DeviceQueueEntry = KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue);
1650 if (!DeviceQueueEntry) break;
1651
1652 WaitContextBlock = CONTAINING_RECORD(DeviceQueueEntry,
1654 WaitQueueEntry);
1655
1656 AdapterObject->CurrentWcb = WaitContextBlock;
1657 AdapterObject->NumberOfMapRegisters = WaitContextBlock->NumberOfMapRegisters;
1658
1659 if ((WaitContextBlock->NumberOfMapRegisters) && (AdapterObject->MasterAdapter))
1660 {
1661 KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1662
1663 if (IsListEmpty(&MasterAdapter->AdapterQueue))
1664 {
1665 Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
1666 WaitContextBlock->NumberOfMapRegisters,
1667 0);
1668 if (Index != MAXULONG)
1669 {
1670 AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1671 if (!AdapterObject->ScatterGather)
1672 {
1673 AdapterObject->MapRegisterBase =(PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1674 }
1675 }
1676 }
1677
1678 if (Index == MAXULONG)
1679 {
1680 InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
1681 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1682 break;
1683 }
1684
1685 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1686 }
1687 else
1688 {
1689 AdapterObject->MapRegisterBase = NULL;
1690 AdapterObject->NumberOfMapRegisters = 0;
1691 }
1692
1693 /* Call the adapter control routine. */
1694 Result = ((PDRIVER_CONTROL)WaitContextBlock->DeviceRoutine)(WaitContextBlock->DeviceObject,
1695 WaitContextBlock->CurrentIrp,
1696 AdapterObject->MapRegisterBase,
1697 WaitContextBlock->DeviceContext);
1698 switch (Result)
1699 {
1700 case KeepObject:
1701 /*
1702 * We're done until the caller manually calls IoFreeAdapterChannel
1703 * or IoFreeMapRegisters.
1704 */
1705 return;
1706
1708 /*
1709 * Hide the map registers so they aren't deallocated next time
1710 * around.
1711 */
1712 AdapterObject->NumberOfMapRegisters = 0;
1713 break;
1714
1715 default:
1716 break;
1717 }
1718 }
1719}
1720
1735VOID
1736NTAPI
1740{
1741 PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
1742 PLIST_ENTRY ListEntry;
1743 KIRQL OldIrql;
1744 ULONG Index;
1745 ULONG Result;
1746
1748
1749 if (!(MasterAdapter) || !(MapRegisterBase)) return;
1750
1751 KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1752
1753 if (NumberOfMapRegisters != 0)
1754 {
1755 PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1756
1757 RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1758 RtlClearBits(MasterAdapter->MapRegisters,
1759 (ULONG)(RealMapRegisterBase - MasterAdapter->MapRegisterBase),
1761 }
1762
1763 /*
1764 * Now that we freed few map registers it's time to look at the master
1765 * adapter queue and see if there is someone waiting for map registers.
1766 */
1767 while (!IsListEmpty(&MasterAdapter->AdapterQueue))
1768 {
1769 ListEntry = RemoveHeadList(&MasterAdapter->AdapterQueue);
1770 AdapterObject = CONTAINING_RECORD(ListEntry, struct _ADAPTER_OBJECT, AdapterQueue);
1771
1772 Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
1773 AdapterObject->NumberOfMapRegisters,
1774 0);
1775 if (Index == MAXULONG)
1776 {
1777 InsertHeadList(&MasterAdapter->AdapterQueue, ListEntry);
1778 break;
1779 }
1780
1781 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1782
1783 AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1784 if (!AdapterObject->ScatterGather)
1785 {
1786 AdapterObject->MapRegisterBase =
1787 (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1788 }
1789
1790 Result = ((PDRIVER_CONTROL)AdapterObject->CurrentWcb->DeviceRoutine)(AdapterObject->CurrentWcb->DeviceObject,
1791 AdapterObject->CurrentWcb->CurrentIrp,
1792 AdapterObject->MapRegisterBase,
1793 AdapterObject->CurrentWcb->DeviceContext);
1794 switch (Result)
1795 {
1797 AdapterObject->NumberOfMapRegisters = 0;
1798 /* fall through */
1799
1800 case DeallocateObject:
1801 if (AdapterObject->NumberOfMapRegisters)
1802 {
1803 KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1804 RtlClearBits(MasterAdapter->MapRegisters,
1805 (ULONG)(AdapterObject->MapRegisterBase -
1806 MasterAdapter->MapRegisterBase),
1807 AdapterObject->NumberOfMapRegisters);
1808 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1809 }
1810
1811 IoFreeAdapterChannel(AdapterObject);
1812 break;
1813
1814 default:
1815 break;
1816 }
1817
1818 KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1819 }
1820
1821 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1822}
1823
1831VOID
1832NTAPI
1835 IN PVOID CurrentVa,
1836 IN ULONG Length,
1838{
1839 ULONG CurrentLength;
1840 ULONG_PTR CurrentAddress;
1843
1845 if (!VirtualAddress)
1846 {
1847 /*
1848 * NOTE: On real NT a mechanism with reserved pages is implemented
1849 * to handle this case in a slow, but graceful non-fatal way.
1850 */
1851 KeBugCheckEx(HAL_MEMORY_ALLOCATION, PAGE_SIZE, 0, (ULONG_PTR)__FILE__, 0);
1852 }
1853
1854 CurrentAddress = (ULONG_PTR)VirtualAddress +
1855 (ULONG_PTR)CurrentVa -
1857
1858 while (Length > 0)
1859 {
1860 ByteOffset = BYTE_OFFSET(CurrentAddress);
1861 CurrentLength = PAGE_SIZE - ByteOffset;
1862 if (CurrentLength > Length) CurrentLength = Length;
1863
1864 if (WriteToDevice)
1865 {
1867 (PVOID)CurrentAddress,
1868 CurrentLength);
1869 }
1870 else
1871 {
1872 RtlCopyMemory((PVOID)CurrentAddress,
1873 (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
1874 CurrentLength);
1875 }
1876
1877 Length -= CurrentLength;
1878 CurrentAddress += CurrentLength;
1880 }
1881}
1882
1914BOOLEAN
1915NTAPI
1917 IN PMDL Mdl,
1919 IN PVOID CurrentVa,
1920 IN ULONG Length,
1922{
1923 BOOLEAN SlaveDma = FALSE;
1924 PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1927 PPFN_NUMBER MdlPagesPtr;
1928
1929 /* Sanity checks */
1931 ASSERT(AdapterObject);
1932
1933 if (!AdapterObject->MasterDevice)
1934 {
1935 /* Mask out (disable) the DMA channel. */
1936 if (AdapterObject->AdapterNumber == 1)
1937 {
1938 PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
1939 WRITE_PORT_UCHAR(&DmaControl1->SingleMask,
1940 AdapterObject->ChannelNumber | DMA_SETMASK);
1941 }
1942 else
1943 {
1944 PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
1945 WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
1946 AdapterObject->ChannelNumber | DMA_SETMASK);
1947 }
1948 SlaveDma = TRUE;
1949 }
1950
1951 /* This can happen if the device supports hardware scatter/gather. */
1952 if (MapRegisterBase == NULL) return TRUE;
1953
1954 RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1955
1956 if (!WriteToDevice)
1957 {
1959 {
1960 if (RealMapRegisterBase->Counter != MAXULONG)
1961 {
1962 if ((SlaveDma) && !(AdapterObject->IgnoreCount))
1963 {
1964 Length -= HalReadDmaCounter(AdapterObject);
1965 }
1966 }
1968 RealMapRegisterBase,
1969 CurrentVa,
1970 Length,
1971 FALSE);
1972 }
1973 else
1974 {
1975 MdlPagesPtr = MmGetMdlPfnArray(Mdl);
1976 MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
1977
1978 PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
1979 PhysicalAddress.QuadPart += BYTE_OFFSET(CurrentVa);
1980
1983 {
1985 RealMapRegisterBase,
1986 CurrentVa,
1987 Length,
1988 FALSE);
1989 }
1990 }
1991 }
1992
1993 RealMapRegisterBase->Counter = 0;
1994
1995 return TRUE;
1996}
1997
2030NTAPI
2032 IN PMDL Mdl,
2034 IN PVOID CurrentVa,
2037{
2038 PPFN_NUMBER MdlPagesPtr;
2039 PFN_NUMBER MdlPage1, MdlPage2;
2042 ULONG TransferLength;
2043 BOOLEAN UseMapRegisters;
2044 PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
2047 ULONG Counter;
2048 DMA_MODE AdapterMode;
2049 KIRQL OldIrql;
2050
2051 /*
2052 * Precalculate some values that are used in all cases.
2053 *
2054 * ByteOffset is offset inside the page at which the transfer starts.
2055 * MdlPagesPtr is pointer inside the MDL page chain at the page where the
2056 * transfer start.
2057 * PhysicalAddress is physical address corresponding to the transfer
2058 * start page and offset.
2059 * TransferLength is the initial length of the transfer, which is reminder
2060 * of the first page. The actual value is calculated below.
2061 *
2062 * Note that all the variables can change during the processing which
2063 * takes place below. These are just initial values.
2064 */
2065 ByteOffset = BYTE_OFFSET(CurrentVa);
2066
2067 MdlPagesPtr = MmGetMdlPfnArray(Mdl);
2068 MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
2069
2070 PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
2072
2073 TransferLength = PAGE_SIZE - ByteOffset;
2074
2075 /*
2076 * Special case for bus master adapters with S/G support. We can directly
2077 * use the buffer specified by the MDL, so not much work has to be done.
2078 *
2079 * Just return the passed VA's corresponding physical address and update
2080 * length to the number of physically contiguous bytes found. Also
2081 * pages crossing the 4Gb boundary aren't considered physically contiguous.
2082 */
2083 if (MapRegisterBase == NULL)
2084 {
2085 while (TransferLength < *Length)
2086 {
2087 MdlPage1 = *MdlPagesPtr;
2088 MdlPage2 = *(MdlPagesPtr + 1);
2089 if (MdlPage1 + 1 != MdlPage2) break;
2090 if ((MdlPage1 ^ MdlPage2) & ~0xFFFFF) break;
2091 TransferLength += PAGE_SIZE;
2092 MdlPagesPtr++;
2093 }
2094
2095 if (TransferLength < *Length) *Length = TransferLength;
2096
2097 return PhysicalAddress;
2098 }
2099
2100 /*
2101 * The code below applies to slave DMA adapters and bus master adapters
2102 * without hardward S/G support.
2103 */
2104 RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
2105
2106 /*
2107 * Try to calculate the size of the transfer. We can only transfer
2108 * pages that are physically contiguous and that don't cross the
2109 * 64Kb boundary (this limitation applies only for ISA controllers).
2110 */
2111 while (TransferLength < *Length)
2112 {
2113 MdlPage1 = *MdlPagesPtr;
2114 MdlPage2 = *(MdlPagesPtr + 1);
2115 if (MdlPage1 + 1 != MdlPage2) break;
2116 if (!HalpEisaDma && ((MdlPage1 ^ MdlPage2) & ~0xF)) break;
2117 TransferLength += PAGE_SIZE;
2118 MdlPagesPtr++;
2119 }
2120
2121 if (TransferLength > *Length) TransferLength = *Length;
2122
2123 /*
2124 * If we're about to simulate software S/G and not all the pages are
2125 * physically contiguous then we must use the map registers to store
2126 * the data and allow the whole transfer to proceed at once.
2127 */
2128 if (((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG) && (TransferLength < *Length))
2129 {
2130 UseMapRegisters = TRUE;
2131 PhysicalAddress = RealMapRegisterBase->PhysicalAddress;
2133 TransferLength = *Length;
2134 RealMapRegisterBase->Counter = MAXULONG;
2135 Counter = 0;
2136 }
2137 else
2138 {
2139 /*
2140 * This is ordinary DMA transfer, so just update the progress
2141 * counters. These are used by IoFlushAdapterBuffers to track
2142 * the transfer progress.
2143 */
2144 UseMapRegisters = FALSE;
2145 Counter = RealMapRegisterBase->Counter;
2146 RealMapRegisterBase->Counter += BYTES_TO_PAGES(ByteOffset + TransferLength);
2147
2148 /*
2149 * Check if the buffer doesn't exceed the highest physical address
2150 * limit of the device. In that case we must use the map registers to
2151 * store the data.
2152 */
2154 if ((PhysicalAddress.QuadPart + TransferLength) > HighestAcceptableAddress.QuadPart)
2155 {
2156 UseMapRegisters = TRUE;
2157 PhysicalAddress = RealMapRegisterBase[Counter].PhysicalAddress;
2160 {
2161 RealMapRegisterBase->Counter = MAXULONG;
2162 Counter = 0;
2163 }
2164 }
2165 }
2166
2167 /*
2168 * If we decided to use the map registers (see above) and we're about
2169 * to transfer data to the device then copy the buffers into the map
2170 * register memory.
2171 */
2172 if ((UseMapRegisters) && (WriteToDevice))
2173 {
2175 RealMapRegisterBase + Counter,
2176 CurrentVa,
2177 TransferLength,
2179 }
2180
2181 /*
2182 * Return the length of transfer that actually takes place.
2183 */
2184 *Length = TransferLength;
2185
2186 /*
2187 * If we're doing slave (system) DMA then program the (E)ISA controller
2188 * to actually start the transfer.
2189 */
2190 if ((AdapterObject) && !(AdapterObject->MasterDevice))
2191 {
2192 AdapterMode = AdapterObject->AdapterMode;
2193
2194 if (WriteToDevice)
2195 {
2196 AdapterMode.TransferType = WRITE_TRANSFER;
2197 }
2198 else
2199 {
2200 AdapterMode.TransferType = READ_TRANSFER;
2201 if (AdapterObject->IgnoreCount)
2202 {
2203 RtlZeroMemory((PUCHAR)RealMapRegisterBase[Counter].VirtualAddress + ByteOffset,
2204 TransferLength);
2205 }
2206 }
2207
2209 if (AdapterObject->Width16Bits)
2210 {
2211 TransferLength >>= 1;
2212 TransferOffset >>= 1;
2213 }
2214
2215 KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
2216
2217 if (AdapterObject->AdapterNumber == 1)
2218 {
2219 PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
2220
2221 /* Reset Register */
2222 WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
2223
2224 /* Set the Mode */
2225 WRITE_PORT_UCHAR(&DmaControl1->Mode, AdapterMode.Byte);
2226
2227 /* Set the Offset Register */
2228 WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2230 WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2231 (UCHAR)(TransferOffset >> 8));
2232
2233 /* Set the Page Register */
2234 WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
2235 (UCHAR)(PhysicalAddress.LowPart >> 16));
2236 if (HalpEisaDma)
2237 {
2238 WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
2239 0);
2240 }
2241
2242 /* Set the Length */
2243 WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2244 (UCHAR)(TransferLength - 1));
2245 WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2246 (UCHAR)((TransferLength - 1) >> 8));
2247
2248 /* Unmask the Channel */
2249 WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK);
2250 }
2251 else
2252 {
2253 PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
2254
2255 /* Reset Register */
2256 WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
2257
2258 /* Set the Mode */
2259 WRITE_PORT_UCHAR(&DmaControl2->Mode, AdapterMode.Byte);
2260
2261 /* Set the Offset Register */
2262 WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2264 WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2265 (UCHAR)(TransferOffset >> 8));
2266
2267 /* Set the Page Register */
2268 WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
2269 (UCHAR)(PhysicalAddress.u.LowPart >> 16));
2270 if (HalpEisaDma)
2271 {
2272 WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
2273 0);
2274 }
2275
2276 /* Set the Length */
2277 WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2278 (UCHAR)(TransferLength - 1));
2279 WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2280 (UCHAR)((TransferLength - 1) >> 8));
2281
2282 /* Unmask the Channel */
2283 WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
2284 AdapterObject->ChannelNumber | DMA_CLEARMASK);
2285 }
2286
2287 KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
2288 }
2289
2290 /*
2291 * Return physical address of the buffer with data that is used for the
2292 * transfer. It can either point inside the Mdl that was passed by the
2293 * caller or into the map registers if the Mdl buffer can't be used
2294 * directly.
2295 */
2296 return PhysicalAddress;
2297}
2298#endif
2299
2305BOOLEAN
2306NTAPI
2308 IN ULONG Length,
2309 IN PHYSICAL_ADDRESS LogicalAddress,
2311{
2312 /* Function always returns true */
2313 return TRUE;
2314}
2315
2316/*
2317 * @implemented
2318 */
2319PVOID
2320NTAPI
2323{
2324 PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
2325 ULONG MapRegisterNumber;
2326
2327 /* Check if it needs map registers */
2328 if (AdapterObject->NeedsMapRegisters)
2329 {
2330 /* Check if we have enough */
2331 if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
2332 {
2333 /* We don't, fail */
2334 AdapterObject->NumberOfMapRegisters = 0;
2335 return NULL;
2336 }
2337
2338 /* Try to find free map registers */
2339 MapRegisterNumber = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
2341 0);
2342
2343 /* Check if nothing was found */
2344 if (MapRegisterNumber == MAXULONG)
2345 {
2346 /* No free registers found, so use the base registers */
2347 RtlSetBits(MasterAdapter->MapRegisters,
2348 0,
2350 MapRegisterNumber = 0;
2351 }
2352
2353 /* Calculate the new base */
2354 AdapterObject->MapRegisterBase =
2355 (PROS_MAP_REGISTER_ENTRY)(MasterAdapter->MapRegisterBase +
2356 MapRegisterNumber);
2357
2358 /* Check if scatter gather isn't supported */
2359 if (!AdapterObject->ScatterGather)
2360 {
2361 /* Set the flag */
2362 AdapterObject->MapRegisterBase =
2364 ((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
2365 }
2366 }
2367 else
2368 {
2369 AdapterObject->MapRegisterBase = NULL;
2370 AdapterObject->NumberOfMapRegisters = 0;
2371 }
2372
2373 /* Return the base */
2374 return AdapterObject->MapRegisterBase;
2375}
2376
2377/* EOF */
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
@ EisaAdapter
Definition: arcname.c:39
#define UNIMPLEMENTED
Definition: debug.h:115
ULONG HalpBusType
Definition: pcibus.c:18
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN WriteToDevice
Definition: cdrom.h:992
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
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
VOID NTAPI MmFreeContiguousMemorySpecifyCache(IN PVOID BaseAddress, IN SIZE_T NumberOfBytes, IN MEMORY_CACHING_TYPE CacheType)
Definition: contmem.c:666
_In_ PIRP Irp
Definition: csq.h:116
PKDEVICE_QUEUE_ENTRY NTAPI KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
Definition: devqueue.c:153
BOOLEAN NTAPI KeInsertDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue, IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)
Definition: devqueue.c:41
VOID NTAPI KeInitializeDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
Definition: devqueue.c:22
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define UlongToPtr(u)
Definition: config.h:106
#define ULONG_PTR
Definition: config.h:101
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:731
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
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
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
VOID NTAPI HalPutDmaAdapter(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:35
PVOID NTAPI HalAllocateCommonBuffer(IN PADAPTER_OBJECT AdapterObject, IN ULONG Length, IN PPHYSICAL_ADDRESS LogicalAddress, IN BOOLEAN CacheEnabled)
Definition: dma.c:46
VOID NTAPI IoFreeMapRegisters(IN PADAPTER_OBJECT AdapterObject, IN PVOID MapRegisterBase, IN ULONG NumberOfMapRegisters)
Definition: dma.c:114
PADAPTER_OBJECT NTAPI HalGetAdapter(IN PDEVICE_DESCRIPTION DeviceDescription, OUT PULONG NumberOfMapRegisters)
Definition: dma.c:22
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
NTSTATUS NTAPI HalAllocateAdapterChannel(IN PADAPTER_OBJECT AdapterObject, IN PWAIT_CONTEXT_BLOCK WaitContextBlock, IN ULONG NumberOfMapRegisters, IN PDRIVER_CONTROL ExecutionRoutine)
Definition: dma.c:88
VOID NTAPI IoFreeAdapterChannel(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:103
VOID NTAPI HalFreeCommonBuffer(IN PADAPTER_OBJECT AdapterObject, IN ULONG Length, IN PHYSICAL_ADDRESS LogicalAddress, IN PVOID VirtualAddress, IN BOOLEAN CacheEnabled)
Definition: dma.c:61
BOOLEAN NTAPI HalFlushCommonBuffer(IN PADAPTER_OBJECT AdapterObject, IN ULONG Length, IN PHYSICAL_ADDRESS LogicalAddress, IN PVOID VirtualAddress)
Definition: dma.c:165
ULONG NTAPI HalReadDmaCounter(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:76
PVOID NTAPI HalAllocateCrashDumpRegisters(IN PADAPTER_OBJECT AdapterObject, IN OUT PULONG NumberOfMapRegisters)
Definition: dma.c:180
VOID FASTCALL KfLowerIrql(IN KIRQL NewIrql)
Definition: pic.c:232
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
PADAPTER_OBJECT NTAPI HalpDmaAllocateMasterAdapter(VOID)
Definition: dma.c:398
static KEVENT HalpDmaLock
Definition: dma.c:83
static PADAPTER_OBJECT HalpMasterAdapter
Definition: dma.c:90
#define MAX_MAP_REGISTERS
Definition: dma.c:158
#define TAG_DMA
Definition: dma.c:160
VOID NTAPI HalpGrowMapBufferWorker(IN PVOID DeferredContext)
Definition: dma.c:1402
BOOLEAN NTAPI HalpGrowMapBuffers(IN PADAPTER_OBJECT AdapterObject, IN ULONG SizeOfMapBuffers)
Definition: dma.c:271
static DMA_OPERATIONS HalpDmaOperations
Definition: dma.c:138
NTSTATUS NTAPI HalBuildMdlFromScatterGatherList(IN PDMA_ADAPTER DmaAdapter, IN PSCATTER_GATHER_LIST ScatterGather, IN PMDL OriginalMdl, OUT PMDL *TargetMdl)
Definition: dma.c:1295
static BOOLEAN HalpEisaDma
Definition: dma.c:88
VOID NTAPI HalpCopyBufferMap(IN PMDL Mdl, IN PROS_MAP_REGISTER_ENTRY MapRegisterBase, IN PVOID CurrentVa, IN ULONG Length, IN BOOLEAN WriteToDevice)
Definition: dma.c:1833
static KSPIN_LOCK HalpDmaAdapterListLock
Definition: dma.c:84
IO_ALLOCATION_ACTION NTAPI HalpScatterGatherAdapterControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID MapRegisterBase, IN PVOID Context)
Definition: dma.c:988
PHYSICAL_ADDRESS NTAPI HalpGetAdapterMaximumPhysicalAddress(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:235
struct _SCATTER_GATHER_CONTEXT * PSCATTER_GATHER_CONTEXT
#define MAX_SG_ELEMENTS
Definition: dma.c:80
VOID HalpInitDma(VOID)
Definition: dma.c:185
PADAPTER_OBJECT NTAPI HalpDmaAllocateChildAdapter(IN ULONG NumberOfMapRegisters, IN PDEVICE_DESCRIPTION DeviceDescription)
Definition: dma.c:455
ULONG NTAPI HalpDmaGetDmaAlignment(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:1316
struct _SCATTER_GATHER_CONTEXT SCATTER_GATHER_CONTEXT
VOID NTAPI HalPutScatterGatherList(IN PADAPTER_OBJECT AdapterObject, IN PSCATTER_GATHER_LIST ScatterGather, IN BOOLEAN WriteToDevice)
Definition: dma.c:1123
static const ULONG_PTR HalpEisaPortPage[8]
Definition: dma.c:93
static PADAPTER_OBJECT HalpEisaAdapter[8]
Definition: dma.c:86
NTSTATUS NTAPI HalBuildScatterGatherList(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, IN PVOID ScatterGatherBuffer, IN ULONG ScatterGatherLength)
Definition: dma.c:1215
PDMA_ADAPTER NTAPI HalpGetDmaAdapter(IN PVOID Context, IN PDEVICE_DESCRIPTION DeviceDescription, OUT PULONG NumberOfMapRegisters)
Definition: dma.c:852
static LIST_ENTRY HalpDmaAdapterList
Definition: dma.c:85
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:1082
NTSTATUS NTAPI HalCalculateScatterGatherListSize(IN PADAPTER_OBJECT AdapterObject, IN PMDL Mdl OPTIONAL, IN PVOID CurrentVa, IN ULONG Length, OUT PULONG ScatterGatherListSize, OUT PULONG pNumberOfMapRegisters)
Definition: dma.c:1157
BOOLEAN NTAPI HalpDmaInitializeEisaAdapter(IN PADAPTER_OBJECT AdapterObject, IN PDEVICE_DESCRIPTION DeviceDescription)
Definition: dma.c:514
#define TYPE_B_TIMING
Definition: haldma.h:151
#define COMPATIBLE_TIMING
Definition: haldma.h:149
#define DMA_CLEARMASK
Definition: haldma.h:175
#define B_16BITS
Definition: haldma.h:146
struct _ROS_MAP_REGISTER_ENTRY * PROS_MAP_REGISTER_ENTRY
#define DEMAND_REQUEST_MODE
Definition: haldma.h:169
#define WRITE_TRANSFER
Definition: haldma.h:166
#define SINGLE_REQUEST_MODE
Definition: haldma.h:170
struct _GROW_WORK_ITEM * PGROW_WORK_ITEM
#define DMA_SETMASK
Definition: haldma.h:174
#define B_32BITS
Definition: haldma.h:145
#define TYPE_A_TIMING
Definition: haldma.h:150
#define MAP_BASE_SW_SG
Definition: haldma.h:367
#define READ_TRANSFER
Definition: haldma.h:165
#define BURST_TIMING
Definition: haldma.h:152
#define B_8BITS
Definition: haldma.h:143
struct _ADAPTER_OBJECT ADAPTER_OBJECT
#define CASCADE_REQUEST_MODE
Definition: haldma.h:172
_In_ ULONG Mode
Definition: hubbusif.h:303
@ Eisa
Definition: hwresource.cpp:139
@ PCIBus
Definition: hwresource.cpp:142
@ Isa
Definition: hwresource.cpp:138
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_PERMANENT
Definition: winternl.h:226
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
NTSYSAPI ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP, ULONG, ULONG)
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
NTSYSAPI void WINAPI RtlSetBits(PRTL_BITMAP, ULONG, ULONG)
static CODE_SEG("PAGE")
Definition: isapnp.c:1482
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define for
Definition: utility.h:88
@ HighPagePriority
Definition: imports.h:57
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
_Out_ PNDIS_HANDLE _Out_ PUINT _In_ PNDIS_STRING _In_ NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress
Definition: ndis.h:3230
#define KernelMode
Definition: asm.h:34
#define MACHINE_TYPE_EISA
Definition: ketypes.h:114
#define PAGE_ROUND_UP(x)
Definition: mmtypes.h:38
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
int Count
Definition: noreturn.cpp:7
#define TypeA
Definition: nslookup.h:13
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define FILE_READ_DATA
Definition: nt_native.h:628
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ NotificationEvent
POBJECT_TYPE IoAdapterObjectType
Definition: adapter.c:18
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
PHYSICAL_ADDRESS NTAPI MmGetPhysicalAddress(IN PVOID Address)
Definition: stubs.c:685
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
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:2935
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:1039
#define READ_PORT_UCHAR(p)
Definition: pc98vid.h:22
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
unsigned short USHORT
Definition: pedump.c:61
static WCHAR Address[46]
Definition: ping.c:68
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
@ Width16Bits
Definition: miniport.h:106
@ Width8Bits
Definition: miniport.h:105
@ Width32Bits
Definition: miniport.h:107
@ TypeB
Definition: miniport.h:114
@ Compatible
Definition: miniport.h:112
@ TypeC
Definition: miniport.h:115
#define ASSERT_IRQL_LESS_OR_EQUAL(x)
Definition: debug.h:251
ULONG * PPFN_NUMBER
Definition: ke.h:9
ULONG PFN_NUMBER
Definition: ke.h:9
VOID NTAPI RtlClearBit(_In_ PRTL_BITMAP BitMapHeader, _In_ BITMAP_INDEX BitNumber)
Definition: bitmap.c:294
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define DPRINT
Definition: sndvol32.h:71
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
UCHAR DmaBaseAddress
Definition: haldma.h:183
UCHAR DmaBaseCount
Definition: haldma.h:184
UCHAR ClearBytePointer
Definition: haldma.h:202
UCHAR Mode
Definition: haldma.h:201
DMA1_ADDRESS_COUNT DmaAddressCount[4]
Definition: haldma.h:197
UCHAR SingleMask
Definition: haldma.h:200
UCHAR DmaBaseAddress
Definition: haldma.h:189
UCHAR DmaBaseCount
Definition: haldma.h:191
UCHAR ClearBytePointer
Definition: haldma.h:219
DMA2_ADDRESS_COUNT DmaAddressCount[4]
Definition: haldma.h:210
UCHAR Mode
Definition: haldma.h:217
UCHAR SingleMask
Definition: haldma.h:215
struct _DMA_OPERATIONS * DmaOperations
Definition: iotypes.h:2295
USHORT Size
Definition: iotypes.h:2294
USHORT Version
Definition: iotypes.h:2293
PFREE_ADAPTER_CHANNEL FreeAdapterChannel
Definition: iotypes.h:2639
PALLOCATE_ADAPTER_CHANNEL AllocateAdapterChannel
Definition: iotypes.h:2637
PFLUSH_ADAPTER_BUFFERS FlushAdapterBuffers
Definition: iotypes.h:2638
PFREE_MAP_REGISTERS FreeMapRegisters
Definition: iotypes.h:2640
PMAP_TRANSFER MapTransfer
Definition: iotypes.h:2641
Definition: ketypes.h:578
Definition: typedefs.h:120
Definition: haldma.h:313
PHYSICAL_ADDRESS PhysicalAddress
Definition: haldma.h:315
PVOID VirtualAddress
Definition: haldma.h:314
ULONG Counter
Definition: haldma.h:316
PVOID AdapterListControlContext
Definition: dma.c:979
ULONG MapRegisterCount
Definition: dma.c:980
WAIT_CONTEXT_BLOCK Wcb
Definition: dma.c:982
PADAPTER_OBJECT AdapterObject
Definition: dma.c:974
BOOLEAN UsingUserBuffer
Definition: dma.c:973
PVOID MapRegisterBase
Definition: dma.c:979
BOOLEAN WriteToDevice
Definition: dma.c:981
PDRIVER_LIST_CONTROL AdapterListControlRoutine
Definition: dma.c:978
PHYSICAL_ADDRESS Address
Definition: iotypes.h:2173
ULONG NumberOfMapRegisters
Definition: iotypes.h:221
PDRIVER_CONTROL DeviceRoutine
Definition: iotypes.h:219
static LARGE_INTEGER Counter
Definition: clock.c:43
#define __WARNING_DEREF_NULL_PTR
Definition: suppress.h:32
#define _PRAGMA_WARNING_SUPPRESS(x)
Definition: suppress.h:28
#define MAXULONG
Definition: typedefs.h:251
uint32_t * PULONG
Definition: typedefs.h:59
#define UNIMPLEMENTED_ONCE
Definition: typedefs.h:30
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
struct _RTL_BITMAP RTL_BITMAP
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define MAXLONG
Definition: umtypes.h:116
UCHAR TimingMode
Definition: haldma.h:135
UCHAR TransferSize
Definition: haldma.h:134
UCHAR ChannelNumber
Definition: haldma.h:133
UCHAR RequestMode
Definition: haldma.h:97
UCHAR Byte
Definition: haldma.h:99
UCHAR TransferType
Definition: haldma.h:94
UCHAR Channel
Definition: haldma.h:93
UCHAR AutoInitialize
Definition: haldma.h:95
LONGLONG QuadPart
Definition: typedefs.h:114
struct _LARGE_INTEGER::@2290 u
ULONG LowPart
Definition: typedefs.h:106
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
_In_ WDFDMATRANSACTION _In_ size_t MaximumLength
_In_ WDFDMATRANSACTION _Out_opt_ ULONG * MapRegisterCount
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_ PCUNICODE_STRING DeviceDescription
Definition: wdfpdo.h:432
_Must_inspect_result_ _In_ WDFUSBDEVICE _In_ WDFREQUEST _In_ PWDF_USB_CONTROL_SETUP_PACKET _In_opt_ WDFMEMORY _In_opt_ PWDFMEMORY_OFFSET TransferOffset
Definition: wdfusb.h:1387
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:115
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:723
_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:409
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
@ DelayedWorkQueue
Definition: extypes.h:190
_Out_ PULONG NumberOfMapRegisters
Definition: halfuncs.h:209
#define HalGetDmaAdapter
Definition: haltypes.h:302
_In_ PDEVICE_OBJECT _In_ ULONG _In_ PDRIVER_CONTROL ExecutionRoutine
Definition: iofuncs.h:1399
_Inout_ PMDL TargetMdl
Definition: iofuncs.h:730
VOID(NTAPI * PFREE_ADAPTER_CHANNEL)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2343
NTSTATUS(NTAPI * PBUILD_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, _In_ PVOID ScatterGatherBuffer, _In_ ULONG ScatterGatherLength)
Definition: iotypes.h:2406
VOID(NTAPI * PFREE_MAP_REGISTERS)(_In_ PDMA_ADAPTER DmaAdapter, PVOID MapRegisterBase, ULONG NumberOfMapRegisters)
Definition: iotypes.h:2347
struct _DMA_OPERATIONS DMA_OPERATIONS
struct _SCATTER_GATHER_LIST SCATTER_GATHER_LIST
Definition: iotypes.h:2204
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS PhysicalAddress
Definition: iotypes.h:1098
ULONG(NTAPI * PREAD_DMA_COUNTER)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2366
struct _SCATTER_GATHER_LIST * PSCATTER_GATHER_LIST
Definition: iotypes.h:2204
_Inout_ struct _IRP _In_ PVOID MapRegisterBase
Definition: iotypes.h:213
enum _IO_ALLOCATION_ACTION IO_ALLOCATION_ACTION
@ DeallocateObject
Definition: iotypes.h:203
@ KeepObject
Definition: iotypes.h:202
@ DeallocateObjectKeepRegisters
Definition: iotypes.h:204
DRIVER_LIST_CONTROL * PDRIVER_LIST_CONTROL
Definition: iotypes.h:2377
#define DEVICE_DESCRIPTION_VERSION1
Definition: iotypes.h:2064
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:2353
NTSTATUS(NTAPI * PBUILD_MDL_FROM_SCATTER_GATHER_LIST)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PSCATTER_GATHER_LIST ScatterGather, _In_ PMDL OriginalMdl, _Out_ PMDL *TargetMdl)
Definition: iotypes.h:2419
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:2334
#define DEVICE_DESCRIPTION_VERSION2
Definition: iotypes.h:2065
_In_ struct _IRP _In_ struct _SCATTER_GATHER_LIST * ScatterGather
Definition: iotypes.h:2375
DRIVER_CONTROL * PDRIVER_CONTROL
Definition: iotypes.h:215
PVOID(NTAPI * PALLOCATE_COMMON_BUFFER)(_In_ PDMA_ADAPTER DmaAdapter, _In_ ULONG Length, _Out_ PPHYSICAL_ADDRESS LogicalAddress, _In_ BOOLEAN CacheEnabled)
Definition: iotypes.h:2311
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:2380
NTSTATUS(NTAPI * PCALCULATE_SCATTER_GATHER_LIST_SIZE)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PMDL Mdl OPTIONAL, _In_ PVOID CurrentVa, _In_ ULONG Length, _Out_ PULONG ScatterGatherListSize, _Out_ OPTIONAL PULONG pNumberOfMapRegisters)
Definition: iotypes.h:2397
VOID(NTAPI * PPUT_SCATTER_GATHER_LIST)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PSCATTER_GATHER_LIST ScatterGather, _In_ BOOLEAN WriteToDevice)
Definition: iotypes.h:2391
VOID(NTAPI * PPUT_DMA_ADAPTER)(PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2307
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:2326
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:2318
ULONG(NTAPI * PGET_DMA_ALIGNMENT)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2362
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
_Inout_ PKDEVICE_QUEUE_ENTRY DeviceQueueEntry
Definition: kefuncs.h:327
@ Executive
Definition: ketypes.h:415
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:687
#define MmGetMdlVirtualAddress(_Mdl)
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
#define BYTE_OFFSET(Va)
#define BYTES_TO_PAGES(Size)
#define MmGetMdlPfnArray(_Mdl)
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS LowestAcceptableAddress
Definition: mmfuncs.h:214
@ MmCached
Definition: mmtypes.h:130
@ MmNonCached
Definition: mmtypes.h:129
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ObReferenceObject
Definition: obfuncs.h:204
unsigned char UCHAR
Definition: xmlstorage.h:181